diff options
Diffstat (limited to 'net/ipv4/udp.c')
-rw-r--r-- | net/ipv4/udp.c | 135 |
1 files changed, 89 insertions, 46 deletions
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 4468e1adc094..185ed3e59802 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c | |||
@@ -246,7 +246,7 @@ int udp_lib_get_port(struct sock *sk, unsigned short snum, | |||
246 | do { | 246 | do { |
247 | if (low <= snum && snum <= high && | 247 | if (low <= snum && snum <= high && |
248 | !test_bit(snum >> udptable->log, bitmap) && | 248 | !test_bit(snum >> udptable->log, bitmap) && |
249 | !inet_is_reserved_local_port(snum)) | 249 | !inet_is_local_reserved_port(net, snum)) |
250 | goto found; | 250 | goto found; |
251 | snum += rand; | 251 | snum += rand; |
252 | } while (snum != first); | 252 | } while (snum != first); |
@@ -727,13 +727,12 @@ EXPORT_SYMBOL(udp_flush_pending_frames); | |||
727 | void udp4_hwcsum(struct sk_buff *skb, __be32 src, __be32 dst) | 727 | void udp4_hwcsum(struct sk_buff *skb, __be32 src, __be32 dst) |
728 | { | 728 | { |
729 | struct udphdr *uh = udp_hdr(skb); | 729 | struct udphdr *uh = udp_hdr(skb); |
730 | struct sk_buff *frags = skb_shinfo(skb)->frag_list; | ||
731 | int offset = skb_transport_offset(skb); | 730 | int offset = skb_transport_offset(skb); |
732 | int len = skb->len - offset; | 731 | int len = skb->len - offset; |
733 | int hlen = len; | 732 | int hlen = len; |
734 | __wsum csum = 0; | 733 | __wsum csum = 0; |
735 | 734 | ||
736 | if (!frags) { | 735 | if (!skb_has_frag_list(skb)) { |
737 | /* | 736 | /* |
738 | * Only one fragment on the socket. | 737 | * Only one fragment on the socket. |
739 | */ | 738 | */ |
@@ -742,15 +741,17 @@ void udp4_hwcsum(struct sk_buff *skb, __be32 src, __be32 dst) | |||
742 | uh->check = ~csum_tcpudp_magic(src, dst, len, | 741 | uh->check = ~csum_tcpudp_magic(src, dst, len, |
743 | IPPROTO_UDP, 0); | 742 | IPPROTO_UDP, 0); |
744 | } else { | 743 | } else { |
744 | struct sk_buff *frags; | ||
745 | |||
745 | /* | 746 | /* |
746 | * HW-checksum won't work as there are two or more | 747 | * HW-checksum won't work as there are two or more |
747 | * fragments on the socket so that all csums of sk_buffs | 748 | * fragments on the socket so that all csums of sk_buffs |
748 | * should be together | 749 | * should be together |
749 | */ | 750 | */ |
750 | do { | 751 | skb_walk_frags(skb, frags) { |
751 | csum = csum_add(csum, frags->csum); | 752 | csum = csum_add(csum, frags->csum); |
752 | hlen -= frags->len; | 753 | hlen -= frags->len; |
753 | } while ((frags = frags->next)); | 754 | } |
754 | 755 | ||
755 | csum = skb_checksum(skb, offset, hlen, csum); | 756 | csum = skb_checksum(skb, offset, hlen, csum); |
756 | skb->ip_summed = CHECKSUM_NONE; | 757 | skb->ip_summed = CHECKSUM_NONE; |
@@ -762,6 +763,43 @@ void udp4_hwcsum(struct sk_buff *skb, __be32 src, __be32 dst) | |||
762 | } | 763 | } |
763 | EXPORT_SYMBOL_GPL(udp4_hwcsum); | 764 | EXPORT_SYMBOL_GPL(udp4_hwcsum); |
764 | 765 | ||
766 | /* Function to set UDP checksum for an IPv4 UDP packet. This is intended | ||
767 | * for the simple case like when setting the checksum for a UDP tunnel. | ||
768 | */ | ||
769 | void udp_set_csum(bool nocheck, struct sk_buff *skb, | ||
770 | __be32 saddr, __be32 daddr, int len) | ||
771 | { | ||
772 | struct udphdr *uh = udp_hdr(skb); | ||
773 | |||
774 | if (nocheck) | ||
775 | uh->check = 0; | ||
776 | else if (skb_is_gso(skb)) | ||
777 | uh->check = ~udp_v4_check(len, saddr, daddr, 0); | ||
778 | else if (skb_dst(skb) && skb_dst(skb)->dev && | ||
779 | (skb_dst(skb)->dev->features & NETIF_F_V4_CSUM)) { | ||
780 | |||
781 | BUG_ON(skb->ip_summed == CHECKSUM_PARTIAL); | ||
782 | |||
783 | skb->ip_summed = CHECKSUM_PARTIAL; | ||
784 | skb->csum_start = skb_transport_header(skb) - skb->head; | ||
785 | skb->csum_offset = offsetof(struct udphdr, check); | ||
786 | uh->check = ~udp_v4_check(len, saddr, daddr, 0); | ||
787 | } else { | ||
788 | __wsum csum; | ||
789 | |||
790 | BUG_ON(skb->ip_summed == CHECKSUM_PARTIAL); | ||
791 | |||
792 | uh->check = 0; | ||
793 | csum = skb_checksum(skb, 0, len, 0); | ||
794 | uh->check = udp_v4_check(len, saddr, daddr, csum); | ||
795 | if (uh->check == 0) | ||
796 | uh->check = CSUM_MANGLED_0; | ||
797 | |||
798 | skb->ip_summed = CHECKSUM_UNNECESSARY; | ||
799 | } | ||
800 | } | ||
801 | EXPORT_SYMBOL(udp_set_csum); | ||
802 | |||
765 | static int udp_send_skb(struct sk_buff *skb, struct flowi4 *fl4) | 803 | static int udp_send_skb(struct sk_buff *skb, struct flowi4 *fl4) |
766 | { | 804 | { |
767 | struct sock *sk = skb->sk; | 805 | struct sock *sk = skb->sk; |
@@ -785,7 +823,7 @@ static int udp_send_skb(struct sk_buff *skb, struct flowi4 *fl4) | |||
785 | if (is_udplite) /* UDP-Lite */ | 823 | if (is_udplite) /* UDP-Lite */ |
786 | csum = udplite_csum(skb); | 824 | csum = udplite_csum(skb); |
787 | 825 | ||
788 | else if (sk->sk_no_check == UDP_CSUM_NOXMIT) { /* UDP csum disabled */ | 826 | else if (sk->sk_no_check_tx) { /* UDP csum disabled */ |
789 | 827 | ||
790 | skb->ip_summed = CHECKSUM_NONE; | 828 | skb->ip_summed = CHECKSUM_NONE; |
791 | goto send; | 829 | goto send; |
@@ -1495,6 +1533,10 @@ int udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) | |||
1495 | if (skb->len > sizeof(struct udphdr) && encap_rcv != NULL) { | 1533 | if (skb->len > sizeof(struct udphdr) && encap_rcv != NULL) { |
1496 | int ret; | 1534 | int ret; |
1497 | 1535 | ||
1536 | /* Verify checksum before giving to encap */ | ||
1537 | if (udp_lib_checksum_complete(skb)) | ||
1538 | goto csum_error; | ||
1539 | |||
1498 | ret = encap_rcv(sk, skb); | 1540 | ret = encap_rcv(sk, skb); |
1499 | if (ret <= 0) { | 1541 | if (ret <= 0) { |
1500 | UDP_INC_STATS_BH(sock_net(sk), | 1542 | UDP_INC_STATS_BH(sock_net(sk), |
@@ -1672,7 +1714,6 @@ static int __udp4_lib_mcast_deliver(struct net *net, struct sk_buff *skb, | |||
1672 | static inline int udp4_csum_init(struct sk_buff *skb, struct udphdr *uh, | 1714 | static inline int udp4_csum_init(struct sk_buff *skb, struct udphdr *uh, |
1673 | int proto) | 1715 | int proto) |
1674 | { | 1716 | { |
1675 | const struct iphdr *iph; | ||
1676 | int err; | 1717 | int err; |
1677 | 1718 | ||
1678 | UDP_SKB_CB(skb)->partial_cov = 0; | 1719 | UDP_SKB_CB(skb)->partial_cov = 0; |
@@ -1684,22 +1725,8 @@ static inline int udp4_csum_init(struct sk_buff *skb, struct udphdr *uh, | |||
1684 | return err; | 1725 | return err; |
1685 | } | 1726 | } |
1686 | 1727 | ||
1687 | iph = ip_hdr(skb); | 1728 | return skb_checksum_init_zero_check(skb, proto, uh->check, |
1688 | if (uh->check == 0) { | 1729 | inet_compute_pseudo); |
1689 | skb->ip_summed = CHECKSUM_UNNECESSARY; | ||
1690 | } else if (skb->ip_summed == CHECKSUM_COMPLETE) { | ||
1691 | if (!csum_tcpudp_magic(iph->saddr, iph->daddr, skb->len, | ||
1692 | proto, skb->csum)) | ||
1693 | skb->ip_summed = CHECKSUM_UNNECESSARY; | ||
1694 | } | ||
1695 | if (!skb_csum_unnecessary(skb)) | ||
1696 | skb->csum = csum_tcpudp_nofold(iph->saddr, iph->daddr, | ||
1697 | skb->len, proto, 0); | ||
1698 | /* Probably, we should checksum udp header (it should be in cache | ||
1699 | * in any case) and data in tiny packets (< rx copybreak). | ||
1700 | */ | ||
1701 | |||
1702 | return 0; | ||
1703 | } | 1730 | } |
1704 | 1731 | ||
1705 | /* | 1732 | /* |
@@ -1886,7 +1913,7 @@ static struct sock *__udp4_lib_demux_lookup(struct net *net, | |||
1886 | unsigned int hash2 = udp4_portaddr_hash(net, loc_addr, hnum); | 1913 | unsigned int hash2 = udp4_portaddr_hash(net, loc_addr, hnum); |
1887 | unsigned int slot2 = hash2 & udp_table.mask; | 1914 | unsigned int slot2 = hash2 & udp_table.mask; |
1888 | struct udp_hslot *hslot2 = &udp_table.hash2[slot2]; | 1915 | struct udp_hslot *hslot2 = &udp_table.hash2[slot2]; |
1889 | INET_ADDR_COOKIE(acookie, rmt_addr, loc_addr) | 1916 | INET_ADDR_COOKIE(acookie, rmt_addr, loc_addr); |
1890 | const __portpair ports = INET_COMBINED_PORTS(rmt_port, hnum); | 1917 | const __portpair ports = INET_COMBINED_PORTS(rmt_port, hnum); |
1891 | 1918 | ||
1892 | rcu_read_lock(); | 1919 | rcu_read_lock(); |
@@ -1979,7 +2006,7 @@ int udp_lib_setsockopt(struct sock *sk, int level, int optname, | |||
1979 | int (*push_pending_frames)(struct sock *)) | 2006 | int (*push_pending_frames)(struct sock *)) |
1980 | { | 2007 | { |
1981 | struct udp_sock *up = udp_sk(sk); | 2008 | struct udp_sock *up = udp_sk(sk); |
1982 | int val; | 2009 | int val, valbool; |
1983 | int err = 0; | 2010 | int err = 0; |
1984 | int is_udplite = IS_UDPLITE(sk); | 2011 | int is_udplite = IS_UDPLITE(sk); |
1985 | 2012 | ||
@@ -1989,6 +2016,8 @@ int udp_lib_setsockopt(struct sock *sk, int level, int optname, | |||
1989 | if (get_user(val, (int __user *)optval)) | 2016 | if (get_user(val, (int __user *)optval)) |
1990 | return -EFAULT; | 2017 | return -EFAULT; |
1991 | 2018 | ||
2019 | valbool = val ? 1 : 0; | ||
2020 | |||
1992 | switch (optname) { | 2021 | switch (optname) { |
1993 | case UDP_CORK: | 2022 | case UDP_CORK: |
1994 | if (val != 0) { | 2023 | if (val != 0) { |
@@ -2018,6 +2047,14 @@ int udp_lib_setsockopt(struct sock *sk, int level, int optname, | |||
2018 | } | 2047 | } |
2019 | break; | 2048 | break; |
2020 | 2049 | ||
2050 | case UDP_NO_CHECK6_TX: | ||
2051 | up->no_check6_tx = valbool; | ||
2052 | break; | ||
2053 | |||
2054 | case UDP_NO_CHECK6_RX: | ||
2055 | up->no_check6_rx = valbool; | ||
2056 | break; | ||
2057 | |||
2021 | /* | 2058 | /* |
2022 | * UDP-Lite's partial checksum coverage (RFC 3828). | 2059 | * UDP-Lite's partial checksum coverage (RFC 3828). |
2023 | */ | 2060 | */ |
@@ -2100,6 +2137,14 @@ int udp_lib_getsockopt(struct sock *sk, int level, int optname, | |||
2100 | val = up->encap_type; | 2137 | val = up->encap_type; |
2101 | break; | 2138 | break; |
2102 | 2139 | ||
2140 | case UDP_NO_CHECK6_TX: | ||
2141 | val = up->no_check6_tx; | ||
2142 | break; | ||
2143 | |||
2144 | case UDP_NO_CHECK6_RX: | ||
2145 | val = up->no_check6_rx; | ||
2146 | break; | ||
2147 | |||
2103 | /* The following two cannot be changed on UDP sockets, the return is | 2148 | /* The following two cannot be changed on UDP sockets, the return is |
2104 | * always 0 (which corresponds to the full checksum coverage of UDP). */ | 2149 | * always 0 (which corresponds to the full checksum coverage of UDP). */ |
2105 | case UDPLITE_SEND_CSCOV: | 2150 | case UDPLITE_SEND_CSCOV: |
@@ -2484,7 +2529,11 @@ struct sk_buff *skb_udp_tunnel_segment(struct sk_buff *skb, | |||
2484 | int tnl_hlen = skb_inner_mac_header(skb) - skb_transport_header(skb); | 2529 | int tnl_hlen = skb_inner_mac_header(skb) - skb_transport_header(skb); |
2485 | __be16 protocol = skb->protocol; | 2530 | __be16 protocol = skb->protocol; |
2486 | netdev_features_t enc_features; | 2531 | netdev_features_t enc_features; |
2487 | int outer_hlen; | 2532 | int udp_offset, outer_hlen; |
2533 | unsigned int oldlen; | ||
2534 | bool need_csum; | ||
2535 | |||
2536 | oldlen = (u16)~skb->len; | ||
2488 | 2537 | ||
2489 | if (unlikely(!pskb_may_pull(skb, tnl_hlen))) | 2538 | if (unlikely(!pskb_may_pull(skb, tnl_hlen))) |
2490 | goto out; | 2539 | goto out; |
@@ -2496,6 +2545,10 @@ struct sk_buff *skb_udp_tunnel_segment(struct sk_buff *skb, | |||
2496 | skb->mac_len = skb_inner_network_offset(skb); | 2545 | skb->mac_len = skb_inner_network_offset(skb); |
2497 | skb->protocol = htons(ETH_P_TEB); | 2546 | skb->protocol = htons(ETH_P_TEB); |
2498 | 2547 | ||
2548 | need_csum = !!(skb_shinfo(skb)->gso_type & SKB_GSO_UDP_TUNNEL_CSUM); | ||
2549 | if (need_csum) | ||
2550 | skb->encap_hdr_csum = 1; | ||
2551 | |||
2499 | /* segment inner packet. */ | 2552 | /* segment inner packet. */ |
2500 | enc_features = skb->dev->hw_enc_features & netif_skb_features(skb); | 2553 | enc_features = skb->dev->hw_enc_features & netif_skb_features(skb); |
2501 | segs = skb_mac_gso_segment(skb, enc_features); | 2554 | segs = skb_mac_gso_segment(skb, enc_features); |
@@ -2506,10 +2559,11 @@ struct sk_buff *skb_udp_tunnel_segment(struct sk_buff *skb, | |||
2506 | } | 2559 | } |
2507 | 2560 | ||
2508 | outer_hlen = skb_tnl_header_len(skb); | 2561 | outer_hlen = skb_tnl_header_len(skb); |
2562 | udp_offset = outer_hlen - tnl_hlen; | ||
2509 | skb = segs; | 2563 | skb = segs; |
2510 | do { | 2564 | do { |
2511 | struct udphdr *uh; | 2565 | struct udphdr *uh; |
2512 | int udp_offset = outer_hlen - tnl_hlen; | 2566 | int len; |
2513 | 2567 | ||
2514 | skb_reset_inner_headers(skb); | 2568 | skb_reset_inner_headers(skb); |
2515 | skb->encapsulation = 1; | 2569 | skb->encapsulation = 1; |
@@ -2520,31 +2574,20 @@ struct sk_buff *skb_udp_tunnel_segment(struct sk_buff *skb, | |||
2520 | skb_reset_mac_header(skb); | 2574 | skb_reset_mac_header(skb); |
2521 | skb_set_network_header(skb, mac_len); | 2575 | skb_set_network_header(skb, mac_len); |
2522 | skb_set_transport_header(skb, udp_offset); | 2576 | skb_set_transport_header(skb, udp_offset); |
2577 | len = skb->len - udp_offset; | ||
2523 | uh = udp_hdr(skb); | 2578 | uh = udp_hdr(skb); |
2524 | uh->len = htons(skb->len - udp_offset); | 2579 | uh->len = htons(len); |
2525 | |||
2526 | /* csum segment if tunnel sets skb with csum. */ | ||
2527 | if (protocol == htons(ETH_P_IP) && unlikely(uh->check)) { | ||
2528 | struct iphdr *iph = ip_hdr(skb); | ||
2529 | 2580 | ||
2530 | uh->check = ~csum_tcpudp_magic(iph->saddr, iph->daddr, | 2581 | if (need_csum) { |
2531 | skb->len - udp_offset, | 2582 | __be32 delta = htonl(oldlen + len); |
2532 | IPPROTO_UDP, 0); | ||
2533 | uh->check = csum_fold(skb_checksum(skb, udp_offset, | ||
2534 | skb->len - udp_offset, 0)); | ||
2535 | if (uh->check == 0) | ||
2536 | uh->check = CSUM_MANGLED_0; | ||
2537 | 2583 | ||
2538 | } else if (protocol == htons(ETH_P_IPV6)) { | 2584 | uh->check = ~csum_fold((__force __wsum) |
2539 | struct ipv6hdr *ipv6h = ipv6_hdr(skb); | 2585 | ((__force u32)uh->check + |
2540 | u32 len = skb->len - udp_offset; | 2586 | (__force u32)delta)); |
2587 | uh->check = gso_make_checksum(skb, ~uh->check); | ||
2541 | 2588 | ||
2542 | uh->check = ~csum_ipv6_magic(&ipv6h->saddr, &ipv6h->daddr, | ||
2543 | len, IPPROTO_UDP, 0); | ||
2544 | uh->check = csum_fold(skb_checksum(skb, udp_offset, len, 0)); | ||
2545 | if (uh->check == 0) | 2589 | if (uh->check == 0) |
2546 | uh->check = CSUM_MANGLED_0; | 2590 | uh->check = CSUM_MANGLED_0; |
2547 | skb->ip_summed = CHECKSUM_NONE; | ||
2548 | } | 2591 | } |
2549 | 2592 | ||
2550 | skb->protocol = protocol; | 2593 | skb->protocol = protocol; |