Hurd: Fix port deallocation on mknod error.
[glibc.git] / nis / ypclnt.c
blobba438f84ab3b52d78587c5ade6631cea77ae35bd
1 /* Copyright (C) 1996-2001, 2002, 2003, 2004, 2005, 2006, 2008
2 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4 Contributed by Thorsten Kukuk <kukuk@suse.de>, 1996.
6 The GNU C Library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
11 The GNU C Library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public
17 License along with the GNU C Library; if not, see
18 <http://www.gnu.org/licenses/>. */
20 #include <errno.h>
21 #include <fcntl.h>
22 #include <string.h>
23 #include <unistd.h>
24 #include <libintl.h>
25 #include <rpc/rpc.h>
26 #include <rpcsvc/nis.h>
27 #include <rpcsvc/yp.h>
28 #include <rpcsvc/ypclnt.h>
29 #include <rpcsvc/ypupd.h>
30 #include <sys/socket.h>
31 #include <sys/uio.h>
32 #include <bits/libc-lock.h>
34 /* This should only be defined on systems with a BSD compatible ypbind */
35 #ifndef BINDINGDIR
36 # define BINDINGDIR "/var/yp/binding"
37 #endif
39 struct dom_binding
41 struct dom_binding *dom_pnext;
42 char dom_domain[YPMAXDOMAIN + 1];
43 struct sockaddr_in dom_server_addr;
44 int dom_socket;
45 CLIENT *dom_client;
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;
57 static void
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 #ifdef SOCK_CLOEXEC
73 # define xflags SOCK_CLOEXEC
74 #else
75 # define xflags 0
76 #endif
77 ysd->dom_client = __libc_clntudp_bufcreate (&ysd->dom_server_addr, YPPROG,
78 YPVERS, UDPTIMEOUT,
79 &ysd->dom_socket,
80 UDPMSGSIZE, UDPMSGSIZE,
81 xflags);
83 if (ysd->dom_client != NULL)
85 #ifndef SOCK_CLOEXEC
86 /* If the program exits, close the socket */
87 if (fcntl (ysd->dom_socket, F_SETFD, FD_CLOEXEC) == -1)
88 perror ("fcntl: F_SETFD");
89 #endif
93 #if USE_BINDINGDIR
94 static void
95 yp_bind_file (const char *domain, dom_binding *ysd)
97 char path[sizeof (BINDINGDIR) + strlen (domain) + 3 * sizeof (unsigned) + 3];
99 snprintf (path, sizeof (path), "%s/%s.%u", BINDINGDIR, domain, YPBINDVERS);
100 int fd = open (path, O_RDONLY);
101 if (fd >= 0)
103 /* We have a binding file and could save a RPC call. The file
104 contains a port number and the YPBIND_RESP record. The port
105 number (16 bits) can be ignored. */
106 struct ypbind_resp ypbr;
108 if (pread (fd, &ypbr, sizeof (ypbr), 2) == sizeof (ypbr))
109 yp_bind_client_create (domain, ysd, &ypbr);
111 close (fd);
114 #endif
116 static int
117 yp_bind_ypbindprog (const char *domain, dom_binding *ysd)
119 struct sockaddr_in clnt_saddr;
120 struct ypbind_resp ypbr;
121 int clnt_sock;
122 CLIENT *client;
124 clnt_saddr.sin_family = AF_INET;
125 clnt_saddr.sin_port = 0;
126 clnt_saddr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
127 clnt_sock = RPC_ANYSOCK;
128 client = clnttcp_create (&clnt_saddr, YPBINDPROG, YPBINDVERS,
129 &clnt_sock, 0, 0);
130 if (client == NULL)
131 return YPERR_YPBIND;
133 /* Check the port number -- should be < IPPORT_RESERVED.
134 If not, it's possible someone has registered a bogus
135 ypbind with the portmapper and is trying to trick us. */
136 if (ntohs (clnt_saddr.sin_port) >= IPPORT_RESERVED)
138 clnt_destroy (client);
139 return YPERR_YPBIND;
142 if (clnt_call (client, YPBINDPROC_DOMAIN,
143 (xdrproc_t) xdr_domainname, (caddr_t) &domain,
144 (xdrproc_t) xdr_ypbind_resp,
145 (caddr_t) &ypbr, RPCTIMEOUT) != RPC_SUCCESS)
147 clnt_destroy (client);
148 return YPERR_YPBIND;
151 clnt_destroy (client);
153 if (ypbr.ypbind_status != YPBIND_SUCC_VAL)
155 fprintf (stderr, "YPBINDPROC_DOMAIN: %s\n",
156 ypbinderr_string (ypbr.ypbind_resp_u.ypbind_error));
157 return YPERR_DOMAIN;
159 memset (&ysd->dom_server_addr, '\0', sizeof ysd->dom_server_addr);
161 yp_bind_client_create (domain, ysd, &ypbr);
163 return YPERR_SUCCESS;
166 static int
167 __yp_bind (const char *domain, dom_binding **ypdb)
169 dom_binding *ysd = NULL;
170 int is_new = 0;
172 if (domain == NULL || domain[0] == '\0')
173 return YPERR_BADARGS;
175 ysd = *ypdb;
176 while (ysd != NULL)
178 if (strcmp (domain, ysd->dom_domain) == 0)
179 break;
180 ysd = ysd->dom_pnext;
183 if (ysd == NULL)
185 is_new = 1;
186 ysd = (dom_binding *) calloc (1, sizeof *ysd);
187 if (__builtin_expect (ysd == NULL, 0))
188 return YPERR_RESRC;
191 #if USE_BINDINGDIR
192 /* Try binding dir at first if we have no binding */
193 if (ysd->dom_client == NULL)
194 yp_bind_file (domain, ysd);
195 #endif /* USE_BINDINGDIR */
197 if (ysd->dom_client == NULL)
199 int retval = yp_bind_ypbindprog (domain, ysd);
200 if (retval != YPERR_SUCCESS)
202 if (is_new)
203 free (ysd);
204 return retval;
208 if (ysd->dom_client == NULL)
210 if (is_new)
211 free (ysd);
212 return YPERR_YPSERV;
215 if (is_new)
217 ysd->dom_pnext = *ypdb;
218 *ypdb = ysd;
221 return YPERR_SUCCESS;
224 static void
225 __yp_unbind (dom_binding *ydb)
227 clnt_destroy (ydb->dom_client);
228 free (ydb);
232 yp_bind (const char *indomain)
234 int status;
236 __libc_lock_lock (ypbindlist_lock);
238 status = __yp_bind (indomain, &ypbindlist);
240 __libc_lock_unlock (ypbindlist_lock);
242 return status;
244 libnsl_hidden_def (yp_bind)
246 static void
247 yp_unbind_locked (const char *indomain)
249 dom_binding *ydbptr, *ydbptr2;
251 ydbptr2 = NULL;
252 ydbptr = ypbindlist;
254 while (ydbptr != NULL)
256 if (strcmp (ydbptr->dom_domain, indomain) == 0)
258 dom_binding *work;
260 work = ydbptr;
261 if (ydbptr2 == NULL)
262 ypbindlist = ypbindlist->dom_pnext;
263 else
264 ydbptr2 = ydbptr->dom_pnext;
265 __yp_unbind (work);
266 break;
268 ydbptr2 = ydbptr;
269 ydbptr = ydbptr->dom_pnext;
273 void
274 yp_unbind (const char *indomain)
276 __libc_lock_lock (ypbindlist_lock);
278 yp_unbind_locked (indomain);
280 __libc_lock_unlock (ypbindlist_lock);
282 return;
285 static int
286 __ypclnt_call (const char *domain, u_long prog, xdrproc_t xargs,
287 caddr_t req, xdrproc_t xres, caddr_t resp, dom_binding **ydb,
288 int print_error)
290 enum clnt_stat result;
292 result = clnt_call ((*ydb)->dom_client, prog,
293 xargs, req, xres, resp, RPCTIMEOUT);
295 if (result != RPC_SUCCESS)
297 /* We don't print an error message, if we try our old,
298 cached data. Only print this for data, which should work. */
299 if (print_error)
300 clnt_perror ((*ydb)->dom_client, "do_ypcall: clnt_call");
302 return YPERR_RPC;
305 return YPERR_SUCCESS;
308 static int
309 do_ypcall (const char *domain, u_long prog, xdrproc_t xargs,
310 caddr_t req, xdrproc_t xres, caddr_t resp)
312 dom_binding *ydb;
313 int status;
314 int saved_errno = errno;
316 status = YPERR_YPERR;
318 __libc_lock_lock (ypbindlist_lock);
319 ydb = ypbindlist;
320 while (ydb != NULL)
322 if (strcmp (domain, ydb->dom_domain) == 0)
324 if (__yp_bind (domain, &ydb) == 0)
326 /* Call server, print no error message, do not unbind. */
327 status = __ypclnt_call (domain, prog, xargs, req, xres,
328 resp, &ydb, 0);
329 if (status == YPERR_SUCCESS)
331 __libc_lock_unlock (ypbindlist_lock);
332 __set_errno (saved_errno);
333 return status;
336 /* We use ypbindlist, and the old cached data is
337 invalid. unbind now and create a new binding */
338 yp_unbind_locked (domain);
340 break;
342 ydb = ydb->dom_pnext;
344 __libc_lock_unlock (ypbindlist_lock);
346 /* First try with cached data failed. Now try to get
347 current data from the system. */
348 ydb = NULL;
349 if (__yp_bind (domain, &ydb) == 0)
351 status = __ypclnt_call (domain, prog, xargs, req, xres,
352 resp, &ydb, 1);
353 __yp_unbind (ydb);
356 #if USE_BINDINGDIR
357 /* If we support binding dir data, we have a third chance:
358 Ask ypbind. */
359 if (status != YPERR_SUCCESS)
361 ydb = calloc (1, sizeof (dom_binding));
362 if (ydb != NULL && yp_bind_ypbindprog (domain, ydb) == YPERR_SUCCESS)
364 status = __ypclnt_call (domain, prog, xargs, req, xres,
365 resp, &ydb, 1);
366 __yp_unbind (ydb);
368 else
369 free (ydb);
371 #endif
373 __set_errno (saved_errno);
375 return status;
378 /* Like do_ypcall, but translate the status value if necessary. */
379 static int
380 do_ypcall_tr (const char *domain, u_long prog, xdrproc_t xargs,
381 caddr_t req, xdrproc_t xres, caddr_t resp)
383 int status = do_ypcall (domain, prog, xargs, req, xres, resp);
384 if (status == YPERR_SUCCESS)
385 /* We cast to ypresp_val although the pointer could also be of
386 type ypresp_key_val or ypresp_master or ypresp_order or
387 ypresp_maplist. But the stat element is in a common prefix so
388 this does not matter. */
389 status = ypprot_err (((struct ypresp_val *) resp)->stat);
390 return status;
394 __libc_lock_define_initialized (static, domainname_lock)
397 yp_get_default_domain (char **outdomain)
399 int result = YPERR_SUCCESS;;
400 *outdomain = NULL;
402 __libc_lock_lock (domainname_lock);
404 if (ypdomainname[0] == '\0')
406 if (getdomainname (ypdomainname, NIS_MAXNAMELEN))
407 result = YPERR_NODOM;
408 else if (strcmp (ypdomainname, "(none)") == 0)
410 /* If domainname is not set, some systems will return "(none)" */
411 ypdomainname[0] = '\0';
412 result = YPERR_NODOM;
414 else
415 *outdomain = ypdomainname;
417 else
418 *outdomain = ypdomainname;
420 __libc_lock_unlock (domainname_lock);
422 return result;
424 libnsl_hidden_def (yp_get_default_domain)
427 __yp_check (char **domain)
429 char *unused;
431 if (ypdomainname[0] == '\0')
432 if (yp_get_default_domain (&unused))
433 return 0;
435 if (domain)
436 *domain = ypdomainname;
438 if (yp_bind (ypdomainname) == 0)
439 return 1;
440 return 0;
444 yp_match (const char *indomain, const char *inmap, const char *inkey,
445 const int inkeylen, char **outval, int *outvallen)
447 ypreq_key req;
448 ypresp_val resp;
449 enum clnt_stat result;
451 if (indomain == NULL || indomain[0] == '\0' ||
452 inmap == NULL || inmap[0] == '\0' ||
453 inkey == NULL || inkey[0] == '\0' || inkeylen <= 0)
454 return YPERR_BADARGS;
456 req.domain = (char *) indomain;
457 req.map = (char *) inmap;
458 req.key.keydat_val = (char *) inkey;
459 req.key.keydat_len = inkeylen;
461 *outval = NULL;
462 *outvallen = 0;
463 memset (&resp, '\0', sizeof (resp));
465 result = do_ypcall_tr (indomain, YPPROC_MATCH, (xdrproc_t) xdr_ypreq_key,
466 (caddr_t) &req, (xdrproc_t) xdr_ypresp_val,
467 (caddr_t) &resp);
469 if (result != YPERR_SUCCESS)
470 return result;
472 *outvallen = resp.val.valdat_len;
473 *outval = malloc (*outvallen + 1);
474 int status = YPERR_RESRC;
475 if (__builtin_expect (*outval != NULL, 1))
477 memcpy (*outval, resp.val.valdat_val, *outvallen);
478 (*outval)[*outvallen] = '\0';
479 status = YPERR_SUCCESS;
482 xdr_free ((xdrproc_t) xdr_ypresp_val, (char *) &resp);
484 return status;
488 yp_first (const char *indomain, const char *inmap, char **outkey,
489 int *outkeylen, char **outval, int *outvallen)
491 ypreq_nokey req;
492 ypresp_key_val resp;
493 enum clnt_stat result;
495 if (indomain == NULL || indomain[0] == '\0' ||
496 inmap == NULL || inmap[0] == '\0')
497 return YPERR_BADARGS;
499 req.domain = (char *) indomain;
500 req.map = (char *) inmap;
502 *outkey = *outval = NULL;
503 *outkeylen = *outvallen = 0;
504 memset (&resp, '\0', sizeof (resp));
506 result = do_ypcall (indomain, YPPROC_FIRST, (xdrproc_t) xdr_ypreq_nokey,
507 (caddr_t) &req, (xdrproc_t) xdr_ypresp_key_val,
508 (caddr_t) &resp);
510 if (result != RPC_SUCCESS)
511 return YPERR_RPC;
512 if (resp.stat != YP_TRUE)
513 return ypprot_err (resp.stat);
515 int status;
516 if (__builtin_expect ((*outkey = malloc (resp.key.keydat_len + 1)) != NULL
517 && (*outval = malloc (resp.val.valdat_len
518 + 1)) != NULL, 1))
520 *outkeylen = resp.key.keydat_len;
521 memcpy (*outkey, resp.key.keydat_val, *outkeylen);
522 (*outkey)[*outkeylen] = '\0';
524 *outvallen = resp.val.valdat_len;
525 memcpy (*outval, resp.val.valdat_val, *outvallen);
526 (*outval)[*outvallen] = '\0';
528 status = YPERR_SUCCESS;
530 else
532 free (*outkey);
533 status = YPERR_RESRC;
536 xdr_free ((xdrproc_t) xdr_ypresp_key_val, (char *) &resp);
538 return status;
542 yp_next (const char *indomain, const char *inmap, const char *inkey,
543 const int inkeylen, char **outkey, int *outkeylen, char **outval,
544 int *outvallen)
546 ypreq_key req;
547 ypresp_key_val resp;
548 enum clnt_stat result;
550 if (indomain == NULL || indomain[0] == '\0' ||
551 inmap == NULL || inmap[0] == '\0' ||
552 inkeylen <= 0 || inkey == NULL || inkey[0] == '\0')
553 return YPERR_BADARGS;
555 req.domain = (char *) indomain;
556 req.map = (char *) inmap;
557 req.key.keydat_val = (char *) inkey;
558 req.key.keydat_len = inkeylen;
560 *outkey = *outval = NULL;
561 *outkeylen = *outvallen = 0;
562 memset (&resp, '\0', sizeof (resp));
564 result = do_ypcall_tr (indomain, YPPROC_NEXT, (xdrproc_t) xdr_ypreq_key,
565 (caddr_t) &req, (xdrproc_t) xdr_ypresp_key_val,
566 (caddr_t) &resp);
568 if (result != YPERR_SUCCESS)
569 return result;
571 int status;
572 if (__builtin_expect ((*outkey = malloc (resp.key.keydat_len + 1)) != NULL
573 && (*outval = malloc (resp.val.valdat_len
574 + 1)) != NULL, 1))
576 *outkeylen = resp.key.keydat_len;
577 memcpy (*outkey, resp.key.keydat_val, *outkeylen);
578 (*outkey)[*outkeylen] = '\0';
580 *outvallen = resp.val.valdat_len;
581 memcpy (*outval, resp.val.valdat_val, *outvallen);
582 (*outval)[*outvallen] = '\0';
584 status = YPERR_SUCCESS;
586 else
588 free (*outkey);
589 status = YPERR_RESRC;
592 xdr_free ((xdrproc_t) xdr_ypresp_key_val, (char *) &resp);
594 return status;
598 yp_master (const char *indomain, const char *inmap, char **outname)
600 ypreq_nokey req;
601 ypresp_master resp;
602 enum clnt_stat result;
604 if (indomain == NULL || indomain[0] == '\0' ||
605 inmap == NULL || inmap[0] == '\0')
606 return YPERR_BADARGS;
608 req.domain = (char *) indomain;
609 req.map = (char *) inmap;
611 memset (&resp, '\0', sizeof (ypresp_master));
613 result = do_ypcall_tr (indomain, YPPROC_MASTER, (xdrproc_t) xdr_ypreq_nokey,
614 (caddr_t) &req, (xdrproc_t) xdr_ypresp_master,
615 (caddr_t) &resp);
617 if (result != YPERR_SUCCESS)
618 return result;
620 *outname = strdup (resp.peer);
621 xdr_free ((xdrproc_t) xdr_ypresp_master, (char *) &resp);
623 return *outname == NULL ? YPERR_YPERR : YPERR_SUCCESS;
625 libnsl_hidden_def (yp_master)
628 yp_order (const char *indomain, const char *inmap, unsigned int *outorder)
630 struct ypreq_nokey req;
631 struct ypresp_order resp;
632 enum clnt_stat result;
634 if (indomain == NULL || indomain[0] == '\0' ||
635 inmap == NULL || inmap[0] == '\0')
636 return YPERR_BADARGS;
638 req.domain = (char *) indomain;
639 req.map = (char *) inmap;
641 memset (&resp, '\0', sizeof (resp));
643 result = do_ypcall_tr (indomain, YPPROC_ORDER, (xdrproc_t) xdr_ypreq_nokey,
644 (caddr_t) &req, (xdrproc_t) xdr_ypresp_order,
645 (caddr_t) &resp);
647 if (result != YPERR_SUCCESS)
648 return result;
650 *outorder = resp.ordernum;
651 xdr_free ((xdrproc_t) xdr_ypresp_order, (char *) &resp);
653 return result;
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 (__builtin_expect (result != RPC_SUCCESS, 0))
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;
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 (__builtin_expect (result == YPERR_SUCCESS, 1))
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;
825 const char *
826 yperr_string (const int error)
828 const char *str;
829 switch (error)
831 case YPERR_SUCCESS:
832 str = N_("Success");
833 break;
834 case YPERR_BADARGS:
835 str = N_("Request arguments bad");
836 break;
837 case YPERR_RPC:
838 str = N_("RPC failure on NIS operation");
839 break;
840 case YPERR_DOMAIN:
841 str = N_("Can't bind to server which serves this domain");
842 break;
843 case YPERR_MAP:
844 str = N_("No such map in server's domain");
845 break;
846 case YPERR_KEY:
847 str = N_("No such key in map");
848 break;
849 case YPERR_YPERR:
850 str = N_("Internal NIS error");
851 break;
852 case YPERR_RESRC:
853 str = N_("Local resource allocation failure");
854 break;
855 case YPERR_NOMORE:
856 str = N_("No more records in map database");
857 break;
858 case YPERR_PMAP:
859 str = N_("Can't communicate with portmapper");
860 break;
861 case YPERR_YPBIND:
862 str = N_("Can't communicate with ypbind");
863 break;
864 case YPERR_YPSERV:
865 str = N_("Can't communicate with ypserv");
866 break;
867 case YPERR_NODOM:
868 str = N_("Local domain name not set");
869 break;
870 case YPERR_BADDB:
871 str = N_("NIS map database is bad");
872 break;
873 case YPERR_VERS:
874 str = N_("NIS client/server version mismatch - can't supply service");
875 break;
876 case YPERR_ACCESS:
877 str = N_("Permission denied");
878 break;
879 case YPERR_BUSY:
880 str = N_("Database is busy");
881 break;
882 default:
883 str = N_("Unknown NIS error code");
884 break;
886 return _(str);
889 static const int8_t yp_2_yperr[] =
891 #define YP2YPERR(yp, yperr) [YP_##yp - YP_VERS] = YPERR_##yperr
892 YP2YPERR (TRUE, SUCCESS),
893 YP2YPERR (NOMORE, NOMORE),
894 YP2YPERR (FALSE, YPERR),
895 YP2YPERR (NOMAP, MAP),
896 YP2YPERR (NODOM, DOMAIN),
897 YP2YPERR (NOKEY, KEY),
898 YP2YPERR (BADOP, YPERR),
899 YP2YPERR (BADDB, BADDB),
900 YP2YPERR (YPERR, YPERR),
901 YP2YPERR (BADARGS, BADARGS),
902 YP2YPERR (VERS, VERS)
905 ypprot_err (const int code)
907 if (code < YP_VERS || code > YP_NOMORE)
908 return YPERR_YPERR;
909 return yp_2_yperr[code - YP_VERS];
911 libnsl_hidden_def (ypprot_err)
913 const char *
914 ypbinderr_string (const int error)
916 const char *str;
917 switch (error)
919 case 0:
920 str = N_("Success");
921 break;
922 case YPBIND_ERR_ERR:
923 str = N_("Internal ypbind error");
924 break;
925 case YPBIND_ERR_NOSERV:
926 str = N_("Domain not bound");
927 break;
928 case YPBIND_ERR_RESC:
929 str = N_("System resource allocation failure");
930 break;
931 default:
932 str = N_("Unknown ypbind error");
933 break;
935 return _(str);
937 libnsl_hidden_def (ypbinderr_string)
939 #define WINDOW 60
942 yp_update (char *domain, char *map, unsigned ypop,
943 char *key, int keylen, char *data, int datalen)
945 union
947 ypupdate_args update_args;
948 ypdelete_args delete_args;
950 args;
951 xdrproc_t xdr_argument;
952 unsigned res = 0;
953 CLIENT *clnt;
954 char *master;
955 struct sockaddr saddr;
956 char servername[MAXNETNAMELEN + 1];
957 int r;
959 if (!domain || !map || !key || (ypop != YPOP_DELETE && !data))
960 return YPERR_BADARGS;
962 args.update_args.mapname = map;
963 args.update_args.key.yp_buf_len = keylen;
964 args.update_args.key.yp_buf_val = key;
965 args.update_args.datum.yp_buf_len = datalen;
966 args.update_args.datum.yp_buf_val = data;
968 if ((r = yp_master (domain, map, &master)) != YPERR_SUCCESS)
969 return r;
971 if (!host2netname (servername, master, domain))
973 fputs (_("yp_update: cannot convert host to netname\n"), stderr);
974 free (master);
975 return YPERR_YPERR;
978 clnt = clnt_create (master, YPU_PROG, YPU_VERS, "tcp");
980 /* We do not need the string anymore. */
981 free (master);
983 if (clnt == NULL)
985 clnt_pcreateerror ("yp_update: clnt_create");
986 return YPERR_RPC;
989 if (!clnt_control (clnt, CLGET_SERVER_ADDR, (char *) &saddr))
991 fputs (_("yp_update: cannot get server address\n"), stderr);
992 return YPERR_RPC;
995 switch (ypop)
997 case YPOP_CHANGE:
998 case YPOP_INSERT:
999 case YPOP_STORE:
1000 xdr_argument = (xdrproc_t) xdr_ypupdate_args;
1001 break;
1002 case YPOP_DELETE:
1003 xdr_argument = (xdrproc_t) xdr_ypdelete_args;
1004 break;
1005 default:
1006 return YPERR_BADARGS;
1007 break;
1010 clnt->cl_auth = authdes_create (servername, WINDOW, &saddr, NULL);
1012 if (clnt->cl_auth == NULL)
1013 clnt->cl_auth = authunix_create_default ();
1015 again:
1016 r = clnt_call (clnt, ypop, xdr_argument, (caddr_t) &args,
1017 (xdrproc_t) xdr_u_int, (caddr_t) &res, RPCTIMEOUT);
1019 if (r == RPC_AUTHERROR)
1021 if (clnt->cl_auth->ah_cred.oa_flavor == AUTH_DES)
1023 auth_destroy (clnt->cl_auth);
1024 clnt->cl_auth = authunix_create_default ();
1025 goto again;
1027 else
1028 return YPERR_ACCESS;
1030 if (r != RPC_SUCCESS)
1032 clnt_perror (clnt, "yp_update: clnt_call");
1033 return YPERR_RPC;
1035 return res;