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, 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>
31 #include <sys/socket.h>
33 #include <bits/libc-lock.h>
35 /* This should only be defined on systems with a BSD compatible ypbind */
37 # define BINDINGDIR "/var/yp/binding"
42 struct dom_binding
*dom_pnext
;
43 char dom_domain
[YPMAXDOMAIN
+ 1];
44 struct sockaddr_in dom_server_addr
;
48 typedef struct dom_binding dom_binding
;
50 static const struct timeval RPCTIMEOUT
= {25, 0};
51 static const struct timeval UDPTIMEOUT
= {5, 0};
52 static int const MAXTRIES
= 2;
53 static char ypdomainname
[NIS_MAXNAMELEN
+ 1];
54 __libc_lock_define_initialized (static, ypbindlist_lock
)
55 static dom_binding
*ypbindlist
= NULL
;
59 yp_bind_client_create (const char *domain
, dom_binding
*ysd
,
60 struct ypbind_resp
*ypbr
)
62 ysd
->dom_server_addr
.sin_family
= AF_INET
;
63 memcpy (&ysd
->dom_server_addr
.sin_port
,
64 ypbr
->ypbind_resp_u
.ypbind_bindinfo
.ypbind_binding_port
,
65 sizeof (ysd
->dom_server_addr
.sin_port
));
66 memcpy (&ysd
->dom_server_addr
.sin_addr
.s_addr
,
67 ypbr
->ypbind_resp_u
.ypbind_bindinfo
.ypbind_binding_addr
,
68 sizeof (ysd
->dom_server_addr
.sin_addr
.s_addr
));
69 strncpy (ysd
->dom_domain
, domain
, YPMAXDOMAIN
);
70 ysd
->dom_domain
[YPMAXDOMAIN
] = '\0';
72 ysd
->dom_socket
= RPC_ANYSOCK
;
74 # define xflags SOCK_CLOEXEC
78 ysd
->dom_client
= __libc_clntudp_bufcreate (&ysd
->dom_server_addr
, YPPROG
,
81 UDPMSGSIZE
, UDPMSGSIZE
,
84 if (ysd
->dom_client
!= NULL
)
87 /* If the program exits, close the socket */
88 if (fcntl (ysd
->dom_socket
, F_SETFD
, FD_CLOEXEC
) == -1)
89 perror ("fcntl: F_SETFD");
96 yp_bind_file (const char *domain
, dom_binding
*ysd
)
98 char path
[sizeof (BINDINGDIR
) + strlen (domain
) + 3 * sizeof (unsigned) + 3];
100 snprintf (path
, sizeof (path
), "%s/%s.%u", BINDINGDIR
, domain
, YPBINDVERS
);
101 int fd
= open (path
, O_RDONLY
);
104 /* We have a binding file and could save a RPC call. The file
105 contains a port number and the YPBIND_RESP record. The port
106 number (16 bits) can be ignored. */
107 struct ypbind_resp ypbr
;
109 if (pread (fd
, &ypbr
, sizeof (ypbr
), 2) == sizeof (ypbr
))
110 yp_bind_client_create (domain
, ysd
, &ypbr
);
118 yp_bind_ypbindprog (const char *domain
, dom_binding
*ysd
)
120 struct sockaddr_in clnt_saddr
;
121 struct ypbind_resp ypbr
;
125 clnt_saddr
.sin_family
= AF_INET
;
126 clnt_saddr
.sin_port
= 0;
127 clnt_saddr
.sin_addr
.s_addr
= htonl (INADDR_LOOPBACK
);
128 clnt_sock
= RPC_ANYSOCK
;
129 client
= clnttcp_create (&clnt_saddr
, YPBINDPROG
, YPBINDVERS
,
134 /* Check the port number -- should be < IPPORT_RESERVED.
135 If not, it's possible someone has registered a bogus
136 ypbind with the portmapper and is trying to trick us. */
137 if (ntohs (clnt_saddr
.sin_port
) >= IPPORT_RESERVED
)
139 clnt_destroy (client
);
143 if (clnt_call (client
, YPBINDPROC_DOMAIN
,
144 (xdrproc_t
) xdr_domainname
, (caddr_t
) &domain
,
145 (xdrproc_t
) xdr_ypbind_resp
,
146 (caddr_t
) &ypbr
, RPCTIMEOUT
) != RPC_SUCCESS
)
148 clnt_destroy (client
);
152 clnt_destroy (client
);
154 if (ypbr
.ypbind_status
!= YPBIND_SUCC_VAL
)
156 fprintf (stderr
, "YPBINDPROC_DOMAIN: %s\n",
157 ypbinderr_string (ypbr
.ypbind_resp_u
.ypbind_error
));
160 memset (&ysd
->dom_server_addr
, '\0', sizeof ysd
->dom_server_addr
);
162 yp_bind_client_create (domain
, ysd
, &ypbr
);
164 return YPERR_SUCCESS
;
168 __yp_bind (const char *domain
, dom_binding
**ypdb
)
170 dom_binding
*ysd
= NULL
;
173 if (domain
== NULL
|| domain
[0] == '\0')
174 return YPERR_BADARGS
;
179 if (strcmp (domain
, ysd
->dom_domain
) == 0)
181 ysd
= ysd
->dom_pnext
;
187 ysd
= (dom_binding
*) calloc (1, sizeof *ysd
);
188 if (__builtin_expect (ysd
== NULL
, 0))
193 /* Try binding dir at first if we have no binding */
194 if (ysd
->dom_client
== NULL
)
195 yp_bind_file (domain
, ysd
);
196 #endif /* USE_BINDINGDIR */
198 if (ysd
->dom_client
== NULL
)
200 int retval
= yp_bind_ypbindprog (domain
, ysd
);
201 if (retval
!= YPERR_SUCCESS
)
209 if (ysd
->dom_client
== NULL
)
218 ysd
->dom_pnext
= *ypdb
;
222 return YPERR_SUCCESS
;
226 __yp_unbind (dom_binding
*ydb
)
228 clnt_destroy (ydb
->dom_client
);
233 yp_bind (const char *indomain
)
237 __libc_lock_lock (ypbindlist_lock
);
239 status
= __yp_bind (indomain
, &ypbindlist
);
241 __libc_lock_unlock (ypbindlist_lock
);
245 libnsl_hidden_def (yp_bind
)
248 yp_unbind_locked (const char *indomain
)
250 dom_binding
*ydbptr
, *ydbptr2
;
255 while (ydbptr
!= NULL
)
257 if (strcmp (ydbptr
->dom_domain
, indomain
) == 0)
263 ypbindlist
= ypbindlist
->dom_pnext
;
265 ydbptr2
= ydbptr
->dom_pnext
;
270 ydbptr
= ydbptr
->dom_pnext
;
275 yp_unbind (const char *indomain
)
277 __libc_lock_lock (ypbindlist_lock
);
279 yp_unbind_locked (indomain
);
281 __libc_lock_unlock (ypbindlist_lock
);
287 __ypclnt_call (const char *domain
, u_long prog
, xdrproc_t xargs
,
288 caddr_t req
, xdrproc_t xres
, caddr_t resp
, dom_binding
**ydb
,
291 enum clnt_stat result
;
293 result
= clnt_call ((*ydb
)->dom_client
, prog
,
294 xargs
, req
, xres
, resp
, RPCTIMEOUT
);
296 if (result
!= RPC_SUCCESS
)
298 /* We don't print an error message, if we try our old,
299 cached data. Only print this for data, which should work. */
301 clnt_perror ((*ydb
)->dom_client
, "do_ypcall: clnt_call");
306 return YPERR_SUCCESS
;
310 do_ypcall (const char *domain
, u_long prog
, xdrproc_t xargs
,
311 caddr_t req
, xdrproc_t xres
, caddr_t resp
)
315 int saved_errno
= errno
;
317 status
= YPERR_YPERR
;
319 __libc_lock_lock (ypbindlist_lock
);
323 if (strcmp (domain
, ydb
->dom_domain
) == 0)
325 if (__yp_bind (domain
, &ydb
) == 0)
327 /* Call server, print no error message, do not unbind. */
328 status
= __ypclnt_call (domain
, prog
, xargs
, req
, xres
,
330 if (status
== YPERR_SUCCESS
)
332 __libc_lock_unlock (ypbindlist_lock
);
333 __set_errno (saved_errno
);
337 /* We use ypbindlist, and the old cached data is
338 invalid. unbind now and create a new binding */
339 yp_unbind_locked (domain
);
343 ydb
= ydb
->dom_pnext
;
345 __libc_lock_unlock (ypbindlist_lock
);
347 /* First try with cached data failed. Now try to get
348 current data from the system. */
350 if (__yp_bind (domain
, &ydb
) == 0)
352 status
= __ypclnt_call (domain
, prog
, xargs
, req
, xres
,
358 /* If we support binding dir data, we have a third chance:
360 if (status
!= YPERR_SUCCESS
)
362 ydb
= calloc (1, sizeof (dom_binding
));
363 if (ydb
!= NULL
&& yp_bind_ypbindprog (domain
, ydb
) == YPERR_SUCCESS
)
365 status
= __ypclnt_call (domain
, prog
, xargs
, req
, xres
,
374 __set_errno (saved_errno
);
379 /* Like do_ypcall, but translate the status value if necessary. */
381 do_ypcall_tr (const char *domain
, u_long prog
, xdrproc_t xargs
,
382 caddr_t req
, xdrproc_t xres
, caddr_t resp
)
384 int status
= do_ypcall (domain
, prog
, xargs
, req
, xres
, resp
);
385 if (status
== YPERR_SUCCESS
)
386 /* We cast to ypresp_val although the pointer could also be of
387 type ypresp_key_val or ypresp_master or ypresp_order or
388 ypresp_maplist. But the stat element is in a common prefix so
389 this does not matter. */
390 status
= ypprot_err (((struct ypresp_val
*) resp
)->stat
);
395 __libc_lock_define_initialized (static, domainname_lock
)
398 yp_get_default_domain (char **outdomain
)
400 int result
= YPERR_SUCCESS
;;
403 __libc_lock_lock (domainname_lock
);
405 if (ypdomainname
[0] == '\0')
407 if (getdomainname (ypdomainname
, NIS_MAXNAMELEN
))
408 result
= YPERR_NODOM
;
409 else if (strcmp (ypdomainname
, "(none)") == 0)
411 /* If domainname is not set, some systems will return "(none)" */
412 ypdomainname
[0] = '\0';
413 result
= YPERR_NODOM
;
416 *outdomain
= ypdomainname
;
419 *outdomain
= ypdomainname
;
421 __libc_lock_unlock (domainname_lock
);
425 libnsl_hidden_def (yp_get_default_domain
)
428 __yp_check (char **domain
)
432 if (ypdomainname
[0] == '\0')
433 if (yp_get_default_domain (&unused
))
437 *domain
= ypdomainname
;
439 if (yp_bind (ypdomainname
) == 0)
445 yp_match (const char *indomain
, const char *inmap
, const char *inkey
,
446 const int inkeylen
, char **outval
, int *outvallen
)
450 enum clnt_stat result
;
452 if (indomain
== NULL
|| indomain
[0] == '\0' ||
453 inmap
== NULL
|| inmap
[0] == '\0' ||
454 inkey
== NULL
|| inkey
[0] == '\0' || inkeylen
<= 0)
455 return YPERR_BADARGS
;
457 req
.domain
= (char *) indomain
;
458 req
.map
= (char *) inmap
;
459 req
.key
.keydat_val
= (char *) inkey
;
460 req
.key
.keydat_len
= inkeylen
;
464 memset (&resp
, '\0', sizeof (resp
));
466 result
= do_ypcall_tr (indomain
, YPPROC_MATCH
, (xdrproc_t
) xdr_ypreq_key
,
467 (caddr_t
) &req
, (xdrproc_t
) xdr_ypresp_val
,
470 if (result
!= YPERR_SUCCESS
)
473 *outvallen
= resp
.val
.valdat_len
;
474 *outval
= malloc (*outvallen
+ 1);
475 int status
= YPERR_RESRC
;
476 if (__builtin_expect (*outval
!= NULL
, 1))
478 memcpy (*outval
, resp
.val
.valdat_val
, *outvallen
);
479 (*outval
)[*outvallen
] = '\0';
480 status
= YPERR_SUCCESS
;
483 xdr_free ((xdrproc_t
) xdr_ypresp_val
, (char *) &resp
);
489 yp_first (const char *indomain
, const char *inmap
, char **outkey
,
490 int *outkeylen
, char **outval
, int *outvallen
)
494 enum clnt_stat result
;
496 if (indomain
== NULL
|| indomain
[0] == '\0' ||
497 inmap
== NULL
|| inmap
[0] == '\0')
498 return YPERR_BADARGS
;
500 req
.domain
= (char *) indomain
;
501 req
.map
= (char *) inmap
;
503 *outkey
= *outval
= NULL
;
504 *outkeylen
= *outvallen
= 0;
505 memset (&resp
, '\0', sizeof (resp
));
507 result
= do_ypcall (indomain
, YPPROC_FIRST
, (xdrproc_t
) xdr_ypreq_nokey
,
508 (caddr_t
) &req
, (xdrproc_t
) xdr_ypresp_key_val
,
511 if (result
!= RPC_SUCCESS
)
513 if (resp
.stat
!= YP_TRUE
)
514 return ypprot_err (resp
.stat
);
517 if (__builtin_expect ((*outkey
= malloc (resp
.key
.keydat_len
+ 1)) != NULL
518 && (*outval
= malloc (resp
.val
.valdat_len
521 *outkeylen
= resp
.key
.keydat_len
;
522 memcpy (*outkey
, resp
.key
.keydat_val
, *outkeylen
);
523 (*outkey
)[*outkeylen
] = '\0';
525 *outvallen
= resp
.val
.valdat_len
;
526 memcpy (*outval
, resp
.val
.valdat_val
, *outvallen
);
527 (*outval
)[*outvallen
] = '\0';
529 status
= YPERR_SUCCESS
;
534 status
= YPERR_RESRC
;
537 xdr_free ((xdrproc_t
) xdr_ypresp_key_val
, (char *) &resp
);
543 yp_next (const char *indomain
, const char *inmap
, const char *inkey
,
544 const int inkeylen
, char **outkey
, int *outkeylen
, char **outval
,
549 enum clnt_stat result
;
551 if (indomain
== NULL
|| indomain
[0] == '\0' ||
552 inmap
== NULL
|| inmap
[0] == '\0' ||
553 inkeylen
<= 0 || inkey
== NULL
|| inkey
[0] == '\0')
554 return YPERR_BADARGS
;
556 req
.domain
= (char *) indomain
;
557 req
.map
= (char *) inmap
;
558 req
.key
.keydat_val
= (char *) inkey
;
559 req
.key
.keydat_len
= inkeylen
;
561 *outkey
= *outval
= NULL
;
562 *outkeylen
= *outvallen
= 0;
563 memset (&resp
, '\0', sizeof (resp
));
565 result
= do_ypcall_tr (indomain
, YPPROC_NEXT
, (xdrproc_t
) xdr_ypreq_key
,
566 (caddr_t
) &req
, (xdrproc_t
) xdr_ypresp_key_val
,
569 if (result
!= YPERR_SUCCESS
)
573 if (__builtin_expect ((*outkey
= malloc (resp
.key
.keydat_len
+ 1)) != NULL
574 && (*outval
= malloc (resp
.val
.valdat_len
577 *outkeylen
= resp
.key
.keydat_len
;
578 memcpy (*outkey
, resp
.key
.keydat_val
, *outkeylen
);
579 (*outkey
)[*outkeylen
] = '\0';
581 *outvallen
= resp
.val
.valdat_len
;
582 memcpy (*outval
, resp
.val
.valdat_val
, *outvallen
);
583 (*outval
)[*outvallen
] = '\0';
585 status
= YPERR_SUCCESS
;
590 status
= YPERR_RESRC
;
593 xdr_free ((xdrproc_t
) xdr_ypresp_key_val
, (char *) &resp
);
599 yp_master (const char *indomain
, const char *inmap
, char **outname
)
603 enum clnt_stat result
;
605 if (indomain
== NULL
|| indomain
[0] == '\0' ||
606 inmap
== NULL
|| inmap
[0] == '\0')
607 return YPERR_BADARGS
;
609 req
.domain
= (char *) indomain
;
610 req
.map
= (char *) inmap
;
612 memset (&resp
, '\0', sizeof (ypresp_master
));
614 result
= do_ypcall_tr (indomain
, YPPROC_MASTER
, (xdrproc_t
) xdr_ypreq_nokey
,
615 (caddr_t
) &req
, (xdrproc_t
) xdr_ypresp_master
,
618 if (result
!= YPERR_SUCCESS
)
621 *outname
= strdup (resp
.peer
);
622 xdr_free ((xdrproc_t
) xdr_ypresp_master
, (char *) &resp
);
624 return *outname
== NULL
? YPERR_YPERR
: YPERR_SUCCESS
;
626 libnsl_hidden_def (yp_master
)
629 yp_order (const char *indomain
, const char *inmap
, unsigned int *outorder
)
631 struct ypreq_nokey req
;
632 struct ypresp_order resp
;
633 enum clnt_stat result
;
635 if (indomain
== NULL
|| indomain
[0] == '\0' ||
636 inmap
== NULL
|| inmap
[0] == '\0')
637 return YPERR_BADARGS
;
639 req
.domain
= (char *) indomain
;
640 req
.map
= (char *) inmap
;
642 memset (&resp
, '\0', sizeof (resp
));
644 result
= do_ypcall_tr (indomain
, YPPROC_ORDER
, (xdrproc_t
) xdr_ypreq_nokey
,
645 (caddr_t
) &req
, (xdrproc_t
) xdr_ypresp_order
,
648 if (result
!= YPERR_SUCCESS
)
651 *outorder
= resp
.ordernum
;
652 xdr_free ((xdrproc_t
) xdr_ypresp_order
, (char *) &resp
);
657 struct ypresp_all_data
659 unsigned long status
;
661 int (*foreach
) (int status
, char *key
, int keylen
,
662 char *val
, int vallen
, char *data
);
666 __xdr_ypresp_all (XDR
*xdrs
, struct ypresp_all_data
*objp
)
670 struct ypresp_all resp
;
672 memset (&resp
, '\0', sizeof (struct ypresp_all
));
673 if (!xdr_ypresp_all (xdrs
, &resp
))
675 xdr_free ((xdrproc_t
) xdr_ypresp_all
, (char *) &resp
);
676 objp
->status
= YP_YPERR
;
681 xdr_free ((xdrproc_t
) xdr_ypresp_all
, (char *) &resp
);
682 objp
->status
= YP_NOMORE
;
686 switch (resp
.ypresp_all_u
.val
.stat
)
690 char key
[resp
.ypresp_all_u
.val
.key
.keydat_len
+ 1];
691 char val
[resp
.ypresp_all_u
.val
.val
.valdat_len
+ 1];
692 int keylen
= resp
.ypresp_all_u
.val
.key
.keydat_len
;
693 int vallen
= resp
.ypresp_all_u
.val
.val
.valdat_len
;
695 /* We are not allowed to modify the key and val data.
696 But we are allowed to add data behind the buffer,
697 if we don't modify the length. So add an extra NUL
698 character to avoid trouble with broken code. */
699 objp
->status
= YP_TRUE
;
700 *((char *) __mempcpy (key
, resp
.ypresp_all_u
.val
.key
.keydat_val
,
702 *((char *) __mempcpy (val
, resp
.ypresp_all_u
.val
.val
.valdat_val
,
704 xdr_free ((xdrproc_t
) xdr_ypresp_all
, (char *) &resp
);
705 if ((*objp
->foreach
) (objp
->status
, key
, keylen
,
706 val
, vallen
, objp
->data
))
711 objp
->status
= resp
.ypresp_all_u
.val
.stat
;
712 xdr_free ((xdrproc_t
) xdr_ypresp_all
, (char *) &resp
);
713 /* Sun says we don't need to make this call, but must return
714 immediately. Since Solaris makes this call, we will call
715 the callback function, too. */
716 (*objp
->foreach
) (objp
->status
, NULL
, 0, NULL
, 0, objp
->data
);
723 yp_all (const char *indomain
, const char *inmap
,
724 const struct ypall_callback
*incallback
)
726 struct ypreq_nokey req
;
727 dom_binding
*ydb
= NULL
;
729 enum clnt_stat result
;
730 struct sockaddr_in clnt_sin
;
732 struct ypresp_all_data data
;
734 int saved_errno
= errno
;
736 if (indomain
== NULL
|| indomain
[0] == '\0'
737 || inmap
== NULL
|| inmap
[0] == '\0')
738 return YPERR_BADARGS
;
743 while (try < MAXTRIES
&& res
!= YPERR_SUCCESS
)
745 if (__yp_bind (indomain
, &ydb
) != 0)
747 __set_errno (saved_errno
);
751 clnt_sock
= RPC_ANYSOCK
;
752 clnt_sin
= ydb
->dom_server_addr
;
753 clnt_sin
.sin_port
= 0;
755 /* We don't need the UDP connection anymore. */
759 clnt
= clnttcp_create (&clnt_sin
, YPPROG
, YPVERS
, &clnt_sock
, 0, 0);
762 __set_errno (saved_errno
);
765 req
.domain
= (char *) indomain
;
766 req
.map
= (char *) inmap
;
768 data
.foreach
= incallback
->foreach
;
769 data
.data
= (void *) incallback
->data
;
771 result
= clnt_call (clnt
, YPPROC_ALL
, (xdrproc_t
) xdr_ypreq_nokey
,
772 (caddr_t
) &req
, (xdrproc_t
) __xdr_ypresp_all
,
773 (caddr_t
) &data
, RPCTIMEOUT
);
775 if (__builtin_expect (result
!= RPC_SUCCESS
, 0))
777 /* Print the error message only on the last try. */
778 if (try == MAXTRIES
- 1)
779 clnt_perror (clnt
, "yp_all: clnt_call");
787 if (res
== YPERR_SUCCESS
&& data
.status
!= YP_NOMORE
)
789 __set_errno (saved_errno
);
790 return ypprot_err (data
.status
);
795 __set_errno (saved_errno
);
802 yp_maplist (const char *indomain
, struct ypmaplist
**outmaplist
)
804 struct ypresp_maplist resp
;
805 enum clnt_stat result
;
807 if (indomain
== NULL
|| indomain
[0] == '\0')
808 return YPERR_BADARGS
;
810 memset (&resp
, '\0', sizeof (resp
));
812 result
= do_ypcall_tr (indomain
, YPPROC_MAPLIST
, (xdrproc_t
) xdr_domainname
,
813 (caddr_t
) &indomain
, (xdrproc_t
) xdr_ypresp_maplist
,
816 if (__builtin_expect (result
== YPERR_SUCCESS
, 1))
818 *outmaplist
= resp
.maps
;
819 /* We don't free the list, this will be done by ypserv
820 xdr_free((xdrproc_t)xdr_ypresp_maplist, (char *)&resp); */
827 yperr_string (const int error
)
836 str
= N_("Request arguments bad");
839 str
= N_("RPC failure on NIS operation");
842 str
= N_("Can't bind to server which serves this domain");
845 str
= N_("No such map in server's domain");
848 str
= N_("No such key in map");
851 str
= N_("Internal NIS error");
854 str
= N_("Local resource allocation failure");
857 str
= N_("No more records in map database");
860 str
= N_("Can't communicate with portmapper");
863 str
= N_("Can't communicate with ypbind");
866 str
= N_("Can't communicate with ypserv");
869 str
= N_("Local domain name not set");
872 str
= N_("NIS map database is bad");
875 str
= N_("NIS client/server version mismatch - can't supply service");
878 str
= N_("Permission denied");
881 str
= N_("Database is busy");
884 str
= N_("Unknown NIS error code");
890 static const int8_t yp_2_yperr
[] =
892 #define YP2YPERR(yp, yperr) [YP_##yp - YP_VERS] = YPERR_##yperr
893 YP2YPERR (TRUE
, SUCCESS
),
894 YP2YPERR (NOMORE
, NOMORE
),
895 YP2YPERR (FALSE
, YPERR
),
896 YP2YPERR (NOMAP
, MAP
),
897 YP2YPERR (NODOM
, DOMAIN
),
898 YP2YPERR (NOKEY
, KEY
),
899 YP2YPERR (BADOP
, YPERR
),
900 YP2YPERR (BADDB
, BADDB
),
901 YP2YPERR (YPERR
, YPERR
),
902 YP2YPERR (BADARGS
, BADARGS
),
903 YP2YPERR (VERS
, VERS
)
906 ypprot_err (const int code
)
908 if (code
< YP_VERS
|| code
> YP_NOMORE
)
910 return yp_2_yperr
[code
- YP_VERS
];
912 libnsl_hidden_def (ypprot_err
)
915 ypbinderr_string (const int error
)
924 str
= N_("Internal ypbind error");
926 case YPBIND_ERR_NOSERV
:
927 str
= N_("Domain not bound");
929 case YPBIND_ERR_RESC
:
930 str
= N_("System resource allocation failure");
933 str
= N_("Unknown ypbind error");
938 libnsl_hidden_def (ypbinderr_string
)
943 yp_update (char *domain
, char *map
, unsigned ypop
,
944 char *key
, int keylen
, char *data
, int datalen
)
948 ypupdate_args update_args
;
949 ypdelete_args delete_args
;
952 xdrproc_t xdr_argument
;
956 struct sockaddr saddr
;
957 char servername
[MAXNETNAMELEN
+ 1];
960 if (!domain
|| !map
|| !key
|| (ypop
!= YPOP_DELETE
&& !data
))
961 return YPERR_BADARGS
;
963 args
.update_args
.mapname
= map
;
964 args
.update_args
.key
.yp_buf_len
= keylen
;
965 args
.update_args
.key
.yp_buf_val
= key
;
966 args
.update_args
.datum
.yp_buf_len
= datalen
;
967 args
.update_args
.datum
.yp_buf_val
= data
;
969 if ((r
= yp_master (domain
, map
, &master
)) != YPERR_SUCCESS
)
972 if (!host2netname (servername
, master
, domain
))
974 fputs (_("yp_update: cannot convert host to netname\n"), stderr
);
979 clnt
= clnt_create (master
, YPU_PROG
, YPU_VERS
, "tcp");
981 /* We do not need the string anymore. */
986 clnt_pcreateerror ("yp_update: clnt_create");
990 if (!clnt_control (clnt
, CLGET_SERVER_ADDR
, (char *) &saddr
))
992 fputs (_("yp_update: cannot get server address\n"), stderr
);
1001 xdr_argument
= (xdrproc_t
) xdr_ypupdate_args
;
1004 xdr_argument
= (xdrproc_t
) xdr_ypdelete_args
;
1007 return YPERR_BADARGS
;
1011 clnt
->cl_auth
= authdes_create (servername
, WINDOW
, &saddr
, NULL
);
1013 if (clnt
->cl_auth
== NULL
)
1014 clnt
->cl_auth
= authunix_create_default ();
1017 r
= clnt_call (clnt
, ypop
, xdr_argument
, (caddr_t
) &args
,
1018 (xdrproc_t
) xdr_u_int
, (caddr_t
) &res
, RPCTIMEOUT
);
1020 if (r
== RPC_AUTHERROR
)
1022 if (clnt
->cl_auth
->ah_cred
.oa_flavor
== AUTH_DES
)
1024 auth_destroy (clnt
->cl_auth
);
1025 clnt
->cl_auth
= authunix_create_default ();
1029 return YPERR_ACCESS
;
1031 if (r
!= RPC_SUCCESS
)
1033 clnt_perror (clnt
, "yp_update: clnt_call");