1 /* Copyright (C) 1996-2001, 2002, 2003, 2004, 2005, 2006, 2008
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, see
18 <http://www.gnu.org/licenses/>. */
26 #include <rpcsvc/nis.h>
27 #include <rpcsvc/yp.h>
28 #include <rpcsvc/ypclnt.h>
29 #include <rpcsvc/ypupd.h>
30 #include <sys/socket.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 const struct timeval RPCTIMEOUT
= {25, 0};
50 static const struct timeval UDPTIMEOUT
= {5, 0};
51 static int const MAXTRIES
= 2;
52 static char ypdomainname
[NIS_MAXNAMELEN
+ 1];
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
;
73 # define xflags SOCK_CLOEXEC
77 ysd
->dom_client
= __libc_clntudp_bufcreate (&ysd
->dom_server_addr
, YPPROG
,
80 UDPMSGSIZE
, UDPMSGSIZE
,
83 if (ysd
->dom_client
!= NULL
)
86 /* If the program exits, close the socket */
87 if (fcntl (ysd
->dom_socket
, F_SETFD
, FD_CLOEXEC
) == -1)
88 perror ("fcntl: F_SETFD");
95 yp_bind_file (const char *domain
, dom_binding
*ysd
)
97 char path
[sizeof (BINDINGDIR
) + strlen (domain
) + 3 * sizeof (unsigned) + 3];
99 snprintf (path
, sizeof (path
), "%s/%s.%u", BINDINGDIR
, domain
, YPBINDVERS
);
100 int fd
= open (path
, O_RDONLY
);
103 /* We have a binding file and could save a RPC call. The file
104 contains a port number and the YPBIND_RESP record. The port
105 number (16 bits) can be ignored. */
106 struct ypbind_resp ypbr
;
108 if (pread (fd
, &ypbr
, sizeof (ypbr
), 2) == sizeof (ypbr
))
109 yp_bind_client_create (domain
, ysd
, &ypbr
);
117 yp_bind_ypbindprog (const char *domain
, dom_binding
*ysd
)
119 struct sockaddr_in clnt_saddr
;
120 struct ypbind_resp ypbr
;
124 clnt_saddr
.sin_family
= AF_INET
;
125 clnt_saddr
.sin_port
= 0;
126 clnt_saddr
.sin_addr
.s_addr
= htonl (INADDR_LOOPBACK
);
127 clnt_sock
= RPC_ANYSOCK
;
128 client
= clnttcp_create (&clnt_saddr
, YPBINDPROG
, YPBINDVERS
,
133 /* Check the port number -- should be < IPPORT_RESERVED.
134 If not, it's possible someone has registered a bogus
135 ypbind with the portmapper and is trying to trick us. */
136 if (ntohs (clnt_saddr
.sin_port
) >= IPPORT_RESERVED
)
138 clnt_destroy (client
);
142 if (clnt_call (client
, YPBINDPROC_DOMAIN
,
143 (xdrproc_t
) xdr_domainname
, (caddr_t
) &domain
,
144 (xdrproc_t
) xdr_ypbind_resp
,
145 (caddr_t
) &ypbr
, RPCTIMEOUT
) != RPC_SUCCESS
)
147 clnt_destroy (client
);
151 clnt_destroy (client
);
153 if (ypbr
.ypbind_status
!= YPBIND_SUCC_VAL
)
155 fprintf (stderr
, "YPBINDPROC_DOMAIN: %s\n",
156 ypbinderr_string (ypbr
.ypbind_resp_u
.ypbind_error
));
159 memset (&ysd
->dom_server_addr
, '\0', sizeof ysd
->dom_server_addr
);
161 yp_bind_client_create (domain
, ysd
, &ypbr
);
163 return YPERR_SUCCESS
;
167 __yp_bind (const char *domain
, dom_binding
**ypdb
)
169 dom_binding
*ysd
= NULL
;
172 if (domain
== NULL
|| domain
[0] == '\0')
173 return YPERR_BADARGS
;
178 if (strcmp (domain
, ysd
->dom_domain
) == 0)
180 ysd
= ysd
->dom_pnext
;
186 ysd
= (dom_binding
*) calloc (1, sizeof *ysd
);
187 if (__builtin_expect (ysd
== NULL
, 0))
192 /* Try binding dir at first if we have no binding */
193 if (ysd
->dom_client
== NULL
)
194 yp_bind_file (domain
, ysd
);
195 #endif /* USE_BINDINGDIR */
197 if (ysd
->dom_client
== NULL
)
199 int retval
= yp_bind_ypbindprog (domain
, ysd
);
200 if (retval
!= YPERR_SUCCESS
)
208 if (ysd
->dom_client
== NULL
)
217 ysd
->dom_pnext
= *ypdb
;
221 return YPERR_SUCCESS
;
225 __yp_unbind (dom_binding
*ydb
)
227 clnt_destroy (ydb
->dom_client
);
232 yp_bind (const char *indomain
)
236 __libc_lock_lock (ypbindlist_lock
);
238 status
= __yp_bind (indomain
, &ypbindlist
);
240 __libc_lock_unlock (ypbindlist_lock
);
244 libnsl_hidden_def (yp_bind
)
247 yp_unbind_locked (const char *indomain
)
249 dom_binding
*ydbptr
, *ydbptr2
;
254 while (ydbptr
!= NULL
)
256 if (strcmp (ydbptr
->dom_domain
, indomain
) == 0)
262 ypbindlist
= ypbindlist
->dom_pnext
;
264 ydbptr2
= ydbptr
->dom_pnext
;
269 ydbptr
= ydbptr
->dom_pnext
;
274 yp_unbind (const char *indomain
)
276 __libc_lock_lock (ypbindlist_lock
);
278 yp_unbind_locked (indomain
);
280 __libc_lock_unlock (ypbindlist_lock
);
286 __ypclnt_call (const char *domain
, u_long prog
, xdrproc_t xargs
,
287 caddr_t req
, xdrproc_t xres
, caddr_t resp
, dom_binding
**ydb
,
290 enum clnt_stat result
;
292 result
= clnt_call ((*ydb
)->dom_client
, prog
,
293 xargs
, req
, xres
, resp
, RPCTIMEOUT
);
295 if (result
!= RPC_SUCCESS
)
297 /* We don't print an error message, if we try our old,
298 cached data. Only print this for data, which should work. */
300 clnt_perror ((*ydb
)->dom_client
, "do_ypcall: clnt_call");
305 return YPERR_SUCCESS
;
309 do_ypcall (const char *domain
, u_long prog
, xdrproc_t xargs
,
310 caddr_t req
, xdrproc_t xres
, caddr_t resp
)
314 int saved_errno
= errno
;
316 status
= YPERR_YPERR
;
318 __libc_lock_lock (ypbindlist_lock
);
322 if (strcmp (domain
, ydb
->dom_domain
) == 0)
324 if (__yp_bind (domain
, &ydb
) == 0)
326 /* Call server, print no error message, do not unbind. */
327 status
= __ypclnt_call (domain
, prog
, xargs
, req
, xres
,
329 if (status
== YPERR_SUCCESS
)
331 __libc_lock_unlock (ypbindlist_lock
);
332 __set_errno (saved_errno
);
336 /* We use ypbindlist, and the old cached data is
337 invalid. unbind now and create a new binding */
338 yp_unbind_locked (domain
);
342 ydb
= ydb
->dom_pnext
;
344 __libc_lock_unlock (ypbindlist_lock
);
346 /* First try with cached data failed. Now try to get
347 current data from the system. */
349 if (__yp_bind (domain
, &ydb
) == 0)
351 status
= __ypclnt_call (domain
, prog
, xargs
, req
, xres
,
357 /* If we support binding dir data, we have a third chance:
359 if (status
!= YPERR_SUCCESS
)
361 ydb
= calloc (1, sizeof (dom_binding
));
362 if (ydb
!= NULL
&& yp_bind_ypbindprog (domain
, ydb
) == YPERR_SUCCESS
)
364 status
= __ypclnt_call (domain
, prog
, xargs
, req
, xres
,
373 __set_errno (saved_errno
);
378 /* Like do_ypcall, but translate the status value if necessary. */
380 do_ypcall_tr (const char *domain
, u_long prog
, xdrproc_t xargs
,
381 caddr_t req
, xdrproc_t xres
, caddr_t resp
)
383 int status
= do_ypcall (domain
, prog
, xargs
, req
, xres
, resp
);
384 if (status
== YPERR_SUCCESS
)
385 /* We cast to ypresp_val although the pointer could also be of
386 type ypresp_key_val or ypresp_master or ypresp_order or
387 ypresp_maplist. But the stat element is in a common prefix so
388 this does not matter. */
389 status
= ypprot_err (((struct ypresp_val
*) resp
)->stat
);
394 __libc_lock_define_initialized (static, domainname_lock
)
397 yp_get_default_domain (char **outdomain
)
399 int result
= YPERR_SUCCESS
;;
402 __libc_lock_lock (domainname_lock
);
404 if (ypdomainname
[0] == '\0')
406 if (getdomainname (ypdomainname
, NIS_MAXNAMELEN
))
407 result
= YPERR_NODOM
;
408 else if (strcmp (ypdomainname
, "(none)") == 0)
410 /* If domainname is not set, some systems will return "(none)" */
411 ypdomainname
[0] = '\0';
412 result
= YPERR_NODOM
;
415 *outdomain
= ypdomainname
;
418 *outdomain
= ypdomainname
;
420 __libc_lock_unlock (domainname_lock
);
424 libnsl_hidden_def (yp_get_default_domain
)
427 __yp_check (char **domain
)
431 if (ypdomainname
[0] == '\0')
432 if (yp_get_default_domain (&unused
))
436 *domain
= ypdomainname
;
438 if (yp_bind (ypdomainname
) == 0)
444 yp_match (const char *indomain
, const char *inmap
, const char *inkey
,
445 const int inkeylen
, char **outval
, int *outvallen
)
449 enum clnt_stat result
;
451 if (indomain
== NULL
|| indomain
[0] == '\0' ||
452 inmap
== NULL
|| inmap
[0] == '\0' ||
453 inkey
== NULL
|| inkey
[0] == '\0' || inkeylen
<= 0)
454 return YPERR_BADARGS
;
456 req
.domain
= (char *) indomain
;
457 req
.map
= (char *) inmap
;
458 req
.key
.keydat_val
= (char *) inkey
;
459 req
.key
.keydat_len
= inkeylen
;
463 memset (&resp
, '\0', sizeof (resp
));
465 result
= do_ypcall_tr (indomain
, YPPROC_MATCH
, (xdrproc_t
) xdr_ypreq_key
,
466 (caddr_t
) &req
, (xdrproc_t
) xdr_ypresp_val
,
469 if (result
!= YPERR_SUCCESS
)
472 *outvallen
= resp
.val
.valdat_len
;
473 *outval
= malloc (*outvallen
+ 1);
474 int status
= YPERR_RESRC
;
475 if (__builtin_expect (*outval
!= NULL
, 1))
477 memcpy (*outval
, resp
.val
.valdat_val
, *outvallen
);
478 (*outval
)[*outvallen
] = '\0';
479 status
= YPERR_SUCCESS
;
482 xdr_free ((xdrproc_t
) xdr_ypresp_val
, (char *) &resp
);
488 yp_first (const char *indomain
, const char *inmap
, char **outkey
,
489 int *outkeylen
, char **outval
, int *outvallen
)
493 enum clnt_stat result
;
495 if (indomain
== NULL
|| indomain
[0] == '\0' ||
496 inmap
== NULL
|| inmap
[0] == '\0')
497 return YPERR_BADARGS
;
499 req
.domain
= (char *) indomain
;
500 req
.map
= (char *) inmap
;
502 *outkey
= *outval
= NULL
;
503 *outkeylen
= *outvallen
= 0;
504 memset (&resp
, '\0', sizeof (resp
));
506 result
= do_ypcall (indomain
, YPPROC_FIRST
, (xdrproc_t
) xdr_ypreq_nokey
,
507 (caddr_t
) &req
, (xdrproc_t
) xdr_ypresp_key_val
,
510 if (result
!= RPC_SUCCESS
)
512 if (resp
.stat
!= YP_TRUE
)
513 return ypprot_err (resp
.stat
);
516 if (__builtin_expect ((*outkey
= malloc (resp
.key
.keydat_len
+ 1)) != NULL
517 && (*outval
= malloc (resp
.val
.valdat_len
520 *outkeylen
= resp
.key
.keydat_len
;
521 memcpy (*outkey
, resp
.key
.keydat_val
, *outkeylen
);
522 (*outkey
)[*outkeylen
] = '\0';
524 *outvallen
= resp
.val
.valdat_len
;
525 memcpy (*outval
, resp
.val
.valdat_val
, *outvallen
);
526 (*outval
)[*outvallen
] = '\0';
528 status
= YPERR_SUCCESS
;
533 status
= YPERR_RESRC
;
536 xdr_free ((xdrproc_t
) xdr_ypresp_key_val
, (char *) &resp
);
542 yp_next (const char *indomain
, const char *inmap
, const char *inkey
,
543 const int inkeylen
, char **outkey
, int *outkeylen
, char **outval
,
548 enum clnt_stat result
;
550 if (indomain
== NULL
|| indomain
[0] == '\0' ||
551 inmap
== NULL
|| inmap
[0] == '\0' ||
552 inkeylen
<= 0 || inkey
== NULL
|| inkey
[0] == '\0')
553 return YPERR_BADARGS
;
555 req
.domain
= (char *) indomain
;
556 req
.map
= (char *) inmap
;
557 req
.key
.keydat_val
= (char *) inkey
;
558 req
.key
.keydat_len
= inkeylen
;
560 *outkey
= *outval
= NULL
;
561 *outkeylen
= *outvallen
= 0;
562 memset (&resp
, '\0', sizeof (resp
));
564 result
= do_ypcall_tr (indomain
, YPPROC_NEXT
, (xdrproc_t
) xdr_ypreq_key
,
565 (caddr_t
) &req
, (xdrproc_t
) xdr_ypresp_key_val
,
568 if (result
!= YPERR_SUCCESS
)
572 if (__builtin_expect ((*outkey
= malloc (resp
.key
.keydat_len
+ 1)) != NULL
573 && (*outval
= malloc (resp
.val
.valdat_len
576 *outkeylen
= resp
.key
.keydat_len
;
577 memcpy (*outkey
, resp
.key
.keydat_val
, *outkeylen
);
578 (*outkey
)[*outkeylen
] = '\0';
580 *outvallen
= resp
.val
.valdat_len
;
581 memcpy (*outval
, resp
.val
.valdat_val
, *outvallen
);
582 (*outval
)[*outvallen
] = '\0';
584 status
= YPERR_SUCCESS
;
589 status
= YPERR_RESRC
;
592 xdr_free ((xdrproc_t
) xdr_ypresp_key_val
, (char *) &resp
);
598 yp_master (const char *indomain
, const char *inmap
, char **outname
)
602 enum clnt_stat result
;
604 if (indomain
== NULL
|| indomain
[0] == '\0' ||
605 inmap
== NULL
|| inmap
[0] == '\0')
606 return YPERR_BADARGS
;
608 req
.domain
= (char *) indomain
;
609 req
.map
= (char *) inmap
;
611 memset (&resp
, '\0', sizeof (ypresp_master
));
613 result
= do_ypcall_tr (indomain
, YPPROC_MASTER
, (xdrproc_t
) xdr_ypreq_nokey
,
614 (caddr_t
) &req
, (xdrproc_t
) xdr_ypresp_master
,
617 if (result
!= YPERR_SUCCESS
)
620 *outname
= strdup (resp
.peer
);
621 xdr_free ((xdrproc_t
) xdr_ypresp_master
, (char *) &resp
);
623 return *outname
== NULL
? YPERR_YPERR
: YPERR_SUCCESS
;
625 libnsl_hidden_def (yp_master
)
628 yp_order (const char *indomain
, const char *inmap
, unsigned int *outorder
)
630 struct ypreq_nokey req
;
631 struct ypresp_order resp
;
632 enum clnt_stat result
;
634 if (indomain
== NULL
|| indomain
[0] == '\0' ||
635 inmap
== NULL
|| inmap
[0] == '\0')
636 return YPERR_BADARGS
;
638 req
.domain
= (char *) indomain
;
639 req
.map
= (char *) inmap
;
641 memset (&resp
, '\0', sizeof (resp
));
643 result
= do_ypcall_tr (indomain
, YPPROC_ORDER
, (xdrproc_t
) xdr_ypreq_nokey
,
644 (caddr_t
) &req
, (xdrproc_t
) xdr_ypresp_order
,
647 if (result
!= YPERR_SUCCESS
)
650 *outorder
= resp
.ordernum
;
651 xdr_free ((xdrproc_t
) xdr_ypresp_order
, (char *) &resp
);
656 struct ypresp_all_data
658 unsigned long status
;
660 int (*foreach
) (int status
, char *key
, int keylen
,
661 char *val
, int vallen
, char *data
);
665 __xdr_ypresp_all (XDR
*xdrs
, struct ypresp_all_data
*objp
)
669 struct ypresp_all resp
;
671 memset (&resp
, '\0', sizeof (struct ypresp_all
));
672 if (!xdr_ypresp_all (xdrs
, &resp
))
674 xdr_free ((xdrproc_t
) xdr_ypresp_all
, (char *) &resp
);
675 objp
->status
= YP_YPERR
;
680 xdr_free ((xdrproc_t
) xdr_ypresp_all
, (char *) &resp
);
681 objp
->status
= YP_NOMORE
;
685 switch (resp
.ypresp_all_u
.val
.stat
)
689 char key
[resp
.ypresp_all_u
.val
.key
.keydat_len
+ 1];
690 char val
[resp
.ypresp_all_u
.val
.val
.valdat_len
+ 1];
691 int keylen
= resp
.ypresp_all_u
.val
.key
.keydat_len
;
692 int vallen
= resp
.ypresp_all_u
.val
.val
.valdat_len
;
694 /* We are not allowed to modify the key and val data.
695 But we are allowed to add data behind the buffer,
696 if we don't modify the length. So add an extra NUL
697 character to avoid trouble with broken code. */
698 objp
->status
= YP_TRUE
;
699 *((char *) __mempcpy (key
, resp
.ypresp_all_u
.val
.key
.keydat_val
,
701 *((char *) __mempcpy (val
, resp
.ypresp_all_u
.val
.val
.valdat_val
,
703 xdr_free ((xdrproc_t
) xdr_ypresp_all
, (char *) &resp
);
704 if ((*objp
->foreach
) (objp
->status
, key
, keylen
,
705 val
, vallen
, objp
->data
))
710 objp
->status
= resp
.ypresp_all_u
.val
.stat
;
711 xdr_free ((xdrproc_t
) xdr_ypresp_all
, (char *) &resp
);
712 /* Sun says we don't need to make this call, but must return
713 immediately. Since Solaris makes this call, we will call
714 the callback function, too. */
715 (*objp
->foreach
) (objp
->status
, NULL
, 0, NULL
, 0, objp
->data
);
722 yp_all (const char *indomain
, const char *inmap
,
723 const struct ypall_callback
*incallback
)
725 struct ypreq_nokey req
;
726 dom_binding
*ydb
= NULL
;
728 enum clnt_stat result
;
729 struct sockaddr_in clnt_sin
;
731 struct ypresp_all_data data
;
733 int saved_errno
= errno
;
735 if (indomain
== NULL
|| indomain
[0] == '\0'
736 || inmap
== NULL
|| inmap
[0] == '\0')
737 return YPERR_BADARGS
;
742 while (try < MAXTRIES
&& res
!= YPERR_SUCCESS
)
744 if (__yp_bind (indomain
, &ydb
) != 0)
746 __set_errno (saved_errno
);
750 clnt_sock
= RPC_ANYSOCK
;
751 clnt_sin
= ydb
->dom_server_addr
;
752 clnt_sin
.sin_port
= 0;
754 /* We don't need the UDP connection anymore. */
758 clnt
= clnttcp_create (&clnt_sin
, YPPROG
, YPVERS
, &clnt_sock
, 0, 0);
761 __set_errno (saved_errno
);
764 req
.domain
= (char *) indomain
;
765 req
.map
= (char *) inmap
;
767 data
.foreach
= incallback
->foreach
;
768 data
.data
= (void *) incallback
->data
;
770 result
= clnt_call (clnt
, YPPROC_ALL
, (xdrproc_t
) xdr_ypreq_nokey
,
771 (caddr_t
) &req
, (xdrproc_t
) __xdr_ypresp_all
,
772 (caddr_t
) &data
, RPCTIMEOUT
);
774 if (__builtin_expect (result
!= RPC_SUCCESS
, 0))
776 /* Print the error message only on the last try. */
777 if (try == MAXTRIES
- 1)
778 clnt_perror (clnt
, "yp_all: clnt_call");
786 if (res
== YPERR_SUCCESS
&& data
.status
!= YP_NOMORE
)
788 __set_errno (saved_errno
);
789 return ypprot_err (data
.status
);
794 __set_errno (saved_errno
);
801 yp_maplist (const char *indomain
, struct ypmaplist
**outmaplist
)
803 struct ypresp_maplist resp
;
804 enum clnt_stat result
;
806 if (indomain
== NULL
|| indomain
[0] == '\0')
807 return YPERR_BADARGS
;
809 memset (&resp
, '\0', sizeof (resp
));
811 result
= do_ypcall_tr (indomain
, YPPROC_MAPLIST
, (xdrproc_t
) xdr_domainname
,
812 (caddr_t
) &indomain
, (xdrproc_t
) xdr_ypresp_maplist
,
815 if (__builtin_expect (result
== YPERR_SUCCESS
, 1))
817 *outmaplist
= resp
.maps
;
818 /* We don't free the list, this will be done by ypserv
819 xdr_free((xdrproc_t)xdr_ypresp_maplist, (char *)&resp); */
826 yperr_string (const int error
)
835 str
= N_("Request arguments bad");
838 str
= N_("RPC failure on NIS operation");
841 str
= N_("Can't bind to server which serves this domain");
844 str
= N_("No such map in server's domain");
847 str
= N_("No such key in map");
850 str
= N_("Internal NIS error");
853 str
= N_("Local resource allocation failure");
856 str
= N_("No more records in map database");
859 str
= N_("Can't communicate with portmapper");
862 str
= N_("Can't communicate with ypbind");
865 str
= N_("Can't communicate with ypserv");
868 str
= N_("Local domain name not set");
871 str
= N_("NIS map database is bad");
874 str
= N_("NIS client/server version mismatch - can't supply service");
877 str
= N_("Permission denied");
880 str
= N_("Database is busy");
883 str
= N_("Unknown NIS error code");
889 static const int8_t yp_2_yperr
[] =
891 #define YP2YPERR(yp, yperr) [YP_##yp - YP_VERS] = YPERR_##yperr
892 YP2YPERR (TRUE
, SUCCESS
),
893 YP2YPERR (NOMORE
, NOMORE
),
894 YP2YPERR (FALSE
, YPERR
),
895 YP2YPERR (NOMAP
, MAP
),
896 YP2YPERR (NODOM
, DOMAIN
),
897 YP2YPERR (NOKEY
, KEY
),
898 YP2YPERR (BADOP
, YPERR
),
899 YP2YPERR (BADDB
, BADDB
),
900 YP2YPERR (YPERR
, YPERR
),
901 YP2YPERR (BADARGS
, BADARGS
),
902 YP2YPERR (VERS
, VERS
)
905 ypprot_err (const int code
)
907 if (code
< YP_VERS
|| code
> YP_NOMORE
)
909 return yp_2_yperr
[code
- YP_VERS
];
911 libnsl_hidden_def (ypprot_err
)
914 ypbinderr_string (const int error
)
923 str
= N_("Internal ypbind error");
925 case YPBIND_ERR_NOSERV
:
926 str
= N_("Domain not bound");
928 case YPBIND_ERR_RESC
:
929 str
= N_("System resource allocation failure");
932 str
= N_("Unknown ypbind error");
937 libnsl_hidden_def (ypbinderr_string
)
942 yp_update (char *domain
, char *map
, unsigned ypop
,
943 char *key
, int keylen
, char *data
, int datalen
)
947 ypupdate_args update_args
;
948 ypdelete_args delete_args
;
951 xdrproc_t xdr_argument
;
955 struct sockaddr saddr
;
956 char servername
[MAXNETNAMELEN
+ 1];
959 if (!domain
|| !map
|| !key
|| (ypop
!= YPOP_DELETE
&& !data
))
960 return YPERR_BADARGS
;
962 args
.update_args
.mapname
= map
;
963 args
.update_args
.key
.yp_buf_len
= keylen
;
964 args
.update_args
.key
.yp_buf_val
= key
;
965 args
.update_args
.datum
.yp_buf_len
= datalen
;
966 args
.update_args
.datum
.yp_buf_val
= data
;
968 if ((r
= yp_master (domain
, map
, &master
)) != YPERR_SUCCESS
)
971 if (!host2netname (servername
, master
, domain
))
973 fputs (_("yp_update: cannot convert host to netname\n"), stderr
);
978 clnt
= clnt_create (master
, YPU_PROG
, YPU_VERS
, "tcp");
980 /* We do not need the string anymore. */
985 clnt_pcreateerror ("yp_update: clnt_create");
989 if (!clnt_control (clnt
, CLGET_SERVER_ADDR
, (char *) &saddr
))
991 fputs (_("yp_update: cannot get server address\n"), stderr
);
1000 xdr_argument
= (xdrproc_t
) xdr_ypupdate_args
;
1003 xdr_argument
= (xdrproc_t
) xdr_ypdelete_args
;
1006 return YPERR_BADARGS
;
1010 clnt
->cl_auth
= authdes_create (servername
, WINDOW
, &saddr
, NULL
);
1012 if (clnt
->cl_auth
== NULL
)
1013 clnt
->cl_auth
= authunix_create_default ();
1016 r
= clnt_call (clnt
, ypop
, xdr_argument
, (caddr_t
) &args
,
1017 (xdrproc_t
) xdr_u_int
, (caddr_t
) &res
, RPCTIMEOUT
);
1019 if (r
== RPC_AUTHERROR
)
1021 if (clnt
->cl_auth
->ah_cred
.oa_flavor
== AUTH_DES
)
1023 auth_destroy (clnt
->cl_auth
);
1024 clnt
->cl_auth
= authunix_create_default ();
1028 return YPERR_ACCESS
;
1030 if (r
!= RPC_SUCCESS
)
1032 clnt_perror (clnt
, "yp_update: clnt_call");