From 542b5ba9e68a6bbabe9b29b5d29b5b793b3e8d4f Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Fri, 14 Aug 2009 13:37:12 -0400 Subject: [PATCH] nfs-utils: add IPv6 support to nfsd Add support for handing off IPv6 sockets to the kernel for nfsd. One of the main goals here is to not change the behavior of options and not to add any new ones, so this patch attempts to do that. We also don't want to break anything in the event that someone has an rpc.nfsd program built with IPv6 capability, but the knfsd doesn't support IPv6. Ditto for the cases where IPv6 is either not compiled in or is compiled in and blacklisted. Signed-off-by: Jeff Layton Signed-off-by: Steve Dickson --- utils/nfsd/nfsd.c | 114 ++++++++++++++++++++++++++++++++++++---------- 1 file changed, 89 insertions(+), 25 deletions(-) diff --git a/utils/nfsd/nfsd.c b/utils/nfsd/nfsd.c index c82249b..650c593 100644 --- a/utils/nfsd/nfsd.c +++ b/utils/nfsd/nfsd.c @@ -42,17 +42,63 @@ static struct option longopts[] = { "syslog", 0, 0, 's' }, { NULL, 0, 0, 0 } }; -unsigned int protobits = NFSCTL_ALLBITS; -unsigned int versbits = NFSCTL_ALLBITS; -int minorvers4 = NFSD_MAXMINORVERS4; /* nfsv4 minor version */ + +/* given a family and ctlbits, disable any that aren't listed in netconfig */ +#ifdef HAVE_LIBTIRPC +static void +nfsd_enable_protos(unsigned int *proto4, unsigned int *proto6) +{ + struct netconfig *nconf; + unsigned int *famproto; + void *handle; + + xlog(D_GENERAL, "Checking netconfig for visible protocols."); + + handle = setnetconfig(); + while((nconf = getnetconfig(handle))) { + if (!(nconf->nc_flag & NC_VISIBLE)) + continue; + + if (!strcmp(nconf->nc_protofmly, NC_INET)) + famproto = proto4; + else if (!strcmp(nconf->nc_protofmly, NC_INET6)) + famproto = proto6; + else + continue; + + if (!strcmp(nconf->nc_proto, NC_TCP)) + NFSCTL_TCPSET(*famproto); + else if (!strcmp(nconf->nc_proto, NC_UDP)) + NFSCTL_UDPSET(*famproto); + + xlog(D_GENERAL, "Enabling %s %s.", nconf->nc_protofmly, + nconf->nc_proto); + } + endnetconfig(handle); + return; +} +#else /* HAVE_LIBTIRPC */ +static void +nfsd_enable_protos(unsigned int *proto4, unsigned int *proto6) +{ + /* Enable all IPv4 protocols if no TIRPC support */ + *proto4 = NFSCTL_ALLBITS; + *proto6 = 0; +} +#endif /* HAVE_LIBTIRPC */ int main(int argc, char **argv) { - int count = 1, c, error, portnum = 0, fd, found_one; + int count = 1, c, error = 0, portnum = 0, fd, found_one; char *p, *progname, *port; char *haddr = NULL; int socket_up = 0; + int minorvers4 = NFSD_MAXMINORVERS4; /* nfsv4 minor version */ + unsigned int versbits = NFSCTL_ALLBITS; + unsigned int protobits = NFSCTL_ALLBITS; + unsigned int proto4 = 0; + unsigned int proto6 = 0; progname = strdup(basename(argv[0])); if (!progname) { @@ -137,15 +183,38 @@ main(int argc, char **argv) } } + if (optind < argc) { + if ((count = atoi(argv[optind])) < 0) { + /* insane # of servers */ + fprintf(stderr, + "%s: invalid server count (%d), using 1\n", + argv[0], count); + count = 1; + } else if (count == 0) { + /* + * don't bother setting anything else if the threads + * are coming down anyway. + */ + socket_up = 1; + goto set_threads; + } + } + xlog_open(progname); - /* - * Do some sanity checking, if the ctlbits are set - */ - if (!NFSCTL_UDPISSET(protobits) && !NFSCTL_TCPISSET(protobits)) { - xlog(L_ERROR, "invalid protocol specified"); - exit(1); + nfsd_enable_protos(&proto4, &proto6); + + if (!NFSCTL_TCPISSET(protobits)) { + NFSCTL_TCPUNSET(proto4); + NFSCTL_TCPUNSET(proto6); + } + + if (!NFSCTL_UDPISSET(protobits)) { + NFSCTL_UDPUNSET(proto4); + NFSCTL_UDPUNSET(proto6); } + + /* make sure that at least one version is enabled */ found_one = 0; for (c = NFSD_MINVERS; c <= NFSD_MAXVERS; c++) { if (NFSCTL_VERISSET(versbits, c)) @@ -156,29 +225,18 @@ main(int argc, char **argv) exit(1); } - if (NFSCTL_VERISSET(versbits, 4) && !NFSCTL_TCPISSET(protobits)) { + if (NFSCTL_VERISSET(versbits, 4) && + !NFSCTL_TCPISSET(proto4) && + !NFSCTL_TCPISSET(proto6)) { xlog(L_ERROR, "version 4 requires the TCP protocol"); exit(1); } - if (haddr == NULL) { - struct in_addr in = {INADDR_ANY}; - haddr = strdup(inet_ntoa(in)); - } if (chdir(NFS_STATEDIR)) { xlog(L_ERROR, "chdir(%s) failed: %m", NFS_STATEDIR); exit(1); } - if (optind < argc) { - if ((count = atoi(argv[optind])) < 0) { - /* insane # of servers */ - xlog(L_ERROR, "invalid server count (%d), using 1", - count); - count = 1; - } - } - /* can only change number of threads if nfsd is already up */ if (nfssvc_inuse()) { socket_up = 1; @@ -191,10 +249,16 @@ main(int argc, char **argv) * interfaces, these are a no-op. */ nfssvc_setvers(versbits, minorvers4); + + error = nfssvc_set_sockets(AF_INET, proto4, haddr, port); + if (!error) + socket_up = 1; - error = nfssvc_set_sockets(AF_INET, protobits, haddr, port); +#ifdef IPV6_SUPPORTED + error = nfssvc_set_sockets(AF_INET6, proto6, haddr, port); if (!error) socket_up = 1; +#endif /* IPV6_SUPPORTED */ set_threads: /* don't start any threads if unable to hand off any sockets */ -- 2.39.2