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