1 /* Copyright (C) 1996, 1997 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 <bits/libc-lock.h>
25 #include <rpcsvc/nis.h>
26 #include <rpcsvc/yp.h>
27 #include <rpcsvc/ypclnt.h>
28 #include <rpcsvc/ypupd.h>
32 struct dom_binding
*dom_pnext
;
33 char dom_domain
[YPMAXDOMAIN
+ 1];
34 struct sockaddr_in dom_server_addr
;
39 typedef struct dom_binding dom_binding
;
41 static struct timeval TIMEOUT
= {25, 0};
42 static int const MAXTRIES
= 5;
43 static char __ypdomainname
[NIS_MAXNAMELEN
+ 1] = "\0";
44 __libc_lock_define_initialized (static, ypbindlist_lock
)
45 static dom_binding
*__ypbindlist
= NULL
;
49 __yp_bind (const char *domain
, dom_binding
** ypdb
)
51 struct sockaddr_in clnt_saddr
;
52 struct ypbind_resp ypbr
;
62 if ((domain
== NULL
) || (strlen (domain
) == 0))
68 if (strcmp (domain
, ysd
->dom_domain
) == 0)
76 ysd
= (dom_binding
*) malloc (sizeof *ysd
);
77 memset (ysd
, '\0', sizeof *ysd
);
94 if (ysd
->dom_vers
== -1)
98 clnt_destroy(ysd
->dom_client
);
99 ysd
->dom_client
= NULL
;
100 ysd
->dom_socket
= -1;
102 memset (&clnt_saddr
, '\0', sizeof clnt_saddr
);
103 clnt_saddr
.sin_family
= AF_INET
;
104 clnt_saddr
.sin_addr
.s_addr
= htonl (INADDR_LOOPBACK
);
105 clnt_sock
= RPC_ANYSOCK
;
106 client
= clnttcp_create (&clnt_saddr
, YPBINDPROG
, YPBINDVERS
,
115 ** Check the port number -- should be < IPPORT_RESERVED.
116 ** If not, it's possible someone has registered a bogus
117 ** ypbind with the portmapper and is trying to trick us.
119 if (ntohs(clnt_saddr
.sin_port
) >= IPPORT_RESERVED
)
121 clnt_destroy(client
);
124 return(YPERR_YPBIND
);
127 if (clnt_call (client
, YPBINDPROC_DOMAIN
,
128 (xdrproc_t
) xdr_domainname
, (caddr_t
) &domain
,
129 (xdrproc_t
) xdr_ypbind_resp
,
130 (caddr_t
) &ypbr
, TIMEOUT
) != RPC_SUCCESS
)
132 clnt_destroy (client
);
139 clnt_destroy (client
);
142 if (ypbr
.ypbind_status
!= YPBIND_SUCC_VAL
)
144 switch (ypbr
.ypbind_resp_u
.ypbind_error
)
147 fputs (_("YPBINDPROC_DOMAIN: Internal error\n"), stderr
);
149 case YPBIND_ERR_NOSERV
:
151 _("YPBINDPROC_DOMAIN: No server for domain %s\n"),
154 case YPBIND_ERR_RESC
:
155 fputs (_("YPBINDPROC_DOMAIN: Resource allocation failure\n"),
159 fputs (_("YPBINDPROC_DOMAIN: Unknown error\n"), stderr
);
166 memset (&ysd
->dom_server_addr
, '\0', sizeof ysd
->dom_server_addr
);
167 ysd
->dom_server_addr
.sin_family
= AF_INET
;
168 memcpy (&ysd
->dom_server_addr
.sin_port
,
169 ypbr
.ypbind_resp_u
.ypbind_bindinfo
.ypbind_binding_port
,
170 sizeof (ysd
->dom_server_addr
.sin_port
));
171 memcpy (&ysd
->dom_server_addr
.sin_addr
.s_addr
,
172 ypbr
.ypbind_resp_u
.ypbind_bindinfo
.ypbind_binding_addr
,
173 sizeof (ysd
->dom_server_addr
.sin_addr
.s_addr
));
174 ysd
->dom_vers
= YPVERS
;
175 strncpy (ysd
->dom_domain
, domain
, YPMAXDOMAIN
);
176 ysd
->dom_domain
[YPMAXDOMAIN
] = '\0';
181 clnt_destroy (ysd
->dom_client
);
182 close (ysd
->dom_socket
);
184 ysd
->dom_socket
= RPC_ANYSOCK
;
185 ysd
->dom_client
= clntudp_create (&ysd
->dom_server_addr
, YPPROG
, YPVERS
,
186 TIMEOUT
, &ysd
->dom_socket
);
187 if (ysd
->dom_client
== NULL
)
191 while (ysd
->dom_client
== NULL
);
193 /* If the program exists, close the socket */
194 if (fcntl (ysd
->dom_socket
, F_SETFD
, 1) == -1)
195 perror (_("fcntl: F_SETFD"));
199 ysd
->dom_pnext
= __ypbindlist
;
206 return YPERR_SUCCESS
;
210 __yp_unbind (dom_binding
*ydb
)
212 clnt_destroy (ydb
->dom_client
);
213 ydb
->dom_client
= NULL
;
214 ydb
->dom_socket
= -1;
218 do_ypcall (const char *domain
, u_long prog
, xdrproc_t xargs
,
219 caddr_t req
, xdrproc_t xres
, caddr_t resp
)
221 dom_binding
*ydb
= NULL
;
225 result
= YPERR_YPERR
;
227 while (try < MAXTRIES
&& result
!= RPC_SUCCESS
)
229 __libc_lock_lock (ypbindlist_lock
);
231 if (__yp_bind (domain
, &ydb
) != 0)
233 __libc_lock_unlock (ypbindlist_lock
);
237 result
= clnt_call (ydb
->dom_client
, prog
,
238 xargs
, req
, xres
, resp
, TIMEOUT
);
240 if (result
!= RPC_SUCCESS
)
242 clnt_perror (ydb
->dom_client
, "do_ypcall: clnt_call");
248 __libc_lock_unlock (ypbindlist_lock
);
257 yp_bind (const char *indomain
)
261 __libc_lock_lock (ypbindlist_lock
);
263 status
= __yp_bind (indomain
, NULL
);
265 __libc_lock_unlock (ypbindlist_lock
);
271 yp_unbind (const char *indomain
)
273 dom_binding
*ydbptr
, *ydbptr2
;
275 __libc_lock_lock (ypbindlist_lock
);
278 ydbptr
= __ypbindlist
;
279 while (ydbptr
!= NULL
)
281 if (strcmp (ydbptr
->dom_domain
, indomain
) == 0)
287 __ypbindlist
= __ypbindlist
->dom_pnext
;
289 ydbptr2
= ydbptr
->dom_pnext
;
295 ydbptr
= ydbptr
->dom_pnext
;
298 __libc_lock_unlock (ypbindlist_lock
);
303 __libc_lock_define_initialized (static, domainname_lock
)
306 yp_get_default_domain (char **outdomain
)
308 int result
= YPERR_SUCCESS
;;
311 __libc_lock_lock (domainname_lock
);
313 if (__ypdomainname
[0] == '\0')
315 if (getdomainname (__ypdomainname
, NIS_MAXNAMELEN
))
316 result
= YPERR_NODOM
;
318 *outdomain
= __ypdomainname
;
321 *outdomain
= __ypdomainname
;
323 __libc_lock_unlock (domainname_lock
);
329 __yp_check (char **domain
)
333 if (__ypdomainname
[0] == '\0')
334 if (yp_get_default_domain (&unused
))
336 else if (strcmp (__ypdomainname
, "(none)") == 0)
340 *domain
= __ypdomainname
;
342 if (yp_bind (__ypdomainname
) == 0)
348 yp_match (const char *indomain
, const char *inmap
, const char *inkey
,
349 const int inkeylen
, char **outval
, int *outvallen
)
355 if (indomain
== NULL
|| indomain
[0] == '\0' ||
356 inmap
== NULL
|| inmap
[0] == '\0' ||
357 inkey
== NULL
|| inkey
[0] == '\0' || inkeylen
<= 0)
358 return YPERR_BADARGS
;
360 req
.domain
= (char *) indomain
;
361 req
.map
= (char *) inmap
;
362 req
.key
.keydat_val
= (char *) inkey
;
363 req
.key
.keydat_len
= inkeylen
;
367 memset (&resp
, '\0', sizeof (resp
));
369 result
= do_ypcall (indomain
, YPPROC_MATCH
, (xdrproc_t
) xdr_ypreq_key
,
370 (caddr_t
) & req
, (xdrproc_t
) xdr_ypresp_val
,
373 if (result
!= RPC_SUCCESS
)
375 if (resp
.stat
!= YP_TRUE
)
376 return ypprot_err (resp
.stat
);
378 *outvallen
= resp
.val
.valdat_len
;
379 *outval
= malloc (*outvallen
+ 1);
380 memcpy (*outval
, resp
.val
.valdat_val
, *outvallen
);
381 (*outval
)[*outvallen
] = '\0';
383 xdr_free ((xdrproc_t
) xdr_ypresp_val
, (char *) &resp
);
385 return YPERR_SUCCESS
;
389 yp_first (const char *indomain
, const char *inmap
, char **outkey
,
390 int *outkeylen
, char **outval
, int *outvallen
)
396 if (indomain
== NULL
|| indomain
[0] == '\0' ||
397 inmap
== NULL
|| inmap
[0] == '\0')
398 return YPERR_BADARGS
;
400 req
.domain
= (char *) indomain
;
401 req
.map
= (char *) inmap
;
403 *outkey
= *outval
= NULL
;
404 *outkeylen
= *outvallen
= 0;
405 memset (&resp
, '\0', sizeof (resp
));
407 result
= do_ypcall (indomain
, YPPROC_FIRST
, (xdrproc_t
) xdr_ypreq_nokey
,
408 (caddr_t
) & req
, (xdrproc_t
) xdr_ypresp_key_val
,
411 if (result
!= RPC_SUCCESS
)
413 if (resp
.stat
!= YP_TRUE
)
414 return ypprot_err (resp
.stat
);
416 *outkeylen
= resp
.key
.keydat_len
;
417 *outkey
= malloc (*outkeylen
+ 1);
418 memcpy (*outkey
, resp
.key
.keydat_val
, *outkeylen
);
419 (*outkey
)[*outkeylen
] = '\0';
420 *outvallen
= resp
.val
.valdat_len
;
421 *outval
= malloc (*outvallen
+ 1);
422 memcpy (*outval
, resp
.val
.valdat_val
, *outvallen
);
423 (*outval
)[*outvallen
] = '\0';
425 xdr_free ((xdrproc_t
) xdr_ypresp_key_val
, (char *) &resp
);
427 return YPERR_SUCCESS
;
431 yp_next (const char *indomain
, const char *inmap
, const char *inkey
,
432 const int inkeylen
, char **outkey
, int *outkeylen
, char **outval
,
439 if (indomain
== NULL
|| indomain
[0] == '\0' ||
440 inmap
== NULL
|| inmap
[0] == '\0' ||
441 inkeylen
<= 0 || inkey
== NULL
|| inkey
[0] == '\0')
442 return YPERR_BADARGS
;
444 req
.domain
= (char *) indomain
;
445 req
.map
= (char *) inmap
;
446 req
.key
.keydat_val
= (char *) inkey
;
447 req
.key
.keydat_len
= inkeylen
;
449 *outkey
= *outval
= NULL
;
450 *outkeylen
= *outvallen
= 0;
451 memset (&resp
, '\0', sizeof (resp
));
453 result
= do_ypcall (indomain
, YPPROC_NEXT
, (xdrproc_t
) xdr_ypreq_key
,
454 (caddr_t
) & req
, (xdrproc_t
) xdr_ypresp_key_val
,
457 if (result
!= RPC_SUCCESS
)
459 if (resp
.stat
!= YP_TRUE
)
460 return ypprot_err (resp
.stat
);
462 *outkeylen
= resp
.key
.keydat_len
;
463 *outkey
= malloc (*outkeylen
+ 1);
464 memcpy (*outkey
, resp
.key
.keydat_val
, *outkeylen
);
465 (*outkey
)[*outkeylen
] = '\0';
466 *outvallen
= resp
.val
.valdat_len
;
467 *outval
= malloc (*outvallen
+ 1);
468 memcpy (*outval
, resp
.val
.valdat_val
, *outvallen
);
469 (*outval
)[*outvallen
] = '\0';
471 xdr_free ((xdrproc_t
) xdr_ypresp_key_val
, (char *) &resp
);
473 return YPERR_SUCCESS
;
477 yp_master (const char *indomain
, const char *inmap
, char **outname
)
483 if (indomain
== NULL
|| indomain
[0] == '\0' ||
484 inmap
== NULL
|| inmap
[0] == '\0')
485 return YPERR_BADARGS
;
487 req
.domain
= (char *) indomain
;
488 req
.map
= (char *) inmap
;
490 memset (&resp
, '\0', sizeof (ypresp_master
));
492 result
= do_ypcall (indomain
, YPPROC_MASTER
, (xdrproc_t
) xdr_ypreq_nokey
,
493 (caddr_t
) & req
, (xdrproc_t
) xdr_ypresp_master
, (caddr_t
) & resp
);
495 if (result
!= RPC_SUCCESS
)
497 if (resp
.stat
!= YP_TRUE
)
498 return ypprot_err (resp
.stat
);
500 *outname
= strdup (resp
.peer
);
501 xdr_free ((xdrproc_t
) xdr_ypresp_master
, (char *) &resp
);
503 return YPERR_SUCCESS
;
507 yp_order (const char *indomain
, const char *inmap
, unsigned int *outorder
)
509 struct ypreq_nokey req
;
510 struct ypresp_order resp
;
513 if (indomain
== NULL
|| indomain
[0] == '\0' ||
514 inmap
== NULL
|| inmap
== '\0')
515 return YPERR_BADARGS
;
517 req
.domain
= (char *) indomain
;
518 req
.map
= (char *) inmap
;
520 memset (&resp
, '\0', sizeof (resp
));
522 result
= do_ypcall (indomain
, YPPROC_ORDER
, (xdrproc_t
) xdr_ypreq_nokey
,
523 (caddr_t
) & req
, (xdrproc_t
) xdr_ypresp_order
, (caddr_t
) & resp
);
525 if (result
!= RPC_SUCCESS
)
527 if (resp
.stat
!= YP_TRUE
)
528 return ypprot_err (resp
.stat
);
530 *outorder
= resp
.ordernum
;
531 xdr_free ((xdrproc_t
) xdr_ypresp_order
, (char *) &resp
);
533 return YPERR_SUCCESS
;
536 static void *ypall_data
;
537 static int (*ypall_foreach
) __P ((int status
, char *key
, int keylen
,
538 char *val
, int vallen
, char *data
));
541 __xdr_ypresp_all (XDR
* xdrs
, u_long
* objp
)
545 struct ypresp_all resp
;
547 memset (&resp
, '\0', sizeof (struct ypresp_all
));
548 if (!xdr_ypresp_all (xdrs
, &resp
))
550 xdr_free ((xdrproc_t
) xdr_ypresp_all
, (char *) &resp
);
556 xdr_free ((xdrproc_t
) xdr_ypresp_all
, (char *) &resp
);
561 switch (resp
.ypresp_all_u
.val
.stat
)
565 char key
[resp
.ypresp_all_u
.val
.key
.keydat_len
+ 1];
566 char val
[resp
.ypresp_all_u
.val
.val
.valdat_len
+ 1];
567 int keylen
= resp
.ypresp_all_u
.val
.key
.keydat_len
;
568 int vallen
= resp
.ypresp_all_u
.val
.val
.valdat_len
;
571 memcpy (key
, resp
.ypresp_all_u
.val
.key
.keydat_val
, keylen
);
573 memcpy (val
, resp
.ypresp_all_u
.val
.val
.valdat_val
, vallen
);
575 xdr_free ((xdrproc_t
) xdr_ypresp_all
, (char *) &resp
);
576 if ((*ypall_foreach
) (*objp
, key
, keylen
,
577 val
, vallen
, ypall_data
))
583 xdr_free ((xdrproc_t
) xdr_ypresp_all
, (char *) &resp
);
587 *objp
= resp
.ypresp_all_u
.val
.stat
;
588 xdr_free ((xdrproc_t
) xdr_ypresp_all
, (char *) &resp
);
595 yp_all (const char *indomain
, const char *inmap
,
596 const struct ypall_callback
*incallback
)
598 struct ypreq_nokey req
;
601 struct sockaddr_in clnt_sin
;
603 unsigned long status
;
606 if (indomain
== NULL
|| indomain
[0] == '\0' ||
607 inmap
== NULL
|| inmap
== '\0')
608 return YPERR_BADARGS
;
611 result
= YPERR_YPERR
;
613 while (try < MAXTRIES
&& result
!= RPC_SUCCESS
)
615 __libc_lock_lock (ypbindlist_lock
);
617 if (__yp_bind (indomain
, &ydb
) != 0)
619 __libc_lock_unlock (ypbindlist_lock
);
623 /* YPPROC_ALL get its own TCP channel to ypserv */
624 clnt_sock
= RPC_ANYSOCK
;
625 clnt_sin
= ydb
->dom_server_addr
;
626 clnt_sin
.sin_port
= 0;
627 clnt
= clnttcp_create (&clnt_sin
, YPPROG
, YPVERS
, &clnt_sock
, 0, 0);
630 puts ("yp_all: clnttcp_create failed");
631 __libc_lock_unlock (ypbindlist_lock
);
634 req
.domain
= (char *) indomain
;
635 req
.map
= (char *) inmap
;
637 ypall_foreach
= incallback
->foreach
;
638 ypall_data
= (void *) incallback
->data
;
640 result
= clnt_call (clnt
, YPPROC_ALL
, (xdrproc_t
) xdr_ypreq_nokey
,
641 (caddr_t
) &req
, (xdrproc_t
) __xdr_ypresp_all
,
642 (caddr_t
) &status
, TIMEOUT
);
646 if (result
!= RPC_SUCCESS
)
648 clnt_perror (ydb
->dom_client
, "yp_all: clnt_call");
653 result
= YPERR_SUCCESS
;
655 __libc_lock_unlock (ypbindlist_lock
);
657 if (status
!= YP_NOMORE
)
658 return ypprot_err (status
);
666 yp_maplist (const char *indomain
, struct ypmaplist
**outmaplist
)
668 struct ypresp_maplist resp
;
671 if (indomain
== NULL
|| indomain
[0] == '\0')
672 return YPERR_BADARGS
;
674 memset (&resp
, '\0', sizeof (resp
));
676 result
= do_ypcall (indomain
, YPPROC_MAPLIST
, (xdrproc_t
) xdr_domainname
,
677 (caddr_t
) & indomain
, (xdrproc_t
) xdr_ypresp_maplist
, (caddr_t
) & resp
);
679 if (result
!= RPC_SUCCESS
)
681 if (resp
.stat
!= YP_TRUE
)
682 return ypprot_err (resp
.stat
);
684 *outmaplist
= resp
.maps
;
685 /* We give the list not free, this will be done by ypserv
686 xdr_free((xdrproc_t)xdr_ypresp_maplist, (char *)&resp); */
688 return YPERR_SUCCESS
;
692 yperr_string (const int error
)
699 return _("Request arguments bad");
701 return _("RPC failure on NIS operation");
703 return _("Can't bind to server which serves this domain");
705 return _("No such map in server's domain");
707 return _("No such key in map");
709 return _("Internal NIS error");
711 return _("Local resource allocation failure");
713 return _("No more records in map database");
715 return _("Can't communicate with portmapper");
717 return _("Can't communicate with ypbind");
719 return _("Can't communicate with ypserv");
721 return _("Local domain name not set");
723 return _("NIS map data base is bad");
725 return _("NIS client/server version mismatch - can't supply service");
727 return _("Permission denied");
729 return _("Database is busy");
731 return _("Unknown NIS error code");
735 ypprot_err (const int code
)
740 return YPERR_SUCCESS
;
758 return YPERR_BADARGS
;
766 ypbinderr_string (const int error
)
773 return _("Internal ypbind error");
774 case YPBIND_ERR_NOSERV
:
775 return _("Domain not bound");
776 case YPBIND_ERR_RESC
:
777 return _("System resource allocation failure");
779 return _("Unknown ypbind error");
787 yp_update (char *domain
, char *map
, unsigned ypop
,
788 char *key
, int keylen
, char *data
, int datalen
)
790 #if defined (HAVE_SECURE_RPC)
793 ypupdate_args update_args
;
794 ypdelete_args delete_args
;
797 xdrproc_t xdr_argument
;
801 struct sockaddr saddr
;
802 char servername
[MAXNETNAMELEN
+ 1];
805 if (!domain
|| !map
|| !key
|| (ypop
!= YPOP_DELETE
&& !data
))
806 return YPERR_BADARGS
;
808 args
.update_args
.mapname
= map
;
809 args
.update_args
.key
.yp_buf_len
= keylen
;
810 args
.update_args
.key
.yp_buf_val
= key
;
811 args
.update_args
.datum
.yp_buf_len
= datalen
;
812 args
.update_args
.datum
.yp_buf_val
= data
;
814 if ((r
= yp_master (domain
, map
, &master
)) != 0)
817 if (!host2netname (servername
, master
, domain
))
819 fputs (_("yp_update: cannot convert host to netname\n"), stderr
);
823 if ((clnt
= clnt_create (master
, YPU_PROG
, YPU_VERS
, "tcp")) == NULL
)
825 clnt_pcreateerror ("yp_update: clnt_create");
829 if (!clnt_control (clnt
, CLGET_SERVER_ADDR
, (char *) &saddr
))
831 fputs (_("yp_update: cannot get server address\n"), stderr
);
840 xdr_argument
= (xdrproc_t
) xdr_ypupdate_args
;
843 xdr_argument
= (xdrproc_t
) xdr_ypdelete_args
;
846 return YPERR_BADARGS
;
850 clnt
->cl_auth
= authdes_create (servername
, WINDOW
, &saddr
, NULL
);
852 if (clnt
->cl_auth
== NULL
)
853 clnt
->cl_auth
= authunix_create_default ();
856 r
= clnt_call (clnt
, ypop
, xdr_argument
, (caddr_t
) &args
,
857 (xdrproc_t
) xdr_u_int
, (caddr_t
) &res
, TIMEOUT
);
859 if (r
== RPC_AUTHERROR
)
861 if (clnt
->cl_auth
->ah_cred
.oa_flavor
== AUTH_DES
)
863 clnt
->cl_auth
= authunix_create_default ();
869 if (r
!= RPC_SUCCESS
)
871 clnt_perror (clnt
, "yp_update: clnt_call");