aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChuck Lever <chuck.lever@oracle.com>2007-02-12 03:53:38 -0500
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-02-12 12:48:36 -0500
commit95756482c9bfa375418c5a32455494a3042f65cd (patch)
tree1c7583a43df17591cae77af601143509ab68c2b1
parentcdd88b9f3ed5013de0f1085e0e2f9123c798609d (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.h5
-rw-r--r--net/sunrpc/svcsock.c53
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
273static inline struct sockaddr_in6 *svc_addr_in6(struct svc_rqst *rqst)
274{
275 return (struct sockaddr_in6 *) &rqst->rq_addr;
276}
277
273static inline struct sockaddr *svc_addr(struct svc_rqst *rqst) 278static 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
724static 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 */
727static int 768static int
728svc_udp_recvfrom(struct svc_rqst *rqstp) 769svc_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 */