diff options
Diffstat (limited to 'net/ipv4')
| -rw-r--r-- | net/ipv4/Kconfig | 1 | ||||
| -rw-r--r-- | net/ipv4/fib_trie.c | 7 | ||||
| -rw-r--r-- | net/ipv4/inet_diag.c | 21 | ||||
| -rw-r--r-- | net/ipv4/ip_fragment.c | 1 | ||||
| -rw-r--r-- | net/ipv4/ip_gre.c | 8 | ||||
| -rw-r--r-- | net/ipv4/ip_input.c | 5 | ||||
| -rw-r--r-- | net/ipv4/ip_tunnel.c | 20 | ||||
| -rw-r--r-- | net/ipv4/ipconfig.c | 4 | ||||
| -rw-r--r-- | net/ipv4/netfilter/nf_defrag_ipv4.c | 2 | ||||
| -rw-r--r-- | net/ipv4/tcp.c | 16 | ||||
| -rw-r--r-- | net/ipv4/tcp_input.c | 12 | ||||
| -rw-r--r-- | net/ipv4/tcp_ipv4.c | 24 | ||||
| -rw-r--r-- | net/ipv4/udp.c | 32 |
13 files changed, 105 insertions, 48 deletions
diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig index c22920525e5d..775824720b6b 100644 --- a/net/ipv4/Kconfig +++ b/net/ipv4/Kconfig | |||
| @@ -353,6 +353,7 @@ config INET_ESP | |||
| 353 | select CRYPTO_CBC | 353 | select CRYPTO_CBC |
| 354 | select CRYPTO_SHA1 | 354 | select CRYPTO_SHA1 |
| 355 | select CRYPTO_DES | 355 | select CRYPTO_DES |
| 356 | select CRYPTO_ECHAINIV | ||
| 356 | ---help--- | 357 | ---help--- |
| 357 | Support for IPsec ESP. | 358 | Support for IPsec ESP. |
| 358 | 359 | ||
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c index 7aea0ccb6be6..d07fc076bea0 100644 --- a/net/ipv4/fib_trie.c +++ b/net/ipv4/fib_trie.c | |||
| @@ -1394,9 +1394,10 @@ found: | |||
| 1394 | struct fib_info *fi = fa->fa_info; | 1394 | struct fib_info *fi = fa->fa_info; |
| 1395 | int nhsel, err; | 1395 | int nhsel, err; |
| 1396 | 1396 | ||
| 1397 | if ((index >= (1ul << fa->fa_slen)) && | 1397 | if ((BITS_PER_LONG > KEYLENGTH) || (fa->fa_slen < KEYLENGTH)) { |
| 1398 | ((BITS_PER_LONG > KEYLENGTH) || (fa->fa_slen != KEYLENGTH))) | 1398 | if (index >= (1ul << fa->fa_slen)) |
| 1399 | continue; | 1399 | continue; |
| 1400 | } | ||
| 1400 | if (fa->fa_tos && fa->fa_tos != flp->flowi4_tos) | 1401 | if (fa->fa_tos && fa->fa_tos != flp->flowi4_tos) |
| 1401 | continue; | 1402 | continue; |
| 1402 | if (fi->fib_dead) | 1403 | if (fi->fib_dead) |
diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c index 8bb8e7ad8548..6029157a19ed 100644 --- a/net/ipv4/inet_diag.c +++ b/net/ipv4/inet_diag.c | |||
| @@ -361,13 +361,20 @@ struct sock *inet_diag_find_one_icsk(struct net *net, | |||
| 361 | req->id.idiag_dport, req->id.idiag_src[0], | 361 | req->id.idiag_dport, req->id.idiag_src[0], |
| 362 | req->id.idiag_sport, req->id.idiag_if); | 362 | req->id.idiag_sport, req->id.idiag_if); |
| 363 | #if IS_ENABLED(CONFIG_IPV6) | 363 | #if IS_ENABLED(CONFIG_IPV6) |
| 364 | else if (req->sdiag_family == AF_INET6) | 364 | else if (req->sdiag_family == AF_INET6) { |
| 365 | sk = inet6_lookup(net, hashinfo, | 365 | if (ipv6_addr_v4mapped((struct in6_addr *)req->id.idiag_dst) && |
| 366 | (struct in6_addr *)req->id.idiag_dst, | 366 | ipv6_addr_v4mapped((struct in6_addr *)req->id.idiag_src)) |
| 367 | req->id.idiag_dport, | 367 | sk = inet_lookup(net, hashinfo, req->id.idiag_dst[3], |
| 368 | (struct in6_addr *)req->id.idiag_src, | 368 | req->id.idiag_dport, req->id.idiag_src[3], |
| 369 | req->id.idiag_sport, | 369 | req->id.idiag_sport, req->id.idiag_if); |
| 370 | req->id.idiag_if); | 370 | else |
| 371 | sk = inet6_lookup(net, hashinfo, | ||
| 372 | (struct in6_addr *)req->id.idiag_dst, | ||
| 373 | req->id.idiag_dport, | ||
| 374 | (struct in6_addr *)req->id.idiag_src, | ||
| 375 | req->id.idiag_sport, | ||
| 376 | req->id.idiag_if); | ||
| 377 | } | ||
| 371 | #endif | 378 | #endif |
| 372 | else | 379 | else |
| 373 | return ERR_PTR(-EINVAL); | 380 | return ERR_PTR(-EINVAL); |
diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c index 3f00810b7288..187c6fcc3027 100644 --- a/net/ipv4/ip_fragment.c +++ b/net/ipv4/ip_fragment.c | |||
| @@ -661,6 +661,7 @@ int ip_defrag(struct net *net, struct sk_buff *skb, u32 user) | |||
| 661 | struct ipq *qp; | 661 | struct ipq *qp; |
| 662 | 662 | ||
| 663 | IP_INC_STATS_BH(net, IPSTATS_MIB_REASMREQDS); | 663 | IP_INC_STATS_BH(net, IPSTATS_MIB_REASMREQDS); |
| 664 | skb_orphan(skb); | ||
| 664 | 665 | ||
| 665 | /* Lookup (or create) queue header */ | 666 | /* Lookup (or create) queue header */ |
| 666 | qp = ip_find(net, ip_hdr(skb), user, vif); | 667 | qp = ip_find(net, ip_hdr(skb), user, vif); |
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index 7c51c4e1661f..56fdf4e0dce4 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c | |||
| @@ -1240,6 +1240,14 @@ struct net_device *gretap_fb_dev_create(struct net *net, const char *name, | |||
| 1240 | err = ipgre_newlink(net, dev, tb, NULL); | 1240 | err = ipgre_newlink(net, dev, tb, NULL); |
| 1241 | if (err < 0) | 1241 | if (err < 0) |
| 1242 | goto out; | 1242 | goto out; |
| 1243 | |||
| 1244 | /* openvswitch users expect packet sizes to be unrestricted, | ||
| 1245 | * so set the largest MTU we can. | ||
| 1246 | */ | ||
| 1247 | err = __ip_tunnel_change_mtu(dev, IP_MAX_MTU, false); | ||
| 1248 | if (err) | ||
| 1249 | goto out; | ||
| 1250 | |||
| 1243 | return dev; | 1251 | return dev; |
| 1244 | out: | 1252 | out: |
| 1245 | free_netdev(dev); | 1253 | free_netdev(dev); |
diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c index b1209b63381f..d77eb0c3b684 100644 --- a/net/ipv4/ip_input.c +++ b/net/ipv4/ip_input.c | |||
| @@ -316,7 +316,10 @@ static int ip_rcv_finish(struct net *net, struct sock *sk, struct sk_buff *skb) | |||
| 316 | const struct iphdr *iph = ip_hdr(skb); | 316 | const struct iphdr *iph = ip_hdr(skb); |
| 317 | struct rtable *rt; | 317 | struct rtable *rt; |
| 318 | 318 | ||
| 319 | if (sysctl_ip_early_demux && !skb_dst(skb) && !skb->sk) { | 319 | if (sysctl_ip_early_demux && |
| 320 | !skb_dst(skb) && | ||
| 321 | !skb->sk && | ||
| 322 | !ip_is_fragment(iph)) { | ||
| 320 | const struct net_protocol *ipprot; | 323 | const struct net_protocol *ipprot; |
| 321 | int protocol = iph->protocol; | 324 | int protocol = iph->protocol; |
| 322 | 325 | ||
diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c index c7bd72e9b544..89e8861e05fc 100644 --- a/net/ipv4/ip_tunnel.c +++ b/net/ipv4/ip_tunnel.c | |||
| @@ -943,17 +943,31 @@ done: | |||
| 943 | } | 943 | } |
| 944 | EXPORT_SYMBOL_GPL(ip_tunnel_ioctl); | 944 | EXPORT_SYMBOL_GPL(ip_tunnel_ioctl); |
| 945 | 945 | ||
| 946 | int ip_tunnel_change_mtu(struct net_device *dev, int new_mtu) | 946 | int __ip_tunnel_change_mtu(struct net_device *dev, int new_mtu, bool strict) |
| 947 | { | 947 | { |
| 948 | struct ip_tunnel *tunnel = netdev_priv(dev); | 948 | struct ip_tunnel *tunnel = netdev_priv(dev); |
| 949 | int t_hlen = tunnel->hlen + sizeof(struct iphdr); | 949 | int t_hlen = tunnel->hlen + sizeof(struct iphdr); |
| 950 | int max_mtu = 0xFFF8 - dev->hard_header_len - t_hlen; | ||
| 950 | 951 | ||
| 951 | if (new_mtu < 68 || | 952 | if (new_mtu < 68) |
| 952 | new_mtu > 0xFFF8 - dev->hard_header_len - t_hlen) | ||
| 953 | return -EINVAL; | 953 | return -EINVAL; |
| 954 | |||
| 955 | if (new_mtu > max_mtu) { | ||
| 956 | if (strict) | ||
| 957 | return -EINVAL; | ||
| 958 | |||
| 959 | new_mtu = max_mtu; | ||
| 960 | } | ||
| 961 | |||
| 954 | dev->mtu = new_mtu; | 962 | dev->mtu = new_mtu; |
| 955 | return 0; | 963 | return 0; |
| 956 | } | 964 | } |
| 965 | EXPORT_SYMBOL_GPL(__ip_tunnel_change_mtu); | ||
| 966 | |||
| 967 | int ip_tunnel_change_mtu(struct net_device *dev, int new_mtu) | ||
| 968 | { | ||
| 969 | return __ip_tunnel_change_mtu(dev, new_mtu, true); | ||
| 970 | } | ||
| 957 | EXPORT_SYMBOL_GPL(ip_tunnel_change_mtu); | 971 | EXPORT_SYMBOL_GPL(ip_tunnel_change_mtu); |
| 958 | 972 | ||
| 959 | static void ip_tunnel_dev_free(struct net_device *dev) | 973 | static void ip_tunnel_dev_free(struct net_device *dev) |
diff --git a/net/ipv4/ipconfig.c b/net/ipv4/ipconfig.c index 67f7c9de0b16..2ed9dd2b5f2f 100644 --- a/net/ipv4/ipconfig.c +++ b/net/ipv4/ipconfig.c | |||
| @@ -143,7 +143,11 @@ static char dhcp_client_identifier[253] __initdata; | |||
| 143 | 143 | ||
| 144 | /* Persistent data: */ | 144 | /* Persistent data: */ |
| 145 | 145 | ||
| 146 | #ifdef IPCONFIG_DYNAMIC | ||
| 146 | static int ic_proto_used; /* Protocol used, if any */ | 147 | static int ic_proto_used; /* Protocol used, if any */ |
| 148 | #else | ||
| 149 | #define ic_proto_used 0 | ||
| 150 | #endif | ||
| 147 | static __be32 ic_nameservers[CONF_NAMESERVERS_MAX]; /* DNS Server IP addresses */ | 151 | static __be32 ic_nameservers[CONF_NAMESERVERS_MAX]; /* DNS Server IP addresses */ |
| 148 | static u8 ic_domain[64]; /* DNS (not NIS) domain name */ | 152 | static u8 ic_domain[64]; /* DNS (not NIS) domain name */ |
| 149 | 153 | ||
diff --git a/net/ipv4/netfilter/nf_defrag_ipv4.c b/net/ipv4/netfilter/nf_defrag_ipv4.c index 6fb869f646bf..a04dee536b8e 100644 --- a/net/ipv4/netfilter/nf_defrag_ipv4.c +++ b/net/ipv4/netfilter/nf_defrag_ipv4.c | |||
| @@ -27,8 +27,6 @@ static int nf_ct_ipv4_gather_frags(struct net *net, struct sk_buff *skb, | |||
| 27 | { | 27 | { |
| 28 | int err; | 28 | int err; |
| 29 | 29 | ||
| 30 | skb_orphan(skb); | ||
| 31 | |||
| 32 | local_bh_disable(); | 30 | local_bh_disable(); |
| 33 | err = ip_defrag(net, skb, user); | 31 | err = ip_defrag(net, skb, user); |
| 34 | local_bh_enable(); | 32 | local_bh_enable(); |
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index fd17eec93525..0c36ef4a3f86 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c | |||
| @@ -279,6 +279,7 @@ | |||
| 279 | 279 | ||
| 280 | #include <asm/uaccess.h> | 280 | #include <asm/uaccess.h> |
| 281 | #include <asm/ioctls.h> | 281 | #include <asm/ioctls.h> |
| 282 | #include <asm/unaligned.h> | ||
| 282 | #include <net/busy_poll.h> | 283 | #include <net/busy_poll.h> |
| 283 | 284 | ||
| 284 | int sysctl_tcp_fin_timeout __read_mostly = TCP_FIN_TIMEOUT; | 285 | int sysctl_tcp_fin_timeout __read_mostly = TCP_FIN_TIMEOUT; |
| @@ -939,7 +940,7 @@ new_segment: | |||
| 939 | 940 | ||
| 940 | i = skb_shinfo(skb)->nr_frags; | 941 | i = skb_shinfo(skb)->nr_frags; |
| 941 | can_coalesce = skb_can_coalesce(skb, i, page, offset); | 942 | can_coalesce = skb_can_coalesce(skb, i, page, offset); |
| 942 | if (!can_coalesce && i >= MAX_SKB_FRAGS) { | 943 | if (!can_coalesce && i >= sysctl_max_skb_frags) { |
| 943 | tcp_mark_push(tp, skb); | 944 | tcp_mark_push(tp, skb); |
| 944 | goto new_segment; | 945 | goto new_segment; |
| 945 | } | 946 | } |
| @@ -1212,7 +1213,7 @@ new_segment: | |||
| 1212 | 1213 | ||
| 1213 | if (!skb_can_coalesce(skb, i, pfrag->page, | 1214 | if (!skb_can_coalesce(skb, i, pfrag->page, |
| 1214 | pfrag->offset)) { | 1215 | pfrag->offset)) { |
| 1215 | if (i == MAX_SKB_FRAGS || !sg) { | 1216 | if (i == sysctl_max_skb_frags || !sg) { |
| 1216 | tcp_mark_push(tp, skb); | 1217 | tcp_mark_push(tp, skb); |
| 1217 | goto new_segment; | 1218 | goto new_segment; |
| 1218 | } | 1219 | } |
| @@ -2638,6 +2639,7 @@ void tcp_get_info(struct sock *sk, struct tcp_info *info) | |||
| 2638 | const struct inet_connection_sock *icsk = inet_csk(sk); | 2639 | const struct inet_connection_sock *icsk = inet_csk(sk); |
| 2639 | u32 now = tcp_time_stamp; | 2640 | u32 now = tcp_time_stamp; |
| 2640 | unsigned int start; | 2641 | unsigned int start; |
| 2642 | u64 rate64; | ||
| 2641 | u32 rate; | 2643 | u32 rate; |
| 2642 | 2644 | ||
| 2643 | memset(info, 0, sizeof(*info)); | 2645 | memset(info, 0, sizeof(*info)); |
| @@ -2703,15 +2705,17 @@ void tcp_get_info(struct sock *sk, struct tcp_info *info) | |||
| 2703 | info->tcpi_total_retrans = tp->total_retrans; | 2705 | info->tcpi_total_retrans = tp->total_retrans; |
| 2704 | 2706 | ||
| 2705 | rate = READ_ONCE(sk->sk_pacing_rate); | 2707 | rate = READ_ONCE(sk->sk_pacing_rate); |
| 2706 | info->tcpi_pacing_rate = rate != ~0U ? rate : ~0ULL; | 2708 | rate64 = rate != ~0U ? rate : ~0ULL; |
| 2709 | put_unaligned(rate64, &info->tcpi_pacing_rate); | ||
| 2707 | 2710 | ||
| 2708 | rate = READ_ONCE(sk->sk_max_pacing_rate); | 2711 | rate = READ_ONCE(sk->sk_max_pacing_rate); |
| 2709 | info->tcpi_max_pacing_rate = rate != ~0U ? rate : ~0ULL; | 2712 | rate64 = rate != ~0U ? rate : ~0ULL; |
| 2713 | put_unaligned(rate64, &info->tcpi_max_pacing_rate); | ||
| 2710 | 2714 | ||
| 2711 | do { | 2715 | do { |
| 2712 | start = u64_stats_fetch_begin_irq(&tp->syncp); | 2716 | start = u64_stats_fetch_begin_irq(&tp->syncp); |
| 2713 | info->tcpi_bytes_acked = tp->bytes_acked; | 2717 | put_unaligned(tp->bytes_acked, &info->tcpi_bytes_acked); |
| 2714 | info->tcpi_bytes_received = tp->bytes_received; | 2718 | put_unaligned(tp->bytes_received, &info->tcpi_bytes_received); |
| 2715 | } while (u64_stats_fetch_retry_irq(&tp->syncp, start)); | 2719 | } while (u64_stats_fetch_retry_irq(&tp->syncp, start)); |
| 2716 | info->tcpi_segs_out = tp->segs_out; | 2720 | info->tcpi_segs_out = tp->segs_out; |
| 2717 | info->tcpi_segs_in = tp->segs_in; | 2721 | info->tcpi_segs_in = tp->segs_in; |
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 0003d409fec5..1c2a73406261 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c | |||
| @@ -2164,8 +2164,7 @@ static void tcp_mark_head_lost(struct sock *sk, int packets, int mark_head) | |||
| 2164 | { | 2164 | { |
| 2165 | struct tcp_sock *tp = tcp_sk(sk); | 2165 | struct tcp_sock *tp = tcp_sk(sk); |
| 2166 | struct sk_buff *skb; | 2166 | struct sk_buff *skb; |
| 2167 | int cnt, oldcnt; | 2167 | int cnt, oldcnt, lost; |
| 2168 | int err; | ||
| 2169 | unsigned int mss; | 2168 | unsigned int mss; |
| 2170 | /* Use SACK to deduce losses of new sequences sent during recovery */ | 2169 | /* Use SACK to deduce losses of new sequences sent during recovery */ |
| 2171 | const u32 loss_high = tcp_is_sack(tp) ? tp->snd_nxt : tp->high_seq; | 2170 | const u32 loss_high = tcp_is_sack(tp) ? tp->snd_nxt : tp->high_seq; |
| @@ -2205,9 +2204,10 @@ static void tcp_mark_head_lost(struct sock *sk, int packets, int mark_head) | |||
| 2205 | break; | 2204 | break; |
| 2206 | 2205 | ||
| 2207 | mss = tcp_skb_mss(skb); | 2206 | mss = tcp_skb_mss(skb); |
| 2208 | err = tcp_fragment(sk, skb, (packets - oldcnt) * mss, | 2207 | /* If needed, chop off the prefix to mark as lost. */ |
| 2209 | mss, GFP_ATOMIC); | 2208 | lost = (packets - oldcnt) * mss; |
| 2210 | if (err < 0) | 2209 | if (lost < skb->len && |
| 2210 | tcp_fragment(sk, skb, lost, mss, GFP_ATOMIC) < 0) | ||
| 2211 | break; | 2211 | break; |
| 2212 | cnt = packets; | 2212 | cnt = packets; |
| 2213 | } | 2213 | } |
| @@ -2366,8 +2366,6 @@ static void tcp_undo_cwnd_reduction(struct sock *sk, bool unmark_loss) | |||
| 2366 | tp->snd_ssthresh = tp->prior_ssthresh; | 2366 | tp->snd_ssthresh = tp->prior_ssthresh; |
| 2367 | tcp_ecn_withdraw_cwr(tp); | 2367 | tcp_ecn_withdraw_cwr(tp); |
| 2368 | } | 2368 | } |
| 2369 | } else { | ||
| 2370 | tp->snd_cwnd = max(tp->snd_cwnd, tp->snd_ssthresh); | ||
| 2371 | } | 2369 | } |
| 2372 | tp->snd_cwnd_stamp = tcp_time_stamp; | 2370 | tp->snd_cwnd_stamp = tcp_time_stamp; |
| 2373 | tp->undo_marker = 0; | 2371 | tp->undo_marker = 0; |
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 5ced3e4013e3..7f6ff037adaf 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c | |||
| @@ -311,7 +311,7 @@ static void do_redirect(struct sk_buff *skb, struct sock *sk) | |||
| 311 | 311 | ||
| 312 | 312 | ||
| 313 | /* handle ICMP messages on TCP_NEW_SYN_RECV request sockets */ | 313 | /* handle ICMP messages on TCP_NEW_SYN_RECV request sockets */ |
| 314 | void tcp_req_err(struct sock *sk, u32 seq) | 314 | void tcp_req_err(struct sock *sk, u32 seq, bool abort) |
| 315 | { | 315 | { |
| 316 | struct request_sock *req = inet_reqsk(sk); | 316 | struct request_sock *req = inet_reqsk(sk); |
| 317 | struct net *net = sock_net(sk); | 317 | struct net *net = sock_net(sk); |
| @@ -323,7 +323,7 @@ void tcp_req_err(struct sock *sk, u32 seq) | |||
| 323 | 323 | ||
| 324 | if (seq != tcp_rsk(req)->snt_isn) { | 324 | if (seq != tcp_rsk(req)->snt_isn) { |
| 325 | NET_INC_STATS_BH(net, LINUX_MIB_OUTOFWINDOWICMPS); | 325 | NET_INC_STATS_BH(net, LINUX_MIB_OUTOFWINDOWICMPS); |
| 326 | } else { | 326 | } else if (abort) { |
| 327 | /* | 327 | /* |
| 328 | * Still in SYN_RECV, just remove it silently. | 328 | * Still in SYN_RECV, just remove it silently. |
| 329 | * There is no good way to pass the error to the newly | 329 | * There is no good way to pass the error to the newly |
| @@ -383,7 +383,12 @@ void tcp_v4_err(struct sk_buff *icmp_skb, u32 info) | |||
| 383 | } | 383 | } |
| 384 | seq = ntohl(th->seq); | 384 | seq = ntohl(th->seq); |
| 385 | if (sk->sk_state == TCP_NEW_SYN_RECV) | 385 | if (sk->sk_state == TCP_NEW_SYN_RECV) |
| 386 | return tcp_req_err(sk, seq); | 386 | return tcp_req_err(sk, seq, |
| 387 | type == ICMP_PARAMETERPROB || | ||
| 388 | type == ICMP_TIME_EXCEEDED || | ||
| 389 | (type == ICMP_DEST_UNREACH && | ||
| 390 | (code == ICMP_NET_UNREACH || | ||
| 391 | code == ICMP_HOST_UNREACH))); | ||
| 387 | 392 | ||
| 388 | bh_lock_sock(sk); | 393 | bh_lock_sock(sk); |
| 389 | /* If too many ICMPs get dropped on busy | 394 | /* If too many ICMPs get dropped on busy |
| @@ -707,7 +712,8 @@ release_sk1: | |||
| 707 | outside socket context is ugly, certainly. What can I do? | 712 | outside socket context is ugly, certainly. What can I do? |
| 708 | */ | 713 | */ |
| 709 | 714 | ||
| 710 | static void tcp_v4_send_ack(struct sk_buff *skb, u32 seq, u32 ack, | 715 | static void tcp_v4_send_ack(struct net *net, |
| 716 | struct sk_buff *skb, u32 seq, u32 ack, | ||
| 711 | u32 win, u32 tsval, u32 tsecr, int oif, | 717 | u32 win, u32 tsval, u32 tsecr, int oif, |
| 712 | struct tcp_md5sig_key *key, | 718 | struct tcp_md5sig_key *key, |
| 713 | int reply_flags, u8 tos) | 719 | int reply_flags, u8 tos) |
| @@ -722,7 +728,6 @@ static void tcp_v4_send_ack(struct sk_buff *skb, u32 seq, u32 ack, | |||
| 722 | ]; | 728 | ]; |
| 723 | } rep; | 729 | } rep; |
| 724 | struct ip_reply_arg arg; | 730 | struct ip_reply_arg arg; |
| 725 | struct net *net = dev_net(skb_dst(skb)->dev); | ||
| 726 | 731 | ||
| 727 | memset(&rep.th, 0, sizeof(struct tcphdr)); | 732 | memset(&rep.th, 0, sizeof(struct tcphdr)); |
| 728 | memset(&arg, 0, sizeof(arg)); | 733 | memset(&arg, 0, sizeof(arg)); |
| @@ -784,7 +789,8 @@ static void tcp_v4_timewait_ack(struct sock *sk, struct sk_buff *skb) | |||
| 784 | struct inet_timewait_sock *tw = inet_twsk(sk); | 789 | struct inet_timewait_sock *tw = inet_twsk(sk); |
| 785 | struct tcp_timewait_sock *tcptw = tcp_twsk(sk); | 790 | struct tcp_timewait_sock *tcptw = tcp_twsk(sk); |
| 786 | 791 | ||
| 787 | tcp_v4_send_ack(skb, tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt, | 792 | tcp_v4_send_ack(sock_net(sk), skb, |
| 793 | tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt, | ||
| 788 | tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale, | 794 | tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale, |
| 789 | tcp_time_stamp + tcptw->tw_ts_offset, | 795 | tcp_time_stamp + tcptw->tw_ts_offset, |
| 790 | tcptw->tw_ts_recent, | 796 | tcptw->tw_ts_recent, |
| @@ -803,8 +809,10 @@ static void tcp_v4_reqsk_send_ack(const struct sock *sk, struct sk_buff *skb, | |||
| 803 | /* sk->sk_state == TCP_LISTEN -> for regular TCP_SYN_RECV | 809 | /* sk->sk_state == TCP_LISTEN -> for regular TCP_SYN_RECV |
| 804 | * sk->sk_state == TCP_SYN_RECV -> for Fast Open. | 810 | * sk->sk_state == TCP_SYN_RECV -> for Fast Open. |
| 805 | */ | 811 | */ |
| 806 | tcp_v4_send_ack(skb, (sk->sk_state == TCP_LISTEN) ? | 812 | u32 seq = (sk->sk_state == TCP_LISTEN) ? tcp_rsk(req)->snt_isn + 1 : |
| 807 | tcp_rsk(req)->snt_isn + 1 : tcp_sk(sk)->snd_nxt, | 813 | tcp_sk(sk)->snd_nxt; |
| 814 | |||
| 815 | tcp_v4_send_ack(sock_net(sk), skb, seq, | ||
| 808 | tcp_rsk(req)->rcv_nxt, req->rsk_rcv_wnd, | 816 | tcp_rsk(req)->rcv_nxt, req->rsk_rcv_wnd, |
| 809 | tcp_time_stamp, | 817 | tcp_time_stamp, |
| 810 | req->ts_recent, | 818 | req->ts_recent, |
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index dc45b538e237..be0b21852b13 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c | |||
| @@ -499,6 +499,7 @@ static struct sock *udp4_lib_lookup2(struct net *net, | |||
| 499 | struct sock *sk, *result; | 499 | struct sock *sk, *result; |
| 500 | struct hlist_nulls_node *node; | 500 | struct hlist_nulls_node *node; |
| 501 | int score, badness, matches = 0, reuseport = 0; | 501 | int score, badness, matches = 0, reuseport = 0; |
| 502 | bool select_ok = true; | ||
| 502 | u32 hash = 0; | 503 | u32 hash = 0; |
| 503 | 504 | ||
| 504 | begin: | 505 | begin: |
| @@ -512,14 +513,18 @@ begin: | |||
| 512 | badness = score; | 513 | badness = score; |
| 513 | reuseport = sk->sk_reuseport; | 514 | reuseport = sk->sk_reuseport; |
| 514 | if (reuseport) { | 515 | if (reuseport) { |
| 515 | struct sock *sk2; | ||
| 516 | hash = udp_ehashfn(net, daddr, hnum, | 516 | hash = udp_ehashfn(net, daddr, hnum, |
| 517 | saddr, sport); | 517 | saddr, sport); |
| 518 | sk2 = reuseport_select_sock(sk, hash, skb, | 518 | if (select_ok) { |
| 519 | sizeof(struct udphdr)); | 519 | struct sock *sk2; |
| 520 | if (sk2) { | 520 | |
| 521 | result = sk2; | 521 | sk2 = reuseport_select_sock(sk, hash, skb, |
| 522 | goto found; | 522 | sizeof(struct udphdr)); |
| 523 | if (sk2) { | ||
| 524 | result = sk2; | ||
| 525 | select_ok = false; | ||
| 526 | goto found; | ||
| 527 | } | ||
| 523 | } | 528 | } |
| 524 | matches = 1; | 529 | matches = 1; |
| 525 | } | 530 | } |
| @@ -563,6 +568,7 @@ struct sock *__udp4_lib_lookup(struct net *net, __be32 saddr, | |||
| 563 | unsigned int hash2, slot2, slot = udp_hashfn(net, hnum, udptable->mask); | 568 | unsigned int hash2, slot2, slot = udp_hashfn(net, hnum, udptable->mask); |
| 564 | struct udp_hslot *hslot2, *hslot = &udptable->hash[slot]; | 569 | struct udp_hslot *hslot2, *hslot = &udptable->hash[slot]; |
| 565 | int score, badness, matches = 0, reuseport = 0; | 570 | int score, badness, matches = 0, reuseport = 0; |
| 571 | bool select_ok = true; | ||
| 566 | u32 hash = 0; | 572 | u32 hash = 0; |
| 567 | 573 | ||
| 568 | rcu_read_lock(); | 574 | rcu_read_lock(); |
| @@ -601,14 +607,18 @@ begin: | |||
| 601 | badness = score; | 607 | badness = score; |
| 602 | reuseport = sk->sk_reuseport; | 608 | reuseport = sk->sk_reuseport; |
| 603 | if (reuseport) { | 609 | if (reuseport) { |
| 604 | struct sock *sk2; | ||
| 605 | hash = udp_ehashfn(net, daddr, hnum, | 610 | hash = udp_ehashfn(net, daddr, hnum, |
| 606 | saddr, sport); | 611 | saddr, sport); |
| 607 | sk2 = reuseport_select_sock(sk, hash, skb, | 612 | if (select_ok) { |
| 613 | struct sock *sk2; | ||
| 614 | |||
| 615 | sk2 = reuseport_select_sock(sk, hash, skb, | ||
| 608 | sizeof(struct udphdr)); | 616 | sizeof(struct udphdr)); |
| 609 | if (sk2) { | 617 | if (sk2) { |
| 610 | result = sk2; | 618 | result = sk2; |
| 611 | goto found; | 619 | select_ok = false; |
| 620 | goto found; | ||
| 621 | } | ||
| 612 | } | 622 | } |
| 613 | matches = 1; | 623 | matches = 1; |
| 614 | } | 624 | } |
