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