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