yp_server.c revision 15426
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 3412891Swpaul#include "yp_extern.h" 3512891Swpaul#include "yp.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 4815426Swpaulstatic char rcsid[] = "$Id: yp_server.c,v 1.5 1996/04/26 04:35:53 wpaul Exp wpaul $"; 4912891Swpaul#endif /* not lint */ 5012891Swpaul 5112891Swpaulint forked = 0; 5212891Swpaulint children = 0; 5312891SwpaulDB *spec_dbp = NULL; /* Special global DB handle for ypproc_all. */ 5415426Swpaulchar *master_string = "YP_MASTER_NAME"; 5515426Swpaulchar *order_string = "YP_LAST_MODIFIED"; 5612891Swpaul 5715426Swpaul#define YP_ALL_TIMEOUT 10 5815426Swpaul 5915426Swpaulstatic int yp_all_timed_out = 0; 6015426Swpaul 6114262Swpaul/* 6214262Swpaul * NIS v2 support. This is where most of the action happens. 6314262Swpaul */ 6414262Swpaul 6512891Swpaulvoid * 6612891Swpaulypproc_null_2_svc(void *argp, struct svc_req *rqstp) 6712891Swpaul{ 6812891Swpaul static char * result; 6912891Swpaul static char rval = 0; 7012891Swpaul 7112891Swpaul if (yp_access(NULL, (struct svc_req *)rqstp)) 7212891Swpaul return(NULL); 7312891Swpaul 7412891Swpaul result = &rval; 7512891Swpaul 7612891Swpaul return((void *) &result); 7712891Swpaul} 7812891Swpaul 7912891Swpaulbool_t * 8012891Swpaulypproc_domain_2_svc(domainname *argp, struct svc_req *rqstp) 8112891Swpaul{ 8212891Swpaul static bool_t result; 8312891Swpaul 8412891Swpaul if (yp_access(NULL, (struct svc_req *)rqstp)) { 8512891Swpaul result = FALSE; 8612891Swpaul return (&result); 8712891Swpaul } 8812891Swpaul 8912891Swpaul if (argp == NULL || yp_validdomain(*argp)) 9012891Swpaul result = FALSE; 9112891Swpaul else 9212891Swpaul result = TRUE; 9312891Swpaul 9412891Swpaul return (&result); 9512891Swpaul} 9612891Swpaul 9712891Swpaulbool_t * 9812891Swpaulypproc_domain_nonack_2_svc(domainname *argp, struct svc_req *rqstp) 9912891Swpaul{ 10012891Swpaul static bool_t result; 10112891Swpaul 10212891Swpaul if (yp_access(NULL, (struct svc_req *)rqstp)) 10312891Swpaul return (NULL); 10412891Swpaul 10512891Swpaul if (argp == NULL || yp_validdomain(*argp)) 10612891Swpaul return (NULL); 10712891Swpaul else 10812891Swpaul result = TRUE; 10912891Swpaul 11012891Swpaul return (&result); 11112891Swpaul} 11212891Swpaul 11312891Swpaulypresp_val * 11412891Swpaulypproc_match_2_svc(ypreq_key *argp, struct svc_req *rqstp) 11512891Swpaul{ 11612891Swpaul static ypresp_val result; 11712891Swpaul DBT key, data; 11812891Swpaul 11914304Swpaul result.val.valdat_val = ""; 12014304Swpaul result.val.valdat_len = 0; 12114304Swpaul 12212891Swpaul if (yp_access(argp->map, (struct svc_req *)rqstp)) { 12312891Swpaul result.stat = YP_YPERR; 12412891Swpaul return (&result); 12512891Swpaul } 12612891Swpaul 12712891Swpaul if (argp->domain == NULL || argp->map == NULL) { 12812891Swpaul result.stat = YP_BADARGS; 12912891Swpaul return (&result); 13012891Swpaul } 13112891Swpaul 13212891Swpaul key.size = argp->key.keydat_len; 13312891Swpaul key.data = argp->key.keydat_val; 13412891Swpaul 13515426Swpaul if ((result.stat = yp_get_record(argp->domain, argp->map, 13615426Swpaul &key, &data, 1)) == YP_TRUE) { 13712891Swpaul result.val.valdat_len = data.size; 13812891Swpaul result.val.valdat_val = data.data; 13912891Swpaul } 14012891Swpaul 14112891Swpaul /* 14212891Swpaul * Do DNS lookups for hosts maps if database lookup failed. 14312891Swpaul */ 14412891Swpaul 14512891Swpaul if (do_dns && result.stat != YP_TRUE && strstr(argp->map, "hosts")) { 14612997Swpaul char *rval = NULL; 14712891Swpaul 14812891Swpaul /* DNS lookups can take time -- do them in a subprocess */ 14912891Swpaul 15012891Swpaul if (!debug && children < MAX_CHILDREN && fork()) { 15112891Swpaul children++; 15212891Swpaul forked = 0; 15312891Swpaul /* 15412891Swpaul * Returning NULL here prevents svc_sendreply() 15512891Swpaul * from being called by the parent. This is vital 15612891Swpaul * since having both the parent and the child process 15712891Swpaul * call it would confuse the client. 15812891Swpaul */ 15912891Swpaul return (NULL); 16012891Swpaul } else { 16112891Swpaul forked++; 16212891Swpaul } 16312891Swpaul 16412891Swpaul if (debug) 16512891Swpaul yp_error("Doing DNS lookup of %.*s", 16612891Swpaul argp->key.keydat_len, 16712891Swpaul argp->key.keydat_val); 16812891Swpaul 16912891Swpaul /* NUL terminate! NUL terminate!! NUL TERMINATE!!! */ 17012891Swpaul argp->key.keydat_val[argp->key.keydat_len] = '\0'; 17112891Swpaul 17212891Swpaul if (!strcmp(argp->map, "hosts.byname")) 17312891Swpaul rval = yp_dnsname((char *)argp->key.keydat_val); 17412891Swpaul else if (!strcmp(argp->map, "hosts.byaddr")) 17512891Swpaul rval = yp_dnsaddr((const char *)argp->key.keydat_val); 17612891Swpaul 17712891Swpaul 17812891Swpaul if (rval) { 17912891Swpaul if (debug) 18014304Swpaul yp_error("DNS lookup successful. Result: %s", 18114304Swpaul rval); 18212891Swpaul result.val.valdat_len = strlen(rval); 18312891Swpaul result.val.valdat_val = rval; 18412891Swpaul result.stat = YP_TRUE; 18512891Swpaul } else { 18612891Swpaul if (debug) 18712891Swpaul yp_error("DNS lookup failed."); 18812891Swpaul result.stat = YP_NOKEY; 18912891Swpaul } 19012891Swpaul } 19112891Swpaul 19212891Swpaul return (&result); 19312891Swpaul} 19412891Swpaul 19512891Swpaulypresp_key_val * 19612891Swpaulypproc_first_2_svc(ypreq_nokey *argp, struct svc_req *rqstp) 19712891Swpaul{ 19812891Swpaul static ypresp_key_val result; 19912891Swpaul DBT key, data; 20012891Swpaul DB *dbp; 20112891Swpaul 20214304Swpaul result.val.valdat_val = result.key.keydat_val = ""; 20314304Swpaul result.val.valdat_len = result.key.keydat_len = 0; 20414304Swpaul 20512891Swpaul if (yp_access(argp->map, (struct svc_req *)rqstp)) { 20612891Swpaul result.stat = YP_YPERR; 20712891Swpaul return (&result); 20812891Swpaul } 20912891Swpaul 21012891Swpaul if (argp->domain == NULL) { 21112891Swpaul result.stat = YP_BADARGS; 21212891Swpaul return (&result); 21312891Swpaul } 21412891Swpaul 21515426Swpaul#ifdef DB_CACHE 21615426Swpaul if ((dbp = yp_open_db_cache(argp->domain, argp->map, NULL, 0)) == NULL) { 21715426Swpaul#else 21812891Swpaul if ((dbp = yp_open_db(argp->domain, argp->map)) == NULL) { 21915426Swpaul#endif 22012891Swpaul result.stat = yp_errno; 22112891Swpaul return(&result); 22212891Swpaul } 22312891Swpaul 22412891Swpaul key.data = NULL; 22512891Swpaul key.size = 0; 22612891Swpaul 22715426Swpaul if ((result.stat = yp_first_record(dbp, &key, &data, 0)) == YP_TRUE) { 22812891Swpaul result.key.keydat_len = key.size; 22912891Swpaul result.key.keydat_val = key.data; 23012891Swpaul result.val.valdat_len = data.size; 23112891Swpaul result.val.valdat_val = data.data; 23212891Swpaul } 23315426Swpaul#ifndef DB_CACHE 23415426Swpaul (void)(dbp->close)(dbp); 23515426Swpaul#endif 23612891Swpaul return (&result); 23712891Swpaul} 23812891Swpaul 23912891Swpaulypresp_key_val * 24012891Swpaulypproc_next_2_svc(ypreq_key *argp, struct svc_req *rqstp) 24112891Swpaul{ 24212891Swpaul static ypresp_key_val result; 24312891Swpaul DBT key, data; 24412891Swpaul DB *dbp; 24512891Swpaul 24614304Swpaul result.val.valdat_val = result.key.keydat_val = ""; 24714304Swpaul result.val.valdat_len = result.key.keydat_len = 0; 24815426Swpaul 24912891Swpaul if (yp_access(argp->map, (struct svc_req *)rqstp)) { 25012891Swpaul result.stat = YP_YPERR; 25112891Swpaul return (&result); 25212891Swpaul } 25312891Swpaul 25412891Swpaul if (argp->domain == NULL || argp->map == NULL) { 25512891Swpaul result.stat = YP_BADARGS; 25612891Swpaul return (&result); 25712891Swpaul } 25812891Swpaul 25915426Swpaul#ifdef DB_CACHE 26015426Swpaul if ((dbp = yp_open_db_cache(argp->domain, argp->map, 26115426Swpaul argp->key.keydat_val, 26215426Swpaul argp->key.keydat_len)) == NULL) { 26315426Swpaul#else 26412891Swpaul if ((dbp = yp_open_db(argp->domain, argp->map)) == NULL) { 26515426Swpaul#endif 26612891Swpaul result.stat = yp_errno; 26712891Swpaul return(&result); 26812891Swpaul } 26912891Swpaul 27012891Swpaul key.size = argp->key.keydat_len; 27112891Swpaul key.data = argp->key.keydat_val; 27212891Swpaul 27315426Swpaul if ((result.stat = yp_next_record(dbp, &key, &data,0,0)) == YP_TRUE) { 27412891Swpaul result.key.keydat_len = key.size; 27512891Swpaul result.key.keydat_val = key.data; 27612891Swpaul result.val.valdat_len = data.size; 27712891Swpaul result.val.valdat_val = data.data; 27812891Swpaul } 27915426Swpaul#ifndef DB_CACHE 28015426Swpaul (void)(dbp->close)(dbp); 28115426Swpaul#endif 28212891Swpaul return (&result); 28312891Swpaul} 28412891Swpaul 28512997Swpaulstatic void ypxfr_callback(rval,addr,transid,prognum,port) 28612997Swpaul ypxfrstat rval; 28712997Swpaul struct sockaddr_in *addr; 28812997Swpaul unsigned int transid; 28912997Swpaul unsigned int prognum; 29012997Swpaul unsigned long port; 29112997Swpaul{ 29212997Swpaul CLIENT *clnt; 29312997Swpaul int sock = RPC_ANYSOCK; 29412997Swpaul struct timeval timeout; 29512997Swpaul yppushresp_xfr ypxfr_resp; 29613375Swpaul struct rpc_err err; 29712997Swpaul 29813375Swpaul timeout.tv_sec = 5; 29912997Swpaul timeout.tv_usec = 0; 30012997Swpaul addr->sin_port = htons(port); 30112997Swpaul 30212997Swpaul if ((clnt = clntudp_create(addr, prognum, 1, timeout, &sock)) == NULL) 30312997Swpaul yp_error("%s", clnt_spcreateerror("failed to establish \ 30412997Swpaulcallback handle")); 30512997Swpaul 30612997Swpaul ypxfr_resp.status = rval; 30712997Swpaul ypxfr_resp.transid = transid; 30812997Swpaul 30913375Swpaul /* Turn the timeout off -- we don't want to block. */ 31013375Swpaul timeout.tv_sec = 0; 31113375Swpaul if (clnt_control(clnt, CLSET_TIMEOUT, (char *)&timeout) == FALSE) 31213375Swpaul yp_error("failed to set timeout on ypproc_xfr callback"); 31312997Swpaul 31413375Swpaul if (yppushproc_xfrresp_1(&ypxfr_resp, clnt) == NULL) { 31513375Swpaul clnt_geterr(clnt, &err); 31613375Swpaul if (err.re_status != RPC_SUCCESS && 31713375Swpaul err.re_status != RPC_TIMEDOUT) 31813375Swpaul yp_error("%s", clnt_sperror(clnt, 31913375Swpaul "ypxfr callback failed")); 32013375Swpaul } 32113375Swpaul 32212997Swpaul clnt_destroy(clnt); 32312997Swpaul return; 32412997Swpaul} 32512997Swpaul 32615426Swpaul#define YPXFR_RETURN(CODE) \ 32715426Swpaul /* Order is important: send regular RPC reply, then callback */ \ 32815426Swpaul result.xfrstat = CODE; \ 32915426Swpaul svc_sendreply(rqstp->rq_xprt, xdr_ypresp_xfr, (char *)&result); \ 33015426Swpaul ypxfr_callback(CODE,rqhost,argp->transid, \ 33115426Swpaul argp->prog,argp->port); \ 33215426Swpaul return(NULL); 33315426Swpaul 33412891Swpaulypresp_xfr * 33512891Swpaulypproc_xfr_2_svc(ypreq_xfr *argp, struct svc_req *rqstp) 33612891Swpaul{ 33712891Swpaul static ypresp_xfr result; 33812997Swpaul struct sockaddr_in *rqhost; 33912891Swpaul 34013375Swpaul result.transid = argp->transid; 34113375Swpaul rqhost = svc_getcaller(rqstp->rq_xprt); 34213375Swpaul 34312891Swpaul if (yp_access(argp->map_parms.map, (struct svc_req *)rqstp)) { 34415426Swpaul YPXFR_RETURN(YPXFR_REFUSED); 34512891Swpaul } 34612891Swpaul 34712891Swpaul if (argp->map_parms.domain == NULL) { 34815426Swpaul YPXFR_RETURN(YPXFR_BADARGS); 34912891Swpaul } 35012891Swpaul 35112891Swpaul if (yp_validdomain(argp->map_parms.domain)) { 35215426Swpaul YPXFR_RETURN(YPXFR_NODOM); 35312891Swpaul } 35412891Swpaul 35512891Swpaul switch(fork()) { 35612891Swpaul case 0: 35712891Swpaul { 35812891Swpaul char g[11], t[11], p[11]; 35912891Swpaul char ypxfr_command[MAXPATHLEN + 2]; 36012891Swpaul 36112891Swpaul sprintf (ypxfr_command, "%sypxfr", _PATH_LIBEXEC); 36212891Swpaul sprintf (t, "%u", argp->transid); 36312891Swpaul sprintf (g, "%u", argp->prog); 36412891Swpaul sprintf (p, "%u", argp->port); 36512997Swpaul if (debug) 36612997Swpaul close(0); close(1); close(2); 36712997Swpaul if (strcmp(yp_dir, _PATH_YP)) { 36814304Swpaul execl(ypxfr_command, "ypxfr", 36914304Swpaul "-d", argp->map_parms.domain, 37014304Swpaul "-h", argp->map_parms.peer, 37114304Swpaul "-p", yp_dir, "-C", t, 37214304Swpaul g, inet_ntoa(rqhost->sin_addr), 37314304Swpaul p, argp->map_parms.map, 37412997Swpaul NULL); 37512997Swpaul } else { 37614304Swpaul execl(ypxfr_command, "ypxfr", 37714304Swpaul "-d", argp->map_parms.domain, 37814304Swpaul "-h", argp->map_parms.peer, 37914304Swpaul "-C", t, 38014304Swpaul g, inet_ntoa(rqhost->sin_addr), 38114304Swpaul p, argp->map_parms.map, 38212997Swpaul NULL); 38312997Swpaul } 38412997Swpaul forked++; 38515426Swpaul yp_error("ypxfr execl(%s): %s", ypxfr_command, strerror(errno)); 38615426Swpaul YPXFR_RETURN(YPXFR_XFRERR); 38712997Swpaul break; 38812891Swpaul } 38912891Swpaul case -1: 39012891Swpaul yp_error("ypxfr fork(): %s", strerror(errno)); 39115426Swpaul YPXFR_RETURN(YPXFR_XFRERR); 39212891Swpaul break; 39312891Swpaul default: 39413375Swpaul result.xfrstat = YPXFR_SUCC; 39512997Swpaul children++; 39612997Swpaul forked = 0; 39712891Swpaul break; 39812891Swpaul } 39913375Swpaul 40013375Swpaul return (&result); 40112891Swpaul} 40215426Swpaul#undef YPXFR_RETURN 40312891Swpaul 40412891Swpaulvoid * 40512891Swpaulypproc_clear_2_svc(void *argp, struct svc_req *rqstp) 40612891Swpaul{ 40712891Swpaul static char * result; 40812891Swpaul static char rval = 0; 40912891Swpaul 41012891Swpaul if (yp_access(NULL, (struct svc_req *)rqstp)) 41112891Swpaul return (NULL); 41215426Swpaul#ifdef DB_CACHE 41315426Swpaul /* clear out the database cache */ 41415426Swpaul yp_flush_all(); 41515426Swpaul#endif 41614240Swpaul /* Re-read the securenets database for the hell of it. */ 41714240Swpaul load_securenets(); 41814240Swpaul 41912891Swpaul result = &rval; 42012891Swpaul return((void *) &result); 42112891Swpaul} 42212891Swpaul 42312891Swpaul/* 42412891Swpaul * For ypproc_all, we have to send a stream of ypresp_all structures 42512891Swpaul * via TCP, but the XDR filter generated from the yp.x protocol 42612891Swpaul * definition file only serializes one such structure. This means that 42712891Swpaul * to send the whole stream, you need a wrapper which feeds all the 42812891Swpaul * records into the underlying XDR routine until it hits an 'EOF.' 42912891Swpaul * But to use the wrapper, you have to violate the boundaries between 43012891Swpaul * RPC layers by calling svc_sendreply() directly from the ypproc_all 43112891Swpaul * service routine instead of letting the RPC dispatcher do it. 43212891Swpaul * 43312891Swpaul * Bleah. 43412891Swpaul */ 43512891Swpaul 43612891Swpaul/* 43712891Swpaul * Custom XDR routine for serialzing results of ypproc_all: keep 43812891Swpaul * reading from the database and spew until we run out of records 43912891Swpaul * or encounter an error. 44012891Swpaul */ 44112891Swpaulstatic bool_t 44212891Swpaulxdr_my_ypresp_all(register XDR *xdrs, ypresp_all *objp) 44312891Swpaul{ 44415426Swpaul DBT key = { NULL, 0 } , data = { NULL, 0 }; 44512891Swpaul 44612891Swpaul while (1) { 44712891Swpaul /* Get a record. */ 44812891Swpaul if ((objp->ypresp_all_u.val.stat = 44915426Swpaul yp_next_record(spec_dbp,&key,&data,1,0)) == YP_TRUE) { 45012891Swpaul objp->ypresp_all_u.val.val.valdat_len = data.size; 45112891Swpaul objp->ypresp_all_u.val.val.valdat_val = data.data; 45212891Swpaul objp->ypresp_all_u.val.key.keydat_len = key.size; 45312891Swpaul objp->ypresp_all_u.val.key.keydat_val = key.data; 45412891Swpaul objp->more = TRUE; 45512891Swpaul } else { 45612891Swpaul objp->more = FALSE; 45712891Swpaul } 45812891Swpaul 45912891Swpaul /* Serialize. */ 46012891Swpaul if (!xdr_ypresp_all(xdrs, objp)) 46112891Swpaul return(FALSE); 46212891Swpaul if (objp->more == FALSE) 46312891Swpaul return(TRUE); 46412891Swpaul } 46512891Swpaul} 46612891Swpaul 46712891Swpaulypresp_all * 46812891Swpaulypproc_all_2_svc(ypreq_nokey *argp, struct svc_req *rqstp) 46912891Swpaul{ 47012891Swpaul static ypresp_all result; 47112891Swpaul 47212891Swpaul /* 47312891Swpaul * Set this here so that the client will be forced to make 47412891Swpaul * at least one attempt to read from us even if all we're 47512891Swpaul * doing is returning an error. 47612891Swpaul */ 47712891Swpaul result.more = TRUE; 47814304Swpaul result.ypresp_all_u.val.key.keydat_len = 0; 47914304Swpaul result.ypresp_all_u.val.key.keydat_val = ""; 48012891Swpaul 48112891Swpaul if (yp_access(argp->map, (struct svc_req *)rqstp)) { 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 49112891Swpaul /* 49212891Swpaul * The ypproc_all procedure can take a while to complete. 49312891Swpaul * Best to handle it in a subprocess so the parent doesn't 49415426Swpaul * block. (Is there a better way to do this? Maybe with 49515426Swpaul * async socket I/O?) 49612891Swpaul */ 49712891Swpaul if (!debug && children < MAX_CHILDREN && fork()) { 49812891Swpaul children++; 49912891Swpaul forked = 0; 50012891Swpaul return (NULL); 50112891Swpaul } else { 50212891Swpaul forked++; 50312891Swpaul } 50412891Swpaul 50515426Swpaul#ifndef DB_CACHE 50612891Swpaul if ((spec_dbp = yp_open_db(argp->domain, argp->map)) == NULL) { 50712891Swpaul result.ypresp_all_u.val.stat = yp_errno; 50812891Swpaul return(&result); 50912891Swpaul } 51015426Swpaul#else 51115426Swpaul if ((spec_dbp = yp_open_db_cache(argp->domain, argp->map, NULL, 0)) == NULL) { 51215426Swpaul result.ypresp_all_u.val.stat = yp_errno; 51315426Swpaul return(&result); 51415426Swpaul } 51515426Swpaul#endif 51612891Swpaul 51712891Swpaul /* Kick off the actual data transfer. */ 51812891Swpaul svc_sendreply(rqstp->rq_xprt, xdr_my_ypresp_all, (char *)&result); 51912891Swpaul 52015426Swpaul#ifndef DB_CACHE 52112891Swpaul (void)(spec_dbp->close)(spec_dbp); 52215426Swpaul#endif 52312891Swpaul /* 52412891Swpaul * Returning NULL prevents the dispatcher from calling 52512891Swpaul * svc_sendreply() since we already did it. 52612891Swpaul */ 52712891Swpaul return (NULL); 52812891Swpaul} 52912891Swpaul 53012891Swpaulypresp_master * 53112891Swpaulypproc_master_2_svc(ypreq_nokey *argp, struct svc_req *rqstp) 53212891Swpaul{ 53312891Swpaul static ypresp_master result; 53415426Swpaul static char ypvalbuf[YPMAXRECORD]; 53515426Swpaul DBT key, data; 53612891Swpaul 53714303Swpaul result.peer = ""; 53814303Swpaul 53912891Swpaul if (yp_access(NULL, (struct svc_req *)rqstp)) { 54012891Swpaul result.stat = YP_YPERR; 54112891Swpaul return(&result); 54212891Swpaul } 54312891Swpaul 54412891Swpaul if (argp->domain == NULL) { 54512891Swpaul result.stat = YP_BADARGS; 54612891Swpaul return (&result); 54712891Swpaul } 54812891Swpaul 54915426Swpaul key.data = master_string; 55015426Swpaul key.size = strlen(master_string); 55112891Swpaul 55215426Swpaul /* 55315426Swpaul * Note that we copy the data retrieved from the database to 55415426Swpaul * a private buffer and NUL terminate the buffer rather than 55515426Swpaul * terminating the data in place. We do this because by stuffing 55615426Swpaul * a '\0' into data.data, we will actually be corrupting memory 55715426Swpaul * allocated by the DB package. This is a bad thing now that we 55815426Swpaul * cache DB handles rather than closing the database immediately. 55915426Swpaul */ 56015426Swpaul if ((result.stat = yp_get_record(argp->domain, argp->map, 56115426Swpaul &key, &data, 1)) == YP_TRUE) { 56215426Swpaul bcopy((char *)data.data, (char *)&ypvalbuf, data.size); 56315426Swpaul ypvalbuf[data.size] = '\0'; 56415426Swpaul result.peer = (char *)&ypvalbuf; 56512891Swpaul } else 56612891Swpaul result.peer = ""; 56712891Swpaul 56812891Swpaul return (&result); 56912891Swpaul} 57012891Swpaul 57112891Swpaulypresp_order * 57212891Swpaulypproc_order_2_svc(ypreq_nokey *argp, struct svc_req *rqstp) 57312891Swpaul{ 57412891Swpaul static ypresp_order result; 57512891Swpaul DBT key,data; 57612891Swpaul 57714304Swpaul result.ordernum = 0; 57814304Swpaul 57912891Swpaul if (yp_access(NULL, (struct svc_req *)rqstp)) { 58012891Swpaul result.stat = YP_YPERR; 58112891Swpaul return(&result); 58212891Swpaul } 58312891Swpaul 58412891Swpaul if (argp->domain == NULL) { 58512891Swpaul result.stat = YP_BADARGS; 58612891Swpaul return (&result); 58712891Swpaul } 58812891Swpaul 58912891Swpaul /* 59012891Swpaul * We could just check the timestamp on the map file, 59112891Swpaul * but that's a hack: we'll only know the last time the file 59212891Swpaul * was touched, not the last time the database contents were 59312891Swpaul * updated. 59412891Swpaul */ 59512891Swpaul 59615426Swpaul key.data = order_string; 59715426Swpaul key.size = strlen(order_string); 59812891Swpaul 59915426Swpaul if ((result.stat = yp_get_record(argp->domain, argp->map, 60015426Swpaul &key, &data, 1)) == YP_TRUE) 60112891Swpaul result.ordernum = atoi((char *)data.data); 60212891Swpaul else 60312891Swpaul result.ordernum = 0; 60412891Swpaul 60515426Swpaul 60612891Swpaul return (&result); 60712891Swpaul} 60812891Swpaul 60912891Swpaulstatic void yp_maplist_free(yp_maplist) 61012891Swpaul struct ypmaplist *yp_maplist; 61112891Swpaul{ 61212891Swpaul register struct ypmaplist *next; 61312891Swpaul 61412891Swpaul while(yp_maplist) { 61512891Swpaul next = yp_maplist->next; 61612891Swpaul free(yp_maplist->map); 61712891Swpaul free(yp_maplist); 61812891Swpaul yp_maplist = next; 61912891Swpaul } 62012891Swpaul return; 62112891Swpaul} 62212891Swpaul 62312891Swpaulstatic struct ypmaplist *yp_maplist_create(domain) 62412891Swpaul const char *domain; 62512891Swpaul{ 62612891Swpaul char yp_mapdir[MAXPATHLEN + 2]; 62712891Swpaul char yp_mapname[MAXPATHLEN + 2]; 62812891Swpaul struct ypmaplist *cur = NULL; 62912891Swpaul struct ypmaplist *yp_maplist = NULL; 63012891Swpaul DIR *dird; 63112891Swpaul struct dirent *dirp; 63212891Swpaul struct stat statbuf; 63312891Swpaul 63412891Swpaul snprintf(yp_mapdir, sizeof(yp_mapdir), "%s/%s", yp_dir, domain); 63512891Swpaul 63612891Swpaul if ((dird = opendir(yp_mapdir)) == NULL) { 63713800Swpaul yp_error("opendir(%s) failed: %s", yp_mapdir, strerror(errno)); 63812891Swpaul return(NULL); 63912891Swpaul } 64012891Swpaul 64112891Swpaul while ((dirp = readdir(dird)) != NULL) { 64212891Swpaul if (strcmp(dirp->d_name, ".") && strcmp(dirp->d_name, "..")) { 64314304Swpaul snprintf(yp_mapname, sizeof(yp_mapname), "%s/%s", 64414304Swpaul yp_mapdir,dirp->d_name); 64514304Swpaul if (stat(yp_mapname, &statbuf) < 0 || 64614304Swpaul !S_ISREG(statbuf.st_mode)) 64712891Swpaul continue; 64814304Swpaul if ((cur = (struct ypmaplist *) 64914304Swpaul malloc(sizeof(struct ypmaplist))) < 0) { 65014304Swpaul yp_error("malloc() failed: %s",strerror(errno)); 65112891Swpaul closedir(dird); 65212891Swpaul yp_maplist_free(yp_maplist); 65312891Swpaul return(NULL); 65412891Swpaul } 65512891Swpaul if ((cur->map = (char *)strdup(dirp->d_name)) == NULL) { 65614304Swpaul yp_error("strdup() failed: %s",strerror(errno)); 65712891Swpaul closedir(dird); 65812891Swpaul yp_maplist_free(yp_maplist); 65912891Swpaul return(NULL); 66012891Swpaul } 66112891Swpaul cur->next = yp_maplist; 66212891Swpaul yp_maplist = cur; 66312891Swpaul if (debug) 66412891Swpaul yp_error("map: %s", yp_maplist->map); 66512891Swpaul } 66612891Swpaul 66712891Swpaul } 66812891Swpaul closedir(dird); 66912891Swpaul return(yp_maplist); 67012891Swpaul} 67112891Swpaul 67212891Swpaulypresp_maplist * 67312891Swpaulypproc_maplist_2_svc(domainname *argp, struct svc_req *rqstp) 67412891Swpaul{ 67515426Swpaul static ypresp_maplist result = { 0, NULL }; 67612891Swpaul 67712891Swpaul if (yp_access(NULL, (struct svc_req *)rqstp)) { 67812891Swpaul result.stat = YP_YPERR; 67912891Swpaul return(&result); 68012891Swpaul } 68112891Swpaul 68212891Swpaul if (argp == NULL) { 68312891Swpaul result.stat = YP_BADARGS; 68412891Swpaul return (&result); 68512891Swpaul } 68612891Swpaul 68712891Swpaul if (yp_validdomain(*argp)) { 68812891Swpaul result.stat = YP_NODOM; 68912891Swpaul return (&result); 69012891Swpaul } 69112891Swpaul 69212891Swpaul /* 69312891Swpaul * We have to construct a linked list for the ypproc_maplist 69412891Swpaul * procedure using dynamically allocated memory. Since the XDR 69512891Swpaul * layer won't free this list for us, we have to deal with it 69612891Swpaul * ourselves. We call yp_maplist_free() first to free any 69712891Swpaul * previously allocated data we may have accumulated to insure 69812891Swpaul * that we have only one linked list in memory at any given 69912891Swpaul * time. 70012891Swpaul */ 70112891Swpaul 70212891Swpaul yp_maplist_free(result.maps); 70312891Swpaul 70412891Swpaul if ((result.maps = yp_maplist_create(*argp)) == NULL) { 70512891Swpaul yp_error("yp_maplist_create failed"); 70612891Swpaul result.stat = YP_YPERR; 70712891Swpaul return(&result); 70812891Swpaul } else 70912891Swpaul result.stat = YP_TRUE; 71012891Swpaul 71112891Swpaul return (&result); 71212891Swpaul} 71314262Swpaul 71414262Swpaul/* 71514262Swpaul * NIS v1 support. The nullproc, domain and domain_nonack 71614262Swpaul * functions from v1 are identical to those in v2, so all 71714262Swpaul * we have to do is hand off to them. 71814262Swpaul * 71914262Swpaul * The other functions are mostly just wrappers around their v2 72014262Swpaul * counterparts. For example, for the v1 'match' procedure, we 72114262Swpaul * crack open the argument structure, make a request to the v2 72214262Swpaul * 'match' function, repackage the data into a v1 response and 72314262Swpaul * then send it on its way. 72414262Swpaul * 72514262Swpaul * Note that we don't support the pull, push and get procedures. 72614262Swpaul * There's little documentation available to show what they 72714262Swpaul * do, and I suspect they're meant largely for map transfers 72814262Swpaul * between master and slave servers. 72914262Swpaul */ 73014262Swpaul 73114262Swpaulvoid * 73214262Swpaulypoldproc_null_1_svc(void *argp, struct svc_req *rqstp) 73314262Swpaul{ 73414262Swpaul return(ypproc_null_2_svc(argp, rqstp)); 73514262Swpaul} 73614262Swpaul 73714262Swpaulbool_t * 73814262Swpaulypoldproc_domain_1_svc(domainname *argp, struct svc_req *rqstp) 73914262Swpaul{ 74014262Swpaul return(ypproc_domain_2_svc(argp, rqstp)); 74114262Swpaul} 74214262Swpaul 74314262Swpaulbool_t * 74414262Swpaulypoldproc_domain_nonack_1_svc(domainname *argp, struct svc_req *rqstp) 74514262Swpaul{ 74614262Swpaul return (ypproc_domain_nonack_2_svc(argp, rqstp)); 74714262Swpaul} 74814262Swpaul 74914304Swpaul/* 75014304Swpaul * the 'match' procedure sends a response of type YPRESP_VAL 75114304Swpaul */ 75214262Swpaulypresponse * 75314262Swpaulypoldproc_match_1_svc(yprequest *argp, struct svc_req *rqstp) 75414262Swpaul{ 75514262Swpaul static ypresponse result; 75614262Swpaul ypresp_val *v2_result; 75714262Swpaul 75814262Swpaul result.yp_resptype = YPRESP_VAL; 75914304Swpaul result.ypresponse_u.yp_resp_valtype.val.valdat_val = ""; 76014304Swpaul result.ypresponse_u.yp_resp_valtype.val.valdat_len = 0; 76114262Swpaul 76214262Swpaul if (argp->yp_reqtype != YPREQ_KEY) { 76314262Swpaul result.ypresponse_u.yp_resp_valtype.stat = YP_BADARGS; 76414262Swpaul return(&result); 76514262Swpaul } 76614262Swpaul 76714262Swpaul v2_result = ypproc_match_2_svc(&argp->yprequest_u.yp_req_keytype,rqstp); 76814262Swpaul if (v2_result == NULL) 76914262Swpaul return(NULL); 77014262Swpaul 77114262Swpaul bcopy((char *)v2_result, 77214262Swpaul (char *)&result.ypresponse_u.yp_resp_valtype, 77314262Swpaul sizeof(ypresp_val)); 77414262Swpaul 77514262Swpaul return (&result); 77614262Swpaul} 77714262Swpaul 77814304Swpaul/* 77914304Swpaul * the 'first' procedure sends a response of type YPRESP_KEY_VAL 78014304Swpaul */ 78114262Swpaulypresponse * 78214262Swpaulypoldproc_first_1_svc(yprequest *argp, struct svc_req *rqstp) 78314262Swpaul{ 78414262Swpaul static ypresponse result; 78514262Swpaul ypresp_key_val *v2_result; 78614262Swpaul 78714262Swpaul result.yp_resptype = YPRESP_KEY_VAL; 78814304Swpaul result.ypresponse_u.yp_resp_key_valtype.val.valdat_val = 78914304Swpaul result.ypresponse_u.yp_resp_key_valtype.key.keydat_val = ""; 79014304Swpaul result.ypresponse_u.yp_resp_key_valtype.val.valdat_len = 79114304Swpaul result.ypresponse_u.yp_resp_key_valtype.key.keydat_len = 0; 79214262Swpaul 79314262Swpaul if (argp->yp_reqtype != YPREQ_NOKEY) { 79414262Swpaul result.ypresponse_u.yp_resp_key_valtype.stat = YP_BADARGS; 79514262Swpaul return(&result); 79614262Swpaul } 79714262Swpaul 79814262Swpaul v2_result = ypproc_first_2_svc(&argp->yprequest_u.yp_req_nokeytype, 79914262Swpaul rqstp); 80014262Swpaul if (v2_result == NULL) 80114262Swpaul return(NULL); 80214262Swpaul 80314262Swpaul bcopy((char *)v2_result, 80414262Swpaul (char *)&result.ypresponse_u.yp_resp_key_valtype, 80514262Swpaul sizeof(ypresp_key_val)); 80614262Swpaul 80714262Swpaul return (&result); 80814262Swpaul} 80914262Swpaul 81014304Swpaul/* 81114304Swpaul * the 'next' procedure sends a response of type YPRESP_KEY_VAL 81214304Swpaul */ 81314262Swpaulypresponse * 81414262Swpaulypoldproc_next_1_svc(yprequest *argp, struct svc_req *rqstp) 81514262Swpaul{ 81614262Swpaul static ypresponse result; 81714262Swpaul ypresp_key_val *v2_result; 81814262Swpaul 81914262Swpaul result.yp_resptype = YPRESP_KEY_VAL; 82014304Swpaul result.ypresponse_u.yp_resp_key_valtype.val.valdat_val = 82114304Swpaul result.ypresponse_u.yp_resp_key_valtype.key.keydat_val = ""; 82214304Swpaul result.ypresponse_u.yp_resp_key_valtype.val.valdat_len = 82314304Swpaul result.ypresponse_u.yp_resp_key_valtype.key.keydat_len = 0; 82414262Swpaul 82514262Swpaul if (argp->yp_reqtype != YPREQ_KEY) { 82614262Swpaul result.ypresponse_u.yp_resp_key_valtype.stat = YP_BADARGS; 82714262Swpaul return(&result); 82814262Swpaul } 82914262Swpaul 83014262Swpaul v2_result = ypproc_next_2_svc(&argp->yprequest_u.yp_req_keytype,rqstp); 83114262Swpaul if (v2_result == NULL) 83214262Swpaul return(NULL); 83314262Swpaul 83414262Swpaul bcopy((char *)v2_result, 83514262Swpaul (char *)&result.ypresponse_u.yp_resp_key_valtype, 83614262Swpaul sizeof(ypresp_key_val)); 83714262Swpaul 83814262Swpaul return (&result); 83914262Swpaul} 84014262Swpaul 84114304Swpaul/* 84214304Swpaul * the 'poll' procedure sends a response of type YPRESP_MAP_PARMS 84314304Swpaul */ 84414262Swpaulypresponse * 84514262Swpaulypoldproc_poll_1_svc(yprequest *argp, struct svc_req *rqstp) 84614262Swpaul{ 84714262Swpaul static ypresponse result; 84814262Swpaul ypresp_master *v2_result1; 84914262Swpaul ypresp_order *v2_result2; 85014262Swpaul 85114262Swpaul result.yp_resptype = YPRESP_MAP_PARMS; 85214262Swpaul result.ypresponse_u.yp_resp_map_parmstype.domain = 85314262Swpaul argp->yprequest_u.yp_req_nokeytype.domain; 85414262Swpaul result.ypresponse_u.yp_resp_map_parmstype.map = 85514262Swpaul argp->yprequest_u.yp_req_nokeytype.map; 85614262Swpaul /* 85714262Swpaul * Hmm... there is no 'status' value in the 85814262Swpaul * yp_resp_map_parmstype structure, so I have to 85914262Swpaul * guess at what to do to indicate a failure. 86014262Swpaul * I hope this is right. 86114262Swpaul */ 86214262Swpaul result.ypresponse_u.yp_resp_map_parmstype.ordernum = 0; 86314262Swpaul result.ypresponse_u.yp_resp_map_parmstype.peer = ""; 86414262Swpaul 86514262Swpaul if (argp->yp_reqtype != YPREQ_MAP_PARMS) { 86614262Swpaul return(&result); 86714262Swpaul } 86814262Swpaul 86914262Swpaul v2_result1 = ypproc_master_2_svc(&argp->yprequest_u.yp_req_nokeytype, 87014262Swpaul rqstp); 87114262Swpaul if (v2_result1 == NULL) 87214262Swpaul return(NULL); 87314262Swpaul 87414262Swpaul if (v2_result1->stat != YP_TRUE) { 87514262Swpaul return(&result); 87614262Swpaul } 87714262Swpaul 87814262Swpaul v2_result2 = ypproc_order_2_svc(&argp->yprequest_u.yp_req_nokeytype, 87914262Swpaul rqstp); 88014262Swpaul if (v2_result2 == NULL) 88114262Swpaul return(NULL); 88214262Swpaul 88314262Swpaul if (v2_result2->stat != YP_TRUE) { 88414262Swpaul return(&result); 88514262Swpaul } 88614262Swpaul 88714262Swpaul result.ypresponse_u.yp_resp_map_parmstype.peer = 88814262Swpaul v2_result1->peer; 88914262Swpaul result.ypresponse_u.yp_resp_map_parmstype.ordernum = 89014262Swpaul v2_result2->ordernum; 89114262Swpaul 89214262Swpaul return (&result); 89314262Swpaul} 89414262Swpaul 89514262Swpaulypresponse * 89614262Swpaulypoldproc_push_1_svc(yprequest *argp, struct svc_req *rqstp) 89714262Swpaul{ 89814262Swpaul static ypresponse result; 89914262Swpaul 90014262Swpaul /* 90114262Swpaul * Not implemented. 90214262Swpaul */ 90314262Swpaul 90414262Swpaul return (&result); 90514262Swpaul} 90614262Swpaul 90714262Swpaulypresponse * 90814262Swpaulypoldproc_pull_1_svc(yprequest *argp, struct svc_req *rqstp) 90914262Swpaul{ 91014262Swpaul static ypresponse result; 91114262Swpaul 91214262Swpaul /* 91314262Swpaul * Not implemented. 91414262Swpaul */ 91514262Swpaul 91614262Swpaul return (&result); 91714262Swpaul} 91814262Swpaul 91914262Swpaulypresponse * 92014262Swpaulypoldproc_get_1_svc(yprequest *argp, struct svc_req *rqstp) 92114262Swpaul{ 92214262Swpaul static ypresponse result; 92314262Swpaul 92414262Swpaul /* 92514262Swpaul * Not implemented. 92614262Swpaul */ 92714262Swpaul 92814262Swpaul return (&result); 92914262Swpaul} 930