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