1 /* Copyright (C) 1996 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3 Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1996.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public License as
7 published by the Free Software Foundation; either version 2 of the
8 License, or (at your option) any later version.
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
15 You should have received a copy of the GNU Library General Public
16 License along with the GNU C Library; see the file COPYING.LIB. If not,
17 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA. */
23 #include <libc-lock.h>
24 #include <rpcsvc/yp.h>
25 #include <rpcsvc/ypclnt.h>
26 #include <rpcsvc/ypupd.h>
30 struct dom_binding
*dom_pnext
;
31 char dom_domain
[YPMAXDOMAIN
+ 1];
32 struct sockaddr_in dom_server_addr
;
37 typedef struct dom_binding dom_binding
;
39 static struct timeval TIMEOUT
= {25, 0};
40 static int const MAXTRIES
= 5;
41 static char __ypdomainname
[MAXHOSTNAMELEN
+ 1] = "\0";
42 __libc_lock_define_initialized (static, ypbindlist_lock
)
43 static dom_binding
*__ypbindlist
= NULL
;
47 __yp_bind (const char *domain
, dom_binding
** ypdb
)
49 struct sockaddr_in clnt_saddr
;
50 struct ypbind_resp ypbr
;
60 if ((domain
== NULL
) || (strlen (domain
) == 0))
66 if (strcmp (domain
, ysd
->dom_domain
) == 0)
74 ysd
= (dom_binding
*) malloc (sizeof *ysd
);
75 memset (ysd
, '\0', sizeof *ysd
);
92 if (ysd
->dom_vers
== -1)
96 clnt_destroy(ysd
->dom_client
);
97 ysd
->dom_client
= NULL
;
100 memset (&clnt_saddr
, '\0', sizeof clnt_saddr
);
101 clnt_saddr
.sin_family
= AF_INET
;
102 clnt_saddr
.sin_addr
.s_addr
= htonl (INADDR_LOOPBACK
);
103 clnt_sock
= RPC_ANYSOCK
;
104 client
= clnttcp_create (&clnt_saddr
, YPBINDPROG
, YPBINDVERS
,
113 ** Check the port number -- should be < IPPORT_RESERVED.
114 ** If not, it's possible someone has registered a bogus
115 ** ypbind with the portmapper and is trying to trick us.
117 if (ntohs(clnt_saddr
.sin_port
) >= IPPORT_RESERVED
)
119 clnt_destroy(client
);
122 return(YPERR_YPBIND
);
125 if (clnt_call (client
, YPBINDPROC_DOMAIN
,
126 (xdrproc_t
) xdr_domainname
, &domain
,
127 (xdrproc_t
) xdr_ypbind_resp
,
128 &ypbr
, TIMEOUT
) != RPC_SUCCESS
)
130 clnt_destroy (client
);
136 clnt_destroy (client
);
137 if (ypbr
.ypbind_status
!= YPBIND_SUCC_VAL
)
139 switch (ypbr
.ypbind_resp_u
.ypbind_error
)
142 fputs (_("YPBINDPROC_DOMAIN: Internal error\n"), stderr
);
144 case YPBIND_ERR_NOSERV
:
146 _("YPBINDPROC_DOMAIN: No server for domain %s\n"),
149 case YPBIND_ERR_RESC
:
150 fputs (_("YPBINDPROC_DOMAIN: Resource allocation failure\n"),
154 fputs (_("YPBINDPROC_DOMAIN: Unknown error\n"), stderr
);
161 memset (&ysd
->dom_server_addr
, '\0', sizeof ysd
->dom_server_addr
);
162 ysd
->dom_server_addr
.sin_family
= AF_INET
;
163 memcpy (&ysd
->dom_server_addr
.sin_port
,
164 ypbr
.ypbind_resp_u
.ypbind_bindinfo
.ypbind_binding_port
,
165 sizeof (ysd
->dom_server_addr
.sin_port
));
166 memcpy (&ysd
->dom_server_addr
.sin_addr
.s_addr
,
167 ypbr
.ypbind_resp_u
.ypbind_bindinfo
.ypbind_binding_addr
,
168 sizeof (ysd
->dom_server_addr
.sin_addr
.s_addr
));
169 ysd
->dom_vers
= YPVERS
;
170 strcpy (ysd
->dom_domain
, domain
);
174 clnt_destroy (ysd
->dom_client
);
175 ysd
->dom_socket
= RPC_ANYSOCK
;
176 ysd
->dom_client
= clntudp_create (&ysd
->dom_server_addr
, YPPROG
, YPVERS
,
177 TIMEOUT
, &ysd
->dom_socket
);
178 if (ysd
->dom_client
== NULL
)
182 while (ysd
->dom_client
== NULL
);
184 /* If the program exists, close the socket */
185 if (fcntl (ysd
->dom_socket
, F_SETFD
, 1) == -1)
186 perror (_("fcntl: F_SETFD"));
190 ysd
->dom_pnext
= __ypbindlist
;
197 return YPERR_SUCCESS
;
201 __yp_unbind (dom_binding
*ydb
)
203 clnt_destroy (ydb
->dom_client
);
204 ydb
->dom_client
= NULL
;
205 ydb
->dom_socket
= -1;
209 do_ypcall (const char *domain
, u_long prog
, xdrproc_t xargs
,
210 caddr_t req
, xdrproc_t xres
, caddr_t resp
)
212 dom_binding
*ydb
= NULL
;
216 result
= YPERR_YPERR
;
218 while (try < MAXTRIES
&& result
!= RPC_SUCCESS
)
220 __libc_lock_lock (ypbindlist_lock
);
222 if (__yp_bind (domain
, &ydb
) != 0)
224 __libc_lock_unlock (ypbindlist_lock
);
228 result
= clnt_call (ydb
->dom_client
, prog
,
229 xargs
, req
, xres
, resp
, TIMEOUT
);
231 if (result
!= RPC_SUCCESS
)
233 clnt_perror (ydb
->dom_client
, "do_ypcall: clnt_call");
239 __libc_lock_unlock (ypbindlist_lock
);
248 yp_bind (const char *indomain
)
252 __libc_lock_lock (ypbindlist_lock
);
254 status
= __yp_bind (indomain
, NULL
);
256 __libc_lock_unlock (ypbindlist_lock
);
262 yp_unbind (const char *indomain
)
264 dom_binding
*ydbptr
, *ydbptr2
;
266 __libc_lock_lock (ypbindlist_lock
);
269 ydbptr
= __ypbindlist
;
270 while (ydbptr
!= NULL
)
272 if (strcmp (ydbptr
->dom_domain
, indomain
) == 0)
278 __ypbindlist
= __ypbindlist
->dom_pnext
;
280 ydbptr2
= ydbptr
->dom_pnext
;
286 ydbptr
= ydbptr
->dom_pnext
;
289 __libc_lock_unlock (ypbindlist_lock
);
294 __libc_lock_define_initialized (static, domainname_lock
)
297 yp_get_default_domain (char **outdomain
)
299 int result
= YPERR_SUCCESS
;;
302 __libc_lock_lock (domainname_lock
);
304 if (__ypdomainname
[0] == '\0')
306 if (getdomainname (__ypdomainname
, MAXHOSTNAMELEN
))
307 result
= YPERR_NODOM
;
309 *outdomain
= __ypdomainname
;
312 *outdomain
= __ypdomainname
;
314 __libc_lock_unlock (domainname_lock
);
320 __yp_check (char **domain
)
324 if (__ypdomainname
[0] == '\0')
325 if (yp_get_default_domain (&unused
))
327 else if (strcmp (__ypdomainname
, "(none)") == 0)
331 *domain
= __ypdomainname
;
333 if (yp_bind (__ypdomainname
) == 0)
339 yp_match (const char *indomain
, const char *inmap
, const char *inkey
,
340 const int inkeylen
, char **outval
, int *outvallen
)
346 if (indomain
== NULL
|| indomain
[0] == '\0' ||
347 inmap
== NULL
|| inmap
[0] == '\0' ||
348 inkey
== NULL
|| inkey
[0] == '\0' || inkeylen
<= 0)
349 return YPERR_BADARGS
;
351 req
.domain
= (char *) indomain
;
352 req
.map
= (char *) inmap
;
353 req
.key
.keydat_val
= (char *) inkey
;
354 req
.key
.keydat_len
= inkeylen
;
358 memset (&resp
, '\0', sizeof (resp
));
360 result
= do_ypcall (indomain
, YPPROC_MATCH
, (xdrproc_t
) xdr_ypreq_key
,
361 (caddr_t
) & req
, (xdrproc_t
) xdr_ypresp_val
,
364 if (result
!= RPC_SUCCESS
)
366 if (resp
.stat
!= YP_TRUE
)
367 return ypprot_err (resp
.stat
);
369 *outvallen
= resp
.val
.valdat_len
;
370 *outval
= malloc (*outvallen
+ 1);
371 memcpy (*outval
, resp
.val
.valdat_val
, *outvallen
);
372 (*outval
)[*outvallen
] = '\0';
374 xdr_free ((xdrproc_t
) xdr_ypresp_val
, (char *) &resp
);
376 return YPERR_SUCCESS
;
380 yp_first (const char *indomain
, const char *inmap
, char **outkey
,
381 int *outkeylen
, char **outval
, int *outvallen
)
387 if (indomain
== NULL
|| indomain
[0] == '\0' ||
388 inmap
== NULL
|| inmap
[0] == '\0')
389 return YPERR_BADARGS
;
391 req
.domain
= (char *) indomain
;
392 req
.map
= (char *) inmap
;
394 *outkey
= *outval
= NULL
;
395 *outkeylen
= *outvallen
= 0;
396 memset (&resp
, '\0', sizeof (resp
));
398 result
= do_ypcall (indomain
, YPPROC_FIRST
, (xdrproc_t
) xdr_ypreq_nokey
,
399 (caddr_t
) & req
, (xdrproc_t
) xdr_ypresp_key_val
,
402 if (result
!= RPC_SUCCESS
)
404 if (resp
.stat
!= YP_TRUE
)
405 return ypprot_err (resp
.stat
);
407 *outkeylen
= resp
.key
.keydat_len
;
408 *outkey
= malloc (*outkeylen
+ 1);
409 memcpy (*outkey
, resp
.key
.keydat_val
, *outkeylen
);
410 (*outkey
)[*outkeylen
] = '\0';
411 *outvallen
= resp
.val
.valdat_len
;
412 *outval
= malloc (*outvallen
+ 1);
413 memcpy (*outval
, resp
.val
.valdat_val
, *outvallen
);
414 (*outval
)[*outvallen
] = '\0';
416 xdr_free ((xdrproc_t
) xdr_ypresp_key_val
, (char *) &resp
);
418 return YPERR_SUCCESS
;
422 yp_next (const char *indomain
, const char *inmap
, const char *inkey
,
423 const int inkeylen
, char **outkey
, int *outkeylen
, char **outval
,
430 if (indomain
== NULL
|| indomain
[0] == '\0' ||
431 inmap
== NULL
|| inmap
[0] == '\0' ||
432 inkeylen
<= 0 || inkey
== NULL
|| inkey
[0] == '\0')
433 return YPERR_BADARGS
;
435 req
.domain
= (char *) indomain
;
436 req
.map
= (char *) inmap
;
437 req
.key
.keydat_val
= (char *) inkey
;
438 req
.key
.keydat_len
= inkeylen
;
440 *outkey
= *outval
= NULL
;
441 *outkeylen
= *outvallen
= 0;
442 memset (&resp
, '\0', sizeof (resp
));
444 result
= do_ypcall (indomain
, YPPROC_NEXT
, (xdrproc_t
) xdr_ypreq_key
,
445 (caddr_t
) & req
, (xdrproc_t
) xdr_ypresp_key_val
,
448 if (result
!= RPC_SUCCESS
)
450 if (resp
.stat
!= YP_TRUE
)
451 return ypprot_err (resp
.stat
);
453 *outkeylen
= resp
.key
.keydat_len
;
454 *outkey
= malloc (*outkeylen
+ 1);
455 memcpy (*outkey
, resp
.key
.keydat_val
, *outkeylen
);
456 (*outkey
)[*outkeylen
] = '\0';
457 *outvallen
= resp
.val
.valdat_len
;
458 *outval
= malloc (*outvallen
+ 1);
459 memcpy (*outval
, resp
.val
.valdat_val
, *outvallen
);
460 (*outval
)[*outvallen
] = '\0';
462 xdr_free ((xdrproc_t
) xdr_ypresp_key_val
, (char *) &resp
);
464 return YPERR_SUCCESS
;
468 yp_master (const char *indomain
, const char *inmap
, char **outname
)
474 if (indomain
== NULL
|| indomain
[0] == '\0' ||
475 inmap
== NULL
|| inmap
[0] == '\0')
476 return YPERR_BADARGS
;
478 req
.domain
= (char *) indomain
;
479 req
.map
= (char *) inmap
;
481 memset (&resp
, '\0', sizeof (ypresp_master
));
483 result
= do_ypcall (indomain
, YPPROC_MASTER
, (xdrproc_t
) xdr_ypreq_nokey
,
484 (caddr_t
) & req
, (xdrproc_t
) xdr_ypresp_master
, (caddr_t
) & resp
);
486 if (result
!= RPC_SUCCESS
)
488 if (resp
.stat
!= YP_TRUE
)
489 return ypprot_err (resp
.stat
);
491 *outname
= strdup (resp
.peer
);
492 xdr_free ((xdrproc_t
) xdr_ypresp_master
, (char *) &resp
);
494 return YPERR_SUCCESS
;
498 yp_order (const char *indomain
, const char *inmap
, unsigned int *outorder
)
500 struct ypreq_nokey req
;
501 struct ypresp_order resp
;
504 if (indomain
== NULL
|| indomain
[0] == '\0' ||
505 inmap
== NULL
|| inmap
== '\0')
506 return YPERR_BADARGS
;
508 req
.domain
= (char *) indomain
;
509 req
.map
= (char *) inmap
;
511 memset (&resp
, '\0', sizeof (resp
));
513 result
= do_ypcall (indomain
, YPPROC_ORDER
, (xdrproc_t
) xdr_ypreq_nokey
,
514 (caddr_t
) & req
, (xdrproc_t
) xdr_ypresp_order
, (caddr_t
) & resp
);
516 if (result
!= RPC_SUCCESS
)
518 if (resp
.stat
!= YP_TRUE
)
519 return ypprot_err (resp
.stat
);
521 *outorder
= resp
.ordernum
;
522 xdr_free ((xdrproc_t
) xdr_ypresp_order
, (char *) &resp
);
524 return YPERR_SUCCESS
;
527 static void *ypall_data
;
528 static int (*ypall_foreach
) ();
531 __xdr_ypresp_all (XDR
* xdrs
, u_long
* objp
)
535 struct ypresp_all resp
;
537 memset (&resp
, '\0', sizeof (struct ypresp_all
));
538 if (!xdr_ypresp_all (xdrs
, &resp
))
540 xdr_free ((xdrproc_t
) xdr_ypresp_all
, (char *) &resp
);
546 xdr_free ((xdrproc_t
) xdr_ypresp_all
, (char *) &resp
);
551 switch (resp
.ypresp_all_u
.val
.stat
)
555 char key
[resp
.ypresp_all_u
.val
.key
.keydat_len
+ 1];
556 char val
[resp
.ypresp_all_u
.val
.val
.valdat_len
+ 1];
557 int keylen
= resp
.ypresp_all_u
.val
.key
.keydat_len
;
558 int vallen
= resp
.ypresp_all_u
.val
.val
.valdat_len
;
561 memcpy (key
, resp
.ypresp_all_u
.val
.key
.keydat_val
, keylen
);
563 memcpy (val
, resp
.ypresp_all_u
.val
.val
.valdat_val
, vallen
);
565 xdr_free ((xdrproc_t
) xdr_ypresp_all
, (char *) &resp
);
566 if ((*ypall_foreach
) (*objp
, key
, keylen
,
567 val
, vallen
, ypall_data
))
573 xdr_free ((xdrproc_t
) xdr_ypresp_all
, (char *) &resp
);
577 *objp
= resp
.ypresp_all_u
.val
.stat
;
578 xdr_free ((xdrproc_t
) xdr_ypresp_all
, (char *) &resp
);
585 yp_all (const char *indomain
, const char *inmap
,
586 const struct ypall_callback
*incallback
)
588 struct ypreq_nokey req
;
591 struct sockaddr_in clnt_sin
;
593 unsigned long status
;
596 if (indomain
== NULL
|| indomain
[0] == '\0' ||
597 inmap
== NULL
|| inmap
== '\0')
598 return YPERR_BADARGS
;
601 result
= YPERR_YPERR
;
603 while (try < MAXTRIES
&& result
!= RPC_SUCCESS
)
605 __libc_lock_lock (ypbindlist_lock
);
607 if (__yp_bind (indomain
, &ydb
) != 0)
609 __libc_lock_unlock (ypbindlist_lock
);
613 /* YPPROC_ALL get its own TCP channel to ypserv */
614 clnt_sock
= RPC_ANYSOCK
;
615 clnt_sin
= ydb
->dom_server_addr
;
616 clnt_sin
.sin_port
= 0;
617 clnt
= clnttcp_create (&clnt_sin
, YPPROG
, YPVERS
, &clnt_sock
, 0, 0);
620 puts ("yp_all: clnttcp_create failed");
621 __libc_lock_unlock (ypbindlist_lock
);
624 req
.domain
= (char *) indomain
;
625 req
.map
= (char *) inmap
;
627 ypall_foreach
= incallback
->foreach
;
628 ypall_data
= (void *) incallback
->data
;
630 result
= clnt_call (clnt
, YPPROC_ALL
, (xdrproc_t
) xdr_ypreq_nokey
, &req
,
631 (xdrproc_t
) __xdr_ypresp_all
, &status
, TIMEOUT
);
633 if (result
!= RPC_SUCCESS
)
635 clnt_perror (ydb
->dom_client
, "yp_all: clnt_call");
643 result
= YPERR_SUCCESS
;
646 __libc_lock_unlock (ypbindlist_lock
);
648 if (status
!= YP_NOMORE
)
649 return ypprot_err (status
);
657 yp_maplist (const char *indomain
, struct ypmaplist
**outmaplist
)
659 struct ypresp_maplist resp
;
662 if (indomain
== NULL
|| indomain
[0] == '\0')
663 return YPERR_BADARGS
;
665 memset (&resp
, '\0', sizeof (resp
));
667 result
= do_ypcall (indomain
, YPPROC_MAPLIST
, (xdrproc_t
) xdr_domainname
,
668 (caddr_t
) & indomain
, (xdrproc_t
) xdr_ypresp_maplist
, (caddr_t
) & resp
);
670 if (result
!= RPC_SUCCESS
)
672 if (resp
.stat
!= YP_TRUE
)
673 return ypprot_err (resp
.stat
);
675 *outmaplist
= resp
.maps
;
676 /* We give the list not free, this will be done by ypserv
677 xdr_free((xdrproc_t)xdr_ypresp_maplist, (char *)&resp); */
679 return YPERR_SUCCESS
;
683 yperr_string (const int error
)
690 return _("Request arguments bad");
692 return _("RPC failure on NIS operation");
694 return _("Can't bind to server which serves this domain");
696 return _("No such map in server's domain");
698 return _("No such key in map");
700 return _("Internal NIS error");
702 return _("Local resource allocation failure");
704 return _("No more records in map database");
706 return _("Can't communicate with portmapper");
708 return _("Can't communicate with ypbind");
710 return _("Can't communicate with ypserv");
712 return _("Local domain name not set");
714 return _("NIS map data base is bad");
716 return _("NIS client/server version mismatch - can't supply service");
718 return _("Permission denied");
720 return _("Database is busy");
722 return _("Unknown NIS error code");
726 ypprot_err (const int code
)
731 return YPERR_SUCCESS
;
749 return YPERR_BADARGS
;
757 ypbinderr_string (const int error
)
764 return _("Internal ypbind error");
765 case YPBIND_ERR_NOSERV
:
766 return _("Domain not bound");
767 case YPBIND_ERR_RESC
:
768 return _("System resource allocation failure");
770 return _("Unknown ypbind error");
778 yp_update (char *domain
, char *map
, unsigned ypop
,
779 char *key
, int keylen
, char *data
, int datalen
)
784 ypupdate_args update_args
;
785 ypdelete_args delete_args
;
788 xdrproc_t xdr_argument
;
792 struct sockaddr saddr
;
793 char servername
[MAXNETNAMELEN
+ 1];
796 if (!domain
|| !map
|| !key
|| (ypop
!= YPOP_DELETE
&& !data
))
797 return YPERR_BADARGS
;
799 args
.update_args
.mapname
= map
;
800 args
.update_args
.key
.yp_buf_len
= keylen
;
801 args
.update_args
.key
.yp_buf_val
= key
;
802 args
.update_args
.datum
.yp_buf_len
= datalen
;
803 args
.update_args
.datum
.yp_buf_val
= data
;
805 if ((r
= yp_master (domain
, map
, &master
)) != 0)
808 if (!host2netname (servername
, master
, domain
))
810 fputs (_("yp_update: cannot convert host to netname\n"), stderr
);
814 if ((clnt
= clnt_create (master
, YPU_PROG
, YPU_VERS
, "tcp")) == NULL
)
816 clnt_pcreateerror ("yp_update: clnt_create");
820 if (!clnt_control (clnt
, CLGET_SERVER_ADDR
, (char *) &saddr
))
822 fputs (_("yp_update: cannot get server address\n"), stderr
);
831 xdr_argument
= (xdrproc_t
) xdr_ypupdate_args
;
834 xdr_argument
= (xdrproc_t
) xdr_ypdelete_args
;
837 return YPERR_BADARGS
;
841 clnt
->cl_auth
= authdes_create (servername
, WINDOW
, &saddr
, NULL
);
843 if (clnt
->cl_auth
== NULL
)
844 clnt
->cl_auth
= authunix_create_default ();
847 r
= clnt_call (clnt
, ypop
, xdr_argument
, &args
,
848 (xdrproc_t
) xdr_u_int
, &res
, TIMEOUT
);
850 if (r
== RPC_AUTHERROR
)
852 if (clnt
->cl_auth
->ah_cred
.oa_flavor
== AUTH_DES
)
854 clnt
->cl_auth
= authunix_create_default ();
860 if (r
!= RPC_SUCCESS
)
862 clnt_perror (clnt
, "yp_update: clnt_call");