diff options
author | dillon <dillon@FreeBSD.org> | 1999-11-11 17:35:36 +0000 |
---|---|---|
committer | dillon <dillon@FreeBSD.org> | 1999-11-11 17:35:36 +0000 |
commit | 4c498c4fdeb063ec3facb3dd2964fb02d90c17f5 (patch) | |
tree | cccb89faeac791d2d80cdc21936bfef7a51de932 | |
parent | ac372bbf0e733ba582ca3078e6ce33d10500e9ca (diff) | |
download | FreeBSD-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>
-rw-r--r-- | sbin/nfsd/nfsd.8 | 32 | ||||
-rw-r--r-- | sbin/nfsd/nfsd.c | 86 | ||||
-rw-r--r-- | usr.sbin/nfsd/nfsd.8 | 32 | ||||
-rw-r--r-- | usr.sbin/nfsd/nfsd.c | 86 |
4 files changed, 186 insertions, 50 deletions
diff --git a/sbin/nfsd/nfsd.8 b/sbin/nfsd/nfsd.8 index e3d3e1c..f0314ae 100644 --- a/sbin/nfsd/nfsd.8 +++ b/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/sbin/nfsd/nfsd.c b/sbin/nfsd/nfsd.c index ca7ecef..9ff9d98 100644 --- a/sbin/nfsd/nfsd.c +++ b/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); 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); |