diff options
Diffstat (limited to 'net/ipv4')
-rw-r--r-- | net/ipv4/tcp_ipv4.c | 10 | ||||
-rw-r--r-- | net/ipv4/tcp_minisocks.c | 27 |
2 files changed, 20 insertions, 17 deletions
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 77f049d00dbb..fda2ca17135e 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c | |||
@@ -1835,20 +1835,10 @@ struct inet_peer *tcp_v4_get_peer(struct sock *sk) | |||
1835 | } | 1835 | } |
1836 | EXPORT_SYMBOL(tcp_v4_get_peer); | 1836 | EXPORT_SYMBOL(tcp_v4_get_peer); |
1837 | 1837 | ||
1838 | void *tcp_v4_tw_get_peer(struct sock *sk) | ||
1839 | { | ||
1840 | const struct inet_timewait_sock *tw = inet_twsk(sk); | ||
1841 | struct net *net = sock_net(sk); | ||
1842 | |||
1843 | return inet_getpeer_v4(net, tw->tw_daddr, 1); | ||
1844 | } | ||
1845 | EXPORT_SYMBOL(tcp_v4_tw_get_peer); | ||
1846 | |||
1847 | static struct timewait_sock_ops tcp_timewait_sock_ops = { | 1838 | static struct timewait_sock_ops tcp_timewait_sock_ops = { |
1848 | .twsk_obj_size = sizeof(struct tcp_timewait_sock), | 1839 | .twsk_obj_size = sizeof(struct tcp_timewait_sock), |
1849 | .twsk_unique = tcp_twsk_unique, | 1840 | .twsk_unique = tcp_twsk_unique, |
1850 | .twsk_destructor= tcp_twsk_destructor, | 1841 | .twsk_destructor= tcp_twsk_destructor, |
1851 | .twsk_getpeer = tcp_v4_tw_get_peer, | ||
1852 | }; | 1842 | }; |
1853 | 1843 | ||
1854 | const struct inet_connection_sock_af_ops ipv4_specific = { | 1844 | const struct inet_connection_sock_af_ops ipv4_specific = { |
diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c index fef9dbf3af00..cb015317c9f7 100644 --- a/net/ipv4/tcp_minisocks.c +++ b/net/ipv4/tcp_minisocks.c | |||
@@ -77,20 +77,19 @@ static bool tcp_remember_stamp(struct sock *sk) | |||
77 | 77 | ||
78 | static bool tcp_tw_remember_stamp(struct inet_timewait_sock *tw) | 78 | static bool tcp_tw_remember_stamp(struct inet_timewait_sock *tw) |
79 | { | 79 | { |
80 | const struct tcp_timewait_sock *tcptw; | ||
80 | struct sock *sk = (struct sock *) tw; | 81 | struct sock *sk = (struct sock *) tw; |
81 | struct inet_peer *peer; | 82 | struct inet_peer *peer; |
82 | 83 | ||
83 | peer = twsk_getpeer(sk); | 84 | tcptw = tcp_twsk(sk); |
85 | peer = tcptw->tw_peer; | ||
84 | if (peer) { | 86 | if (peer) { |
85 | const struct tcp_timewait_sock *tcptw = tcp_twsk(sk); | ||
86 | |||
87 | if ((s32)(peer->tcp_ts - tcptw->tw_ts_recent) <= 0 || | 87 | if ((s32)(peer->tcp_ts - tcptw->tw_ts_recent) <= 0 || |
88 | ((u32)get_seconds() - peer->tcp_ts_stamp > TCP_PAWS_MSL && | 88 | ((u32)get_seconds() - peer->tcp_ts_stamp > TCP_PAWS_MSL && |
89 | peer->tcp_ts_stamp <= (u32)tcptw->tw_ts_recent_stamp)) { | 89 | peer->tcp_ts_stamp <= (u32)tcptw->tw_ts_recent_stamp)) { |
90 | peer->tcp_ts_stamp = (u32)tcptw->tw_ts_recent_stamp; | 90 | peer->tcp_ts_stamp = (u32)tcptw->tw_ts_recent_stamp; |
91 | peer->tcp_ts = tcptw->tw_ts_recent; | 91 | peer->tcp_ts = tcptw->tw_ts_recent; |
92 | } | 92 | } |
93 | inet_putpeer(peer); | ||
94 | return true; | 93 | return true; |
95 | } | 94 | } |
96 | return false; | 95 | return false; |
@@ -314,9 +313,12 @@ void tcp_time_wait(struct sock *sk, int state, int timeo) | |||
314 | const struct inet_connection_sock *icsk = inet_csk(sk); | 313 | const struct inet_connection_sock *icsk = inet_csk(sk); |
315 | const struct tcp_sock *tp = tcp_sk(sk); | 314 | const struct tcp_sock *tp = tcp_sk(sk); |
316 | bool recycle_ok = false; | 315 | bool recycle_ok = false; |
316 | bool recycle_on = false; | ||
317 | 317 | ||
318 | if (tcp_death_row.sysctl_tw_recycle && tp->rx_opt.ts_recent_stamp) | 318 | if (tcp_death_row.sysctl_tw_recycle && tp->rx_opt.ts_recent_stamp) { |
319 | recycle_ok = tcp_remember_stamp(sk); | 319 | recycle_ok = tcp_remember_stamp(sk); |
320 | recycle_on = true; | ||
321 | } | ||
320 | 322 | ||
321 | if (tcp_death_row.tw_count < tcp_death_row.sysctl_max_tw_buckets) | 323 | if (tcp_death_row.tw_count < tcp_death_row.sysctl_max_tw_buckets) |
322 | tw = inet_twsk_alloc(sk, state); | 324 | tw = inet_twsk_alloc(sk, state); |
@@ -324,8 +326,10 @@ void tcp_time_wait(struct sock *sk, int state, int timeo) | |||
324 | if (tw != NULL) { | 326 | if (tw != NULL) { |
325 | struct tcp_timewait_sock *tcptw = tcp_twsk((struct sock *)tw); | 327 | struct tcp_timewait_sock *tcptw = tcp_twsk((struct sock *)tw); |
326 | const int rto = (icsk->icsk_rto << 2) - (icsk->icsk_rto >> 1); | 328 | const int rto = (icsk->icsk_rto << 2) - (icsk->icsk_rto >> 1); |
329 | struct inet_sock *inet = inet_sk(sk); | ||
330 | struct inet_peer *peer = NULL; | ||
327 | 331 | ||
328 | tw->tw_transparent = inet_sk(sk)->transparent; | 332 | tw->tw_transparent = inet->transparent; |
329 | tw->tw_rcv_wscale = tp->rx_opt.rcv_wscale; | 333 | tw->tw_rcv_wscale = tp->rx_opt.rcv_wscale; |
330 | tcptw->tw_rcv_nxt = tp->rcv_nxt; | 334 | tcptw->tw_rcv_nxt = tp->rcv_nxt; |
331 | tcptw->tw_snd_nxt = tp->snd_nxt; | 335 | tcptw->tw_snd_nxt = tp->snd_nxt; |
@@ -347,6 +351,12 @@ void tcp_time_wait(struct sock *sk, int state, int timeo) | |||
347 | } | 351 | } |
348 | #endif | 352 | #endif |
349 | 353 | ||
354 | if (recycle_on) | ||
355 | peer = icsk->icsk_af_ops->get_peer(sk); | ||
356 | tcptw->tw_peer = peer; | ||
357 | if (peer) | ||
358 | atomic_inc(&peer->refcnt); | ||
359 | |||
350 | #ifdef CONFIG_TCP_MD5SIG | 360 | #ifdef CONFIG_TCP_MD5SIG |
351 | /* | 361 | /* |
352 | * The timewait bucket does not have the key DB from the | 362 | * The timewait bucket does not have the key DB from the |
@@ -398,8 +408,11 @@ void tcp_time_wait(struct sock *sk, int state, int timeo) | |||
398 | 408 | ||
399 | void tcp_twsk_destructor(struct sock *sk) | 409 | void tcp_twsk_destructor(struct sock *sk) |
400 | { | 410 | { |
401 | #ifdef CONFIG_TCP_MD5SIG | ||
402 | struct tcp_timewait_sock *twsk = tcp_twsk(sk); | 411 | struct tcp_timewait_sock *twsk = tcp_twsk(sk); |
412 | |||
413 | if (twsk->tw_peer) | ||
414 | inet_putpeer(twsk->tw_peer); | ||
415 | #ifdef CONFIG_TCP_MD5SIG | ||
403 | if (twsk->tw_md5_key) { | 416 | if (twsk->tw_md5_key) { |
404 | tcp_free_md5sig_pool(); | 417 | tcp_free_md5sig_pool(); |
405 | kfree_rcu(twsk->tw_md5_key, rcu); | 418 | kfree_rcu(twsk->tw_md5_key, rcu); |