1 /* Copyright (C) 1996-2001, 2002, 2003, 2004 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3 Contributed by Thorsten Kukuk <kukuk@suse.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 Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the 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 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, write to the Free
17 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
26 #include <rpcsvc/nis.h>
27 #include <rpcsvc/yp.h>
28 #include <rpcsvc/ypclnt.h>
29 #include <rpcsvc/ypupd.h>
31 #include <bits/libc-lock.h>
33 /* This should only be defined on systems with a BSD compatible ypbind */
35 # define BINDINGDIR "/var/yp/binding"
40 struct dom_binding
*dom_pnext
;
41 char dom_domain
[YPMAXDOMAIN
+ 1];
42 struct sockaddr_in dom_server_addr
;
46 typedef struct dom_binding dom_binding
;
48 static struct timeval RPCTIMEOUT
= {25, 0};
49 static struct timeval UDPTIMEOUT
= {5, 0};
50 static int const MAXTRIES
= 2;
51 static char __ypdomainname
[NIS_MAXNAMELEN
+ 1] = "\0";
52 __libc_lock_define_initialized (static, ypbindlist_lock
)
53 static dom_binding
*__ypbindlist
= NULL
;
57 yp_bind_client_create (const char *domain
, dom_binding
*ysd
,
58 struct ypbind_resp
*ypbr
)
60 ysd
->dom_server_addr
.sin_family
= AF_INET
;
61 memcpy (&ysd
->dom_server_addr
.sin_port
,
62 ypbr
->ypbind_resp_u
.ypbind_bindinfo
.ypbind_binding_port
,
63 sizeof (ysd
->dom_server_addr
.sin_port
));
64 memcpy (&ysd
->dom_server_addr
.sin_addr
.s_addr
,
65 ypbr
->ypbind_resp_u
.ypbind_bindinfo
.ypbind_binding_addr
,
66 sizeof (ysd
->dom_server_addr
.sin_addr
.s_addr
));
67 strncpy (ysd
->dom_domain
, domain
, YPMAXDOMAIN
);
68 ysd
->dom_domain
[YPMAXDOMAIN
] = '\0';
70 ysd
->dom_socket
= RPC_ANYSOCK
;
71 ysd
->dom_client
= clntudp_create (&ysd
->dom_server_addr
, YPPROG
, YPVERS
,
72 UDPTIMEOUT
, &ysd
->dom_socket
);
74 if (ysd
->dom_client
!= NULL
)
76 /* If the program exits, close the socket */
77 if (fcntl (ysd
->dom_socket
, F_SETFD
, FD_CLOEXEC
) == -1)
78 perror ("fcntl: F_SETFD");
84 yp_bind_file (const char *domain
, dom_binding
*ysd
)
86 char path
[sizeof (BINDINGDIR
) + strlen (domain
) + 3 * sizeof (unsigned) + 3];
88 snprintf (path
, sizeof (path
), "%s/%s.%u", BINDINGDIR
, domain
, YPBINDVERS
);
89 int fd
= open (path
, O_RDONLY
);
92 /* We have a binding file and could save a RPC call. The file
93 contains a port number and the YPBIND_RESP record. The port
94 number (16 bits) can be ignored. */
95 struct ypbind_resp ypbr
;
97 if (pread (fd
, &ypbr
, sizeof (ypbr
), 2) == sizeof (ypbr
))
98 yp_bind_client_create (domain
, ysd
, &ypbr
);
106 yp_bind_ypbindprog (const char *domain
, dom_binding
*ysd
)
108 struct sockaddr_in clnt_saddr
;
109 struct ypbind_resp ypbr
;
113 memset (&clnt_saddr
, '\0', sizeof clnt_saddr
);
114 clnt_saddr
.sin_family
= AF_INET
;
115 clnt_saddr
.sin_addr
.s_addr
= htonl (INADDR_LOOPBACK
);
116 clnt_sock
= RPC_ANYSOCK
;
117 client
= clnttcp_create (&clnt_saddr
, YPBINDPROG
, YPBINDVERS
,
122 /* Check the port number -- should be < IPPORT_RESERVED.
123 If not, it's possible someone has registered a bogus
124 ypbind with the portmapper and is trying to trick us. */
125 if (ntohs (clnt_saddr
.sin_port
) >= IPPORT_RESERVED
)
127 clnt_destroy (client
);
131 if (clnt_call (client
, YPBINDPROC_DOMAIN
,
132 (xdrproc_t
) xdr_domainname
, (caddr_t
) &domain
,
133 (xdrproc_t
) xdr_ypbind_resp
,
134 (caddr_t
) &ypbr
, RPCTIMEOUT
) != RPC_SUCCESS
)
136 clnt_destroy (client
);
140 clnt_destroy (client
);
142 if (ypbr
.ypbind_status
!= YPBIND_SUCC_VAL
)
144 fprintf (stderr
, _("YPBINDPROC_DOMAIN: %s\n"),
145 ypbinderr_string (ypbr
.ypbind_resp_u
.ypbind_error
));
148 memset (&ysd
->dom_server_addr
, '\0', sizeof ysd
->dom_server_addr
);
150 yp_bind_client_create (domain
, ysd
, &ypbr
);
152 return YPERR_SUCCESS
;
156 __yp_bind (const char *domain
, dom_binding
**ypdb
)
158 dom_binding
*ysd
= NULL
;
161 if (domain
== NULL
|| domain
[0] == '\0')
162 return YPERR_BADARGS
;
167 if (strcmp (domain
, ysd
->dom_domain
) == 0)
169 ysd
= ysd
->dom_pnext
;
175 ysd
= (dom_binding
*) calloc (1, sizeof *ysd
);
176 if (__builtin_expect (ysd
== NULL
, 0))
181 /* Try binding dir at first if we have no binding */
182 if (ysd
->dom_client
== NULL
)
183 yp_bind_file (domain
, ysd
);
184 #endif /* USE_BINDINGDIR */
186 if (ysd
->dom_client
== NULL
)
188 int retval
= yp_bind_ypbindprog (domain
, ysd
);
189 if (retval
!= YPERR_SUCCESS
)
197 if (ysd
->dom_client
== NULL
)
206 ysd
->dom_pnext
= *ypdb
;
210 return YPERR_SUCCESS
;
214 __yp_unbind (dom_binding
*ydb
)
216 clnt_destroy (ydb
->dom_client
);
221 yp_bind (const char *indomain
)
225 __libc_lock_lock (ypbindlist_lock
);
227 status
= __yp_bind (indomain
, &__ypbindlist
);
229 __libc_lock_unlock (ypbindlist_lock
);
233 libnsl_hidden_def (yp_bind
)
236 yp_unbind_locked (const char *indomain
)
238 dom_binding
*ydbptr
, *ydbptr2
;
241 ydbptr
= __ypbindlist
;
243 while (ydbptr
!= NULL
)
245 if (strcmp (ydbptr
->dom_domain
, indomain
) == 0)
251 __ypbindlist
= __ypbindlist
->dom_pnext
;
253 ydbptr2
= ydbptr
->dom_pnext
;
258 ydbptr
= ydbptr
->dom_pnext
;
263 yp_unbind (const char *indomain
)
265 __libc_lock_lock (ypbindlist_lock
);
267 yp_unbind_locked (indomain
);
269 __libc_lock_unlock (ypbindlist_lock
);
275 __ypclnt_call (const char *domain
, u_long prog
, xdrproc_t xargs
,
276 caddr_t req
, xdrproc_t xres
, caddr_t resp
, dom_binding
**ydb
,
279 enum clnt_stat result
;
281 result
= clnt_call ((*ydb
)->dom_client
, prog
,
282 xargs
, req
, xres
, resp
, RPCTIMEOUT
);
284 if (result
!= RPC_SUCCESS
)
286 /* We don't print an error message, if we try our old,
287 cached data. Only print this for data, which should work. */
289 clnt_perror ((*ydb
)->dom_client
, "do_ypcall: clnt_call");
294 return YPERR_SUCCESS
;
298 do_ypcall (const char *domain
, u_long prog
, xdrproc_t xargs
,
299 caddr_t req
, xdrproc_t xres
, caddr_t resp
)
303 int saved_errno
= errno
;
305 status
= YPERR_YPERR
;
307 __libc_lock_lock (ypbindlist_lock
);
311 if (strcmp (domain
, ydb
->dom_domain
) == 0)
313 if (__yp_bind (domain
, &ydb
) == 0)
315 /* Call server, print no error message, do not unbind. */
316 status
= __ypclnt_call (domain
, prog
, xargs
, req
, xres
,
318 if (status
== YPERR_SUCCESS
)
320 __libc_lock_unlock (ypbindlist_lock
);
321 __set_errno (saved_errno
);
325 /* We use ypbindlist, and the old cached data is
326 invalid. unbind now and create a new binding */
327 yp_unbind_locked (domain
);
331 ydb
= ydb
->dom_pnext
;
333 __libc_lock_unlock (ypbindlist_lock
);
335 /* First try with cached data failed. Now try to get
336 current data from the system. */
338 if (__yp_bind (domain
, &ydb
) == 0)
340 status
= __ypclnt_call (domain
, prog
, xargs
, req
, xres
,
346 /* If we support binding dir data, we have a third chance:
348 if (status
!= YPERR_SUCCESS
)
350 ydb
= calloc (1, sizeof (dom_binding
));
351 if (yp_bind_ypbindprog (domain
, ydb
) == YPERR_SUCCESS
)
353 status
= __ypclnt_call (domain
, prog
, xargs
, req
, xres
,
362 __set_errno (saved_errno
);
368 __libc_lock_define_initialized (static, domainname_lock
)
371 yp_get_default_domain (char **outdomain
)
373 int result
= YPERR_SUCCESS
;;
376 __libc_lock_lock (domainname_lock
);
378 if (__ypdomainname
[0] == '\0')
380 if (getdomainname (__ypdomainname
, NIS_MAXNAMELEN
))
381 result
= YPERR_NODOM
;
382 else if (strcmp (__ypdomainname
, "(none)") == 0)
384 /* If domainname is not set, some systems will return "(none)" */
385 __ypdomainname
[0] = '\0';
386 result
= YPERR_NODOM
;
389 *outdomain
= __ypdomainname
;
392 *outdomain
= __ypdomainname
;
394 __libc_lock_unlock (domainname_lock
);
398 libnsl_hidden_def (yp_get_default_domain
)
401 __yp_check (char **domain
)
405 if (__ypdomainname
[0] == '\0')
406 if (yp_get_default_domain (&unused
))
410 *domain
= __ypdomainname
;
412 if (yp_bind (__ypdomainname
) == 0)
418 yp_match (const char *indomain
, const char *inmap
, const char *inkey
,
419 const int inkeylen
, char **outval
, int *outvallen
)
423 enum clnt_stat result
;
425 if (indomain
== NULL
|| indomain
[0] == '\0' ||
426 inmap
== NULL
|| inmap
[0] == '\0' ||
427 inkey
== NULL
|| inkey
[0] == '\0' || inkeylen
<= 0)
428 return YPERR_BADARGS
;
430 req
.domain
= (char *) indomain
;
431 req
.map
= (char *) inmap
;
432 req
.key
.keydat_val
= (char *) inkey
;
433 req
.key
.keydat_len
= inkeylen
;
437 memset (&resp
, '\0', sizeof (resp
));
439 result
= do_ypcall (indomain
, YPPROC_MATCH
, (xdrproc_t
) xdr_ypreq_key
,
440 (caddr_t
) & req
, (xdrproc_t
) xdr_ypresp_val
,
443 if (result
!= YPERR_SUCCESS
)
445 if (resp
.stat
!= YP_TRUE
)
446 return ypprot_err (resp
.stat
);
448 *outvallen
= resp
.val
.valdat_len
;
449 *outval
= malloc (*outvallen
+ 1);
450 if (__builtin_expect (*outval
== NULL
, 0))
452 memcpy (*outval
, resp
.val
.valdat_val
, *outvallen
);
453 (*outval
)[*outvallen
] = '\0';
455 xdr_free ((xdrproc_t
) xdr_ypresp_val
, (char *) &resp
);
457 return YPERR_SUCCESS
;
461 yp_first (const char *indomain
, const char *inmap
, char **outkey
,
462 int *outkeylen
, char **outval
, int *outvallen
)
466 enum clnt_stat result
;
468 if (indomain
== NULL
|| indomain
[0] == '\0' ||
469 inmap
== NULL
|| inmap
[0] == '\0')
470 return YPERR_BADARGS
;
472 req
.domain
= (char *) indomain
;
473 req
.map
= (char *) inmap
;
475 *outkey
= *outval
= NULL
;
476 *outkeylen
= *outvallen
= 0;
477 memset (&resp
, '\0', sizeof (resp
));
479 result
= do_ypcall (indomain
, YPPROC_FIRST
, (xdrproc_t
) xdr_ypreq_nokey
,
480 (caddr_t
) & req
, (xdrproc_t
) xdr_ypresp_key_val
,
483 if (result
!= RPC_SUCCESS
)
485 if (resp
.stat
!= YP_TRUE
)
486 return ypprot_err (resp
.stat
);
488 *outkeylen
= resp
.key
.keydat_len
;
489 *outkey
= malloc (*outkeylen
+ 1);
490 if (__builtin_expect (*outkey
== NULL
, 0))
492 memcpy (*outkey
, resp
.key
.keydat_val
, *outkeylen
);
493 (*outkey
)[*outkeylen
] = '\0';
494 *outvallen
= resp
.val
.valdat_len
;
495 *outval
= malloc (*outvallen
+ 1);
496 if (__builtin_expect (*outval
== NULL
, 0))
498 memcpy (*outval
, resp
.val
.valdat_val
, *outvallen
);
499 (*outval
)[*outvallen
] = '\0';
501 xdr_free ((xdrproc_t
) xdr_ypresp_key_val
, (char *) &resp
);
503 return YPERR_SUCCESS
;
507 yp_next (const char *indomain
, const char *inmap
, const char *inkey
,
508 const int inkeylen
, char **outkey
, int *outkeylen
, char **outval
,
513 enum clnt_stat result
;
515 if (indomain
== NULL
|| indomain
[0] == '\0' ||
516 inmap
== NULL
|| inmap
[0] == '\0' ||
517 inkeylen
<= 0 || inkey
== NULL
|| inkey
[0] == '\0')
518 return YPERR_BADARGS
;
520 req
.domain
= (char *) indomain
;
521 req
.map
= (char *) inmap
;
522 req
.key
.keydat_val
= (char *) inkey
;
523 req
.key
.keydat_len
= inkeylen
;
525 *outkey
= *outval
= NULL
;
526 *outkeylen
= *outvallen
= 0;
527 memset (&resp
, '\0', sizeof (resp
));
529 result
= do_ypcall (indomain
, YPPROC_NEXT
, (xdrproc_t
) xdr_ypreq_key
,
530 (caddr_t
) & req
, (xdrproc_t
) xdr_ypresp_key_val
,
533 if (result
!= YPERR_SUCCESS
)
535 if (resp
.stat
!= YP_TRUE
)
536 return ypprot_err (resp
.stat
);
538 *outkeylen
= resp
.key
.keydat_len
;
539 *outkey
= malloc (*outkeylen
+ 1);
540 if (__builtin_expect (*outkey
== NULL
, 0))
542 memcpy (*outkey
, resp
.key
.keydat_val
, *outkeylen
);
543 (*outkey
)[*outkeylen
] = '\0';
544 *outvallen
= resp
.val
.valdat_len
;
545 *outval
= malloc (*outvallen
+ 1);
546 if (__builtin_expect (*outval
== NULL
, 0))
548 memcpy (*outval
, resp
.val
.valdat_val
, *outvallen
);
549 (*outval
)[*outvallen
] = '\0';
551 xdr_free ((xdrproc_t
) xdr_ypresp_key_val
, (char *) &resp
);
553 return YPERR_SUCCESS
;
557 yp_master (const char *indomain
, const char *inmap
, char **outname
)
561 enum clnt_stat result
;
563 if (indomain
== NULL
|| indomain
[0] == '\0' ||
564 inmap
== NULL
|| inmap
[0] == '\0')
565 return YPERR_BADARGS
;
567 req
.domain
= (char *) indomain
;
568 req
.map
= (char *) inmap
;
570 memset (&resp
, '\0', sizeof (ypresp_master
));
572 result
= do_ypcall (indomain
, YPPROC_MASTER
, (xdrproc_t
) xdr_ypreq_nokey
,
573 (caddr_t
) & req
, (xdrproc_t
) xdr_ypresp_master
, (caddr_t
) & resp
);
575 if (result
!= YPERR_SUCCESS
)
577 if (resp
.stat
!= YP_TRUE
)
578 return ypprot_err (resp
.stat
);
580 *outname
= strdup (resp
.peer
);
581 xdr_free ((xdrproc_t
) xdr_ypresp_master
, (char *) &resp
);
583 return *outname
== NULL
? YPERR_YPERR
: YPERR_SUCCESS
;
585 libnsl_hidden_def (yp_master
)
588 yp_order (const char *indomain
, const char *inmap
, unsigned int *outorder
)
590 struct ypreq_nokey req
;
591 struct ypresp_order resp
;
592 enum clnt_stat result
;
594 if (indomain
== NULL
|| indomain
[0] == '\0' ||
595 inmap
== NULL
|| inmap
== '\0')
596 return YPERR_BADARGS
;
598 req
.domain
= (char *) indomain
;
599 req
.map
= (char *) inmap
;
601 memset (&resp
, '\0', sizeof (resp
));
603 result
= do_ypcall (indomain
, YPPROC_ORDER
, (xdrproc_t
) xdr_ypreq_nokey
,
604 (caddr_t
) & req
, (xdrproc_t
) xdr_ypresp_order
, (caddr_t
) & resp
);
606 if (result
!= YPERR_SUCCESS
)
608 if (resp
.stat
!= YP_TRUE
)
609 return ypprot_err (resp
.stat
);
611 *outorder
= resp
.ordernum
;
612 xdr_free ((xdrproc_t
) xdr_ypresp_order
, (char *) &resp
);
614 return YPERR_SUCCESS
;
617 struct ypresp_all_data
619 unsigned long status
;
621 int (*foreach
) (int status
, char *key
, int keylen
,
622 char *val
, int vallen
, char *data
);
626 __xdr_ypresp_all (XDR
*xdrs
, struct ypresp_all_data
*objp
)
630 struct ypresp_all resp
;
632 memset (&resp
, '\0', sizeof (struct ypresp_all
));
633 if (!xdr_ypresp_all (xdrs
, &resp
))
635 xdr_free ((xdrproc_t
) xdr_ypresp_all
, (char *) &resp
);
636 objp
->status
= YP_YPERR
;
641 xdr_free ((xdrproc_t
) xdr_ypresp_all
, (char *) &resp
);
642 objp
->status
= YP_NOMORE
;
646 switch (resp
.ypresp_all_u
.val
.stat
)
650 char key
[resp
.ypresp_all_u
.val
.key
.keydat_len
+ 1];
651 char val
[resp
.ypresp_all_u
.val
.val
.valdat_len
+ 1];
652 int keylen
= resp
.ypresp_all_u
.val
.key
.keydat_len
;
653 int vallen
= resp
.ypresp_all_u
.val
.val
.valdat_len
;
655 /* We are not allowed to modify the key and val data.
656 But we are allowed to add data behind the buffer,
657 if we don't modify the length. So add an extra NUL
658 character to avoid trouble with broken code. */
659 objp
->status
= YP_TRUE
;
660 memcpy (key
, resp
.ypresp_all_u
.val
.key
.keydat_val
, keylen
);
662 memcpy (val
, resp
.ypresp_all_u
.val
.val
.valdat_val
, vallen
);
664 xdr_free ((xdrproc_t
) xdr_ypresp_all
, (char *) &resp
);
665 if ((*objp
->foreach
) (objp
->status
, key
, keylen
,
666 val
, vallen
, objp
->data
))
671 objp
->status
= resp
.ypresp_all_u
.val
.stat
;
672 xdr_free ((xdrproc_t
) xdr_ypresp_all
, (char *) &resp
);
673 /* Sun says we don't need to make this call, but must return
674 immediatly. Since Solaris makes this call, we will call
675 the callback function, too. */
676 (*objp
->foreach
) (objp
->status
, NULL
, 0, NULL
, 0, objp
->data
);
683 yp_all (const char *indomain
, const char *inmap
,
684 const struct ypall_callback
*incallback
)
686 struct ypreq_nokey req
;
687 dom_binding
*ydb
= NULL
;
689 enum clnt_stat result
;
690 struct sockaddr_in clnt_sin
;
692 struct ypresp_all_data data
;
694 int saved_errno
= errno
;
696 if (indomain
== NULL
|| indomain
[0] == '\0' ||
697 inmap
== NULL
|| inmap
== '\0')
698 return YPERR_BADARGS
;
703 while (try < MAXTRIES
&& res
!= YPERR_SUCCESS
)
705 if (__yp_bind (indomain
, &ydb
) != 0)
707 __set_errno (saved_errno
);
711 clnt_sock
= RPC_ANYSOCK
;
712 clnt_sin
= ydb
->dom_server_addr
;
713 clnt_sin
.sin_port
= 0;
715 /* We don't need the UDP connection anymore. */
719 clnt
= clnttcp_create (&clnt_sin
, YPPROG
, YPVERS
, &clnt_sock
, 0, 0);
722 __set_errno (saved_errno
);
725 req
.domain
= (char *) indomain
;
726 req
.map
= (char *) inmap
;
728 data
.foreach
= incallback
->foreach
;
729 data
.data
= (void *) incallback
->data
;
731 result
= clnt_call (clnt
, YPPROC_ALL
, (xdrproc_t
) xdr_ypreq_nokey
,
732 (caddr_t
) &req
, (xdrproc_t
) __xdr_ypresp_all
,
733 (caddr_t
) &data
, RPCTIMEOUT
);
735 if (result
!= RPC_SUCCESS
)
737 /* Print the error message only on the last try */
738 if (try == MAXTRIES
- 1)
739 clnt_perror (clnt
, "yp_all: clnt_call");
747 if (res
== YPERR_SUCCESS
&& data
.status
!= YP_NOMORE
)
749 __set_errno (saved_errno
);
750 return ypprot_err (data
.status
);
755 __set_errno (saved_errno
);
761 yp_maplist (const char *indomain
, struct ypmaplist
**outmaplist
)
763 struct ypresp_maplist resp
;
764 enum clnt_stat result
;
766 if (indomain
== NULL
|| indomain
[0] == '\0')
767 return YPERR_BADARGS
;
769 memset (&resp
, '\0', sizeof (resp
));
771 result
= do_ypcall (indomain
, YPPROC_MAPLIST
, (xdrproc_t
) xdr_domainname
,
772 (caddr_t
) & indomain
, (xdrproc_t
) xdr_ypresp_maplist
, (caddr_t
) & resp
);
774 if (result
!= YPERR_SUCCESS
)
776 if (resp
.stat
!= YP_TRUE
)
777 return ypprot_err (resp
.stat
);
779 *outmaplist
= resp
.maps
;
780 /* We give the list not free, this will be done by ypserv
781 xdr_free((xdrproc_t)xdr_ypresp_maplist, (char *)&resp); */
783 return YPERR_SUCCESS
;
787 yperr_string (const int error
)
794 return _("Request arguments bad");
796 return _("RPC failure on NIS operation");
798 return _("Can't bind to server which serves this domain");
800 return _("No such map in server's domain");
802 return _("No such key in map");
804 return _("Internal NIS error");
806 return _("Local resource allocation failure");
808 return _("No more records in map database");
810 return _("Can't communicate with portmapper");
812 return _("Can't communicate with ypbind");
814 return _("Can't communicate with ypserv");
816 return _("Local domain name not set");
818 return _("NIS map database is bad");
820 return _("NIS client/server version mismatch - can't supply service");
822 return _("Permission denied");
824 return _("Database is busy");
826 return _("Unknown NIS error code");
829 static const int8_t yp_2_yperr
[] =
831 #define YP2YPERR(yp, yperr) [YP_##yp - YP_VERS] = YPERR_##yperr
832 YP2YPERR (NOKEY
, KEY
),
833 YP2YPERR (BADOP
, YPERR
),
834 YP2YPERR (BADDB
, BADDB
),
835 YP2YPERR (YPERR
, YPERR
),
836 YP2YPERR (BADARGS
, BADARGS
),
837 YP2YPERR (VERS
, VERS
)
840 ypprot_err (const int code
)
842 if (code
< YP_VERS
|| code
> YP_NOKEY
)
844 return yp_2_yperr
[code
- YP_VERS
];
846 libnsl_hidden_def (ypprot_err
)
849 ypbinderr_string (const int error
)
856 return _("Internal ypbind error");
857 case YPBIND_ERR_NOSERV
:
858 return _("Domain not bound");
859 case YPBIND_ERR_RESC
:
860 return _("System resource allocation failure");
862 return _("Unknown ypbind error");
865 libnsl_hidden_def (ypbinderr_string
)
870 yp_update (char *domain
, char *map
, unsigned ypop
,
871 char *key
, int keylen
, char *data
, int datalen
)
875 ypupdate_args update_args
;
876 ypdelete_args delete_args
;
879 xdrproc_t xdr_argument
;
883 struct sockaddr saddr
;
884 char servername
[MAXNETNAMELEN
+ 1];
887 if (!domain
|| !map
|| !key
|| (ypop
!= YPOP_DELETE
&& !data
))
888 return YPERR_BADARGS
;
890 args
.update_args
.mapname
= map
;
891 args
.update_args
.key
.yp_buf_len
= keylen
;
892 args
.update_args
.key
.yp_buf_val
= key
;
893 args
.update_args
.datum
.yp_buf_len
= datalen
;
894 args
.update_args
.datum
.yp_buf_val
= data
;
896 if ((r
= yp_master (domain
, map
, &master
)) != 0)
899 if (!host2netname (servername
, master
, domain
))
901 fputs (_("yp_update: cannot convert host to netname\n"), stderr
);
905 if ((clnt
= clnt_create (master
, YPU_PROG
, YPU_VERS
, "tcp")) == NULL
)
907 clnt_pcreateerror ("yp_update: clnt_create");
911 if (!clnt_control (clnt
, CLGET_SERVER_ADDR
, (char *) &saddr
))
913 fputs (_("yp_update: cannot get server address\n"), stderr
);
922 xdr_argument
= (xdrproc_t
) xdr_ypupdate_args
;
925 xdr_argument
= (xdrproc_t
) xdr_ypdelete_args
;
928 return YPERR_BADARGS
;
932 clnt
->cl_auth
= authdes_create (servername
, WINDOW
, &saddr
, NULL
);
934 if (clnt
->cl_auth
== NULL
)
935 clnt
->cl_auth
= authunix_create_default ();
938 r
= clnt_call (clnt
, ypop
, xdr_argument
, (caddr_t
) &args
,
939 (xdrproc_t
) xdr_u_int
, (caddr_t
) &res
, RPCTIMEOUT
);
941 if (r
== RPC_AUTHERROR
)
943 if (clnt
->cl_auth
->ah_cred
.oa_flavor
== AUTH_DES
)
945 clnt
->cl_auth
= authunix_create_default ();
951 if (r
!= RPC_SUCCESS
)
953 clnt_perror (clnt
, "yp_update: clnt_call");