aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChuck Lever <chuck.lever@oracle.com>2008-08-18 19:34:16 -0400
committerJ. Bruce Fields <bfields@citi.umich.edu>2008-09-29 18:13:38 -0400
commita26cfad6e0a308a2c68df1f1ef50aabd48b17e6d (patch)
tree9d200a635720bde73b66fd96e4db9e7ff9be3af7
parent7252d575ab0e8771269a3d245c36a05ace5152bd (diff)
SUNRPC: Support IPv6 when registering kernel RPC services
In order to advertise NFS-related services on IPv6 interfaces via rpcbind, the kernel RPC server implementation must use rpcb_v4_register() instead of rpcb_register(). A new kernel build option allows distributions to use the legacy v2 call until they integrate an appropriate user-space rpcbind daemon that can support IPv6 RPC services. I tried adding some automatic logic to fall back if registering with a v4 protocol request failed, but there are too many corner cases. So I just made it a compile-time switch that distributions can throw when they've replaced portmapper with rpcbind. Signed-off-by: Chuck Lever <chuck.lever@oracle.com> Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
-rw-r--r--fs/Kconfig22
-rw-r--r--include/linux/sunrpc/svc.h4
-rw-r--r--net/sunrpc/svc.c95
3 files changed, 113 insertions, 8 deletions
diff --git a/fs/Kconfig b/fs/Kconfig
index c6ae4d4842eb..ed57a5a37250 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -1773,6 +1773,28 @@ config SUNRPC_XPRT_RDMA
1773 1773
1774 If unsure, say N. 1774 If unsure, say N.
1775 1775
1776config SUNRPC_REGISTER_V4
1777 bool "Register local RPC services via rpcbind v4 (EXPERIMENTAL)"
1778 depends on SUNRPC && EXPERIMENTAL
1779 default n
1780 help
1781 Sun added support for registering RPC services at an IPv6
1782 address by creating two new versions of the rpcbind protocol
1783 (RFC 1833).
1784
1785 This option enables support in the kernel RPC server for
1786 registering kernel RPC services via version 4 of the rpcbind
1787 protocol. If you enable this option, you must run a portmapper
1788 daemon that supports rpcbind protocol version 4.
1789
1790 Serving NFS over IPv6 from knfsd (the kernel's NFS server)
1791 requires that you enable this option and use a portmapper that
1792 supports rpcbind version 4.
1793
1794 If unsure, say N to get traditional behavior (register kernel
1795 RPC services using only rpcbind version 2). Distributions
1796 using the legacy Linux portmapper daemon must say N here.
1797
1776config RPCSEC_GSS_KRB5 1798config RPCSEC_GSS_KRB5
1777 tristate "Secure RPC: Kerberos V mechanism (EXPERIMENTAL)" 1799 tristate "Secure RPC: Kerberos V mechanism (EXPERIMENTAL)"
1778 depends on SUNRPC && EXPERIMENTAL 1800 depends on SUNRPC && EXPERIMENTAL
diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h
index 23143f38b121..54a79e1ad634 100644
--- a/include/linux/sunrpc/svc.h
+++ b/include/linux/sunrpc/svc.h
@@ -393,7 +393,9 @@ struct svc_serv * svc_create_pooled(struct svc_program *, unsigned int,
393int svc_set_num_threads(struct svc_serv *, struct svc_pool *, int); 393int svc_set_num_threads(struct svc_serv *, struct svc_pool *, int);
394void svc_destroy(struct svc_serv *); 394void svc_destroy(struct svc_serv *);
395int svc_process(struct svc_rqst *); 395int svc_process(struct svc_rqst *);
396int svc_register(struct svc_serv *, int, unsigned short); 396int svc_register(const struct svc_serv *, const unsigned short,
397 const unsigned short);
398
397void svc_wake_up(struct svc_serv *); 399void svc_wake_up(struct svc_serv *);
398void svc_reserve(struct svc_rqst *rqstp, int space); 400void svc_reserve(struct svc_rqst *rqstp, int space);
399struct svc_pool * svc_pool_for_cpu(struct svc_serv *serv, int cpu); 401struct svc_pool * svc_pool_for_cpu(struct svc_serv *serv, int cpu);
diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c
index 9eb78a771da5..c43ccb628052 100644
--- a/net/sunrpc/svc.c
+++ b/net/sunrpc/svc.c
@@ -719,13 +719,92 @@ svc_exit_thread(struct svc_rqst *rqstp)
719} 719}
720EXPORT_SYMBOL(svc_exit_thread); 720EXPORT_SYMBOL(svc_exit_thread);
721 721
722#ifdef CONFIG_SUNRPC_REGISTER_V4
722/* 723/*
723 * Register an RPC service with the local portmapper. 724 * Registering kernel RPC services with rpcbind version 2 will work
724 * To unregister a service, call this routine with 725 * over either IPv4 or IPv6, since the Linux kernel always registers
725 * proto and port == 0. 726 * services for the "any" address.
727 *
728 * However, the local rpcbind daemon listens on either only AF_INET
729 * or AF_INET6 (never both). When it listens on AF_INET6, an rpcbind
730 * version 2 registration will result in registering the service at
731 * IN6ADDR_ANY, even if the RPC service being registered is not
732 * IPv6-enabled.
733 *
734 * Rpcbind version 4 allows us to be a little more specific. Kernel
735 * RPC services that don't yet support AF_INET6 can register
736 * themselves as IPv4-only with the local rpcbind daemon, even if the
737 * daemon is listening only on AF_INET6.
738 *
739 * And, registering IPv6-enabled kernel RPC services via AF_INET6
740 * verifies that the local user space rpcbind daemon is properly
741 * configured to support remote AF_INET6 rpcbind requests.
742 *
743 * An AF_INET6 registration request will fail if the local rpcbind
744 * daemon is not set up to listen on AF_INET6. Likewise, we fail
745 * AF_INET6 registration requests if svc_register() is configured to
746 * support only rpcbind version 2.
726 */ 747 */
727int 748static int __svc_register(const u32 program, const u32 version,
728svc_register(struct svc_serv *serv, int proto, unsigned short port) 749 const sa_family_t family,
750 const unsigned short protocol,
751 const unsigned short port)
752{
753 struct sockaddr_in sin = {
754 .sin_family = AF_INET,
755 .sin_addr.s_addr = htonl(INADDR_ANY),
756 .sin_port = htons(port),
757 };
758 struct sockaddr_in6 sin6 = {
759 .sin6_family = AF_INET6,
760 .sin6_addr = IN6ADDR_ANY_INIT,
761 .sin6_port = htons(port),
762 };
763 struct sockaddr *sap;
764 char *netid;
765
766 switch (family) {
767 case AF_INET:
768 sap = (struct sockaddr *)&sin;
769 netid = RPCBIND_NETID_TCP;
770 if (protocol == IPPROTO_UDP)
771 netid = RPCBIND_NETID_UDP;
772 break;
773 case AF_INET6:
774 sap = (struct sockaddr *)&sin6;
775 netid = RPCBIND_NETID_TCP6;
776 if (protocol == IPPROTO_UDP)
777 netid = RPCBIND_NETID_UDP6;
778 break;
779 default:
780 return -EAFNOSUPPORT;
781 }
782
783 return rpcb_v4_register(program, version, sap, netid);
784}
785#else
786static int __svc_register(const u32 program, const u32 version,
787 sa_family_t family,
788 const unsigned short protocol,
789 const unsigned short port)
790{
791 if (family != AF_INET)
792 return -EAFNOSUPPORT;
793
794 return rpcb_register(program, version, protocol, port);
795}
796#endif
797
798/**
799 * svc_register - register an RPC service with the local portmapper
800 * @serv: svc_serv struct for the service to register
801 * @proto: transport protocol number to advertise
802 * @port: port to advertise
803 *
804 * Service is registered for any address in serv's address family
805 */
806int svc_register(const struct svc_serv *serv, const unsigned short proto,
807 const unsigned short port)
729{ 808{
730 struct svc_program *progp; 809 struct svc_program *progp;
731 unsigned int i; 810 unsigned int i;
@@ -738,8 +817,9 @@ svc_register(struct svc_serv *serv, int proto, unsigned short port)
738 if (progp->pg_vers[i] == NULL) 817 if (progp->pg_vers[i] == NULL)
739 continue; 818 continue;
740 819
741 dprintk("svc: svc_register(%s, %s, %d, %d)%s\n", 820 dprintk("svc: svc_register(%s, %u, %s, %u, %d)%s\n",
742 progp->pg_name, 821 progp->pg_name,
822 serv->sv_family,
743 proto == IPPROTO_UDP? "udp" : "tcp", 823 proto == IPPROTO_UDP? "udp" : "tcp",
744 port, 824 port,
745 i, 825 i,
@@ -749,7 +829,8 @@ svc_register(struct svc_serv *serv, int proto, unsigned short port)
749 if (progp->pg_vers[i]->vs_hidden) 829 if (progp->pg_vers[i]->vs_hidden)
750 continue; 830 continue;
751 831
752 error = rpcb_register(progp->pg_prog, i, proto, port); 832 error = __svc_register(progp->pg_prog, i,
833 serv->sv_family, proto, port);
753 if (error < 0) 834 if (error < 0)
754 break; 835 break;
755 } 836 }