|
@@ -110,8 +110,38 @@ static u32 tcp_v4_init_ts_off(const struct net *net, const struct sk_buff *skb)
|
|
|
|
|
|
int tcp_twsk_unique(struct sock *sk, struct sock *sktw, void *twp)
|
|
|
{
|
|
|
+ const struct inet_timewait_sock *tw = inet_twsk(sktw);
|
|
|
const struct tcp_timewait_sock *tcptw = tcp_twsk(sktw);
|
|
|
struct tcp_sock *tp = tcp_sk(sk);
|
|
|
+ int reuse = sock_net(sk)->ipv4.sysctl_tcp_tw_reuse;
|
|
|
+
|
|
|
+ if (reuse == 2) {
|
|
|
+ /* Still does not detect *everything* that goes through
|
|
|
+ * lo, since we require a loopback src or dst address
|
|
|
+ * or direct binding to 'lo' interface.
|
|
|
+ */
|
|
|
+ bool loopback = false;
|
|
|
+ if (tw->tw_bound_dev_if == LOOPBACK_IFINDEX)
|
|
|
+ loopback = true;
|
|
|
+#if IS_ENABLED(CONFIG_IPV6)
|
|
|
+ if (tw->tw_family == AF_INET6) {
|
|
|
+ if (ipv6_addr_loopback(&tw->tw_v6_daddr) ||
|
|
|
+ (ipv6_addr_v4mapped(&tw->tw_v6_daddr) &&
|
|
|
+ (tw->tw_v6_daddr.s6_addr[12] == 127)) ||
|
|
|
+ ipv6_addr_loopback(&tw->tw_v6_rcv_saddr) ||
|
|
|
+ (ipv6_addr_v4mapped(&tw->tw_v6_rcv_saddr) &&
|
|
|
+ (tw->tw_v6_rcv_saddr.s6_addr[12] == 127)))
|
|
|
+ loopback = true;
|
|
|
+ } else
|
|
|
+#endif
|
|
|
+ {
|
|
|
+ if (ipv4_is_loopback(tw->tw_daddr) ||
|
|
|
+ ipv4_is_loopback(tw->tw_rcv_saddr))
|
|
|
+ loopback = true;
|
|
|
+ }
|
|
|
+ if (!loopback)
|
|
|
+ reuse = 0;
|
|
|
+ }
|
|
|
|
|
|
/* With PAWS, it is safe from the viewpoint
|
|
|
of data integrity. Even without PAWS it is safe provided sequence
|
|
@@ -125,8 +155,7 @@ int tcp_twsk_unique(struct sock *sk, struct sock *sktw, void *twp)
|
|
|
and use initial timestamp retrieved from peer table.
|
|
|
*/
|
|
|
if (tcptw->tw_ts_recent_stamp &&
|
|
|
- (!twp || (sock_net(sk)->ipv4.sysctl_tcp_tw_reuse &&
|
|
|
- get_seconds() - tcptw->tw_ts_recent_stamp > 1))) {
|
|
|
+ (!twp || (reuse && get_seconds() - tcptw->tw_ts_recent_stamp > 1))) {
|
|
|
tp->write_seq = tcptw->tw_snd_nxt + 65535 + 2;
|
|
|
if (tp->write_seq == 0)
|
|
|
tp->write_seq = 1;
|
|
@@ -2529,7 +2558,7 @@ static int __net_init tcp_sk_init(struct net *net)
|
|
|
net->ipv4.sysctl_tcp_orphan_retries = 0;
|
|
|
net->ipv4.sysctl_tcp_fin_timeout = TCP_FIN_TIMEOUT;
|
|
|
net->ipv4.sysctl_tcp_notsent_lowat = UINT_MAX;
|
|
|
- net->ipv4.sysctl_tcp_tw_reuse = 0;
|
|
|
+ net->ipv4.sysctl_tcp_tw_reuse = 2;
|
|
|
|
|
|
cnt = tcp_hashinfo.ehash_mask + 1;
|
|
|
net->ipv4.tcp_death_row.sysctl_max_tw_buckets = (cnt + 1) / 2;
|