nfsd.c revision 74800
11558Srgrimes/*
21558Srgrimes * Copyright (c) 1989, 1993, 1994
31558Srgrimes *	The Regents of the University of California.  All rights reserved.
41558Srgrimes *
51558Srgrimes * This code is derived from software contributed to Berkeley by
61558Srgrimes * Rick Macklem at The University of Guelph.
71558Srgrimes *
81558Srgrimes * Redistribution and use in source and binary forms, with or without
91558Srgrimes * modification, are permitted provided that the following conditions
101558Srgrimes * are met:
111558Srgrimes * 1. Redistributions of source code must retain the above copyright
121558Srgrimes *    notice, this list of conditions and the following disclaimer.
131558Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
141558Srgrimes *    notice, this list of conditions and the following disclaimer in the
151558Srgrimes *    documentation and/or other materials provided with the distribution.
161558Srgrimes * 3. All advertising materials mentioning features or use of this software
171558Srgrimes *    must display the following acknowledgement:
181558Srgrimes *	This product includes software developed by the University of
191558Srgrimes *	California, Berkeley and its contributors.
201558Srgrimes * 4. Neither the name of the University nor the names of its contributors
211558Srgrimes *    may be used to endorse or promote products derived from this software
221558Srgrimes *    without specific prior written permission.
231558Srgrimes *
241558Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
251558Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
261558Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
271558Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
281558Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
291558Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
301558Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
311558Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
321558Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
331558Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
341558Srgrimes * SUCH DAMAGE.
351558Srgrimes */
361558Srgrimes
371558Srgrimes#ifndef lint
3837666Scharnierstatic const char copyright[] =
391558Srgrimes"@(#) Copyright (c) 1989, 1993, 1994\n\
401558Srgrimes	The Regents of the University of California.  All rights reserved.\n";
411558Srgrimes#endif not lint
421558Srgrimes
431558Srgrimes#ifndef lint
4437666Scharnier#if 0
4523684Speterstatic char sccsid[] = "@(#)nfsd.c	8.9 (Berkeley) 3/29/95";
4637666Scharnier#endif
4737666Scharnierstatic const char rcsid[] =
4850476Speter  "$FreeBSD: head/usr.sbin/nfsd/nfsd.c 74800 2001-03-25 23:32:55Z alfred $";
491558Srgrimes#endif not lint
501558Srgrimes
511558Srgrimes#include <sys/param.h>
521558Srgrimes#include <sys/syslog.h>
531558Srgrimes#include <sys/wait.h>
541558Srgrimes#include <sys/mount.h>
551558Srgrimes
561558Srgrimes#include <rpc/rpc.h>
571558Srgrimes#include <rpc/pmap_clnt.h>
581558Srgrimes
5953096Sdillon#include <netdb.h>
6053096Sdillon#include <arpa/inet.h>
611558Srgrimes#include <nfs/rpcv2.h>
629336Sdfr#include <nfs/nfsproto.h>
631558Srgrimes#include <nfs/nfs.h>
641558Srgrimes
659336Sdfr#ifdef NFSKERB
6623684Speter#include <kerberosIV/des.h>
671558Srgrimes#include <kerberosIV/krb.h>
681558Srgrimes#endif
691558Srgrimes
701558Srgrimes#include <err.h>
711558Srgrimes#include <errno.h>
721558Srgrimes#include <stdio.h>
731558Srgrimes#include <stdlib.h>
741558Srgrimes#include <strings.h>
751558Srgrimes#include <unistd.h>
7674462Salfred#include <netdb.h>
771558Srgrimes
781558Srgrimes/* Global defs */
791558Srgrimes#ifdef DEBUG
801558Srgrimes#define	syslog(e, s)	fprintf(stderr,(s))
811558Srgrimesint	debug = 1;
821558Srgrimes#else
831558Srgrimesint	debug = 0;
841558Srgrimes#endif
851558Srgrimes
861558Srgrimesstruct	nfsd_srvargs nsd;
8713141Speter#ifdef OLD_SETPROCTITLE
881558Srgrimeschar	**Argv = NULL;		/* pointer to argument vector */
891558Srgrimeschar	*LastArg = NULL;	/* end of argv */
9013141Speter#endif
911558Srgrimes
929336Sdfr#ifdef NFSKERB
931558Srgrimeschar		lnam[ANAME_SZ];
941558SrgrimesKTEXT_ST	kt;
959336SdfrAUTH_DAT	kauth;
961558Srgrimeschar		inst[INST_SZ];
979336Sdfrstruct nfsrpc_fullblock kin, kout;
989336Sdfrstruct nfsrpc_fullverf kverf;
999336SdfrNFSKERBKEY_T	kivec;
1009336Sdfrstruct timeval	ktv;
1019336SdfrNFSKERBKEYSCHED_T kerb_keysched;
1021558Srgrimes#endif
1031558Srgrimes
10474462Salfred#define	MAXNFSDCNT	20
10574462Salfred#define	DEFNFSDCNT	 4
10674462Salfredpid_t	children[MAXNFSDCNT];	/* PIDs of children */
10774462Salfredint	nfsdcnt;		/* number of children */
10874462Salfred
10974462Salfredvoid	cleanup(int);
11074462Salfredvoid	killchildren(void);
11174462Salfredvoid	nonfs (int);
11274462Salfredvoid	reapchild (int);
11374462Salfredint	setbindhost (struct addrinfo **ia, const char *bindhost, struct addrinfo hints);
11413141Speter#ifdef OLD_SETPROCTITLE
1159336Sdfr#ifdef __FreeBSD__
11674462Salfredvoid	setproctitle (char *);
1179336Sdfr#endif
11813141Speter#endif
11974462Salfredvoid	unregistration (void);
12074462Salfredvoid	usage (void);
1211558Srgrimes
1221558Srgrimes/*
1231558Srgrimes * Nfs server daemon mostly just a user context for nfssvc()
1241558Srgrimes *
1251558Srgrimes * 1 - do file descriptor and signal cleanup
1261558Srgrimes * 2 - fork the nfsd(s)
1271558Srgrimes * 3 - create server socket(s)
12874462Salfred * 4 - register socket with rpcbind
1291558Srgrimes *
1301558Srgrimes * For connectionless protocols, just pass the socket into the kernel via.
1311558Srgrimes * nfssvc().
1321558Srgrimes * For connection based sockets, loop doing accepts. When you get a new
1331558Srgrimes * socket from accept, pass the msgsock into the kernel via. nfssvc().
1341558Srgrimes * The arguments are:
1351558Srgrimes *	-c - support iso cltp clients
13674462Salfred *	-r - reregister with rpcbind
13774462Salfred *	-d - unregister with rpcbind
1381558Srgrimes *	-t - support tcp nfs clients
1391558Srgrimes *	-u - support udp nfs clients
1401558Srgrimes * followed by "n" which is the number of nfsds' to fork off
1411558Srgrimes */
1421558Srgrimesint
1431558Srgrimesmain(argc, argv, envp)
1441558Srgrimes	int argc;
1451558Srgrimes	char *argv[], *envp[];
1461558Srgrimes{
1471558Srgrimes	struct nfsd_args nfsdargs;
14874462Salfred	struct addrinfo *ai_udp, *ai_tcp, *ai_udp6, *ai_tcp6, hints;
14974462Salfred	struct netconfig *nconf_udp, *nconf_tcp, *nconf_udp6, *nconf_tcp6;
15074462Salfred	struct netbuf nb_udp, nb_tcp, nb_udp6, nb_tcp6;
15174462Salfred	struct sockaddr_in inetpeer;
15274462Salfred	struct sockaddr_in6 inet6peer;
1531558Srgrimes	fd_set ready, sockbits;
15474462Salfred	fd_set v4bits, v6bits;
1551558Srgrimes	int ch, cltpflag, connect_type_cnt, i, len, maxsock, msgsock;
15674462Salfred	int nfssvc_flag, on = 1, unregister, reregister, sock;
15774462Salfred	int tcp6sock, ip6flag, tcpflag, tcpsock;
15874462Salfred	int udpflag, ecode, s;
15974462Salfred	int bindhostc = 0, bindanyflag, rpcbreg, rpcbregcnt;
16053096Sdillon	char **bindhost = NULL;
16174462Salfred	pid_t pid;
16237666Scharnier#ifdef NFSKERB
16337666Scharnier	struct group *grp;
16437666Scharnier	struct passwd *pwd;
16537666Scharnier	struct ucred *cr;
16637666Scharnier	struct timeval ktv;
16737666Scharnier	char **cpp;
16837666Scharnier#endif
1699336Sdfr#ifdef __FreeBSD__
17023684Speter	struct vfsconf vfc;
17123684Speter	int error;
1721558Srgrimes
17323684Speter	error = getvfsbyname("nfs", &vfc);
17423684Speter	if (error && vfsisloadable("nfs")) {
17523684Speter		if (vfsload("nfs"))
1762999Swollman			err(1, "vfsload(nfs)");
1772999Swollman		endvfsent();	/* flush cache */
17823684Speter		error = getvfsbyname("nfs", &vfc);
1792999Swollman	}
18023684Speter	if (error)
1812999Swollman		errx(1, "NFS is not available in the running kernel");
1829336Sdfr#endif
1832999Swollman
18413141Speter#ifdef OLD_SETPROCTITLE
1851558Srgrimes	/* Save start and extent of argv for setproctitle. */
1861558Srgrimes	Argv = argv;
1871558Srgrimes	if (envp == 0 || *envp == 0)
1881558Srgrimes		envp = argv;
1891558Srgrimes	while (*envp)
1901558Srgrimes		envp++;
1911558Srgrimes	LastArg = envp[-1] + strlen(envp[-1]);
19213141Speter#endif
1931558Srgrimes
1941558Srgrimes	nfsdcnt = DEFNFSDCNT;
19574462Salfred	cltpflag = unregister = reregister = tcpflag = 0;
19674800Salfred	bindanyflag = udpflag;
19774462Salfred#define	GETOPT	"ah:n:rdtu"
19874462Salfred#define	USAGE	"[-ardtu] [-n num_servers] [-h bindip]"
19924359Simp	while ((ch = getopt(argc, argv, GETOPT)) != -1)
2001558Srgrimes		switch (ch) {
20153096Sdillon		case 'a':
20253096Sdillon			bindanyflag = 1;
20353096Sdillon			break;
2041558Srgrimes		case 'n':
2051558Srgrimes			nfsdcnt = atoi(optarg);
2061558Srgrimes			if (nfsdcnt < 1 || nfsdcnt > MAXNFSDCNT) {
20731206Sjdp				warnx("nfsd count %d; reset to %d", nfsdcnt,
20831206Sjdp				    DEFNFSDCNT);
2091558Srgrimes				nfsdcnt = DEFNFSDCNT;
2101558Srgrimes			}
2111558Srgrimes			break;
21253096Sdillon		case 'h':
21353096Sdillon			bindhostc++;
21453096Sdillon			bindhost = realloc(bindhost,sizeof(char *)*bindhostc);
21553096Sdillon			if (bindhost == NULL)
21653096Sdillon				errx(1, "Out of memory");
21753096Sdillon			bindhost[bindhostc-1] = strdup(optarg);
21853096Sdillon			if (bindhost[bindhostc-1] == NULL)
21953096Sdillon				errx(1, "Out of memory");
22053096Sdillon			break;
2211558Srgrimes		case 'r':
2221558Srgrimes			reregister = 1;
2231558Srgrimes			break;
22474462Salfred		case 'd':
22574462Salfred			unregister = 1;
22674462Salfred			break;
2271558Srgrimes		case 't':
2281558Srgrimes			tcpflag = 1;
2291558Srgrimes			break;
2301558Srgrimes		case 'u':
2311558Srgrimes			udpflag = 1;
2321558Srgrimes			break;
2331558Srgrimes		default:
2341558Srgrimes		case '?':
2351558Srgrimes			usage();
2361558Srgrimes		};
23715496Sbde	if (!tcpflag && !udpflag)
23815496Sbde		udpflag = 1;
2391558Srgrimes	argv += optind;
2401558Srgrimes	argc -= optind;
2411558Srgrimes
2421558Srgrimes	/*
2431558Srgrimes	 * XXX
2441558Srgrimes	 * Backward compatibility, trailing number is the count of daemons.
2451558Srgrimes	 */
2461558Srgrimes	if (argc > 1)
2471558Srgrimes		usage();
2481558Srgrimes	if (argc == 1) {
2491558Srgrimes		nfsdcnt = atoi(argv[0]);
2501558Srgrimes		if (nfsdcnt < 1 || nfsdcnt > MAXNFSDCNT) {
25131206Sjdp			warnx("nfsd count %d; reset to %d", nfsdcnt,
25231206Sjdp			    DEFNFSDCNT);
2531558Srgrimes			nfsdcnt = DEFNFSDCNT;
2541558Srgrimes		}
2551558Srgrimes	}
25674800Salfred
25774462Salfred	ip6flag = 1;
25874462Salfred	s = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
25974800Salfred	if (s == -1) {
26074800Salfred		if (errno != EPROTONOSUPPORT)
26174800Salfred			err(1, "socket");
26274462Salfred		ip6flag = 0;
26374800Salfred	} else if (getnetconfigent("udp6") == NULL ||
26474800Salfred		getnetconfigent("tcp6") == NULL) {
26574800Salfred		ip6flag = 0;
26674800Salfred	}
26774800Salfred	if (s != -1)
26874462Salfred		close(s);
2691558Srgrimes
27053096Sdillon	if (bindhostc == 0 || bindanyflag) {
27153096Sdillon		bindhostc++;
27253096Sdillon		bindhost = realloc(bindhost,sizeof(char *)*bindhostc);
27353096Sdillon		if (bindhost == NULL)
27453096Sdillon			errx(1, "Out of memory");
27553096Sdillon		bindhost[bindhostc-1] = strdup("*");
27653096Sdillon		if (bindhost[bindhostc-1] == NULL)
27753096Sdillon			errx(1, "Out of memory");
27853096Sdillon	}
27953096Sdillon
28074462Salfred	if (unregister) {
28174462Salfred		unregistration();
28274462Salfred		exit (0);
28374462Salfred	}
2841558Srgrimes	if (reregister) {
28574462Salfred		if (udpflag) {
28674462Salfred			memset(&hints, 0, sizeof hints);
28774462Salfred			hints.ai_flags = AI_PASSIVE;
28874462Salfred			hints.ai_family = AF_INET;
28974462Salfred			hints.ai_socktype = SOCK_DGRAM;
29074462Salfred			hints.ai_protocol = IPPROTO_UDP;
29174462Salfred			ecode = getaddrinfo(NULL, "nfs", &hints, &ai_udp);
29274800Salfred			if (ecode != 0)
29374800Salfred				err(1, "getaddrinfo udp: %s", gai_strerror(ecode));
29474462Salfred			nconf_udp = getnetconfigent("udp");
29574462Salfred			if (nconf_udp == NULL)
29674462Salfred				err(1, "getnetconfigent udp failed");
29774462Salfred			nb_udp.buf = ai_udp->ai_addr;
29874462Salfred			nb_udp.len = nb_udp.maxlen = ai_udp->ai_addrlen;
29974462Salfred			if ((!rpcb_set(RPCPROG_NFS, 2, nconf_udp, &nb_udp)) ||
30074462Salfred			    (!rpcb_set(RPCPROG_NFS, 3, nconf_udp, &nb_udp)))
30174462Salfred				err(1, "rpcb_set udp failed");
30274462Salfred			freeaddrinfo(ai_udp);
30374462Salfred		}
30474462Salfred		if (udpflag && ip6flag) {
30574462Salfred			memset(&hints, 0, sizeof hints);
30674462Salfred			hints.ai_flags = AI_PASSIVE;
30774462Salfred			hints.ai_family = AF_INET6;
30874462Salfred			hints.ai_socktype = SOCK_DGRAM;
30974462Salfred			hints.ai_protocol = IPPROTO_UDP;
31074462Salfred			ecode = getaddrinfo(NULL, "nfs", &hints, &ai_udp6);
31174800Salfred			if (ecode != 0)
31274800Salfred				err(1, "getaddrinfo udp6: %s", gai_strerror(ecode));
31374462Salfred			nconf_udp6 = getnetconfigent("udp6");
31474462Salfred			if (nconf_udp6 == NULL)
31574462Salfred				err(1, "getnetconfigent udp6 failed");
31674462Salfred			nb_udp6.buf = ai_udp6->ai_addr;
31774462Salfred			nb_udp6.len = nb_udp6.maxlen = ai_udp6->ai_addrlen;
31874462Salfred			if ((!rpcb_set(RPCPROG_NFS, 2, nconf_udp6, &nb_udp6)) ||
31974462Salfred			    (!rpcb_set(RPCPROG_NFS, 3, nconf_udp6, &nb_udp6)))
32074462Salfred				err(1, "rpcb_set udp6 failed");
32174462Salfred			freeaddrinfo(ai_udp6);
32274462Salfred		}
32374462Salfred		if (tcpflag) {
32474462Salfred			memset(&hints, 0, sizeof hints);
32574462Salfred			hints.ai_flags = AI_PASSIVE;
32674462Salfred			hints.ai_family = AF_INET;
32774462Salfred			hints.ai_socktype = SOCK_STREAM;
32874462Salfred			hints.ai_protocol = IPPROTO_TCP;
32974462Salfred			ecode = getaddrinfo(NULL, "nfs", &hints, &ai_tcp);
33074800Salfred			if (ecode != 0)
33174800Salfred				err(1, "getaddrinfo tcp: %s", gai_strerror(ecode));
33274462Salfred			nconf_tcp = getnetconfigent("tcp");
33374462Salfred			if (nconf_tcp == NULL)
33474462Salfred				err(1, "getnetconfigent tcp failed");
33574462Salfred			nb_tcp.buf = ai_tcp->ai_addr;
33674462Salfred			nb_tcp.len = nb_tcp.maxlen = ai_tcp->ai_addrlen;
33774462Salfred			if ((!rpcb_set(RPCPROG_NFS, 2, nconf_tcp, &nb_tcp)) ||
33874462Salfred			    (!rpcb_set(RPCPROG_NFS, 3, nconf_tcp, &nb_tcp)))
33974462Salfred				err(1, "rpcb_set tcp failed");
34074462Salfred			freeaddrinfo(ai_tcp);
34174462Salfred		}
34274462Salfred		if (tcpflag && ip6flag) {
34374462Salfred			memset(&hints, 0, sizeof hints);
34474462Salfred			hints.ai_flags = AI_PASSIVE;
34574462Salfred			hints.ai_family = AF_INET6;
34674462Salfred			hints.ai_socktype = SOCK_STREAM;
34774462Salfred			hints.ai_protocol = IPPROTO_TCP;
34874462Salfred			ecode = getaddrinfo(NULL, "nfs", &hints, &ai_tcp6);
34974800Salfred			if (ecode != 0)
35074800Salfred				err(1, "getaddrinfo tcp6: %s", gai_strerror(ecode));
35174462Salfred			nconf_tcp6 = getnetconfigent("tcp6");
35274462Salfred			if (nconf_tcp6 == NULL)
35374462Salfred				err(1, "getnetconfigent tcp6 failed");
35474462Salfred			nb_tcp6.buf = ai_tcp6->ai_addr;
35574462Salfred			nb_tcp6.len = nb_tcp6.maxlen = ai_tcp6->ai_addrlen;
35674462Salfred			if ((!rpcb_set(RPCPROG_NFS, 2, nconf_tcp6, &nb_tcp6)) ||
35774462Salfred			    (!rpcb_set(RPCPROG_NFS, 3, nconf_tcp6, &nb_tcp6)))
35874462Salfred				err(1, "rpcb_set tcp6 failed");
35974462Salfred			freeaddrinfo(ai_tcp6);
36074462Salfred		}
36174462Salfred		exit (0);
3621558Srgrimes	}
36374800Salfred	if (debug == 0) {
36474800Salfred		daemon(0, 0);
36574800Salfred		(void)signal(SIGHUP, SIG_IGN);
36674800Salfred		(void)signal(SIGINT, SIG_IGN);
36774800Salfred		(void)signal(SIGSYS, nonfs);
36874800Salfred		(void)signal(SIGUSR1, cleanup);
36974800Salfred		/*
37074800Salfred		 * nfsd sits in the kernel most of the time.  It needs
37174800Salfred		 * to ignore SIGTERM/SIGQUIT in order to stay alive as long
37274800Salfred		 * as possible during a shutdown, otherwise loopback
37374800Salfred		 * mounts will not be able to unmount.
37474800Salfred		 */
37574800Salfred		(void)signal(SIGTERM, SIG_IGN);
37674800Salfred		(void)signal(SIGQUIT, SIG_IGN);
37774800Salfred	}
37874800Salfred	(void)signal(SIGCHLD, reapchild);
37974462Salfred
3801558Srgrimes	openlog("nfsd:", LOG_PID, LOG_DAEMON);
3811558Srgrimes
3821558Srgrimes	for (i = 0; i < nfsdcnt; i++) {
38374462Salfred		switch ((pid = fork())) {
3841558Srgrimes		case -1:
3851558Srgrimes			syslog(LOG_ERR, "fork: %m");
38674462Salfred			killchildren();
3871558Srgrimes			exit (1);
3881558Srgrimes		case 0:
3891558Srgrimes			break;
3901558Srgrimes		default:
39174462Salfred			children[i] = pid;
3921558Srgrimes			continue;
3931558Srgrimes		}
3941558Srgrimes
3959336Sdfr		setproctitle("server");
3961558Srgrimes		nfssvc_flag = NFSSVC_NFSD;
3971558Srgrimes		nsd.nsd_nfsd = NULL;
3989336Sdfr#ifdef NFSKERB
3999336Sdfr		if (sizeof (struct nfsrpc_fullverf) != RPCX_FULLVERF ||
4009336Sdfr		    sizeof (struct nfsrpc_fullblock) != RPCX_FULLBLOCK)
4019336Sdfr		    syslog(LOG_ERR, "Yikes NFSKERB structs not packed!");
4029336Sdfr		nsd.nsd_authstr = (u_char *)&kt;
4039336Sdfr		nsd.nsd_authlen = sizeof (kt);
4049336Sdfr		nsd.nsd_verfstr = (u_char *)&kverf;
4059336Sdfr		nsd.nsd_verflen = sizeof (kverf);
4061558Srgrimes#endif
4071558Srgrimes		while (nfssvc(nfssvc_flag, &nsd) < 0) {
4081558Srgrimes			if (errno != ENEEDAUTH) {
4091558Srgrimes				syslog(LOG_ERR, "nfssvc: %m");
4101558Srgrimes				exit(1);
4111558Srgrimes			}
4121558Srgrimes			nfssvc_flag = NFSSVC_NFSD | NFSSVC_AUTHINFAIL;
4139336Sdfr#ifdef NFSKERB
4149336Sdfr			/*
4159336Sdfr			 * Get the Kerberos ticket out of the authenticator
4169336Sdfr			 * verify it and convert the principal name to a user
4179336Sdfr			 * name. The user name is then converted to a set of
4189336Sdfr			 * user credentials via the password and group file.
4199336Sdfr			 * Finally, decrypt the timestamp and validate it.
4209336Sdfr			 * For more info see the IETF Draft "Authentication
4219336Sdfr			 * in ONC RPC".
4229336Sdfr			 */
4239336Sdfr			kt.length = ntohl(kt.length);
4249336Sdfr			if (gettimeofday(&ktv, (struct timezone *)0) == 0 &&
4259336Sdfr			    kt.length > 0 && kt.length <=
4269336Sdfr			    (RPCAUTH_MAXSIZ - 3 * NFSX_UNSIGNED)) {
4279336Sdfr			    kin.w1 = NFS_KERBW1(kt);
4289336Sdfr			    kt.mbz = 0;
4299336Sdfr			    (void)strcpy(inst, "*");
4309336Sdfr			    if (krb_rd_req(&kt, NFS_KERBSRV,
4319336Sdfr				inst, nsd.nsd_haddr, &kauth, "") == RD_AP_OK &&
4329336Sdfr				krb_kntoln(&kauth, lnam) == KSUCCESS &&
4339336Sdfr				(pwd = getpwnam(lnam)) != NULL) {
4341558Srgrimes				cr = &nsd.nsd_cr;
4351558Srgrimes				cr->cr_uid = pwd->pw_uid;
4361558Srgrimes				cr->cr_groups[0] = pwd->pw_gid;
4371558Srgrimes				cr->cr_ngroups = 1;
4381558Srgrimes				setgrent();
4391558Srgrimes				while ((grp = getgrent()) != NULL) {
4401558Srgrimes					if (grp->gr_gid == cr->cr_groups[0])
4411558Srgrimes						continue;
4421558Srgrimes					for (cpp = grp->gr_mem;
4431558Srgrimes					    *cpp != NULL; ++cpp)
4441558Srgrimes						if (!strcmp(*cpp, lnam))
4451558Srgrimes							break;
4461558Srgrimes					if (*cpp == NULL)
4471558Srgrimes						continue;
4481558Srgrimes					cr->cr_groups[cr->cr_ngroups++]
4491558Srgrimes					    = grp->gr_gid;
4501558Srgrimes					if (cr->cr_ngroups == NGROUPS)
4511558Srgrimes						break;
4521558Srgrimes				}
4531558Srgrimes				endgrent();
4549336Sdfr
4559336Sdfr				/*
4569336Sdfr				 * Get the timestamp verifier out of the
4579336Sdfr				 * authenticator and verifier strings.
4589336Sdfr				 */
4599336Sdfr				kin.t1 = kverf.t1;
4609336Sdfr				kin.t2 = kverf.t2;
4619336Sdfr				kin.w2 = kverf.w2;
4629336Sdfr				bzero((caddr_t)kivec, sizeof (kivec));
4639336Sdfr				bcopy((caddr_t)kauth.session,
4649336Sdfr				    (caddr_t)nsd.nsd_key,sizeof(kauth.session));
4659336Sdfr
4669336Sdfr				/*
4679336Sdfr				 * Decrypt the timestamp verifier in CBC mode.
4689336Sdfr				 */
4699336Sdfr				XXX
4709336Sdfr
4719336Sdfr				/*
4729336Sdfr				 * Validate the timestamp verifier, to
4739336Sdfr				 * check that the session key is ok.
4749336Sdfr				 */
4759336Sdfr				nsd.nsd_timestamp.tv_sec = ntohl(kout.t1);
4769336Sdfr				nsd.nsd_timestamp.tv_usec = ntohl(kout.t2);
4779336Sdfr				nsd.nsd_ttl = ntohl(kout.w1);
4789336Sdfr				if ((nsd.nsd_ttl - 1) == ntohl(kout.w2))
4799336Sdfr				    nfssvc_flag = NFSSVC_NFSD | NFSSVC_AUTHIN;
4801558Srgrimes			}
4819336Sdfr#endif /* NFSKERB */
4821558Srgrimes		}
4831558Srgrimes		exit(0);
4841558Srgrimes	}
4851558Srgrimes
48674462Salfred	if (atexit(killchildren) == -1) {
48774462Salfred 		syslog(LOG_ERR, "atexit: %s", strerror(errno));
48874462Salfred 		exit(1);
48974462Salfred 	}
49074462Salfred	FD_ZERO(&v4bits);
49174462Salfred	FD_ZERO(&v6bits);
49274462Salfred
49374462Salfred	rpcbregcnt = 0;
49474462Salfred	/* Set up the socket for udp and rpcb register it. */
49574462Salfred	if (udpflag) {
49674462Salfred		rpcbreg = 0;
49774462Salfred		for (i = 0; i < bindhostc; i++) {
49874462Salfred			memset(&hints, 0, sizeof hints);
49974462Salfred			hints.ai_flags = AI_PASSIVE;
50074462Salfred			hints.ai_family = AF_INET;
50174462Salfred			hints.ai_socktype = SOCK_DGRAM;
50274462Salfred			hints.ai_protocol = IPPROTO_UDP;
50374462Salfred			if (setbindhost(&ai_udp, bindhost[i], hints) == 0) {
50474462Salfred				rpcbreg = 1;
50574462Salfred				rpcbregcnt++;
50674462Salfred				if ((sock = socket(ai_udp->ai_family,
50774462Salfred				    ai_udp->ai_socktype,
50874462Salfred				    ai_udp->ai_protocol)) < 0) {
50974462Salfred					syslog(LOG_ERR,
51074462Salfred					    "can't create udp socket");
51174462Salfred					exit(1);
51274462Salfred				}
51374462Salfred				if (bind(sock, ai_udp->ai_addr,
51474462Salfred				    ai_udp->ai_addrlen) < 0) {
51574462Salfred					syslog(LOG_ERR,
51674462Salfred					    "can't bind udp addr %s: %m",
51774462Salfred					    bindhost[i]);
51874462Salfred					exit(1);
51974462Salfred				}
52074462Salfred				freeaddrinfo(ai_udp);
52174462Salfred				nfsdargs.sock = sock;
52274462Salfred				nfsdargs.name = NULL;
52374462Salfred				nfsdargs.namelen = 0;
52474462Salfred				if (nfssvc(NFSSVC_ADDSOCK, &nfsdargs) < 0) {
52574462Salfred					syslog(LOG_ERR, "can't Add UDP socket");
52674462Salfred					exit(1);
52774462Salfred				}
52874462Salfred				(void)close(sock);
52974462Salfred			}
5301558Srgrimes		}
53174462Salfred		if (rpcbreg == 1) {
53274462Salfred			memset(&hints, 0, sizeof hints);
53374462Salfred			hints.ai_flags = AI_PASSIVE;
53474462Salfred			hints.ai_family = AF_INET;
53574462Salfred			hints.ai_socktype = SOCK_DGRAM;
53674462Salfred			hints.ai_protocol = IPPROTO_UDP;
53774462Salfred			ecode = getaddrinfo(NULL, "nfs", &hints, &ai_udp);
53874462Salfred			if (ecode != 0) {
53974462Salfred				syslog(LOG_ERR, "getaddrinfo udp: %s",
54074462Salfred				   gai_strerror(ecode));
54174462Salfred				exit(1);
54274462Salfred			}
54374462Salfred			nconf_udp = getnetconfigent("udp");
54474462Salfred			if (nconf_udp == NULL)
54574462Salfred				err(1, "getnetconfigent udp failed");
54674462Salfred			nb_udp.buf = ai_udp->ai_addr;
54774462Salfred			nb_udp.len = nb_udp.maxlen = ai_udp->ai_addrlen;
54874462Salfred			if ((!rpcb_set(RPCPROG_NFS, 2, nconf_udp, &nb_udp)) ||
54974462Salfred			    (!rpcb_set(RPCPROG_NFS, 3, nconf_udp, &nb_udp)))
55074462Salfred				err(1, "rpcb_set udp failed");
55174462Salfred			freeaddrinfo(ai_udp);
5521558Srgrimes		}
5531558Srgrimes	}
5541558Srgrimes
55574462Salfred	/* Set up the socket for udp6 and rpcb register it. */
55674462Salfred	if (udpflag && ip6flag) {
55774462Salfred		rpcbreg = 0;
55874462Salfred		for (i = 0; i < bindhostc; i++) {
55974462Salfred			memset(&hints, 0, sizeof hints);
56074462Salfred			hints.ai_flags = AI_PASSIVE;
56174462Salfred			hints.ai_family = AF_INET6;
56274462Salfred			hints.ai_socktype = SOCK_DGRAM;
56374462Salfred			hints.ai_protocol = IPPROTO_UDP;
56474462Salfred			if (setbindhost(&ai_udp6, bindhost[i], hints) == 0) {
56574462Salfred				rpcbreg = 1;
56674462Salfred				rpcbregcnt++;
56774462Salfred				if ((sock = socket(ai_udp6->ai_family,
56874462Salfred				    ai_udp6->ai_socktype,
56974462Salfred				    ai_udp6->ai_protocol)) < 0) {
57074462Salfred					syslog(LOG_ERR,
57174462Salfred						"can't create udp6 socket");
57274462Salfred					exit(1);
57374462Salfred				}
57474462Salfred				if (setsockopt(sock, IPPROTO_IPV6,
57574462Salfred				    IPV6_BINDV6ONLY,
57674462Salfred				    &on, sizeof on) < 0) {
57774462Salfred					syslog(LOG_ERR,
57874462Salfred					    "can't set v6-only binding for "
57974462Salfred					    "udp6 socket: %m");
58074462Salfred					exit(1);
58174462Salfred				}
58274462Salfred				if (bind(sock, ai_udp6->ai_addr,
58374462Salfred				    ai_udp6->ai_addrlen) < 0) {
58474462Salfred					syslog(LOG_ERR,
58574462Salfred					    "can't bind udp6 addr %s: %m",
58674462Salfred					    bindhost[i]);
58774462Salfred					exit(1);
58874462Salfred				}
58974462Salfred				freeaddrinfo(ai_udp6);
59074462Salfred				nfsdargs.sock = sock;
59174462Salfred				nfsdargs.name = NULL;
59274462Salfred				nfsdargs.namelen = 0;
59374462Salfred				if (nfssvc(NFSSVC_ADDSOCK, &nfsdargs) < 0) {
59474462Salfred					syslog(LOG_ERR,
59574462Salfred					    "can't add UDP6 socket");
59674462Salfred					exit(1);
59774462Salfred				}
59874462Salfred				(void)close(sock);
59974462Salfred			}
6001558Srgrimes		}
60174462Salfred		if (rpcbreg == 1) {
60274462Salfred			memset(&hints, 0, sizeof hints);
60374462Salfred			hints.ai_flags = AI_PASSIVE;
60474462Salfred			hints.ai_family = AF_INET6;
60574462Salfred			hints.ai_socktype = SOCK_DGRAM;
60674462Salfred			hints.ai_protocol = IPPROTO_UDP;
60774462Salfred			ecode = getaddrinfo(NULL, "nfs", &hints, &ai_udp6);
60874462Salfred			if (ecode != 0) {
60974462Salfred				syslog(LOG_ERR, "getaddrinfo udp6: %s",
61074462Salfred				   gai_strerror(ecode));
61174462Salfred				exit(1);
61274462Salfred			}
61374462Salfred			nconf_udp6 = getnetconfigent("udp6");
61474462Salfred			if (nconf_udp6 == NULL)
61574462Salfred				err(1, "getnetconfigent udp6 failed");
61674462Salfred			nb_udp6.buf = ai_udp6->ai_addr;
61774462Salfred			nb_udp6.len = nb_udp6.maxlen = ai_udp6->ai_addrlen;
61874462Salfred			if ((!rpcb_set(RPCPROG_NFS, 2, nconf_udp6, &nb_udp6)) ||
61974462Salfred			    (!rpcb_set(RPCPROG_NFS, 3, nconf_udp6, &nb_udp6)))
62074462Salfred				err(1, "rpcb_set udp6 failed");
62174462Salfred			freeaddrinfo(ai_udp6);
6221558Srgrimes		}
6231558Srgrimes	}
6241558Srgrimes
62574462Salfred	/* Set up the socket for tcp and rpcb register it. */
62674462Salfred	if (tcpflag) {
62774462Salfred		rpcbreg = 0;
62874462Salfred		for (i = 0; i < bindhostc; i++) {
62974462Salfred			memset(&hints, 0, sizeof hints);
63074462Salfred			hints.ai_flags = AI_PASSIVE;
63174462Salfred			hints.ai_family = AF_INET;
63274462Salfred			hints.ai_socktype = SOCK_STREAM;
63374462Salfred			hints.ai_protocol = IPPROTO_TCP;
63474462Salfred			if (setbindhost(&ai_tcp, bindhost[i], hints) == 0) {
63574462Salfred				rpcbreg = 1;
63674462Salfred				rpcbregcnt++;
63774462Salfred				if ((tcpsock = socket(AF_INET, SOCK_STREAM,
63874462Salfred				    0)) < 0) {
63974462Salfred					syslog(LOG_ERR,
64074462Salfred					    "can't create tpc socket");
64174462Salfred					exit(1);
64274462Salfred				}
64374462Salfred				if (setsockopt(tcpsock, SOL_SOCKET,
64474462Salfred				    SO_REUSEADDR,
64574462Salfred				    (char *)&on, sizeof(on)) < 0)
64674462Salfred					syslog(LOG_ERR,
64774462Salfred					     "setsockopt SO_REUSEADDR: %m");
64874462Salfred				if (bind(tcpsock, ai_tcp->ai_addr,
64974462Salfred				    ai_tcp->ai_addrlen) < 0) {
65074462Salfred					syslog(LOG_ERR,
65174462Salfred					    "can't bind tcp addr %s: %m",
65274462Salfred					    bindhost[i]);
65374462Salfred					exit(1);
65474462Salfred				}
65574462Salfred				if (listen(tcpsock, 5) < 0) {
65674462Salfred					syslog(LOG_ERR, "listen failed");
65774462Salfred					exit(1);
65874462Salfred				}
65974462Salfred				freeaddrinfo(ai_tcp);
66074462Salfred				FD_SET(tcpsock, &sockbits);
66174462Salfred				FD_SET(tcpsock, &v4bits);
66274462Salfred				maxsock = tcpsock;
66374462Salfred				connect_type_cnt++;
66474462Salfred			}
6651558Srgrimes		}
66674462Salfred		if (rpcbreg == 1) {
66774462Salfred			memset(&hints, 0, sizeof hints);
66874462Salfred			hints.ai_flags = AI_PASSIVE;
66974462Salfred			hints.ai_family = AF_INET;
67074462Salfred			hints.ai_socktype = SOCK_STREAM;
67174462Salfred			hints.ai_protocol = IPPROTO_TCP;
67274462Salfred			ecode = getaddrinfo(NULL, "nfs", &hints,
67374462Salfred			     &ai_tcp);
67474462Salfred			if (ecode != 0) {
67574462Salfred				syslog(LOG_ERR, "getaddrinfo tcp: %s",
67674462Salfred				   gai_strerror(ecode));
67774462Salfred				exit(1);
67874462Salfred			}
67974462Salfred			nconf_tcp = getnetconfigent("tcp");
68074462Salfred			if (nconf_tcp == NULL)
68174462Salfred				err(1, "getnetconfigent tcp failed");
68274462Salfred			nb_tcp.buf = ai_tcp->ai_addr;
68374462Salfred			nb_tcp.len = nb_tcp.maxlen = ai_tcp->ai_addrlen;
68474462Salfred			if ((!rpcb_set(RPCPROG_NFS, 2, nconf_tcp,
68574462Salfred			    &nb_tcp)) || (!rpcb_set(RPCPROG_NFS, 3,
68674462Salfred			    nconf_tcp, &nb_tcp)))
68774462Salfred				err(1, "rpcb_set tcp failed");
68874462Salfred			freeaddrinfo(ai_tcp);
6891558Srgrimes		}
6901558Srgrimes	}
6911558Srgrimes
69274462Salfred	/* Set up the socket for tcp6 and rpcb register it. */
69374462Salfred	if (tcpflag && ip6flag) {
69474462Salfred		rpcbreg = 0;
69574462Salfred		for (i = 0; i < bindhostc; i++) {
69674462Salfred			memset(&hints, 0, sizeof hints);
69774462Salfred			hints.ai_flags = AI_PASSIVE;
69874462Salfred			hints.ai_family = AF_INET6;
69974462Salfred			hints.ai_socktype = SOCK_STREAM;
70074462Salfred			hints.ai_protocol = IPPROTO_TCP;
70174462Salfred			if (setbindhost(&ai_tcp6, bindhost[i], hints) == 0) {
70274462Salfred				rpcbreg = 1;
70374462Salfred				rpcbregcnt++;
70474462Salfred				if ((tcp6sock = socket(ai_tcp6->ai_family,
70574462Salfred				    ai_tcp6->ai_socktype,
70674462Salfred				    ai_tcp6->ai_protocol)) < 0) {
70774462Salfred					syslog(LOG_ERR,
70874462Salfred					    "can't create tcp6 socket");
70974462Salfred					exit(1);
71074462Salfred				}
71174462Salfred				if (setsockopt(tcp6sock, SOL_SOCKET,
71274462Salfred				    SO_REUSEADDR,
71374462Salfred				    (char *)&on, sizeof(on)) < 0)
71474462Salfred					syslog(LOG_ERR,
71574462Salfred					    "setsockopt SO_REUSEADDR: %m");
71674462Salfred				if (setsockopt(tcp6sock, IPPROTO_IPV6,
71774462Salfred				    IPV6_BINDV6ONLY, &on, sizeof on) < 0) {
71874462Salfred					syslog(LOG_ERR,
71974462Salfred					"can't set v6-only binding for tcp6 "
72074462Salfred					    "socket: %m");
72174462Salfred					exit(1);
72274462Salfred				}
72374462Salfred				if (bind(tcp6sock, ai_tcp6->ai_addr,
72474462Salfred				    ai_tcp6->ai_addrlen) < 0) {
72574462Salfred					syslog(LOG_ERR,
72674462Salfred					    "can't bind tcp6 addr %s: %m",
72774462Salfred					    bindhost[i]);
72874462Salfred					exit(1);
72974462Salfred				}
73074462Salfred				if (listen(tcp6sock, 5) < 0) {
73174462Salfred					syslog(LOG_ERR, "listen failed");
73274462Salfred					exit(1);
73374462Salfred				}
73474462Salfred				freeaddrinfo(ai_tcp6);
73574462Salfred				FD_SET(tcp6sock, &sockbits);
73674462Salfred				FD_SET(tcp6sock, &v6bits);
73774462Salfred				if (maxsock < tcp6sock)
73874462Salfred					maxsock = tcp6sock;
73974462Salfred				connect_type_cnt++;
74074462Salfred			}
7411558Srgrimes		}
74274462Salfred		if (rpcbreg == 1) {
74374462Salfred			memset(&hints, 0, sizeof hints);
74474462Salfred			hints.ai_flags = AI_PASSIVE;
74574462Salfred			hints.ai_family = AF_INET6;
74674462Salfred			hints.ai_socktype = SOCK_STREAM;
74774462Salfred			hints.ai_protocol = IPPROTO_TCP;
74874462Salfred			ecode = getaddrinfo(NULL, "nfs", &hints, &ai_tcp6);
74974462Salfred			if (ecode != 0) {
75074462Salfred				syslog(LOG_ERR, "getaddrinfo tcp6: %s",
75174462Salfred				   gai_strerror(ecode));
75274462Salfred				exit(1);
75374462Salfred			}
75474462Salfred			nconf_tcp6 = getnetconfigent("tcp6");
75574462Salfred			if (nconf_tcp6 == NULL)
75674462Salfred				err(1, "getnetconfigent tcp6 failed");
75774462Salfred			nb_tcp6.buf = ai_tcp6->ai_addr;
75874462Salfred			nb_tcp6.len = nb_tcp6.maxlen = ai_tcp6->ai_addrlen;
75974462Salfred			if ((!rpcb_set(RPCPROG_NFS, 2, nconf_tcp6, &nb_tcp6)) ||
76074462Salfred			    (!rpcb_set(RPCPROG_NFS, 3, nconf_tcp6, &nb_tcp6)))
76174462Salfred				err(1, "rpcb_set tcp6 failed");
76274462Salfred			freeaddrinfo(ai_tcp6);
7631558Srgrimes		}
7641558Srgrimes	}
7651558Srgrimes
76674462Salfred	if (rpcbregcnt == 0) {
76774462Salfred		syslog(LOG_ERR, "rpcb_set() failed, nothing to do: %m");
76874462Salfred		exit(1);
7691558Srgrimes	}
7701558Srgrimes
77174462Salfred	if ((tcpflag) && (connect_type_cnt == 0)) {
77274462Salfred		syslog(LOG_ERR, "tcp connects == 0, nothing to do: %m");
77374462Salfred		exit(1);
77474462Salfred	}
7751558Srgrimes
7769336Sdfr	setproctitle("master");
7771558Srgrimes
7781558Srgrimes	/*
7791558Srgrimes	 * Loop forever accepting connections and passing the sockets
7801558Srgrimes	 * into the kernel for the mounts.
7811558Srgrimes	 */
7821558Srgrimes	for (;;) {
7831558Srgrimes		ready = sockbits;
7841558Srgrimes		if (connect_type_cnt > 1) {
7851558Srgrimes			if (select(maxsock + 1,
7861558Srgrimes			    &ready, NULL, NULL, NULL) < 1) {
7871558Srgrimes				syslog(LOG_ERR, "select failed: %m");
7881558Srgrimes				exit(1);
7891558Srgrimes			}
7901558Srgrimes		}
79174462Salfred		for (tcpsock = 0; tcpsock <= maxsock; tcpsock++) {
79274462Salfred			if (FD_ISSET(tcpsock, &ready)) {
79374462Salfred				if (FD_ISSET(tcpsock, &v4bits)) {
79474462Salfred					len = sizeof(inetpeer);
79574462Salfred					if ((msgsock = accept(tcpsock,
79674462Salfred					    (struct sockaddr *)&inetpeer, &len)) < 0) {
79774462Salfred						syslog(LOG_ERR, "accept failed: %m");
79874462Salfred						exit(1);
79974462Salfred					}
80074462Salfred					memset(inetpeer.sin_zero, 0,
80174462Salfred						sizeof(inetpeer.sin_zero));
80274462Salfred					if (setsockopt(msgsock, SOL_SOCKET,
80374462Salfred					    SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0)
80474462Salfred						syslog(LOG_ERR,
80574462Salfred						    "setsockopt SO_KEEPALIVE: %m");
80674462Salfred					nfsdargs.sock = msgsock;
80774462Salfred					nfsdargs.name = (caddr_t)&inetpeer;
80874462Salfred					nfsdargs.namelen = sizeof(inetpeer);
80974462Salfred					nfssvc(NFSSVC_ADDSOCK, &nfsdargs);
81074462Salfred					(void)close(msgsock);
81174462Salfred				} else if (FD_ISSET(tcpsock, &v6bits)) {
81274462Salfred					len = sizeof(inet6peer);
81374462Salfred					if ((msgsock = accept(tcpsock,
81474462Salfred					    (struct sockaddr *)&inet6peer,
81574462Salfred					    &len)) < 0) {
81674462Salfred						syslog(LOG_ERR,
81774462Salfred						     "accept failed: %m");
81874462Salfred						exit(1);
81974462Salfred					}
82074462Salfred					if (setsockopt(msgsock, SOL_SOCKET,
82174462Salfred					    SO_KEEPALIVE, (char *)&on,
82274462Salfred					    sizeof(on)) < 0)
82374462Salfred						syslog(LOG_ERR, "setsockopt "
82474462Salfred						    "SO_KEEPALIVE: %m");
82574462Salfred					nfsdargs.sock = msgsock;
82674462Salfred					nfsdargs.name = (caddr_t)&inet6peer;
82774462Salfred					nfsdargs.namelen = sizeof(inet6peer);
82874462Salfred					nfssvc(NFSSVC_ADDSOCK, &nfsdargs);
82974462Salfred					(void)close(msgsock);
83074462Salfred				}
8311558Srgrimes			}
8321558Srgrimes		}
8331558Srgrimes	}
8341558Srgrimes}
8351558Srgrimes
83674462Salfredint
83774462Salfredsetbindhost(struct addrinfo **ai, const char *bindhost, struct addrinfo hints)
83853096Sdillon{
83974462Salfred	int ecode;
84074462Salfred	u_int32_t host_addr[4];  /* IPv4 or IPv6 */
84174462Salfred	const char *hostptr;
84253096Sdillon
84374462Salfred	if (bindhost == NULL || strcmp("*", bindhost) == 0)
84474462Salfred		hostptr = NULL;
84574462Salfred	else
84674462Salfred		hostptr = bindhost;
84774462Salfred
84874462Salfred	if (hostptr != NULL) {
84974462Salfred		switch (hints.ai_family) {
85074462Salfred		case AF_INET:
85174462Salfred			if (inet_pton(AF_INET, hostptr, host_addr) == 1) {
85274462Salfred				hints.ai_flags = AI_NUMERICHOST;
85374462Salfred			} else {
85474462Salfred				if (inet_pton(AF_INET6, hostptr,
85574462Salfred				    host_addr) == 1)
85674462Salfred					return (1);
85753096Sdillon			}
85874462Salfred			break;
85974462Salfred		case AF_INET6:
86074462Salfred			if (inet_pton(AF_INET6, hostptr, host_addr) == 1) {
86174462Salfred				hints.ai_flags = AI_NUMERICHOST;
86274462Salfred			} else {
86374462Salfred				if (inet_pton(AF_INET, hostptr,
86474462Salfred				    host_addr) == 1)
86574462Salfred					return (1);
86674462Salfred			}
86774462Salfred			break;
86874462Salfred		default:
86953096Sdillon		}
87053096Sdillon	}
87174462Salfred
87274462Salfred	ecode = getaddrinfo(hostptr, "nfs", &hints, ai);
87374462Salfred	if (ecode != 0) {
87474462Salfred		syslog(LOG_ERR, "getaddrinfo %s: %s", bindhost,
87574462Salfred		    gai_strerror(ecode));
87674462Salfred		return (1);
87774462Salfred	}
87874462Salfred	return (0);
87953096Sdillon}
88053096Sdillon
88153096Sdillonvoid
8821558Srgrimesusage()
8831558Srgrimes{
8849336Sdfr	(void)fprintf(stderr, "usage: nfsd %s\n", USAGE);
8851558Srgrimes	exit(1);
8861558Srgrimes}
8871558Srgrimes
8881558Srgrimesvoid
8891558Srgrimesnonfs(signo)
8901558Srgrimes	int signo;
8911558Srgrimes{
89237666Scharnier	syslog(LOG_ERR, "missing system call: NFS not available");
8931558Srgrimes}
8941558Srgrimes
8951558Srgrimesvoid
8961558Srgrimesreapchild(signo)
8971558Srgrimes	int signo;
8981558Srgrimes{
8991558Srgrimes
9009336Sdfr	while (wait3(NULL, WNOHANG, NULL) > 0);
9011558Srgrimes}
9021558Srgrimes
90374462Salfredvoid
90474462Salfredunregistration()
90574462Salfred{
90674462Salfred	if ((!rpcb_unset(RPCPROG_NFS, 2, NULL)) ||
90774462Salfred	    (!rpcb_unset(RPCPROG_NFS, 3, NULL)))
90874462Salfred		syslog(LOG_ERR, "rpcb_unset failed");
90974462Salfred}
91074462Salfred
91174462Salfredvoid
91274462Salfredkillchildren()
91374462Salfred{
91474462Salfred	int i;
91574462Salfred	sigset_t sigs;
91674462Salfred
91774462Salfred	sigemptyset(&sigs);
91874462Salfred	/*
91974462Salfred	* Block SIGCHLD to avoid killing a reaped process (although it is
92074462Salfred	* unlikely, the pid might have been reused).
92174462Salfred	*/
92274462Salfred	sigaddset(&sigs, SIGCHLD);
92374462Salfred	if (sigprocmask(SIG_BLOCK, &sigs, NULL) == -1) {
92474462Salfred		syslog(LOG_ERR, "sigprocmask: %s",
92574462Salfred		   strerror(errno));
92674462Salfred		return;
92774462Salfred	}
92874462Salfred	for (i = 0; i < nfsdcnt; i++) {
92974462Salfred		if (children[i] > 0)
93074462Salfred			kill(children[i], SIGKILL);
93174462Salfred	}
93274462Salfred	if (sigprocmask(SIG_UNBLOCK, &sigs, NULL) == -1) {
93374462Salfred		syslog(LOG_ERR, "sigprocmask: %s", strerror(errno));
93474462Salfred	}
93574462Salfred	unregistration();
93674462Salfred}
93774462Salfred
93874462Salfredvoid
93974462Salfredcleanup(signo)
94074462Salfred{
94174462Salfred	killchildren();
94274462Salfred	exit (0);
94374462Salfred}
94474462Salfred
94513141Speter#ifdef OLD_SETPROCTITLE
9469336Sdfr#ifdef __FreeBSD__
9471558Srgrimesvoid
9481558Srgrimessetproctitle(a)
9491558Srgrimes	char *a;
9501558Srgrimes{
9511558Srgrimes	register char *cp;
9521558Srgrimes	char buf[80];
9531558Srgrimes
9541558Srgrimes	cp = Argv[0];
9559336Sdfr	(void)snprintf(buf, sizeof(buf), "nfsd-%s", a);
9561558Srgrimes	(void)strncpy(cp, buf, LastArg - cp);
9571558Srgrimes	cp += strlen(cp);
9581558Srgrimes	while (cp < LastArg)
9592030Sdg		*cp++ = '\0';
96012869Speter	Argv[1] = NULL;
9611558Srgrimes}
9629336Sdfr#endif	/* __FreeBSD__ */
96313141Speter#endif
964