xref: /freebsd/usr.sbin/nfsd/nfsd.c (revision 8fae3551ec46402adf7ab034cf9e02bcbc7ca8ee)
18fae3551SRodney W. Grimes /*
28fae3551SRodney W. Grimes  * Copyright (c) 1989, 1993, 1994
38fae3551SRodney W. Grimes  *	The Regents of the University of California.  All rights reserved.
48fae3551SRodney W. Grimes  *
58fae3551SRodney W. Grimes  * This code is derived from software contributed to Berkeley by
68fae3551SRodney W. Grimes  * Rick Macklem at The University of Guelph.
78fae3551SRodney W. Grimes  *
88fae3551SRodney W. Grimes  * Redistribution and use in source and binary forms, with or without
98fae3551SRodney W. Grimes  * modification, are permitted provided that the following conditions
108fae3551SRodney W. Grimes  * are met:
118fae3551SRodney W. Grimes  * 1. Redistributions of source code must retain the above copyright
128fae3551SRodney W. Grimes  *    notice, this list of conditions and the following disclaimer.
138fae3551SRodney W. Grimes  * 2. Redistributions in binary form must reproduce the above copyright
148fae3551SRodney W. Grimes  *    notice, this list of conditions and the following disclaimer in the
158fae3551SRodney W. Grimes  *    documentation and/or other materials provided with the distribution.
168fae3551SRodney W. Grimes  * 3. All advertising materials mentioning features or use of this software
178fae3551SRodney W. Grimes  *    must display the following acknowledgement:
188fae3551SRodney W. Grimes  *	This product includes software developed by the University of
198fae3551SRodney W. Grimes  *	California, Berkeley and its contributors.
208fae3551SRodney W. Grimes  * 4. Neither the name of the University nor the names of its contributors
218fae3551SRodney W. Grimes  *    may be used to endorse or promote products derived from this software
228fae3551SRodney W. Grimes  *    without specific prior written permission.
238fae3551SRodney W. Grimes  *
248fae3551SRodney W. Grimes  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
258fae3551SRodney W. Grimes  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
268fae3551SRodney W. Grimes  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
278fae3551SRodney W. Grimes  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
288fae3551SRodney W. Grimes  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
298fae3551SRodney W. Grimes  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
308fae3551SRodney W. Grimes  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
318fae3551SRodney W. Grimes  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
328fae3551SRodney W. Grimes  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
338fae3551SRodney W. Grimes  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
348fae3551SRodney W. Grimes  * SUCH DAMAGE.
358fae3551SRodney W. Grimes  */
368fae3551SRodney W. Grimes 
378fae3551SRodney W. Grimes #ifndef lint
388fae3551SRodney W. Grimes static char copyright[] =
398fae3551SRodney W. Grimes "@(#) Copyright (c) 1989, 1993, 1994\n\
408fae3551SRodney W. Grimes 	The Regents of the University of California.  All rights reserved.\n";
418fae3551SRodney W. Grimes #endif not lint
428fae3551SRodney W. Grimes 
438fae3551SRodney W. Grimes #ifndef lint
448fae3551SRodney W. Grimes static char sccsid[] = "@(#)nfsd.c	8.7 (Berkeley) 2/22/94";
458fae3551SRodney W. Grimes #endif not lint
468fae3551SRodney W. Grimes 
478fae3551SRodney W. Grimes #include <sys/param.h>
488fae3551SRodney W. Grimes #include <sys/syslog.h>
498fae3551SRodney W. Grimes #include <sys/ioctl.h>
508fae3551SRodney W. Grimes #include <sys/stat.h>
518fae3551SRodney W. Grimes #include <sys/wait.h>
528fae3551SRodney W. Grimes #include <sys/uio.h>
538fae3551SRodney W. Grimes #include <sys/ucred.h>
548fae3551SRodney W. Grimes #include <sys/mount.h>
558fae3551SRodney W. Grimes #include <sys/socket.h>
568fae3551SRodney W. Grimes #include <sys/socketvar.h>
578fae3551SRodney W. Grimes 
588fae3551SRodney W. Grimes #include <rpc/rpc.h>
598fae3551SRodney W. Grimes #include <rpc/pmap_clnt.h>
608fae3551SRodney W. Grimes #include <rpc/pmap_prot.h>
618fae3551SRodney W. Grimes 
628fae3551SRodney W. Grimes #ifdef ISO
638fae3551SRodney W. Grimes #include <netiso/iso.h>
648fae3551SRodney W. Grimes #endif
658fae3551SRodney W. Grimes #include <nfs/rpcv2.h>
668fae3551SRodney W. Grimes #include <nfs/nfsv2.h>
678fae3551SRodney W. Grimes #include <nfs/nfs.h>
688fae3551SRodney W. Grimes 
698fae3551SRodney W. Grimes #ifdef KERBEROS
708fae3551SRodney W. Grimes #include <kerberosIV/des.h>
718fae3551SRodney W. Grimes #include <kerberosIV/krb.h>
728fae3551SRodney W. Grimes #endif
738fae3551SRodney W. Grimes 
748fae3551SRodney W. Grimes #include <err.h>
758fae3551SRodney W. Grimes #include <errno.h>
768fae3551SRodney W. Grimes #include <fcntl.h>
778fae3551SRodney W. Grimes #include <grp.h>
788fae3551SRodney W. Grimes #include <pwd.h>
798fae3551SRodney W. Grimes #include <signal.h>
808fae3551SRodney W. Grimes #include <stdio.h>
818fae3551SRodney W. Grimes #include <stdlib.h>
828fae3551SRodney W. Grimes #include <strings.h>
838fae3551SRodney W. Grimes #include <unistd.h>
848fae3551SRodney W. Grimes 
858fae3551SRodney W. Grimes /* Global defs */
868fae3551SRodney W. Grimes #ifdef DEBUG
878fae3551SRodney W. Grimes #define	syslog(e, s)	fprintf(stderr,(s))
888fae3551SRodney W. Grimes int	debug = 1;
898fae3551SRodney W. Grimes #else
908fae3551SRodney W. Grimes int	debug = 0;
918fae3551SRodney W. Grimes #endif
928fae3551SRodney W. Grimes 
938fae3551SRodney W. Grimes struct	nfsd_srvargs nsd;
948fae3551SRodney W. Grimes char	**Argv = NULL;		/* pointer to argument vector */
958fae3551SRodney W. Grimes char	*LastArg = NULL;	/* end of argv */
968fae3551SRodney W. Grimes 
978fae3551SRodney W. Grimes #ifdef KERBEROS
988fae3551SRodney W. Grimes char		lnam[ANAME_SZ];
998fae3551SRodney W. Grimes KTEXT_ST	kt;
1008fae3551SRodney W. Grimes AUTH_DAT	auth;
1018fae3551SRodney W. Grimes char		inst[INST_SZ];
1028fae3551SRodney W. Grimes #endif
1038fae3551SRodney W. Grimes 
1048fae3551SRodney W. Grimes void	nonfs __P((int));
1058fae3551SRodney W. Grimes void	reapchild __P((int));
1068fae3551SRodney W. Grimes void	setproctitle __P((char *));
1078fae3551SRodney W. Grimes void	usage __P((void));
1088fae3551SRodney W. Grimes 
1098fae3551SRodney W. Grimes /*
1108fae3551SRodney W. Grimes  * Nfs server daemon mostly just a user context for nfssvc()
1118fae3551SRodney W. Grimes  *
1128fae3551SRodney W. Grimes  * 1 - do file descriptor and signal cleanup
1138fae3551SRodney W. Grimes  * 2 - fork the nfsd(s)
1148fae3551SRodney W. Grimes  * 3 - create server socket(s)
1158fae3551SRodney W. Grimes  * 4 - register socket with portmap
1168fae3551SRodney W. Grimes  *
1178fae3551SRodney W. Grimes  * For connectionless protocols, just pass the socket into the kernel via.
1188fae3551SRodney W. Grimes  * nfssvc().
1198fae3551SRodney W. Grimes  * For connection based sockets, loop doing accepts. When you get a new
1208fae3551SRodney W. Grimes  * socket from accept, pass the msgsock into the kernel via. nfssvc().
1218fae3551SRodney W. Grimes  * The arguments are:
1228fae3551SRodney W. Grimes  *	-c - support iso cltp clients
1238fae3551SRodney W. Grimes  *	-r - reregister with portmapper
1248fae3551SRodney W. Grimes  *	-t - support tcp nfs clients
1258fae3551SRodney W. Grimes  *	-u - support udp nfs clients
1268fae3551SRodney W. Grimes  * followed by "n" which is the number of nfsds' to fork off
1278fae3551SRodney W. Grimes  */
1288fae3551SRodney W. Grimes int
1298fae3551SRodney W. Grimes main(argc, argv, envp)
1308fae3551SRodney W. Grimes 	int argc;
1318fae3551SRodney W. Grimes 	char *argv[], *envp[];
1328fae3551SRodney W. Grimes {
1338fae3551SRodney W. Grimes 	extern int optind;
1348fae3551SRodney W. Grimes 	struct group *grp;
1358fae3551SRodney W. Grimes 	struct nfsd_args nfsdargs;
1368fae3551SRodney W. Grimes 	struct passwd *pwd;
1378fae3551SRodney W. Grimes 	struct ucred *cr;
1388fae3551SRodney W. Grimes 	struct sockaddr_in inetaddr, inetpeer;
1398fae3551SRodney W. Grimes #ifdef ISO
1408fae3551SRodney W. Grimes 	struct sockaddr_iso isoaddr, isopeer;
1418fae3551SRodney W. Grimes #endif
1428fae3551SRodney W. Grimes 	fd_set ready, sockbits;
1438fae3551SRodney W. Grimes 	int ch, cltpflag, connect_type_cnt, i, len, maxsock, msgsock;
1448fae3551SRodney W. Grimes 	int nfsdcnt, nfssvc_flag, on, reregister, sock, tcpflag, tcpsock;
1458fae3551SRodney W. Grimes 	int tp4cnt, tp4flag, tp4sock, tpipcnt, tpipflag, tpipsock, udpflag;
1468fae3551SRodney W. Grimes 	char *cp, **cpp;
1478fae3551SRodney W. Grimes 
1488fae3551SRodney W. Grimes 	/* Save start and extent of argv for setproctitle. */
1498fae3551SRodney W. Grimes 	Argv = argv;
1508fae3551SRodney W. Grimes 	if (envp == 0 || *envp == 0)
1518fae3551SRodney W. Grimes 		envp = argv;
1528fae3551SRodney W. Grimes 	while (*envp)
1538fae3551SRodney W. Grimes 		envp++;
1548fae3551SRodney W. Grimes 	LastArg = envp[-1] + strlen(envp[-1]);
1558fae3551SRodney W. Grimes 
1568fae3551SRodney W. Grimes #define	MAXNFSDCNT	20
1578fae3551SRodney W. Grimes #define	DEFNFSDCNT	 4
1588fae3551SRodney W. Grimes 	nfsdcnt = DEFNFSDCNT;
1598fae3551SRodney W. Grimes 	cltpflag = reregister = tcpflag = tp4cnt = tp4flag = tpipcnt = 0;
1608fae3551SRodney W. Grimes 	tpipflag = udpflag = 0;
1618fae3551SRodney W. Grimes #ifdef ISO
1628fae3551SRodney W. Grimes #define	GETOPT	"cn:rtu"
1638fae3551SRodney W. Grimes #define	USAGE	"[-crtu] [-n num_servers]"
1648fae3551SRodney W. Grimes #else
1658fae3551SRodney W. Grimes #define	GETOPT	"n:rtu"
1668fae3551SRodney W. Grimes #define	USAGE	"[-rtu] [-n num_servers]"
1678fae3551SRodney W. Grimes #endif
1688fae3551SRodney W. Grimes 	while ((ch = getopt(argc, argv, GETOPT)) != EOF)
1698fae3551SRodney W. Grimes 		switch (ch) {
1708fae3551SRodney W. Grimes 		case 'n':
1718fae3551SRodney W. Grimes 			nfsdcnt = atoi(optarg);
1728fae3551SRodney W. Grimes 			if (nfsdcnt < 1 || nfsdcnt > MAXNFSDCNT) {
1738fae3551SRodney W. Grimes 				warnx("nfsd count %d; reset to %d", DEFNFSDCNT);
1748fae3551SRodney W. Grimes 				nfsdcnt = DEFNFSDCNT;
1758fae3551SRodney W. Grimes 			}
1768fae3551SRodney W. Grimes 			break;
1778fae3551SRodney W. Grimes 		case 'r':
1788fae3551SRodney W. Grimes 			reregister = 1;
1798fae3551SRodney W. Grimes 			break;
1808fae3551SRodney W. Grimes 		case 't':
1818fae3551SRodney W. Grimes 			tcpflag = 1;
1828fae3551SRodney W. Grimes 			break;
1838fae3551SRodney W. Grimes 		case 'u':
1848fae3551SRodney W. Grimes 			udpflag = 1;
1858fae3551SRodney W. Grimes 			break;
1868fae3551SRodney W. Grimes #ifdef ISO
1878fae3551SRodney W. Grimes 		case 'c':
1888fae3551SRodney W. Grimes 			cltpflag = 1;
1898fae3551SRodney W. Grimes 			break;
1908fae3551SRodney W. Grimes #ifdef notyet
1918fae3551SRodney W. Grimes 		case 'i':
1928fae3551SRodney W. Grimes 			tp4cnt = 1;
1938fae3551SRodney W. Grimes 			break;
1948fae3551SRodney W. Grimes 		case 'p':
1958fae3551SRodney W. Grimes 			tpipcnt = 1;
1968fae3551SRodney W. Grimes 			break;
1978fae3551SRodney W. Grimes #endif /* notyet */
1988fae3551SRodney W. Grimes #endif /* ISO */
1998fae3551SRodney W. Grimes 		default:
2008fae3551SRodney W. Grimes 		case '?':
2018fae3551SRodney W. Grimes 			usage();
2028fae3551SRodney W. Grimes 		};
2038fae3551SRodney W. Grimes 	argv += optind;
2048fae3551SRodney W. Grimes 	argc -= optind;
2058fae3551SRodney W. Grimes 
2068fae3551SRodney W. Grimes 	/*
2078fae3551SRodney W. Grimes 	 * XXX
2088fae3551SRodney W. Grimes 	 * Backward compatibility, trailing number is the count of daemons.
2098fae3551SRodney W. Grimes 	 */
2108fae3551SRodney W. Grimes 	if (argc > 1)
2118fae3551SRodney W. Grimes 		usage();
2128fae3551SRodney W. Grimes 	if (argc == 1) {
2138fae3551SRodney W. Grimes 		nfsdcnt = atoi(argv[0]);
2148fae3551SRodney W. Grimes 		if (nfsdcnt < 1 || nfsdcnt > MAXNFSDCNT) {
2158fae3551SRodney W. Grimes 			warnx("nfsd count %d; reset to %d", DEFNFSDCNT);
2168fae3551SRodney W. Grimes 			nfsdcnt = DEFNFSDCNT;
2178fae3551SRodney W. Grimes 		}
2188fae3551SRodney W. Grimes 	}
2198fae3551SRodney W. Grimes 
2208fae3551SRodney W. Grimes 	if (debug == 0) {
2218fae3551SRodney W. Grimes 		daemon(0, 0);
2228fae3551SRodney W. Grimes 		(void)signal(SIGHUP, SIG_IGN);
2238fae3551SRodney W. Grimes 		(void)signal(SIGINT, SIG_IGN);
2248fae3551SRodney W. Grimes 		(void)signal(SIGQUIT, SIG_IGN);
2258fae3551SRodney W. Grimes 		(void)signal(SIGSYS, nonfs);
2268fae3551SRodney W. Grimes 		(void)signal(SIGTERM, SIG_IGN);
2278fae3551SRodney W. Grimes 	}
2288fae3551SRodney W. Grimes 	(void)signal(SIGCHLD, reapchild);
2298fae3551SRodney W. Grimes 
2308fae3551SRodney W. Grimes 	if (reregister) {
2318fae3551SRodney W. Grimes 		if (udpflag &&
2328fae3551SRodney W. Grimes 		    !pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_UDP, NFS_PORT))
2338fae3551SRodney W. Grimes 			err(1, "can't register with portmap for UDP.");
2348fae3551SRodney W. Grimes 		if (tcpflag &&
2358fae3551SRodney W. Grimes 		    !pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_TCP, NFS_PORT))
2368fae3551SRodney W. Grimes 			err(1, "can't register with portmap for TCP.");
2378fae3551SRodney W. Grimes 		exit(0);
2388fae3551SRodney W. Grimes 	}
2398fae3551SRodney W. Grimes 	openlog("nfsd:", LOG_PID, LOG_DAEMON);
2408fae3551SRodney W. Grimes 
2418fae3551SRodney W. Grimes 	for (i = 0; i < nfsdcnt; i++) {
2428fae3551SRodney W. Grimes 		switch (fork()) {
2438fae3551SRodney W. Grimes 		case -1:
2448fae3551SRodney W. Grimes 			syslog(LOG_ERR, "fork: %m");
2458fae3551SRodney W. Grimes 			exit (1);
2468fae3551SRodney W. Grimes 		case 0:
2478fae3551SRodney W. Grimes 			break;
2488fae3551SRodney W. Grimes 		default:
2498fae3551SRodney W. Grimes 			continue;
2508fae3551SRodney W. Grimes 		}
2518fae3551SRodney W. Grimes 
2528fae3551SRodney W. Grimes 		setproctitle("nfsd-srv");
2538fae3551SRodney W. Grimes 		nfssvc_flag = NFSSVC_NFSD;
2548fae3551SRodney W. Grimes 		nsd.nsd_nfsd = NULL;
2558fae3551SRodney W. Grimes #ifdef KERBEROS
2568fae3551SRodney W. Grimes 		nsd.nsd_authstr = (char *)kt.dat;
2578fae3551SRodney W. Grimes #endif
2588fae3551SRodney W. Grimes 		while (nfssvc(nfssvc_flag, &nsd) < 0) {
2598fae3551SRodney W. Grimes 			if (errno != ENEEDAUTH) {
2608fae3551SRodney W. Grimes 				syslog(LOG_ERR, "nfssvc: %m");
2618fae3551SRodney W. Grimes 				exit(1);
2628fae3551SRodney W. Grimes 			}
2638fae3551SRodney W. Grimes 			nfssvc_flag = NFSSVC_NFSD | NFSSVC_AUTHINFAIL;
2648fae3551SRodney W. Grimes #ifdef KERBEROS
2658fae3551SRodney W. Grimes 			kt.length = nsd.nsd_authlen;
2668fae3551SRodney W. Grimes 			kt.mbz = 0;
2678fae3551SRodney W. Grimes 			(void)strcpy(inst, "*");
2688fae3551SRodney W. Grimes 			if (krb_rd_req(&kt, "rcmd",
2698fae3551SRodney W. Grimes 			    inst, nsd.nsd_haddr, &auth, "") == RD_AP_OK &&
2708fae3551SRodney W. Grimes 			    krb_kntoln(&auth, lnam) == KSUCCESS &&
2718fae3551SRodney W. Grimes 			    (pwd = getpwnam(lnam)) != NULL) {
2728fae3551SRodney W. Grimes 				cr = &nsd.nsd_cr;
2738fae3551SRodney W. Grimes 				cr->cr_uid = pwd->pw_uid;
2748fae3551SRodney W. Grimes 				cr->cr_groups[0] = pwd->pw_gid;
2758fae3551SRodney W. Grimes 				cr->cr_ngroups = 1;
2768fae3551SRodney W. Grimes 				setgrent();
2778fae3551SRodney W. Grimes 				while ((grp = getgrent()) != NULL) {
2788fae3551SRodney W. Grimes 					if (grp->gr_gid == cr->cr_groups[0])
2798fae3551SRodney W. Grimes 						continue;
2808fae3551SRodney W. Grimes 					for (cpp = grp->gr_mem;
2818fae3551SRodney W. Grimes 					    *cpp != NULL; ++cpp)
2828fae3551SRodney W. Grimes 						if (!strcmp(*cpp, lnam))
2838fae3551SRodney W. Grimes 							break;
2848fae3551SRodney W. Grimes 					if (*cpp == NULL)
2858fae3551SRodney W. Grimes 						continue;
2868fae3551SRodney W. Grimes 					cr->cr_groups[cr->cr_ngroups++]
2878fae3551SRodney W. Grimes 					    = grp->gr_gid;
2888fae3551SRodney W. Grimes 					if (cr->cr_ngroups == NGROUPS)
2898fae3551SRodney W. Grimes 						break;
2908fae3551SRodney W. Grimes 				}
2918fae3551SRodney W. Grimes 				endgrent();
2928fae3551SRodney W. Grimes 				nfssvc_flag = NFSSVC_NFSD | NFSSVC_AUTHIN;
2938fae3551SRodney W. Grimes 			}
2948fae3551SRodney W. Grimes #endif /* KERBEROS */
2958fae3551SRodney W. Grimes 		}
2968fae3551SRodney W. Grimes 		exit(0);
2978fae3551SRodney W. Grimes 	}
2988fae3551SRodney W. Grimes 
2998fae3551SRodney W. Grimes 	/* If we are serving udp, set up the socket. */
3008fae3551SRodney W. Grimes 	if (udpflag) {
3018fae3551SRodney W. Grimes 		if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
3028fae3551SRodney W. Grimes 			syslog(LOG_ERR, "can't create udp socket");
3038fae3551SRodney W. Grimes 			exit(1);
3048fae3551SRodney W. Grimes 		}
3058fae3551SRodney W. Grimes 		inetaddr.sin_family = AF_INET;
3068fae3551SRodney W. Grimes 		inetaddr.sin_addr.s_addr = INADDR_ANY;
3078fae3551SRodney W. Grimes 		inetaddr.sin_port = htons(NFS_PORT);
3088fae3551SRodney W. Grimes 		inetaddr.sin_len = sizeof(inetaddr);
3098fae3551SRodney W. Grimes 		if (bind(sock,
3108fae3551SRodney W. Grimes 		    (struct sockaddr *)&inetaddr, sizeof(inetaddr)) < 0) {
3118fae3551SRodney W. Grimes 			syslog(LOG_ERR, "can't bind udp addr");
3128fae3551SRodney W. Grimes 			exit(1);
3138fae3551SRodney W. Grimes 		}
3148fae3551SRodney W. Grimes 		if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_UDP, NFS_PORT)) {
3158fae3551SRodney W. Grimes 			syslog(LOG_ERR, "can't register with udp portmap");
3168fae3551SRodney W. Grimes 			exit(1);
3178fae3551SRodney W. Grimes 		}
3188fae3551SRodney W. Grimes 		nfsdargs.sock = sock;
3198fae3551SRodney W. Grimes 		nfsdargs.name = NULL;
3208fae3551SRodney W. Grimes 		nfsdargs.namelen = 0;
3218fae3551SRodney W. Grimes 		if (nfssvc(NFSSVC_ADDSOCK, &nfsdargs) < 0) {
3228fae3551SRodney W. Grimes 			syslog(LOG_ERR, "can't Add UDP socket");
3238fae3551SRodney W. Grimes 			exit(1);
3248fae3551SRodney W. Grimes 		}
3258fae3551SRodney W. Grimes 		(void)close(sock);
3268fae3551SRodney W. Grimes 	}
3278fae3551SRodney W. Grimes 
3288fae3551SRodney W. Grimes #ifdef ISO
3298fae3551SRodney W. Grimes 	/* If we are serving cltp, set up the socket. */
3308fae3551SRodney W. Grimes 	if (cltpflag) {
3318fae3551SRodney W. Grimes 		if ((sock = socket(AF_ISO, SOCK_DGRAM, 0)) < 0) {
3328fae3551SRodney W. Grimes 			syslog(LOG_ERR, "can't create cltp socket");
3338fae3551SRodney W. Grimes 			exit(1);
3348fae3551SRodney W. Grimes 		}
3358fae3551SRodney W. Grimes 		memset(&isoaddr, 0, sizeof(isoaddr));
3368fae3551SRodney W. Grimes 		isoaddr.siso_family = AF_ISO;
3378fae3551SRodney W. Grimes 		isoaddr.siso_tlen = 2;
3388fae3551SRodney W. Grimes 		cp = TSEL(&isoaddr);
3398fae3551SRodney W. Grimes 		*cp++ = (NFS_PORT >> 8);
3408fae3551SRodney W. Grimes 		*cp = (NFS_PORT & 0xff);
3418fae3551SRodney W. Grimes 		isoaddr.siso_len = sizeof(isoaddr);
3428fae3551SRodney W. Grimes 		if (bind(sock,
3438fae3551SRodney W. Grimes 		    (struct sockaddr *)&isoaddr, sizeof(isoaddr)) < 0) {
3448fae3551SRodney W. Grimes 			syslog(LOG_ERR, "can't bind cltp addr");
3458fae3551SRodney W. Grimes 			exit(1);
3468fae3551SRodney W. Grimes 		}
3478fae3551SRodney W. Grimes #ifdef notyet
3488fae3551SRodney W. Grimes 		/*
3498fae3551SRodney W. Grimes 		 * XXX
3508fae3551SRodney W. Grimes 		 * Someday this should probably use "rpcbind", the son of
3518fae3551SRodney W. Grimes 		 * portmap.
3528fae3551SRodney W. Grimes 		 */
3538fae3551SRodney W. Grimes 		if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_UDP, NFS_PORT)) {
3548fae3551SRodney W. Grimes 			syslog(LOG_ERR, "can't register with udp portmap");
3558fae3551SRodney W. Grimes 			exit(1);
3568fae3551SRodney W. Grimes 		}
3578fae3551SRodney W. Grimes #endif /* notyet */
3588fae3551SRodney W. Grimes 		nfsdargs.sock = sock;
3598fae3551SRodney W. Grimes 		nfsdargs.name = NULL;
3608fae3551SRodney W. Grimes 		nfsdargs.namelen = 0;
3618fae3551SRodney W. Grimes 		if (nfssvc(NFSSVC_ADDSOCK, &nfsdargs) < 0) {
3628fae3551SRodney W. Grimes 			syslog(LOG_ERR, "can't add UDP socket");
3638fae3551SRodney W. Grimes 			exit(1);
3648fae3551SRodney W. Grimes 		}
3658fae3551SRodney W. Grimes 		close(sock);
3668fae3551SRodney W. Grimes 	}
3678fae3551SRodney W. Grimes #endif /* ISO */
3688fae3551SRodney W. Grimes 
3698fae3551SRodney W. Grimes 	/* Now set up the master server socket waiting for tcp connections. */
3708fae3551SRodney W. Grimes 	on = 1;
3718fae3551SRodney W. Grimes 	FD_ZERO(&sockbits);
3728fae3551SRodney W. Grimes 	connect_type_cnt = 0;
3738fae3551SRodney W. Grimes 	if (tcpflag) {
3748fae3551SRodney W. Grimes 		if ((tcpsock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
3758fae3551SRodney W. Grimes 			syslog(LOG_ERR, "can't create tcp socket");
3768fae3551SRodney W. Grimes 			exit(1);
3778fae3551SRodney W. Grimes 		}
3788fae3551SRodney W. Grimes 		if (setsockopt(tcpsock,
3798fae3551SRodney W. Grimes 		    SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0)
3808fae3551SRodney W. Grimes 			syslog(LOG_ERR, "setsockopt SO_REUSEADDR: %m");
3818fae3551SRodney W. Grimes 		inetaddr.sin_family = AF_INET;
3828fae3551SRodney W. Grimes 		inetaddr.sin_addr.s_addr = INADDR_ANY;
3838fae3551SRodney W. Grimes 		inetaddr.sin_port = htons(NFS_PORT);
3848fae3551SRodney W. Grimes 		inetaddr.sin_len = sizeof(inetaddr);
3858fae3551SRodney W. Grimes 		if (bind(tcpsock,
3868fae3551SRodney W. Grimes 		    (struct sockaddr *)&inetaddr, sizeof (inetaddr)) < 0) {
3878fae3551SRodney W. Grimes 			syslog(LOG_ERR, "can't bind tcp addr");
3888fae3551SRodney W. Grimes 			exit(1);
3898fae3551SRodney W. Grimes 		}
3908fae3551SRodney W. Grimes 		if (listen(tcpsock, 5) < 0) {
3918fae3551SRodney W. Grimes 			syslog(LOG_ERR, "listen failed");
3928fae3551SRodney W. Grimes 			exit(1);
3938fae3551SRodney W. Grimes 		}
3948fae3551SRodney W. Grimes 		if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_TCP, NFS_PORT)) {
3958fae3551SRodney W. Grimes 			syslog(LOG_ERR, "can't register tcp with portmap");
3968fae3551SRodney W. Grimes 			exit(1);
3978fae3551SRodney W. Grimes 		}
3988fae3551SRodney W. Grimes 		FD_SET(tcpsock, &sockbits);
3998fae3551SRodney W. Grimes 		maxsock = tcpsock;
4008fae3551SRodney W. Grimes 		connect_type_cnt++;
4018fae3551SRodney W. Grimes 	}
4028fae3551SRodney W. Grimes 
4038fae3551SRodney W. Grimes #ifdef notyet
4048fae3551SRodney W. Grimes 	/* Now set up the master server socket waiting for tp4 connections. */
4058fae3551SRodney W. Grimes 	if (tp4flag) {
4068fae3551SRodney W. Grimes 		if ((tp4sock = socket(AF_ISO, SOCK_SEQPACKET, 0)) < 0) {
4078fae3551SRodney W. Grimes 			syslog(LOG_ERR, "can't create tp4 socket");
4088fae3551SRodney W. Grimes 			exit(1);
4098fae3551SRodney W. Grimes 		}
4108fae3551SRodney W. Grimes 		if (setsockopt(tp4sock,
4118fae3551SRodney W. Grimes 		    SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0)
4128fae3551SRodney W. Grimes 			syslog(LOG_ERR, "setsockopt SO_REUSEADDR: %m");
4138fae3551SRodney W. Grimes 		memset(&isoaddr, 0, sizeof(isoaddr));
4148fae3551SRodney W. Grimes 		isoaddr.siso_family = AF_ISO;
4158fae3551SRodney W. Grimes 		isoaddr.siso_tlen = 2;
4168fae3551SRodney W. Grimes 		cp = TSEL(&isoaddr);
4178fae3551SRodney W. Grimes 		*cp++ = (NFS_PORT >> 8);
4188fae3551SRodney W. Grimes 		*cp = (NFS_PORT & 0xff);
4198fae3551SRodney W. Grimes 		isoaddr.siso_len = sizeof(isoaddr);
4208fae3551SRodney W. Grimes 		if (bind(tp4sock,
4218fae3551SRodney W. Grimes 		    (struct sockaddr *)&isoaddr, sizeof (isoaddr)) < 0) {
4228fae3551SRodney W. Grimes 			syslog(LOG_ERR, "can't bind tp4 addr");
4238fae3551SRodney W. Grimes 			exit(1);
4248fae3551SRodney W. Grimes 		}
4258fae3551SRodney W. Grimes 		if (listen(tp4sock, 5) < 0) {
4268fae3551SRodney W. Grimes 			syslog(LOG_ERR, "listen failed");
4278fae3551SRodney W. Grimes 			exit(1);
4288fae3551SRodney W. Grimes 		}
4298fae3551SRodney W. Grimes 		/*
4308fae3551SRodney W. Grimes 		 * XXX
4318fae3551SRodney W. Grimes 		 * Someday this should probably use "rpcbind", the son of
4328fae3551SRodney W. Grimes 		 * portmap.
4338fae3551SRodney W. Grimes 		 */
4348fae3551SRodney W. Grimes 		if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_TCP, NFS_PORT)) {
4358fae3551SRodney W. Grimes 			syslog(LOG_ERR, "can't register tcp with portmap");
4368fae3551SRodney W. Grimes 			exit(1);
4378fae3551SRodney W. Grimes 		}
4388fae3551SRodney W. Grimes 		FD_SET(tp4sock, &sockbits);
4398fae3551SRodney W. Grimes 		maxsock = tp4sock;
4408fae3551SRodney W. Grimes 		connect_type_cnt++;
4418fae3551SRodney W. Grimes 	}
4428fae3551SRodney W. Grimes 
4438fae3551SRodney W. Grimes 	/* Now set up the master server socket waiting for tpip connections. */
4448fae3551SRodney W. Grimes 	if (tpipflag) {
4458fae3551SRodney W. Grimes 		if ((tpipsock = socket(AF_INET, SOCK_SEQPACKET, 0)) < 0) {
4468fae3551SRodney W. Grimes 			syslog(LOG_ERR, "can't create tpip socket");
4478fae3551SRodney W. Grimes 			exit(1);
4488fae3551SRodney W. Grimes 		}
4498fae3551SRodney W. Grimes 		if (setsockopt(tpipsock,
4508fae3551SRodney W. Grimes 		    SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0)
4518fae3551SRodney W. Grimes 			syslog(LOG_ERR, "setsockopt SO_REUSEADDR: %m");
4528fae3551SRodney W. Grimes 		inetaddr.sin_family = AF_INET;
4538fae3551SRodney W. Grimes 		inetaddr.sin_addr.s_addr = INADDR_ANY;
4548fae3551SRodney W. Grimes 		inetaddr.sin_port = htons(NFS_PORT);
4558fae3551SRodney W. Grimes 		inetaddr.sin_len = sizeof(inetaddr);
4568fae3551SRodney W. Grimes 		if (bind(tpipsock,
4578fae3551SRodney W. Grimes 		    (struct sockaddr *)&inetaddr, sizeof (inetaddr)) < 0) {
4588fae3551SRodney W. Grimes 			syslog(LOG_ERR, "can't bind tcp addr");
4598fae3551SRodney W. Grimes 			exit(1);
4608fae3551SRodney W. Grimes 		}
4618fae3551SRodney W. Grimes 		if (listen(tpipsock, 5) < 0) {
4628fae3551SRodney W. Grimes 			syslog(LOG_ERR, "listen failed");
4638fae3551SRodney W. Grimes 			exit(1);
4648fae3551SRodney W. Grimes 		}
4658fae3551SRodney W. Grimes 		/*
4668fae3551SRodney W. Grimes 		 * XXX
4678fae3551SRodney W. Grimes 		 * Someday this should probably use "rpcbind", the son of
4688fae3551SRodney W. Grimes 		 * portmap.
4698fae3551SRodney W. Grimes 		 */
4708fae3551SRodney W. Grimes 		if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_TCP, NFS_PORT)) {
4718fae3551SRodney W. Grimes 			syslog(LOG_ERR, "can't register tcp with portmap");
4728fae3551SRodney W. Grimes 			exit(1);
4738fae3551SRodney W. Grimes 		}
4748fae3551SRodney W. Grimes 		FD_SET(tpipsock, &sockbits);
4758fae3551SRodney W. Grimes 		maxsock = tpipsock;
4768fae3551SRodney W. Grimes 		connect_type_cnt++;
4778fae3551SRodney W. Grimes 	}
4788fae3551SRodney W. Grimes #endif /* notyet */
4798fae3551SRodney W. Grimes 
4808fae3551SRodney W. Grimes 	if (connect_type_cnt == 0)
4818fae3551SRodney W. Grimes 		exit(0);
4828fae3551SRodney W. Grimes 
4838fae3551SRodney W. Grimes 	setproctitle("nfsd-master");
4848fae3551SRodney W. Grimes 
4858fae3551SRodney W. Grimes 	/*
4868fae3551SRodney W. Grimes 	 * Loop forever accepting connections and passing the sockets
4878fae3551SRodney W. Grimes 	 * into the kernel for the mounts.
4888fae3551SRodney W. Grimes 	 */
4898fae3551SRodney W. Grimes 	for (;;) {
4908fae3551SRodney W. Grimes 		ready = sockbits;
4918fae3551SRodney W. Grimes 		if (connect_type_cnt > 1) {
4928fae3551SRodney W. Grimes 			if (select(maxsock + 1,
4938fae3551SRodney W. Grimes 			    &ready, NULL, NULL, NULL) < 1) {
4948fae3551SRodney W. Grimes 				syslog(LOG_ERR, "select failed: %m");
4958fae3551SRodney W. Grimes 				exit(1);
4968fae3551SRodney W. Grimes 			}
4978fae3551SRodney W. Grimes 		}
4988fae3551SRodney W. Grimes 		if (tcpflag && FD_ISSET(tcpsock, &ready)) {
4998fae3551SRodney W. Grimes 			len = sizeof(inetpeer);
5008fae3551SRodney W. Grimes 			if ((msgsock = accept(tcpsock,
5018fae3551SRodney W. Grimes 			    (struct sockaddr *)&inetpeer, &len)) < 0) {
5028fae3551SRodney W. Grimes 				syslog(LOG_ERR, "accept failed: %m");
5038fae3551SRodney W. Grimes 				exit(1);
5048fae3551SRodney W. Grimes 			}
5058fae3551SRodney W. Grimes 			memset(inetpeer.sin_zero, 0, sizeof(inetpeer.sin_zero));
5068fae3551SRodney W. Grimes 			if (setsockopt(msgsock, SOL_SOCKET,
5078fae3551SRodney W. Grimes 			    SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0)
5088fae3551SRodney W. Grimes 				syslog(LOG_ERR,
5098fae3551SRodney W. Grimes 				    "setsockopt SO_KEEPALIVE: %m");
5108fae3551SRodney W. Grimes 			nfsdargs.sock = msgsock;
5118fae3551SRodney W. Grimes 			nfsdargs.name = (caddr_t)&inetpeer;
5128fae3551SRodney W. Grimes 			nfsdargs.namelen = sizeof(inetpeer);
5138fae3551SRodney W. Grimes 			nfssvc(NFSSVC_ADDSOCK, &nfsdargs);
5148fae3551SRodney W. Grimes 			(void)close(msgsock);
5158fae3551SRodney W. Grimes 		}
5168fae3551SRodney W. Grimes #ifdef notyet
5178fae3551SRodney W. Grimes 		if (tp4flag && FD_ISSET(tp4sock, &ready)) {
5188fae3551SRodney W. Grimes 			len = sizeof(isopeer);
5198fae3551SRodney W. Grimes 			if ((msgsock = accept(tp4sock,
5208fae3551SRodney W. Grimes 			    (struct sockaddr *)&isopeer, &len)) < 0) {
5218fae3551SRodney W. Grimes 				syslog(LOG_ERR, "accept failed: %m");
5228fae3551SRodney W. Grimes 				exit(1);
5238fae3551SRodney W. Grimes 			}
5248fae3551SRodney W. Grimes 			if (setsockopt(msgsock, SOL_SOCKET,
5258fae3551SRodney W. Grimes 			    SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0)
5268fae3551SRodney W. Grimes 				syslog(LOG_ERR,
5278fae3551SRodney W. Grimes 				    "setsockopt SO_KEEPALIVE: %m");
5288fae3551SRodney W. Grimes 			nfsdargs.sock = msgsock;
5298fae3551SRodney W. Grimes 			nfsdargs.name = (caddr_t)&isopeer;
5308fae3551SRodney W. Grimes 			nfsdargs.namelen = len;
5318fae3551SRodney W. Grimes 			nfssvc(NFSSVC_ADDSOCK, &nfsdargs);
5328fae3551SRodney W. Grimes 			(void)close(msgsock);
5338fae3551SRodney W. Grimes 		}
5348fae3551SRodney W. Grimes 		if (tpipflag && FD_ISSET(tpipsock, &ready)) {
5358fae3551SRodney W. Grimes 			len = sizeof(inetpeer);
5368fae3551SRodney W. Grimes 			if ((msgsock = accept(tpipsock,
5378fae3551SRodney W. Grimes 			    (struct sockaddr *)&inetpeer, &len)) < 0) {
5388fae3551SRodney W. Grimes 				syslog(LOG_ERR, "Accept failed: %m");
5398fae3551SRodney W. Grimes 				exit(1);
5408fae3551SRodney W. Grimes 			}
5418fae3551SRodney W. Grimes 			if (setsockopt(msgsock, SOL_SOCKET,
5428fae3551SRodney W. Grimes 			    SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0)
5438fae3551SRodney W. Grimes 				syslog(LOG_ERR, "setsockopt SO_KEEPALIVE: %m");
5448fae3551SRodney W. Grimes 			nfsdargs.sock = msgsock;
5458fae3551SRodney W. Grimes 			nfsdargs.name = (caddr_t)&inetpeer;
5468fae3551SRodney W. Grimes 			nfsdargs.namelen = len;
5478fae3551SRodney W. Grimes 			nfssvc(NFSSVC_ADDSOCK, &nfsdargs);
5488fae3551SRodney W. Grimes 			(void)close(msgsock);
5498fae3551SRodney W. Grimes 		}
5508fae3551SRodney W. Grimes #endif /* notyet */
5518fae3551SRodney W. Grimes 	}
5528fae3551SRodney W. Grimes }
5538fae3551SRodney W. Grimes 
5548fae3551SRodney W. Grimes void
5558fae3551SRodney W. Grimes usage()
5568fae3551SRodney W. Grimes {
5578fae3551SRodney W. Grimes 	(void)fprintf(stderr, "nfsd %s\n", USAGE);
5588fae3551SRodney W. Grimes 	exit(1);
5598fae3551SRodney W. Grimes }
5608fae3551SRodney W. Grimes 
5618fae3551SRodney W. Grimes void
5628fae3551SRodney W. Grimes nonfs(signo)
5638fae3551SRodney W. Grimes 	int signo;
5648fae3551SRodney W. Grimes {
5658fae3551SRodney W. Grimes 	syslog(LOG_ERR, "missing system call: NFS not available.");
5668fae3551SRodney W. Grimes }
5678fae3551SRodney W. Grimes 
5688fae3551SRodney W. Grimes void
5698fae3551SRodney W. Grimes reapchild(signo)
5708fae3551SRodney W. Grimes 	int signo;
5718fae3551SRodney W. Grimes {
5728fae3551SRodney W. Grimes 
5738fae3551SRodney W. Grimes 	while (wait3(NULL, WNOHANG, NULL));
5748fae3551SRodney W. Grimes }
5758fae3551SRodney W. Grimes 
5768fae3551SRodney W. Grimes void
5778fae3551SRodney W. Grimes setproctitle(a)
5788fae3551SRodney W. Grimes 	char *a;
5798fae3551SRodney W. Grimes {
5808fae3551SRodney W. Grimes 	register char *cp;
5818fae3551SRodney W. Grimes 	char buf[80];
5828fae3551SRodney W. Grimes 
5838fae3551SRodney W. Grimes 	cp = Argv[0];
5848fae3551SRodney W. Grimes 	(void)snprintf(buf, sizeof(buf), "%s", a);
5858fae3551SRodney W. Grimes 	(void)strncpy(cp, buf, LastArg - cp);
5868fae3551SRodney W. Grimes 	cp += strlen(cp);
5878fae3551SRodney W. Grimes 	while (cp < LastArg)
5888fae3551SRodney W. Grimes 		*cp++ = ' ';
5898fae3551SRodney W. Grimes }
590