summaryrefslogtreecommitdiffstats
path: root/usr.sbin/nfsd
diff options
context:
space:
mode:
authordillon <dillon@FreeBSD.org>1999-11-11 17:35:36 +0000
committerdillon <dillon@FreeBSD.org>1999-11-11 17:35:36 +0000
commit4c498c4fdeb063ec3facb3dd2964fb02d90c17f5 (patch)
treecccb89faeac791d2d80cdc21936bfef7a51de932 /usr.sbin/nfsd
parentac372bbf0e733ba582ca3078e6ce33d10500e9ca (diff)
downloadFreeBSD-src-4c498c4fdeb063ec3facb3dd2964fb02d90c17f5.zip
FreeBSD-src-4c498c4fdeb063ec3facb3dd2964fb02d90c17f5.tar.gz
Give nfsd the ability to bind to specific IP addresses through the -h
option and add explicit option to bind to the wildcard address. The default is to bind to the wildcard address when no -h option has been specified and thus backwards compatibility is maintained. PR: kern/13049 Reviewed by: David Malone <dwmalone@maths.tcd.ie> Submitted by: Matt Dillon <dillon@freebsd.org>, David Malone <dwmalone@maths.tcd.ie>
Diffstat (limited to 'usr.sbin/nfsd')
-rw-r--r--usr.sbin/nfsd/nfsd.832
-rw-r--r--usr.sbin/nfsd/nfsd.c86
2 files changed, 93 insertions, 25 deletions
diff --git a/usr.sbin/nfsd/nfsd.8 b/usr.sbin/nfsd/nfsd.8
index e3d3e1c..f0314ae 100644
--- a/usr.sbin/nfsd/nfsd.8
+++ b/usr.sbin/nfsd/nfsd.8
@@ -42,8 +42,9 @@
server
.Sh SYNOPSIS
.Nm nfsd
-.Op Fl rut
+.Op Fl arut
.Op Fl n Ar num_servers
+.Op Fl h Ar bindip
.Sh DESCRIPTION
.Nm Nfsd
runs on a server machine to service
@@ -72,6 +73,19 @@ or
options to re-register NFS if the portmap server is restarted.
.It Fl n
Specifies how many servers to create.
+.It Fl h Ar bindip
+Specifies which IP address or hostname to bind to on the local host.
+This option is recommended when a host has multiple interfaces. Multiple
+.Fl h
+options may be specified.
+.It Fl a
+Specifies that nfsd should bind to the wildcard IP address.
+This is the default if no
+.Fl h
+options are given. It may also be specified in addition to any
+.Fl h
+options given. Note that NFS/UDP does not operate properly when
+bound to the wildcard IP address whether you use -a or do not use -h.
.It Fl t
Serve
.Tn TCP NFS
@@ -119,6 +133,19 @@ KLD is available,
.Nm nfsd
will exit with an error.
.Pp
+If
+.Nm nfsd
+is to be run on a host with multiple interfaces or interface aliases, use
+of the
+.Fl h
+option is recommended. If you do not use the option NFS may not respond to
+UDP packets from the same IP address they were sent to. Use of this option
+is also recommended when securing NFS exports on a firewalling machine such
+that the NFS sockets can only be accessed by the inside interface.
+.Nm Ipfw
+would then be used to block nfs-related packets that come in on the outside
+interface.
+.Pp
The
.Nm nfsd
utility exits 0 on success, and >0 if an error occurs.
@@ -127,7 +154,8 @@ utility exits 0 on success, and >0 if an error occurs.
.Xr nfssvc 2 ,
.Xr kldload 8 ,
.Xr mountd 8 ,
-.Xr portmap 8
+.Xr portmap 8 ,
+.Xr ipfw 8
.Sh HISTORY
The
.Nm nfsd
diff --git a/usr.sbin/nfsd/nfsd.c b/usr.sbin/nfsd/nfsd.c
index ca7ecef..9ff9d98 100644
--- a/usr.sbin/nfsd/nfsd.c
+++ b/usr.sbin/nfsd/nfsd.c
@@ -56,6 +56,8 @@ static const char rcsid[] =
#include <rpc/rpc.h>
#include <rpc/pmap_clnt.h>
+#include <netdb.h>
+#include <arpa/inet.h>
#ifdef ISO
#include <netiso/iso.h>
#endif
@@ -104,6 +106,7 @@ NFSKERBKEYSCHED_T kerb_keysched;
void nonfs __P((int));
void reapchild __P((int));
+void setbindhost __P((struct sockaddr_in *ia, const char *bindhost));
#ifdef OLD_SETPROCTITLE
#ifdef __FreeBSD__
void setproctitle __P((char *));
@@ -145,6 +148,8 @@ main(argc, argv, envp)
int ch, cltpflag, connect_type_cnt, i, len, maxsock, msgsock;
int nfsdcnt, nfssvc_flag, on, reregister, sock, tcpflag, tcpsock;
int tp4cnt, tp4flag, tpipcnt, tpipflag, udpflag;
+ int bindhostc = 0, bindanyflag;
+ char **bindhost = NULL;
#ifdef notyet
int tp4sock, tpipsock;
#endif
@@ -184,16 +189,19 @@ main(argc, argv, envp)
#define DEFNFSDCNT 4
nfsdcnt = DEFNFSDCNT;
cltpflag = reregister = tcpflag = tp4cnt = tp4flag = tpipcnt = 0;
- tpipflag = udpflag = 0;
+ bindanyflag = tpipflag = udpflag = 0;
#ifdef ISO
-#define GETOPT "cn:rtu"
-#define USAGE "[-crtu] [-n num_servers]"
+#define GETOPT "ach:n:rtu"
+#define USAGE "[-acrtu] [-n num_servers] [-h bindip]"
#else
-#define GETOPT "n:rtu"
-#define USAGE "[-rtu] [-n num_servers]"
+#define GETOPT "ah:n:rtu"
+#define USAGE "[-artu] [-n num_servers] [-h bindip]"
#endif
while ((ch = getopt(argc, argv, GETOPT)) != -1)
switch (ch) {
+ case 'a':
+ bindanyflag = 1;
+ break;
case 'n':
nfsdcnt = atoi(optarg);
if (nfsdcnt < 1 || nfsdcnt > MAXNFSDCNT) {
@@ -202,6 +210,15 @@ main(argc, argv, envp)
nfsdcnt = DEFNFSDCNT;
}
break;
+ case 'h':
+ bindhostc++;
+ bindhost = realloc(bindhost,sizeof(char *)*bindhostc);
+ if (bindhost == NULL)
+ errx(1, "Out of memory");
+ bindhost[bindhostc-1] = strdup(optarg);
+ if (bindhost[bindhostc-1] == NULL)
+ errx(1, "Out of memory");
+ break;
case 'r':
reregister = 1;
break;
@@ -248,6 +265,16 @@ main(argc, argv, envp)
}
}
+ if (bindhostc == 0 || bindanyflag) {
+ bindhostc++;
+ bindhost = realloc(bindhost,sizeof(char *)*bindhostc);
+ if (bindhost == NULL)
+ errx(1, "Out of memory");
+ bindhost[bindhostc-1] = strdup("*");
+ if (bindhost[bindhostc-1] == NULL)
+ errx(1, "Out of memory");
+ }
+
if (debug == 0) {
daemon(0, 0);
(void)signal(SIGHUP, SIG_IGN);
@@ -374,18 +401,15 @@ main(argc, argv, envp)
}
/* If we are serving udp, set up the socket. */
- if (udpflag) {
+ for (i = 0; udpflag && i < bindhostc; i++) {
if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
syslog(LOG_ERR, "can't create udp socket");
exit(1);
}
- inetaddr.sin_family = AF_INET;
- inetaddr.sin_addr.s_addr = INADDR_ANY;
- inetaddr.sin_port = htons(NFS_PORT);
- inetaddr.sin_len = sizeof(inetaddr);
+ setbindhost(&inetaddr, bindhost[i]);
if (bind(sock,
(struct sockaddr *)&inetaddr, sizeof(inetaddr)) < 0) {
- syslog(LOG_ERR, "can't bind udp addr");
+ syslog(LOG_ERR, "can't bind udp addr %s: %m", bindhost[i]);
exit(1);
}
if (!pmap_set(RPCPROG_NFS, 2, IPPROTO_UDP, NFS_PORT) ||
@@ -448,7 +472,7 @@ main(argc, argv, envp)
on = 1;
FD_ZERO(&sockbits);
connect_type_cnt = 0;
- if (tcpflag) {
+ for (i = 0; tcpflag && i < bindhostc; i++) {
if ((tcpsock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
syslog(LOG_ERR, "can't create tcp socket");
exit(1);
@@ -456,13 +480,10 @@ main(argc, argv, envp)
if (setsockopt(tcpsock,
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);
+ setbindhost(&inetaddr, bindhost[i]);
if (bind(tcpsock,
(struct sockaddr *)&inetaddr, sizeof (inetaddr)) < 0) {
- syslog(LOG_ERR, "can't bind tcp addr");
+ syslog(LOG_ERR, "can't bind tcp addr %s: %m", bindhost[i]);
exit(1);
}
if (listen(tcpsock, 5) < 0) {
@@ -520,7 +541,7 @@ main(argc, argv, envp)
}
/* Now set up the master server socket waiting for tpip connections. */
- if (tpipflag) {
+ for (i = 0; tpipflag && i < bindhostc; i++) {
if ((tpipsock = socket(AF_INET, SOCK_SEQPACKET, 0)) < 0) {
syslog(LOG_ERR, "can't create tpip socket");
exit(1);
@@ -528,13 +549,10 @@ main(argc, argv, envp)
if (setsockopt(tpipsock,
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);
+ setbindhost(&inetaddr, bindhost[i]);
if (bind(tpipsock,
(struct sockaddr *)&inetaddr, sizeof (inetaddr)) < 0) {
- syslog(LOG_ERR, "can't bind tcp addr");
+ syslog(LOG_ERR, "can't bind tcp addr %s: %m", bindhost[i]);
exit(1);
}
if (listen(tpipsock, 5) < 0) {
@@ -631,6 +649,28 @@ main(argc, argv, envp)
}
void
+setbindhost(struct sockaddr_in *ia, const char *bindhost)
+{
+ ia->sin_family = AF_INET;
+ ia->sin_port = htons(NFS_PORT);
+ ia->sin_len = sizeof(*ia);
+ if (bindhost == NULL || strcmp(bindhost,"*") == 0) {
+ ia->sin_addr.s_addr = INADDR_ANY;
+ } else {
+ if (inet_aton(bindhost, &ia->sin_addr) == 0) {
+ struct hostent *he;
+
+ he = gethostbyname2(bindhost, ia->sin_family);
+ if (he == NULL) {
+ syslog(LOG_ERR, "gethostbyname of %s failed", bindhost);
+ exit(1);
+ }
+ bcopy(he->h_addr, &ia->sin_addr, he->h_length);
+ }
+ }
+}
+
+void
usage()
{
(void)fprintf(stderr, "usage: nfsd %s\n", USAGE);
OpenPOWER on IntegriCloud