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