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