1 /* 2 * Copyright (c) 1995 3 * Bill Paul <wpaul@ctr.columbia.edu>. 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 Bill Paul. 16 * 4. Neither the name of the author nor the names of any co-contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 * 32 */ 33 34 #ifndef lint 35 static const char rcsid[] = 36 "$FreeBSD$"; 37 #endif /* not lint */ 38 39 #include "yp.h" 40 #include "yp_extern.h" 41 #include <dirent.h> 42 #include <errno.h> 43 #include <stdlib.h> 44 #include <sys/stat.h> 45 #include <sys/param.h> 46 #include <sys/types.h> 47 #include <sys/socket.h> 48 #include <netinet/in.h> 49 #include <arpa/inet.h> 50 #include <rpc/rpc.h> 51 52 int children = 0; 53 54 #define MASTER_STRING "YP_MASTER_NAME" 55 #define MASTER_SZ sizeof(MASTER_STRING) - 1 56 #define ORDER_STRING "YP_LAST_MODIFIED" 57 #define ORDER_SZ sizeof(ORDER_STRING) - 1 58 59 static pid_t 60 yp_fork(void) 61 { 62 if (yp_pid != getpid()) { 63 yp_error("child %d trying to fork!", getpid()); 64 errno = EEXIST; 65 return(-1); 66 } 67 68 return(fork()); 69 } 70 71 /* 72 * NIS v2 support. This is where most of the action happens. 73 */ 74 75 void * 76 ypproc_null_2_svc(void *argp, struct svc_req *rqstp) 77 { 78 static char * result; 79 static char rval = 0; 80 81 #ifdef DB_CACHE 82 if (yp_access(NULL, NULL, (struct svc_req *)rqstp)) 83 #else 84 if (yp_access(NULL, (struct svc_req *)rqstp)) 85 #endif 86 return(NULL); 87 88 result = &rval; 89 90 return((void *) &result); 91 } 92 93 bool_t * 94 ypproc_domain_2_svc(domainname *argp, struct svc_req *rqstp) 95 { 96 static bool_t result; 97 98 #ifdef DB_CACHE 99 if (yp_access(NULL, NULL, (struct svc_req *)rqstp)) { 100 #else 101 if (yp_access(NULL, (struct svc_req *)rqstp)) { 102 #endif 103 result = FALSE; 104 return (&result); 105 } 106 107 if (argp == NULL || yp_validdomain(*argp)) 108 result = FALSE; 109 else 110 result = TRUE; 111 112 return (&result); 113 } 114 115 bool_t * 116 ypproc_domain_nonack_2_svc(domainname *argp, struct svc_req *rqstp) 117 { 118 static bool_t result; 119 120 #ifdef DB_CACHE 121 if (yp_access(NULL, NULL, (struct svc_req *)rqstp)) 122 #else 123 if (yp_access(NULL, (struct svc_req *)rqstp)) 124 #endif 125 return (NULL); 126 127 if (argp == NULL || yp_validdomain(*argp)) 128 return (NULL); 129 else 130 result = TRUE; 131 132 return (&result); 133 } 134 135 ypresp_val * 136 ypproc_match_2_svc(ypreq_key *argp, struct svc_req *rqstp) 137 { 138 static ypresp_val result; 139 140 result.val.valdat_val = ""; 141 result.val.valdat_len = 0; 142 143 #ifdef DB_CACHE 144 if (yp_access(argp->map, argp->domain, (struct svc_req *)rqstp)) { 145 #else 146 if (yp_access(argp->map, (struct svc_req *)rqstp)) { 147 #endif 148 result.stat = YP_YPERR; 149 return (&result); 150 } 151 152 if (argp->domain == NULL || argp->map == NULL) { 153 result.stat = YP_BADARGS; 154 return (&result); 155 } 156 157 if (yp_select_map(argp->map, argp->domain, NULL, 1) != YP_TRUE) { 158 result.stat = yp_errno; 159 return(&result); 160 } 161 162 result.stat = yp_getbykey(&argp->key, &result.val); 163 164 /* 165 * Do DNS lookups for hosts maps if database lookup failed. 166 */ 167 168 #ifdef DB_CACHE 169 if (result.stat != YP_TRUE && 170 (yp_testflag(argp->map, argp->domain, YP_INTERDOMAIN) || 171 (strstr(argp->map, "hosts") && do_dns))) { 172 #else 173 if (do_dns && result.stat != YP_TRUE && strstr(argp->map, "hosts")) { 174 #endif 175 char nbuf[YPMAXRECORD]; 176 177 /* NUL terminate! NUL terminate!! NUL TERMINATE!!! */ 178 bcopy(argp->key.keydat_val, nbuf, argp->key.keydat_len); 179 nbuf[argp->key.keydat_len] = '\0'; 180 181 if (debug) 182 yp_error("doing DNS lookup of %s", nbuf); 183 184 if (!strcmp(argp->map, "hosts.byname")) 185 result.stat = yp_async_lookup_name(rqstp, nbuf); 186 else if (!strcmp(argp->map, "hosts.byaddr")) 187 result.stat = yp_async_lookup_addr(rqstp, nbuf); 188 189 if (result.stat == YP_TRUE) 190 return(NULL); 191 } 192 193 return (&result); 194 } 195 196 ypresp_key_val * 197 ypproc_first_2_svc(ypreq_nokey *argp, struct svc_req *rqstp) 198 { 199 static ypresp_key_val result; 200 201 result.val.valdat_val = result.key.keydat_val = ""; 202 result.val.valdat_len = result.key.keydat_len = 0; 203 204 #ifdef DB_CACHE 205 if (yp_access(argp->map, argp->domain, (struct svc_req *)rqstp)) { 206 #else 207 if (yp_access(argp->map, (struct svc_req *)rqstp)) { 208 #endif 209 result.stat = YP_YPERR; 210 return (&result); 211 } 212 213 if (argp->domain == NULL) { 214 result.stat = YP_BADARGS; 215 return (&result); 216 } 217 218 if (yp_select_map(argp->map, argp->domain, NULL, 0) != YP_TRUE) { 219 result.stat = yp_errno; 220 return(&result); 221 } 222 223 result.stat = yp_firstbykey(&result.key, &result.val); 224 225 return (&result); 226 } 227 228 ypresp_key_val * 229 ypproc_next_2_svc(ypreq_key *argp, struct svc_req *rqstp) 230 { 231 static ypresp_key_val result; 232 233 result.val.valdat_val = result.key.keydat_val = ""; 234 result.val.valdat_len = result.key.keydat_len = 0; 235 236 #ifdef DB_CACHE 237 if (yp_access(argp->map, argp->domain, (struct svc_req *)rqstp)) { 238 #else 239 if (yp_access(argp->map, (struct svc_req *)rqstp)) { 240 #endif 241 result.stat = YP_YPERR; 242 return (&result); 243 } 244 245 if (argp->domain == NULL || argp->map == NULL) { 246 result.stat = YP_BADARGS; 247 return (&result); 248 } 249 250 if (yp_select_map(argp->map, argp->domain, &argp->key, 0) != YP_TRUE) { 251 result.stat = yp_errno; 252 return(&result); 253 } 254 255 result.key.keydat_len = argp->key.keydat_len; 256 result.key.keydat_val = argp->key.keydat_val; 257 258 result.stat = yp_nextbykey(&result.key, &result.val); 259 260 return (&result); 261 } 262 263 static void 264 ypxfr_callback(ypxfrstat rval, struct sockaddr_in *addr, unsigned int transid, 265 unsigned int prognum, unsigned long port) 266 { 267 CLIENT *clnt; 268 int sock = RPC_ANYSOCK; 269 struct timeval timeout; 270 yppushresp_xfr ypxfr_resp; 271 struct rpc_err err; 272 273 timeout.tv_sec = 5; 274 timeout.tv_usec = 0; 275 addr->sin_port = htons(port); 276 277 if ((clnt = clntudp_create(addr,prognum,1,timeout,&sock)) == NULL) { 278 yp_error("%s: %s", inet_ntoa(addr->sin_addr), 279 clnt_spcreateerror("failed to establish callback handle")); 280 return; 281 } 282 283 ypxfr_resp.status = rval; 284 ypxfr_resp.transid = transid; 285 286 /* Turn the timeout off -- we don't want to block. */ 287 timeout.tv_sec = 0; 288 if (clnt_control(clnt, CLSET_TIMEOUT, &timeout) == FALSE) 289 yp_error("failed to set timeout on ypproc_xfr callback"); 290 291 if (yppushproc_xfrresp_1(&ypxfr_resp, clnt) == NULL) { 292 clnt_geterr(clnt, &err); 293 if (err.re_status != RPC_SUCCESS && 294 err.re_status != RPC_TIMEDOUT) 295 yp_error("%s", clnt_sperror(clnt, 296 "ypxfr callback failed")); 297 } 298 299 clnt_destroy(clnt); 300 return; 301 } 302 303 #define YPXFR_RETURN(CODE) \ 304 /* Order is important: send regular RPC reply, then callback */ \ 305 result.xfrstat = CODE; \ 306 svc_sendreply(rqstp->rq_xprt, (xdrproc_t)xdr_ypresp_xfr, &result); \ 307 ypxfr_callback(CODE,rqhost,argp->transid, \ 308 argp->prog,argp->port); \ 309 return(NULL); 310 311 ypresp_xfr * 312 ypproc_xfr_2_svc(ypreq_xfr *argp, struct svc_req *rqstp) 313 { 314 static ypresp_xfr result; 315 struct sockaddr_in *rqhost; 316 ypresp_master *mres; 317 ypreq_nokey mreq; 318 319 result.transid = argp->transid; 320 rqhost = svc_getcaller(rqstp->rq_xprt); 321 322 #ifdef DB_CACHE 323 if (yp_access(argp->map_parms.map, 324 argp->map_parms.domain, (struct svc_req *)rqstp)) { 325 #else 326 if (yp_access(argp->map_parms.map, (struct svc_req *)rqstp)) { 327 #endif 328 YPXFR_RETURN(YPXFR_REFUSED) 329 } 330 331 332 if (argp->map_parms.domain == NULL) { 333 YPXFR_RETURN(YPXFR_BADARGS) 334 } 335 336 if (yp_validdomain(argp->map_parms.domain)) { 337 YPXFR_RETURN(YPXFR_NODOM) 338 } 339 340 /* 341 * Determine the master host ourselves. The caller may 342 * be up to no good. This has the side effect of verifying 343 * that the requested map and domain actually exist. 344 */ 345 346 mreq.domain = argp->map_parms.domain; 347 mreq.map = argp->map_parms.map; 348 349 mres = ypproc_master_2_svc(&mreq, rqstp); 350 351 if (mres->stat != YP_TRUE) { 352 yp_error("couldn't find master for map %s@%s", 353 argp->map_parms.map, 354 argp->map_parms.domain); 355 yp_error("host at %s (%s) may be pulling my leg", 356 argp->map_parms.peer, 357 inet_ntoa(rqhost->sin_addr)); 358 YPXFR_RETURN(YPXFR_REFUSED) 359 } 360 361 switch (yp_fork()) { 362 case 0: 363 { 364 char g[11], t[11], p[11]; 365 char ypxfr_command[MAXPATHLEN + 2]; 366 367 snprintf (ypxfr_command, sizeof(ypxfr_command), "%sypxfr", _PATH_LIBEXEC); 368 snprintf (t, sizeof(t), "%u", argp->transid); 369 snprintf (g, sizeof(g), "%u", argp->prog); 370 snprintf (p, sizeof(p), "%u", argp->port); 371 if (debug) { 372 close(0); close(1); close(2); 373 } 374 if (strcmp(yp_dir, _PATH_YP)) { 375 execl(ypxfr_command, "ypxfr", 376 "-d", argp->map_parms.domain, 377 "-h", mres->peer, 378 "-p", yp_dir, "-C", t, 379 g, inet_ntoa(rqhost->sin_addr), 380 p, argp->map_parms.map, 381 NULL); 382 } else { 383 execl(ypxfr_command, "ypxfr", 384 "-d", argp->map_parms.domain, 385 "-h", mres->peer, 386 "-C", t, 387 g, inet_ntoa(rqhost->sin_addr), 388 p, argp->map_parms.map, 389 NULL); 390 } 391 yp_error("ypxfr execl(%s): %s", ypxfr_command, strerror(errno)); 392 YPXFR_RETURN(YPXFR_XFRERR) 393 /* 394 * Just to safe, prevent PR #10970 from biting us in 395 * the unlikely case that execing ypxfr fails. We don't 396 * want to have any child processes spawned from this 397 * child process. 398 */ 399 _exit(0); 400 break; 401 } 402 case -1: 403 yp_error("ypxfr fork(): %s", strerror(errno)); 404 YPXFR_RETURN(YPXFR_XFRERR) 405 break; 406 default: 407 result.xfrstat = YPXFR_SUCC; 408 children++; 409 break; 410 } 411 412 return (&result); 413 } 414 #undef YPXFR_RETURN 415 416 void * 417 ypproc_clear_2_svc(void *argp, struct svc_req *rqstp) 418 { 419 static char * result; 420 static char rval = 0; 421 422 #ifdef DB_CACHE 423 if (yp_access(NULL, NULL, (struct svc_req *)rqstp)) 424 #else 425 if (yp_access(NULL, (struct svc_req *)rqstp)) 426 #endif 427 return (NULL); 428 #ifdef DB_CACHE 429 /* clear out the database cache */ 430 yp_flush_all(); 431 #endif 432 /* Re-read the securenets database for the hell of it. */ 433 load_securenets(); 434 435 result = &rval; 436 return((void *) &result); 437 } 438 439 /* 440 * For ypproc_all, we have to send a stream of ypresp_all structures 441 * via TCP, but the XDR filter generated from the yp.x protocol 442 * definition file only serializes one such structure. This means that 443 * to send the whole stream, you need a wrapper which feeds all the 444 * records into the underlying XDR routine until it hits an 'EOF.' 445 * But to use the wrapper, you have to violate the boundaries between 446 * RPC layers by calling svc_sendreply() directly from the ypproc_all 447 * service routine instead of letting the RPC dispatcher do it. 448 * 449 * Bleah. 450 */ 451 452 /* 453 * Custom XDR routine for serialzing results of ypproc_all: keep 454 * reading from the database and spew until we run out of records 455 * or encounter an error. 456 */ 457 static bool_t 458 xdr_my_ypresp_all(register XDR *xdrs, ypresp_all *objp) 459 { 460 while (1) { 461 /* Get a record. */ 462 if ((objp->ypresp_all_u.val.stat = 463 yp_nextbykey(&objp->ypresp_all_u.val.key, 464 &objp->ypresp_all_u.val.val)) == YP_TRUE) { 465 objp->more = TRUE; 466 } else { 467 objp->more = FALSE; 468 } 469 470 /* Serialize. */ 471 if (!xdr_ypresp_all(xdrs, objp)) 472 return(FALSE); 473 if (objp->more == FALSE) 474 return(TRUE); 475 } 476 } 477 478 ypresp_all * 479 ypproc_all_2_svc(ypreq_nokey *argp, struct svc_req *rqstp) 480 { 481 static ypresp_all result; 482 483 /* 484 * Set this here so that the client will be forced to make 485 * at least one attempt to read from us even if all we're 486 * doing is returning an error. 487 */ 488 result.more = TRUE; 489 result.ypresp_all_u.val.key.keydat_len = 0; 490 result.ypresp_all_u.val.key.keydat_val = ""; 491 492 #ifdef DB_CACHE 493 if (yp_access(argp->map, argp->domain, (struct svc_req *)rqstp)) { 494 #else 495 if (yp_access(argp->map, (struct svc_req *)rqstp)) { 496 #endif 497 result.ypresp_all_u.val.stat = YP_YPERR; 498 return (&result); 499 } 500 501 if (argp->domain == NULL || argp->map == NULL) { 502 result.ypresp_all_u.val.stat = YP_BADARGS; 503 return (&result); 504 } 505 506 /* 507 * XXX If we hit the child limit, fail the request. 508 * If we don't, and the map is large, we could block for 509 * a long time in the parent. 510 */ 511 if (children >= MAX_CHILDREN) { 512 result.ypresp_all_u.val.stat = YP_YPERR; 513 return(&result); 514 } 515 516 /* 517 * The ypproc_all procedure can take a while to complete. 518 * Best to handle it in a subprocess so the parent doesn't 519 * block. (Is there a better way to do this? Maybe with 520 * async socket I/O?) 521 */ 522 if (!debug) { 523 switch (yp_fork()) { 524 case 0: 525 break; 526 case -1: 527 yp_error("ypall fork(): %s", strerror(errno)); 528 result.ypresp_all_u.val.stat = YP_YPERR; 529 return(&result); 530 break; 531 default: 532 children++; 533 return (NULL); 534 break; 535 } 536 } 537 538 /* 539 * Fix for PR #10971: don't let the child ypserv share 540 * DB handles with the parent process. 541 */ 542 #ifdef DB_CACHE 543 yp_flush_all(); 544 #endif 545 546 if (yp_select_map(argp->map, argp->domain, 547 &result.ypresp_all_u.val.key, 0) != YP_TRUE) { 548 result.ypresp_all_u.val.stat = yp_errno; 549 return(&result); 550 } 551 552 /* Kick off the actual data transfer. */ 553 svc_sendreply(rqstp->rq_xprt, (xdrproc_t)xdr_my_ypresp_all, &result); 554 555 /* 556 * Proper fix for PR #10970: exit here so that we don't risk 557 * having a child spawned from this sub-process. 558 */ 559 _exit(0); 560 } 561 562 ypresp_master * 563 ypproc_master_2_svc(ypreq_nokey *argp, struct svc_req *rqstp) 564 { 565 static ypresp_master result; 566 static char ypvalbuf[YPMAXRECORD]; 567 keydat key = { MASTER_SZ, MASTER_STRING }; 568 valdat val; 569 570 result.peer = ""; 571 572 #ifdef DB_CACHE 573 if (yp_access(argp->map, argp->domain, (struct svc_req *)rqstp)) { 574 #else 575 if (yp_access(argp->map, (struct svc_req *)rqstp)) { 576 #endif 577 result.stat = YP_YPERR; 578 return(&result); 579 } 580 581 if (argp->domain == NULL) { 582 result.stat = YP_BADARGS; 583 return (&result); 584 } 585 586 if (yp_select_map(argp->map, argp->domain, &key, 1) != YP_TRUE) { 587 result.stat = yp_errno; 588 return(&result); 589 } 590 591 /* 592 * Note that we copy the data retrieved from the database to 593 * a private buffer and NUL terminate the buffer rather than 594 * terminating the data in place. We do this because by stuffing 595 * a '\0' into data.data, we will actually be corrupting memory 596 * allocated by the DB package. This is a bad thing now that we 597 * cache DB handles rather than closing the database immediately. 598 */ 599 result.stat = yp_getbykey(&key, &val); 600 if (result.stat == YP_TRUE) { 601 bcopy(val.valdat_val, &ypvalbuf, val.valdat_len); 602 ypvalbuf[val.valdat_len] = '\0'; 603 result.peer = ypvalbuf; 604 } else 605 result.peer = ""; 606 607 return (&result); 608 } 609 610 ypresp_order * 611 ypproc_order_2_svc(ypreq_nokey *argp, struct svc_req *rqstp) 612 { 613 static ypresp_order result; 614 keydat key = { ORDER_SZ, ORDER_STRING }; 615 valdat val; 616 617 result.ordernum = 0; 618 619 #ifdef DB_CACHE 620 if (yp_access(argp->map, argp->domain, (struct svc_req *)rqstp)) { 621 #else 622 if (yp_access(argp->map, (struct svc_req *)rqstp)) { 623 #endif 624 result.stat = YP_YPERR; 625 return(&result); 626 } 627 628 if (argp->domain == NULL) { 629 result.stat = YP_BADARGS; 630 return (&result); 631 } 632 633 /* 634 * We could just check the timestamp on the map file, 635 * but that's a hack: we'll only know the last time the file 636 * was touched, not the last time the database contents were 637 * updated. 638 */ 639 640 if (yp_select_map(argp->map, argp->domain, &key, 1) != YP_TRUE) { 641 result.stat = yp_errno; 642 return(&result); 643 } 644 645 result.stat = yp_getbykey(&key, &val); 646 647 if (result.stat == YP_TRUE) 648 result.ordernum = atoi(val.valdat_val); 649 else 650 result.ordernum = 0; 651 652 return (&result); 653 } 654 655 static void yp_maplist_free(struct ypmaplist *yp_maplist) 656 { 657 register struct ypmaplist *next; 658 659 while (yp_maplist) { 660 next = yp_maplist->next; 661 free(yp_maplist->map); 662 free(yp_maplist); 663 yp_maplist = next; 664 } 665 return; 666 } 667 668 static struct ypmaplist * 669 yp_maplist_create(const char *domain) 670 { 671 char yp_mapdir[MAXPATHLEN + 2]; 672 char yp_mapname[MAXPATHLEN + 2]; 673 struct ypmaplist *cur = NULL; 674 struct ypmaplist *yp_maplist = NULL; 675 DIR *dird; 676 struct dirent *dirp; 677 struct stat statbuf; 678 679 snprintf(yp_mapdir, sizeof(yp_mapdir), "%s/%s", yp_dir, domain); 680 681 if ((dird = opendir(yp_mapdir)) == NULL) { 682 yp_error("opendir(%s) failed: %s", yp_mapdir, strerror(errno)); 683 return(NULL); 684 } 685 686 while ((dirp = readdir(dird)) != NULL) { 687 if (strcmp(dirp->d_name, ".") && strcmp(dirp->d_name, "..")) { 688 snprintf(yp_mapname, sizeof(yp_mapname), "%s/%s", 689 yp_mapdir,dirp->d_name); 690 if (stat(yp_mapname, &statbuf) < 0 || 691 !S_ISREG(statbuf.st_mode)) 692 continue; 693 if ((cur = (struct ypmaplist *) 694 malloc(sizeof(struct ypmaplist))) == NULL) { 695 yp_error("malloc() failed"); 696 closedir(dird); 697 yp_maplist_free(yp_maplist); 698 return(NULL); 699 } 700 if ((cur->map = strdup(dirp->d_name)) == NULL) { 701 yp_error("strdup() failed: %s",strerror(errno)); 702 closedir(dird); 703 yp_maplist_free(yp_maplist); 704 return(NULL); 705 } 706 cur->next = yp_maplist; 707 yp_maplist = cur; 708 if (debug) 709 yp_error("map: %s", yp_maplist->map); 710 } 711 712 } 713 closedir(dird); 714 return(yp_maplist); 715 } 716 717 ypresp_maplist * 718 ypproc_maplist_2_svc(domainname *argp, struct svc_req *rqstp) 719 { 720 static ypresp_maplist result = { 0, NULL }; 721 722 #ifdef DB_CACHE 723 if (yp_access(NULL, NULL, (struct svc_req *)rqstp)) { 724 #else 725 if (yp_access(NULL, (struct svc_req *)rqstp)) { 726 #endif 727 result.stat = YP_YPERR; 728 return(&result); 729 } 730 731 if (argp == NULL) { 732 result.stat = YP_BADARGS; 733 return (&result); 734 } 735 736 if (yp_validdomain(*argp)) { 737 result.stat = YP_NODOM; 738 return (&result); 739 } 740 741 /* 742 * We have to construct a linked list for the ypproc_maplist 743 * procedure using dynamically allocated memory. Since the XDR 744 * layer won't free this list for us, we have to deal with it 745 * ourselves. We call yp_maplist_free() first to free any 746 * previously allocated data we may have accumulated to insure 747 * that we have only one linked list in memory at any given 748 * time. 749 */ 750 751 yp_maplist_free(result.maps); 752 753 if ((result.maps = yp_maplist_create(*argp)) == NULL) { 754 yp_error("yp_maplist_create failed"); 755 result.stat = YP_YPERR; 756 return(&result); 757 } else 758 result.stat = YP_TRUE; 759 760 return (&result); 761 } 762 763 /* 764 * NIS v1 support. The nullproc, domain and domain_nonack 765 * functions from v1 are identical to those in v2, so all 766 * we have to do is hand off to them. 767 * 768 * The other functions are mostly just wrappers around their v2 769 * counterparts. For example, for the v1 'match' procedure, we 770 * crack open the argument structure, make a request to the v2 771 * 'match' function, repackage the data into a v1 response and 772 * then send it on its way. 773 * 774 * Note that we don't support the pull, push and get procedures. 775 * There's little documentation available to show what they 776 * do, and I suspect they're meant largely for map transfers 777 * between master and slave servers. 778 */ 779 780 void * 781 ypoldproc_null_1_svc(void *argp, struct svc_req *rqstp) 782 { 783 return(ypproc_null_2_svc(argp, rqstp)); 784 } 785 786 bool_t * 787 ypoldproc_domain_1_svc(domainname *argp, struct svc_req *rqstp) 788 { 789 return(ypproc_domain_2_svc(argp, rqstp)); 790 } 791 792 bool_t * 793 ypoldproc_domain_nonack_1_svc(domainname *argp, struct svc_req *rqstp) 794 { 795 return (ypproc_domain_nonack_2_svc(argp, rqstp)); 796 } 797 798 /* 799 * the 'match' procedure sends a response of type YPRESP_VAL 800 */ 801 ypresponse * 802 ypoldproc_match_1_svc(yprequest *argp, struct svc_req *rqstp) 803 { 804 static ypresponse result; 805 ypresp_val *v2_result; 806 807 result.yp_resptype = YPRESP_VAL; 808 result.ypresponse_u.yp_resp_valtype.val.valdat_val = ""; 809 result.ypresponse_u.yp_resp_valtype.val.valdat_len = 0; 810 811 if (argp->yp_reqtype != YPREQ_KEY) { 812 result.ypresponse_u.yp_resp_valtype.stat = YP_BADARGS; 813 return(&result); 814 } 815 816 v2_result = ypproc_match_2_svc(&argp->yprequest_u.yp_req_keytype,rqstp); 817 if (v2_result == NULL) 818 return(NULL); 819 820 bcopy(v2_result, &result.ypresponse_u.yp_resp_valtype, 821 sizeof(ypresp_val)); 822 823 return (&result); 824 } 825 826 /* 827 * the 'first' procedure sends a response of type YPRESP_KEY_VAL 828 */ 829 ypresponse * 830 ypoldproc_first_1_svc(yprequest *argp, struct svc_req *rqstp) 831 { 832 static ypresponse result; 833 ypresp_key_val *v2_result; 834 835 result.yp_resptype = YPRESP_KEY_VAL; 836 result.ypresponse_u.yp_resp_key_valtype.val.valdat_val = 837 result.ypresponse_u.yp_resp_key_valtype.key.keydat_val = ""; 838 result.ypresponse_u.yp_resp_key_valtype.val.valdat_len = 839 result.ypresponse_u.yp_resp_key_valtype.key.keydat_len = 0; 840 841 if (argp->yp_reqtype != YPREQ_NOKEY) { 842 result.ypresponse_u.yp_resp_key_valtype.stat = YP_BADARGS; 843 return(&result); 844 } 845 846 v2_result = ypproc_first_2_svc(&argp->yprequest_u.yp_req_nokeytype, 847 rqstp); 848 if (v2_result == NULL) 849 return(NULL); 850 851 bcopy(v2_result, &result.ypresponse_u.yp_resp_key_valtype, 852 sizeof(ypresp_key_val)); 853 854 return (&result); 855 } 856 857 /* 858 * the 'next' procedure sends a response of type YPRESP_KEY_VAL 859 */ 860 ypresponse * 861 ypoldproc_next_1_svc(yprequest *argp, struct svc_req *rqstp) 862 { 863 static ypresponse result; 864 ypresp_key_val *v2_result; 865 866 result.yp_resptype = YPRESP_KEY_VAL; 867 result.ypresponse_u.yp_resp_key_valtype.val.valdat_val = 868 result.ypresponse_u.yp_resp_key_valtype.key.keydat_val = ""; 869 result.ypresponse_u.yp_resp_key_valtype.val.valdat_len = 870 result.ypresponse_u.yp_resp_key_valtype.key.keydat_len = 0; 871 872 if (argp->yp_reqtype != YPREQ_KEY) { 873 result.ypresponse_u.yp_resp_key_valtype.stat = YP_BADARGS; 874 return(&result); 875 } 876 877 v2_result = ypproc_next_2_svc(&argp->yprequest_u.yp_req_keytype,rqstp); 878 if (v2_result == NULL) 879 return(NULL); 880 881 bcopy(v2_result, &result.ypresponse_u.yp_resp_key_valtype, 882 sizeof(ypresp_key_val)); 883 884 return (&result); 885 } 886 887 /* 888 * the 'poll' procedure sends a response of type YPRESP_MAP_PARMS 889 */ 890 ypresponse * 891 ypoldproc_poll_1_svc(yprequest *argp, struct svc_req *rqstp) 892 { 893 static ypresponse result; 894 ypresp_master *v2_result1; 895 ypresp_order *v2_result2; 896 897 result.yp_resptype = YPRESP_MAP_PARMS; 898 result.ypresponse_u.yp_resp_map_parmstype.domain = 899 argp->yprequest_u.yp_req_nokeytype.domain; 900 result.ypresponse_u.yp_resp_map_parmstype.map = 901 argp->yprequest_u.yp_req_nokeytype.map; 902 /* 903 * Hmm... there is no 'status' value in the 904 * yp_resp_map_parmstype structure, so I have to 905 * guess at what to do to indicate a failure. 906 * I hope this is right. 907 */ 908 result.ypresponse_u.yp_resp_map_parmstype.ordernum = 0; 909 result.ypresponse_u.yp_resp_map_parmstype.peer = ""; 910 911 if (argp->yp_reqtype != YPREQ_MAP_PARMS) { 912 return(&result); 913 } 914 915 v2_result1 = ypproc_master_2_svc(&argp->yprequest_u.yp_req_nokeytype, 916 rqstp); 917 if (v2_result1 == NULL) 918 return(NULL); 919 920 if (v2_result1->stat != YP_TRUE) { 921 return(&result); 922 } 923 924 v2_result2 = ypproc_order_2_svc(&argp->yprequest_u.yp_req_nokeytype, 925 rqstp); 926 if (v2_result2 == NULL) 927 return(NULL); 928 929 if (v2_result2->stat != YP_TRUE) { 930 return(&result); 931 } 932 933 result.ypresponse_u.yp_resp_map_parmstype.peer = 934 v2_result1->peer; 935 result.ypresponse_u.yp_resp_map_parmstype.ordernum = 936 v2_result2->ordernum; 937 938 return (&result); 939 } 940 941 ypresponse * 942 ypoldproc_push_1_svc(yprequest *argp, struct svc_req *rqstp) 943 { 944 static ypresponse result; 945 946 /* 947 * Not implemented. 948 */ 949 950 return (&result); 951 } 952 953 ypresponse * 954 ypoldproc_pull_1_svc(yprequest *argp, struct svc_req *rqstp) 955 { 956 static ypresponse result; 957 958 /* 959 * Not implemented. 960 */ 961 962 return (&result); 963 } 964 965 ypresponse * 966 ypoldproc_get_1_svc(yprequest *argp, struct svc_req *rqstp) 967 { 968 static ypresponse result; 969 970 /* 971 * Not implemented. 972 */ 973 974 return (&result); 975 } 976