1 /* Copyright (C) 1996-2017 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>
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
;
71 ysd
->dom_client
= __libc_clntudp_bufcreate (&ysd
->dom_server_addr
, YPPROG
,
74 UDPMSGSIZE
, UDPMSGSIZE
,
80 yp_bind_file (const char *domain
, dom_binding
*ysd
)
82 char path
[sizeof (BINDINGDIR
) + strlen (domain
) + 3 * sizeof (unsigned) + 3];
84 snprintf (path
, sizeof (path
), "%s/%s.%u", BINDINGDIR
, domain
, YPBINDVERS
);
85 int fd
= open (path
, O_RDONLY
);
88 /* We have a binding file and could save a RPC call. The file
89 contains a port number and the YPBIND_RESP record. The port
90 number (16 bits) can be ignored. */
91 struct ypbind_resp ypbr
;
93 if (pread (fd
, &ypbr
, sizeof (ypbr
), 2) == sizeof (ypbr
))
94 yp_bind_client_create (domain
, ysd
, &ypbr
);
102 yp_bind_ypbindprog (const char *domain
, dom_binding
*ysd
)
104 struct sockaddr_in clnt_saddr
;
105 struct ypbind_resp ypbr
;
109 clnt_saddr
.sin_family
= AF_INET
;
110 clnt_saddr
.sin_port
= 0;
111 clnt_saddr
.sin_addr
.s_addr
= htonl (INADDR_LOOPBACK
);
112 clnt_sock
= RPC_ANYSOCK
;
113 client
= clnttcp_create (&clnt_saddr
, YPBINDPROG
, YPBINDVERS
,
118 /* Check the port number -- should be < IPPORT_RESERVED.
119 If not, it's possible someone has registered a bogus
120 ypbind with the portmapper and is trying to trick us. */
121 if (ntohs (clnt_saddr
.sin_port
) >= IPPORT_RESERVED
)
123 clnt_destroy (client
);
127 if (clnt_call (client
, YPBINDPROC_DOMAIN
,
128 (xdrproc_t
) xdr_domainname
, (caddr_t
) &domain
,
129 (xdrproc_t
) xdr_ypbind_resp
,
130 (caddr_t
) &ypbr
, RPCTIMEOUT
) != RPC_SUCCESS
)
132 clnt_destroy (client
);
136 clnt_destroy (client
);
138 if (ypbr
.ypbind_status
!= YPBIND_SUCC_VAL
)
140 fprintf (stderr
, "YPBINDPROC_DOMAIN: %s\n",
141 ypbinderr_string (ypbr
.ypbind_resp_u
.ypbind_error
));
144 memset (&ysd
->dom_server_addr
, '\0', sizeof ysd
->dom_server_addr
);
146 yp_bind_client_create (domain
, ysd
, &ypbr
);
148 return YPERR_SUCCESS
;
152 __yp_bind (const char *domain
, dom_binding
**ypdb
)
154 dom_binding
*ysd
= NULL
;
157 if (domain
== NULL
|| domain
[0] == '\0')
158 return YPERR_BADARGS
;
163 if (strcmp (domain
, ysd
->dom_domain
) == 0)
165 ysd
= ysd
->dom_pnext
;
171 ysd
= (dom_binding
*) calloc (1, sizeof *ysd
);
172 if (__glibc_unlikely (ysd
== NULL
))
177 /* Try binding dir at first if we have no binding */
178 if (ysd
->dom_client
== NULL
)
179 yp_bind_file (domain
, ysd
);
180 #endif /* USE_BINDINGDIR */
182 if (ysd
->dom_client
== NULL
)
184 int retval
= yp_bind_ypbindprog (domain
, ysd
);
185 if (retval
!= YPERR_SUCCESS
)
193 if (ysd
->dom_client
== NULL
)
202 ysd
->dom_pnext
= *ypdb
;
206 return YPERR_SUCCESS
;
210 __yp_unbind (dom_binding
*ydb
)
212 clnt_destroy (ydb
->dom_client
);
217 yp_bind (const char *indomain
)
221 __libc_lock_lock (ypbindlist_lock
);
223 status
= __yp_bind (indomain
, &ypbindlist
);
225 __libc_lock_unlock (ypbindlist_lock
);
229 libnsl_hidden_nolink_def (yp_bind
, GLIBC_2_0
)
232 yp_unbind_locked (const char *indomain
)
234 dom_binding
*ydbptr
, *ydbptr2
;
239 while (ydbptr
!= NULL
)
241 if (strcmp (ydbptr
->dom_domain
, indomain
) == 0)
247 ypbindlist
= ypbindlist
->dom_pnext
;
249 ydbptr2
= ydbptr
->dom_pnext
;
254 ydbptr
= ydbptr
->dom_pnext
;
259 yp_unbind (const char *indomain
)
261 __libc_lock_lock (ypbindlist_lock
);
263 yp_unbind_locked (indomain
);
265 __libc_lock_unlock (ypbindlist_lock
);
269 libnsl_hidden_nolink_def(yp_unbind
, GLIBC_2_0
)
272 __ypclnt_call (const char *domain
, u_long prog
, xdrproc_t xargs
,
273 caddr_t req
, xdrproc_t xres
, caddr_t resp
, dom_binding
**ydb
,
276 enum clnt_stat result
;
278 result
= clnt_call ((*ydb
)->dom_client
, prog
,
279 xargs
, req
, xres
, resp
, RPCTIMEOUT
);
281 if (result
!= RPC_SUCCESS
)
283 /* We don't print an error message, if we try our old,
284 cached data. Only print this for data, which should work. */
286 clnt_perror ((*ydb
)->dom_client
, "do_ypcall: clnt_call");
291 return YPERR_SUCCESS
;
295 do_ypcall (const char *domain
, u_long prog
, xdrproc_t xargs
,
296 caddr_t req
, xdrproc_t xres
, caddr_t resp
)
300 int saved_errno
= errno
;
302 status
= YPERR_YPERR
;
304 __libc_lock_lock (ypbindlist_lock
);
308 if (strcmp (domain
, ydb
->dom_domain
) == 0)
310 if (__yp_bind (domain
, &ydb
) == 0)
312 /* Call server, print no error message, do not unbind. */
313 status
= __ypclnt_call (domain
, prog
, xargs
, req
, xres
,
315 if (status
== YPERR_SUCCESS
)
317 __libc_lock_unlock (ypbindlist_lock
);
318 __set_errno (saved_errno
);
322 /* We use ypbindlist, and the old cached data is
323 invalid. unbind now and create a new binding */
324 yp_unbind_locked (domain
);
328 ydb
= ydb
->dom_pnext
;
330 __libc_lock_unlock (ypbindlist_lock
);
332 /* First try with cached data failed. Now try to get
333 current data from the system. */
335 if (__yp_bind (domain
, &ydb
) == 0)
337 status
= __ypclnt_call (domain
, prog
, xargs
, req
, xres
,
343 /* If we support binding dir data, we have a third chance:
345 if (status
!= YPERR_SUCCESS
)
347 ydb
= calloc (1, sizeof (dom_binding
));
348 if (ydb
!= NULL
&& yp_bind_ypbindprog (domain
, ydb
) == YPERR_SUCCESS
)
350 status
= __ypclnt_call (domain
, prog
, xargs
, req
, xres
,
359 __set_errno (saved_errno
);
364 /* Like do_ypcall, but translate the status value if necessary. */
366 do_ypcall_tr (const char *domain
, u_long prog
, xdrproc_t xargs
,
367 caddr_t req
, xdrproc_t xres
, caddr_t resp
)
369 int status
= do_ypcall (domain
, prog
, xargs
, req
, xres
, resp
);
370 if (status
== YPERR_SUCCESS
)
371 /* We cast to ypresp_val although the pointer could also be of
372 type ypresp_key_val or ypresp_master or ypresp_order or
373 ypresp_maplist. But the stat element is in a common prefix so
374 this does not matter. */
375 status
= ypprot_err (((struct ypresp_val
*) resp
)->stat
);
380 __libc_lock_define_initialized (static, domainname_lock
)
383 yp_get_default_domain (char **outdomain
)
385 int result
= YPERR_SUCCESS
;;
388 __libc_lock_lock (domainname_lock
);
390 if (ypdomainname
[0] == '\0')
392 if (getdomainname (ypdomainname
, NIS_MAXNAMELEN
))
393 result
= YPERR_NODOM
;
394 else if (strcmp (ypdomainname
, "(none)") == 0)
396 /* If domainname is not set, some systems will return "(none)" */
397 ypdomainname
[0] = '\0';
398 result
= YPERR_NODOM
;
401 *outdomain
= ypdomainname
;
404 *outdomain
= ypdomainname
;
406 __libc_lock_unlock (domainname_lock
);
410 libnsl_hidden_nolink_def (yp_get_default_domain
, GLIBC_2_0
)
413 __yp_check (char **domain
)
417 if (ypdomainname
[0] == '\0')
418 if (yp_get_default_domain (&unused
))
422 *domain
= ypdomainname
;
424 if (yp_bind (ypdomainname
) == 0)
428 libnsl_hidden_nolink_def(__yp_check
, GLIBC_2_0
)
431 yp_match (const char *indomain
, const char *inmap
, const char *inkey
,
432 const int inkeylen
, char **outval
, int *outvallen
)
436 enum clnt_stat result
;
438 if (indomain
== NULL
|| indomain
[0] == '\0' ||
439 inmap
== NULL
|| inmap
[0] == '\0' ||
440 inkey
== NULL
|| inkey
[0] == '\0' || inkeylen
<= 0)
441 return YPERR_BADARGS
;
443 req
.domain
= (char *) indomain
;
444 req
.map
= (char *) inmap
;
445 req
.key
.keydat_val
= (char *) inkey
;
446 req
.key
.keydat_len
= inkeylen
;
450 memset (&resp
, '\0', sizeof (resp
));
452 result
= do_ypcall_tr (indomain
, YPPROC_MATCH
, (xdrproc_t
) xdr_ypreq_key
,
453 (caddr_t
) &req
, (xdrproc_t
) xdr_ypresp_val
,
456 if (result
!= YPERR_SUCCESS
)
459 *outvallen
= resp
.val
.valdat_len
;
460 *outval
= malloc (*outvallen
+ 1);
461 int status
= YPERR_RESRC
;
462 if (__glibc_likely (*outval
!= NULL
))
464 memcpy (*outval
, resp
.val
.valdat_val
, *outvallen
);
465 (*outval
)[*outvallen
] = '\0';
466 status
= YPERR_SUCCESS
;
469 xdr_free ((xdrproc_t
) xdr_ypresp_val
, (char *) &resp
);
473 libnsl_hidden_nolink_def(yp_match
, GLIBC_2_0
)
476 yp_first (const char *indomain
, const char *inmap
, char **outkey
,
477 int *outkeylen
, char **outval
, int *outvallen
)
481 enum clnt_stat result
;
483 if (indomain
== NULL
|| indomain
[0] == '\0' ||
484 inmap
== NULL
|| inmap
[0] == '\0')
485 return YPERR_BADARGS
;
487 req
.domain
= (char *) indomain
;
488 req
.map
= (char *) inmap
;
490 *outkey
= *outval
= NULL
;
491 *outkeylen
= *outvallen
= 0;
492 memset (&resp
, '\0', sizeof (resp
));
494 result
= do_ypcall (indomain
, YPPROC_FIRST
, (xdrproc_t
) xdr_ypreq_nokey
,
495 (caddr_t
) &req
, (xdrproc_t
) xdr_ypresp_key_val
,
498 if (result
!= RPC_SUCCESS
)
500 if (resp
.stat
!= YP_TRUE
)
501 return ypprot_err (resp
.stat
);
504 if (__builtin_expect ((*outkey
= malloc (resp
.key
.keydat_len
+ 1)) != NULL
505 && (*outval
= malloc (resp
.val
.valdat_len
508 *outkeylen
= resp
.key
.keydat_len
;
509 memcpy (*outkey
, resp
.key
.keydat_val
, *outkeylen
);
510 (*outkey
)[*outkeylen
] = '\0';
512 *outvallen
= resp
.val
.valdat_len
;
513 memcpy (*outval
, resp
.val
.valdat_val
, *outvallen
);
514 (*outval
)[*outvallen
] = '\0';
516 status
= YPERR_SUCCESS
;
521 status
= YPERR_RESRC
;
524 xdr_free ((xdrproc_t
) xdr_ypresp_key_val
, (char *) &resp
);
528 libnsl_hidden_nolink_def(yp_first
, GLIBC_2_0
)
531 yp_next (const char *indomain
, const char *inmap
, const char *inkey
,
532 const int inkeylen
, char **outkey
, int *outkeylen
, char **outval
,
537 enum clnt_stat result
;
539 if (indomain
== NULL
|| indomain
[0] == '\0' ||
540 inmap
== NULL
|| inmap
[0] == '\0' ||
541 inkeylen
<= 0 || inkey
== NULL
|| inkey
[0] == '\0')
542 return YPERR_BADARGS
;
544 req
.domain
= (char *) indomain
;
545 req
.map
= (char *) inmap
;
546 req
.key
.keydat_val
= (char *) inkey
;
547 req
.key
.keydat_len
= inkeylen
;
549 *outkey
= *outval
= NULL
;
550 *outkeylen
= *outvallen
= 0;
551 memset (&resp
, '\0', sizeof (resp
));
553 result
= do_ypcall_tr (indomain
, YPPROC_NEXT
, (xdrproc_t
) xdr_ypreq_key
,
554 (caddr_t
) &req
, (xdrproc_t
) xdr_ypresp_key_val
,
557 if (result
!= YPERR_SUCCESS
)
561 if (__builtin_expect ((*outkey
= malloc (resp
.key
.keydat_len
+ 1)) != NULL
562 && (*outval
= malloc (resp
.val
.valdat_len
565 *outkeylen
= resp
.key
.keydat_len
;
566 memcpy (*outkey
, resp
.key
.keydat_val
, *outkeylen
);
567 (*outkey
)[*outkeylen
] = '\0';
569 *outvallen
= resp
.val
.valdat_len
;
570 memcpy (*outval
, resp
.val
.valdat_val
, *outvallen
);
571 (*outval
)[*outvallen
] = '\0';
573 status
= YPERR_SUCCESS
;
578 status
= YPERR_RESRC
;
581 xdr_free ((xdrproc_t
) xdr_ypresp_key_val
, (char *) &resp
);
585 libnsl_hidden_nolink_def(yp_next
, GLIBC_2_0
)
588 yp_master (const char *indomain
, const char *inmap
, char **outname
)
592 enum clnt_stat result
;
594 if (indomain
== NULL
|| indomain
[0] == '\0' ||
595 inmap
== NULL
|| inmap
[0] == '\0')
596 return YPERR_BADARGS
;
598 req
.domain
= (char *) indomain
;
599 req
.map
= (char *) inmap
;
601 memset (&resp
, '\0', sizeof (ypresp_master
));
603 result
= do_ypcall_tr (indomain
, YPPROC_MASTER
, (xdrproc_t
) xdr_ypreq_nokey
,
604 (caddr_t
) &req
, (xdrproc_t
) xdr_ypresp_master
,
607 if (result
!= YPERR_SUCCESS
)
610 *outname
= strdup (resp
.peer
);
611 xdr_free ((xdrproc_t
) xdr_ypresp_master
, (char *) &resp
);
613 return *outname
== NULL
? YPERR_YPERR
: YPERR_SUCCESS
;
615 libnsl_hidden_nolink_def (yp_master
, GLIBC_2_0
)
618 yp_order (const char *indomain
, const char *inmap
, unsigned int *outorder
)
620 struct ypreq_nokey req
;
621 struct ypresp_order resp
;
622 enum clnt_stat result
;
624 if (indomain
== NULL
|| indomain
[0] == '\0' ||
625 inmap
== NULL
|| inmap
[0] == '\0')
626 return YPERR_BADARGS
;
628 req
.domain
= (char *) indomain
;
629 req
.map
= (char *) inmap
;
631 memset (&resp
, '\0', sizeof (resp
));
633 result
= do_ypcall_tr (indomain
, YPPROC_ORDER
, (xdrproc_t
) xdr_ypreq_nokey
,
634 (caddr_t
) &req
, (xdrproc_t
) xdr_ypresp_order
,
637 if (result
!= YPERR_SUCCESS
)
640 *outorder
= resp
.ordernum
;
641 xdr_free ((xdrproc_t
) xdr_ypresp_order
, (char *) &resp
);
645 libnsl_hidden_nolink_def(yp_order
, GLIBC_2_0
)
647 struct ypresp_all_data
649 unsigned long status
;
651 int (*foreach
) (int status
, char *key
, int keylen
,
652 char *val
, int vallen
, char *data
);
656 __xdr_ypresp_all (XDR
*xdrs
, struct ypresp_all_data
*objp
)
660 struct ypresp_all resp
;
662 memset (&resp
, '\0', sizeof (struct ypresp_all
));
663 if (!xdr_ypresp_all (xdrs
, &resp
))
665 xdr_free ((xdrproc_t
) xdr_ypresp_all
, (char *) &resp
);
666 objp
->status
= YP_YPERR
;
671 xdr_free ((xdrproc_t
) xdr_ypresp_all
, (char *) &resp
);
672 objp
->status
= YP_NOMORE
;
676 switch (resp
.ypresp_all_u
.val
.stat
)
680 char key
[resp
.ypresp_all_u
.val
.key
.keydat_len
+ 1];
681 char val
[resp
.ypresp_all_u
.val
.val
.valdat_len
+ 1];
682 int keylen
= resp
.ypresp_all_u
.val
.key
.keydat_len
;
683 int vallen
= resp
.ypresp_all_u
.val
.val
.valdat_len
;
685 /* We are not allowed to modify the key and val data.
686 But we are allowed to add data behind the buffer,
687 if we don't modify the length. So add an extra NUL
688 character to avoid trouble with broken code. */
689 objp
->status
= YP_TRUE
;
690 *((char *) __mempcpy (key
, resp
.ypresp_all_u
.val
.key
.keydat_val
,
692 *((char *) __mempcpy (val
, resp
.ypresp_all_u
.val
.val
.valdat_val
,
694 xdr_free ((xdrproc_t
) xdr_ypresp_all
, (char *) &resp
);
695 if ((*objp
->foreach
) (objp
->status
, key
, keylen
,
696 val
, vallen
, objp
->data
))
701 objp
->status
= resp
.ypresp_all_u
.val
.stat
;
702 xdr_free ((xdrproc_t
) xdr_ypresp_all
, (char *) &resp
);
703 /* Sun says we don't need to make this call, but must return
704 immediately. Since Solaris makes this call, we will call
705 the callback function, too. */
706 (*objp
->foreach
) (objp
->status
, NULL
, 0, NULL
, 0, objp
->data
);
713 yp_all (const char *indomain
, const char *inmap
,
714 const struct ypall_callback
*incallback
)
716 struct ypreq_nokey req
;
717 dom_binding
*ydb
= NULL
;
719 enum clnt_stat result
;
720 struct sockaddr_in clnt_sin
;
722 struct ypresp_all_data data
;
724 int saved_errno
= errno
;
726 if (indomain
== NULL
|| indomain
[0] == '\0'
727 || inmap
== NULL
|| inmap
[0] == '\0')
728 return YPERR_BADARGS
;
733 while (try < MAXTRIES
&& res
!= YPERR_SUCCESS
)
735 if (__yp_bind (indomain
, &ydb
) != 0)
737 __set_errno (saved_errno
);
741 clnt_sock
= RPC_ANYSOCK
;
742 clnt_sin
= ydb
->dom_server_addr
;
743 clnt_sin
.sin_port
= 0;
745 /* We don't need the UDP connection anymore. */
749 clnt
= clnttcp_create (&clnt_sin
, YPPROG
, YPVERS
, &clnt_sock
, 0, 0);
752 __set_errno (saved_errno
);
755 req
.domain
= (char *) indomain
;
756 req
.map
= (char *) inmap
;
758 data
.foreach
= incallback
->foreach
;
759 data
.data
= (void *) incallback
->data
;
761 result
= clnt_call (clnt
, YPPROC_ALL
, (xdrproc_t
) xdr_ypreq_nokey
,
762 (caddr_t
) &req
, (xdrproc_t
) __xdr_ypresp_all
,
763 (caddr_t
) &data
, RPCTIMEOUT
);
765 if (__glibc_unlikely (result
!= RPC_SUCCESS
))
767 /* Print the error message only on the last try. */
768 if (try == MAXTRIES
- 1)
769 clnt_perror (clnt
, "yp_all: clnt_call");
777 if (res
== YPERR_SUCCESS
&& data
.status
!= YP_NOMORE
)
779 __set_errno (saved_errno
);
780 return ypprot_err (data
.status
);
785 __set_errno (saved_errno
);
789 libnsl_hidden_nolink_def (yp_all
, GLIBC_2_0
)
792 yp_maplist (const char *indomain
, struct ypmaplist
**outmaplist
)
794 struct ypresp_maplist resp
;
795 enum clnt_stat result
;
797 if (indomain
== NULL
|| indomain
[0] == '\0')
798 return YPERR_BADARGS
;
800 memset (&resp
, '\0', sizeof (resp
));
802 result
= do_ypcall_tr (indomain
, YPPROC_MAPLIST
, (xdrproc_t
) xdr_domainname
,
803 (caddr_t
) &indomain
, (xdrproc_t
) xdr_ypresp_maplist
,
806 if (__glibc_likely (result
== YPERR_SUCCESS
))
808 *outmaplist
= resp
.maps
;
809 /* We don't free the list, this will be done by ypserv
810 xdr_free((xdrproc_t)xdr_ypresp_maplist, (char *)&resp); */
817 yperr_string (const int error
)
826 str
= N_("Request arguments bad");
829 str
= N_("RPC failure on NIS operation");
832 str
= N_("Can't bind to server which serves this domain");
835 str
= N_("No such map in server's domain");
838 str
= N_("No such key in map");
841 str
= N_("Internal NIS error");
844 str
= N_("Local resource allocation failure");
847 str
= N_("No more records in map database");
850 str
= N_("Can't communicate with portmapper");
853 str
= N_("Can't communicate with ypbind");
856 str
= N_("Can't communicate with ypserv");
859 str
= N_("Local domain name not set");
862 str
= N_("NIS map database is bad");
865 str
= N_("NIS client/server version mismatch - can't supply service");
868 str
= N_("Permission denied");
871 str
= N_("Database is busy");
874 str
= N_("Unknown NIS error code");
879 libnsl_hidden_nolink_def(yperr_string
, GLIBC_2_0
)
881 static const int8_t yp_2_yperr
[] =
883 #define YP2YPERR(yp, yperr) [YP_##yp - YP_VERS] = YPERR_##yperr
884 YP2YPERR (TRUE
, SUCCESS
),
885 YP2YPERR (NOMORE
, NOMORE
),
886 YP2YPERR (FALSE
, YPERR
),
887 YP2YPERR (NOMAP
, MAP
),
888 YP2YPERR (NODOM
, DOMAIN
),
889 YP2YPERR (NOKEY
, KEY
),
890 YP2YPERR (BADOP
, YPERR
),
891 YP2YPERR (BADDB
, BADDB
),
892 YP2YPERR (YPERR
, YPERR
),
893 YP2YPERR (BADARGS
, BADARGS
),
894 YP2YPERR (VERS
, VERS
)
897 ypprot_err (const int code
)
899 if (code
< YP_VERS
|| code
> YP_NOMORE
)
901 return yp_2_yperr
[code
- YP_VERS
];
903 libnsl_hidden_nolink_def (ypprot_err
, GLIBC_2_0
)
906 ypbinderr_string (const int error
)
915 str
= N_("Internal ypbind error");
917 case YPBIND_ERR_NOSERV
:
918 str
= N_("Domain not bound");
920 case YPBIND_ERR_RESC
:
921 str
= N_("System resource allocation failure");
924 str
= N_("Unknown ypbind error");
929 libnsl_hidden_nolink_def (ypbinderr_string
, GLIBC_2_0
)
934 yp_update (char *domain
, char *map
, unsigned ypop
,
935 char *key
, int keylen
, char *data
, int datalen
)
939 ypupdate_args update_args
;
940 ypdelete_args delete_args
;
943 xdrproc_t xdr_argument
;
947 struct sockaddr saddr
;
948 char servername
[MAXNETNAMELEN
+ 1];
951 if (!domain
|| !map
|| !key
|| (ypop
!= YPOP_DELETE
&& !data
))
952 return YPERR_BADARGS
;
954 args
.update_args
.mapname
= map
;
955 args
.update_args
.key
.yp_buf_len
= keylen
;
956 args
.update_args
.key
.yp_buf_val
= key
;
957 args
.update_args
.datum
.yp_buf_len
= datalen
;
958 args
.update_args
.datum
.yp_buf_val
= data
;
960 if ((r
= yp_master (domain
, map
, &master
)) != YPERR_SUCCESS
)
963 if (!host2netname (servername
, master
, domain
))
965 fputs (_("yp_update: cannot convert host to netname\n"), stderr
);
970 clnt
= clnt_create (master
, YPU_PROG
, YPU_VERS
, "tcp");
972 /* We do not need the string anymore. */
977 clnt_pcreateerror ("yp_update: clnt_create");
981 if (!clnt_control (clnt
, CLGET_SERVER_ADDR
, (char *) &saddr
))
983 fputs (_("yp_update: cannot get server address\n"), stderr
);
992 xdr_argument
= (xdrproc_t
) xdr_ypupdate_args
;
995 xdr_argument
= (xdrproc_t
) xdr_ypdelete_args
;
998 return YPERR_BADARGS
;
1002 clnt
->cl_auth
= authdes_create (servername
, WINDOW
, &saddr
, NULL
);
1004 if (clnt
->cl_auth
== NULL
)
1005 clnt
->cl_auth
= authunix_create_default ();
1008 r
= clnt_call (clnt
, ypop
, xdr_argument
, (caddr_t
) &args
,
1009 (xdrproc_t
) xdr_u_int
, (caddr_t
) &res
, RPCTIMEOUT
);
1011 if (r
== RPC_AUTHERROR
)
1013 if (clnt
->cl_auth
->ah_cred
.oa_flavor
== AUTH_DES
)
1015 auth_destroy (clnt
->cl_auth
);
1016 clnt
->cl_auth
= authunix_create_default ();
1020 return YPERR_ACCESS
;
1022 if (r
!= RPC_SUCCESS
)
1024 clnt_perror (clnt
, "yp_update: clnt_call");
1029 libnsl_hidden_nolink_def(yp_update
, GLIBC_2_0
)