GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: sbin/nfsd/nfsd.c Lines: 0 135 0.0 %
Date: 2016-12-06 Branches: 0 88 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: nfsd.c,v 1.36 2016/06/07 01:29:38 tedu Exp $	*/
2
/*	$NetBSD: nfsd.c,v 1.19 1996/02/18 23:18:56 mycroft Exp $	*/
3
4
/*
5
 * Copyright (c) 1989, 1993, 1994
6
 *	The Regents of the University of California.  All rights reserved.
7
 *
8
 * This code is derived from software contributed to Berkeley by
9
 * Rick Macklem at The University of Guelph.
10
 *
11
 * Redistribution and use in source and binary forms, with or without
12
 * modification, are permitted provided that the following conditions
13
 * are met:
14
 * 1. Redistributions of source code must retain the above copyright
15
 *    notice, this list of conditions and the following disclaimer.
16
 * 2. Redistributions in binary form must reproduce the above copyright
17
 *    notice, this list of conditions and the following disclaimer in the
18
 *    documentation and/or other materials provided with the distribution.
19
 * 3. Neither the name of the University nor the names of its contributors
20
 *    may be used to endorse or promote products derived from this software
21
 *    without specific prior written permission.
22
 *
23
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33
 * SUCH DAMAGE.
34
 */
35
36
#include <sys/ioctl.h>
37
#include <sys/stat.h>
38
#include <sys/wait.h>
39
#include <sys/uio.h>
40
#include <sys/ucred.h>
41
#include <sys/mount.h>
42
#include <sys/socket.h>
43
#include <sys/socketvar.h>
44
45
#include <rpc/rpc.h>
46
#include <rpc/pmap_clnt.h>
47
#include <rpc/pmap_prot.h>
48
49
#include <nfs/rpcv2.h>
50
#include <nfs/nfsproto.h>
51
#include <nfs/nfs.h>
52
53
#include <err.h>
54
#include <errno.h>
55
#include <fcntl.h>
56
#include <grp.h>
57
#include <pwd.h>
58
#include <signal.h>
59
#include <stdio.h>
60
#include <stdlib.h>
61
#include <string.h>
62
#include <syslog.h>
63
#include <unistd.h>
64
65
/* Global defs */
66
#ifdef DEBUG
67
#define	syslog(e, s)	fprintf(stderr,(s))
68
int	debug = 1;
69
#else
70
int	debug = 0;
71
#endif
72
73
struct	nfsd_srvargs nsd;
74
75
void	nonfs(int);
76
void	reapchild(int);
77
void	usage(void);
78
79
#define	MAXNFSDCNT	20
80
#define	DEFNFSDCNT	 4
81
82
/*
83
 * Nfs server daemon mostly just a user context for nfssvc()
84
 *
85
 * 1 - do file descriptor and signal cleanup
86
 * 2 - fork the nfsd(s)
87
 * 3 - create server socket(s)
88
 * 4 - register socket with portmap
89
 *
90
 * For connectionless protocols, just pass the socket into the kernel via.
91
 * nfssvc().
92
 * For connection based sockets, loop doing accepts. When you get a new
93
 * socket from accept, pass the msgsock into the kernel via. nfssvc().
94
 * The arguments are:
95
 *	-r - reregister with portmapper
96
 *	-t - support tcp nfs clients
97
 *	-u - support udp nfs clients
98
 * followed by "n" which is the number of nfsds' to fork off
99
 */
100
int
101
main(int argc, char *argv[])
102
{
103
	struct nfsd_args nfsdargs;
104
	struct sockaddr_in inetaddr;
105
	int ch, connect_type_cnt, i;
106
	int nfsdcnt = DEFNFSDCNT, on, reregister = 0, sock;
107
	int udpflag = 0, tcpflag = 0, tcpsock;
108
	const char *errstr = NULL;
109
110
	/* Start by writing to both console and log. */
111
	openlog("nfsd", LOG_PID | LOG_PERROR, LOG_DAEMON);
112
113
	if (argc == 1)
114
		udpflag = 1;
115
	while ((ch = getopt(argc, argv, "n:rtu")) != -1)
116
		switch (ch) {
117
		case 'n':
118
			nfsdcnt = strtonum(optarg, 1, MAXNFSDCNT, &errstr);
119
			if (errstr) {
120
				syslog(LOG_ERR, "nfsd count is %s: %s", errstr, optarg);
121
				return(1);
122
			}
123
			break;
124
		case 'r':
125
			reregister = 1;
126
			break;
127
		case 't':
128
			tcpflag = 1;
129
			break;
130
		case 'u':
131
			udpflag = 1;
132
			break;
133
		default:
134
			usage();
135
		};
136
	argv += optind;
137
	argc -= optind;
138
139
	/*
140
	 * XXX
141
	 * Backward compatibility, trailing number is the count of daemons.
142
	 */
143
	if (argc > 1)
144
		usage();
145
	if (argc == 1) {
146
		nfsdcnt = strtonum(argv[0], 1, MAXNFSDCNT, &errstr);
147
		if (errstr) {
148
			syslog(LOG_ERR, "nfsd count is %s: %s", errstr, optarg);
149
			return(1);
150
		}
151
	}
152
153
	if (debug == 0) {
154
		daemon(0, 0);
155
		(void)signal(SIGHUP, SIG_IGN);
156
		(void)signal(SIGINT, SIG_IGN);
157
		(void)signal(SIGQUIT, SIG_IGN);
158
		(void)signal(SIGSYS, nonfs);
159
	}
160
	(void)signal(SIGCHLD, reapchild);
161
162
	if (reregister) {
163
		if (udpflag &&
164
		    (!pmap_set(RPCPROG_NFS, 2, IPPROTO_UDP, NFS_PORT) ||
165
		     !pmap_set(RPCPROG_NFS, 3, IPPROTO_UDP, NFS_PORT))) {
166
			syslog(LOG_ERR, "can't register with portmap for UDP (%m).");
167
			return (1);
168
		}
169
		if (tcpflag &&
170
		    (!pmap_set(RPCPROG_NFS, 2, IPPROTO_TCP, NFS_PORT) ||
171
		     !pmap_set(RPCPROG_NFS, 3, IPPROTO_TCP, NFS_PORT))) {
172
			syslog(LOG_ERR, "can't register with portmap for TCP (%m).");
173
			return (1);
174
		}
175
		return (0);
176
	}
177
178
	/* Cut back to writing to log only. */
179
	closelog();
180
	openlog("nfsd", LOG_PID, LOG_DAEMON);
181
182
	for (i = 0; i < nfsdcnt; i++) {
183
		switch (fork()) {
184
		case -1:
185
			syslog(LOG_ERR, "fork: %m");
186
			return (1);
187
		case 0:
188
			break;
189
		default:
190
			continue;
191
		}
192
193
		setproctitle("server");
194
		nsd.nsd_nfsd = NULL;
195
		if (nfssvc(NFSSVC_NFSD, &nsd) < 0) {
196
			syslog(LOG_ERR, "nfssvc: %m");
197
			return (1);
198
		}
199
		return (0);
200
	}
201
202
	/* If we are serving udp, set up the socket. */
203
	if (udpflag) {
204
		if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
205
			syslog(LOG_ERR, "can't create udp socket");
206
			return (1);
207
		}
208
		memset(&inetaddr, 0, sizeof inetaddr);
209
		inetaddr.sin_family = AF_INET;
210
		inetaddr.sin_addr.s_addr = INADDR_ANY;
211
		inetaddr.sin_port = htons(NFS_PORT);
212
		inetaddr.sin_len = sizeof(inetaddr);
213
		if (bind(sock, (struct sockaddr *)&inetaddr,
214
		    sizeof(inetaddr)) < 0) {
215
			syslog(LOG_ERR, "can't bind udp addr");
216
			return (1);
217
		}
218
		if (!pmap_set(RPCPROG_NFS, 2, IPPROTO_UDP, NFS_PORT) ||
219
		    !pmap_set(RPCPROG_NFS, 3, IPPROTO_UDP, NFS_PORT)) {
220
			syslog(LOG_ERR, "can't register with udp portmap");
221
			return (1);
222
		}
223
		nfsdargs.sock = sock;
224
		nfsdargs.name = NULL;
225
		nfsdargs.namelen = 0;
226
		if (nfssvc(NFSSVC_ADDSOCK, &nfsdargs) < 0) {
227
			syslog(LOG_ERR, "can't Add UDP socket");
228
			return (1);
229
		}
230
		(void)close(sock);
231
	}
232
233
	/* Now set up the master server socket waiting for tcp connections. */
234
	on = 1;
235
	connect_type_cnt = 0;
236
	if (tcpflag) {
237
		if ((tcpsock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
238
			syslog(LOG_ERR, "can't create tcp socket");
239
			return (1);
240
		}
241
		if (setsockopt(tcpsock,
242
		    SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0)
243
			syslog(LOG_ERR, "setsockopt SO_REUSEADDR: %m");
244
		memset(&inetaddr, 0, sizeof inetaddr);
245
		inetaddr.sin_family = AF_INET;
246
		inetaddr.sin_addr.s_addr = INADDR_ANY;
247
		inetaddr.sin_port = htons(NFS_PORT);
248
		inetaddr.sin_len = sizeof(inetaddr);
249
		if (bind(tcpsock, (struct sockaddr *)&inetaddr,
250
		    sizeof (inetaddr)) < 0) {
251
			syslog(LOG_ERR, "can't bind tcp addr");
252
			return (1);
253
		}
254
		if (listen(tcpsock, 5) < 0) {
255
			syslog(LOG_ERR, "listen failed");
256
			return (1);
257
		}
258
		if (!pmap_set(RPCPROG_NFS, 2, IPPROTO_TCP, NFS_PORT) ||
259
		    !pmap_set(RPCPROG_NFS, 3, IPPROTO_TCP, NFS_PORT)) {
260
			syslog(LOG_ERR, "can't register tcp with portmap");
261
			return (1);
262
		}
263
		connect_type_cnt++;
264
	}
265
266
	if (connect_type_cnt == 0)
267
		return (0);
268
269
	setproctitle("master");
270
271
	/*
272
	 * Loop forever accepting connections and passing the sockets
273
	 * into the kernel for the mounts.
274
	 */
275
	for (;;) {
276
		struct pollfd		pfd;
277
		struct sockaddr_in	inetpeer;
278
		int ret, msgsock;
279
		socklen_t len;
280
281
		pfd.fd = tcpsock;
282
		pfd.events = POLLIN;
283
284
		if (connect_type_cnt > 1) {
285
			ret = poll(&pfd, 1, INFTIM);
286
			if (ret < 1) {
287
				syslog(LOG_ERR, "poll failed: %m");
288
				return (1);
289
			}
290
291
		}
292
293
		if (tcpflag) {
294
			len = sizeof(inetpeer);
295
			if ((msgsock = accept(tcpsock,
296
			    (struct sockaddr *)&inetpeer, &len)) < 0) {
297
				if (errno == EWOULDBLOCK || errno == EINTR ||
298
				    errno == ECONNABORTED)
299
					continue;
300
				syslog(LOG_ERR, "accept failed: %m");
301
				return (1);
302
			}
303
			memset(inetpeer.sin_zero, 0, sizeof(inetpeer.sin_zero));
304
			if (setsockopt(msgsock, SOL_SOCKET,
305
			    SO_KEEPALIVE, &on, sizeof(on)) < 0)
306
				syslog(LOG_ERR,
307
				    "setsockopt SO_KEEPALIVE: %m");
308
			nfsdargs.sock = msgsock;
309
			nfsdargs.name = (caddr_t)&inetpeer;
310
			nfsdargs.namelen = sizeof(inetpeer);
311
			if (nfssvc(NFSSVC_ADDSOCK, &nfsdargs) < 0) {
312
				syslog(LOG_ERR, "can't Add TCP socket");
313
				return (1);
314
			}
315
			(void)close(msgsock);
316
		}
317
	}
318
}
319
320
void
321
usage(void)
322
{
323
	(void)fprintf(stderr, "usage: nfsd [-rtu] [-n num_servers]\n");
324
	exit(1);
325
}
326
327
/* ARGSUSED */
328
void
329
nonfs(int signo)
330
{
331
	int save_errno = errno;
332
	struct syslog_data sdata = SYSLOG_DATA_INIT;
333
334
	syslog_r(LOG_ERR, &sdata, "missing system call: NFS not available.");
335
	errno = save_errno;
336
}
337
338
/* ARGSUSED */
339
void
340
reapchild(int signo)
341
{
342
	int save_errno = errno;
343
344
	while (wait3(NULL, WNOHANG, NULL) > 0)
345
		continue;
346
	errno = save_errno;
347
}