yp_server.c revision 19131
1234285Sdim/* 2234285Sdim * Copyright (c) 1995 3234285Sdim * Bill Paul <wpaul@ctr.columbia.edu>. All rights reserved. 4234285Sdim * 5234285Sdim * Redistribution and use in source and binary forms, with or without 6234285Sdim * modification, are permitted provided that the following conditions 7234285Sdim * are met: 8234285Sdim * 1. Redistributions of source code must retain the above copyright 9234285Sdim * notice, this list of conditions and the following disclaimer. 10234285Sdim * 2. Redistributions in binary form must reproduce the above copyright 11234285Sdim * notice, this list of conditions and the following disclaimer in the 12234285Sdim * documentation and/or other materials provided with the distribution. 13234285Sdim * 3. All advertising materials mentioning features or use of this software 14234285Sdim * must display the following acknowledgement: 15234285Sdim * This product includes software developed by Bill Paul. 16234285Sdim * 4. Neither the name of the author nor the names of any co-contributors 17234285Sdim * may be used to endorse or promote products derived from this software 18234285Sdim * without specific prior written permission. 19234285Sdim * 20234285Sdim * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND 21249423Sdim * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22234285Sdim * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23234285Sdim * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR CONTRIBUTORS BE LIABLE 24234285Sdim * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25234285Sdim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26234285Sdim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27234285Sdim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28234285Sdim * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29234285Sdim * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30234285Sdim * SUCH DAMAGE. 31234285Sdim * 32239462Sdim */ 33239462Sdim 34239462Sdim#include "yp_extern.h" 35234285Sdim#include "yp.h" 36234285Sdim#include <stdlib.h> 37234285Sdim#include <dirent.h> 38234285Sdim#include <sys/stat.h> 39234285Sdim#include <sys/param.h> 40234285Sdim#include <errno.h> 41234982Sdim#include <sys/types.h> 42234982Sdim#include <sys/socket.h> 43234982Sdim#include <netinet/in.h> 44234285Sdim#include <arpa/inet.h> 45234285Sdim#include <rpc/rpc.h> 46234285Sdim 47234285Sdim#ifndef lint 48234285Sdimstatic const char rcsid[] = "$Id: yp_server.c,v 1.10 1996/05/31 16:01:51 wpaul Exp $"; 49234285Sdim#endif /* not lint */ 50234285Sdim 51234285Sdimint forked = 0; 52234285Sdimint children = 0; 53234982SdimDB *spec_dbp = NULL; /* Special global DB handle for ypproc_all. */ 54234982Sdimchar *master_string = "YP_MASTER_NAME"; 55234982Sdimchar *order_string = "YP_LAST_MODIFIED"; 56239462Sdim 57239462Sdim/* 58239462Sdim * NIS v2 support. This is where most of the action happens. 59234982Sdim */ 60234982Sdim 61234982Sdimvoid * 62234285Sdimypproc_null_2_svc(void *argp, struct svc_req *rqstp) 63234285Sdim{ 64234285Sdim static char * result; 65234285Sdim static char rval = 0; 66234285Sdim 67234285Sdim if (yp_access(NULL, (struct svc_req *)rqstp)) 68234285Sdim return(NULL); 69234285Sdim 70234285Sdim result = &rval; 71234285Sdim 72234285Sdim return((void *) &result); 73234285Sdim} 74234285Sdim 75234285Sdimbool_t * 76234285Sdimypproc_domain_2_svc(domainname *argp, struct svc_req *rqstp) 77234285Sdim{ 78234285Sdim static bool_t result; 79234285Sdim 80234285Sdim if (yp_access(NULL, (struct svc_req *)rqstp)) { 81234285Sdim result = FALSE; 82234285Sdim return (&result); 83234285Sdim } 84234285Sdim 85234285Sdim if (argp == NULL || yp_validdomain(*argp)) 86234285Sdim result = FALSE; 87249423Sdim else 88249423Sdim result = TRUE; 89249423Sdim 90234285Sdim return (&result); 91234285Sdim} 92234285Sdim 93239462Sdimbool_t * 94239462Sdimypproc_domain_nonack_2_svc(domainname *argp, struct svc_req *rqstp) 95239462Sdim{ 96234285Sdim static bool_t result; 97234285Sdim 98234285Sdim if (yp_access(NULL, (struct svc_req *)rqstp)) 99234285Sdim return (NULL); 100234285Sdim 101234285Sdim if (argp == NULL || yp_validdomain(*argp)) 102234285Sdim return (NULL); 103234285Sdim else 104234285Sdim result = TRUE; 105234285Sdim 106234285Sdim return (&result); 107234285Sdim} 108234285Sdim 109234285Sdimypresp_val * 110234285Sdimypproc_match_2_svc(ypreq_key *argp, struct svc_req *rqstp) 111234285Sdim{ 112234285Sdim static ypresp_val result; 113234285Sdim DBT key, data; 114243830Sdim 115243830Sdim result.val.valdat_val = ""; 116243830Sdim result.val.valdat_len = 0; 117263508Sdim 118243830Sdim if (yp_access(argp->map, (struct svc_req *)rqstp)) { 119243830Sdim result.stat = YP_YPERR; 120251662Sdim return (&result); 121251662Sdim } 122251662Sdim 123251662Sdim if (argp->domain == NULL || argp->map == NULL) { 124251662Sdim result.stat = YP_BADARGS; 125251662Sdim return (&result); 126234285Sdim } 127234285Sdim 128234285Sdim key.size = argp->key.keydat_len; 129234285Sdim key.data = argp->key.keydat_val; 130234285Sdim 131234285Sdim if ((result.stat = yp_get_record(argp->domain, argp->map, 132234285Sdim &key, &data, 1)) == YP_TRUE) { 133234285Sdim result.val.valdat_len = data.size; 134234285Sdim result.val.valdat_val = data.data; 135234285Sdim } 136234285Sdim 137234285Sdim /* 138234285Sdim * Do DNS lookups for hosts maps if database lookup failed. 139234285Sdim */ 140234285Sdim 141 if (do_dns && result.stat != YP_TRUE && strstr(argp->map, "hosts")) { 142 char *rval = NULL; 143 144 /* DNS lookups can take time -- do them in a subprocess */ 145 146 if (!debug && children < MAX_CHILDREN && fork()) { 147 children++; 148 forked = 0; 149 /* 150 * Returning NULL here prevents svc_sendreply() 151 * from being called by the parent. This is vital 152 * since having both the parent and the child process 153 * call it would confuse the client. 154 */ 155 return (NULL); 156 } else { 157 forked++; 158 } 159 160 if (debug) 161 yp_error("Doing DNS lookup of %.*s", 162 argp->key.keydat_len, 163 argp->key.keydat_val); 164 165 /* NUL terminate! NUL terminate!! NUL TERMINATE!!! */ 166 argp->key.keydat_val[argp->key.keydat_len] = '\0'; 167 168 if (!strcmp(argp->map, "hosts.byname")) 169 rval = yp_dnsname((char *)argp->key.keydat_val); 170 else if (!strcmp(argp->map, "hosts.byaddr")) 171 rval = yp_dnsaddr((const char *)argp->key.keydat_val); 172 173 174 if (rval) { 175 if (debug) 176 yp_error("DNS lookup successful. Result: %s", 177 rval); 178 result.val.valdat_len = strlen(rval); 179 result.val.valdat_val = rval; 180 result.stat = YP_TRUE; 181 } else { 182 if (debug) 183 yp_error("DNS lookup failed."); 184 result.stat = YP_NOKEY; 185 } 186 } 187 188 return (&result); 189} 190 191ypresp_key_val * 192ypproc_first_2_svc(ypreq_nokey *argp, struct svc_req *rqstp) 193{ 194 static ypresp_key_val result; 195 DBT key, data; 196 DB *dbp; 197 198 result.val.valdat_val = result.key.keydat_val = ""; 199 result.val.valdat_len = result.key.keydat_len = 0; 200 201 if (yp_access(argp->map, (struct svc_req *)rqstp)) { 202 result.stat = YP_YPERR; 203 return (&result); 204 } 205 206 if (argp->domain == NULL) { 207 result.stat = YP_BADARGS; 208 return (&result); 209 } 210 211#ifdef DB_CACHE 212 if ((dbp = yp_open_db_cache(argp->domain, argp->map, NULL, 0)) == NULL) { 213#else 214 if ((dbp = yp_open_db(argp->domain, argp->map)) == NULL) { 215#endif 216 result.stat = yp_errno; 217 return(&result); 218 } 219 220 key.data = NULL; 221 key.size = 0; 222 223 if ((result.stat = yp_first_record(dbp, &key, &data, 0)) == YP_TRUE) { 224 result.key.keydat_len = key.size; 225 result.key.keydat_val = key.data; 226 result.val.valdat_len = data.size; 227 result.val.valdat_val = data.data; 228 } 229#ifndef DB_CACHE 230 (void)(dbp->close)(dbp); 231#endif 232 return (&result); 233} 234 235ypresp_key_val * 236ypproc_next_2_svc(ypreq_key *argp, struct svc_req *rqstp) 237{ 238 static ypresp_key_val result; 239 DBT key, data; 240 DB *dbp; 241 242 result.val.valdat_val = result.key.keydat_val = ""; 243 result.val.valdat_len = result.key.keydat_len = 0; 244 245 if (yp_access(argp->map, (struct svc_req *)rqstp)) { 246 result.stat = YP_YPERR; 247 return (&result); 248 } 249 250 if (argp->domain == NULL || argp->map == NULL) { 251 result.stat = YP_BADARGS; 252 return (&result); 253 } 254 255#ifdef DB_CACHE 256 if ((dbp = yp_open_db_cache(argp->domain, argp->map, 257 argp->key.keydat_val, 258 argp->key.keydat_len)) == NULL) { 259#else 260 if ((dbp = yp_open_db(argp->domain, argp->map)) == NULL) { 261#endif 262 result.stat = yp_errno; 263 return(&result); 264 } 265 266 key.size = argp->key.keydat_len; 267 key.data = argp->key.keydat_val; 268 269 if ((result.stat = yp_next_record(dbp, &key, &data,0,0)) == YP_TRUE) { 270 result.key.keydat_len = key.size; 271 result.key.keydat_val = key.data; 272 result.val.valdat_len = data.size; 273 result.val.valdat_val = data.data; 274 } 275#ifndef DB_CACHE 276 (void)(dbp->close)(dbp); 277#endif 278 return (&result); 279} 280 281static void ypxfr_callback(rval,addr,transid,prognum,port) 282 ypxfrstat rval; 283 struct sockaddr_in *addr; 284 unsigned int transid; 285 unsigned int prognum; 286 unsigned long port; 287{ 288 CLIENT *clnt; 289 int sock = RPC_ANYSOCK; 290 struct timeval timeout; 291 yppushresp_xfr ypxfr_resp; 292 struct rpc_err err; 293 294 timeout.tv_sec = 5; 295 timeout.tv_usec = 0; 296 addr->sin_port = htons(port); 297 298 if ((clnt = clntudp_create(addr,prognum,1,timeout,&sock)) == NULL) { 299 yp_error("%s: %s", inet_ntoa(addr->sin_addr), 300 clnt_spcreateerror("failed to establish callback handle")); 301 return; 302 } 303 304 ypxfr_resp.status = rval; 305 ypxfr_resp.transid = transid; 306 307 /* Turn the timeout off -- we don't want to block. */ 308 timeout.tv_sec = 0; 309 if (clnt_control(clnt, CLSET_TIMEOUT, (char *)&timeout) == FALSE) 310 yp_error("failed to set timeout on ypproc_xfr callback"); 311 312 if (yppushproc_xfrresp_1(&ypxfr_resp, clnt) == NULL) { 313 clnt_geterr(clnt, &err); 314 if (err.re_status != RPC_SUCCESS && 315 err.re_status != RPC_TIMEDOUT) 316 yp_error("%s", clnt_sperror(clnt, 317 "ypxfr callback failed")); 318 } 319 320 clnt_destroy(clnt); 321 return; 322} 323 324#define YPXFR_RETURN(CODE) \ 325 /* Order is important: send regular RPC reply, then callback */ \ 326 result.xfrstat = CODE; \ 327 svc_sendreply(rqstp->rq_xprt, xdr_ypresp_xfr, (char *)&result); \ 328 ypxfr_callback(CODE,rqhost,argp->transid, \ 329 argp->prog,argp->port); \ 330 return(NULL); 331 332ypresp_xfr * 333ypproc_xfr_2_svc(ypreq_xfr *argp, struct svc_req *rqstp) 334{ 335 static ypresp_xfr result; 336 struct sockaddr_in *rqhost; 337 338 result.transid = argp->transid; 339 rqhost = svc_getcaller(rqstp->rq_xprt); 340 341 if (yp_access(argp->map_parms.map, (struct svc_req *)rqstp)) { 342 YPXFR_RETURN(YPXFR_REFUSED); 343 } 344 345 if (argp->map_parms.domain == NULL) { 346 YPXFR_RETURN(YPXFR_BADARGS); 347 } 348 349 if (yp_validdomain(argp->map_parms.domain)) { 350 YPXFR_RETURN(YPXFR_NODOM); 351 } 352 353 switch(fork()) { 354 case 0: 355 { 356 char g[11], t[11], p[11]; 357 char ypxfr_command[MAXPATHLEN + 2]; 358 359 sprintf (ypxfr_command, "%sypxfr", _PATH_LIBEXEC); 360 sprintf (t, "%u", argp->transid); 361 sprintf (g, "%u", argp->prog); 362 sprintf (p, "%u", argp->port); 363 if (debug) 364 close(0); close(1); close(2); 365 if (strcmp(yp_dir, _PATH_YP)) { 366 execl(ypxfr_command, "ypxfr", 367 "-d", argp->map_parms.domain, 368 "-h", argp->map_parms.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", argp->map_parms.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 if (yp_access(NULL, (struct svc_req *)rqstp)) 409 return (NULL); 410#ifdef DB_CACHE 411 /* clear out the database cache */ 412 yp_flush_all(); 413#endif 414 /* Re-read the securenets database for the hell of it. */ 415 load_securenets(); 416 417 result = &rval; 418 return((void *) &result); 419} 420 421/* 422 * For ypproc_all, we have to send a stream of ypresp_all structures 423 * via TCP, but the XDR filter generated from the yp.x protocol 424 * definition file only serializes one such structure. This means that 425 * to send the whole stream, you need a wrapper which feeds all the 426 * records into the underlying XDR routine until it hits an 'EOF.' 427 * But to use the wrapper, you have to violate the boundaries between 428 * RPC layers by calling svc_sendreply() directly from the ypproc_all 429 * service routine instead of letting the RPC dispatcher do it. 430 * 431 * Bleah. 432 */ 433 434/* 435 * Custom XDR routine for serialzing results of ypproc_all: keep 436 * reading from the database and spew until we run out of records 437 * or encounter an error. 438 */ 439static bool_t 440xdr_my_ypresp_all(register XDR *xdrs, ypresp_all *objp) 441{ 442 DBT key = { NULL, 0 } , data = { NULL, 0 }; 443 444 while (1) { 445 /* Get a record. */ 446 if ((objp->ypresp_all_u.val.stat = 447 yp_next_record(spec_dbp,&key,&data,1,0)) == YP_TRUE) { 448 objp->ypresp_all_u.val.val.valdat_len = data.size; 449 objp->ypresp_all_u.val.val.valdat_val = data.data; 450 objp->ypresp_all_u.val.key.keydat_len = key.size; 451 objp->ypresp_all_u.val.key.keydat_val = key.data; 452 objp->more = TRUE; 453 } else { 454 objp->more = FALSE; 455 } 456 457 /* Serialize. */ 458 if (!xdr_ypresp_all(xdrs, objp)) 459 return(FALSE); 460 if (objp->more == FALSE) 461 return(TRUE); 462 } 463} 464 465ypresp_all * 466ypproc_all_2_svc(ypreq_nokey *argp, struct svc_req *rqstp) 467{ 468 static ypresp_all result; 469 470 /* 471 * Set this here so that the client will be forced to make 472 * at least one attempt to read from us even if all we're 473 * doing is returning an error. 474 */ 475 result.more = TRUE; 476 result.ypresp_all_u.val.key.keydat_len = 0; 477 result.ypresp_all_u.val.key.keydat_val = ""; 478 479 if (yp_access(argp->map, (struct svc_req *)rqstp)) { 480 result.ypresp_all_u.val.stat = YP_YPERR; 481 return (&result); 482 } 483 484 if (argp->domain == NULL || argp->map == NULL) { 485 result.ypresp_all_u.val.stat = YP_BADARGS; 486 return (&result); 487 } 488 489 /* 490 * The ypproc_all procedure can take a while to complete. 491 * Best to handle it in a subprocess so the parent doesn't 492 * block. (Is there a better way to do this? Maybe with 493 * async socket I/O?) 494 */ 495 if (!debug && children < MAX_CHILDREN && fork()) { 496 children++; 497 forked = 0; 498 return (NULL); 499 } else { 500 forked++; 501 } 502 503#ifndef DB_CACHE 504 if ((spec_dbp = yp_open_db(argp->domain, argp->map)) == NULL) { 505 result.ypresp_all_u.val.stat = yp_errno; 506 return(&result); 507 } 508#else 509 if ((spec_dbp = yp_open_db_cache(argp->domain, argp->map, NULL, 0)) == NULL) { 510 result.ypresp_all_u.val.stat = yp_errno; 511 return(&result); 512 } 513#endif 514 515 /* Kick off the actual data transfer. */ 516 svc_sendreply(rqstp->rq_xprt, xdr_my_ypresp_all, (char *)&result); 517 518#ifndef DB_CACHE 519 (void)(spec_dbp->close)(spec_dbp); 520#endif 521 /* 522 * Returning NULL prevents the dispatcher from calling 523 * svc_sendreply() since we already did it. 524 */ 525 return (NULL); 526} 527 528ypresp_master * 529ypproc_master_2_svc(ypreq_nokey *argp, struct svc_req *rqstp) 530{ 531 static ypresp_master result; 532 static char ypvalbuf[YPMAXRECORD]; 533 DBT key, data; 534 535 result.peer = ""; 536 537 if (yp_access(NULL, (struct svc_req *)rqstp)) { 538 result.stat = YP_YPERR; 539 return(&result); 540 } 541 542 if (argp->domain == NULL) { 543 result.stat = YP_BADARGS; 544 return (&result); 545 } 546 547 key.data = master_string; 548 key.size = strlen(master_string); 549 550 /* 551 * Note that we copy the data retrieved from the database to 552 * a private buffer and NUL terminate the buffer rather than 553 * terminating the data in place. We do this because by stuffing 554 * a '\0' into data.data, we will actually be corrupting memory 555 * allocated by the DB package. This is a bad thing now that we 556 * cache DB handles rather than closing the database immediately. 557 */ 558 if ((result.stat = yp_get_record(argp->domain, argp->map, 559 &key, &data, 1)) == YP_TRUE) { 560 bcopy((char *)data.data, (char *)&ypvalbuf, data.size); 561 ypvalbuf[data.size] = '\0'; 562 result.peer = (char *)&ypvalbuf; 563 } else 564 result.peer = ""; 565 566 return (&result); 567} 568 569ypresp_order * 570ypproc_order_2_svc(ypreq_nokey *argp, struct svc_req *rqstp) 571{ 572 static ypresp_order result; 573 DBT key,data; 574 575 result.ordernum = 0; 576 577 if (yp_access(NULL, (struct svc_req *)rqstp)) { 578 result.stat = YP_YPERR; 579 return(&result); 580 } 581 582 if (argp->domain == NULL) { 583 result.stat = YP_BADARGS; 584 return (&result); 585 } 586 587 /* 588 * We could just check the timestamp on the map file, 589 * but that's a hack: we'll only know the last time the file 590 * was touched, not the last time the database contents were 591 * updated. 592 */ 593 594 key.data = order_string; 595 key.size = strlen(order_string); 596 597 if ((result.stat = yp_get_record(argp->domain, argp->map, 598 &key, &data, 1)) == YP_TRUE) 599 result.ordernum = atoi((char *)data.data); 600 else 601 result.ordernum = 0; 602 603 604 return (&result); 605} 606 607static void yp_maplist_free(yp_maplist) 608 struct ypmaplist *yp_maplist; 609{ 610 register struct ypmaplist *next; 611 612 while(yp_maplist) { 613 next = yp_maplist->next; 614 free(yp_maplist->map); 615 free(yp_maplist); 616 yp_maplist = next; 617 } 618 return; 619} 620 621static struct ypmaplist *yp_maplist_create(domain) 622 const char *domain; 623{ 624 char yp_mapdir[MAXPATHLEN + 2]; 625 char yp_mapname[MAXPATHLEN + 2]; 626 struct ypmaplist *cur = NULL; 627 struct ypmaplist *yp_maplist = NULL; 628 DIR *dird; 629 struct dirent *dirp; 630 struct stat statbuf; 631 632 snprintf(yp_mapdir, sizeof(yp_mapdir), "%s/%s", yp_dir, domain); 633 634 if ((dird = opendir(yp_mapdir)) == NULL) { 635 yp_error("opendir(%s) failed: %s", yp_mapdir, strerror(errno)); 636 return(NULL); 637 } 638 639 while ((dirp = readdir(dird)) != NULL) { 640 if (strcmp(dirp->d_name, ".") && strcmp(dirp->d_name, "..")) { 641 snprintf(yp_mapname, sizeof(yp_mapname), "%s/%s", 642 yp_mapdir,dirp->d_name); 643 if (stat(yp_mapname, &statbuf) < 0 || 644 !S_ISREG(statbuf.st_mode)) 645 continue; 646 if ((cur = (struct ypmaplist *) 647 malloc(sizeof(struct ypmaplist))) == NULL) { 648 yp_error("malloc() failed: %s",strerror(errno)); 649 closedir(dird); 650 yp_maplist_free(yp_maplist); 651 return(NULL); 652 } 653 if ((cur->map = (char *)strdup(dirp->d_name)) == NULL) { 654 yp_error("strdup() failed: %s",strerror(errno)); 655 closedir(dird); 656 yp_maplist_free(yp_maplist); 657 return(NULL); 658 } 659 cur->next = yp_maplist; 660 yp_maplist = cur; 661 if (debug) 662 yp_error("map: %s", yp_maplist->map); 663 } 664 665 } 666 closedir(dird); 667 return(yp_maplist); 668} 669 670ypresp_maplist * 671ypproc_maplist_2_svc(domainname *argp, struct svc_req *rqstp) 672{ 673 static ypresp_maplist result = { 0, NULL }; 674 675 if (yp_access(NULL, (struct svc_req *)rqstp)) { 676 result.stat = YP_YPERR; 677 return(&result); 678 } 679 680 if (argp == NULL) { 681 result.stat = YP_BADARGS; 682 return (&result); 683 } 684 685 if (yp_validdomain(*argp)) { 686 result.stat = YP_NODOM; 687 return (&result); 688 } 689 690 /* 691 * We have to construct a linked list for the ypproc_maplist 692 * procedure using dynamically allocated memory. Since the XDR 693 * layer won't free this list for us, we have to deal with it 694 * ourselves. We call yp_maplist_free() first to free any 695 * previously allocated data we may have accumulated to insure 696 * that we have only one linked list in memory at any given 697 * time. 698 */ 699 700 yp_maplist_free(result.maps); 701 702 if ((result.maps = yp_maplist_create(*argp)) == NULL) { 703 yp_error("yp_maplist_create failed"); 704 result.stat = YP_YPERR; 705 return(&result); 706 } else 707 result.stat = YP_TRUE; 708 709 return (&result); 710} 711 712/* 713 * NIS v1 support. The nullproc, domain and domain_nonack 714 * functions from v1 are identical to those in v2, so all 715 * we have to do is hand off to them. 716 * 717 * The other functions are mostly just wrappers around their v2 718 * counterparts. For example, for the v1 'match' procedure, we 719 * crack open the argument structure, make a request to the v2 720 * 'match' function, repackage the data into a v1 response and 721 * then send it on its way. 722 * 723 * Note that we don't support the pull, push and get procedures. 724 * There's little documentation available to show what they 725 * do, and I suspect they're meant largely for map transfers 726 * between master and slave servers. 727 */ 728 729void * 730ypoldproc_null_1_svc(void *argp, struct svc_req *rqstp) 731{ 732 return(ypproc_null_2_svc(argp, rqstp)); 733} 734 735bool_t * 736ypoldproc_domain_1_svc(domainname *argp, struct svc_req *rqstp) 737{ 738 return(ypproc_domain_2_svc(argp, rqstp)); 739} 740 741bool_t * 742ypoldproc_domain_nonack_1_svc(domainname *argp, struct svc_req *rqstp) 743{ 744 return (ypproc_domain_nonack_2_svc(argp, rqstp)); 745} 746 747/* 748 * the 'match' procedure sends a response of type YPRESP_VAL 749 */ 750ypresponse * 751ypoldproc_match_1_svc(yprequest *argp, struct svc_req *rqstp) 752{ 753 static ypresponse result; 754 ypresp_val *v2_result; 755 756 result.yp_resptype = YPRESP_VAL; 757 result.ypresponse_u.yp_resp_valtype.val.valdat_val = ""; 758 result.ypresponse_u.yp_resp_valtype.val.valdat_len = 0; 759 760 if (argp->yp_reqtype != YPREQ_KEY) { 761 result.ypresponse_u.yp_resp_valtype.stat = YP_BADARGS; 762 return(&result); 763 } 764 765 v2_result = ypproc_match_2_svc(&argp->yprequest_u.yp_req_keytype,rqstp); 766 if (v2_result == NULL) 767 return(NULL); 768 769 bcopy((char *)v2_result, 770 (char *)&result.ypresponse_u.yp_resp_valtype, 771 sizeof(ypresp_val)); 772 773 return (&result); 774} 775 776/* 777 * the 'first' procedure sends a response of type YPRESP_KEY_VAL 778 */ 779ypresponse * 780ypoldproc_first_1_svc(yprequest *argp, struct svc_req *rqstp) 781{ 782 static ypresponse result; 783 ypresp_key_val *v2_result; 784 785 result.yp_resptype = YPRESP_KEY_VAL; 786 result.ypresponse_u.yp_resp_key_valtype.val.valdat_val = 787 result.ypresponse_u.yp_resp_key_valtype.key.keydat_val = ""; 788 result.ypresponse_u.yp_resp_key_valtype.val.valdat_len = 789 result.ypresponse_u.yp_resp_key_valtype.key.keydat_len = 0; 790 791 if (argp->yp_reqtype != YPREQ_NOKEY) { 792 result.ypresponse_u.yp_resp_key_valtype.stat = YP_BADARGS; 793 return(&result); 794 } 795 796 v2_result = ypproc_first_2_svc(&argp->yprequest_u.yp_req_nokeytype, 797 rqstp); 798 if (v2_result == NULL) 799 return(NULL); 800 801 bcopy((char *)v2_result, 802 (char *)&result.ypresponse_u.yp_resp_key_valtype, 803 sizeof(ypresp_key_val)); 804 805 return (&result); 806} 807 808/* 809 * the 'next' procedure sends a response of type YPRESP_KEY_VAL 810 */ 811ypresponse * 812ypoldproc_next_1_svc(yprequest *argp, struct svc_req *rqstp) 813{ 814 static ypresponse result; 815 ypresp_key_val *v2_result; 816 817 result.yp_resptype = YPRESP_KEY_VAL; 818 result.ypresponse_u.yp_resp_key_valtype.val.valdat_val = 819 result.ypresponse_u.yp_resp_key_valtype.key.keydat_val = ""; 820 result.ypresponse_u.yp_resp_key_valtype.val.valdat_len = 821 result.ypresponse_u.yp_resp_key_valtype.key.keydat_len = 0; 822 823 if (argp->yp_reqtype != YPREQ_KEY) { 824 result.ypresponse_u.yp_resp_key_valtype.stat = YP_BADARGS; 825 return(&result); 826 } 827 828 v2_result = ypproc_next_2_svc(&argp->yprequest_u.yp_req_keytype,rqstp); 829 if (v2_result == NULL) 830 return(NULL); 831 832 bcopy((char *)v2_result, 833 (char *)&result.ypresponse_u.yp_resp_key_valtype, 834 sizeof(ypresp_key_val)); 835 836 return (&result); 837} 838 839/* 840 * the 'poll' procedure sends a response of type YPRESP_MAP_PARMS 841 */ 842ypresponse * 843ypoldproc_poll_1_svc(yprequest *argp, struct svc_req *rqstp) 844{ 845 static ypresponse result; 846 ypresp_master *v2_result1; 847 ypresp_order *v2_result2; 848 849 result.yp_resptype = YPRESP_MAP_PARMS; 850 result.ypresponse_u.yp_resp_map_parmstype.domain = 851 argp->yprequest_u.yp_req_nokeytype.domain; 852 result.ypresponse_u.yp_resp_map_parmstype.map = 853 argp->yprequest_u.yp_req_nokeytype.map; 854 /* 855 * Hmm... there is no 'status' value in the 856 * yp_resp_map_parmstype structure, so I have to 857 * guess at what to do to indicate a failure. 858 * I hope this is right. 859 */ 860 result.ypresponse_u.yp_resp_map_parmstype.ordernum = 0; 861 result.ypresponse_u.yp_resp_map_parmstype.peer = ""; 862 863 if (argp->yp_reqtype != YPREQ_MAP_PARMS) { 864 return(&result); 865 } 866 867 v2_result1 = ypproc_master_2_svc(&argp->yprequest_u.yp_req_nokeytype, 868 rqstp); 869 if (v2_result1 == NULL) 870 return(NULL); 871 872 if (v2_result1->stat != YP_TRUE) { 873 return(&result); 874 } 875 876 v2_result2 = ypproc_order_2_svc(&argp->yprequest_u.yp_req_nokeytype, 877 rqstp); 878 if (v2_result2 == NULL) 879 return(NULL); 880 881 if (v2_result2->stat != YP_TRUE) { 882 return(&result); 883 } 884 885 result.ypresponse_u.yp_resp_map_parmstype.peer = 886 v2_result1->peer; 887 result.ypresponse_u.yp_resp_map_parmstype.ordernum = 888 v2_result2->ordernum; 889 890 return (&result); 891} 892 893ypresponse * 894ypoldproc_push_1_svc(yprequest *argp, struct svc_req *rqstp) 895{ 896 static ypresponse result; 897 898 /* 899 * Not implemented. 900 */ 901 902 return (&result); 903} 904 905ypresponse * 906ypoldproc_pull_1_svc(yprequest *argp, struct svc_req *rqstp) 907{ 908 static ypresponse result; 909 910 /* 911 * Not implemented. 912 */ 913 914 return (&result); 915} 916 917ypresponse * 918ypoldproc_get_1_svc(yprequest *argp, struct svc_req *rqstp) 919{ 920 static ypresponse result; 921 922 /* 923 * Not implemented. 924 */ 925 926 return (&result); 927} 928