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