ypbind.c revision 213611
11927Swollman/* 21927Swollman * Copyright (c) 1992/3 Theo de Raadt <deraadt@fsa.ca> 31927Swollman * All rights reserved. 41927Swollman * 51927Swollman * Redistribution and use in source and binary forms, with or without 61927Swollman * modification, are permitted provided that the following conditions 71927Swollman * are met: 81927Swollman * 1. Redistributions of source code must retain the above copyright 91927Swollman * notice, this list of conditions and the following disclaimer. 101927Swollman * 2. Redistributions in binary form must reproduce the above copyright 111927Swollman * notice, this list of conditions and the following disclaimer in the 121927Swollman * documentation and/or other materials provided with the distribution. 131927Swollman * 3. The name of the author may not be used to endorse or promote 141927Swollman * products derived from this software without specific prior written 151927Swollman * permission. 161927Swollman * 171927Swollman * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 181927Swollman * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 191927Swollman * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 201927Swollman * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 211927Swollman * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 221927Swollman * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 231927Swollman * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 241927Swollman * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 251927Swollman * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 261927Swollman * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 271927Swollman * SUCH DAMAGE. 281927Swollman */ 291927Swollman 30114601Sobrien#include <sys/cdefs.h> 31114601Sobrien__FBSDID("$FreeBSD: head/usr.sbin/ypbind/ypbind.c 213611 2010-10-08 20:17:17Z markm $"); 321927Swollman 331927Swollman#include <sys/param.h> 341927Swollman#include <sys/types.h> 358091Swpaul#include <sys/wait.h> 361927Swollman#include <sys/ioctl.h> 371927Swollman#include <sys/signal.h> 381927Swollman#include <sys/socket.h> 391927Swollman#include <sys/file.h> 401927Swollman#include <sys/fcntl.h> 418091Swpaul#include <sys/stat.h> 421927Swollman#include <sys/uio.h> 431927Swollman#include <ctype.h> 441927Swollman#include <dirent.h> 4530762Scharnier#include <err.h> 4630762Scharnier#include <errno.h> 471927Swollman#include <netdb.h> 4830762Scharnier#include <signal.h> 4930762Scharnier#include <stdio.h> 5030762Scharnier#include <stdlib.h> 511927Swollman#include <string.h> 5230762Scharnier#include <syslog.h> 5330762Scharnier#include <unistd.h> 541927Swollman#include <rpc/rpc.h> 551927Swollman#include <rpc/xdr.h> 561927Swollman#include <net/if.h> 576732Swpaul#include <netinet/in.h> 581927Swollman#include <arpa/inet.h> 591927Swollman#include <rpc/pmap_clnt.h> 601927Swollman#include <rpc/pmap_prot.h> 611927Swollman#include <rpc/pmap_rmt.h> 6230762Scharnier#include <rpc/rpc_com.h> 6312862Swpaul#include <rpcsvc/yp.h> 641927Swollman#include <rpcsvc/ypclnt.h> 6526135Swpaul#include "yp_ping.h" 661927Swollman 671927Swollman#ifndef BINDINGDIR 681927Swollman#define BINDINGDIR "/var/yp/binding" 691927Swollman#endif 701927Swollman 718474Swpaul#ifndef YPBINDLOCK 728474Swpaul#define YPBINDLOCK "/var/run/ypbind.lock" 738474Swpaul#endif 748474Swpaul 751927Swollmanstruct _dom_binding { 761927Swollman struct _dom_binding *dom_pnext; 771927Swollman char dom_domain[YPMAXDOMAIN + 1]; 781927Swollman struct sockaddr_in dom_server_addr; 791927Swollman long int dom_vers; 801927Swollman int dom_lockfd; 811927Swollman int dom_alive; 828755Swpaul int dom_broadcast_pid; 838755Swpaul int dom_pipe_fds[2]; 848091Swpaul int dom_default; 851927Swollman}; 861927Swollman 878755Swpaul#define READFD ypdb->dom_pipe_fds[0] 888755Swpaul#define WRITEFD ypdb->dom_pipe_fds[1] 898755Swpaul#define BROADFD broad_domain->dom_pipe_fds[1] 908755Swpaul 911927Swollmanextern bool_t xdr_domainname(), xdr_ypbind_resp(); 921927Swollmanextern bool_t xdr_ypreq_key(), xdr_ypresp_val(); 931927Swollmanextern bool_t xdr_ypbind_setdom(); 941927Swollman 9590297Sdesvoid checkwork(void); 9690297Sdesvoid *ypbindproc_null_2_yp(SVCXPRT *, void *, CLIENT *); 9790297Sdesvoid *ypbindproc_setdom_2_yp(SVCXPRT *, struct ypbind_setdom *, CLIENT *); 9890297Sdesvoid rpc_received(char *, struct sockaddr_in *, int); 9990297Sdesvoid broadcast(struct _dom_binding *); 10090297Sdesint ping(struct _dom_binding *); 10190297Sdesint tell_parent(char *, struct sockaddr_in *); 10290297Sdesvoid handle_children(struct _dom_binding *); 10390297Sdesvoid reaper(int); 10490297Sdesvoid terminate(int); 10590297Sdesvoid yp_restricted_mode(char *); 10690297Sdesint verify(struct in_addr); 1078091Swpaul 10812862Swpaulchar *domain_name; 1091927Swollmanstruct _dom_binding *ypbindlist; 1108755Swpaulstatic struct _dom_binding *broad_domain; 1111927Swollman 1121927Swollman#define YPSET_NO 0 1131927Swollman#define YPSET_LOCAL 1 1141927Swollman#define YPSET_ALL 2 1151927Swollmanint ypsetmode = YPSET_NO; 1166732Swpaulint ypsecuremode = 0; 11721581Swpaulint ppid; 1186732Swpaul 119213611Smarkm#define NOT_RESPONDING_HYSTERESIS 10 120213611Smarkmstatic int not_responding_count = 0; 121213611Smarkm 1229600Swpaul/* 1239600Swpaul * Special restricted mode variables: when in restricted mode, only the 1249600Swpaul * specified restricted_domain will be bound, and only the servers listed 1259600Swpaul * in restricted_addrs will be used for binding. 1269600Swpaul */ 1279600Swpaul#define RESTRICTED_SERVERS 10 1289600Swpaulint yp_restricted = 0; 12926135Swpaulint yp_manycast = 0; 1309600Swpaulstruct in_addr restricted_addrs[RESTRICTED_SERVERS]; 1319600Swpaul 1328091Swpaul/* No more than MAX_CHILDREN child broadcasters at a time. */ 1338755Swpaul#ifndef MAX_CHILDREN 1348091Swpaul#define MAX_CHILDREN 5 1358755Swpaul#endif 1368425Swpaul/* No more than MAX_DOMAINS simultaneous domains */ 1378755Swpaul#ifndef MAX_DOMAINS 1388425Swpaul#define MAX_DOMAINS 200 1398755Swpaul#endif 1408755Swpaul/* RPC timeout value */ 1418425Swpaul#ifndef FAIL_THRESHOLD 14221539Swpaul#define FAIL_THRESHOLD 20 1438425Swpaul#endif 1448425Swpaul 1459600Swpaul/* Number of times to fish for a response froma particular set of hosts */ 1469600Swpaul#ifndef MAX_RETRIES 1479600Swpaul#define MAX_RETRIES 30 1489600Swpaul#endif 1499600Swpaul 1509600Swpaulint retries = 0; 1518091Swpaulint children = 0; 1528425Swpaulint domains = 0; 1538474Swpaulint yplockfd; 1548755Swpaulfd_set fdsr; 1558091Swpaul 1561927SwollmanSVCXPRT *udptransp, *tcptransp; 1571927Swollman 1581927Swollmanvoid * 15990298Sdesypbindproc_null_2_yp(SVCXPRT *transp, void *argp, CLIENT *clnt) 1601927Swollman{ 1611927Swollman static char res; 1621927Swollman 16395658Sdes bzero(&res, sizeof(res)); 16495658Sdes return &res; 1651927Swollman} 1661927Swollman 1671927Swollmanstruct ypbind_resp * 16890298Sdesypbindproc_domain_2_yp(SVCXPRT *transp, domainname *argp, CLIENT *clnt) 1691927Swollman{ 1701927Swollman static struct ypbind_resp res; 1711927Swollman struct _dom_binding *ypdb; 1721927Swollman char path[MAXPATHLEN]; 1731927Swollman 17495658Sdes bzero(&res, sizeof res); 1751927Swollman res.ypbind_status = YPBIND_FAIL_VAL; 17612862Swpaul res.ypbind_resp_u.ypbind_error = YPBIND_ERR_NOSERV; 1771927Swollman 17824782Swpaul if (strchr(*argp, '/')) { 17924782Swpaul syslog(LOG_WARNING, "Domain name '%s' has embedded slash -- \ 18024782Swpaulrejecting.", *argp); 18124782Swpaul return(&res); 18224782Swpaul } 18324782Swpaul 18490297Sdes for (ypdb = ypbindlist; ypdb; ypdb = ypdb->dom_pnext) { 18590297Sdes if (strcmp(ypdb->dom_domain, *argp) == 0) 1861927Swollman break; 1878755Swpaul } 1881927Swollman 18990297Sdes if (ypdb == NULL) { 1909600Swpaul if (yp_restricted) { 19112862Swpaul syslog(LOG_NOTICE, "Running in restricted mode -- request to bind domain \"%s\" rejected.\n", *argp); 19290297Sdes return (&res); 1939600Swpaul } 1949600Swpaul 1958474Swpaul if (domains >= MAX_DOMAINS) { 1968425Swpaul syslog(LOG_WARNING, "domain limit (%d) exceeded", 1978425Swpaul MAX_DOMAINS); 19812862Swpaul res.ypbind_resp_u.ypbind_error = YPBIND_ERR_RESC; 19990297Sdes return (&res); 2008425Swpaul } 2011927Swollman ypdb = (struct _dom_binding *)malloc(sizeof *ypdb); 2028857Srgrimes if (ypdb == NULL) { 20321539Swpaul syslog(LOG_WARNING, "malloc: %m"); 20412862Swpaul res.ypbind_resp_u.ypbind_error = YPBIND_ERR_RESC; 20590297Sdes return (&res); 2068246Swpaul } 20795658Sdes bzero(ypdb, sizeof *ypdb); 20812862Swpaul strncpy(ypdb->dom_domain, *argp, sizeof ypdb->dom_domain); 2091927Swollman ypdb->dom_vers = YPVERS; 2101927Swollman ypdb->dom_alive = 0; 2118091Swpaul ypdb->dom_default = 0; 2121927Swollman ypdb->dom_lockfd = -1; 2138425Swpaul sprintf(path, "%s/%s.%ld", BINDINGDIR, 2148425Swpaul ypdb->dom_domain, ypdb->dom_vers); 2151927Swollman unlink(path); 2161927Swollman ypdb->dom_pnext = ypbindlist; 2171927Swollman ypbindlist = ypdb; 2188425Swpaul domains++; 2191927Swollman } 2201927Swollman 2218755Swpaul if (ping(ypdb)) { 22290297Sdes return (&res); 2238755Swpaul } 2241927Swollman 2251927Swollman res.ypbind_status = YPBIND_SUCC_VAL; 22612862Swpaul res.ypbind_resp_u.ypbind_error = 0; /* Success */ 22745656Ssimokawa *(u_int32_t *)&res.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_addr = 2281927Swollman ypdb->dom_server_addr.sin_addr.s_addr; 22912862Swpaul *(u_short *)&res.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_port = 2308091Swpaul ypdb->dom_server_addr.sin_port; 2311927Swollman /*printf("domain %s at %s/%d\n", ypdb->dom_domain, 2321927Swollman inet_ntoa(ypdb->dom_server_addr.sin_addr), 2331927Swollman ntohs(ypdb->dom_server_addr.sin_port));*/ 23490297Sdes return (&res); 2351927Swollman} 2361927Swollman 2378755Swpaulvoid * 23890298Sdesypbindproc_setdom_2_yp(SVCXPRT *transp, ypbind_setdom *argp, CLIENT *clnt) 2391927Swollman{ 2401927Swollman struct sockaddr_in *fromsin, bindsin; 24143854Swpaul static char *result = NULL; 2421927Swollman 24324782Swpaul if (strchr(argp->ypsetdom_domain, '/')) { 24424782Swpaul syslog(LOG_WARNING, "Domain name '%s' has embedded slash -- \ 24524782Swpaulrejecting.", argp->ypsetdom_domain); 24630762Scharnier return(NULL); 24724782Swpaul } 2481927Swollman fromsin = svc_getcaller(transp); 2491927Swollman 25090297Sdes switch (ypsetmode) { 2511927Swollman case YPSET_LOCAL: 25290297Sdes if (fromsin->sin_addr.s_addr != htonl(INADDR_LOOPBACK)) { 2538755Swpaul svcerr_noprog(transp); 25430762Scharnier return(NULL); 2558755Swpaul } 2561927Swollman break; 2571927Swollman case YPSET_ALL: 2581927Swollman break; 2591927Swollman case YPSET_NO: 2601927Swollman default: 2618755Swpaul svcerr_noprog(transp); 26230762Scharnier return(NULL); 2631927Swollman } 2641927Swollman 26590297Sdes if (ntohs(fromsin->sin_port) >= IPPORT_RESERVED) { 2668755Swpaul svcerr_noprog(transp); 26730762Scharnier return(NULL); 2688755Swpaul } 2691927Swollman 27090297Sdes if (argp->ypsetdom_vers != YPVERS) { 2718755Swpaul svcerr_noprog(transp); 27230762Scharnier return(NULL); 2738755Swpaul } 2741927Swollman 27595658Sdes bzero(&bindsin, sizeof bindsin); 2761927Swollman bindsin.sin_family = AF_INET; 27745656Ssimokawa bindsin.sin_addr.s_addr = *(u_int32_t *)argp->ypsetdom_binding.ypbind_binding_addr; 27812862Swpaul bindsin.sin_port = *(u_short *)argp->ypsetdom_binding.ypbind_binding_port; 2791927Swollman rpc_received(argp->ypsetdom_domain, &bindsin, 1); 2801927Swollman 28143854Swpaul return((void *) &result); 2821927Swollman} 2831927Swollman 28495658Sdesvoid 28590298Sdesypbindprog_2(struct svc_req *rqstp, register SVCXPRT *transp) 2861927Swollman{ 2871927Swollman union { 28812862Swpaul domainname ypbindproc_domain_2_arg; 2891927Swollman struct ypbind_setdom ypbindproc_setdom_2_arg; 2901927Swollman } argument; 2911927Swollman struct authunix_parms *creds; 2921927Swollman char *result; 2931927Swollman bool_t (*xdr_argument)(), (*xdr_result)(); 2941927Swollman char *(*local)(); 2951927Swollman 2961927Swollman switch (rqstp->rq_proc) { 2971927Swollman case YPBINDPROC_NULL: 2981927Swollman xdr_argument = xdr_void; 2991927Swollman xdr_result = xdr_void; 30032631Swpaul local = (char *(*)()) ypbindproc_null_2_yp; 3011927Swollman break; 3021927Swollman 3031927Swollman case YPBINDPROC_DOMAIN: 3041927Swollman xdr_argument = xdr_domainname; 3051927Swollman xdr_result = xdr_ypbind_resp; 30632631Swpaul local = (char *(*)()) ypbindproc_domain_2_yp; 3071927Swollman break; 3081927Swollman 3091927Swollman case YPBINDPROC_SETDOM: 31090297Sdes switch (rqstp->rq_cred.oa_flavor) { 3111927Swollman case AUTH_UNIX: 3121927Swollman creds = (struct authunix_parms *)rqstp->rq_clntcred; 31390297Sdes if (creds->aup_uid != 0) { 3141927Swollman svcerr_auth(transp, AUTH_BADCRED); 3151927Swollman return; 3161927Swollman } 3171927Swollman break; 3181927Swollman default: 3191927Swollman svcerr_auth(transp, AUTH_TOOWEAK); 3201927Swollman return; 3211927Swollman } 3221927Swollman 3231927Swollman xdr_argument = xdr_ypbind_setdom; 3241927Swollman xdr_result = xdr_void; 32532631Swpaul local = (char *(*)()) ypbindproc_setdom_2_yp; 3261927Swollman break; 3271927Swollman 3281927Swollman default: 3291927Swollman svcerr_noproc(transp); 3301927Swollman return; 3311927Swollman } 33295658Sdes bzero(&argument, sizeof(argument)); 33395658Sdes if (!svc_getargs(transp, (xdrproc_t)xdr_argument, &argument)) { 3341927Swollman svcerr_decode(transp); 3351927Swollman return; 3361927Swollman } 3371927Swollman result = (*local)(transp, &argument, rqstp); 33895658Sdes if (result != NULL && 33995658Sdes !svc_sendreply(transp, (xdrproc_t)xdr_result, result)) { 3401927Swollman svcerr_systemerr(transp); 3411927Swollman } 3421927Swollman return; 3431927Swollman} 3441927Swollman 3458091Swpaul/* Jack the reaper */ 34690298Sdesvoid 34790298Sdesreaper(int sig) 3488091Swpaul{ 3498091Swpaul int st; 3508091Swpaul 35190297Sdes while (wait3(&st, WNOHANG, NULL) > 0) 3529532Swpaul children--; 3538091Swpaul} 3548091Swpaul 35590298Sdesvoid 35690298Sdesterminate(int sig) 3578425Swpaul{ 3588425Swpaul struct _dom_binding *ypdb; 3598425Swpaul char path[MAXPATHLEN]; 3608425Swpaul 36121581Swpaul if (ppid != getpid()) 36221581Swpaul exit(0); 36321581Swpaul 36490297Sdes for (ypdb = ypbindlist; ypdb; ypdb = ypdb->dom_pnext) { 3658425Swpaul close(ypdb->dom_lockfd); 3668755Swpaul if (ypdb->dom_broadcast_pid) 3678755Swpaul kill(ypdb->dom_broadcast_pid, SIGINT); 3688425Swpaul sprintf(path, "%s/%s.%ld", BINDINGDIR, 3698425Swpaul ypdb->dom_domain, ypdb->dom_vers); 3708425Swpaul unlink(path); 3718425Swpaul } 3728474Swpaul close(yplockfd); 3738474Swpaul unlink(YPBINDLOCK); 3748425Swpaul pmap_unset(YPBINDPROG, YPBINDVERS); 3758425Swpaul exit(0); 3768425Swpaul} 3778857Srgrimes 37821581Swpaulint 37990298Sdesmain(int argc, char *argv[]) 3801927Swollman{ 3811927Swollman struct timeval tv; 3821927Swollman int i; 3838425Swpaul DIR *dird; 3848425Swpaul struct dirent *dirp; 38578674Sben struct _dom_binding *ypdb, *next; 3861927Swollman 3878474Swpaul /* Check that another ypbind isn't already running. */ 38830762Scharnier if ((yplockfd = (open(YPBINDLOCK, O_RDONLY|O_CREAT, 0444))) == -1) 38930762Scharnier err(1, "%s", YPBINDLOCK); 3908474Swpaul 39190297Sdes if (flock(yplockfd, LOCK_EX|LOCK_NB) == -1 && errno == EWOULDBLOCK) 39230762Scharnier errx(1, "another ypbind is already running. Aborting"); 3938474Swpaul 3949600Swpaul /* XXX domainname will be overriden if we use restricted mode */ 39512862Swpaul yp_get_default_domain(&domain_name); 39690297Sdes if (domain_name[0] == '\0') 39730762Scharnier errx(1, "domainname not set. Aborting"); 3981927Swollman 39990297Sdes for (i = 1; i<argc; i++) { 40090297Sdes if (strcmp("-ypset", argv[i]) == 0) 4011927Swollman ypsetmode = YPSET_ALL; 4021927Swollman else if (strcmp("-ypsetme", argv[i]) == 0) 4036732Swpaul ypsetmode = YPSET_LOCAL; 4046732Swpaul else if (strcmp("-s", argv[i]) == 0) 4056732Swpaul ypsecuremode++; 4069600Swpaul else if (strcmp("-S", argv[i]) == 0 && argc > i) 40779953Sdd yp_restricted_mode(argv[++i]); 40826135Swpaul else if (strcmp("-m", argv[i]) == 0) 40926135Swpaul yp_manycast++; 41079665Sdd else 41179665Sdd errx(1, "unknown option: %s", argv[i]); 4121927Swollman } 4131927Swollman 4148425Swpaul /* blow away everything in BINDINGDIR (if it exists) */ 4151927Swollman 4168425Swpaul if ((dird = opendir(BINDINGDIR)) != NULL) { 4178425Swpaul char path[MAXPATHLEN]; 4188425Swpaul while ((dirp = readdir(dird)) != NULL) 4198425Swpaul if (strcmp(dirp->d_name, ".") && 4208425Swpaul strcmp(dirp->d_name, "..")) { 4218425Swpaul sprintf(path,"%s/%s",BINDINGDIR,dirp->d_name); 4228425Swpaul unlink(path); 4238425Swpaul } 4248425Swpaul closedir(dird); 4258425Swpaul } 4261927Swollman 4271927Swollman#ifdef DAEMON 42830762Scharnier if (daemon(0,0)) 42930762Scharnier err(1, "fork"); 4301927Swollman#endif 4311927Swollman 4321927Swollman pmap_unset(YPBINDPROG, YPBINDVERS); 4331927Swollman 4341927Swollman udptransp = svcudp_create(RPC_ANYSOCK); 43530762Scharnier if (udptransp == NULL) 43630762Scharnier errx(1, "cannot create udp service"); 4371927Swollman if (!svc_register(udptransp, YPBINDPROG, YPBINDVERS, ypbindprog_2, 43830762Scharnier IPPROTO_UDP)) 43930762Scharnier errx(1, "unable to register (YPBINDPROG, YPBINDVERS, udp)"); 4401927Swollman 4411927Swollman tcptransp = svctcp_create(RPC_ANYSOCK, 0, 0); 44230762Scharnier if (tcptransp == NULL) 44330762Scharnier errx(1, "cannot create tcp service"); 4441927Swollman 4451927Swollman if (!svc_register(tcptransp, YPBINDPROG, YPBINDVERS, ypbindprog_2, 44630762Scharnier IPPROTO_TCP)) 44730762Scharnier errx(1, "unable to register (YPBINDPROG, YPBINDVERS, tcp)"); 4481927Swollman 4491927Swollman /* build initial domain binding, make it "unsuccessful" */ 4501927Swollman ypbindlist = (struct _dom_binding *)malloc(sizeof *ypbindlist); 45130762Scharnier if (ypbindlist == NULL) 45230762Scharnier errx(1, "malloc"); 45395658Sdes bzero(ypbindlist, sizeof *ypbindlist); 45412862Swpaul strncpy(ypbindlist->dom_domain, domain_name, sizeof ypbindlist->dom_domain); 4551927Swollman ypbindlist->dom_vers = YPVERS; 4561927Swollman ypbindlist->dom_alive = 0; 4571927Swollman ypbindlist->dom_lockfd = -1; 4588091Swpaul ypbindlist->dom_default = 1; 4598425Swpaul domains++; 4601927Swollman 4618425Swpaul signal(SIGCHLD, reaper); 4628425Swpaul signal(SIGTERM, terminate); 4638425Swpaul 46421581Swpaul ppid = getpid(); /* Remember who we are. */ 46521581Swpaul 4668246Swpaul openlog(argv[0], LOG_PID, LOG_DAEMON); 4676478Swpaul 4688425Swpaul /* Kick off the default domain */ 4698425Swpaul broadcast(ypbindlist); 4708425Swpaul 47190297Sdes while (1) { 4721927Swollman fdsr = svc_fdset; 4738091Swpaul 4748425Swpaul tv.tv_sec = 60; 4751927Swollman tv.tv_usec = 0; 4761927Swollman 47790297Sdes switch (select(_rpc_dtablesize(), &fdsr, NULL, NULL, &tv)) { 4781927Swollman case 0: 4791927Swollman checkwork(); 4801927Swollman break; 4811927Swollman case -1: 4828755Swpaul if (errno != EINTR) 48321539Swpaul syslog(LOG_WARNING, "select: %m"); 4848755Swpaul break; 4851927Swollman default: 48690297Sdes for (ypdb = ypbindlist; ypdb; ypdb = next) { 48778674Sben next = ypdb->dom_pnext; 4888755Swpaul if (READFD > 0 && FD_ISSET(READFD, &fdsr)) { 4898853Swpaul handle_children(ypdb); 4908755Swpaul if (children == (MAX_CHILDREN - 1)) 4918755Swpaul checkwork(); 4928091Swpaul } 4931927Swollman } 4941927Swollman svc_getreqset(&fdsr); 4951927Swollman break; 4961927Swollman } 4971927Swollman } 49821581Swpaul 49921581Swpaul /* NOTREACHED */ 50021581Swpaul exit(1); 5011927Swollman} 5021927Swollman 5038091Swpaulvoid 50490298Sdescheckwork(void) 5051927Swollman{ 5061927Swollman struct _dom_binding *ypdb; 5071927Swollman 50890297Sdes for (ypdb = ypbindlist; ypdb; ypdb = ypdb->dom_pnext) 5098425Swpaul ping(ypdb); 5101927Swollman} 5111927Swollman 5128091Swpaul/* The clnt_broadcast() callback mechanism sucks. */ 5138091Swpaul 5148091Swpaul/* 5158091Swpaul * Receive results from broadcaster. Don't worry about passing 5168853Swpaul * bogus info to rpc_received() -- it can handle it. Note that we 5178853Swpaul * must be sure to invalidate the dom_pipe_fds descriptors here: 5188853Swpaul * since descriptors can be re-used, we have to make sure we 5198853Swpaul * don't mistake one of the RPC descriptors for one of the pipes. 5208853Swpaul * What's weird is that forgetting to invalidate the pipe descriptors 5218853Swpaul * doesn't always result in an error (otherwise I would have caught 5228853Swpaul * the mistake much sooner), even though logically it should. 5238091Swpaul */ 52490298Sdesvoid 52590298Sdeshandle_children(struct _dom_binding *ypdb) 5268091Swpaul{ 5278091Swpaul char buf[YPMAXDOMAIN + 1]; 5288091Swpaul struct sockaddr_in addr; 52921539Swpaul int d = 0, a = 0; 53021539Swpaul struct _dom_binding *y, *prev = NULL; 53121539Swpaul char path[MAXPATHLEN]; 5328091Swpaul 53321539Swpaul if ((d = read(READFD, &buf, sizeof(buf))) <= 0) 53421539Swpaul syslog(LOG_WARNING, "could not read from child: %m"); 5358755Swpaul 53621539Swpaul if ((a = read(READFD, &addr, sizeof(struct sockaddr_in))) < 0) 53721539Swpaul syslog(LOG_WARNING, "could not read from child: %m"); 53821539Swpaul 5398853Swpaul close(READFD); 5408853Swpaul FD_CLR(READFD, &fdsr); 5418853Swpaul FD_CLR(READFD, &svc_fdset); 5428853Swpaul READFD = WRITEFD = -1; 54321539Swpaul if (d > 0 && a > 0) 54495658Sdes rpc_received(buf, &addr, 0); 54521539Swpaul else { 54690297Sdes for (y = ypbindlist; y; y = y->dom_pnext) { 54721539Swpaul if (y == ypdb) 54821539Swpaul break; 54921539Swpaul prev = y; 55021539Swpaul } 55190297Sdes switch (ypdb->dom_default) { 55221539Swpaul case 0: 55321539Swpaul if (prev == NULL) 55421539Swpaul ypbindlist = y->dom_pnext; 55521539Swpaul else 55621539Swpaul prev->dom_pnext = y->dom_pnext; 55721539Swpaul sprintf(path, "%s/%s.%ld", BINDINGDIR, 55821539Swpaul ypdb->dom_domain, YPVERS); 55921539Swpaul close(ypdb->dom_lockfd); 56021539Swpaul unlink(path); 56121539Swpaul free(ypdb); 56221539Swpaul domains--; 56321539Swpaul return; 56421539Swpaul case 1: 56521539Swpaul ypdb->dom_broadcast_pid = 0; 56621539Swpaul ypdb->dom_alive = 0; 56721539Swpaul broadcast(ypdb); 56821539Swpaul return; 56921539Swpaul default: 57021539Swpaul break; 57121539Swpaul } 57221539Swpaul } 57321539Swpaul 57421539Swpaul return; 5758091Swpaul} 5768091Swpaul 5778091Swpaul/* 5788091Swpaul * Send our dying words back to our parent before we perish. 5798091Swpaul */ 5808091Swpaulint 58190298Sdestell_parent(char *dom, struct sockaddr_in *addr) 5821927Swollman{ 5838091Swpaul char buf[YPMAXDOMAIN + 1]; 5848091Swpaul struct timeval timeout; 5858091Swpaul fd_set fds; 5861927Swollman 5878091Swpaul timeout.tv_sec = 5; 5888091Swpaul timeout.tv_usec = 0; 5891927Swollman 5908755Swpaul sprintf(buf, "%s", broad_domain->dom_domain); 5918755Swpaul if (write(BROADFD, &buf, sizeof(buf)) < 0) 5928091Swpaul return(1); 5931927Swollman 5948091Swpaul /* 5958091Swpaul * Stay in sync with parent: wait for it to read our first 5968091Swpaul * message before sending the second. 5978091Swpaul */ 5981927Swollman 5998091Swpaul FD_ZERO(&fds); 6008755Swpaul FD_SET(BROADFD, &fds); 6018091Swpaul if (select(FD_SETSIZE, NULL, &fds, NULL, &timeout) == -1) 6028091Swpaul return(1); 6038755Swpaul if (FD_ISSET(BROADFD, &fds)) { 6048755Swpaul if (write(BROADFD, addr, sizeof(struct sockaddr_in)) < 0) 6058091Swpaul return(1); 6068091Swpaul } else { 6078091Swpaul return(1); 6081927Swollman } 6091927Swollman 6108755Swpaul close(BROADFD); 6118091Swpaul return (0); 6128091Swpaul} 6131927Swollman 6148091Swpaulbool_t broadcast_result(out, addr) 6158091Swpaulbool_t *out; 6168091Swpaulstruct sockaddr_in *addr; 6178091Swpaul{ 6189600Swpaul if (retries >= MAX_RETRIES) { 61995658Sdes bzero(addr, sizeof(struct sockaddr_in)); 6209600Swpaul if (tell_parent(broad_domain->dom_domain, addr)) 6219600Swpaul syslog(LOG_WARNING, "lost connection to parent"); 62290297Sdes return (TRUE); 6239600Swpaul } 6249600Swpaul 6259600Swpaul if (yp_restricted && verify(addr->sin_addr)) { 6269600Swpaul retries++; 6279600Swpaul syslog(LOG_NOTICE, "NIS server at %s not in restricted mode access list -- rejecting.\n",inet_ntoa(addr->sin_addr)); 62890297Sdes return (FALSE); 6299600Swpaul } else { 6309600Swpaul if (tell_parent(broad_domain->dom_domain, addr)) 6319600Swpaul syslog(LOG_WARNING, "lost connection to parent"); 63290297Sdes return (TRUE); 6339600Swpaul } 6348091Swpaul} 6358091Swpaul 6368091Swpaul/* 6378091Swpaul * The right way to send RPC broadcasts. 6388091Swpaul * Use the clnt_broadcast() RPC service. Unfortunately, clnt_broadcast() 63972091Sasmodai * blocks while waiting for replies, so we have to fork off separate 6408091Swpaul * broadcaster processes that do the waiting and then transmit their 6418091Swpaul * results back to the parent for processing. We also have to remember 6428091Swpaul * to save the name of the domain we're trying to bind in a global 6438091Swpaul * variable since clnt_broadcast() provides no way to pass things to 6448091Swpaul * the 'eachresult' callback function. 6458091Swpaul */ 6468091Swpaulvoid 64790298Sdesbroadcast(struct _dom_binding *ypdb) 6488091Swpaul{ 6498091Swpaul bool_t out = FALSE; 6508091Swpaul enum clnt_stat stat; 6518091Swpaul 6528755Swpaul if (children >= MAX_CHILDREN || ypdb->dom_broadcast_pid) 6538091Swpaul return; 6548091Swpaul 6558755Swpaul if (pipe(ypdb->dom_pipe_fds) < 0) { 65621539Swpaul syslog(LOG_WARNING, "pipe: %m"); 6578091Swpaul return; 6581927Swollman } 6591927Swollman 660213611Smarkm if (ypdb->dom_vers == -1 && (long)ypdb->dom_server_addr.sin_addr.s_addr) { 661213611Smarkm if (not_responding_count++ >= NOT_RESPONDING_HYSTERESIS) { 662213611Smarkm not_responding_count = NOT_RESPONDING_HYSTERESIS; 663213611Smarkm syslog(LOG_WARNING, "NIS server [%s] for domain \"%s\" not responding", 664213611Smarkm inet_ntoa(ypdb->dom_server_addr.sin_addr), ypdb->dom_domain); 665213611Smarkm } 666213611Smarkm } 6678425Swpaul 6688755Swpaul broad_domain = ypdb; 6698425Swpaul flock(ypdb->dom_lockfd, LOCK_UN); 6708425Swpaul 67190297Sdes switch ((ypdb->dom_broadcast_pid = fork())) { 6728091Swpaul case 0: 6738755Swpaul close(READFD); 67421539Swpaul signal(SIGCHLD, SIG_DFL); 67521539Swpaul signal(SIGTERM, SIG_DFL); 6768091Swpaul break; 6778091Swpaul case -1: 67821539Swpaul syslog(LOG_WARNING, "fork: %m"); 6798755Swpaul close(READFD); 6808755Swpaul close(WRITEFD); 6818091Swpaul return; 6828091Swpaul default: 6838755Swpaul close(WRITEFD); 6848755Swpaul FD_SET(READFD, &svc_fdset); 6858091Swpaul children++; 6868091Swpaul return; 6871927Swollman } 6886478Swpaul 6898755Swpaul /* Release all locks before doing anything else. */ 69090297Sdes while (ypbindlist) { 6918755Swpaul close(ypbindlist->dom_lockfd); 6928755Swpaul ypbindlist = ypbindlist->dom_pnext; 6938755Swpaul } 6948755Swpaul close(yplockfd); 6958755Swpaul 69626135Swpaul /* 69726135Swpaul * Special 'many-cast' behavior. If we're in restricted mode, 69826135Swpaul * we have a list of possible server addresses to try. What 69926135Swpaul * we can do is transmit to each ypserv's YPPROC_DOMAIN_NONACK 70026135Swpaul * procedure and time the replies. Whoever replies fastest 70126135Swpaul * gets to be our server. Note that this is not a broadcast 70226135Swpaul * operation: we transmit uni-cast datagrams only. 70326135Swpaul */ 70426135Swpaul if (yp_restricted && yp_manycast) { 70526135Swpaul short port; 70626135Swpaul int i; 70726135Swpaul struct sockaddr_in sin; 70826135Swpaul 70926135Swpaul i = __yp_ping(restricted_addrs, yp_restricted, 71026135Swpaul ypdb->dom_domain, &port); 71126135Swpaul if (i == -1) { 71295658Sdes bzero(&ypdb->dom_server_addr, 71395658Sdes sizeof(struct sockaddr_in)); 71426135Swpaul if (tell_parent(ypdb->dom_domain, 71595658Sdes &ypdb->dom_server_addr)) 71626135Swpaul syslog(LOG_WARNING, "lost connection to parent"); 71726135Swpaul } else { 71895658Sdes bzero(&sin, sizeof(struct sockaddr_in)); 71995658Sdes bcopy(&restricted_addrs[i], 72095658Sdes &sin.sin_addr, sizeof(struct in_addr)); 72126135Swpaul sin.sin_family = AF_INET; 72226135Swpaul sin.sin_port = port; 72326135Swpaul if (tell_parent(broad_domain->dom_domain, &sin)) 72426135Swpaul syslog(LOG_WARNING, 72526135Swpaul "lost connection to parent"); 72626135Swpaul } 72726135Swpaul _exit(0); 72826135Swpaul } 72926135Swpaul 7309600Swpaul retries = 0; 7319600Swpaul 73212862Swpaul { 73312862Swpaul char *ptr; 7348091Swpaul 73595658Sdes ptr = ypdb->dom_domain; 73612862Swpaul stat = clnt_broadcast(YPPROG, YPVERS, YPPROC_DOMAIN_NONACK, 73795658Sdes (xdrproc_t)xdr_domainname, &ptr, 73895658Sdes (xdrproc_t)xdr_bool, &out, 73974462Salfred (resultproc_t)broadcast_result); 74012862Swpaul } 74112862Swpaul 7428091Swpaul if (stat != RPC_SUCCESS) { 74395658Sdes bzero(&ypdb->dom_server_addr, 74495658Sdes sizeof(struct sockaddr_in)); 7458755Swpaul if (tell_parent(ypdb->dom_domain, &ypdb->dom_server_addr)) 7468091Swpaul syslog(LOG_WARNING, "lost connection to parent"); 7478091Swpaul } 7488755Swpaul 74926135Swpaul _exit(0); 7501927Swollman} 7511927Swollman 7528091Swpaul/* 7538091Swpaul * The right way to check if a server is alive. 7548091Swpaul * Attempt to get a client handle pointing to the server and send a 7558755Swpaul * YPPROC_DOMAIN. If we can't get a handle or we get a reply of FALSE, 7568755Swpaul * we invalidate this binding entry and send out a broadcast to try to 7578755Swpaul * establish a new binding. Note that we treat non-default domains 7588091Swpaul * specially: once bound, we keep tabs on our server, but if it 7598091Swpaul * goes away and fails to respond after one round of broadcasting, we 7608091Swpaul * abandon it until a client specifically references it again. We make 7618091Swpaul * every effort to keep our default domain bound, however, since we 7628091Swpaul * need it to keep the system on its feet. 7638091Swpaul */ 7648091Swpaulint 76590298Sdesping(struct _dom_binding *ypdb) 7661927Swollman{ 7678091Swpaul bool_t out; 7688091Swpaul struct timeval interval, timeout; 7698091Swpaul enum clnt_stat stat; 7708091Swpaul int rpcsock = RPC_ANYSOCK; 7718755Swpaul CLIENT *client_handle; 7721927Swollman 7738755Swpaul interval.tv_sec = FAIL_THRESHOLD; 7748091Swpaul interval.tv_usec = 0; 7758091Swpaul timeout.tv_sec = FAIL_THRESHOLD; 7768091Swpaul timeout.tv_usec = 0; 7771927Swollman 7788755Swpaul if (ypdb->dom_broadcast_pid) 7798091Swpaul return(1); 7808091Swpaul 7818755Swpaul if ((client_handle = clntudp_bufcreate(&ypdb->dom_server_addr, 7828755Swpaul YPPROG, YPVERS, interval, &rpcsock, RPCSMALLMSGSIZE, 7838755Swpaul RPCSMALLMSGSIZE)) == (CLIENT *)NULL) { 7848755Swpaul /* Can't get a handle: we're dead. */ 7858755Swpaul ypdb->dom_alive = 0; 7868755Swpaul ypdb->dom_vers = -1; 7878755Swpaul broadcast(ypdb); 7888755Swpaul return(1); 7891927Swollman } 7901927Swollman 79112862Swpaul { 79212862Swpaul char *ptr; 79312862Swpaul 79495658Sdes ptr = ypdb->dom_domain; 79512862Swpaul 79695658Sdes stat = clnt_call(client_handle, YPPROC_DOMAIN, 79795658Sdes (xdrproc_t)xdr_domainname, &ptr, 79895658Sdes (xdrproc_t)xdr_bool, &out, timeout); 79995658Sdes if (stat != RPC_SUCCESS || out == FALSE) { 80012862Swpaul ypdb->dom_alive = 0; 80112862Swpaul ypdb->dom_vers = -1; 80212862Swpaul clnt_destroy(client_handle); 80312862Swpaul broadcast(ypdb); 80412862Swpaul return(1); 80512862Swpaul } 8068091Swpaul } 8071927Swollman 8088755Swpaul clnt_destroy(client_handle); 8098091Swpaul return(0); 8101927Swollman} 8111927Swollman 81290298Sdesvoid 81390298Sdesrpc_received(char *dom, struct sockaddr_in *raddrp, int force) 8141927Swollman{ 8158425Swpaul struct _dom_binding *ypdb, *prev = NULL; 8161927Swollman struct iovec iov[2]; 8171927Swollman struct ypbind_resp ybr; 8181927Swollman char path[MAXPATHLEN]; 8191927Swollman int fd; 8201927Swollman 8216732Swpaul /*printf("returned from %s/%d about %s\n", inet_ntoa(raddrp->sin_addr), 8226732Swpaul ntohs(raddrp->sin_port), dom);*/ 8231927Swollman 82490297Sdes if (dom == NULL) 8251927Swollman return; 8261927Swollman 82790297Sdes for (ypdb = ypbindlist; ypdb; ypdb = ypdb->dom_pnext) { 82890297Sdes if (strcmp(ypdb->dom_domain, dom) == 0) 8298091Swpaul break; 8308425Swpaul prev = ypdb; 8318425Swpaul } 8328091Swpaul 8338755Swpaul if (ypdb && force) { 8348755Swpaul if (ypdb->dom_broadcast_pid) { 8358755Swpaul kill(ypdb->dom_broadcast_pid, SIGINT); 8368755Swpaul close(READFD); 8378853Swpaul FD_CLR(READFD, &fdsr); 8388853Swpaul FD_CLR(READFD, &svc_fdset); 8398853Swpaul READFD = WRITEFD = -1; 8408755Swpaul } 8418755Swpaul } 8428755Swpaul 8439600Swpaul /* if in secure mode, check originating port number */ 8449600Swpaul if ((ypsecuremode && (ntohs(raddrp->sin_port) >= IPPORT_RESERVED))) { 8456732Swpaul syslog(LOG_WARNING, "Rejected NIS server on [%s/%d] for domain %s.", 8466732Swpaul inet_ntoa(raddrp->sin_addr), ntohs(raddrp->sin_port), 8476732Swpaul dom); 8488246Swpaul if (ypdb != NULL) { 8498755Swpaul ypdb->dom_broadcast_pid = 0; 8508246Swpaul ypdb->dom_alive = 0; 8518246Swpaul } 8526732Swpaul return; 8536732Swpaul } 8546732Swpaul 8558246Swpaul if (raddrp->sin_addr.s_addr == (long)0) { 85690297Sdes switch (ypdb->dom_default) { 8578755Swpaul case 0: 8588755Swpaul if (prev == NULL) 8598755Swpaul ypbindlist = ypdb->dom_pnext; 8608755Swpaul else 8618755Swpaul prev->dom_pnext = ypdb->dom_pnext; 8628755Swpaul sprintf(path, "%s/%s.%ld", BINDINGDIR, 8638755Swpaul ypdb->dom_domain, YPVERS); 8648755Swpaul close(ypdb->dom_lockfd); 8658755Swpaul unlink(path); 8668755Swpaul free(ypdb); 8678755Swpaul domains--; 8688755Swpaul return; 8698755Swpaul case 1: 8708755Swpaul ypdb->dom_broadcast_pid = 0; 8718755Swpaul ypdb->dom_alive = 0; 8728755Swpaul broadcast(ypdb); 8738755Swpaul return; 8748755Swpaul default: 8758755Swpaul break; 8768755Swpaul } 8778246Swpaul } 8788246Swpaul 87990297Sdes if (ypdb == NULL) { 8808246Swpaul if (force == 0) 8811927Swollman return; 8821927Swollman ypdb = (struct _dom_binding *)malloc(sizeof *ypdb); 8838857Srgrimes if (ypdb == NULL) { 88421539Swpaul syslog(LOG_WARNING, "malloc: %m"); 8858246Swpaul return; 8868246Swpaul } 88795658Sdes bzero(ypdb, sizeof *ypdb); 8881927Swollman strncpy(ypdb->dom_domain, dom, sizeof ypdb->dom_domain); 8891927Swollman ypdb->dom_lockfd = -1; 8908091Swpaul ypdb->dom_default = 0; 8911927Swollman ypdb->dom_pnext = ypbindlist; 8921927Swollman ypbindlist = ypdb; 8931927Swollman } 8941927Swollman 8958091Swpaul /* We've recovered from a crash: inform the world. */ 896213611Smarkm if (ypdb->dom_vers == -1 && ypdb->dom_server_addr.sin_addr.s_addr) { 897213611Smarkm if (not_responding_count >= NOT_RESPONDING_HYSTERESIS) { 898213611Smarkm not_responding_count = 0; 899213611Smarkm syslog(LOG_WARNING, "NIS server [%s] for domain \"%s\" OK", 900213611Smarkm inet_ntoa(raddrp->sin_addr), ypdb->dom_domain); 901213611Smarkm } 902213611Smarkm } 9036478Swpaul 90495658Sdes bcopy(raddrp, &ypdb->dom_server_addr, 9051927Swollman sizeof ypdb->dom_server_addr); 9066478Swpaul 9071927Swollman ypdb->dom_vers = YPVERS; 9081927Swollman ypdb->dom_alive = 1; 9098755Swpaul ypdb->dom_broadcast_pid = 0; 9101927Swollman 91190297Sdes if (ypdb->dom_lockfd != -1) 9121927Swollman close(ypdb->dom_lockfd); 9131927Swollman 9148091Swpaul sprintf(path, "%s/%s.%ld", BINDINGDIR, 9151927Swollman ypdb->dom_domain, ypdb->dom_vers); 9161927Swollman#ifdef O_SHLOCK 91790297Sdes if ((fd = open(path, O_CREAT|O_SHLOCK|O_RDWR|O_TRUNC, 0644)) == -1) { 9181927Swollman (void)mkdir(BINDINGDIR, 0755); 91990297Sdes if ((fd = open(path, O_CREAT|O_SHLOCK|O_RDWR|O_TRUNC, 0644)) == -1) 9201927Swollman return; 9211927Swollman } 9221927Swollman#else 92390297Sdes if ((fd = open(path, O_CREAT|O_RDWR|O_TRUNC, 0644)) == -1) { 9241927Swollman (void)mkdir(BINDINGDIR, 0755); 92590297Sdes if ((fd = open(path, O_CREAT|O_RDWR|O_TRUNC, 0644)) == -1) 9261927Swollman return; 9271927Swollman } 9281927Swollman flock(fd, LOCK_SH); 9291927Swollman#endif 9301927Swollman 9311927Swollman /* 9321927Swollman * ok, if BINDINGDIR exists, and we can create the binding file, 9331927Swollman * then write to it.. 9341927Swollman */ 9351927Swollman ypdb->dom_lockfd = fd; 9361927Swollman 93795658Sdes iov[0].iov_base = (char *)&(udptransp->xp_port); 9381927Swollman iov[0].iov_len = sizeof udptransp->xp_port; 93995658Sdes iov[1].iov_base = (char *)&ybr; 9401927Swollman iov[1].iov_len = sizeof ybr; 9411927Swollman 9421927Swollman bzero(&ybr, sizeof ybr); 9431927Swollman ybr.ypbind_status = YPBIND_SUCC_VAL; 94445656Ssimokawa *(u_int32_t *)&ybr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_addr = raddrp->sin_addr.s_addr; 94512862Swpaul *(u_short *)&ybr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_port = raddrp->sin_port; 9461927Swollman 94790297Sdes if (writev(ypdb->dom_lockfd, iov, 2) != iov[0].iov_len + iov[1].iov_len) { 94821539Swpaul syslog(LOG_WARNING, "write: %m"); 9491927Swollman close(ypdb->dom_lockfd); 9501927Swollman ypdb->dom_lockfd = -1; 9511927Swollman return; 9521927Swollman } 9531927Swollman} 9549600Swpaul 9559600Swpaul/* 9569600Swpaul * Check address against list of allowed servers. Return 0 if okay, 9579600Swpaul * 1 if not matched. 9589600Swpaul */ 9599600Swpaulint 96090298Sdesverify(struct in_addr addr) 9619600Swpaul{ 9629600Swpaul int i; 9639600Swpaul 9649600Swpaul for (i = 0; i < RESTRICTED_SERVERS; i++) 96595658Sdes if (!bcmp(&addr, &restricted_addrs[i], sizeof(struct in_addr))) 9669600Swpaul return(0); 9679600Swpaul 9689600Swpaul return(1); 9699600Swpaul} 9709600Swpaul 9719600Swpaul/* 9729600Swpaul * Try to set restricted mode. We default to normal mode if we can't 9739600Swpaul * resolve the specified hostnames. 9749600Swpaul */ 9759600Swpaulvoid 97690298Sdesyp_restricted_mode(char *args) 9779600Swpaul{ 9789600Swpaul struct hostent *h; 9799600Swpaul int i = 0; 9809600Swpaul char *s; 9819600Swpaul 9829600Swpaul /* Find the restricted domain. */ 9839600Swpaul if ((s = strsep(&args, ",")) == NULL) 9849600Swpaul return; 98512862Swpaul domain_name = s; 9869600Swpaul 9879600Swpaul /* Get the addresses of the servers. */ 9889600Swpaul while ((s = strsep(&args, ",")) != NULL && i < RESTRICTED_SERVERS) { 9899600Swpaul if ((h = gethostbyname(s)) == NULL) 9909600Swpaul return; 99195658Sdes bcopy (h->h_addr_list[0], &restricted_addrs[i], 99295658Sdes sizeof(struct in_addr)); 99395658Sdes i++; 9949600Swpaul } 9959600Swpaul 9969600Swpaul /* ypset and ypsetme not allowed with restricted mode */ 9979600Swpaul ypsetmode = YPSET_NO; 99890297Sdes 99926135Swpaul yp_restricted = i; 10009600Swpaul return; 10019600Swpaul} 1002