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