18fae3551SRodney W. Grimes /* 28fae3551SRodney W. Grimes * Copyright (c) 1989, 1993, 1994 38fae3551SRodney W. Grimes * The Regents of the University of California. All rights reserved. 48fae3551SRodney W. Grimes * 58fae3551SRodney W. Grimes * This code is derived from software contributed to Berkeley by 68fae3551SRodney W. Grimes * Rick Macklem at The University of Guelph. 78fae3551SRodney W. Grimes * 88fae3551SRodney W. Grimes * Redistribution and use in source and binary forms, with or without 98fae3551SRodney W. Grimes * modification, are permitted provided that the following conditions 108fae3551SRodney W. Grimes * are met: 118fae3551SRodney W. Grimes * 1. Redistributions of source code must retain the above copyright 128fae3551SRodney W. Grimes * notice, this list of conditions and the following disclaimer. 138fae3551SRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright 148fae3551SRodney W. Grimes * notice, this list of conditions and the following disclaimer in the 158fae3551SRodney W. Grimes * documentation and/or other materials provided with the distribution. 168fae3551SRodney W. Grimes * 3. All advertising materials mentioning features or use of this software 178fae3551SRodney W. Grimes * must display the following acknowledgement: 188fae3551SRodney W. Grimes * This product includes software developed by the University of 198fae3551SRodney W. Grimes * California, Berkeley and its contributors. 208fae3551SRodney W. Grimes * 4. Neither the name of the University nor the names of its contributors 218fae3551SRodney W. Grimes * may be used to endorse or promote products derived from this software 228fae3551SRodney W. Grimes * without specific prior written permission. 238fae3551SRodney W. Grimes * 248fae3551SRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 258fae3551SRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 268fae3551SRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 278fae3551SRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 288fae3551SRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 298fae3551SRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 308fae3551SRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 318fae3551SRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 328fae3551SRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 338fae3551SRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 348fae3551SRodney W. Grimes * SUCH DAMAGE. 358fae3551SRodney W. Grimes */ 368fae3551SRodney W. Grimes 378fae3551SRodney W. Grimes #ifndef lint 389b4d716bSPhilippe Charnier static const char copyright[] = 398fae3551SRodney W. Grimes "@(#) Copyright (c) 1989, 1993, 1994\n\ 408fae3551SRodney W. Grimes The Regents of the University of California. All rights reserved.\n"; 418fae3551SRodney W. Grimes #endif not lint 428fae3551SRodney W. Grimes 438fae3551SRodney W. Grimes #ifndef lint 449b4d716bSPhilippe Charnier #if 0 4508966bd5SPeter Wemm static char sccsid[] = "@(#)nfsd.c 8.9 (Berkeley) 3/29/95"; 469b4d716bSPhilippe Charnier #endif 479b4d716bSPhilippe Charnier static const char rcsid[] = 487f3dea24SPeter Wemm "$FreeBSD$"; 498fae3551SRodney W. Grimes #endif not lint 508fae3551SRodney W. Grimes 518fae3551SRodney W. Grimes #include <sys/param.h> 528fae3551SRodney W. Grimes #include <sys/syslog.h> 538fae3551SRodney W. Grimes #include <sys/wait.h> 548fae3551SRodney W. Grimes #include <sys/mount.h> 558fae3551SRodney W. Grimes 568fae3551SRodney W. Grimes #include <rpc/rpc.h> 578fae3551SRodney W. Grimes #include <rpc/pmap_clnt.h> 588fae3551SRodney W. Grimes 5992fc2acfSMatthew Dillon #include <netdb.h> 6092fc2acfSMatthew Dillon #include <arpa/inet.h> 618fae3551SRodney W. Grimes #include <nfs/rpcv2.h> 62a62dc406SDoug Rabson #include <nfs/nfsproto.h> 638fae3551SRodney W. Grimes #include <nfs/nfs.h> 648fae3551SRodney W. Grimes 65a62dc406SDoug Rabson #ifdef NFSKERB 6608966bd5SPeter Wemm #include <kerberosIV/des.h> 678fae3551SRodney W. Grimes #include <kerberosIV/krb.h> 688fae3551SRodney W. Grimes #endif 698fae3551SRodney W. Grimes 708fae3551SRodney W. Grimes #include <err.h> 718fae3551SRodney W. Grimes #include <errno.h> 728fae3551SRodney W. Grimes #include <stdio.h> 738fae3551SRodney W. Grimes #include <stdlib.h> 748fae3551SRodney W. Grimes #include <strings.h> 758fae3551SRodney W. Grimes #include <unistd.h> 768360efbdSAlfred Perlstein #include <netdb.h> 778fae3551SRodney W. Grimes 788fae3551SRodney W. Grimes /* Global defs */ 798fae3551SRodney W. Grimes #ifdef DEBUG 808fae3551SRodney W. Grimes #define syslog(e, s) fprintf(stderr,(s)) 818fae3551SRodney W. Grimes int debug = 1; 828fae3551SRodney W. Grimes #else 838fae3551SRodney W. Grimes int debug = 0; 848fae3551SRodney W. Grimes #endif 858fae3551SRodney W. Grimes 868fae3551SRodney W. Grimes struct nfsd_srvargs nsd; 87c129841aSPeter Wemm #ifdef OLD_SETPROCTITLE 888fae3551SRodney W. Grimes char **Argv = NULL; /* pointer to argument vector */ 898fae3551SRodney W. Grimes char *LastArg = NULL; /* end of argv */ 90c129841aSPeter Wemm #endif 918fae3551SRodney W. Grimes 92a62dc406SDoug Rabson #ifdef NFSKERB 938fae3551SRodney W. Grimes char lnam[ANAME_SZ]; 948fae3551SRodney W. Grimes KTEXT_ST kt; 95a62dc406SDoug Rabson AUTH_DAT kauth; 968fae3551SRodney W. Grimes char inst[INST_SZ]; 97a62dc406SDoug Rabson struct nfsrpc_fullblock kin, kout; 98a62dc406SDoug Rabson struct nfsrpc_fullverf kverf; 99a62dc406SDoug Rabson NFSKERBKEY_T kivec; 100a62dc406SDoug Rabson struct timeval ktv; 101a62dc406SDoug Rabson NFSKERBKEYSCHED_T kerb_keysched; 1028fae3551SRodney W. Grimes #endif 1038fae3551SRodney W. Grimes 1048360efbdSAlfred Perlstein #define MAXNFSDCNT 20 1058360efbdSAlfred Perlstein #define DEFNFSDCNT 4 1068360efbdSAlfred Perlstein pid_t children[MAXNFSDCNT]; /* PIDs of children */ 1078360efbdSAlfred Perlstein int nfsdcnt; /* number of children */ 1088360efbdSAlfred Perlstein 1098360efbdSAlfred Perlstein void cleanup(int); 1108360efbdSAlfred Perlstein void killchildren(void); 1118360efbdSAlfred Perlstein void nonfs (int); 1128360efbdSAlfred Perlstein void reapchild (int); 1138360efbdSAlfred Perlstein int setbindhost (struct addrinfo **ia, const char *bindhost, struct addrinfo hints); 114c129841aSPeter Wemm #ifdef OLD_SETPROCTITLE 115a62dc406SDoug Rabson #ifdef __FreeBSD__ 1168360efbdSAlfred Perlstein void setproctitle (char *); 117a62dc406SDoug Rabson #endif 118c129841aSPeter Wemm #endif 1198360efbdSAlfred Perlstein void unregistration (void); 1208360efbdSAlfred Perlstein void usage (void); 1218fae3551SRodney W. Grimes 1228fae3551SRodney W. Grimes /* 1238fae3551SRodney W. Grimes * Nfs server daemon mostly just a user context for nfssvc() 1248fae3551SRodney W. Grimes * 1258fae3551SRodney W. Grimes * 1 - do file descriptor and signal cleanup 1268fae3551SRodney W. Grimes * 2 - fork the nfsd(s) 1278fae3551SRodney W. Grimes * 3 - create server socket(s) 1288360efbdSAlfred Perlstein * 4 - register socket with rpcbind 1298fae3551SRodney W. Grimes * 1308fae3551SRodney W. Grimes * For connectionless protocols, just pass the socket into the kernel via. 1318fae3551SRodney W. Grimes * nfssvc(). 1328fae3551SRodney W. Grimes * For connection based sockets, loop doing accepts. When you get a new 1338fae3551SRodney W. Grimes * socket from accept, pass the msgsock into the kernel via. nfssvc(). 1348fae3551SRodney W. Grimes * The arguments are: 1358fae3551SRodney W. Grimes * -c - support iso cltp clients 1368360efbdSAlfred Perlstein * -r - reregister with rpcbind 1378360efbdSAlfred Perlstein * -d - unregister with rpcbind 1388fae3551SRodney W. Grimes * -t - support tcp nfs clients 1398fae3551SRodney W. Grimes * -u - support udp nfs clients 1408fae3551SRodney W. Grimes * followed by "n" which is the number of nfsds' to fork off 1418fae3551SRodney W. Grimes */ 1428fae3551SRodney W. Grimes int 1438fae3551SRodney W. Grimes main(argc, argv, envp) 1448fae3551SRodney W. Grimes int argc; 1458fae3551SRodney W. Grimes char *argv[], *envp[]; 1468fae3551SRodney W. Grimes { 1478fae3551SRodney W. Grimes struct nfsd_args nfsdargs; 1488360efbdSAlfred Perlstein struct addrinfo *ai_udp, *ai_tcp, *ai_udp6, *ai_tcp6, hints; 1498360efbdSAlfred Perlstein struct netconfig *nconf_udp, *nconf_tcp, *nconf_udp6, *nconf_tcp6; 1508360efbdSAlfred Perlstein struct netbuf nb_udp, nb_tcp, nb_udp6, nb_tcp6; 1518360efbdSAlfred Perlstein struct sockaddr_in inetpeer; 1528360efbdSAlfred Perlstein struct sockaddr_in6 inet6peer; 1538fae3551SRodney W. Grimes fd_set ready, sockbits; 1548360efbdSAlfred Perlstein fd_set v4bits, v6bits; 1558fae3551SRodney W. Grimes int ch, cltpflag, connect_type_cnt, i, len, maxsock, msgsock; 1568360efbdSAlfred Perlstein int nfssvc_flag, on = 1, unregister, reregister, sock; 1578360efbdSAlfred Perlstein int tcp6sock, ip6flag, tcpflag, tcpsock; 1588360efbdSAlfred Perlstein int udpflag, ecode, s; 1598360efbdSAlfred Perlstein int bindhostc = 0, bindanyflag, rpcbreg, rpcbregcnt; 16092fc2acfSMatthew Dillon char **bindhost = NULL; 1618360efbdSAlfred Perlstein pid_t pid; 1629b4d716bSPhilippe Charnier #ifdef NFSKERB 1639b4d716bSPhilippe Charnier struct group *grp; 1649b4d716bSPhilippe Charnier struct passwd *pwd; 1659b4d716bSPhilippe Charnier struct ucred *cr; 1669b4d716bSPhilippe Charnier struct timeval ktv; 1679b4d716bSPhilippe Charnier char **cpp; 1689b4d716bSPhilippe Charnier #endif 169a62dc406SDoug Rabson #ifdef __FreeBSD__ 17008966bd5SPeter Wemm struct vfsconf vfc; 17108966bd5SPeter Wemm int error; 172d599144dSGarrett Wollman 17308966bd5SPeter Wemm error = getvfsbyname("nfs", &vfc); 17408966bd5SPeter Wemm if (error && vfsisloadable("nfs")) { 175d599144dSGarrett Wollman if (vfsload("nfs")) 176d599144dSGarrett Wollman err(1, "vfsload(nfs)"); 177d599144dSGarrett Wollman endvfsent(); /* flush cache */ 17808966bd5SPeter Wemm error = getvfsbyname("nfs", &vfc); 179d599144dSGarrett Wollman } 18008966bd5SPeter Wemm if (error) 181d599144dSGarrett Wollman errx(1, "NFS is not available in the running kernel"); 182a62dc406SDoug Rabson #endif 1838fae3551SRodney W. Grimes 184c129841aSPeter Wemm #ifdef OLD_SETPROCTITLE 1858fae3551SRodney W. Grimes /* Save start and extent of argv for setproctitle. */ 1868fae3551SRodney W. Grimes Argv = argv; 1878fae3551SRodney W. Grimes if (envp == 0 || *envp == 0) 1888fae3551SRodney W. Grimes envp = argv; 1898fae3551SRodney W. Grimes while (*envp) 1908fae3551SRodney W. Grimes envp++; 1918fae3551SRodney W. Grimes LastArg = envp[-1] + strlen(envp[-1]); 192c129841aSPeter Wemm #endif 1938fae3551SRodney W. Grimes 1948fae3551SRodney W. Grimes nfsdcnt = DEFNFSDCNT; 1958360efbdSAlfred Perlstein cltpflag = unregister = reregister = tcpflag = 0; 1968360efbdSAlfred Perlstein bindanyflag = udpflag = ip6flag = 0; 1978360efbdSAlfred Perlstein #define GETOPT "ah:n:rdtu" 1988360efbdSAlfred Perlstein #define USAGE "[-ardtu] [-n num_servers] [-h bindip]" 1998d64695cSWarner Losh while ((ch = getopt(argc, argv, GETOPT)) != -1) 2008fae3551SRodney W. Grimes switch (ch) { 20192fc2acfSMatthew Dillon case 'a': 20292fc2acfSMatthew Dillon bindanyflag = 1; 20392fc2acfSMatthew Dillon break; 2048fae3551SRodney W. Grimes case 'n': 2058fae3551SRodney W. Grimes nfsdcnt = atoi(optarg); 2068fae3551SRodney W. Grimes if (nfsdcnt < 1 || nfsdcnt > MAXNFSDCNT) { 2073e83b874SJohn Polstra warnx("nfsd count %d; reset to %d", nfsdcnt, 2083e83b874SJohn Polstra DEFNFSDCNT); 2098fae3551SRodney W. Grimes nfsdcnt = DEFNFSDCNT; 2108fae3551SRodney W. Grimes } 2118fae3551SRodney W. Grimes break; 21292fc2acfSMatthew Dillon case 'h': 21392fc2acfSMatthew Dillon bindhostc++; 21492fc2acfSMatthew Dillon bindhost = realloc(bindhost,sizeof(char *)*bindhostc); 21592fc2acfSMatthew Dillon if (bindhost == NULL) 21692fc2acfSMatthew Dillon errx(1, "Out of memory"); 21792fc2acfSMatthew Dillon bindhost[bindhostc-1] = strdup(optarg); 21892fc2acfSMatthew Dillon if (bindhost[bindhostc-1] == NULL) 21992fc2acfSMatthew Dillon errx(1, "Out of memory"); 22092fc2acfSMatthew Dillon break; 2218fae3551SRodney W. Grimes case 'r': 2228fae3551SRodney W. Grimes reregister = 1; 2238fae3551SRodney W. Grimes break; 2248360efbdSAlfred Perlstein case 'd': 2258360efbdSAlfred Perlstein unregister = 1; 2268360efbdSAlfred Perlstein break; 2278fae3551SRodney W. Grimes case 't': 2288fae3551SRodney W. Grimes tcpflag = 1; 2298fae3551SRodney W. Grimes break; 2308fae3551SRodney W. Grimes case 'u': 2318fae3551SRodney W. Grimes udpflag = 1; 2328fae3551SRodney W. Grimes break; 2338fae3551SRodney W. Grimes default: 2348fae3551SRodney W. Grimes case '?': 2358fae3551SRodney W. Grimes usage(); 2368fae3551SRodney W. Grimes }; 23752efa6c1SBruce Evans if (!tcpflag && !udpflag) 23852efa6c1SBruce Evans udpflag = 1; 2398fae3551SRodney W. Grimes argv += optind; 2408fae3551SRodney W. Grimes argc -= optind; 2418fae3551SRodney W. Grimes 2428fae3551SRodney W. Grimes /* 2438fae3551SRodney W. Grimes * XXX 2448fae3551SRodney W. Grimes * Backward compatibility, trailing number is the count of daemons. 2458fae3551SRodney W. Grimes */ 2468fae3551SRodney W. Grimes if (argc > 1) 2478fae3551SRodney W. Grimes usage(); 2488fae3551SRodney W. Grimes if (argc == 1) { 2498fae3551SRodney W. Grimes nfsdcnt = atoi(argv[0]); 2508fae3551SRodney W. Grimes if (nfsdcnt < 1 || nfsdcnt > MAXNFSDCNT) { 2513e83b874SJohn Polstra warnx("nfsd count %d; reset to %d", nfsdcnt, 2523e83b874SJohn Polstra DEFNFSDCNT); 2538fae3551SRodney W. Grimes nfsdcnt = DEFNFSDCNT; 2548fae3551SRodney W. Grimes } 2558fae3551SRodney W. Grimes } 2568360efbdSAlfred Perlstein ip6flag = 1; 2578360efbdSAlfred Perlstein s = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP); 2588360efbdSAlfred Perlstein if (s < 0 && (errno == EPROTONOSUPPORT || 2598360efbdSAlfred Perlstein errno == EPFNOSUPPORT || errno == EAFNOSUPPORT)) 2608360efbdSAlfred Perlstein ip6flag = 0; 2618360efbdSAlfred Perlstein else 2628360efbdSAlfred Perlstein close(s); 2638fae3551SRodney W. Grimes 26492fc2acfSMatthew Dillon if (bindhostc == 0 || bindanyflag) { 26592fc2acfSMatthew Dillon bindhostc++; 26692fc2acfSMatthew Dillon bindhost = realloc(bindhost,sizeof(char *)*bindhostc); 26792fc2acfSMatthew Dillon if (bindhost == NULL) 26892fc2acfSMatthew Dillon errx(1, "Out of memory"); 26992fc2acfSMatthew Dillon bindhost[bindhostc-1] = strdup("*"); 27092fc2acfSMatthew Dillon if (bindhost[bindhostc-1] == NULL) 27192fc2acfSMatthew Dillon errx(1, "Out of memory"); 27292fc2acfSMatthew Dillon } 27392fc2acfSMatthew Dillon 2748fae3551SRodney W. Grimes if (debug == 0) { 2758fae3551SRodney W. Grimes daemon(0, 0); 2768fae3551SRodney W. Grimes (void)signal(SIGHUP, SIG_IGN); 2778fae3551SRodney W. Grimes (void)signal(SIGINT, SIG_IGN); 2788fae3551SRodney W. Grimes (void)signal(SIGSYS, nonfs); 2798360efbdSAlfred Perlstein (void)signal(SIGUSR1, cleanup); 2808360efbdSAlfred Perlstein /* 2818360efbdSAlfred Perlstein * nfsd sits in the kernel most of the time. It needs 2828360efbdSAlfred Perlstein * to ignore SIGTERM/SIGQUIT in order to stay alive as long 2838360efbdSAlfred Perlstein * as possible during a shutdown, otherwise loopback 2848360efbdSAlfred Perlstein * mounts will not be able to unmount. 2858360efbdSAlfred Perlstein */ 2868fae3551SRodney W. Grimes (void)signal(SIGTERM, SIG_IGN); 2878360efbdSAlfred Perlstein (void)signal(SIGQUIT, SIG_IGN); 2888fae3551SRodney W. Grimes } 2898fae3551SRodney W. Grimes (void)signal(SIGCHLD, reapchild); 2908360efbdSAlfred Perlstein if (unregister) { 2918360efbdSAlfred Perlstein unregistration(); 2928fae3551SRodney W. Grimes exit (0); 2938fae3551SRodney W. Grimes } 2948360efbdSAlfred Perlstein if (reregister) { 2958360efbdSAlfred Perlstein if (udpflag) { 2968360efbdSAlfred Perlstein memset(&hints, 0, sizeof hints); 2978360efbdSAlfred Perlstein hints.ai_flags = AI_PASSIVE; 2988360efbdSAlfred Perlstein hints.ai_family = AF_INET; 2998360efbdSAlfred Perlstein hints.ai_socktype = SOCK_DGRAM; 3008360efbdSAlfred Perlstein hints.ai_protocol = IPPROTO_UDP; 3018360efbdSAlfred Perlstein ecode = getaddrinfo(NULL, "nfs", &hints, &ai_udp); 3028360efbdSAlfred Perlstein if (ecode != 0) { 3038360efbdSAlfred Perlstein syslog(LOG_ERR, "getaddrinfo udp: %s", 3048360efbdSAlfred Perlstein gai_strerror(ecode)); 3058360efbdSAlfred Perlstein exit(1); 3068360efbdSAlfred Perlstein } 3078360efbdSAlfred Perlstein nconf_udp = getnetconfigent("udp"); 3088360efbdSAlfred Perlstein if (nconf_udp == NULL) 3098360efbdSAlfred Perlstein err(1, "getnetconfigent udp failed"); 3108360efbdSAlfred Perlstein nb_udp.buf = ai_udp->ai_addr; 3118360efbdSAlfred Perlstein nb_udp.len = nb_udp.maxlen = ai_udp->ai_addrlen; 3128360efbdSAlfred Perlstein if ((!rpcb_set(RPCPROG_NFS, 2, nconf_udp, &nb_udp)) || 3138360efbdSAlfred Perlstein (!rpcb_set(RPCPROG_NFS, 3, nconf_udp, &nb_udp))) 3148360efbdSAlfred Perlstein err(1, "rpcb_set udp failed"); 3158360efbdSAlfred Perlstein freeaddrinfo(ai_udp); 3168360efbdSAlfred Perlstein } 3178360efbdSAlfred Perlstein if (udpflag && ip6flag) { 3188360efbdSAlfred Perlstein memset(&hints, 0, sizeof hints); 3198360efbdSAlfred Perlstein hints.ai_flags = AI_PASSIVE; 3208360efbdSAlfred Perlstein hints.ai_family = AF_INET6; 3218360efbdSAlfred Perlstein hints.ai_socktype = SOCK_DGRAM; 3228360efbdSAlfred Perlstein hints.ai_protocol = IPPROTO_UDP; 3238360efbdSAlfred Perlstein ecode = getaddrinfo(NULL, "nfs", &hints, &ai_udp6); 3248360efbdSAlfred Perlstein if (ecode != 0) { 3258360efbdSAlfred Perlstein syslog(LOG_ERR, "getaddrinfo udp6: %s", 3268360efbdSAlfred Perlstein gai_strerror(ecode)); 3278360efbdSAlfred Perlstein exit(1); 3288360efbdSAlfred Perlstein } 3298360efbdSAlfred Perlstein nconf_udp6 = getnetconfigent("udp6"); 3308360efbdSAlfred Perlstein if (nconf_udp6 == NULL) 3318360efbdSAlfred Perlstein err(1, "getnetconfigent udp6 failed"); 3328360efbdSAlfred Perlstein nb_udp6.buf = ai_udp6->ai_addr; 3338360efbdSAlfred Perlstein nb_udp6.len = nb_udp6.maxlen = ai_udp6->ai_addrlen; 3348360efbdSAlfred Perlstein if ((!rpcb_set(RPCPROG_NFS, 2, nconf_udp6, &nb_udp6)) || 3358360efbdSAlfred Perlstein (!rpcb_set(RPCPROG_NFS, 3, nconf_udp6, &nb_udp6))) 3368360efbdSAlfred Perlstein err(1, "rpcb_set udp6 failed"); 3378360efbdSAlfred Perlstein freeaddrinfo(ai_udp6); 3388360efbdSAlfred Perlstein } 3398360efbdSAlfred Perlstein if (tcpflag) { 3408360efbdSAlfred Perlstein memset(&hints, 0, sizeof hints); 3418360efbdSAlfred Perlstein hints.ai_flags = AI_PASSIVE; 3428360efbdSAlfred Perlstein hints.ai_family = AF_INET; 3438360efbdSAlfred Perlstein hints.ai_socktype = SOCK_STREAM; 3448360efbdSAlfred Perlstein hints.ai_protocol = IPPROTO_TCP; 3458360efbdSAlfred Perlstein ecode = getaddrinfo(NULL, "nfs", &hints, &ai_tcp); 3468360efbdSAlfred Perlstein if (ecode != 0) { 3478360efbdSAlfred Perlstein syslog(LOG_ERR, "getaddrinfo tcp: %s", 3488360efbdSAlfred Perlstein gai_strerror(ecode)); 3498360efbdSAlfred Perlstein exit(1); 3508360efbdSAlfred Perlstein } 3518360efbdSAlfred Perlstein nconf_tcp = getnetconfigent("tcp"); 3528360efbdSAlfred Perlstein if (nconf_tcp == NULL) 3538360efbdSAlfred Perlstein err(1, "getnetconfigent tcp failed"); 3548360efbdSAlfred Perlstein nb_tcp.buf = ai_tcp->ai_addr; 3558360efbdSAlfred Perlstein nb_tcp.len = nb_tcp.maxlen = ai_tcp->ai_addrlen; 3568360efbdSAlfred Perlstein if ((!rpcb_set(RPCPROG_NFS, 2, nconf_tcp, &nb_tcp)) || 3578360efbdSAlfred Perlstein (!rpcb_set(RPCPROG_NFS, 3, nconf_tcp, &nb_tcp))) 3588360efbdSAlfred Perlstein err(1, "rpcb_set tcp failed"); 3598360efbdSAlfred Perlstein freeaddrinfo(ai_tcp); 3608360efbdSAlfred Perlstein } 3618360efbdSAlfred Perlstein if (tcpflag && ip6flag) { 3628360efbdSAlfred Perlstein memset(&hints, 0, sizeof hints); 3638360efbdSAlfred Perlstein hints.ai_flags = AI_PASSIVE; 3648360efbdSAlfred Perlstein hints.ai_family = AF_INET6; 3658360efbdSAlfred Perlstein hints.ai_socktype = SOCK_STREAM; 3668360efbdSAlfred Perlstein hints.ai_protocol = IPPROTO_TCP; 3678360efbdSAlfred Perlstein ecode = getaddrinfo(NULL, "nfs", &hints, &ai_tcp6); 3688360efbdSAlfred Perlstein if (ecode != 0) { 3698360efbdSAlfred Perlstein syslog(LOG_ERR, "getaddrinfo tcp6: %s", 3708360efbdSAlfred Perlstein gai_strerror(ecode)); 3718360efbdSAlfred Perlstein exit(1); 3728360efbdSAlfred Perlstein } 3738360efbdSAlfred Perlstein nconf_tcp6 = getnetconfigent("tcp6"); 3748360efbdSAlfred Perlstein if (nconf_tcp6 == NULL) 3758360efbdSAlfred Perlstein err(1, "getnetconfigent tcp6 failed"); 3768360efbdSAlfred Perlstein nb_tcp6.buf = ai_tcp6->ai_addr; 3778360efbdSAlfred Perlstein nb_tcp6.len = nb_tcp6.maxlen = ai_tcp6->ai_addrlen; 3788360efbdSAlfred Perlstein if ((!rpcb_set(RPCPROG_NFS, 2, nconf_tcp6, &nb_tcp6)) || 3798360efbdSAlfred Perlstein (!rpcb_set(RPCPROG_NFS, 3, nconf_tcp6, &nb_tcp6))) 3808360efbdSAlfred Perlstein err(1, "rpcb_set tcp6 failed"); 3818360efbdSAlfred Perlstein freeaddrinfo(ai_tcp6); 3828360efbdSAlfred Perlstein } 3838360efbdSAlfred Perlstein exit (0); 3848360efbdSAlfred Perlstein } 3858360efbdSAlfred Perlstein 3868fae3551SRodney W. Grimes openlog("nfsd:", LOG_PID, LOG_DAEMON); 3878fae3551SRodney W. Grimes 3888fae3551SRodney W. Grimes for (i = 0; i < nfsdcnt; i++) { 3898360efbdSAlfred Perlstein switch ((pid = fork())) { 3908fae3551SRodney W. Grimes case -1: 3918fae3551SRodney W. Grimes syslog(LOG_ERR, "fork: %m"); 3928360efbdSAlfred Perlstein killchildren(); 3938fae3551SRodney W. Grimes exit (1); 3948fae3551SRodney W. Grimes case 0: 3958fae3551SRodney W. Grimes break; 3968fae3551SRodney W. Grimes default: 3978360efbdSAlfred Perlstein children[i] = pid; 3988fae3551SRodney W. Grimes continue; 3998fae3551SRodney W. Grimes } 4008fae3551SRodney W. Grimes 401a62dc406SDoug Rabson setproctitle("server"); 4028fae3551SRodney W. Grimes nfssvc_flag = NFSSVC_NFSD; 4038fae3551SRodney W. Grimes nsd.nsd_nfsd = NULL; 404a62dc406SDoug Rabson #ifdef NFSKERB 405a62dc406SDoug Rabson if (sizeof (struct nfsrpc_fullverf) != RPCX_FULLVERF || 406a62dc406SDoug Rabson sizeof (struct nfsrpc_fullblock) != RPCX_FULLBLOCK) 407a62dc406SDoug Rabson syslog(LOG_ERR, "Yikes NFSKERB structs not packed!"); 408a62dc406SDoug Rabson nsd.nsd_authstr = (u_char *)&kt; 409a62dc406SDoug Rabson nsd.nsd_authlen = sizeof (kt); 410a62dc406SDoug Rabson nsd.nsd_verfstr = (u_char *)&kverf; 411a62dc406SDoug Rabson nsd.nsd_verflen = sizeof (kverf); 4128fae3551SRodney W. Grimes #endif 4138fae3551SRodney W. Grimes while (nfssvc(nfssvc_flag, &nsd) < 0) { 4148fae3551SRodney W. Grimes if (errno != ENEEDAUTH) { 4158fae3551SRodney W. Grimes syslog(LOG_ERR, "nfssvc: %m"); 4168fae3551SRodney W. Grimes exit(1); 4178fae3551SRodney W. Grimes } 4188fae3551SRodney W. Grimes nfssvc_flag = NFSSVC_NFSD | NFSSVC_AUTHINFAIL; 419a62dc406SDoug Rabson #ifdef NFSKERB 420a62dc406SDoug Rabson /* 421a62dc406SDoug Rabson * Get the Kerberos ticket out of the authenticator 422a62dc406SDoug Rabson * verify it and convert the principal name to a user 423a62dc406SDoug Rabson * name. The user name is then converted to a set of 424a62dc406SDoug Rabson * user credentials via the password and group file. 425a62dc406SDoug Rabson * Finally, decrypt the timestamp and validate it. 426a62dc406SDoug Rabson * For more info see the IETF Draft "Authentication 427a62dc406SDoug Rabson * in ONC RPC". 428a62dc406SDoug Rabson */ 429a62dc406SDoug Rabson kt.length = ntohl(kt.length); 430a62dc406SDoug Rabson if (gettimeofday(&ktv, (struct timezone *)0) == 0 && 431a62dc406SDoug Rabson kt.length > 0 && kt.length <= 432a62dc406SDoug Rabson (RPCAUTH_MAXSIZ - 3 * NFSX_UNSIGNED)) { 433a62dc406SDoug Rabson kin.w1 = NFS_KERBW1(kt); 4348fae3551SRodney W. Grimes kt.mbz = 0; 4358fae3551SRodney W. Grimes (void)strcpy(inst, "*"); 436a62dc406SDoug Rabson if (krb_rd_req(&kt, NFS_KERBSRV, 437a62dc406SDoug Rabson inst, nsd.nsd_haddr, &kauth, "") == RD_AP_OK && 438a62dc406SDoug Rabson krb_kntoln(&kauth, lnam) == KSUCCESS && 4398fae3551SRodney W. Grimes (pwd = getpwnam(lnam)) != NULL) { 4408fae3551SRodney W. Grimes cr = &nsd.nsd_cr; 4418fae3551SRodney W. Grimes cr->cr_uid = pwd->pw_uid; 4428fae3551SRodney W. Grimes cr->cr_groups[0] = pwd->pw_gid; 4438fae3551SRodney W. Grimes cr->cr_ngroups = 1; 4448fae3551SRodney W. Grimes setgrent(); 4458fae3551SRodney W. Grimes while ((grp = getgrent()) != NULL) { 4468fae3551SRodney W. Grimes if (grp->gr_gid == cr->cr_groups[0]) 4478fae3551SRodney W. Grimes continue; 4488fae3551SRodney W. Grimes for (cpp = grp->gr_mem; 4498fae3551SRodney W. Grimes *cpp != NULL; ++cpp) 4508fae3551SRodney W. Grimes if (!strcmp(*cpp, lnam)) 4518fae3551SRodney W. Grimes break; 4528fae3551SRodney W. Grimes if (*cpp == NULL) 4538fae3551SRodney W. Grimes continue; 4548fae3551SRodney W. Grimes cr->cr_groups[cr->cr_ngroups++] 4558fae3551SRodney W. Grimes = grp->gr_gid; 4568fae3551SRodney W. Grimes if (cr->cr_ngroups == NGROUPS) 4578fae3551SRodney W. Grimes break; 4588fae3551SRodney W. Grimes } 4598fae3551SRodney W. Grimes endgrent(); 460a62dc406SDoug Rabson 461a62dc406SDoug Rabson /* 462a62dc406SDoug Rabson * Get the timestamp verifier out of the 463a62dc406SDoug Rabson * authenticator and verifier strings. 464a62dc406SDoug Rabson */ 465a62dc406SDoug Rabson kin.t1 = kverf.t1; 466a62dc406SDoug Rabson kin.t2 = kverf.t2; 467a62dc406SDoug Rabson kin.w2 = kverf.w2; 468a62dc406SDoug Rabson bzero((caddr_t)kivec, sizeof (kivec)); 469a62dc406SDoug Rabson bcopy((caddr_t)kauth.session, 470a62dc406SDoug Rabson (caddr_t)nsd.nsd_key,sizeof(kauth.session)); 471a62dc406SDoug Rabson 472a62dc406SDoug Rabson /* 473a62dc406SDoug Rabson * Decrypt the timestamp verifier in CBC mode. 474a62dc406SDoug Rabson */ 475a62dc406SDoug Rabson XXX 476a62dc406SDoug Rabson 477a62dc406SDoug Rabson /* 478a62dc406SDoug Rabson * Validate the timestamp verifier, to 479a62dc406SDoug Rabson * check that the session key is ok. 480a62dc406SDoug Rabson */ 481a62dc406SDoug Rabson nsd.nsd_timestamp.tv_sec = ntohl(kout.t1); 482a62dc406SDoug Rabson nsd.nsd_timestamp.tv_usec = ntohl(kout.t2); 483a62dc406SDoug Rabson nsd.nsd_ttl = ntohl(kout.w1); 484a62dc406SDoug Rabson if ((nsd.nsd_ttl - 1) == ntohl(kout.w2)) 4858fae3551SRodney W. Grimes nfssvc_flag = NFSSVC_NFSD | NFSSVC_AUTHIN; 4868fae3551SRodney W. Grimes } 487a62dc406SDoug Rabson #endif /* NFSKERB */ 4888fae3551SRodney W. Grimes } 4898fae3551SRodney W. Grimes exit(0); 4908fae3551SRodney W. Grimes } 4918fae3551SRodney W. Grimes 4928360efbdSAlfred Perlstein if (atexit(killchildren) == -1) { 4938360efbdSAlfred Perlstein syslog(LOG_ERR, "atexit: %s", strerror(errno)); 4948fae3551SRodney W. Grimes exit(1); 4958fae3551SRodney W. Grimes } 4968360efbdSAlfred Perlstein FD_ZERO(&v4bits); 4978360efbdSAlfred Perlstein FD_ZERO(&v6bits); 4988360efbdSAlfred Perlstein 4998360efbdSAlfred Perlstein rpcbregcnt = 0; 5008360efbdSAlfred Perlstein /* Set up the socket for udp and rpcb register it. */ 5018360efbdSAlfred Perlstein if (udpflag) { 5028360efbdSAlfred Perlstein rpcbreg = 0; 5038360efbdSAlfred Perlstein for (i = 0; i < bindhostc; i++) { 5048360efbdSAlfred Perlstein memset(&hints, 0, sizeof hints); 5058360efbdSAlfred Perlstein hints.ai_flags = AI_PASSIVE; 5068360efbdSAlfred Perlstein hints.ai_family = AF_INET; 5078360efbdSAlfred Perlstein hints.ai_socktype = SOCK_DGRAM; 5088360efbdSAlfred Perlstein hints.ai_protocol = IPPROTO_UDP; 5098360efbdSAlfred Perlstein if (setbindhost(&ai_udp, bindhost[i], hints) == 0) { 5108360efbdSAlfred Perlstein rpcbreg = 1; 5118360efbdSAlfred Perlstein rpcbregcnt++; 5128360efbdSAlfred Perlstein if ((sock = socket(ai_udp->ai_family, 5138360efbdSAlfred Perlstein ai_udp->ai_socktype, 5148360efbdSAlfred Perlstein ai_udp->ai_protocol)) < 0) { 5158360efbdSAlfred Perlstein syslog(LOG_ERR, 5168360efbdSAlfred Perlstein "can't create udp socket"); 5178fae3551SRodney W. Grimes exit(1); 5188fae3551SRodney W. Grimes } 5198360efbdSAlfred Perlstein if (bind(sock, ai_udp->ai_addr, 5208360efbdSAlfred Perlstein ai_udp->ai_addrlen) < 0) { 5218360efbdSAlfred Perlstein syslog(LOG_ERR, 5228360efbdSAlfred Perlstein "can't bind udp addr %s: %m", 5238360efbdSAlfred Perlstein bindhost[i]); 5248fae3551SRodney W. Grimes exit(1); 5258fae3551SRodney W. Grimes } 5268360efbdSAlfred Perlstein freeaddrinfo(ai_udp); 5278fae3551SRodney W. Grimes nfsdargs.sock = sock; 5288fae3551SRodney W. Grimes nfsdargs.name = NULL; 5298fae3551SRodney W. Grimes nfsdargs.namelen = 0; 5308fae3551SRodney W. Grimes if (nfssvc(NFSSVC_ADDSOCK, &nfsdargs) < 0) { 5318fae3551SRodney W. Grimes syslog(LOG_ERR, "can't Add UDP socket"); 5328fae3551SRodney W. Grimes exit(1); 5338fae3551SRodney W. Grimes } 5348fae3551SRodney W. Grimes (void)close(sock); 5358fae3551SRodney W. Grimes } 5368360efbdSAlfred Perlstein } 5378360efbdSAlfred Perlstein if (rpcbreg == 1) { 5388360efbdSAlfred Perlstein memset(&hints, 0, sizeof hints); 5398360efbdSAlfred Perlstein hints.ai_flags = AI_PASSIVE; 5408360efbdSAlfred Perlstein hints.ai_family = AF_INET; 5418360efbdSAlfred Perlstein hints.ai_socktype = SOCK_DGRAM; 5428360efbdSAlfred Perlstein hints.ai_protocol = IPPROTO_UDP; 5438360efbdSAlfred Perlstein ecode = getaddrinfo(NULL, "nfs", &hints, &ai_udp); 5448360efbdSAlfred Perlstein if (ecode != 0) { 5458360efbdSAlfred Perlstein syslog(LOG_ERR, "getaddrinfo udp: %s", 5468360efbdSAlfred Perlstein gai_strerror(ecode)); 5478360efbdSAlfred Perlstein exit(1); 5488360efbdSAlfred Perlstein } 5498360efbdSAlfred Perlstein nconf_udp = getnetconfigent("udp"); 5508360efbdSAlfred Perlstein if (nconf_udp == NULL) 5518360efbdSAlfred Perlstein err(1, "getnetconfigent udp failed"); 5528360efbdSAlfred Perlstein nb_udp.buf = ai_udp->ai_addr; 5538360efbdSAlfred Perlstein nb_udp.len = nb_udp.maxlen = ai_udp->ai_addrlen; 5548360efbdSAlfred Perlstein if ((!rpcb_set(RPCPROG_NFS, 2, nconf_udp, &nb_udp)) || 5558360efbdSAlfred Perlstein (!rpcb_set(RPCPROG_NFS, 3, nconf_udp, &nb_udp))) 5568360efbdSAlfred Perlstein err(1, "rpcb_set udp failed"); 5578360efbdSAlfred Perlstein freeaddrinfo(ai_udp); 5588360efbdSAlfred Perlstein } 5598360efbdSAlfred Perlstein } 5608fae3551SRodney W. Grimes 5618360efbdSAlfred Perlstein /* Set up the socket for udp6 and rpcb register it. */ 5628360efbdSAlfred Perlstein if (udpflag && ip6flag) { 5638360efbdSAlfred Perlstein rpcbreg = 0; 5648360efbdSAlfred Perlstein for (i = 0; i < bindhostc; i++) { 5658360efbdSAlfred Perlstein memset(&hints, 0, sizeof hints); 5668360efbdSAlfred Perlstein hints.ai_flags = AI_PASSIVE; 5678360efbdSAlfred Perlstein hints.ai_family = AF_INET6; 5688360efbdSAlfred Perlstein hints.ai_socktype = SOCK_DGRAM; 5698360efbdSAlfred Perlstein hints.ai_protocol = IPPROTO_UDP; 5708360efbdSAlfred Perlstein if (setbindhost(&ai_udp6, bindhost[i], hints) == 0) { 5718360efbdSAlfred Perlstein rpcbreg = 1; 5728360efbdSAlfred Perlstein rpcbregcnt++; 5738360efbdSAlfred Perlstein if ((sock = socket(ai_udp6->ai_family, 5748360efbdSAlfred Perlstein ai_udp6->ai_socktype, 5758360efbdSAlfred Perlstein ai_udp6->ai_protocol)) < 0) { 5768360efbdSAlfred Perlstein syslog(LOG_ERR, 5778360efbdSAlfred Perlstein "can't create udp6 socket"); 5788fae3551SRodney W. Grimes exit(1); 5798fae3551SRodney W. Grimes } 5808360efbdSAlfred Perlstein if (setsockopt(sock, IPPROTO_IPV6, 5818360efbdSAlfred Perlstein IPV6_BINDV6ONLY, 5828360efbdSAlfred Perlstein &on, sizeof on) < 0) { 5838360efbdSAlfred Perlstein syslog(LOG_ERR, 5848360efbdSAlfred Perlstein "can't set v6-only binding for " 5858360efbdSAlfred Perlstein "udp6 socket: %m"); 5868fae3551SRodney W. Grimes exit(1); 5878fae3551SRodney W. Grimes } 5888360efbdSAlfred Perlstein if (bind(sock, ai_udp6->ai_addr, 5898360efbdSAlfred Perlstein ai_udp6->ai_addrlen) < 0) { 5908360efbdSAlfred Perlstein syslog(LOG_ERR, 5918360efbdSAlfred Perlstein "can't bind udp6 addr %s: %m", 5928360efbdSAlfred Perlstein bindhost[i]); 5938fae3551SRodney W. Grimes exit(1); 5948fae3551SRodney W. Grimes } 5958360efbdSAlfred Perlstein freeaddrinfo(ai_udp6); 5968fae3551SRodney W. Grimes nfsdargs.sock = sock; 5978fae3551SRodney W. Grimes nfsdargs.name = NULL; 5988fae3551SRodney W. Grimes nfsdargs.namelen = 0; 5998fae3551SRodney W. Grimes if (nfssvc(NFSSVC_ADDSOCK, &nfsdargs) < 0) { 6008360efbdSAlfred Perlstein syslog(LOG_ERR, 6018360efbdSAlfred Perlstein "can't add UDP6 socket"); 6028fae3551SRodney W. Grimes exit(1); 6038fae3551SRodney W. Grimes } 6048360efbdSAlfred Perlstein (void)close(sock); 6058fae3551SRodney W. Grimes } 6068360efbdSAlfred Perlstein } 6078360efbdSAlfred Perlstein if (rpcbreg == 1) { 6088360efbdSAlfred Perlstein memset(&hints, 0, sizeof hints); 6098360efbdSAlfred Perlstein hints.ai_flags = AI_PASSIVE; 6108360efbdSAlfred Perlstein hints.ai_family = AF_INET6; 6118360efbdSAlfred Perlstein hints.ai_socktype = SOCK_DGRAM; 6128360efbdSAlfred Perlstein hints.ai_protocol = IPPROTO_UDP; 6138360efbdSAlfred Perlstein ecode = getaddrinfo(NULL, "nfs", &hints, &ai_udp6); 6148360efbdSAlfred Perlstein if (ecode != 0) { 6158360efbdSAlfred Perlstein syslog(LOG_ERR, "getaddrinfo udp6: %s", 6168360efbdSAlfred Perlstein gai_strerror(ecode)); 6178360efbdSAlfred Perlstein exit(1); 6188360efbdSAlfred Perlstein } 6198360efbdSAlfred Perlstein nconf_udp6 = getnetconfigent("udp6"); 6208360efbdSAlfred Perlstein if (nconf_udp6 == NULL) 6218360efbdSAlfred Perlstein err(1, "getnetconfigent udp6 failed"); 6228360efbdSAlfred Perlstein nb_udp6.buf = ai_udp6->ai_addr; 6238360efbdSAlfred Perlstein nb_udp6.len = nb_udp6.maxlen = ai_udp6->ai_addrlen; 6248360efbdSAlfred Perlstein if ((!rpcb_set(RPCPROG_NFS, 2, nconf_udp6, &nb_udp6)) || 6258360efbdSAlfred Perlstein (!rpcb_set(RPCPROG_NFS, 3, nconf_udp6, &nb_udp6))) 6268360efbdSAlfred Perlstein err(1, "rpcb_set udp6 failed"); 6278360efbdSAlfred Perlstein freeaddrinfo(ai_udp6); 6288360efbdSAlfred Perlstein } 6298360efbdSAlfred Perlstein } 6308fae3551SRodney W. Grimes 6318360efbdSAlfred Perlstein /* Set up the socket for tcp and rpcb register it. */ 6328360efbdSAlfred Perlstein if (tcpflag) { 6338360efbdSAlfred Perlstein rpcbreg = 0; 6348360efbdSAlfred Perlstein for (i = 0; i < bindhostc; i++) { 6358360efbdSAlfred Perlstein memset(&hints, 0, sizeof hints); 6368360efbdSAlfred Perlstein hints.ai_flags = AI_PASSIVE; 6378360efbdSAlfred Perlstein hints.ai_family = AF_INET; 6388360efbdSAlfred Perlstein hints.ai_socktype = SOCK_STREAM; 6398360efbdSAlfred Perlstein hints.ai_protocol = IPPROTO_TCP; 6408360efbdSAlfred Perlstein if (setbindhost(&ai_tcp, bindhost[i], hints) == 0) { 6418360efbdSAlfred Perlstein rpcbreg = 1; 6428360efbdSAlfred Perlstein rpcbregcnt++; 6438360efbdSAlfred Perlstein if ((tcpsock = socket(AF_INET, SOCK_STREAM, 6448360efbdSAlfred Perlstein 0)) < 0) { 6458360efbdSAlfred Perlstein syslog(LOG_ERR, 6468360efbdSAlfred Perlstein "can't create tpc socket"); 6478fae3551SRodney W. Grimes exit(1); 6488fae3551SRodney W. Grimes } 6498360efbdSAlfred Perlstein if (setsockopt(tcpsock, SOL_SOCKET, 6508360efbdSAlfred Perlstein SO_REUSEADDR, 6518360efbdSAlfred Perlstein (char *)&on, sizeof(on)) < 0) 6528360efbdSAlfred Perlstein syslog(LOG_ERR, 6538360efbdSAlfred Perlstein "setsockopt SO_REUSEADDR: %m"); 6548360efbdSAlfred Perlstein if (bind(tcpsock, ai_tcp->ai_addr, 6558360efbdSAlfred Perlstein ai_tcp->ai_addrlen) < 0) { 6568360efbdSAlfred Perlstein syslog(LOG_ERR, 6578360efbdSAlfred Perlstein "can't bind tcp addr %s: %m", 6588360efbdSAlfred Perlstein bindhost[i]); 6598fae3551SRodney W. Grimes exit(1); 6608fae3551SRodney W. Grimes } 6618fae3551SRodney W. Grimes if (listen(tcpsock, 5) < 0) { 6628fae3551SRodney W. Grimes syslog(LOG_ERR, "listen failed"); 6638fae3551SRodney W. Grimes exit(1); 6648fae3551SRodney W. Grimes } 6658360efbdSAlfred Perlstein freeaddrinfo(ai_tcp); 6668fae3551SRodney W. Grimes FD_SET(tcpsock, &sockbits); 6678360efbdSAlfred Perlstein FD_SET(tcpsock, &v4bits); 6688fae3551SRodney W. Grimes maxsock = tcpsock; 6698fae3551SRodney W. Grimes connect_type_cnt++; 6708fae3551SRodney W. Grimes } 6718360efbdSAlfred Perlstein } 6728360efbdSAlfred Perlstein if (rpcbreg == 1) { 6738360efbdSAlfred Perlstein memset(&hints, 0, sizeof hints); 6748360efbdSAlfred Perlstein hints.ai_flags = AI_PASSIVE; 6758360efbdSAlfred Perlstein hints.ai_family = AF_INET; 6768360efbdSAlfred Perlstein hints.ai_socktype = SOCK_STREAM; 6778360efbdSAlfred Perlstein hints.ai_protocol = IPPROTO_TCP; 6788360efbdSAlfred Perlstein ecode = getaddrinfo(NULL, "nfs", &hints, 6798360efbdSAlfred Perlstein &ai_tcp); 6808360efbdSAlfred Perlstein if (ecode != 0) { 6818360efbdSAlfred Perlstein syslog(LOG_ERR, "getaddrinfo tcp: %s", 6828360efbdSAlfred Perlstein gai_strerror(ecode)); 6838360efbdSAlfred Perlstein exit(1); 6848360efbdSAlfred Perlstein } 6858360efbdSAlfred Perlstein nconf_tcp = getnetconfigent("tcp"); 6868360efbdSAlfred Perlstein if (nconf_tcp == NULL) 6878360efbdSAlfred Perlstein err(1, "getnetconfigent tcp failed"); 6888360efbdSAlfred Perlstein nb_tcp.buf = ai_tcp->ai_addr; 6898360efbdSAlfred Perlstein nb_tcp.len = nb_tcp.maxlen = ai_tcp->ai_addrlen; 6908360efbdSAlfred Perlstein if ((!rpcb_set(RPCPROG_NFS, 2, nconf_tcp, 6918360efbdSAlfred Perlstein &nb_tcp)) || (!rpcb_set(RPCPROG_NFS, 3, 6928360efbdSAlfred Perlstein nconf_tcp, &nb_tcp))) 6938360efbdSAlfred Perlstein err(1, "rpcb_set tcp failed"); 6948360efbdSAlfred Perlstein freeaddrinfo(ai_tcp); 6958360efbdSAlfred Perlstein } 6968360efbdSAlfred Perlstein } 6978fae3551SRodney W. Grimes 6988360efbdSAlfred Perlstein /* Set up the socket for tcp6 and rpcb register it. */ 6998360efbdSAlfred Perlstein if (tcpflag && ip6flag) { 7008360efbdSAlfred Perlstein rpcbreg = 0; 7018360efbdSAlfred Perlstein for (i = 0; i < bindhostc; i++) { 7028360efbdSAlfred Perlstein memset(&hints, 0, sizeof hints); 7038360efbdSAlfred Perlstein hints.ai_flags = AI_PASSIVE; 7048360efbdSAlfred Perlstein hints.ai_family = AF_INET6; 7058360efbdSAlfred Perlstein hints.ai_socktype = SOCK_STREAM; 7068360efbdSAlfred Perlstein hints.ai_protocol = IPPROTO_TCP; 7078360efbdSAlfred Perlstein if (setbindhost(&ai_tcp6, bindhost[i], hints) == 0) { 7088360efbdSAlfred Perlstein rpcbreg = 1; 7098360efbdSAlfred Perlstein rpcbregcnt++; 7108360efbdSAlfred Perlstein if ((tcp6sock = socket(ai_tcp6->ai_family, 7118360efbdSAlfred Perlstein ai_tcp6->ai_socktype, 7128360efbdSAlfred Perlstein ai_tcp6->ai_protocol)) < 0) { 7138360efbdSAlfred Perlstein syslog(LOG_ERR, 7148360efbdSAlfred Perlstein "can't create tcp6 socket"); 7158fae3551SRodney W. Grimes exit(1); 7168fae3551SRodney W. Grimes } 7178360efbdSAlfred Perlstein if (setsockopt(tcp6sock, SOL_SOCKET, 7188360efbdSAlfred Perlstein SO_REUSEADDR, 7198360efbdSAlfred Perlstein (char *)&on, sizeof(on)) < 0) 7208360efbdSAlfred Perlstein syslog(LOG_ERR, 7218360efbdSAlfred Perlstein "setsockopt SO_REUSEADDR: %m"); 7228360efbdSAlfred Perlstein if (setsockopt(tcp6sock, IPPROTO_IPV6, 7238360efbdSAlfred Perlstein IPV6_BINDV6ONLY, &on, sizeof on) < 0) { 7248360efbdSAlfred Perlstein syslog(LOG_ERR, 7258360efbdSAlfred Perlstein "can't set v6-only binding for tcp6 " 7268360efbdSAlfred Perlstein "socket: %m"); 7278fae3551SRodney W. Grimes exit(1); 7288fae3551SRodney W. Grimes } 7298360efbdSAlfred Perlstein if (bind(tcp6sock, ai_tcp6->ai_addr, 7308360efbdSAlfred Perlstein ai_tcp6->ai_addrlen) < 0) { 7318360efbdSAlfred Perlstein syslog(LOG_ERR, 7328360efbdSAlfred Perlstein "can't bind tcp6 addr %s: %m", 7338360efbdSAlfred Perlstein bindhost[i]); 7348360efbdSAlfred Perlstein exit(1); 7358360efbdSAlfred Perlstein } 7368360efbdSAlfred Perlstein if (listen(tcp6sock, 5) < 0) { 7378fae3551SRodney W. Grimes syslog(LOG_ERR, "listen failed"); 7388fae3551SRodney W. Grimes exit(1); 7398fae3551SRodney W. Grimes } 7408360efbdSAlfred Perlstein freeaddrinfo(ai_tcp6); 7418360efbdSAlfred Perlstein FD_SET(tcp6sock, &sockbits); 7428360efbdSAlfred Perlstein FD_SET(tcp6sock, &v6bits); 7438360efbdSAlfred Perlstein if (maxsock < tcp6sock) 7448360efbdSAlfred Perlstein maxsock = tcp6sock; 7458fae3551SRodney W. Grimes connect_type_cnt++; 7468fae3551SRodney W. Grimes } 7478360efbdSAlfred Perlstein } 7488360efbdSAlfred Perlstein if (rpcbreg == 1) { 7498360efbdSAlfred Perlstein memset(&hints, 0, sizeof hints); 7508360efbdSAlfred Perlstein hints.ai_flags = AI_PASSIVE; 7518360efbdSAlfred Perlstein hints.ai_family = AF_INET6; 7528360efbdSAlfred Perlstein hints.ai_socktype = SOCK_STREAM; 7538360efbdSAlfred Perlstein hints.ai_protocol = IPPROTO_TCP; 7548360efbdSAlfred Perlstein ecode = getaddrinfo(NULL, "nfs", &hints, &ai_tcp6); 7558360efbdSAlfred Perlstein if (ecode != 0) { 7568360efbdSAlfred Perlstein syslog(LOG_ERR, "getaddrinfo tcp6: %s", 7578360efbdSAlfred Perlstein gai_strerror(ecode)); 7588360efbdSAlfred Perlstein exit(1); 7598360efbdSAlfred Perlstein } 7608360efbdSAlfred Perlstein nconf_tcp6 = getnetconfigent("tcp6"); 7618360efbdSAlfred Perlstein if (nconf_tcp6 == NULL) 7628360efbdSAlfred Perlstein err(1, "getnetconfigent tcp6 failed"); 7638360efbdSAlfred Perlstein nb_tcp6.buf = ai_tcp6->ai_addr; 7648360efbdSAlfred Perlstein nb_tcp6.len = nb_tcp6.maxlen = ai_tcp6->ai_addrlen; 7658360efbdSAlfred Perlstein if ((!rpcb_set(RPCPROG_NFS, 2, nconf_tcp6, &nb_tcp6)) || 7668360efbdSAlfred Perlstein (!rpcb_set(RPCPROG_NFS, 3, nconf_tcp6, &nb_tcp6))) 7678360efbdSAlfred Perlstein err(1, "rpcb_set tcp6 failed"); 7688360efbdSAlfred Perlstein freeaddrinfo(ai_tcp6); 7698360efbdSAlfred Perlstein } 7708360efbdSAlfred Perlstein } 7718fae3551SRodney W. Grimes 7728360efbdSAlfred Perlstein if (rpcbregcnt == 0) { 7738360efbdSAlfred Perlstein syslog(LOG_ERR, "rpcb_set() failed, nothing to do: %m"); 7748fae3551SRodney W. Grimes exit(1); 7758fae3551SRodney W. Grimes } 7768fae3551SRodney W. Grimes 7778360efbdSAlfred Perlstein if ((tcpflag) && (connect_type_cnt == 0)) { 7788360efbdSAlfred Perlstein syslog(LOG_ERR, "tcp connects == 0, nothing to do: %m"); 7798360efbdSAlfred Perlstein exit(1); 7808360efbdSAlfred Perlstein } 7818fae3551SRodney W. Grimes 782a62dc406SDoug Rabson setproctitle("master"); 7838fae3551SRodney W. Grimes 7848fae3551SRodney W. Grimes /* 7858fae3551SRodney W. Grimes * Loop forever accepting connections and passing the sockets 7868fae3551SRodney W. Grimes * into the kernel for the mounts. 7878fae3551SRodney W. Grimes */ 7888fae3551SRodney W. Grimes for (;;) { 7898fae3551SRodney W. Grimes ready = sockbits; 7908fae3551SRodney W. Grimes if (connect_type_cnt > 1) { 7918fae3551SRodney W. Grimes if (select(maxsock + 1, 7928fae3551SRodney W. Grimes &ready, NULL, NULL, NULL) < 1) { 7938fae3551SRodney W. Grimes syslog(LOG_ERR, "select failed: %m"); 7948fae3551SRodney W. Grimes exit(1); 7958fae3551SRodney W. Grimes } 7968fae3551SRodney W. Grimes } 7978360efbdSAlfred Perlstein for (tcpsock = 0; tcpsock <= maxsock; tcpsock++) { 7988360efbdSAlfred Perlstein if (FD_ISSET(tcpsock, &ready)) { 7998360efbdSAlfred Perlstein if (FD_ISSET(tcpsock, &v4bits)) { 8008fae3551SRodney W. Grimes len = sizeof(inetpeer); 8018fae3551SRodney W. Grimes if ((msgsock = accept(tcpsock, 8028fae3551SRodney W. Grimes (struct sockaddr *)&inetpeer, &len)) < 0) { 8038fae3551SRodney W. Grimes syslog(LOG_ERR, "accept failed: %m"); 8048fae3551SRodney W. Grimes exit(1); 8058fae3551SRodney W. Grimes } 8068360efbdSAlfred Perlstein memset(inetpeer.sin_zero, 0, 8078360efbdSAlfred Perlstein sizeof(inetpeer.sin_zero)); 8088fae3551SRodney W. Grimes if (setsockopt(msgsock, SOL_SOCKET, 8098fae3551SRodney W. Grimes SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0) 8108fae3551SRodney W. Grimes syslog(LOG_ERR, 8118fae3551SRodney W. Grimes "setsockopt SO_KEEPALIVE: %m"); 8128fae3551SRodney W. Grimes nfsdargs.sock = msgsock; 8138fae3551SRodney W. Grimes nfsdargs.name = (caddr_t)&inetpeer; 8148fae3551SRodney W. Grimes nfsdargs.namelen = sizeof(inetpeer); 8158fae3551SRodney W. Grimes nfssvc(NFSSVC_ADDSOCK, &nfsdargs); 8168fae3551SRodney W. Grimes (void)close(msgsock); 8178360efbdSAlfred Perlstein } else if (FD_ISSET(tcpsock, &v6bits)) { 8188360efbdSAlfred Perlstein len = sizeof(inet6peer); 8198360efbdSAlfred Perlstein if ((msgsock = accept(tcpsock, 8208360efbdSAlfred Perlstein (struct sockaddr *)&inet6peer, 8218360efbdSAlfred Perlstein &len)) < 0) { 8228fae3551SRodney W. Grimes syslog(LOG_ERR, 8238360efbdSAlfred Perlstein "accept failed: %m"); 8248fae3551SRodney W. Grimes exit(1); 8258fae3551SRodney W. Grimes } 8268fae3551SRodney W. Grimes if (setsockopt(msgsock, SOL_SOCKET, 8278360efbdSAlfred Perlstein SO_KEEPALIVE, (char *)&on, 8288360efbdSAlfred Perlstein sizeof(on)) < 0) 8298360efbdSAlfred Perlstein syslog(LOG_ERR, "setsockopt " 8308360efbdSAlfred Perlstein "SO_KEEPALIVE: %m"); 8318fae3551SRodney W. Grimes nfsdargs.sock = msgsock; 8328360efbdSAlfred Perlstein nfsdargs.name = (caddr_t)&inet6peer; 8338360efbdSAlfred Perlstein nfsdargs.namelen = sizeof(inet6peer); 8348fae3551SRodney W. Grimes nfssvc(NFSSVC_ADDSOCK, &nfsdargs); 8358fae3551SRodney W. Grimes (void)close(msgsock); 8368fae3551SRodney W. Grimes } 8378360efbdSAlfred Perlstein } 8388360efbdSAlfred Perlstein } 8398fae3551SRodney W. Grimes } 8408fae3551SRodney W. Grimes } 8418fae3551SRodney W. Grimes 8428360efbdSAlfred Perlstein int 8438360efbdSAlfred Perlstein setbindhost(struct addrinfo **ai, const char *bindhost, struct addrinfo hints) 84492fc2acfSMatthew Dillon { 8458360efbdSAlfred Perlstein int ecode; 8468360efbdSAlfred Perlstein u_int32_t host_addr[4]; /* IPv4 or IPv6 */ 8478360efbdSAlfred Perlstein const char *hostptr; 84892fc2acfSMatthew Dillon 8498360efbdSAlfred Perlstein if (bindhost == NULL || strcmp("*", bindhost) == 0) 8508360efbdSAlfred Perlstein hostptr = NULL; 8518360efbdSAlfred Perlstein else 8528360efbdSAlfred Perlstein hostptr = bindhost; 8538360efbdSAlfred Perlstein 8548360efbdSAlfred Perlstein if (hostptr != NULL) { 8558360efbdSAlfred Perlstein switch (hints.ai_family) { 8568360efbdSAlfred Perlstein case AF_INET: 8578360efbdSAlfred Perlstein if (inet_pton(AF_INET, hostptr, host_addr) == 1) { 8588360efbdSAlfred Perlstein hints.ai_flags = AI_NUMERICHOST; 8598360efbdSAlfred Perlstein } else { 8608360efbdSAlfred Perlstein if (inet_pton(AF_INET6, hostptr, 8618360efbdSAlfred Perlstein host_addr) == 1) 8628360efbdSAlfred Perlstein return (1); 86392fc2acfSMatthew Dillon } 8648360efbdSAlfred Perlstein break; 8658360efbdSAlfred Perlstein case AF_INET6: 8668360efbdSAlfred Perlstein if (inet_pton(AF_INET6, hostptr, host_addr) == 1) { 8678360efbdSAlfred Perlstein hints.ai_flags = AI_NUMERICHOST; 8688360efbdSAlfred Perlstein } else { 8698360efbdSAlfred Perlstein if (inet_pton(AF_INET, hostptr, 8708360efbdSAlfred Perlstein host_addr) == 1) 8718360efbdSAlfred Perlstein return (1); 8728360efbdSAlfred Perlstein } 8738360efbdSAlfred Perlstein break; 8748360efbdSAlfred Perlstein default: 87592fc2acfSMatthew Dillon } 87692fc2acfSMatthew Dillon } 8778360efbdSAlfred Perlstein 8788360efbdSAlfred Perlstein ecode = getaddrinfo(hostptr, "nfs", &hints, ai); 8798360efbdSAlfred Perlstein if (ecode != 0) { 8808360efbdSAlfred Perlstein syslog(LOG_ERR, "getaddrinfo %s: %s", bindhost, 8818360efbdSAlfred Perlstein gai_strerror(ecode)); 8828360efbdSAlfred Perlstein return (1); 8838360efbdSAlfred Perlstein } 8848360efbdSAlfred Perlstein return (0); 88592fc2acfSMatthew Dillon } 88692fc2acfSMatthew Dillon 88792fc2acfSMatthew Dillon void 8888fae3551SRodney W. Grimes usage() 8898fae3551SRodney W. Grimes { 890a62dc406SDoug Rabson (void)fprintf(stderr, "usage: nfsd %s\n", USAGE); 8918fae3551SRodney W. Grimes exit(1); 8928fae3551SRodney W. Grimes } 8938fae3551SRodney W. Grimes 8948fae3551SRodney W. Grimes void 8958fae3551SRodney W. Grimes nonfs(signo) 8968fae3551SRodney W. Grimes int signo; 8978fae3551SRodney W. Grimes { 8989b4d716bSPhilippe Charnier syslog(LOG_ERR, "missing system call: NFS not available"); 8998fae3551SRodney W. Grimes } 9008fae3551SRodney W. Grimes 9018fae3551SRodney W. Grimes void 9028fae3551SRodney W. Grimes reapchild(signo) 9038fae3551SRodney W. Grimes int signo; 9048fae3551SRodney W. Grimes { 9058fae3551SRodney W. Grimes 906a62dc406SDoug Rabson while (wait3(NULL, WNOHANG, NULL) > 0); 9078fae3551SRodney W. Grimes } 9088fae3551SRodney W. Grimes 9098360efbdSAlfred Perlstein void 9108360efbdSAlfred Perlstein unregistration() 9118360efbdSAlfred Perlstein { 9128360efbdSAlfred Perlstein if ((!rpcb_unset(RPCPROG_NFS, 2, NULL)) || 9138360efbdSAlfred Perlstein (!rpcb_unset(RPCPROG_NFS, 3, NULL))) 9148360efbdSAlfred Perlstein syslog(LOG_ERR, "rpcb_unset failed"); 9158360efbdSAlfred Perlstein } 9168360efbdSAlfred Perlstein 9178360efbdSAlfred Perlstein void 9188360efbdSAlfred Perlstein killchildren() 9198360efbdSAlfred Perlstein { 9208360efbdSAlfred Perlstein int i; 9218360efbdSAlfred Perlstein sigset_t sigs; 9228360efbdSAlfred Perlstein 9238360efbdSAlfred Perlstein sigemptyset(&sigs); 9248360efbdSAlfred Perlstein /* 9258360efbdSAlfred Perlstein * Block SIGCHLD to avoid killing a reaped process (although it is 9268360efbdSAlfred Perlstein * unlikely, the pid might have been reused). 9278360efbdSAlfred Perlstein */ 9288360efbdSAlfred Perlstein sigaddset(&sigs, SIGCHLD); 9298360efbdSAlfred Perlstein if (sigprocmask(SIG_BLOCK, &sigs, NULL) == -1) { 9308360efbdSAlfred Perlstein syslog(LOG_ERR, "sigprocmask: %s", 9318360efbdSAlfred Perlstein strerror(errno)); 9328360efbdSAlfred Perlstein return; 9338360efbdSAlfred Perlstein } 9348360efbdSAlfred Perlstein for (i = 0; i < nfsdcnt; i++) { 9358360efbdSAlfred Perlstein if (children[i] > 0) 9368360efbdSAlfred Perlstein kill(children[i], SIGKILL); 9378360efbdSAlfred Perlstein } 9388360efbdSAlfred Perlstein if (sigprocmask(SIG_UNBLOCK, &sigs, NULL) == -1) { 9398360efbdSAlfred Perlstein syslog(LOG_ERR, "sigprocmask: %s", strerror(errno)); 9408360efbdSAlfred Perlstein } 9418360efbdSAlfred Perlstein unregistration(); 9428360efbdSAlfred Perlstein } 9438360efbdSAlfred Perlstein 9448360efbdSAlfred Perlstein void 9458360efbdSAlfred Perlstein cleanup(signo) 9468360efbdSAlfred Perlstein { 9478360efbdSAlfred Perlstein killchildren(); 9488360efbdSAlfred Perlstein exit (0); 9498360efbdSAlfred Perlstein } 9508360efbdSAlfred Perlstein 951c129841aSPeter Wemm #ifdef OLD_SETPROCTITLE 952a62dc406SDoug Rabson #ifdef __FreeBSD__ 9538fae3551SRodney W. Grimes void 9548fae3551SRodney W. Grimes setproctitle(a) 9558fae3551SRodney W. Grimes char *a; 9568fae3551SRodney W. Grimes { 9578fae3551SRodney W. Grimes register char *cp; 9588fae3551SRodney W. Grimes char buf[80]; 9598fae3551SRodney W. Grimes 9608fae3551SRodney W. Grimes cp = Argv[0]; 961a62dc406SDoug Rabson (void)snprintf(buf, sizeof(buf), "nfsd-%s", a); 9628fae3551SRodney W. Grimes (void)strncpy(cp, buf, LastArg - cp); 9638fae3551SRodney W. Grimes cp += strlen(cp); 9648fae3551SRodney W. Grimes while (cp < LastArg) 9656aab3b5aSDavid Greenman *cp++ = '\0'; 96609802b4aSPeter Wemm Argv[1] = NULL; 9678fae3551SRodney W. Grimes } 968a62dc406SDoug Rabson #endif /* __FreeBSD__ */ 969c129841aSPeter Wemm #endif 970