libio: Avoid dup already opened file descriptor [BZ#21393]
[glibc.git] / nis / ypclnt.c
blob3c4af2e0cffa274d9a0ba2de6d029e2bb02ddbd6
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/>. */
19 #include <errno.h>
20 #include <fcntl.h>
21 #include <string.h>
22 #include <unistd.h>
23 #include <libintl.h>
24 #include <rpc/rpc.h>
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>
30 #include <sys/uio.h>
31 #include <libc-lock.h>
33 /* This should only be defined on systems with a BSD compatible ypbind */
34 #ifndef BINDINGDIR
35 # define BINDINGDIR "/var/yp/binding"
36 #endif
38 struct dom_binding
40 struct dom_binding *dom_pnext;
41 char dom_domain[YPMAXDOMAIN + 1];
42 struct sockaddr_in dom_server_addr;
43 int dom_socket;
44 CLIENT *dom_client;
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;
56 static void
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,
72 YPVERS, UDPTIMEOUT,
73 &ysd->dom_socket,
74 UDPMSGSIZE, UDPMSGSIZE,
75 SOCK_CLOEXEC);
78 #if USE_BINDINGDIR
79 static void
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);
86 if (fd >= 0)
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);
96 close (fd);
99 #endif
101 static int
102 yp_bind_ypbindprog (const char *domain, dom_binding *ysd)
104 struct sockaddr_in clnt_saddr;
105 struct ypbind_resp ypbr;
106 int clnt_sock;
107 CLIENT *client;
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,
114 &clnt_sock, 0, 0);
115 if (client == NULL)
116 return YPERR_YPBIND;
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);
124 return YPERR_YPBIND;
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);
133 return YPERR_YPBIND;
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));
142 return YPERR_DOMAIN;
144 memset (&ysd->dom_server_addr, '\0', sizeof ysd->dom_server_addr);
146 yp_bind_client_create (domain, ysd, &ypbr);
148 return YPERR_SUCCESS;
151 static int
152 __yp_bind (const char *domain, dom_binding **ypdb)
154 dom_binding *ysd = NULL;
155 int is_new = 0;
157 if (domain == NULL || domain[0] == '\0')
158 return YPERR_BADARGS;
160 ysd = *ypdb;
161 while (ysd != NULL)
163 if (strcmp (domain, ysd->dom_domain) == 0)
164 break;
165 ysd = ysd->dom_pnext;
168 if (ysd == NULL)
170 is_new = 1;
171 ysd = (dom_binding *) calloc (1, sizeof *ysd);
172 if (__glibc_unlikely (ysd == NULL))
173 return YPERR_RESRC;
176 #if USE_BINDINGDIR
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)
187 if (is_new)
188 free (ysd);
189 return retval;
193 if (ysd->dom_client == NULL)
195 if (is_new)
196 free (ysd);
197 return YPERR_YPSERV;
200 if (is_new)
202 ysd->dom_pnext = *ypdb;
203 *ypdb = ysd;
206 return YPERR_SUCCESS;
209 static void
210 __yp_unbind (dom_binding *ydb)
212 clnt_destroy (ydb->dom_client);
213 free (ydb);
217 yp_bind (const char *indomain)
219 int status;
221 __libc_lock_lock (ypbindlist_lock);
223 status = __yp_bind (indomain, &ypbindlist);
225 __libc_lock_unlock (ypbindlist_lock);
227 return status;
229 libnsl_hidden_nolink_def (yp_bind, GLIBC_2_0)
231 static void
232 yp_unbind_locked (const char *indomain)
234 dom_binding *ydbptr, *ydbptr2;
236 ydbptr2 = NULL;
237 ydbptr = ypbindlist;
239 while (ydbptr != NULL)
241 if (strcmp (ydbptr->dom_domain, indomain) == 0)
243 dom_binding *work;
245 work = ydbptr;
246 if (ydbptr2 == NULL)
247 ypbindlist = ypbindlist->dom_pnext;
248 else
249 ydbptr2 = ydbptr->dom_pnext;
250 __yp_unbind (work);
251 break;
253 ydbptr2 = ydbptr;
254 ydbptr = ydbptr->dom_pnext;
258 void
259 yp_unbind (const char *indomain)
261 __libc_lock_lock (ypbindlist_lock);
263 yp_unbind_locked (indomain);
265 __libc_lock_unlock (ypbindlist_lock);
267 return;
269 libnsl_hidden_nolink_def(yp_unbind, GLIBC_2_0)
271 static int
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,
274 int print_error)
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. */
285 if (print_error)
286 clnt_perror ((*ydb)->dom_client, "do_ypcall: clnt_call");
288 return YPERR_RPC;
291 return YPERR_SUCCESS;
294 static int
295 do_ypcall (const char *domain, u_long prog, xdrproc_t xargs,
296 caddr_t req, xdrproc_t xres, caddr_t resp)
298 dom_binding *ydb;
299 int status;
300 int saved_errno = errno;
302 status = YPERR_YPERR;
304 __libc_lock_lock (ypbindlist_lock);
305 ydb = ypbindlist;
306 while (ydb != NULL)
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,
314 resp, &ydb, 0);
315 if (status == YPERR_SUCCESS)
317 __libc_lock_unlock (ypbindlist_lock);
318 __set_errno (saved_errno);
319 return status;
322 /* We use ypbindlist, and the old cached data is
323 invalid. unbind now and create a new binding */
324 yp_unbind_locked (domain);
326 break;
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. */
334 ydb = NULL;
335 if (__yp_bind (domain, &ydb) == 0)
337 status = __ypclnt_call (domain, prog, xargs, req, xres,
338 resp, &ydb, 1);
339 __yp_unbind (ydb);
342 #if USE_BINDINGDIR
343 /* If we support binding dir data, we have a third chance:
344 Ask ypbind. */
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,
351 resp, &ydb, 1);
352 __yp_unbind (ydb);
354 else
355 free (ydb);
357 #endif
359 __set_errno (saved_errno);
361 return status;
364 /* Like do_ypcall, but translate the status value if necessary. */
365 static int
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);
376 return status;
380 __libc_lock_define_initialized (static, domainname_lock)
383 yp_get_default_domain (char **outdomain)
385 int result = YPERR_SUCCESS;;
386 *outdomain = NULL;
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;
400 else
401 *outdomain = ypdomainname;
403 else
404 *outdomain = ypdomainname;
406 __libc_lock_unlock (domainname_lock);
408 return result;
410 libnsl_hidden_nolink_def (yp_get_default_domain, GLIBC_2_0)
413 __yp_check (char **domain)
415 char *unused;
417 if (ypdomainname[0] == '\0')
418 if (yp_get_default_domain (&unused))
419 return 0;
421 if (domain)
422 *domain = ypdomainname;
424 if (yp_bind (ypdomainname) == 0)
425 return 1;
426 return 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)
434 ypreq_key req;
435 ypresp_val resp;
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;
448 *outval = NULL;
449 *outvallen = 0;
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,
454 (caddr_t) &resp);
456 if (result != YPERR_SUCCESS)
457 return result;
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);
471 return status;
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)
479 ypreq_nokey req;
480 ypresp_key_val resp;
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,
496 (caddr_t) &resp);
498 if (result != RPC_SUCCESS)
499 return YPERR_RPC;
500 if (resp.stat != YP_TRUE)
501 return ypprot_err (resp.stat);
503 int status;
504 if (__builtin_expect ((*outkey = malloc (resp.key.keydat_len + 1)) != NULL
505 && (*outval = malloc (resp.val.valdat_len
506 + 1)) != NULL, 1))
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;
518 else
520 free (*outkey);
521 status = YPERR_RESRC;
524 xdr_free ((xdrproc_t) xdr_ypresp_key_val, (char *) &resp);
526 return status;
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,
533 int *outvallen)
535 ypreq_key req;
536 ypresp_key_val resp;
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,
555 (caddr_t) &resp);
557 if (result != YPERR_SUCCESS)
558 return result;
560 int status;
561 if (__builtin_expect ((*outkey = malloc (resp.key.keydat_len + 1)) != NULL
562 && (*outval = malloc (resp.val.valdat_len
563 + 1)) != NULL, 1))
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;
575 else
577 free (*outkey);
578 status = YPERR_RESRC;
581 xdr_free ((xdrproc_t) xdr_ypresp_key_val, (char *) &resp);
583 return status;
585 libnsl_hidden_nolink_def(yp_next, GLIBC_2_0)
588 yp_master (const char *indomain, const char *inmap, char **outname)
590 ypreq_nokey req;
591 ypresp_master resp;
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,
605 (caddr_t) &resp);
607 if (result != YPERR_SUCCESS)
608 return result;
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,
635 (caddr_t) &resp);
637 if (result != YPERR_SUCCESS)
638 return result;
640 *outorder = resp.ordernum;
641 xdr_free ((xdrproc_t) xdr_ypresp_order, (char *) &resp);
643 return result;
645 libnsl_hidden_nolink_def(yp_order, GLIBC_2_0)
647 struct ypresp_all_data
649 unsigned long status;
650 void *data;
651 int (*foreach) (int status, char *key, int keylen,
652 char *val, int vallen, char *data);
655 static bool_t
656 __xdr_ypresp_all (XDR *xdrs, struct ypresp_all_data *objp)
658 while (1)
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;
667 return FALSE;
669 if (resp.more == 0)
671 xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp);
672 objp->status = YP_NOMORE;
673 return TRUE;
676 switch (resp.ypresp_all_u.val.stat)
678 case YP_TRUE:
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,
691 keylen)) = '\0';
692 *((char *) __mempcpy (val, resp.ypresp_all_u.val.val.valdat_val,
693 vallen)) = '\0';
694 xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp);
695 if ((*objp->foreach) (objp->status, key, keylen,
696 val, vallen, objp->data))
697 return TRUE;
699 break;
700 default:
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);
707 return TRUE;
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;
718 int try, res;
719 enum clnt_stat result;
720 struct sockaddr_in clnt_sin;
721 CLIENT *clnt;
722 struct ypresp_all_data data;
723 int clnt_sock;
724 int saved_errno = errno;
726 if (indomain == NULL || indomain[0] == '\0'
727 || inmap == NULL || inmap[0] == '\0')
728 return YPERR_BADARGS;
730 try = 0;
731 res = YPERR_YPERR;
733 while (try < MAXTRIES && res != YPERR_SUCCESS)
735 if (__yp_bind (indomain, &ydb) != 0)
737 __set_errno (saved_errno);
738 return YPERR_DOMAIN;
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. */
746 __yp_unbind (ydb);
747 ydb = NULL;
749 clnt = clnttcp_create (&clnt_sin, YPPROG, YPVERS, &clnt_sock, 0, 0);
750 if (clnt == NULL)
752 __set_errno (saved_errno);
753 return YPERR_PMAP;
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");
770 res = YPERR_RPC;
772 else
773 res = YPERR_SUCCESS;
775 clnt_destroy (clnt);
777 if (res == YPERR_SUCCESS && data.status != YP_NOMORE)
779 __set_errno (saved_errno);
780 return ypprot_err (data.status);
782 ++try;
785 __set_errno (saved_errno);
787 return res;
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,
804 (caddr_t) &resp);
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); */
813 return result;
816 const char *
817 yperr_string (const int error)
819 const char *str;
820 switch (error)
822 case YPERR_SUCCESS:
823 str = N_("Success");
824 break;
825 case YPERR_BADARGS:
826 str = N_("Request arguments bad");
827 break;
828 case YPERR_RPC:
829 str = N_("RPC failure on NIS operation");
830 break;
831 case YPERR_DOMAIN:
832 str = N_("Can't bind to server which serves this domain");
833 break;
834 case YPERR_MAP:
835 str = N_("No such map in server's domain");
836 break;
837 case YPERR_KEY:
838 str = N_("No such key in map");
839 break;
840 case YPERR_YPERR:
841 str = N_("Internal NIS error");
842 break;
843 case YPERR_RESRC:
844 str = N_("Local resource allocation failure");
845 break;
846 case YPERR_NOMORE:
847 str = N_("No more records in map database");
848 break;
849 case YPERR_PMAP:
850 str = N_("Can't communicate with portmapper");
851 break;
852 case YPERR_YPBIND:
853 str = N_("Can't communicate with ypbind");
854 break;
855 case YPERR_YPSERV:
856 str = N_("Can't communicate with ypserv");
857 break;
858 case YPERR_NODOM:
859 str = N_("Local domain name not set");
860 break;
861 case YPERR_BADDB:
862 str = N_("NIS map database is bad");
863 break;
864 case YPERR_VERS:
865 str = N_("NIS client/server version mismatch - can't supply service");
866 break;
867 case YPERR_ACCESS:
868 str = N_("Permission denied");
869 break;
870 case YPERR_BUSY:
871 str = N_("Database is busy");
872 break;
873 default:
874 str = N_("Unknown NIS error code");
875 break;
877 return _(str);
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)
900 return YPERR_YPERR;
901 return yp_2_yperr[code - YP_VERS];
903 libnsl_hidden_nolink_def (ypprot_err, GLIBC_2_0)
905 const char *
906 ypbinderr_string (const int error)
908 const char *str;
909 switch (error)
911 case 0:
912 str = N_("Success");
913 break;
914 case YPBIND_ERR_ERR:
915 str = N_("Internal ypbind error");
916 break;
917 case YPBIND_ERR_NOSERV:
918 str = N_("Domain not bound");
919 break;
920 case YPBIND_ERR_RESC:
921 str = N_("System resource allocation failure");
922 break;
923 default:
924 str = N_("Unknown ypbind error");
925 break;
927 return _(str);
929 libnsl_hidden_nolink_def (ypbinderr_string, GLIBC_2_0)
931 #define WINDOW 60
934 yp_update (char *domain, char *map, unsigned ypop,
935 char *key, int keylen, char *data, int datalen)
937 union
939 ypupdate_args update_args;
940 ypdelete_args delete_args;
942 args;
943 xdrproc_t xdr_argument;
944 unsigned res = 0;
945 CLIENT *clnt;
946 char *master;
947 struct sockaddr saddr;
948 char servername[MAXNETNAMELEN + 1];
949 int r;
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)
961 return r;
963 if (!host2netname (servername, master, domain))
965 fputs (_("yp_update: cannot convert host to netname\n"), stderr);
966 free (master);
967 return YPERR_YPERR;
970 clnt = clnt_create (master, YPU_PROG, YPU_VERS, "tcp");
972 /* We do not need the string anymore. */
973 free (master);
975 if (clnt == NULL)
977 clnt_pcreateerror ("yp_update: clnt_create");
978 return YPERR_RPC;
981 if (!clnt_control (clnt, CLGET_SERVER_ADDR, (char *) &saddr))
983 fputs (_("yp_update: cannot get server address\n"), stderr);
984 return YPERR_RPC;
987 switch (ypop)
989 case YPOP_CHANGE:
990 case YPOP_INSERT:
991 case YPOP_STORE:
992 xdr_argument = (xdrproc_t) xdr_ypupdate_args;
993 break;
994 case YPOP_DELETE:
995 xdr_argument = (xdrproc_t) xdr_ypdelete_args;
996 break;
997 default:
998 return YPERR_BADARGS;
999 break;
1002 clnt->cl_auth = authdes_create (servername, WINDOW, &saddr, NULL);
1004 if (clnt->cl_auth == NULL)
1005 clnt->cl_auth = authunix_create_default ();
1007 again:
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 ();
1017 goto again;
1019 else
1020 return YPERR_ACCESS;
1022 if (r != RPC_SUCCESS)
1024 clnt_perror (clnt, "yp_update: clnt_call");
1025 return YPERR_RPC;
1027 return res;
1029 libnsl_hidden_nolink_def(yp_update, GLIBC_2_0)