aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/udp.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6/udp.c')
-rw-r--r--net/ipv6/udp.c65
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 */
758static 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
755int __udp6_lib_rcv(struct sk_buff *skb, struct udp_table *udptable, 777int __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
876report_csum_error:
877 udp6_csum_zero_error(skb);
869csum_error: 878csum_error:
870 __UDP6_INC_STATS(net, UDP_MIB_CSUMERRORS, proto == IPPROTO_UDPLITE); 879 __UDP6_INC_STATS(net, UDP_MIB_CSUMERRORS, proto == IPPROTO_UDPLITE);
871discard: 880discard: