aboutsummaryrefslogtreecommitdiffstats
path: root/net/sunrpc/svc.c
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 /net/sunrpc/svc.c
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>
Diffstat (limited to 'net/sunrpc/svc.c')
-rw-r--r--net/sunrpc/svc.c95
1 files changed, 88 insertions, 7 deletions
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 }