diff options
Diffstat (limited to 'net/ipv4')
| -rw-r--r-- | net/ipv4/gre_offload.c | 11 | ||||
| -rw-r--r-- | net/ipv4/inet_diag.c | 16 | ||||
| -rw-r--r-- | net/ipv4/ip_gre.c | 1 | ||||
| -rw-r--r-- | net/ipv4/ip_output.c | 5 | ||||
| -rw-r--r-- | net/ipv4/udp.c | 6 | ||||
| -rw-r--r-- | net/ipv4/udp_offload.c | 37 |
6 files changed, 51 insertions, 25 deletions
diff --git a/net/ipv4/gre_offload.c b/net/ipv4/gre_offload.c index e5d436188464..2cd02f32f99f 100644 --- a/net/ipv4/gre_offload.c +++ b/net/ipv4/gre_offload.c | |||
| @@ -28,6 +28,7 @@ static struct sk_buff *gre_gso_segment(struct sk_buff *skb, | |||
| 28 | netdev_features_t enc_features; | 28 | netdev_features_t enc_features; |
| 29 | int ghl = GRE_HEADER_SECTION; | 29 | int ghl = GRE_HEADER_SECTION; |
| 30 | struct gre_base_hdr *greh; | 30 | struct gre_base_hdr *greh; |
| 31 | u16 mac_offset = skb->mac_header; | ||
| 31 | int mac_len = skb->mac_len; | 32 | int mac_len = skb->mac_len; |
| 32 | __be16 protocol = skb->protocol; | 33 | __be16 protocol = skb->protocol; |
| 33 | int tnl_hlen; | 34 | int tnl_hlen; |
| @@ -58,13 +59,13 @@ static struct sk_buff *gre_gso_segment(struct sk_buff *skb, | |||
| 58 | } else | 59 | } else |
| 59 | csum = false; | 60 | csum = false; |
| 60 | 61 | ||
| 62 | if (unlikely(!pskb_may_pull(skb, ghl))) | ||
| 63 | goto out; | ||
| 64 | |||
| 61 | /* setup inner skb. */ | 65 | /* setup inner skb. */ |
| 62 | skb->protocol = greh->protocol; | 66 | skb->protocol = greh->protocol; |
| 63 | skb->encapsulation = 0; | 67 | skb->encapsulation = 0; |
| 64 | 68 | ||
| 65 | if (unlikely(!pskb_may_pull(skb, ghl))) | ||
| 66 | goto out; | ||
| 67 | |||
| 68 | __skb_pull(skb, ghl); | 69 | __skb_pull(skb, ghl); |
| 69 | skb_reset_mac_header(skb); | 70 | skb_reset_mac_header(skb); |
| 70 | skb_set_network_header(skb, skb_inner_network_offset(skb)); | 71 | skb_set_network_header(skb, skb_inner_network_offset(skb)); |
| @@ -73,8 +74,10 @@ static struct sk_buff *gre_gso_segment(struct sk_buff *skb, | |||
| 73 | /* segment inner packet. */ | 74 | /* segment inner packet. */ |
| 74 | enc_features = skb->dev->hw_enc_features & netif_skb_features(skb); | 75 | enc_features = skb->dev->hw_enc_features & netif_skb_features(skb); |
| 75 | segs = skb_mac_gso_segment(skb, enc_features); | 76 | segs = skb_mac_gso_segment(skb, enc_features); |
| 76 | if (!segs || IS_ERR(segs)) | 77 | if (!segs || IS_ERR(segs)) { |
| 78 | skb_gso_error_unwind(skb, protocol, ghl, mac_offset, mac_len); | ||
| 77 | goto out; | 79 | goto out; |
| 80 | } | ||
| 78 | 81 | ||
| 79 | skb = segs; | 82 | skb = segs; |
| 80 | tnl_hlen = skb_tnl_header_len(skb); | 83 | tnl_hlen = skb_tnl_header_len(skb); |
diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c index 56a964a553d2..a0f52dac8940 100644 --- a/net/ipv4/inet_diag.c +++ b/net/ipv4/inet_diag.c | |||
| @@ -106,6 +106,10 @@ int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk, | |||
| 106 | 106 | ||
| 107 | r->id.idiag_sport = inet->inet_sport; | 107 | r->id.idiag_sport = inet->inet_sport; |
| 108 | r->id.idiag_dport = inet->inet_dport; | 108 | r->id.idiag_dport = inet->inet_dport; |
| 109 | |||
| 110 | memset(&r->id.idiag_src, 0, sizeof(r->id.idiag_src)); | ||
| 111 | memset(&r->id.idiag_dst, 0, sizeof(r->id.idiag_dst)); | ||
| 112 | |||
| 109 | r->id.idiag_src[0] = inet->inet_rcv_saddr; | 113 | r->id.idiag_src[0] = inet->inet_rcv_saddr; |
| 110 | r->id.idiag_dst[0] = inet->inet_daddr; | 114 | r->id.idiag_dst[0] = inet->inet_daddr; |
| 111 | 115 | ||
| @@ -240,12 +244,19 @@ static int inet_twsk_diag_fill(struct inet_timewait_sock *tw, | |||
| 240 | 244 | ||
| 241 | r->idiag_family = tw->tw_family; | 245 | r->idiag_family = tw->tw_family; |
| 242 | r->idiag_retrans = 0; | 246 | r->idiag_retrans = 0; |
| 247 | |||
| 243 | r->id.idiag_if = tw->tw_bound_dev_if; | 248 | r->id.idiag_if = tw->tw_bound_dev_if; |
| 244 | sock_diag_save_cookie(tw, r->id.idiag_cookie); | 249 | sock_diag_save_cookie(tw, r->id.idiag_cookie); |
| 250 | |||
| 245 | r->id.idiag_sport = tw->tw_sport; | 251 | r->id.idiag_sport = tw->tw_sport; |
| 246 | r->id.idiag_dport = tw->tw_dport; | 252 | r->id.idiag_dport = tw->tw_dport; |
| 253 | |||
| 254 | memset(&r->id.idiag_src, 0, sizeof(r->id.idiag_src)); | ||
| 255 | memset(&r->id.idiag_dst, 0, sizeof(r->id.idiag_dst)); | ||
| 256 | |||
| 247 | r->id.idiag_src[0] = tw->tw_rcv_saddr; | 257 | r->id.idiag_src[0] = tw->tw_rcv_saddr; |
| 248 | r->id.idiag_dst[0] = tw->tw_daddr; | 258 | r->id.idiag_dst[0] = tw->tw_daddr; |
| 259 | |||
| 249 | r->idiag_state = tw->tw_substate; | 260 | r->idiag_state = tw->tw_substate; |
| 250 | r->idiag_timer = 3; | 261 | r->idiag_timer = 3; |
| 251 | r->idiag_expires = jiffies_to_msecs(tmo); | 262 | r->idiag_expires = jiffies_to_msecs(tmo); |
| @@ -726,8 +737,13 @@ static int inet_diag_fill_req(struct sk_buff *skb, struct sock *sk, | |||
| 726 | 737 | ||
| 727 | r->id.idiag_sport = inet->inet_sport; | 738 | r->id.idiag_sport = inet->inet_sport; |
| 728 | r->id.idiag_dport = ireq->ir_rmt_port; | 739 | r->id.idiag_dport = ireq->ir_rmt_port; |
| 740 | |||
| 741 | memset(&r->id.idiag_src, 0, sizeof(r->id.idiag_src)); | ||
| 742 | memset(&r->id.idiag_dst, 0, sizeof(r->id.idiag_dst)); | ||
| 743 | |||
| 729 | r->id.idiag_src[0] = ireq->ir_loc_addr; | 744 | r->id.idiag_src[0] = ireq->ir_loc_addr; |
| 730 | r->id.idiag_dst[0] = ireq->ir_rmt_addr; | 745 | r->id.idiag_dst[0] = ireq->ir_rmt_addr; |
| 746 | |||
| 731 | r->idiag_expires = jiffies_to_msecs(tmo); | 747 | r->idiag_expires = jiffies_to_msecs(tmo); |
| 732 | r->idiag_rqueue = 0; | 748 | r->idiag_rqueue = 0; |
| 733 | r->idiag_wqueue = 0; | 749 | r->idiag_wqueue = 0; |
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index d7aea4c5b940..e560ef34cf4b 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c | |||
| @@ -217,6 +217,7 @@ static int ipgre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi) | |||
| 217 | iph->saddr, iph->daddr, tpi->key); | 217 | iph->saddr, iph->daddr, tpi->key); |
| 218 | 218 | ||
| 219 | if (tunnel) { | 219 | if (tunnel) { |
| 220 | skb_pop_mac_header(skb); | ||
| 220 | ip_tunnel_rcv(tunnel, skb, tpi, log_ecn_error); | 221 | ip_tunnel_rcv(tunnel, skb, tpi, log_ecn_error); |
| 221 | return PACKET_RCVD; | 222 | return PACKET_RCVD; |
| 222 | } | 223 | } |
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index 912402752f2f..df184616493f 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c | |||
| @@ -828,7 +828,7 @@ static int __ip_append_data(struct sock *sk, | |||
| 828 | 828 | ||
| 829 | if (cork->length + length > maxnonfragsize - fragheaderlen) { | 829 | if (cork->length + length > maxnonfragsize - fragheaderlen) { |
| 830 | ip_local_error(sk, EMSGSIZE, fl4->daddr, inet->inet_dport, | 830 | ip_local_error(sk, EMSGSIZE, fl4->daddr, inet->inet_dport, |
| 831 | mtu-exthdrlen); | 831 | mtu - (opt ? opt->optlen : 0)); |
| 832 | return -EMSGSIZE; | 832 | return -EMSGSIZE; |
| 833 | } | 833 | } |
| 834 | 834 | ||
| @@ -1151,7 +1151,8 @@ ssize_t ip_append_page(struct sock *sk, struct flowi4 *fl4, struct page *page, | |||
| 1151 | mtu : 0xFFFF; | 1151 | mtu : 0xFFFF; |
| 1152 | 1152 | ||
| 1153 | if (cork->length + size > maxnonfragsize - fragheaderlen) { | 1153 | if (cork->length + size > maxnonfragsize - fragheaderlen) { |
| 1154 | ip_local_error(sk, EMSGSIZE, fl4->daddr, inet->inet_dport, mtu); | 1154 | ip_local_error(sk, EMSGSIZE, fl4->daddr, inet->inet_dport, |
| 1155 | mtu - (opt ? opt->optlen : 0)); | ||
| 1155 | return -EMSGSIZE; | 1156 | return -EMSGSIZE; |
| 1156 | } | 1157 | } |
| 1157 | 1158 | ||
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index d5d24ecde6a5..80f649fbee63 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c | |||
| @@ -2478,6 +2478,7 @@ struct sk_buff *skb_udp_tunnel_segment(struct sk_buff *skb, | |||
| 2478 | netdev_features_t features) | 2478 | netdev_features_t features) |
| 2479 | { | 2479 | { |
| 2480 | struct sk_buff *segs = ERR_PTR(-EINVAL); | 2480 | struct sk_buff *segs = ERR_PTR(-EINVAL); |
| 2481 | u16 mac_offset = skb->mac_header; | ||
| 2481 | int mac_len = skb->mac_len; | 2482 | int mac_len = skb->mac_len; |
| 2482 | int tnl_hlen = skb_inner_mac_header(skb) - skb_transport_header(skb); | 2483 | int tnl_hlen = skb_inner_mac_header(skb) - skb_transport_header(skb); |
| 2483 | __be16 protocol = skb->protocol; | 2484 | __be16 protocol = skb->protocol; |
| @@ -2497,8 +2498,11 @@ struct sk_buff *skb_udp_tunnel_segment(struct sk_buff *skb, | |||
| 2497 | /* segment inner packet. */ | 2498 | /* segment inner packet. */ |
| 2498 | enc_features = skb->dev->hw_enc_features & netif_skb_features(skb); | 2499 | enc_features = skb->dev->hw_enc_features & netif_skb_features(skb); |
| 2499 | segs = skb_mac_gso_segment(skb, enc_features); | 2500 | segs = skb_mac_gso_segment(skb, enc_features); |
| 2500 | if (!segs || IS_ERR(segs)) | 2501 | if (!segs || IS_ERR(segs)) { |
| 2502 | skb_gso_error_unwind(skb, protocol, tnl_hlen, mac_offset, | ||
| 2503 | mac_len); | ||
| 2501 | goto out; | 2504 | goto out; |
| 2505 | } | ||
| 2502 | 2506 | ||
| 2503 | outer_hlen = skb_tnl_header_len(skb); | 2507 | outer_hlen = skb_tnl_header_len(skb); |
| 2504 | skb = segs; | 2508 | skb = segs; |
diff --git a/net/ipv4/udp_offload.c b/net/ipv4/udp_offload.c index 83206de2bc76..79c62bdcd3c5 100644 --- a/net/ipv4/udp_offload.c +++ b/net/ipv4/udp_offload.c | |||
| @@ -41,6 +41,14 @@ static struct sk_buff *udp4_ufo_fragment(struct sk_buff *skb, | |||
| 41 | { | 41 | { |
| 42 | struct sk_buff *segs = ERR_PTR(-EINVAL); | 42 | struct sk_buff *segs = ERR_PTR(-EINVAL); |
| 43 | unsigned int mss; | 43 | unsigned int mss; |
| 44 | int offset; | ||
| 45 | __wsum csum; | ||
| 46 | |||
| 47 | if (skb->encapsulation && | ||
| 48 | skb_shinfo(skb)->gso_type & SKB_GSO_UDP_TUNNEL) { | ||
| 49 | segs = skb_udp_tunnel_segment(skb, features); | ||
| 50 | goto out; | ||
| 51 | } | ||
| 44 | 52 | ||
| 45 | mss = skb_shinfo(skb)->gso_size; | 53 | mss = skb_shinfo(skb)->gso_size; |
| 46 | if (unlikely(skb->len <= mss)) | 54 | if (unlikely(skb->len <= mss)) |
| @@ -63,27 +71,20 @@ static struct sk_buff *udp4_ufo_fragment(struct sk_buff *skb, | |||
| 63 | goto out; | 71 | goto out; |
| 64 | } | 72 | } |
| 65 | 73 | ||
| 74 | /* Do software UFO. Complete and fill in the UDP checksum as | ||
| 75 | * HW cannot do checksum of UDP packets sent as multiple | ||
| 76 | * IP fragments. | ||
| 77 | */ | ||
| 78 | offset = skb_checksum_start_offset(skb); | ||
| 79 | csum = skb_checksum(skb, offset, skb->len - offset, 0); | ||
| 80 | offset += skb->csum_offset; | ||
| 81 | *(__sum16 *)(skb->data + offset) = csum_fold(csum); | ||
| 82 | skb->ip_summed = CHECKSUM_NONE; | ||
| 83 | |||
| 66 | /* Fragment the skb. IP headers of the fragments are updated in | 84 | /* Fragment the skb. IP headers of the fragments are updated in |
| 67 | * inet_gso_segment() | 85 | * inet_gso_segment() |
| 68 | */ | 86 | */ |
| 69 | if (skb->encapsulation && skb_shinfo(skb)->gso_type & SKB_GSO_UDP_TUNNEL) | 87 | segs = skb_segment(skb, features); |
| 70 | segs = skb_udp_tunnel_segment(skb, features); | ||
| 71 | else { | ||
| 72 | int offset; | ||
| 73 | __wsum csum; | ||
| 74 | |||
| 75 | /* Do software UFO. Complete and fill in the UDP checksum as | ||
| 76 | * HW cannot do checksum of UDP packets sent as multiple | ||
| 77 | * IP fragments. | ||
| 78 | */ | ||
| 79 | offset = skb_checksum_start_offset(skb); | ||
| 80 | csum = skb_checksum(skb, offset, skb->len - offset, 0); | ||
| 81 | offset += skb->csum_offset; | ||
| 82 | *(__sum16 *)(skb->data + offset) = csum_fold(csum); | ||
| 83 | skb->ip_summed = CHECKSUM_NONE; | ||
| 84 | |||
| 85 | segs = skb_segment(skb, features); | ||
| 86 | } | ||
| 87 | out: | 88 | out: |
| 88 | return segs; | 89 | return segs; |
| 89 | } | 90 | } |
