yp_server.c revision 27589
112891Swpaul/* 212891Swpaul * Copyright (c) 1995 312891Swpaul * Bill Paul <wpaul@ctr.columbia.edu>. All rights reserved. 412891Swpaul * 512891Swpaul * Redistribution and use in source and binary forms, with or without 612891Swpaul * modification, are permitted provided that the following conditions 712891Swpaul * are met: 812891Swpaul * 1. Redistributions of source code must retain the above copyright 912891Swpaul * notice, this list of conditions and the following disclaimer. 1012891Swpaul * 2. Redistributions in binary form must reproduce the above copyright 1112891Swpaul * notice, this list of conditions and the following disclaimer in the 1212891Swpaul * documentation and/or other materials provided with the distribution. 1312891Swpaul * 3. All advertising materials mentioning features or use of this software 1412891Swpaul * must display the following acknowledgement: 1512891Swpaul * This product includes software developed by Bill Paul. 1612891Swpaul * 4. Neither the name of the author nor the names of any co-contributors 1712891Swpaul * may be used to endorse or promote products derived from this software 1812891Swpaul * without specific prior written permission. 1912891Swpaul * 2012891Swpaul * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND 2112891Swpaul * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2212891Swpaul * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2312891Swpaul * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR CONTRIBUTORS BE LIABLE 2412891Swpaul * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2512891Swpaul * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2612891Swpaul * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2712891Swpaul * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2812891Swpaul * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2912891Swpaul * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3012891Swpaul * SUCH DAMAGE. 3112891Swpaul * 3212891Swpaul */ 3312891Swpaul 3420818Swpaul#include "yp.h" 3512891Swpaul#include "yp_extern.h" 3612891Swpaul#include <stdlib.h> 3712891Swpaul#include <dirent.h> 3812891Swpaul#include <sys/stat.h> 3912891Swpaul#include <sys/param.h> 4012891Swpaul#include <errno.h> 4112891Swpaul#include <sys/types.h> 4212891Swpaul#include <sys/socket.h> 4312891Swpaul#include <netinet/in.h> 4412891Swpaul#include <arpa/inet.h> 4512997Swpaul#include <rpc/rpc.h> 4612891Swpaul 4712891Swpaul#ifndef lint 4827589Swpaulstatic const char rcsid[] = "$Id: yp_server.c,v 1.22 1997/04/28 14:18:38 wpaul Exp $"; 4912891Swpaul#endif /* not lint */ 5012891Swpaul 5112891Swpaulint forked = 0; 5212891Swpaulint children = 0; 5319161Swpaulstatic char *master_string = "YP_MASTER_NAME"; 5419161Swpaulstatic char *order_string = "YP_LAST_MODIFIED"; 5519161Swpaulstatic int master_sz = sizeof("YP_MASTER_NAME") - 1; 5619161Swpaulstatic int order_sz = sizeof("YP_LAST_MODIFIED") - 1; 5712891Swpaul 5814262Swpaul/* 5914262Swpaul * NIS v2 support. This is where most of the action happens. 6014262Swpaul */ 6114262Swpaul 6212891Swpaulvoid * 6312891Swpaulypproc_null_2_svc(void *argp, struct svc_req *rqstp) 6412891Swpaul{ 6512891Swpaul static char * result; 6612891Swpaul static char rval = 0; 6712891Swpaul 6819161Swpaul#ifdef DB_CACHE 6919161Swpaul if (yp_access(NULL, NULL, (struct svc_req *)rqstp)) 7019161Swpaul#else 7112891Swpaul if (yp_access(NULL, (struct svc_req *)rqstp)) 7219161Swpaul#endif 7312891Swpaul return(NULL); 7412891Swpaul 7512891Swpaul result = &rval; 7612891Swpaul 7712891Swpaul return((void *) &result); 7812891Swpaul} 7912891Swpaul 8012891Swpaulbool_t * 8112891Swpaulypproc_domain_2_svc(domainname *argp, struct svc_req *rqstp) 8212891Swpaul{ 8312891Swpaul static bool_t result; 8412891Swpaul 8519161Swpaul#ifdef DB_CACHE 8619161Swpaul if (yp_access(NULL, NULL, (struct svc_req *)rqstp)) { 8719161Swpaul#else 8812891Swpaul if (yp_access(NULL, (struct svc_req *)rqstp)) { 8919161Swpaul#endif 9012891Swpaul result = FALSE; 9112891Swpaul return (&result); 9212891Swpaul } 9312891Swpaul 9412891Swpaul if (argp == NULL || yp_validdomain(*argp)) 9512891Swpaul result = FALSE; 9612891Swpaul else 9712891Swpaul result = TRUE; 9812891Swpaul 9912891Swpaul return (&result); 10012891Swpaul} 10112891Swpaul 10212891Swpaulbool_t * 10312891Swpaulypproc_domain_nonack_2_svc(domainname *argp, struct svc_req *rqstp) 10412891Swpaul{ 10512891Swpaul static bool_t result; 10612891Swpaul 10719161Swpaul#ifdef DB_CACHE 10819161Swpaul if (yp_access(NULL, NULL, (struct svc_req *)rqstp)) 10919161Swpaul#else 11012891Swpaul if (yp_access(NULL, (struct svc_req *)rqstp)) 11119161Swpaul#endif 11212891Swpaul return (NULL); 11312891Swpaul 11412891Swpaul if (argp == NULL || yp_validdomain(*argp)) 11512891Swpaul return (NULL); 11612891Swpaul else 11712891Swpaul result = TRUE; 11812891Swpaul 11912891Swpaul return (&result); 12012891Swpaul} 12112891Swpaul 12212891Swpaulypresp_val * 12312891Swpaulypproc_match_2_svc(ypreq_key *argp, struct svc_req *rqstp) 12412891Swpaul{ 12512891Swpaul static ypresp_val result; 12612891Swpaul 12714304Swpaul result.val.valdat_val = ""; 12814304Swpaul result.val.valdat_len = 0; 12919161Swpaul 13019161Swpaul#ifdef DB_CACHE 13119161Swpaul if (yp_access(argp->map, argp->domain, (struct svc_req *)rqstp)) { 13219161Swpaul#else 13312891Swpaul if (yp_access(argp->map, (struct svc_req *)rqstp)) { 13419161Swpaul#endif 13512891Swpaul result.stat = YP_YPERR; 13612891Swpaul return (&result); 13712891Swpaul } 13812891Swpaul 13912891Swpaul if (argp->domain == NULL || argp->map == NULL) { 14012891Swpaul result.stat = YP_BADARGS; 14112891Swpaul return (&result); 14212891Swpaul } 14312891Swpaul 14420818Swpaul if (yp_select_map(argp->map, argp->domain, &argp->key, 1) != YP_TRUE) { 14520818Swpaul result.stat = yp_errno; 14620818Swpaul return(&result); 14712891Swpaul } 14812891Swpaul 14920818Swpaul result.stat = yp_getbykey(&argp->key, &result.val); 15020818Swpaul 15112891Swpaul /* 15212891Swpaul * Do DNS lookups for hosts maps if database lookup failed. 15312891Swpaul */ 15412891Swpaul 15519161Swpaul#ifdef DB_CACHE 15619161Swpaul if (result.stat != YP_TRUE && 15719161Swpaul (yp_testflag(argp->map, argp->domain, YP_INTERDOMAIN) || 15819161Swpaul (strstr(argp->map, "hosts") && do_dns))) { 15919161Swpaul#else 16012891Swpaul if (do_dns && result.stat != YP_TRUE && strstr(argp->map, "hosts")) { 16119161Swpaul#endif 16227589Swpaul char nbuf[YPMAXRECORD]; 16320818Swpaul 16420818Swpaul /* NUL terminate! NUL terminate!! NUL TERMINATE!!! */ 16527589Swpaul bcopy(argp->key.keydat_val, nbuf, argp->key.keydat_len); 16627589Swpaul nbuf[argp->key.keydat_len] = '\0'; 16712891Swpaul 16812891Swpaul if (debug) 16927589Swpaul yp_error("Doing DNS lookup of %s", nbuf); 17012891Swpaul 17112891Swpaul if (!strcmp(argp->map, "hosts.byname")) 17227589Swpaul result.stat = yp_async_lookup_name(rqstp, nbuf); 17312891Swpaul else if (!strcmp(argp->map, "hosts.byaddr")) 17427589Swpaul result.stat = yp_async_lookup_addr(rqstp, nbuf); 17512891Swpaul 17620818Swpaul if (result.stat == YP_TRUE) 17720818Swpaul return(NULL); 17812891Swpaul } 17912891Swpaul 18012891Swpaul return (&result); 18112891Swpaul} 18212891Swpaul 18312891Swpaulypresp_key_val * 18412891Swpaulypproc_first_2_svc(ypreq_nokey *argp, struct svc_req *rqstp) 18512891Swpaul{ 18612891Swpaul static ypresp_key_val result; 18712891Swpaul 18814304Swpaul result.val.valdat_val = result.key.keydat_val = ""; 18914304Swpaul result.val.valdat_len = result.key.keydat_len = 0; 19019161Swpaul 19119161Swpaul#ifdef DB_CACHE 19219161Swpaul if (yp_access(argp->map, argp->domain, (struct svc_req *)rqstp)) { 19319161Swpaul#else 19412891Swpaul if (yp_access(argp->map, (struct svc_req *)rqstp)) { 19519161Swpaul#endif 19612891Swpaul result.stat = YP_YPERR; 19712891Swpaul return (&result); 19812891Swpaul } 19912891Swpaul 20012891Swpaul if (argp->domain == NULL) { 20112891Swpaul result.stat = YP_BADARGS; 20212891Swpaul return (&result); 20312891Swpaul } 20412891Swpaul 20520818Swpaul if (yp_select_map(argp->map, argp->domain, &result.key, 0) != YP_TRUE) { 20612891Swpaul result.stat = yp_errno; 20712891Swpaul return(&result); 20812891Swpaul } 20912891Swpaul 21020818Swpaul result.stat = yp_firstbykey(&result.key, &result.val); 21112891Swpaul 21212891Swpaul return (&result); 21312891Swpaul} 21412891Swpaul 21512891Swpaulypresp_key_val * 21612891Swpaulypproc_next_2_svc(ypreq_key *argp, struct svc_req *rqstp) 21712891Swpaul{ 21812891Swpaul static ypresp_key_val result; 21912891Swpaul 22014304Swpaul result.val.valdat_val = result.key.keydat_val = ""; 22114304Swpaul result.val.valdat_len = result.key.keydat_len = 0; 22215426Swpaul 22319161Swpaul#ifdef DB_CACHE 22419161Swpaul if (yp_access(argp->map, argp->domain, (struct svc_req *)rqstp)) { 22519161Swpaul#else 22612891Swpaul if (yp_access(argp->map, (struct svc_req *)rqstp)) { 22719161Swpaul#endif 22812891Swpaul result.stat = YP_YPERR; 22912891Swpaul return (&result); 23012891Swpaul } 23112891Swpaul 23212891Swpaul if (argp->domain == NULL || argp->map == NULL) { 23312891Swpaul result.stat = YP_BADARGS; 23412891Swpaul return (&result); 23512891Swpaul } 23612891Swpaul 23720818Swpaul if (yp_select_map(argp->map, argp->domain, &argp->key, 0) != YP_TRUE) { 23812891Swpaul result.stat = yp_errno; 23912891Swpaul return(&result); 24012891Swpaul } 24112891Swpaul 24220818Swpaul result.key.keydat_len = argp->key.keydat_len; 24320818Swpaul result.key.keydat_val = argp->key.keydat_val; 24412891Swpaul 24520818Swpaul result.stat = yp_nextbykey(&result.key, &result.val); 24620818Swpaul 24712891Swpaul return (&result); 24812891Swpaul} 24912891Swpaul 25012997Swpaulstatic void ypxfr_callback(rval,addr,transid,prognum,port) 25112997Swpaul ypxfrstat rval; 25212997Swpaul struct sockaddr_in *addr; 25312997Swpaul unsigned int transid; 25412997Swpaul unsigned int prognum; 25512997Swpaul unsigned long port; 25612997Swpaul{ 25712997Swpaul CLIENT *clnt; 25812997Swpaul int sock = RPC_ANYSOCK; 25912997Swpaul struct timeval timeout; 26012997Swpaul yppushresp_xfr ypxfr_resp; 26113375Swpaul struct rpc_err err; 26212997Swpaul 26313375Swpaul timeout.tv_sec = 5; 26412997Swpaul timeout.tv_usec = 0; 26512997Swpaul addr->sin_port = htons(port); 26612997Swpaul 26719131Swpaul if ((clnt = clntudp_create(addr,prognum,1,timeout,&sock)) == NULL) { 26819131Swpaul yp_error("%s: %s", inet_ntoa(addr->sin_addr), 26919161Swpaul clnt_spcreateerror("failed to establish callback handle")); 27019131Swpaul return; 27119131Swpaul } 27212997Swpaul 27312997Swpaul ypxfr_resp.status = rval; 27412997Swpaul ypxfr_resp.transid = transid; 27512997Swpaul 27613375Swpaul /* Turn the timeout off -- we don't want to block. */ 27713375Swpaul timeout.tv_sec = 0; 27813375Swpaul if (clnt_control(clnt, CLSET_TIMEOUT, (char *)&timeout) == FALSE) 27913375Swpaul yp_error("failed to set timeout on ypproc_xfr callback"); 28012997Swpaul 28113375Swpaul if (yppushproc_xfrresp_1(&ypxfr_resp, clnt) == NULL) { 28213375Swpaul clnt_geterr(clnt, &err); 28313375Swpaul if (err.re_status != RPC_SUCCESS && 28413375Swpaul err.re_status != RPC_TIMEDOUT) 28513375Swpaul yp_error("%s", clnt_sperror(clnt, 28613375Swpaul "ypxfr callback failed")); 28713375Swpaul } 28813375Swpaul 28912997Swpaul clnt_destroy(clnt); 29012997Swpaul return; 29112997Swpaul} 29212997Swpaul 29315426Swpaul#define YPXFR_RETURN(CODE) \ 29415426Swpaul /* Order is important: send regular RPC reply, then callback */ \ 29515426Swpaul result.xfrstat = CODE; \ 29615426Swpaul svc_sendreply(rqstp->rq_xprt, xdr_ypresp_xfr, (char *)&result); \ 29715426Swpaul ypxfr_callback(CODE,rqhost,argp->transid, \ 29815426Swpaul argp->prog,argp->port); \ 29915426Swpaul return(NULL); 30015426Swpaul 30112891Swpaulypresp_xfr * 30212891Swpaulypproc_xfr_2_svc(ypreq_xfr *argp, struct svc_req *rqstp) 30312891Swpaul{ 30412891Swpaul static ypresp_xfr result; 30512997Swpaul struct sockaddr_in *rqhost; 30624780Swpaul ypresp_master *mres; 30724780Swpaul ypreq_nokey mreq; 30812891Swpaul 30913375Swpaul result.transid = argp->transid; 31013375Swpaul rqhost = svc_getcaller(rqstp->rq_xprt); 31113375Swpaul 31219161Swpaul#ifdef DB_CACHE 31319161Swpaul if (yp_access(argp->map_parms.map, 31419161Swpaul argp->map_parms.domain, (struct svc_req *)rqstp)) { 31519161Swpaul#else 31612891Swpaul if (yp_access(argp->map_parms.map, (struct svc_req *)rqstp)) { 31719161Swpaul#endif 31824780Swpaul YPXFR_RETURN(YPXFR_REFUSED) 31912891Swpaul } 32012891Swpaul 32124780Swpaul 32212891Swpaul if (argp->map_parms.domain == NULL) { 32324780Swpaul YPXFR_RETURN(YPXFR_BADARGS) 32412891Swpaul } 32512891Swpaul 32612891Swpaul if (yp_validdomain(argp->map_parms.domain)) { 32724780Swpaul YPXFR_RETURN(YPXFR_NODOM) 32812891Swpaul } 32912891Swpaul 33024780Swpaul /* 33124780Swpaul * Determine the master host ourselves. The caller may 33224780Swpaul * be up to no good. This has the side effect of verifying 33324780Swpaul * that the requested map and domain actually exist. 33424780Swpaul */ 33524780Swpaul 33624780Swpaul mreq.domain = argp->map_parms.domain; 33724780Swpaul mreq.map = argp->map_parms.map; 33824780Swpaul 33924780Swpaul mres = ypproc_master_2_svc(&mreq, rqstp); 34024780Swpaul 34124780Swpaul if (mres->stat != YP_TRUE) { 34224780Swpaul yp_error("couldn't find master for map %s@%s", 34324780Swpaul argp->map_parms.map, 34424780Swpaul argp->map_parms.domain); 34524780Swpaul yp_error("host at %s (%s) may be pulling my leg", 34624780Swpaul argp->map_parms.peer, 34724780Swpaul inet_ntoa(rqhost->sin_addr)); 34824780Swpaul YPXFR_RETURN(YPXFR_REFUSED) 34924780Swpaul } 35024780Swpaul 35112891Swpaul switch(fork()) { 35212891Swpaul case 0: 35312891Swpaul { 35412891Swpaul char g[11], t[11], p[11]; 35512891Swpaul char ypxfr_command[MAXPATHLEN + 2]; 35612891Swpaul 35712891Swpaul sprintf (ypxfr_command, "%sypxfr", _PATH_LIBEXEC); 35812891Swpaul sprintf (t, "%u", argp->transid); 35912891Swpaul sprintf (g, "%u", argp->prog); 36012891Swpaul sprintf (p, "%u", argp->port); 36122321Swpaul if (debug) { 36212997Swpaul close(0); close(1); close(2); 36322321Swpaul } 36412997Swpaul if (strcmp(yp_dir, _PATH_YP)) { 36514304Swpaul execl(ypxfr_command, "ypxfr", 36614304Swpaul "-d", argp->map_parms.domain, 36724780Swpaul "-h", mres->peer, 36814304Swpaul "-p", yp_dir, "-C", t, 36914304Swpaul g, inet_ntoa(rqhost->sin_addr), 37014304Swpaul p, argp->map_parms.map, 37112997Swpaul NULL); 37212997Swpaul } else { 37314304Swpaul execl(ypxfr_command, "ypxfr", 37414304Swpaul "-d", argp->map_parms.domain, 37524780Swpaul "-h", mres->peer, 37614304Swpaul "-C", t, 37714304Swpaul g, inet_ntoa(rqhost->sin_addr), 37814304Swpaul p, argp->map_parms.map, 37912997Swpaul NULL); 38012997Swpaul } 38112997Swpaul forked++; 38215426Swpaul yp_error("ypxfr execl(%s): %s", ypxfr_command, strerror(errno)); 38324780Swpaul YPXFR_RETURN(YPXFR_XFRERR) 38412997Swpaul break; 38512891Swpaul } 38612891Swpaul case -1: 38712891Swpaul yp_error("ypxfr fork(): %s", strerror(errno)); 38824780Swpaul YPXFR_RETURN(YPXFR_XFRERR) 38912891Swpaul break; 39012891Swpaul default: 39113375Swpaul result.xfrstat = YPXFR_SUCC; 39212997Swpaul children++; 39312997Swpaul forked = 0; 39412891Swpaul break; 39512891Swpaul } 39613375Swpaul 39713375Swpaul return (&result); 39812891Swpaul} 39915426Swpaul#undef YPXFR_RETURN 40012891Swpaul 40112891Swpaulvoid * 40212891Swpaulypproc_clear_2_svc(void *argp, struct svc_req *rqstp) 40312891Swpaul{ 40412891Swpaul static char * result; 40512891Swpaul static char rval = 0; 40612891Swpaul 40719161Swpaul#ifdef DB_CACHE 40819161Swpaul if (yp_access(NULL, NULL, (struct svc_req *)rqstp)) 40919161Swpaul#else 41012891Swpaul if (yp_access(NULL, (struct svc_req *)rqstp)) 41119161Swpaul#endif 41212891Swpaul return (NULL); 41315426Swpaul#ifdef DB_CACHE 41415426Swpaul /* clear out the database cache */ 41515426Swpaul yp_flush_all(); 41615426Swpaul#endif 41714240Swpaul /* Re-read the securenets database for the hell of it. */ 41814240Swpaul load_securenets(); 41914240Swpaul 42012891Swpaul result = &rval; 42112891Swpaul return((void *) &result); 42212891Swpaul} 42312891Swpaul 42412891Swpaul/* 42512891Swpaul * For ypproc_all, we have to send a stream of ypresp_all structures 42612891Swpaul * via TCP, but the XDR filter generated from the yp.x protocol 42712891Swpaul * definition file only serializes one such structure. This means that 42812891Swpaul * to send the whole stream, you need a wrapper which feeds all the 42912891Swpaul * records into the underlying XDR routine until it hits an 'EOF.' 43012891Swpaul * But to use the wrapper, you have to violate the boundaries between 43112891Swpaul * RPC layers by calling svc_sendreply() directly from the ypproc_all 43212891Swpaul * service routine instead of letting the RPC dispatcher do it. 43312891Swpaul * 43412891Swpaul * Bleah. 43512891Swpaul */ 43612891Swpaul 43712891Swpaul/* 43820100Swpaul * Custom XDR routine for serialzing results of ypproc_all: keep 43920100Swpaul * reading from the database and spew until we run out of records 44020100Swpaul * or encounter an error. 44112891Swpaul */ 44212891Swpaulstatic bool_t 44312891Swpaulxdr_my_ypresp_all(register XDR *xdrs, ypresp_all *objp) 44412891Swpaul{ 44520100Swpaul while (1) { 44620100Swpaul /* Get a record. */ 44720100Swpaul if ((objp->ypresp_all_u.val.stat = 44820818Swpaul yp_nextbykey(&objp->ypresp_all_u.val.key, 44920818Swpaul &objp->ypresp_all_u.val.val)) == YP_TRUE) { 45020100Swpaul objp->more = TRUE; 45120100Swpaul } else { 45220100Swpaul objp->more = FALSE; 45320100Swpaul } 45420100Swpaul 45520100Swpaul /* Serialize. */ 45620100Swpaul if (!xdr_ypresp_all(xdrs, objp)) 45720100Swpaul return(FALSE); 45820100Swpaul if (objp->more == FALSE) 45920100Swpaul return(TRUE); 46020100Swpaul } 46112891Swpaul} 46212891Swpaul 46312891Swpaulypresp_all * 46412891Swpaulypproc_all_2_svc(ypreq_nokey *argp, struct svc_req *rqstp) 46512891Swpaul{ 46612891Swpaul static ypresp_all result; 46712891Swpaul 46812891Swpaul /* 46912891Swpaul * Set this here so that the client will be forced to make 47012891Swpaul * at least one attempt to read from us even if all we're 47112891Swpaul * doing is returning an error. 47212891Swpaul */ 47312891Swpaul result.more = TRUE; 47414304Swpaul result.ypresp_all_u.val.key.keydat_len = 0; 47514304Swpaul result.ypresp_all_u.val.key.keydat_val = ""; 47612891Swpaul 47719161Swpaul#ifdef DB_CACHE 47819161Swpaul if (yp_access(argp->map, argp->domain, (struct svc_req *)rqstp)) { 47919161Swpaul#else 48012891Swpaul if (yp_access(argp->map, (struct svc_req *)rqstp)) { 48119161Swpaul#endif 48212891Swpaul result.ypresp_all_u.val.stat = YP_YPERR; 48312891Swpaul return (&result); 48412891Swpaul } 48512891Swpaul 48612891Swpaul if (argp->domain == NULL || argp->map == NULL) { 48712891Swpaul result.ypresp_all_u.val.stat = YP_BADARGS; 48812891Swpaul return (&result); 48912891Swpaul } 49012891Swpaul 49120100Swpaul /* 49221389Swpaul * XXX If we hit the child limit, fail the request. 49321389Swpaul * If we don't, and the map is large, we could block for 49421389Swpaul * a long time in the parent. 49521389Swpaul */ 49621389Swpaul if (children >= MAX_CHILDREN) { 49721389Swpaul result.ypresp_all_u.val.stat = YP_YPERR; 49821389Swpaul return(&result); 49921389Swpaul } 50021389Swpaul 50121389Swpaul /* 50220100Swpaul * The ypproc_all procedure can take a while to complete. 50320100Swpaul * Best to handle it in a subprocess so the parent doesn't 50420100Swpaul * block. (Is there a better way to do this? Maybe with 50520100Swpaul * async socket I/O?) 50620100Swpaul */ 50720100Swpaul if (!debug && children < MAX_CHILDREN && fork()) { 50820100Swpaul children++; 50920100Swpaul forked = 0; 51020100Swpaul return (NULL); 51120100Swpaul } else { 51220100Swpaul forked++; 51320100Swpaul } 51420100Swpaul 51520818Swpaul if (yp_select_map(argp->map, argp->domain, 51620818Swpaul &result.ypresp_all_u.val.key, 0) != YP_TRUE) { 51712891Swpaul result.ypresp_all_u.val.stat = yp_errno; 51812891Swpaul return(&result); 51912891Swpaul } 52012891Swpaul 52112891Swpaul /* Kick off the actual data transfer. */ 52220100Swpaul svc_sendreply(rqstp->rq_xprt, xdr_my_ypresp_all, (char *)&result); 52320100Swpaul 52412891Swpaul /* 52512891Swpaul * Returning NULL prevents the dispatcher from calling 52612891Swpaul * svc_sendreply() since we already did it. 52712891Swpaul */ 52812891Swpaul return (NULL); 52912891Swpaul} 53012891Swpaul 53112891Swpaulypresp_master * 53212891Swpaulypproc_master_2_svc(ypreq_nokey *argp, struct svc_req *rqstp) 53312891Swpaul{ 53412891Swpaul static ypresp_master result; 53515426Swpaul static char ypvalbuf[YPMAXRECORD]; 53620818Swpaul keydat key = { master_sz, master_string }; 53720818Swpaul valdat val; 53812891Swpaul 53914303Swpaul result.peer = ""; 54014303Swpaul 54119161Swpaul#ifdef DB_CACHE 54219161Swpaul if (yp_access(argp->map, argp->domain, (struct svc_req *)rqstp)) { 54319161Swpaul#else 54419161Swpaul if (yp_access(argp->map, (struct svc_req *)rqstp)) { 54519161Swpaul#endif 54612891Swpaul result.stat = YP_YPERR; 54712891Swpaul return(&result); 54812891Swpaul } 54912891Swpaul 55012891Swpaul if (argp->domain == NULL) { 55112891Swpaul result.stat = YP_BADARGS; 55212891Swpaul return (&result); 55312891Swpaul } 55412891Swpaul 55520818Swpaul if (yp_select_map(argp->map, argp->domain, &key, 1) != YP_TRUE) { 55620818Swpaul result.stat = yp_errno; 55720818Swpaul return(&result); 55820818Swpaul } 55920818Swpaul 56015426Swpaul /* 56115426Swpaul * Note that we copy the data retrieved from the database to 56215426Swpaul * a private buffer and NUL terminate the buffer rather than 56315426Swpaul * terminating the data in place. We do this because by stuffing 56415426Swpaul * a '\0' into data.data, we will actually be corrupting memory 56515426Swpaul * allocated by the DB package. This is a bad thing now that we 56615426Swpaul * cache DB handles rather than closing the database immediately. 56715426Swpaul */ 56820818Swpaul result.stat = yp_getbykey(&key, &val); 56920818Swpaul if (result.stat == YP_TRUE) { 57020818Swpaul bcopy((char *)val.valdat_val, (char *)&ypvalbuf, 57120818Swpaul val.valdat_len); 57220818Swpaul ypvalbuf[val.valdat_len] = '\0'; 57315426Swpaul result.peer = (char *)&ypvalbuf; 57412891Swpaul } else 57512891Swpaul result.peer = ""; 57612891Swpaul 57712891Swpaul return (&result); 57812891Swpaul} 57912891Swpaul 58012891Swpaulypresp_order * 58112891Swpaulypproc_order_2_svc(ypreq_nokey *argp, struct svc_req *rqstp) 58212891Swpaul{ 58312891Swpaul static ypresp_order result; 58420818Swpaul keydat key = { order_sz, order_string }; 58520818Swpaul valdat val; 58612891Swpaul 58714304Swpaul result.ordernum = 0; 58814304Swpaul 58919161Swpaul#ifdef DB_CACHE 59019161Swpaul if (yp_access(argp->map, argp->domain, (struct svc_req *)rqstp)) { 59119161Swpaul#else 59219161Swpaul if (yp_access(argp->map, (struct svc_req *)rqstp)) { 59319161Swpaul#endif 59412891Swpaul result.stat = YP_YPERR; 59512891Swpaul return(&result); 59612891Swpaul } 59712891Swpaul 59812891Swpaul if (argp->domain == NULL) { 59912891Swpaul result.stat = YP_BADARGS; 60012891Swpaul return (&result); 60112891Swpaul } 60212891Swpaul 60312891Swpaul /* 60412891Swpaul * We could just check the timestamp on the map file, 60512891Swpaul * but that's a hack: we'll only know the last time the file 60612891Swpaul * was touched, not the last time the database contents were 60712891Swpaul * updated. 60812891Swpaul */ 60912891Swpaul 61020818Swpaul if (yp_select_map(argp->map, argp->domain, &key, 1) != YP_TRUE) { 61120818Swpaul result.stat = yp_errno; 61220818Swpaul return(&result); 61320818Swpaul } 61420818Swpaul 61520818Swpaul result.stat = yp_getbykey(&key, &val); 61620818Swpaul 61720818Swpaul if (result.stat == YP_TRUE) 61820818Swpaul result.ordernum = atoi((char *)val.valdat_val); 61912891Swpaul else 62012891Swpaul result.ordernum = 0; 62112891Swpaul 62212891Swpaul return (&result); 62312891Swpaul} 62412891Swpaul 62512891Swpaulstatic void yp_maplist_free(yp_maplist) 62612891Swpaul struct ypmaplist *yp_maplist; 62712891Swpaul{ 62812891Swpaul register struct ypmaplist *next; 62912891Swpaul 63012891Swpaul while(yp_maplist) { 63112891Swpaul next = yp_maplist->next; 63212891Swpaul free(yp_maplist->map); 63312891Swpaul free(yp_maplist); 63412891Swpaul yp_maplist = next; 63512891Swpaul } 63612891Swpaul return; 63712891Swpaul} 63812891Swpaul 63912891Swpaulstatic struct ypmaplist *yp_maplist_create(domain) 64012891Swpaul const char *domain; 64112891Swpaul{ 64212891Swpaul char yp_mapdir[MAXPATHLEN + 2]; 64312891Swpaul char yp_mapname[MAXPATHLEN + 2]; 64412891Swpaul struct ypmaplist *cur = NULL; 64512891Swpaul struct ypmaplist *yp_maplist = NULL; 64612891Swpaul DIR *dird; 64712891Swpaul struct dirent *dirp; 64812891Swpaul struct stat statbuf; 64912891Swpaul 65012891Swpaul snprintf(yp_mapdir, sizeof(yp_mapdir), "%s/%s", yp_dir, domain); 65112891Swpaul 65212891Swpaul if ((dird = opendir(yp_mapdir)) == NULL) { 65313800Swpaul yp_error("opendir(%s) failed: %s", yp_mapdir, strerror(errno)); 65412891Swpaul return(NULL); 65512891Swpaul } 65612891Swpaul 65712891Swpaul while ((dirp = readdir(dird)) != NULL) { 65812891Swpaul if (strcmp(dirp->d_name, ".") && strcmp(dirp->d_name, "..")) { 65914304Swpaul snprintf(yp_mapname, sizeof(yp_mapname), "%s/%s", 66014304Swpaul yp_mapdir,dirp->d_name); 66114304Swpaul if (stat(yp_mapname, &statbuf) < 0 || 66214304Swpaul !S_ISREG(statbuf.st_mode)) 66312891Swpaul continue; 66414304Swpaul if ((cur = (struct ypmaplist *) 66516044Swpaul malloc(sizeof(struct ypmaplist))) == NULL) { 66614304Swpaul yp_error("malloc() failed: %s",strerror(errno)); 66712891Swpaul closedir(dird); 66812891Swpaul yp_maplist_free(yp_maplist); 66912891Swpaul return(NULL); 67012891Swpaul } 67112891Swpaul if ((cur->map = (char *)strdup(dirp->d_name)) == NULL) { 67214304Swpaul yp_error("strdup() failed: %s",strerror(errno)); 67312891Swpaul closedir(dird); 67412891Swpaul yp_maplist_free(yp_maplist); 67512891Swpaul return(NULL); 67612891Swpaul } 67712891Swpaul cur->next = yp_maplist; 67812891Swpaul yp_maplist = cur; 67912891Swpaul if (debug) 68012891Swpaul yp_error("map: %s", yp_maplist->map); 68112891Swpaul } 68212891Swpaul 68312891Swpaul } 68412891Swpaul closedir(dird); 68512891Swpaul return(yp_maplist); 68612891Swpaul} 68712891Swpaul 68812891Swpaulypresp_maplist * 68912891Swpaulypproc_maplist_2_svc(domainname *argp, struct svc_req *rqstp) 69012891Swpaul{ 69115426Swpaul static ypresp_maplist result = { 0, NULL }; 69212891Swpaul 69319161Swpaul#ifdef DB_CACHE 69419161Swpaul if (yp_access(NULL, NULL, (struct svc_req *)rqstp)) { 69519161Swpaul#else 69612891Swpaul if (yp_access(NULL, (struct svc_req *)rqstp)) { 69719161Swpaul#endif 69812891Swpaul result.stat = YP_YPERR; 69912891Swpaul return(&result); 70012891Swpaul } 70112891Swpaul 70212891Swpaul if (argp == NULL) { 70312891Swpaul result.stat = YP_BADARGS; 70412891Swpaul return (&result); 70512891Swpaul } 70612891Swpaul 70712891Swpaul if (yp_validdomain(*argp)) { 70812891Swpaul result.stat = YP_NODOM; 70912891Swpaul return (&result); 71012891Swpaul } 71112891Swpaul 71212891Swpaul /* 71312891Swpaul * We have to construct a linked list for the ypproc_maplist 71412891Swpaul * procedure using dynamically allocated memory. Since the XDR 71512891Swpaul * layer won't free this list for us, we have to deal with it 71612891Swpaul * ourselves. We call yp_maplist_free() first to free any 71712891Swpaul * previously allocated data we may have accumulated to insure 71812891Swpaul * that we have only one linked list in memory at any given 71912891Swpaul * time. 72012891Swpaul */ 72112891Swpaul 72212891Swpaul yp_maplist_free(result.maps); 72312891Swpaul 72412891Swpaul if ((result.maps = yp_maplist_create(*argp)) == NULL) { 72512891Swpaul yp_error("yp_maplist_create failed"); 72612891Swpaul result.stat = YP_YPERR; 72712891Swpaul return(&result); 72812891Swpaul } else 72912891Swpaul result.stat = YP_TRUE; 73012891Swpaul 73112891Swpaul return (&result); 73212891Swpaul} 73314262Swpaul 73414262Swpaul/* 73514262Swpaul * NIS v1 support. The nullproc, domain and domain_nonack 73614262Swpaul * functions from v1 are identical to those in v2, so all 73714262Swpaul * we have to do is hand off to them. 73814262Swpaul * 73914262Swpaul * The other functions are mostly just wrappers around their v2 74014262Swpaul * counterparts. For example, for the v1 'match' procedure, we 74114262Swpaul * crack open the argument structure, make a request to the v2 74214262Swpaul * 'match' function, repackage the data into a v1 response and 74314262Swpaul * then send it on its way. 74414262Swpaul * 74514262Swpaul * Note that we don't support the pull, push and get procedures. 74614262Swpaul * There's little documentation available to show what they 74714262Swpaul * do, and I suspect they're meant largely for map transfers 74814262Swpaul * between master and slave servers. 74914262Swpaul */ 75014262Swpaul 75114262Swpaulvoid * 75214262Swpaulypoldproc_null_1_svc(void *argp, struct svc_req *rqstp) 75314262Swpaul{ 75414262Swpaul return(ypproc_null_2_svc(argp, rqstp)); 75514262Swpaul} 75614262Swpaul 75714262Swpaulbool_t * 75814262Swpaulypoldproc_domain_1_svc(domainname *argp, struct svc_req *rqstp) 75914262Swpaul{ 76014262Swpaul return(ypproc_domain_2_svc(argp, rqstp)); 76114262Swpaul} 76214262Swpaul 76314262Swpaulbool_t * 76414262Swpaulypoldproc_domain_nonack_1_svc(domainname *argp, struct svc_req *rqstp) 76514262Swpaul{ 76614262Swpaul return (ypproc_domain_nonack_2_svc(argp, rqstp)); 76714262Swpaul} 76814262Swpaul 76914304Swpaul/* 77014304Swpaul * the 'match' procedure sends a response of type YPRESP_VAL 77114304Swpaul */ 77214262Swpaulypresponse * 77314262Swpaulypoldproc_match_1_svc(yprequest *argp, struct svc_req *rqstp) 77414262Swpaul{ 77514262Swpaul static ypresponse result; 77614262Swpaul ypresp_val *v2_result; 77714262Swpaul 77814262Swpaul result.yp_resptype = YPRESP_VAL; 77914304Swpaul result.ypresponse_u.yp_resp_valtype.val.valdat_val = ""; 78014304Swpaul result.ypresponse_u.yp_resp_valtype.val.valdat_len = 0; 78114262Swpaul 78214262Swpaul if (argp->yp_reqtype != YPREQ_KEY) { 78314262Swpaul result.ypresponse_u.yp_resp_valtype.stat = YP_BADARGS; 78414262Swpaul return(&result); 78514262Swpaul } 78614262Swpaul 78714262Swpaul v2_result = ypproc_match_2_svc(&argp->yprequest_u.yp_req_keytype,rqstp); 78814262Swpaul if (v2_result == NULL) 78914262Swpaul return(NULL); 79014262Swpaul 79114262Swpaul bcopy((char *)v2_result, 79214262Swpaul (char *)&result.ypresponse_u.yp_resp_valtype, 79314262Swpaul sizeof(ypresp_val)); 79414262Swpaul 79514262Swpaul return (&result); 79614262Swpaul} 79714262Swpaul 79814304Swpaul/* 79914304Swpaul * the 'first' procedure sends a response of type YPRESP_KEY_VAL 80014304Swpaul */ 80114262Swpaulypresponse * 80214262Swpaulypoldproc_first_1_svc(yprequest *argp, struct svc_req *rqstp) 80314262Swpaul{ 80414262Swpaul static ypresponse result; 80514262Swpaul ypresp_key_val *v2_result; 80614262Swpaul 80714262Swpaul result.yp_resptype = YPRESP_KEY_VAL; 80814304Swpaul result.ypresponse_u.yp_resp_key_valtype.val.valdat_val = 80914304Swpaul result.ypresponse_u.yp_resp_key_valtype.key.keydat_val = ""; 81014304Swpaul result.ypresponse_u.yp_resp_key_valtype.val.valdat_len = 81114304Swpaul result.ypresponse_u.yp_resp_key_valtype.key.keydat_len = 0; 81214262Swpaul 81314262Swpaul if (argp->yp_reqtype != YPREQ_NOKEY) { 81414262Swpaul result.ypresponse_u.yp_resp_key_valtype.stat = YP_BADARGS; 81514262Swpaul return(&result); 81614262Swpaul } 81714262Swpaul 81814262Swpaul v2_result = ypproc_first_2_svc(&argp->yprequest_u.yp_req_nokeytype, 81914262Swpaul rqstp); 82014262Swpaul if (v2_result == NULL) 82114262Swpaul return(NULL); 82214262Swpaul 82314262Swpaul bcopy((char *)v2_result, 82414262Swpaul (char *)&result.ypresponse_u.yp_resp_key_valtype, 82514262Swpaul sizeof(ypresp_key_val)); 82614262Swpaul 82714262Swpaul return (&result); 82814262Swpaul} 82914262Swpaul 83014304Swpaul/* 83114304Swpaul * the 'next' procedure sends a response of type YPRESP_KEY_VAL 83214304Swpaul */ 83314262Swpaulypresponse * 83414262Swpaulypoldproc_next_1_svc(yprequest *argp, struct svc_req *rqstp) 83514262Swpaul{ 83614262Swpaul static ypresponse result; 83714262Swpaul ypresp_key_val *v2_result; 83814262Swpaul 83914262Swpaul result.yp_resptype = YPRESP_KEY_VAL; 84014304Swpaul result.ypresponse_u.yp_resp_key_valtype.val.valdat_val = 84114304Swpaul result.ypresponse_u.yp_resp_key_valtype.key.keydat_val = ""; 84214304Swpaul result.ypresponse_u.yp_resp_key_valtype.val.valdat_len = 84314304Swpaul result.ypresponse_u.yp_resp_key_valtype.key.keydat_len = 0; 84414262Swpaul 84514262Swpaul if (argp->yp_reqtype != YPREQ_KEY) { 84614262Swpaul result.ypresponse_u.yp_resp_key_valtype.stat = YP_BADARGS; 84714262Swpaul return(&result); 84814262Swpaul } 84914262Swpaul 85014262Swpaul v2_result = ypproc_next_2_svc(&argp->yprequest_u.yp_req_keytype,rqstp); 85114262Swpaul if (v2_result == NULL) 85214262Swpaul return(NULL); 85314262Swpaul 85414262Swpaul bcopy((char *)v2_result, 85514262Swpaul (char *)&result.ypresponse_u.yp_resp_key_valtype, 85614262Swpaul sizeof(ypresp_key_val)); 85714262Swpaul 85814262Swpaul return (&result); 85914262Swpaul} 86014262Swpaul 86114304Swpaul/* 86214304Swpaul * the 'poll' procedure sends a response of type YPRESP_MAP_PARMS 86314304Swpaul */ 86414262Swpaulypresponse * 86514262Swpaulypoldproc_poll_1_svc(yprequest *argp, struct svc_req *rqstp) 86614262Swpaul{ 86714262Swpaul static ypresponse result; 86814262Swpaul ypresp_master *v2_result1; 86914262Swpaul ypresp_order *v2_result2; 87014262Swpaul 87114262Swpaul result.yp_resptype = YPRESP_MAP_PARMS; 87214262Swpaul result.ypresponse_u.yp_resp_map_parmstype.domain = 87314262Swpaul argp->yprequest_u.yp_req_nokeytype.domain; 87414262Swpaul result.ypresponse_u.yp_resp_map_parmstype.map = 87514262Swpaul argp->yprequest_u.yp_req_nokeytype.map; 87614262Swpaul /* 87714262Swpaul * Hmm... there is no 'status' value in the 87814262Swpaul * yp_resp_map_parmstype structure, so I have to 87914262Swpaul * guess at what to do to indicate a failure. 88014262Swpaul * I hope this is right. 88114262Swpaul */ 88214262Swpaul result.ypresponse_u.yp_resp_map_parmstype.ordernum = 0; 88314262Swpaul result.ypresponse_u.yp_resp_map_parmstype.peer = ""; 88414262Swpaul 88514262Swpaul if (argp->yp_reqtype != YPREQ_MAP_PARMS) { 88614262Swpaul return(&result); 88714262Swpaul } 88814262Swpaul 88914262Swpaul v2_result1 = ypproc_master_2_svc(&argp->yprequest_u.yp_req_nokeytype, 89014262Swpaul rqstp); 89114262Swpaul if (v2_result1 == NULL) 89214262Swpaul return(NULL); 89314262Swpaul 89414262Swpaul if (v2_result1->stat != YP_TRUE) { 89514262Swpaul return(&result); 89614262Swpaul } 89714262Swpaul 89814262Swpaul v2_result2 = ypproc_order_2_svc(&argp->yprequest_u.yp_req_nokeytype, 89914262Swpaul rqstp); 90014262Swpaul if (v2_result2 == NULL) 90114262Swpaul return(NULL); 90214262Swpaul 90314262Swpaul if (v2_result2->stat != YP_TRUE) { 90414262Swpaul return(&result); 90514262Swpaul } 90614262Swpaul 90714262Swpaul result.ypresponse_u.yp_resp_map_parmstype.peer = 90814262Swpaul v2_result1->peer; 90914262Swpaul result.ypresponse_u.yp_resp_map_parmstype.ordernum = 91014262Swpaul v2_result2->ordernum; 91114262Swpaul 91214262Swpaul return (&result); 91314262Swpaul} 91414262Swpaul 91514262Swpaulypresponse * 91614262Swpaulypoldproc_push_1_svc(yprequest *argp, struct svc_req *rqstp) 91714262Swpaul{ 91814262Swpaul static ypresponse result; 91914262Swpaul 92014262Swpaul /* 92114262Swpaul * Not implemented. 92214262Swpaul */ 92314262Swpaul 92414262Swpaul return (&result); 92514262Swpaul} 92614262Swpaul 92714262Swpaulypresponse * 92814262Swpaulypoldproc_pull_1_svc(yprequest *argp, struct svc_req *rqstp) 92914262Swpaul{ 93014262Swpaul static ypresponse result; 93114262Swpaul 93214262Swpaul /* 93314262Swpaul * Not implemented. 93414262Swpaul */ 93514262Swpaul 93614262Swpaul return (&result); 93714262Swpaul} 93814262Swpaul 93914262Swpaulypresponse * 94014262Swpaulypoldproc_get_1_svc(yprequest *argp, struct svc_req *rqstp) 94114262Swpaul{ 94214262Swpaul static ypresponse result; 94314262Swpaul 94414262Swpaul /* 94514262Swpaul * Not implemented. 94614262Swpaul */ 94714262Swpaul 94814262Swpaul return (&result); 94914262Swpaul} 950