xref: /original-bsd/sbin/nfsd/nfsd.c (revision 698bcc85)
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.10 (Berkeley) 04/24/91";
19 #endif not lint
20 
21 #include <sys/types.h>
22 #include <sys/signal.h>
23 #include <sys/ioctl.h>
24 #include <sys/stat.h>
25 #include <sys/wait.h>
26 #include <sys/mount.h>
27 #include <sys/socket.h>
28 #include <sys/socketvar.h>
29 #include <stdio.h>
30 #include <syslog.h>
31 #include <fcntl.h>
32 #include <string.h>
33 #include <netdb.h>
34 #include <rpc/rpc.h>
35 #include <rpc/pmap_clnt.h>
36 #include <rpc/pmap_prot.h>
37 #include <nfs/rpcv2.h>
38 #include <nfs/nfsv2.h>
39 
40 /* Global defs */
41 #ifdef DEBUG
42 #define	syslog(e, s)	fprintf(stderr,(s))
43 int	debug = 1;
44 #else
45 int	debug = 0;
46 #endif
47 struct hadr {
48 	u_long	ha_sad;
49 	struct hadr *ha_next;
50 };
51 struct	hadr hphead;
52 char	**Argv = NULL;		/* pointer to argument vector */
53 char	*LastArg = NULL;	/* end of argv */
54 void	reapchild();
55 
56 /*
57  * Nfs server daemon mostly just a user context for nfssvc()
58  * 1 - do file descriptor and signal cleanup
59  * 2 - create server socket
60  * 3 - register socket with portmap
61  * For SOCK_DGRAM, just fork children and send them into the kernel
62  * by calling nfssvc()
63  * For connection based sockets, loop doing accepts. When you get a new socket
64  * from accept, fork a child that drops into the kernel via. nfssvc.
65  * This child will return from nfssvc when the connection is closed, so
66  * just shutdown() and exit().
67  * The arguments are:
68  * -t - support tcp nfs clients
69  * -u - support udp nfs clients
70  */
71 main(argc, argv, envp)
72 	int argc;
73 	char *argv[], *envp[];
74 {
75 	register int i;
76 	register char *cp, *cp2;
77 	register struct hadr *hp;
78 	int udpcnt, sock, msgsock, tcpflag = 0, udpflag = 0, ret, len;
79 	int reregister = 0;
80 	char opt;
81 	extern int optind;
82 	extern char *optarg;
83 	struct sockaddr_in saddr, msk, mtch, peername;
84 
85 
86 	/*
87 	 *  Save start and extent of argv for setproctitle.
88 	 */
89 
90 	Argv = argv;
91 	if (envp == 0 || *envp == 0)
92 		envp = argv;
93 	while (*envp)
94 		envp++;
95 	LastArg = envp[-1] + strlen(envp[-1]);
96 	while ((opt = getopt(argc, argv, "rt:u:")) != EOF)
97 		switch (opt) {
98 		case 'r':
99 			reregister++;
100 			break;
101 		case 't':
102 			tcpflag++;
103 			if (cp = index(optarg, ',')) {
104 				*cp++ = '\0';
105 				msk.sin_addr.s_addr = inet_addr(optarg);
106 				if (msk.sin_addr.s_addr == -1)
107 					usage();
108 				if (cp2 = index(cp, ','))
109 					*cp2++ = '\0';
110 				mtch.sin_addr.s_addr = inet_addr(cp);
111 				if (mtch.sin_addr.s_addr == -1)
112 					usage();
113 				cp = cp2;
114 				hphead.ha_next = (struct hadr *)0;
115 				while (cp) {
116 					if (cp2 = index(cp, ','))
117 						*cp2++ = '\0';
118 					hp = (struct hadr *)
119 						malloc(sizeof (struct hadr));
120 					hp->ha_sad = inet_addr(cp);
121 					if (hp->ha_sad == -1)
122 						usage();
123 					hp->ha_next = hphead.ha_next;
124 					hphead.ha_next = hp;
125 					cp = cp2;
126 				}
127 			} else
128 				usage();
129 			break;
130 		case 'u':
131 			udpflag++;
132 			if (cp = index(optarg, ',')) {
133 				*cp++ = '\0';
134 				msk.sin_addr.s_addr = inet_addr(optarg);
135 				if (msk.sin_addr.s_addr == -1)
136 					usage();
137 				if (cp2 = index(cp, ','))
138 					*cp2++ = '\0';
139 				mtch.sin_addr.s_addr = inet_addr(cp);
140 				if (mtch.sin_addr.s_addr == -1)
141 					usage();
142 				if (cp2)
143 					udpcnt = atoi(cp2);
144 				if (udpcnt < 1 || udpcnt > 20)
145 					udpcnt = 1;
146 			} else
147 				usage();
148 			break;
149 		default:
150 		case '?':
151 			usage();
152 		}
153 
154 	/*
155 	 * Default, if neither UDP nor TCP is specified,
156 	 * is to support UDP only; a numeric argument indicates
157 	 * the number of server daemons to run.
158 	 */
159 	if (udpflag == 0 && tcpflag == 0) {
160 		if (argc > 1)
161 			udpcnt = atoi(*++argv);
162 		if (udpcnt < 1 || udpcnt > 20)
163 			udpcnt = 1;
164 		msk.sin_addr.s_addr = mtch.sin_addr.s_addr = 0;
165 		udpflag++;
166 	}
167 
168 	if (debug == 0) {
169 		daemon(0, 0);
170 		signal(SIGINT, SIG_IGN);
171 		signal(SIGQUIT, SIG_IGN);
172 		signal(SIGTERM, SIG_IGN);
173 		signal(SIGHUP, SIG_IGN);
174 	}
175 	signal(SIGCHLD, reapchild);
176 
177 	if (reregister) {
178 		if (udpflag && !pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_UDP,
179 		    NFS_PORT)) {
180 			fprintf(stderr,
181 			    "Can't register with portmap for UDP\n");
182 			exit(1);
183 		}
184 		if (tcpflag && !pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_TCP,
185 		    NFS_PORT)) {
186 			fprintf(stderr,
187 			    "Can't register with portmap for TCP\n");
188 			exit(1);
189 		}
190 		exit(0);
191 	}
192 	openlog("nfsd:", LOG_PID, LOG_DAEMON);
193 #ifdef notdef
194 	/* why? unregisters both protocols even if we restart only one */
195 	pmap_unset(RPCPROG_NFS, NFS_VER2);
196 #endif
197 	if (udpflag) {
198 		if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
199 			syslog(LOG_ERR, "Can't create socket");
200 			exit(1);
201 		}
202 		saddr.sin_family = AF_INET;
203 		saddr.sin_addr.s_addr = INADDR_ANY;
204 		saddr.sin_port = htons(NFS_PORT);
205 		if (bind(sock, (struct sockaddr *)&saddr, sizeof(saddr)) < 0) {
206 			syslog(LOG_ERR, "Can't bind addr");
207 			exit(1);
208 		}
209 		if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_UDP, NFS_PORT)) {
210 			syslog(LOG_ERR, "Can't register with portmap");
211 			exit(1);
212 		}
213 
214 		/*
215 		 * Send the nfs datagram servers
216 		 * right down into the kernel
217 		 */
218 		for (i = 0; i < udpcnt; i++)
219 			if (fork() == 0) {
220 				setproctitle("nfsd-udp",
221 				    (struct sockaddr_in *)NULL);
222 				ret = nfssvc(sock, &msk, sizeof(msk),
223 						&mtch, sizeof(mtch));
224 				if (ret < 0)
225 					syslog(LOG_ERR, "nfssvc() failed %m");
226 				exit(1);
227 			}
228 		close(sock);
229 	}
230 
231 	/*
232 	 * Now set up the master STREAM server waiting for tcp connections.
233 	 */
234 	if (tcpflag) {
235 		int on = 1;
236 
237 		if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
238 			syslog(LOG_ERR, "Can't create socket");
239 			exit(1);
240 		}
241 		if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
242 		    (char *) &on, sizeof(on)) < 0)
243 			syslog(LOG_ERR, "setsockopt SO_REUSEADDR: %m");
244 		saddr.sin_family = AF_INET;
245 		saddr.sin_addr.s_addr = INADDR_ANY;
246 		saddr.sin_port = htons(NFS_PORT);
247 		if (bind(sock, (struct sockaddr *)&saddr, sizeof(saddr)) < 0) {
248 			syslog(LOG_ERR, "Can't bind addr");
249 			exit(1);
250 		}
251 		if (listen(sock, 5) < 0) {
252 			syslog(LOG_ERR, "Listen failed");
253 			exit(1);
254 		}
255 		if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_TCP, NFS_PORT)) {
256 			syslog(LOG_ERR, "Can't register with portmap");
257 			exit(1);
258 		}
259 		setproctitle("nfsd-listen", (struct sockaddr_in *)NULL);
260 		/*
261 		 * Loop forever accepting connections and sending the children
262 		 * into the kernel to service the mounts.
263 		 */
264 		for (;;) {
265 			len = sizeof(peername);
266 			if ((msgsock = accept(sock,
267 			    (struct sockaddr *)&peername, &len)) < 0) {
268 				syslog(LOG_ERR, "Accept failed: %m");
269 				exit(1);
270 			}
271 			if ((peername.sin_addr.s_addr & msk.sin_addr.s_addr) !=
272 			   mtch.sin_addr.s_addr) {
273 				hp = hphead.ha_next;
274 				while (hp) {
275 					if (peername.sin_addr.s_addr ==
276 						hp->ha_sad)
277 						break;
278 					hp = hp->ha_next;
279 				}
280 				if (hp == NULL) {
281 					shutdown(msgsock, 2);
282 					close(msgsock);
283 					continue;
284 				}
285 			}
286 			if (fork() == 0) {
287 				close(sock);
288 				setproctitle("nfsd-tcp", &peername);
289 				if (setsockopt(msgsock, SOL_SOCKET,
290 				    SO_KEEPALIVE, (char *) &on, sizeof(on)) < 0)
291 					syslog(LOG_ERR,
292 					    "setsockopt SO_KEEPALIVE: %m");
293 				ret = nfssvc(msgsock, &msk, sizeof(msk),
294 						&mtch, sizeof(mtch));
295 				shutdown(msgsock, 2);
296 				if (ret < 0)
297 					syslog(LOG_NOTICE,
298 					    "Nfssvc STREAM Failed");
299 				exit(1);
300 			}
301 			close(msgsock);
302 		}
303 	}
304 }
305 
306 usage()
307 {
308 	fprintf(stderr, "nfsd [-t msk,mtch[,addrs]] [-u msk,mtch,numprocs]\n");
309 	exit(1);
310 }
311 
312 void
313 reapchild()
314 {
315 
316 	while (wait3((int *) NULL, WNOHANG, (struct rusage *) NULL))
317 		;
318 }
319 
320 setproctitle(a, sin)
321 	char *a;
322 	struct sockaddr_in *sin;
323 {
324 	register char *cp;
325 	char buf[80];
326 
327 	cp = Argv[0];
328 	if (sin)
329 		(void) sprintf(buf, "%s [%s]", a, inet_ntoa(sin->sin_addr));
330 	else
331 		(void) sprintf(buf, "%s", a);
332 	(void) strncpy(cp, buf, LastArg - cp);
333 	cp += strlen(cp);
334 	while (cp < LastArg)
335 		*cp++ = ' ';
336 }
337