diff options
Diffstat (limited to 'net/ipv6/udp.c')
-rw-r--r-- | net/ipv6/udp.c | 34 |
1 files changed, 22 insertions, 12 deletions
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index d8e5e852fc7a..d4defdd44937 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c | |||
@@ -450,15 +450,16 @@ try_again: | |||
450 | sin6->sin6_family = AF_INET6; | 450 | sin6->sin6_family = AF_INET6; |
451 | sin6->sin6_port = udp_hdr(skb)->source; | 451 | sin6->sin6_port = udp_hdr(skb)->source; |
452 | sin6->sin6_flowinfo = 0; | 452 | sin6->sin6_flowinfo = 0; |
453 | sin6->sin6_scope_id = 0; | ||
454 | 453 | ||
455 | if (is_udp4) | 454 | if (is_udp4) { |
456 | ipv6_addr_set_v4mapped(ip_hdr(skb)->saddr, | 455 | ipv6_addr_set_v4mapped(ip_hdr(skb)->saddr, |
457 | &sin6->sin6_addr); | 456 | &sin6->sin6_addr); |
458 | else { | 457 | sin6->sin6_scope_id = 0; |
458 | } else { | ||
459 | sin6->sin6_addr = ipv6_hdr(skb)->saddr; | 459 | sin6->sin6_addr = ipv6_hdr(skb)->saddr; |
460 | if (ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_LINKLOCAL) | 460 | sin6->sin6_scope_id = |
461 | sin6->sin6_scope_id = IP6CB(skb)->iif; | 461 | ipv6_iface_scope_id(&sin6->sin6_addr, |
462 | IP6CB(skb)->iif); | ||
462 | } | 463 | } |
463 | 464 | ||
464 | } | 465 | } |
@@ -482,12 +483,17 @@ out: | |||
482 | csum_copy_err: | 483 | csum_copy_err: |
483 | slow = lock_sock_fast(sk); | 484 | slow = lock_sock_fast(sk); |
484 | if (!skb_kill_datagram(sk, skb, flags)) { | 485 | if (!skb_kill_datagram(sk, skb, flags)) { |
485 | if (is_udp4) | 486 | if (is_udp4) { |
487 | UDP_INC_STATS_USER(sock_net(sk), | ||
488 | UDP_MIB_CSUMERRORS, is_udplite); | ||
486 | UDP_INC_STATS_USER(sock_net(sk), | 489 | UDP_INC_STATS_USER(sock_net(sk), |
487 | UDP_MIB_INERRORS, is_udplite); | 490 | UDP_MIB_INERRORS, is_udplite); |
488 | else | 491 | } else { |
492 | UDP6_INC_STATS_USER(sock_net(sk), | ||
493 | UDP_MIB_CSUMERRORS, is_udplite); | ||
489 | UDP6_INC_STATS_USER(sock_net(sk), | 494 | UDP6_INC_STATS_USER(sock_net(sk), |
490 | UDP_MIB_INERRORS, is_udplite); | 495 | UDP_MIB_INERRORS, is_udplite); |
496 | } | ||
491 | } | 497 | } |
492 | unlock_sock_fast(sk, slow); | 498 | unlock_sock_fast(sk, slow); |
493 | 499 | ||
@@ -636,7 +642,7 @@ int udpv6_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) | |||
636 | 642 | ||
637 | if (rcu_access_pointer(sk->sk_filter)) { | 643 | if (rcu_access_pointer(sk->sk_filter)) { |
638 | if (udp_lib_checksum_complete(skb)) | 644 | if (udp_lib_checksum_complete(skb)) |
639 | goto drop; | 645 | goto csum_error; |
640 | } | 646 | } |
641 | 647 | ||
642 | if (sk_rcvqueues_full(sk, skb, sk->sk_rcvbuf)) | 648 | if (sk_rcvqueues_full(sk, skb, sk->sk_rcvbuf)) |
@@ -655,6 +661,8 @@ int udpv6_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) | |||
655 | bh_unlock_sock(sk); | 661 | bh_unlock_sock(sk); |
656 | 662 | ||
657 | return rc; | 663 | return rc; |
664 | csum_error: | ||
665 | UDP6_INC_STATS_BH(sock_net(sk), UDP_MIB_CSUMERRORS, is_udplite); | ||
658 | drop: | 666 | drop: |
659 | UDP6_INC_STATS_BH(sock_net(sk), UDP_MIB_INERRORS, is_udplite); | 667 | UDP6_INC_STATS_BH(sock_net(sk), UDP_MIB_INERRORS, is_udplite); |
660 | atomic_inc(&sk->sk_drops); | 668 | atomic_inc(&sk->sk_drops); |
@@ -816,7 +824,7 @@ int __udp6_lib_rcv(struct sk_buff *skb, struct udp_table *udptable, | |||
816 | } | 824 | } |
817 | 825 | ||
818 | if (udp6_csum_init(skb, uh, proto)) | 826 | if (udp6_csum_init(skb, uh, proto)) |
819 | goto discard; | 827 | goto csum_error; |
820 | 828 | ||
821 | /* | 829 | /* |
822 | * Multicast receive code | 830 | * Multicast receive code |
@@ -849,7 +857,7 @@ int __udp6_lib_rcv(struct sk_buff *skb, struct udp_table *udptable, | |||
849 | goto discard; | 857 | goto discard; |
850 | 858 | ||
851 | if (udp_lib_checksum_complete(skb)) | 859 | if (udp_lib_checksum_complete(skb)) |
852 | goto discard; | 860 | goto csum_error; |
853 | 861 | ||
854 | UDP6_INC_STATS_BH(net, UDP_MIB_NOPORTS, proto == IPPROTO_UDPLITE); | 862 | UDP6_INC_STATS_BH(net, UDP_MIB_NOPORTS, proto == IPPROTO_UDPLITE); |
855 | icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0); | 863 | icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0); |
@@ -866,7 +874,9 @@ short_packet: | |||
866 | skb->len, | 874 | skb->len, |
867 | daddr, | 875 | daddr, |
868 | ntohs(uh->dest)); | 876 | ntohs(uh->dest)); |
869 | 877 | goto discard; | |
878 | csum_error: | ||
879 | UDP6_INC_STATS_BH(net, UDP_MIB_CSUMERRORS, proto == IPPROTO_UDPLITE); | ||
870 | discard: | 880 | discard: |
871 | UDP6_INC_STATS_BH(net, UDP_MIB_INERRORS, proto == IPPROTO_UDPLITE); | 881 | UDP6_INC_STATS_BH(net, UDP_MIB_INERRORS, proto == IPPROTO_UDPLITE); |
872 | kfree_skb(skb); | 882 | kfree_skb(skb); |
@@ -1118,7 +1128,7 @@ do_udp_sendmsg: | |||
1118 | 1128 | ||
1119 | if (addr_len >= sizeof(struct sockaddr_in6) && | 1129 | if (addr_len >= sizeof(struct sockaddr_in6) && |
1120 | sin6->sin6_scope_id && | 1130 | sin6->sin6_scope_id && |
1121 | ipv6_addr_type(daddr)&IPV6_ADDR_LINKLOCAL) | 1131 | __ipv6_addr_needs_scope_id(__ipv6_addr_type(daddr))) |
1122 | fl6.flowi6_oif = sin6->sin6_scope_id; | 1132 | fl6.flowi6_oif = sin6->sin6_scope_id; |
1123 | } else { | 1133 | } else { |
1124 | if (sk->sk_state != TCP_ESTABLISHED) | 1134 | if (sk->sk_state != TCP_ESTABLISHED) |