diff options
Diffstat (limited to 'net/ipv4')
-rw-r--r-- | net/ipv4/gre_demux.c | 1 | ||||
-rw-r--r-- | net/ipv4/icmp.c | 2 | ||||
-rw-r--r-- | net/ipv4/igmp.c | 10 | ||||
-rw-r--r-- | net/ipv4/ip_tunnel.c | 26 | ||||
-rw-r--r-- | net/ipv4/route.c | 15 | ||||
-rw-r--r-- | net/ipv4/tcp.c | 3 | ||||
-rw-r--r-- | net/ipv4/tcp_fastopen.c | 2 | ||||
-rw-r--r-- | net/ipv4/tcp_input.c | 10 | ||||
-rw-r--r-- | net/ipv4/tcp_output.c | 6 | ||||
-rw-r--r-- | net/ipv4/udp.c | 5 |
10 files changed, 44 insertions, 36 deletions
diff --git a/net/ipv4/gre_demux.c b/net/ipv4/gre_demux.c index 4e9619bca732..0485bf7f8f03 100644 --- a/net/ipv4/gre_demux.c +++ b/net/ipv4/gre_demux.c | |||
@@ -68,6 +68,7 @@ void gre_build_header(struct sk_buff *skb, const struct tnl_ptk_info *tpi, | |||
68 | 68 | ||
69 | skb_push(skb, hdr_len); | 69 | skb_push(skb, hdr_len); |
70 | 70 | ||
71 | skb_reset_transport_header(skb); | ||
71 | greh = (struct gre_base_hdr *)skb->data; | 72 | greh = (struct gre_base_hdr *)skb->data; |
72 | greh->flags = tnl_flags_to_gre_flags(tpi->flags); | 73 | greh->flags = tnl_flags_to_gre_flags(tpi->flags); |
73 | greh->protocol = tpi->proto; | 74 | greh->protocol = tpi->proto; |
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c index 79c3d947a481..42b7bcf8045b 100644 --- a/net/ipv4/icmp.c +++ b/net/ipv4/icmp.c | |||
@@ -739,8 +739,6 @@ static void icmp_unreach(struct sk_buff *skb) | |||
739 | /* fall through */ | 739 | /* fall through */ |
740 | case 0: | 740 | case 0: |
741 | info = ntohs(icmph->un.frag.mtu); | 741 | info = ntohs(icmph->un.frag.mtu); |
742 | if (!info) | ||
743 | goto out; | ||
744 | } | 742 | } |
745 | break; | 743 | break; |
746 | case ICMP_SR_FAILED: | 744 | case ICMP_SR_FAILED: |
diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c index 6748d420f714..db710b059bab 100644 --- a/net/ipv4/igmp.c +++ b/net/ipv4/igmp.c | |||
@@ -1944,6 +1944,10 @@ int ip_mc_leave_group(struct sock *sk, struct ip_mreqn *imr) | |||
1944 | 1944 | ||
1945 | rtnl_lock(); | 1945 | rtnl_lock(); |
1946 | in_dev = ip_mc_find_dev(net, imr); | 1946 | in_dev = ip_mc_find_dev(net, imr); |
1947 | if (!in_dev) { | ||
1948 | ret = -ENODEV; | ||
1949 | goto out; | ||
1950 | } | ||
1947 | ifindex = imr->imr_ifindex; | 1951 | ifindex = imr->imr_ifindex; |
1948 | for (imlp = &inet->mc_list; | 1952 | for (imlp = &inet->mc_list; |
1949 | (iml = rtnl_dereference(*imlp)) != NULL; | 1953 | (iml = rtnl_dereference(*imlp)) != NULL; |
@@ -1961,16 +1965,14 @@ int ip_mc_leave_group(struct sock *sk, struct ip_mreqn *imr) | |||
1961 | 1965 | ||
1962 | *imlp = iml->next_rcu; | 1966 | *imlp = iml->next_rcu; |
1963 | 1967 | ||
1964 | if (in_dev) | 1968 | ip_mc_dec_group(in_dev, group); |
1965 | ip_mc_dec_group(in_dev, group); | ||
1966 | rtnl_unlock(); | 1969 | rtnl_unlock(); |
1967 | /* decrease mem now to avoid the memleak warning */ | 1970 | /* decrease mem now to avoid the memleak warning */ |
1968 | atomic_sub(sizeof(*iml), &sk->sk_omem_alloc); | 1971 | atomic_sub(sizeof(*iml), &sk->sk_omem_alloc); |
1969 | kfree_rcu(iml, rcu); | 1972 | kfree_rcu(iml, rcu); |
1970 | return 0; | 1973 | return 0; |
1971 | } | 1974 | } |
1972 | if (!in_dev) | 1975 | out: |
1973 | ret = -ENODEV; | ||
1974 | rtnl_unlock(); | 1976 | rtnl_unlock(); |
1975 | return ret; | 1977 | return ret; |
1976 | } | 1978 | } |
diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c index 097b3e7c1e8f..6f9de61dce5f 100644 --- a/net/ipv4/ip_tunnel.c +++ b/net/ipv4/ip_tunnel.c | |||
@@ -73,12 +73,7 @@ static void __tunnel_dst_set(struct ip_tunnel_dst *idst, | |||
73 | { | 73 | { |
74 | struct dst_entry *old_dst; | 74 | struct dst_entry *old_dst; |
75 | 75 | ||
76 | if (dst) { | 76 | dst_clone(dst); |
77 | if (dst->flags & DST_NOCACHE) | ||
78 | dst = NULL; | ||
79 | else | ||
80 | dst_clone(dst); | ||
81 | } | ||
82 | old_dst = xchg((__force struct dst_entry **)&idst->dst, dst); | 77 | old_dst = xchg((__force struct dst_entry **)&idst->dst, dst); |
83 | dst_release(old_dst); | 78 | dst_release(old_dst); |
84 | } | 79 | } |
@@ -108,13 +103,14 @@ static struct rtable *tunnel_rtable_get(struct ip_tunnel *t, u32 cookie) | |||
108 | 103 | ||
109 | rcu_read_lock(); | 104 | rcu_read_lock(); |
110 | dst = rcu_dereference(this_cpu_ptr(t->dst_cache)->dst); | 105 | dst = rcu_dereference(this_cpu_ptr(t->dst_cache)->dst); |
106 | if (dst && !atomic_inc_not_zero(&dst->__refcnt)) | ||
107 | dst = NULL; | ||
111 | if (dst) { | 108 | if (dst) { |
112 | if (dst->obsolete && dst->ops->check(dst, cookie) == NULL) { | 109 | if (dst->obsolete && dst->ops->check(dst, cookie) == NULL) { |
113 | rcu_read_unlock(); | ||
114 | tunnel_dst_reset(t); | 110 | tunnel_dst_reset(t); |
115 | return NULL; | 111 | dst_release(dst); |
112 | dst = NULL; | ||
116 | } | 113 | } |
117 | dst_hold(dst); | ||
118 | } | 114 | } |
119 | rcu_read_unlock(); | 115 | rcu_read_unlock(); |
120 | return (struct rtable *)dst; | 116 | return (struct rtable *)dst; |
@@ -173,6 +169,7 @@ struct ip_tunnel *ip_tunnel_lookup(struct ip_tunnel_net *itn, | |||
173 | 169 | ||
174 | hlist_for_each_entry_rcu(t, head, hash_node) { | 170 | hlist_for_each_entry_rcu(t, head, hash_node) { |
175 | if (remote != t->parms.iph.daddr || | 171 | if (remote != t->parms.iph.daddr || |
172 | t->parms.iph.saddr != 0 || | ||
176 | !(t->dev->flags & IFF_UP)) | 173 | !(t->dev->flags & IFF_UP)) |
177 | continue; | 174 | continue; |
178 | 175 | ||
@@ -189,10 +186,11 @@ struct ip_tunnel *ip_tunnel_lookup(struct ip_tunnel_net *itn, | |||
189 | head = &itn->tunnels[hash]; | 186 | head = &itn->tunnels[hash]; |
190 | 187 | ||
191 | hlist_for_each_entry_rcu(t, head, hash_node) { | 188 | hlist_for_each_entry_rcu(t, head, hash_node) { |
192 | if ((local != t->parms.iph.saddr && | 189 | if ((local != t->parms.iph.saddr || t->parms.iph.daddr != 0) && |
193 | (local != t->parms.iph.daddr || | 190 | (local != t->parms.iph.daddr || !ipv4_is_multicast(local))) |
194 | !ipv4_is_multicast(local))) || | 191 | continue; |
195 | !(t->dev->flags & IFF_UP)) | 192 | |
193 | if (!(t->dev->flags & IFF_UP)) | ||
196 | continue; | 194 | continue; |
197 | 195 | ||
198 | if (!ip_tunnel_key_match(&t->parms, flags, key)) | 196 | if (!ip_tunnel_key_match(&t->parms, flags, key)) |
@@ -209,6 +207,8 @@ struct ip_tunnel *ip_tunnel_lookup(struct ip_tunnel_net *itn, | |||
209 | 207 | ||
210 | hlist_for_each_entry_rcu(t, head, hash_node) { | 208 | hlist_for_each_entry_rcu(t, head, hash_node) { |
211 | if (t->parms.i_key != key || | 209 | if (t->parms.i_key != key || |
210 | t->parms.iph.saddr != 0 || | ||
211 | t->parms.iph.daddr != 0 || | ||
212 | !(t->dev->flags & IFF_UP)) | 212 | !(t->dev->flags & IFF_UP)) |
213 | continue; | 213 | continue; |
214 | 214 | ||
diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 082239ffe34a..3162ea923ded 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c | |||
@@ -1010,7 +1010,7 @@ void ipv4_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, u32 mtu) | |||
1010 | const struct iphdr *iph = (const struct iphdr *) skb->data; | 1010 | const struct iphdr *iph = (const struct iphdr *) skb->data; |
1011 | struct flowi4 fl4; | 1011 | struct flowi4 fl4; |
1012 | struct rtable *rt; | 1012 | struct rtable *rt; |
1013 | struct dst_entry *dst; | 1013 | struct dst_entry *odst = NULL; |
1014 | bool new = false; | 1014 | bool new = false; |
1015 | 1015 | ||
1016 | bh_lock_sock(sk); | 1016 | bh_lock_sock(sk); |
@@ -1018,16 +1018,17 @@ void ipv4_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, u32 mtu) | |||
1018 | if (!ip_sk_accept_pmtu(sk)) | 1018 | if (!ip_sk_accept_pmtu(sk)) |
1019 | goto out; | 1019 | goto out; |
1020 | 1020 | ||
1021 | rt = (struct rtable *) __sk_dst_get(sk); | 1021 | odst = sk_dst_get(sk); |
1022 | 1022 | ||
1023 | if (sock_owned_by_user(sk) || !rt) { | 1023 | if (sock_owned_by_user(sk) || !odst) { |
1024 | __ipv4_sk_update_pmtu(skb, sk, mtu); | 1024 | __ipv4_sk_update_pmtu(skb, sk, mtu); |
1025 | goto out; | 1025 | goto out; |
1026 | } | 1026 | } |
1027 | 1027 | ||
1028 | __build_flow_key(&fl4, sk, iph, 0, 0, 0, 0, 0); | 1028 | __build_flow_key(&fl4, sk, iph, 0, 0, 0, 0, 0); |
1029 | 1029 | ||
1030 | if (!__sk_dst_check(sk, 0)) { | 1030 | rt = (struct rtable *)odst; |
1031 | if (odst->obsolete && odst->ops->check(odst, 0) == NULL) { | ||
1031 | rt = ip_route_output_flow(sock_net(sk), &fl4, sk); | 1032 | rt = ip_route_output_flow(sock_net(sk), &fl4, sk); |
1032 | if (IS_ERR(rt)) | 1033 | if (IS_ERR(rt)) |
1033 | goto out; | 1034 | goto out; |
@@ -1037,8 +1038,7 @@ void ipv4_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, u32 mtu) | |||
1037 | 1038 | ||
1038 | __ip_rt_update_pmtu((struct rtable *) rt->dst.path, &fl4, mtu); | 1039 | __ip_rt_update_pmtu((struct rtable *) rt->dst.path, &fl4, mtu); |
1039 | 1040 | ||
1040 | dst = dst_check(&rt->dst, 0); | 1041 | if (!dst_check(&rt->dst, 0)) { |
1041 | if (!dst) { | ||
1042 | if (new) | 1042 | if (new) |
1043 | dst_release(&rt->dst); | 1043 | dst_release(&rt->dst); |
1044 | 1044 | ||
@@ -1050,10 +1050,11 @@ void ipv4_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, u32 mtu) | |||
1050 | } | 1050 | } |
1051 | 1051 | ||
1052 | if (new) | 1052 | if (new) |
1053 | __sk_dst_set(sk, &rt->dst); | 1053 | sk_dst_set(sk, &rt->dst); |
1054 | 1054 | ||
1055 | out: | 1055 | out: |
1056 | bh_unlock_sock(sk); | 1056 | bh_unlock_sock(sk); |
1057 | dst_release(odst); | ||
1057 | } | 1058 | } |
1058 | EXPORT_SYMBOL_GPL(ipv4_sk_update_pmtu); | 1059 | EXPORT_SYMBOL_GPL(ipv4_sk_update_pmtu); |
1059 | 1060 | ||
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index eb1dde37e678..9d2118e5fbc7 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c | |||
@@ -1108,7 +1108,7 @@ int tcp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, | |||
1108 | if (unlikely(tp->repair)) { | 1108 | if (unlikely(tp->repair)) { |
1109 | if (tp->repair_queue == TCP_RECV_QUEUE) { | 1109 | if (tp->repair_queue == TCP_RECV_QUEUE) { |
1110 | copied = tcp_send_rcvq(sk, msg, size); | 1110 | copied = tcp_send_rcvq(sk, msg, size); |
1111 | goto out; | 1111 | goto out_nopush; |
1112 | } | 1112 | } |
1113 | 1113 | ||
1114 | err = -EINVAL; | 1114 | err = -EINVAL; |
@@ -1282,6 +1282,7 @@ wait_for_memory: | |||
1282 | out: | 1282 | out: |
1283 | if (copied) | 1283 | if (copied) |
1284 | tcp_push(sk, flags, mss_now, tp->nonagle, size_goal); | 1284 | tcp_push(sk, flags, mss_now, tp->nonagle, size_goal); |
1285 | out_nopush: | ||
1285 | release_sock(sk); | 1286 | release_sock(sk); |
1286 | return copied + copied_syn; | 1287 | return copied + copied_syn; |
1287 | 1288 | ||
diff --git a/net/ipv4/tcp_fastopen.c b/net/ipv4/tcp_fastopen.c index 62e48cf84e60..9771563ab564 100644 --- a/net/ipv4/tcp_fastopen.c +++ b/net/ipv4/tcp_fastopen.c | |||
@@ -131,7 +131,7 @@ static bool tcp_fastopen_create_child(struct sock *sk, | |||
131 | struct dst_entry *dst, | 131 | struct dst_entry *dst, |
132 | struct request_sock *req) | 132 | struct request_sock *req) |
133 | { | 133 | { |
134 | struct tcp_sock *tp = tcp_sk(sk); | 134 | struct tcp_sock *tp; |
135 | struct request_sock_queue *queue = &inet_csk(sk)->icsk_accept_queue; | 135 | struct request_sock_queue *queue = &inet_csk(sk)->icsk_accept_queue; |
136 | struct sock *child; | 136 | struct sock *child; |
137 | 137 | ||
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 40661fc1e233..40639c288dc2 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c | |||
@@ -1106,7 +1106,7 @@ static bool tcp_check_dsack(struct sock *sk, const struct sk_buff *ack_skb, | |||
1106 | } | 1106 | } |
1107 | 1107 | ||
1108 | /* D-SACK for already forgotten data... Do dumb counting. */ | 1108 | /* D-SACK for already forgotten data... Do dumb counting. */ |
1109 | if (dup_sack && tp->undo_marker && tp->undo_retrans && | 1109 | if (dup_sack && tp->undo_marker && tp->undo_retrans > 0 && |
1110 | !after(end_seq_0, prior_snd_una) && | 1110 | !after(end_seq_0, prior_snd_una) && |
1111 | after(end_seq_0, tp->undo_marker)) | 1111 | after(end_seq_0, tp->undo_marker)) |
1112 | tp->undo_retrans--; | 1112 | tp->undo_retrans--; |
@@ -1162,7 +1162,7 @@ static int tcp_match_skb_to_sack(struct sock *sk, struct sk_buff *skb, | |||
1162 | unsigned int new_len = (pkt_len / mss) * mss; | 1162 | unsigned int new_len = (pkt_len / mss) * mss; |
1163 | if (!in_sack && new_len < pkt_len) { | 1163 | if (!in_sack && new_len < pkt_len) { |
1164 | new_len += mss; | 1164 | new_len += mss; |
1165 | if (new_len > skb->len) | 1165 | if (new_len >= skb->len) |
1166 | return 0; | 1166 | return 0; |
1167 | } | 1167 | } |
1168 | pkt_len = new_len; | 1168 | pkt_len = new_len; |
@@ -1187,7 +1187,7 @@ static u8 tcp_sacktag_one(struct sock *sk, | |||
1187 | 1187 | ||
1188 | /* Account D-SACK for retransmitted packet. */ | 1188 | /* Account D-SACK for retransmitted packet. */ |
1189 | if (dup_sack && (sacked & TCPCB_RETRANS)) { | 1189 | if (dup_sack && (sacked & TCPCB_RETRANS)) { |
1190 | if (tp->undo_marker && tp->undo_retrans && | 1190 | if (tp->undo_marker && tp->undo_retrans > 0 && |
1191 | after(end_seq, tp->undo_marker)) | 1191 | after(end_seq, tp->undo_marker)) |
1192 | tp->undo_retrans--; | 1192 | tp->undo_retrans--; |
1193 | if (sacked & TCPCB_SACKED_ACKED) | 1193 | if (sacked & TCPCB_SACKED_ACKED) |
@@ -1893,7 +1893,7 @@ static void tcp_clear_retrans_partial(struct tcp_sock *tp) | |||
1893 | tp->lost_out = 0; | 1893 | tp->lost_out = 0; |
1894 | 1894 | ||
1895 | tp->undo_marker = 0; | 1895 | tp->undo_marker = 0; |
1896 | tp->undo_retrans = 0; | 1896 | tp->undo_retrans = -1; |
1897 | } | 1897 | } |
1898 | 1898 | ||
1899 | void tcp_clear_retrans(struct tcp_sock *tp) | 1899 | void tcp_clear_retrans(struct tcp_sock *tp) |
@@ -2665,7 +2665,7 @@ static void tcp_enter_recovery(struct sock *sk, bool ece_ack) | |||
2665 | 2665 | ||
2666 | tp->prior_ssthresh = 0; | 2666 | tp->prior_ssthresh = 0; |
2667 | tp->undo_marker = tp->snd_una; | 2667 | tp->undo_marker = tp->snd_una; |
2668 | tp->undo_retrans = tp->retrans_out; | 2668 | tp->undo_retrans = tp->retrans_out ? : -1; |
2669 | 2669 | ||
2670 | if (inet_csk(sk)->icsk_ca_state < TCP_CA_CWR) { | 2670 | if (inet_csk(sk)->icsk_ca_state < TCP_CA_CWR) { |
2671 | if (!ece_ack) | 2671 | if (!ece_ack) |
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index d92bce0ea24e..179b51e6bda3 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c | |||
@@ -2525,8 +2525,6 @@ int tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb) | |||
2525 | if (!tp->retrans_stamp) | 2525 | if (!tp->retrans_stamp) |
2526 | tp->retrans_stamp = TCP_SKB_CB(skb)->when; | 2526 | tp->retrans_stamp = TCP_SKB_CB(skb)->when; |
2527 | 2527 | ||
2528 | tp->undo_retrans += tcp_skb_pcount(skb); | ||
2529 | |||
2530 | /* snd_nxt is stored to detect loss of retransmitted segment, | 2528 | /* snd_nxt is stored to detect loss of retransmitted segment, |
2531 | * see tcp_input.c tcp_sacktag_write_queue(). | 2529 | * see tcp_input.c tcp_sacktag_write_queue(). |
2532 | */ | 2530 | */ |
@@ -2534,6 +2532,10 @@ int tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb) | |||
2534 | } else if (err != -EBUSY) { | 2532 | } else if (err != -EBUSY) { |
2535 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPRETRANSFAIL); | 2533 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPRETRANSFAIL); |
2536 | } | 2534 | } |
2535 | |||
2536 | if (tp->undo_retrans < 0) | ||
2537 | tp->undo_retrans = 0; | ||
2538 | tp->undo_retrans += tcp_skb_pcount(skb); | ||
2537 | return err; | 2539 | return err; |
2538 | } | 2540 | } |
2539 | 2541 | ||
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index d92f94b7e402..7d5a8661df76 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c | |||
@@ -1588,8 +1588,11 @@ int udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) | |||
1588 | goto csum_error; | 1588 | goto csum_error; |
1589 | 1589 | ||
1590 | 1590 | ||
1591 | if (sk_rcvqueues_full(sk, skb, sk->sk_rcvbuf)) | 1591 | if (sk_rcvqueues_full(sk, skb, sk->sk_rcvbuf)) { |
1592 | UDP_INC_STATS_BH(sock_net(sk), UDP_MIB_RCVBUFERRORS, | ||
1593 | is_udplite); | ||
1592 | goto drop; | 1594 | goto drop; |
1595 | } | ||
1593 | 1596 | ||
1594 | rc = 0; | 1597 | rc = 0; |
1595 | 1598 | ||