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