yp_server.c revision 28042
1238106Sdes/* 2238106Sdes * Copyright (c) 1995 3238106Sdes * Bill Paul <wpaul@ctr.columbia.edu>. All rights reserved. 4238106Sdes * 5238106Sdes * Redistribution and use in source and binary forms, with or without 6238106Sdes * modification, are permitted provided that the following conditions 7238106Sdes * are met: 8238106Sdes * 1. Redistributions of source code must retain the above copyright 9238106Sdes * notice, this list of conditions and the following disclaimer. 10238106Sdes * 2. Redistributions in binary form must reproduce the above copyright 11238106Sdes * notice, this list of conditions and the following disclaimer in the 12238106Sdes * documentation and/or other materials provided with the distribution. 13238106Sdes * 3. All advertising materials mentioning features or use of this software 14238106Sdes * must display the following acknowledgement: 15238106Sdes * This product includes software developed by Bill Paul. 16238106Sdes * 4. Neither the name of the author nor the names of any co-contributors 17238106Sdes * may be used to endorse or promote products derived from this software 18238106Sdes * without specific prior written permission. 19238106Sdes * 20238106Sdes * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND 21238106Sdes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22238106Sdes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23238106Sdes * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR CONTRIBUTORS BE LIABLE 24269257Sdes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25269257Sdes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26269257Sdes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27269257Sdes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28269257Sdes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29269257Sdes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30269257Sdes * SUCH DAMAGE. 31269257Sdes * 32269257Sdes */ 33269257Sdes 34238106Sdes#include "yp.h" 35238106Sdes#include "yp_extern.h" 36238106Sdes#include <stdlib.h> 37238106Sdes#include <dirent.h> 38238106Sdes#include <sys/stat.h> 39238106Sdes#include <sys/param.h> 40238106Sdes#include <errno.h> 41238106Sdes#include <sys/types.h> 42238106Sdes#include <sys/socket.h> 43238106Sdes#include <netinet/in.h> 44238106Sdes#include <arpa/inet.h> 45238106Sdes#include <rpc/rpc.h> 46238106Sdes 47238106Sdes#ifndef lint 48238106Sdesstatic const char rcsid[] = "$Id: yp_server.c,v 1.22 1997/04/28 14:18:38 wpaul Exp $"; 49238106Sdes#endif /* not lint */ 50238106Sdes 51238106Sdesint forked = 0; 52238106Sdesint children = 0; 53238106Sdes 54238106Sdes#define MASTER_STRING "YP_MASTER_NAME" 55238106Sdes#define MASTER_SZ sizeof(MASTER_STRING) - 1 56238106Sdes#define ORDER_STRING "YP_LAST_MODIFIED" 57238106Sdes#define ORDER_SZ sizeof(ORDER_STRING) - 1 58238106Sdes 59238106Sdes/* 60238106Sdes * NIS v2 support. This is where most of the action happens. 61238106Sdes */ 62238106Sdes 63238106Sdesvoid * 64238106Sdesypproc_null_2_svc(void *argp, struct svc_req *rqstp) 65238106Sdes{ 66238106Sdes static char * result; 67238106Sdes static char rval = 0; 68238106Sdes 69238106Sdes#ifdef DB_CACHE 70238106Sdes if (yp_access(NULL, NULL, (struct svc_req *)rqstp)) 71238106Sdes#else 72238106Sdes if (yp_access(NULL, (struct svc_req *)rqstp)) 73238106Sdes#endif 74238106Sdes return(NULL); 75238106Sdes 76238106Sdes result = &rval; 77238106Sdes 78238106Sdes return((void *) &result); 79238106Sdes} 80238106Sdes 81238106Sdesbool_t * 82238106Sdesypproc_domain_2_svc(domainname *argp, struct svc_req *rqstp) 83238106Sdes{ 84238106Sdes static bool_t result; 85238106Sdes 86238106Sdes#ifdef DB_CACHE 87238106Sdes if (yp_access(NULL, NULL, (struct svc_req *)rqstp)) { 88238106Sdes#else 89238106Sdes if (yp_access(NULL, (struct svc_req *)rqstp)) { 90238106Sdes#endif 91238106Sdes result = FALSE; 92238106Sdes return (&result); 93238106Sdes } 94238106Sdes 95238106Sdes if (argp == NULL || yp_validdomain(*argp)) 96238106Sdes result = FALSE; 97238106Sdes else 98238106Sdes result = TRUE; 99238106Sdes 100238106Sdes return (&result); 101238106Sdes} 102238106Sdes 103238106Sdesbool_t * 104238106Sdesypproc_domain_nonack_2_svc(domainname *argp, struct svc_req *rqstp) 105238106Sdes{ 106238106Sdes static bool_t result; 107238106Sdes 108238106Sdes#ifdef DB_CACHE 109238106Sdes if (yp_access(NULL, NULL, (struct svc_req *)rqstp)) 110238106Sdes#else 111238106Sdes if (yp_access(NULL, (struct svc_req *)rqstp)) 112238106Sdes#endif 113238106Sdes return (NULL); 114238106Sdes 115238106Sdes if (argp == NULL || yp_validdomain(*argp)) 116238106Sdes return (NULL); 117238106Sdes else 118238106Sdes result = TRUE; 119238106Sdes 120238106Sdes return (&result); 121238106Sdes} 122238106Sdes 123238106Sdesypresp_val * 124238106Sdesypproc_match_2_svc(ypreq_key *argp, struct svc_req *rqstp) 125238106Sdes{ 126238106Sdes static ypresp_val result; 127238106Sdes 128238106Sdes result.val.valdat_val = ""; 129238106Sdes result.val.valdat_len = 0; 130238106Sdes 131238106Sdes#ifdef DB_CACHE 132238106Sdes if (yp_access(argp->map, argp->domain, (struct svc_req *)rqstp)) { 133238106Sdes#else 134238106Sdes if (yp_access(argp->map, (struct svc_req *)rqstp)) { 135238106Sdes#endif 136238106Sdes result.stat = YP_YPERR; 137238106Sdes return (&result); 138238106Sdes } 139238106Sdes 140238106Sdes if (argp->domain == NULL || argp->map == NULL) { 141238106Sdes result.stat = YP_BADARGS; 142238106Sdes return (&result); 143238106Sdes } 144238106Sdes 145238106Sdes if (yp_select_map(argp->map, argp->domain, &argp->key, 1) != YP_TRUE) { 146238106Sdes result.stat = yp_errno; 147238106Sdes return(&result); 148238106Sdes } 149238106Sdes 150238106Sdes result.stat = yp_getbykey(&argp->key, &result.val); 151238106Sdes 152238106Sdes /* 153238106Sdes * Do DNS lookups for hosts maps if database lookup failed. 154238106Sdes */ 155238106Sdes 156238106Sdes#ifdef DB_CACHE 157238106Sdes if (result.stat != YP_TRUE && 158238106Sdes (yp_testflag(argp->map, argp->domain, YP_INTERDOMAIN) || 159238106Sdes (strstr(argp->map, "hosts") && do_dns))) { 160238106Sdes#else 161238106Sdes if (do_dns && result.stat != YP_TRUE && strstr(argp->map, "hosts")) { 162238106Sdes#endif 163238106Sdes char nbuf[YPMAXRECORD]; 164238106Sdes 165238106Sdes /* NUL terminate! NUL terminate!! NUL TERMINATE!!! */ 166238106Sdes bcopy(argp->key.keydat_val, nbuf, argp->key.keydat_len); 167238106Sdes nbuf[argp->key.keydat_len] = '\0'; 168238106Sdes 169238106Sdes if (debug) 170238106Sdes yp_error("Doing DNS lookup of %s", nbuf); 171238106Sdes 172238106Sdes if (!strcmp(argp->map, "hosts.byname")) 173238106Sdes result.stat = yp_async_lookup_name(rqstp, nbuf); 174238106Sdes else if (!strcmp(argp->map, "hosts.byaddr")) 175238106Sdes result.stat = yp_async_lookup_addr(rqstp, nbuf); 176238106Sdes 177238106Sdes if (result.stat == YP_TRUE) 178238106Sdes return(NULL); 179238106Sdes } 180238106Sdes 181238106Sdes return (&result); 182238106Sdes} 183238106Sdes 184238106Sdesypresp_key_val * 185238106Sdesypproc_first_2_svc(ypreq_nokey *argp, struct svc_req *rqstp) 186238106Sdes{ 187238106Sdes static ypresp_key_val result; 188238106Sdes 189238106Sdes result.val.valdat_val = result.key.keydat_val = ""; 190238106Sdes result.val.valdat_len = result.key.keydat_len = 0; 191238106Sdes 192238106Sdes#ifdef DB_CACHE 193238106Sdes if (yp_access(argp->map, argp->domain, (struct svc_req *)rqstp)) { 194238106Sdes#else 195238106Sdes if (yp_access(argp->map, (struct svc_req *)rqstp)) { 196238106Sdes#endif 197238106Sdes result.stat = YP_YPERR; 198238106Sdes return (&result); 199238106Sdes } 200238106Sdes 201238106Sdes if (argp->domain == NULL) { 202238106Sdes result.stat = YP_BADARGS; 203238106Sdes return (&result); 204238106Sdes } 205238106Sdes 206238106Sdes if (yp_select_map(argp->map, argp->domain, &result.key, 0) != YP_TRUE) { 207238106Sdes result.stat = yp_errno; 208238106Sdes return(&result); 209238106Sdes } 210238106Sdes 211238106Sdes result.stat = yp_firstbykey(&result.key, &result.val); 212238106Sdes 213238106Sdes return (&result); 214238106Sdes} 215238106Sdes 216238106Sdesypresp_key_val * 217238106Sdesypproc_next_2_svc(ypreq_key *argp, struct svc_req *rqstp) 218238106Sdes{ 219238106Sdes 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