ypbind.c revision 74462
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 3030762Scharnier#ifndef lint 3130762Scharnierstatic const char rcsid[] = 3250479Speter "$FreeBSD: head/usr.sbin/ypbind/ypbind.c 74462 2001-03-19 12:50:13Z alfred $"; 3330762Scharnier#endif /* not lint */ 341927Swollman 351927Swollman#include <sys/param.h> 361927Swollman#include <sys/types.h> 378091Swpaul#include <sys/wait.h> 381927Swollman#include <sys/ioctl.h> 391927Swollman#include <sys/signal.h> 401927Swollman#include <sys/socket.h> 411927Swollman#include <sys/file.h> 421927Swollman#include <sys/fcntl.h> 438091Swpaul#include <sys/stat.h> 441927Swollman#include <sys/uio.h> 451927Swollman#include <ctype.h> 461927Swollman#include <dirent.h> 4730762Scharnier#include <err.h> 4830762Scharnier#include <errno.h> 491927Swollman#include <netdb.h> 5030762Scharnier#include <signal.h> 5130762Scharnier#include <stdio.h> 5230762Scharnier#include <stdlib.h> 531927Swollman#include <string.h> 5430762Scharnier#include <syslog.h> 5530762Scharnier#include <unistd.h> 561927Swollman#include <rpc/rpc.h> 571927Swollman#include <rpc/xdr.h> 581927Swollman#include <net/if.h> 596732Swpaul#include <netinet/in.h> 601927Swollman#include <arpa/inet.h> 611927Swollman#include <rpc/pmap_clnt.h> 621927Swollman#include <rpc/pmap_prot.h> 631927Swollman#include <rpc/pmap_rmt.h> 6430762Scharnier#include <rpc/rpc_com.h> 6512862Swpaul#include <rpcsvc/yp.h> 6612862Swpaulstruct dom_binding{}; 671927Swollman#include <rpcsvc/ypclnt.h> 6826135Swpaul#include "yp_ping.h" 691927Swollman 701927Swollman#ifndef BINDINGDIR 711927Swollman#define BINDINGDIR "/var/yp/binding" 721927Swollman#endif 731927Swollman 748474Swpaul#ifndef YPBINDLOCK 758474Swpaul#define YPBINDLOCK "/var/run/ypbind.lock" 768474Swpaul#endif 778474Swpaul 781927Swollmanstruct _dom_binding { 791927Swollman struct _dom_binding *dom_pnext; 801927Swollman char dom_domain[YPMAXDOMAIN + 1]; 811927Swollman struct sockaddr_in dom_server_addr; 821927Swollman long int dom_vers; 831927Swollman int dom_lockfd; 841927Swollman int dom_alive; 858755Swpaul int dom_broadcast_pid; 868755Swpaul int dom_pipe_fds[2]; 878091Swpaul int dom_default; 881927Swollman}; 891927Swollman 908755Swpaul#define READFD ypdb->dom_pipe_fds[0] 918755Swpaul#define WRITEFD ypdb->dom_pipe_fds[1] 928755Swpaul#define BROADFD broad_domain->dom_pipe_fds[1] 938755Swpaul 941927Swollmanextern bool_t xdr_domainname(), xdr_ypbind_resp(); 951927Swollmanextern bool_t xdr_ypreq_key(), xdr_ypresp_val(); 961927Swollmanextern bool_t xdr_ypbind_setdom(); 971927Swollman 988091Swpaulvoid checkwork __P((void)); 9932631Swpaulvoid *ypbindproc_null_2_yp __P((SVCXPRT *, void *, CLIENT *)); 10032631Swpaulvoid *ypbindproc_setdom_2_yp __P((SVCXPRT *, struct ypbind_setdom *, CLIENT *)); 1018091Swpaulvoid rpc_received __P((char *, struct sockaddr_in *, int )); 1028091Swpaulvoid broadcast __P((struct _dom_binding *)); 1038425Swpaulint ping __P((struct _dom_binding *)); 1048755Swpaulint tell_parent __P((char *, struct sockaddr_in *)); 1058853Swpaulvoid handle_children __P(( struct _dom_binding * )); 1068425Swpaulvoid reaper __P((int)); 1078425Swpaulvoid terminate __P((int)); 1089600Swpaulvoid yp_restricted_mode __P((char *)); 1099600Swpaulint verify __P((struct in_addr)); 1108091Swpaul 11112862Swpaulchar *domain_name; 1121927Swollmanstruct _dom_binding *ypbindlist; 1138755Swpaulstatic struct _dom_binding *broad_domain; 1141927Swollman 1151927Swollman#define YPSET_NO 0 1161927Swollman#define YPSET_LOCAL 1 1171927Swollman#define YPSET_ALL 2 1181927Swollmanint ypsetmode = YPSET_NO; 1196732Swpaulint ypsecuremode = 0; 12021581Swpaulint ppid; 1216732Swpaul 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 * 15932631Swpaulypbindproc_null_2_yp(transp, argp, clnt) 1601927SwollmanSVCXPRT *transp; 1611927Swollmanvoid *argp; 1621927SwollmanCLIENT *clnt; 1631927Swollman{ 1641927Swollman static char res; 1651927Swollman 1661927Swollman bzero((char *)&res, sizeof(res)); 1671927Swollman return (void *)&res; 1681927Swollman} 1691927Swollman 1701927Swollmanstruct ypbind_resp * 17132631Swpaulypbindproc_domain_2_yp(transp, argp, clnt) 1721927SwollmanSVCXPRT *transp; 17312862Swpauldomainname *argp; 1741927SwollmanCLIENT *clnt; 1751927Swollman{ 1761927Swollman static struct ypbind_resp res; 1771927Swollman struct _dom_binding *ypdb; 1781927Swollman char path[MAXPATHLEN]; 1791927Swollman 1801927Swollman bzero((char *)&res, sizeof res); 1811927Swollman res.ypbind_status = YPBIND_FAIL_VAL; 18212862Swpaul res.ypbind_resp_u.ypbind_error = YPBIND_ERR_NOSERV; 1831927Swollman 18424782Swpaul if (strchr(*argp, '/')) { 18524782Swpaul syslog(LOG_WARNING, "Domain name '%s' has embedded slash -- \ 18624782Swpaulrejecting.", *argp); 18724782Swpaul return(&res); 18824782Swpaul } 18924782Swpaul 1908755Swpaul for(ypdb=ypbindlist; ypdb; ypdb=ypdb->dom_pnext) { 19112862Swpaul if( strcmp(ypdb->dom_domain, *argp) == 0) 1921927Swollman break; 1938755Swpaul } 1941927Swollman 1951927Swollman if(ypdb==NULL) { 1969600Swpaul if (yp_restricted) { 19712862Swpaul syslog(LOG_NOTICE, "Running in restricted mode -- request to bind domain \"%s\" rejected.\n", *argp); 1989600Swpaul return &res; 1999600Swpaul } 2009600Swpaul 2018474Swpaul if (domains >= MAX_DOMAINS) { 2028425Swpaul syslog(LOG_WARNING, "domain limit (%d) exceeded", 2038425Swpaul MAX_DOMAINS); 20412862Swpaul res.ypbind_resp_u.ypbind_error = YPBIND_ERR_RESC; 2058428Swpaul return &res; 2068425Swpaul } 2071927Swollman ypdb = (struct _dom_binding *)malloc(sizeof *ypdb); 2088857Srgrimes if (ypdb == NULL) { 20921539Swpaul syslog(LOG_WARNING, "malloc: %m"); 21012862Swpaul res.ypbind_resp_u.ypbind_error = YPBIND_ERR_RESC; 2118428Swpaul return &res; 2128246Swpaul } 2131927Swollman bzero((char *)ypdb, sizeof *ypdb); 21412862Swpaul strncpy(ypdb->dom_domain, *argp, sizeof ypdb->dom_domain); 2151927Swollman ypdb->dom_vers = YPVERS; 2161927Swollman ypdb->dom_alive = 0; 2178091Swpaul ypdb->dom_default = 0; 2181927Swollman ypdb->dom_lockfd = -1; 2198425Swpaul sprintf(path, "%s/%s.%ld", BINDINGDIR, 2208425Swpaul ypdb->dom_domain, ypdb->dom_vers); 2211927Swollman unlink(path); 2221927Swollman ypdb->dom_pnext = ypbindlist; 2231927Swollman ypbindlist = ypdb; 2248425Swpaul domains++; 2251927Swollman } 2261927Swollman 2278755Swpaul if (ping(ypdb)) { 2287982Swpaul return &res; 2298755Swpaul } 2301927Swollman 2311927Swollman res.ypbind_status = YPBIND_SUCC_VAL; 23212862Swpaul res.ypbind_resp_u.ypbind_error = 0; /* Success */ 23345656Ssimokawa *(u_int32_t *)&res.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_addr = 2341927Swollman ypdb->dom_server_addr.sin_addr.s_addr; 23512862Swpaul *(u_short *)&res.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_port = 2368091Swpaul ypdb->dom_server_addr.sin_port; 2371927Swollman /*printf("domain %s at %s/%d\n", ypdb->dom_domain, 2381927Swollman inet_ntoa(ypdb->dom_server_addr.sin_addr), 2391927Swollman ntohs(ypdb->dom_server_addr.sin_port));*/ 2401927Swollman return &res; 2411927Swollman} 2421927Swollman 2438755Swpaulvoid * 24432631Swpaulypbindproc_setdom_2_yp(transp, argp, clnt) 2451927SwollmanSVCXPRT *transp; 24612862Swpaulypbind_setdom *argp; 2471927SwollmanCLIENT *clnt; 2481927Swollman{ 2491927Swollman struct sockaddr_in *fromsin, bindsin; 25043854Swpaul static char *result = NULL; 2511927Swollman 25224782Swpaul if (strchr(argp->ypsetdom_domain, '/')) { 25324782Swpaul syslog(LOG_WARNING, "Domain name '%s' has embedded slash -- \ 25424782Swpaulrejecting.", argp->ypsetdom_domain); 25530762Scharnier return(NULL); 25624782Swpaul } 2571927Swollman fromsin = svc_getcaller(transp); 2581927Swollman 2591927Swollman switch(ypsetmode) { 2601927Swollman case YPSET_LOCAL: 2618755Swpaul if( fromsin->sin_addr.s_addr != htonl(INADDR_LOOPBACK)) { 2628755Swpaul svcerr_noprog(transp); 26330762Scharnier return(NULL); 2648755Swpaul } 2651927Swollman break; 2661927Swollman case YPSET_ALL: 2671927Swollman break; 2681927Swollman case YPSET_NO: 2691927Swollman default: 2708755Swpaul svcerr_noprog(transp); 27130762Scharnier return(NULL); 2721927Swollman } 2731927Swollman 2748755Swpaul if(ntohs(fromsin->sin_port) >= IPPORT_RESERVED) { 2758755Swpaul svcerr_noprog(transp); 27630762Scharnier return(NULL); 2778755Swpaul } 2781927Swollman 2798755Swpaul if(argp->ypsetdom_vers != YPVERS) { 2808755Swpaul svcerr_noprog(transp); 28130762Scharnier return(NULL); 2828755Swpaul } 2831927Swollman 2841927Swollman bzero((char *)&bindsin, sizeof bindsin); 2851927Swollman bindsin.sin_family = AF_INET; 28645656Ssimokawa bindsin.sin_addr.s_addr = *(u_int32_t *)argp->ypsetdom_binding.ypbind_binding_addr; 28712862Swpaul bindsin.sin_port = *(u_short *)argp->ypsetdom_binding.ypbind_binding_port; 2881927Swollman rpc_received(argp->ypsetdom_domain, &bindsin, 1); 2891927Swollman 29043854Swpaul return((void *) &result); 2911927Swollman} 2921927Swollman 2931927Swollmanstatic void 2941927Swollmanypbindprog_2(rqstp, transp) 2951927Swollmanstruct svc_req *rqstp; 2961927Swollmanregister SVCXPRT *transp; 2971927Swollman{ 2981927Swollman union { 29912862Swpaul domainname ypbindproc_domain_2_arg; 3001927Swollman struct ypbind_setdom ypbindproc_setdom_2_arg; 3011927Swollman } argument; 3021927Swollman struct authunix_parms *creds; 3031927Swollman char *result; 3041927Swollman bool_t (*xdr_argument)(), (*xdr_result)(); 3051927Swollman char *(*local)(); 3061927Swollman 3071927Swollman switch (rqstp->rq_proc) { 3081927Swollman case YPBINDPROC_NULL: 3091927Swollman xdr_argument = xdr_void; 3101927Swollman xdr_result = xdr_void; 31132631Swpaul local = (char *(*)()) ypbindproc_null_2_yp; 3121927Swollman break; 3131927Swollman 3141927Swollman case YPBINDPROC_DOMAIN: 3151927Swollman xdr_argument = xdr_domainname; 3161927Swollman xdr_result = xdr_ypbind_resp; 31732631Swpaul local = (char *(*)()) ypbindproc_domain_2_yp; 3181927Swollman break; 3191927Swollman 3201927Swollman case YPBINDPROC_SETDOM: 3211927Swollman switch(rqstp->rq_cred.oa_flavor) { 3221927Swollman case AUTH_UNIX: 3231927Swollman creds = (struct authunix_parms *)rqstp->rq_clntcred; 3241927Swollman if( creds->aup_uid != 0) { 3251927Swollman svcerr_auth(transp, AUTH_BADCRED); 3261927Swollman return; 3271927Swollman } 3281927Swollman break; 3291927Swollman default: 3301927Swollman svcerr_auth(transp, AUTH_TOOWEAK); 3311927Swollman return; 3321927Swollman } 3331927Swollman 3341927Swollman xdr_argument = xdr_ypbind_setdom; 3351927Swollman xdr_result = xdr_void; 33632631Swpaul local = (char *(*)()) ypbindproc_setdom_2_yp; 3371927Swollman break; 3381927Swollman 3391927Swollman default: 3401927Swollman svcerr_noproc(transp); 3411927Swollman return; 3421927Swollman } 3431927Swollman bzero((char *)&argument, sizeof(argument)); 34421096Speter if (!svc_getargs(transp, xdr_argument, (caddr_t)&argument)) { 3451927Swollman svcerr_decode(transp); 3461927Swollman return; 3471927Swollman } 3481927Swollman result = (*local)(transp, &argument, rqstp); 3491927Swollman if (result != NULL && !svc_sendreply(transp, xdr_result, result)) { 3501927Swollman svcerr_systemerr(transp); 3511927Swollman } 3521927Swollman return; 3531927Swollman} 3541927Swollman 3558091Swpaul/* Jack the reaper */ 3568091Swpaulvoid reaper(sig) 3578091Swpaulint sig; 3588091Swpaul{ 3598091Swpaul int st; 3608091Swpaul 3619532Swpaul while(wait3(&st, WNOHANG, NULL) > 0) 3629532Swpaul children--; 3638091Swpaul} 3648091Swpaul 3658425Swpaulvoid terminate(sig) 3668425Swpaulint sig; 3678425Swpaul{ 3688425Swpaul struct _dom_binding *ypdb; 3698425Swpaul char path[MAXPATHLEN]; 3708425Swpaul 37121581Swpaul if (ppid != getpid()) 37221581Swpaul exit(0); 37321581Swpaul 3748425Swpaul for(ypdb=ypbindlist; ypdb; ypdb=ypdb->dom_pnext) { 3758425Swpaul close(ypdb->dom_lockfd); 3768755Swpaul if (ypdb->dom_broadcast_pid) 3778755Swpaul kill(ypdb->dom_broadcast_pid, SIGINT); 3788425Swpaul sprintf(path, "%s/%s.%ld", BINDINGDIR, 3798425Swpaul ypdb->dom_domain, ypdb->dom_vers); 3808425Swpaul unlink(path); 3818425Swpaul } 3828474Swpaul close(yplockfd); 3838474Swpaul unlink(YPBINDLOCK); 3848425Swpaul pmap_unset(YPBINDPROG, YPBINDVERS); 3858425Swpaul exit(0); 3868425Swpaul} 3878857Srgrimes 38821581Swpaulint 3891927Swollmanmain(argc, argv) 3908091Swpaulint argc; 3911927Swollmanchar **argv; 3921927Swollman{ 3931927Swollman struct timeval tv; 3941927Swollman int i; 3958425Swpaul DIR *dird; 3968425Swpaul struct dirent *dirp; 3978755Swpaul struct _dom_binding *ypdb; 3981927Swollman 3998474Swpaul /* Check that another ypbind isn't already running. */ 40030762Scharnier if ((yplockfd = (open(YPBINDLOCK, O_RDONLY|O_CREAT, 0444))) == -1) 40130762Scharnier err(1, "%s", YPBINDLOCK); 4028474Swpaul 40330762Scharnier if(flock(yplockfd, LOCK_EX|LOCK_NB) == -1 && errno == EWOULDBLOCK) 40430762Scharnier errx(1, "another ypbind is already running. Aborting"); 4058474Swpaul 4069600Swpaul /* XXX domainname will be overriden if we use restricted mode */ 40712862Swpaul yp_get_default_domain(&domain_name); 40830762Scharnier if( domain_name[0] == '\0') 40930762Scharnier errx(1, "domainname not set. Aborting"); 4101927Swollman 4111927Swollman for(i=1; i<argc; i++) { 4121927Swollman if( strcmp("-ypset", argv[i]) == 0) 4131927Swollman ypsetmode = YPSET_ALL; 4141927Swollman else if (strcmp("-ypsetme", argv[i]) == 0) 4156732Swpaul ypsetmode = YPSET_LOCAL; 4166732Swpaul else if (strcmp("-s", argv[i]) == 0) 4176732Swpaul ypsecuremode++; 4189600Swpaul else if (strcmp("-S", argv[i]) == 0 && argc > i) 4199600Swpaul yp_restricted_mode(argv[i+1]); 42026135Swpaul else if (strcmp("-m", argv[i]) == 0) 42126135Swpaul yp_manycast++; 4221927Swollman } 4231927Swollman 4248425Swpaul /* blow away everything in BINDINGDIR (if it exists) */ 4251927Swollman 4268425Swpaul if ((dird = opendir(BINDINGDIR)) != NULL) { 4278425Swpaul char path[MAXPATHLEN]; 4288425Swpaul while ((dirp = readdir(dird)) != NULL) 4298425Swpaul if (strcmp(dirp->d_name, ".") && 4308425Swpaul strcmp(dirp->d_name, "..")) { 4318425Swpaul sprintf(path,"%s/%s",BINDINGDIR,dirp->d_name); 4328425Swpaul unlink(path); 4338425Swpaul } 4348425Swpaul closedir(dird); 4358425Swpaul } 4361927Swollman 4371927Swollman#ifdef DAEMON 43830762Scharnier if (daemon(0,0)) 43930762Scharnier err(1, "fork"); 4401927Swollman#endif 4411927Swollman 4421927Swollman pmap_unset(YPBINDPROG, YPBINDVERS); 4431927Swollman 4441927Swollman udptransp = svcudp_create(RPC_ANYSOCK); 44530762Scharnier if (udptransp == NULL) 44630762Scharnier errx(1, "cannot create udp service"); 4471927Swollman if (!svc_register(udptransp, YPBINDPROG, YPBINDVERS, ypbindprog_2, 44830762Scharnier IPPROTO_UDP)) 44930762Scharnier errx(1, "unable to register (YPBINDPROG, YPBINDVERS, udp)"); 4501927Swollman 4511927Swollman tcptransp = svctcp_create(RPC_ANYSOCK, 0, 0); 45230762Scharnier if (tcptransp == NULL) 45330762Scharnier errx(1, "cannot create tcp service"); 4541927Swollman 4551927Swollman if (!svc_register(tcptransp, YPBINDPROG, YPBINDVERS, ypbindprog_2, 45630762Scharnier IPPROTO_TCP)) 45730762Scharnier errx(1, "unable to register (YPBINDPROG, YPBINDVERS, tcp)"); 4581927Swollman 4591927Swollman /* build initial domain binding, make it "unsuccessful" */ 4601927Swollman ypbindlist = (struct _dom_binding *)malloc(sizeof *ypbindlist); 46130762Scharnier if (ypbindlist == NULL) 46230762Scharnier errx(1, "malloc"); 4631927Swollman bzero((char *)ypbindlist, sizeof *ypbindlist); 46412862Swpaul strncpy(ypbindlist->dom_domain, domain_name, sizeof ypbindlist->dom_domain); 4651927Swollman ypbindlist->dom_vers = YPVERS; 4661927Swollman ypbindlist->dom_alive = 0; 4671927Swollman ypbindlist->dom_lockfd = -1; 4688091Swpaul ypbindlist->dom_default = 1; 4698425Swpaul domains++; 4701927Swollman 4718425Swpaul signal(SIGCHLD, reaper); 4728425Swpaul signal(SIGTERM, terminate); 4738425Swpaul 47421581Swpaul ppid = getpid(); /* Remember who we are. */ 47521581Swpaul 4768246Swpaul openlog(argv[0], LOG_PID, LOG_DAEMON); 4776478Swpaul 4788425Swpaul /* Kick off the default domain */ 4798425Swpaul broadcast(ypbindlist); 4808425Swpaul 4811927Swollman while(1) { 4821927Swollman fdsr = svc_fdset; 4838091Swpaul 4848425Swpaul tv.tv_sec = 60; 4851927Swollman tv.tv_usec = 0; 4861927Swollman 4878091Swpaul switch(select(_rpc_dtablesize(), &fdsr, NULL, NULL, &tv)) { 4881927Swollman case 0: 4891927Swollman checkwork(); 4901927Swollman break; 4911927Swollman case -1: 4928755Swpaul if (errno != EINTR) 49321539Swpaul syslog(LOG_WARNING, "select: %m"); 4948755Swpaul break; 4951927Swollman default: 4968755Swpaul for(ypdb=ypbindlist; ypdb; ypdb=ypdb->dom_pnext) { 4978755Swpaul if (READFD > 0 && FD_ISSET(READFD, &fdsr)) { 4988853Swpaul handle_children(ypdb); 4998755Swpaul if (children == (MAX_CHILDREN - 1)) 5008755Swpaul checkwork(); 5018091Swpaul } 5021927Swollman } 5031927Swollman svc_getreqset(&fdsr); 5041927Swollman break; 5051927Swollman } 5061927Swollman } 50721581Swpaul 50821581Swpaul /* NOTREACHED */ 50921581Swpaul exit(1); 5101927Swollman} 5111927Swollman 5128091Swpaulvoid 5131927Swollmancheckwork() 5141927Swollman{ 5151927Swollman struct _dom_binding *ypdb; 5161927Swollman 5178425Swpaul for(ypdb=ypbindlist; ypdb; ypdb=ypdb->dom_pnext) 5188425Swpaul ping(ypdb); 5191927Swollman} 5201927Swollman 5218091Swpaul/* The clnt_broadcast() callback mechanism sucks. */ 5228091Swpaul 5238091Swpaul/* 5248091Swpaul * Receive results from broadcaster. Don't worry about passing 5258853Swpaul * bogus info to rpc_received() -- it can handle it. Note that we 5268853Swpaul * must be sure to invalidate the dom_pipe_fds descriptors here: 5278853Swpaul * since descriptors can be re-used, we have to make sure we 5288853Swpaul * don't mistake one of the RPC descriptors for one of the pipes. 5298853Swpaul * What's weird is that forgetting to invalidate the pipe descriptors 5308853Swpaul * doesn't always result in an error (otherwise I would have caught 5318853Swpaul * the mistake much sooner), even though logically it should. 5328091Swpaul */ 5338853Swpaulvoid handle_children(ypdb) 5348853Swpaulstruct _dom_binding *ypdb; 5358091Swpaul{ 5368091Swpaul char buf[YPMAXDOMAIN + 1]; 5378091Swpaul struct sockaddr_in addr; 53821539Swpaul int d = 0, a = 0; 53921539Swpaul struct _dom_binding *y, *prev = NULL; 54021539Swpaul char path[MAXPATHLEN]; 5418091Swpaul 54221539Swpaul if ((d = read(READFD, &buf, sizeof(buf))) <= 0) 54321539Swpaul syslog(LOG_WARNING, "could not read from child: %m"); 5448755Swpaul 54521539Swpaul if ((a = read(READFD, &addr, sizeof(struct sockaddr_in))) < 0) 54621539Swpaul syslog(LOG_WARNING, "could not read from child: %m"); 54721539Swpaul 5488853Swpaul close(READFD); 5498853Swpaul FD_CLR(READFD, &fdsr); 5508853Swpaul FD_CLR(READFD, &svc_fdset); 5518853Swpaul READFD = WRITEFD = -1; 55221539Swpaul if (d > 0 && a > 0) 55321539Swpaul rpc_received((char *)&buf, &addr, 0); 55421539Swpaul else { 55521539Swpaul for(y=ypbindlist; y; y=y->dom_pnext) { 55621539Swpaul if (y == ypdb) 55721539Swpaul break; 55821539Swpaul prev = y; 55921539Swpaul } 56021539Swpaul switch(ypdb->dom_default) { 56121539Swpaul case 0: 56221539Swpaul if (prev == NULL) 56321539Swpaul ypbindlist = y->dom_pnext; 56421539Swpaul else 56521539Swpaul prev->dom_pnext = y->dom_pnext; 56621539Swpaul sprintf(path, "%s/%s.%ld", BINDINGDIR, 56721539Swpaul ypdb->dom_domain, YPVERS); 56821539Swpaul close(ypdb->dom_lockfd); 56921539Swpaul unlink(path); 57021539Swpaul free(ypdb); 57121539Swpaul domains--; 57221539Swpaul return; 57321539Swpaul case 1: 57421539Swpaul ypdb->dom_broadcast_pid = 0; 57521539Swpaul ypdb->dom_alive = 0; 57621539Swpaul broadcast(ypdb); 57721539Swpaul return; 57821539Swpaul default: 57921539Swpaul break; 58021539Swpaul } 58121539Swpaul } 58221539Swpaul 58321539Swpaul return; 5848091Swpaul} 5858091Swpaul 5868091Swpaul/* 5878091Swpaul * Send our dying words back to our parent before we perish. 5888091Swpaul */ 5898091Swpaulint 5908091Swpaultell_parent(dom, addr) 5911927Swollmanchar *dom; 5928091Swpaulstruct sockaddr_in *addr; 5931927Swollman{ 5948091Swpaul char buf[YPMAXDOMAIN + 1]; 5958091Swpaul struct timeval timeout; 5968091Swpaul fd_set fds; 5971927Swollman 5988091Swpaul timeout.tv_sec = 5; 5998091Swpaul timeout.tv_usec = 0; 6001927Swollman 6018755Swpaul sprintf(buf, "%s", broad_domain->dom_domain); 6028755Swpaul if (write(BROADFD, &buf, sizeof(buf)) < 0) 6038091Swpaul return(1); 6041927Swollman 6058091Swpaul /* 6068091Swpaul * Stay in sync with parent: wait for it to read our first 6078091Swpaul * message before sending the second. 6088091Swpaul */ 6091927Swollman 6108091Swpaul FD_ZERO(&fds); 6118755Swpaul FD_SET(BROADFD, &fds); 6128091Swpaul if (select(FD_SETSIZE, NULL, &fds, NULL, &timeout) == -1) 6138091Swpaul return(1); 6148755Swpaul if (FD_ISSET(BROADFD, &fds)) { 6158755Swpaul if (write(BROADFD, addr, sizeof(struct sockaddr_in)) < 0) 6168091Swpaul return(1); 6178091Swpaul } else { 6188091Swpaul return(1); 6191927Swollman } 6201927Swollman 6218755Swpaul close(BROADFD); 6228091Swpaul return (0); 6238091Swpaul} 6241927Swollman 6258091Swpaulbool_t broadcast_result(out, addr) 6268091Swpaulbool_t *out; 6278091Swpaulstruct sockaddr_in *addr; 6288091Swpaul{ 6299600Swpaul if (retries >= MAX_RETRIES) { 6309600Swpaul bzero((char *)addr, sizeof(struct sockaddr_in)); 6319600Swpaul if (tell_parent(broad_domain->dom_domain, addr)) 6329600Swpaul syslog(LOG_WARNING, "lost connection to parent"); 6339600Swpaul return TRUE; 6349600Swpaul } 6359600Swpaul 6369600Swpaul if (yp_restricted && verify(addr->sin_addr)) { 6379600Swpaul retries++; 6389600Swpaul syslog(LOG_NOTICE, "NIS server at %s not in restricted mode access list -- rejecting.\n",inet_ntoa(addr->sin_addr)); 6399600Swpaul return FALSE; 6409600Swpaul } else { 6419600Swpaul if (tell_parent(broad_domain->dom_domain, addr)) 6429600Swpaul syslog(LOG_WARNING, "lost connection to parent"); 6439600Swpaul return TRUE; 6449600Swpaul } 6458091Swpaul} 6468091Swpaul 6478091Swpaul/* 6488091Swpaul * The right way to send RPC broadcasts. 6498091Swpaul * Use the clnt_broadcast() RPC service. Unfortunately, clnt_broadcast() 65072091Sasmodai * blocks while waiting for replies, so we have to fork off separate 6518091Swpaul * broadcaster processes that do the waiting and then transmit their 6528091Swpaul * results back to the parent for processing. We also have to remember 6538091Swpaul * to save the name of the domain we're trying to bind in a global 6548091Swpaul * variable since clnt_broadcast() provides no way to pass things to 6558091Swpaul * the 'eachresult' callback function. 6568091Swpaul */ 6578091Swpaulvoid 6588091Swpaulbroadcast(ypdb) 6598091Swpaulstruct _dom_binding *ypdb; 6608091Swpaul{ 6618091Swpaul bool_t out = FALSE; 6628091Swpaul enum clnt_stat stat; 6638091Swpaul 6648755Swpaul if (children >= MAX_CHILDREN || ypdb->dom_broadcast_pid) 6658091Swpaul return; 6668091Swpaul 6678755Swpaul if (pipe(ypdb->dom_pipe_fds) < 0) { 66821539Swpaul syslog(LOG_WARNING, "pipe: %m"); 6698091Swpaul return; 6701927Swollman } 6711927Swollman 67230762Scharnier if (ypdb->dom_vers == -1 && (long)ypdb->dom_server_addr.sin_addr.s_addr) 6738755Swpaul syslog(LOG_WARNING, "NIS server [%s] for domain \"%s\" not responding", 6748425Swpaul inet_ntoa(ypdb->dom_server_addr.sin_addr), ypdb->dom_domain); 6758425Swpaul 6768755Swpaul broad_domain = ypdb; 6778425Swpaul flock(ypdb->dom_lockfd, LOCK_UN); 6788425Swpaul 6798755Swpaul switch((ypdb->dom_broadcast_pid = fork())) { 6808091Swpaul case 0: 6818755Swpaul close(READFD); 68221539Swpaul signal(SIGCHLD, SIG_DFL); 68321539Swpaul signal(SIGTERM, SIG_DFL); 6848091Swpaul break; 6858091Swpaul case -1: 68621539Swpaul syslog(LOG_WARNING, "fork: %m"); 6878755Swpaul close(READFD); 6888755Swpaul close(WRITEFD); 6898091Swpaul return; 6908091Swpaul default: 6918755Swpaul close(WRITEFD); 6928755Swpaul FD_SET(READFD, &svc_fdset); 6938091Swpaul children++; 6948091Swpaul return; 6951927Swollman } 6966478Swpaul 6978755Swpaul /* Release all locks before doing anything else. */ 6988755Swpaul while(ypbindlist) { 6998755Swpaul close(ypbindlist->dom_lockfd); 7008755Swpaul ypbindlist = ypbindlist->dom_pnext; 7018755Swpaul } 7028755Swpaul close(yplockfd); 7038755Swpaul 70426135Swpaul /* 70526135Swpaul * Special 'many-cast' behavior. If we're in restricted mode, 70626135Swpaul * we have a list of possible server addresses to try. What 70726135Swpaul * we can do is transmit to each ypserv's YPPROC_DOMAIN_NONACK 70826135Swpaul * procedure and time the replies. Whoever replies fastest 70926135Swpaul * gets to be our server. Note that this is not a broadcast 71026135Swpaul * operation: we transmit uni-cast datagrams only. 71126135Swpaul */ 71226135Swpaul if (yp_restricted && yp_manycast) { 71326135Swpaul short port; 71426135Swpaul int i; 71526135Swpaul struct sockaddr_in sin; 71626135Swpaul 71726135Swpaul i = __yp_ping(restricted_addrs, yp_restricted, 71826135Swpaul ypdb->dom_domain, &port); 71926135Swpaul if (i == -1) { 72026135Swpaul bzero((char *)&ypdb->dom_server_addr, 72126135Swpaul sizeof(struct sockaddr_in)); 72226135Swpaul if (tell_parent(ypdb->dom_domain, 72326135Swpaul &ypdb->dom_server_addr)) 72426135Swpaul syslog(LOG_WARNING, "lost connection to parent"); 72526135Swpaul } else { 72626135Swpaul bzero((char *)&sin, sizeof(struct sockaddr_in)); 72726135Swpaul bcopy((char *)&restricted_addrs[i], 72826135Swpaul (char *)&sin.sin_addr, sizeof(struct in_addr)); 72926135Swpaul sin.sin_family = AF_INET; 73026135Swpaul sin.sin_port = port; 73126135Swpaul if (tell_parent(broad_domain->dom_domain, &sin)) 73226135Swpaul syslog(LOG_WARNING, 73326135Swpaul "lost connection to parent"); 73426135Swpaul } 73526135Swpaul _exit(0); 73626135Swpaul } 73726135Swpaul 7389600Swpaul retries = 0; 7399600Swpaul 74012862Swpaul { 74112862Swpaul char *ptr; 7428091Swpaul 74312862Swpaul ptr = (char *)&ypdb->dom_domain; 74412862Swpaul stat = clnt_broadcast(YPPROG, YPVERS, YPPROC_DOMAIN_NONACK, 74512862Swpaul xdr_domainname, (char *)&ptr, xdr_bool, (char *)&out, 74674462Salfred (resultproc_t)broadcast_result); 74712862Swpaul } 74812862Swpaul 7498091Swpaul if (stat != RPC_SUCCESS) { 7508091Swpaul bzero((char *)&ypdb->dom_server_addr, 7518091Swpaul sizeof(struct sockaddr_in)); 7528755Swpaul if (tell_parent(ypdb->dom_domain, &ypdb->dom_server_addr)) 7538091Swpaul syslog(LOG_WARNING, "lost connection to parent"); 7548091Swpaul } 7558755Swpaul 75626135Swpaul _exit(0); 7571927Swollman} 7581927Swollman 7598091Swpaul/* 7608091Swpaul * The right way to check if a server is alive. 7618091Swpaul * Attempt to get a client handle pointing to the server and send a 7628755Swpaul * YPPROC_DOMAIN. If we can't get a handle or we get a reply of FALSE, 7638755Swpaul * we invalidate this binding entry and send out a broadcast to try to 7648755Swpaul * establish a new binding. Note that we treat non-default domains 7658091Swpaul * specially: once bound, we keep tabs on our server, but if it 7668091Swpaul * goes away and fails to respond after one round of broadcasting, we 7678091Swpaul * abandon it until a client specifically references it again. We make 7688091Swpaul * every effort to keep our default domain bound, however, since we 7698091Swpaul * need it to keep the system on its feet. 7708091Swpaul */ 7718091Swpaulint 7728425Swpaulping(ypdb) 7738091Swpaulstruct _dom_binding *ypdb; 7741927Swollman{ 7758091Swpaul bool_t out; 7768091Swpaul struct timeval interval, timeout; 7778091Swpaul enum clnt_stat stat; 7788091Swpaul int rpcsock = RPC_ANYSOCK; 7798755Swpaul CLIENT *client_handle; 7801927Swollman 7818755Swpaul interval.tv_sec = FAIL_THRESHOLD; 7828091Swpaul interval.tv_usec = 0; 7838091Swpaul timeout.tv_sec = FAIL_THRESHOLD; 7848091Swpaul timeout.tv_usec = 0; 7851927Swollman 7868755Swpaul if (ypdb->dom_broadcast_pid) 7878091Swpaul return(1); 7888091Swpaul 7898755Swpaul if ((client_handle = clntudp_bufcreate(&ypdb->dom_server_addr, 7908755Swpaul YPPROG, YPVERS, interval, &rpcsock, RPCSMALLMSGSIZE, 7918755Swpaul RPCSMALLMSGSIZE)) == (CLIENT *)NULL) { 7928755Swpaul /* Can't get a handle: we're dead. */ 7938755Swpaul ypdb->dom_alive = 0; 7948755Swpaul ypdb->dom_vers = -1; 7958755Swpaul broadcast(ypdb); 7968755Swpaul return(1); 7971927Swollman } 7981927Swollman 79912862Swpaul { 80012862Swpaul char *ptr; 80112862Swpaul 80212862Swpaul ptr = (char *)&ypdb->dom_domain; 80312862Swpaul 80412862Swpaul if ((stat = clnt_call(client_handle, YPPROC_DOMAIN, 80512862Swpaul xdr_domainname, (char *)&ptr, xdr_bool, (char *)&out, 80612862Swpaul timeout)) != RPC_SUCCESS || out == FALSE) { 80712862Swpaul ypdb->dom_alive = 0; 80812862Swpaul ypdb->dom_vers = -1; 80912862Swpaul clnt_destroy(client_handle); 81012862Swpaul broadcast(ypdb); 81112862Swpaul return(1); 81212862Swpaul } 8138091Swpaul } 8141927Swollman 8158755Swpaul clnt_destroy(client_handle); 8168091Swpaul return(0); 8171927Swollman} 8181927Swollman 8198091Swpaulvoid rpc_received(dom, raddrp, force) 8201927Swollmanchar *dom; 8211927Swollmanstruct sockaddr_in *raddrp; 8221927Swollmanint force; 8231927Swollman{ 8248425Swpaul struct _dom_binding *ypdb, *prev = NULL; 8251927Swollman struct iovec iov[2]; 8261927Swollman struct ypbind_resp ybr; 8271927Swollman char path[MAXPATHLEN]; 8281927Swollman int fd; 8291927Swollman 8306732Swpaul /*printf("returned from %s/%d about %s\n", inet_ntoa(raddrp->sin_addr), 8316732Swpaul ntohs(raddrp->sin_port), dom);*/ 8321927Swollman 8331927Swollman if(dom==NULL) 8341927Swollman return; 8351927Swollman 8368425Swpaul for(ypdb=ypbindlist; ypdb; ypdb=ypdb->dom_pnext) { 8378091Swpaul if( strcmp(ypdb->dom_domain, dom) == 0) 8388091Swpaul break; 8398425Swpaul prev = ypdb; 8408425Swpaul } 8418091Swpaul 8428755Swpaul if (ypdb && force) { 8438755Swpaul if (ypdb->dom_broadcast_pid) { 8448755Swpaul kill(ypdb->dom_broadcast_pid, SIGINT); 8458755Swpaul close(READFD); 8468853Swpaul FD_CLR(READFD, &fdsr); 8478853Swpaul FD_CLR(READFD, &svc_fdset); 8488853Swpaul READFD = WRITEFD = -1; 8498755Swpaul } 8508755Swpaul } 8518755Swpaul 8529600Swpaul /* if in secure mode, check originating port number */ 8539600Swpaul if ((ypsecuremode && (ntohs(raddrp->sin_port) >= IPPORT_RESERVED))) { 8546732Swpaul syslog(LOG_WARNING, "Rejected NIS server on [%s/%d] for domain %s.", 8556732Swpaul inet_ntoa(raddrp->sin_addr), ntohs(raddrp->sin_port), 8566732Swpaul dom); 8578246Swpaul if (ypdb != NULL) { 8588755Swpaul ypdb->dom_broadcast_pid = 0; 8598246Swpaul ypdb->dom_alive = 0; 8608246Swpaul } 8616732Swpaul return; 8626732Swpaul } 8636732Swpaul 8648246Swpaul if (raddrp->sin_addr.s_addr == (long)0) { 8658755Swpaul switch(ypdb->dom_default) { 8668755Swpaul case 0: 8678755Swpaul if (prev == NULL) 8688755Swpaul ypbindlist = ypdb->dom_pnext; 8698755Swpaul else 8708755Swpaul prev->dom_pnext = ypdb->dom_pnext; 8718755Swpaul sprintf(path, "%s/%s.%ld", BINDINGDIR, 8728755Swpaul ypdb->dom_domain, YPVERS); 8738755Swpaul close(ypdb->dom_lockfd); 8748755Swpaul unlink(path); 8758755Swpaul free(ypdb); 8768755Swpaul domains--; 8778755Swpaul return; 8788755Swpaul case 1: 8798755Swpaul ypdb->dom_broadcast_pid = 0; 8808755Swpaul ypdb->dom_alive = 0; 8818755Swpaul broadcast(ypdb); 8828755Swpaul return; 8838755Swpaul default: 8848755Swpaul break; 8858755Swpaul } 8868246Swpaul } 8878246Swpaul 8881927Swollman if(ypdb==NULL) { 8898246Swpaul if (force == 0) 8901927Swollman return; 8911927Swollman ypdb = (struct _dom_binding *)malloc(sizeof *ypdb); 8928857Srgrimes if (ypdb == NULL) { 89321539Swpaul syslog(LOG_WARNING, "malloc: %m"); 8948246Swpaul return; 8958246Swpaul } 8961927Swollman bzero((char *)ypdb, sizeof *ypdb); 8971927Swollman strncpy(ypdb->dom_domain, dom, sizeof ypdb->dom_domain); 8981927Swollman ypdb->dom_lockfd = -1; 8998091Swpaul ypdb->dom_default = 0; 9001927Swollman ypdb->dom_pnext = ypbindlist; 9011927Swollman ypbindlist = ypdb; 9021927Swollman } 9031927Swollman 9048091Swpaul /* We've recovered from a crash: inform the world. */ 90530762Scharnier if (ypdb->dom_vers == -1 && ypdb->dom_server_addr.sin_addr.s_addr) 9068755Swpaul syslog(LOG_WARNING, "NIS server [%s] for domain \"%s\" OK", 9078755Swpaul inet_ntoa(raddrp->sin_addr), ypdb->dom_domain); 9086478Swpaul 9091927Swollman bcopy((char *)raddrp, (char *)&ypdb->dom_server_addr, 9101927Swollman sizeof ypdb->dom_server_addr); 9116478Swpaul 9121927Swollman ypdb->dom_vers = YPVERS; 9131927Swollman ypdb->dom_alive = 1; 9148755Swpaul ypdb->dom_broadcast_pid = 0; 9151927Swollman 9161927Swollman if(ypdb->dom_lockfd != -1) 9171927Swollman close(ypdb->dom_lockfd); 9181927Swollman 9198091Swpaul sprintf(path, "%s/%s.%ld", BINDINGDIR, 9201927Swollman ypdb->dom_domain, ypdb->dom_vers); 9211927Swollman#ifdef O_SHLOCK 9227864Swpaul if( (fd=open(path, O_CREAT|O_SHLOCK|O_RDWR|O_TRUNC, 0644)) == -1) { 9231927Swollman (void)mkdir(BINDINGDIR, 0755); 9247864Swpaul if( (fd=open(path, O_CREAT|O_SHLOCK|O_RDWR|O_TRUNC, 0644)) == -1) 9251927Swollman return; 9261927Swollman } 9271927Swollman#else 9287864Swpaul if( (fd=open(path, O_CREAT|O_RDWR|O_TRUNC, 0644)) == -1) { 9291927Swollman (void)mkdir(BINDINGDIR, 0755); 9307864Swpaul if( (fd=open(path, O_CREAT|O_RDWR|O_TRUNC, 0644)) == -1) 9311927Swollman return; 9321927Swollman } 9331927Swollman flock(fd, LOCK_SH); 9341927Swollman#endif 9351927Swollman 9361927Swollman /* 9371927Swollman * ok, if BINDINGDIR exists, and we can create the binding file, 9381927Swollman * then write to it.. 9391927Swollman */ 9401927Swollman ypdb->dom_lockfd = fd; 9411927Swollman 9421927Swollman iov[0].iov_base = (caddr_t)&(udptransp->xp_port); 9431927Swollman iov[0].iov_len = sizeof udptransp->xp_port; 9441927Swollman iov[1].iov_base = (caddr_t)&ybr; 9451927Swollman iov[1].iov_len = sizeof ybr; 9461927Swollman 9471927Swollman bzero(&ybr, sizeof ybr); 9481927Swollman ybr.ypbind_status = YPBIND_SUCC_VAL; 94945656Ssimokawa *(u_int32_t *)&ybr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_addr = raddrp->sin_addr.s_addr; 95012862Swpaul *(u_short *)&ybr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_port = raddrp->sin_port; 9511927Swollman 9521927Swollman if( writev(ypdb->dom_lockfd, iov, 2) != iov[0].iov_len + iov[1].iov_len) { 95321539Swpaul syslog(LOG_WARNING, "write: %m"); 9541927Swollman close(ypdb->dom_lockfd); 9551927Swollman ypdb->dom_lockfd = -1; 9561927Swollman return; 9571927Swollman } 9581927Swollman} 9599600Swpaul 9609600Swpaul/* 9619600Swpaul * Check address against list of allowed servers. Return 0 if okay, 9629600Swpaul * 1 if not matched. 9639600Swpaul */ 9649600Swpaulint 9659600Swpaulverify(addr) 9669600Swpaulstruct in_addr addr; 9679600Swpaul{ 9689600Swpaul int i; 9699600Swpaul 9709600Swpaul for (i = 0; i < RESTRICTED_SERVERS; i++) 9719600Swpaul if (!bcmp((char *)&addr, (char *)&restricted_addrs[i], 9729600Swpaul sizeof(struct in_addr))) 9739600Swpaul return(0); 9749600Swpaul 9759600Swpaul return(1); 9769600Swpaul} 9779600Swpaul 9789600Swpaul/* 9799600Swpaul * Try to set restricted mode. We default to normal mode if we can't 9809600Swpaul * resolve the specified hostnames. 9819600Swpaul */ 9829600Swpaulvoid 9839600Swpaulyp_restricted_mode(args) 9849600Swpaulchar *args; 9859600Swpaul{ 9869600Swpaul struct hostent *h; 9879600Swpaul int i = 0; 9889600Swpaul char *s; 9899600Swpaul 9909600Swpaul /* Find the restricted domain. */ 9919600Swpaul if ((s = strsep(&args, ",")) == NULL) 9929600Swpaul return; 99312862Swpaul domain_name = s; 9949600Swpaul 9959600Swpaul /* Get the addresses of the servers. */ 9969600Swpaul while ((s = strsep(&args, ",")) != NULL && i < RESTRICTED_SERVERS) { 9979600Swpaul if ((h = gethostbyname(s)) == NULL) 9989600Swpaul return; 9999600Swpaul bcopy ((char *)h->h_addr_list[0], (char *)&restricted_addrs[i], 10009600Swpaul sizeof(struct in_addr)); 10019600Swpaul i++; 10029600Swpaul } 10039600Swpaul 10049600Swpaul /* ypset and ypsetme not allowed with restricted mode */ 10059600Swpaul ypsetmode = YPSET_NO; 10069600Swpaul 100726135Swpaul yp_restricted = i; 10089600Swpaul return; 10099600Swpaul} 1010