]> sourceware.org Git - glibc.git/blob - nis/ypclnt.c
Update.
[glibc.git] / nis / ypclnt.c
1 /* Copyright (C) 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3 Contributed by Thorsten Kukuk <kukuk@suse.de>, 1996.
4
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public License as
7 published by the Free Software Foundation; either version 2 of the
8 License, or (at your option) any later version.
9
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 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public
16 License along with the GNU C Library; see the file COPYING.LIB. If not,
17 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA. */
19
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/uio.h>
31 #include <bits/libc-lock.h>
32
33 /* This should only be defined on systems with a BSD compatible ypbind */
34 #ifndef BINDINGDIR
35 # define BINDINGDIR "/var/yp/binding"
36 #endif
37
38 struct dom_binding
39 {
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;
45 };
46 typedef struct dom_binding dom_binding;
47
48 static struct timeval RPCTIMEOUT = {25, 0};
49 static struct timeval UDPTIMEOUT = {5, 0};
50 static int const MAXTRIES = 2;
51 static char __ypdomainname[NIS_MAXNAMELEN + 1] = "\0";
52 __libc_lock_define_initialized (static, ypbindlist_lock)
53 static dom_binding *__ypbindlist = NULL;
54
55
56 static int
57 __yp_bind (const char *domain, dom_binding **ypdb)
58 {
59 struct sockaddr_in clnt_saddr;
60 struct ypbind_resp ypbr;
61 dom_binding *ysd = NULL;
62 int clnt_sock;
63 CLIENT *client;
64 int is_new = 0;
65
66 if (domain == NULL || domain[0] == '\0')
67 return YPERR_BADARGS;
68
69 if (ypdb != NULL)
70 {
71 ysd = *ypdb;
72 while (ysd != NULL)
73 {
74 if (strcmp (domain, ysd->dom_domain) == 0)
75 break;
76 ysd = ysd->dom_pnext;
77 }
78 }
79
80 if (ysd == NULL)
81 {
82 is_new = 1;
83 ysd = (dom_binding *) calloc (1, sizeof *ysd);
84 }
85
86 #if USE_BINDINGDIR
87 if (ysd->dom_client == NULL)
88 {
89 /* Try binding dir at first if we have no binding */
90 char path[sizeof (BINDINGDIR) + strlen (domain) + 10];
91 struct iovec vec[2];
92 unsigned short port;
93 int fd;
94
95 sprintf (path, "%s/%s.%d", BINDINGDIR, domain, YPBINDVERS);
96 fd = open (path, O_RDONLY);
97 if (fd >= 0)
98 {
99 /* We have a binding file and could save a RPC call */
100 vec[0].iov_base = &port;
101 vec[0].iov_len = sizeof (port);
102 vec[1].iov_base = &ypbr;
103 vec[1].iov_len = sizeof (ypbr);
104
105 if (readv (fd, vec, 2) == sizeof (port) + sizeof (ypbr))
106 {
107 ysd->dom_server_addr.sin_family = AF_INET;
108 memcpy (&ysd->dom_server_addr.sin_port,
109 ypbr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_port,
110 sizeof (ysd->dom_server_addr.sin_port));
111 memcpy (&ysd->dom_server_addr.sin_addr.s_addr,
112 ypbr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_addr,
113 sizeof (ysd->dom_server_addr.sin_addr.s_addr));
114 strncpy (ysd->dom_domain, domain, YPMAXDOMAIN);
115 ysd->dom_domain[YPMAXDOMAIN] = '\0';
116
117 ysd->dom_socket = RPC_ANYSOCK;
118 ysd->dom_client = clntudp_create (&ysd->dom_server_addr, YPPROG,
119 YPVERS, UDPTIMEOUT,
120 &ysd->dom_socket);
121
122 if (ysd->dom_client != NULL)
123 /* If the program exits, close the socket */
124 if (fcntl (ysd->dom_socket, F_SETFD, 1) == -1)
125 perror ("fcntl: F_SETFD");
126 }
127 close (fd);
128 }
129 }
130 #endif /* USE_BINDINGDIR */
131
132 if (ysd->dom_client == NULL)
133 {
134 memset (&clnt_saddr, '\0', sizeof clnt_saddr);
135 clnt_saddr.sin_family = AF_INET;
136 clnt_saddr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
137 clnt_sock = RPC_ANYSOCK;
138 client = clnttcp_create (&clnt_saddr, YPBINDPROG, YPBINDVERS,
139 &clnt_sock, 0, 0);
140 if (client == NULL)
141 {
142 if (is_new)
143 free (ysd);
144 return YPERR_YPBIND;
145 }
146 /* Check the port number -- should be < IPPORT_RESERVED.
147 If not, it's possible someone has registered a bogus
148 ypbind with the portmapper and is trying to trick us. */
149 if (ntohs (clnt_saddr.sin_port) >= IPPORT_RESERVED)
150 {
151 clnt_destroy (client);
152 if (is_new)
153 free (ysd);
154 return YPERR_YPBIND;
155 }
156
157 if (clnt_call (client, YPBINDPROC_DOMAIN,
158 (xdrproc_t) xdr_domainname, (caddr_t) &domain,
159 (xdrproc_t) xdr_ypbind_resp,
160 (caddr_t) &ypbr, RPCTIMEOUT) != RPC_SUCCESS)
161 {
162 clnt_destroy (client);
163 if (is_new)
164 free (ysd);
165 return YPERR_YPBIND;
166 }
167
168 clnt_destroy (client);
169
170 if (ypbr.ypbind_status != YPBIND_SUCC_VAL)
171 {
172 fprintf (stderr, _("YPBINDPROC_DOMAIN: %s\n"),
173 ypbinderr_string (ypbr.ypbind_resp_u.ypbind_error));
174 if (is_new)
175 free (ysd);
176 return YPERR_DOMAIN;
177 }
178 memset (&ysd->dom_server_addr, '\0', sizeof ysd->dom_server_addr);
179 ysd->dom_server_addr.sin_family = AF_INET;
180 memcpy (&ysd->dom_server_addr.sin_port,
181 ypbr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_port,
182 sizeof (ysd->dom_server_addr.sin_port));
183 memcpy (&ysd->dom_server_addr.sin_addr.s_addr,
184 ypbr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_addr,
185 sizeof (ysd->dom_server_addr.sin_addr.s_addr));
186 strncpy (ysd->dom_domain, domain, YPMAXDOMAIN);
187 ysd->dom_domain[YPMAXDOMAIN] = '\0';
188
189 ysd->dom_socket = RPC_ANYSOCK;
190 ysd->dom_client = clntudp_create (&ysd->dom_server_addr, YPPROG, YPVERS,
191 UDPTIMEOUT, &ysd->dom_socket);
192
193 if (ysd->dom_client != NULL)
194 /* If the program exits, close the socket */
195 if (fcntl (ysd->dom_socket, F_SETFD, 1) == -1)
196 perror ("fcntl: F_SETFD");
197 }
198
199 if (ysd->dom_client == NULL)
200 {
201 if (is_new)
202 free (ysd);
203 return YPERR_YPSERV;
204 }
205
206 if (is_new && ypdb != NULL)
207 {
208 ysd->dom_pnext = *ypdb;
209 *ypdb = ysd;
210 }
211
212 return YPERR_SUCCESS;
213 }
214
215 static void
216 __yp_unbind (dom_binding *ydb)
217 {
218 clnt_destroy (ydb->dom_client);
219 ydb->dom_client = NULL;
220 }
221
222 int
223 yp_bind (const char *indomain)
224 {
225 int status;
226
227 __libc_lock_lock (ypbindlist_lock);
228
229 status = __yp_bind (indomain, &__ypbindlist);
230
231 __libc_lock_unlock (ypbindlist_lock);
232
233 return status;
234 }
235
236 static void
237 yp_unbind_locked (const char *indomain)
238 {
239 dom_binding *ydbptr, *ydbptr2;
240
241 ydbptr2 = NULL;
242 ydbptr = __ypbindlist;
243
244 while (ydbptr != NULL)
245 {
246 if (strcmp (ydbptr->dom_domain, indomain) == 0)
247 {
248 dom_binding *work;
249
250 work = ydbptr;
251 if (ydbptr2 == NULL)
252 __ypbindlist = __ypbindlist->dom_pnext;
253 else
254 ydbptr2 = ydbptr->dom_pnext;
255 __yp_unbind (work);
256 free (work);
257 break;
258 }
259 ydbptr2 = ydbptr;
260 ydbptr = ydbptr->dom_pnext;
261 }
262 }
263
264 void
265 yp_unbind (const char *indomain)
266 {
267 __libc_lock_lock (ypbindlist_lock);
268
269 yp_unbind_locked (indomain);
270
271 __libc_lock_unlock (ypbindlist_lock);
272
273 return;
274 }
275
276 static int
277 do_ypcall (const char *domain, u_long prog, xdrproc_t xargs,
278 caddr_t req, xdrproc_t xres, caddr_t resp)
279 {
280 dom_binding *ydb = NULL;
281 bool_t use_ypbindlist = FALSE;
282 int try, status;
283 enum clnt_stat result;
284 int saved_errno = errno;
285
286 try = 0;
287 status = YPERR_YPERR;
288
289 __libc_lock_lock (ypbindlist_lock);
290 if (__ypbindlist != NULL)
291 {
292 ydb = __ypbindlist;
293 while (ydb != NULL)
294 {
295 if (strcmp (domain, ydb->dom_domain) == 0)
296 break;
297 ydb = ydb->dom_pnext;
298 }
299 if (ydb != NULL)
300 use_ypbindlist = TRUE;
301 else
302 __libc_lock_unlock (ypbindlist_lock);
303 }
304 else
305 __libc_lock_unlock (ypbindlist_lock);
306
307 while (try < MAXTRIES && status != YPERR_SUCCESS)
308 {
309 if (__yp_bind (domain, &ydb) != 0)
310 {
311 if (use_ypbindlist)
312 __libc_lock_unlock (ypbindlist_lock);
313 __set_errno (saved_errno);
314 return YPERR_DOMAIN;
315 }
316
317 result = clnt_call (ydb->dom_client, prog,
318 xargs, req, xres, resp, RPCTIMEOUT);
319
320 if (result != RPC_SUCCESS)
321 {
322 /* Don't print the error message on the first try. It
323 could be that we use cached data which is now invalid. */
324 if (try != 0)
325 clnt_perror (ydb->dom_client, "do_ypcall: clnt_call");
326
327 if (use_ypbindlist)
328 {
329 /* We use ypbindlist, and the old cached data is
330 invalid. unbind now and create a new binding */
331 yp_unbind_locked (domain);
332 __libc_lock_unlock (ypbindlist_lock);
333 use_ypbindlist = FALSE;
334 }
335 else
336 {
337 __yp_unbind (ydb);
338 free (ydb);
339 }
340
341 ydb = NULL;
342 status = YPERR_RPC;
343 }
344 else
345 status = YPERR_SUCCESS;
346
347 try++;
348 }
349 if (use_ypbindlist)
350 {
351 __libc_lock_unlock (ypbindlist_lock);
352 use_ypbindlist = FALSE;
353 }
354 else
355 if (ydb != NULL)
356 {
357 __yp_unbind (ydb);
358 free (ydb);
359 ydb = NULL;
360 }
361
362 __set_errno (saved_errno);
363
364 return status;
365 }
366
367
368 __libc_lock_define_initialized (static, domainname_lock)
369
370 int
371 yp_get_default_domain (char **outdomain)
372 {
373 int result = YPERR_SUCCESS;;
374 *outdomain = NULL;
375
376 __libc_lock_lock (domainname_lock);
377
378 if (__ypdomainname[0] == '\0')
379 {
380 if (getdomainname (__ypdomainname, NIS_MAXNAMELEN))
381 result = YPERR_NODOM;
382 else if (strcmp (__ypdomainname, "(none)") == 0)
383 {
384 /* If domainname is not set, some systems will return "(none)" */
385 __ypdomainname[0] = '\0';
386 result = YPERR_NODOM;
387 }
388 else
389 *outdomain = __ypdomainname;
390 }
391 else
392 *outdomain = __ypdomainname;
393
394 __libc_lock_unlock (domainname_lock);
395
396 return result;
397 }
398
399 int
400 __yp_check (char **domain)
401 {
402 char *unused;
403
404 if (__ypdomainname[0] == '\0')
405 if (yp_get_default_domain (&unused))
406 return 0;
407
408 if (domain)
409 *domain = __ypdomainname;
410
411 if (yp_bind (__ypdomainname) == 0)
412 return 1;
413 return 0;
414 }
415
416 int
417 yp_match (const char *indomain, const char *inmap, const char *inkey,
418 const int inkeylen, char **outval, int *outvallen)
419 {
420 ypreq_key req;
421 ypresp_val resp;
422 enum clnt_stat result;
423
424 if (indomain == NULL || indomain[0] == '\0' ||
425 inmap == NULL || inmap[0] == '\0' ||
426 inkey == NULL || inkey[0] == '\0' || inkeylen <= 0)
427 return YPERR_BADARGS;
428
429 req.domain = (char *) indomain;
430 req.map = (char *) inmap;
431 req.key.keydat_val = (char *) inkey;
432 req.key.keydat_len = inkeylen;
433
434 *outval = NULL;
435 *outvallen = 0;
436 memset (&resp, '\0', sizeof (resp));
437
438 result = do_ypcall (indomain, YPPROC_MATCH, (xdrproc_t) xdr_ypreq_key,
439 (caddr_t) & req, (xdrproc_t) xdr_ypresp_val,
440 (caddr_t) & resp);
441
442 if (result != YPERR_SUCCESS)
443 return result;
444 if (resp.stat != YP_TRUE)
445 return ypprot_err (resp.stat);
446
447 *outvallen = resp.val.valdat_len;
448 *outval = malloc (*outvallen + 1);
449 memcpy (*outval, resp.val.valdat_val, *outvallen);
450 (*outval)[*outvallen] = '\0';
451
452 xdr_free ((xdrproc_t) xdr_ypresp_val, (char *) &resp);
453
454 return YPERR_SUCCESS;
455 }
456
457 int
458 yp_first (const char *indomain, const char *inmap, char **outkey,
459 int *outkeylen, char **outval, int *outvallen)
460 {
461 ypreq_nokey req;
462 ypresp_key_val resp;
463 enum clnt_stat result;
464
465 if (indomain == NULL || indomain[0] == '\0' ||
466 inmap == NULL || inmap[0] == '\0')
467 return YPERR_BADARGS;
468
469 req.domain = (char *) indomain;
470 req.map = (char *) inmap;
471
472 *outkey = *outval = NULL;
473 *outkeylen = *outvallen = 0;
474 memset (&resp, '\0', sizeof (resp));
475
476 result = do_ypcall (indomain, YPPROC_FIRST, (xdrproc_t) xdr_ypreq_nokey,
477 (caddr_t) & req, (xdrproc_t) xdr_ypresp_key_val,
478 (caddr_t) & resp);
479
480 if (result != RPC_SUCCESS)
481 return YPERR_RPC;
482 if (resp.stat != YP_TRUE)
483 return ypprot_err (resp.stat);
484
485 *outkeylen = resp.key.keydat_len;
486 *outkey = malloc (*outkeylen + 1);
487 memcpy (*outkey, resp.key.keydat_val, *outkeylen);
488 (*outkey)[*outkeylen] = '\0';
489 *outvallen = resp.val.valdat_len;
490 *outval = malloc (*outvallen + 1);
491 memcpy (*outval, resp.val.valdat_val, *outvallen);
492 (*outval)[*outvallen] = '\0';
493
494 xdr_free ((xdrproc_t) xdr_ypresp_key_val, (char *) &resp);
495
496 return YPERR_SUCCESS;
497 }
498
499 int
500 yp_next (const char *indomain, const char *inmap, const char *inkey,
501 const int inkeylen, char **outkey, int *outkeylen, char **outval,
502 int *outvallen)
503 {
504 ypreq_key req;
505 ypresp_key_val resp;
506 enum clnt_stat result;
507
508 if (indomain == NULL || indomain[0] == '\0' ||
509 inmap == NULL || inmap[0] == '\0' ||
510 inkeylen <= 0 || inkey == NULL || inkey[0] == '\0')
511 return YPERR_BADARGS;
512
513 req.domain = (char *) indomain;
514 req.map = (char *) inmap;
515 req.key.keydat_val = (char *) inkey;
516 req.key.keydat_len = inkeylen;
517
518 *outkey = *outval = NULL;
519 *outkeylen = *outvallen = 0;
520 memset (&resp, '\0', sizeof (resp));
521
522 result = do_ypcall (indomain, YPPROC_NEXT, (xdrproc_t) xdr_ypreq_key,
523 (caddr_t) & req, (xdrproc_t) xdr_ypresp_key_val,
524 (caddr_t) & resp);
525
526 if (result != YPERR_SUCCESS)
527 return result;
528 if (resp.stat != YP_TRUE)
529 return ypprot_err (resp.stat);
530
531 *outkeylen = resp.key.keydat_len;
532 *outkey = malloc (*outkeylen + 1);
533 memcpy (*outkey, resp.key.keydat_val, *outkeylen);
534 (*outkey)[*outkeylen] = '\0';
535 *outvallen = resp.val.valdat_len;
536 *outval = malloc (*outvallen + 1);
537 memcpy (*outval, resp.val.valdat_val, *outvallen);
538 (*outval)[*outvallen] = '\0';
539
540 xdr_free ((xdrproc_t) xdr_ypresp_key_val, (char *) &resp);
541
542 return YPERR_SUCCESS;
543 }
544
545 int
546 yp_master (const char *indomain, const char *inmap, char **outname)
547 {
548 ypreq_nokey req;
549 ypresp_master resp;
550 enum clnt_stat result;
551
552 if (indomain == NULL || indomain[0] == '\0' ||
553 inmap == NULL || inmap[0] == '\0')
554 return YPERR_BADARGS;
555
556 req.domain = (char *) indomain;
557 req.map = (char *) inmap;
558
559 memset (&resp, '\0', sizeof (ypresp_master));
560
561 result = do_ypcall (indomain, YPPROC_MASTER, (xdrproc_t) xdr_ypreq_nokey,
562 (caddr_t) & req, (xdrproc_t) xdr_ypresp_master, (caddr_t) & resp);
563
564 if (result != YPERR_SUCCESS)
565 return result;
566 if (resp.stat != YP_TRUE)
567 return ypprot_err (resp.stat);
568
569 *outname = strdup (resp.peer);
570 xdr_free ((xdrproc_t) xdr_ypresp_master, (char *) &resp);
571
572 return *outname == NULL ? YPERR_YPERR : YPERR_SUCCESS;
573 }
574
575 int
576 yp_order (const char *indomain, const char *inmap, unsigned int *outorder)
577 {
578 struct ypreq_nokey req;
579 struct ypresp_order resp;
580 enum clnt_stat result;
581
582 if (indomain == NULL || indomain[0] == '\0' ||
583 inmap == NULL || inmap == '\0')
584 return YPERR_BADARGS;
585
586 req.domain = (char *) indomain;
587 req.map = (char *) inmap;
588
589 memset (&resp, '\0', sizeof (resp));
590
591 result = do_ypcall (indomain, YPPROC_ORDER, (xdrproc_t) xdr_ypreq_nokey,
592 (caddr_t) & req, (xdrproc_t) xdr_ypresp_order, (caddr_t) & resp);
593
594 if (result != YPERR_SUCCESS)
595 return result;
596 if (resp.stat != YP_TRUE)
597 return ypprot_err (resp.stat);
598
599 *outorder = resp.ordernum;
600 xdr_free ((xdrproc_t) xdr_ypresp_order, (char *) &resp);
601
602 return YPERR_SUCCESS;
603 }
604
605 static void *ypall_data;
606 static int (*ypall_foreach) (int status, char *key, int keylen,
607 char *val, int vallen, char *data);
608
609 static bool_t
610 __xdr_ypresp_all (XDR *xdrs, u_long *objp)
611 {
612 while (1)
613 {
614 struct ypresp_all resp;
615
616 memset (&resp, '\0', sizeof (struct ypresp_all));
617 if (!xdr_ypresp_all (xdrs, &resp))
618 {
619 xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp);
620 *objp = YP_YPERR;
621 return FALSE;
622 }
623 if (resp.more == 0)
624 {
625 xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp);
626 *objp = YP_NOMORE;
627 return TRUE;
628 }
629
630 switch (resp.ypresp_all_u.val.stat)
631 {
632 case YP_TRUE:
633 {
634 char key[resp.ypresp_all_u.val.key.keydat_len + 1];
635 char val[resp.ypresp_all_u.val.val.valdat_len + 1];
636 int keylen = resp.ypresp_all_u.val.key.keydat_len;
637 int vallen = resp.ypresp_all_u.val.val.valdat_len;
638
639 /* We are not allowed to modify the key and val data.
640 But we are allowed to add data behind the buffer,
641 if we don't modify the length. So add an extra NUL
642 character to avoid trouble with broken code. */
643 *objp = YP_TRUE;
644 memcpy (key, resp.ypresp_all_u.val.key.keydat_val, keylen);
645 key[keylen] = '\0';
646 memcpy (val, resp.ypresp_all_u.val.val.valdat_val, vallen);
647 val[vallen] = '\0';
648 xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp);
649 if ((*ypall_foreach) (*objp, key, keylen,
650 val, vallen, ypall_data))
651 return TRUE;
652 }
653 break;
654 default:
655 *objp = resp.ypresp_all_u.val.stat;
656 xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp);
657 /* Sun says we don't need to make this call, but must return
658 immediatly. Since Solaris makes this call, we will call
659 the callback function, too. */
660 (*ypall_foreach) (*objp, NULL, 0, NULL, 0, ypall_data);
661 return TRUE;
662 }
663 }
664 }
665
666 int
667 yp_all (const char *indomain, const char *inmap,
668 const struct ypall_callback *incallback)
669 {
670 struct ypreq_nokey req;
671 dom_binding *ydb = NULL;
672 int try, res;
673 enum clnt_stat result;
674 struct sockaddr_in clnt_sin;
675 CLIENT *clnt;
676 unsigned long status;
677 int clnt_sock;
678 int saved_errno = errno;
679
680 if (indomain == NULL || indomain[0] == '\0' ||
681 inmap == NULL || inmap == '\0')
682 return YPERR_BADARGS;
683
684 try = 0;
685 res = YPERR_YPERR;
686
687 while (try < MAXTRIES && res != YPERR_SUCCESS)
688 {
689 if (__yp_bind (indomain, &ydb) != 0)
690 {
691 __set_errno (saved_errno);
692 return YPERR_DOMAIN;
693 }
694
695 /* YPPROC_ALL get its own TCP channel to ypserv. Therefore we
696 close the socket opened by the __yp_bind call. */
697 close (ydb->dom_socket);
698 clnt_sock = RPC_ANYSOCK;
699 clnt_sin = ydb->dom_server_addr;
700 clnt_sin.sin_port = 0;
701 clnt = clnttcp_create (&clnt_sin, YPPROG, YPVERS, &clnt_sock, 0, 0);
702 if (clnt == NULL)
703 {
704 __yp_unbind (ydb);
705 __set_errno (saved_errno);
706 return YPERR_PMAP;
707 }
708 req.domain = (char *) indomain;
709 req.map = (char *) inmap;
710
711 ypall_foreach = incallback->foreach;
712 ypall_data = (void *) incallback->data;
713
714 result = clnt_call (clnt, YPPROC_ALL, (xdrproc_t) xdr_ypreq_nokey,
715 (caddr_t) &req, (xdrproc_t) __xdr_ypresp_all,
716 (caddr_t) &status, RPCTIMEOUT);
717
718 if (result != RPC_SUCCESS)
719 {
720 clnt_perror (clnt, "yp_all: clnt_call");
721 res = YPERR_RPC;
722 }
723 else
724 res = YPERR_SUCCESS;
725
726 __yp_unbind (ydb);
727 clnt_destroy (clnt);
728
729 if (status != YP_NOMORE)
730 {
731 __set_errno (saved_errno);
732 return ypprot_err (status);
733 }
734 ++try;
735 }
736
737 __set_errno (saved_errno);
738
739 return res;
740 }
741
742 int
743 yp_maplist (const char *indomain, struct ypmaplist **outmaplist)
744 {
745 struct ypresp_maplist resp;
746 enum clnt_stat result;
747
748 if (indomain == NULL || indomain[0] == '\0')
749 return YPERR_BADARGS;
750
751 memset (&resp, '\0', sizeof (resp));
752
753 result = do_ypcall (indomain, YPPROC_MAPLIST, (xdrproc_t) xdr_domainname,
754 (caddr_t) & indomain, (xdrproc_t) xdr_ypresp_maplist, (caddr_t) & resp);
755
756 if (result != YPERR_SUCCESS)
757 return result;
758 if (resp.stat != YP_TRUE)
759 return ypprot_err (resp.stat);
760
761 *outmaplist = resp.maps;
762 /* We give the list not free, this will be done by ypserv
763 xdr_free((xdrproc_t)xdr_ypresp_maplist, (char *)&resp); */
764
765 return YPERR_SUCCESS;
766 }
767
768 const char *
769 yperr_string (const int error)
770 {
771 switch (error)
772 {
773 case YPERR_SUCCESS:
774 return _("Success");
775 case YPERR_BADARGS:
776 return _("Request arguments bad");
777 case YPERR_RPC:
778 return _("RPC failure on NIS operation");
779 case YPERR_DOMAIN:
780 return _("Can't bind to server which serves this domain");
781 case YPERR_MAP:
782 return _("No such map in server's domain");
783 case YPERR_KEY:
784 return _("No such key in map");
785 case YPERR_YPERR:
786 return _("Internal NIS error");
787 case YPERR_RESRC:
788 return _("Local resource allocation failure");
789 case YPERR_NOMORE:
790 return _("No more records in map database");
791 case YPERR_PMAP:
792 return _("Can't communicate with portmapper");
793 case YPERR_YPBIND:
794 return _("Can't communicate with ypbind");
795 case YPERR_YPSERV:
796 return _("Can't communicate with ypserv");
797 case YPERR_NODOM:
798 return _("Local domain name not set");
799 case YPERR_BADDB:
800 return _("NIS map database is bad");
801 case YPERR_VERS:
802 return _("NIS client/server version mismatch - can't supply service");
803 case YPERR_ACCESS:
804 return _("Permission denied");
805 case YPERR_BUSY:
806 return _("Database is busy");
807 }
808 return _("Unknown NIS error code");
809 }
810
811 int
812 ypprot_err (const int code)
813 {
814 switch (code)
815 {
816 case YP_TRUE:
817 return YPERR_SUCCESS;
818 case YP_NOMORE:
819 return YPERR_NOMORE;
820 case YP_FALSE:
821 return YPERR_YPERR;
822 case YP_NOMAP:
823 return YPERR_MAP;
824 case YP_NODOM:
825 return YPERR_DOMAIN;
826 case YP_NOKEY:
827 return YPERR_KEY;
828 case YP_BADOP:
829 return YPERR_YPERR;
830 case YP_BADDB:
831 return YPERR_BADDB;
832 case YP_YPERR:
833 return YPERR_YPERR;
834 case YP_BADARGS:
835 return YPERR_BADARGS;
836 case YP_VERS:
837 return YPERR_VERS;
838 }
839 return YPERR_YPERR;
840 }
841
842 const char *
843 ypbinderr_string (const int error)
844 {
845 switch (error)
846 {
847 case 0:
848 return _("Success");
849 case YPBIND_ERR_ERR:
850 return _("Internal ypbind error");
851 case YPBIND_ERR_NOSERV:
852 return _("Domain not bound");
853 case YPBIND_ERR_RESC:
854 return _("System resource allocation failure");
855 default:
856 return _("Unknown ypbind error");
857 }
858 }
859
860
861 #define WINDOW 60
862
863 int
864 yp_update (char *domain, char *map, unsigned ypop,
865 char *key, int keylen, char *data, int datalen)
866 {
867 union
868 {
869 ypupdate_args update_args;
870 ypdelete_args delete_args;
871 }
872 args;
873 xdrproc_t xdr_argument;
874 unsigned res = 0;
875 CLIENT *clnt;
876 char *master;
877 struct sockaddr saddr;
878 char servername[MAXNETNAMELEN + 1];
879 int r;
880
881 if (!domain || !map || !key || (ypop != YPOP_DELETE && !data))
882 return YPERR_BADARGS;
883
884 args.update_args.mapname = map;
885 args.update_args.key.yp_buf_len = keylen;
886 args.update_args.key.yp_buf_val = key;
887 args.update_args.datum.yp_buf_len = datalen;
888 args.update_args.datum.yp_buf_val = data;
889
890 if ((r = yp_master (domain, map, &master)) != 0)
891 return r;
892
893 if (!host2netname (servername, master, domain))
894 {
895 fputs (_("yp_update: cannot convert host to netname\n"), stderr);
896 return YPERR_YPERR;
897 }
898
899 if ((clnt = clnt_create (master, YPU_PROG, YPU_VERS, "tcp")) == NULL)
900 {
901 clnt_pcreateerror ("yp_update: clnt_create");
902 return YPERR_RPC;
903 }
904
905 if (!clnt_control (clnt, CLGET_SERVER_ADDR, (char *) &saddr))
906 {
907 fputs (_("yp_update: cannot get server address\n"), stderr);
908 return YPERR_RPC;
909 }
910
911 switch (ypop)
912 {
913 case YPOP_CHANGE:
914 case YPOP_INSERT:
915 case YPOP_STORE:
916 xdr_argument = (xdrproc_t) xdr_ypupdate_args;
917 break;
918 case YPOP_DELETE:
919 xdr_argument = (xdrproc_t) xdr_ypdelete_args;
920 break;
921 default:
922 return YPERR_BADARGS;
923 break;
924 }
925
926 clnt->cl_auth = authdes_create (servername, WINDOW, &saddr, NULL);
927
928 if (clnt->cl_auth == NULL)
929 clnt->cl_auth = authunix_create_default ();
930
931 again:
932 r = clnt_call (clnt, ypop, xdr_argument, (caddr_t) &args,
933 (xdrproc_t) xdr_u_int, (caddr_t) &res, RPCTIMEOUT);
934
935 if (r == RPC_AUTHERROR)
936 {
937 if (clnt->cl_auth->ah_cred.oa_flavor == AUTH_DES)
938 {
939 clnt->cl_auth = authunix_create_default ();
940 goto again;
941 }
942 else
943 return YPERR_ACCESS;
944 }
945 if (r != RPC_SUCCESS)
946 {
947 clnt_perror (clnt, "yp_update: clnt_call");
948 return YPERR_RPC;
949 }
950 return res;
951 }
This page took 0.078653 seconds and 6 git commands to generate.