diff options
Diffstat (limited to 'net/sunrpc/svcsock.c')
-rw-r--r-- | net/sunrpc/svcsock.c | 53 |
1 files changed, 43 insertions, 10 deletions
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 */ |