yp_server.c revision 24780
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#include "yp.h" 35#include "yp_extern.h" 36#include <stdlib.h> 37#include <dirent.h> 38#include <sys/stat.h> 39#include <sys/param.h> 40#include <errno.h> 41#include <sys/types.h> 42#include <sys/socket.h> 43#include <netinet/in.h> 44#include <arpa/inet.h> 45#include <rpc/rpc.h> 46 47#ifndef lint 48static const char rcsid[] = "$Id: yp_server.c,v 1.5 1997/03/15 06:06:06 wpaul Exp wpaul $"; 49#endif /* not lint */ 50 51int forked = 0; 52int children = 0; 53static char *master_string = "YP_MASTER_NAME"; 54static char *order_string = "YP_LAST_MODIFIED"; 55static int master_sz = sizeof("YP_MASTER_NAME") - 1; 56static int order_sz = sizeof("YP_LAST_MODIFIED") - 1; 57 58/* 59 * NIS v2 support. This is where most of the action happens. 60 */ 61 62void * 63ypproc_null_2_svc(void *argp, struct svc_req *rqstp) 64{ 65 static char * result; 66 static char rval = 0; 67 68#ifdef DB_CACHE 69 if (yp_access(NULL, NULL, (struct svc_req *)rqstp)) 70#else 71 if (yp_access(NULL, (struct svc_req *)rqstp)) 72#endif 73 return(NULL); 74 75 result = &rval; 76 77 return((void *) &result); 78} 79 80bool_t * 81ypproc_domain_2_svc(domainname *argp, struct svc_req *rqstp) 82{ 83 static bool_t result; 84 85#ifdef DB_CACHE 86 if (yp_access(NULL, NULL, (struct svc_req *)rqstp)) { 87#else 88 if (yp_access(NULL, (struct svc_req *)rqstp)) { 89#endif 90 result = FALSE; 91 return (&result); 92 } 93 94 if (argp == NULL || yp_validdomain(*argp)) 95 result = FALSE; 96 else 97 result = TRUE; 98 99 return (&result); 100} 101 102bool_t * 103ypproc_domain_nonack_2_svc(domainname *argp, struct svc_req *rqstp) 104{ 105 static bool_t result; 106 107#ifdef DB_CACHE 108 if (yp_access(NULL, NULL, (struct svc_req *)rqstp)) 109#else 110 if (yp_access(NULL, (struct svc_req *)rqstp)) 111#endif 112 return (NULL); 113 114 if (argp == NULL || yp_validdomain(*argp)) 115 return (NULL); 116 else 117 result = TRUE; 118 119 return (&result); 120} 121 122ypresp_val * 123ypproc_match_2_svc(ypreq_key *argp, struct svc_req *rqstp) 124{ 125 static ypresp_val result; 126 127 result.val.valdat_val = ""; 128 result.val.valdat_len = 0; 129 130#ifdef DB_CACHE 131 if (yp_access(argp->map, argp->domain, (struct svc_req *)rqstp)) { 132#else 133 if (yp_access(argp->map, (struct svc_req *)rqstp)) { 134#endif 135 result.stat = YP_YPERR; 136 return (&result); 137 } 138 139 if (argp->domain == NULL || argp->map == NULL) { 140 result.stat = YP_BADARGS; 141 return (&result); 142 } 143 144 if (yp_select_map(argp->map, argp->domain, &argp->key, 1) != YP_TRUE) { 145 result.stat = yp_errno; 146 return(&result); 147 } 148 149 result.stat = yp_getbykey(&argp->key, &result.val); 150 151 /* 152 * Do DNS lookups for hosts maps if database lookup failed. 153 */ 154 155#ifdef DB_CACHE 156 if (result.stat != YP_TRUE && 157 (yp_testflag(argp->map, argp->domain, YP_INTERDOMAIN) || 158 (strstr(argp->map, "hosts") && do_dns))) { 159#else 160 if (do_dns && result.stat != YP_TRUE && strstr(argp->map, "hosts")) { 161#endif 162 163 /* NUL terminate! NUL terminate!! NUL TERMINATE!!! */ 164 argp->key.keydat_val[argp->key.keydat_len] = '\0'; 165 166 if (debug) 167 yp_error("Doing DNS lookup of %.*s", 168 argp->key.keydat_len, 169 argp->key.keydat_val); 170 171 if (!strcmp(argp->map, "hosts.byname")) 172 result.stat = yp_async_lookup_name(rqstp, 173 (char *)argp->key.keydat_val); 174 else if (!strcmp(argp->map, "hosts.byaddr")) 175 result.stat = yp_async_lookup_addr(rqstp, 176 (char *)argp->key.keydat_val); 177 178 if (result.stat == YP_TRUE) 179 return(NULL); 180 } 181 182 return (&result); 183} 184 185ypresp_key_val * 186ypproc_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, &result.key, 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 217ypresp_key_val * 218ypproc_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 252static 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 303ypresp_xfr * 304ypproc_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 /* 315 * The FreeBSD ypxfr(8) program will not talk to a ypserv(8) 316 * or rpc.ypxfrd(8) unless it's using a reserved port, but we 317 * may as well check that the process calling this procedure 318 * is also using one. 319 * 320 * yp_access() may also do a reserved port test, but only 321 * if the YP_SECURE flag is set in the map. For this procedure, 322 * the check should be unconditional. 323 */ 324 if (ntohs(rqhost->sin_port) >= IPPORT_RESERVED) { 325 yp_error("ypxfr request from non-reserved port (%s:%d) -- \ 326rejecting", inet_ntoa(rqhost->sin_addr), ntohs(rqhost->sin_port)); 327 YPXFR_RETURN(YPXFR_REFUSED) 328 } 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(fork()) { 370 case 0: 371 { 372 char g[11], t[11], p[11]; 373 char ypxfr_command[MAXPATHLEN + 2]; 374 375 sprintf (ypxfr_command, "%sypxfr", _PATH_LIBEXEC); 376 sprintf (t, "%u", argp->transid); 377 sprintf (g, "%u", argp->prog); 378 sprintf (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 forked++; 400 yp_error("ypxfr execl(%s): %s", ypxfr_command, strerror(errno)); 401 YPXFR_RETURN(YPXFR_XFRERR) 402 break; 403 } 404 case -1: 405 yp_error("ypxfr fork(): %s", strerror(errno)); 406 YPXFR_RETURN(YPXFR_XFRERR) 407 break; 408 default: 409 result.xfrstat = YPXFR_SUCC; 410 children++; 411 forked = 0; 412 break; 413 } 414 415 return (&result); 416} 417#undef YPXFR_RETURN 418 419void * 420ypproc_clear_2_svc(void *argp, struct svc_req *rqstp) 421{ 422 static char * result; 423 static char rval = 0; 424 425#ifdef DB_CACHE 426 if (yp_access(NULL, NULL, (struct svc_req *)rqstp)) 427#else 428 if (yp_access(NULL, (struct svc_req *)rqstp)) 429#endif 430 return (NULL); 431#ifdef DB_CACHE 432 /* clear out the database cache */ 433 yp_flush_all(); 434#endif 435 /* Re-read the securenets database for the hell of it. */ 436 load_securenets(); 437 438 result = &rval; 439 return((void *) &result); 440} 441 442/* 443 * For ypproc_all, we have to send a stream of ypresp_all structures 444 * via TCP, but the XDR filter generated from the yp.x protocol 445 * definition file only serializes one such structure. This means that 446 * to send the whole stream, you need a wrapper which feeds all the 447 * records into the underlying XDR routine until it hits an 'EOF.' 448 * But to use the wrapper, you have to violate the boundaries between 449 * RPC layers by calling svc_sendreply() directly from the ypproc_all 450 * service routine instead of letting the RPC dispatcher do it. 451 * 452 * Bleah. 453 */ 454 455/* 456 * Custom XDR routine for serialzing results of ypproc_all: keep 457 * reading from the database and spew until we run out of records 458 * or encounter an error. 459 */ 460static bool_t 461xdr_my_ypresp_all(register XDR *xdrs, ypresp_all *objp) 462{ 463 while (1) { 464 /* Get a record. */ 465 if ((objp->ypresp_all_u.val.stat = 466 yp_nextbykey(&objp->ypresp_all_u.val.key, 467 &objp->ypresp_all_u.val.val)) == YP_TRUE) { 468 objp->more = TRUE; 469 } else { 470 objp->more = FALSE; 471 } 472 473 /* Serialize. */ 474 if (!xdr_ypresp_all(xdrs, objp)) 475 return(FALSE); 476 if (objp->more == FALSE) 477 return(TRUE); 478 } 479} 480 481ypresp_all * 482ypproc_all_2_svc(ypreq_nokey *argp, struct svc_req *rqstp) 483{ 484 static ypresp_all result; 485 486 /* 487 * Set this here so that the client will be forced to make 488 * at least one attempt to read from us even if all we're 489 * doing is returning an error. 490 */ 491 result.more = TRUE; 492 result.ypresp_all_u.val.key.keydat_len = 0; 493 result.ypresp_all_u.val.key.keydat_val = ""; 494 495#ifdef DB_CACHE 496 if (yp_access(argp->map, argp->domain, (struct svc_req *)rqstp)) { 497#else 498 if (yp_access(argp->map, (struct svc_req *)rqstp)) { 499#endif 500 result.ypresp_all_u.val.stat = YP_YPERR; 501 return (&result); 502 } 503 504 if (argp->domain == NULL || argp->map == NULL) { 505 result.ypresp_all_u.val.stat = YP_BADARGS; 506 return (&result); 507 } 508 509 /* 510 * XXX If we hit the child limit, fail the request. 511 * If we don't, and the map is large, we could block for 512 * a long time in the parent. 513 */ 514 if (children >= MAX_CHILDREN) { 515 result.ypresp_all_u.val.stat = YP_YPERR; 516 return(&result); 517 } 518 519 /* 520 * The ypproc_all procedure can take a while to complete. 521 * Best to handle it in a subprocess so the parent doesn't 522 * block. (Is there a better way to do this? Maybe with 523 * async socket I/O?) 524 */ 525 if (!debug && children < MAX_CHILDREN && fork()) { 526 children++; 527 forked = 0; 528 return (NULL); 529 } else { 530 forked++; 531 } 532 533 if (yp_select_map(argp->map, argp->domain, 534 &result.ypresp_all_u.val.key, 0) != YP_TRUE) { 535 result.ypresp_all_u.val.stat = yp_errno; 536 return(&result); 537 } 538 539 /* Kick off the actual data transfer. */ 540 svc_sendreply(rqstp->rq_xprt, xdr_my_ypresp_all, (char *)&result); 541 542 /* 543 * Returning NULL prevents the dispatcher from calling 544 * svc_sendreply() since we already did it. 545 */ 546 return (NULL); 547} 548 549ypresp_master * 550ypproc_master_2_svc(ypreq_nokey *argp, struct svc_req *rqstp) 551{ 552 static ypresp_master result; 553 static char ypvalbuf[YPMAXRECORD]; 554 keydat key = { master_sz, master_string }; 555 valdat val; 556 557 result.peer = ""; 558 559#ifdef DB_CACHE 560 if (yp_access(argp->map, argp->domain, (struct svc_req *)rqstp)) { 561#else 562 if (yp_access(argp->map, (struct svc_req *)rqstp)) { 563#endif 564 result.stat = YP_YPERR; 565 return(&result); 566 } 567 568 if (argp->domain == NULL) { 569 result.stat = YP_BADARGS; 570 return (&result); 571 } 572 573 if (yp_select_map(argp->map, argp->domain, &key, 1) != YP_TRUE) { 574 result.stat = yp_errno; 575 return(&result); 576 } 577 578 /* 579 * Note that we copy the data retrieved from the database to 580 * a private buffer and NUL terminate the buffer rather than 581 * terminating the data in place. We do this because by stuffing 582 * a '\0' into data.data, we will actually be corrupting memory 583 * allocated by the DB package. This is a bad thing now that we 584 * cache DB handles rather than closing the database immediately. 585 */ 586 result.stat = yp_getbykey(&key, &val); 587 if (result.stat == YP_TRUE) { 588 bcopy((char *)val.valdat_val, (char *)&ypvalbuf, 589 val.valdat_len); 590 ypvalbuf[val.valdat_len] = '\0'; 591 result.peer = (char *)&ypvalbuf; 592 } else 593 result.peer = ""; 594 595 return (&result); 596} 597 598ypresp_order * 599ypproc_order_2_svc(ypreq_nokey *argp, struct svc_req *rqstp) 600{ 601 static ypresp_order result; 602 keydat key = { order_sz, order_string }; 603 valdat val; 604 605 result.ordernum = 0; 606 607#ifdef DB_CACHE 608 if (yp_access(argp->map, argp->domain, (struct svc_req *)rqstp)) { 609#else 610 if (yp_access(argp->map, (struct svc_req *)rqstp)) { 611#endif 612 result.stat = YP_YPERR; 613 return(&result); 614 } 615 616 if (argp->domain == NULL) { 617 result.stat = YP_BADARGS; 618 return (&result); 619 } 620 621 /* 622 * We could just check the timestamp on the map file, 623 * but that's a hack: we'll only know the last time the file 624 * was touched, not the last time the database contents were 625 * updated. 626 */ 627 628 if (yp_select_map(argp->map, argp->domain, &key, 1) != YP_TRUE) { 629 result.stat = yp_errno; 630 return(&result); 631 } 632 633 result.stat = yp_getbykey(&key, &val); 634 635 if (result.stat == YP_TRUE) 636 result.ordernum = atoi((char *)val.valdat_val); 637 else 638 result.ordernum = 0; 639 640 return (&result); 641} 642 643static void yp_maplist_free(yp_maplist) 644 struct ypmaplist *yp_maplist; 645{ 646 register struct ypmaplist *next; 647 648 while(yp_maplist) { 649 next = yp_maplist->next; 650 free(yp_maplist->map); 651 free(yp_maplist); 652 yp_maplist = next; 653 } 654 return; 655} 656 657static struct ypmaplist *yp_maplist_create(domain) 658 const char *domain; 659{ 660 char yp_mapdir[MAXPATHLEN + 2]; 661 char yp_mapname[MAXPATHLEN + 2]; 662 struct ypmaplist *cur = NULL; 663 struct ypmaplist *yp_maplist = NULL; 664 DIR *dird; 665 struct dirent *dirp; 666 struct stat statbuf; 667 668 snprintf(yp_mapdir, sizeof(yp_mapdir), "%s/%s", yp_dir, domain); 669 670 if ((dird = opendir(yp_mapdir)) == NULL) { 671 yp_error("opendir(%s) failed: %s", yp_mapdir, strerror(errno)); 672 return(NULL); 673 } 674 675 while ((dirp = readdir(dird)) != NULL) { 676 if (strcmp(dirp->d_name, ".") && strcmp(dirp->d_name, "..")) { 677 snprintf(yp_mapname, sizeof(yp_mapname), "%s/%s", 678 yp_mapdir,dirp->d_name); 679 if (stat(yp_mapname, &statbuf) < 0 || 680 !S_ISREG(statbuf.st_mode)) 681 continue; 682 if ((cur = (struct ypmaplist *) 683 malloc(sizeof(struct ypmaplist))) == NULL) { 684 yp_error("malloc() failed: %s",strerror(errno)); 685 closedir(dird); 686 yp_maplist_free(yp_maplist); 687 return(NULL); 688 } 689 if ((cur->map = (char *)strdup(dirp->d_name)) == NULL) { 690 yp_error("strdup() failed: %s",strerror(errno)); 691 closedir(dird); 692 yp_maplist_free(yp_maplist); 693 return(NULL); 694 } 695 cur->next = yp_maplist; 696 yp_maplist = cur; 697 if (debug) 698 yp_error("map: %s", yp_maplist->map); 699 } 700 701 } 702 closedir(dird); 703 return(yp_maplist); 704} 705 706ypresp_maplist * 707ypproc_maplist_2_svc(domainname *argp, struct svc_req *rqstp) 708{ 709 static ypresp_maplist result = { 0, NULL }; 710 711#ifdef DB_CACHE 712 if (yp_access(NULL, NULL, (struct svc_req *)rqstp)) { 713#else 714 if (yp_access(NULL, (struct svc_req *)rqstp)) { 715#endif 716 result.stat = YP_YPERR; 717 return(&result); 718 } 719 720 if (argp == NULL) { 721 result.stat = YP_BADARGS; 722 return (&result); 723 } 724 725 if (yp_validdomain(*argp)) { 726 result.stat = YP_NODOM; 727 return (&result); 728 } 729 730 /* 731 * We have to construct a linked list for the ypproc_maplist 732 * procedure using dynamically allocated memory. Since the XDR 733 * layer won't free this list for us, we have to deal with it 734 * ourselves. We call yp_maplist_free() first to free any 735 * previously allocated data we may have accumulated to insure 736 * that we have only one linked list in memory at any given 737 * time. 738 */ 739 740 yp_maplist_free(result.maps); 741 742 if ((result.maps = yp_maplist_create(*argp)) == NULL) { 743 yp_error("yp_maplist_create failed"); 744 result.stat = YP_YPERR; 745 return(&result); 746 } else 747 result.stat = YP_TRUE; 748 749 return (&result); 750} 751 752/* 753 * NIS v1 support. The nullproc, domain and domain_nonack 754 * functions from v1 are identical to those in v2, so all 755 * we have to do is hand off to them. 756 * 757 * The other functions are mostly just wrappers around their v2 758 * counterparts. For example, for the v1 'match' procedure, we 759 * crack open the argument structure, make a request to the v2 760 * 'match' function, repackage the data into a v1 response and 761 * then send it on its way. 762 * 763 * Note that we don't support the pull, push and get procedures. 764 * There's little documentation available to show what they 765 * do, and I suspect they're meant largely for map transfers 766 * between master and slave servers. 767 */ 768 769void * 770ypoldproc_null_1_svc(void *argp, struct svc_req *rqstp) 771{ 772 return(ypproc_null_2_svc(argp, rqstp)); 773} 774 775bool_t * 776ypoldproc_domain_1_svc(domainname *argp, struct svc_req *rqstp) 777{ 778 return(ypproc_domain_2_svc(argp, rqstp)); 779} 780 781bool_t * 782ypoldproc_domain_nonack_1_svc(domainname *argp, struct svc_req *rqstp) 783{ 784 return (ypproc_domain_nonack_2_svc(argp, rqstp)); 785} 786 787/* 788 * the 'match' procedure sends a response of type YPRESP_VAL 789 */ 790ypresponse * 791ypoldproc_match_1_svc(yprequest *argp, struct svc_req *rqstp) 792{ 793 static ypresponse result; 794 ypresp_val *v2_result; 795 796 result.yp_resptype = YPRESP_VAL; 797 result.ypresponse_u.yp_resp_valtype.val.valdat_val = ""; 798 result.ypresponse_u.yp_resp_valtype.val.valdat_len = 0; 799 800 if (argp->yp_reqtype != YPREQ_KEY) { 801 result.ypresponse_u.yp_resp_valtype.stat = YP_BADARGS; 802 return(&result); 803 } 804 805 v2_result = ypproc_match_2_svc(&argp->yprequest_u.yp_req_keytype,rqstp); 806 if (v2_result == NULL) 807 return(NULL); 808 809 bcopy((char *)v2_result, 810 (char *)&result.ypresponse_u.yp_resp_valtype, 811 sizeof(ypresp_val)); 812 813 return (&result); 814} 815 816/* 817 * the 'first' procedure sends a response of type YPRESP_KEY_VAL 818 */ 819ypresponse * 820ypoldproc_first_1_svc(yprequest *argp, struct svc_req *rqstp) 821{ 822 static ypresponse result; 823 ypresp_key_val *v2_result; 824 825 result.yp_resptype = YPRESP_KEY_VAL; 826 result.ypresponse_u.yp_resp_key_valtype.val.valdat_val = 827 result.ypresponse_u.yp_resp_key_valtype.key.keydat_val = ""; 828 result.ypresponse_u.yp_resp_key_valtype.val.valdat_len = 829 result.ypresponse_u.yp_resp_key_valtype.key.keydat_len = 0; 830 831 if (argp->yp_reqtype != YPREQ_NOKEY) { 832 result.ypresponse_u.yp_resp_key_valtype.stat = YP_BADARGS; 833 return(&result); 834 } 835 836 v2_result = ypproc_first_2_svc(&argp->yprequest_u.yp_req_nokeytype, 837 rqstp); 838 if (v2_result == NULL) 839 return(NULL); 840 841 bcopy((char *)v2_result, 842 (char *)&result.ypresponse_u.yp_resp_key_valtype, 843 sizeof(ypresp_key_val)); 844 845 return (&result); 846} 847 848/* 849 * the 'next' procedure sends a response of type YPRESP_KEY_VAL 850 */ 851ypresponse * 852ypoldproc_next_1_svc(yprequest *argp, struct svc_req *rqstp) 853{ 854 static ypresponse result; 855 ypresp_key_val *v2_result; 856 857 result.yp_resptype = YPRESP_KEY_VAL; 858 result.ypresponse_u.yp_resp_key_valtype.val.valdat_val = 859 result.ypresponse_u.yp_resp_key_valtype.key.keydat_val = ""; 860 result.ypresponse_u.yp_resp_key_valtype.val.valdat_len = 861 result.ypresponse_u.yp_resp_key_valtype.key.keydat_len = 0; 862 863 if (argp->yp_reqtype != YPREQ_KEY) { 864 result.ypresponse_u.yp_resp_key_valtype.stat = YP_BADARGS; 865 return(&result); 866 } 867 868 v2_result = ypproc_next_2_svc(&argp->yprequest_u.yp_req_keytype,rqstp); 869 if (v2_result == NULL) 870 return(NULL); 871 872 bcopy((char *)v2_result, 873 (char *)&result.ypresponse_u.yp_resp_key_valtype, 874 sizeof(ypresp_key_val)); 875 876 return (&result); 877} 878 879/* 880 * the 'poll' procedure sends a response of type YPRESP_MAP_PARMS 881 */ 882ypresponse * 883ypoldproc_poll_1_svc(yprequest *argp, struct svc_req *rqstp) 884{ 885 static ypresponse result; 886 ypresp_master *v2_result1; 887 ypresp_order *v2_result2; 888 889 result.yp_resptype = YPRESP_MAP_PARMS; 890 result.ypresponse_u.yp_resp_map_parmstype.domain = 891 argp->yprequest_u.yp_req_nokeytype.domain; 892 result.ypresponse_u.yp_resp_map_parmstype.map = 893 argp->yprequest_u.yp_req_nokeytype.map; 894 /* 895 * Hmm... there is no 'status' value in the 896 * yp_resp_map_parmstype structure, so I have to 897 * guess at what to do to indicate a failure. 898 * I hope this is right. 899 */ 900 result.ypresponse_u.yp_resp_map_parmstype.ordernum = 0; 901 result.ypresponse_u.yp_resp_map_parmstype.peer = ""; 902 903 if (argp->yp_reqtype != YPREQ_MAP_PARMS) { 904 return(&result); 905 } 906 907 v2_result1 = ypproc_master_2_svc(&argp->yprequest_u.yp_req_nokeytype, 908 rqstp); 909 if (v2_result1 == NULL) 910 return(NULL); 911 912 if (v2_result1->stat != YP_TRUE) { 913 return(&result); 914 } 915 916 v2_result2 = ypproc_order_2_svc(&argp->yprequest_u.yp_req_nokeytype, 917 rqstp); 918 if (v2_result2 == NULL) 919 return(NULL); 920 921 if (v2_result2->stat != YP_TRUE) { 922 return(&result); 923 } 924 925 result.ypresponse_u.yp_resp_map_parmstype.peer = 926 v2_result1->peer; 927 result.ypresponse_u.yp_resp_map_parmstype.ordernum = 928 v2_result2->ordernum; 929 930 return (&result); 931} 932 933ypresponse * 934ypoldproc_push_1_svc(yprequest *argp, struct svc_req *rqstp) 935{ 936 static ypresponse result; 937 938 /* 939 * Not implemented. 940 */ 941 942 return (&result); 943} 944 945ypresponse * 946ypoldproc_pull_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 957ypresponse * 958ypoldproc_get_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