Home | History | Annotate | Line # | Download | only in nfsd
nfsd.c revision 1.28.2.1
      1  1.28.2.1       he /*	$NetBSD: nfsd.c,v 1.28.2.1 1999/09/29 07:15:26 he Exp $	*/
      2      1.16      cgd 
      3       1.1      cgd /*
      4      1.11  mycroft  * Copyright (c) 1989, 1993, 1994
      5      1.11  mycroft  *	The Regents of the University of California.  All rights reserved.
      6       1.1      cgd  *
      7       1.1      cgd  * This code is derived from software contributed to Berkeley by
      8       1.1      cgd  * Rick Macklem at The University of Guelph.
      9       1.1      cgd  *
     10       1.1      cgd  * Redistribution and use in source and binary forms, with or without
     11       1.1      cgd  * modification, are permitted provided that the following conditions
     12       1.1      cgd  * are met:
     13       1.1      cgd  * 1. Redistributions of source code must retain the above copyright
     14       1.1      cgd  *    notice, this list of conditions and the following disclaimer.
     15       1.1      cgd  * 2. Redistributions in binary form must reproduce the above copyright
     16       1.1      cgd  *    notice, this list of conditions and the following disclaimer in the
     17       1.1      cgd  *    documentation and/or other materials provided with the distribution.
     18       1.1      cgd  * 3. All advertising materials mentioning features or use of this software
     19       1.1      cgd  *    must display the following acknowledgement:
     20       1.1      cgd  *	This product includes software developed by the University of
     21       1.1      cgd  *	California, Berkeley and its contributors.
     22       1.1      cgd  * 4. Neither the name of the University nor the names of its contributors
     23       1.1      cgd  *    may be used to endorse or promote products derived from this software
     24       1.1      cgd  *    without specific prior written permission.
     25       1.1      cgd  *
     26       1.1      cgd  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     27       1.1      cgd  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     28       1.1      cgd  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     29       1.1      cgd  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     30       1.1      cgd  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     31       1.1      cgd  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     32       1.1      cgd  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     33       1.1      cgd  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     34       1.1      cgd  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     35       1.1      cgd  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     36       1.1      cgd  * SUCH DAMAGE.
     37       1.1      cgd  */
     38       1.1      cgd 
     39      1.23    lukem #include <sys/cdefs.h>
     40       1.1      cgd #ifndef lint
     41      1.23    lukem __COPYRIGHT("@(#) Copyright (c) 1989, 1993, 1994\n\
     42      1.23    lukem 	The Regents of the University of California.  All rights reserved.\n");
     43       1.1      cgd #endif not lint
     44       1.1      cgd 
     45       1.1      cgd #ifndef lint
     46      1.16      cgd #if 0
     47      1.18     fvdl static char sccsid[] = "@(#)nfsd.c	8.9 (Berkeley) 3/29/95";
     48      1.16      cgd #else
     49  1.28.2.1       he __RCSID("$NetBSD: nfsd.c,v 1.28.2.1 1999/09/29 07:15:26 he Exp $");
     50      1.16      cgd #endif
     51      1.18     fvdl #endif /* not lint */
     52       1.1      cgd 
     53      1.11  mycroft #include <sys/param.h>
     54       1.1      cgd #include <sys/ioctl.h>
     55       1.1      cgd #include <sys/stat.h>
     56       1.1      cgd #include <sys/wait.h>
     57      1.11  mycroft #include <sys/uio.h>
     58      1.11  mycroft #include <sys/ucred.h>
     59       1.1      cgd #include <sys/mount.h>
     60       1.1      cgd #include <sys/socket.h>
     61       1.1      cgd #include <sys/socketvar.h>
     62      1.11  mycroft 
     63       1.1      cgd #include <rpc/rpc.h>
     64       1.1      cgd #include <rpc/pmap_clnt.h>
     65       1.1      cgd #include <rpc/pmap_prot.h>
     66      1.11  mycroft 
     67      1.11  mycroft #ifdef ISO
     68      1.11  mycroft #include <netiso/iso.h>
     69      1.11  mycroft #endif
     70       1.1      cgd #include <nfs/rpcv2.h>
     71      1.18     fvdl #include <nfs/nfsproto.h>
     72      1.11  mycroft #include <nfs/nfs.h>
     73      1.11  mycroft 
     74      1.18     fvdl #ifdef NFSKERB
     75      1.11  mycroft #include <kerberosIV/des.h>
     76      1.11  mycroft #include <kerberosIV/krb.h>
     77      1.11  mycroft #endif
     78      1.11  mycroft 
     79      1.11  mycroft #include <err.h>
     80      1.11  mycroft #include <errno.h>
     81      1.11  mycroft #include <fcntl.h>
     82      1.11  mycroft #include <grp.h>
     83      1.11  mycroft #include <pwd.h>
     84      1.11  mycroft #include <signal.h>
     85      1.11  mycroft #include <stdio.h>
     86      1.11  mycroft #include <stdlib.h>
     87      1.25    perry #include <string.h>
     88      1.19  mycroft #include <syslog.h>
     89      1.11  mycroft #include <unistd.h>
     90       1.1      cgd 
     91       1.1      cgd /* Global defs */
     92       1.1      cgd #ifdef DEBUG
     93       1.1      cgd #define	syslog(e, s)	fprintf(stderr,(s))
     94       1.1      cgd int	debug = 1;
     95       1.1      cgd #else
     96       1.1      cgd int	debug = 0;
     97       1.1      cgd #endif
     98      1.11  mycroft 
     99      1.11  mycroft struct	nfsd_srvargs nsd;
    100      1.11  mycroft 
    101      1.18     fvdl #ifdef NFSKERB
    102      1.11  mycroft char		lnam[ANAME_SZ];
    103      1.11  mycroft KTEXT_ST	kt;
    104      1.18     fvdl AUTH_DAT	kauth;
    105      1.11  mycroft char		inst[INST_SZ];
    106      1.18     fvdl struct nfsrpc_fullblock kin, kout;
    107      1.18     fvdl struct nfsrpc_fullverf kverf;
    108      1.18     fvdl NFSKERBKEY_T	kivec;
    109      1.18     fvdl struct timeval	ktv;
    110      1.18     fvdl NFSKERBKEYSCHED_T kerb_keysched;
    111      1.11  mycroft #endif
    112      1.11  mycroft 
    113      1.23    lukem int	main __P((int, char **));
    114      1.11  mycroft void	nonfs __P((int));
    115      1.11  mycroft void	reapchild __P((int));
    116      1.11  mycroft void	usage __P((void));
    117       1.1      cgd 
    118       1.1      cgd /*
    119       1.1      cgd  * Nfs server daemon mostly just a user context for nfssvc()
    120      1.11  mycroft  *
    121       1.1      cgd  * 1 - do file descriptor and signal cleanup
    122      1.11  mycroft  * 2 - fork the nfsd(s)
    123      1.11  mycroft  * 3 - create server socket(s)
    124      1.11  mycroft  * 4 - register socket with portmap
    125      1.11  mycroft  *
    126      1.28    lukem  * For connectionless protocols, just pass the socket into the kernel via
    127      1.11  mycroft  * nfssvc().
    128      1.11  mycroft  * For connection based sockets, loop doing accepts. When you get a new
    129      1.28    lukem  * socket from accept, pass the msgsock into the kernel via nfssvc().
    130       1.1      cgd  * The arguments are:
    131      1.11  mycroft  *	-c - support iso cltp clients
    132      1.11  mycroft  *	-r - reregister with portmapper
    133      1.11  mycroft  *	-t - support tcp nfs clients
    134      1.11  mycroft  *	-u - support udp nfs clients
    135      1.11  mycroft  * followed by "n" which is the number of nfsds' to fork off
    136       1.1      cgd  */
    137      1.11  mycroft int
    138      1.23    lukem main(argc, argv)
    139       1.1      cgd 	int argc;
    140      1.23    lukem 	char *argv[];
    141       1.1      cgd {
    142      1.11  mycroft 	struct nfsd_args nfsdargs;
    143      1.11  mycroft 	struct sockaddr_in inetaddr, inetpeer;
    144      1.11  mycroft #ifdef ISO
    145      1.11  mycroft 	struct sockaddr_iso isoaddr, isopeer;
    146      1.11  mycroft #endif
    147      1.11  mycroft 	fd_set ready, sockbits;
    148      1.11  mycroft 	int ch, cltpflag, connect_type_cnt, i, len, maxsock, msgsock;
    149      1.11  mycroft 	int nfsdcnt, nfssvc_flag, on, reregister, sock, tcpflag, tcpsock;
    150      1.23    lukem 	int tp4cnt, tp4flag, tpipcnt, tpipflag, udpflag;
    151      1.23    lukem #ifdef NFSKERB
    152      1.23    lukem 	struct group *grp;
    153      1.23    lukem 	struct passwd *pwd;
    154      1.23    lukem 	struct ucred *cr;
    155      1.23    lukem 	struct timeval ktv;
    156      1.23    lukem 	int tp4sock, tpipsock;
    157      1.11  mycroft 	char *cp, **cpp;
    158      1.23    lukem #endif
    159      1.11  mycroft 
    160      1.11  mycroft #define	MAXNFSDCNT	20
    161      1.11  mycroft #define	DEFNFSDCNT	 4
    162      1.11  mycroft 	nfsdcnt = DEFNFSDCNT;
    163      1.11  mycroft 	cltpflag = reregister = tcpflag = tp4cnt = tp4flag = tpipcnt = 0;
    164      1.11  mycroft 	tpipflag = udpflag = 0;
    165      1.23    lukem 	maxsock = tcpsock = 0;
    166      1.11  mycroft #ifdef ISO
    167      1.11  mycroft #define	GETOPT	"cn:rtu"
    168      1.11  mycroft #define	USAGE	"[-crtu] [-n num_servers]"
    169      1.11  mycroft #else
    170      1.11  mycroft #define	GETOPT	"n:rtu"
    171      1.11  mycroft #define	USAGE	"[-rtu] [-n num_servers]"
    172      1.11  mycroft #endif
    173      1.22   kleink 	while ((ch = getopt(argc, argv, GETOPT)) != -1)
    174      1.11  mycroft 		switch (ch) {
    175      1.11  mycroft 		case 'n':
    176      1.11  mycroft 			nfsdcnt = atoi(optarg);
    177      1.11  mycroft 			if (nfsdcnt < 1 || nfsdcnt > MAXNFSDCNT) {
    178      1.21     fvdl 				warnx("nfsd count %d; reset to %d", nfsdcnt, DEFNFSDCNT);
    179      1.11  mycroft 				nfsdcnt = DEFNFSDCNT;
    180      1.11  mycroft 			}
    181      1.11  mycroft 			break;
    182       1.1      cgd 		case 'r':
    183      1.11  mycroft 			reregister = 1;
    184       1.1      cgd 			break;
    185       1.1      cgd 		case 't':
    186      1.11  mycroft 			tcpflag = 1;
    187       1.1      cgd 			break;
    188       1.1      cgd 		case 'u':
    189      1.11  mycroft 			udpflag = 1;
    190      1.11  mycroft 			break;
    191      1.11  mycroft #ifdef ISO
    192      1.11  mycroft 		case 'c':
    193      1.11  mycroft 			cltpflag = 1;
    194       1.1      cgd 			break;
    195      1.11  mycroft #ifdef notyet
    196      1.11  mycroft 		case 'i':
    197      1.11  mycroft 			tp4cnt = 1;
    198      1.11  mycroft 			break;
    199      1.11  mycroft 		case 'p':
    200      1.11  mycroft 			tpipcnt = 1;
    201      1.11  mycroft 			break;
    202      1.11  mycroft #endif /* notyet */
    203      1.11  mycroft #endif /* ISO */
    204       1.1      cgd 		default:
    205       1.1      cgd 		case '?':
    206       1.1      cgd 			usage();
    207      1.11  mycroft 		};
    208      1.11  mycroft 	argv += optind;
    209      1.11  mycroft 	argc -= optind;
    210       1.1      cgd 
    211       1.1      cgd 	/*
    212      1.11  mycroft 	 * XXX
    213      1.11  mycroft 	 * Backward compatibility, trailing number is the count of daemons.
    214       1.1      cgd 	 */
    215      1.11  mycroft 	if (argc > 1)
    216      1.11  mycroft 		usage();
    217      1.11  mycroft 	if (argc == 1) {
    218      1.11  mycroft 		nfsdcnt = atoi(argv[0]);
    219      1.11  mycroft 		if (nfsdcnt < 1 || nfsdcnt > MAXNFSDCNT) {
    220      1.21     fvdl 			warnx("nfsd count %d; reset to %d", nfsdcnt, DEFNFSDCNT);
    221      1.11  mycroft 			nfsdcnt = DEFNFSDCNT;
    222      1.11  mycroft 		}
    223       1.1      cgd 	}
    224  1.28.2.1       he 
    225  1.28.2.1       he 	/*
    226  1.28.2.1       he 	 * If none of TCP or UDP are specified, default to UDP only.
    227  1.28.2.1       he 	 */
    228  1.28.2.1       he 	if (tcpflag == 0 && udpflag == 0)
    229  1.28.2.1       he 		udpflag = 1;
    230       1.1      cgd 
    231       1.1      cgd 	if (debug == 0) {
    232       1.1      cgd 		daemon(0, 0);
    233      1.11  mycroft 		(void)signal(SIGHUP, SIG_IGN);
    234      1.11  mycroft 		(void)signal(SIGINT, SIG_IGN);
    235      1.11  mycroft 		(void)signal(SIGQUIT, SIG_IGN);
    236      1.11  mycroft 		(void)signal(SIGSYS, nonfs);
    237       1.1      cgd 	}
    238      1.11  mycroft 	(void)signal(SIGCHLD, reapchild);
    239      1.11  mycroft 
    240      1.11  mycroft 	if (reregister) {
    241      1.11  mycroft 		if (udpflag &&
    242      1.18     fvdl 		    (!pmap_set(RPCPROG_NFS, 2, IPPROTO_UDP, NFS_PORT) ||
    243      1.18     fvdl 		     !pmap_set(RPCPROG_NFS, 3, IPPROTO_UDP, NFS_PORT)))
    244      1.11  mycroft 			err(1, "can't register with portmap for UDP.");
    245      1.11  mycroft 		if (tcpflag &&
    246      1.18     fvdl 		    (!pmap_set(RPCPROG_NFS, 2, IPPROTO_TCP, NFS_PORT) ||
    247      1.18     fvdl 		     !pmap_set(RPCPROG_NFS, 3, IPPROTO_TCP, NFS_PORT)))
    248      1.11  mycroft 			err(1, "can't register with portmap for TCP.");
    249      1.11  mycroft 		exit(0);
    250       1.8      cgd 	}
    251      1.11  mycroft 	openlog("nfsd:", LOG_PID, LOG_DAEMON);
    252      1.11  mycroft 
    253      1.11  mycroft 	for (i = 0; i < nfsdcnt; i++) {
    254      1.11  mycroft 		switch (fork()) {
    255      1.11  mycroft 		case -1:
    256      1.11  mycroft 			syslog(LOG_ERR, "fork: %m");
    257      1.11  mycroft 			exit (1);
    258      1.11  mycroft 		case 0:
    259      1.11  mycroft 			break;
    260      1.11  mycroft 		default:
    261      1.11  mycroft 			continue;
    262       1.1      cgd 		}
    263      1.11  mycroft 
    264      1.13  mycroft 		setproctitle("server");
    265      1.11  mycroft 		nfssvc_flag = NFSSVC_NFSD;
    266      1.11  mycroft 		nsd.nsd_nfsd = NULL;
    267      1.18     fvdl #ifdef NFSKERB
    268      1.18     fvdl 		if (sizeof (struct nfsrpc_fullverf) != RPCX_FULLVERF ||
    269      1.18     fvdl 		    sizeof (struct nfsrpc_fullblock) != RPCX_FULLBLOCK)
    270      1.18     fvdl 		    syslog(LOG_ERR, "Yikes NFSKERB structs not packed!");
    271      1.18     fvdl 		nsd.nsd_authstr = (u_char *)&kt;
    272      1.18     fvdl 		nsd.nsd_authlen = sizeof (kt);
    273      1.18     fvdl 		nsd.nsd_verfstr = (u_char *)&kverf;
    274      1.18     fvdl 		nsd.nsd_verflen = sizeof (kverf);
    275      1.11  mycroft #endif
    276      1.11  mycroft 		while (nfssvc(nfssvc_flag, &nsd) < 0) {
    277      1.11  mycroft 			if (errno != ENEEDAUTH) {
    278      1.11  mycroft 				syslog(LOG_ERR, "nfssvc: %m");
    279      1.11  mycroft 				exit(1);
    280      1.11  mycroft 			}
    281      1.11  mycroft 			nfssvc_flag = NFSSVC_NFSD | NFSSVC_AUTHINFAIL;
    282      1.18     fvdl #ifdef NFSKERB
    283      1.18     fvdl 			/*
    284      1.18     fvdl 			 * Get the Kerberos ticket out of the authenticator
    285      1.18     fvdl 			 * verify it and convert the principal name to a user
    286      1.18     fvdl 			 * name. The user name is then converted to a set of
    287      1.18     fvdl 			 * user credentials via the password and group file.
    288      1.18     fvdl 			 * Finally, decrypt the timestamp and validate it.
    289      1.18     fvdl 			 * For more info see the IETF Draft "Authentication
    290      1.18     fvdl 			 * in ONC RPC".
    291      1.18     fvdl 			 */
    292      1.18     fvdl 			kt.length = ntohl(kt.length);
    293      1.18     fvdl 			if (gettimeofday(&ktv, (struct timezone *)0) == 0 &&
    294      1.18     fvdl 			    kt.length > 0 && kt.length <=
    295      1.18     fvdl 			    (RPCAUTH_MAXSIZ - 3 * NFSX_UNSIGNED)) {
    296      1.18     fvdl 			    kin.w1 = NFS_KERBW1(kt);
    297      1.18     fvdl 			    kt.mbz = 0;
    298      1.18     fvdl 			    (void)strcpy(inst, "*");
    299      1.18     fvdl 			    if (krb_rd_req(&kt, NFS_KERBSRV,
    300      1.18     fvdl 				inst, nsd.nsd_haddr, &kauth, "") == RD_AP_OK &&
    301      1.18     fvdl 				krb_kntoln(&kauth, lnam) == KSUCCESS &&
    302      1.18     fvdl 				(pwd = getpwnam(lnam)) != NULL) {
    303      1.11  mycroft 				cr = &nsd.nsd_cr;
    304      1.11  mycroft 				cr->cr_uid = pwd->pw_uid;
    305      1.11  mycroft 				cr->cr_groups[0] = pwd->pw_gid;
    306      1.11  mycroft 				cr->cr_ngroups = 1;
    307      1.11  mycroft 				setgrent();
    308      1.11  mycroft 				while ((grp = getgrent()) != NULL) {
    309      1.11  mycroft 					if (grp->gr_gid == cr->cr_groups[0])
    310      1.11  mycroft 						continue;
    311      1.11  mycroft 					for (cpp = grp->gr_mem;
    312      1.11  mycroft 					    *cpp != NULL; ++cpp)
    313      1.11  mycroft 						if (!strcmp(*cpp, lnam))
    314      1.11  mycroft 							break;
    315      1.11  mycroft 					if (*cpp == NULL)
    316      1.11  mycroft 						continue;
    317      1.11  mycroft 					cr->cr_groups[cr->cr_ngroups++]
    318      1.11  mycroft 					    = grp->gr_gid;
    319      1.11  mycroft 					if (cr->cr_ngroups == NGROUPS)
    320      1.11  mycroft 						break;
    321      1.11  mycroft 				}
    322      1.11  mycroft 				endgrent();
    323      1.18     fvdl 
    324      1.18     fvdl 				/*
    325      1.18     fvdl 				 * Get the timestamp verifier out of the
    326      1.18     fvdl 				 * authenticator and verifier strings.
    327      1.18     fvdl 				 */
    328      1.18     fvdl 				kin.t1 = kverf.t1;
    329      1.18     fvdl 				kin.t2 = kverf.t2;
    330      1.18     fvdl 				kin.w2 = kverf.w2;
    331      1.24    lukem 				memset((caddr_t)kivec, 0, sizeof (kivec));
    332      1.24    lukem 				memmove((caddr_t)nsd.nsd_key,
    333      1.24    lukem 				    (caddr_t)kauth.session,
    334      1.24    lukem 				    sizeof(kauth.session));
    335      1.18     fvdl 
    336      1.18     fvdl 				/*
    337      1.18     fvdl 				 * Decrypt the timestamp verifier in CBC mode.
    338      1.18     fvdl 				 */
    339      1.18     fvdl 				XXX
    340      1.18     fvdl 
    341      1.18     fvdl 				/*
    342      1.18     fvdl 				 * Validate the timestamp verifier, to
    343      1.18     fvdl 				 * check that the session key is ok.
    344      1.18     fvdl 				 */
    345      1.18     fvdl 				nsd.nsd_timestamp.tv_sec = ntohl(kout.t1);
    346      1.18     fvdl 				nsd.nsd_timestamp.tv_usec = ntohl(kout.t2);
    347      1.18     fvdl 				nsd.nsd_ttl = ntohl(kout.w1);
    348      1.18     fvdl 				if ((nsd.nsd_ttl - 1) == ntohl(kout.w2))
    349      1.18     fvdl 				    nfssvc_flag = NFSSVC_NFSD | NFSSVC_AUTHIN;
    350      1.11  mycroft 			}
    351      1.18     fvdl #endif /* NFSKERB */
    352       1.1      cgd 		}
    353       1.1      cgd 		exit(0);
    354       1.1      cgd 	}
    355      1.11  mycroft 
    356      1.11  mycroft 	/* If we are serving udp, set up the socket. */
    357       1.1      cgd 	if (udpflag) {
    358       1.1      cgd 		if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
    359      1.11  mycroft 			syslog(LOG_ERR, "can't create udp socket");
    360       1.1      cgd 			exit(1);
    361       1.1      cgd 		}
    362      1.11  mycroft 		inetaddr.sin_family = AF_INET;
    363      1.11  mycroft 		inetaddr.sin_addr.s_addr = INADDR_ANY;
    364      1.11  mycroft 		inetaddr.sin_port = htons(NFS_PORT);
    365      1.11  mycroft 		inetaddr.sin_len = sizeof(inetaddr);
    366      1.20  mycroft 		memset(inetaddr.sin_zero, 0, sizeof(inetaddr.sin_zero));
    367      1.11  mycroft 		if (bind(sock,
    368      1.11  mycroft 		    (struct sockaddr *)&inetaddr, sizeof(inetaddr)) < 0) {
    369      1.11  mycroft 			syslog(LOG_ERR, "can't bind udp addr");
    370       1.1      cgd 			exit(1);
    371       1.1      cgd 		}
    372      1.18     fvdl 		if (!pmap_set(RPCPROG_NFS, 2, IPPROTO_UDP, NFS_PORT) ||
    373      1.18     fvdl 		    !pmap_set(RPCPROG_NFS, 3, IPPROTO_UDP, NFS_PORT)) {
    374      1.11  mycroft 			syslog(LOG_ERR, "can't register with udp portmap");
    375      1.11  mycroft 			exit(1);
    376      1.11  mycroft 		}
    377      1.11  mycroft 		nfsdargs.sock = sock;
    378      1.11  mycroft 		nfsdargs.name = NULL;
    379      1.11  mycroft 		nfsdargs.namelen = 0;
    380      1.11  mycroft 		if (nfssvc(NFSSVC_ADDSOCK, &nfsdargs) < 0) {
    381      1.11  mycroft 			syslog(LOG_ERR, "can't Add UDP socket");
    382      1.11  mycroft 			exit(1);
    383      1.11  mycroft 		}
    384      1.11  mycroft 		(void)close(sock);
    385      1.11  mycroft 	}
    386      1.11  mycroft 
    387      1.11  mycroft #ifdef ISO
    388      1.11  mycroft 	/* If we are serving cltp, set up the socket. */
    389      1.11  mycroft 	if (cltpflag) {
    390      1.11  mycroft 		if ((sock = socket(AF_ISO, SOCK_DGRAM, 0)) < 0) {
    391      1.11  mycroft 			syslog(LOG_ERR, "can't create cltp socket");
    392      1.11  mycroft 			exit(1);
    393      1.11  mycroft 		}
    394      1.11  mycroft 		memset(&isoaddr, 0, sizeof(isoaddr));
    395      1.11  mycroft 		isoaddr.siso_family = AF_ISO;
    396      1.11  mycroft 		isoaddr.siso_tlen = 2;
    397      1.11  mycroft 		cp = TSEL(&isoaddr);
    398      1.11  mycroft 		*cp++ = (NFS_PORT >> 8);
    399      1.11  mycroft 		*cp = (NFS_PORT & 0xff);
    400      1.11  mycroft 		isoaddr.siso_len = sizeof(isoaddr);
    401      1.11  mycroft 		if (bind(sock,
    402      1.11  mycroft 		    (struct sockaddr *)&isoaddr, sizeof(isoaddr)) < 0) {
    403      1.11  mycroft 			syslog(LOG_ERR, "can't bind cltp addr");
    404       1.1      cgd 			exit(1);
    405       1.1      cgd 		}
    406      1.11  mycroft #ifdef notyet
    407       1.1      cgd 		/*
    408      1.11  mycroft 		 * XXX
    409      1.11  mycroft 		 * Someday this should probably use "rpcbind", the son of
    410      1.11  mycroft 		 * portmap.
    411       1.1      cgd 		 */
    412      1.11  mycroft 		if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_UDP, NFS_PORT)) {
    413      1.11  mycroft 			syslog(LOG_ERR, "can't register with udp portmap");
    414      1.11  mycroft 			exit(1);
    415      1.11  mycroft 		}
    416      1.11  mycroft #endif /* notyet */
    417      1.11  mycroft 		nfsdargs.sock = sock;
    418      1.11  mycroft 		nfsdargs.name = NULL;
    419      1.11  mycroft 		nfsdargs.namelen = 0;
    420      1.11  mycroft 		if (nfssvc(NFSSVC_ADDSOCK, &nfsdargs) < 0) {
    421      1.11  mycroft 			syslog(LOG_ERR, "can't add UDP socket");
    422      1.11  mycroft 			exit(1);
    423      1.11  mycroft 		}
    424       1.1      cgd 		close(sock);
    425       1.1      cgd 	}
    426      1.11  mycroft #endif /* ISO */
    427       1.1      cgd 
    428      1.11  mycroft 	/* Now set up the master server socket waiting for tcp connections. */
    429      1.11  mycroft 	on = 1;
    430      1.11  mycroft 	FD_ZERO(&sockbits);
    431      1.11  mycroft 	connect_type_cnt = 0;
    432       1.1      cgd 	if (tcpflag) {
    433      1.11  mycroft 		if ((tcpsock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
    434      1.11  mycroft 			syslog(LOG_ERR, "can't create tcp socket");
    435      1.11  mycroft 			exit(1);
    436      1.11  mycroft 		}
    437      1.11  mycroft 		if (setsockopt(tcpsock,
    438      1.11  mycroft 		    SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0)
    439      1.11  mycroft 			syslog(LOG_ERR, "setsockopt SO_REUSEADDR: %m");
    440      1.11  mycroft 		inetaddr.sin_family = AF_INET;
    441      1.11  mycroft 		inetaddr.sin_addr.s_addr = INADDR_ANY;
    442      1.11  mycroft 		inetaddr.sin_port = htons(NFS_PORT);
    443      1.11  mycroft 		inetaddr.sin_len = sizeof(inetaddr);
    444      1.20  mycroft 		memset(inetaddr.sin_zero, 0, sizeof(inetaddr.sin_zero));
    445      1.11  mycroft 		if (bind(tcpsock,
    446      1.11  mycroft 		    (struct sockaddr *)&inetaddr, sizeof (inetaddr)) < 0) {
    447      1.11  mycroft 			syslog(LOG_ERR, "can't bind tcp addr");
    448      1.11  mycroft 			exit(1);
    449      1.11  mycroft 		}
    450      1.11  mycroft 		if (listen(tcpsock, 5) < 0) {
    451      1.11  mycroft 			syslog(LOG_ERR, "listen failed");
    452      1.11  mycroft 			exit(1);
    453      1.11  mycroft 		}
    454      1.18     fvdl 		if (!pmap_set(RPCPROG_NFS, 2, IPPROTO_TCP, NFS_PORT) ||
    455      1.18     fvdl 		    !pmap_set(RPCPROG_NFS, 3, IPPROTO_TCP, NFS_PORT)) {
    456      1.11  mycroft 			syslog(LOG_ERR, "can't register tcp with portmap");
    457      1.11  mycroft 			exit(1);
    458      1.11  mycroft 		}
    459      1.11  mycroft 		FD_SET(tcpsock, &sockbits);
    460      1.11  mycroft 		maxsock = tcpsock;
    461      1.11  mycroft 		connect_type_cnt++;
    462      1.11  mycroft 	}
    463       1.1      cgd 
    464      1.11  mycroft #ifdef notyet
    465      1.11  mycroft 	/* Now set up the master server socket waiting for tp4 connections. */
    466      1.11  mycroft 	if (tp4flag) {
    467      1.11  mycroft 		if ((tp4sock = socket(AF_ISO, SOCK_SEQPACKET, 0)) < 0) {
    468      1.11  mycroft 			syslog(LOG_ERR, "can't create tp4 socket");
    469       1.1      cgd 			exit(1);
    470       1.1      cgd 		}
    471      1.11  mycroft 		if (setsockopt(tp4sock,
    472      1.11  mycroft 		    SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0)
    473       1.1      cgd 			syslog(LOG_ERR, "setsockopt SO_REUSEADDR: %m");
    474      1.11  mycroft 		memset(&isoaddr, 0, sizeof(isoaddr));
    475      1.11  mycroft 		isoaddr.siso_family = AF_ISO;
    476      1.11  mycroft 		isoaddr.siso_tlen = 2;
    477      1.11  mycroft 		cp = TSEL(&isoaddr);
    478      1.11  mycroft 		*cp++ = (NFS_PORT >> 8);
    479      1.11  mycroft 		*cp = (NFS_PORT & 0xff);
    480      1.11  mycroft 		isoaddr.siso_len = sizeof(isoaddr);
    481      1.11  mycroft 		if (bind(tp4sock,
    482      1.12  mycroft 		    (struct sockaddr *)&isoaddr, sizeof(isoaddr)) < 0) {
    483      1.11  mycroft 			syslog(LOG_ERR, "can't bind tp4 addr");
    484       1.1      cgd 			exit(1);
    485       1.1      cgd 		}
    486      1.11  mycroft 		if (listen(tp4sock, 5) < 0) {
    487      1.11  mycroft 			syslog(LOG_ERR, "listen failed");
    488       1.1      cgd 			exit(1);
    489       1.1      cgd 		}
    490      1.11  mycroft 		/*
    491      1.11  mycroft 		 * XXX
    492      1.11  mycroft 		 * Someday this should probably use "rpcbind", the son of
    493      1.11  mycroft 		 * portmap.
    494      1.11  mycroft 		 */
    495       1.1      cgd 		if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_TCP, NFS_PORT)) {
    496      1.11  mycroft 			syslog(LOG_ERR, "can't register tcp with portmap");
    497      1.11  mycroft 			exit(1);
    498      1.11  mycroft 		}
    499      1.11  mycroft 		FD_SET(tp4sock, &sockbits);
    500      1.11  mycroft 		maxsock = tp4sock;
    501      1.11  mycroft 		connect_type_cnt++;
    502      1.11  mycroft 	}
    503      1.11  mycroft 
    504      1.11  mycroft 	/* Now set up the master server socket waiting for tpip connections. */
    505      1.11  mycroft 	if (tpipflag) {
    506      1.11  mycroft 		if ((tpipsock = socket(AF_INET, SOCK_SEQPACKET, 0)) < 0) {
    507      1.11  mycroft 			syslog(LOG_ERR, "can't create tpip socket");
    508      1.11  mycroft 			exit(1);
    509      1.11  mycroft 		}
    510      1.11  mycroft 		if (setsockopt(tpipsock,
    511      1.11  mycroft 		    SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0)
    512      1.11  mycroft 			syslog(LOG_ERR, "setsockopt SO_REUSEADDR: %m");
    513      1.11  mycroft 		inetaddr.sin_family = AF_INET;
    514      1.11  mycroft 		inetaddr.sin_addr.s_addr = INADDR_ANY;
    515      1.11  mycroft 		inetaddr.sin_port = htons(NFS_PORT);
    516      1.11  mycroft 		inetaddr.sin_len = sizeof(inetaddr);
    517      1.20  mycroft 		memset(inetaddr.sin_zero, 0, sizeof(inetaddr.sin_zero));
    518      1.11  mycroft 		if (bind(tpipsock,
    519      1.11  mycroft 		    (struct sockaddr *)&inetaddr, sizeof (inetaddr)) < 0) {
    520      1.11  mycroft 			syslog(LOG_ERR, "can't bind tcp addr");
    521      1.11  mycroft 			exit(1);
    522      1.11  mycroft 		}
    523      1.11  mycroft 		if (listen(tpipsock, 5) < 0) {
    524      1.11  mycroft 			syslog(LOG_ERR, "listen failed");
    525       1.1      cgd 			exit(1);
    526       1.1      cgd 		}
    527       1.1      cgd 		/*
    528      1.11  mycroft 		 * XXX
    529      1.11  mycroft 		 * Someday this should probably use "rpcbind", the son of
    530      1.11  mycroft 		 * portmap.
    531       1.1      cgd 		 */
    532      1.11  mycroft 		if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_TCP, NFS_PORT)) {
    533      1.11  mycroft 			syslog(LOG_ERR, "can't register tcp with portmap");
    534      1.11  mycroft 			exit(1);
    535      1.11  mycroft 		}
    536      1.11  mycroft 		FD_SET(tpipsock, &sockbits);
    537      1.11  mycroft 		maxsock = tpipsock;
    538      1.11  mycroft 		connect_type_cnt++;
    539      1.11  mycroft 	}
    540      1.11  mycroft #endif /* notyet */
    541      1.11  mycroft 
    542      1.11  mycroft 	if (connect_type_cnt == 0)
    543      1.11  mycroft 		exit(0);
    544      1.11  mycroft 
    545      1.13  mycroft 	setproctitle("master");
    546      1.11  mycroft 
    547      1.11  mycroft 	/*
    548      1.11  mycroft 	 * Loop forever accepting connections and passing the sockets
    549      1.11  mycroft 	 * into the kernel for the mounts.
    550      1.11  mycroft 	 */
    551      1.11  mycroft 	for (;;) {
    552      1.11  mycroft 		ready = sockbits;
    553      1.11  mycroft 		if (connect_type_cnt > 1) {
    554      1.11  mycroft 			if (select(maxsock + 1,
    555      1.11  mycroft 			    &ready, NULL, NULL, NULL) < 1) {
    556      1.11  mycroft 				syslog(LOG_ERR, "select failed: %m");
    557      1.11  mycroft 				exit(1);
    558      1.11  mycroft 			}
    559      1.11  mycroft 		}
    560      1.11  mycroft 		if (tcpflag && FD_ISSET(tcpsock, &ready)) {
    561      1.11  mycroft 			len = sizeof(inetpeer);
    562      1.11  mycroft 			if ((msgsock = accept(tcpsock,
    563      1.11  mycroft 			    (struct sockaddr *)&inetpeer, &len)) < 0) {
    564      1.11  mycroft 				syslog(LOG_ERR, "accept failed: %m");
    565       1.1      cgd 				exit(1);
    566       1.1      cgd 			}
    567      1.11  mycroft 			memset(inetpeer.sin_zero, 0, sizeof(inetpeer.sin_zero));
    568      1.11  mycroft 			if (setsockopt(msgsock, SOL_SOCKET,
    569      1.11  mycroft 			    SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0)
    570      1.11  mycroft 				syslog(LOG_ERR,
    571      1.11  mycroft 				    "setsockopt SO_KEEPALIVE: %m");
    572      1.11  mycroft 			nfsdargs.sock = msgsock;
    573      1.11  mycroft 			nfsdargs.name = (caddr_t)&inetpeer;
    574      1.11  mycroft 			nfsdargs.namelen = sizeof(inetpeer);
    575      1.11  mycroft 			nfssvc(NFSSVC_ADDSOCK, &nfsdargs);
    576      1.11  mycroft 			(void)close(msgsock);
    577      1.11  mycroft 		}
    578      1.11  mycroft #ifdef notyet
    579      1.11  mycroft 		if (tp4flag && FD_ISSET(tp4sock, &ready)) {
    580      1.11  mycroft 			len = sizeof(isopeer);
    581      1.11  mycroft 			if ((msgsock = accept(tp4sock,
    582      1.11  mycroft 			    (struct sockaddr *)&isopeer, &len)) < 0) {
    583      1.11  mycroft 				syslog(LOG_ERR, "accept failed: %m");
    584      1.11  mycroft 				exit(1);
    585       1.1      cgd 			}
    586      1.11  mycroft 			if (setsockopt(msgsock, SOL_SOCKET,
    587      1.11  mycroft 			    SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0)
    588      1.11  mycroft 				syslog(LOG_ERR,
    589      1.11  mycroft 				    "setsockopt SO_KEEPALIVE: %m");
    590      1.11  mycroft 			nfsdargs.sock = msgsock;
    591      1.11  mycroft 			nfsdargs.name = (caddr_t)&isopeer;
    592      1.11  mycroft 			nfsdargs.namelen = len;
    593      1.11  mycroft 			nfssvc(NFSSVC_ADDSOCK, &nfsdargs);
    594      1.11  mycroft 			(void)close(msgsock);
    595      1.11  mycroft 		}
    596      1.11  mycroft 		if (tpipflag && FD_ISSET(tpipsock, &ready)) {
    597      1.11  mycroft 			len = sizeof(inetpeer);
    598      1.11  mycroft 			if ((msgsock = accept(tpipsock,
    599      1.11  mycroft 			    (struct sockaddr *)&inetpeer, &len)) < 0) {
    600      1.11  mycroft 				syslog(LOG_ERR, "Accept failed: %m");
    601       1.1      cgd 				exit(1);
    602       1.1      cgd 			}
    603      1.11  mycroft 			if (setsockopt(msgsock, SOL_SOCKET,
    604      1.11  mycroft 			    SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0)
    605      1.11  mycroft 				syslog(LOG_ERR, "setsockopt SO_KEEPALIVE: %m");
    606      1.11  mycroft 			nfsdargs.sock = msgsock;
    607      1.11  mycroft 			nfsdargs.name = (caddr_t)&inetpeer;
    608      1.11  mycroft 			nfsdargs.namelen = len;
    609      1.11  mycroft 			nfssvc(NFSSVC_ADDSOCK, &nfsdargs);
    610      1.11  mycroft 			(void)close(msgsock);
    611       1.1      cgd 		}
    612      1.11  mycroft #endif /* notyet */
    613       1.1      cgd 	}
    614       1.1      cgd }
    615       1.1      cgd 
    616      1.11  mycroft void
    617       1.1      cgd usage()
    618       1.1      cgd {
    619      1.26      mrg 
    620      1.15  mycroft 	(void)fprintf(stderr, "usage: nfsd %s\n", USAGE);
    621       1.1      cgd 	exit(1);
    622       1.1      cgd }
    623       1.1      cgd 
    624       1.1      cgd void
    625      1.11  mycroft nonfs(signo)
    626      1.11  mycroft 	int signo;
    627       1.1      cgd {
    628      1.15  mycroft 
    629      1.11  mycroft 	syslog(LOG_ERR, "missing system call: NFS not available.");
    630       1.1      cgd }
    631       1.4    glass 
    632      1.11  mycroft void
    633      1.11  mycroft reapchild(signo)
    634      1.11  mycroft 	int signo;
    635       1.4    glass {
    636      1.11  mycroft 
    637      1.18     fvdl 	while (wait3(NULL, WNOHANG, NULL) > 0);
    638       1.4    glass }
    639