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