yp_server.c revision 19161
125723Stegge/* 225723Stegge * Copyright (c) 1995 325723Stegge * Bill Paul <wpaul@ctr.columbia.edu>. All rights reserved. 425723Stegge * 525723Stegge * Redistribution and use in source and binary forms, with or without 625723Stegge * modification, are permitted provided that the following conditions 725723Stegge * are met: 825723Stegge * 1. Redistributions of source code must retain the above copyright 925723Stegge * notice, this list of conditions and the following disclaimer. 1025723Stegge * 2. Redistributions in binary form must reproduce the above copyright 1125723Stegge * notice, this list of conditions and the following disclaimer in the 1225723Stegge * documentation and/or other materials provided with the distribution. 1325723Stegge * 3. All advertising materials mentioning features or use of this software 1425723Stegge * must display the following acknowledgement: 1525723Stegge * This product includes software developed by Bill Paul. 1625723Stegge * 4. Neither the name of the author nor the names of any co-contributors 1725723Stegge * may be used to endorse or promote products derived from this software 1825723Stegge * without specific prior written permission. 1925723Stegge * 2025723Stegge * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND 2125723Stegge * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2225723Stegge * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2325723Stegge * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR CONTRIBUTORS BE LIABLE 2425723Stegge * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2525723Stegge * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2625723Stegge * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2725723Stegge * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2825723Stegge * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2925723Stegge * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3025723Stegge * SUCH DAMAGE. 3125723Stegge * 3225723Stegge */ 3325723Stegge 3425723Stegge#include "yp_extern.h" 3525723Stegge#include "yp.h" 3625723Stegge#include <stdlib.h> 3725723Stegge#include <dirent.h> 3825723Stegge#include <sys/stat.h> 3925723Stegge#include <sys/param.h> 4025723Stegge#include <errno.h> 4125723Stegge#include <sys/types.h> 4225723Stegge#include <sys/socket.h> 4383651Speter#include <netinet/in.h> 4483651Speter#include <arpa/inet.h> 4583651Speter#include <rpc/rpc.h> 4632358Seivind 4732358Seivind#ifndef lint 4825723Steggestatic const char rcsid[] = "$Id: yp_server.c,v 1.10 1996/05/31 16:01:51 wpaul Exp $"; 4925723Stegge#endif /* not lint */ 5025723Stegge 5125723Steggeint forked = 0; 5267834Steggeint children = 0; 5325723Steggestatic DB *spec_dbp = NULL; /* Special global DB handle for ypproc_all. */ 5425723Steggestatic char *master_string = "YP_MASTER_NAME"; 5588743Srwatsonstatic char *order_string = "YP_LAST_MODIFIED"; 5625723Steggestatic int master_sz = sizeof("YP_MASTER_NAME") - 1; 5725723Steggestatic int order_sz = sizeof("YP_LAST_MODIFIED") - 1; 5892219Sluigi 5934924Sbde/* 6025723Stegge * NIS v2 support. This is where most of the action happens. 6125723Stegge */ 6225723Stegge 6325723Steggevoid * 6425723Steggeypproc_null_2_svc(void *argp, struct svc_req *rqstp) 6525723Stegge{ 6625723Stegge static char * result; 6725723Stegge static char rval = 0; 6825723Stegge 6925723Stegge#ifdef DB_CACHE 7083651Speter if (yp_access(NULL, NULL, (struct svc_req *)rqstp)) 7183651Speter#else 7283651Speter if (yp_access(NULL, (struct svc_req *)rqstp)) 7325723Stegge#endif 7425723Stegge return(NULL); 7525723Stegge 7632609Stegge result = &rval; 7725723Stegge 7867834Stegge return((void *) &result); 7967834Stegge} 8067834Stegge 8167834Steggebool_t * 8225723Steggeypproc_domain_2_svc(domainname *argp, struct svc_req *rqstp) 8325723Stegge{ 8425723Stegge static bool_t result; 8525723Stegge 8625723Stegge#ifdef DB_CACHE 8725723Stegge if (yp_access(NULL, NULL, (struct svc_req *)rqstp)) { 8825723Stegge#else 8925723Stegge if (yp_access(NULL, (struct svc_req *)rqstp)) { 9025723Stegge#endif 9125723Stegge result = FALSE; 9267531Stegge return (&result); 9367531Stegge } 9467531Stegge 9567531Stegge if (argp == NULL || yp_validdomain(*argp)) 9667531Stegge result = FALSE; 9767531Stegge else 9867531Stegge result = TRUE; 9967531Stegge 10067531Stegge return (&result); 10167531Stegge} 10267531Stegge 10367531Steggebool_t * 10467531Steggeypproc_domain_nonack_2_svc(domainname *argp, struct svc_req *rqstp) 10567531Stegge{ 10688680Sambrisko static bool_t result; 10725723Stegge 10825723Stegge#ifdef DB_CACHE 10967834Stegge if (yp_access(NULL, NULL, (struct svc_req *)rqstp)) 11067834Stegge#else 11167834Stegge if (yp_access(NULL, (struct svc_req *)rqstp)) 11267834Stegge#endif 11367834Stegge return (NULL); 11467834Stegge 11567834Stegge if (argp == NULL || yp_validdomain(*argp)) 11667834Stegge return (NULL); 11767834Stegge else 11867834Stegge result = TRUE; 11967834Stegge 12067834Stegge return (&result); 12167834Stegge} 12267834Stegge 12367834Steggeypresp_val * 12467834Steggeypproc_match_2_svc(ypreq_key *argp, struct svc_req *rqstp) 12567834Stegge{ 12667834Stegge static ypresp_val result; 12767834Stegge DBT key, data; 12867834Stegge 12967834Stegge result.val.valdat_val = ""; 13067834Stegge result.val.valdat_len = 0; 13167834Stegge 13271915Stegge#ifdef DB_CACHE 13371915Stegge if (yp_access(argp->map, argp->domain, (struct svc_req *)rqstp)) { 13467834Stegge#else 13567834Stegge if (yp_access(argp->map, (struct svc_req *)rqstp)) { 13671915Stegge#endif 13767834Stegge result.stat = YP_YPERR; 13871915Stegge return (&result); 13971915Stegge } 14071915Stegge 14167834Stegge if (argp->domain == NULL || argp->map == NULL) { 14267834Stegge result.stat = YP_BADARGS; 14367834Stegge return (&result); 14467834Stegge } 14567834Stegge 14667834Stegge key.size = argp->key.keydat_len; 14767834Stegge key.data = argp->key.keydat_val; 14867834Stegge 14967834Stegge if ((result.stat = yp_get_record(argp->domain, argp->map, 15067834Stegge &key, &data, 1)) == YP_TRUE) { 15167834Stegge result.val.valdat_len = data.size; 15267834Stegge result.val.valdat_val = data.data; 15367834Stegge } 15467834Stegge 15567834Stegge /* 15667834Stegge * Do DNS lookups for hosts maps if database lookup failed. 15767834Stegge */ 15867834Stegge 15967834Stegge#ifdef DB_CACHE 16067834Stegge if (result.stat != YP_TRUE && 16167834Stegge (yp_testflag(argp->map, argp->domain, YP_INTERDOMAIN) || 16267834Stegge (strstr(argp->map, "hosts") && do_dns))) { 16367834Stegge#else 16467834Stegge if (do_dns && result.stat != YP_TRUE && strstr(argp->map, "hosts")) { 16567834Stegge#endif 16667834Stegge char *rval = NULL; 16767834Stegge 16867834Stegge /* DNS lookups can take time -- do them in a subprocess */ 16967834Stegge 17067834Stegge if (!debug && children < MAX_CHILDREN && fork()) { 17167834Stegge children++; 17267834Stegge forked = 0; 17325723Stegge /* 17425723Stegge * Returning NULL here prevents svc_sendreply() 17525723Stegge * from being called by the parent. This is vital 17667834Stegge * since having both the parent and the child process 17767834Stegge * call it would confuse the client. 17867834Stegge */ 17967834Stegge return (NULL); 18067834Stegge } else { 18167834Stegge forked++; 18267834Stegge } 18367834Stegge 18467834Stegge if (debug) 18567834Stegge yp_error("Doing DNS lookup of %.*s", 18667834Stegge argp->key.keydat_len, 18767834Stegge argp->key.keydat_val); 18867834Stegge 18967834Stegge /* NUL terminate! NUL terminate!! NUL TERMINATE!!! */ 19067834Stegge argp->key.keydat_val[argp->key.keydat_len] = '\0'; 19167834Stegge 19267834Stegge if (!strcmp(argp->map, "hosts.byname")) 19367834Stegge rval = yp_dnsname((char *)argp->key.keydat_val); 19467834Stegge else if (!strcmp(argp->map, "hosts.byaddr")) 19567834Stegge rval = yp_dnsaddr((const char *)argp->key.keydat_val); 19667834Stegge 19767834Stegge 19867834Stegge if (rval) { 19967834Stegge if (debug) 20067834Stegge yp_error("DNS lookup successful. Result: %s", 20192219Sluigi rval); 20267834Stegge result.val.valdat_len = strlen(rval); 20371915Stegge result.val.valdat_val = rval; 20471915Stegge result.stat = YP_TRUE; 20571915Stegge } else { 20671915Stegge if (debug) 20771915Stegge yp_error("DNS lookup failed."); 20871915Stegge result.stat = YP_NOKEY; 20971915Stegge } 21071915Stegge } 21171915Stegge 21271915Stegge return (&result); 21371915Stegge} 21492219Sluigi 21592219Sluigiypresp_key_val * 21692219Sluigiypproc_first_2_svc(ypreq_nokey *argp, struct svc_req *rqstp) 21792219Sluigi{ 21825723Stegge static ypresp_key_val result; 21983651Speter DBT key, data; 22083651Speter DB *dbp; 22183651Speter 22283651Speter result.val.valdat_val = result.key.keydat_val = ""; 22383651Speter result.val.valdat_len = result.key.keydat_len = 0; 22483651Speter 22583651Speter#ifdef DB_CACHE 22683651Speter if (yp_access(argp->map, argp->domain, (struct svc_req *)rqstp)) { 22783651Speter#else 22883651Speter if (yp_access(argp->map, (struct svc_req *)rqstp)) { 22983651Speter#endif 23083651Speter result.stat = YP_YPERR; 23183651Speter return (&result); 23283651Speter } 23383651Speter 23483651Speter if (argp->domain == NULL) { 23583651Speter result.stat = YP_BADARGS; 23667834Stegge return (&result); 23783651Speter } 23867834Stegge 23983651Speter#ifdef DB_CACHE 24025723Stegge if ((dbp = yp_open_db_cache(argp->domain, argp->map, NULL, 0)) == NULL) { 24125723Stegge#else 24283651Speter if ((dbp = yp_open_db(argp->domain, argp->map)) == NULL) { 24325723Stegge#endif 24425723Stegge result.stat = yp_errno; 24525723Stegge return(&result); 24625723Stegge } 24767834Stegge 24825723Stegge key.data = NULL; 24925723Stegge key.size = 0; 25025723Stegge 25183651Speter if ((result.stat = yp_first_record(dbp, &key, &data, 0)) == YP_TRUE) { 25283651Speter result.key.keydat_len = key.size; 25325723Stegge result.key.keydat_val = key.data; 25483651Speter result.val.valdat_len = data.size; 25583651Speter result.val.valdat_val = data.data; 25625723Stegge } 25783651Speter#ifndef DB_CACHE 25883651Speter (void)(dbp->close)(dbp); 25925723Stegge#endif 26083651Speter return (&result); 26183651Speter} 26283651Speter 26367834Steggeypresp_key_val * 26483651Speterypproc_next_2_svc(ypreq_key *argp, struct svc_req *rqstp) 26583651Speter{ 26667834Stegge static ypresp_key_val result; 26771915Stegge DBT key, data; 26871915Stegge DB *dbp; 26971915Stegge 27071915Stegge result.val.valdat_val = result.key.keydat_val = ""; 27167834Stegge result.val.valdat_len = result.key.keydat_len = 0; 27267834Stegge 27367834Stegge#ifdef DB_CACHE 27467834Stegge if (yp_access(argp->map, argp->domain, (struct svc_req *)rqstp)) { 27583651Speter#else 27667834Stegge if (yp_access(argp->map, (struct svc_req *)rqstp)) { 27767834Stegge#endif 27867834Stegge result.stat = YP_YPERR; 27967834Stegge return (&result); 28067834Stegge } 28167834Stegge 28267834Stegge if (argp->domain == NULL || argp->map == NULL) { 28325723Stegge result.stat = YP_BADARGS; 28467531Stegge return (&result); 28583651Speter } 28625723Stegge 28783651Speter#ifdef DB_CACHE 28867531Stegge if ((dbp = yp_open_db_cache(argp->domain, argp->map, 28967531Stegge argp->key.keydat_val, 29067531Stegge argp->key.keydat_len)) == NULL) { 29167531Stegge#else 29267531Stegge if ((dbp = yp_open_db(argp->domain, argp->map)) == NULL) { 29367531Stegge#endif 29467531Stegge result.stat = yp_errno; 29567531Stegge return(&result); 29683651Speter } 29767531Stegge 29867834Stegge key.size = argp->key.keydat_len; 29967834Stegge key.data = argp->key.keydat_val; 30067531Stegge 30167531Stegge if ((result.stat = yp_next_record(dbp, &key, &data,0,0)) == YP_TRUE) { 30267834Stegge result.key.keydat_len = key.size; 30367834Stegge result.key.keydat_val = key.data; 30467531Stegge result.val.valdat_len = data.size; 30567531Stegge result.val.valdat_val = data.data; 30667531Stegge } 30767531Stegge#ifndef DB_CACHE 30867531Stegge (void)(dbp->close)(dbp); 30967531Stegge#endif 31067531Stegge return (&result); 31183651Speter} 31267531Stegge 31367531Steggestatic void ypxfr_callback(rval,addr,transid,prognum,port) 31467531Stegge ypxfrstat rval; 31567531Stegge struct sockaddr_in *addr; 31667531Stegge unsigned int transid; 31767531Stegge unsigned int prognum; 31867531Stegge unsigned long port; 31967531Stegge{ 32067531Stegge CLIENT *clnt; 32167531Stegge int sock = RPC_ANYSOCK; 32267531Stegge struct timeval timeout; 32367531Stegge yppushresp_xfr ypxfr_resp; 32425723Stegge struct rpc_err err; 32525723Stegge 32667531Stegge timeout.tv_sec = 5; 32767531Stegge timeout.tv_usec = 0; 32825723Stegge addr->sin_port = htons(port); 32983651Speter 33067531Stegge if ((clnt = clntudp_create(addr,prognum,1,timeout,&sock)) == NULL) { 33167531Stegge yp_error("%s: %s", inet_ntoa(addr->sin_addr), 33267531Stegge clnt_spcreateerror("failed to establish callback handle")); 33367531Stegge return; 33467531Stegge } 33525723Stegge 33625723Stegge ypxfr_resp.status = rval; 33767531Stegge ypxfr_resp.transid = transid; 33867531Stegge 33925723Stegge /* Turn the timeout off -- we don't want to block. */ 34083651Speter timeout.tv_sec = 0; 34167531Stegge if (clnt_control(clnt, CLSET_TIMEOUT, (char *)&timeout) == FALSE) 34267531Stegge yp_error("failed to set timeout on ypproc_xfr callback"); 34367531Stegge 34467531Stegge if (yppushproc_xfrresp_1(&ypxfr_resp, clnt) == NULL) { 34567531Stegge clnt_geterr(clnt, &err); 34667531Stegge if (err.re_status != RPC_SUCCESS && 34767531Stegge err.re_status != RPC_TIMEDOUT) 34867531Stegge yp_error("%s", clnt_sperror(clnt, 34967531Stegge "ypxfr callback failed")); 35025723Stegge } 35167531Stegge 35267531Stegge clnt_destroy(clnt); 35367531Stegge return; 35425723Stegge} 35583651Speter 35667531Stegge#define YPXFR_RETURN(CODE) \ 35767534Stegge /* Order is important: send regular RPC reply, then callback */ \ 35867531Stegge result.xfrstat = CODE; \ 35967531Stegge svc_sendreply(rqstp->rq_xprt, xdr_ypresp_xfr, (char *)&result); \ 36067531Stegge ypxfr_callback(CODE,rqhost,argp->transid, \ 36167531Stegge argp->prog,argp->port); \ 36267531Stegge return(NULL); 36367531Stegge 36467534Steggeypresp_xfr * 36567534Steggeypproc_xfr_2_svc(ypreq_xfr *argp, struct svc_req *rqstp) 36667531Stegge{ 36767531Stegge static ypresp_xfr result; 36867531Stegge struct sockaddr_in *rqhost; 36925723Stegge 37025723Stegge result.transid = argp->transid; 37167531Stegge rqhost = svc_getcaller(rqstp->rq_xprt); 37267531Stegge 37325723Stegge#ifdef DB_CACHE 37483651Speter if (yp_access(argp->map_parms.map, 37567531Stegge argp->map_parms.domain, (struct svc_req *)rqstp)) { 37667531Stegge#else 37725723Stegge if (yp_access(argp->map_parms.map, (struct svc_req *)rqstp)) { 37825723Stegge#endif 37967531Stegge YPXFR_RETURN(YPXFR_REFUSED); 38067834Stegge } 38167834Stegge 38283651Speter if (argp->map_parms.domain == NULL) { 38367834Stegge YPXFR_RETURN(YPXFR_BADARGS); 38467834Stegge } 38567834Stegge 38667834Stegge if (yp_validdomain(argp->map_parms.domain)) { 38767834Stegge YPXFR_RETURN(YPXFR_NODOM); 38867834Stegge } 38967834Stegge 39067834Stegge switch(fork()) { 39167834Stegge case 0: 39267834Stegge { 39367834Stegge char g[11], t[11], p[11]; 39467834Stegge char ypxfr_command[MAXPATHLEN + 2]; 39567834Stegge 39667531Stegge sprintf (ypxfr_command, "%sypxfr", _PATH_LIBEXEC); 39725723Stegge sprintf (t, "%u", argp->transid); 39867531Stegge sprintf (g, "%u", argp->prog); 39967531Stegge sprintf (p, "%u", argp->port); 40083651Speter if (debug) 40167531Stegge close(0); close(1); close(2); 40267531Stegge if (strcmp(yp_dir, _PATH_YP)) { 40367531Stegge execl(ypxfr_command, "ypxfr", 40467834Stegge "-d", argp->map_parms.domain, 40567531Stegge "-h", argp->map_parms.peer, 40667531Stegge "-p", yp_dir, "-C", t, 40767834Stegge g, inet_ntoa(rqhost->sin_addr), 40867834Stegge p, argp->map_parms.map, 40967834Stegge NULL); 41025723Stegge } else { 41125723Stegge execl(ypxfr_command, "ypxfr", 41267834Stegge "-d", argp->map_parms.domain, 41325723Stegge "-h", argp->map_parms.peer, 41467834Stegge "-C", t, 41567834Stegge g, inet_ntoa(rqhost->sin_addr), 41667834Stegge p, argp->map_parms.map, 41783651Speter NULL); 41867834Stegge } 41967834Stegge forked++; 42067834Stegge yp_error("ypxfr execl(%s): %s", ypxfr_command, strerror(errno)); 42167834Stegge YPXFR_RETURN(YPXFR_XFRERR); 42267834Stegge break; 42367834Stegge } 42467834Stegge case -1: 42567834Stegge yp_error("ypxfr fork(): %s", strerror(errno)); 42667834Stegge YPXFR_RETURN(YPXFR_XFRERR); 42767834Stegge break; 42867834Stegge default: 42967834Stegge result.xfrstat = YPXFR_SUCC; 43067834Stegge children++; 43167834Stegge forked = 0; 43267834Stegge break; 43383651Speter } 43467834Stegge 43567834Stegge return (&result); 43671915Stegge} 43771915Stegge#undef YPXFR_RETURN 43871915Stegge 43971915Steggevoid * 44071915Steggeypproc_clear_2_svc(void *argp, struct svc_req *rqstp) 44167834Stegge{ 44267834Stegge static char * result; 44367834Stegge static char rval = 0; 44467834Stegge 44571915Stegge#ifdef DB_CACHE 44671915Stegge if (yp_access(NULL, NULL, (struct svc_req *)rqstp)) 44771915Stegge#else 44883651Speter if (yp_access(NULL, (struct svc_req *)rqstp)) 44971915Stegge#endif 45071915Stegge return (NULL); 45171915Stegge#ifdef DB_CACHE 45271915Stegge /* clear out the database cache */ 45371915Stegge yp_flush_all(); 45471915Stegge#endif 45571915Stegge /* Re-read the securenets database for the hell of it. */ 45671915Stegge load_securenets(); 45771915Stegge 45883651Speter result = &rval; 45971915Stegge return((void *) &result); 46071915Stegge} 46171915Stegge 46271915Stegge/* 46371915Stegge * For ypproc_all, we have to send a stream of ypresp_all structures 46471915Stegge * via TCP, but the XDR filter generated from the yp.x protocol 46571915Stegge * definition file only serializes one such structure. This means that 46671915Stegge * to send the whole stream, you need a wrapper which feeds all the 46771915Stegge * records into the underlying XDR routine until it hits an 'EOF.' 46883651Speter * But to use the wrapper, you have to violate the boundaries between 46971915Stegge * RPC layers by calling svc_sendreply() directly from the ypproc_all 47071915Stegge * service routine instead of letting the RPC dispatcher do it. 47171915Stegge * 47271915Stegge * Bleah. 47371915Stegge */ 47471915Stegge 47533181Seivind/* 47667834Stegge * Custom XDR routine for serialzing results of ypproc_all: keep 47783651Speter * reading from the database and spew until we run out of records 47867834Stegge * or encounter an error. 47971915Stegge */ 48071915Steggestatic bool_t 48183651Speterxdr_my_ypresp_all(register XDR *xdrs, ypresp_all *objp) 48267834Stegge{ 48367834Stegge DBT key = { NULL, 0 } , data = { NULL, 0 }; 48467834Stegge 48567834Stegge while (1) { 48667834Stegge /* Get a record. */ 48767834Stegge if ((objp->ypresp_all_u.val.stat = 48867834Stegge yp_next_record(spec_dbp,&key,&data,1,0)) == YP_TRUE) { 48967834Stegge objp->ypresp_all_u.val.val.valdat_len = data.size; 49067834Stegge objp->ypresp_all_u.val.val.valdat_val = data.data; 49167834Stegge objp->ypresp_all_u.val.key.keydat_len = key.size; 49267834Stegge objp->ypresp_all_u.val.key.keydat_val = key.data; 49367834Stegge objp->more = TRUE; 49467834Stegge } else { 49583651Speter objp->more = FALSE; 49671915Stegge } 49771915Stegge 49871915Stegge /* Serialize. */ 49971915Stegge if (!xdr_ypresp_all(xdrs, objp)) 50071915Stegge return(FALSE); 50171915Stegge if (objp->more == FALSE) 50283651Speter return(TRUE); 50371915Stegge } 50471915Stegge} 50571915Stegge 50671915Steggeypresp_all * 50771915Steggeypproc_all_2_svc(ypreq_nokey *argp, struct svc_req *rqstp) 50871915Stegge{ 50971915Stegge static ypresp_all result; 51071915Stegge 51171915Stegge /* 51271915Stegge * Set this here so that the client will be forced to make 51371915Stegge * at least one attempt to read from us even if all we're 51471915Stegge * doing is returning an error. 51571915Stegge */ 51671915Stegge result.more = TRUE; 51783651Speter result.ypresp_all_u.val.key.keydat_len = 0; 51867834Stegge result.ypresp_all_u.val.key.keydat_val = ""; 51983651Speter 52071915Stegge#ifdef DB_CACHE 52171915Stegge if (yp_access(argp->map, argp->domain, (struct svc_req *)rqstp)) { 52271915Stegge#else 52371915Stegge if (yp_access(argp->map, (struct svc_req *)rqstp)) { 52467834Stegge#endif 52567834Stegge result.ypresp_all_u.val.stat = YP_YPERR; 52667834Stegge return (&result); 52767834Stegge } 52867834Stegge 52967834Stegge if (argp->domain == NULL || argp->map == NULL) { 53067834Stegge result.ypresp_all_u.val.stat = YP_BADARGS; 53183651Speter return (&result); 53283651Speter } 53367834Stegge 53483651Speter /* 53567834Stegge * The ypproc_all procedure can take a while to complete. 53671915Stegge * Best to handle it in a subprocess so the parent doesn't 53771915Stegge * block. (Is there a better way to do this? Maybe with 53871915Stegge * async socket I/O?) 53971915Stegge */ 54071915Stegge if (!debug && children < MAX_CHILDREN && fork()) { 54171915Stegge children++; 54271915Stegge forked = 0; 54371915Stegge return (NULL); 54471915Stegge } else { 54571915Stegge forked++; 54671915Stegge } 54783651Speter 54883651Speter#ifndef DB_CACHE 54971915Stegge if ((spec_dbp = yp_open_db(argp->domain, argp->map)) == NULL) { 55071915Stegge result.ypresp_all_u.val.stat = yp_errno; 55171915Stegge return(&result); 55271915Stegge } 55371915Stegge#else 55471915Stegge if ((spec_dbp = yp_open_db_cache(argp->domain, argp->map, NULL, 0)) == NULL) { 55571915Stegge result.ypresp_all_u.val.stat = yp_errno; 55671915Stegge return(&result); 55771915Stegge } 55871915Stegge#endif 55971915Stegge 56083651Speter /* Kick off the actual data transfer. */ 56167834Stegge svc_sendreply(rqstp->rq_xprt, xdr_my_ypresp_all, (char *)&result); 56267834Stegge 56367834Stegge#ifndef DB_CACHE 56467834Stegge (void)(spec_dbp->close)(spec_dbp); 56567834Stegge#endif 56667834Stegge /* 56767834Stegge * Returning NULL prevents the dispatcher from calling 56867834Stegge * svc_sendreply() since we already did it. 56967834Stegge */ 57067834Stegge return (NULL); 57167834Stegge} 57267834Stegge 57367834Steggeypresp_master * 57483651Speterypproc_master_2_svc(ypreq_nokey *argp, struct svc_req *rqstp) 57525723Stegge{ 57625723Stegge static ypresp_master result; 57767834Stegge static char ypvalbuf[YPMAXRECORD]; 57825723Stegge DBT key = { master_string, master_sz }, data; 57938482Swollman 58025723Stegge result.peer = ""; 58167834Stegge 58267834Stegge#ifdef DB_CACHE 58367834Stegge if (yp_access(argp->map, argp->domain, (struct svc_req *)rqstp)) { 58438482Swollman#else 58567834Stegge if (yp_access(argp->map, (struct svc_req *)rqstp)) { 58667834Stegge#endif 58767834Stegge result.stat = YP_YPERR; 58871915Stegge return(&result); 58971915Stegge } 59083651Speter 59125723Stegge if (argp->domain == NULL) { 59225723Stegge result.stat = YP_BADARGS; 59325723Stegge return (&result); 59491406Sjhb } 59567834Stegge 59625723Stegge /* 59783651Speter * Note that we copy the data retrieved from the database to 59838482Swollman * a private buffer and NUL terminate the buffer rather than 59938482Swollman * terminating the data in place. We do this because by stuffing 60067834Stegge * a '\0' into data.data, we will actually be corrupting memory 60138482Swollman * allocated by the DB package. This is a bad thing now that we 60238482Swollman * cache DB handles rather than closing the database immediately. 60338482Swollman */ 60438482Swollman if ((result.stat = yp_get_record(argp->domain, argp->map, 60583651Speter &key, &data, 1)) == YP_TRUE) { 60667834Stegge bcopy((char *)data.data, (char *)&ypvalbuf, data.size); 60767834Stegge ypvalbuf[data.size] = '\0'; 60825723Stegge result.peer = (char *)&ypvalbuf; 60983651Speter } else 61025723Stegge result.peer = ""; 61125723Stegge 61225723Stegge return (&result); 61338482Swollman} 61467834Stegge 61538482Swollmanypresp_order * 61638482Swollmanypproc_order_2_svc(ypreq_nokey *argp, struct svc_req *rqstp) 61767834Stegge{ 61867834Stegge static ypresp_order result; 61967834Stegge DBT key = { order_string, order_sz }, data; 62038482Swollman 62125723Stegge result.ordernum = 0; 62225723Stegge 62367834Stegge#ifdef DB_CACHE 62467834Stegge if (yp_access(argp->map, argp->domain, (struct svc_req *)rqstp)) { 62567834Stegge#else 62667834Stegge if (yp_access(argp->map, (struct svc_req *)rqstp)) { 62767834Stegge#endif 62867834Stegge result.stat = YP_YPERR; 62967834Stegge return(&result); 63067834Stegge } 63167834Stegge 63267834Stegge if (argp->domain == NULL) { 63367834Stegge result.stat = YP_BADARGS; 63483651Speter return (&result); 63567834Stegge } 63625723Stegge 63725723Stegge /* 63867834Stegge * We could just check the timestamp on the map file, 63967834Stegge * but that's a hack: we'll only know the last time the file 64025723Stegge * was touched, not the last time the database contents were 64183366Sjulian * updated. 64267834Stegge */ 64325723Stegge 64425723Stegge if ((result.stat = yp_get_record(argp->domain, argp->map, 64525723Stegge &key, &data, 1)) == YP_TRUE) 64683651Speter result.ordernum = atoi((char *)data.data); 64725723Stegge else 64825723Stegge result.ordernum = 0; 64925723Stegge 65067834Stegge 65167834Stegge return (&result); 65225723Stegge} 65325723Stegge 65483651Speterstatic void yp_maplist_free(yp_maplist) 65525723Stegge struct ypmaplist *yp_maplist; 65625723Stegge{ 65725723Stegge register struct ypmaplist *next; 65825723Stegge 65925723Stegge while(yp_maplist) { 66025723Stegge next = yp_maplist->next; 66167834Stegge free(yp_maplist->map); 66225723Stegge free(yp_maplist); 66383651Speter yp_maplist = next; 66467834Stegge } 66567834Stegge return; 66667834Stegge} 66767834Stegge 66867834Steggestatic struct ypmaplist *yp_maplist_create(domain) 66967834Stegge const char *domain; 67071915Stegge{ 67167834Stegge char yp_mapdir[MAXPATHLEN + 2]; 67267834Stegge char yp_mapname[MAXPATHLEN + 2]; 67367834Stegge struct ypmaplist *cur = NULL; 67467834Stegge struct ypmaplist *yp_maplist = NULL; 67567834Stegge DIR *dird; 67683651Speter struct dirent *dirp; 67767834Stegge struct stat statbuf; 67867834Stegge 67967834Stegge snprintf(yp_mapdir, sizeof(yp_mapdir), "%s/%s", yp_dir, domain); 68067834Stegge 68171915Stegge if ((dird = opendir(yp_mapdir)) == NULL) { 68267834Stegge yp_error("opendir(%s) failed: %s", yp_mapdir, strerror(errno)); 68367834Stegge return(NULL); 68467834Stegge } 68571915Stegge 68667834Stegge while ((dirp = readdir(dird)) != NULL) { 68725723Stegge if (strcmp(dirp->d_name, ".") && strcmp(dirp->d_name, "..")) { 68867834Stegge snprintf(yp_mapname, sizeof(yp_mapname), "%s/%s", 68967834Stegge yp_mapdir,dirp->d_name); 69067834Stegge if (stat(yp_mapname, &statbuf) < 0 || 69171915Stegge !S_ISREG(statbuf.st_mode)) 69271915Stegge continue; 69371915Stegge if ((cur = (struct ypmaplist *) 69471915Stegge malloc(sizeof(struct ypmaplist))) == NULL) { 69571915Stegge yp_error("malloc() failed: %s",strerror(errno)); 69671915Stegge closedir(dird); 69771915Stegge yp_maplist_free(yp_maplist); 69871915Stegge return(NULL); 69983366Sjulian } 70071915Stegge if ((cur->map = (char *)strdup(dirp->d_name)) == NULL) { 70183651Speter yp_error("strdup() failed: %s",strerror(errno)); 70267834Stegge closedir(dird); 70383651Speter yp_maplist_free(yp_maplist); 70467834Stegge return(NULL); 70571915Stegge } 70671915Stegge cur->next = yp_maplist; 70771915Stegge yp_maplist = cur; 70871915Stegge if (debug) 70971915Stegge yp_error("map: %s", yp_maplist->map); 71071915Stegge } 71171915Stegge 71271915Stegge } 71371915Stegge closedir(dird); 71471915Stegge return(yp_maplist); 71571915Stegge} 71671915Stegge 71771915Steggeypresp_maplist * 71867834Steggeypproc_maplist_2_svc(domainname *argp, struct svc_req *rqstp) 71971915Stegge{ 72067834Stegge static ypresp_maplist result = { 0, NULL }; 72167834Stegge 72267834Stegge#ifdef DB_CACHE 72367834Stegge if (yp_access(NULL, NULL, (struct svc_req *)rqstp)) { 72467834Stegge#else 72567834Stegge if (yp_access(NULL, (struct svc_req *)rqstp)) { 72667834Stegge#endif 72767834Stegge result.stat = YP_YPERR; 72867834Stegge return(&result); 72983651Speter } 73067834Stegge 73167834Stegge if (argp == NULL) { 73267834Stegge result.stat = YP_BADARGS; 73367834Stegge return (&result); 73467834Stegge } 73567834Stegge 73683366Sjulian if (yp_validdomain(*argp)) { 73783651Speter result.stat = YP_NODOM; 73867834Stegge return (&result); 73983651Speter } 74067834Stegge 74167834Stegge /* 74267834Stegge * We have to construct a linked list for the ypproc_maplist 74383366Sjulian * procedure using dynamically allocated memory. Since the XDR 74467834Stegge * layer won't free this list for us, we have to deal with it 74567834Stegge * ourselves. We call yp_maplist_free() first to free any 74667834Stegge * previously allocated data we may have accumulated to insure 74767834Stegge * that we have only one linked list in memory at any given 74883651Speter * time. 74967834Stegge */ 75083366Sjulian 75167834Stegge yp_maplist_free(result.maps); 75267834Stegge 75367834Stegge if ((result.maps = yp_maplist_create(*argp)) == NULL) { 75467834Stegge yp_error("yp_maplist_create failed"); 75567834Stegge result.stat = YP_YPERR; 75667834Stegge return(&result); 75767834Stegge } else 75883651Speter result.stat = YP_TRUE; 75967834Stegge 76083651Speter return (&result); 76167834Stegge} 76267834Stegge 76367834Stegge/* 76467834Stegge * NIS v1 support. The nullproc, domain and domain_nonack 76583366Sjulian * functions from v1 are identical to those in v2, so all 76667834Stegge * we have to do is hand off to them. 76767834Stegge * 76867834Stegge * The other functions are mostly just wrappers around their v2 76967834Stegge * counterparts. For example, for the v1 'match' procedure, we 77083651Speter * crack open the argument structure, make a request to the v2 77125723Stegge * 'match' function, repackage the data into a v1 response and 77283651Speter * then send it on its way. 77367834Stegge * 77467834Stegge * Note that we don't support the pull, push and get procedures. 77567834Stegge * There's little documentation available to show what they 77667834Stegge * do, and I suspect they're meant largely for map transfers 77767834Stegge * between master and slave servers. 77883651Speter */ 77925723Stegge 78025723Steggevoid * 78125723Steggeypoldproc_null_1_svc(void *argp, struct svc_req *rqstp) 78267834Stegge{ 78371915Stegge return(ypproc_null_2_svc(argp, rqstp)); 78467834Stegge} 78567834Stegge 78667834Steggebool_t * 78783651Speterypoldproc_domain_1_svc(domainname *argp, struct svc_req *rqstp) 78825723Stegge{ 78925723Stegge return(ypproc_domain_2_svc(argp, rqstp)); 79025723Stegge} 79125723Stegge 79267834Steggebool_t * 79367834Steggeypoldproc_domain_nonack_1_svc(domainname *argp, struct svc_req *rqstp) 79467834Stegge{ 79567834Stegge return (ypproc_domain_nonack_2_svc(argp, rqstp)); 79683651Speter} 79725723Stegge 79825723Stegge/* 79925723Stegge * the 'match' procedure sends a response of type YPRESP_VAL 80025723Stegge */ 80125723Steggeypresponse * 80267834Steggeypoldproc_match_1_svc(yprequest *argp, struct svc_req *rqstp) 80383366Sjulian{ 80483651Speter static ypresponse result; 80525723Stegge ypresp_val *v2_result; 80667531Stegge 80767531Stegge result.yp_resptype = YPRESP_VAL; 80867834Stegge result.ypresponse_u.yp_resp_valtype.val.valdat_val = ""; 80967834Stegge result.ypresponse_u.yp_resp_valtype.val.valdat_len = 0; 81067834Stegge 81167834Stegge if (argp->yp_reqtype != YPREQ_KEY) { 81271915Stegge result.ypresponse_u.yp_resp_valtype.stat = YP_BADARGS; 81371915Stegge return(&result); 81467834Stegge } 81583651Speter 81667834Stegge v2_result = ypproc_match_2_svc(&argp->yprequest_u.yp_req_keytype,rqstp); 81767834Stegge if (v2_result == NULL) 81867834Stegge return(NULL); 81925723Stegge 82067834Stegge bcopy((char *)v2_result, 82125723Stegge (char *)&result.ypresponse_u.yp_resp_valtype, 82267834Stegge sizeof(ypresp_val)); 82383651Speter 82432609Stegge return (&result); 82532609Stegge} 82625723Stegge 82767834Stegge/* 82883651Speter * the 'first' procedure sends a response of type YPRESP_KEY_VAL 82967834Stegge */ 83067834Steggeypresponse * 83167531Steggeypoldproc_first_1_svc(yprequest *argp, struct svc_req *rqstp) 83283651Speter{ 83367834Stegge static ypresponse result; 83467834Stegge ypresp_key_val *v2_result; 83567834Stegge 83667834Stegge result.yp_resptype = YPRESP_KEY_VAL; 83767834Stegge result.ypresponse_u.yp_resp_key_valtype.val.valdat_val = 83867834Stegge result.ypresponse_u.yp_resp_key_valtype.key.keydat_val = ""; 83983651Speter result.ypresponse_u.yp_resp_key_valtype.val.valdat_len = 84067834Stegge result.ypresponse_u.yp_resp_key_valtype.key.keydat_len = 0; 84167834Stegge 84267834Stegge if (argp->yp_reqtype != YPREQ_NOKEY) { 84383651Speter result.ypresponse_u.yp_resp_key_valtype.stat = YP_BADARGS; 84467834Stegge return(&result); 84567834Stegge } 84667834Stegge 84767834Stegge v2_result = ypproc_first_2_svc(&argp->yprequest_u.yp_req_nokeytype, 84867834Stegge rqstp); 84925723Stegge if (v2_result == NULL) 85067834Stegge return(NULL); 85167834Stegge 85225723Stegge bcopy((char *)v2_result, 85367834Stegge (char *)&result.ypresponse_u.yp_resp_key_valtype, 85471915Stegge sizeof(ypresp_key_val)); 85571915Stegge 85671915Stegge return (&result); 85771915Stegge} 85871915Stegge 85971915Stegge/* 86071915Stegge * the 'next' procedure sends a response of type YPRESP_KEY_VAL 86171915Stegge */ 86271915Steggeypresponse * 86371915Steggeypoldproc_next_1_svc(yprequest *argp, struct svc_req *rqstp) 86471915Stegge{ 86571915Stegge static ypresponse result; 86671915Stegge ypresp_key_val *v2_result; 86771915Stegge 86871915Stegge result.yp_resptype = YPRESP_KEY_VAL; 86971915Stegge result.ypresponse_u.yp_resp_key_valtype.val.valdat_val = 87071915Stegge result.ypresponse_u.yp_resp_key_valtype.key.keydat_val = ""; 87171915Stegge result.ypresponse_u.yp_resp_key_valtype.val.valdat_len = 87271915Stegge result.ypresponse_u.yp_resp_key_valtype.key.keydat_len = 0; 87371915Stegge 87467834Stegge if (argp->yp_reqtype != YPREQ_KEY) { 87571915Stegge result.ypresponse_u.yp_resp_key_valtype.stat = YP_BADARGS; 87667834Stegge return(&result); 87767834Stegge } 87867834Stegge 87967834Stegge v2_result = ypproc_next_2_svc(&argp->yprequest_u.yp_req_keytype,rqstp); 88067834Stegge if (v2_result == NULL) 88167834Stegge return(NULL); 88267834Stegge 88367834Stegge bcopy((char *)v2_result, 88467834Stegge (char *)&result.ypresponse_u.yp_resp_key_valtype, 88567834Stegge sizeof(ypresp_key_val)); 88667834Stegge 88767834Stegge return (&result); 88867834Stegge} 88967834Stegge 89067834Stegge/* 89167834Stegge * the 'poll' procedure sends a response of type YPRESP_MAP_PARMS 89267834Stegge */ 89367834Steggeypresponse * 89467834Steggeypoldproc_poll_1_svc(yprequest *argp, struct svc_req *rqstp) 89567834Stegge{ 89667834Stegge static ypresponse result; 89767834Stegge ypresp_master *v2_result1; 89867834Stegge ypresp_order *v2_result2; 89967834Stegge 90067834Stegge result.yp_resptype = YPRESP_MAP_PARMS; 90167834Stegge result.ypresponse_u.yp_resp_map_parmstype.domain = 90267834Stegge argp->yprequest_u.yp_req_nokeytype.domain; 90367834Stegge result.ypresponse_u.yp_resp_map_parmstype.map = 90425723Stegge argp->yprequest_u.yp_req_nokeytype.map; 90567834Stegge /* 90667834Stegge * Hmm... there is no 'status' value in the 90767834Stegge * yp_resp_map_parmstype structure, so I have to 90867834Stegge * guess at what to do to indicate a failure. 90971915Stegge * I hope this is right. 91071915Stegge */ 91171915Stegge result.ypresponse_u.yp_resp_map_parmstype.ordernum = 0; 91271915Stegge result.ypresponse_u.yp_resp_map_parmstype.peer = ""; 91371915Stegge 91471915Stegge if (argp->yp_reqtype != YPREQ_MAP_PARMS) { 91571915Stegge return(&result); 91671915Stegge } 91771915Stegge 91871915Stegge v2_result1 = ypproc_master_2_svc(&argp->yprequest_u.yp_req_nokeytype, 91971915Stegge rqstp); 92083651Speter if (v2_result1 == NULL) 92171915Stegge return(NULL); 92271915Stegge 92383651Speter if (v2_result1->stat != YP_TRUE) { 92467834Stegge return(&result); 92567834Stegge } 92667834Stegge 92767834Stegge v2_result2 = ypproc_order_2_svc(&argp->yprequest_u.yp_req_nokeytype, 92867834Stegge rqstp); 92925723Stegge if (v2_result2 == NULL) 93083651Speter return(NULL); 93183651Speter 93267834Stegge if (v2_result2->stat != YP_TRUE) { 93367834Stegge return(&result); 93467834Stegge } 93525723Stegge 93667834Stegge result.ypresponse_u.yp_resp_map_parmstype.peer = 93771915Stegge v2_result1->peer; 93871915Stegge result.ypresponse_u.yp_resp_map_parmstype.ordernum = 93971915Stegge v2_result2->ordernum; 94071915Stegge 94167834Stegge return (&result); 94267834Stegge} 94367834Stegge 94467834Steggeypresponse * 94567834Steggeypoldproc_push_1_svc(yprequest *argp, struct svc_req *rqstp) 94667834Stegge{ 94767834Stegge static ypresponse result; 94867834Stegge 94967834Stegge /* 95067834Stegge * Not implemented. 95167834Stegge */ 95267834Stegge 95371915Stegge return (&result); 95467834Stegge} 95567834Stegge 95667834Steggeypresponse * 95767834Steggeypoldproc_pull_1_svc(yprequest *argp, struct svc_req *rqstp) 95867834Stegge{ 95925723Stegge static ypresponse result; 96025723Stegge 96183651Speter /* 96267531Stegge * Not implemented. 96367531Stegge */ 96425723Stegge 96525723Stegge return (&result); 96625723Stegge} 96725723Stegge 96867531Steggeypresponse * 96967834Steggeypoldproc_get_1_svc(yprequest *argp, struct svc_req *rqstp) 97083651Speter{ 97125723Stegge static ypresponse result; 97267531Stegge 97367531Stegge /* 97467834Stegge * Not implemented. 97567834Stegge */ 97667834Stegge 97767834Stegge return (&result); 97825723Stegge} 97991406Sjhb