1 /* $NetBSD: nfsd.c,v 1.5 2015/08/21 14:19:10 christos Exp $ */
4 * Copyright (c) 1989, 1993, 1994
5 * The Regents of the University of California. All rights reserved.
7 * This code is derived from software contributed to Berkeley by
8 * Rick Macklem at The University of Guelph.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 #include <sys/cdefs.h>
37 __COPYRIGHT("@(#) Copyright (c) 1989, 1993, 1994\
38 The Regents of the University of California. All rights reserved.");
43 static char sccsid
[] = "@(#)nfsd.c 8.9 (Berkeley) 3/29/95";
45 __RCSID("$NetBSD: nfsd.c,v 1.5 2015/08/21 14:19:10 christos Exp $");
49 #include <sys/param.h>
50 #include <sys/ioctl.h>
54 #include <sys/ucred.h>
55 #include <sys/mount.h>
56 #include <sys/socket.h>
57 #include <sys/socketvar.h>
61 #include <rpc/pmap_clnt.h>
62 #include <rpc/pmap_prot.h>
64 #include <nfs/rpcv2.h>
65 #include <nfs/nfsproto.h>
82 #include <rump/rump.h>
83 #include <rump/rump_syscalls.h>
87 #define syslog(e, s, args...) \
89 fprintf(stderr,(s), ## args); \
90 fprintf(stderr, "\n"); \
91 } while (/*CONSTCOND*/0)
103 struct nfsd_srvargs nsd
;
106 nfssvc_flag
= NFSSVC_NFSD
;
107 memset(&nsd
, 0, sizeof(nsd
));
108 while (rump_sys_nfssvc(nfssvc_flag
, &nsd
) < 0) {
109 if (errno
!= ENEEDAUTH
) {
110 syslog(LOG_ERR
, "nfssvc (%s)", strerror(errno
));
113 nfssvc_flag
= NFSSVC_NFSD
| NFSSVC_AUTHINFAIL
;
120 * Nfs server daemon mostly just a user context for nfssvc()
122 * 1 - do file descriptor and signal cleanup
123 * 2 - create the nfsd thread(s)
124 * 3 - create server socket(s)
125 * 4 - register socket with portmap
127 * For connectionless protocols, just pass the socket into the kernel via
129 * For connection based sockets, loop doing accepts. When you get a new
130 * socket from accept, pass the msgsock into the kernel via nfssvc().
132 * -c - support iso cltp clients
133 * -r - reregister with portmapper
134 * -t - support tcp nfs clients
135 * -u - support udp nfs clients
136 * followed by "n" which is the number of nfsd threads to create
138 int nfsd_main(int, char**);
140 nfsd_main(argc
, argv
)
144 struct nfsd_args nfsdargs
;
145 struct addrinfo
*ai_udp
, *ai_tcp
, *ai_udp6
, *ai_tcp6
, hints
;
146 struct netconfig
*nconf_udp
, *nconf_tcp
, *nconf_udp6
, *nconf_tcp6
;
147 struct netbuf nb_udp
, nb_tcp
, nb_udp6
, nb_tcp6
;
148 struct sockaddr_in inetpeer
;
149 struct pollfd set
[4];
151 int ch
, connect_type_cnt
, i
, msgsock
;
152 int nfsdcnt
, on
= 1, reregister
, sock
, tcpflag
, tcpsock
;
153 int tcp6sock
, ip6flag
;
154 int tp4cnt
, tp4flag
, tpipcnt
, udpflag
, ecode
, s
;
157 nfsdcnt
= DEFNFSDCNT
;
158 reregister
= tcpflag
= tp4cnt
= tp4flag
= tpipcnt
= 0;
159 udpflag
= ip6flag
= 0;
160 nconf_udp
= nconf_tcp
= nconf_udp6
= nconf_tcp6
= NULL
;
161 tcpsock
= tcp6sock
= -1;
162 #define GETOPT "6n:rtu"
163 #define USAGE "[-rtu] [-n num_servers]"
164 while ((ch
= getopt(argc
, argv
, GETOPT
)) != -1) {
168 s
= socket(PF_INET6
, SOCK_DGRAM
, IPPROTO_UDP
);
169 if (s
< 0 && (errno
== EPROTONOSUPPORT
||
170 errno
== EPFNOSUPPORT
|| errno
== EAFNOSUPPORT
))
176 nfsdcnt
= atoi(optarg
);
178 warnx("nfsd count %d; reset to %d", nfsdcnt
, DEFNFSDCNT
);
179 nfsdcnt
= DEFNFSDCNT
;
201 * Backward compatibility, trailing number is the count of daemons.
206 nfsdcnt
= atoi(argv
[0]);
208 warnx("nfsd count %d; reset to %d", nfsdcnt
, DEFNFSDCNT
);
209 nfsdcnt
= DEFNFSDCNT
;
214 * If none of TCP or UDP are specified, default to UDP only.
216 if (tcpflag
== 0 && udpflag
== 0)
220 fprintf(stderr
, "non-debug not supported here\n");
223 #ifdef not_the_debug_man
225 (void)signal(SIGHUP
, SIG_IGN
);
226 (void)signal(SIGINT
, SIG_IGN
);
227 (void)signal(SIGQUIT
, SIG_IGN
);
228 (void)signal(SIGSYS
, nonfs
);
233 memset(&hints
, 0, sizeof hints
);
234 hints
.ai_flags
= AI_PASSIVE
;
235 hints
.ai_family
= PF_INET
;
236 hints
.ai_socktype
= SOCK_DGRAM
;
237 hints
.ai_protocol
= IPPROTO_UDP
;
239 ecode
= getaddrinfo(NULL
, "nfs", &hints
, &ai_udp
);
241 syslog(LOG_ERR
, "getaddrinfo udp: %s",
242 gai_strerror(ecode
));
246 nconf_udp
= getnetconfigent("udp");
248 if (nconf_udp
== NULL
)
249 err(1, "getnetconfigent udp failed");
251 nb_udp
.buf
= ai_udp
->ai_addr
;
252 nb_udp
.len
= nb_udp
.maxlen
= ai_udp
->ai_addrlen
;
254 if (!rpcb_set(RPCPROG_NFS
, 2, nconf_udp
, &nb_udp
))
255 err(1, "rpcb_set udp failed");
259 memset(&hints
, 0, sizeof hints
);
260 hints
.ai_flags
= AI_PASSIVE
;
261 hints
.ai_family
= PF_INET
;
262 hints
.ai_socktype
= SOCK_STREAM
;
263 hints
.ai_protocol
= IPPROTO_TCP
;
265 ecode
= getaddrinfo(NULL
, "nfs", &hints
, &ai_tcp
);
267 syslog(LOG_ERR
, "getaddrinfo tcp: %s",
268 gai_strerror(ecode
));
272 nconf_tcp
= getnetconfigent("tcp");
274 if (nconf_tcp
== NULL
)
275 err(1, "getnetconfigent tcp failed");
277 nb_tcp
.buf
= ai_tcp
->ai_addr
;
278 nb_tcp
.len
= nb_tcp
.maxlen
= ai_tcp
->ai_addrlen
;
280 if (!rpcb_set(RPCPROG_NFS
, 2, nconf_tcp
, &nb_tcp
))
281 err(1, "rpcb_set tcp failed");
284 if (udpflag
&& ip6flag
) {
285 memset(&hints
, 0, sizeof hints
);
286 hints
.ai_flags
= AI_PASSIVE
;
287 hints
.ai_family
= PF_INET6
;
288 hints
.ai_socktype
= SOCK_DGRAM
;
289 hints
.ai_protocol
= IPPROTO_UDP
;
291 ecode
= getaddrinfo(NULL
, "nfs", &hints
, &ai_udp6
);
293 syslog(LOG_ERR
, "getaddrinfo udp: %s",
294 gai_strerror(ecode
));
298 nconf_udp6
= getnetconfigent("udp6");
300 if (nconf_udp6
== NULL
)
301 err(1, "getnetconfigent udp6 failed");
303 nb_udp6
.buf
= ai_udp6
->ai_addr
;
304 nb_udp6
.len
= nb_udp6
.maxlen
= ai_udp6
->ai_addrlen
;
306 if (!rpcb_set(RPCPROG_NFS
, 2, nconf_udp6
, &nb_udp6
))
307 err(1, "rpcb_set udp6 failed");
310 if (tcpflag
&& ip6flag
) {
311 memset(&hints
, 0, sizeof hints
);
312 hints
.ai_flags
= AI_PASSIVE
;
313 hints
.ai_family
= PF_INET6
;
314 hints
.ai_socktype
= SOCK_STREAM
;
315 hints
.ai_protocol
= IPPROTO_TCP
;
317 ecode
= getaddrinfo(NULL
, "nfs", &hints
, &ai_tcp6
);
319 syslog(LOG_ERR
, "getaddrinfo tcp: %s",
320 gai_strerror(ecode
));
324 nconf_tcp6
= getnetconfigent("tcp6");
326 if (nconf_tcp6
== NULL
)
327 err(1, "getnetconfigent tcp6 failed");
329 nb_tcp6
.buf
= ai_tcp6
->ai_addr
;
330 nb_tcp6
.len
= nb_tcp6
.maxlen
= ai_tcp6
->ai_addrlen
;
332 if (!rpcb_set(RPCPROG_NFS
, 2, nconf_tcp6
, &nb_tcp6
))
333 err(1, "rpcb_set tcp6 failed");
336 openlog("nfsd", LOG_PID
, LOG_DAEMON
);
338 for (i
= 0; i
< nfsdcnt
; i
++) {
340 pthread_create(&t
, NULL
, child
, NULL
);
343 /* If we are serving udp, set up the socket. */
345 if ((sock
= rump_sys_socket(ai_udp
->ai_family
, ai_udp
->ai_socktype
,
346 ai_udp
->ai_protocol
)) < 0) {
347 syslog(LOG_ERR
, "can't create udp socket");
350 if (bind(sock
, ai_udp
->ai_addr
, ai_udp
->ai_addrlen
) < 0) {
351 syslog(LOG_ERR
, "can't bind udp addr");
354 if (!rpcb_set(RPCPROG_NFS
, 2, nconf_udp
, &nb_udp
) ||
355 !rpcb_set(RPCPROG_NFS
, 3, nconf_udp
, &nb_udp
)) {
356 syslog(LOG_ERR
, "can't register with udp portmap");
359 nfsdargs
.sock
= sock
;
360 nfsdargs
.name
= NULL
;
361 nfsdargs
.namelen
= 0;
362 if (rump_sys_nfssvc(NFSSVC_ADDSOCK
, &nfsdargs
) < 0) {
363 syslog(LOG_ERR
, "can't add UDP socket");
366 (void)rump_sys_close(sock
);
369 if (udpflag
&&ip6flag
) {
370 if ((sock
= rump_sys_socket(ai_udp6
->ai_family
, ai_udp6
->ai_socktype
,
371 ai_udp6
->ai_protocol
)) < 0) {
372 syslog(LOG_ERR
, "can't create udp socket");
375 if (rump_sys_setsockopt(sock
, IPPROTO_IPV6
, IPV6_V6ONLY
,
376 &on
, sizeof on
) < 0) {
377 syslog(LOG_ERR
, "can't set v6-only binding for udp6 "
378 "socket (%s)", strerror(errno
));
381 if (rump_sys_bind(sock
, ai_udp6
->ai_addr
, ai_udp6
->ai_addrlen
) < 0) {
382 syslog(LOG_ERR
, "can't bind udp addr (%s)",
386 if (!rpcb_set(RPCPROG_NFS
, 2, nconf_udp6
, &nb_udp6
) ||
387 !rpcb_set(RPCPROG_NFS
, 3, nconf_udp6
, &nb_udp6
)) {
388 syslog(LOG_ERR
, "can't register with udp portmap");
391 nfsdargs
.sock
= sock
;
392 nfsdargs
.name
= NULL
;
393 nfsdargs
.namelen
= 0;
394 if (rump_sys_nfssvc(NFSSVC_ADDSOCK
, &nfsdargs
) < 0) {
395 syslog(LOG_ERR
, "can't add UDP6 socket (%s)",
399 (void)rump_sys_close(sock
);
402 /* Now set up the master server socket waiting for tcp connections. */
404 connect_type_cnt
= 0;
406 if ((tcpsock
= rump_sys_socket(ai_tcp
->ai_family
, ai_tcp
->ai_socktype
,
407 ai_tcp
->ai_protocol
)) < 0) {
408 syslog(LOG_ERR
, "can't create tcp socket");
411 if (setsockopt(tcpsock
,
412 SOL_SOCKET
, SO_REUSEADDR
, (char *)&on
, sizeof(on
)) < 0)
413 syslog(LOG_ERR
, "setsockopt SO_REUSEADDR (%s)",
415 if (bind(tcpsock
, ai_tcp
->ai_addr
, ai_tcp
->ai_addrlen
) < 0) {
416 syslog(LOG_ERR
, "can't bind tcp addr");
419 if (rump_sys_listen(tcpsock
, 5) < 0) {
420 syslog(LOG_ERR
, "listen failed");
423 if (!rpcb_set(RPCPROG_NFS
, 2, nconf_tcp
, &nb_tcp
) ||
424 !rpcb_set(RPCPROG_NFS
, 3, nconf_tcp
, &nb_tcp
)) {
425 syslog(LOG_ERR
, "can't register tcp with rpcbind");
429 set
[0].events
= POLLIN
;
434 if (tcpflag
&& ip6flag
) {
435 if ((tcp6sock
= socket(ai_tcp6
->ai_family
, ai_tcp6
->ai_socktype
,
436 ai_tcp6
->ai_protocol
)) < 0) {
437 syslog(LOG_ERR
, "can't create tcp socket (%s)",
441 if (setsockopt(tcp6sock
,
442 SOL_SOCKET
, SO_REUSEADDR
, (char *)&on
, sizeof(on
)) < 0)
443 syslog(LOG_ERR
, "setsockopt SO_REUSEADDR (%s)",
445 if (setsockopt(tcp6sock
, IPPROTO_IPV6
, IPV6_V6ONLY
,
446 &on
, sizeof on
) < 0) {
447 syslog(LOG_ERR
, "can't set v6-only binding for tcp6 "
448 "socket (%s)", strerror(errno
));
451 if (bind(tcp6sock
, ai_tcp6
->ai_addr
, ai_tcp6
->ai_addrlen
) < 0) {
452 syslog(LOG_ERR
, "can't bind tcp6 addr (%s)",
456 if (listen(tcp6sock
, 5) < 0) {
457 syslog(LOG_ERR
, "listen failed (%s)", strerror(errno
));
460 if (!rpcb_set(RPCPROG_NFS
, 2, nconf_tcp6
, &nb_tcp6
) ||
461 !rpcb_set(RPCPROG_NFS
, 3, nconf_tcp6
, &nb_tcp6
)) {
462 syslog(LOG_ERR
, "can't register tcp6 with rpcbind");
465 set
[1].fd
= tcp6sock
;
466 set
[1].events
= POLLIN
;
474 if (connect_type_cnt
== 0) {
480 * Loop forever accepting connections and passing the sockets
481 * into the kernel for the mounts.
484 if (rump_sys_poll(set
, 4, INFTIM
) < 1) {
485 syslog(LOG_ERR
, "poll failed (%s)", strerror(errno
));
489 len
= sizeof(inetpeer
);
490 if ((msgsock
= accept(tcpsock
,
491 (struct sockaddr
*)&inetpeer
, &len
)) < 0) {
492 syslog(LOG_ERR
, "accept failed (%s)",
496 memset(inetpeer
.sin_zero
, 0, sizeof(inetpeer
.sin_zero
));
497 if (setsockopt(msgsock
, SOL_SOCKET
,
498 SO_KEEPALIVE
, (char *)&on
, sizeof(on
)) < 0)
499 syslog(LOG_ERR
, "setsockopt SO_KEEPALIVE (%s)",
501 nfsdargs
.sock
= msgsock
;
502 nfsdargs
.name
= (caddr_t
)&inetpeer
;
503 nfsdargs
.namelen
= sizeof(inetpeer
);
504 rump_sys_nfssvc(NFSSVC_ADDSOCK
, &nfsdargs
);
505 (void)rump_sys_close(msgsock
);
509 if (set
[1].revents
& POLLIN
) {
510 len
= sizeof(inet6peer
);
511 if ((msgsock
= rump_sys_accept(tcp6sock
,
512 (struct sockaddr
*)&inet6peer
, &len
, &error
)) < 0) {
513 syslog(LOG_ERR
, "accept failed (%s)",
517 if (rump_sys_setsockopt(msgsock
, SOL_SOCKET
,
518 SO_KEEPALIVE
, (char *)&on
, sizeof(on
), &error
) < 0)
520 "setsockopt SO_KEEPALIVE (%s)",
522 nfsdargs
.sock
= msgsock
;
523 nfsdargs
.name
= (caddr_t
)&inet6peer
;
524 nfsdargs
.namelen
= sizeof(inet6peer
);
525 rump_sys_nfssvc(NFSSVC_ADDSOCK
, &nfsdargs
, &error
);
526 (void)rump_sys_close(msgsock
, &error
);
529 if (set
[2].revents
& POLLIN
) {
530 len
= sizeof(isopeer
);
531 if ((msgsock
= rump_sys_accept(tp4sock
,
532 (struct sockaddr
*)&isopeer
, &len
, &error
)) < 0) {
533 syslog(LOG_ERR
, "accept failed (%s)",
537 if (rump_sys_setsockopt(msgsock
, SOL_SOCKET
,
538 SO_KEEPALIVE
, (char *)&on
, sizeof(on
), &error
) < 0)
539 syslog(LOG_ERR
, "setsockopt SO_KEEPALIVE (%s)",
541 nfsdargs
.sock
= msgsock
;
542 nfsdargs
.name
= (caddr_t
)&isopeer
;
543 nfsdargs
.namelen
= len
;
544 rump_sys_nfssvc(NFSSVC_ADDSOCK
, &nfsdargs
, &error
);
545 (void)rump_sys_close(msgsock
, &error
);
548 if (set
[3].revents
& POLLIN
) {
549 len
= sizeof(inetpeer
);
550 if ((msgsock
= rump_sys_accept(tpipsock
,
551 (struct sockaddr
*)&inetpeer
, &len
)) < 0) {
552 syslog(LOG_ERR
, "accept failed (%s)",
556 if (setsockopt(msgsock
, SOL_SOCKET
,
557 SO_KEEPALIVE
, (char *)&on
, sizeof(on
)) < 0)
558 syslog(LOG_ERR
, "setsockopt SO_KEEPALIVE (%s)",
560 nfsdargs
.sock
= msgsock
;
561 nfsdargs
.name
= (caddr_t
)&inetpeer
;
562 nfsdargs
.namelen
= len
;
563 rump_sys_nfssvc(NFSSVC_ADDSOCK
, &nfsdargs
);
564 (void)rump_sys_close(msgsock
);
573 (void)fprintf(stderr
, "usage: nfsd %s\n", USAGE
);
581 syslog(LOG_ERR
, "missing system call: NFS not available.");