1 /* Copyright (C) 1996-2018 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 <libc-lock.h>
32 #include <shlib-compat.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 if (status
== YPERR_SUCCESS
)
372 /* We cast to ypresp_val although the pointer could also be of
373 type ypresp_key_val or ypresp_master or ypresp_order or
374 ypresp_maplist. But the stat element is in a common prefix so
375 this does not matter. */
376 status
= ypprot_err (((struct ypresp_val
*) resp
)->stat
);
381 __libc_lock_define_initialized (static, domainname_lock
)
384 yp_get_default_domain (char **outdomain
)
386 int result
= YPERR_SUCCESS
;;
389 __libc_lock_lock (domainname_lock
);
391 if (ypdomainname
[0] == '\0')
393 if (getdomainname (ypdomainname
, NIS_MAXNAMELEN
))
394 result
= YPERR_NODOM
;
395 else if (strcmp (ypdomainname
, "(none)") == 0)
397 /* If domainname is not set, some systems will return "(none)" */
398 ypdomainname
[0] = '\0';
399 result
= YPERR_NODOM
;
402 *outdomain
= ypdomainname
;
405 *outdomain
= ypdomainname
;
407 __libc_lock_unlock (domainname_lock
);
411 libnsl_hidden_nolink_def (yp_get_default_domain
, GLIBC_2_0
)
414 __yp_check (char **domain
)
418 if (ypdomainname
[0] == '\0')
419 if (yp_get_default_domain (&unused
))
423 *domain
= ypdomainname
;
425 if (yp_bind (ypdomainname
) == 0)
429 libnsl_hidden_nolink_def(__yp_check
, GLIBC_2_0
)
432 yp_match (const char *indomain
, const char *inmap
, const char *inkey
,
433 const int inkeylen
, char **outval
, int *outvallen
)
437 enum clnt_stat result
;
439 if (indomain
== NULL
|| indomain
[0] == '\0' ||
440 inmap
== NULL
|| inmap
[0] == '\0' ||
441 inkey
== NULL
|| inkey
[0] == '\0' || inkeylen
<= 0)
442 return YPERR_BADARGS
;
444 req
.domain
= (char *) indomain
;
445 req
.map
= (char *) inmap
;
446 req
.key
.keydat_val
= (char *) inkey
;
447 req
.key
.keydat_len
= inkeylen
;
451 memset (&resp
, '\0', sizeof (resp
));
453 result
= do_ypcall_tr (indomain
, YPPROC_MATCH
, (xdrproc_t
) xdr_ypreq_key
,
454 (caddr_t
) &req
, (xdrproc_t
) xdr_ypresp_val
,
457 if (result
!= YPERR_SUCCESS
)
460 *outvallen
= resp
.val
.valdat_len
;
461 *outval
= malloc (*outvallen
+ 1);
462 int status
= YPERR_RESRC
;
463 if (__glibc_likely (*outval
!= NULL
))
465 memcpy (*outval
, resp
.val
.valdat_val
, *outvallen
);
466 (*outval
)[*outvallen
] = '\0';
467 status
= YPERR_SUCCESS
;
470 xdr_free ((xdrproc_t
) xdr_ypresp_val
, (char *) &resp
);
474 libnsl_hidden_nolink_def(yp_match
, GLIBC_2_0
)
477 yp_first (const char *indomain
, const char *inmap
, char **outkey
,
478 int *outkeylen
, char **outval
, int *outvallen
)
482 enum clnt_stat result
;
484 if (indomain
== NULL
|| indomain
[0] == '\0' ||
485 inmap
== NULL
|| inmap
[0] == '\0')
486 return YPERR_BADARGS
;
488 req
.domain
= (char *) indomain
;
489 req
.map
= (char *) inmap
;
491 *outkey
= *outval
= NULL
;
492 *outkeylen
= *outvallen
= 0;
493 memset (&resp
, '\0', sizeof (resp
));
495 result
= do_ypcall (indomain
, YPPROC_FIRST
, (xdrproc_t
) xdr_ypreq_nokey
,
496 (caddr_t
) &req
, (xdrproc_t
) xdr_ypresp_key_val
,
499 if (result
!= RPC_SUCCESS
)
501 if (resp
.stat
!= YP_TRUE
)
502 return ypprot_err (resp
.stat
);
505 if (__builtin_expect ((*outkey
= malloc (resp
.key
.keydat_len
+ 1)) != NULL
506 && (*outval
= malloc (resp
.val
.valdat_len
509 *outkeylen
= resp
.key
.keydat_len
;
510 memcpy (*outkey
, resp
.key
.keydat_val
, *outkeylen
);
511 (*outkey
)[*outkeylen
] = '\0';
513 *outvallen
= resp
.val
.valdat_len
;
514 memcpy (*outval
, resp
.val
.valdat_val
, *outvallen
);
515 (*outval
)[*outvallen
] = '\0';
517 status
= YPERR_SUCCESS
;
522 status
= YPERR_RESRC
;
525 xdr_free ((xdrproc_t
) xdr_ypresp_key_val
, (char *) &resp
);
529 libnsl_hidden_nolink_def(yp_first
, GLIBC_2_0
)
532 yp_next (const char *indomain
, const char *inmap
, const char *inkey
,
533 const int inkeylen
, char **outkey
, int *outkeylen
, char **outval
,
538 enum clnt_stat result
;
540 if (indomain
== NULL
|| indomain
[0] == '\0' ||
541 inmap
== NULL
|| inmap
[0] == '\0' ||
542 inkeylen
<= 0 || inkey
== NULL
|| inkey
[0] == '\0')
543 return YPERR_BADARGS
;
545 req
.domain
= (char *) indomain
;
546 req
.map
= (char *) inmap
;
547 req
.key
.keydat_val
= (char *) inkey
;
548 req
.key
.keydat_len
= inkeylen
;
550 *outkey
= *outval
= NULL
;
551 *outkeylen
= *outvallen
= 0;
552 memset (&resp
, '\0', sizeof (resp
));
554 result
= do_ypcall_tr (indomain
, YPPROC_NEXT
, (xdrproc_t
) xdr_ypreq_key
,
555 (caddr_t
) &req
, (xdrproc_t
) xdr_ypresp_key_val
,
558 if (result
!= YPERR_SUCCESS
)
562 if (__builtin_expect ((*outkey
= malloc (resp
.key
.keydat_len
+ 1)) != NULL
563 && (*outval
= malloc (resp
.val
.valdat_len
566 *outkeylen
= resp
.key
.keydat_len
;
567 memcpy (*outkey
, resp
.key
.keydat_val
, *outkeylen
);
568 (*outkey
)[*outkeylen
] = '\0';
570 *outvallen
= resp
.val
.valdat_len
;
571 memcpy (*outval
, resp
.val
.valdat_val
, *outvallen
);
572 (*outval
)[*outvallen
] = '\0';
574 status
= YPERR_SUCCESS
;
579 status
= YPERR_RESRC
;
582 xdr_free ((xdrproc_t
) xdr_ypresp_key_val
, (char *) &resp
);
586 libnsl_hidden_nolink_def(yp_next
, GLIBC_2_0
)
589 yp_master (const char *indomain
, const char *inmap
, char **outname
)
593 enum clnt_stat result
;
595 if (indomain
== NULL
|| indomain
[0] == '\0' ||
596 inmap
== NULL
|| inmap
[0] == '\0')
597 return YPERR_BADARGS
;
599 req
.domain
= (char *) indomain
;
600 req
.map
= (char *) inmap
;
602 memset (&resp
, '\0', sizeof (ypresp_master
));
604 result
= do_ypcall_tr (indomain
, YPPROC_MASTER
, (xdrproc_t
) xdr_ypreq_nokey
,
605 (caddr_t
) &req
, (xdrproc_t
) xdr_ypresp_master
,
608 if (result
!= YPERR_SUCCESS
)
611 *outname
= strdup (resp
.peer
);
612 xdr_free ((xdrproc_t
) xdr_ypresp_master
, (char *) &resp
);
614 return *outname
== NULL
? YPERR_YPERR
: YPERR_SUCCESS
;
616 libnsl_hidden_nolink_def (yp_master
, GLIBC_2_0
)
619 yp_order (const char *indomain
, const char *inmap
, unsigned int *outorder
)
621 struct ypreq_nokey req
;
622 struct ypresp_order resp
;
623 enum clnt_stat result
;
625 if (indomain
== NULL
|| indomain
[0] == '\0' ||
626 inmap
== NULL
|| inmap
[0] == '\0')
627 return YPERR_BADARGS
;
629 req
.domain
= (char *) indomain
;
630 req
.map
= (char *) inmap
;
632 memset (&resp
, '\0', sizeof (resp
));
634 result
= do_ypcall_tr (indomain
, YPPROC_ORDER
, (xdrproc_t
) xdr_ypreq_nokey
,
635 (caddr_t
) &req
, (xdrproc_t
) xdr_ypresp_order
,
638 if (result
!= YPERR_SUCCESS
)
641 *outorder
= resp
.ordernum
;
642 xdr_free ((xdrproc_t
) xdr_ypresp_order
, (char *) &resp
);
646 libnsl_hidden_nolink_def(yp_order
, GLIBC_2_0
)
648 struct ypresp_all_data
650 unsigned long status
;
652 int (*foreach
) (int status
, char *key
, int keylen
,
653 char *val
, int vallen
, char *data
);
657 __xdr_ypresp_all (XDR
*xdrs
, struct ypresp_all_data
*objp
)
661 struct ypresp_all resp
;
663 memset (&resp
, '\0', sizeof (struct ypresp_all
));
664 if (!xdr_ypresp_all (xdrs
, &resp
))
666 xdr_free ((xdrproc_t
) xdr_ypresp_all
, (char *) &resp
);
667 objp
->status
= YP_YPERR
;
672 xdr_free ((xdrproc_t
) xdr_ypresp_all
, (char *) &resp
);
673 objp
->status
= YP_NOMORE
;
677 switch (resp
.ypresp_all_u
.val
.stat
)
681 char key
[resp
.ypresp_all_u
.val
.key
.keydat_len
+ 1];
682 char val
[resp
.ypresp_all_u
.val
.val
.valdat_len
+ 1];
683 int keylen
= resp
.ypresp_all_u
.val
.key
.keydat_len
;
684 int vallen
= resp
.ypresp_all_u
.val
.val
.valdat_len
;
686 /* We are not allowed to modify the key and val data.
687 But we are allowed to add data behind the buffer,
688 if we don't modify the length. So add an extra NUL
689 character to avoid trouble with broken code. */
690 objp
->status
= YP_TRUE
;
691 *((char *) __mempcpy (key
, resp
.ypresp_all_u
.val
.key
.keydat_val
,
693 *((char *) __mempcpy (val
, resp
.ypresp_all_u
.val
.val
.valdat_val
,
695 xdr_free ((xdrproc_t
) xdr_ypresp_all
, (char *) &resp
);
696 if ((*objp
->foreach
) (objp
->status
, key
, keylen
,
697 val
, vallen
, objp
->data
))
702 objp
->status
= resp
.ypresp_all_u
.val
.stat
;
703 xdr_free ((xdrproc_t
) xdr_ypresp_all
, (char *) &resp
);
704 /* Sun says we don't need to make this call, but must return
705 immediately. Since Solaris makes this call, we will call
706 the callback function, too. */
707 (*objp
->foreach
) (objp
->status
, NULL
, 0, NULL
, 0, objp
->data
);
714 yp_all (const char *indomain
, const char *inmap
,
715 const struct ypall_callback
*incallback
)
717 struct ypreq_nokey req
;
718 dom_binding
*ydb
= NULL
;
720 enum clnt_stat result
;
721 struct sockaddr_in clnt_sin
;
723 struct ypresp_all_data data
;
725 int saved_errno
= errno
;
727 if (indomain
== NULL
|| indomain
[0] == '\0'
728 || inmap
== NULL
|| inmap
[0] == '\0')
729 return YPERR_BADARGS
;
734 while (try < MAXTRIES
&& res
!= YPERR_SUCCESS
)
736 if (__yp_bind (indomain
, &ydb
) != 0)
738 __set_errno (saved_errno
);
742 clnt_sock
= RPC_ANYSOCK
;
743 clnt_sin
= ydb
->dom_server_addr
;
744 clnt_sin
.sin_port
= 0;
746 /* We don't need the UDP connection anymore. */
750 clnt
= clnttcp_create (&clnt_sin
, YPPROG
, YPVERS
, &clnt_sock
, 0, 0);
753 __set_errno (saved_errno
);
756 req
.domain
= (char *) indomain
;
757 req
.map
= (char *) inmap
;
759 data
.foreach
= incallback
->foreach
;
760 data
.data
= (void *) incallback
->data
;
762 result
= clnt_call (clnt
, YPPROC_ALL
, (xdrproc_t
) xdr_ypreq_nokey
,
763 (caddr_t
) &req
, (xdrproc_t
) __xdr_ypresp_all
,
764 (caddr_t
) &data
, RPCTIMEOUT
);
766 if (__glibc_unlikely (result
!= RPC_SUCCESS
))
768 /* Print the error message only on the last try. */
769 if (try == MAXTRIES
- 1)
770 clnt_perror (clnt
, "yp_all: clnt_call");
778 if (res
== YPERR_SUCCESS
&& data
.status
!= YP_NOMORE
)
780 __set_errno (saved_errno
);
781 return ypprot_err (data
.status
);
786 __set_errno (saved_errno
);
790 libnsl_hidden_nolink_def (yp_all
, GLIBC_2_0
)
793 yp_maplist (const char *indomain
, struct ypmaplist
**outmaplist
)
795 struct ypresp_maplist resp
;
796 enum clnt_stat result
;
798 if (indomain
== NULL
|| indomain
[0] == '\0')
799 return YPERR_BADARGS
;
801 memset (&resp
, '\0', sizeof (resp
));
803 result
= do_ypcall_tr (indomain
, YPPROC_MAPLIST
, (xdrproc_t
) xdr_domainname
,
804 (caddr_t
) &indomain
, (xdrproc_t
) xdr_ypresp_maplist
,
807 if (__glibc_likely (result
== YPERR_SUCCESS
))
809 *outmaplist
= resp
.maps
;
810 /* We don't free the list, this will be done by ypserv
811 xdr_free((xdrproc_t)xdr_ypresp_maplist, (char *)&resp); */
816 libnsl_hidden_nolink_def (yp_maplist
, GLIBC_2_0
)
819 yperr_string (const int error
)
828 str
= N_("Request arguments bad");
831 str
= N_("RPC failure on NIS operation");
834 str
= N_("Can't bind to server which serves this domain");
837 str
= N_("No such map in server's domain");
840 str
= N_("No such key in map");
843 str
= N_("Internal NIS error");
846 str
= N_("Local resource allocation failure");
849 str
= N_("No more records in map database");
852 str
= N_("Can't communicate with portmapper");
855 str
= N_("Can't communicate with ypbind");
858 str
= N_("Can't communicate with ypserv");
861 str
= N_("Local domain name not set");
864 str
= N_("NIS map database is bad");
867 str
= N_("NIS client/server version mismatch - can't supply service");
870 str
= N_("Permission denied");
873 str
= N_("Database is busy");
876 str
= N_("Unknown NIS error code");
881 libnsl_hidden_nolink_def(yperr_string
, GLIBC_2_0
)
883 static const int8_t yp_2_yperr
[] =
885 #define YP2YPERR(yp, yperr) [YP_##yp - YP_VERS] = YPERR_##yperr
886 YP2YPERR (TRUE
, SUCCESS
),
887 YP2YPERR (NOMORE
, NOMORE
),
888 YP2YPERR (FALSE
, YPERR
),
889 YP2YPERR (NOMAP
, MAP
),
890 YP2YPERR (NODOM
, DOMAIN
),
891 YP2YPERR (NOKEY
, KEY
),
892 YP2YPERR (BADOP
, YPERR
),
893 YP2YPERR (BADDB
, BADDB
),
894 YP2YPERR (YPERR
, YPERR
),
895 YP2YPERR (BADARGS
, BADARGS
),
896 YP2YPERR (VERS
, VERS
)
899 ypprot_err (const int code
)
901 if (code
< YP_VERS
|| code
> YP_NOMORE
)
903 return yp_2_yperr
[code
- YP_VERS
];
905 libnsl_hidden_nolink_def (ypprot_err
, GLIBC_2_0
)
908 ypbinderr_string (const int error
)
917 str
= N_("Internal ypbind error");
919 case YPBIND_ERR_NOSERV
:
920 str
= N_("Domain not bound");
922 case YPBIND_ERR_RESC
:
923 str
= N_("System resource allocation failure");
926 str
= N_("Unknown ypbind error");
931 libnsl_hidden_nolink_def (ypbinderr_string
, GLIBC_2_0
)
936 yp_update (char *domain
, char *map
, unsigned ypop
,
937 char *key
, int keylen
, char *data
, int datalen
)
941 ypupdate_args update_args
;
942 ypdelete_args delete_args
;
945 xdrproc_t xdr_argument
;
949 struct sockaddr saddr
;
950 char servername
[MAXNETNAMELEN
+ 1];
953 if (!domain
|| !map
|| !key
|| (ypop
!= YPOP_DELETE
&& !data
))
954 return YPERR_BADARGS
;
956 args
.update_args
.mapname
= map
;
957 args
.update_args
.key
.yp_buf_len
= keylen
;
958 args
.update_args
.key
.yp_buf_val
= key
;
959 args
.update_args
.datum
.yp_buf_len
= datalen
;
960 args
.update_args
.datum
.yp_buf_val
= data
;
962 if ((r
= yp_master (domain
, map
, &master
)) != YPERR_SUCCESS
)
965 if (!host2netname (servername
, master
, domain
))
967 fputs (_("yp_update: cannot convert host to netname\n"), stderr
);
972 clnt
= clnt_create (master
, YPU_PROG
, YPU_VERS
, "tcp");
974 /* We do not need the string anymore. */
979 clnt_pcreateerror ("yp_update: clnt_create");
983 if (!clnt_control (clnt
, CLGET_SERVER_ADDR
, (char *) &saddr
))
985 fputs (_("yp_update: cannot get server address\n"), stderr
);
994 xdr_argument
= (xdrproc_t
) xdr_ypupdate_args
;
997 xdr_argument
= (xdrproc_t
) xdr_ypdelete_args
;
1000 return YPERR_BADARGS
;
1004 clnt
->cl_auth
= authdes_create (servername
, WINDOW
, &saddr
, NULL
);
1006 if (clnt
->cl_auth
== NULL
)
1007 clnt
->cl_auth
= authunix_create_default ();
1010 r
= clnt_call (clnt
, ypop
, xdr_argument
, (caddr_t
) &args
,
1011 (xdrproc_t
) xdr_u_int
, (caddr_t
) &res
, RPCTIMEOUT
);
1013 if (r
== RPC_AUTHERROR
)
1015 if (clnt
->cl_auth
->ah_cred
.oa_flavor
== AUTH_DES
)
1017 auth_destroy (clnt
->cl_auth
);
1018 clnt
->cl_auth
= authunix_create_default ();
1022 return YPERR_ACCESS
;
1024 if (r
!= RPC_SUCCESS
)
1026 clnt_perror (clnt
, "yp_update: clnt_call");
1031 libnsl_hidden_nolink_def(yp_update
, GLIBC_2_0
)