1 /* Copyright (C) 1996-2023 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
4 The GNU C Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
9 The GNU C Library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
14 You should have received a copy of the GNU Lesser General Public
15 License along with the GNU C Library; if not, see
16 <https://www.gnu.org/licenses/>. */
24 #include <rpcsvc/nis.h>
25 #include <rpcsvc/yp.h>
26 #include <rpcsvc/ypclnt.h>
27 #include <rpcsvc/ypupd.h>
28 #include <sys/socket.h>
30 #include <libc-lock.h>
31 #include <shlib-compat.h>
32 #include <libc-diag.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
;
72 ysd
->dom_client
= __libc_clntudp_bufcreate (&ysd
->dom_server_addr
, YPPROG
,
75 UDPMSGSIZE
, UDPMSGSIZE
,
81 yp_bind_file (const char *domain
, dom_binding
*ysd
)
83 char path
[sizeof (BINDINGDIR
) + strlen (domain
) + 3 * sizeof (unsigned) + 3];
85 snprintf (path
, sizeof (path
), "%s/%s.%u", BINDINGDIR
, domain
, YPBINDVERS
);
86 int fd
= open (path
, O_RDONLY
);
89 /* We have a binding file and could save a RPC call. The file
90 contains a port number and the YPBIND_RESP record. The port
91 number (16 bits) can be ignored. */
92 struct ypbind_resp ypbr
;
94 if (pread (fd
, &ypbr
, sizeof (ypbr
), 2) == sizeof (ypbr
))
95 yp_bind_client_create (domain
, ysd
, &ypbr
);
103 yp_bind_ypbindprog (const char *domain
, dom_binding
*ysd
)
105 struct sockaddr_in clnt_saddr
;
106 struct ypbind_resp ypbr
;
110 clnt_saddr
.sin_family
= AF_INET
;
111 clnt_saddr
.sin_port
= 0;
112 clnt_saddr
.sin_addr
.s_addr
= htonl (INADDR_LOOPBACK
);
113 clnt_sock
= RPC_ANYSOCK
;
114 client
= clnttcp_create (&clnt_saddr
, YPBINDPROG
, YPBINDVERS
,
119 /* Check the port number -- should be < IPPORT_RESERVED.
120 If not, it's possible someone has registered a bogus
121 ypbind with the portmapper and is trying to trick us. */
122 if (ntohs (clnt_saddr
.sin_port
) >= IPPORT_RESERVED
)
124 clnt_destroy (client
);
128 if (clnt_call (client
, YPBINDPROC_DOMAIN
,
129 (xdrproc_t
) xdr_domainname
, (caddr_t
) &domain
,
130 (xdrproc_t
) xdr_ypbind_resp
,
131 (caddr_t
) &ypbr
, RPCTIMEOUT
) != RPC_SUCCESS
)
133 clnt_destroy (client
);
137 clnt_destroy (client
);
139 if (ypbr
.ypbind_status
!= YPBIND_SUCC_VAL
)
141 fprintf (stderr
, "YPBINDPROC_DOMAIN: %s\n",
142 ypbinderr_string (ypbr
.ypbind_resp_u
.ypbind_error
));
145 memset (&ysd
->dom_server_addr
, '\0', sizeof ysd
->dom_server_addr
);
147 yp_bind_client_create (domain
, ysd
, &ypbr
);
149 return YPERR_SUCCESS
;
153 __yp_bind (const char *domain
, dom_binding
**ypdb
)
155 dom_binding
*ysd
= NULL
;
158 if (domain
== NULL
|| domain
[0] == '\0')
159 return YPERR_BADARGS
;
164 if (strcmp (domain
, ysd
->dom_domain
) == 0)
166 ysd
= ysd
->dom_pnext
;
172 ysd
= (dom_binding
*) calloc (1, sizeof *ysd
);
173 if (__glibc_unlikely (ysd
== NULL
))
178 /* Try binding dir at first if we have no binding */
179 if (ysd
->dom_client
== NULL
)
180 yp_bind_file (domain
, ysd
);
181 #endif /* USE_BINDINGDIR */
183 if (ysd
->dom_client
== NULL
)
185 int retval
= yp_bind_ypbindprog (domain
, ysd
);
186 if (retval
!= YPERR_SUCCESS
)
194 if (ysd
->dom_client
== NULL
)
203 ysd
->dom_pnext
= *ypdb
;
207 return YPERR_SUCCESS
;
211 __yp_unbind (dom_binding
*ydb
)
213 clnt_destroy (ydb
->dom_client
);
218 yp_bind (const char *indomain
)
222 __libc_lock_lock (ypbindlist_lock
);
224 status
= __yp_bind (indomain
, &ypbindlist
);
226 __libc_lock_unlock (ypbindlist_lock
);
230 libnsl_hidden_nolink_def (yp_bind
, GLIBC_2_0
)
233 yp_unbind_locked (const char *indomain
)
235 dom_binding
*ydbptr
, *ydbptr2
;
240 while (ydbptr
!= NULL
)
242 if (strcmp (ydbptr
->dom_domain
, indomain
) == 0)
248 ypbindlist
= ypbindlist
->dom_pnext
;
250 ydbptr2
= ydbptr
->dom_pnext
;
255 ydbptr
= ydbptr
->dom_pnext
;
260 yp_unbind (const char *indomain
)
262 __libc_lock_lock (ypbindlist_lock
);
264 yp_unbind_locked (indomain
);
266 __libc_lock_unlock (ypbindlist_lock
);
270 libnsl_hidden_nolink_def(yp_unbind
, GLIBC_2_0
)
273 __ypclnt_call (const char *domain
, u_long prog
, xdrproc_t xargs
,
274 caddr_t req
, xdrproc_t xres
, caddr_t resp
, dom_binding
**ydb
,
277 enum clnt_stat result
;
279 result
= clnt_call ((*ydb
)->dom_client
, prog
,
280 xargs
, req
, xres
, resp
, RPCTIMEOUT
);
282 if (result
!= RPC_SUCCESS
)
284 /* We don't print an error message, if we try our old,
285 cached data. Only print this for data, which should work. */
287 clnt_perror ((*ydb
)->dom_client
, "do_ypcall: clnt_call");
292 return YPERR_SUCCESS
;
296 do_ypcall (const char *domain
, u_long prog
, xdrproc_t xargs
,
297 caddr_t req
, xdrproc_t xres
, caddr_t resp
)
301 int saved_errno
= errno
;
303 status
= YPERR_YPERR
;
305 __libc_lock_lock (ypbindlist_lock
);
309 if (strcmp (domain
, ydb
->dom_domain
) == 0)
311 if (__yp_bind (domain
, &ydb
) == 0)
313 /* Call server, print no error message, do not unbind. */
314 status
= __ypclnt_call (domain
, prog
, xargs
, req
, xres
,
316 if (status
== YPERR_SUCCESS
)
318 __libc_lock_unlock (ypbindlist_lock
);
319 __set_errno (saved_errno
);
323 /* We use ypbindlist, and the old cached data is
324 invalid. unbind now and create a new binding */
325 yp_unbind_locked (domain
);
329 ydb
= ydb
->dom_pnext
;
331 __libc_lock_unlock (ypbindlist_lock
);
333 /* First try with cached data failed. Now try to get
334 current data from the system. */
336 if (__yp_bind (domain
, &ydb
) == 0)
338 status
= __ypclnt_call (domain
, prog
, xargs
, req
, xres
,
344 /* If we support binding dir data, we have a third chance:
346 if (status
!= YPERR_SUCCESS
)
348 ydb
= calloc (1, sizeof (dom_binding
));
349 if (ydb
!= NULL
&& yp_bind_ypbindprog (domain
, ydb
) == YPERR_SUCCESS
)
351 status
= __ypclnt_call (domain
, prog
, xargs
, req
, xres
,
360 __set_errno (saved_errno
);
365 /* Like do_ypcall, but translate the status value if necessary. */
367 do_ypcall_tr (const char *domain
, u_long prog
, xdrproc_t xargs
,
368 caddr_t req
, xdrproc_t xres
, caddr_t resp
)
370 int status
= do_ypcall (domain
, prog
, xargs
, req
, xres
, resp
);
371 DIAG_PUSH_NEEDS_COMMENT
;
372 /* This cast results in a warning that a ypresp_val is partly
373 outside the bounds of the actual object referenced, but as
374 explained below only the stat element (in a common prefix) is
376 DIAG_IGNORE_NEEDS_COMMENT (11, "-Warray-bounds");
377 if (status
== YPERR_SUCCESS
)
378 /* We cast to ypresp_val although the pointer could also be of
379 type ypresp_key_val or ypresp_master or ypresp_order or
380 ypresp_maplist. But the stat element is in a common prefix so
381 this does not matter. */
382 status
= ypprot_err (((struct ypresp_val
*) resp
)->stat
);
383 DIAG_POP_NEEDS_COMMENT
;
388 __libc_lock_define_initialized (static, domainname_lock
)
391 yp_get_default_domain (char **outdomain
)
393 int result
= YPERR_SUCCESS
;;
396 __libc_lock_lock (domainname_lock
);
398 if (ypdomainname
[0] == '\0')
400 if (getdomainname (ypdomainname
, NIS_MAXNAMELEN
))
401 result
= YPERR_NODOM
;
402 else if (strcmp (ypdomainname
, "(none)") == 0)
404 /* If domainname is not set, some systems will return "(none)" */
405 ypdomainname
[0] = '\0';
406 result
= YPERR_NODOM
;
409 *outdomain
= ypdomainname
;
412 *outdomain
= ypdomainname
;
414 __libc_lock_unlock (domainname_lock
);
418 libnsl_hidden_nolink_def (yp_get_default_domain
, GLIBC_2_0
)
421 __yp_check (char **domain
)
425 if (ypdomainname
[0] == '\0')
426 if (yp_get_default_domain (&unused
))
430 *domain
= ypdomainname
;
432 if (yp_bind (ypdomainname
) == 0)
436 libnsl_hidden_nolink_def(__yp_check
, GLIBC_2_0
)
439 yp_match (const char *indomain
, const char *inmap
, const char *inkey
,
440 const int inkeylen
, char **outval
, int *outvallen
)
444 enum clnt_stat result
;
446 if (indomain
== NULL
|| indomain
[0] == '\0'
447 || inmap
== NULL
|| inmap
[0] == '\0'
448 || inkey
== NULL
|| inkey
[0] == '\0' || inkeylen
<= 0)
449 return YPERR_BADARGS
;
451 req
.domain
= (char *) indomain
;
452 req
.map
= (char *) inmap
;
453 req
.key
.keydat_val
= (char *) inkey
;
454 req
.key
.keydat_len
= inkeylen
;
458 memset (&resp
, '\0', sizeof (resp
));
460 result
= do_ypcall_tr (indomain
, YPPROC_MATCH
, (xdrproc_t
) xdr_ypreq_key
,
461 (caddr_t
) &req
, (xdrproc_t
) xdr_ypresp_val
,
464 if (result
!= YPERR_SUCCESS
)
467 *outvallen
= resp
.val
.valdat_len
;
468 *outval
= malloc (*outvallen
+ 1);
469 int status
= YPERR_RESRC
;
470 if (__glibc_likely (*outval
!= NULL
))
472 memcpy (*outval
, resp
.val
.valdat_val
, *outvallen
);
473 (*outval
)[*outvallen
] = '\0';
474 status
= YPERR_SUCCESS
;
477 xdr_free ((xdrproc_t
) xdr_ypresp_val
, (char *) &resp
);
481 libnsl_hidden_nolink_def(yp_match
, GLIBC_2_0
)
484 yp_first (const char *indomain
, const char *inmap
, char **outkey
,
485 int *outkeylen
, char **outval
, int *outvallen
)
489 enum clnt_stat result
;
491 if (indomain
== NULL
|| indomain
[0] == '\0'
492 || inmap
== NULL
|| inmap
[0] == '\0')
493 return YPERR_BADARGS
;
495 req
.domain
= (char *) indomain
;
496 req
.map
= (char *) inmap
;
498 *outkey
= *outval
= NULL
;
499 *outkeylen
= *outvallen
= 0;
500 memset (&resp
, '\0', sizeof (resp
));
502 result
= do_ypcall (indomain
, YPPROC_FIRST
, (xdrproc_t
) xdr_ypreq_nokey
,
503 (caddr_t
) &req
, (xdrproc_t
) xdr_ypresp_key_val
,
506 if (result
!= RPC_SUCCESS
)
508 if (resp
.stat
!= YP_TRUE
)
509 return ypprot_err (resp
.stat
);
512 if (__builtin_expect ((*outkey
= malloc (resp
.key
.keydat_len
+ 1)) != NULL
513 && (*outval
= malloc (resp
.val
.valdat_len
516 *outkeylen
= resp
.key
.keydat_len
;
517 memcpy (*outkey
, resp
.key
.keydat_val
, *outkeylen
);
518 (*outkey
)[*outkeylen
] = '\0';
520 *outvallen
= resp
.val
.valdat_len
;
521 memcpy (*outval
, resp
.val
.valdat_val
, *outvallen
);
522 (*outval
)[*outvallen
] = '\0';
524 status
= YPERR_SUCCESS
;
529 status
= YPERR_RESRC
;
532 xdr_free ((xdrproc_t
) xdr_ypresp_key_val
, (char *) &resp
);
536 libnsl_hidden_nolink_def(yp_first
, GLIBC_2_0
)
539 yp_next (const char *indomain
, const char *inmap
, const char *inkey
,
540 const int inkeylen
, char **outkey
, int *outkeylen
, char **outval
,
545 enum clnt_stat result
;
547 if (indomain
== NULL
|| indomain
[0] == '\0'
548 || inmap
== NULL
|| inmap
[0] == '\0'
549 || inkeylen
<= 0 || inkey
== NULL
|| inkey
[0] == '\0')
550 return YPERR_BADARGS
;
552 req
.domain
= (char *) indomain
;
553 req
.map
= (char *) inmap
;
554 req
.key
.keydat_val
= (char *) inkey
;
555 req
.key
.keydat_len
= inkeylen
;
557 *outkey
= *outval
= NULL
;
558 *outkeylen
= *outvallen
= 0;
559 memset (&resp
, '\0', sizeof (resp
));
561 result
= do_ypcall_tr (indomain
, YPPROC_NEXT
, (xdrproc_t
) xdr_ypreq_key
,
562 (caddr_t
) &req
, (xdrproc_t
) xdr_ypresp_key_val
,
565 if (result
!= YPERR_SUCCESS
)
569 if (__builtin_expect ((*outkey
= malloc (resp
.key
.keydat_len
+ 1)) != NULL
570 && (*outval
= malloc (resp
.val
.valdat_len
573 *outkeylen
= resp
.key
.keydat_len
;
574 memcpy (*outkey
, resp
.key
.keydat_val
, *outkeylen
);
575 (*outkey
)[*outkeylen
] = '\0';
577 *outvallen
= resp
.val
.valdat_len
;
578 memcpy (*outval
, resp
.val
.valdat_val
, *outvallen
);
579 (*outval
)[*outvallen
] = '\0';
581 status
= YPERR_SUCCESS
;
586 status
= YPERR_RESRC
;
589 xdr_free ((xdrproc_t
) xdr_ypresp_key_val
, (char *) &resp
);
593 libnsl_hidden_nolink_def(yp_next
, GLIBC_2_0
)
596 yp_master (const char *indomain
, const char *inmap
, char **outname
)
600 enum clnt_stat result
;
602 if (indomain
== NULL
|| indomain
[0] == '\0'
603 || inmap
== NULL
|| inmap
[0] == '\0')
604 return YPERR_BADARGS
;
606 req
.domain
= (char *) indomain
;
607 req
.map
= (char *) inmap
;
609 memset (&resp
, '\0', sizeof (ypresp_master
));
611 result
= do_ypcall_tr (indomain
, YPPROC_MASTER
, (xdrproc_t
) xdr_ypreq_nokey
,
612 (caddr_t
) &req
, (xdrproc_t
) xdr_ypresp_master
,
615 if (result
!= YPERR_SUCCESS
)
618 *outname
= strdup (resp
.peer
);
619 xdr_free ((xdrproc_t
) xdr_ypresp_master
, (char *) &resp
);
621 return *outname
== NULL
? YPERR_YPERR
: YPERR_SUCCESS
;
623 libnsl_hidden_nolink_def (yp_master
, GLIBC_2_0
)
626 yp_order (const char *indomain
, const char *inmap
, unsigned int *outorder
)
628 struct ypreq_nokey req
;
629 struct ypresp_order resp
;
630 enum clnt_stat result
;
632 if (indomain
== NULL
|| indomain
[0] == '\0'
633 || inmap
== NULL
|| inmap
[0] == '\0')
634 return YPERR_BADARGS
;
636 req
.domain
= (char *) indomain
;
637 req
.map
= (char *) inmap
;
639 memset (&resp
, '\0', sizeof (resp
));
641 result
= do_ypcall_tr (indomain
, YPPROC_ORDER
, (xdrproc_t
) xdr_ypreq_nokey
,
642 (caddr_t
) &req
, (xdrproc_t
) xdr_ypresp_order
,
645 if (result
!= YPERR_SUCCESS
)
648 *outorder
= resp
.ordernum
;
649 xdr_free ((xdrproc_t
) xdr_ypresp_order
, (char *) &resp
);
653 libnsl_hidden_nolink_def(yp_order
, GLIBC_2_0
)
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
);
797 libnsl_hidden_nolink_def (yp_all
, GLIBC_2_0
)
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); */
823 libnsl_hidden_nolink_def (yp_maplist
, GLIBC_2_0
)
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");
888 libnsl_hidden_nolink_def(yperr_string
, GLIBC_2_0
)
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_nolink_def (ypprot_err
, GLIBC_2_0
)
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_nolink_def (ypbinderr_string
, GLIBC_2_0
)
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");
1038 libnsl_hidden_nolink_def(yp_update
, GLIBC_2_0
)