1 /* Copyright (C) 1996-2015 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, see
17 <http://www.gnu.org/licenses/>. */
25 #include <rpcsvc/nis.h>
26 #include <rpcsvc/yp.h>
27 #include <rpcsvc/ypclnt.h>
28 #include <rpcsvc/ypupd.h>
29 #include <sys/socket.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 const struct timeval RPCTIMEOUT
= {25, 0};
49 static const struct timeval UDPTIMEOUT
= {5, 0};
50 static int const MAXTRIES
= 2;
51 static char ypdomainname
[NIS_MAXNAMELEN
+ 1];
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
;
72 # define xflags SOCK_CLOEXEC
76 ysd
->dom_client
= __libc_clntudp_bufcreate (&ysd
->dom_server_addr
, YPPROG
,
79 UDPMSGSIZE
, UDPMSGSIZE
,
82 if (ysd
->dom_client
!= NULL
)
85 /* If the program exits, close the socket */
86 if (fcntl (ysd
->dom_socket
, F_SETFD
, FD_CLOEXEC
) == -1)
87 perror ("fcntl: F_SETFD");
94 yp_bind_file (const char *domain
, dom_binding
*ysd
)
96 char path
[sizeof (BINDINGDIR
) + strlen (domain
) + 3 * sizeof (unsigned) + 3];
98 snprintf (path
, sizeof (path
), "%s/%s.%u", BINDINGDIR
, domain
, YPBINDVERS
);
99 int fd
= open (path
, O_RDONLY
);
102 /* We have a binding file and could save a RPC call. The file
103 contains a port number and the YPBIND_RESP record. The port
104 number (16 bits) can be ignored. */
105 struct ypbind_resp ypbr
;
107 if (pread (fd
, &ypbr
, sizeof (ypbr
), 2) == sizeof (ypbr
))
108 yp_bind_client_create (domain
, ysd
, &ypbr
);
116 yp_bind_ypbindprog (const char *domain
, dom_binding
*ysd
)
118 struct sockaddr_in clnt_saddr
;
119 struct ypbind_resp ypbr
;
123 clnt_saddr
.sin_family
= AF_INET
;
124 clnt_saddr
.sin_port
= 0;
125 clnt_saddr
.sin_addr
.s_addr
= htonl (INADDR_LOOPBACK
);
126 clnt_sock
= RPC_ANYSOCK
;
127 client
= clnttcp_create (&clnt_saddr
, YPBINDPROG
, YPBINDVERS
,
132 /* Check the port number -- should be < IPPORT_RESERVED.
133 If not, it's possible someone has registered a bogus
134 ypbind with the portmapper and is trying to trick us. */
135 if (ntohs (clnt_saddr
.sin_port
) >= IPPORT_RESERVED
)
137 clnt_destroy (client
);
141 if (clnt_call (client
, YPBINDPROC_DOMAIN
,
142 (xdrproc_t
) xdr_domainname
, (caddr_t
) &domain
,
143 (xdrproc_t
) xdr_ypbind_resp
,
144 (caddr_t
) &ypbr
, RPCTIMEOUT
) != RPC_SUCCESS
)
146 clnt_destroy (client
);
150 clnt_destroy (client
);
152 if (ypbr
.ypbind_status
!= YPBIND_SUCC_VAL
)
154 fprintf (stderr
, "YPBINDPROC_DOMAIN: %s\n",
155 ypbinderr_string (ypbr
.ypbind_resp_u
.ypbind_error
));
158 memset (&ysd
->dom_server_addr
, '\0', sizeof ysd
->dom_server_addr
);
160 yp_bind_client_create (domain
, ysd
, &ypbr
);
162 return YPERR_SUCCESS
;
166 __yp_bind (const char *domain
, dom_binding
**ypdb
)
168 dom_binding
*ysd
= NULL
;
171 if (domain
== NULL
|| domain
[0] == '\0')
172 return YPERR_BADARGS
;
177 if (strcmp (domain
, ysd
->dom_domain
) == 0)
179 ysd
= ysd
->dom_pnext
;
185 ysd
= (dom_binding
*) calloc (1, sizeof *ysd
);
186 if (__glibc_unlikely (ysd
== NULL
))
191 /* Try binding dir at first if we have no binding */
192 if (ysd
->dom_client
== NULL
)
193 yp_bind_file (domain
, ysd
);
194 #endif /* USE_BINDINGDIR */
196 if (ysd
->dom_client
== NULL
)
198 int retval
= yp_bind_ypbindprog (domain
, ysd
);
199 if (retval
!= YPERR_SUCCESS
)
207 if (ysd
->dom_client
== NULL
)
216 ysd
->dom_pnext
= *ypdb
;
220 return YPERR_SUCCESS
;
224 __yp_unbind (dom_binding
*ydb
)
226 clnt_destroy (ydb
->dom_client
);
231 yp_bind (const char *indomain
)
235 __libc_lock_lock (ypbindlist_lock
);
237 status
= __yp_bind (indomain
, &ypbindlist
);
239 __libc_lock_unlock (ypbindlist_lock
);
243 libnsl_hidden_def (yp_bind
)
246 yp_unbind_locked (const char *indomain
)
248 dom_binding
*ydbptr
, *ydbptr2
;
253 while (ydbptr
!= NULL
)
255 if (strcmp (ydbptr
->dom_domain
, indomain
) == 0)
261 ypbindlist
= ypbindlist
->dom_pnext
;
263 ydbptr2
= ydbptr
->dom_pnext
;
268 ydbptr
= ydbptr
->dom_pnext
;
273 yp_unbind (const char *indomain
)
275 __libc_lock_lock (ypbindlist_lock
);
277 yp_unbind_locked (indomain
);
279 __libc_lock_unlock (ypbindlist_lock
);
285 __ypclnt_call (const char *domain
, u_long prog
, xdrproc_t xargs
,
286 caddr_t req
, xdrproc_t xres
, caddr_t resp
, dom_binding
**ydb
,
289 enum clnt_stat result
;
291 result
= clnt_call ((*ydb
)->dom_client
, prog
,
292 xargs
, req
, xres
, resp
, RPCTIMEOUT
);
294 if (result
!= RPC_SUCCESS
)
296 /* We don't print an error message, if we try our old,
297 cached data. Only print this for data, which should work. */
299 clnt_perror ((*ydb
)->dom_client
, "do_ypcall: clnt_call");
304 return YPERR_SUCCESS
;
308 do_ypcall (const char *domain
, u_long prog
, xdrproc_t xargs
,
309 caddr_t req
, xdrproc_t xres
, caddr_t resp
)
313 int saved_errno
= errno
;
315 status
= YPERR_YPERR
;
317 __libc_lock_lock (ypbindlist_lock
);
321 if (strcmp (domain
, ydb
->dom_domain
) == 0)
323 if (__yp_bind (domain
, &ydb
) == 0)
325 /* Call server, print no error message, do not unbind. */
326 status
= __ypclnt_call (domain
, prog
, xargs
, req
, xres
,
328 if (status
== YPERR_SUCCESS
)
330 __libc_lock_unlock (ypbindlist_lock
);
331 __set_errno (saved_errno
);
335 /* We use ypbindlist, and the old cached data is
336 invalid. unbind now and create a new binding */
337 yp_unbind_locked (domain
);
341 ydb
= ydb
->dom_pnext
;
343 __libc_lock_unlock (ypbindlist_lock
);
345 /* First try with cached data failed. Now try to get
346 current data from the system. */
348 if (__yp_bind (domain
, &ydb
) == 0)
350 status
= __ypclnt_call (domain
, prog
, xargs
, req
, xres
,
356 /* If we support binding dir data, we have a third chance:
358 if (status
!= YPERR_SUCCESS
)
360 ydb
= calloc (1, sizeof (dom_binding
));
361 if (ydb
!= NULL
&& yp_bind_ypbindprog (domain
, ydb
) == YPERR_SUCCESS
)
363 status
= __ypclnt_call (domain
, prog
, xargs
, req
, xres
,
372 __set_errno (saved_errno
);
377 /* Like do_ypcall, but translate the status value if necessary. */
379 do_ypcall_tr (const char *domain
, u_long prog
, xdrproc_t xargs
,
380 caddr_t req
, xdrproc_t xres
, caddr_t resp
)
382 int status
= do_ypcall (domain
, prog
, xargs
, req
, xres
, resp
);
383 if (status
== YPERR_SUCCESS
)
384 /* We cast to ypresp_val although the pointer could also be of
385 type ypresp_key_val or ypresp_master or ypresp_order or
386 ypresp_maplist. But the stat element is in a common prefix so
387 this does not matter. */
388 status
= ypprot_err (((struct ypresp_val
*) resp
)->stat
);
393 __libc_lock_define_initialized (static, domainname_lock
)
396 yp_get_default_domain (char **outdomain
)
398 int result
= YPERR_SUCCESS
;;
401 __libc_lock_lock (domainname_lock
);
403 if (ypdomainname
[0] == '\0')
405 if (getdomainname (ypdomainname
, NIS_MAXNAMELEN
))
406 result
= YPERR_NODOM
;
407 else if (strcmp (ypdomainname
, "(none)") == 0)
409 /* If domainname is not set, some systems will return "(none)" */
410 ypdomainname
[0] = '\0';
411 result
= YPERR_NODOM
;
414 *outdomain
= ypdomainname
;
417 *outdomain
= ypdomainname
;
419 __libc_lock_unlock (domainname_lock
);
423 libnsl_hidden_def (yp_get_default_domain
)
426 __yp_check (char **domain
)
430 if (ypdomainname
[0] == '\0')
431 if (yp_get_default_domain (&unused
))
435 *domain
= ypdomainname
;
437 if (yp_bind (ypdomainname
) == 0)
443 yp_match (const char *indomain
, const char *inmap
, const char *inkey
,
444 const int inkeylen
, char **outval
, int *outvallen
)
448 enum clnt_stat result
;
450 if (indomain
== NULL
|| indomain
[0] == '\0' ||
451 inmap
== NULL
|| inmap
[0] == '\0' ||
452 inkey
== NULL
|| inkey
[0] == '\0' || inkeylen
<= 0)
453 return YPERR_BADARGS
;
455 req
.domain
= (char *) indomain
;
456 req
.map
= (char *) inmap
;
457 req
.key
.keydat_val
= (char *) inkey
;
458 req
.key
.keydat_len
= inkeylen
;
462 memset (&resp
, '\0', sizeof (resp
));
464 result
= do_ypcall_tr (indomain
, YPPROC_MATCH
, (xdrproc_t
) xdr_ypreq_key
,
465 (caddr_t
) &req
, (xdrproc_t
) xdr_ypresp_val
,
468 if (result
!= YPERR_SUCCESS
)
471 *outvallen
= resp
.val
.valdat_len
;
472 *outval
= malloc (*outvallen
+ 1);
473 int status
= YPERR_RESRC
;
474 if (__glibc_likely (*outval
!= NULL
))
476 memcpy (*outval
, resp
.val
.valdat_val
, *outvallen
);
477 (*outval
)[*outvallen
] = '\0';
478 status
= YPERR_SUCCESS
;
481 xdr_free ((xdrproc_t
) xdr_ypresp_val
, (char *) &resp
);
487 yp_first (const char *indomain
, const char *inmap
, char **outkey
,
488 int *outkeylen
, char **outval
, int *outvallen
)
492 enum clnt_stat result
;
494 if (indomain
== NULL
|| indomain
[0] == '\0' ||
495 inmap
== NULL
|| inmap
[0] == '\0')
496 return YPERR_BADARGS
;
498 req
.domain
= (char *) indomain
;
499 req
.map
= (char *) inmap
;
501 *outkey
= *outval
= NULL
;
502 *outkeylen
= *outvallen
= 0;
503 memset (&resp
, '\0', sizeof (resp
));
505 result
= do_ypcall (indomain
, YPPROC_FIRST
, (xdrproc_t
) xdr_ypreq_nokey
,
506 (caddr_t
) &req
, (xdrproc_t
) xdr_ypresp_key_val
,
509 if (result
!= RPC_SUCCESS
)
511 if (resp
.stat
!= YP_TRUE
)
512 return ypprot_err (resp
.stat
);
515 if (__builtin_expect ((*outkey
= malloc (resp
.key
.keydat_len
+ 1)) != NULL
516 && (*outval
= malloc (resp
.val
.valdat_len
519 *outkeylen
= resp
.key
.keydat_len
;
520 memcpy (*outkey
, resp
.key
.keydat_val
, *outkeylen
);
521 (*outkey
)[*outkeylen
] = '\0';
523 *outvallen
= resp
.val
.valdat_len
;
524 memcpy (*outval
, resp
.val
.valdat_val
, *outvallen
);
525 (*outval
)[*outvallen
] = '\0';
527 status
= YPERR_SUCCESS
;
532 status
= YPERR_RESRC
;
535 xdr_free ((xdrproc_t
) xdr_ypresp_key_val
, (char *) &resp
);
541 yp_next (const char *indomain
, const char *inmap
, const char *inkey
,
542 const int inkeylen
, char **outkey
, int *outkeylen
, char **outval
,
547 enum clnt_stat result
;
549 if (indomain
== NULL
|| indomain
[0] == '\0' ||
550 inmap
== NULL
|| inmap
[0] == '\0' ||
551 inkeylen
<= 0 || inkey
== NULL
|| inkey
[0] == '\0')
552 return YPERR_BADARGS
;
554 req
.domain
= (char *) indomain
;
555 req
.map
= (char *) inmap
;
556 req
.key
.keydat_val
= (char *) inkey
;
557 req
.key
.keydat_len
= inkeylen
;
559 *outkey
= *outval
= NULL
;
560 *outkeylen
= *outvallen
= 0;
561 memset (&resp
, '\0', sizeof (resp
));
563 result
= do_ypcall_tr (indomain
, YPPROC_NEXT
, (xdrproc_t
) xdr_ypreq_key
,
564 (caddr_t
) &req
, (xdrproc_t
) xdr_ypresp_key_val
,
567 if (result
!= YPERR_SUCCESS
)
571 if (__builtin_expect ((*outkey
= malloc (resp
.key
.keydat_len
+ 1)) != NULL
572 && (*outval
= malloc (resp
.val
.valdat_len
575 *outkeylen
= resp
.key
.keydat_len
;
576 memcpy (*outkey
, resp
.key
.keydat_val
, *outkeylen
);
577 (*outkey
)[*outkeylen
] = '\0';
579 *outvallen
= resp
.val
.valdat_len
;
580 memcpy (*outval
, resp
.val
.valdat_val
, *outvallen
);
581 (*outval
)[*outvallen
] = '\0';
583 status
= YPERR_SUCCESS
;
588 status
= YPERR_RESRC
;
591 xdr_free ((xdrproc_t
) xdr_ypresp_key_val
, (char *) &resp
);
597 yp_master (const char *indomain
, const char *inmap
, char **outname
)
601 enum clnt_stat result
;
603 if (indomain
== NULL
|| indomain
[0] == '\0' ||
604 inmap
== NULL
|| inmap
[0] == '\0')
605 return YPERR_BADARGS
;
607 req
.domain
= (char *) indomain
;
608 req
.map
= (char *) inmap
;
610 memset (&resp
, '\0', sizeof (ypresp_master
));
612 result
= do_ypcall_tr (indomain
, YPPROC_MASTER
, (xdrproc_t
) xdr_ypreq_nokey
,
613 (caddr_t
) &req
, (xdrproc_t
) xdr_ypresp_master
,
616 if (result
!= YPERR_SUCCESS
)
619 *outname
= strdup (resp
.peer
);
620 xdr_free ((xdrproc_t
) xdr_ypresp_master
, (char *) &resp
);
622 return *outname
== NULL
? YPERR_YPERR
: YPERR_SUCCESS
;
624 libnsl_hidden_def (yp_master
)
627 yp_order (const char *indomain
, const char *inmap
, unsigned int *outorder
)
629 struct ypreq_nokey req
;
630 struct ypresp_order resp
;
631 enum clnt_stat result
;
633 if (indomain
== NULL
|| indomain
[0] == '\0' ||
634 inmap
== NULL
|| inmap
[0] == '\0')
635 return YPERR_BADARGS
;
637 req
.domain
= (char *) indomain
;
638 req
.map
= (char *) inmap
;
640 memset (&resp
, '\0', sizeof (resp
));
642 result
= do_ypcall_tr (indomain
, YPPROC_ORDER
, (xdrproc_t
) xdr_ypreq_nokey
,
643 (caddr_t
) &req
, (xdrproc_t
) xdr_ypresp_order
,
646 if (result
!= YPERR_SUCCESS
)
649 *outorder
= resp
.ordernum
;
650 xdr_free ((xdrproc_t
) xdr_ypresp_order
, (char *) &resp
);
655 struct ypresp_all_data
657 unsigned long status
;
659 int (*foreach
) (int status
, char *key
, int keylen
,
660 char *val
, int vallen
, char *data
);
664 __xdr_ypresp_all (XDR
*xdrs
, struct ypresp_all_data
*objp
)
668 struct ypresp_all resp
;
670 memset (&resp
, '\0', sizeof (struct ypresp_all
));
671 if (!xdr_ypresp_all (xdrs
, &resp
))
673 xdr_free ((xdrproc_t
) xdr_ypresp_all
, (char *) &resp
);
674 objp
->status
= YP_YPERR
;
679 xdr_free ((xdrproc_t
) xdr_ypresp_all
, (char *) &resp
);
680 objp
->status
= YP_NOMORE
;
684 switch (resp
.ypresp_all_u
.val
.stat
)
688 char key
[resp
.ypresp_all_u
.val
.key
.keydat_len
+ 1];
689 char val
[resp
.ypresp_all_u
.val
.val
.valdat_len
+ 1];
690 int keylen
= resp
.ypresp_all_u
.val
.key
.keydat_len
;
691 int vallen
= resp
.ypresp_all_u
.val
.val
.valdat_len
;
693 /* We are not allowed to modify the key and val data.
694 But we are allowed to add data behind the buffer,
695 if we don't modify the length. So add an extra NUL
696 character to avoid trouble with broken code. */
697 objp
->status
= YP_TRUE
;
698 *((char *) __mempcpy (key
, resp
.ypresp_all_u
.val
.key
.keydat_val
,
700 *((char *) __mempcpy (val
, resp
.ypresp_all_u
.val
.val
.valdat_val
,
702 xdr_free ((xdrproc_t
) xdr_ypresp_all
, (char *) &resp
);
703 if ((*objp
->foreach
) (objp
->status
, key
, keylen
,
704 val
, vallen
, objp
->data
))
709 objp
->status
= resp
.ypresp_all_u
.val
.stat
;
710 xdr_free ((xdrproc_t
) xdr_ypresp_all
, (char *) &resp
);
711 /* Sun says we don't need to make this call, but must return
712 immediately. Since Solaris makes this call, we will call
713 the callback function, too. */
714 (*objp
->foreach
) (objp
->status
, NULL
, 0, NULL
, 0, objp
->data
);
721 yp_all (const char *indomain
, const char *inmap
,
722 const struct ypall_callback
*incallback
)
724 struct ypreq_nokey req
;
725 dom_binding
*ydb
= NULL
;
727 enum clnt_stat result
;
728 struct sockaddr_in clnt_sin
;
730 struct ypresp_all_data data
;
732 int saved_errno
= errno
;
734 if (indomain
== NULL
|| indomain
[0] == '\0'
735 || inmap
== NULL
|| inmap
[0] == '\0')
736 return YPERR_BADARGS
;
741 while (try < MAXTRIES
&& res
!= YPERR_SUCCESS
)
743 if (__yp_bind (indomain
, &ydb
) != 0)
745 __set_errno (saved_errno
);
749 clnt_sock
= RPC_ANYSOCK
;
750 clnt_sin
= ydb
->dom_server_addr
;
751 clnt_sin
.sin_port
= 0;
753 /* We don't need the UDP connection anymore. */
757 clnt
= clnttcp_create (&clnt_sin
, YPPROG
, YPVERS
, &clnt_sock
, 0, 0);
760 __set_errno (saved_errno
);
763 req
.domain
= (char *) indomain
;
764 req
.map
= (char *) inmap
;
766 data
.foreach
= incallback
->foreach
;
767 data
.data
= (void *) incallback
->data
;
769 result
= clnt_call (clnt
, YPPROC_ALL
, (xdrproc_t
) xdr_ypreq_nokey
,
770 (caddr_t
) &req
, (xdrproc_t
) __xdr_ypresp_all
,
771 (caddr_t
) &data
, RPCTIMEOUT
);
773 if (__glibc_unlikely (result
!= RPC_SUCCESS
))
775 /* Print the error message only on the last try. */
776 if (try == MAXTRIES
- 1)
777 clnt_perror (clnt
, "yp_all: clnt_call");
785 if (res
== YPERR_SUCCESS
&& data
.status
!= YP_NOMORE
)
787 __set_errno (saved_errno
);
788 return ypprot_err (data
.status
);
793 __set_errno (saved_errno
);
800 yp_maplist (const char *indomain
, struct ypmaplist
**outmaplist
)
802 struct ypresp_maplist resp
;
803 enum clnt_stat result
;
805 if (indomain
== NULL
|| indomain
[0] == '\0')
806 return YPERR_BADARGS
;
808 memset (&resp
, '\0', sizeof (resp
));
810 result
= do_ypcall_tr (indomain
, YPPROC_MAPLIST
, (xdrproc_t
) xdr_domainname
,
811 (caddr_t
) &indomain
, (xdrproc_t
) xdr_ypresp_maplist
,
814 if (__glibc_likely (result
== YPERR_SUCCESS
))
816 *outmaplist
= resp
.maps
;
817 /* We don't free the list, this will be done by ypserv
818 xdr_free((xdrproc_t)xdr_ypresp_maplist, (char *)&resp); */
825 yperr_string (const int error
)
834 str
= N_("Request arguments bad");
837 str
= N_("RPC failure on NIS operation");
840 str
= N_("Can't bind to server which serves this domain");
843 str
= N_("No such map in server's domain");
846 str
= N_("No such key in map");
849 str
= N_("Internal NIS error");
852 str
= N_("Local resource allocation failure");
855 str
= N_("No more records in map database");
858 str
= N_("Can't communicate with portmapper");
861 str
= N_("Can't communicate with ypbind");
864 str
= N_("Can't communicate with ypserv");
867 str
= N_("Local domain name not set");
870 str
= N_("NIS map database is bad");
873 str
= N_("NIS client/server version mismatch - can't supply service");
876 str
= N_("Permission denied");
879 str
= N_("Database is busy");
882 str
= N_("Unknown NIS error code");
888 static const int8_t yp_2_yperr
[] =
890 #define YP2YPERR(yp, yperr) [YP_##yp - YP_VERS] = YPERR_##yperr
891 YP2YPERR (TRUE
, SUCCESS
),
892 YP2YPERR (NOMORE
, NOMORE
),
893 YP2YPERR (FALSE
, YPERR
),
894 YP2YPERR (NOMAP
, MAP
),
895 YP2YPERR (NODOM
, DOMAIN
),
896 YP2YPERR (NOKEY
, KEY
),
897 YP2YPERR (BADOP
, YPERR
),
898 YP2YPERR (BADDB
, BADDB
),
899 YP2YPERR (YPERR
, YPERR
),
900 YP2YPERR (BADARGS
, BADARGS
),
901 YP2YPERR (VERS
, VERS
)
904 ypprot_err (const int code
)
906 if (code
< YP_VERS
|| code
> YP_NOMORE
)
908 return yp_2_yperr
[code
- YP_VERS
];
910 libnsl_hidden_def (ypprot_err
)
913 ypbinderr_string (const int error
)
922 str
= N_("Internal ypbind error");
924 case YPBIND_ERR_NOSERV
:
925 str
= N_("Domain not bound");
927 case YPBIND_ERR_RESC
:
928 str
= N_("System resource allocation failure");
931 str
= N_("Unknown ypbind error");
936 libnsl_hidden_def (ypbinderr_string
)
941 yp_update (char *domain
, char *map
, unsigned ypop
,
942 char *key
, int keylen
, char *data
, int datalen
)
946 ypupdate_args update_args
;
947 ypdelete_args delete_args
;
950 xdrproc_t xdr_argument
;
954 struct sockaddr saddr
;
955 char servername
[MAXNETNAMELEN
+ 1];
958 if (!domain
|| !map
|| !key
|| (ypop
!= YPOP_DELETE
&& !data
))
959 return YPERR_BADARGS
;
961 args
.update_args
.mapname
= map
;
962 args
.update_args
.key
.yp_buf_len
= keylen
;
963 args
.update_args
.key
.yp_buf_val
= key
;
964 args
.update_args
.datum
.yp_buf_len
= datalen
;
965 args
.update_args
.datum
.yp_buf_val
= data
;
967 if ((r
= yp_master (domain
, map
, &master
)) != YPERR_SUCCESS
)
970 if (!host2netname (servername
, master
, domain
))
972 fputs (_("yp_update: cannot convert host to netname\n"), stderr
);
977 clnt
= clnt_create (master
, YPU_PROG
, YPU_VERS
, "tcp");
979 /* We do not need the string anymore. */
984 clnt_pcreateerror ("yp_update: clnt_create");
988 if (!clnt_control (clnt
, CLGET_SERVER_ADDR
, (char *) &saddr
))
990 fputs (_("yp_update: cannot get server address\n"), stderr
);
999 xdr_argument
= (xdrproc_t
) xdr_ypupdate_args
;
1002 xdr_argument
= (xdrproc_t
) xdr_ypdelete_args
;
1005 return YPERR_BADARGS
;
1009 clnt
->cl_auth
= authdes_create (servername
, WINDOW
, &saddr
, NULL
);
1011 if (clnt
->cl_auth
== NULL
)
1012 clnt
->cl_auth
= authunix_create_default ();
1015 r
= clnt_call (clnt
, ypop
, xdr_argument
, (caddr_t
) &args
,
1016 (xdrproc_t
) xdr_u_int
, (caddr_t
) &res
, RPCTIMEOUT
);
1018 if (r
== RPC_AUTHERROR
)
1020 if (clnt
->cl_auth
->ah_cred
.oa_flavor
== AUTH_DES
)
1022 auth_destroy (clnt
->cl_auth
);
1023 clnt
->cl_auth
= authunix_create_default ();
1027 return YPERR_ACCESS
;
1029 if (r
!= RPC_SUCCESS
)
1031 clnt_perror (clnt
, "yp_update: clnt_call");