malloc: Use different tag after mremap
[glibc.git] / nis / ypclnt.c
blobdb1a9c68564f5ee06d2094c89394645979bac973
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/>. */
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>
32 #include <shlib-compat.h>
33 #include <libc-diag.h>
35 /* This should only be defined on systems with a BSD compatible ypbind */
36 #ifndef BINDINGDIR
37 # define BINDINGDIR "/var/yp/binding"
38 #endif
40 struct dom_binding
42 struct dom_binding *dom_pnext;
43 char dom_domain[YPMAXDOMAIN + 1];
44 struct sockaddr_in dom_server_addr;
45 int dom_socket;
46 CLIENT *dom_client;
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;
58 static void
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,
74 YPVERS, UDPTIMEOUT,
75 &ysd->dom_socket,
76 UDPMSGSIZE, UDPMSGSIZE,
77 SOCK_CLOEXEC);
80 #if USE_BINDINGDIR
81 static void
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);
88 if (fd >= 0)
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);
98 close (fd);
101 #endif
103 static int
104 yp_bind_ypbindprog (const char *domain, dom_binding *ysd)
106 struct sockaddr_in clnt_saddr;
107 struct ypbind_resp ypbr;
108 int clnt_sock;
109 CLIENT *client;
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,
116 &clnt_sock, 0, 0);
117 if (client == NULL)
118 return YPERR_YPBIND;
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);
126 return YPERR_YPBIND;
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);
135 return YPERR_YPBIND;
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));
144 return YPERR_DOMAIN;
146 memset (&ysd->dom_server_addr, '\0', sizeof ysd->dom_server_addr);
148 yp_bind_client_create (domain, ysd, &ypbr);
150 return YPERR_SUCCESS;
153 static int
154 __yp_bind (const char *domain, dom_binding **ypdb)
156 dom_binding *ysd = NULL;
157 int is_new = 0;
159 if (domain == NULL || domain[0] == '\0')
160 return YPERR_BADARGS;
162 ysd = *ypdb;
163 while (ysd != NULL)
165 if (strcmp (domain, ysd->dom_domain) == 0)
166 break;
167 ysd = ysd->dom_pnext;
170 if (ysd == NULL)
172 is_new = 1;
173 ysd = (dom_binding *) calloc (1, sizeof *ysd);
174 if (__glibc_unlikely (ysd == NULL))
175 return YPERR_RESRC;
178 #if USE_BINDINGDIR
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)
189 if (is_new)
190 free (ysd);
191 return retval;
195 if (ysd->dom_client == NULL)
197 if (is_new)
198 free (ysd);
199 return YPERR_YPSERV;
202 if (is_new)
204 ysd->dom_pnext = *ypdb;
205 *ypdb = ysd;
208 return YPERR_SUCCESS;
211 static void
212 __yp_unbind (dom_binding *ydb)
214 clnt_destroy (ydb->dom_client);
215 free (ydb);
219 yp_bind (const char *indomain)
221 int status;
223 __libc_lock_lock (ypbindlist_lock);
225 status = __yp_bind (indomain, &ypbindlist);
227 __libc_lock_unlock (ypbindlist_lock);
229 return status;
231 libnsl_hidden_nolink_def (yp_bind, GLIBC_2_0)
233 static void
234 yp_unbind_locked (const char *indomain)
236 dom_binding *ydbptr, *ydbptr2;
238 ydbptr2 = NULL;
239 ydbptr = ypbindlist;
241 while (ydbptr != NULL)
243 if (strcmp (ydbptr->dom_domain, indomain) == 0)
245 dom_binding *work;
247 work = ydbptr;
248 if (ydbptr2 == NULL)
249 ypbindlist = ypbindlist->dom_pnext;
250 else
251 ydbptr2 = ydbptr->dom_pnext;
252 __yp_unbind (work);
253 break;
255 ydbptr2 = ydbptr;
256 ydbptr = ydbptr->dom_pnext;
260 void
261 yp_unbind (const char *indomain)
263 __libc_lock_lock (ypbindlist_lock);
265 yp_unbind_locked (indomain);
267 __libc_lock_unlock (ypbindlist_lock);
269 return;
271 libnsl_hidden_nolink_def(yp_unbind, GLIBC_2_0)
273 static int
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,
276 int print_error)
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. */
287 if (print_error)
288 clnt_perror ((*ydb)->dom_client, "do_ypcall: clnt_call");
290 return YPERR_RPC;
293 return YPERR_SUCCESS;
296 static int
297 do_ypcall (const char *domain, u_long prog, xdrproc_t xargs,
298 caddr_t req, xdrproc_t xres, caddr_t resp)
300 dom_binding *ydb;
301 int status;
302 int saved_errno = errno;
304 status = YPERR_YPERR;
306 __libc_lock_lock (ypbindlist_lock);
307 ydb = ypbindlist;
308 while (ydb != NULL)
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,
316 resp, &ydb, 0);
317 if (status == YPERR_SUCCESS)
319 __libc_lock_unlock (ypbindlist_lock);
320 __set_errno (saved_errno);
321 return status;
324 /* We use ypbindlist, and the old cached data is
325 invalid. unbind now and create a new binding */
326 yp_unbind_locked (domain);
328 break;
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. */
336 ydb = NULL;
337 if (__yp_bind (domain, &ydb) == 0)
339 status = __ypclnt_call (domain, prog, xargs, req, xres,
340 resp, &ydb, 1);
341 __yp_unbind (ydb);
344 #if USE_BINDINGDIR
345 /* If we support binding dir data, we have a third chance:
346 Ask ypbind. */
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,
353 resp, &ydb, 1);
354 __yp_unbind (ydb);
356 else
357 free (ydb);
359 #endif
361 __set_errno (saved_errno);
363 return status;
366 /* Like do_ypcall, but translate the status value if necessary. */
367 static int
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
376 accessed. */
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;
385 return status;
389 __libc_lock_define_initialized (static, domainname_lock)
392 yp_get_default_domain (char **outdomain)
394 int result = YPERR_SUCCESS;;
395 *outdomain = NULL;
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;
409 else
410 *outdomain = ypdomainname;
412 else
413 *outdomain = ypdomainname;
415 __libc_lock_unlock (domainname_lock);
417 return result;
419 libnsl_hidden_nolink_def (yp_get_default_domain, GLIBC_2_0)
422 __yp_check (char **domain)
424 char *unused;
426 if (ypdomainname[0] == '\0')
427 if (yp_get_default_domain (&unused))
428 return 0;
430 if (domain)
431 *domain = ypdomainname;
433 if (yp_bind (ypdomainname) == 0)
434 return 1;
435 return 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)
443 ypreq_key req;
444 ypresp_val resp;
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;
457 *outval = NULL;
458 *outvallen = 0;
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,
463 (caddr_t) &resp);
465 if (result != YPERR_SUCCESS)
466 return result;
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);
480 return status;
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)
488 ypreq_nokey req;
489 ypresp_key_val resp;
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,
505 (caddr_t) &resp);
507 if (result != RPC_SUCCESS)
508 return YPERR_RPC;
509 if (resp.stat != YP_TRUE)
510 return ypprot_err (resp.stat);
512 int status;
513 if (__builtin_expect ((*outkey = malloc (resp.key.keydat_len + 1)) != NULL
514 && (*outval = malloc (resp.val.valdat_len
515 + 1)) != NULL, 1))
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;
527 else
529 free (*outkey);
530 status = YPERR_RESRC;
533 xdr_free ((xdrproc_t) xdr_ypresp_key_val, (char *) &resp);
535 return status;
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,
542 int *outvallen)
544 ypreq_key req;
545 ypresp_key_val resp;
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,
564 (caddr_t) &resp);
566 if (result != YPERR_SUCCESS)
567 return result;
569 int status;
570 if (__builtin_expect ((*outkey = malloc (resp.key.keydat_len + 1)) != NULL
571 && (*outval = malloc (resp.val.valdat_len
572 + 1)) != NULL, 1))
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;
584 else
586 free (*outkey);
587 status = YPERR_RESRC;
590 xdr_free ((xdrproc_t) xdr_ypresp_key_val, (char *) &resp);
592 return status;
594 libnsl_hidden_nolink_def(yp_next, GLIBC_2_0)
597 yp_master (const char *indomain, const char *inmap, char **outname)
599 ypreq_nokey req;
600 ypresp_master resp;
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,
614 (caddr_t) &resp);
616 if (result != YPERR_SUCCESS)
617 return result;
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,
644 (caddr_t) &resp);
646 if (result != YPERR_SUCCESS)
647 return result;
649 *outorder = resp.ordernum;
650 xdr_free ((xdrproc_t) xdr_ypresp_order, (char *) &resp);
652 return result;
654 libnsl_hidden_nolink_def(yp_order, GLIBC_2_0)
656 struct ypresp_all_data
658 unsigned long status;
659 void *data;
660 int (*foreach) (int status, char *key, int keylen,
661 char *val, int vallen, char *data);
664 static bool_t
665 __xdr_ypresp_all (XDR *xdrs, struct ypresp_all_data *objp)
667 while (1)
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;
676 return FALSE;
678 if (resp.more == 0)
680 xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp);
681 objp->status = YP_NOMORE;
682 return TRUE;
685 switch (resp.ypresp_all_u.val.stat)
687 case YP_TRUE:
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,
700 keylen)) = '\0';
701 *((char *) __mempcpy (val, resp.ypresp_all_u.val.val.valdat_val,
702 vallen)) = '\0';
703 xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp);
704 if ((*objp->foreach) (objp->status, key, keylen,
705 val, vallen, objp->data))
706 return TRUE;
708 break;
709 default:
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);
716 return TRUE;
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;
727 int try, res;
728 enum clnt_stat result;
729 struct sockaddr_in clnt_sin;
730 CLIENT *clnt;
731 struct ypresp_all_data data;
732 int clnt_sock;
733 int saved_errno = errno;
735 if (indomain == NULL || indomain[0] == '\0'
736 || inmap == NULL || inmap[0] == '\0')
737 return YPERR_BADARGS;
739 try = 0;
740 res = YPERR_YPERR;
742 while (try < MAXTRIES && res != YPERR_SUCCESS)
744 if (__yp_bind (indomain, &ydb) != 0)
746 __set_errno (saved_errno);
747 return YPERR_DOMAIN;
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. */
755 __yp_unbind (ydb);
756 ydb = NULL;
758 clnt = clnttcp_create (&clnt_sin, YPPROG, YPVERS, &clnt_sock, 0, 0);
759 if (clnt == NULL)
761 __set_errno (saved_errno);
762 return YPERR_PMAP;
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");
779 res = YPERR_RPC;
781 else
782 res = YPERR_SUCCESS;
784 clnt_destroy (clnt);
786 if (res == YPERR_SUCCESS && data.status != YP_NOMORE)
788 __set_errno (saved_errno);
789 return ypprot_err (data.status);
791 ++try;
794 __set_errno (saved_errno);
796 return res;
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,
813 (caddr_t) &resp);
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); */
822 return result;
824 libnsl_hidden_nolink_def (yp_maplist, GLIBC_2_0)
826 const char *
827 yperr_string (const int error)
829 const char *str;
830 switch (error)
832 case YPERR_SUCCESS:
833 str = N_("Success");
834 break;
835 case YPERR_BADARGS:
836 str = N_("Request arguments bad");
837 break;
838 case YPERR_RPC:
839 str = N_("RPC failure on NIS operation");
840 break;
841 case YPERR_DOMAIN:
842 str = N_("Can't bind to server which serves this domain");
843 break;
844 case YPERR_MAP:
845 str = N_("No such map in server's domain");
846 break;
847 case YPERR_KEY:
848 str = N_("No such key in map");
849 break;
850 case YPERR_YPERR:
851 str = N_("Internal NIS error");
852 break;
853 case YPERR_RESRC:
854 str = N_("Local resource allocation failure");
855 break;
856 case YPERR_NOMORE:
857 str = N_("No more records in map database");
858 break;
859 case YPERR_PMAP:
860 str = N_("Can't communicate with portmapper");
861 break;
862 case YPERR_YPBIND:
863 str = N_("Can't communicate with ypbind");
864 break;
865 case YPERR_YPSERV:
866 str = N_("Can't communicate with ypserv");
867 break;
868 case YPERR_NODOM:
869 str = N_("Local domain name not set");
870 break;
871 case YPERR_BADDB:
872 str = N_("NIS map database is bad");
873 break;
874 case YPERR_VERS:
875 str = N_("NIS client/server version mismatch - can't supply service");
876 break;
877 case YPERR_ACCESS:
878 str = N_("Permission denied");
879 break;
880 case YPERR_BUSY:
881 str = N_("Database is busy");
882 break;
883 default:
884 str = N_("Unknown NIS error code");
885 break;
887 return _(str);
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)
910 return YPERR_YPERR;
911 return yp_2_yperr[code - YP_VERS];
913 libnsl_hidden_nolink_def (ypprot_err, GLIBC_2_0)
915 const char *
916 ypbinderr_string (const int error)
918 const char *str;
919 switch (error)
921 case 0:
922 str = N_("Success");
923 break;
924 case YPBIND_ERR_ERR:
925 str = N_("Internal ypbind error");
926 break;
927 case YPBIND_ERR_NOSERV:
928 str = N_("Domain not bound");
929 break;
930 case YPBIND_ERR_RESC:
931 str = N_("System resource allocation failure");
932 break;
933 default:
934 str = N_("Unknown ypbind error");
935 break;
937 return _(str);
939 libnsl_hidden_nolink_def (ypbinderr_string, GLIBC_2_0)
941 #define WINDOW 60
944 yp_update (char *domain, char *map, unsigned ypop,
945 char *key, int keylen, char *data, int datalen)
947 union
949 ypupdate_args update_args;
950 ypdelete_args delete_args;
952 args;
953 xdrproc_t xdr_argument;
954 unsigned res = 0;
955 CLIENT *clnt;
956 char *master;
957 struct sockaddr saddr;
958 char servername[MAXNETNAMELEN + 1];
959 int r;
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)
971 return r;
973 if (!host2netname (servername, master, domain))
975 fputs (_("yp_update: cannot convert host to netname\n"), stderr);
976 free (master);
977 return YPERR_YPERR;
980 clnt = clnt_create (master, YPU_PROG, YPU_VERS, "tcp");
982 /* We do not need the string anymore. */
983 free (master);
985 if (clnt == NULL)
987 clnt_pcreateerror ("yp_update: clnt_create");
988 return YPERR_RPC;
991 if (!clnt_control (clnt, CLGET_SERVER_ADDR, (char *) &saddr))
993 fputs (_("yp_update: cannot get server address\n"), stderr);
994 return YPERR_RPC;
997 switch (ypop)
999 case YPOP_CHANGE:
1000 case YPOP_INSERT:
1001 case YPOP_STORE:
1002 xdr_argument = (xdrproc_t) xdr_ypupdate_args;
1003 break;
1004 case YPOP_DELETE:
1005 xdr_argument = (xdrproc_t) xdr_ypdelete_args;
1006 break;
1007 default:
1008 return YPERR_BADARGS;
1009 break;
1012 clnt->cl_auth = authdes_create (servername, WINDOW, &saddr, NULL);
1014 if (clnt->cl_auth == NULL)
1015 clnt->cl_auth = authunix_create_default ();
1017 again:
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 ();
1027 goto again;
1029 else
1030 return YPERR_ACCESS;
1032 if (r != RPC_SUCCESS)
1034 clnt_perror (clnt, "yp_update: clnt_call");
1035 return YPERR_RPC;
1037 return res;
1039 libnsl_hidden_nolink_def(yp_update, GLIBC_2_0)