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