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