nfsd.c revision 74800
1/*
2 * Copyright (c) 1989, 1993, 1994
3 *	The Regents of the University of California.  All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Rick Macklem at The University of Guelph.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 *    must display the following acknowledgement:
18 *	This product includes software developed by the University of
19 *	California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 *    may be used to endorse or promote products derived from this software
22 *    without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 */
36
37#ifndef lint
38static const char copyright[] =
39"@(#) Copyright (c) 1989, 1993, 1994\n\
40	The Regents of the University of California.  All rights reserved.\n";
41#endif not lint
42
43#ifndef lint
44#if 0
45static char sccsid[] = "@(#)nfsd.c	8.9 (Berkeley) 3/29/95";
46#endif
47static const char rcsid[] =
48  "$FreeBSD: head/usr.sbin/nfsd/nfsd.c 74800 2001-03-25 23:32:55Z alfred $";
49#endif not lint
50
51#include <sys/param.h>
52#include <sys/syslog.h>
53#include <sys/wait.h>
54#include <sys/mount.h>
55
56#include <rpc/rpc.h>
57#include <rpc/pmap_clnt.h>
58
59#include <netdb.h>
60#include <arpa/inet.h>
61#include <nfs/rpcv2.h>
62#include <nfs/nfsproto.h>
63#include <nfs/nfs.h>
64
65#ifdef NFSKERB
66#include <kerberosIV/des.h>
67#include <kerberosIV/krb.h>
68#endif
69
70#include <err.h>
71#include <errno.h>
72#include <stdio.h>
73#include <stdlib.h>
74#include <strings.h>
75#include <unistd.h>
76#include <netdb.h>
77
78/* Global defs */
79#ifdef DEBUG
80#define	syslog(e, s)	fprintf(stderr,(s))
81int	debug = 1;
82#else
83int	debug = 0;
84#endif
85
86struct	nfsd_srvargs nsd;
87#ifdef OLD_SETPROCTITLE
88char	**Argv = NULL;		/* pointer to argument vector */
89char	*LastArg = NULL;	/* end of argv */
90#endif
91
92#ifdef NFSKERB
93char		lnam[ANAME_SZ];
94KTEXT_ST	kt;
95AUTH_DAT	kauth;
96char		inst[INST_SZ];
97struct nfsrpc_fullblock kin, kout;
98struct nfsrpc_fullverf kverf;
99NFSKERBKEY_T	kivec;
100struct timeval	ktv;
101NFSKERBKEYSCHED_T kerb_keysched;
102#endif
103
104#define	MAXNFSDCNT	20
105#define	DEFNFSDCNT	 4
106pid_t	children[MAXNFSDCNT];	/* PIDs of children */
107int	nfsdcnt;		/* number of children */
108
109void	cleanup(int);
110void	killchildren(void);
111void	nonfs (int);
112void	reapchild (int);
113int	setbindhost (struct addrinfo **ia, const char *bindhost, struct addrinfo hints);
114#ifdef OLD_SETPROCTITLE
115#ifdef __FreeBSD__
116void	setproctitle (char *);
117#endif
118#endif
119void	unregistration (void);
120void	usage (void);
121
122/*
123 * Nfs server daemon mostly just a user context for nfssvc()
124 *
125 * 1 - do file descriptor and signal cleanup
126 * 2 - fork the nfsd(s)
127 * 3 - create server socket(s)
128 * 4 - register socket with rpcbind
129 *
130 * For connectionless protocols, just pass the socket into the kernel via.
131 * nfssvc().
132 * For connection based sockets, loop doing accepts. When you get a new
133 * socket from accept, pass the msgsock into the kernel via. nfssvc().
134 * The arguments are:
135 *	-c - support iso cltp clients
136 *	-r - reregister with rpcbind
137 *	-d - unregister with rpcbind
138 *	-t - support tcp nfs clients
139 *	-u - support udp nfs clients
140 * followed by "n" which is the number of nfsds' to fork off
141 */
142int
143main(argc, argv, envp)
144	int argc;
145	char *argv[], *envp[];
146{
147	struct nfsd_args nfsdargs;
148	struct addrinfo *ai_udp, *ai_tcp, *ai_udp6, *ai_tcp6, hints;
149	struct netconfig *nconf_udp, *nconf_tcp, *nconf_udp6, *nconf_tcp6;
150	struct netbuf nb_udp, nb_tcp, nb_udp6, nb_tcp6;
151	struct sockaddr_in inetpeer;
152	struct sockaddr_in6 inet6peer;
153	fd_set ready, sockbits;
154	fd_set v4bits, v6bits;
155	int ch, cltpflag, connect_type_cnt, i, len, maxsock, msgsock;
156	int nfssvc_flag, on = 1, unregister, reregister, sock;
157	int tcp6sock, ip6flag, tcpflag, tcpsock;
158	int udpflag, ecode, s;
159	int bindhostc = 0, bindanyflag, rpcbreg, rpcbregcnt;
160	char **bindhost = NULL;
161	pid_t pid;
162#ifdef NFSKERB
163	struct group *grp;
164	struct passwd *pwd;
165	struct ucred *cr;
166	struct timeval ktv;
167	char **cpp;
168#endif
169#ifdef __FreeBSD__
170	struct vfsconf vfc;
171	int error;
172
173	error = getvfsbyname("nfs", &vfc);
174	if (error && vfsisloadable("nfs")) {
175		if (vfsload("nfs"))
176			err(1, "vfsload(nfs)");
177		endvfsent();	/* flush cache */
178		error = getvfsbyname("nfs", &vfc);
179	}
180	if (error)
181		errx(1, "NFS is not available in the running kernel");
182#endif
183
184#ifdef OLD_SETPROCTITLE
185	/* Save start and extent of argv for setproctitle. */
186	Argv = argv;
187	if (envp == 0 || *envp == 0)
188		envp = argv;
189	while (*envp)
190		envp++;
191	LastArg = envp[-1] + strlen(envp[-1]);
192#endif
193
194	nfsdcnt = DEFNFSDCNT;
195	cltpflag = unregister = reregister = tcpflag = 0;
196	bindanyflag = udpflag;
197#define	GETOPT	"ah:n:rdtu"
198#define	USAGE	"[-ardtu] [-n num_servers] [-h bindip]"
199	while ((ch = getopt(argc, argv, GETOPT)) != -1)
200		switch (ch) {
201		case 'a':
202			bindanyflag = 1;
203			break;
204		case 'n':
205			nfsdcnt = atoi(optarg);
206			if (nfsdcnt < 1 || nfsdcnt > MAXNFSDCNT) {
207				warnx("nfsd count %d; reset to %d", nfsdcnt,
208				    DEFNFSDCNT);
209				nfsdcnt = DEFNFSDCNT;
210			}
211			break;
212		case 'h':
213			bindhostc++;
214			bindhost = realloc(bindhost,sizeof(char *)*bindhostc);
215			if (bindhost == NULL)
216				errx(1, "Out of memory");
217			bindhost[bindhostc-1] = strdup(optarg);
218			if (bindhost[bindhostc-1] == NULL)
219				errx(1, "Out of memory");
220			break;
221		case 'r':
222			reregister = 1;
223			break;
224		case 'd':
225			unregister = 1;
226			break;
227		case 't':
228			tcpflag = 1;
229			break;
230		case 'u':
231			udpflag = 1;
232			break;
233		default:
234		case '?':
235			usage();
236		};
237	if (!tcpflag && !udpflag)
238		udpflag = 1;
239	argv += optind;
240	argc -= optind;
241
242	/*
243	 * XXX
244	 * Backward compatibility, trailing number is the count of daemons.
245	 */
246	if (argc > 1)
247		usage();
248	if (argc == 1) {
249		nfsdcnt = atoi(argv[0]);
250		if (nfsdcnt < 1 || nfsdcnt > MAXNFSDCNT) {
251			warnx("nfsd count %d; reset to %d", nfsdcnt,
252			    DEFNFSDCNT);
253			nfsdcnt = DEFNFSDCNT;
254		}
255	}
256
257	ip6flag = 1;
258	s = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
259	if (s == -1) {
260		if (errno != EPROTONOSUPPORT)
261			err(1, "socket");
262		ip6flag = 0;
263	} else if (getnetconfigent("udp6") == NULL ||
264		getnetconfigent("tcp6") == NULL) {
265		ip6flag = 0;
266	}
267	if (s != -1)
268		close(s);
269
270	if (bindhostc == 0 || bindanyflag) {
271		bindhostc++;
272		bindhost = realloc(bindhost,sizeof(char *)*bindhostc);
273		if (bindhost == NULL)
274			errx(1, "Out of memory");
275		bindhost[bindhostc-1] = strdup("*");
276		if (bindhost[bindhostc-1] == NULL)
277			errx(1, "Out of memory");
278	}
279
280	if (unregister) {
281		unregistration();
282		exit (0);
283	}
284	if (reregister) {
285		if (udpflag) {
286			memset(&hints, 0, sizeof hints);
287			hints.ai_flags = AI_PASSIVE;
288			hints.ai_family = AF_INET;
289			hints.ai_socktype = SOCK_DGRAM;
290			hints.ai_protocol = IPPROTO_UDP;
291			ecode = getaddrinfo(NULL, "nfs", &hints, &ai_udp);
292			if (ecode != 0)
293				err(1, "getaddrinfo udp: %s", gai_strerror(ecode));
294			nconf_udp = getnetconfigent("udp");
295			if (nconf_udp == NULL)
296				err(1, "getnetconfigent udp failed");
297			nb_udp.buf = ai_udp->ai_addr;
298			nb_udp.len = nb_udp.maxlen = ai_udp->ai_addrlen;
299			if ((!rpcb_set(RPCPROG_NFS, 2, nconf_udp, &nb_udp)) ||
300			    (!rpcb_set(RPCPROG_NFS, 3, nconf_udp, &nb_udp)))
301				err(1, "rpcb_set udp failed");
302			freeaddrinfo(ai_udp);
303		}
304		if (udpflag && ip6flag) {
305			memset(&hints, 0, sizeof hints);
306			hints.ai_flags = AI_PASSIVE;
307			hints.ai_family = AF_INET6;
308			hints.ai_socktype = SOCK_DGRAM;
309			hints.ai_protocol = IPPROTO_UDP;
310			ecode = getaddrinfo(NULL, "nfs", &hints, &ai_udp6);
311			if (ecode != 0)
312				err(1, "getaddrinfo udp6: %s", gai_strerror(ecode));
313			nconf_udp6 = getnetconfigent("udp6");
314			if (nconf_udp6 == NULL)
315				err(1, "getnetconfigent udp6 failed");
316			nb_udp6.buf = ai_udp6->ai_addr;
317			nb_udp6.len = nb_udp6.maxlen = ai_udp6->ai_addrlen;
318			if ((!rpcb_set(RPCPROG_NFS, 2, nconf_udp6, &nb_udp6)) ||
319			    (!rpcb_set(RPCPROG_NFS, 3, nconf_udp6, &nb_udp6)))
320				err(1, "rpcb_set udp6 failed");
321			freeaddrinfo(ai_udp6);
322		}
323		if (tcpflag) {
324			memset(&hints, 0, sizeof hints);
325			hints.ai_flags = AI_PASSIVE;
326			hints.ai_family = AF_INET;
327			hints.ai_socktype = SOCK_STREAM;
328			hints.ai_protocol = IPPROTO_TCP;
329			ecode = getaddrinfo(NULL, "nfs", &hints, &ai_tcp);
330			if (ecode != 0)
331				err(1, "getaddrinfo tcp: %s", gai_strerror(ecode));
332			nconf_tcp = getnetconfigent("tcp");
333			if (nconf_tcp == NULL)
334				err(1, "getnetconfigent tcp failed");
335			nb_tcp.buf = ai_tcp->ai_addr;
336			nb_tcp.len = nb_tcp.maxlen = ai_tcp->ai_addrlen;
337			if ((!rpcb_set(RPCPROG_NFS, 2, nconf_tcp, &nb_tcp)) ||
338			    (!rpcb_set(RPCPROG_NFS, 3, nconf_tcp, &nb_tcp)))
339				err(1, "rpcb_set tcp failed");
340			freeaddrinfo(ai_tcp);
341		}
342		if (tcpflag && ip6flag) {
343			memset(&hints, 0, sizeof hints);
344			hints.ai_flags = AI_PASSIVE;
345			hints.ai_family = AF_INET6;
346			hints.ai_socktype = SOCK_STREAM;
347			hints.ai_protocol = IPPROTO_TCP;
348			ecode = getaddrinfo(NULL, "nfs", &hints, &ai_tcp6);
349			if (ecode != 0)
350				err(1, "getaddrinfo tcp6: %s", gai_strerror(ecode));
351			nconf_tcp6 = getnetconfigent("tcp6");
352			if (nconf_tcp6 == NULL)
353				err(1, "getnetconfigent tcp6 failed");
354			nb_tcp6.buf = ai_tcp6->ai_addr;
355			nb_tcp6.len = nb_tcp6.maxlen = ai_tcp6->ai_addrlen;
356			if ((!rpcb_set(RPCPROG_NFS, 2, nconf_tcp6, &nb_tcp6)) ||
357			    (!rpcb_set(RPCPROG_NFS, 3, nconf_tcp6, &nb_tcp6)))
358				err(1, "rpcb_set tcp6 failed");
359			freeaddrinfo(ai_tcp6);
360		}
361		exit (0);
362	}
363	if (debug == 0) {
364		daemon(0, 0);
365		(void)signal(SIGHUP, SIG_IGN);
366		(void)signal(SIGINT, SIG_IGN);
367		(void)signal(SIGSYS, nonfs);
368		(void)signal(SIGUSR1, cleanup);
369		/*
370		 * nfsd sits in the kernel most of the time.  It needs
371		 * to ignore SIGTERM/SIGQUIT in order to stay alive as long
372		 * as possible during a shutdown, otherwise loopback
373		 * mounts will not be able to unmount.
374		 */
375		(void)signal(SIGTERM, SIG_IGN);
376		(void)signal(SIGQUIT, SIG_IGN);
377	}
378	(void)signal(SIGCHLD, reapchild);
379
380	openlog("nfsd:", LOG_PID, LOG_DAEMON);
381
382	for (i = 0; i < nfsdcnt; i++) {
383		switch ((pid = fork())) {
384		case -1:
385			syslog(LOG_ERR, "fork: %m");
386			killchildren();
387			exit (1);
388		case 0:
389			break;
390		default:
391			children[i] = pid;
392			continue;
393		}
394
395		setproctitle("server");
396		nfssvc_flag = NFSSVC_NFSD;
397		nsd.nsd_nfsd = NULL;
398#ifdef NFSKERB
399		if (sizeof (struct nfsrpc_fullverf) != RPCX_FULLVERF ||
400		    sizeof (struct nfsrpc_fullblock) != RPCX_FULLBLOCK)
401		    syslog(LOG_ERR, "Yikes NFSKERB structs not packed!");
402		nsd.nsd_authstr = (u_char *)&kt;
403		nsd.nsd_authlen = sizeof (kt);
404		nsd.nsd_verfstr = (u_char *)&kverf;
405		nsd.nsd_verflen = sizeof (kverf);
406#endif
407		while (nfssvc(nfssvc_flag, &nsd) < 0) {
408			if (errno != ENEEDAUTH) {
409				syslog(LOG_ERR, "nfssvc: %m");
410				exit(1);
411			}
412			nfssvc_flag = NFSSVC_NFSD | NFSSVC_AUTHINFAIL;
413#ifdef NFSKERB
414			/*
415			 * Get the Kerberos ticket out of the authenticator
416			 * verify it and convert the principal name to a user
417			 * name. The user name is then converted to a set of
418			 * user credentials via the password and group file.
419			 * Finally, decrypt the timestamp and validate it.
420			 * For more info see the IETF Draft "Authentication
421			 * in ONC RPC".
422			 */
423			kt.length = ntohl(kt.length);
424			if (gettimeofday(&ktv, (struct timezone *)0) == 0 &&
425			    kt.length > 0 && kt.length <=
426			    (RPCAUTH_MAXSIZ - 3 * NFSX_UNSIGNED)) {
427			    kin.w1 = NFS_KERBW1(kt);
428			    kt.mbz = 0;
429			    (void)strcpy(inst, "*");
430			    if (krb_rd_req(&kt, NFS_KERBSRV,
431				inst, nsd.nsd_haddr, &kauth, "") == RD_AP_OK &&
432				krb_kntoln(&kauth, lnam) == KSUCCESS &&
433				(pwd = getpwnam(lnam)) != NULL) {
434				cr = &nsd.nsd_cr;
435				cr->cr_uid = pwd->pw_uid;
436				cr->cr_groups[0] = pwd->pw_gid;
437				cr->cr_ngroups = 1;
438				setgrent();
439				while ((grp = getgrent()) != NULL) {
440					if (grp->gr_gid == cr->cr_groups[0])
441						continue;
442					for (cpp = grp->gr_mem;
443					    *cpp != NULL; ++cpp)
444						if (!strcmp(*cpp, lnam))
445							break;
446					if (*cpp == NULL)
447						continue;
448					cr->cr_groups[cr->cr_ngroups++]
449					    = grp->gr_gid;
450					if (cr->cr_ngroups == NGROUPS)
451						break;
452				}
453				endgrent();
454
455				/*
456				 * Get the timestamp verifier out of the
457				 * authenticator and verifier strings.
458				 */
459				kin.t1 = kverf.t1;
460				kin.t2 = kverf.t2;
461				kin.w2 = kverf.w2;
462				bzero((caddr_t)kivec, sizeof (kivec));
463				bcopy((caddr_t)kauth.session,
464				    (caddr_t)nsd.nsd_key,sizeof(kauth.session));
465
466				/*
467				 * Decrypt the timestamp verifier in CBC mode.
468				 */
469				XXX
470
471				/*
472				 * Validate the timestamp verifier, to
473				 * check that the session key is ok.
474				 */
475				nsd.nsd_timestamp.tv_sec = ntohl(kout.t1);
476				nsd.nsd_timestamp.tv_usec = ntohl(kout.t2);
477				nsd.nsd_ttl = ntohl(kout.w1);
478				if ((nsd.nsd_ttl - 1) == ntohl(kout.w2))
479				    nfssvc_flag = NFSSVC_NFSD | NFSSVC_AUTHIN;
480			}
481#endif /* NFSKERB */
482		}
483		exit(0);
484	}
485
486	if (atexit(killchildren) == -1) {
487 		syslog(LOG_ERR, "atexit: %s", strerror(errno));
488 		exit(1);
489 	}
490	FD_ZERO(&v4bits);
491	FD_ZERO(&v6bits);
492
493	rpcbregcnt = 0;
494	/* Set up the socket for udp and rpcb register it. */
495	if (udpflag) {
496		rpcbreg = 0;
497		for (i = 0; i < bindhostc; i++) {
498			memset(&hints, 0, sizeof hints);
499			hints.ai_flags = AI_PASSIVE;
500			hints.ai_family = AF_INET;
501			hints.ai_socktype = SOCK_DGRAM;
502			hints.ai_protocol = IPPROTO_UDP;
503			if (setbindhost(&ai_udp, bindhost[i], hints) == 0) {
504				rpcbreg = 1;
505				rpcbregcnt++;
506				if ((sock = socket(ai_udp->ai_family,
507				    ai_udp->ai_socktype,
508				    ai_udp->ai_protocol)) < 0) {
509					syslog(LOG_ERR,
510					    "can't create udp socket");
511					exit(1);
512				}
513				if (bind(sock, ai_udp->ai_addr,
514				    ai_udp->ai_addrlen) < 0) {
515					syslog(LOG_ERR,
516					    "can't bind udp addr %s: %m",
517					    bindhost[i]);
518					exit(1);
519				}
520				freeaddrinfo(ai_udp);
521				nfsdargs.sock = sock;
522				nfsdargs.name = NULL;
523				nfsdargs.namelen = 0;
524				if (nfssvc(NFSSVC_ADDSOCK, &nfsdargs) < 0) {
525					syslog(LOG_ERR, "can't Add UDP socket");
526					exit(1);
527				}
528				(void)close(sock);
529			}
530		}
531		if (rpcbreg == 1) {
532			memset(&hints, 0, sizeof hints);
533			hints.ai_flags = AI_PASSIVE;
534			hints.ai_family = AF_INET;
535			hints.ai_socktype = SOCK_DGRAM;
536			hints.ai_protocol = IPPROTO_UDP;
537			ecode = getaddrinfo(NULL, "nfs", &hints, &ai_udp);
538			if (ecode != 0) {
539				syslog(LOG_ERR, "getaddrinfo udp: %s",
540				   gai_strerror(ecode));
541				exit(1);
542			}
543			nconf_udp = getnetconfigent("udp");
544			if (nconf_udp == NULL)
545				err(1, "getnetconfigent udp failed");
546			nb_udp.buf = ai_udp->ai_addr;
547			nb_udp.len = nb_udp.maxlen = ai_udp->ai_addrlen;
548			if ((!rpcb_set(RPCPROG_NFS, 2, nconf_udp, &nb_udp)) ||
549			    (!rpcb_set(RPCPROG_NFS, 3, nconf_udp, &nb_udp)))
550				err(1, "rpcb_set udp failed");
551			freeaddrinfo(ai_udp);
552		}
553	}
554
555	/* Set up the socket for udp6 and rpcb register it. */
556	if (udpflag && ip6flag) {
557		rpcbreg = 0;
558		for (i = 0; i < bindhostc; i++) {
559			memset(&hints, 0, sizeof hints);
560			hints.ai_flags = AI_PASSIVE;
561			hints.ai_family = AF_INET6;
562			hints.ai_socktype = SOCK_DGRAM;
563			hints.ai_protocol = IPPROTO_UDP;
564			if (setbindhost(&ai_udp6, bindhost[i], hints) == 0) {
565				rpcbreg = 1;
566				rpcbregcnt++;
567				if ((sock = socket(ai_udp6->ai_family,
568				    ai_udp6->ai_socktype,
569				    ai_udp6->ai_protocol)) < 0) {
570					syslog(LOG_ERR,
571						"can't create udp6 socket");
572					exit(1);
573				}
574				if (setsockopt(sock, IPPROTO_IPV6,
575				    IPV6_BINDV6ONLY,
576				    &on, sizeof on) < 0) {
577					syslog(LOG_ERR,
578					    "can't set v6-only binding for "
579					    "udp6 socket: %m");
580					exit(1);
581				}
582				if (bind(sock, ai_udp6->ai_addr,
583				    ai_udp6->ai_addrlen) < 0) {
584					syslog(LOG_ERR,
585					    "can't bind udp6 addr %s: %m",
586					    bindhost[i]);
587					exit(1);
588				}
589				freeaddrinfo(ai_udp6);
590				nfsdargs.sock = sock;
591				nfsdargs.name = NULL;
592				nfsdargs.namelen = 0;
593				if (nfssvc(NFSSVC_ADDSOCK, &nfsdargs) < 0) {
594					syslog(LOG_ERR,
595					    "can't add UDP6 socket");
596					exit(1);
597				}
598				(void)close(sock);
599			}
600		}
601		if (rpcbreg == 1) {
602			memset(&hints, 0, sizeof hints);
603			hints.ai_flags = AI_PASSIVE;
604			hints.ai_family = AF_INET6;
605			hints.ai_socktype = SOCK_DGRAM;
606			hints.ai_protocol = IPPROTO_UDP;
607			ecode = getaddrinfo(NULL, "nfs", &hints, &ai_udp6);
608			if (ecode != 0) {
609				syslog(LOG_ERR, "getaddrinfo udp6: %s",
610				   gai_strerror(ecode));
611				exit(1);
612			}
613			nconf_udp6 = getnetconfigent("udp6");
614			if (nconf_udp6 == NULL)
615				err(1, "getnetconfigent udp6 failed");
616			nb_udp6.buf = ai_udp6->ai_addr;
617			nb_udp6.len = nb_udp6.maxlen = ai_udp6->ai_addrlen;
618			if ((!rpcb_set(RPCPROG_NFS, 2, nconf_udp6, &nb_udp6)) ||
619			    (!rpcb_set(RPCPROG_NFS, 3, nconf_udp6, &nb_udp6)))
620				err(1, "rpcb_set udp6 failed");
621			freeaddrinfo(ai_udp6);
622		}
623	}
624
625	/* Set up the socket for tcp and rpcb register it. */
626	if (tcpflag) {
627		rpcbreg = 0;
628		for (i = 0; i < bindhostc; i++) {
629			memset(&hints, 0, sizeof hints);
630			hints.ai_flags = AI_PASSIVE;
631			hints.ai_family = AF_INET;
632			hints.ai_socktype = SOCK_STREAM;
633			hints.ai_protocol = IPPROTO_TCP;
634			if (setbindhost(&ai_tcp, bindhost[i], hints) == 0) {
635				rpcbreg = 1;
636				rpcbregcnt++;
637				if ((tcpsock = socket(AF_INET, SOCK_STREAM,
638				    0)) < 0) {
639					syslog(LOG_ERR,
640					    "can't create tpc socket");
641					exit(1);
642				}
643				if (setsockopt(tcpsock, SOL_SOCKET,
644				    SO_REUSEADDR,
645				    (char *)&on, sizeof(on)) < 0)
646					syslog(LOG_ERR,
647					     "setsockopt SO_REUSEADDR: %m");
648				if (bind(tcpsock, ai_tcp->ai_addr,
649				    ai_tcp->ai_addrlen) < 0) {
650					syslog(LOG_ERR,
651					    "can't bind tcp addr %s: %m",
652					    bindhost[i]);
653					exit(1);
654				}
655				if (listen(tcpsock, 5) < 0) {
656					syslog(LOG_ERR, "listen failed");
657					exit(1);
658				}
659				freeaddrinfo(ai_tcp);
660				FD_SET(tcpsock, &sockbits);
661				FD_SET(tcpsock, &v4bits);
662				maxsock = tcpsock;
663				connect_type_cnt++;
664			}
665		}
666		if (rpcbreg == 1) {
667			memset(&hints, 0, sizeof hints);
668			hints.ai_flags = AI_PASSIVE;
669			hints.ai_family = AF_INET;
670			hints.ai_socktype = SOCK_STREAM;
671			hints.ai_protocol = IPPROTO_TCP;
672			ecode = getaddrinfo(NULL, "nfs", &hints,
673			     &ai_tcp);
674			if (ecode != 0) {
675				syslog(LOG_ERR, "getaddrinfo tcp: %s",
676				   gai_strerror(ecode));
677				exit(1);
678			}
679			nconf_tcp = getnetconfigent("tcp");
680			if (nconf_tcp == NULL)
681				err(1, "getnetconfigent tcp failed");
682			nb_tcp.buf = ai_tcp->ai_addr;
683			nb_tcp.len = nb_tcp.maxlen = ai_tcp->ai_addrlen;
684			if ((!rpcb_set(RPCPROG_NFS, 2, nconf_tcp,
685			    &nb_tcp)) || (!rpcb_set(RPCPROG_NFS, 3,
686			    nconf_tcp, &nb_tcp)))
687				err(1, "rpcb_set tcp failed");
688			freeaddrinfo(ai_tcp);
689		}
690	}
691
692	/* Set up the socket for tcp6 and rpcb register it. */
693	if (tcpflag && ip6flag) {
694		rpcbreg = 0;
695		for (i = 0; i < bindhostc; i++) {
696			memset(&hints, 0, sizeof hints);
697			hints.ai_flags = AI_PASSIVE;
698			hints.ai_family = AF_INET6;
699			hints.ai_socktype = SOCK_STREAM;
700			hints.ai_protocol = IPPROTO_TCP;
701			if (setbindhost(&ai_tcp6, bindhost[i], hints) == 0) {
702				rpcbreg = 1;
703				rpcbregcnt++;
704				if ((tcp6sock = socket(ai_tcp6->ai_family,
705				    ai_tcp6->ai_socktype,
706				    ai_tcp6->ai_protocol)) < 0) {
707					syslog(LOG_ERR,
708					    "can't create tcp6 socket");
709					exit(1);
710				}
711				if (setsockopt(tcp6sock, SOL_SOCKET,
712				    SO_REUSEADDR,
713				    (char *)&on, sizeof(on)) < 0)
714					syslog(LOG_ERR,
715					    "setsockopt SO_REUSEADDR: %m");
716				if (setsockopt(tcp6sock, IPPROTO_IPV6,
717				    IPV6_BINDV6ONLY, &on, sizeof on) < 0) {
718					syslog(LOG_ERR,
719					"can't set v6-only binding for tcp6 "
720					    "socket: %m");
721					exit(1);
722				}
723				if (bind(tcp6sock, ai_tcp6->ai_addr,
724				    ai_tcp6->ai_addrlen) < 0) {
725					syslog(LOG_ERR,
726					    "can't bind tcp6 addr %s: %m",
727					    bindhost[i]);
728					exit(1);
729				}
730				if (listen(tcp6sock, 5) < 0) {
731					syslog(LOG_ERR, "listen failed");
732					exit(1);
733				}
734				freeaddrinfo(ai_tcp6);
735				FD_SET(tcp6sock, &sockbits);
736				FD_SET(tcp6sock, &v6bits);
737				if (maxsock < tcp6sock)
738					maxsock = tcp6sock;
739				connect_type_cnt++;
740			}
741		}
742		if (rpcbreg == 1) {
743			memset(&hints, 0, sizeof hints);
744			hints.ai_flags = AI_PASSIVE;
745			hints.ai_family = AF_INET6;
746			hints.ai_socktype = SOCK_STREAM;
747			hints.ai_protocol = IPPROTO_TCP;
748			ecode = getaddrinfo(NULL, "nfs", &hints, &ai_tcp6);
749			if (ecode != 0) {
750				syslog(LOG_ERR, "getaddrinfo tcp6: %s",
751				   gai_strerror(ecode));
752				exit(1);
753			}
754			nconf_tcp6 = getnetconfigent("tcp6");
755			if (nconf_tcp6 == NULL)
756				err(1, "getnetconfigent tcp6 failed");
757			nb_tcp6.buf = ai_tcp6->ai_addr;
758			nb_tcp6.len = nb_tcp6.maxlen = ai_tcp6->ai_addrlen;
759			if ((!rpcb_set(RPCPROG_NFS, 2, nconf_tcp6, &nb_tcp6)) ||
760			    (!rpcb_set(RPCPROG_NFS, 3, nconf_tcp6, &nb_tcp6)))
761				err(1, "rpcb_set tcp6 failed");
762			freeaddrinfo(ai_tcp6);
763		}
764	}
765
766	if (rpcbregcnt == 0) {
767		syslog(LOG_ERR, "rpcb_set() failed, nothing to do: %m");
768		exit(1);
769	}
770
771	if ((tcpflag) && (connect_type_cnt == 0)) {
772		syslog(LOG_ERR, "tcp connects == 0, nothing to do: %m");
773		exit(1);
774	}
775
776	setproctitle("master");
777
778	/*
779	 * Loop forever accepting connections and passing the sockets
780	 * into the kernel for the mounts.
781	 */
782	for (;;) {
783		ready = sockbits;
784		if (connect_type_cnt > 1) {
785			if (select(maxsock + 1,
786			    &ready, NULL, NULL, NULL) < 1) {
787				syslog(LOG_ERR, "select failed: %m");
788				exit(1);
789			}
790		}
791		for (tcpsock = 0; tcpsock <= maxsock; tcpsock++) {
792			if (FD_ISSET(tcpsock, &ready)) {
793				if (FD_ISSET(tcpsock, &v4bits)) {
794					len = sizeof(inetpeer);
795					if ((msgsock = accept(tcpsock,
796					    (struct sockaddr *)&inetpeer, &len)) < 0) {
797						syslog(LOG_ERR, "accept failed: %m");
798						exit(1);
799					}
800					memset(inetpeer.sin_zero, 0,
801						sizeof(inetpeer.sin_zero));
802					if (setsockopt(msgsock, SOL_SOCKET,
803					    SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0)
804						syslog(LOG_ERR,
805						    "setsockopt SO_KEEPALIVE: %m");
806					nfsdargs.sock = msgsock;
807					nfsdargs.name = (caddr_t)&inetpeer;
808					nfsdargs.namelen = sizeof(inetpeer);
809					nfssvc(NFSSVC_ADDSOCK, &nfsdargs);
810					(void)close(msgsock);
811				} else if (FD_ISSET(tcpsock, &v6bits)) {
812					len = sizeof(inet6peer);
813					if ((msgsock = accept(tcpsock,
814					    (struct sockaddr *)&inet6peer,
815					    &len)) < 0) {
816						syslog(LOG_ERR,
817						     "accept failed: %m");
818						exit(1);
819					}
820					if (setsockopt(msgsock, SOL_SOCKET,
821					    SO_KEEPALIVE, (char *)&on,
822					    sizeof(on)) < 0)
823						syslog(LOG_ERR, "setsockopt "
824						    "SO_KEEPALIVE: %m");
825					nfsdargs.sock = msgsock;
826					nfsdargs.name = (caddr_t)&inet6peer;
827					nfsdargs.namelen = sizeof(inet6peer);
828					nfssvc(NFSSVC_ADDSOCK, &nfsdargs);
829					(void)close(msgsock);
830				}
831			}
832		}
833	}
834}
835
836int
837setbindhost(struct addrinfo **ai, const char *bindhost, struct addrinfo hints)
838{
839	int ecode;
840	u_int32_t host_addr[4];  /* IPv4 or IPv6 */
841	const char *hostptr;
842
843	if (bindhost == NULL || strcmp("*", bindhost) == 0)
844		hostptr = NULL;
845	else
846		hostptr = bindhost;
847
848	if (hostptr != NULL) {
849		switch (hints.ai_family) {
850		case AF_INET:
851			if (inet_pton(AF_INET, hostptr, host_addr) == 1) {
852				hints.ai_flags = AI_NUMERICHOST;
853			} else {
854				if (inet_pton(AF_INET6, hostptr,
855				    host_addr) == 1)
856					return (1);
857			}
858			break;
859		case AF_INET6:
860			if (inet_pton(AF_INET6, hostptr, host_addr) == 1) {
861				hints.ai_flags = AI_NUMERICHOST;
862			} else {
863				if (inet_pton(AF_INET, hostptr,
864				    host_addr) == 1)
865					return (1);
866			}
867			break;
868		default:
869		}
870	}
871
872	ecode = getaddrinfo(hostptr, "nfs", &hints, ai);
873	if (ecode != 0) {
874		syslog(LOG_ERR, "getaddrinfo %s: %s", bindhost,
875		    gai_strerror(ecode));
876		return (1);
877	}
878	return (0);
879}
880
881void
882usage()
883{
884	(void)fprintf(stderr, "usage: nfsd %s\n", USAGE);
885	exit(1);
886}
887
888void
889nonfs(signo)
890	int signo;
891{
892	syslog(LOG_ERR, "missing system call: NFS not available");
893}
894
895void
896reapchild(signo)
897	int signo;
898{
899
900	while (wait3(NULL, WNOHANG, NULL) > 0);
901}
902
903void
904unregistration()
905{
906	if ((!rpcb_unset(RPCPROG_NFS, 2, NULL)) ||
907	    (!rpcb_unset(RPCPROG_NFS, 3, NULL)))
908		syslog(LOG_ERR, "rpcb_unset failed");
909}
910
911void
912killchildren()
913{
914	int i;
915	sigset_t sigs;
916
917	sigemptyset(&sigs);
918	/*
919	* Block SIGCHLD to avoid killing a reaped process (although it is
920	* unlikely, the pid might have been reused).
921	*/
922	sigaddset(&sigs, SIGCHLD);
923	if (sigprocmask(SIG_BLOCK, &sigs, NULL) == -1) {
924		syslog(LOG_ERR, "sigprocmask: %s",
925		   strerror(errno));
926		return;
927	}
928	for (i = 0; i < nfsdcnt; i++) {
929		if (children[i] > 0)
930			kill(children[i], SIGKILL);
931	}
932	if (sigprocmask(SIG_UNBLOCK, &sigs, NULL) == -1) {
933		syslog(LOG_ERR, "sigprocmask: %s", strerror(errno));
934	}
935	unregistration();
936}
937
938void
939cleanup(signo)
940{
941	killchildren();
942	exit (0);
943}
944
945#ifdef OLD_SETPROCTITLE
946#ifdef __FreeBSD__
947void
948setproctitle(a)
949	char *a;
950{
951	register char *cp;
952	char buf[80];
953
954	cp = Argv[0];
955	(void)snprintf(buf, sizeof(buf), "nfsd-%s", a);
956	(void)strncpy(cp, buf, LastArg - cp);
957	cp += strlen(cp);
958	while (cp < LastArg)
959		*cp++ = '\0';
960	Argv[1] = NULL;
961}
962#endif	/* __FreeBSD__ */
963#endif
964