aboutsummaryrefslogtreecommitdiffstats
path: root/net/sunrpc/svcsock.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/sunrpc/svcsock.c')
-rw-r--r--net/sunrpc/svcsock.c53
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
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 */