diff options
Diffstat (limited to 'net/ipv6/udp.c')
| -rw-r--r-- | net/ipv6/udp.c | 65 |
1 files changed, 37 insertions, 28 deletions
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 83f4c77c79d8..28c4aa5078fc 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c | |||
| @@ -752,6 +752,28 @@ static void udp6_sk_rx_dst_set(struct sock *sk, struct dst_entry *dst) | |||
| 752 | } | 752 | } |
| 753 | } | 753 | } |
| 754 | 754 | ||
| 755 | /* wrapper for udp_queue_rcv_skb tacking care of csum conversion and | ||
| 756 | * return code conversion for ip layer consumption | ||
| 757 | */ | ||
| 758 | static int udp6_unicast_rcv_skb(struct sock *sk, struct sk_buff *skb, | ||
| 759 | struct udphdr *uh) | ||
| 760 | { | ||
| 761 | int ret; | ||
| 762 | |||
| 763 | if (inet_get_convert_csum(sk) && uh->check && !IS_UDPLITE(sk)) | ||
| 764 | skb_checksum_try_convert(skb, IPPROTO_UDP, uh->check, | ||
| 765 | ip6_compute_pseudo); | ||
| 766 | |||
| 767 | ret = udpv6_queue_rcv_skb(sk, skb); | ||
| 768 | |||
| 769 | /* a return value > 0 means to resubmit the input, but | ||
| 770 | * it wants the return to be -protocol, or 0 | ||
| 771 | */ | ||
| 772 | if (ret > 0) | ||
| 773 | return -ret; | ||
| 774 | return 0; | ||
| 775 | } | ||
| 776 | |||
| 755 | int __udp6_lib_rcv(struct sk_buff *skb, struct udp_table *udptable, | 777 | int __udp6_lib_rcv(struct sk_buff *skb, struct udp_table *udptable, |
| 756 | int proto) | 778 | int proto) |
| 757 | { | 779 | { |
| @@ -803,13 +825,14 @@ int __udp6_lib_rcv(struct sk_buff *skb, struct udp_table *udptable, | |||
| 803 | if (unlikely(sk->sk_rx_dst != dst)) | 825 | if (unlikely(sk->sk_rx_dst != dst)) |
| 804 | udp6_sk_rx_dst_set(sk, dst); | 826 | udp6_sk_rx_dst_set(sk, dst); |
| 805 | 827 | ||
| 806 | ret = udpv6_queue_rcv_skb(sk, skb); | 828 | if (!uh->check && !udp_sk(sk)->no_check6_rx) { |
| 807 | sock_put(sk); | 829 | sock_put(sk); |
| 830 | goto report_csum_error; | ||
| 831 | } | ||
| 808 | 832 | ||
| 809 | /* a return value > 0 means to resubmit the input */ | 833 | ret = udp6_unicast_rcv_skb(sk, skb, uh); |
| 810 | if (ret > 0) | 834 | sock_put(sk); |
| 811 | return ret; | 835 | return ret; |
| 812 | return 0; | ||
| 813 | } | 836 | } |
| 814 | 837 | ||
| 815 | /* | 838 | /* |
| @@ -822,30 +845,13 @@ int __udp6_lib_rcv(struct sk_buff *skb, struct udp_table *udptable, | |||
| 822 | /* Unicast */ | 845 | /* Unicast */ |
| 823 | sk = __udp6_lib_lookup_skb(skb, uh->source, uh->dest, udptable); | 846 | sk = __udp6_lib_lookup_skb(skb, uh->source, uh->dest, udptable); |
| 824 | if (sk) { | 847 | if (sk) { |
| 825 | int ret; | 848 | if (!uh->check && !udp_sk(sk)->no_check6_rx) |
| 826 | 849 | goto report_csum_error; | |
| 827 | if (!uh->check && !udp_sk(sk)->no_check6_rx) { | 850 | return udp6_unicast_rcv_skb(sk, skb, uh); |
| 828 | udp6_csum_zero_error(skb); | ||
| 829 | goto csum_error; | ||
| 830 | } | ||
| 831 | |||
| 832 | if (inet_get_convert_csum(sk) && uh->check && !IS_UDPLITE(sk)) | ||
| 833 | skb_checksum_try_convert(skb, IPPROTO_UDP, uh->check, | ||
| 834 | ip6_compute_pseudo); | ||
| 835 | |||
| 836 | ret = udpv6_queue_rcv_skb(sk, skb); | ||
| 837 | |||
| 838 | /* a return value > 0 means to resubmit the input */ | ||
| 839 | if (ret > 0) | ||
| 840 | return ret; | ||
| 841 | |||
| 842 | return 0; | ||
| 843 | } | 851 | } |
| 844 | 852 | ||
| 845 | if (!uh->check) { | 853 | if (!uh->check) |
| 846 | udp6_csum_zero_error(skb); | 854 | goto report_csum_error; |
| 847 | goto csum_error; | ||
| 848 | } | ||
| 849 | 855 | ||
| 850 | if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) | 856 | if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) |
| 851 | goto discard; | 857 | goto discard; |
| @@ -866,6 +872,9 @@ short_packet: | |||
| 866 | ulen, skb->len, | 872 | ulen, skb->len, |
| 867 | daddr, ntohs(uh->dest)); | 873 | daddr, ntohs(uh->dest)); |
| 868 | goto discard; | 874 | goto discard; |
| 875 | |||
| 876 | report_csum_error: | ||
| 877 | udp6_csum_zero_error(skb); | ||
| 869 | csum_error: | 878 | csum_error: |
| 870 | __UDP6_INC_STATS(net, UDP_MIB_CSUMERRORS, proto == IPPROTO_UDPLITE); | 879 | __UDP6_INC_STATS(net, UDP_MIB_CSUMERRORS, proto == IPPROTO_UDPLITE); |
| 871 | discard: | 880 | discard: |
