nfsd.c revision 13141
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
381558Srgrimesstatic 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
441558Srgrimesstatic char sccsid[] = "@(#)nfsd.c	8.7 (Berkeley) 2/22/94";
451558Srgrimes#endif not lint
461558Srgrimes
471558Srgrimes#include <sys/param.h>
481558Srgrimes#include <sys/syslog.h>
491558Srgrimes#include <sys/ioctl.h>
501558Srgrimes#include <sys/stat.h>
511558Srgrimes#include <sys/wait.h>
521558Srgrimes#include <sys/uio.h>
531558Srgrimes#include <sys/ucred.h>
541558Srgrimes#include <sys/mount.h>
551558Srgrimes#include <sys/socket.h>
561558Srgrimes#include <sys/socketvar.h>
571558Srgrimes
581558Srgrimes#include <rpc/rpc.h>
591558Srgrimes#include <rpc/pmap_clnt.h>
601558Srgrimes#include <rpc/pmap_prot.h>
611558Srgrimes
621558Srgrimes#ifdef ISO
631558Srgrimes#include <netiso/iso.h>
641558Srgrimes#endif
651558Srgrimes#include <nfs/rpcv2.h>
669336Sdfr#include <nfs/nfsproto.h>
671558Srgrimes#include <nfs/nfs.h>
681558Srgrimes
699336Sdfr#ifdef NFSKERB
701558Srgrimes#include <kerberosIV/des.h>
711558Srgrimes#include <kerberosIV/krb.h>
721558Srgrimes#endif
731558Srgrimes
741558Srgrimes#include <err.h>
751558Srgrimes#include <errno.h>
761558Srgrimes#include <fcntl.h>
771558Srgrimes#include <grp.h>
781558Srgrimes#include <pwd.h>
791558Srgrimes#include <signal.h>
801558Srgrimes#include <stdio.h>
811558Srgrimes#include <stdlib.h>
821558Srgrimes#include <strings.h>
831558Srgrimes#include <unistd.h>
8413141Speter#include <libutil.h>
851558Srgrimes
861558Srgrimes/* Global defs */
871558Srgrimes#ifdef DEBUG
881558Srgrimes#define	syslog(e, s)	fprintf(stderr,(s))
891558Srgrimesint	debug = 1;
901558Srgrimes#else
911558Srgrimesint	debug = 0;
921558Srgrimes#endif
931558Srgrimes
941558Srgrimesstruct	nfsd_srvargs nsd;
9513141Speter#ifdef OLD_SETPROCTITLE
961558Srgrimeschar	**Argv = NULL;		/* pointer to argument vector */
971558Srgrimeschar	*LastArg = NULL;	/* end of argv */
9813141Speter#endif
991558Srgrimes
1009336Sdfr#ifdef NFSKERB
1011558Srgrimeschar		lnam[ANAME_SZ];
1021558SrgrimesKTEXT_ST	kt;
1039336SdfrAUTH_DAT	kauth;
1041558Srgrimeschar		inst[INST_SZ];
1059336Sdfrstruct nfsrpc_fullblock kin, kout;
1069336Sdfrstruct nfsrpc_fullverf kverf;
1079336SdfrNFSKERBKEY_T	kivec;
1089336Sdfrstruct timeval	ktv;
1099336SdfrNFSKERBKEYSCHED_T kerb_keysched;
1101558Srgrimes#endif
1111558Srgrimes
1121558Srgrimesvoid	nonfs __P((int));
1131558Srgrimesvoid	reapchild __P((int));
11413141Speter#ifdef OLD_SETPROCTITLE
1159336Sdfr#ifdef __FreeBSD__
1161558Srgrimesvoid	setproctitle __P((char *));
1179336Sdfr#endif
11813141Speter#endif
1191558Srgrimesvoid	usage __P((void));
1201558Srgrimes
1211558Srgrimes/*
1221558Srgrimes * Nfs server daemon mostly just a user context for nfssvc()
1231558Srgrimes *
1241558Srgrimes * 1 - do file descriptor and signal cleanup
1251558Srgrimes * 2 - fork the nfsd(s)
1261558Srgrimes * 3 - create server socket(s)
1271558Srgrimes * 4 - register socket with portmap
1281558Srgrimes *
1291558Srgrimes * For connectionless protocols, just pass the socket into the kernel via.
1301558Srgrimes * nfssvc().
1311558Srgrimes * For connection based sockets, loop doing accepts. When you get a new
1321558Srgrimes * socket from accept, pass the msgsock into the kernel via. nfssvc().
1331558Srgrimes * The arguments are:
1341558Srgrimes *	-c - support iso cltp clients
1351558Srgrimes *	-r - reregister with portmapper
1361558Srgrimes *	-t - support tcp nfs clients
1371558Srgrimes *	-u - support udp nfs clients
1381558Srgrimes * followed by "n" which is the number of nfsds' to fork off
1391558Srgrimes */
1401558Srgrimesint
1411558Srgrimesmain(argc, argv, envp)
1421558Srgrimes	int argc;
1431558Srgrimes	char *argv[], *envp[];
1441558Srgrimes{
1451558Srgrimes	extern int optind;
1461558Srgrimes	struct group *grp;
1471558Srgrimes	struct nfsd_args nfsdargs;
1481558Srgrimes	struct passwd *pwd;
1491558Srgrimes	struct ucred *cr;
1501558Srgrimes	struct sockaddr_in inetaddr, inetpeer;
1511558Srgrimes#ifdef ISO
1521558Srgrimes	struct sockaddr_iso isoaddr, isopeer;
1531558Srgrimes#endif
1549336Sdfr	struct timeval ktv;
1551558Srgrimes	fd_set ready, sockbits;
1561558Srgrimes	int ch, cltpflag, connect_type_cnt, i, len, maxsock, msgsock;
1571558Srgrimes	int nfsdcnt, nfssvc_flag, on, reregister, sock, tcpflag, tcpsock;
1581558Srgrimes	int tp4cnt, tp4flag, tp4sock, tpipcnt, tpipflag, tpipsock, udpflag;
1591558Srgrimes	char *cp, **cpp;
1609336Sdfr#ifdef __FreeBSD__
1612999Swollman	struct vfsconf *vfc;
1621558Srgrimes
1632999Swollman	vfc = getvfsbyname("nfs");
1642999Swollman	if(!vfc && vfsisloadable("nfs")) {
1652999Swollman		if(vfsload("nfs"))
1662999Swollman			err(1, "vfsload(nfs)");
1672999Swollman		endvfsent();	/* flush cache */
1682999Swollman		vfc = getvfsbyname("nfs"); /* probably unnecessary */
1692999Swollman	}
1702999Swollman	if(!vfc) {
1712999Swollman		errx(1, "NFS is not available in the running kernel");
1722999Swollman	}
1739336Sdfr#endif
1742999Swollman
17513141Speter#ifdef OLD_SETPROCTITLE
1761558Srgrimes	/* Save start and extent of argv for setproctitle. */
1771558Srgrimes	Argv = argv;
1781558Srgrimes	if (envp == 0 || *envp == 0)
1791558Srgrimes		envp = argv;
1801558Srgrimes	while (*envp)
1811558Srgrimes		envp++;
1821558Srgrimes	LastArg = envp[-1] + strlen(envp[-1]);
18313141Speter#endif
1841558Srgrimes
1851558Srgrimes#define	MAXNFSDCNT	20
1861558Srgrimes#define	DEFNFSDCNT	 4
1871558Srgrimes	nfsdcnt = DEFNFSDCNT;
1881558Srgrimes	cltpflag = reregister = tcpflag = tp4cnt = tp4flag = tpipcnt = 0;
1891558Srgrimes	tpipflag = udpflag = 0;
1901558Srgrimes#ifdef ISO
1911558Srgrimes#define	GETOPT	"cn:rtu"
1921558Srgrimes#define	USAGE	"[-crtu] [-n num_servers]"
1931558Srgrimes#else
1941558Srgrimes#define	GETOPT	"n:rtu"
1951558Srgrimes#define	USAGE	"[-rtu] [-n num_servers]"
1961558Srgrimes#endif
1971558Srgrimes	while ((ch = getopt(argc, argv, GETOPT)) != EOF)
1981558Srgrimes		switch (ch) {
1991558Srgrimes		case 'n':
2001558Srgrimes			nfsdcnt = atoi(optarg);
2011558Srgrimes			if (nfsdcnt < 1 || nfsdcnt > MAXNFSDCNT) {
2021558Srgrimes				warnx("nfsd count %d; reset to %d", DEFNFSDCNT);
2031558Srgrimes				nfsdcnt = DEFNFSDCNT;
2041558Srgrimes			}
2051558Srgrimes			break;
2061558Srgrimes		case 'r':
2071558Srgrimes			reregister = 1;
2081558Srgrimes			break;
2091558Srgrimes		case 't':
2101558Srgrimes			tcpflag = 1;
2111558Srgrimes			break;
2121558Srgrimes		case 'u':
2131558Srgrimes			udpflag = 1;
2141558Srgrimes			break;
2151558Srgrimes#ifdef ISO
2161558Srgrimes		case 'c':
2171558Srgrimes			cltpflag = 1;
2181558Srgrimes			break;
2191558Srgrimes#ifdef notyet
2201558Srgrimes		case 'i':
2211558Srgrimes			tp4cnt = 1;
2221558Srgrimes			break;
2231558Srgrimes		case 'p':
2241558Srgrimes			tpipcnt = 1;
2251558Srgrimes			break;
2261558Srgrimes#endif /* notyet */
2271558Srgrimes#endif /* ISO */
2281558Srgrimes		default:
2291558Srgrimes		case '?':
2301558Srgrimes			usage();
2311558Srgrimes		};
2321558Srgrimes	argv += optind;
2331558Srgrimes	argc -= optind;
2341558Srgrimes
2351558Srgrimes	/*
2361558Srgrimes	 * XXX
2371558Srgrimes	 * Backward compatibility, trailing number is the count of daemons.
2381558Srgrimes	 */
2391558Srgrimes	if (argc > 1)
2401558Srgrimes		usage();
2411558Srgrimes	if (argc == 1) {
2421558Srgrimes		nfsdcnt = atoi(argv[0]);
2431558Srgrimes		if (nfsdcnt < 1 || nfsdcnt > MAXNFSDCNT) {
2441558Srgrimes			warnx("nfsd count %d; reset to %d", DEFNFSDCNT);
2451558Srgrimes			nfsdcnt = DEFNFSDCNT;
2461558Srgrimes		}
2471558Srgrimes	}
2481558Srgrimes
2491558Srgrimes	if (debug == 0) {
2501558Srgrimes		daemon(0, 0);
2511558Srgrimes		(void)signal(SIGHUP, SIG_IGN);
2521558Srgrimes		(void)signal(SIGINT, SIG_IGN);
2531558Srgrimes		(void)signal(SIGQUIT, SIG_IGN);
2541558Srgrimes		(void)signal(SIGSYS, nonfs);
2551558Srgrimes		(void)signal(SIGTERM, SIG_IGN);
2561558Srgrimes	}
2571558Srgrimes	(void)signal(SIGCHLD, reapchild);
2581558Srgrimes
2591558Srgrimes	if (reregister) {
2601558Srgrimes		if (udpflag &&
2619336Sdfr		    (!pmap_set(RPCPROG_NFS, 2, IPPROTO_UDP, NFS_PORT) ||
2629336Sdfr		     !pmap_set(RPCPROG_NFS, 3, IPPROTO_UDP, NFS_PORT)))
2631558Srgrimes			err(1, "can't register with portmap for UDP.");
2641558Srgrimes		if (tcpflag &&
2659336Sdfr		    (!pmap_set(RPCPROG_NFS, 2, IPPROTO_TCP, NFS_PORT) ||
2669336Sdfr		     !pmap_set(RPCPROG_NFS, 3, IPPROTO_TCP, NFS_PORT)))
2671558Srgrimes			err(1, "can't register with portmap for TCP.");
2681558Srgrimes		exit(0);
2691558Srgrimes	}
2701558Srgrimes	openlog("nfsd:", LOG_PID, LOG_DAEMON);
2711558Srgrimes
2721558Srgrimes	for (i = 0; i < nfsdcnt; i++) {
2731558Srgrimes		switch (fork()) {
2741558Srgrimes		case -1:
2751558Srgrimes			syslog(LOG_ERR, "fork: %m");
2761558Srgrimes			exit (1);
2771558Srgrimes		case 0:
2781558Srgrimes			break;
2791558Srgrimes		default:
2801558Srgrimes			continue;
2811558Srgrimes		}
2821558Srgrimes
2839336Sdfr		setproctitle("server");
2841558Srgrimes		nfssvc_flag = NFSSVC_NFSD;
2851558Srgrimes		nsd.nsd_nfsd = NULL;
2869336Sdfr#ifdef NFSKERB
2879336Sdfr		if (sizeof (struct nfsrpc_fullverf) != RPCX_FULLVERF ||
2889336Sdfr		    sizeof (struct nfsrpc_fullblock) != RPCX_FULLBLOCK)
2899336Sdfr		    syslog(LOG_ERR, "Yikes NFSKERB structs not packed!");
2909336Sdfr		nsd.nsd_authstr = (u_char *)&kt;
2919336Sdfr		nsd.nsd_authlen = sizeof (kt);
2929336Sdfr		nsd.nsd_verfstr = (u_char *)&kverf;
2939336Sdfr		nsd.nsd_verflen = sizeof (kverf);
2941558Srgrimes#endif
2951558Srgrimes		while (nfssvc(nfssvc_flag, &nsd) < 0) {
2961558Srgrimes			if (errno != ENEEDAUTH) {
2971558Srgrimes				syslog(LOG_ERR, "nfssvc: %m");
2981558Srgrimes				exit(1);
2991558Srgrimes			}
3001558Srgrimes			nfssvc_flag = NFSSVC_NFSD | NFSSVC_AUTHINFAIL;
3019336Sdfr#ifdef NFSKERB
3029336Sdfr			/*
3039336Sdfr			 * Get the Kerberos ticket out of the authenticator
3049336Sdfr			 * verify it and convert the principal name to a user
3059336Sdfr			 * name. The user name is then converted to a set of
3069336Sdfr			 * user credentials via the password and group file.
3079336Sdfr			 * Finally, decrypt the timestamp and validate it.
3089336Sdfr			 * For more info see the IETF Draft "Authentication
3099336Sdfr			 * in ONC RPC".
3109336Sdfr			 */
3119336Sdfr			kt.length = ntohl(kt.length);
3129336Sdfr			if (gettimeofday(&ktv, (struct timezone *)0) == 0 &&
3139336Sdfr			    kt.length > 0 && kt.length <=
3149336Sdfr			    (RPCAUTH_MAXSIZ - 3 * NFSX_UNSIGNED)) {
3159336Sdfr			    kin.w1 = NFS_KERBW1(kt);
3169336Sdfr			    kt.mbz = 0;
3179336Sdfr			    (void)strcpy(inst, "*");
3189336Sdfr			    if (krb_rd_req(&kt, NFS_KERBSRV,
3199336Sdfr				inst, nsd.nsd_haddr, &kauth, "") == RD_AP_OK &&
3209336Sdfr				krb_kntoln(&kauth, lnam) == KSUCCESS &&
3219336Sdfr				(pwd = getpwnam(lnam)) != NULL) {
3221558Srgrimes				cr = &nsd.nsd_cr;
3231558Srgrimes				cr->cr_uid = pwd->pw_uid;
3241558Srgrimes				cr->cr_groups[0] = pwd->pw_gid;
3251558Srgrimes				cr->cr_ngroups = 1;
3261558Srgrimes				setgrent();
3271558Srgrimes				while ((grp = getgrent()) != NULL) {
3281558Srgrimes					if (grp->gr_gid == cr->cr_groups[0])
3291558Srgrimes						continue;
3301558Srgrimes					for (cpp = grp->gr_mem;
3311558Srgrimes					    *cpp != NULL; ++cpp)
3321558Srgrimes						if (!strcmp(*cpp, lnam))
3331558Srgrimes							break;
3341558Srgrimes					if (*cpp == NULL)
3351558Srgrimes						continue;
3361558Srgrimes					cr->cr_groups[cr->cr_ngroups++]
3371558Srgrimes					    = grp->gr_gid;
3381558Srgrimes					if (cr->cr_ngroups == NGROUPS)
3391558Srgrimes						break;
3401558Srgrimes				}
3411558Srgrimes				endgrent();
3429336Sdfr
3439336Sdfr				/*
3449336Sdfr				 * Get the timestamp verifier out of the
3459336Sdfr				 * authenticator and verifier strings.
3469336Sdfr				 */
3479336Sdfr				kin.t1 = kverf.t1;
3489336Sdfr				kin.t2 = kverf.t2;
3499336Sdfr				kin.w2 = kverf.w2;
3509336Sdfr				bzero((caddr_t)kivec, sizeof (kivec));
3519336Sdfr				bcopy((caddr_t)kauth.session,
3529336Sdfr				    (caddr_t)nsd.nsd_key,sizeof(kauth.session));
3539336Sdfr
3549336Sdfr				/*
3559336Sdfr				 * Decrypt the timestamp verifier in CBC mode.
3569336Sdfr				 */
3579336Sdfr				XXX
3589336Sdfr
3599336Sdfr				/*
3609336Sdfr				 * Validate the timestamp verifier, to
3619336Sdfr				 * check that the session key is ok.
3629336Sdfr				 */
3639336Sdfr				nsd.nsd_timestamp.tv_sec = ntohl(kout.t1);
3649336Sdfr				nsd.nsd_timestamp.tv_usec = ntohl(kout.t2);
3659336Sdfr				nsd.nsd_ttl = ntohl(kout.w1);
3669336Sdfr				if ((nsd.nsd_ttl - 1) == ntohl(kout.w2))
3679336Sdfr				    nfssvc_flag = NFSSVC_NFSD | NFSSVC_AUTHIN;
3681558Srgrimes			}
3699336Sdfr#endif /* NFSKERB */
3701558Srgrimes		}
3711558Srgrimes		exit(0);
3721558Srgrimes	}
3731558Srgrimes
3741558Srgrimes	/* If we are serving udp, set up the socket. */
3751558Srgrimes	if (udpflag) {
3761558Srgrimes		if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
3771558Srgrimes			syslog(LOG_ERR, "can't create udp socket");
3781558Srgrimes			exit(1);
3791558Srgrimes		}
3801558Srgrimes		inetaddr.sin_family = AF_INET;
3811558Srgrimes		inetaddr.sin_addr.s_addr = INADDR_ANY;
3821558Srgrimes		inetaddr.sin_port = htons(NFS_PORT);
3831558Srgrimes		inetaddr.sin_len = sizeof(inetaddr);
3841558Srgrimes		if (bind(sock,
3851558Srgrimes		    (struct sockaddr *)&inetaddr, sizeof(inetaddr)) < 0) {
3861558Srgrimes			syslog(LOG_ERR, "can't bind udp addr");
3871558Srgrimes			exit(1);
3881558Srgrimes		}
3899336Sdfr		if (!pmap_set(RPCPROG_NFS, 2, IPPROTO_UDP, NFS_PORT) ||
3909336Sdfr		    !pmap_set(RPCPROG_NFS, 3, IPPROTO_UDP, NFS_PORT)) {
3911558Srgrimes			syslog(LOG_ERR, "can't register with udp portmap");
3921558Srgrimes			exit(1);
3931558Srgrimes		}
3941558Srgrimes		nfsdargs.sock = sock;
3951558Srgrimes		nfsdargs.name = NULL;
3961558Srgrimes		nfsdargs.namelen = 0;
3971558Srgrimes		if (nfssvc(NFSSVC_ADDSOCK, &nfsdargs) < 0) {
3981558Srgrimes			syslog(LOG_ERR, "can't Add UDP socket");
3991558Srgrimes			exit(1);
4001558Srgrimes		}
4011558Srgrimes		(void)close(sock);
4021558Srgrimes	}
4031558Srgrimes
4041558Srgrimes#ifdef ISO
4051558Srgrimes	/* If we are serving cltp, set up the socket. */
4061558Srgrimes	if (cltpflag) {
4071558Srgrimes		if ((sock = socket(AF_ISO, SOCK_DGRAM, 0)) < 0) {
4081558Srgrimes			syslog(LOG_ERR, "can't create cltp socket");
4091558Srgrimes			exit(1);
4101558Srgrimes		}
4111558Srgrimes		memset(&isoaddr, 0, sizeof(isoaddr));
4121558Srgrimes		isoaddr.siso_family = AF_ISO;
4131558Srgrimes		isoaddr.siso_tlen = 2;
4141558Srgrimes		cp = TSEL(&isoaddr);
4151558Srgrimes		*cp++ = (NFS_PORT >> 8);
4161558Srgrimes		*cp = (NFS_PORT & 0xff);
4171558Srgrimes		isoaddr.siso_len = sizeof(isoaddr);
4181558Srgrimes		if (bind(sock,
4191558Srgrimes		    (struct sockaddr *)&isoaddr, sizeof(isoaddr)) < 0) {
4201558Srgrimes			syslog(LOG_ERR, "can't bind cltp addr");
4211558Srgrimes			exit(1);
4221558Srgrimes		}
4231558Srgrimes#ifdef notyet
4241558Srgrimes		/*
4251558Srgrimes		 * XXX
4261558Srgrimes		 * Someday this should probably use "rpcbind", the son of
4271558Srgrimes		 * portmap.
4281558Srgrimes		 */
4291558Srgrimes		if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_UDP, NFS_PORT)) {
4301558Srgrimes			syslog(LOG_ERR, "can't register with udp portmap");
4311558Srgrimes			exit(1);
4321558Srgrimes		}
4331558Srgrimes#endif /* notyet */
4341558Srgrimes		nfsdargs.sock = sock;
4351558Srgrimes		nfsdargs.name = NULL;
4361558Srgrimes		nfsdargs.namelen = 0;
4371558Srgrimes		if (nfssvc(NFSSVC_ADDSOCK, &nfsdargs) < 0) {
4381558Srgrimes			syslog(LOG_ERR, "can't add UDP socket");
4391558Srgrimes			exit(1);
4401558Srgrimes		}
4411558Srgrimes		close(sock);
4421558Srgrimes	}
4431558Srgrimes#endif /* ISO */
4441558Srgrimes
4451558Srgrimes	/* Now set up the master server socket waiting for tcp connections. */
4461558Srgrimes	on = 1;
4471558Srgrimes	FD_ZERO(&sockbits);
4481558Srgrimes	connect_type_cnt = 0;
4491558Srgrimes	if (tcpflag) {
4501558Srgrimes		if ((tcpsock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
4511558Srgrimes			syslog(LOG_ERR, "can't create tcp socket");
4521558Srgrimes			exit(1);
4531558Srgrimes		}
4541558Srgrimes		if (setsockopt(tcpsock,
4551558Srgrimes		    SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0)
4561558Srgrimes			syslog(LOG_ERR, "setsockopt SO_REUSEADDR: %m");
4571558Srgrimes		inetaddr.sin_family = AF_INET;
4581558Srgrimes		inetaddr.sin_addr.s_addr = INADDR_ANY;
4591558Srgrimes		inetaddr.sin_port = htons(NFS_PORT);
4601558Srgrimes		inetaddr.sin_len = sizeof(inetaddr);
4611558Srgrimes		if (bind(tcpsock,
4621558Srgrimes		    (struct sockaddr *)&inetaddr, sizeof (inetaddr)) < 0) {
4631558Srgrimes			syslog(LOG_ERR, "can't bind tcp addr");
4641558Srgrimes			exit(1);
4651558Srgrimes		}
4661558Srgrimes		if (listen(tcpsock, 5) < 0) {
4671558Srgrimes			syslog(LOG_ERR, "listen failed");
4681558Srgrimes			exit(1);
4691558Srgrimes		}
4709336Sdfr		if (!pmap_set(RPCPROG_NFS, 2, IPPROTO_TCP, NFS_PORT) ||
4719336Sdfr		    !pmap_set(RPCPROG_NFS, 3, IPPROTO_TCP, NFS_PORT)) {
4721558Srgrimes			syslog(LOG_ERR, "can't register tcp with portmap");
4731558Srgrimes			exit(1);
4741558Srgrimes		}
4751558Srgrimes		FD_SET(tcpsock, &sockbits);
4761558Srgrimes		maxsock = tcpsock;
4771558Srgrimes		connect_type_cnt++;
4781558Srgrimes	}
4791558Srgrimes
4801558Srgrimes#ifdef notyet
4811558Srgrimes	/* Now set up the master server socket waiting for tp4 connections. */
4821558Srgrimes	if (tp4flag) {
4831558Srgrimes		if ((tp4sock = socket(AF_ISO, SOCK_SEQPACKET, 0)) < 0) {
4841558Srgrimes			syslog(LOG_ERR, "can't create tp4 socket");
4851558Srgrimes			exit(1);
4861558Srgrimes		}
4871558Srgrimes		if (setsockopt(tp4sock,
4881558Srgrimes		    SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0)
4891558Srgrimes			syslog(LOG_ERR, "setsockopt SO_REUSEADDR: %m");
4901558Srgrimes		memset(&isoaddr, 0, sizeof(isoaddr));
4911558Srgrimes		isoaddr.siso_family = AF_ISO;
4921558Srgrimes		isoaddr.siso_tlen = 2;
4931558Srgrimes		cp = TSEL(&isoaddr);
4941558Srgrimes		*cp++ = (NFS_PORT >> 8);
4951558Srgrimes		*cp = (NFS_PORT & 0xff);
4961558Srgrimes		isoaddr.siso_len = sizeof(isoaddr);
4971558Srgrimes		if (bind(tp4sock,
4981558Srgrimes		    (struct sockaddr *)&isoaddr, sizeof (isoaddr)) < 0) {
4991558Srgrimes			syslog(LOG_ERR, "can't bind tp4 addr");
5001558Srgrimes			exit(1);
5011558Srgrimes		}
5021558Srgrimes		if (listen(tp4sock, 5) < 0) {
5031558Srgrimes			syslog(LOG_ERR, "listen failed");
5041558Srgrimes			exit(1);
5051558Srgrimes		}
5061558Srgrimes		/*
5071558Srgrimes		 * XXX
5081558Srgrimes		 * Someday this should probably use "rpcbind", the son of
5091558Srgrimes		 * portmap.
5101558Srgrimes		 */
5111558Srgrimes		if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_TCP, NFS_PORT)) {
5121558Srgrimes			syslog(LOG_ERR, "can't register tcp with portmap");
5131558Srgrimes			exit(1);
5141558Srgrimes		}
5151558Srgrimes		FD_SET(tp4sock, &sockbits);
5161558Srgrimes		maxsock = tp4sock;
5171558Srgrimes		connect_type_cnt++;
5181558Srgrimes	}
5191558Srgrimes
5201558Srgrimes	/* Now set up the master server socket waiting for tpip connections. */
5211558Srgrimes	if (tpipflag) {
5221558Srgrimes		if ((tpipsock = socket(AF_INET, SOCK_SEQPACKET, 0)) < 0) {
5231558Srgrimes			syslog(LOG_ERR, "can't create tpip socket");
5241558Srgrimes			exit(1);
5251558Srgrimes		}
5261558Srgrimes		if (setsockopt(tpipsock,
5271558Srgrimes		    SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0)
5281558Srgrimes			syslog(LOG_ERR, "setsockopt SO_REUSEADDR: %m");
5291558Srgrimes		inetaddr.sin_family = AF_INET;
5301558Srgrimes		inetaddr.sin_addr.s_addr = INADDR_ANY;
5311558Srgrimes		inetaddr.sin_port = htons(NFS_PORT);
5321558Srgrimes		inetaddr.sin_len = sizeof(inetaddr);
5331558Srgrimes		if (bind(tpipsock,
5341558Srgrimes		    (struct sockaddr *)&inetaddr, sizeof (inetaddr)) < 0) {
5351558Srgrimes			syslog(LOG_ERR, "can't bind tcp addr");
5361558Srgrimes			exit(1);
5371558Srgrimes		}
5381558Srgrimes		if (listen(tpipsock, 5) < 0) {
5391558Srgrimes			syslog(LOG_ERR, "listen failed");
5401558Srgrimes			exit(1);
5411558Srgrimes		}
5421558Srgrimes		/*
5431558Srgrimes		 * XXX
5441558Srgrimes		 * Someday this should probably use "rpcbind", the son of
5451558Srgrimes		 * portmap.
5461558Srgrimes		 */
5471558Srgrimes		if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_TCP, NFS_PORT)) {
5481558Srgrimes			syslog(LOG_ERR, "can't register tcp with portmap");
5491558Srgrimes			exit(1);
5501558Srgrimes		}
5511558Srgrimes		FD_SET(tpipsock, &sockbits);
5521558Srgrimes		maxsock = tpipsock;
5531558Srgrimes		connect_type_cnt++;
5541558Srgrimes	}
5551558Srgrimes#endif /* notyet */
5561558Srgrimes
5571558Srgrimes	if (connect_type_cnt == 0)
5581558Srgrimes		exit(0);
5591558Srgrimes
5609336Sdfr	setproctitle("master");
5611558Srgrimes
5621558Srgrimes	/*
5631558Srgrimes	 * Loop forever accepting connections and passing the sockets
5641558Srgrimes	 * into the kernel for the mounts.
5651558Srgrimes	 */
5661558Srgrimes	for (;;) {
5671558Srgrimes		ready = sockbits;
5681558Srgrimes		if (connect_type_cnt > 1) {
5691558Srgrimes			if (select(maxsock + 1,
5701558Srgrimes			    &ready, NULL, NULL, NULL) < 1) {
5711558Srgrimes				syslog(LOG_ERR, "select failed: %m");
5721558Srgrimes				exit(1);
5731558Srgrimes			}
5741558Srgrimes		}
5751558Srgrimes		if (tcpflag && FD_ISSET(tcpsock, &ready)) {
5761558Srgrimes			len = sizeof(inetpeer);
5771558Srgrimes			if ((msgsock = accept(tcpsock,
5781558Srgrimes			    (struct sockaddr *)&inetpeer, &len)) < 0) {
5791558Srgrimes				syslog(LOG_ERR, "accept failed: %m");
5801558Srgrimes				exit(1);
5811558Srgrimes			}
5821558Srgrimes			memset(inetpeer.sin_zero, 0, sizeof(inetpeer.sin_zero));
5831558Srgrimes			if (setsockopt(msgsock, SOL_SOCKET,
5841558Srgrimes			    SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0)
5851558Srgrimes				syslog(LOG_ERR,
5861558Srgrimes				    "setsockopt SO_KEEPALIVE: %m");
5871558Srgrimes			nfsdargs.sock = msgsock;
5881558Srgrimes			nfsdargs.name = (caddr_t)&inetpeer;
5891558Srgrimes			nfsdargs.namelen = sizeof(inetpeer);
5901558Srgrimes			nfssvc(NFSSVC_ADDSOCK, &nfsdargs);
5911558Srgrimes			(void)close(msgsock);
5921558Srgrimes		}
5931558Srgrimes#ifdef notyet
5941558Srgrimes		if (tp4flag && FD_ISSET(tp4sock, &ready)) {
5951558Srgrimes			len = sizeof(isopeer);
5961558Srgrimes			if ((msgsock = accept(tp4sock,
5971558Srgrimes			    (struct sockaddr *)&isopeer, &len)) < 0) {
5981558Srgrimes				syslog(LOG_ERR, "accept failed: %m");
5991558Srgrimes				exit(1);
6001558Srgrimes			}
6011558Srgrimes			if (setsockopt(msgsock, SOL_SOCKET,
6021558Srgrimes			    SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0)
6031558Srgrimes				syslog(LOG_ERR,
6041558Srgrimes				    "setsockopt SO_KEEPALIVE: %m");
6051558Srgrimes			nfsdargs.sock = msgsock;
6061558Srgrimes			nfsdargs.name = (caddr_t)&isopeer;
6071558Srgrimes			nfsdargs.namelen = len;
6081558Srgrimes			nfssvc(NFSSVC_ADDSOCK, &nfsdargs);
6091558Srgrimes			(void)close(msgsock);
6101558Srgrimes		}
6111558Srgrimes		if (tpipflag && FD_ISSET(tpipsock, &ready)) {
6121558Srgrimes			len = sizeof(inetpeer);
6131558Srgrimes			if ((msgsock = accept(tpipsock,
6141558Srgrimes			    (struct sockaddr *)&inetpeer, &len)) < 0) {
6151558Srgrimes				syslog(LOG_ERR, "Accept failed: %m");
6161558Srgrimes				exit(1);
6171558Srgrimes			}
6181558Srgrimes			if (setsockopt(msgsock, SOL_SOCKET,
6191558Srgrimes			    SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0)
6201558Srgrimes				syslog(LOG_ERR, "setsockopt SO_KEEPALIVE: %m");
6211558Srgrimes			nfsdargs.sock = msgsock;
6221558Srgrimes			nfsdargs.name = (caddr_t)&inetpeer;
6231558Srgrimes			nfsdargs.namelen = len;
6241558Srgrimes			nfssvc(NFSSVC_ADDSOCK, &nfsdargs);
6251558Srgrimes			(void)close(msgsock);
6261558Srgrimes		}
6271558Srgrimes#endif /* notyet */
6281558Srgrimes	}
6291558Srgrimes}
6301558Srgrimes
6311558Srgrimesvoid
6321558Srgrimesusage()
6331558Srgrimes{
6349336Sdfr	(void)fprintf(stderr, "usage: nfsd %s\n", USAGE);
6351558Srgrimes	exit(1);
6361558Srgrimes}
6371558Srgrimes
6381558Srgrimesvoid
6391558Srgrimesnonfs(signo)
6401558Srgrimes	int signo;
6411558Srgrimes{
6421558Srgrimes	syslog(LOG_ERR, "missing system call: NFS not available.");
6431558Srgrimes}
6441558Srgrimes
6451558Srgrimesvoid
6461558Srgrimesreapchild(signo)
6471558Srgrimes	int signo;
6481558Srgrimes{
6491558Srgrimes
6509336Sdfr	while (wait3(NULL, WNOHANG, NULL) > 0);
6511558Srgrimes}
6521558Srgrimes
65313141Speter#ifdef OLD_SETPROCTITLE
6549336Sdfr#ifdef __FreeBSD__
6551558Srgrimesvoid
6561558Srgrimessetproctitle(a)
6571558Srgrimes	char *a;
6581558Srgrimes{
6591558Srgrimes	register char *cp;
6601558Srgrimes	char buf[80];
6611558Srgrimes
6621558Srgrimes	cp = Argv[0];
6639336Sdfr	(void)snprintf(buf, sizeof(buf), "nfsd-%s", a);
6641558Srgrimes	(void)strncpy(cp, buf, LastArg - cp);
6651558Srgrimes	cp += strlen(cp);
6661558Srgrimes	while (cp < LastArg)
6672030Sdg		*cp++ = '\0';
66812869Speter	Argv[1] = NULL;
6691558Srgrimes}
6709336Sdfr#endif	/* __FreeBSD__ */
67113141Speter#endif
672