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