diff options
author | Chuck Lever <chuck.lever@oracle.com> | 2007-02-12 03:53:38 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-02-12 12:48:36 -0500 |
commit | 95756482c9bfa375418c5a32455494a3042f65cd (patch) | |
tree | 1c7583a43df17591cae77af601143509ab68c2b1 | |
parent | cdd88b9f3ed5013de0f1085e0e2f9123c798609d (diff) |
[PATCH] knfsd: SUNRPC: support IPv6 addresses in RPC server's UDP receive path
Add support for IPv6 addresses in the RPC server's UDP receive path.
[akpm@linux-foundation.org: cleanups]
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Cc: Aurelien Charbon <aurelien.charbon@ext.bull.net>
Signed-off-by: Neil Brown <neilb@suse.de>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r-- | include/linux/sunrpc/svc.h | 5 | ||||
-rw-r--r-- | net/sunrpc/svcsock.c | 53 |
2 files changed, 48 insertions, 10 deletions
diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h index 6d6892fa1d40..83b3c7b433aa 100644 --- a/include/linux/sunrpc/svc.h +++ b/include/linux/sunrpc/svc.h | |||
@@ -270,6 +270,11 @@ static inline struct sockaddr_in *svc_addr_in(struct svc_rqst *rqst) | |||
270 | return (struct sockaddr_in *) &rqst->rq_addr; | 270 | return (struct sockaddr_in *) &rqst->rq_addr; |
271 | } | 271 | } |
272 | 272 | ||
273 | static inline struct sockaddr_in6 *svc_addr_in6(struct svc_rqst *rqst) | ||
274 | { | ||
275 | return (struct sockaddr_in6 *) &rqst->rq_addr; | ||
276 | } | ||
277 | |||
273 | static inline struct sockaddr *svc_addr(struct svc_rqst *rqst) | 278 | static inline struct sockaddr *svc_addr(struct svc_rqst *rqst) |
274 | { | 279 | { |
275 | return (struct sockaddr *) &rqst->rq_addr; | 280 | return (struct sockaddr *) &rqst->rq_addr; |
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c index 72831b8a58fb..6f509b9cae2c 100644 --- a/net/sunrpc/svcsock.c +++ b/net/sunrpc/svcsock.c | |||
@@ -721,13 +721,53 @@ svc_write_space(struct sock *sk) | |||
721 | } | 721 | } |
722 | } | 722 | } |
723 | 723 | ||
724 | static void svc_udp_get_sender_address(struct svc_rqst *rqstp, | ||
725 | struct sk_buff *skb) | ||
726 | { | ||
727 | switch (rqstp->rq_sock->sk_sk->sk_family) { | ||
728 | case AF_INET: { | ||
729 | /* this seems to come from net/ipv4/udp.c:udp_recvmsg */ | ||
730 | struct sockaddr_in *sin = svc_addr_in(rqstp); | ||
731 | |||
732 | sin->sin_family = AF_INET; | ||
733 | sin->sin_port = skb->h.uh->source; | ||
734 | sin->sin_addr.s_addr = skb->nh.iph->saddr; | ||
735 | rqstp->rq_addrlen = sizeof(struct sockaddr_in); | ||
736 | /* Remember which interface received this request */ | ||
737 | rqstp->rq_daddr.addr.s_addr = skb->nh.iph->daddr; | ||
738 | } | ||
739 | break; | ||
740 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
741 | case AF_INET6: { | ||
742 | /* this is derived from net/ipv6/udp.c:udpv6_recvmesg */ | ||
743 | struct sockaddr_in6 *sin6 = svc_addr_in6(rqstp); | ||
744 | |||
745 | sin6->sin6_family = AF_INET6; | ||
746 | sin6->sin6_port = skb->h.uh->source; | ||
747 | sin6->sin6_flowinfo = 0; | ||
748 | sin6->sin6_scope_id = 0; | ||
749 | if (ipv6_addr_type(&sin6->sin6_addr) & | ||
750 | IPV6_ADDR_LINKLOCAL) | ||
751 | sin6->sin6_scope_id = IP6CB(skb)->iif; | ||
752 | ipv6_addr_copy(&sin6->sin6_addr, | ||
753 | &skb->nh.ipv6h->saddr); | ||
754 | rqstp->rq_addrlen = sizeof(struct sockaddr_in); | ||
755 | /* Remember which interface received this request */ | ||
756 | ipv6_addr_copy(&rqstp->rq_daddr.addr6, | ||
757 | &skb->nh.ipv6h->saddr); | ||
758 | } | ||
759 | break; | ||
760 | #endif | ||
761 | } | ||
762 | return; | ||
763 | } | ||
764 | |||
724 | /* | 765 | /* |
725 | * Receive a datagram from a UDP socket. | 766 | * Receive a datagram from a UDP socket. |
726 | */ | 767 | */ |
727 | static int | 768 | static int |
728 | svc_udp_recvfrom(struct svc_rqst *rqstp) | 769 | svc_udp_recvfrom(struct svc_rqst *rqstp) |
729 | { | 770 | { |
730 | struct sockaddr_in *sin = svc_addr_in(rqstp); | ||
731 | struct svc_sock *svsk = rqstp->rq_sock; | 771 | struct svc_sock *svsk = rqstp->rq_sock; |
732 | struct svc_serv *serv = svsk->sk_server; | 772 | struct svc_serv *serv = svsk->sk_server; |
733 | struct sk_buff *skb; | 773 | struct sk_buff *skb; |
@@ -785,16 +825,9 @@ svc_udp_recvfrom(struct svc_rqst *rqstp) | |||
785 | len = skb->len - sizeof(struct udphdr); | 825 | len = skb->len - sizeof(struct udphdr); |
786 | rqstp->rq_arg.len = len; | 826 | rqstp->rq_arg.len = len; |
787 | 827 | ||
788 | rqstp->rq_prot = IPPROTO_UDP; | 828 | rqstp->rq_prot = IPPROTO_UDP; |
789 | |||
790 | /* Get sender address */ | ||
791 | sin->sin_family = AF_INET; | ||
792 | sin->sin_port = skb->h.uh->source; | ||
793 | sin->sin_addr.s_addr = skb->nh.iph->saddr; | ||
794 | rqstp->rq_addrlen = sizeof(struct sockaddr_in); | ||
795 | 829 | ||
796 | /* Remember which interface received this request */ | 830 | svc_udp_get_sender_address(rqstp, skb); |
797 | rqstp->rq_daddr.addr.s_addr = skb->nh.iph->daddr; | ||
798 | 831 | ||
799 | if (skb_is_nonlinear(skb)) { | 832 | if (skb_is_nonlinear(skb)) { |
800 | /* we have to copy */ | 833 | /* we have to copy */ |