* Copyright (c) 1989 The Regents of the University of California.
* This code is derived from software contributed to Berkeley by
* Rick Macklem at The University of Guelph.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
"@(#) Copyright (c) 1989 Regents of the University of California.\n\
static char sccsid
[] = "@(#)nfsd.c 5.10 (Berkeley) 4/24/91";
#include <sys/socketvar.h>
#include <rpc/pmap_clnt.h>
#include <rpc/pmap_prot.h>
#define syslog(e, s) fprintf(stderr,(s))
char **Argv
= NULL
; /* pointer to argument vector */
char *LastArg
= NULL
; /* end of argv */
* Nfs server daemon mostly just a user context for nfssvc()
* 1 - do file descriptor and signal cleanup
* 2 - create server socket
* 3 - register socket with portmap
* For SOCK_DGRAM, just fork children and send them into the kernel
* For connection based sockets, loop doing accepts. When you get a new socket
* from accept, fork a child that drops into the kernel via. nfssvc.
* This child will return from nfssvc when the connection is closed, so
* just shutdown() and exit().
* -t - support tcp nfs clients
* -u - support udp nfs clients
register struct hadr
*hp
;
int udpcnt
, sock
, msgsock
, tcpflag
= 0, udpflag
= 0, ret
, len
;
struct sockaddr_in saddr
, msk
, mtch
, peername
;
* Save start and extent of argv for setproctitle.
if (envp
== 0 || *envp
== 0)
LastArg
= envp
[-1] + strlen(envp
[-1]);
while ((opt
= getopt(argc
, argv
, "rt:u:")) != EOF
)
if (cp
= index(optarg
, ',')) {
msk
.sin_addr
.s_addr
= inet_addr(optarg
);
if (msk
.sin_addr
.s_addr
== -1)
if (cp2
= index(cp
, ','))
mtch
.sin_addr
.s_addr
= inet_addr(cp
);
if (mtch
.sin_addr
.s_addr
== -1)
hphead
.ha_next
= (struct hadr
*)0;
if (cp2
= index(cp
, ','))
malloc(sizeof (struct hadr
));
hp
->ha_sad
= inet_addr(cp
);
hp
->ha_next
= hphead
.ha_next
;
if (cp
= index(optarg
, ',')) {
msk
.sin_addr
.s_addr
= inet_addr(optarg
);
if (msk
.sin_addr
.s_addr
== -1)
if (cp2
= index(cp
, ','))
mtch
.sin_addr
.s_addr
= inet_addr(cp
);
if (mtch
.sin_addr
.s_addr
== -1)
if (udpcnt
< 1 || udpcnt
> 20)
* Default, if neither UDP nor TCP is specified,
* is to support UDP only; a numeric argument indicates
* the number of server daemons to run.
if (udpflag
== 0 && tcpflag
== 0) {
if (udpcnt
< 1 || udpcnt
> 20)
msk
.sin_addr
.s_addr
= mtch
.sin_addr
.s_addr
= 0;
signal(SIGQUIT
, SIG_IGN
);
signal(SIGTERM
, SIG_IGN
);
signal(SIGCHLD
, reapchild
);
if (udpflag
&& !pmap_set(RPCPROG_NFS
, NFS_VER2
, IPPROTO_UDP
,
"Can't register with portmap for UDP\n");
if (tcpflag
&& !pmap_set(RPCPROG_NFS
, NFS_VER2
, IPPROTO_TCP
,
"Can't register with portmap for TCP\n");
openlog("nfsd:", LOG_PID
, LOG_DAEMON
);
/* why? unregisters both protocols even if we restart only one */
pmap_unset(RPCPROG_NFS
, NFS_VER2
);
if ((sock
= socket(AF_INET
, SOCK_DGRAM
, 0)) < 0) {
syslog(LOG_ERR
, "Can't create socket");
saddr
.sin_family
= AF_INET
;
saddr
.sin_addr
.s_addr
= INADDR_ANY
;
saddr
.sin_port
= htons(NFS_PORT
);
if (bind(sock
, (struct sockaddr
*)&saddr
, sizeof(saddr
)) < 0) {
syslog(LOG_ERR
, "Can't bind addr");
if (!pmap_set(RPCPROG_NFS
, NFS_VER2
, IPPROTO_UDP
, NFS_PORT
)) {
syslog(LOG_ERR
, "Can't register with portmap");
* Send the nfs datagram servers
* right down into the kernel
for (i
= 0; i
< udpcnt
; i
++)
(struct sockaddr_in
*)NULL
);
ret
= nfssvc(sock
, &msk
, sizeof(msk
),
syslog(LOG_ERR
, "nfssvc() failed %m");
* Now set up the master STREAM server waiting for tcp connections.
if ((sock
= socket(AF_INET
, SOCK_STREAM
, 0)) < 0) {
syslog(LOG_ERR
, "Can't create socket");
if (setsockopt(sock
, SOL_SOCKET
, SO_REUSEADDR
,
(char *) &on
, sizeof(on
)) < 0)
syslog(LOG_ERR
, "setsockopt SO_REUSEADDR: %m");
saddr
.sin_family
= AF_INET
;
saddr
.sin_addr
.s_addr
= INADDR_ANY
;
saddr
.sin_port
= htons(NFS_PORT
);
if (bind(sock
, (struct sockaddr
*)&saddr
, sizeof(saddr
)) < 0) {
syslog(LOG_ERR
, "Can't bind addr");
if (listen(sock
, 5) < 0) {
syslog(LOG_ERR
, "Listen failed");
if (!pmap_set(RPCPROG_NFS
, NFS_VER2
, IPPROTO_TCP
, NFS_PORT
)) {
syslog(LOG_ERR
, "Can't register with portmap");
setproctitle("nfsd-listen", (struct sockaddr_in
*)NULL
);
* Loop forever accepting connections and sending the children
* into the kernel to service the mounts.
if ((msgsock
= accept(sock
,
(struct sockaddr
*)&peername
, &len
)) < 0) {
syslog(LOG_ERR
, "Accept failed: %m");
if ((peername
.sin_addr
.s_addr
& msk
.sin_addr
.s_addr
) !=
if (peername
.sin_addr
.s_addr
==
setproctitle("nfsd-tcp", &peername
);
if (setsockopt(msgsock
, SOL_SOCKET
,
SO_KEEPALIVE
, (char *) &on
, sizeof(on
)) < 0)
"setsockopt SO_KEEPALIVE: %m");
ret
= nfssvc(msgsock
, &msk
, sizeof(msk
),
fprintf(stderr
, "nfsd [-t msk,mtch[,addrs]] [-u msk,mtch,numprocs]\n");
while (wait3((int *) NULL
, WNOHANG
, (struct rusage
*) NULL
))
(void) sprintf(buf
, "%s [%s]", a
, inet_ntoa(sin
->sin_addr
));
(void) sprintf(buf
, "%s", a
);
(void) strncpy(cp
, buf
, LastArg
- cp
);