1219888Sed/* 2257547Sray * Copyright (c) 1995 3219888Sed * Bill Paul <wpaul@ctr.columbia.edu>. All rights reserved. 4219888Sed * 5219888Sed * Redistribution and use in source and binary forms, with or without 6219888Sed * modification, are permitted provided that the following conditions 7219888Sed * are met: 8257547Sray * 1. Redistributions of source code must retain the above copyright 9257547Sray * notice, this list of conditions and the following disclaimer. 10257547Sray * 2. Redistributions in binary form must reproduce the above copyright 11219888Sed * notice, this list of conditions and the following disclaimer in the 12219888Sed * documentation and/or other materials provided with the distribution. 13219888Sed * 3. All advertising materials mentioning features or use of this software 14219888Sed * must display the following acknowledgement: 15219888Sed * This product includes software developed by Bill Paul. 16219888Sed * 4. Neither the name of the author nor the names of any co-contributors 17219888Sed * may be used to endorse or promote products derived from this software 18219888Sed * without specific prior written permission. 19219888Sed * 20219888Sed * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND 21219888Sed * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22219888Sed * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23219888Sed * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR CONTRIBUTORS BE LIABLE 24219888Sed * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25219888Sed * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26219888Sed * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27219888Sed * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28219888Sed * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29219888Sed * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30219888Sed * SUCH DAMAGE. 31219888Sed * 32219888Sed */ 33219888Sed 34219888Sed#include <sys/cdefs.h> 35219888Sed__FBSDID("$FreeBSD$"); 36219888Sed 37219888Sed#include "yp.h" 38219888Sed#include "yp_extern.h" 39219888Sed#include <dirent.h> 40219888Sed#include <errno.h> 41219888Sed#include <stdlib.h> 42219888Sed#include <sys/stat.h> 43219888Sed#include <sys/param.h> 44219888Sed#include <sys/types.h> 45219888Sed#include <sys/socket.h> 46256145Sray#include <netinet/in.h> 47219888Sed#include <arpa/inet.h> 48219888Sed#include <rpc/rpc.h> 49219888Sed 50219888Sedint children = 0; 51219888Sed 52219888Sed#define MASTER_STRING "YP_MASTER_NAME" 53219888Sed#define MASTER_SZ sizeof(MASTER_STRING) - 1 54219888Sed#define ORDER_STRING "YP_LAST_MODIFIED" 55219888Sed#define ORDER_SZ sizeof(ORDER_STRING) - 1 56219888Sed 57219888Sedstatic pid_t 58219888Sedyp_fork(void) 59219888Sed{ 60219888Sed if (yp_pid != getpid()) { 61219888Sed yp_error("child %d trying to fork!", getpid()); 62219888Sed errno = EEXIST; 63219888Sed return(-1); 64219888Sed } 65219888Sed 66219888Sed return(fork()); 67219888Sed} 68219888Sed 69219888Sed/* 70219888Sed * NIS v2 support. This is where most of the action happens. 71219888Sed */ 72219888Sed 73219888Sedvoid * 74219888Sedypproc_null_2_svc(void *argp, struct svc_req *rqstp) 75219888Sed{ 76219888Sed static char * result; 77219888Sed static char rval = 0; 78219888Sed 79219888Sed#ifdef DB_CACHE 80219888Sed if (yp_access(NULL, NULL, (struct svc_req *)rqstp)) 81219888Sed#else 82219888Sed if (yp_access(NULL, (struct svc_req *)rqstp)) 83219888Sed#endif 84219888Sed return(NULL); 85257296Snwhitehorn 86219888Sed result = &rval; 87219888Sed 88219888Sed return((void *) &result); 89219888Sed} 90219888Sed 91219888Sedbool_t * 92257296Snwhitehornypproc_domain_2_svc(domainname *argp, struct svc_req *rqstp) 93219888Sed{ 94219888Sed static bool_t result; 95219888Sed 96219888Sed#ifdef DB_CACHE 97219888Sed if (yp_access(NULL, NULL, (struct svc_req *)rqstp)) { 98219888Sed#else 99219888Sed if (yp_access(NULL, (struct svc_req *)rqstp)) { 100219888Sed#endif 101219888Sed result = FALSE; 102219888Sed return (&result); 103219888Sed } 104256145Sray 105256145Sray if (argp == NULL || yp_validdomain(*argp)) 106256145Sray result = FALSE; 107256145Sray else 108256145Sray result = TRUE; 109256145Sray 110258023Sray return (&result); 111256145Sray} 112219888Sed 113219888Sedbool_t * 114256145Srayypproc_domain_nonack_2_svc(domainname *argp, struct svc_req *rqstp) 115219888Sed{ 116219888Sed static bool_t result; 117219888Sed 118219888Sed#ifdef DB_CACHE 119219888Sed if (yp_access(NULL, NULL, (struct svc_req *)rqstp)) 120219888Sed#else 121219888Sed if (yp_access(NULL, (struct svc_req *)rqstp)) 122219888Sed#endif 123219888Sed return (NULL); 124257986Sray 125219888Sed if (argp == NULL || yp_validdomain(*argp)) 126256145Sray return (NULL); 127256145Sray else 128256145Sray result = TRUE; 129256145Sray 130256145Sray return (&result); 131256145Sray} 132256145Sray 133256145Srayypresp_val * 134256145Srayypproc_match_2_svc(ypreq_key *argp, struct svc_req *rqstp) 135219888Sed{ 136256145Sray static ypresp_val result; 137256145Sray 138256145Sray result.val.valdat_val = ""; 139256145Sray result.val.valdat_len = 0; 140256145Sray 141256145Sray#ifdef DB_CACHE 142256145Sray if (yp_access(argp->map, argp->domain, (struct svc_req *)rqstp)) { 143256145Sray#else 144256145Sray if (yp_access(argp->map, (struct svc_req *)rqstp)) { 145256145Sray#endif 146256145Sray result.stat = YP_YPERR; 147256145Sray return (&result); 148256145Sray } 149256145Sray 150256145Sray if (argp->domain == NULL || argp->map == NULL) { 151256145Sray result.stat = YP_BADARGS; 152256145Sray return (&result); 153256145Sray } 154256145Sray 155256145Sray if (yp_select_map(argp->map, argp->domain, NULL, 1) != YP_TRUE) { 156256145Sray result.stat = yp_errno; 157256145Sray return(&result); 158256145Sray } 159256145Sray 160256145Sray result.stat = yp_getbykey(&argp->key, &result.val); 161256145Sray 162256145Sray /* 163256145Sray * Do DNS lookups for hosts maps if database lookup failed. 164256145Sray */ 165256145Sray 166256145Sray#ifdef DB_CACHE 167256145Sray if (do_dns && result.stat != YP_TRUE && 168256145Sray (yp_testflag(argp->map, argp->domain, YP_INTERDOMAIN) || 169256145Sray (strstr(argp->map, "hosts") || strstr(argp->map, "ipnodes")))) { 170256145Sray#else 171256145Sray if (do_dns && result.stat != YP_TRUE && 172256145Sray (strstr(argp->map, "hosts") || strstr(argp->map, "ipnodes"))) { 173256145Sray#endif 174256145Sray char nbuf[YPMAXRECORD]; 175256145Sray 176256145Sray /* NUL terminate! NUL terminate!! NUL TERMINATE!!! */ 177256145Sray bcopy(argp->key.keydat_val, nbuf, argp->key.keydat_len); 178256145Sray nbuf[argp->key.keydat_len] = '\0'; 179256145Sray 180256145Sray if (debug) 181256145Sray yp_error("doing DNS lookup of %s", nbuf); 182256145Sray 183256145Sray if (!strcmp(argp->map, "hosts.byname")) 184256145Sray result.stat = yp_async_lookup_name(rqstp, nbuf, 185256145Sray AF_INET); 186256145Sray else if (!strcmp(argp->map, "hosts.byaddr")) 187256145Sray result.stat = yp_async_lookup_addr(rqstp, nbuf, 188256145Sray AF_INET); 189256145Sray else if (!strcmp(argp->map, "ipnodes.byname")) 190256145Sray result.stat = yp_async_lookup_name(rqstp, nbuf, 191256145Sray AF_INET6); 192256145Sray else if (!strcmp(argp->map, "ipnodes.byaddr")) 193256145Sray result.stat = yp_async_lookup_addr(rqstp, nbuf, 194256145Sray AF_INET6); 195256145Sray 196256145Sray if (result.stat == YP_TRUE) 197256145Sray return(NULL); 198256145Sray } 199256145Sray 200256145Sray return (&result); 201256145Sray} 202256145Sray 203256145Srayypresp_key_val * 204256145Srayypproc_first_2_svc(ypreq_nokey *argp, struct svc_req *rqstp) 205256145Sray{ 206256145Sray static ypresp_key_val result; 207256145Sray 208256145Sray result.val.valdat_val = result.key.keydat_val = ""; 209256145Sray result.val.valdat_len = result.key.keydat_len = 0; 210256145Sray 211256145Sray#ifdef DB_CACHE 212256145Sray if (yp_access(argp->map, argp->domain, (struct svc_req *)rqstp)) { 213256145Sray#else 214256145Sray if (yp_access(argp->map, (struct svc_req *)rqstp)) { 215256145Sray#endif 216256145Sray result.stat = YP_YPERR; 217256145Sray return (&result); 218256145Sray } 219256145Sray 220256145Sray if (argp->domain == NULL) { 221219888Sed result.stat = YP_BADARGS; 222219888Sed return (&result); 223219888Sed } 224256145Sray 225219888Sed if (yp_select_map(argp->map, argp->domain, NULL, 0) != YP_TRUE) { 226219888Sed result.stat = yp_errno; 227219888Sed return(&result); 228256145Sray } 229256145Sray 230219888Sed result.stat = yp_firstbykey(&result.key, &result.val); 231256145Sray 232219888Sed return (&result); 233256145Sray} 234256145Sray 235256145Srayypresp_key_val * 236256145Srayypproc_next_2_svc(ypreq_key *argp, struct svc_req *rqstp) 237256145Sray{ 238219888Sed static ypresp_key_val result; 239219888Sed 240219888Sed result.val.valdat_val = result.key.keydat_val = ""; 241219888Sed result.val.valdat_len = result.key.keydat_len = 0; 242219888Sed 243256145Sray#ifdef DB_CACHE 244256145Sray if (yp_access(argp->map, argp->domain, (struct svc_req *)rqstp)) { 245256145Sray#else 246219888Sed if (yp_access(argp->map, (struct svc_req *)rqstp)) { 247219888Sed#endif 248219888Sed result.stat = YP_YPERR; 249256145Sray return (&result); 250219888Sed } 251256145Sray 252219888Sed if (argp->domain == NULL || argp->map == NULL) { 253256145Sray result.stat = YP_BADARGS; 254256145Sray return (&result); 255256145Sray } 256219888Sed 257219888Sed if (yp_select_map(argp->map, argp->domain, &argp->key, 0) != YP_TRUE) { 258219888Sed result.stat = yp_errno; 259219888Sed return(&result); 260219888Sed } 261219888Sed 262219888Sed result.key.keydat_len = argp->key.keydat_len; 263219888Sed result.key.keydat_val = argp->key.keydat_val; 264219888Sed 265219888Sed result.stat = yp_nextbykey(&result.key, &result.val); 266219888Sed 267219888Sed return (&result); 268219888Sed} 269219888Sed 270219888Sedstatic void 271219888Sedypxfr_callback(ypxfrstat rval, struct sockaddr_in *addr, unsigned int transid, 272219888Sed unsigned int prognum, unsigned long port) 273219888Sed{ 274219888Sed CLIENT *clnt; 275219888Sed int sock = RPC_ANYSOCK; 276219888Sed struct timeval timeout; 277219888Sed yppushresp_xfr ypxfr_resp; 278219888Sed struct rpc_err err; 279219888Sed 280219888Sed timeout.tv_sec = 5; 281219888Sed timeout.tv_usec = 0; 282257076Sray addr->sin_port = htons(port); 283257076Sray 284257076Sray if ((clnt = clntudp_create(addr,prognum,1,timeout,&sock)) == NULL) { 285257076Sray yp_error("%s: %s", inet_ntoa(addr->sin_addr), 286257076Sray clnt_spcreateerror("failed to establish callback handle")); 287257076Sray return; 288257076Sray } 289257076Sray 290257076Sray ypxfr_resp.status = rval; 291257076Sray ypxfr_resp.transid = transid; 292257076Sray 293257076Sray /* Turn the timeout off -- we don't want to block. */ 294257076Sray timeout.tv_sec = 0; 295257076Sray if (clnt_control(clnt, CLSET_TIMEOUT, &timeout) == FALSE) 296257076Sray yp_error("failed to set timeout on ypproc_xfr callback"); 297257076Sray 298257076Sray if (yppushproc_xfrresp_1(&ypxfr_resp, clnt) == NULL) { 299257076Sray clnt_geterr(clnt, &err); 300257076Sray if (err.re_status != RPC_SUCCESS && 301257076Sray err.re_status != RPC_TIMEDOUT) 302257076Sray yp_error("%s", clnt_sperror(clnt, 303257076Sray "ypxfr callback failed")); 304257076Sray } 305257076Sray 306257076Sray clnt_destroy(clnt); 307219888Sed return; 308257076Sray} 309257076Sray 310257076Sray#define YPXFR_RETURN(CODE) \ 311257076Sray /* Order is important: send regular RPC reply, then callback */ \ 312257076Sray result.xfrstat = CODE; \ 313257076Sray svc_sendreply(rqstp->rq_xprt, (xdrproc_t)xdr_ypresp_xfr, &result); \ 314257076Sray ypxfr_callback(CODE,rqhost,argp->transid, \ 315257076Sray argp->prog,argp->port); \ 316257076Sray return(NULL); 317257076Sray 318257076Srayypresp_xfr * 319257076Srayypproc_xfr_2_svc(ypreq_xfr *argp, struct svc_req *rqstp) 320257076Sray{ 321257076Sray static ypresp_xfr result; 322257076Sray struct sockaddr_in *rqhost; 323257076Sray ypresp_master *mres; 324257076Sray ypreq_nokey mreq; 325257076Sray 326257076Sray result.transid = argp->transid; 327257076Sray rqhost = svc_getcaller(rqstp->rq_xprt); 328257076Sray 329257076Sray#ifdef DB_CACHE 330257076Sray if (yp_access(argp->map_parms.map, 331257076Sray argp->map_parms.domain, (struct svc_req *)rqstp)) { 332257076Sray#else 333257076Sray if (yp_access(argp->map_parms.map, (struct svc_req *)rqstp)) { 334257076Sray#endif 335257076Sray YPXFR_RETURN(YPXFR_REFUSED) 336257076Sray } 337257076Sray 338257076Sray 339257076Sray if (argp->map_parms.domain == NULL) { 340257076Sray YPXFR_RETURN(YPXFR_BADARGS) 341257076Sray } 342257076Sray 343257076Sray if (yp_validdomain(argp->map_parms.domain)) { 344257076Sray YPXFR_RETURN(YPXFR_NODOM) 345257076Sray } 346257076Sray 347257076Sray /* 348257076Sray * Determine the master host ourselves. The caller may 349257076Sray * be up to no good. This has the side effect of verifying 350257076Sray * that the requested map and domain actually exist. 351257076Sray */ 352257076Sray 353257076Sray mreq.domain = argp->map_parms.domain; 354257076Sray mreq.map = argp->map_parms.map; 355257076Sray 356257076Sray mres = ypproc_master_2_svc(&mreq, rqstp); 357257076Sray 358257076Sray if (mres->stat != YP_TRUE) { 359257076Sray yp_error("couldn't find master for map %s@%s", 360257076Sray argp->map_parms.map, 361257076Sray argp->map_parms.domain); 362257076Sray yp_error("host at %s (%s) may be pulling my leg", 363257076Sray argp->map_parms.peer, 364257076Sray inet_ntoa(rqhost->sin_addr)); 365257076Sray YPXFR_RETURN(YPXFR_REFUSED) 366257076Sray } 367257076Sray 368257076Sray switch (yp_fork()) { 369257076Sray case 0: 370257076Sray { 371257076Sray char g[11], t[11], p[11]; 372257076Sray char ypxfr_command[MAXPATHLEN + 2]; 373257076Sray 374257076Sray snprintf (ypxfr_command, sizeof(ypxfr_command), "%sypxfr", _PATH_LIBEXEC); 375257076Sray snprintf (t, sizeof(t), "%u", argp->transid); 376257076Sray snprintf (g, sizeof(g), "%u", argp->prog); 377257076Sray snprintf (p, sizeof(p), "%u", argp->port); 378257076Sray if (debug) { 379257076Sray close(0); close(1); close(2); 380257076Sray } 381257076Sray if (strcmp(yp_dir, _PATH_YP)) { 382257076Sray execl(ypxfr_command, "ypxfr", 383257076Sray "-d", argp->map_parms.domain, 384257076Sray "-h", mres->peer, 385257076Sray "-p", yp_dir, "-C", t, 386257076Sray g, inet_ntoa(rqhost->sin_addr), 387257076Sray p, argp->map_parms.map, 388257294Snwhitehorn NULL); 389219888Sed } else { 390219888Sed execl(ypxfr_command, "ypxfr", 391257294Snwhitehorn "-d", argp->map_parms.domain, 392219888Sed "-h", mres->peer, 393219888Sed "-C", t, 394219888Sed g, inet_ntoa(rqhost->sin_addr), 395219888Sed p, argp->map_parms.map, 396257076Sray NULL); 397257076Sray } 398257076Sray yp_error("ypxfr execl(%s): %s", ypxfr_command, strerror(errno)); 399257076Sray YPXFR_RETURN(YPXFR_XFRERR) 400257076Sray /* 401257076Sray * Just to safe, prevent PR #10970 from biting us in 402257076Sray * the unlikely case that execing ypxfr fails. We don't 403257076Sray * want to have any child processes spawned from this 404257076Sray * child process. 405219888Sed */ 406219888Sed _exit(0); 407219888Sed break; 408219888Sed } 409219888Sed case -1: 410219888Sed yp_error("ypxfr fork(): %s", strerror(errno)); 411256145Sray YPXFR_RETURN(YPXFR_XFRERR) 412219888Sed break; 413219888Sed default: 414219888Sed result.xfrstat = YPXFR_SUCC; 415219888Sed children++; 416219888Sed break; 417219888Sed } 418219888Sed 419219888Sed return (&result); 420219888Sed} 421219888Sed#undef YPXFR_RETURN 422219888Sed 423256145Srayvoid * 424219888Sedypproc_clear_2_svc(void *argp, struct svc_req *rqstp) 425219888Sed{ 426219888Sed static char * result; 427256145Sray static char rval = 0; 428257076Sray 429219888Sed#ifdef DB_CACHE 430219888Sed if (yp_access(NULL, NULL, (struct svc_req *)rqstp)) 431219888Sed#else 432219888Sed if (yp_access(NULL, (struct svc_req *)rqstp)) 433219888Sed#endif 434219888Sed return (NULL); 435219888Sed#ifdef DB_CACHE 436219888Sed /* clear out the database cache */ 437219888Sed yp_flush_all(); 438219888Sed#endif 439219888Sed /* Re-read the securenets database for the hell of it. */ 440219888Sed load_securenets(); 441219888Sed 442219888Sed result = &rval; 443219888Sed return((void *) &result); 444219888Sed} 445219888Sed 446219888Sed/* 447219888Sed * For ypproc_all, we have to send a stream of ypresp_all structures 448219888Sed * via TCP, but the XDR filter generated from the yp.x protocol 449219888Sed * definition file only serializes one such structure. This means that 450219888Sed * to send the whole stream, you need a wrapper which feeds all the 451219888Sed * records into the underlying XDR routine until it hits an 'EOF.' 452219888Sed * But to use the wrapper, you have to violate the boundaries between 453219888Sed * RPC layers by calling svc_sendreply() directly from the ypproc_all 454219888Sed * service routine instead of letting the RPC dispatcher do it. 455219888Sed * 456219888Sed * Bleah. 457219888Sed */ 458219888Sed 459219888Sed/* 460219888Sed * Custom XDR routine for serialzing results of ypproc_all: keep 461219888Sed * reading from the database and spew until we run out of records 462219888Sed * or encounter an error. 463219888Sed */ 464219888Sedstatic bool_t 465219888Sedxdr_my_ypresp_all(register XDR *xdrs, ypresp_all *objp) 466219888Sed{ 467219888Sed while (1) { 468219888Sed /* Get a record. */ 469219888Sed if ((objp->ypresp_all_u.val.stat = 470219888Sed yp_nextbykey(&objp->ypresp_all_u.val.key, 471219888Sed &objp->ypresp_all_u.val.val)) == YP_TRUE) { 472219888Sed objp->more = TRUE; 473219888Sed } else { 474219888Sed objp->more = FALSE; 475256145Sray } 476219888Sed 477219888Sed /* Serialize. */ 478219888Sed if (!xdr_ypresp_all(xdrs, objp)) 479219888Sed return(FALSE); 480219888Sed if (objp->more == FALSE) 481219888Sed return(TRUE); 482219888Sed } 483257294Snwhitehorn} 484257294Snwhitehorn 485257294Snwhitehornypresp_all * 486257294Snwhitehornypproc_all_2_svc(ypreq_nokey *argp, struct svc_req *rqstp) 487257294Snwhitehorn{ 488257294Snwhitehorn static ypresp_all result; 489257294Snwhitehorn 490257294Snwhitehorn /* 491257294Snwhitehorn * Set this here so that the client will be forced to make 492257294Snwhitehorn * at least one attempt to read from us even if all we're 493257294Snwhitehorn * doing is returning an error. 494257294Snwhitehorn */ 495257294Snwhitehorn result.more = TRUE; 496257294Snwhitehorn result.ypresp_all_u.val.key.keydat_len = 0; 497257294Snwhitehorn result.ypresp_all_u.val.key.keydat_val = ""; 498257294Snwhitehorn 499257294Snwhitehorn#ifdef DB_CACHE 500257294Snwhitehorn if (yp_access(argp->map, argp->domain, (struct svc_req *)rqstp)) { 501257294Snwhitehorn#else 502257294Snwhitehorn if (yp_access(argp->map, (struct svc_req *)rqstp)) { 503257294Snwhitehorn#endif 504257294Snwhitehorn result.ypresp_all_u.val.stat = YP_YPERR; 505257294Snwhitehorn return (&result); 506257294Snwhitehorn } 507257294Snwhitehorn 508219888Sed if (argp->domain == NULL || argp->map == NULL) { 509219888Sed result.ypresp_all_u.val.stat = YP_BADARGS; 510219888Sed return (&result); 511219888Sed } 512219888Sed 513219888Sed /* 514219888Sed * XXX If we hit the child limit, fail the request. 515219888Sed * If we don't, and the map is large, we could block for 516256145Sray * a long time in the parent. 517256145Sray */ 518219888Sed if (children >= MAX_CHILDREN) { 519256145Sray result.ypresp_all_u.val.stat = YP_YPERR; 520219888Sed return(&result); 521219888Sed } 522219888Sed 523219888Sed /* 524219888Sed * The ypproc_all procedure can take a while to complete. 525219888Sed * Best to handle it in a subprocess so the parent doesn't 526219888Sed * block. (Is there a better way to do this? Maybe with 527219888Sed * async socket I/O?) 528219888Sed */ 529219888Sed if (!debug) { 530219888Sed switch (yp_fork()) { 531219888Sed case 0: 532219888Sed break; 533219888Sed case -1: 534219888Sed yp_error("ypall fork(): %s", strerror(errno)); 535219888Sed result.ypresp_all_u.val.stat = YP_YPERR; 536256145Sray return(&result); 537256145Sray break; 538219888Sed default: 539219888Sed children++; 540256145Sray return (NULL); 541256145Sray break; 542219888Sed } 543219888Sed } 544219888Sed 545219888Sed /* 546219888Sed * Fix for PR #10971: don't let the child ypserv share 547219888Sed * DB handles with the parent process. 548219888Sed */ 549219888Sed#ifdef DB_CACHE 550219888Sed yp_flush_all(); 551219888Sed#endif 552219888Sed 553219888Sed if (yp_select_map(argp->map, argp->domain, 554219888Sed &result.ypresp_all_u.val.key, 0) != YP_TRUE) { 555219888Sed result.ypresp_all_u.val.stat = yp_errno; 556219888Sed return(&result); 557219888Sed } 558219888Sed 559219888Sed /* Kick off the actual data transfer. */ 560219888Sed svc_sendreply(rqstp->rq_xprt, (xdrproc_t)xdr_my_ypresp_all, &result); 561219888Sed 562219888Sed /* 563219888Sed * Proper fix for PR #10970: exit here so that we don't risk 564219888Sed * having a child spawned from this sub-process. 565219888Sed */ 566219888Sed if (!debug) 567219888Sed _exit(0); 568219888Sed 569219888Sed return &result; 570219888Sed} 571219888Sed 572219888Sedypresp_master * 573219888Sedypproc_master_2_svc(ypreq_nokey *argp, struct svc_req *rqstp) 574256145Sray{ 575219888Sed static ypresp_master result; 576219888Sed static char ypvalbuf[YPMAXRECORD]; 577219888Sed keydat key = { MASTER_SZ, MASTER_STRING }; 578219888Sed valdat val; 579219888Sed 580219888Sed result.peer = ""; 581219888Sed 582219888Sed#ifdef DB_CACHE 583219888Sed if (yp_access(argp->map, argp->domain, (struct svc_req *)rqstp)) { 584219888Sed#else 585219888Sed if (yp_access(argp->map, (struct svc_req *)rqstp)) { 586219888Sed#endif 587219888Sed result.stat = YP_YPERR; 588219888Sed return(&result); 589219888Sed } 590219888Sed 591219888Sed if (argp->domain == NULL) { 592219888Sed result.stat = YP_BADARGS; 593219888Sed return (&result); 594219888Sed } 595219888Sed 596219888Sed if (yp_select_map(argp->map, argp->domain, &key, 1) != YP_TRUE) { 597219888Sed result.stat = yp_errno; 598219888Sed return(&result); 599219888Sed } 600219888Sed 601219888Sed /* 602219888Sed * Note that we copy the data retrieved from the database to 603219888Sed * a private buffer and NUL terminate the buffer rather than 604219888Sed * terminating the data in place. We do this because by stuffing 605219888Sed * a '\0' into data.data, we will actually be corrupting memory 606219888Sed * allocated by the DB package. This is a bad thing now that we 607219888Sed * cache DB handles rather than closing the database immediately. 608219888Sed */ 609219888Sed result.stat = yp_getbykey(&key, &val); 610219888Sed if (result.stat == YP_TRUE) { 611219888Sed bcopy(val.valdat_val, &ypvalbuf, val.valdat_len); 612219888Sed ypvalbuf[val.valdat_len] = '\0'; 613219888Sed result.peer = ypvalbuf; 614219888Sed } else 615219888Sed result.peer = ""; 616219888Sed 617219888Sed return (&result); 618219888Sed} 619219888Sed 620219888Sedypresp_order * 621219888Sedypproc_order_2_svc(ypreq_nokey *argp, struct svc_req *rqstp) 622219888Sed{ 623219888Sed static ypresp_order result; 624219888Sed keydat key = { ORDER_SZ, ORDER_STRING }; 625219888Sed valdat val; 626219888Sed 627219888Sed result.ordernum = 0; 628219888Sed 629219888Sed#ifdef DB_CACHE 630219888Sed if (yp_access(argp->map, argp->domain, (struct svc_req *)rqstp)) { 631219888Sed#else 632219888Sed if (yp_access(argp->map, (struct svc_req *)rqstp)) { 633219888Sed#endif 634219888Sed result.stat = YP_YPERR; 635219888Sed return(&result); 636219888Sed } 637219888Sed 638219888Sed if (argp->domain == NULL) { 639219888Sed result.stat = YP_BADARGS; 640219888Sed return (&result); 641257979Sray } 642257979Sray 643219888Sed /* 644257988Sray * We could just check the timestamp on the map file, 645219888Sed * but that's a hack: we'll only know the last time the file 646219888Sed * was touched, not the last time the database contents were 647219888Sed * updated. 648219888Sed */ 649219888Sed 650219888Sed if (yp_select_map(argp->map, argp->domain, &key, 1) != YP_TRUE) { 651219888Sed result.stat = yp_errno; 652219888Sed return(&result); 653219888Sed } 654219888Sed 655219888Sed result.stat = yp_getbykey(&key, &val); 656219888Sed 657219888Sed if (result.stat == YP_TRUE) 658257981Sray result.ordernum = atoi(val.valdat_val); 659256145Sray else 660257981Sray result.ordernum = 0; 661257981Sray 662256145Sray return (&result); 663257988Sray} 664219888Sed 665219888Sedstatic void yp_maplist_free(struct ypmaplist *yp_maplist) 666219888Sed{ 667219888Sed register struct ypmaplist *next; 668219888Sed 669219888Sed while (yp_maplist) { 670219888Sed next = yp_maplist->next; 671219888Sed free(yp_maplist->map); 672256145Sray free(yp_maplist); 673219888Sed yp_maplist = next; 674219888Sed } 675219888Sed return; 676219888Sed} 677219888Sed 678219888Sedstatic struct ypmaplist * 679219888Sedyp_maplist_create(const char *domain) 680257981Sray{ 681257981Sray char yp_mapdir[MAXPATHLEN + 2]; 682257981Sray char yp_mapname[MAXPATHLEN + 2]; 683219888Sed struct ypmaplist *cur = NULL; 684257981Sray struct ypmaplist *yp_maplist = NULL; 685257981Sray DIR *dird; 686257981Sray struct dirent *dirp; 687219888Sed struct stat statbuf; 688219888Sed 689219888Sed snprintf(yp_mapdir, sizeof(yp_mapdir), "%s/%s", yp_dir, domain); 690256145Sray 691219888Sed if ((dird = opendir(yp_mapdir)) == NULL) { 692219888Sed yp_error("opendir(%s) failed: %s", yp_mapdir, strerror(errno)); 693219888Sed return(NULL); 694219888Sed } 695219888Sed 696256145Sray while ((dirp = readdir(dird)) != NULL) { 697256903Sray if (strcmp(dirp->d_name, ".") && strcmp(dirp->d_name, "..")) { 698219888Sed snprintf(yp_mapname, sizeof(yp_mapname), "%s/%s", 699219888Sed yp_mapdir,dirp->d_name); 700257981Sray if (stat(yp_mapname, &statbuf) < 0 || 701257981Sray !S_ISREG(statbuf.st_mode)) 702257981Sray continue; 703257981Sray if ((cur = (struct ypmaplist *) 704257988Sray malloc(sizeof(struct ypmaplist))) == NULL) { 705257981Sray yp_error("malloc() failed"); 706257981Sray closedir(dird); 707257981Sray yp_maplist_free(yp_maplist); 708257981Sray return(NULL); 709257981Sray } 710257981Sray if ((cur->map = strdup(dirp->d_name)) == NULL) { 711257981Sray yp_error("strdup() failed: %s",strerror(errno)); 712257981Sray closedir(dird); 713257988Sray yp_maplist_free(yp_maplist); 714257981Sray return(NULL); 715257981Sray } 716257981Sray cur->next = yp_maplist; 717257981Sray yp_maplist = cur; 718257981Sray if (debug) 719257981Sray yp_error("map: %s", yp_maplist->map); 720257981Sray } 721219888Sed 722219888Sed } 723219888Sed closedir(dird); 724219888Sed return(yp_maplist); 725219888Sed} 726257387Sray 727219888Sedypresp_maplist * 728257387Srayypproc_maplist_2_svc(domainname *argp, struct svc_req *rqstp) 729257387Sray{ 730219888Sed static ypresp_maplist result = { 0, NULL }; 731257387Sray 732219888Sed#ifdef DB_CACHE 733219888Sed if (yp_access(NULL, NULL, (struct svc_req *)rqstp)) { 734219888Sed#else 735219888Sed if (yp_access(NULL, (struct svc_req *)rqstp)) { 736219888Sed#endif 737219888Sed result.stat = YP_YPERR; 738219888Sed return(&result); 739219888Sed } 740219888Sed 741219888Sed if (argp == NULL) { 742219888Sed result.stat = YP_BADARGS; 743219888Sed return (&result); 744219888Sed } 745219888Sed 746257626Sray if (yp_validdomain(*argp)) { 747257626Sray result.stat = YP_NODOM; 748219888Sed return (&result); 749219888Sed } 750219888Sed 751219888Sed /* 752219888Sed * We have to construct a linked list for the ypproc_maplist 753219888Sed * procedure using dynamically allocated memory. Since the XDR 754219888Sed * layer won't free this list for us, we have to deal with it 755219888Sed * ourselves. We call yp_maplist_free() first to free any 756219888Sed * previously allocated data we may have accumulated to insure 757256145Sray * that we have only one linked list in memory at any given 758256145Sray * time. 759256145Sray */ 760256145Sray 761256145Sray yp_maplist_free(result.maps); 762257722Sray 763256145Sray if ((result.maps = yp_maplist_create(*argp)) == NULL) { 764256145Sray yp_error("yp_maplist_create failed"); 765256145Sray result.stat = YP_YPERR; 766256145Sray return(&result); 767256145Sray } else 768256145Sray result.stat = YP_TRUE; 769257988Sray 770257988Sray return (&result); 771256145Sray} 772256145Sray 773256145Sray/* 774256145Sray * NIS v1 support. The nullproc, domain and domain_nonack 775256145Sray * functions from v1 are identical to those in v2, so all 776256145Sray * we have to do is hand off to them. 777219888Sed * 778219888Sed * The other functions are mostly just wrappers around their v2 779219888Sed * counterparts. For example, for the v1 'match' procedure, we 780219888Sed * crack open the argument structure, make a request to the v2 781219888Sed * 'match' function, repackage the data into a v1 response and 782219888Sed * then send it on its way. 783256145Sray * 784256145Sray * Note that we don't support the pull, push and get procedures. 785256145Sray * There's little documentation available to show what they 786256145Sray * do, and I suspect they're meant largely for map transfers 787219888Sed * between master and slave servers. 788219888Sed */ 789219888Sed 790219888Sedvoid * 791219888Sedypoldproc_null_1_svc(void *argp, struct svc_req *rqstp) 792219888Sed{ 793230469Snwhitehorn return(ypproc_null_2_svc(argp, rqstp)); 794230469Snwhitehorn} 795230469Snwhitehorn 796219888Sedbool_t * 797256145Srayypoldproc_domain_1_svc(domainname *argp, struct svc_req *rqstp) 798219888Sed{ 799219888Sed return(ypproc_domain_2_svc(argp, rqstp)); 800219888Sed} 801219888Sed 802219888Sedbool_t * 803219888Sedypoldproc_domain_nonack_1_svc(domainname *argp, struct svc_req *rqstp) 804219888Sed{ 805219888Sed return (ypproc_domain_nonack_2_svc(argp, rqstp)); 806219888Sed} 807256145Sray 808219888Sed/* 809256145Sray * the 'match' procedure sends a response of type YPRESP_VAL 810256145Sray */ 811219888Sedypresponse * 812219888Sedypoldproc_match_1_svc(yprequest *argp, struct svc_req *rqstp) 813219888Sed{ 814219888Sed static ypresponse result; 815219888Sed ypresp_val *v2_result; 816219888Sed 817219888Sed result.yp_resptype = YPRESP_VAL; 818219888Sed result.ypresponse_u.yp_resp_valtype.val.valdat_val = ""; 819257076Sray result.ypresponse_u.yp_resp_valtype.val.valdat_len = 0; 820219888Sed 821219888Sed if (argp->yp_reqtype != YPREQ_KEY) { 822257076Sray result.ypresponse_u.yp_resp_valtype.stat = YP_BADARGS; 823257076Sray return(&result); 824257076Sray } 825257076Sray 826219888Sed v2_result = ypproc_match_2_svc(&argp->yprequest_u.yp_req_keytype,rqstp); 827219888Sed if (v2_result == NULL) 828256145Sray return(NULL); 829219888Sed 830256145Sray bcopy(v2_result, &result.ypresponse_u.yp_resp_valtype, 831256145Sray sizeof(ypresp_val)); 832219888Sed 833219888Sed return (&result); 834219888Sed} 835219888Sed 836219888Sed/* 837219888Sed * the 'first' procedure sends a response of type YPRESP_KEY_VAL 838219888Sed */ 839219888Sedypresponse * 840256145Srayypoldproc_first_1_svc(yprequest *argp, struct svc_req *rqstp) 841256145Sray{ 842256145Sray static ypresponse result; 843256145Sray ypresp_key_val *v2_result; 844219888Sed 845219888Sed result.yp_resptype = YPRESP_KEY_VAL; 846219888Sed result.ypresponse_u.yp_resp_key_valtype.val.valdat_val = 847219888Sed result.ypresponse_u.yp_resp_key_valtype.key.keydat_val = ""; 848219888Sed result.ypresponse_u.yp_resp_key_valtype.val.valdat_len = 849219888Sed result.ypresponse_u.yp_resp_key_valtype.key.keydat_len = 0; 850256145Sray 851257076Sray if (argp->yp_reqtype != YPREQ_NOKEY) { 852257076Sray result.ypresponse_u.yp_resp_key_valtype.stat = YP_BADARGS; 853257076Sray return(&result); 854257076Sray } 855257076Sray 856257076Sray v2_result = ypproc_first_2_svc(&argp->yprequest_u.yp_req_nokeytype, 857219888Sed rqstp); 858219888Sed if (v2_result == NULL) 859219888Sed return(NULL); 860257076Sray 861219888Sed bcopy(v2_result, &result.ypresponse_u.yp_resp_key_valtype, 862219888Sed sizeof(ypresp_key_val)); 863219888Sed 864219888Sed return (&result); 865256145Sray} 866219888Sed 867219888Sed/* 868257076Sray * the 'next' procedure sends a response of type YPRESP_KEY_VAL 869219888Sed */ 870256145Srayypresponse * 871219888Sedypoldproc_next_1_svc(yprequest *argp, struct svc_req *rqstp) 872219888Sed{ 873257076Sray static ypresponse result; 874257076Sray ypresp_key_val *v2_result; 875257076Sray 876219888Sed result.yp_resptype = YPRESP_KEY_VAL; 877257076Sray result.ypresponse_u.yp_resp_key_valtype.val.valdat_val = 878257076Sray result.ypresponse_u.yp_resp_key_valtype.key.keydat_val = ""; 879219888Sed result.ypresponse_u.yp_resp_key_valtype.val.valdat_len = 880257076Sray result.ypresponse_u.yp_resp_key_valtype.key.keydat_len = 0; 881257076Sray 882219888Sed if (argp->yp_reqtype != YPREQ_KEY) { 883257076Sray result.ypresponse_u.yp_resp_key_valtype.stat = YP_BADARGS; 884257076Sray return(&result); 885219888Sed } 886219888Sed 887219888Sed v2_result = ypproc_next_2_svc(&argp->yprequest_u.yp_req_keytype,rqstp); 888219888Sed if (v2_result == NULL) 889219888Sed return(NULL); 890219888Sed 891219888Sed bcopy(v2_result, &result.ypresponse_u.yp_resp_key_valtype, 892219888Sed sizeof(ypresp_key_val)); 893256145Sray 894257076Sray return (&result); 895257076Sray} 896257076Sray 897257076Sray/* 898219888Sed * the 'poll' procedure sends a response of type YPRESP_MAP_PARMS 899219888Sed */ 900219888Sedypresponse * 901219888Sedypoldproc_poll_1_svc(yprequest *argp, struct svc_req *rqstp) 902219888Sed{ 903219888Sed static ypresponse result; 904219888Sed ypresp_master *v2_result1; 905219888Sed ypresp_order *v2_result2; 906219888Sed 907219888Sed result.yp_resptype = YPRESP_MAP_PARMS; 908219888Sed result.ypresponse_u.yp_resp_map_parmstype.domain = 909219888Sed argp->yprequest_u.yp_req_nokeytype.domain; 910219888Sed result.ypresponse_u.yp_resp_map_parmstype.map = 911256145Sray argp->yprequest_u.yp_req_nokeytype.map; 912219888Sed /* 913256145Sray * Hmm... there is no 'status' value in the 914256145Sray * yp_resp_map_parmstype structure, so I have to 915219888Sed * guess at what to do to indicate a failure. 916219888Sed * I hope this is right. 917219888Sed */ 918219888Sed result.ypresponse_u.yp_resp_map_parmstype.ordernum = 0; 919219888Sed result.ypresponse_u.yp_resp_map_parmstype.peer = ""; 920219888Sed 921219888Sed if (argp->yp_reqtype != YPREQ_MAP_PARMS) { 922219888Sed return(&result); 923219888Sed } 924219888Sed 925219888Sed v2_result1 = ypproc_master_2_svc(&argp->yprequest_u.yp_req_nokeytype, 926219888Sed rqstp); 927219888Sed if (v2_result1 == NULL) 928219888Sed return(NULL); 929219888Sed 930219888Sed if (v2_result1->stat != YP_TRUE) { 931219888Sed return(&result); 932219888Sed } 933219888Sed 934219888Sed v2_result2 = ypproc_order_2_svc(&argp->yprequest_u.yp_req_nokeytype, 935219888Sed rqstp); 936219888Sed if (v2_result2 == NULL) 937219888Sed return(NULL); 938219888Sed 939219888Sed if (v2_result2->stat != YP_TRUE) { 940219888Sed return(&result); 941219888Sed } 942219888Sed 943219888Sed result.ypresponse_u.yp_resp_map_parmstype.peer = 944219888Sed v2_result1->peer; 945219888Sed result.ypresponse_u.yp_resp_map_parmstype.ordernum = 946219888Sed v2_result2->ordernum; 947219888Sed 948219888Sed return (&result); 949219888Sed} 950219888Sed 951219888Sedypresponse * 952219888Sedypoldproc_push_1_svc(yprequest *argp, struct svc_req *rqstp) 953219888Sed{ 954219888Sed static ypresponse result; 955257978Sray 956257978Sray /* 957257978Sray * Not implemented. 958219888Sed */ 959219888Sed 960219888Sed return (&result); 961256145Sray} 962256903Sray 963219888Sedypresponse * 964219888Sedypoldproc_pull_1_svc(yprequest *argp, struct svc_req *rqstp) 965219888Sed{ 966219888Sed static ypresponse result; 967219888Sed 968219888Sed /* 969219888Sed * Not implemented. 970219888Sed */ 971219888Sed 972219888Sed return (&result); 973219888Sed} 974219888Sed 975219888Sedypresponse * 976219888Sedypoldproc_get_1_svc(yprequest *argp, struct svc_req *rqstp) 977219888Sed{ 978219888Sed static ypresponse result; 979256145Sray 980256145Sray /* 981256145Sray * Not implemented. 982256145Sray */ 983256145Sray 984256145Sray return (&result); 985256145Sray} 986256145Sray