1 /* Copyright (C) 1996-2001, 2002, 2003, 2004, 2005
2 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4 Contributed by Thorsten Kukuk <kukuk@suse.de>, 1996.
6 The GNU C Library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
11 The GNU C Library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public
17 License along with the GNU C Library; if not, write to the Free
18 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
27 #include <rpcsvc/nis.h>
28 #include <rpcsvc/yp.h>
29 #include <rpcsvc/ypclnt.h>
30 #include <rpcsvc/ypupd.h>
32 #include <bits/libc-lock.h>
34 /* This should only be defined on systems with a BSD compatible ypbind */
36 # define BINDINGDIR "/var/yp/binding"
41 struct dom_binding
*dom_pnext
;
42 char dom_domain
[YPMAXDOMAIN
+ 1];
43 struct sockaddr_in dom_server_addr
;
47 typedef struct dom_binding dom_binding
;
49 static struct timeval RPCTIMEOUT
= {25, 0};
50 static struct timeval UDPTIMEOUT
= {5, 0};
51 static int const MAXTRIES
= 2;
52 static char __ypdomainname
[NIS_MAXNAMELEN
+ 1] = "\0";
53 __libc_lock_define_initialized (static, ypbindlist_lock
)
54 static dom_binding
*__ypbindlist
= NULL
;
58 yp_bind_client_create (const char *domain
, dom_binding
*ysd
,
59 struct ypbind_resp
*ypbr
)
61 ysd
->dom_server_addr
.sin_family
= AF_INET
;
62 memcpy (&ysd
->dom_server_addr
.sin_port
,
63 ypbr
->ypbind_resp_u
.ypbind_bindinfo
.ypbind_binding_port
,
64 sizeof (ysd
->dom_server_addr
.sin_port
));
65 memcpy (&ysd
->dom_server_addr
.sin_addr
.s_addr
,
66 ypbr
->ypbind_resp_u
.ypbind_bindinfo
.ypbind_binding_addr
,
67 sizeof (ysd
->dom_server_addr
.sin_addr
.s_addr
));
68 strncpy (ysd
->dom_domain
, domain
, YPMAXDOMAIN
);
69 ysd
->dom_domain
[YPMAXDOMAIN
] = '\0';
71 ysd
->dom_socket
= RPC_ANYSOCK
;
72 ysd
->dom_client
= clntudp_create (&ysd
->dom_server_addr
, YPPROG
, YPVERS
,
73 UDPTIMEOUT
, &ysd
->dom_socket
);
75 if (ysd
->dom_client
!= NULL
)
77 /* If the program exits, close the socket */
78 if (fcntl (ysd
->dom_socket
, F_SETFD
, FD_CLOEXEC
) == -1)
79 perror ("fcntl: F_SETFD");
85 yp_bind_file (const char *domain
, dom_binding
*ysd
)
87 char path
[sizeof (BINDINGDIR
) + strlen (domain
) + 3 * sizeof (unsigned) + 3];
89 snprintf (path
, sizeof (path
), "%s/%s.%u", BINDINGDIR
, domain
, YPBINDVERS
);
90 int fd
= open (path
, O_RDONLY
);
93 /* We have a binding file and could save a RPC call. The file
94 contains a port number and the YPBIND_RESP record. The port
95 number (16 bits) can be ignored. */
96 struct ypbind_resp ypbr
;
98 if (pread (fd
, &ypbr
, sizeof (ypbr
), 2) == sizeof (ypbr
))
99 yp_bind_client_create (domain
, ysd
, &ypbr
);
107 yp_bind_ypbindprog (const char *domain
, dom_binding
*ysd
)
109 struct sockaddr_in clnt_saddr
;
110 struct ypbind_resp ypbr
;
114 memset (&clnt_saddr
, '\0', sizeof clnt_saddr
);
115 clnt_saddr
.sin_family
= AF_INET
;
116 clnt_saddr
.sin_addr
.s_addr
= htonl (INADDR_LOOPBACK
);
117 clnt_sock
= RPC_ANYSOCK
;
118 client
= clnttcp_create (&clnt_saddr
, YPBINDPROG
, YPBINDVERS
,
123 /* Check the port number -- should be < IPPORT_RESERVED.
124 If not, it's possible someone has registered a bogus
125 ypbind with the portmapper and is trying to trick us. */
126 if (ntohs (clnt_saddr
.sin_port
) >= IPPORT_RESERVED
)
128 clnt_destroy (client
);
132 if (clnt_call (client
, YPBINDPROC_DOMAIN
,
133 (xdrproc_t
) xdr_domainname
, (caddr_t
) &domain
,
134 (xdrproc_t
) xdr_ypbind_resp
,
135 (caddr_t
) &ypbr
, RPCTIMEOUT
) != RPC_SUCCESS
)
137 clnt_destroy (client
);
141 clnt_destroy (client
);
143 if (ypbr
.ypbind_status
!= YPBIND_SUCC_VAL
)
145 fprintf (stderr
, _("YPBINDPROC_DOMAIN: %s\n"),
146 ypbinderr_string (ypbr
.ypbind_resp_u
.ypbind_error
));
149 memset (&ysd
->dom_server_addr
, '\0', sizeof ysd
->dom_server_addr
);
151 yp_bind_client_create (domain
, ysd
, &ypbr
);
153 return YPERR_SUCCESS
;
157 __yp_bind (const char *domain
, dom_binding
**ypdb
)
159 dom_binding
*ysd
= NULL
;
162 if (domain
== NULL
|| domain
[0] == '\0')
163 return YPERR_BADARGS
;
168 if (strcmp (domain
, ysd
->dom_domain
) == 0)
170 ysd
= ysd
->dom_pnext
;
176 ysd
= (dom_binding
*) calloc (1, sizeof *ysd
);
177 if (__builtin_expect (ysd
== NULL
, 0))
182 /* Try binding dir at first if we have no binding */
183 if (ysd
->dom_client
== NULL
)
184 yp_bind_file (domain
, ysd
);
185 #endif /* USE_BINDINGDIR */
187 if (ysd
->dom_client
== NULL
)
189 int retval
= yp_bind_ypbindprog (domain
, ysd
);
190 if (retval
!= YPERR_SUCCESS
)
198 if (ysd
->dom_client
== NULL
)
207 ysd
->dom_pnext
= *ypdb
;
211 return YPERR_SUCCESS
;
215 __yp_unbind (dom_binding
*ydb
)
217 clnt_destroy (ydb
->dom_client
);
222 yp_bind (const char *indomain
)
226 __libc_lock_lock (ypbindlist_lock
);
228 status
= __yp_bind (indomain
, &__ypbindlist
);
230 __libc_lock_unlock (ypbindlist_lock
);
234 libnsl_hidden_def (yp_bind
)
237 yp_unbind_locked (const char *indomain
)
239 dom_binding
*ydbptr
, *ydbptr2
;
242 ydbptr
= __ypbindlist
;
244 while (ydbptr
!= NULL
)
246 if (strcmp (ydbptr
->dom_domain
, indomain
) == 0)
252 __ypbindlist
= __ypbindlist
->dom_pnext
;
254 ydbptr2
= ydbptr
->dom_pnext
;
259 ydbptr
= ydbptr
->dom_pnext
;
264 yp_unbind (const char *indomain
)
266 __libc_lock_lock (ypbindlist_lock
);
268 yp_unbind_locked (indomain
);
270 __libc_lock_unlock (ypbindlist_lock
);
276 __ypclnt_call (const char *domain
, u_long prog
, xdrproc_t xargs
,
277 caddr_t req
, xdrproc_t xres
, caddr_t resp
, dom_binding
**ydb
,
280 enum clnt_stat result
;
282 result
= clnt_call ((*ydb
)->dom_client
, prog
,
283 xargs
, req
, xres
, resp
, RPCTIMEOUT
);
285 if (result
!= RPC_SUCCESS
)
287 /* We don't print an error message, if we try our old,
288 cached data. Only print this for data, which should work. */
290 clnt_perror ((*ydb
)->dom_client
, "do_ypcall: clnt_call");
295 return YPERR_SUCCESS
;
299 do_ypcall (const char *domain
, u_long prog
, xdrproc_t xargs
,
300 caddr_t req
, xdrproc_t xres
, caddr_t resp
)
304 int saved_errno
= errno
;
306 status
= YPERR_YPERR
;
308 __libc_lock_lock (ypbindlist_lock
);
312 if (strcmp (domain
, ydb
->dom_domain
) == 0)
314 if (__yp_bind (domain
, &ydb
) == 0)
316 /* Call server, print no error message, do not unbind. */
317 status
= __ypclnt_call (domain
, prog
, xargs
, req
, xres
,
319 if (status
== YPERR_SUCCESS
)
321 __libc_lock_unlock (ypbindlist_lock
);
322 __set_errno (saved_errno
);
326 /* We use ypbindlist, and the old cached data is
327 invalid. unbind now and create a new binding */
328 yp_unbind_locked (domain
);
332 ydb
= ydb
->dom_pnext
;
334 __libc_lock_unlock (ypbindlist_lock
);
336 /* First try with cached data failed. Now try to get
337 current data from the system. */
339 if (__yp_bind (domain
, &ydb
) == 0)
341 status
= __ypclnt_call (domain
, prog
, xargs
, req
, xres
,
347 /* If we support binding dir data, we have a third chance:
349 if (status
!= YPERR_SUCCESS
)
351 ydb
= calloc (1, sizeof (dom_binding
));
352 if (yp_bind_ypbindprog (domain
, ydb
) == YPERR_SUCCESS
)
354 status
= __ypclnt_call (domain
, prog
, xargs
, req
, xres
,
363 __set_errno (saved_errno
);
369 __libc_lock_define_initialized (static, domainname_lock
)
372 yp_get_default_domain (char **outdomain
)
374 int result
= YPERR_SUCCESS
;;
377 __libc_lock_lock (domainname_lock
);
379 if (__ypdomainname
[0] == '\0')
381 if (getdomainname (__ypdomainname
, NIS_MAXNAMELEN
))
382 result
= YPERR_NODOM
;
383 else if (strcmp (__ypdomainname
, "(none)") == 0)
385 /* If domainname is not set, some systems will return "(none)" */
386 __ypdomainname
[0] = '\0';
387 result
= YPERR_NODOM
;
390 *outdomain
= __ypdomainname
;
393 *outdomain
= __ypdomainname
;
395 __libc_lock_unlock (domainname_lock
);
399 libnsl_hidden_def (yp_get_default_domain
)
402 __yp_check (char **domain
)
406 if (__ypdomainname
[0] == '\0')
407 if (yp_get_default_domain (&unused
))
411 *domain
= __ypdomainname
;
413 if (yp_bind (__ypdomainname
) == 0)
419 yp_match (const char *indomain
, const char *inmap
, const char *inkey
,
420 const int inkeylen
, char **outval
, int *outvallen
)
424 enum clnt_stat result
;
426 if (indomain
== NULL
|| indomain
[0] == '\0' ||
427 inmap
== NULL
|| inmap
[0] == '\0' ||
428 inkey
== NULL
|| inkey
[0] == '\0' || inkeylen
<= 0)
429 return YPERR_BADARGS
;
431 req
.domain
= (char *) indomain
;
432 req
.map
= (char *) inmap
;
433 req
.key
.keydat_val
= (char *) inkey
;
434 req
.key
.keydat_len
= inkeylen
;
438 memset (&resp
, '\0', sizeof (resp
));
440 result
= do_ypcall (indomain
, YPPROC_MATCH
, (xdrproc_t
) xdr_ypreq_key
,
441 (caddr_t
) & req
, (xdrproc_t
) xdr_ypresp_val
,
444 if (result
!= YPERR_SUCCESS
)
446 if (resp
.stat
!= YP_TRUE
)
447 return ypprot_err (resp
.stat
);
449 *outvallen
= resp
.val
.valdat_len
;
450 *outval
= malloc (*outvallen
+ 1);
451 if (__builtin_expect (*outval
== NULL
, 0))
453 memcpy (*outval
, resp
.val
.valdat_val
, *outvallen
);
454 (*outval
)[*outvallen
] = '\0';
456 xdr_free ((xdrproc_t
) xdr_ypresp_val
, (char *) &resp
);
458 return YPERR_SUCCESS
;
462 yp_first (const char *indomain
, const char *inmap
, char **outkey
,
463 int *outkeylen
, char **outval
, int *outvallen
)
467 enum clnt_stat result
;
469 if (indomain
== NULL
|| indomain
[0] == '\0' ||
470 inmap
== NULL
|| inmap
[0] == '\0')
471 return YPERR_BADARGS
;
473 req
.domain
= (char *) indomain
;
474 req
.map
= (char *) inmap
;
476 *outkey
= *outval
= NULL
;
477 *outkeylen
= *outvallen
= 0;
478 memset (&resp
, '\0', sizeof (resp
));
480 result
= do_ypcall (indomain
, YPPROC_FIRST
, (xdrproc_t
) xdr_ypreq_nokey
,
481 (caddr_t
) & req
, (xdrproc_t
) xdr_ypresp_key_val
,
484 if (result
!= RPC_SUCCESS
)
486 if (resp
.stat
!= YP_TRUE
)
487 return ypprot_err (resp
.stat
);
489 *outkeylen
= resp
.key
.keydat_len
;
490 *outkey
= malloc (*outkeylen
+ 1);
491 if (__builtin_expect (*outkey
== NULL
, 0))
493 memcpy (*outkey
, resp
.key
.keydat_val
, *outkeylen
);
494 (*outkey
)[*outkeylen
] = '\0';
495 *outvallen
= resp
.val
.valdat_len
;
496 *outval
= malloc (*outvallen
+ 1);
497 if (__builtin_expect (*outval
== NULL
, 0))
499 memcpy (*outval
, resp
.val
.valdat_val
, *outvallen
);
500 (*outval
)[*outvallen
] = '\0';
502 xdr_free ((xdrproc_t
) xdr_ypresp_key_val
, (char *) &resp
);
504 return YPERR_SUCCESS
;
508 yp_next (const char *indomain
, const char *inmap
, const char *inkey
,
509 const int inkeylen
, char **outkey
, int *outkeylen
, char **outval
,
514 enum clnt_stat result
;
516 if (indomain
== NULL
|| indomain
[0] == '\0' ||
517 inmap
== NULL
|| inmap
[0] == '\0' ||
518 inkeylen
<= 0 || inkey
== NULL
|| inkey
[0] == '\0')
519 return YPERR_BADARGS
;
521 req
.domain
= (char *) indomain
;
522 req
.map
= (char *) inmap
;
523 req
.key
.keydat_val
= (char *) inkey
;
524 req
.key
.keydat_len
= inkeylen
;
526 *outkey
= *outval
= NULL
;
527 *outkeylen
= *outvallen
= 0;
528 memset (&resp
, '\0', sizeof (resp
));
530 result
= do_ypcall (indomain
, YPPROC_NEXT
, (xdrproc_t
) xdr_ypreq_key
,
531 (caddr_t
) & req
, (xdrproc_t
) xdr_ypresp_key_val
,
534 if (result
!= YPERR_SUCCESS
)
536 if (resp
.stat
!= YP_TRUE
)
537 return ypprot_err (resp
.stat
);
539 *outkeylen
= resp
.key
.keydat_len
;
540 *outkey
= malloc (*outkeylen
+ 1);
541 if (__builtin_expect (*outkey
== NULL
, 0))
543 memcpy (*outkey
, resp
.key
.keydat_val
, *outkeylen
);
544 (*outkey
)[*outkeylen
] = '\0';
545 *outvallen
= resp
.val
.valdat_len
;
546 *outval
= malloc (*outvallen
+ 1);
547 if (__builtin_expect (*outval
== NULL
, 0))
549 memcpy (*outval
, resp
.val
.valdat_val
, *outvallen
);
550 (*outval
)[*outvallen
] = '\0';
552 xdr_free ((xdrproc_t
) xdr_ypresp_key_val
, (char *) &resp
);
554 return YPERR_SUCCESS
;
558 yp_master (const char *indomain
, const char *inmap
, char **outname
)
562 enum clnt_stat result
;
564 if (indomain
== NULL
|| indomain
[0] == '\0' ||
565 inmap
== NULL
|| inmap
[0] == '\0')
566 return YPERR_BADARGS
;
568 req
.domain
= (char *) indomain
;
569 req
.map
= (char *) inmap
;
571 memset (&resp
, '\0', sizeof (ypresp_master
));
573 result
= do_ypcall (indomain
, YPPROC_MASTER
, (xdrproc_t
) xdr_ypreq_nokey
,
574 (caddr_t
) & req
, (xdrproc_t
) xdr_ypresp_master
, (caddr_t
) & resp
);
576 if (result
!= YPERR_SUCCESS
)
578 if (resp
.stat
!= YP_TRUE
)
579 return ypprot_err (resp
.stat
);
581 *outname
= strdup (resp
.peer
);
582 xdr_free ((xdrproc_t
) xdr_ypresp_master
, (char *) &resp
);
584 return *outname
== NULL
? YPERR_YPERR
: YPERR_SUCCESS
;
586 libnsl_hidden_def (yp_master
)
589 yp_order (const char *indomain
, const char *inmap
, unsigned int *outorder
)
591 struct ypreq_nokey req
;
592 struct ypresp_order resp
;
593 enum clnt_stat result
;
595 if (indomain
== NULL
|| indomain
[0] == '\0' ||
596 inmap
== NULL
|| inmap
== '\0')
597 return YPERR_BADARGS
;
599 req
.domain
= (char *) indomain
;
600 req
.map
= (char *) inmap
;
602 memset (&resp
, '\0', sizeof (resp
));
604 result
= do_ypcall (indomain
, YPPROC_ORDER
, (xdrproc_t
) xdr_ypreq_nokey
,
605 (caddr_t
) & req
, (xdrproc_t
) xdr_ypresp_order
, (caddr_t
) & resp
);
607 if (result
!= YPERR_SUCCESS
)
609 if (resp
.stat
!= YP_TRUE
)
610 return ypprot_err (resp
.stat
);
612 *outorder
= resp
.ordernum
;
613 xdr_free ((xdrproc_t
) xdr_ypresp_order
, (char *) &resp
);
615 return YPERR_SUCCESS
;
618 struct ypresp_all_data
620 unsigned long status
;
622 int (*foreach
) (int status
, char *key
, int keylen
,
623 char *val
, int vallen
, char *data
);
627 __xdr_ypresp_all (XDR
*xdrs
, struct ypresp_all_data
*objp
)
631 struct ypresp_all resp
;
633 memset (&resp
, '\0', sizeof (struct ypresp_all
));
634 if (!xdr_ypresp_all (xdrs
, &resp
))
636 xdr_free ((xdrproc_t
) xdr_ypresp_all
, (char *) &resp
);
637 objp
->status
= YP_YPERR
;
642 xdr_free ((xdrproc_t
) xdr_ypresp_all
, (char *) &resp
);
643 objp
->status
= YP_NOMORE
;
647 switch (resp
.ypresp_all_u
.val
.stat
)
651 char key
[resp
.ypresp_all_u
.val
.key
.keydat_len
+ 1];
652 char val
[resp
.ypresp_all_u
.val
.val
.valdat_len
+ 1];
653 int keylen
= resp
.ypresp_all_u
.val
.key
.keydat_len
;
654 int vallen
= resp
.ypresp_all_u
.val
.val
.valdat_len
;
656 /* We are not allowed to modify the key and val data.
657 But we are allowed to add data behind the buffer,
658 if we don't modify the length. So add an extra NUL
659 character to avoid trouble with broken code. */
660 objp
->status
= YP_TRUE
;
661 memcpy (key
, resp
.ypresp_all_u
.val
.key
.keydat_val
, keylen
);
663 memcpy (val
, resp
.ypresp_all_u
.val
.val
.valdat_val
, vallen
);
665 xdr_free ((xdrproc_t
) xdr_ypresp_all
, (char *) &resp
);
666 if ((*objp
->foreach
) (objp
->status
, key
, keylen
,
667 val
, vallen
, objp
->data
))
672 objp
->status
= resp
.ypresp_all_u
.val
.stat
;
673 xdr_free ((xdrproc_t
) xdr_ypresp_all
, (char *) &resp
);
674 /* Sun says we don't need to make this call, but must return
675 immediatly. Since Solaris makes this call, we will call
676 the callback function, too. */
677 (*objp
->foreach
) (objp
->status
, NULL
, 0, NULL
, 0, objp
->data
);
684 yp_all (const char *indomain
, const char *inmap
,
685 const struct ypall_callback
*incallback
)
687 struct ypreq_nokey req
;
688 dom_binding
*ydb
= NULL
;
690 enum clnt_stat result
;
691 struct sockaddr_in clnt_sin
;
693 struct ypresp_all_data data
;
695 int saved_errno
= errno
;
697 if (indomain
== NULL
|| indomain
[0] == '\0' ||
698 inmap
== NULL
|| inmap
== '\0')
699 return YPERR_BADARGS
;
704 while (try < MAXTRIES
&& res
!= YPERR_SUCCESS
)
706 if (__yp_bind (indomain
, &ydb
) != 0)
708 __set_errno (saved_errno
);
712 clnt_sock
= RPC_ANYSOCK
;
713 clnt_sin
= ydb
->dom_server_addr
;
714 clnt_sin
.sin_port
= 0;
716 /* We don't need the UDP connection anymore. */
720 clnt
= clnttcp_create (&clnt_sin
, YPPROG
, YPVERS
, &clnt_sock
, 0, 0);
723 __set_errno (saved_errno
);
726 req
.domain
= (char *) indomain
;
727 req
.map
= (char *) inmap
;
729 data
.foreach
= incallback
->foreach
;
730 data
.data
= (void *) incallback
->data
;
732 result
= clnt_call (clnt
, YPPROC_ALL
, (xdrproc_t
) xdr_ypreq_nokey
,
733 (caddr_t
) &req
, (xdrproc_t
) __xdr_ypresp_all
,
734 (caddr_t
) &data
, RPCTIMEOUT
);
736 if (result
!= RPC_SUCCESS
)
738 /* Print the error message only on the last try */
739 if (try == MAXTRIES
- 1)
740 clnt_perror (clnt
, "yp_all: clnt_call");
748 if (res
== YPERR_SUCCESS
&& data
.status
!= YP_NOMORE
)
750 __set_errno (saved_errno
);
751 return ypprot_err (data
.status
);
756 __set_errno (saved_errno
);
762 yp_maplist (const char *indomain
, struct ypmaplist
**outmaplist
)
764 struct ypresp_maplist resp
;
765 enum clnt_stat result
;
767 if (indomain
== NULL
|| indomain
[0] == '\0')
768 return YPERR_BADARGS
;
770 memset (&resp
, '\0', sizeof (resp
));
772 result
= do_ypcall (indomain
, YPPROC_MAPLIST
, (xdrproc_t
) xdr_domainname
,
773 (caddr_t
) & indomain
, (xdrproc_t
) xdr_ypresp_maplist
, (caddr_t
) & resp
);
775 if (result
!= YPERR_SUCCESS
)
777 if (resp
.stat
!= YP_TRUE
)
778 return ypprot_err (resp
.stat
);
780 *outmaplist
= resp
.maps
;
781 /* We give the list not free, this will be done by ypserv
782 xdr_free((xdrproc_t)xdr_ypresp_maplist, (char *)&resp); */
784 return YPERR_SUCCESS
;
788 yperr_string (const int error
)
795 return _("Request arguments bad");
797 return _("RPC failure on NIS operation");
799 return _("Can't bind to server which serves this domain");
801 return _("No such map in server's domain");
803 return _("No such key in map");
805 return _("Internal NIS error");
807 return _("Local resource allocation failure");
809 return _("No more records in map database");
811 return _("Can't communicate with portmapper");
813 return _("Can't communicate with ypbind");
815 return _("Can't communicate with ypserv");
817 return _("Local domain name not set");
819 return _("NIS map database is bad");
821 return _("NIS client/server version mismatch - can't supply service");
823 return _("Permission denied");
825 return _("Database is busy");
827 return _("Unknown NIS error code");
830 static const int8_t yp_2_yperr
[] =
832 #define YP2YPERR(yp, yperr) [YP_##yp - YP_VERS] = YPERR_##yperr
833 YP2YPERR (TRUE
, SUCCESS
),
834 YP2YPERR (NOMORE
, NOMORE
),
835 YP2YPERR (FALSE
, YPERR
),
836 YP2YPERR (NOMAP
, MAP
),
837 YP2YPERR (NODOM
, DOMAIN
),
838 YP2YPERR (NOKEY
, KEY
),
839 YP2YPERR (BADOP
, YPERR
),
840 YP2YPERR (BADDB
, BADDB
),
841 YP2YPERR (YPERR
, YPERR
),
842 YP2YPERR (BADARGS
, BADARGS
),
843 YP2YPERR (VERS
, VERS
)
846 ypprot_err (const int code
)
848 if (code
< YP_VERS
|| code
> YP_NOMORE
)
850 return yp_2_yperr
[code
- YP_VERS
];
852 libnsl_hidden_def (ypprot_err
)
855 ypbinderr_string (const int error
)
862 return _("Internal ypbind error");
863 case YPBIND_ERR_NOSERV
:
864 return _("Domain not bound");
865 case YPBIND_ERR_RESC
:
866 return _("System resource allocation failure");
868 return _("Unknown ypbind error");
871 libnsl_hidden_def (ypbinderr_string
)
876 yp_update (char *domain
, char *map
, unsigned ypop
,
877 char *key
, int keylen
, char *data
, int datalen
)
881 ypupdate_args update_args
;
882 ypdelete_args delete_args
;
885 xdrproc_t xdr_argument
;
889 struct sockaddr saddr
;
890 char servername
[MAXNETNAMELEN
+ 1];
893 if (!domain
|| !map
|| !key
|| (ypop
!= YPOP_DELETE
&& !data
))
894 return YPERR_BADARGS
;
896 args
.update_args
.mapname
= map
;
897 args
.update_args
.key
.yp_buf_len
= keylen
;
898 args
.update_args
.key
.yp_buf_val
= key
;
899 args
.update_args
.datum
.yp_buf_len
= datalen
;
900 args
.update_args
.datum
.yp_buf_val
= data
;
902 if ((r
= yp_master (domain
, map
, &master
)) != 0)
905 if (!host2netname (servername
, master
, domain
))
907 fputs (_("yp_update: cannot convert host to netname\n"), stderr
);
911 if ((clnt
= clnt_create (master
, YPU_PROG
, YPU_VERS
, "tcp")) == NULL
)
913 clnt_pcreateerror ("yp_update: clnt_create");
917 if (!clnt_control (clnt
, CLGET_SERVER_ADDR
, (char *) &saddr
))
919 fputs (_("yp_update: cannot get server address\n"), stderr
);
928 xdr_argument
= (xdrproc_t
) xdr_ypupdate_args
;
931 xdr_argument
= (xdrproc_t
) xdr_ypdelete_args
;
934 return YPERR_BADARGS
;
938 clnt
->cl_auth
= authdes_create (servername
, WINDOW
, &saddr
, NULL
);
940 if (clnt
->cl_auth
== NULL
)
941 clnt
->cl_auth
= authunix_create_default ();
944 r
= clnt_call (clnt
, ypop
, xdr_argument
, (caddr_t
) &args
,
945 (xdrproc_t
) xdr_u_int
, (caddr_t
) &res
, RPCTIMEOUT
);
947 if (r
== RPC_AUTHERROR
)
949 if (clnt
->cl_auth
->ah_cred
.oa_flavor
== AUTH_DES
)
951 clnt
->cl_auth
= authunix_create_default ();
957 if (r
!= RPC_SUCCESS
)
959 clnt_perror (clnt
, "yp_update: clnt_call");