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