1 /* Copyright (C) 1996-2021 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 <https://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 <libc-lock.h>
32 #include <shlib-compat.h>
33 #include <libc-diag.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
;
73 ysd
->dom_client
= __libc_clntudp_bufcreate (&ysd
->dom_server_addr
, YPPROG
,
76 UDPMSGSIZE
, UDPMSGSIZE
,
82 yp_bind_file (const char *domain
, dom_binding
*ysd
)
84 char path
[sizeof (BINDINGDIR
) + strlen (domain
) + 3 * sizeof (unsigned) + 3];
86 snprintf (path
, sizeof (path
), "%s/%s.%u", BINDINGDIR
, domain
, YPBINDVERS
);
87 int fd
= open (path
, O_RDONLY
);
90 /* We have a binding file and could save a RPC call. The file
91 contains a port number and the YPBIND_RESP record. The port
92 number (16 bits) can be ignored. */
93 struct ypbind_resp ypbr
;
95 if (pread (fd
, &ypbr
, sizeof (ypbr
), 2) == sizeof (ypbr
))
96 yp_bind_client_create (domain
, ysd
, &ypbr
);
104 yp_bind_ypbindprog (const char *domain
, dom_binding
*ysd
)
106 struct sockaddr_in clnt_saddr
;
107 struct ypbind_resp ypbr
;
111 clnt_saddr
.sin_family
= AF_INET
;
112 clnt_saddr
.sin_port
= 0;
113 clnt_saddr
.sin_addr
.s_addr
= htonl (INADDR_LOOPBACK
);
114 clnt_sock
= RPC_ANYSOCK
;
115 client
= clnttcp_create (&clnt_saddr
, YPBINDPROG
, YPBINDVERS
,
120 /* Check the port number -- should be < IPPORT_RESERVED.
121 If not, it's possible someone has registered a bogus
122 ypbind with the portmapper and is trying to trick us. */
123 if (ntohs (clnt_saddr
.sin_port
) >= IPPORT_RESERVED
)
125 clnt_destroy (client
);
129 if (clnt_call (client
, YPBINDPROC_DOMAIN
,
130 (xdrproc_t
) xdr_domainname
, (caddr_t
) &domain
,
131 (xdrproc_t
) xdr_ypbind_resp
,
132 (caddr_t
) &ypbr
, RPCTIMEOUT
) != RPC_SUCCESS
)
134 clnt_destroy (client
);
138 clnt_destroy (client
);
140 if (ypbr
.ypbind_status
!= YPBIND_SUCC_VAL
)
142 fprintf (stderr
, "YPBINDPROC_DOMAIN: %s\n",
143 ypbinderr_string (ypbr
.ypbind_resp_u
.ypbind_error
));
146 memset (&ysd
->dom_server_addr
, '\0', sizeof ysd
->dom_server_addr
);
148 yp_bind_client_create (domain
, ysd
, &ypbr
);
150 return YPERR_SUCCESS
;
154 __yp_bind (const char *domain
, dom_binding
**ypdb
)
156 dom_binding
*ysd
= NULL
;
159 if (domain
== NULL
|| domain
[0] == '\0')
160 return YPERR_BADARGS
;
165 if (strcmp (domain
, ysd
->dom_domain
) == 0)
167 ysd
= ysd
->dom_pnext
;
173 ysd
= (dom_binding
*) calloc (1, sizeof *ysd
);
174 if (__glibc_unlikely (ysd
== NULL
))
179 /* Try binding dir at first if we have no binding */
180 if (ysd
->dom_client
== NULL
)
181 yp_bind_file (domain
, ysd
);
182 #endif /* USE_BINDINGDIR */
184 if (ysd
->dom_client
== NULL
)
186 int retval
= yp_bind_ypbindprog (domain
, ysd
);
187 if (retval
!= YPERR_SUCCESS
)
195 if (ysd
->dom_client
== NULL
)
204 ysd
->dom_pnext
= *ypdb
;
208 return YPERR_SUCCESS
;
212 __yp_unbind (dom_binding
*ydb
)
214 clnt_destroy (ydb
->dom_client
);
219 yp_bind (const char *indomain
)
223 __libc_lock_lock (ypbindlist_lock
);
225 status
= __yp_bind (indomain
, &ypbindlist
);
227 __libc_lock_unlock (ypbindlist_lock
);
231 libnsl_hidden_nolink_def (yp_bind
, GLIBC_2_0
)
234 yp_unbind_locked (const char *indomain
)
236 dom_binding
*ydbptr
, *ydbptr2
;
241 while (ydbptr
!= NULL
)
243 if (strcmp (ydbptr
->dom_domain
, indomain
) == 0)
249 ypbindlist
= ypbindlist
->dom_pnext
;
251 ydbptr2
= ydbptr
->dom_pnext
;
256 ydbptr
= ydbptr
->dom_pnext
;
261 yp_unbind (const char *indomain
)
263 __libc_lock_lock (ypbindlist_lock
);
265 yp_unbind_locked (indomain
);
267 __libc_lock_unlock (ypbindlist_lock
);
271 libnsl_hidden_nolink_def(yp_unbind
, GLIBC_2_0
)
274 __ypclnt_call (const char *domain
, u_long prog
, xdrproc_t xargs
,
275 caddr_t req
, xdrproc_t xres
, caddr_t resp
, dom_binding
**ydb
,
278 enum clnt_stat result
;
280 result
= clnt_call ((*ydb
)->dom_client
, prog
,
281 xargs
, req
, xres
, resp
, RPCTIMEOUT
);
283 if (result
!= RPC_SUCCESS
)
285 /* We don't print an error message, if we try our old,
286 cached data. Only print this for data, which should work. */
288 clnt_perror ((*ydb
)->dom_client
, "do_ypcall: clnt_call");
293 return YPERR_SUCCESS
;
297 do_ypcall (const char *domain
, u_long prog
, xdrproc_t xargs
,
298 caddr_t req
, xdrproc_t xres
, caddr_t resp
)
302 int saved_errno
= errno
;
304 status
= YPERR_YPERR
;
306 __libc_lock_lock (ypbindlist_lock
);
310 if (strcmp (domain
, ydb
->dom_domain
) == 0)
312 if (__yp_bind (domain
, &ydb
) == 0)
314 /* Call server, print no error message, do not unbind. */
315 status
= __ypclnt_call (domain
, prog
, xargs
, req
, xres
,
317 if (status
== YPERR_SUCCESS
)
319 __libc_lock_unlock (ypbindlist_lock
);
320 __set_errno (saved_errno
);
324 /* We use ypbindlist, and the old cached data is
325 invalid. unbind now and create a new binding */
326 yp_unbind_locked (domain
);
330 ydb
= ydb
->dom_pnext
;
332 __libc_lock_unlock (ypbindlist_lock
);
334 /* First try with cached data failed. Now try to get
335 current data from the system. */
337 if (__yp_bind (domain
, &ydb
) == 0)
339 status
= __ypclnt_call (domain
, prog
, xargs
, req
, xres
,
345 /* If we support binding dir data, we have a third chance:
347 if (status
!= YPERR_SUCCESS
)
349 ydb
= calloc (1, sizeof (dom_binding
));
350 if (ydb
!= NULL
&& yp_bind_ypbindprog (domain
, ydb
) == YPERR_SUCCESS
)
352 status
= __ypclnt_call (domain
, prog
, xargs
, req
, xres
,
361 __set_errno (saved_errno
);
366 /* Like do_ypcall, but translate the status value if necessary. */
368 do_ypcall_tr (const char *domain
, u_long prog
, xdrproc_t xargs
,
369 caddr_t req
, xdrproc_t xres
, caddr_t resp
)
371 int status
= do_ypcall (domain
, prog
, xargs
, req
, xres
, resp
);
372 DIAG_PUSH_NEEDS_COMMENT
;
373 /* This cast results in a warning that a ypresp_val is partly
374 outside the bounds of the actual object referenced, but as
375 explained below only the stat element (in a common prefix) is
377 DIAG_IGNORE_NEEDS_COMMENT (11, "-Warray-bounds");
378 if (status
== YPERR_SUCCESS
)
379 /* We cast to ypresp_val although the pointer could also be of
380 type ypresp_key_val or ypresp_master or ypresp_order or
381 ypresp_maplist. But the stat element is in a common prefix so
382 this does not matter. */
383 status
= ypprot_err (((struct ypresp_val
*) resp
)->stat
);
384 DIAG_POP_NEEDS_COMMENT
;
389 __libc_lock_define_initialized (static, domainname_lock
)
392 yp_get_default_domain (char **outdomain
)
394 int result
= YPERR_SUCCESS
;;
397 __libc_lock_lock (domainname_lock
);
399 if (ypdomainname
[0] == '\0')
401 if (getdomainname (ypdomainname
, NIS_MAXNAMELEN
))
402 result
= YPERR_NODOM
;
403 else if (strcmp (ypdomainname
, "(none)") == 0)
405 /* If domainname is not set, some systems will return "(none)" */
406 ypdomainname
[0] = '\0';
407 result
= YPERR_NODOM
;
410 *outdomain
= ypdomainname
;
413 *outdomain
= ypdomainname
;
415 __libc_lock_unlock (domainname_lock
);
419 libnsl_hidden_nolink_def (yp_get_default_domain
, GLIBC_2_0
)
422 __yp_check (char **domain
)
426 if (ypdomainname
[0] == '\0')
427 if (yp_get_default_domain (&unused
))
431 *domain
= ypdomainname
;
433 if (yp_bind (ypdomainname
) == 0)
437 libnsl_hidden_nolink_def(__yp_check
, GLIBC_2_0
)
440 yp_match (const char *indomain
, const char *inmap
, const char *inkey
,
441 const int inkeylen
, char **outval
, int *outvallen
)
445 enum clnt_stat result
;
447 if (indomain
== NULL
|| indomain
[0] == '\0'
448 || inmap
== NULL
|| inmap
[0] == '\0'
449 || inkey
== NULL
|| inkey
[0] == '\0' || inkeylen
<= 0)
450 return YPERR_BADARGS
;
452 req
.domain
= (char *) indomain
;
453 req
.map
= (char *) inmap
;
454 req
.key
.keydat_val
= (char *) inkey
;
455 req
.key
.keydat_len
= inkeylen
;
459 memset (&resp
, '\0', sizeof (resp
));
461 result
= do_ypcall_tr (indomain
, YPPROC_MATCH
, (xdrproc_t
) xdr_ypreq_key
,
462 (caddr_t
) &req
, (xdrproc_t
) xdr_ypresp_val
,
465 if (result
!= YPERR_SUCCESS
)
468 *outvallen
= resp
.val
.valdat_len
;
469 *outval
= malloc (*outvallen
+ 1);
470 int status
= YPERR_RESRC
;
471 if (__glibc_likely (*outval
!= NULL
))
473 memcpy (*outval
, resp
.val
.valdat_val
, *outvallen
);
474 (*outval
)[*outvallen
] = '\0';
475 status
= YPERR_SUCCESS
;
478 xdr_free ((xdrproc_t
) xdr_ypresp_val
, (char *) &resp
);
482 libnsl_hidden_nolink_def(yp_match
, GLIBC_2_0
)
485 yp_first (const char *indomain
, const char *inmap
, char **outkey
,
486 int *outkeylen
, char **outval
, int *outvallen
)
490 enum clnt_stat result
;
492 if (indomain
== NULL
|| indomain
[0] == '\0'
493 || inmap
== NULL
|| inmap
[0] == '\0')
494 return YPERR_BADARGS
;
496 req
.domain
= (char *) indomain
;
497 req
.map
= (char *) inmap
;
499 *outkey
= *outval
= NULL
;
500 *outkeylen
= *outvallen
= 0;
501 memset (&resp
, '\0', sizeof (resp
));
503 result
= do_ypcall (indomain
, YPPROC_FIRST
, (xdrproc_t
) xdr_ypreq_nokey
,
504 (caddr_t
) &req
, (xdrproc_t
) xdr_ypresp_key_val
,
507 if (result
!= RPC_SUCCESS
)
509 if (resp
.stat
!= YP_TRUE
)
510 return ypprot_err (resp
.stat
);
513 if (__builtin_expect ((*outkey
= malloc (resp
.key
.keydat_len
+ 1)) != NULL
514 && (*outval
= malloc (resp
.val
.valdat_len
517 *outkeylen
= resp
.key
.keydat_len
;
518 memcpy (*outkey
, resp
.key
.keydat_val
, *outkeylen
);
519 (*outkey
)[*outkeylen
] = '\0';
521 *outvallen
= resp
.val
.valdat_len
;
522 memcpy (*outval
, resp
.val
.valdat_val
, *outvallen
);
523 (*outval
)[*outvallen
] = '\0';
525 status
= YPERR_SUCCESS
;
530 status
= YPERR_RESRC
;
533 xdr_free ((xdrproc_t
) xdr_ypresp_key_val
, (char *) &resp
);
537 libnsl_hidden_nolink_def(yp_first
, GLIBC_2_0
)
540 yp_next (const char *indomain
, const char *inmap
, const char *inkey
,
541 const int inkeylen
, char **outkey
, int *outkeylen
, char **outval
,
546 enum clnt_stat result
;
548 if (indomain
== NULL
|| indomain
[0] == '\0'
549 || inmap
== NULL
|| inmap
[0] == '\0'
550 || inkeylen
<= 0 || inkey
== NULL
|| inkey
[0] == '\0')
551 return YPERR_BADARGS
;
553 req
.domain
= (char *) indomain
;
554 req
.map
= (char *) inmap
;
555 req
.key
.keydat_val
= (char *) inkey
;
556 req
.key
.keydat_len
= inkeylen
;
558 *outkey
= *outval
= NULL
;
559 *outkeylen
= *outvallen
= 0;
560 memset (&resp
, '\0', sizeof (resp
));
562 result
= do_ypcall_tr (indomain
, YPPROC_NEXT
, (xdrproc_t
) xdr_ypreq_key
,
563 (caddr_t
) &req
, (xdrproc_t
) xdr_ypresp_key_val
,
566 if (result
!= YPERR_SUCCESS
)
570 if (__builtin_expect ((*outkey
= malloc (resp
.key
.keydat_len
+ 1)) != NULL
571 && (*outval
= malloc (resp
.val
.valdat_len
574 *outkeylen
= resp
.key
.keydat_len
;
575 memcpy (*outkey
, resp
.key
.keydat_val
, *outkeylen
);
576 (*outkey
)[*outkeylen
] = '\0';
578 *outvallen
= resp
.val
.valdat_len
;
579 memcpy (*outval
, resp
.val
.valdat_val
, *outvallen
);
580 (*outval
)[*outvallen
] = '\0';
582 status
= YPERR_SUCCESS
;
587 status
= YPERR_RESRC
;
590 xdr_free ((xdrproc_t
) xdr_ypresp_key_val
, (char *) &resp
);
594 libnsl_hidden_nolink_def(yp_next
, GLIBC_2_0
)
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_nolink_def (yp_master
, GLIBC_2_0
)
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
);
654 libnsl_hidden_nolink_def(yp_order
, GLIBC_2_0
)
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 (__glibc_unlikely (result
!= RPC_SUCCESS
))
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
);
798 libnsl_hidden_nolink_def (yp_all
, GLIBC_2_0
)
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 (__glibc_likely (result
== YPERR_SUCCESS
))
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); */
824 libnsl_hidden_nolink_def (yp_maplist
, GLIBC_2_0
)
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");
889 libnsl_hidden_nolink_def(yperr_string
, GLIBC_2_0
)
891 static const int8_t yp_2_yperr
[] =
893 #define YP2YPERR(yp, yperr) [YP_##yp - YP_VERS] = YPERR_##yperr
894 YP2YPERR (TRUE
, SUCCESS
),
895 YP2YPERR (NOMORE
, NOMORE
),
896 YP2YPERR (FALSE
, YPERR
),
897 YP2YPERR (NOMAP
, MAP
),
898 YP2YPERR (NODOM
, DOMAIN
),
899 YP2YPERR (NOKEY
, KEY
),
900 YP2YPERR (BADOP
, YPERR
),
901 YP2YPERR (BADDB
, BADDB
),
902 YP2YPERR (YPERR
, YPERR
),
903 YP2YPERR (BADARGS
, BADARGS
),
904 YP2YPERR (VERS
, VERS
)
907 ypprot_err (const int code
)
909 if (code
< YP_VERS
|| code
> YP_NOMORE
)
911 return yp_2_yperr
[code
- YP_VERS
];
913 libnsl_hidden_nolink_def (ypprot_err
, GLIBC_2_0
)
916 ypbinderr_string (const int error
)
925 str
= N_("Internal ypbind error");
927 case YPBIND_ERR_NOSERV
:
928 str
= N_("Domain not bound");
930 case YPBIND_ERR_RESC
:
931 str
= N_("System resource allocation failure");
934 str
= N_("Unknown ypbind error");
939 libnsl_hidden_nolink_def (ypbinderr_string
, GLIBC_2_0
)
944 yp_update (char *domain
, char *map
, unsigned ypop
,
945 char *key
, int keylen
, char *data
, int datalen
)
949 ypupdate_args update_args
;
950 ypdelete_args delete_args
;
953 xdrproc_t xdr_argument
;
957 struct sockaddr saddr
;
958 char servername
[MAXNETNAMELEN
+ 1];
961 if (!domain
|| !map
|| !key
|| (ypop
!= YPOP_DELETE
&& !data
))
962 return YPERR_BADARGS
;
964 args
.update_args
.mapname
= map
;
965 args
.update_args
.key
.yp_buf_len
= keylen
;
966 args
.update_args
.key
.yp_buf_val
= key
;
967 args
.update_args
.datum
.yp_buf_len
= datalen
;
968 args
.update_args
.datum
.yp_buf_val
= data
;
970 if ((r
= yp_master (domain
, map
, &master
)) != YPERR_SUCCESS
)
973 if (!host2netname (servername
, master
, domain
))
975 fputs (_("yp_update: cannot convert host to netname\n"), stderr
);
980 clnt
= clnt_create (master
, YPU_PROG
, YPU_VERS
, "tcp");
982 /* We do not need the string anymore. */
987 clnt_pcreateerror ("yp_update: clnt_create");
991 if (!clnt_control (clnt
, CLGET_SERVER_ADDR
, (char *) &saddr
))
993 fputs (_("yp_update: cannot get server address\n"), stderr
);
1002 xdr_argument
= (xdrproc_t
) xdr_ypupdate_args
;
1005 xdr_argument
= (xdrproc_t
) xdr_ypdelete_args
;
1008 return YPERR_BADARGS
;
1012 clnt
->cl_auth
= authdes_create (servername
, WINDOW
, &saddr
, NULL
);
1014 if (clnt
->cl_auth
== NULL
)
1015 clnt
->cl_auth
= authunix_create_default ();
1018 r
= clnt_call (clnt
, ypop
, xdr_argument
, (caddr_t
) &args
,
1019 (xdrproc_t
) xdr_u_int
, (caddr_t
) &res
, RPCTIMEOUT
);
1021 if (r
== RPC_AUTHERROR
)
1023 if (clnt
->cl_auth
->ah_cred
.oa_flavor
== AUTH_DES
)
1025 auth_destroy (clnt
->cl_auth
);
1026 clnt
->cl_auth
= authunix_create_default ();
1030 return YPERR_ACCESS
;
1032 if (r
!= RPC_SUCCESS
)
1034 clnt_perror (clnt
, "yp_update: clnt_call");
1039 libnsl_hidden_nolink_def(yp_update
, GLIBC_2_0
)