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$"); 321927Swollman 331927Swollman#include <sys/param.h> 341927Swollman#include <sys/types.h> 358091Swpaul#include <sys/wait.h> 361927Swollman#include <sys/ioctl.h> 37226690Sglebius#include <sys/mman.h> 381927Swollman#include <sys/signal.h> 391927Swollman#include <sys/socket.h> 401927Swollman#include <sys/file.h> 411927Swollman#include <sys/fcntl.h> 428091Swpaul#include <sys/stat.h> 431927Swollman#include <sys/uio.h> 441927Swollman#include <ctype.h> 451927Swollman#include <dirent.h> 4630762Scharnier#include <err.h> 4730762Scharnier#include <errno.h> 481927Swollman#include <netdb.h> 4930762Scharnier#include <signal.h> 5030762Scharnier#include <stdio.h> 5130762Scharnier#include <stdlib.h> 521927Swollman#include <string.h> 5330762Scharnier#include <syslog.h> 5430762Scharnier#include <unistd.h> 551927Swollman#include <rpc/rpc.h> 561927Swollman#include <rpc/xdr.h> 571927Swollman#include <net/if.h> 586732Swpaul#include <netinet/in.h> 591927Swollman#include <arpa/inet.h> 601927Swollman#include <rpc/pmap_clnt.h> 611927Swollman#include <rpc/pmap_prot.h> 621927Swollman#include <rpc/pmap_rmt.h> 6330762Scharnier#include <rpc/rpc_com.h> 6412862Swpaul#include <rpcsvc/yp.h> 651927Swollman#include <rpcsvc/ypclnt.h> 6626135Swpaul#include "yp_ping.h" 671927Swollman 681927Swollman#ifndef BINDINGDIR 691927Swollman#define BINDINGDIR "/var/yp/binding" 701927Swollman#endif 711927Swollman 728474Swpaul#ifndef YPBINDLOCK 738474Swpaul#define YPBINDLOCK "/var/run/ypbind.lock" 748474Swpaul#endif 758474Swpaul 761927Swollmanstruct _dom_binding { 771927Swollman struct _dom_binding *dom_pnext; 781927Swollman char dom_domain[YPMAXDOMAIN + 1]; 791927Swollman struct sockaddr_in dom_server_addr; 801927Swollman long int dom_vers; 811927Swollman int dom_lockfd; 821927Swollman int dom_alive; 838755Swpaul int dom_broadcast_pid; 848755Swpaul int dom_pipe_fds[2]; 858091Swpaul int dom_default; 861927Swollman}; 871927Swollman 888755Swpaul#define READFD ypdb->dom_pipe_fds[0] 898755Swpaul#define WRITEFD ypdb->dom_pipe_fds[1] 908755Swpaul#define BROADFD broad_domain->dom_pipe_fds[1] 918755Swpaul 921927Swollmanextern bool_t xdr_domainname(), xdr_ypbind_resp(); 931927Swollmanextern bool_t xdr_ypreq_key(), xdr_ypresp_val(); 941927Swollmanextern bool_t xdr_ypbind_setdom(); 951927Swollman 9690297Sdesvoid checkwork(void); 9790297Sdesvoid *ypbindproc_null_2_yp(SVCXPRT *, void *, CLIENT *); 9890297Sdesvoid *ypbindproc_setdom_2_yp(SVCXPRT *, struct ypbind_setdom *, CLIENT *); 9990297Sdesvoid rpc_received(char *, struct sockaddr_in *, int); 10090297Sdesvoid broadcast(struct _dom_binding *); 10190297Sdesint ping(struct _dom_binding *); 10290297Sdesint tell_parent(char *, struct sockaddr_in *); 10390297Sdesvoid handle_children(struct _dom_binding *); 10490297Sdesvoid reaper(int); 10590297Sdesvoid terminate(int); 10690297Sdesvoid yp_restricted_mode(char *); 10790297Sdesint verify(struct in_addr); 1088091Swpaul 10912862Swpaulchar *domain_name; 1101927Swollmanstruct _dom_binding *ypbindlist; 1118755Swpaulstatic struct _dom_binding *broad_domain; 1121927Swollman 1131927Swollman#define YPSET_NO 0 1141927Swollman#define YPSET_LOCAL 1 1151927Swollman#define YPSET_ALL 2 1161927Swollmanint ypsetmode = YPSET_NO; 1176732Swpaulint ypsecuremode = 0; 11821581Swpaulint ppid; 1196732Swpaul 120213611Smarkm#define NOT_RESPONDING_HYSTERESIS 10 121213611Smarkmstatic int not_responding_count = 0; 122213611Smarkm 1239600Swpaul/* 1249600Swpaul * Special restricted mode variables: when in restricted mode, only the 1259600Swpaul * specified restricted_domain will be bound, and only the servers listed 1269600Swpaul * in restricted_addrs will be used for binding. 1279600Swpaul */ 1289600Swpaul#define RESTRICTED_SERVERS 10 1299600Swpaulint yp_restricted = 0; 13026135Swpaulint yp_manycast = 0; 1319600Swpaulstruct in_addr restricted_addrs[RESTRICTED_SERVERS]; 1329600Swpaul 1338091Swpaul/* No more than MAX_CHILDREN child broadcasters at a time. */ 1348755Swpaul#ifndef MAX_CHILDREN 1358091Swpaul#define MAX_CHILDREN 5 1368755Swpaul#endif 1378425Swpaul/* No more than MAX_DOMAINS simultaneous domains */ 1388755Swpaul#ifndef MAX_DOMAINS 1398425Swpaul#define MAX_DOMAINS 200 1408755Swpaul#endif 1418755Swpaul/* RPC timeout value */ 1428425Swpaul#ifndef FAIL_THRESHOLD 14321539Swpaul#define FAIL_THRESHOLD 20 1448425Swpaul#endif 1458425Swpaul 1469600Swpaul/* Number of times to fish for a response froma particular set of hosts */ 1479600Swpaul#ifndef MAX_RETRIES 1489600Swpaul#define MAX_RETRIES 30 1499600Swpaul#endif 1509600Swpaul 1519600Swpaulint retries = 0; 1528091Swpaulint children = 0; 1538425Swpaulint domains = 0; 1548474Swpaulint yplockfd; 1558755Swpaulfd_set fdsr; 1568091Swpaul 1571927SwollmanSVCXPRT *udptransp, *tcptransp; 1581927Swollman 1591927Swollmanvoid * 16090298Sdesypbindproc_null_2_yp(SVCXPRT *transp, void *argp, CLIENT *clnt) 1611927Swollman{ 1621927Swollman static char res; 1631927Swollman 16495658Sdes bzero(&res, sizeof(res)); 16595658Sdes return &res; 1661927Swollman} 1671927Swollman 1681927Swollmanstruct ypbind_resp * 16990298Sdesypbindproc_domain_2_yp(SVCXPRT *transp, domainname *argp, CLIENT *clnt) 1701927Swollman{ 1711927Swollman static struct ypbind_resp res; 1721927Swollman struct _dom_binding *ypdb; 1731927Swollman char path[MAXPATHLEN]; 1741927Swollman 17595658Sdes bzero(&res, sizeof res); 1761927Swollman res.ypbind_status = YPBIND_FAIL_VAL; 17712862Swpaul res.ypbind_resp_u.ypbind_error = YPBIND_ERR_NOSERV; 1781927Swollman 17924782Swpaul if (strchr(*argp, '/')) { 18024782Swpaul syslog(LOG_WARNING, "Domain name '%s' has embedded slash -- \ 18124782Swpaulrejecting.", *argp); 18224782Swpaul return(&res); 18324782Swpaul } 18424782Swpaul 18590297Sdes for (ypdb = ypbindlist; ypdb; ypdb = ypdb->dom_pnext) { 18690297Sdes if (strcmp(ypdb->dom_domain, *argp) == 0) 1871927Swollman break; 1888755Swpaul } 1891927Swollman 19090297Sdes if (ypdb == NULL) { 1919600Swpaul if (yp_restricted) { 19212862Swpaul syslog(LOG_NOTICE, "Running in restricted mode -- request to bind domain \"%s\" rejected.\n", *argp); 19390297Sdes return (&res); 1949600Swpaul } 1959600Swpaul 1968474Swpaul if (domains >= MAX_DOMAINS) { 1978425Swpaul syslog(LOG_WARNING, "domain limit (%d) exceeded", 1988425Swpaul MAX_DOMAINS); 19912862Swpaul res.ypbind_resp_u.ypbind_error = YPBIND_ERR_RESC; 20090297Sdes return (&res); 2018425Swpaul } 2021927Swollman ypdb = (struct _dom_binding *)malloc(sizeof *ypdb); 2038857Srgrimes if (ypdb == NULL) { 20421539Swpaul syslog(LOG_WARNING, "malloc: %m"); 20512862Swpaul res.ypbind_resp_u.ypbind_error = YPBIND_ERR_RESC; 20690297Sdes return (&res); 2078246Swpaul } 20895658Sdes bzero(ypdb, sizeof *ypdb); 20912862Swpaul strncpy(ypdb->dom_domain, *argp, sizeof ypdb->dom_domain); 2101927Swollman ypdb->dom_vers = YPVERS; 2111927Swollman ypdb->dom_alive = 0; 2128091Swpaul ypdb->dom_default = 0; 2131927Swollman ypdb->dom_lockfd = -1; 2148425Swpaul sprintf(path, "%s/%s.%ld", BINDINGDIR, 2158425Swpaul ypdb->dom_domain, ypdb->dom_vers); 2161927Swollman unlink(path); 2171927Swollman ypdb->dom_pnext = ypbindlist; 2181927Swollman ypbindlist = ypdb; 2198425Swpaul domains++; 2201927Swollman } 2211927Swollman 2228755Swpaul if (ping(ypdb)) { 22390297Sdes return (&res); 2248755Swpaul } 2251927Swollman 2261927Swollman res.ypbind_status = YPBIND_SUCC_VAL; 22712862Swpaul res.ypbind_resp_u.ypbind_error = 0; /* Success */ 22845656Ssimokawa *(u_int32_t *)&res.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_addr = 2291927Swollman ypdb->dom_server_addr.sin_addr.s_addr; 23012862Swpaul *(u_short *)&res.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_port = 2318091Swpaul ypdb->dom_server_addr.sin_port; 2321927Swollman /*printf("domain %s at %s/%d\n", ypdb->dom_domain, 2331927Swollman inet_ntoa(ypdb->dom_server_addr.sin_addr), 2341927Swollman ntohs(ypdb->dom_server_addr.sin_port));*/ 23590297Sdes return (&res); 2361927Swollman} 2371927Swollman 2388755Swpaulvoid * 23990298Sdesypbindproc_setdom_2_yp(SVCXPRT *transp, ypbind_setdom *argp, CLIENT *clnt) 2401927Swollman{ 2411927Swollman struct sockaddr_in *fromsin, bindsin; 24243854Swpaul static char *result = NULL; 2431927Swollman 24424782Swpaul if (strchr(argp->ypsetdom_domain, '/')) { 24524782Swpaul syslog(LOG_WARNING, "Domain name '%s' has embedded slash -- \ 24624782Swpaulrejecting.", argp->ypsetdom_domain); 24730762Scharnier return(NULL); 24824782Swpaul } 2491927Swollman fromsin = svc_getcaller(transp); 2501927Swollman 25190297Sdes switch (ypsetmode) { 2521927Swollman case YPSET_LOCAL: 25390297Sdes if (fromsin->sin_addr.s_addr != htonl(INADDR_LOOPBACK)) { 2548755Swpaul svcerr_noprog(transp); 25530762Scharnier return(NULL); 2568755Swpaul } 2571927Swollman break; 2581927Swollman case YPSET_ALL: 2591927Swollman break; 2601927Swollman case YPSET_NO: 2611927Swollman default: 2628755Swpaul svcerr_noprog(transp); 26330762Scharnier return(NULL); 2641927Swollman } 2651927Swollman 26690297Sdes if (ntohs(fromsin->sin_port) >= IPPORT_RESERVED) { 2678755Swpaul svcerr_noprog(transp); 26830762Scharnier return(NULL); 2698755Swpaul } 2701927Swollman 27190297Sdes if (argp->ypsetdom_vers != YPVERS) { 2728755Swpaul svcerr_noprog(transp); 27330762Scharnier return(NULL); 2748755Swpaul } 2751927Swollman 27695658Sdes bzero(&bindsin, sizeof bindsin); 2771927Swollman bindsin.sin_family = AF_INET; 27845656Ssimokawa bindsin.sin_addr.s_addr = *(u_int32_t *)argp->ypsetdom_binding.ypbind_binding_addr; 27912862Swpaul bindsin.sin_port = *(u_short *)argp->ypsetdom_binding.ypbind_binding_port; 2801927Swollman rpc_received(argp->ypsetdom_domain, &bindsin, 1); 2811927Swollman 28243854Swpaul return((void *) &result); 2831927Swollman} 2841927Swollman 28595658Sdesvoid 28690298Sdesypbindprog_2(struct svc_req *rqstp, register SVCXPRT *transp) 2871927Swollman{ 2881927Swollman union { 28912862Swpaul domainname ypbindproc_domain_2_arg; 2901927Swollman struct ypbind_setdom ypbindproc_setdom_2_arg; 2911927Swollman } argument; 2921927Swollman struct authunix_parms *creds; 2931927Swollman char *result; 2941927Swollman bool_t (*xdr_argument)(), (*xdr_result)(); 2951927Swollman char *(*local)(); 2961927Swollman 2971927Swollman switch (rqstp->rq_proc) { 2981927Swollman case YPBINDPROC_NULL: 2991927Swollman xdr_argument = xdr_void; 3001927Swollman xdr_result = xdr_void; 30132631Swpaul local = (char *(*)()) ypbindproc_null_2_yp; 3021927Swollman break; 3031927Swollman 3041927Swollman case YPBINDPROC_DOMAIN: 3051927Swollman xdr_argument = xdr_domainname; 3061927Swollman xdr_result = xdr_ypbind_resp; 30732631Swpaul local = (char *(*)()) ypbindproc_domain_2_yp; 3081927Swollman break; 3091927Swollman 3101927Swollman case YPBINDPROC_SETDOM: 31190297Sdes switch (rqstp->rq_cred.oa_flavor) { 3121927Swollman case AUTH_UNIX: 3131927Swollman creds = (struct authunix_parms *)rqstp->rq_clntcred; 31490297Sdes if (creds->aup_uid != 0) { 3151927Swollman svcerr_auth(transp, AUTH_BADCRED); 3161927Swollman return; 3171927Swollman } 3181927Swollman break; 3191927Swollman default: 3201927Swollman svcerr_auth(transp, AUTH_TOOWEAK); 3211927Swollman return; 3221927Swollman } 3231927Swollman 3241927Swollman xdr_argument = xdr_ypbind_setdom; 3251927Swollman xdr_result = xdr_void; 32632631Swpaul local = (char *(*)()) ypbindproc_setdom_2_yp; 3271927Swollman break; 3281927Swollman 3291927Swollman default: 3301927Swollman svcerr_noproc(transp); 3311927Swollman return; 3321927Swollman } 33395658Sdes bzero(&argument, sizeof(argument)); 33495658Sdes if (!svc_getargs(transp, (xdrproc_t)xdr_argument, &argument)) { 3351927Swollman svcerr_decode(transp); 3361927Swollman return; 3371927Swollman } 3381927Swollman result = (*local)(transp, &argument, rqstp); 33995658Sdes if (result != NULL && 34095658Sdes !svc_sendreply(transp, (xdrproc_t)xdr_result, result)) { 3411927Swollman svcerr_systemerr(transp); 3421927Swollman } 3431927Swollman return; 3441927Swollman} 3451927Swollman 3468091Swpaul/* Jack the reaper */ 34790298Sdesvoid 34890298Sdesreaper(int sig) 3498091Swpaul{ 3508091Swpaul int st; 3518091Swpaul 35290297Sdes while (wait3(&st, WNOHANG, NULL) > 0) 3539532Swpaul children--; 3548091Swpaul} 3558091Swpaul 35690298Sdesvoid 35790298Sdesterminate(int sig) 3588425Swpaul{ 3598425Swpaul struct _dom_binding *ypdb; 3608425Swpaul char path[MAXPATHLEN]; 3618425Swpaul 36221581Swpaul if (ppid != getpid()) 36321581Swpaul exit(0); 36421581Swpaul 36590297Sdes for (ypdb = ypbindlist; ypdb; ypdb = ypdb->dom_pnext) { 3668425Swpaul close(ypdb->dom_lockfd); 3678755Swpaul if (ypdb->dom_broadcast_pid) 3688755Swpaul kill(ypdb->dom_broadcast_pid, SIGINT); 3698425Swpaul sprintf(path, "%s/%s.%ld", BINDINGDIR, 3708425Swpaul ypdb->dom_domain, ypdb->dom_vers); 3718425Swpaul unlink(path); 3728425Swpaul } 3738474Swpaul close(yplockfd); 3748474Swpaul unlink(YPBINDLOCK); 3758425Swpaul pmap_unset(YPBINDPROG, YPBINDVERS); 3768425Swpaul exit(0); 3778425Swpaul} 3788857Srgrimes 37921581Swpaulint 38090298Sdesmain(int argc, char *argv[]) 3811927Swollman{ 3821927Swollman struct timeval tv; 3831927Swollman int i; 3848425Swpaul DIR *dird; 3858425Swpaul struct dirent *dirp; 38678674Sben struct _dom_binding *ypdb, *next; 3871927Swollman 3888474Swpaul /* Check that another ypbind isn't already running. */ 38930762Scharnier if ((yplockfd = (open(YPBINDLOCK, O_RDONLY|O_CREAT, 0444))) == -1) 39030762Scharnier err(1, "%s", YPBINDLOCK); 3918474Swpaul 39290297Sdes if (flock(yplockfd, LOCK_EX|LOCK_NB) == -1 && errno == EWOULDBLOCK) 39330762Scharnier errx(1, "another ypbind is already running. Aborting"); 3948474Swpaul 3959600Swpaul /* XXX domainname will be overriden if we use restricted mode */ 39612862Swpaul yp_get_default_domain(&domain_name); 39790297Sdes if (domain_name[0] == '\0') 39830762Scharnier errx(1, "domainname not set. Aborting"); 3991927Swollman 40090297Sdes for (i = 1; i<argc; i++) { 40190297Sdes if (strcmp("-ypset", argv[i]) == 0) 4021927Swollman ypsetmode = YPSET_ALL; 4031927Swollman else if (strcmp("-ypsetme", argv[i]) == 0) 4046732Swpaul ypsetmode = YPSET_LOCAL; 4056732Swpaul else if (strcmp("-s", argv[i]) == 0) 4066732Swpaul ypsecuremode++; 4079600Swpaul else if (strcmp("-S", argv[i]) == 0 && argc > i) 40879953Sdd yp_restricted_mode(argv[++i]); 40926135Swpaul else if (strcmp("-m", argv[i]) == 0) 41026135Swpaul yp_manycast++; 41179665Sdd else 41279665Sdd errx(1, "unknown option: %s", argv[i]); 4131927Swollman } 4141927Swollman 4158425Swpaul /* blow away everything in BINDINGDIR (if it exists) */ 4161927Swollman 4178425Swpaul if ((dird = opendir(BINDINGDIR)) != NULL) { 4188425Swpaul char path[MAXPATHLEN]; 4198425Swpaul while ((dirp = readdir(dird)) != NULL) 4208425Swpaul if (strcmp(dirp->d_name, ".") && 4218425Swpaul strcmp(dirp->d_name, "..")) { 4228425Swpaul sprintf(path,"%s/%s",BINDINGDIR,dirp->d_name); 4238425Swpaul unlink(path); 4248425Swpaul } 4258425Swpaul closedir(dird); 4268425Swpaul } 4271927Swollman 4281927Swollman#ifdef DAEMON 42930762Scharnier if (daemon(0,0)) 43030762Scharnier err(1, "fork"); 4311927Swollman#endif 4321927Swollman 4331927Swollman pmap_unset(YPBINDPROG, YPBINDVERS); 4341927Swollman 4351927Swollman udptransp = svcudp_create(RPC_ANYSOCK); 43630762Scharnier if (udptransp == NULL) 43730762Scharnier errx(1, "cannot create udp service"); 4381927Swollman if (!svc_register(udptransp, YPBINDPROG, YPBINDVERS, ypbindprog_2, 43930762Scharnier IPPROTO_UDP)) 44030762Scharnier errx(1, "unable to register (YPBINDPROG, YPBINDVERS, udp)"); 4411927Swollman 4421927Swollman tcptransp = svctcp_create(RPC_ANYSOCK, 0, 0); 44330762Scharnier if (tcptransp == NULL) 44430762Scharnier errx(1, "cannot create tcp service"); 4451927Swollman 4461927Swollman if (!svc_register(tcptransp, YPBINDPROG, YPBINDVERS, ypbindprog_2, 44730762Scharnier IPPROTO_TCP)) 44830762Scharnier errx(1, "unable to register (YPBINDPROG, YPBINDVERS, tcp)"); 4491927Swollman 4501927Swollman /* build initial domain binding, make it "unsuccessful" */ 4511927Swollman ypbindlist = (struct _dom_binding *)malloc(sizeof *ypbindlist); 45230762Scharnier if (ypbindlist == NULL) 45330762Scharnier errx(1, "malloc"); 45495658Sdes bzero(ypbindlist, sizeof *ypbindlist); 45512862Swpaul strncpy(ypbindlist->dom_domain, domain_name, sizeof ypbindlist->dom_domain); 4561927Swollman ypbindlist->dom_vers = YPVERS; 4571927Swollman ypbindlist->dom_alive = 0; 4581927Swollman ypbindlist->dom_lockfd = -1; 4598091Swpaul ypbindlist->dom_default = 1; 4608425Swpaul domains++; 4611927Swollman 4628425Swpaul signal(SIGCHLD, reaper); 4638425Swpaul signal(SIGTERM, terminate); 4648425Swpaul 46521581Swpaul ppid = getpid(); /* Remember who we are. */ 46621581Swpaul 4678246Swpaul openlog(argv[0], LOG_PID, LOG_DAEMON); 4686478Swpaul 469226690Sglebius if (madvise(NULL, 0, MADV_PROTECT) != 0) 470226690Sglebius syslog(LOG_WARNING, "madvise(): %m"); 471226690Sglebius 4728425Swpaul /* Kick off the default domain */ 4738425Swpaul broadcast(ypbindlist); 4748425Swpaul 47590297Sdes while (1) { 4761927Swollman fdsr = svc_fdset; 4778091Swpaul 4788425Swpaul tv.tv_sec = 60; 4791927Swollman tv.tv_usec = 0; 4801927Swollman 48190297Sdes switch (select(_rpc_dtablesize(), &fdsr, NULL, NULL, &tv)) { 4821927Swollman case 0: 4831927Swollman checkwork(); 4841927Swollman break; 4851927Swollman case -1: 4868755Swpaul if (errno != EINTR) 48721539Swpaul syslog(LOG_WARNING, "select: %m"); 4888755Swpaul break; 4891927Swollman default: 49090297Sdes for (ypdb = ypbindlist; ypdb; ypdb = next) { 49178674Sben next = ypdb->dom_pnext; 4928755Swpaul if (READFD > 0 && FD_ISSET(READFD, &fdsr)) { 4938853Swpaul handle_children(ypdb); 4948755Swpaul if (children == (MAX_CHILDREN - 1)) 4958755Swpaul checkwork(); 4968091Swpaul } 4971927Swollman } 4981927Swollman svc_getreqset(&fdsr); 4991927Swollman break; 5001927Swollman } 5011927Swollman } 50221581Swpaul 50321581Swpaul /* NOTREACHED */ 50421581Swpaul exit(1); 5051927Swollman} 5061927Swollman 5078091Swpaulvoid 50890298Sdescheckwork(void) 5091927Swollman{ 5101927Swollman struct _dom_binding *ypdb; 5111927Swollman 51290297Sdes for (ypdb = ypbindlist; ypdb; ypdb = ypdb->dom_pnext) 5138425Swpaul ping(ypdb); 5141927Swollman} 5151927Swollman 5168091Swpaul/* The clnt_broadcast() callback mechanism sucks. */ 5178091Swpaul 5188091Swpaul/* 5198091Swpaul * Receive results from broadcaster. Don't worry about passing 5208853Swpaul * bogus info to rpc_received() -- it can handle it. Note that we 5218853Swpaul * must be sure to invalidate the dom_pipe_fds descriptors here: 5228853Swpaul * since descriptors can be re-used, we have to make sure we 5238853Swpaul * don't mistake one of the RPC descriptors for one of the pipes. 5248853Swpaul * What's weird is that forgetting to invalidate the pipe descriptors 5258853Swpaul * doesn't always result in an error (otherwise I would have caught 5268853Swpaul * the mistake much sooner), even though logically it should. 5278091Swpaul */ 52890298Sdesvoid 52990298Sdeshandle_children(struct _dom_binding *ypdb) 5308091Swpaul{ 5318091Swpaul char buf[YPMAXDOMAIN + 1]; 5328091Swpaul struct sockaddr_in addr; 53321539Swpaul int d = 0, a = 0; 53421539Swpaul struct _dom_binding *y, *prev = NULL; 53521539Swpaul char path[MAXPATHLEN]; 5368091Swpaul 53721539Swpaul if ((d = read(READFD, &buf, sizeof(buf))) <= 0) 53821539Swpaul syslog(LOG_WARNING, "could not read from child: %m"); 5398755Swpaul 54021539Swpaul if ((a = read(READFD, &addr, sizeof(struct sockaddr_in))) < 0) 54121539Swpaul syslog(LOG_WARNING, "could not read from child: %m"); 54221539Swpaul 5438853Swpaul close(READFD); 5448853Swpaul FD_CLR(READFD, &fdsr); 5458853Swpaul FD_CLR(READFD, &svc_fdset); 5468853Swpaul READFD = WRITEFD = -1; 54721539Swpaul if (d > 0 && a > 0) 54895658Sdes rpc_received(buf, &addr, 0); 54921539Swpaul else { 55090297Sdes for (y = ypbindlist; y; y = y->dom_pnext) { 55121539Swpaul if (y == ypdb) 55221539Swpaul break; 55321539Swpaul prev = y; 55421539Swpaul } 55590297Sdes switch (ypdb->dom_default) { 55621539Swpaul case 0: 55721539Swpaul if (prev == NULL) 55821539Swpaul ypbindlist = y->dom_pnext; 55921539Swpaul else 56021539Swpaul prev->dom_pnext = y->dom_pnext; 56121539Swpaul sprintf(path, "%s/%s.%ld", BINDINGDIR, 56221539Swpaul ypdb->dom_domain, YPVERS); 56321539Swpaul close(ypdb->dom_lockfd); 56421539Swpaul unlink(path); 56521539Swpaul free(ypdb); 56621539Swpaul domains--; 56721539Swpaul return; 56821539Swpaul case 1: 56921539Swpaul ypdb->dom_broadcast_pid = 0; 57021539Swpaul ypdb->dom_alive = 0; 57121539Swpaul broadcast(ypdb); 57221539Swpaul return; 57321539Swpaul default: 57421539Swpaul break; 57521539Swpaul } 57621539Swpaul } 57721539Swpaul 57821539Swpaul return; 5798091Swpaul} 5808091Swpaul 5818091Swpaul/* 5828091Swpaul * Send our dying words back to our parent before we perish. 5838091Swpaul */ 5848091Swpaulint 58590298Sdestell_parent(char *dom, struct sockaddr_in *addr) 5861927Swollman{ 5878091Swpaul char buf[YPMAXDOMAIN + 1]; 5888091Swpaul struct timeval timeout; 5898091Swpaul fd_set fds; 5901927Swollman 5918091Swpaul timeout.tv_sec = 5; 5928091Swpaul timeout.tv_usec = 0; 5931927Swollman 5948755Swpaul sprintf(buf, "%s", broad_domain->dom_domain); 5958755Swpaul if (write(BROADFD, &buf, sizeof(buf)) < 0) 5968091Swpaul return(1); 5971927Swollman 5988091Swpaul /* 5998091Swpaul * Stay in sync with parent: wait for it to read our first 6008091Swpaul * message before sending the second. 6018091Swpaul */ 6021927Swollman 6038091Swpaul FD_ZERO(&fds); 6048755Swpaul FD_SET(BROADFD, &fds); 6058091Swpaul if (select(FD_SETSIZE, NULL, &fds, NULL, &timeout) == -1) 6068091Swpaul return(1); 6078755Swpaul if (FD_ISSET(BROADFD, &fds)) { 6088755Swpaul if (write(BROADFD, addr, sizeof(struct sockaddr_in)) < 0) 6098091Swpaul return(1); 6108091Swpaul } else { 6118091Swpaul return(1); 6121927Swollman } 6131927Swollman 6148755Swpaul close(BROADFD); 6158091Swpaul return (0); 6168091Swpaul} 6171927Swollman 6188091Swpaulbool_t broadcast_result(out, addr) 6198091Swpaulbool_t *out; 6208091Swpaulstruct sockaddr_in *addr; 6218091Swpaul{ 6229600Swpaul if (retries >= MAX_RETRIES) { 62395658Sdes bzero(addr, sizeof(struct sockaddr_in)); 6249600Swpaul if (tell_parent(broad_domain->dom_domain, addr)) 6259600Swpaul syslog(LOG_WARNING, "lost connection to parent"); 62690297Sdes return (TRUE); 6279600Swpaul } 6289600Swpaul 6299600Swpaul if (yp_restricted && verify(addr->sin_addr)) { 6309600Swpaul retries++; 6319600Swpaul syslog(LOG_NOTICE, "NIS server at %s not in restricted mode access list -- rejecting.\n",inet_ntoa(addr->sin_addr)); 63290297Sdes return (FALSE); 6339600Swpaul } else { 6349600Swpaul if (tell_parent(broad_domain->dom_domain, addr)) 6359600Swpaul syslog(LOG_WARNING, "lost connection to parent"); 63690297Sdes return (TRUE); 6379600Swpaul } 6388091Swpaul} 6398091Swpaul 6408091Swpaul/* 6418091Swpaul * The right way to send RPC broadcasts. 6428091Swpaul * Use the clnt_broadcast() RPC service. Unfortunately, clnt_broadcast() 64372091Sasmodai * blocks while waiting for replies, so we have to fork off separate 6448091Swpaul * broadcaster processes that do the waiting and then transmit their 6458091Swpaul * results back to the parent for processing. We also have to remember 6468091Swpaul * to save the name of the domain we're trying to bind in a global 6478091Swpaul * variable since clnt_broadcast() provides no way to pass things to 6488091Swpaul * the 'eachresult' callback function. 6498091Swpaul */ 6508091Swpaulvoid 65190298Sdesbroadcast(struct _dom_binding *ypdb) 6528091Swpaul{ 6538091Swpaul bool_t out = FALSE; 6548091Swpaul enum clnt_stat stat; 6558091Swpaul 6568755Swpaul if (children >= MAX_CHILDREN || ypdb->dom_broadcast_pid) 6578091Swpaul return; 6588091Swpaul 6598755Swpaul if (pipe(ypdb->dom_pipe_fds) < 0) { 66021539Swpaul syslog(LOG_WARNING, "pipe: %m"); 6618091Swpaul return; 6621927Swollman } 6631927Swollman 664213611Smarkm if (ypdb->dom_vers == -1 && (long)ypdb->dom_server_addr.sin_addr.s_addr) { 665213611Smarkm if (not_responding_count++ >= NOT_RESPONDING_HYSTERESIS) { 666213611Smarkm not_responding_count = NOT_RESPONDING_HYSTERESIS; 667213611Smarkm syslog(LOG_WARNING, "NIS server [%s] for domain \"%s\" not responding", 668213611Smarkm inet_ntoa(ypdb->dom_server_addr.sin_addr), ypdb->dom_domain); 669213611Smarkm } 670213611Smarkm } 6718425Swpaul 6728755Swpaul broad_domain = ypdb; 6738425Swpaul flock(ypdb->dom_lockfd, LOCK_UN); 6748425Swpaul 67590297Sdes switch ((ypdb->dom_broadcast_pid = fork())) { 6768091Swpaul case 0: 6778755Swpaul close(READFD); 67821539Swpaul signal(SIGCHLD, SIG_DFL); 67921539Swpaul signal(SIGTERM, SIG_DFL); 6808091Swpaul break; 6818091Swpaul case -1: 68221539Swpaul syslog(LOG_WARNING, "fork: %m"); 6838755Swpaul close(READFD); 6848755Swpaul close(WRITEFD); 6858091Swpaul return; 6868091Swpaul default: 6878755Swpaul close(WRITEFD); 6888755Swpaul FD_SET(READFD, &svc_fdset); 6898091Swpaul children++; 6908091Swpaul return; 6911927Swollman } 6926478Swpaul 6938755Swpaul /* Release all locks before doing anything else. */ 69490297Sdes while (ypbindlist) { 6958755Swpaul close(ypbindlist->dom_lockfd); 6968755Swpaul ypbindlist = ypbindlist->dom_pnext; 6978755Swpaul } 6988755Swpaul close(yplockfd); 6998755Swpaul 70026135Swpaul /* 70126135Swpaul * Special 'many-cast' behavior. If we're in restricted mode, 70226135Swpaul * we have a list of possible server addresses to try. What 70326135Swpaul * we can do is transmit to each ypserv's YPPROC_DOMAIN_NONACK 70426135Swpaul * procedure and time the replies. Whoever replies fastest 70526135Swpaul * gets to be our server. Note that this is not a broadcast 70626135Swpaul * operation: we transmit uni-cast datagrams only. 70726135Swpaul */ 70826135Swpaul if (yp_restricted && yp_manycast) { 70926135Swpaul short port; 71026135Swpaul int i; 71126135Swpaul struct sockaddr_in sin; 71226135Swpaul 71326135Swpaul i = __yp_ping(restricted_addrs, yp_restricted, 71426135Swpaul ypdb->dom_domain, &port); 71526135Swpaul if (i == -1) { 71695658Sdes bzero(&ypdb->dom_server_addr, 71795658Sdes sizeof(struct sockaddr_in)); 71826135Swpaul if (tell_parent(ypdb->dom_domain, 71995658Sdes &ypdb->dom_server_addr)) 72026135Swpaul syslog(LOG_WARNING, "lost connection to parent"); 72126135Swpaul } else { 72295658Sdes bzero(&sin, sizeof(struct sockaddr_in)); 72395658Sdes bcopy(&restricted_addrs[i], 72495658Sdes &sin.sin_addr, sizeof(struct in_addr)); 72526135Swpaul sin.sin_family = AF_INET; 72626135Swpaul sin.sin_port = port; 72726135Swpaul if (tell_parent(broad_domain->dom_domain, &sin)) 72826135Swpaul syslog(LOG_WARNING, 72926135Swpaul "lost connection to parent"); 73026135Swpaul } 73126135Swpaul _exit(0); 73226135Swpaul } 73326135Swpaul 7349600Swpaul retries = 0; 7359600Swpaul 73612862Swpaul { 73712862Swpaul char *ptr; 7388091Swpaul 73995658Sdes ptr = ypdb->dom_domain; 74012862Swpaul stat = clnt_broadcast(YPPROG, YPVERS, YPPROC_DOMAIN_NONACK, 74195658Sdes (xdrproc_t)xdr_domainname, &ptr, 74295658Sdes (xdrproc_t)xdr_bool, &out, 74374462Salfred (resultproc_t)broadcast_result); 74412862Swpaul } 74512862Swpaul 7468091Swpaul if (stat != RPC_SUCCESS) { 74795658Sdes bzero(&ypdb->dom_server_addr, 74895658Sdes sizeof(struct sockaddr_in)); 7498755Swpaul if (tell_parent(ypdb->dom_domain, &ypdb->dom_server_addr)) 7508091Swpaul syslog(LOG_WARNING, "lost connection to parent"); 7518091Swpaul } 7528755Swpaul 75326135Swpaul _exit(0); 7541927Swollman} 7551927Swollman 7568091Swpaul/* 7578091Swpaul * The right way to check if a server is alive. 7588091Swpaul * Attempt to get a client handle pointing to the server and send a 7598755Swpaul * YPPROC_DOMAIN. If we can't get a handle or we get a reply of FALSE, 7608755Swpaul * we invalidate this binding entry and send out a broadcast to try to 7618755Swpaul * establish a new binding. Note that we treat non-default domains 7628091Swpaul * specially: once bound, we keep tabs on our server, but if it 7638091Swpaul * goes away and fails to respond after one round of broadcasting, we 7648091Swpaul * abandon it until a client specifically references it again. We make 7658091Swpaul * every effort to keep our default domain bound, however, since we 7668091Swpaul * need it to keep the system on its feet. 7678091Swpaul */ 7688091Swpaulint 76990298Sdesping(struct _dom_binding *ypdb) 7701927Swollman{ 7718091Swpaul bool_t out; 7728091Swpaul struct timeval interval, timeout; 7738091Swpaul enum clnt_stat stat; 7748091Swpaul int rpcsock = RPC_ANYSOCK; 7758755Swpaul CLIENT *client_handle; 7761927Swollman 7778755Swpaul interval.tv_sec = FAIL_THRESHOLD; 7788091Swpaul interval.tv_usec = 0; 7798091Swpaul timeout.tv_sec = FAIL_THRESHOLD; 7808091Swpaul timeout.tv_usec = 0; 7811927Swollman 7828755Swpaul if (ypdb->dom_broadcast_pid) 7838091Swpaul return(1); 7848091Swpaul 7858755Swpaul if ((client_handle = clntudp_bufcreate(&ypdb->dom_server_addr, 7868755Swpaul YPPROG, YPVERS, interval, &rpcsock, RPCSMALLMSGSIZE, 7878755Swpaul RPCSMALLMSGSIZE)) == (CLIENT *)NULL) { 7888755Swpaul /* Can't get a handle: we're dead. */ 7898755Swpaul ypdb->dom_alive = 0; 7908755Swpaul ypdb->dom_vers = -1; 7918755Swpaul broadcast(ypdb); 7928755Swpaul return(1); 7931927Swollman } 7941927Swollman 79512862Swpaul { 79612862Swpaul char *ptr; 79712862Swpaul 79895658Sdes ptr = ypdb->dom_domain; 79912862Swpaul 80095658Sdes stat = clnt_call(client_handle, YPPROC_DOMAIN, 80195658Sdes (xdrproc_t)xdr_domainname, &ptr, 80295658Sdes (xdrproc_t)xdr_bool, &out, timeout); 80395658Sdes if (stat != RPC_SUCCESS || out == FALSE) { 80412862Swpaul ypdb->dom_alive = 0; 80512862Swpaul ypdb->dom_vers = -1; 80612862Swpaul clnt_destroy(client_handle); 80712862Swpaul broadcast(ypdb); 80812862Swpaul return(1); 80912862Swpaul } 8108091Swpaul } 8111927Swollman 8128755Swpaul clnt_destroy(client_handle); 8138091Swpaul return(0); 8141927Swollman} 8151927Swollman 81690298Sdesvoid 81790298Sdesrpc_received(char *dom, struct sockaddr_in *raddrp, int force) 8181927Swollman{ 8198425Swpaul struct _dom_binding *ypdb, *prev = NULL; 8201927Swollman struct iovec iov[2]; 8211927Swollman struct ypbind_resp ybr; 8221927Swollman char path[MAXPATHLEN]; 8231927Swollman int fd; 8241927Swollman 8256732Swpaul /*printf("returned from %s/%d about %s\n", inet_ntoa(raddrp->sin_addr), 8266732Swpaul ntohs(raddrp->sin_port), dom);*/ 8271927Swollman 82890297Sdes if (dom == NULL) 8291927Swollman return; 8301927Swollman 83190297Sdes for (ypdb = ypbindlist; ypdb; ypdb = ypdb->dom_pnext) { 83290297Sdes if (strcmp(ypdb->dom_domain, dom) == 0) 8338091Swpaul break; 8348425Swpaul prev = ypdb; 8358425Swpaul } 8368091Swpaul 8378755Swpaul if (ypdb && force) { 8388755Swpaul if (ypdb->dom_broadcast_pid) { 8398755Swpaul kill(ypdb->dom_broadcast_pid, SIGINT); 8408755Swpaul close(READFD); 8418853Swpaul FD_CLR(READFD, &fdsr); 8428853Swpaul FD_CLR(READFD, &svc_fdset); 8438853Swpaul READFD = WRITEFD = -1; 8448755Swpaul } 8458755Swpaul } 8468755Swpaul 8479600Swpaul /* if in secure mode, check originating port number */ 8489600Swpaul if ((ypsecuremode && (ntohs(raddrp->sin_port) >= IPPORT_RESERVED))) { 8496732Swpaul syslog(LOG_WARNING, "Rejected NIS server on [%s/%d] for domain %s.", 8506732Swpaul inet_ntoa(raddrp->sin_addr), ntohs(raddrp->sin_port), 8516732Swpaul dom); 8528246Swpaul if (ypdb != NULL) { 8538755Swpaul ypdb->dom_broadcast_pid = 0; 8548246Swpaul ypdb->dom_alive = 0; 8558246Swpaul } 8566732Swpaul return; 8576732Swpaul } 8586732Swpaul 8598246Swpaul if (raddrp->sin_addr.s_addr == (long)0) { 86090297Sdes switch (ypdb->dom_default) { 8618755Swpaul case 0: 8628755Swpaul if (prev == NULL) 8638755Swpaul ypbindlist = ypdb->dom_pnext; 8648755Swpaul else 8658755Swpaul prev->dom_pnext = ypdb->dom_pnext; 8668755Swpaul sprintf(path, "%s/%s.%ld", BINDINGDIR, 8678755Swpaul ypdb->dom_domain, YPVERS); 8688755Swpaul close(ypdb->dom_lockfd); 8698755Swpaul unlink(path); 8708755Swpaul free(ypdb); 8718755Swpaul domains--; 8728755Swpaul return; 8738755Swpaul case 1: 8748755Swpaul ypdb->dom_broadcast_pid = 0; 8758755Swpaul ypdb->dom_alive = 0; 8768755Swpaul broadcast(ypdb); 8778755Swpaul return; 8788755Swpaul default: 8798755Swpaul break; 8808755Swpaul } 8818246Swpaul } 8828246Swpaul 88390297Sdes if (ypdb == NULL) { 8848246Swpaul if (force == 0) 8851927Swollman return; 8861927Swollman ypdb = (struct _dom_binding *)malloc(sizeof *ypdb); 8878857Srgrimes if (ypdb == NULL) { 88821539Swpaul syslog(LOG_WARNING, "malloc: %m"); 8898246Swpaul return; 8908246Swpaul } 89195658Sdes bzero(ypdb, sizeof *ypdb); 8921927Swollman strncpy(ypdb->dom_domain, dom, sizeof ypdb->dom_domain); 8931927Swollman ypdb->dom_lockfd = -1; 8948091Swpaul ypdb->dom_default = 0; 8951927Swollman ypdb->dom_pnext = ypbindlist; 8961927Swollman ypbindlist = ypdb; 8971927Swollman } 8981927Swollman 8998091Swpaul /* We've recovered from a crash: inform the world. */ 900213611Smarkm if (ypdb->dom_vers == -1 && ypdb->dom_server_addr.sin_addr.s_addr) { 901213611Smarkm if (not_responding_count >= NOT_RESPONDING_HYSTERESIS) { 902213611Smarkm not_responding_count = 0; 903213611Smarkm syslog(LOG_WARNING, "NIS server [%s] for domain \"%s\" OK", 904213611Smarkm inet_ntoa(raddrp->sin_addr), ypdb->dom_domain); 905213611Smarkm } 906213611Smarkm } 9076478Swpaul 90895658Sdes bcopy(raddrp, &ypdb->dom_server_addr, 9091927Swollman sizeof ypdb->dom_server_addr); 9106478Swpaul 9111927Swollman ypdb->dom_vers = YPVERS; 9121927Swollman ypdb->dom_alive = 1; 9138755Swpaul ypdb->dom_broadcast_pid = 0; 9141927Swollman 91590297Sdes if (ypdb->dom_lockfd != -1) 9161927Swollman close(ypdb->dom_lockfd); 9171927Swollman 9188091Swpaul sprintf(path, "%s/%s.%ld", BINDINGDIR, 9191927Swollman ypdb->dom_domain, ypdb->dom_vers); 9201927Swollman#ifdef O_SHLOCK 92190297Sdes if ((fd = open(path, O_CREAT|O_SHLOCK|O_RDWR|O_TRUNC, 0644)) == -1) { 9221927Swollman (void)mkdir(BINDINGDIR, 0755); 92390297Sdes if ((fd = open(path, O_CREAT|O_SHLOCK|O_RDWR|O_TRUNC, 0644)) == -1) 9241927Swollman return; 9251927Swollman } 9261927Swollman#else 92790297Sdes if ((fd = open(path, O_CREAT|O_RDWR|O_TRUNC, 0644)) == -1) { 9281927Swollman (void)mkdir(BINDINGDIR, 0755); 92990297Sdes if ((fd = open(path, O_CREAT|O_RDWR|O_TRUNC, 0644)) == -1) 9301927Swollman return; 9311927Swollman } 9321927Swollman flock(fd, LOCK_SH); 9331927Swollman#endif 9341927Swollman 9351927Swollman /* 9361927Swollman * ok, if BINDINGDIR exists, and we can create the binding file, 9371927Swollman * then write to it.. 9381927Swollman */ 9391927Swollman ypdb->dom_lockfd = fd; 9401927Swollman 94195658Sdes iov[0].iov_base = (char *)&(udptransp->xp_port); 9421927Swollman iov[0].iov_len = sizeof udptransp->xp_port; 94395658Sdes iov[1].iov_base = (char *)&ybr; 9441927Swollman iov[1].iov_len = sizeof ybr; 9451927Swollman 9461927Swollman bzero(&ybr, sizeof ybr); 9471927Swollman ybr.ypbind_status = YPBIND_SUCC_VAL; 94845656Ssimokawa *(u_int32_t *)&ybr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_addr = raddrp->sin_addr.s_addr; 94912862Swpaul *(u_short *)&ybr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_port = raddrp->sin_port; 9501927Swollman 95190297Sdes if (writev(ypdb->dom_lockfd, iov, 2) != iov[0].iov_len + iov[1].iov_len) { 95221539Swpaul syslog(LOG_WARNING, "write: %m"); 9531927Swollman close(ypdb->dom_lockfd); 9541927Swollman ypdb->dom_lockfd = -1; 9551927Swollman return; 9561927Swollman } 9571927Swollman} 9589600Swpaul 9599600Swpaul/* 9609600Swpaul * Check address against list of allowed servers. Return 0 if okay, 9619600Swpaul * 1 if not matched. 9629600Swpaul */ 9639600Swpaulint 96490298Sdesverify(struct in_addr addr) 9659600Swpaul{ 9669600Swpaul int i; 9679600Swpaul 9689600Swpaul for (i = 0; i < RESTRICTED_SERVERS; i++) 96995658Sdes if (!bcmp(&addr, &restricted_addrs[i], sizeof(struct in_addr))) 9709600Swpaul return(0); 9719600Swpaul 9729600Swpaul return(1); 9739600Swpaul} 9749600Swpaul 9759600Swpaul/* 9769600Swpaul * Try to set restricted mode. We default to normal mode if we can't 9779600Swpaul * resolve the specified hostnames. 9789600Swpaul */ 9799600Swpaulvoid 98090298Sdesyp_restricted_mode(char *args) 9819600Swpaul{ 9829600Swpaul struct hostent *h; 9839600Swpaul int i = 0; 9849600Swpaul char *s; 9859600Swpaul 9869600Swpaul /* Find the restricted domain. */ 9879600Swpaul if ((s = strsep(&args, ",")) == NULL) 9889600Swpaul return; 98912862Swpaul domain_name = s; 9909600Swpaul 9919600Swpaul /* Get the addresses of the servers. */ 9929600Swpaul while ((s = strsep(&args, ",")) != NULL && i < RESTRICTED_SERVERS) { 9939600Swpaul if ((h = gethostbyname(s)) == NULL) 9949600Swpaul return; 99595658Sdes bcopy (h->h_addr_list[0], &restricted_addrs[i], 99695658Sdes sizeof(struct in_addr)); 99795658Sdes i++; 9989600Swpaul } 9999600Swpaul 10009600Swpaul /* ypset and ypsetme not allowed with restricted mode */ 10019600Swpaul ypsetmode = YPSET_NO; 100290297Sdes 100326135Swpaul yp_restricted = i; 10049600Swpaul return; 10059600Swpaul} 1006