Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/usr.sbin/nfsd Let nfsd behave like all other programs: tries...



details:   https://anonhg.NetBSD.org/src/rev/7047ecb1df70
branches:  trunk
changeset: 780957:7047ecb1df70
user:      christos <christos%NetBSD.org@localhost>
date:      Mon Aug 13 08:19:11 2012 +0000

description:
Let nfsd behave like all other programs: tries to use both inet4 and inet6
by default and both udp and tcp: -4 uses only inet4, -6 uses only inet6,
-t uses only tcp, -u uses only udp. For compatibility, we detect old option
usage, we warn, and DTRT.

diffstat:

 usr.sbin/nfsd/nfsd.8 |   27 +-
 usr.sbin/nfsd/nfsd.c |  561 +++++++++++++++++++-------------------------------
 2 files changed, 234 insertions(+), 354 deletions(-)

diffs (truncated from 747 to 300 lines):

diff -r 0feadb305de6 -r 7047ecb1df70 usr.sbin/nfsd/nfsd.8
--- a/usr.sbin/nfsd/nfsd.8      Mon Aug 13 08:07:03 2012 +0000
+++ b/usr.sbin/nfsd/nfsd.8      Mon Aug 13 08:19:11 2012 +0000
@@ -1,4 +1,4 @@
-.\"   $NetBSD: nfsd.8,v 1.21 2008/03/17 09:57:11 yamt Exp $
+.\"   $NetBSD: nfsd.8,v 1.22 2012/08/13 08:19:11 christos Exp $
 .\"
 .\" Copyright (c) 1989, 1991, 1993
 .\"    The Regents of the University of California.  All rights reserved.
@@ -29,7 +29,7 @@
 .\"
 .\"    @(#)nfsd.8      8.4 (Berkeley) 3/29/95
 .\"
-.Dd March 17, 2008
+.Dd August 12, 2012
 .Dt NFSD 8
 .Os
 .Sh NAME
@@ -39,7 +39,7 @@
 server
 .Sh SYNOPSIS
 .Nm
-.Op Fl 6rut
+.Op Fl 46rut
 .Op Fl n Ar num_threads
 .Sh DESCRIPTION
 .Nm
@@ -73,20 +73,31 @@
 A server should run enough threads to handle
 the maximum level of concurrency from its clients.
 .It Fl 6
-Listen to IPv6 requests as well as IPv4 requests. If IPv6 support is not
-available, nfsd will silently continue and just use IPv4.
+Listen to only IPv6 requests.
+By default
+.Nm
+listens to both IPv6 and IPv4 and tries to register for both.
+.It Fl 4
+Listen to only IPv4 requests.
 .It Fl t
-Serve
+Serve only
 .Tn TCP NFS
 clients.
+By default
+.Nm
+serves both 
+.Tn TCP NFS
+and
+.TN UDP NFS
+clients
 .It Fl u
-Serve
+Serve only
 .Tn UDP NFS
 clients.
 .El
 .Pp
 For example,
-.Dq Li "nfsd -t -u -n 6"
+.Dq Li "nfsd -n 6"
 serves
 .Tn UDP
 and
diff -r 0feadb305de6 -r 7047ecb1df70 usr.sbin/nfsd/nfsd.c
--- a/usr.sbin/nfsd/nfsd.c      Mon Aug 13 08:07:03 2012 +0000
+++ b/usr.sbin/nfsd/nfsd.c      Mon Aug 13 08:19:11 2012 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: nfsd.c,v 1.58 2011/08/30 20:07:31 joerg Exp $  */
+/*     $NetBSD: nfsd.c,v 1.59 2012/08/13 08:19:11 christos Exp $       */
 
 /*
  * Copyright (c) 1989, 1993, 1994
@@ -42,7 +42,7 @@
 #if 0
 static char sccsid[] = "@(#)nfsd.c     8.9 (Berkeley) 3/29/95";
 #else
-__RCSID("$NetBSD: nfsd.c,v 1.58 2011/08/30 20:07:31 joerg Exp $");
+__RCSID("$NetBSD: nfsd.c,v 1.59 2012/08/13 08:19:11 christos Exp $");
 #endif
 #endif /* not lint */
 
@@ -114,6 +114,135 @@
        return NULL;
 }
 
+struct conf {
+       struct addrinfo *ai;
+       struct netconfig *nc;
+       struct netbuf nb;
+       struct pollfd pfd;
+};
+
+#define NFS_UDP4       0
+#define NFS_TCP4       1
+#define NFS_UDP6       2
+#define NFS_TCP6       3
+
+static int cfg_family[] = { PF_INET, PF_INET, PF_INET6, PF_INET6 };
+static const char *cfg_netconf[] = { "udp", "tcp", "udp6", "tcp6" };
+static int cfg_socktype[] = {
+    SOCK_DGRAM, SOCK_STREAM, SOCK_DGRAM, SOCK_STREAM };
+static int cfg_protocol[] = {
+    IPPROTO_UDP, IPPROTO_TCP, IPPROTO_UDP, IPPROTO_TCP };
+
+static int
+tryconf(struct conf *cfg, int t, int reregister)
+{
+       struct addrinfo hints;
+       int ecode;
+
+       memset(cfg, 0, sizeof(cfg));
+       memset(&hints, 0, sizeof hints);
+       hints.ai_flags = AI_PASSIVE;
+       hints.ai_family = cfg_family[t];
+       hints.ai_socktype = cfg_socktype[t];
+       hints.ai_protocol = cfg_protocol[t];
+
+       ecode = getaddrinfo(NULL, "nfs", &hints, &cfg->ai);
+       if (ecode != 0) {
+               syslog(LOG_ERR, "getaddrinfo %s: %s", cfg_netconf[t],
+                   gai_strerror(ecode));
+               return -1;
+       }
+
+       cfg->nc = getnetconfigent(cfg_netconf[t]);
+
+       if (cfg->nc == NULL) {
+               syslog(LOG_ERR, "getnetconfigent %s failed: %m",
+                   cfg_netconf[t]);
+               return -1;
+       }
+
+       cfg->nb.buf = cfg->ai->ai_addr;
+       cfg->nb.len = cfg->nb.maxlen = cfg->ai->ai_addrlen;
+       if (reregister)
+               if (!rpcb_set(RPCPROG_NFS, 2, cfg->nc, &cfg->nb)) {
+                       syslog(LOG_ERR, "rpcb_set %s failed", cfg_netconf[t]);
+                       freenetconfigent(cfg->nc);
+                       cfg->nc = NULL;
+                       return -1;
+               }
+       return 0;
+}
+
+static int
+setupsock(struct conf *cfg, struct pollfd *set, int p)
+{
+       int sock;
+       struct nfsd_args nfsdargs;
+       struct addrinfo *ai = cfg->ai;
+       int on = 1;
+
+       sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
+
+       if (sock == -1) {
+               syslog(LOG_ERR, "can't create %s socket: %m", cfg_netconf[p]);
+               return -1;
+       }
+       if (cfg_family[p] == PF_INET6) {
+               if (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &on,
+                   sizeof(on)) == -1) {
+                       syslog(LOG_ERR, "can't set v6-only binding for %s "
+                           "socket: %m", cfg_netconf[p]);
+                       goto out;
+               }
+       }
+
+       if (cfg_protocol[p] == IPPROTO_TCP) {
+               if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on,
+                   sizeof(on)) == -1) {
+                       syslog(LOG_ERR, "setsockopt SO_REUSEADDR for %s: %m",
+                           cfg_netconf[p]);
+                       goto out;
+               }
+       }
+
+       if (bind(sock, ai->ai_addr, ai->ai_addrlen) == -1) {
+               syslog(LOG_ERR, "can't bind %s addr: %m", cfg_netconf[p]);
+               goto out;
+       }
+
+       if (cfg_protocol[p] == IPPROTO_TCP) {
+               if (listen(sock, 5) == -1) {
+                       syslog(LOG_ERR, "listen failed");
+                       goto out;
+               }
+       }
+
+       if (!rpcb_set(RPCPROG_NFS, 2, cfg->nc, &cfg->nb) ||
+           !rpcb_set(RPCPROG_NFS, 3, cfg->nc, &cfg->nb)) {
+               syslog(LOG_ERR, "can't register with %s portmap",
+                   cfg_netconf[p]);
+               goto out;
+       }
+
+
+       if (cfg_protocol[p] == IPPROTO_TCP)
+               set->fd = sock;
+       else {
+               nfsdargs.sock = sock;
+               nfsdargs.name = NULL;
+               nfsdargs.namelen = 0;
+               if (nfssvc(NFSSVC_ADDSOCK, &nfsdargs) < 0) {
+                       syslog(LOG_ERR, "can't add %s socket", cfg_netconf[p]);
+                       goto out;
+               }
+               (void)close(sock);
+       }
+       return 0;
+out:
+       (void)close(sock);
+       return -1;
+}
+
 /*
  * Nfs server daemon mostly just a user context for nfssvc()
  *
@@ -127,41 +256,37 @@
  * For connection based sockets, loop doing accepts. When you get a new
  * socket from accept, pass the msgsock into the kernel via nfssvc().
  * The arguments are:
- *     -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 nfsd threads to create
+ *     -t - support only tcp nfs clients
+ *     -u - support only udp nfs clients
+ *     -n num how many threads to create.
+ *     -4 - use only ipv4
+ *     -6 - use only ipv6
  */
 int
 main(int argc, char *argv[])
 {
-       struct nfsd_args nfsdargs;
-       struct addrinfo *ai_udp, *ai_tcp, *ai_udp6, *ai_tcp6, hints;
-       struct netconfig *nconf_udp, *nconf_tcp, *nconf_udp6, *nconf_tcp6;
-       struct netbuf nb_udp, nb_tcp, nb_udp6, nb_tcp6;
-       struct sockaddr_in inetpeer;
-       struct sockaddr_in6 inet6peer;
-       struct pollfd set[4];
-       socklen_t len;
-       int ch, cltpflag, connect_type_cnt, i, maxsock, msgsock, serrno;
-       int nfsdcnt, on = 1, reregister, sock, tcpflag, tcpsock;
-       int tcp6sock, ip6flag;
-       int tp4cnt, tp4flag, tpipcnt, tpipflag, udpflag, ecode, s;
+       struct conf cfg[4];
+       struct pollfd set[__arraycount(cfg)];
+       int ch, connect_type_cnt;
+       size_t i, nfsdcnt;
+       int reregister;
+       int tcpflag, udpflag;
+       int ip6flag, ip4flag;
+       int s, compat;
 
 #define        DEFNFSDCNT       4
        nfsdcnt = DEFNFSDCNT;
-       cltpflag = reregister = tcpflag = tp4cnt = tp4flag = tpipcnt = 0;
-       tpipflag = udpflag = ip6flag = 0;
-       nconf_udp = nconf_tcp = nconf_udp6 = nconf_tcp6 = NULL;
-       maxsock = 0;
-       tcpsock = tcp6sock = -1;
-#define        GETOPT  "6n:rtu"
-#define        USAGE   "[-rtu] [-n num_servers]"
+       compat = reregister = 0;
+       tcpflag = udpflag = 1;
+       ip6flag = ip4flag = 1;
+#define        GETOPT  "46n:rtu"
+#define        USAGE   "[-46rtu] [-n num_servers]"
        while ((ch = getopt(argc, argv, GETOPT)) != -1) {
                switch (ch) {
                case '6':
                        ip6flag = 1;
+                       ip4flag = 0;
                        s = socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP);
                        if (s < 0 && (errno == EPROTONOSUPPORT ||
                            errno == EPFNOSUPPORT || errno == EAFNOSUPPORT))
@@ -169,10 +294,21 @@
                        else
                                close(s);
                        break;
+               case '4':
+                       ip6flag = 0;
+                       ip4flag = 1;
+                       s = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
+                       if (s < 0 && (errno == EPROTONOSUPPORT ||
+                           errno == EPFNOSUPPORT || errno == EAFNOSUPPORT))
+                               ip4flag = 0;
+                       else
+                               close(s);
+                       break;
                case 'n':
                        nfsdcnt = atoi(optarg);
                        if (nfsdcnt < 1) {
-                               warnx("nfsd count %d; reset to %d", nfsdcnt, DEFNFSDCNT);
+                               warnx("nfsd count %zu; reset to %d", nfsdcnt,
+                                   DEFNFSDCNT);
                                nfsdcnt = DEFNFSDCNT;



Home | Main Index | Thread Index | Old Index