yplib.c revision 1.16 1 /* $NetBSD: yplib.c,v 1.16 1995/07/14 21:04:24 christos Exp $ */
2
3 /*
4 * Copyright (c) 1992, 1993 Theo de Raadt <deraadt (at) fsa.ca>
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by Theo de Raadt.
18 * 4. The name of the author may not be used to endorse or promote products
19 * derived from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
22 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
25 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34 #ifndef LINT
35 static char rcsid[] = "$NetBSD: yplib.c,v 1.16 1995/07/14 21:04:24 christos Exp $";
36 #endif
37
38 #include <sys/param.h>
39 #include <sys/types.h>
40 #include <sys/socket.h>
41 #include <sys/file.h>
42 #include <sys/uio.h>
43 #include <errno.h>
44 #include <stdio.h>
45 #include <stdlib.h>
46 #include <string.h>
47 #include <unistd.h>
48 #include <rpc/rpc.h>
49 #include <rpc/xdr.h>
50 #include <rpcsvc/yp_prot.h>
51 #include <rpcsvc/ypclnt.h>
52
53 #define BINDINGDIR "/var/yp/binding"
54 #define YPBINDLOCK "/var/run/ypbind.lock"
55 #define YPMATCHCACHE
56
57 int (*ypresp_allfn) __P((u_long, char *, int, char *, int, void *));
58 void *ypresp_data;
59
60 struct dom_binding *_ypbindlist;
61 static char _yp_domain[MAXHOSTNAMELEN];
62 int _yplib_timeout = 10;
63
64 static bool_t ypmatch_add __P((const char *, const char *, int, char *, int));
65 static bool_t ypmatch_find __P((const char *, const char *, int, const char **,
66 int *));
67 static void _yp_unbind __P((struct dom_binding *));
68
69 #ifdef YPMATCHCACHE
70 int _yplib_cache = 5;
71
72 static struct ypmatch_ent {
73 struct ypmatch_ent *next;
74 char *map, *key;
75 char *val;
76 int keylen, vallen;
77 time_t expire_t;
78 } *ypmc;
79
80 static bool_t
81 ypmatch_add(map, key, keylen, val, vallen)
82 const char *map;
83 const char *key;
84 int keylen;
85 char *val;
86 int vallen;
87 {
88 struct ypmatch_ent *ep;
89 time_t t;
90
91 (void)time(&t);
92
93 for (ep = ypmc; ep; ep = ep->next)
94 if (ep->expire_t < t)
95 break;
96 if (ep == NULL) {
97 if ((ep = malloc(sizeof *ep)) == NULL)
98 return 0;
99 (void)memset(ep, 0, sizeof *ep);
100 if (ypmc)
101 ep->next = ypmc;
102 ypmc = ep;
103 }
104
105 if (ep->key) {
106 free(ep->key);
107 ep->key = NULL;
108 }
109 if (ep->val) {
110 free(ep->val);
111 ep->val = NULL;
112 }
113
114 if ((ep->key = malloc(keylen)) == NULL)
115 return 0;
116
117 if ((ep->val = malloc(vallen)) == NULL) {
118 free(ep->key);
119 ep->key = NULL;
120 return 0;
121 }
122
123 ep->keylen = keylen;
124 ep->vallen = vallen;
125
126 (void)memcpy(ep->key, key, ep->keylen);
127 (void)memcpy(ep->val, val, ep->vallen);
128
129 if (ep->map) {
130 if (strcmp(ep->map, map)) {
131 free(ep->map);
132 if ((ep->map = strdup(map)) == NULL)
133 return 0;
134 }
135 } else {
136 if ((ep->map = strdup(map)) == NULL)
137 return 0;
138 }
139
140 ep->expire_t = t + _yplib_cache;
141 return 1;
142 }
143
144 static bool_t
145 ypmatch_find(map, key, keylen, val, vallen)
146 const char *map;
147 const char *key;
148 int keylen;
149 const char **val;
150 int *vallen;
151 {
152 struct ypmatch_ent *ep;
153 time_t t;
154
155 if (ypmc == NULL)
156 return 0;
157
158 (void) time(&t);
159
160 for (ep = ypmc; ep; ep = ep->next) {
161 if (ep->keylen != keylen)
162 continue;
163 if (strcmp(ep->map, map))
164 continue;
165 if (memcmp(ep->key, key, keylen))
166 continue;
167 if (t > ep->expire_t)
168 continue;
169
170 *val = ep->val;
171 *vallen = ep->vallen;
172 return 1;
173 }
174 return 0;
175 }
176 #endif
177
178 int
179 _yp_dobind(dom, ypdb)
180 const char *dom;
181 struct dom_binding **ypdb;
182 {
183 static int pid = -1;
184 char path[MAXPATHLEN];
185 struct dom_binding *ysd, *ysd2;
186 struct ypbind_resp ypbr;
187 struct timeval tv;
188 struct sockaddr_in clnt_sin;
189 int clnt_sock, fd, gpid;
190 CLIENT *client;
191 int new = 0, r;
192 int count = 0;
193
194 /*
195 * test if YP is running or not
196 */
197 if ((fd = open(YPBINDLOCK, O_RDONLY)) == -1)
198 return YPERR_YPBIND;
199 if (!(flock(fd, LOCK_EX | LOCK_NB) == -1 && errno == EWOULDBLOCK)) {
200 (void)close(fd);
201 return YPERR_YPBIND;
202 }
203 (void)close(fd);
204
205 gpid = getpid();
206 if (!(pid == -1 || pid == gpid)) {
207 ysd = _ypbindlist;
208 while (ysd) {
209 if (ysd->dom_client)
210 clnt_destroy(ysd->dom_client);
211 ysd2 = ysd->dom_pnext;
212 free(ysd);
213 ysd = ysd2;
214 }
215 _ypbindlist = NULL;
216 }
217 pid = gpid;
218
219 if (ypdb != NULL)
220 *ypdb = NULL;
221
222 if (dom == NULL || strlen(dom) == 0)
223 return YPERR_BADARGS;
224
225 for (ysd = _ypbindlist; ysd; ysd = ysd->dom_pnext)
226 if (strcmp(dom, ysd->dom_domain) == 0)
227 break;
228 if (ysd == NULL) {
229 if ((ysd = malloc(sizeof *ysd)) == NULL)
230 return YPERR_YPERR;
231 (void)memset(ysd, 0, sizeof *ysd);
232 ysd->dom_socket = -1;
233 ysd->dom_vers = 0;
234 new = 1;
235 }
236 again:
237 if (ysd->dom_vers == 0) {
238 (void) snprintf(path, sizeof(path), "%s/%s.%d",
239 BINDINGDIR, dom, 2);
240 if ((fd = open(path, O_RDONLY)) == -1) {
241 /*
242 * no binding file, YP is dead, or not yet fully
243 * alive.
244 */
245 goto trynet;
246 }
247 if (flock(fd, LOCK_EX | LOCK_NB) == -1 &&
248 errno == EWOULDBLOCK) {
249 struct iovec iov[2];
250 struct ypbind_resp ybr;
251 u_short ypb_port;
252 struct ypbind_binding *bn;
253
254 iov[0].iov_base = (caddr_t) & ypb_port;
255 iov[0].iov_len = sizeof ypb_port;
256 iov[1].iov_base = (caddr_t) & ybr;
257 iov[1].iov_len = sizeof ybr;
258
259 r = readv(fd, iov, 2);
260 if (r != iov[0].iov_len + iov[1].iov_len) {
261 (void)close(fd);
262 ysd->dom_vers = -1;
263 goto again;
264 }
265 (void)memset(&ysd->dom_server_addr, 0,
266 sizeof ysd->dom_server_addr);
267 ysd->dom_server_addr.sin_len =
268 sizeof(struct sockaddr_in);
269 ysd->dom_server_addr.sin_family = AF_INET;
270 bn = &ybr.ypbind_respbody.ypbind_bindinfo;
271 ysd->dom_server_addr.sin_port =
272 bn->ypbind_binding_port;
273
274 ysd->dom_server_addr.sin_addr =
275 bn->ypbind_binding_addr;
276
277 ysd->dom_server_port = ysd->dom_server_addr.sin_port;
278 (void)close(fd);
279 goto gotit;
280 } else {
281 /* no lock on binding file, YP is dead. */
282 (void)close(fd);
283 if (new)
284 free(ysd);
285 return YPERR_YPBIND;
286 }
287 }
288 trynet:
289 if (ysd->dom_vers == -1 || ysd->dom_vers == 0) {
290 struct ypbind_binding *bn;
291 (void)memset(&clnt_sin, 0, sizeof clnt_sin);
292 clnt_sin.sin_len = sizeof(struct sockaddr_in);
293 clnt_sin.sin_family = AF_INET;
294 clnt_sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
295
296 clnt_sock = RPC_ANYSOCK;
297 client = clnttcp_create(&clnt_sin, YPBINDPROG, YPBINDVERS,
298 &clnt_sock, 0, 0);
299 if (client == NULL) {
300 clnt_pcreateerror("clnttcp_create");
301 if (new)
302 free(ysd);
303 return YPERR_YPBIND;
304 }
305 tv.tv_sec = _yplib_timeout;
306 tv.tv_usec = 0;
307 r = clnt_call(client, YPBINDPROC_DOMAIN, xdr_domainname,
308 dom, xdr_ypbind_resp, &ypbr, tv);
309 if (r != RPC_SUCCESS) {
310 if (new == 0 || count)
311 fprintf(stderr,
312 "YP server for domain %s not responding, still trying\n",
313 dom);
314 count++;
315 clnt_destroy(client);
316 ysd->dom_vers = -1;
317 goto again;
318 }
319 clnt_destroy(client);
320
321 (void)memset(&ysd->dom_server_addr, 0,
322 sizeof ysd->dom_server_addr);
323 ysd->dom_server_addr.sin_len = sizeof(struct sockaddr_in);
324 ysd->dom_server_addr.sin_family = AF_INET;
325 bn = &ypbr.ypbind_respbody.ypbind_bindinfo;
326 ysd->dom_server_addr.sin_port =
327 bn->ypbind_binding_port;
328 ysd->dom_server_addr.sin_addr.s_addr =
329 bn->ypbind_binding_addr.s_addr;
330 ysd->dom_server_port =
331 bn->ypbind_binding_port;
332 gotit:
333 ysd->dom_vers = YPVERS;
334 (void)strcpy(ysd->dom_domain, dom);
335 }
336 tv.tv_sec = _yplib_timeout / 2;
337 tv.tv_usec = 0;
338 if (ysd->dom_client)
339 clnt_destroy(ysd->dom_client);
340 ysd->dom_socket = RPC_ANYSOCK;
341 ysd->dom_client = clntudp_create(&ysd->dom_server_addr,
342 YPPROG, YPVERS, tv, &ysd->dom_socket);
343 if (ysd->dom_client == NULL) {
344 clnt_pcreateerror("clntudp_create");
345 ysd->dom_vers = -1;
346 goto again;
347 }
348 if (fcntl(ysd->dom_socket, F_SETFD, 1) == -1)
349 perror("fcntl: F_SETFD");
350
351 if (new) {
352 ysd->dom_pnext = _ypbindlist;
353 _ypbindlist = ysd;
354 }
355 if (ypdb != NULL)
356 *ypdb = ysd;
357 return 0;
358 }
359
360 static void
361 _yp_unbind(ypb)
362 struct dom_binding *ypb;
363 {
364 clnt_destroy(ypb->dom_client);
365 ypb->dom_client = NULL;
366 ypb->dom_socket = -1;
367 }
368
369 int
370 yp_bind(dom)
371 const char *dom;
372 {
373 return _yp_dobind(dom, NULL);
374 }
375
376 void
377 yp_unbind(dom)
378 const char *dom;
379 {
380 struct dom_binding *ypb, *ypbp;
381
382 ypbp = NULL;
383 for (ypb = _ypbindlist; ypb; ypb = ypb->dom_pnext) {
384 if (strcmp(dom, ypb->dom_domain) == 0) {
385 clnt_destroy(ypb->dom_client);
386 if (ypbp)
387 ypbp->dom_pnext = ypb->dom_pnext;
388 else
389 _ypbindlist = ypb->dom_pnext;
390 free(ypb);
391 return;
392 }
393 ypbp = ypb;
394 }
395 return;
396 }
397
398 int
399 yp_match(indomain, inmap, inkey, inkeylen, outval, outvallen)
400 const char *indomain;
401 const char *inmap;
402 const char *inkey;
403 int inkeylen;
404 char **outval;
405 int *outvallen;
406 {
407 struct dom_binding *ysd;
408 struct ypresp_val yprv;
409 struct timeval tv;
410 struct ypreq_key yprk;
411 int r;
412
413 *outval = NULL;
414 *outvallen = 0;
415
416 again:
417 if (_yp_dobind(indomain, &ysd) != 0)
418 return YPERR_DOMAIN;
419
420 #ifdef YPMATCHCACHE
421 if (!strcmp(_yp_domain, indomain) && ypmatch_find(inmap, inkey,
422 inkeylen, &yprv.valdat.dptr, &yprv.valdat.dsize)) {
423 *outvallen = yprv.valdat.dsize;
424 if ((*outval = malloc(*outvallen + 1)) == NULL)
425 return YPERR_YPERR;
426 (void)memcpy(*outval, yprv.valdat.dptr, *outvallen);
427 (*outval)[*outvallen] = '\0';
428 return 0;
429 }
430 #endif
431
432 tv.tv_sec = _yplib_timeout;
433 tv.tv_usec = 0;
434
435 yprk.domain = indomain;
436 yprk.map = inmap;
437 yprk.keydat.dptr = (char *) inkey;
438 yprk.keydat.dsize = inkeylen;
439
440 memset(&yprv, 0, sizeof yprv);
441
442 r = clnt_call(ysd->dom_client, YPPROC_MATCH,
443 xdr_ypreq_key, &yprk, xdr_ypresp_val, &yprv, tv);
444 if (r != RPC_SUCCESS) {
445 clnt_perror(ysd->dom_client, "yp_match: clnt_call");
446 ysd->dom_vers = -1;
447 goto again;
448 }
449 if (!(r = ypprot_err(yprv.status))) {
450 *outvallen = yprv.valdat.dsize;
451 if ((*outval = malloc(*outvallen + 1)) == NULL)
452 return YPERR_YPERR;
453 (void)memcpy(*outval, yprv.valdat.dptr, *outvallen);
454 (*outval)[*outvallen] = '\0';
455 #ifdef YPMATCHCACHE
456 if (strcmp(_yp_domain, indomain) == 0)
457 if (!ypmatch_add(inmap, inkey, inkeylen,
458 *outval, *outvallen))
459 r = RPC_SYSTEMERROR;
460 #endif
461 }
462 xdr_free(xdr_ypresp_val, (char *) &yprv);
463 _yp_unbind(ysd);
464 return r;
465 }
466
467 int
468 yp_get_default_domain(domp)
469 char **domp;
470 {
471 *domp = NULL;
472 if (_yp_domain[0] == '\0')
473 if (getdomainname(_yp_domain, sizeof _yp_domain))
474 return YPERR_NODOM;
475 *domp = _yp_domain;
476 return 0;
477 }
478
479 int
480 yp_first(indomain, inmap, outkey, outkeylen, outval, outvallen)
481 const char *indomain;
482 const char *inmap;
483 char **outkey;
484 int *outkeylen;
485 char **outval;
486 int *outvallen;
487 {
488 struct ypresp_key_val yprkv;
489 struct ypreq_nokey yprnk;
490 struct dom_binding *ysd;
491 struct timeval tv;
492 int r;
493
494 *outkey = *outval = NULL;
495 *outkeylen = *outvallen = 0;
496
497 again:
498 if (_yp_dobind(indomain, &ysd) != 0)
499 return YPERR_DOMAIN;
500
501 tv.tv_sec = _yplib_timeout;
502 tv.tv_usec = 0;
503
504 yprnk.domain = indomain;
505 yprnk.map = inmap;
506 (void)memset(&yprkv, 0, sizeof yprkv);
507
508 r = clnt_call(ysd->dom_client, YPPROC_FIRST,
509 xdr_ypreq_nokey, &yprnk, xdr_ypresp_key_val, &yprkv, tv);
510 if (r != RPC_SUCCESS) {
511 clnt_perror(ysd->dom_client, "yp_first: clnt_call");
512 ysd->dom_vers = -1;
513 goto again;
514 }
515 if (!(r = ypprot_err(yprkv.status))) {
516 *outkeylen = yprkv.keydat.dsize;
517 if ((*outkey = malloc(*outkeylen + 1)) == NULL)
518 r = RPC_SYSTEMERROR;
519 else {
520 (void)memcpy(*outkey, yprkv.keydat.dptr, *outkeylen);
521 (*outkey)[*outkeylen] = '\0';
522 }
523 *outvallen = yprkv.valdat.dsize;
524 if ((*outval = malloc(*outvallen + 1)) == NULL)
525 r = RPC_SYSTEMERROR;
526 else {
527 (void)memcpy(*outval, yprkv.valdat.dptr, *outvallen);
528 (*outval)[*outvallen] = '\0';
529 }
530 }
531 xdr_free(xdr_ypresp_key_val, (char *) &yprkv);
532 _yp_unbind(ysd);
533 return r;
534 }
535
536 int
537 yp_next(indomain, inmap, inkey, inkeylen, outkey, outkeylen, outval, outvallen)
538 const char *indomain;
539 const char *inmap;
540 const char *inkey;
541 int inkeylen;
542 char **outkey;
543 int *outkeylen;
544 char **outval;
545 int *outvallen;
546 {
547 struct ypresp_key_val yprkv;
548 struct ypreq_key yprk;
549 struct dom_binding *ysd;
550 struct timeval tv;
551 int r;
552
553 *outkey = *outval = NULL;
554 *outkeylen = *outvallen = 0;
555
556 again:
557 if (_yp_dobind(indomain, &ysd) != 0)
558 return YPERR_DOMAIN;
559
560 tv.tv_sec = _yplib_timeout;
561 tv.tv_usec = 0;
562
563 yprk.domain = indomain;
564 yprk.map = inmap;
565 yprk.keydat.dptr = inkey;
566 yprk.keydat.dsize = inkeylen;
567 (void)memset(&yprkv, 0, sizeof yprkv);
568
569 r = clnt_call(ysd->dom_client, YPPROC_NEXT,
570 xdr_ypreq_key, &yprk, xdr_ypresp_key_val, &yprkv, tv);
571 if (r != RPC_SUCCESS) {
572 clnt_perror(ysd->dom_client, "yp_next: clnt_call");
573 ysd->dom_vers = -1;
574 goto again;
575 }
576 if (!(r = ypprot_err(yprkv.status))) {
577 *outkeylen = yprkv.keydat.dsize;
578 if ((*outkey = malloc(*outkeylen + 1)) == NULL)
579 r = RPC_SYSTEMERROR;
580 else {
581 (void)memcpy(*outkey, yprkv.keydat.dptr, *outkeylen);
582 (*outkey)[*outkeylen] = '\0';
583 }
584 *outvallen = yprkv.valdat.dsize;
585 if ((*outval = malloc(*outvallen + 1)) == NULL)
586 r = RPC_SYSTEMERROR;
587 else {
588 (void)memcpy(*outval, yprkv.valdat.dptr, *outvallen);
589 (*outval)[*outvallen] = '\0';
590 }
591 }
592 xdr_free(xdr_ypresp_key_val, (char *) &yprkv);
593 _yp_unbind(ysd);
594 return r;
595 }
596
597 int
598 yp_all(indomain, inmap, incallback)
599 const char *indomain;
600 const char *inmap;
601 struct ypall_callback *incallback;
602 {
603 struct ypreq_nokey yprnk;
604 struct dom_binding *ysd;
605 struct timeval tv;
606 struct sockaddr_in clnt_sin;
607 CLIENT *clnt;
608 u_long status;
609 int clnt_sock;
610
611 if (_yp_dobind(indomain, &ysd) != 0)
612 return YPERR_DOMAIN;
613
614 tv.tv_sec = _yplib_timeout;
615 tv.tv_usec = 0;
616 clnt_sock = RPC_ANYSOCK;
617 clnt_sin = ysd->dom_server_addr;
618 clnt_sin.sin_port = 0;
619 clnt = clnttcp_create(&clnt_sin, YPPROG, YPVERS, &clnt_sock, 0, 0);
620 if (clnt == NULL) {
621 printf("clnttcp_create failed\n");
622 return YPERR_PMAP;
623 }
624 yprnk.domain = indomain;
625 yprnk.map = inmap;
626 ypresp_allfn = incallback->foreach;
627 ypresp_data = (void *) incallback->data;
628
629 (void) clnt_call(clnt, YPPROC_ALL,
630 xdr_ypreq_nokey, &yprnk, xdr_ypresp_all_seq, &status, tv);
631 clnt_destroy(clnt);
632 /* not really needed... */
633 xdr_free(xdr_ypresp_all_seq, (char *) &status);
634 _yp_unbind(ysd);
635
636 if (status != YP_FALSE)
637 return ypprot_err(status);
638 return 0;
639 }
640
641 int
642 yp_order(indomain, inmap, outorder)
643 const char *indomain;
644 const char *inmap;
645 int *outorder;
646 {
647 struct dom_binding *ysd;
648 struct ypresp_order ypro;
649 struct ypreq_nokey yprnk;
650 struct timeval tv;
651 int r;
652
653 again:
654 if (_yp_dobind(indomain, &ysd) != 0)
655 return YPERR_DOMAIN;
656
657 tv.tv_sec = _yplib_timeout;
658 tv.tv_usec = 0;
659
660 yprnk.domain = indomain;
661 yprnk.map = inmap;
662
663 (void)memset(&ypro, 0, sizeof ypro);
664
665 r = clnt_call(ysd->dom_client, YPPROC_ORDER,
666 xdr_ypreq_nokey, &yprnk, xdr_ypresp_order, &ypro, tv);
667 if (r != RPC_SUCCESS) {
668 clnt_perror(ysd->dom_client, "yp_order: clnt_call");
669 ysd->dom_vers = -1;
670 goto again;
671 }
672 *outorder = ypro.ordernum;
673 xdr_free(xdr_ypresp_order, (char *) &ypro);
674 _yp_unbind(ysd);
675 return ypprot_err(ypro.status);
676 }
677
678 int
679 yp_master(indomain, inmap, outname)
680 const char *indomain;
681 const char *inmap;
682 char **outname;
683 {
684 struct dom_binding *ysd;
685 struct ypresp_master yprm;
686 struct ypreq_nokey yprnk;
687 struct timeval tv;
688 int r;
689
690 again:
691 if (_yp_dobind(indomain, &ysd) != 0)
692 return YPERR_DOMAIN;
693
694 tv.tv_sec = _yplib_timeout;
695 tv.tv_usec = 0;
696
697 yprnk.domain = indomain;
698 yprnk.map = inmap;
699
700 (void)memset(&yprm, 0, sizeof yprm);
701
702 r = clnt_call(ysd->dom_client, YPPROC_MASTER,
703 xdr_ypreq_nokey, &yprnk, xdr_ypresp_master, &yprm, tv);
704 if (r != RPC_SUCCESS) {
705 clnt_perror(ysd->dom_client, "yp_master: clnt_call");
706 ysd->dom_vers = -1;
707 goto again;
708 }
709 if (!(r = ypprot_err(yprm.status))) {
710 if ((*outname = strdup(yprm.master)) == NULL)
711 r = RPC_SYSTEMERROR;
712 }
713 xdr_free(xdr_ypresp_master, (char *) &yprm);
714 _yp_unbind(ysd);
715 return r;
716 }
717
718 int
719 yp_maplist(indomain, outmaplist)
720 const char *indomain;
721 struct ypmaplist **outmaplist;
722 {
723 struct dom_binding *ysd;
724 struct ypresp_maplist ypml;
725 struct timeval tv;
726 int r;
727
728 again:
729 if (_yp_dobind(indomain, &ysd) != 0)
730 return YPERR_DOMAIN;
731
732 tv.tv_sec = _yplib_timeout;
733 tv.tv_usec = 0;
734
735 memset(&ypml, 0, sizeof ypml);
736
737 r = clnt_call(ysd->dom_client, YPPROC_MAPLIST,
738 xdr_domainname, indomain, xdr_ypresp_maplist, &ypml, tv);
739 if (r != RPC_SUCCESS) {
740 clnt_perror(ysd->dom_client, "yp_maplist: clnt_call");
741 ysd->dom_vers = -1;
742 goto again;
743 }
744 *outmaplist = ypml.list;
745 /* NO: xdr_free(xdr_ypresp_maplist, &ypml); */
746 _yp_unbind(ysd);
747 return ypprot_err(ypml.status);
748 }
749
750 char *
751 yperr_string(incode)
752 int incode;
753 {
754 static char err[80];
755
756 switch (incode) {
757 case 0:
758 return "Success";
759 case YPERR_BADARGS:
760 return "Request arguments bad";
761 case YPERR_RPC:
762 return "RPC failure";
763 case YPERR_DOMAIN:
764 return "Can't bind to server which serves this domain";
765 case YPERR_MAP:
766 return "No such map in server's domain";
767 case YPERR_KEY:
768 return "No such key in map";
769 case YPERR_YPERR:
770 return "YP server error";
771 case YPERR_RESRC:
772 return "Local resource allocation failure";
773 case YPERR_NOMORE:
774 return "No more records in map database";
775 case YPERR_PMAP:
776 return "Can't communicate with portmapper";
777 case YPERR_YPBIND:
778 return "Can't communicate with ypbind";
779 case YPERR_YPSERV:
780 return "Can't communicate with ypserv";
781 case YPERR_NODOM:
782 return "Local domain name not set";
783 case YPERR_BADDB:
784 return "Server data base is bad";
785 case YPERR_VERS:
786 return "YP server version mismatch - server can't supply service.";
787 case YPERR_ACCESS:
788 return "Access violation";
789 case YPERR_BUSY:
790 return "Database is busy";
791 }
792 (void) snprintf(err, sizeof(err), "YP unknown error %d\n", incode);
793 return err;
794 }
795
796 int
797 ypprot_err(incode)
798 unsigned int incode;
799 {
800 switch (incode) {
801 case YP_TRUE:
802 return 0;
803 case YP_FALSE:
804 return YPERR_YPBIND;
805 case YP_NOMORE:
806 return YPERR_NOMORE;
807 case YP_NOMAP:
808 return YPERR_MAP;
809 case YP_NODOM:
810 return YPERR_NODOM;
811 case YP_NOKEY:
812 return YPERR_KEY;
813 case YP_BADOP:
814 return YPERR_YPERR;
815 case YP_BADDB:
816 return YPERR_BADDB;
817 case YP_YPERR:
818 return YPERR_YPERR;
819 case YP_BADARGS:
820 return YPERR_BADARGS;
821 case YP_VERS:
822 return YPERR_VERS;
823 }
824 return YPERR_YPERR;
825 }
826
827 int
828 _yp_check(dom)
829 char **dom;
830 {
831 char *unused;
832
833 if (_yp_domain[0] == '\0')
834 if (yp_get_default_domain(&unused))
835 return 0;
836
837 if (dom)
838 *dom = _yp_domain;
839
840 if (yp_bind(_yp_domain) == 0)
841 return 1;
842 return 0;
843 }
844