aboutsummaryrefslogtreecommitdiffstats
path: root/net/sunrpc/svc.c
diff options
context:
space:
mode:
authorChuck Lever <chuck.lever@oracle.com>2008-09-15 17:27:23 -0400
committerJ. Bruce Fields <bfields@citi.umich.edu>2008-09-29 18:13:39 -0400
commit2c7eb0b206b8408d92c518033a359f4374c75314 (patch)
treefb3e01b4ede433ec53856574ef683fe54583f2df /net/sunrpc/svc.c
parente018040a824ab48211a1fcb86acebc9fc84759b0 (diff)
SUNRPC: Register both netids for AF_INET6 servers
TI-RPC is a user-space library of RPC functions that replaces ONC RPC and allows RPC to operate in the new world of IPv6. TI-RPC combines the concept of a transport protocol (UDP and TCP) and a protocol family (PF_INET and PF_INET6) into a single identifier called a "netid." For example, "udp" means UDP over IPv4, and "udp6" means UDP over IPv6. For rpcbind, then, the RPC service tuple that is registered and advertised is: [RPC program, RPC version, service address and port, netid] instead of [RPC program, RPC version, port, protocol] Service address is typically ANYADDR, but can be a specific address of one of the interfaces on a multi-homed host. The third item in the new tuple is expressed as a universal address. The current Linux rpcbind implementation registers a netid for both protocol families when RPCB_SET is done for just the PF_INET6 version of the netid (ie udp6 or tcp6). So registering "udp6" causes a registration for "udp" to appear automatically as well. We've recently determined that this is incorrect behavior. In the TI-RPC world, "udp6" is not meant to imply that the registered RPC service handles requests from AF_INET as well, even if the listener socket does address mapping. "udp" and "udp6" are entirely separate capabilities, and must be registered separately. The Linux kernel, unlike TI-RPC, leverages address mapping to allow a single listener socket to handle requests for both AF_INET and AF_INET6. This is still OK, but the kernel currently assumes registering "udp6" will cover "udp" as well. It registers only "udp6" for it's AF_INET6 services, even though they handle both AF_INET and AF_INET6 on the same port. So svc_register() actually needs to register both "udp" and "udp6" explicitly (and likewise for TCP). Until rpcbind is fixed, the kernel can ignore the return code for the second RPCB_SET call. Please merge this with commit 15231312: SUNRPC: Support IPv6 when registering kernel RPC services Signed-off-by: Chuck Lever <chuck.lever@oracle.com> Cc: Olaf Kirch <okir@suse.de> Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
Diffstat (limited to 'net/sunrpc/svc.c')
-rw-r--r--net/sunrpc/svc.c143
1 files changed, 100 insertions, 43 deletions
diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c
index c43ccb628052..b8d2fcd0f715 100644
--- a/net/sunrpc/svc.c
+++ b/net/sunrpc/svc.c
@@ -720,69 +720,125 @@ svc_exit_thread(struct svc_rqst *rqstp)
720EXPORT_SYMBOL(svc_exit_thread); 720EXPORT_SYMBOL(svc_exit_thread);
721 721
722#ifdef CONFIG_SUNRPC_REGISTER_V4 722#ifdef CONFIG_SUNRPC_REGISTER_V4
723
723/* 724/*
724 * Registering kernel RPC services with rpcbind version 2 will work 725 * Register an "inet" protocol family netid with the local
725 * over either IPv4 or IPv6, since the Linux kernel always registers 726 * rpcbind daemon via an rpcbind v4 SET request.
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 * 727 *
734 * Rpcbind version 4 allows us to be a little more specific. Kernel 728 * No netconfig infrastructure is available in the kernel, so
735 * RPC services that don't yet support AF_INET6 can register 729 * we map IP_ protocol numbers to netids by hand.
736 * themselves as IPv4-only with the local rpcbind daemon, even if the
737 * daemon is listening only on AF_INET6.
738 * 730 *
739 * And, registering IPv6-enabled kernel RPC services via AF_INET6 731 * Returns zero on success; a negative errno value is returned
740 * verifies that the local user space rpcbind daemon is properly 732 * if any error occurs.
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.
747 */ 733 */
748static int __svc_register(const u32 program, const u32 version, 734static int __svc_rpcb_register4(const u32 program, const u32 version,
749 const sa_family_t family, 735 const unsigned short protocol,
750 const unsigned short protocol, 736 const unsigned short port)
751 const unsigned short port)
752{ 737{
753 struct sockaddr_in sin = { 738 struct sockaddr_in sin = {
754 .sin_family = AF_INET, 739 .sin_family = AF_INET,
755 .sin_addr.s_addr = htonl(INADDR_ANY), 740 .sin_addr.s_addr = htonl(INADDR_ANY),
756 .sin_port = htons(port), 741 .sin_port = htons(port),
757 }; 742 };
743 char *netid;
744
745 switch (protocol) {
746 case IPPROTO_UDP:
747 netid = RPCBIND_NETID_UDP;
748 break;
749 case IPPROTO_TCP:
750 netid = RPCBIND_NETID_TCP;
751 break;
752 default:
753 return -EPROTONOSUPPORT;
754 }
755
756 return rpcb_v4_register(program, version,
757 (struct sockaddr *)&sin, netid);
758}
759
760/*
761 * Register an "inet6" protocol family netid with the local
762 * rpcbind daemon via an rpcbind v4 SET request.
763 *
764 * No netconfig infrastructure is available in the kernel, so
765 * we map IP_ protocol numbers to netids by hand.
766 *
767 * Returns zero on success; a negative errno value is returned
768 * if any error occurs.
769 */
770static int __svc_rpcb_register6(const u32 program, const u32 version,
771 const unsigned short protocol,
772 const unsigned short port)
773{
758 struct sockaddr_in6 sin6 = { 774 struct sockaddr_in6 sin6 = {
759 .sin6_family = AF_INET6, 775 .sin6_family = AF_INET6,
760 .sin6_addr = IN6ADDR_ANY_INIT, 776 .sin6_addr = IN6ADDR_ANY_INIT,
761 .sin6_port = htons(port), 777 .sin6_port = htons(port),
762 }; 778 };
763 struct sockaddr *sap;
764 char *netid; 779 char *netid;
765 780
766 switch (family) { 781 switch (protocol) {
767 case AF_INET: 782 case IPPROTO_UDP:
768 sap = (struct sockaddr *)&sin; 783 netid = RPCBIND_NETID_UDP6;
769 netid = RPCBIND_NETID_TCP;
770 if (protocol == IPPROTO_UDP)
771 netid = RPCBIND_NETID_UDP;
772 break; 784 break;
773 case AF_INET6: 785 case IPPROTO_TCP:
774 sap = (struct sockaddr *)&sin6;
775 netid = RPCBIND_NETID_TCP6; 786 netid = RPCBIND_NETID_TCP6;
776 if (protocol == IPPROTO_UDP)
777 netid = RPCBIND_NETID_UDP6;
778 break; 787 break;
779 default: 788 default:
780 return -EAFNOSUPPORT; 789 return -EPROTONOSUPPORT;
790 }
791
792 return rpcb_v4_register(program, version,
793 (struct sockaddr *)&sin6, netid);
794}
795
796/*
797 * Register a kernel RPC service via rpcbind version 4.
798 *
799 * Returns zero on success; a negative errno value is returned
800 * if any error occurs.
801 */
802static int __svc_register(const u32 program, const u32 version,
803 const sa_family_t family,
804 const unsigned short protocol,
805 const unsigned short port)
806{
807 int error;
808
809 switch (family) {
810 case AF_INET:
811 return __svc_rpcb_register4(program, version,
812 protocol, port);
813 case AF_INET6:
814 error = __svc_rpcb_register6(program, version,
815 protocol, port);
816 if (error < 0)
817 return error;
818
819 /*
820 * Work around bug in some versions of Linux rpcbind
821 * which don't allow registration of both inet and
822 * inet6 netids.
823 *
824 * Error return ignored for now.
825 */
826 __svc_rpcb_register4(program, version,
827 protocol, port);
828 return 0;
781 } 829 }
782 830
783 return rpcb_v4_register(program, version, sap, netid); 831 return -EAFNOSUPPORT;
784} 832}
785#else 833
834#else /* CONFIG_SUNRPC_REGISTER_V4 */
835
836/*
837 * Register a kernel RPC service via rpcbind version 2.
838 *
839 * Returns zero on success; a negative errno value is returned
840 * if any error occurs.
841 */
786static int __svc_register(const u32 program, const u32 version, 842static int __svc_register(const u32 program, const u32 version,
787 sa_family_t family, 843 sa_family_t family,
788 const unsigned short protocol, 844 const unsigned short protocol,
@@ -793,7 +849,8 @@ static int __svc_register(const u32 program, const u32 version,
793 849
794 return rpcb_register(program, version, protocol, port); 850 return rpcb_register(program, version, protocol, port);
795} 851}
796#endif 852
853#endif /* CONFIG_SUNRPC_REGISTER_V4 */
797 854
798/** 855/**
799 * svc_register - register an RPC service with the local portmapper 856 * svc_register - register an RPC service with the local portmapper
@@ -817,12 +874,12 @@ int svc_register(const struct svc_serv *serv, const unsigned short proto,
817 if (progp->pg_vers[i] == NULL) 874 if (progp->pg_vers[i] == NULL)
818 continue; 875 continue;
819 876
820 dprintk("svc: svc_register(%s, %u, %s, %u, %d)%s\n", 877 dprintk("svc: svc_register(%sv%d, %s, %u, %u)%s\n",
821 progp->pg_name, 878 progp->pg_name,
822 serv->sv_family, 879 i,
823 proto == IPPROTO_UDP? "udp" : "tcp", 880 proto == IPPROTO_UDP? "udp" : "tcp",
824 port, 881 port,
825 i, 882 serv->sv_family,
826 progp->pg_vers[i]->vs_hidden? 883 progp->pg_vers[i]->vs_hidden?
827 " (but not telling portmap)" : ""); 884 " (but not telling portmap)" : "");
828 885