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