xref: /original-bsd/sbin/nfsd/nfsd.c (revision c3e32dec)
1 /*
2  * Copyright (c) 1989, 1993
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  * %sccs.include.redist.c%
9  */
10 
11 #ifndef lint
12 static char copyright[] =
13 "@(#) Copyright (c) 1989, 1993\n\
14 	The Regents of the University of California.  All rights reserved.\n";
15 #endif not lint
16 
17 #ifndef lint
18 static char sccsid[] = "@(#)nfsd.c	8.1 (Berkeley) 06/05/93";
19 #endif not lint
20 
21 #include <stdio.h>
22 #include <signal.h>
23 #include <fcntl.h>
24 #include <strings.h>
25 #include <pwd.h>
26 #include <grp.h>
27 #include <sys/types.h>
28 #include <sys/syslog.h>
29 #include <sys/param.h>
30 #include <sys/errno.h>
31 #include <sys/ioctl.h>
32 #include <sys/stat.h>
33 #include <sys/wait.h>
34 #include <sys/uio.h>
35 #include <sys/namei.h>
36 #include <sys/ucred.h>
37 #include <sys/mount.h>
38 #include <sys/socket.h>
39 #include <sys/socketvar.h>
40 #include <rpc/rpc.h>
41 #include <rpc/pmap_clnt.h>
42 #include <rpc/pmap_prot.h>
43 #ifdef ISO
44 #include <netiso/iso.h>
45 #endif
46 #include <nfs/rpcv2.h>
47 #include <nfs/nfsv2.h>
48 #include <nfs/nfs.h>
49 #ifdef KERBEROS
50 #include <kerberosIV/des.h>
51 #include <kerberosIV/krb.h>
52 #endif
53 
54 /* Global defs */
55 #ifdef DEBUG
56 #define	syslog(e, s)	fprintf(stderr,(s))
57 int	debug = 1;
58 #else
59 int	debug = 0;
60 #endif
61 struct	nfsd_srvargs nsd;
62 extern	int errno;
63 char	**Argv = NULL;		/* pointer to argument vector */
64 char	*LastArg = NULL;	/* end of argv */
65 void	reapchild();
66 
67 #ifdef KERBEROS
68 char		lnam[ANAME_SZ];
69 KTEXT_ST	kt;
70 AUTH_DAT	auth;
71 char		inst[INST_SZ];
72 #endif /* KERBEROS */
73 
74 /*
75  * Nfs server daemon mostly just a user context for nfssvc()
76  * 1 - do file descriptor and signal cleanup
77  * 2 - fork the nfsd(s)
78  * 3 - create server socket(s)
79  * 4 - register socket with portmap
80  * For connectionless protocols, just pass the socket into the kernel via.
81  * nfssvc().
82  * For connection based sockets, loop doing accepts. When you get a new socket
83  * from accept, pass the msgsock into the kernel via. nfssvc().
84  * The arguments are:
85  * -u - support udp nfs clients
86  * -t - support tcp nfs clients
87  * -c - support iso cltp clients
88  * -r - reregister with portmapper
89  * followed by "n" which is the number of nfsds' to fork off
90  */
91 main(argc, argv, envp)
92 	int argc;
93 	char *argv[], *envp[];
94 {
95 	register int i;
96 	register char *cp, **cpp;
97 	register struct ucred *cr = &nsd.nsd_cr;
98 	struct passwd *pwd;
99 	struct group *grp;
100 	int sock, msgsock, tcpflag = 0, udpflag = 0, ret, len;
101 	int cltpflag = 0, tp4flag = 0, tpipflag = 0, connect_type_cnt = 0;
102 	int maxsock, tcpsock, tp4sock, tpipsock, nfsdcnt = 4;
103 	int nfssvc_flag, opt, on = 1, reregister = 0;
104 	struct sockaddr_in inetaddr, inetpeer;
105 #ifdef ISO
106 	struct sockaddr_iso isoaddr, isopeer;
107 #endif
108 	struct nfsd_args nfsdargs;
109 	fd_set ready, sockbits;
110 	extern int optind;
111 	extern char *optarg;
112 
113 	/*
114 	 *  Save start and extent of argv for setproctitle.
115 	 */
116 	Argv = argv;
117 	if (envp == 0 || *envp == 0)
118 		envp = argv;
119 	while (*envp)
120 		envp++;
121 	LastArg = envp[-1] + strlen(envp[-1]);
122 	while ((opt = getopt(argc, argv, "utcr")) != EOF)
123 		switch (opt) {
124 		case 'u':
125 			udpflag++;
126 			break;
127 		case 't':
128 			tcpflag++;
129 			break;
130 		case 'r':
131 			reregister++;
132 			break;
133 #ifdef ISO
134 		case 'c':
135 			cltpflag++;
136 			break;
137 #ifdef notyet
138 		case 'i':
139 			tp4cnt++;
140 			break;
141 		case 'p':
142 			tpipcnt++;
143 			break;
144 #endif /* notyet */
145 #endif	/* ISO */
146 		default:
147 		case '?':
148 			usage();
149 		};
150 	if (optind < argc)
151 		nfsdcnt = atoi(argv[optind]);
152 	if (nfsdcnt < 1 || nfsdcnt > 20)
153 		nfsdcnt = 4;
154 
155 	if (debug == 0) {
156 		daemon(0, 0);
157 		signal(SIGINT, SIG_IGN);
158 		signal(SIGQUIT, SIG_IGN);
159 		signal(SIGTERM, SIG_IGN);
160 		signal(SIGHUP, SIG_IGN);
161 	}
162 	signal(SIGCHLD, reapchild);
163 
164 	if (reregister) {
165 		if (udpflag && !pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_UDP,
166 		    NFS_PORT)) {
167 			fprintf(stderr,
168 			    "Can't register with portmap for UDP\n");
169 			exit(1);
170 		}
171 		if (tcpflag && !pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_TCP,
172 		    NFS_PORT)) {
173 			fprintf(stderr,
174 			    "Can't register with portmap for TCP\n");
175 			exit(1);
176 		}
177 		exit(0);
178 	}
179 	openlog("nfsd:", LOG_PID, LOG_DAEMON);
180 
181 	for (i = 0; i < nfsdcnt; i++)
182 	    if (fork() == 0) {
183 		setproctitle("nfsd-srv");
184 		nfssvc_flag = NFSSVC_NFSD;
185 		nsd.nsd_nfsd = (struct nfsd *)0;
186 #ifdef KERBEROS
187 		nsd.nsd_authstr = (char *)kt.dat;
188 #endif
189 		while (nfssvc(nfssvc_flag, (caddr_t)&nsd) < 0) {
190 		    if (errno == ENEEDAUTH) {
191 			nfssvc_flag = (NFSSVC_NFSD | NFSSVC_AUTHINFAIL);
192 #ifdef KERBEROS
193 			kt.length = nsd.nsd_authlen;
194 			kt.mbz = 0;
195 			strcpy(inst, "*");
196 			if (krb_rd_req(&kt, "rcmd", inst, nsd.nsd_haddr,
197 			    &auth, "") == RD_AP_OK &&
198 			    krb_kntoln(&auth, lnam) == KSUCCESS &&
199 			    (pwd = getpwnam(lnam))) {
200 			    cr->cr_uid = pwd->pw_uid;
201 			    cr->cr_groups[0] = pwd->pw_gid;
202 			    cr->cr_ngroups = 1;
203 			    setgrent();
204 			    while (grp = getgrent()) {
205 				if (grp->gr_gid == cr->cr_groups[0])
206 				    continue;
207 				cpp = grp->gr_mem;
208 				while (*cpp) {
209 				    if (!strcmp(*cpp, lnam))
210 					break;
211 				    cpp++;
212 				}
213 				if (*cpp) {
214 				    cr->cr_groups[cr->cr_ngroups++] = grp->gr_gid;
215 				    if (cr->cr_ngroups == NGROUPS)
216 					break;
217 				}
218 			    }
219 			    endgrent();
220 			    nfssvc_flag = (NFSSVC_NFSD | NFSSVC_AUTHIN);
221 			}
222 #endif	/* KERBEROS */
223 		    } else {
224 			syslog(LOG_ERR, "Nfsd died %m");
225 			exit(1);
226 		    }
227 		}
228 		exit();
229 	    }
230 
231 	/*
232 	 * If we are serving udp, set up the socket.
233 	 */
234 	if (udpflag) {
235 		if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
236 			syslog(LOG_ERR, "Can't create udp socket");
237 			exit(1);
238 		}
239 		inetaddr.sin_family = AF_INET;
240 		inetaddr.sin_addr.s_addr = INADDR_ANY;
241 		inetaddr.sin_port = htons(NFS_PORT);
242 		inetaddr.sin_len = sizeof(inetaddr);
243 		if (bind(sock, (struct sockaddr *)&inetaddr, sizeof(inetaddr)) < 0) {
244 			syslog(LOG_ERR, "Can't bind udp addr");
245 			exit(1);
246 		}
247 		if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_UDP, NFS_PORT)) {
248 			syslog(LOG_ERR, "Can't register with udp portmap");
249 			exit(1);
250 		}
251 		nfsdargs.sock = sock;
252 		nfsdargs.name = (caddr_t)0;
253 		nfsdargs.namelen = 0;
254 		if (nfssvc(NFSSVC_ADDSOCK, &nfsdargs) < 0) {
255 			syslog(LOG_ERR, "Can't Add UDP socket");
256 			exit(1);
257 		}
258 		close(sock);
259 	}
260 
261 	/*
262 	 * If we are serving cltp, set up the socket.
263 	 */
264 #ifdef ISO
265 	if (cltpflag) {
266 		if ((sock = socket(AF_ISO, SOCK_DGRAM, 0)) < 0) {
267 			syslog(LOG_ERR, "Can't create cltp socket");
268 			exit(1);
269 		}
270 		bzero((caddr_t)&isoaddr, sizeof (isoaddr));
271 		isoaddr.siso_family = AF_ISO;
272 		isoaddr.siso_tlen = 2;
273 		cp = TSEL(&isoaddr);
274 		*cp++ = (NFS_PORT >> 8);
275 		*cp = (NFS_PORT & 0xff);
276 		isoaddr.siso_len = sizeof(isoaddr);
277 		if (bind(sock, (struct sockaddr *)&isoaddr, sizeof(isoaddr)) < 0) {
278 			syslog(LOG_ERR, "Can't bind cltp addr");
279 			exit(1);
280 		}
281 #ifdef notyet
282 		/*
283 		 * Someday this should probably use "rpcbind", the son of
284 		 * portmap.
285 		 */
286 		if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_UDP, NFS_PORT)) {
287 			syslog(LOG_ERR, "Can't register with udp portmap");
288 			exit(1);
289 		}
290 #endif /* notyet */
291 		nfsdargs.sock = sock;
292 		nfsdargs.name = (caddr_t)0;
293 		nfsdargs.namelen = 0;
294 		if (nfssvc(NFSSVC_ADDSOCK, &nfsdargs) < 0) {
295 			syslog(LOG_ERR, "Can't Add UDP socket");
296 			exit();
297 		}
298 		close(sock);
299 	}
300 #endif	/* ISO */
301 
302 	/*
303 	 * Now set up the master server socket waiting for tcp connections.
304 	 */
305 	FD_ZERO(&sockbits);
306 	if (tcpflag) {
307 		if ((tcpsock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
308 			syslog(LOG_ERR, "Can't create tcp socket");
309 			exit(1);
310 		}
311 		if (setsockopt(tcpsock, SOL_SOCKET, SO_REUSEADDR,
312 		    (char *) &on, sizeof(on)) < 0)
313 			syslog(LOG_ERR, "setsockopt SO_REUSEADDR: %m");
314 		inetaddr.sin_family = AF_INET;
315 		inetaddr.sin_addr.s_addr = INADDR_ANY;
316 		inetaddr.sin_port = htons(NFS_PORT);
317 		inetaddr.sin_len = sizeof (inetaddr);
318 		if (bind(tcpsock, (struct sockaddr *)&inetaddr, sizeof (inetaddr)) < 0) {
319 			syslog(LOG_ERR, "Can't bind tcp addr");
320 			exit(1);
321 		}
322 		if (listen(tcpsock, 5) < 0) {
323 			syslog(LOG_ERR, "Listen failed");
324 			exit(1);
325 		}
326 		if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_TCP, NFS_PORT)) {
327 			syslog(LOG_ERR, "Can't register tcp with portmap");
328 			exit(1);
329 		}
330 		FD_SET(tcpsock, &sockbits);
331 		maxsock = tcpsock;
332 		connect_type_cnt++;
333 	}
334 
335 #ifdef notyet
336 	/*
337 	 * Now set up the master server socket waiting for tp4 connections.
338 	 */
339 	if (tp4flag) {
340 		if ((tp4sock = socket(AF_ISO, SOCK_SEQPACKET, 0)) < 0) {
341 			syslog(LOG_ERR, "Can't create tp4 socket");
342 			exit(1);
343 		}
344 		if (setsockopt(tp4sock, SOL_SOCKET, SO_REUSEADDR,
345 		    (char *) &on, sizeof(on)) < 0)
346 			syslog(LOG_ERR, "setsockopt SO_REUSEADDR: %m");
347 		bzero((caddr_t)&isoaddr, sizeof (isoaddr));
348 		isoaddr.siso_family = AF_ISO;
349 		isoaddr.siso_tlen = 2;
350 		cp = TSEL(&isoaddr);
351 		*cp++ = (NFS_PORT >> 8);
352 		*cp = (NFS_PORT & 0xff);
353 		isoaddr.siso_len = sizeof(isoaddr);
354 		if (bind(tp4sock, (struct sockaddr *)&isoaddr, sizeof (isoaddr)) < 0) {
355 			syslog(LOG_ERR, "Can't bind tp4 addr");
356 			exit(1);
357 		}
358 		if (listen(tp4sock, 5) < 0) {
359 			syslog(LOG_ERR, "Listen failed");
360 			exit(1);
361 		}
362 		/*
363 		 * Someday this should probably use "rpcbind".
364 		 */
365 		if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_TCP, NFS_PORT)) {
366 			syslog(LOG_ERR, "Can't register tcp with portmap");
367 			exit(1);
368 		}
369 		FD_SET(tp4sock, &sockbits);
370 		maxsock = tp4sock;
371 		connect_type_cnt++;
372 	}
373 
374 	/*
375 	 * Now set up the master server socket waiting for tpip connections.
376 	 */
377 	if (tpipflag) {
378 		if ((tpipsock = socket(AF_INET, SOCK_SEQPACKET, 0)) < 0) {
379 			syslog(LOG_ERR, "Can't create tpip socket");
380 			exit(1);
381 		}
382 		if (setsockopt(tpipsock, SOL_SOCKET, SO_REUSEADDR,
383 		    (char *) &on, sizeof(on)) < 0)
384 			syslog(LOG_ERR, "setsockopt SO_REUSEADDR: %m");
385 		inetaddr.sin_family = AF_INET;
386 		inetaddr.sin_addr.s_addr = INADDR_ANY;
387 		inetaddr.sin_port = htons(NFS_PORT);
388 		inetaddr.sin_len = sizeof (inetaddr);
389 		if (bind(tpipsock, (struct sockaddr *)&inetaddr, sizeof (inetaddr)) < 0) {
390 			syslog(LOG_ERR, "Can't bind tcp addr");
391 			exit(1);
392 		}
393 		if (listen(tpipsock, 5) < 0) {
394 			syslog(LOG_ERR, "Listen failed");
395 			exit(1);
396 		}
397 		/*
398 		 * Someday this should use "rpcbind"
399 		 */
400 		if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_TCP, NFS_PORT)) {
401 			syslog(LOG_ERR, "Can't register tcp with portmap");
402 			exit(1);
403 		}
404 		FD_SET(tpipsock, &sockbits);
405 		maxsock = tpipsock;
406 		connect_type_cnt++;
407 	}
408 #endif	/* notyet */
409 
410 	if (connect_type_cnt == 0)
411 		exit();
412 	setproctitle("nfsd-master");
413 	/*
414 	 * Loop forever accepting connections and passing the sockets
415 	 * into the kernel for the mounts.
416 	 */
417 	for (;;) {
418 		ready = sockbits;
419 		if (connect_type_cnt > 1) {
420 			if (select(maxsock + 1, &ready, (fd_set *)0,
421 				(fd_set *)0, (struct timeval *)0) < 1) {
422 				syslog(LOG_ERR, "Select failed");
423 				exit(1);
424 			}
425 		}
426 		if (tcpflag && FD_ISSET(tcpsock, &ready)) {
427 			len = sizeof(inetpeer);
428 			if ((msgsock = accept(tcpsock,
429 			    (struct sockaddr *)&inetpeer, &len)) < 0) {
430 				syslog(LOG_ERR, "Accept failed: %m");
431 				exit(1);
432 			}
433 			bzero((char *)inetpeer.sin_zero,
434 			    sizeof(inetpeer.sin_zero));
435 			if (setsockopt(msgsock, SOL_SOCKET,
436 			    SO_KEEPALIVE, (char *) &on, sizeof(on)) < 0)
437 				syslog(LOG_ERR,
438 				    "setsockopt SO_KEEPALIVE: %m");
439 			nfsdargs.sock = msgsock;
440 			nfsdargs.name = (caddr_t)&inetpeer;
441 			nfsdargs.namelen = sizeof(inetpeer);
442 			nfssvc(NFSSVC_ADDSOCK, &nfsdargs);
443 			close(msgsock);
444 		}
445 #ifdef notyet
446 		if (tp4flag && FD_ISSET(tp4sock, &ready)) {
447 			len = sizeof(isopeer);
448 			if ((msgsock = accept(tp4sock,
449 			    (struct sockaddr *)&isopeer, &len)) < 0) {
450 				syslog(LOG_ERR, "Accept failed: %m");
451 				exit(1);
452 			}
453 			if (setsockopt(msgsock, SOL_SOCKET,
454 			    SO_KEEPALIVE, (char *) &on, sizeof(on)) < 0)
455 				syslog(LOG_ERR,
456 				    "setsockopt SO_KEEPALIVE: %m");
457 			nfsdargs.sock = msgsock;
458 			nfsdargs.name = (caddr_t)&isopeer;
459 			nfsdargs.namelen = len;
460 			nfssvc(NFSSVC_ADDSOCK, &nfsdargs);
461 			close(msgsock);
462 		}
463 		if (tpipflag && FD_ISSET(tpipsock, &ready)) {
464 			len = sizeof(inetpeer);
465 			if ((msgsock = accept(tpipsock,
466 			    (struct sockaddr *)&inetpeer, &len)) < 0) {
467 				syslog(LOG_ERR, "Accept failed: %m");
468 				exit(1);
469 			}
470 			if (setsockopt(msgsock, SOL_SOCKET,
471 			    SO_KEEPALIVE, (char *) &on, sizeof(on)) < 0)
472 				syslog(LOG_ERR,
473 				    "setsockopt SO_KEEPALIVE: %m");
474 			nfsdargs.sock = msgsock;
475 			nfsdargs.name = (caddr_t)&inetpeer;
476 			nfsdargs.namelen = len;
477 			nfssvc(NFSSVC_ADDSOCK, &nfsdargs);
478 			close(msgsock);
479 		}
480 #endif	/* notyet */
481 	}
482 }
483 
484 usage()
485 {
486 	fprintf(stderr, "nfsd [-u] [-t] [-c] [-r] [num_nfsds]\n");
487 	exit(1);
488 }
489 
490 void
491 reapchild()
492 {
493 
494 	while (wait3((int *) NULL, WNOHANG, (struct rusage *) NULL))
495 		;
496 }
497 
498 setproctitle(a)
499 	char *a;
500 {
501 	register char *cp;
502 	char buf[80];
503 
504 	cp = Argv[0];
505 	(void) sprintf(buf, "%s", a);
506 	(void) strncpy(cp, buf, LastArg - cp);
507 	cp += strlen(cp);
508 	while (cp < LastArg)
509 		*cp++ = ' ';
510 }
511