xref: /original-bsd/sbin/nfsd/nfsd.c (revision 68549010)
1 /*
2  * Copyright (c) 1989 The Regents of the University of California.
3  * 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 char copyright[] =
13 "@(#) Copyright (c) 1989 Regents of the University of California.\n\
14  All rights reserved.\n";
15 #endif not lint
16 
17 #ifndef lint
18 static char sccsid[] = "@(#)nfsd.c	5.11 (Berkeley) 02/15/92";
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/krb.h>
51 #endif
52 
53 /* Global defs */
54 #ifdef DEBUG
55 #define	syslog(e, s)	fprintf(stderr,(s))
56 int	debug = 1;
57 #else
58 int	debug = 0;
59 #endif
60 struct	nfsd_srvargs nsd;
61 extern	int errno;
62 char	**Argv = NULL;		/* pointer to argument vector */
63 char	*LastArg = NULL;	/* end of argv */
64 void	reapchild();
65 
66 #ifdef KERBEROS
67 char		lnam[ANAME_SZ];
68 KTEXT_ST	kt;
69 AUTH_DAT	auth;
70 char		inst[INST_SZ];
71 #endif /* KERBEROS */
72 
73 /*
74  * Nfs server daemon mostly just a user context for nfssvc()
75  * 1 - do file descriptor and signal cleanup
76  * 2 - fork the nfsd(s)
77  * 3 - create server socket(s)
78  * 4 - register socket with portmap
79  * For connectionless protocols, just pass the socket into the kernel via.
80  * nfssvc().
81  * For connection based sockets, loop doing accepts. When you get a new socket
82  * from accept, pass the msgsock into the kernel via. nfssvc().
83  * The arguments are:
84  * -u - support udp nfs clients
85  * -t - support tcp nfs clients
86  * -c - support iso cltp clients
87  * -r - reregister with portmapper
88  * followed by "n" which is the number of nfsds' to fork off
89  */
90 main(argc, argv, envp)
91 	int argc;
92 	char *argv[], *envp[];
93 {
94 	register int i;
95 	register char *cp, **cpp;
96 	register struct ucred *cr = &nsd.nsd_cr;
97 	struct passwd *pwd;
98 	struct group *grp;
99 	int sock, msgsock, tcpflag = 0, udpflag = 0, ret, len;
100 	int cltpflag = 0, tp4flag = 0, tpipflag = 0, connect_type_cnt = 0;
101 	int maxsock, tcpsock, tp4sock, tpipsock, nfsdcnt = 4;
102 	int nfssvc_flag, opt, on = 1, reregister = 0;
103 	struct sockaddr_in inetaddr, inetpeer;
104 #ifdef ISO
105 	struct sockaddr_iso isoaddr, isopeer;
106 #endif
107 	struct nfsd_args nfsdargs;
108 	fd_set ready, sockbits;
109 	extern int optind;
110 	extern char *optarg;
111 
112 	/*
113 	 *  Save start and extent of argv for setproctitle.
114 	 */
115 	Argv = argv;
116 	if (envp == 0 || *envp == 0)
117 		envp = argv;
118 	while (*envp)
119 		envp++;
120 	LastArg = envp[-1] + strlen(envp[-1]);
121 	while ((opt = getopt(argc, argv, "utcr")) != EOF)
122 		switch (opt) {
123 		case 'u':
124 			udpflag++;
125 			break;
126 		case 't':
127 			tcpflag++;
128 			break;
129 		case 'r':
130 			reregister++;
131 			break;
132 #ifdef ISO
133 		case 'c':
134 			cltpflag++;
135 			break;
136 #ifdef notyet
137 		case 'i':
138 			tp4cnt++;
139 			break;
140 		case 'p':
141 			tpipcnt++;
142 			break;
143 #endif /* notyet */
144 #endif	/* ISO */
145 		default:
146 		case '?':
147 			usage();
148 		};
149 	if (optind < argc)
150 		nfsdcnt = atoi(argv[optind]);
151 	if (nfsdcnt < 1 || nfsdcnt > 20)
152 		nfsdcnt = 4;
153 
154 	if (debug == 0) {
155 		daemon(0, 0);
156 		signal(SIGINT, SIG_IGN);
157 		signal(SIGQUIT, SIG_IGN);
158 		signal(SIGTERM, SIG_IGN);
159 		signal(SIGHUP, SIG_IGN);
160 	}
161 	signal(SIGCHLD, reapchild);
162 
163 	if (reregister) {
164 		if (udpflag && !pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_UDP,
165 		    NFS_PORT)) {
166 			fprintf(stderr,
167 			    "Can't register with portmap for UDP\n");
168 			exit(1);
169 		}
170 		if (tcpflag && !pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_TCP,
171 		    NFS_PORT)) {
172 			fprintf(stderr,
173 			    "Can't register with portmap for TCP\n");
174 			exit(1);
175 		}
176 		exit(0);
177 	}
178 	openlog("nfsd:", LOG_PID, LOG_DAEMON);
179 
180 	for (i = 0; i < nfsdcnt; i++)
181 	    if (fork() == 0) {
182 		setproctitle("nfsd-srv");
183 		nfssvc_flag = NFSSVC_NFSD;
184 		nsd.nsd_nfsd = (struct nfsd *)0;
185 #ifdef KERBEROS
186 		nsd.nsd_authstr = (char *)kt.dat;
187 #endif
188 		while (nfssvc(nfssvc_flag, (caddr_t)&nsd) < 0) {
189 		    if (errno == ENEEDAUTH) {
190 			nfssvc_flag = (NFSSVC_NFSD | NFSSVC_AUTHINFAIL);
191 #ifdef KERBEROS
192 			kt.length = nsd.nsd_authlen;
193 			kt.mbz = 0;
194 			strcpy(inst, "*");
195 			if (krb_rd_req(&kt, "rcmd", inst, nsd.nsd_haddr,
196 			    &auth, "") == RD_AP_OK &&
197 			    krb_kntoln(&auth, lnam) == KSUCCESS &&
198 			    (pwd = getpwnam(lnam))) {
199 			    cr->cr_uid = pwd->pw_uid;
200 			    cr->cr_groups[0] = pwd->pw_gid;
201 			    cr->cr_ngroups = 1;
202 			    setgrent();
203 			    while (grp = getgrent()) {
204 				if (grp->gr_gid == cr->cr_groups[0])
205 				    continue;
206 				cpp = grp->gr_mem;
207 				while (*cpp) {
208 				    if (!strcmp(*cpp, lnam))
209 					break;
210 				    cpp++;
211 				}
212 				if (*cpp) {
213 				    cr->cr_groups[cr->cr_ngroups++] = grp->gr_gid;
214 				    if (cr->cr_ngroups == NGROUPS)
215 					break;
216 				}
217 			    }
218 			    endgrent();
219 			    nfssvc_flag = (NFSSVC_NFSD | NFSSVC_AUTHIN);
220 			}
221 #endif	/* KERBEROS */
222 		    } else {
223 fprintf(stderr, "errno=%d\n",errno);
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 			if (setsockopt(msgsock, SOL_SOCKET,
434 			    SO_KEEPALIVE, (char *) &on, sizeof(on)) < 0)
435 				syslog(LOG_ERR,
436 				    "setsockopt SO_KEEPALIVE: %m");
437 			nfsdargs.sock = msgsock;
438 			nfsdargs.name = (caddr_t)&inetpeer;
439 			nfsdargs.namelen = len;
440 			nfssvc(NFSSVC_ADDSOCK, &nfsdargs);
441 			close(msgsock);
442 		}
443 #ifdef notyet
444 		if (tp4flag && FD_ISSET(tp4sock, &ready)) {
445 			len = sizeof(isopeer);
446 			if ((msgsock = accept(tp4sock,
447 			    (struct sockaddr *)&isopeer, &len)) < 0) {
448 				syslog(LOG_ERR, "Accept failed: %m");
449 				exit(1);
450 			}
451 			if (setsockopt(msgsock, SOL_SOCKET,
452 			    SO_KEEPALIVE, (char *) &on, sizeof(on)) < 0)
453 				syslog(LOG_ERR,
454 				    "setsockopt SO_KEEPALIVE: %m");
455 			nfsdargs.sock = msgsock;
456 			nfsdargs.name = (caddr_t)&isopeer;
457 			nfsdargs.namelen = len;
458 			nfssvc(NFSSVC_ADDSOCK, &nfsdargs);
459 			close(msgsock);
460 		}
461 		if (tpipflag && FD_ISSET(tpipsock, &ready)) {
462 			len = sizeof(inetpeer);
463 			if ((msgsock = accept(tpipsock,
464 			    (struct sockaddr *)&inetpeer, &len)) < 0) {
465 				syslog(LOG_ERR, "Accept failed: %m");
466 				exit(1);
467 			}
468 			if (setsockopt(msgsock, SOL_SOCKET,
469 			    SO_KEEPALIVE, (char *) &on, sizeof(on)) < 0)
470 				syslog(LOG_ERR,
471 				    "setsockopt SO_KEEPALIVE: %m");
472 			nfsdargs.sock = msgsock;
473 			nfsdargs.name = (caddr_t)&inetpeer;
474 			nfsdargs.namelen = len;
475 			nfssvc(NFSSVC_ADDSOCK, &nfsdargs);
476 			close(msgsock);
477 		}
478 #endif	/* notyet */
479 	}
480 }
481 
482 usage()
483 {
484 	fprintf(stderr, "nfsd [-u] [-t] [-c] [-r] [num_nfsds]\n");
485 	exit(1);
486 }
487 
488 void
489 reapchild()
490 {
491 
492 	while (wait3((int *) NULL, WNOHANG, (struct rusage *) NULL))
493 		;
494 }
495 
496 setproctitle(a)
497 	char *a;
498 {
499 	register char *cp;
500 	char buf[80];
501 
502 	cp = Argv[0];
503 	(void) sprintf(buf, "%s", a);
504 	(void) strncpy(cp, buf, LastArg - cp);
505 	cp += strlen(cp);
506 	while (cp < LastArg)
507 		*cp++ = ' ';
508 }
509