yp_server.c revision 90298
1251881Speter/* 2251881Speter * Copyright (c) 1995 3251881Speter * Bill Paul <wpaul@ctr.columbia.edu>. All rights reserved. 4251881Speter * 5251881Speter * Redistribution and use in source and binary forms, with or without 6251881Speter * modification, are permitted provided that the following conditions 7251881Speter * are met: 8251881Speter * 1. Redistributions of source code must retain the above copyright 9251881Speter * notice, this list of conditions and the following disclaimer. 10251881Speter * 2. Redistributions in binary form must reproduce the above copyright 11251881Speter * notice, this list of conditions and the following disclaimer in the 12251881Speter * documentation and/or other materials provided with the distribution. 13251881Speter * 3. All advertising materials mentioning features or use of this software 14251881Speter * must display the following acknowledgement: 15251881Speter * This product includes software developed by Bill Paul. 16251881Speter * 4. Neither the name of the author nor the names of any co-contributors 17251881Speter * may be used to endorse or promote products derived from this software 18251881Speter * without specific prior written permission. 19251881Speter * 20251881Speter * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND 21251881Speter * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22251881Speter * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23251881Speter * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR CONTRIBUTORS BE LIABLE 24251881Speter * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25251881Speter * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26251881Speter * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27251881Speter * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28251881Speter * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29251881Speter * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30251881Speter * SUCH DAMAGE. 31251881Speter * 32251881Speter */ 33251881Speter 34251881Speter#ifndef lint 35251881Speterstatic const char rcsid[] = 36251881Speter "$FreeBSD: head/usr.sbin/ypserv/yp_server.c 90298 2002-02-06 15:26:07Z des $"; 37251881Speter#endif /* not lint */ 38251881Speter 39251881Speter#include "yp.h" 40251881Speter#include "yp_extern.h" 41251881Speter#include <dirent.h> 42251881Speter#include <errno.h> 43251881Speter#include <stdlib.h> 44251881Speter#include <sys/stat.h> 45251881Speter#include <sys/param.h> 46251881Speter#include <sys/types.h> 47251881Speter#include <sys/socket.h> 48251881Speter#include <netinet/in.h> 49251881Speter#include <arpa/inet.h> 50251881Speter#include <rpc/rpc.h> 51251881Speter 52251881Speterint children = 0; 53251881Speter 54251881Speter#define MASTER_STRING "YP_MASTER_NAME" 55251881Speter#define MASTER_SZ sizeof(MASTER_STRING) - 1 56251881Speter#define ORDER_STRING "YP_LAST_MODIFIED" 57251881Speter#define ORDER_SZ sizeof(ORDER_STRING) - 1 58251881Speter 59251881Speterstatic pid_t 60251881Speteryp_fork(void) 61251881Speter{ 62251881Speter if (yp_pid != getpid()) { 63251881Speter yp_error("child %d trying to fork!", getpid()); 64251881Speter errno = EEXIST; 65251881Speter return(-1); 66251881Speter } 67251881Speter 68251881Speter return(fork()); 69251881Speter} 70251881Speter 71251881Speter/* 72251881Speter * NIS v2 support. This is where most of the action happens. 73251881Speter */ 74251881Speter 75251881Spetervoid * 76251881Speterypproc_null_2_svc(void *argp, struct svc_req *rqstp) 77251881Speter{ 78251881Speter static char * result; 79251881Speter static char rval = 0; 80251881Speter 81251881Speter#ifdef DB_CACHE 82251881Speter if (yp_access(NULL, NULL, (struct svc_req *)rqstp)) 83251881Speter#else 84251881Speter if (yp_access(NULL, (struct svc_req *)rqstp)) 85251881Speter#endif 86251881Speter return(NULL); 87251881Speter 88251881Speter result = &rval; 89251881Speter 90251881Speter return((void *) &result); 91251881Speter} 92251881Speter 93251881Speterbool_t * 94251881Speterypproc_domain_2_svc(domainname *argp, struct svc_req *rqstp) 95251881Speter{ 96251881Speter static bool_t result; 97251881Speter 98251881Speter#ifdef DB_CACHE 99251881Speter if (yp_access(NULL, NULL, (struct svc_req *)rqstp)) { 100251881Speter#else 101251881Speter if (yp_access(NULL, (struct svc_req *)rqstp)) { 102251881Speter#endif 103251881Speter result = FALSE; 104251881Speter return (&result); 105251881Speter } 106251881Speter 107251881Speter if (argp == NULL || yp_validdomain(*argp)) 108251881Speter result = FALSE; 109251881Speter else 110251881Speter result = TRUE; 111251881Speter 112251881Speter return (&result); 113251881Speter} 114251881Speter 115251881Speterbool_t * 116251881Speterypproc_domain_nonack_2_svc(domainname *argp, struct svc_req *rqstp) 117251881Speter{ 118251881Speter static bool_t result; 119251881Speter 120251881Speter#ifdef DB_CACHE 121251881Speter if (yp_access(NULL, NULL, (struct svc_req *)rqstp)) 122251881Speter#else 123251881Speter if (yp_access(NULL, (struct svc_req *)rqstp)) 124251881Speter#endif 125251881Speter return (NULL); 126251881Speter 127251881Speter if (argp == NULL || yp_validdomain(*argp)) 128251881Speter return (NULL); 129251881Speter else 130251881Speter result = TRUE; 131251881Speter 132251881Speter return (&result); 133251881Speter} 134251881Speter 135251881Speterypresp_val * 136251881Speterypproc_match_2_svc(ypreq_key *argp, struct svc_req *rqstp) 137251881Speter{ 138251881Speter static ypresp_val result; 139251881Speter 140251881Speter result.val.valdat_val = ""; 141251881Speter result.val.valdat_len = 0; 142251881Speter 143251881Speter#ifdef DB_CACHE 144251881Speter if (yp_access(argp->map, argp->domain, (struct svc_req *)rqstp)) { 145251881Speter#else 146251881Speter if (yp_access(argp->map, (struct svc_req *)rqstp)) { 147251881Speter#endif 148251881Speter result.stat = YP_YPERR; 149251881Speter return (&result); 150251881Speter } 151251881Speter 152251881Speter if (argp->domain == NULL || argp->map == NULL) { 153251881Speter result.stat = YP_BADARGS; 154251881Speter return (&result); 155251881Speter } 156251881Speter 157251881Speter if (yp_select_map(argp->map, argp->domain, NULL, 1) != YP_TRUE) { 158251881Speter result.stat = yp_errno; 159251881Speter return(&result); 160251881Speter } 161251881Speter 162251881Speter result.stat = yp_getbykey(&argp->key, &result.val); 163251881Speter 164251881Speter /* 165251881Speter * Do DNS lookups for hosts maps if database lookup failed. 166251881Speter */ 167251881Speter 168251881Speter#ifdef DB_CACHE 169251881Speter if (result.stat != YP_TRUE && 170251881Speter (yp_testflag(argp->map, argp->domain, YP_INTERDOMAIN) || 171251881Speter (strstr(argp->map, "hosts") && do_dns))) { 172251881Speter#else 173251881Speter if (do_dns && result.stat != YP_TRUE && strstr(argp->map, "hosts")) { 174251881Speter#endif 175251881Speter char nbuf[YPMAXRECORD]; 176251881Speter 177251881Speter /* NUL terminate! NUL terminate!! NUL TERMINATE!!! */ 178251881Speter bcopy(argp->key.keydat_val, nbuf, argp->key.keydat_len); 179251881Speter nbuf[argp->key.keydat_len] = '\0'; 180251881Speter 181251881Speter if (debug) 182251881Speter yp_error("doing DNS lookup of %s", nbuf); 183251881Speter 184251881Speter if (!strcmp(argp->map, "hosts.byname")) 185251881Speter result.stat = yp_async_lookup_name(rqstp, nbuf); 186251881Speter else if (!strcmp(argp->map, "hosts.byaddr")) 187251881Speter result.stat = yp_async_lookup_addr(rqstp, nbuf); 188251881Speter 189251881Speter if (result.stat == YP_TRUE) 190251881Speter return(NULL); 191251881Speter } 192251881Speter 193251881Speter return (&result); 194251881Speter} 195251881Speter 196251881Speterypresp_key_val * 197251881Speterypproc_first_2_svc(ypreq_nokey *argp, struct svc_req *rqstp) 198251881Speter{ 199251881Speter static ypresp_key_val result; 200251881Speter 201251881Speter result.val.valdat_val = result.key.keydat_val = ""; 202251881Speter result.val.valdat_len = result.key.keydat_len = 0; 203251881Speter 204251881Speter#ifdef DB_CACHE 205251881Speter if (yp_access(argp->map, argp->domain, (struct svc_req *)rqstp)) { 206251881Speter#else 207251881Speter if (yp_access(argp->map, (struct svc_req *)rqstp)) { 208251881Speter#endif 209251881Speter result.stat = YP_YPERR; 210251881Speter return (&result); 211251881Speter } 212251881Speter 213251881Speter if (argp->domain == NULL) { 214251881Speter result.stat = YP_BADARGS; 215251881Speter return (&result); 216251881Speter } 217251881Speter 218251881Speter if (yp_select_map(argp->map, argp->domain, NULL, 0) != YP_TRUE) { 219251881Speter result.stat = yp_errno; 220251881Speter return(&result); 221251881Speter } 222251881Speter 223251881Speter result.stat = yp_firstbykey(&result.key, &result.val); 224251881Speter 225251881Speter return (&result); 226251881Speter} 227251881Speter 228251881Speterypresp_key_val * 229251881Speterypproc_next_2_svc(ypreq_key *argp, struct svc_req *rqstp) 230251881Speter{ 231251881Speter static ypresp_key_val result; 232251881Speter 233251881Speter result.val.valdat_val = result.key.keydat_val = ""; 234251881Speter result.val.valdat_len = result.key.keydat_len = 0; 235251881Speter 236251881Speter#ifdef DB_CACHE 237251881Speter if (yp_access(argp->map, argp->domain, (struct svc_req *)rqstp)) { 238251881Speter#else 239251881Speter if (yp_access(argp->map, (struct svc_req *)rqstp)) { 240251881Speter#endif 241251881Speter result.stat = YP_YPERR; 242251881Speter return (&result); 243251881Speter } 244251881Speter 245251881Speter if (argp->domain == NULL || argp->map == NULL) { 246251881Speter result.stat = YP_BADARGS; 247251881Speter return (&result); 248251881Speter } 249251881Speter 250251881Speter if (yp_select_map(argp->map, argp->domain, &argp->key, 0) != YP_TRUE) { 251251881Speter result.stat = yp_errno; 252251881Speter return(&result); 253251881Speter } 254251881Speter 255251881Speter result.key.keydat_len = argp->key.keydat_len; 256251881Speter result.key.keydat_val = argp->key.keydat_val; 257251881Speter 258251881Speter result.stat = yp_nextbykey(&result.key, &result.val); 259251881Speter 260251881Speter return (&result); 261251881Speter} 262251881Speter 263251881Speterstatic void 264251881Speterypxfr_callback(ypxfrstat rval, struct sockaddr_in *addr, unsigned int transid, 265251881Speter unsigned int prognum, unsigned long port) 266251881Speter{ 267251881Speter CLIENT *clnt; 268251881Speter int sock = RPC_ANYSOCK; 269251881Speter struct timeval timeout; 270251881Speter yppushresp_xfr ypxfr_resp; 271251881Speter struct rpc_err err; 272251881Speter 273251881Speter timeout.tv_sec = 5; 274251881Speter timeout.tv_usec = 0; 275251881Speter addr->sin_port = htons(port); 276251881Speter 277251881Speter if ((clnt = clntudp_create(addr,prognum,1,timeout,&sock)) == NULL) { 278251881Speter yp_error("%s: %s", inet_ntoa(addr->sin_addr), 279251881Speter clnt_spcreateerror("failed to establish callback handle")); 280251881Speter return; 281251881Speter } 282251881Speter 283251881Speter ypxfr_resp.status = rval; 284251881Speter ypxfr_resp.transid = transid; 285251881Speter 286251881Speter /* Turn the timeout off -- we don't want to block. */ 287251881Speter timeout.tv_sec = 0; 288251881Speter if (clnt_control(clnt, CLSET_TIMEOUT, (char *)&timeout) == FALSE) 289251881Speter yp_error("failed to set timeout on ypproc_xfr callback"); 290251881Speter 291251881Speter if (yppushproc_xfrresp_1(&ypxfr_resp, clnt) == NULL) { 292251881Speter clnt_geterr(clnt, &err); 293251881Speter if (err.re_status != RPC_SUCCESS && 294251881Speter err.re_status != RPC_TIMEDOUT) 295251881Speter yp_error("%s", clnt_sperror(clnt, 296251881Speter "ypxfr callback failed")); 297251881Speter } 298251881Speter 299251881Speter clnt_destroy(clnt); 300251881Speter return; 301251881Speter} 302251881Speter 303251881Speter#define YPXFR_RETURN(CODE) \ 304251881Speter /* Order is important: send regular RPC reply, then callback */ \ 305251881Speter result.xfrstat = CODE; \ 306251881Speter svc_sendreply(rqstp->rq_xprt, xdr_ypresp_xfr, (char *)&result); \ 307251881Speter ypxfr_callback(CODE,rqhost,argp->transid, \ 308251881Speter argp->prog,argp->port); \ 309251881Speter return(NULL); 310251881Speter 311251881Speterypresp_xfr * 312251881Speterypproc_xfr_2_svc(ypreq_xfr *argp, struct svc_req *rqstp) 313251881Speter{ 314251881Speter static ypresp_xfr result; 315251881Speter struct sockaddr_in *rqhost; 316251881Speter ypresp_master *mres; 317251881Speter ypreq_nokey mreq; 318251881Speter 319251881Speter result.transid = argp->transid; 320251881Speter rqhost = svc_getcaller(rqstp->rq_xprt); 321251881Speter 322251881Speter#ifdef DB_CACHE 323251881Speter if (yp_access(argp->map_parms.map, 324251881Speter argp->map_parms.domain, (struct svc_req *)rqstp)) { 325251881Speter#else 326251881Speter if (yp_access(argp->map_parms.map, (struct svc_req *)rqstp)) { 327251881Speter#endif 328251881Speter YPXFR_RETURN(YPXFR_REFUSED) 329251881Speter } 330251881Speter 331251881Speter 332251881Speter if (argp->map_parms.domain == NULL) { 333251881Speter YPXFR_RETURN(YPXFR_BADARGS) 334251881Speter } 335251881Speter 336251881Speter if (yp_validdomain(argp->map_parms.domain)) { 337251881Speter YPXFR_RETURN(YPXFR_NODOM) 338251881Speter } 339251881Speter 340251881Speter /* 341251881Speter * Determine the master host ourselves. The caller may 342251881Speter * be up to no good. This has the side effect of verifying 343251881Speter * that the requested map and domain actually exist. 344251881Speter */ 345251881Speter 346251881Speter mreq.domain = argp->map_parms.domain; 347251881Speter mreq.map = argp->map_parms.map; 348251881Speter 349251881Speter mres = ypproc_master_2_svc(&mreq, rqstp); 350251881Speter 351251881Speter if (mres->stat != YP_TRUE) { 352251881Speter yp_error("couldn't find master for map %s@%s", 353251881Speter argp->map_parms.map, 354251881Speter argp->map_parms.domain); 355251881Speter yp_error("host at %s (%s) may be pulling my leg", 356251881Speter argp->map_parms.peer, 357251881Speter inet_ntoa(rqhost->sin_addr)); 358251881Speter YPXFR_RETURN(YPXFR_REFUSED) 359251881Speter } 360251881Speter 361251881Speter switch (yp_fork()) { 362251881Speter case 0: 363251881Speter { 364251881Speter char g[11], t[11], p[11]; 365251881Speter char ypxfr_command[MAXPATHLEN + 2]; 366251881Speter 367251881Speter snprintf (ypxfr_command, sizeof(ypxfr_command), "%sypxfr", _PATH_LIBEXEC); 368251881Speter snprintf (t, sizeof(t), "%u", argp->transid); 369251881Speter snprintf (g, sizeof(g), "%u", argp->prog); 370251881Speter snprintf (p, sizeof(p), "%u", argp->port); 371251881Speter if (debug) { 372251881Speter close(0); close(1); close(2); 373251881Speter } 374251881Speter if (strcmp(yp_dir, _PATH_YP)) { 375251881Speter execl(ypxfr_command, "ypxfr", 376251881Speter "-d", argp->map_parms.domain, 377251881Speter "-h", mres->peer, 378251881Speter "-p", yp_dir, "-C", t, 379251881Speter g, inet_ntoa(rqhost->sin_addr), 380251881Speter p, argp->map_parms.map, 381251881Speter (char *)NULL); 382251881Speter } else { 383251881Speter execl(ypxfr_command, "ypxfr", 384251881Speter "-d", argp->map_parms.domain, 385251881Speter "-h", mres->peer, 386251881Speter "-C", t, 387251881Speter g, inet_ntoa(rqhost->sin_addr), 388251881Speter p, argp->map_parms.map, 389251881Speter (char *)NULL); 390251881Speter } 391251881Speter yp_error("ypxfr execl(%s): %s", ypxfr_command, strerror(errno)); 392251881Speter YPXFR_RETURN(YPXFR_XFRERR) 393251881Speter /* 394251881Speter * Just to safe, prevent PR #10970 from biting us in 395251881Speter * the unlikely case that execing ypxfr fails. We don't 396251881Speter * want to have any child processes spawned from this 397251881Speter * child process. 398251881Speter */ 399251881Speter _exit(0); 400251881Speter break; 401251881Speter } 402251881Speter case -1: 403251881Speter yp_error("ypxfr fork(): %s", strerror(errno)); 404251881Speter YPXFR_RETURN(YPXFR_XFRERR) 405251881Speter break; 406251881Speter default: 407251881Speter result.xfrstat = YPXFR_SUCC; 408251881Speter children++; 409251881Speter break; 410251881Speter } 411251881Speter 412251881Speter return (&result); 413251881Speter} 414251881Speter#undef YPXFR_RETURN 415251881Speter 416251881Spetervoid * 417251881Speterypproc_clear_2_svc(void *argp, struct svc_req *rqstp) 418251881Speter{ 419251881Speter static char * result; 420251881Speter static char rval = 0; 421251881Speter 422251881Speter#ifdef DB_CACHE 423251881Speter if (yp_access(NULL, NULL, (struct svc_req *)rqstp)) 424251881Speter#else 425251881Speter if (yp_access(NULL, (struct svc_req *)rqstp)) 426251881Speter#endif 427251881Speter return (NULL); 428251881Speter#ifdef DB_CACHE 429251881Speter /* clear out the database cache */ 430251881Speter yp_flush_all(); 431#endif 432 /* Re-read the securenets database for the hell of it. */ 433 load_securenets(); 434 435 result = &rval; 436 return((void *) &result); 437} 438 439/* 440 * For ypproc_all, we have to send a stream of ypresp_all structures 441 * via TCP, but the XDR filter generated from the yp.x protocol 442 * definition file only serializes one such structure. This means that 443 * to send the whole stream, you need a wrapper which feeds all the 444 * records into the underlying XDR routine until it hits an 'EOF.' 445 * But to use the wrapper, you have to violate the boundaries between 446 * RPC layers by calling svc_sendreply() directly from the ypproc_all 447 * service routine instead of letting the RPC dispatcher do it. 448 * 449 * Bleah. 450 */ 451 452/* 453 * Custom XDR routine for serialzing results of ypproc_all: keep 454 * reading from the database and spew until we run out of records 455 * or encounter an error. 456 */ 457static bool_t 458xdr_my_ypresp_all(register XDR *xdrs, ypresp_all *objp) 459{ 460 while (1) { 461 /* Get a record. */ 462 if ((objp->ypresp_all_u.val.stat = 463 yp_nextbykey(&objp->ypresp_all_u.val.key, 464 &objp->ypresp_all_u.val.val)) == YP_TRUE) { 465 objp->more = TRUE; 466 } else { 467 objp->more = FALSE; 468 } 469 470 /* Serialize. */ 471 if (!xdr_ypresp_all(xdrs, objp)) 472 return(FALSE); 473 if (objp->more == FALSE) 474 return(TRUE); 475 } 476} 477 478ypresp_all * 479ypproc_all_2_svc(ypreq_nokey *argp, struct svc_req *rqstp) 480{ 481 static ypresp_all result; 482 483 /* 484 * Set this here so that the client will be forced to make 485 * at least one attempt to read from us even if all we're 486 * doing is returning an error. 487 */ 488 result.more = TRUE; 489 result.ypresp_all_u.val.key.keydat_len = 0; 490 result.ypresp_all_u.val.key.keydat_val = ""; 491 492#ifdef DB_CACHE 493 if (yp_access(argp->map, argp->domain, (struct svc_req *)rqstp)) { 494#else 495 if (yp_access(argp->map, (struct svc_req *)rqstp)) { 496#endif 497 result.ypresp_all_u.val.stat = YP_YPERR; 498 return (&result); 499 } 500 501 if (argp->domain == NULL || argp->map == NULL) { 502 result.ypresp_all_u.val.stat = YP_BADARGS; 503 return (&result); 504 } 505 506 /* 507 * XXX If we hit the child limit, fail the request. 508 * If we don't, and the map is large, we could block for 509 * a long time in the parent. 510 */ 511 if (children >= MAX_CHILDREN) { 512 result.ypresp_all_u.val.stat = YP_YPERR; 513 return(&result); 514 } 515 516 /* 517 * The ypproc_all procedure can take a while to complete. 518 * Best to handle it in a subprocess so the parent doesn't 519 * block. (Is there a better way to do this? Maybe with 520 * async socket I/O?) 521 */ 522 if (!debug) { 523 switch (yp_fork()) { 524 case 0: 525 break; 526 case -1: 527 yp_error("ypall fork(): %s", strerror(errno)); 528 result.ypresp_all_u.val.stat = YP_YPERR; 529 return(&result); 530 break; 531 default: 532 children++; 533 return (NULL); 534 break; 535 } 536 } 537 538 /* 539 * Fix for PR #10971: don't let the child ypserv share 540 * DB handles with the parent process. 541 */ 542#ifdef DB_CACHE 543 yp_flush_all(); 544#endif 545 546 if (yp_select_map(argp->map, argp->domain, 547 &result.ypresp_all_u.val.key, 0) != YP_TRUE) { 548 result.ypresp_all_u.val.stat = yp_errno; 549 return(&result); 550 } 551 552 /* Kick off the actual data transfer. */ 553 svc_sendreply(rqstp->rq_xprt, xdr_my_ypresp_all, (char *)&result); 554 555 /* 556 * Proper fix for PR #10970: exit here so that we don't risk 557 * having a child spawned from this sub-process. 558 */ 559 _exit(0); 560} 561 562ypresp_master * 563ypproc_master_2_svc(ypreq_nokey *argp, struct svc_req *rqstp) 564{ 565 static ypresp_master result; 566 static char ypvalbuf[YPMAXRECORD]; 567 keydat key = { MASTER_SZ, MASTER_STRING }; 568 valdat val; 569 570 result.peer = ""; 571 572#ifdef DB_CACHE 573 if (yp_access(argp->map, argp->domain, (struct svc_req *)rqstp)) { 574#else 575 if (yp_access(argp->map, (struct svc_req *)rqstp)) { 576#endif 577 result.stat = YP_YPERR; 578 return(&result); 579 } 580 581 if (argp->domain == NULL) { 582 result.stat = YP_BADARGS; 583 return (&result); 584 } 585 586 if (yp_select_map(argp->map, argp->domain, &key, 1) != YP_TRUE) { 587 result.stat = yp_errno; 588 return(&result); 589 } 590 591 /* 592 * Note that we copy the data retrieved from the database to 593 * a private buffer and NUL terminate the buffer rather than 594 * terminating the data in place. We do this because by stuffing 595 * a '\0' into data.data, we will actually be corrupting memory 596 * allocated by the DB package. This is a bad thing now that we 597 * cache DB handles rather than closing the database immediately. 598 */ 599 result.stat = yp_getbykey(&key, &val); 600 if (result.stat == YP_TRUE) { 601 bcopy((char *)val.valdat_val, (char *)&ypvalbuf, 602 val.valdat_len); 603 ypvalbuf[val.valdat_len] = '\0'; 604 result.peer = (char *)&ypvalbuf; 605 } else 606 result.peer = ""; 607 608 return (&result); 609} 610 611ypresp_order * 612ypproc_order_2_svc(ypreq_nokey *argp, struct svc_req *rqstp) 613{ 614 static ypresp_order result; 615 keydat key = { ORDER_SZ, ORDER_STRING }; 616 valdat val; 617 618 result.ordernum = 0; 619 620#ifdef DB_CACHE 621 if (yp_access(argp->map, argp->domain, (struct svc_req *)rqstp)) { 622#else 623 if (yp_access(argp->map, (struct svc_req *)rqstp)) { 624#endif 625 result.stat = YP_YPERR; 626 return(&result); 627 } 628 629 if (argp->domain == NULL) { 630 result.stat = YP_BADARGS; 631 return (&result); 632 } 633 634 /* 635 * We could just check the timestamp on the map file, 636 * but that's a hack: we'll only know the last time the file 637 * was touched, not the last time the database contents were 638 * updated. 639 */ 640 641 if (yp_select_map(argp->map, argp->domain, &key, 1) != YP_TRUE) { 642 result.stat = yp_errno; 643 return(&result); 644 } 645 646 result.stat = yp_getbykey(&key, &val); 647 648 if (result.stat == YP_TRUE) 649 result.ordernum = atoi((char *)val.valdat_val); 650 else 651 result.ordernum = 0; 652 653 return (&result); 654} 655 656static void yp_maplist_free(struct ypmaplist *yp_maplist) 657{ 658 register struct ypmaplist *next; 659 660 while (yp_maplist) { 661 next = yp_maplist->next; 662 free(yp_maplist->map); 663 free(yp_maplist); 664 yp_maplist = next; 665 } 666 return; 667} 668 669static struct ypmaplist * 670yp_maplist_create(const char *domain) 671{ 672 char yp_mapdir[MAXPATHLEN + 2]; 673 char yp_mapname[MAXPATHLEN + 2]; 674 struct ypmaplist *cur = NULL; 675 struct ypmaplist *yp_maplist = NULL; 676 DIR *dird; 677 struct dirent *dirp; 678 struct stat statbuf; 679 680 snprintf(yp_mapdir, sizeof(yp_mapdir), "%s/%s", yp_dir, domain); 681 682 if ((dird = opendir(yp_mapdir)) == NULL) { 683 yp_error("opendir(%s) failed: %s", yp_mapdir, strerror(errno)); 684 return(NULL); 685 } 686 687 while ((dirp = readdir(dird)) != NULL) { 688 if (strcmp(dirp->d_name, ".") && strcmp(dirp->d_name, "..")) { 689 snprintf(yp_mapname, sizeof(yp_mapname), "%s/%s", 690 yp_mapdir,dirp->d_name); 691 if (stat(yp_mapname, &statbuf) < 0 || 692 !S_ISREG(statbuf.st_mode)) 693 continue; 694 if ((cur = (struct ypmaplist *) 695 malloc(sizeof(struct ypmaplist))) == NULL) { 696 yp_error("malloc() failed"); 697 closedir(dird); 698 yp_maplist_free(yp_maplist); 699 return(NULL); 700 } 701 if ((cur->map = (char *)strdup(dirp->d_name)) == NULL) { 702 yp_error("strdup() failed: %s",strerror(errno)); 703 closedir(dird); 704 yp_maplist_free(yp_maplist); 705 return(NULL); 706 } 707 cur->next = yp_maplist; 708 yp_maplist = cur; 709 if (debug) 710 yp_error("map: %s", yp_maplist->map); 711 } 712 713 } 714 closedir(dird); 715 return(yp_maplist); 716} 717 718ypresp_maplist * 719ypproc_maplist_2_svc(domainname *argp, struct svc_req *rqstp) 720{ 721 static ypresp_maplist result = { 0, NULL }; 722 723#ifdef DB_CACHE 724 if (yp_access(NULL, NULL, (struct svc_req *)rqstp)) { 725#else 726 if (yp_access(NULL, (struct svc_req *)rqstp)) { 727#endif 728 result.stat = YP_YPERR; 729 return(&result); 730 } 731 732 if (argp == NULL) { 733 result.stat = YP_BADARGS; 734 return (&result); 735 } 736 737 if (yp_validdomain(*argp)) { 738 result.stat = YP_NODOM; 739 return (&result); 740 } 741 742 /* 743 * We have to construct a linked list for the ypproc_maplist 744 * procedure using dynamically allocated memory. Since the XDR 745 * layer won't free this list for us, we have to deal with it 746 * ourselves. We call yp_maplist_free() first to free any 747 * previously allocated data we may have accumulated to insure 748 * that we have only one linked list in memory at any given 749 * time. 750 */ 751 752 yp_maplist_free(result.maps); 753 754 if ((result.maps = yp_maplist_create(*argp)) == NULL) { 755 yp_error("yp_maplist_create failed"); 756 result.stat = YP_YPERR; 757 return(&result); 758 } else 759 result.stat = YP_TRUE; 760 761 return (&result); 762} 763 764/* 765 * NIS v1 support. The nullproc, domain and domain_nonack 766 * functions from v1 are identical to those in v2, so all 767 * we have to do is hand off to them. 768 * 769 * The other functions are mostly just wrappers around their v2 770 * counterparts. For example, for the v1 'match' procedure, we 771 * crack open the argument structure, make a request to the v2 772 * 'match' function, repackage the data into a v1 response and 773 * then send it on its way. 774 * 775 * Note that we don't support the pull, push and get procedures. 776 * There's little documentation available to show what they 777 * do, and I suspect they're meant largely for map transfers 778 * between master and slave servers. 779 */ 780 781void * 782ypoldproc_null_1_svc(void *argp, struct svc_req *rqstp) 783{ 784 return(ypproc_null_2_svc(argp, rqstp)); 785} 786 787bool_t * 788ypoldproc_domain_1_svc(domainname *argp, struct svc_req *rqstp) 789{ 790 return(ypproc_domain_2_svc(argp, rqstp)); 791} 792 793bool_t * 794ypoldproc_domain_nonack_1_svc(domainname *argp, struct svc_req *rqstp) 795{ 796 return (ypproc_domain_nonack_2_svc(argp, rqstp)); 797} 798 799/* 800 * the 'match' procedure sends a response of type YPRESP_VAL 801 */ 802ypresponse * 803ypoldproc_match_1_svc(yprequest *argp, struct svc_req *rqstp) 804{ 805 static ypresponse result; 806 ypresp_val *v2_result; 807 808 result.yp_resptype = YPRESP_VAL; 809 result.ypresponse_u.yp_resp_valtype.val.valdat_val = ""; 810 result.ypresponse_u.yp_resp_valtype.val.valdat_len = 0; 811 812 if (argp->yp_reqtype != YPREQ_KEY) { 813 result.ypresponse_u.yp_resp_valtype.stat = YP_BADARGS; 814 return(&result); 815 } 816 817 v2_result = ypproc_match_2_svc(&argp->yprequest_u.yp_req_keytype,rqstp); 818 if (v2_result == NULL) 819 return(NULL); 820 821 bcopy((char *)v2_result, 822 (char *)&result.ypresponse_u.yp_resp_valtype, 823 sizeof(ypresp_val)); 824 825 return (&result); 826} 827 828/* 829 * the 'first' procedure sends a response of type YPRESP_KEY_VAL 830 */ 831ypresponse * 832ypoldproc_first_1_svc(yprequest *argp, struct svc_req *rqstp) 833{ 834 static ypresponse result; 835 ypresp_key_val *v2_result; 836 837 result.yp_resptype = YPRESP_KEY_VAL; 838 result.ypresponse_u.yp_resp_key_valtype.val.valdat_val = 839 result.ypresponse_u.yp_resp_key_valtype.key.keydat_val = ""; 840 result.ypresponse_u.yp_resp_key_valtype.val.valdat_len = 841 result.ypresponse_u.yp_resp_key_valtype.key.keydat_len = 0; 842 843 if (argp->yp_reqtype != YPREQ_NOKEY) { 844 result.ypresponse_u.yp_resp_key_valtype.stat = YP_BADARGS; 845 return(&result); 846 } 847 848 v2_result = ypproc_first_2_svc(&argp->yprequest_u.yp_req_nokeytype, 849 rqstp); 850 if (v2_result == NULL) 851 return(NULL); 852 853 bcopy((char *)v2_result, 854 (char *)&result.ypresponse_u.yp_resp_key_valtype, 855 sizeof(ypresp_key_val)); 856 857 return (&result); 858} 859 860/* 861 * the 'next' procedure sends a response of type YPRESP_KEY_VAL 862 */ 863ypresponse * 864ypoldproc_next_1_svc(yprequest *argp, struct svc_req *rqstp) 865{ 866 static ypresponse result; 867 ypresp_key_val *v2_result; 868 869 result.yp_resptype = YPRESP_KEY_VAL; 870 result.ypresponse_u.yp_resp_key_valtype.val.valdat_val = 871 result.ypresponse_u.yp_resp_key_valtype.key.keydat_val = ""; 872 result.ypresponse_u.yp_resp_key_valtype.val.valdat_len = 873 result.ypresponse_u.yp_resp_key_valtype.key.keydat_len = 0; 874 875 if (argp->yp_reqtype != YPREQ_KEY) { 876 result.ypresponse_u.yp_resp_key_valtype.stat = YP_BADARGS; 877 return(&result); 878 } 879 880 v2_result = ypproc_next_2_svc(&argp->yprequest_u.yp_req_keytype,rqstp); 881 if (v2_result == NULL) 882 return(NULL); 883 884 bcopy((char *)v2_result, 885 (char *)&result.ypresponse_u.yp_resp_key_valtype, 886 sizeof(ypresp_key_val)); 887 888 return (&result); 889} 890 891/* 892 * the 'poll' procedure sends a response of type YPRESP_MAP_PARMS 893 */ 894ypresponse * 895ypoldproc_poll_1_svc(yprequest *argp, struct svc_req *rqstp) 896{ 897 static ypresponse result; 898 ypresp_master *v2_result1; 899 ypresp_order *v2_result2; 900 901 result.yp_resptype = YPRESP_MAP_PARMS; 902 result.ypresponse_u.yp_resp_map_parmstype.domain = 903 argp->yprequest_u.yp_req_nokeytype.domain; 904 result.ypresponse_u.yp_resp_map_parmstype.map = 905 argp->yprequest_u.yp_req_nokeytype.map; 906 /* 907 * Hmm... there is no 'status' value in the 908 * yp_resp_map_parmstype structure, so I have to 909 * guess at what to do to indicate a failure. 910 * I hope this is right. 911 */ 912 result.ypresponse_u.yp_resp_map_parmstype.ordernum = 0; 913 result.ypresponse_u.yp_resp_map_parmstype.peer = ""; 914 915 if (argp->yp_reqtype != YPREQ_MAP_PARMS) { 916 return(&result); 917 } 918 919 v2_result1 = ypproc_master_2_svc(&argp->yprequest_u.yp_req_nokeytype, 920 rqstp); 921 if (v2_result1 == NULL) 922 return(NULL); 923 924 if (v2_result1->stat != YP_TRUE) { 925 return(&result); 926 } 927 928 v2_result2 = ypproc_order_2_svc(&argp->yprequest_u.yp_req_nokeytype, 929 rqstp); 930 if (v2_result2 == NULL) 931 return(NULL); 932 933 if (v2_result2->stat != YP_TRUE) { 934 return(&result); 935 } 936 937 result.ypresponse_u.yp_resp_map_parmstype.peer = 938 v2_result1->peer; 939 result.ypresponse_u.yp_resp_map_parmstype.ordernum = 940 v2_result2->ordernum; 941 942 return (&result); 943} 944 945ypresponse * 946ypoldproc_push_1_svc(yprequest *argp, struct svc_req *rqstp) 947{ 948 static ypresponse result; 949 950 /* 951 * Not implemented. 952 */ 953 954 return (&result); 955} 956 957ypresponse * 958ypoldproc_pull_1_svc(yprequest *argp, struct svc_req *rqstp) 959{ 960 static ypresponse result; 961 962 /* 963 * Not implemented. 964 */ 965 966 return (&result); 967} 968 969ypresponse * 970ypoldproc_get_1_svc(yprequest *argp, struct svc_req *rqstp) 971{ 972 static ypresponse result; 973 974 /* 975 * Not implemented. 976 */ 977 978 return (&result); 979} 980