1b370456456bf8991e770ba3c7829f37c925cd7d
* Copyright (c) 1989, 1993, 1994
* The Regents of the University of California. All rights reserved.
* This code is derived from software contributed to Berkeley by
* Rick Macklem at The University of Guelph.
* %sccs.include.redist.c%
static char copyright
[] =
"@(#) Copyright (c) 1989, 1993, 1994\n\
The Regents of the University of California. All rights reserved.\n";
static char sccsid
[] = "@(#)nfsd.c 8.8 (Berkeley) %G%";
#include <sys/socketvar.h>
#include <rpc/pmap_clnt.h>
#include <rpc/pmap_prot.h>
#include <kerberosIV/des.h>
#include <kerberosIV/krb.h>
#define syslog(e, s) fprintf(stderr,(s))
char **Argv
= NULL
; /* pointer to argument vector */
char *LastArg
= NULL
; /* end of argv */
void reapchild
__P((int));
void setproctitle
__P((char *));
* Nfs server daemon mostly just a user context for nfssvc()
* 1 - do file descriptor and signal cleanup
* 3 - create server socket(s)
* 4 - register socket with portmap
* For connectionless protocols, just pass the socket into the kernel via.
* For connection based sockets, loop doing accepts. When you get a new
* socket from accept, pass the msgsock into the kernel via. nfssvc().
* -c - support iso cltp clients
* -r - reregister with portmapper
* -t - support tcp nfs clients
* -u - support udp nfs clients
* followed by "n" which is the number of nfsds' to fork off
struct nfsd_args nfsdargs
;
struct sockaddr_in inetaddr
, inetpeer
;
struct sockaddr_iso isoaddr
, isopeer
;
int ch
, cltpflag
, connect_type_cnt
, i
, len
, maxsock
, msgsock
;
int nfsdcnt
, nfssvc_flag
, on
, reregister
, sock
, tcpflag
, tcpsock
;
int tp4cnt
, tp4flag
, tp4sock
, tpipcnt
, tpipflag
, tpipsock
, udpflag
;
/* Save start and extent of argv for setproctitle. */
if (envp
== 0 || *envp
== 0)
LastArg
= envp
[-1] + strlen(envp
[-1]);
cltpflag
= reregister
= tcpflag
= tp4cnt
= tp4flag
= tpipcnt
= 0;
#define USAGE "[-crtu] [-n num_servers]"
#define USAGE "[-rtu] [-n num_servers]"
while ((ch
= getopt(argc
, argv
, GETOPT
)) != EOF
)
if (nfsdcnt
< 1 || nfsdcnt
> MAXNFSDCNT
) {
warnx("nfsd count %d; reset to %d", DEFNFSDCNT
);
* Backward compatibility, trailing number is the count of daemons.
if (nfsdcnt
< 1 || nfsdcnt
> MAXNFSDCNT
) {
warnx("nfsd count %d; reset to %d", DEFNFSDCNT
);
(void)signal(SIGHUP
, SIG_IGN
);
(void)signal(SIGINT
, SIG_IGN
);
(void)signal(SIGQUIT
, SIG_IGN
);
(void)signal(SIGSYS
, nonfs
);
(void)signal(SIGTERM
, SIG_IGN
);
(void)signal(SIGCHLD
, reapchild
);
!pmap_set(RPCPROG_NFS
, NFS_VER2
, IPPROTO_UDP
, NFS_PORT
))
err(1, "can't register with portmap for UDP.");
!pmap_set(RPCPROG_NFS
, NFS_VER2
, IPPROTO_TCP
, NFS_PORT
))
err(1, "can't register with portmap for TCP.");
openlog("nfsd:", LOG_PID
, LOG_DAEMON
);
for (i
= 0; i
< nfsdcnt
; i
++) {
syslog(LOG_ERR
, "fork: %m");
setproctitle("nfsd-srv");
nfssvc_flag
= NFSSVC_NFSD
;
nsd
.nsd_authstr
= (char *)kt
.dat
;
while (nfssvc(nfssvc_flag
, &nsd
) < 0) {
if (errno
!= ENEEDAUTH
) {
syslog(LOG_ERR
, "nfssvc: %m");
nfssvc_flag
= NFSSVC_NFSD
| NFSSVC_AUTHINFAIL
;
kt
.length
= nsd
.nsd_authlen
;
if (krb_rd_req(&kt
, "rcmd",
inst
, nsd
.nsd_haddr
, &auth
, "") == RD_AP_OK
&&
krb_kntoln(&auth
, lnam
) == KSUCCESS
&&
(pwd
= getpwnam(lnam
)) != NULL
) {
cr
->cr_uid
= pwd
->pw_uid
;
cr
->cr_groups
[0] = pwd
->pw_gid
;
while ((grp
= getgrent()) != NULL
) {
if (grp
->gr_gid
== cr
->cr_groups
[0])
cr
->cr_groups
[cr
->cr_ngroups
++]
if (cr
->cr_ngroups
== NGROUPS
)
nfssvc_flag
= NFSSVC_NFSD
| NFSSVC_AUTHIN
;
/* If we are serving udp, set up the socket. */
if ((sock
= socket(AF_INET
, SOCK_DGRAM
, 0)) < 0) {
syslog(LOG_ERR
, "can't create udp socket");
inetaddr
.sin_family
= AF_INET
;
inetaddr
.sin_addr
.s_addr
= INADDR_ANY
;
inetaddr
.sin_port
= htons(NFS_PORT
);
inetaddr
.sin_len
= sizeof(inetaddr
);
(struct sockaddr
*)&inetaddr
, sizeof(inetaddr
)) < 0) {
syslog(LOG_ERR
, "can't bind udp addr");
if (!pmap_set(RPCPROG_NFS
, NFS_VER2
, IPPROTO_UDP
, NFS_PORT
)) {
syslog(LOG_ERR
, "can't register with udp portmap");
if (nfssvc(NFSSVC_ADDSOCK
, &nfsdargs
) < 0) {
syslog(LOG_ERR
, "can't Add UDP socket");
/* If we are serving cltp, set up the socket. */
if ((sock
= socket(AF_ISO
, SOCK_DGRAM
, 0)) < 0) {
syslog(LOG_ERR
, "can't create cltp socket");
memset(&isoaddr
, 0, sizeof(isoaddr
));
isoaddr
.siso_family
= AF_ISO
;
isoaddr
.siso_len
= sizeof(isoaddr
);
(struct sockaddr
*)&isoaddr
, sizeof(isoaddr
)) < 0) {
syslog(LOG_ERR
, "can't bind cltp addr");
* Someday this should probably use "rpcbind", the son of
if (!pmap_set(RPCPROG_NFS
, NFS_VER2
, IPPROTO_UDP
, NFS_PORT
)) {
syslog(LOG_ERR
, "can't register with udp portmap");
if (nfssvc(NFSSVC_ADDSOCK
, &nfsdargs
) < 0) {
syslog(LOG_ERR
, "can't add UDP socket");
/* Now set up the master server socket waiting for tcp connections. */
if ((tcpsock
= socket(AF_INET
, SOCK_STREAM
, 0)) < 0) {
syslog(LOG_ERR
, "can't create tcp socket");
SOL_SOCKET
, SO_REUSEADDR
, (char *)&on
, sizeof(on
)) < 0)
syslog(LOG_ERR
, "setsockopt SO_REUSEADDR: %m");
inetaddr
.sin_family
= AF_INET
;
inetaddr
.sin_addr
.s_addr
= INADDR_ANY
;
inetaddr
.sin_port
= htons(NFS_PORT
);
inetaddr
.sin_len
= sizeof(inetaddr
);
(struct sockaddr
*)&inetaddr
, sizeof (inetaddr
)) < 0) {
syslog(LOG_ERR
, "can't bind tcp addr");
if (listen(tcpsock
, 5) < 0) {
syslog(LOG_ERR
, "listen failed");
if (!pmap_set(RPCPROG_NFS
, NFS_VER2
, IPPROTO_TCP
, NFS_PORT
)) {
syslog(LOG_ERR
, "can't register tcp with portmap");
FD_SET(tcpsock
, &sockbits
);
/* Now set up the master server socket waiting for tp4 connections. */
if ((tp4sock
= socket(AF_ISO
, SOCK_SEQPACKET
, 0)) < 0) {
syslog(LOG_ERR
, "can't create tp4 socket");
SOL_SOCKET
, SO_REUSEADDR
, (char *)&on
, sizeof(on
)) < 0)
syslog(LOG_ERR
, "setsockopt SO_REUSEADDR: %m");
memset(&isoaddr
, 0, sizeof(isoaddr
));
isoaddr
.siso_family
= AF_ISO
;
isoaddr
.siso_len
= sizeof(isoaddr
);
(struct sockaddr
*)&isoaddr
, sizeof (isoaddr
)) < 0) {
syslog(LOG_ERR
, "can't bind tp4 addr");
if (listen(tp4sock
, 5) < 0) {
syslog(LOG_ERR
, "listen failed");
* Someday this should probably use "rpcbind", the son of
if (!pmap_set(RPCPROG_NFS
, NFS_VER2
, IPPROTO_TCP
, NFS_PORT
)) {
syslog(LOG_ERR
, "can't register tcp with portmap");
FD_SET(tp4sock
, &sockbits
);
/* Now set up the master server socket waiting for tpip connections. */
if ((tpipsock
= socket(AF_INET
, SOCK_SEQPACKET
, 0)) < 0) {
syslog(LOG_ERR
, "can't create tpip socket");
SOL_SOCKET
, SO_REUSEADDR
, (char *)&on
, sizeof(on
)) < 0)
syslog(LOG_ERR
, "setsockopt SO_REUSEADDR: %m");
inetaddr
.sin_family
= AF_INET
;
inetaddr
.sin_addr
.s_addr
= INADDR_ANY
;
inetaddr
.sin_port
= htons(NFS_PORT
);
inetaddr
.sin_len
= sizeof(inetaddr
);
(struct sockaddr
*)&inetaddr
, sizeof (inetaddr
)) < 0) {
syslog(LOG_ERR
, "can't bind tcp addr");
if (listen(tpipsock
, 5) < 0) {
syslog(LOG_ERR
, "listen failed");
* Someday this should probably use "rpcbind", the son of
if (!pmap_set(RPCPROG_NFS
, NFS_VER2
, IPPROTO_TCP
, NFS_PORT
)) {
syslog(LOG_ERR
, "can't register tcp with portmap");
FD_SET(tpipsock
, &sockbits
);
if (connect_type_cnt
== 0)
setproctitle("nfsd-master");
* Loop forever accepting connections and passing the sockets
* into the kernel for the mounts.
if (connect_type_cnt
> 1) {
&ready
, NULL
, NULL
, NULL
) < 1) {
syslog(LOG_ERR
, "select failed: %m");
if (tcpflag
&& FD_ISSET(tcpsock
, &ready
)) {
if ((msgsock
= accept(tcpsock
,
(struct sockaddr
*)&inetpeer
, &len
)) < 0) {
syslog(LOG_ERR
, "accept failed: %m");
memset(inetpeer
.sin_zero
, 0, sizeof(inetpeer
.sin_zero
));
if (setsockopt(msgsock
, SOL_SOCKET
,
SO_KEEPALIVE
, (char *)&on
, sizeof(on
)) < 0)
"setsockopt SO_KEEPALIVE: %m");
nfsdargs
.name
= (caddr_t
)&inetpeer
;
nfsdargs
.namelen
= sizeof(inetpeer
);
nfssvc(NFSSVC_ADDSOCK
, &nfsdargs
);
if (tp4flag
&& FD_ISSET(tp4sock
, &ready
)) {
if ((msgsock
= accept(tp4sock
,
(struct sockaddr
*)&isopeer
, &len
)) < 0) {
syslog(LOG_ERR
, "accept failed: %m");
if (setsockopt(msgsock
, SOL_SOCKET
,
SO_KEEPALIVE
, (char *)&on
, sizeof(on
)) < 0)
"setsockopt SO_KEEPALIVE: %m");
nfsdargs
.name
= (caddr_t
)&isopeer
;
nfssvc(NFSSVC_ADDSOCK
, &nfsdargs
);
if (tpipflag
&& FD_ISSET(tpipsock
, &ready
)) {
if ((msgsock
= accept(tpipsock
,
(struct sockaddr
*)&inetpeer
, &len
)) < 0) {
syslog(LOG_ERR
, "Accept failed: %m");
if (setsockopt(msgsock
, SOL_SOCKET
,
SO_KEEPALIVE
, (char *)&on
, sizeof(on
)) < 0)
syslog(LOG_ERR
, "setsockopt SO_KEEPALIVE: %m");
nfsdargs
.name
= (caddr_t
)&inetpeer
;
nfssvc(NFSSVC_ADDSOCK
, &nfsdargs
);
(void)fprintf(stderr
, "nfsd %s\n", USAGE
);
syslog(LOG_ERR
, "missing system call: NFS not available.");
while (wait3(NULL
, WNOHANG
, NULL
));
(void)snprintf(buf
, sizeof(buf
), "%s", a
);
(void)strncpy(cp
, buf
, LastArg
- cp
);