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.12 1995/09/02 04:16:21 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 YPBINDLOCK 50 #define YPBINDLOCK "/var/run/ypbind.lock" 51 #endif 52 53 #ifndef BINDINGDIR 54 #define BINDINGDIR "/var/yp/binding" 55 #endif 56 #define YPMATCHCACHE 57 #define MAX_RETRIES 20 58 59 extern bool_t xdr_domainname(), xdr_ypbind_resp(); 60 extern bool_t xdr_ypreq_key(), xdr_ypresp_val(); 61 extern bool_t xdr_ypreq_nokey(), xdr_ypresp_key_val(); 62 extern bool_t xdr_ypresp_all(), xdr_ypresp_all_seq(); 63 extern bool_t xdr_ypresp_master(); 64 65 int (*ypresp_allfn)(); 66 void *ypresp_data; 67 68 struct dom_binding *_ypbindlist; 69 static char _yp_domain[MAXHOSTNAMELEN]; 70 int _yplib_timeout = 10; 71 72 #ifdef YPMATCHCACHE 73 int _yplib_cache = 5; 74 75 static struct ypmatch_ent { 76 struct ypmatch_ent *next; 77 char *map, *key, *val; 78 int keylen, vallen; 79 time_t expire_t; 80 } *ypmc; 81 82 static void 83 ypmatch_add(map, key, keylen, val, vallen) 84 char *map; 85 char *key; 86 int keylen; 87 char *val; 88 int vallen; 89 { 90 struct ypmatch_ent *ep; 91 time_t t; 92 93 time(&t); 94 95 for(ep=ypmc; ep; ep=ep->next) 96 if(ep->expire_t < t) 97 break; 98 if(ep==NULL) { 99 ep = (struct ypmatch_ent *)malloc(sizeof *ep); 100 bzero((char *)ep, sizeof *ep); 101 if(ypmc) 102 ep->next = ypmc; 103 ypmc = ep; 104 } 105 106 if(ep->key) 107 free(ep->key); 108 if(ep->val) 109 free(ep->val); 110 111 ep->key = NULL; 112 ep->val = NULL; 113 114 ep->key = (char *)malloc(keylen); 115 if(ep->key==NULL) 116 return; 117 118 ep->val = (char *)malloc(vallen); 119 if(ep->key==NULL) { 120 free(ep->key); 121 ep->key = NULL; 122 return; 123 } 124 ep->keylen = keylen; 125 ep->vallen = vallen; 126 127 bcopy(key, ep->key, ep->keylen); 128 bcopy(val, ep->val, ep->vallen); 129 130 if(ep->map) { 131 if( strcmp(ep->map, map) ) { 132 free(ep->map); 133 ep->map = strdup(map); 134 } 135 } else { 136 ep->map = strdup(map); 137 } 138 139 ep->expire_t = t + _yplib_cache; 140 } 141 142 static bool_t 143 ypmatch_find(map, key, keylen, val, vallen) 144 char *map; 145 char *key; 146 int keylen; 147 char **val; 148 int *vallen; 149 { 150 struct ypmatch_ent *ep; 151 time_t t; 152 153 if(ypmc==NULL) 154 return 0; 155 156 time(&t); 157 158 for(ep=ypmc; ep; ep=ep->next) { 159 if(ep->keylen != keylen) 160 continue; 161 if(strcmp(ep->map, map)) 162 continue; 163 if(bcmp(ep->key, key, keylen)) 164 continue; 165 if(t > ep->expire_t) 166 continue; 167 168 *val = ep->val; 169 *vallen = ep->vallen; 170 return 1; 171 } 172 return 0; 173 } 174 #endif 175 176 char * 177 ypbinderr_string(incode) 178 int incode; 179 { 180 static char err[80]; 181 switch(incode) { 182 case 0: 183 return "Success"; 184 case YPBIND_ERR_ERR: 185 return "Internal ypbind error"; 186 case YPBIND_ERR_NOSERV: 187 return "Domain not bound"; 188 case YPBIND_ERR_RESC: 189 return "System resource allocation failure"; 190 } 191 sprintf(err, "Unknown ypbind error: #%d\n", incode); 192 return err; 193 } 194 195 int 196 _yp_dobind(dom, ypdb) 197 char *dom; 198 struct dom_binding **ypdb; 199 { 200 static int pid = -1; 201 char path[MAXPATHLEN]; 202 struct dom_binding *ysd, *ysd2; 203 struct ypbind_resp ypbr; 204 struct timeval tv; 205 struct sockaddr_in clnt_sin; 206 int clnt_sock, lfd, fd, gpid; 207 CLIENT *client; 208 int new = 0, r; 209 int retries = 0; 210 211 gpid = getpid(); 212 if( !(pid==-1 || pid==gpid) ) { 213 ysd = _ypbindlist; 214 while(ysd) { 215 if(ysd->dom_client) 216 clnt_destroy(ysd->dom_client); 217 ysd2 = ysd->dom_pnext; 218 free(ysd); 219 ysd = ysd2; 220 } 221 _ypbindlist = NULL; 222 } 223 pid = gpid; 224 225 if(ypdb!=NULL) 226 *ypdb = NULL; 227 228 if(dom==NULL || strlen(dom)==0) 229 return YPERR_BADARGS; 230 231 for(ysd = _ypbindlist; ysd; ysd = ysd->dom_pnext) 232 if( strcmp(dom, ysd->dom_domain) == 0) 233 break; 234 if(ysd==NULL) { 235 ysd = (struct dom_binding *)malloc(sizeof *ysd); 236 bzero((char *)ysd, sizeof *ysd); 237 ysd->dom_socket = -1; 238 ysd->dom_vers = 0; 239 new = 1; 240 } 241 242 if ((lfd = open(YPBINDLOCK, O_RDONLY)) == -1) 243 return(YPERR_YPBIND); 244 errno = 0; 245 switch (flock(lfd, LOCK_EX|LOCK_NB) == -1 && errno == EWOULDBLOCK) { 246 case 0: 247 close(lfd); 248 return (YPERR_YPBIND); 249 break; 250 case 1: 251 default: 252 close(lfd); 253 break; 254 } 255 256 again: 257 retries++; 258 if (retries > MAX_RETRIES) { 259 if (new) 260 free(ysd); 261 return(YPERR_YPBIND); 262 } 263 #ifdef BINDINGDIR 264 if(ysd->dom_vers==0) { 265 sprintf(path, "%s/%s.%d", BINDINGDIR, dom, 2); 266 if( (fd=open(path, O_RDONLY)) == -1) { 267 /* no binding file, YP is dead. */ 268 /* Try to bring it back to life. */ 269 close(fd); 270 goto skipit; 271 } 272 if( flock(fd, LOCK_EX|LOCK_NB) == -1 && errno==EWOULDBLOCK) { 273 struct iovec iov[2]; 274 struct ypbind_resp ybr; 275 u_short ypb_port; 276 277 iov[0].iov_base = (caddr_t)&ypb_port; 278 iov[0].iov_len = sizeof ypb_port; 279 iov[1].iov_base = (caddr_t)&ybr; 280 iov[1].iov_len = sizeof ybr; 281 282 r = readv(fd, iov, 2); 283 if(r != iov[0].iov_len + iov[1].iov_len) { 284 close(fd); 285 ysd->dom_vers = -1; 286 goto again; 287 } 288 289 bzero(&ysd->dom_server_addr, sizeof ysd->dom_server_addr); 290 ysd->dom_server_addr.sin_family = AF_INET; 291 ysd->dom_server_addr.sin_len = sizeof(struct sockaddr_in); 292 ysd->dom_server_addr.sin_addr = 293 ybr.ypbind_respbody.ypbind_bindinfo.ypbind_binding_addr; 294 ysd->dom_server_addr.sin_port = 295 ybr.ypbind_respbody.ypbind_bindinfo.ypbind_binding_port; 296 297 ysd->dom_server_port = ysd->dom_server_addr.sin_port; 298 close(fd); 299 goto gotit; 300 } else { 301 /* no lock on binding file, YP is dead. */ 302 /* Try to bring it back to life. */ 303 close(fd); 304 goto skipit; 305 } 306 } 307 skipit: 308 #endif 309 if(ysd->dom_vers==-1 || ysd->dom_vers==0) { 310 bzero((char *)&clnt_sin, sizeof clnt_sin); 311 clnt_sin.sin_family = AF_INET; 312 clnt_sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 313 314 clnt_sock = RPC_ANYSOCK; 315 client = clnttcp_create(&clnt_sin, YPBINDPROG, YPBINDVERS, &clnt_sock, 316 0, 0); 317 if(client==NULL) { 318 clnt_pcreateerror("clnttcp_create"); 319 if(new) 320 free(ysd); 321 return (YPERR_YPBIND); 322 } 323 324 tv.tv_sec = _yplib_timeout/2; 325 tv.tv_usec = 0; 326 r = clnt_call(client, YPBINDPROC_DOMAIN, 327 xdr_domainname, dom, xdr_ypbind_resp, &ypbr, tv); 328 if(r != RPC_SUCCESS) { 329 fprintf(stderr, 330 "YP: server for domain %s not responding, retrying\n", dom); 331 clnt_destroy(client); 332 ysd->dom_vers = -1; 333 goto again; 334 } else { 335 if (ypbr.ypbind_status != YPBIND_SUCC_VAL) { 336 clnt_destroy(client); 337 ysd->dom_vers = -1; 338 sleep(_yplib_timeout/2); 339 goto again; 340 } 341 } 342 clnt_destroy(client); 343 344 bzero((char *)&ysd->dom_server_addr, sizeof ysd->dom_server_addr); 345 ysd->dom_server_addr.sin_family = AF_INET; 346 ysd->dom_server_addr.sin_port = 347 ypbr.ypbind_respbody.ypbind_bindinfo.ypbind_binding_port; 348 ysd->dom_server_addr.sin_addr.s_addr = 349 ypbr.ypbind_respbody.ypbind_bindinfo.ypbind_binding_addr.s_addr; 350 ysd->dom_server_port = 351 ypbr.ypbind_respbody.ypbind_bindinfo.ypbind_binding_port; 352 gotit: 353 ysd->dom_vers = YPVERS; 354 strcpy(ysd->dom_domain, dom); 355 } 356 357 tv.tv_sec = _yplib_timeout/2; 358 tv.tv_usec = 0; 359 if(ysd->dom_client) 360 clnt_destroy(ysd->dom_client); 361 ysd->dom_socket = RPC_ANYSOCK; 362 ysd->dom_client = clntudp_create(&ysd->dom_server_addr, 363 YPPROG, YPVERS, tv, &ysd->dom_socket); 364 if(ysd->dom_client==NULL) { 365 clnt_pcreateerror("clntudp_create"); 366 ysd->dom_vers = -1; 367 goto again; 368 } 369 if( fcntl(ysd->dom_socket, F_SETFD, 1) == -1) 370 perror("fcntl: F_SETFD"); 371 372 if(new) { 373 ysd->dom_pnext = _ypbindlist; 374 _ypbindlist = ysd; 375 } 376 377 if(ypdb!=NULL) 378 *ypdb = ysd; 379 return 0; 380 } 381 382 static void 383 _yp_unbind(ypb) 384 struct dom_binding *ypb; 385 { 386 clnt_destroy(ypb->dom_client); 387 ypb->dom_client = NULL; 388 ypb->dom_socket = -1; 389 } 390 391 int 392 yp_bind(dom) 393 char *dom; 394 { 395 return _yp_dobind(dom, NULL); 396 } 397 398 void 399 yp_unbind(dom) 400 char *dom; 401 { 402 struct dom_binding *ypb, *ypbp; 403 404 ypbp = NULL; 405 for(ypb=_ypbindlist; ypb; ypb=ypb->dom_pnext) { 406 if( strcmp(dom, ypb->dom_domain) == 0) { 407 clnt_destroy(ypb->dom_client); 408 if(ypbp) 409 ypbp->dom_pnext = ypb->dom_pnext; 410 else 411 _ypbindlist = ypb->dom_pnext; 412 free(ypb); 413 return; 414 } 415 ypbp = ypb; 416 } 417 return; 418 } 419 420 int 421 yp_match(indomain, inmap, inkey, inkeylen, outval, outvallen) 422 char *indomain; 423 char *inmap; 424 const char *inkey; 425 int inkeylen; 426 char **outval; 427 int *outvallen; 428 { 429 struct dom_binding *ysd; 430 struct ypresp_val yprv; 431 struct timeval tv; 432 struct ypreq_key yprk; 433 int r; 434 435 *outval = NULL; 436 *outvallen = 0; 437 438 /* Sanity check */ 439 440 if (inkey == NULL || !strlen(inkey) || inkeylen <= 0 || 441 inmap == NULL || !strlen(inmap) || 442 indomain == NULL || !strlen(indomain)) 443 return YPERR_BADARGS; 444 445 #ifdef YPMATCHCACHE 446 if( !strcmp(_yp_domain, indomain) && ypmatch_find(inmap, inkey, 447 inkeylen, &yprv.valdat.dptr, &yprv.valdat.dsize)) { 448 *outvallen = yprv.valdat.dsize; 449 *outval = (char *)malloc(*outvallen+1); 450 bcopy(yprv.valdat.dptr, *outval, *outvallen); 451 (*outval)[*outvallen] = '\0'; 452 return 0; 453 } 454 #endif 455 456 again: 457 if( _yp_dobind(indomain, &ysd) != 0) 458 return YPERR_DOMAIN; 459 460 tv.tv_sec = _yplib_timeout; 461 tv.tv_usec = 0; 462 463 yprk.domain = indomain; 464 yprk.map = inmap; 465 yprk.keydat.dptr = (char *)inkey; 466 yprk.keydat.dsize = inkeylen; 467 468 bzero((char *)&yprv, sizeof yprv); 469 470 r = clnt_call(ysd->dom_client, YPPROC_MATCH, 471 xdr_ypreq_key, &yprk, xdr_ypresp_val, &yprv, tv); 472 if(r != RPC_SUCCESS) { 473 clnt_perror(ysd->dom_client, "yp_match: clnt_call"); 474 ysd->dom_vers = -1; 475 goto again; 476 } 477 if( !(r=ypprot_err(yprv.status)) ) { 478 *outvallen = yprv.valdat.dsize; 479 *outval = (char *)malloc(*outvallen+1); 480 bcopy(yprv.valdat.dptr, *outval, *outvallen); 481 (*outval)[*outvallen] = '\0'; 482 #ifdef YPMATCHCACHE 483 if( strcmp(_yp_domain, indomain)==0 ) 484 ypmatch_add(inmap, inkey, inkeylen, *outval, *outvallen); 485 #endif 486 } 487 xdr_free(xdr_ypresp_val, (char *)&yprv); 488 _yp_unbind(ysd); 489 return r; 490 } 491 492 int 493 yp_get_default_domain(domp) 494 char **domp; 495 { 496 *domp = NULL; 497 if(_yp_domain[0] == '\0') 498 if( getdomainname(_yp_domain, sizeof _yp_domain)) 499 return YPERR_NODOM; 500 *domp = _yp_domain; 501 return 0; 502 } 503 504 int 505 yp_first(indomain, inmap, outkey, outkeylen, outval, outvallen) 506 char *indomain; 507 char *inmap; 508 char **outkey; 509 int *outkeylen; 510 char **outval; 511 int *outvallen; 512 { 513 struct ypresp_key_val yprkv; 514 struct ypreq_nokey yprnk; 515 struct dom_binding *ysd; 516 struct timeval tv; 517 int r; 518 519 /* Sanity check */ 520 521 if (indomain == NULL || !strlen(indomain) || 522 inmap == NULL || !strlen(inmap)) 523 return YPERR_BADARGS; 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 yprnk.domain = indomain; 536 yprnk.map = inmap; 537 bzero((char *)&yprkv, sizeof yprkv); 538 539 r = clnt_call(ysd->dom_client, YPPROC_FIRST, 540 xdr_ypreq_nokey, &yprnk, xdr_ypresp_key_val, &yprkv, tv); 541 if(r != RPC_SUCCESS) { 542 clnt_perror(ysd->dom_client, "yp_first: clnt_call"); 543 ysd->dom_vers = 0; 544 goto again; 545 } 546 if( !(r=ypprot_err(yprkv.status)) ) { 547 *outkeylen = yprkv.keydat.dsize; 548 *outkey = (char *)malloc(*outkeylen+1); 549 bcopy(yprkv.keydat.dptr, *outkey, *outkeylen); 550 (*outkey)[*outkeylen] = '\0'; 551 *outvallen = yprkv.valdat.dsize; 552 *outval = (char *)malloc(*outvallen+1); 553 bcopy(yprkv.valdat.dptr, *outval, *outvallen); 554 (*outval)[*outvallen] = '\0'; 555 } 556 xdr_free(xdr_ypresp_key_val, (char *)&yprkv); 557 _yp_unbind(ysd); 558 return r; 559 } 560 561 int 562 yp_next(indomain, inmap, inkey, inkeylen, outkey, outkeylen, outval, outvallen) 563 char *indomain; 564 char *inmap; 565 char *inkey; 566 int inkeylen; 567 char **outkey; 568 int *outkeylen; 569 char **outval; 570 int *outvallen; 571 { 572 struct ypresp_key_val yprkv; 573 struct ypreq_key yprk; 574 struct dom_binding *ysd; 575 struct timeval tv; 576 int r; 577 578 /* Sanity check */ 579 580 if (inkey == NULL || !strlen(inkey) || inkeylen <= 0 || 581 inmap == NULL || !strlen(inmap) || 582 indomain == NULL || !strlen(indomain)) 583 return YPERR_BADARGS; 584 585 *outkey = *outval = NULL; 586 *outkeylen = *outvallen = 0; 587 588 again: 589 if( _yp_dobind(indomain, &ysd) != 0) 590 return YPERR_DOMAIN; 591 592 tv.tv_sec = _yplib_timeout; 593 tv.tv_usec = 0; 594 595 yprk.domain = indomain; 596 yprk.map = inmap; 597 yprk.keydat.dptr = inkey; 598 yprk.keydat.dsize = inkeylen; 599 bzero((char *)&yprkv, sizeof yprkv); 600 601 r = clnt_call(ysd->dom_client, YPPROC_NEXT, 602 xdr_ypreq_key, &yprk, xdr_ypresp_key_val, &yprkv, tv); 603 if(r != RPC_SUCCESS) { 604 clnt_perror(ysd->dom_client, "yp_next: clnt_call"); 605 ysd->dom_vers = -1; 606 goto again; 607 } 608 if( !(r=ypprot_err(yprkv.status)) ) { 609 *outkeylen = yprkv.keydat.dsize; 610 *outkey = (char *)malloc(*outkeylen+1); 611 bcopy(yprkv.keydat.dptr, *outkey, *outkeylen); 612 (*outkey)[*outkeylen] = '\0'; 613 *outvallen = yprkv.valdat.dsize; 614 *outval = (char *)malloc(*outvallen+1); 615 bcopy(yprkv.valdat.dptr, *outval, *outvallen); 616 (*outval)[*outvallen] = '\0'; 617 } 618 xdr_free(xdr_ypresp_key_val, (char *)&yprkv); 619 _yp_unbind(ysd); 620 return r; 621 } 622 623 int 624 yp_all(indomain, inmap, incallback) 625 char *indomain; 626 char *inmap; 627 struct ypall_callback *incallback; 628 { 629 struct ypreq_nokey yprnk; 630 struct dom_binding *ysd; 631 struct timeval tv; 632 struct sockaddr_in clnt_sin; 633 CLIENT *clnt; 634 u_long status; 635 int clnt_sock; 636 637 /* Sanity check */ 638 639 if (indomain == NULL || !strlen(indomain) || 640 inmap == NULL || !strlen(inmap)) 641 return YPERR_BADARGS; 642 643 if( _yp_dobind(indomain, &ysd) != 0) 644 return YPERR_DOMAIN; 645 646 tv.tv_sec = _yplib_timeout; 647 tv.tv_usec = 0; 648 clnt_sock = RPC_ANYSOCK; 649 clnt_sin = ysd->dom_server_addr; 650 clnt_sin.sin_port = 0; 651 clnt = clnttcp_create(&clnt_sin, YPPROG, YPVERS, &clnt_sock, 0, 0); 652 if(clnt==NULL) { 653 printf("clnttcp_create failed\n"); 654 return YPERR_PMAP; 655 } 656 657 yprnk.domain = indomain; 658 yprnk.map = inmap; 659 ypresp_allfn = incallback->foreach; 660 ypresp_data = (void *)incallback->data; 661 662 (void) clnt_call(clnt, YPPROC_ALL, 663 xdr_ypreq_nokey, &yprnk, xdr_ypresp_all_seq, &status, tv); 664 clnt_destroy(clnt); 665 xdr_free(xdr_ypresp_all_seq, (char *)&status); /* not really needed... */ 666 _yp_unbind(ysd); 667 668 if(status != YP_FALSE) 669 return ypprot_err(status); 670 return 0; 671 } 672 673 int 674 yp_order(indomain, inmap, outorder) 675 char *indomain; 676 char *inmap; 677 int *outorder; 678 { 679 struct dom_binding *ysd; 680 struct ypresp_order ypro; 681 struct ypreq_nokey yprnk; 682 struct timeval tv; 683 int r; 684 685 /* Sanity check */ 686 687 if (indomain == NULL || !strlen(indomain) || 688 inmap == NULL || !strlen(inmap)) 689 return YPERR_BADARGS; 690 691 again: 692 if( _yp_dobind(indomain, &ysd) != 0) 693 return YPERR_DOMAIN; 694 695 tv.tv_sec = _yplib_timeout; 696 tv.tv_usec = 0; 697 698 yprnk.domain = indomain; 699 yprnk.map = inmap; 700 701 bzero((char *)(char *)&ypro, sizeof ypro); 702 703 r = clnt_call(ysd->dom_client, YPPROC_ORDER, 704 xdr_ypreq_nokey, &yprnk, xdr_ypresp_order, &ypro, tv); 705 if(r != RPC_SUCCESS) { 706 clnt_perror(ysd->dom_client, "yp_order: clnt_call"); 707 ysd->dom_vers = -1; 708 goto again; 709 } 710 711 *outorder = ypro.ordernum; 712 xdr_free(xdr_ypresp_order, (char *)&ypro); 713 _yp_unbind(ysd); 714 return ypprot_err(ypro.status); 715 } 716 717 int 718 yp_master(indomain, inmap, outname) 719 char *indomain; 720 char *inmap; 721 char **outname; 722 { 723 struct dom_binding *ysd; 724 struct ypresp_master yprm; 725 struct ypreq_nokey yprnk; 726 struct timeval tv; 727 int r; 728 729 /* Sanity check */ 730 731 if (indomain == NULL || !strlen(indomain) || 732 inmap == NULL || !strlen(inmap)) 733 return YPERR_BADARGS; 734 again: 735 if( _yp_dobind(indomain, &ysd) != 0) 736 return YPERR_DOMAIN; 737 738 tv.tv_sec = _yplib_timeout; 739 tv.tv_usec = 0; 740 741 yprnk.domain = indomain; 742 yprnk.map = inmap; 743 744 bzero((char *)&yprm, sizeof yprm); 745 746 r = clnt_call(ysd->dom_client, YPPROC_MASTER, 747 xdr_ypreq_nokey, &yprnk, xdr_ypresp_master, &yprm, tv); 748 if(r != RPC_SUCCESS) { 749 clnt_perror(ysd->dom_client, "yp_master: clnt_call"); 750 ysd->dom_vers = -1; 751 goto again; 752 } 753 if( !(r=ypprot_err(yprm.status)) ) { 754 *outname = (char *)strdup(yprm.master); 755 } 756 xdr_free(xdr_ypresp_master, (char *)&yprm); 757 _yp_unbind(ysd); 758 return r; 759 } 760 int 761 yp_maplist(indomain, outmaplist) 762 char *indomain; 763 struct ypmaplist **outmaplist; 764 { 765 struct dom_binding *ysd; 766 struct ypresp_maplist ypml; 767 struct timeval tv; 768 int r; 769 770 /* Sanity check */ 771 772 if (indomain == NULL || !strlen(indomain)) 773 return YPERR_BADARGS; 774 775 again: 776 if( _yp_dobind(indomain, &ysd) != 0) 777 return YPERR_DOMAIN; 778 779 tv.tv_sec = _yplib_timeout; 780 tv.tv_usec = 0; 781 782 bzero((char *)&ypml, sizeof ypml); 783 784 r = clnt_call(ysd->dom_client, YPPROC_MAPLIST, 785 xdr_domainname, indomain, xdr_ypresp_maplist, &ypml, tv); 786 if (r != RPC_SUCCESS) { 787 clnt_perror(ysd->dom_client, "yp_maplist: clnt_call"); 788 ysd->dom_vers = -1; 789 goto again; 790 } 791 *outmaplist = ypml.list; 792 /* NO: xdr_free(xdr_ypresp_maplist, &ypml);*/ 793 _yp_unbind(ysd); 794 return ypprot_err(ypml.status); 795 } 796 797 char * 798 yperr_string(incode) 799 int incode; 800 { 801 static char err[80]; 802 803 switch(incode) { 804 case 0: 805 return "Success"; 806 case YPERR_BADARGS: 807 return "Request arguments bad"; 808 case YPERR_RPC: 809 return "RPC failure"; 810 case YPERR_DOMAIN: 811 return "Can't bind to server which serves this domain"; 812 case YPERR_MAP: 813 return "No such map in server's domain"; 814 case YPERR_KEY: 815 return "No such key in map"; 816 case YPERR_YPERR: 817 return "YP server error"; 818 case YPERR_RESRC: 819 return "Local resource allocation failure"; 820 case YPERR_NOMORE: 821 return "No more records in map database"; 822 case YPERR_PMAP: 823 return "Can't communicate with portmapper"; 824 case YPERR_YPBIND: 825 return "Can't communicate with ypbind"; 826 case YPERR_YPSERV: 827 return "Can't communicate with ypserv"; 828 case YPERR_NODOM: 829 return "Local domain name not set"; 830 case YPERR_BADDB: 831 return "Server data base is bad"; 832 case YPERR_VERS: 833 return "YP server version mismatch - server can't supply service."; 834 case YPERR_ACCESS: 835 return "Access violation"; 836 case YPERR_BUSY: 837 return "Database is busy"; 838 } 839 sprintf(err, "YP unknown error %d\n", incode); 840 return err; 841 } 842 843 int 844 ypprot_err(incode) 845 unsigned int incode; 846 { 847 switch(incode) { 848 case YP_TRUE: 849 return 0; 850 case YP_FALSE: 851 return YPERR_YPBIND; 852 case YP_NOMORE: 853 return YPERR_NOMORE; 854 case YP_NOMAP: 855 return YPERR_MAP; 856 case YP_NODOM: 857 return YPERR_DOMAIN; 858 case YP_NOKEY: 859 return YPERR_KEY; 860 case YP_BADOP: 861 return YPERR_YPERR; 862 case YP_BADDB: 863 return YPERR_BADDB; 864 case YP_YPERR: 865 return YPERR_YPERR; 866 case YP_BADARGS: 867 return YPERR_BADARGS; 868 case YP_VERS: 869 return YPERR_VERS; 870 } 871 return YPERR_YPERR; 872 } 873 874 int 875 _yp_check(dom) 876 char **dom; 877 { 878 char *unused; 879 880 if( _yp_domain[0]=='\0' ) 881 if( yp_get_default_domain(&unused) ) 882 return 0; 883 884 if(dom) 885 *dom = _yp_domain; 886 887 if( yp_bind(_yp_domain)==0 ) { 888 yp_unbind(_yp_domain); 889 return 1; 890 } 891 return 0; 892 } 893