Blame view

net/ipv4/tcp_minisocks.c 24.1 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
  /*
   * INET		An implementation of the TCP/IP protocol suite for the LINUX
   *		operating system.  INET is implemented using the  BSD Socket
   *		interface as the means of communication with the user level.
   *
   *		Implementation of the Transmission Control Protocol(TCP).
   *
02c30a84e   Jesper Juhl   [PATCH] update Ro...
8
   * Authors:	Ross Biro
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
9
10
11
12
13
14
15
16
17
18
19
   *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
   *		Mark Evans, <evansmp@uhura.aston.ac.uk>
   *		Corey Minyard <wf-rch!minyard@relay.EU.net>
   *		Florian La Roche, <flla@stud.uni-sb.de>
   *		Charles Hedrick, <hedrick@klinzhai.rutgers.edu>
   *		Linus Torvalds, <torvalds@cs.helsinki.fi>
   *		Alan Cox, <gw4pts@gw4pts.ampr.org>
   *		Matthew Dillon, <dillon@apollo.west.oic.com>
   *		Arnt Gulbrandsen, <agulbra@nvg.unit.no>
   *		Jorge Cwik, <jorge@laser.satlink.net>
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
20
21
  #include <linux/mm.h>
  #include <linux/module.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
22
  #include <linux/slab.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
23
24
25
26
27
  #include <linux/sysctl.h>
  #include <linux/workqueue.h>
  #include <net/tcp.h>
  #include <net/inet_common.h>
  #include <net/xfrm.h>
e994b7c90   David S. Miller   tcp: Don't make s...
28
  int sysctl_tcp_syncookies __read_mostly = 1;
c6aefafb7   Glenn Griffin   [TCP]: Add IPv6 s...
29
  EXPORT_SYMBOL(sysctl_tcp_syncookies);
ab32ea5d8   Brian Haley   [NET/IPV4/IPV6]: ...
30
  int sysctl_tcp_abort_on_overflow __read_mostly;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
31

295ff7edb   Arnaldo Carvalho de Melo   [TIMEWAIT]: Intro...
32
33
34
  struct inet_timewait_death_row tcp_death_row = {
  	.sysctl_max_tw_buckets = NR_FILE * 2,
  	.period		= TCP_TIMEWAIT_LEN / INET_TWDR_TWKILL_SLOTS,
e4d919188   Ingo Molnar   [PATCH] lockdep: ...
35
  	.death_lock	= __SPIN_LOCK_UNLOCKED(tcp_death_row.death_lock),
295ff7edb   Arnaldo Carvalho de Melo   [TIMEWAIT]: Intro...
36
37
38
39
  	.hashinfo	= &tcp_hashinfo,
  	.tw_timer	= TIMER_INITIALIZER(inet_twdr_hangman, 0,
  					    (unsigned long)&tcp_death_row),
  	.twkill_work	= __WORK_INITIALIZER(tcp_death_row.twkill_work,
65f27f384   David Howells   WorkStruct: Pass ...
40
  					     inet_twdr_twkill_work),
295ff7edb   Arnaldo Carvalho de Melo   [TIMEWAIT]: Intro...
41
42
43
44
45
46
  /* Short-time timewait calendar */
  
  	.twcal_hand	= -1,
  	.twcal_timer	= TIMER_INITIALIZER(inet_twdr_twcal_tick, 0,
  					    (unsigned long)&tcp_death_row),
  };
295ff7edb   Arnaldo Carvalho de Melo   [TIMEWAIT]: Intro...
47
  EXPORT_SYMBOL_GPL(tcp_death_row);
3f419d2d4   David S. Miller   inet: Turn ->reme...
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
  /* VJ's idea. Save last timestamp seen from this destination
   * and hold it at least for normal timewait interval to use for duplicate
   * segment detection in subsequent connections, before they enter synchronized
   * state.
   */
  
  static int tcp_remember_stamp(struct sock *sk)
  {
  	const struct inet_connection_sock *icsk = inet_csk(sk);
  	struct tcp_sock *tp = tcp_sk(sk);
  	struct inet_peer *peer;
  	bool release_it;
  
  	peer = icsk->icsk_af_ops->get_peer(sk, &release_it);
  	if (peer) {
  		if ((s32)(peer->tcp_ts - tp->rx_opt.ts_recent) <= 0 ||
  		    ((u32)get_seconds() - peer->tcp_ts_stamp > TCP_PAWS_MSL &&
  		     peer->tcp_ts_stamp <= (u32)tp->rx_opt.ts_recent_stamp)) {
  			peer->tcp_ts_stamp = (u32)tp->rx_opt.ts_recent_stamp;
  			peer->tcp_ts = tp->rx_opt.ts_recent;
  		}
  		if (release_it)
  			inet_putpeer(peer);
  		return 1;
  	}
  
  	return 0;
  }
ccb7c410d   David S. Miller   timewait_sock: Cr...
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
  static int tcp_tw_remember_stamp(struct inet_timewait_sock *tw)
  {
  	struct sock *sk = (struct sock *) tw;
  	struct inet_peer *peer;
  
  	peer = twsk_getpeer(sk);
  	if (peer) {
  		const struct tcp_timewait_sock *tcptw = tcp_twsk(sk);
  
  		if ((s32)(peer->tcp_ts - tcptw->tw_ts_recent) <= 0 ||
  		    ((u32)get_seconds() - peer->tcp_ts_stamp > TCP_PAWS_MSL &&
  		     peer->tcp_ts_stamp <= (u32)tcptw->tw_ts_recent_stamp)) {
  			peer->tcp_ts_stamp = (u32)tcptw->tw_ts_recent_stamp;
  			peer->tcp_ts	   = tcptw->tw_ts_recent;
  		}
  		inet_putpeer(peer);
  		return 1;
  	}
  	return 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
96
97
98
99
100
101
  static __inline__ int tcp_in_window(u32 seq, u32 end_seq, u32 s_win, u32 e_win)
  {
  	if (seq == s_win)
  		return 1;
  	if (after(end_seq, s_win) && before(seq, e_win))
  		return 1;
a02cec215   Eric Dumazet   net: return opera...
102
  	return seq == e_win && seq == end_seq;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
103
  }
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
104
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
   * * Main purpose of TIME-WAIT state is to close connection gracefully,
   *   when one of ends sits in LAST-ACK or CLOSING retransmitting FIN
   *   (and, probably, tail of data) and one or more our ACKs are lost.
   * * What is TIME-WAIT timeout? It is associated with maximal packet
   *   lifetime in the internet, which results in wrong conclusion, that
   *   it is set to catch "old duplicate segments" wandering out of their path.
   *   It is not quite correct. This timeout is calculated so that it exceeds
   *   maximal retransmission timeout enough to allow to lose one (or more)
   *   segments sent by peer and our ACKs. This time may be calculated from RTO.
   * * When TIME-WAIT socket receives RST, it means that another end
   *   finally closed and we are allowed to kill TIME-WAIT too.
   * * Second purpose of TIME-WAIT is catching old duplicate segments.
   *   Well, certainly it is pure paranoia, but if we load TIME-WAIT
   *   with this semantics, we MUST NOT kill TIME-WAIT state with RSTs.
   * * If we invented some more clever way to catch duplicates
   *   (f.e. based on PAWS), we could truncate TIME-WAIT to several RTOs.
   *
   * The algorithm below is based on FORMAL INTERPRETATION of RFCs.
   * When you compare it to RFCs, please, read section SEGMENT ARRIVES
   * from the very beginning.
   *
   * NOTE. With recycling (and later with fin-wait-2) TW bucket
   * is _not_ stateless. It means, that strictly speaking we must
   * spinlock it. I do not want! Well, probability of misbehaviour
   * is ridiculously low and, seems, we could use some mb() tricks
   * to avoid misread sequence numbers, states etc.  --ANK
   */
  enum tcp_tw_status
8feaf0c0a   Arnaldo Carvalho de Melo   [INET]: Generalis...
133
134
  tcp_timewait_state_process(struct inet_timewait_sock *tw, struct sk_buff *skb,
  			   const struct tcphdr *th)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
135
136
  {
  	struct tcp_options_received tmp_opt;
4957faade   William Allen Simpson   TCPCT part 1g: Re...
137
138
  	u8 *hash_location;
  	struct tcp_timewait_sock *tcptw = tcp_twsk((struct sock *)tw);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
139
  	int paws_reject = 0;
bb5b7c112   David S. Miller   tcp: Revert per-r...
140
  	tmp_opt.saw_tstamp = 0;
8feaf0c0a   Arnaldo Carvalho de Melo   [INET]: Generalis...
141
  	if (th->doff > (sizeof(*th) >> 2) && tcptw->tw_ts_recent_stamp) {
bb5b7c112   David S. Miller   tcp: Revert per-r...
142
  		tcp_parse_options(skb, &tmp_opt, &hash_location, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
143
144
  
  		if (tmp_opt.saw_tstamp) {
8feaf0c0a   Arnaldo Carvalho de Melo   [INET]: Generalis...
145
146
  			tmp_opt.ts_recent	= tcptw->tw_ts_recent;
  			tmp_opt.ts_recent_stamp	= tcptw->tw_ts_recent_stamp;
c887e6d2d   Ilpo Järvinen   tcp: consolidate ...
147
  			paws_reject = tcp_paws_reject(&tmp_opt, th->rst);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
148
149
150
151
152
153
154
155
156
  		}
  	}
  
  	if (tw->tw_substate == TCP_FIN_WAIT2) {
  		/* Just repeat all the checks of tcp_rcv_state_process() */
  
  		/* Out of window, send ACK */
  		if (paws_reject ||
  		    !tcp_in_window(TCP_SKB_CB(skb)->seq, TCP_SKB_CB(skb)->end_seq,
8feaf0c0a   Arnaldo Carvalho de Melo   [INET]: Generalis...
157
158
  				   tcptw->tw_rcv_nxt,
  				   tcptw->tw_rcv_nxt + tcptw->tw_rcv_wnd))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
159
160
161
162
  			return TCP_TW_ACK;
  
  		if (th->rst)
  			goto kill;
8feaf0c0a   Arnaldo Carvalho de Melo   [INET]: Generalis...
163
  		if (th->syn && !before(TCP_SKB_CB(skb)->seq, tcptw->tw_rcv_nxt))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
164
165
166
  			goto kill_with_rst;
  
  		/* Dup ACK? */
1ac530b35   Wei Yongjun   tcp: missing chec...
167
168
  		if (!th->ack ||
  		    !after(TCP_SKB_CB(skb)->end_seq, tcptw->tw_rcv_nxt) ||
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
169
  		    TCP_SKB_CB(skb)->end_seq == TCP_SKB_CB(skb)->seq) {
8feaf0c0a   Arnaldo Carvalho de Melo   [INET]: Generalis...
170
  			inet_twsk_put(tw);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
171
172
173
174
175
176
177
  			return TCP_TW_SUCCESS;
  		}
  
  		/* New data or FIN. If new data arrive after half-duplex close,
  		 * reset.
  		 */
  		if (!th->fin ||
8feaf0c0a   Arnaldo Carvalho de Melo   [INET]: Generalis...
178
  		    TCP_SKB_CB(skb)->end_seq != tcptw->tw_rcv_nxt + 1) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
179
  kill_with_rst:
295ff7edb   Arnaldo Carvalho de Melo   [TIMEWAIT]: Intro...
180
  			inet_twsk_deschedule(tw, &tcp_death_row);
8feaf0c0a   Arnaldo Carvalho de Melo   [INET]: Generalis...
181
  			inet_twsk_put(tw);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
182
183
184
185
  			return TCP_TW_RST;
  		}
  
  		/* FIN arrived, enter true time-wait state. */
8feaf0c0a   Arnaldo Carvalho de Melo   [INET]: Generalis...
186
187
  		tw->tw_substate	  = TCP_TIME_WAIT;
  		tcptw->tw_rcv_nxt = TCP_SKB_CB(skb)->end_seq;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
188
  		if (tmp_opt.saw_tstamp) {
9d729f72d   James Morris   [NET]: Convert xt...
189
  			tcptw->tw_ts_recent_stamp = get_seconds();
8feaf0c0a   Arnaldo Carvalho de Melo   [INET]: Generalis...
190
  			tcptw->tw_ts_recent	  = tmp_opt.rcv_tsval;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
191
  		}
ccb7c410d   David S. Miller   timewait_sock: Cr...
192
193
194
  		if (tcp_death_row.sysctl_tw_recycle &&
  		    tcptw->tw_ts_recent_stamp &&
  		    tcp_tw_remember_stamp(tw))
696ab2d3b   Arnaldo Carvalho de Melo   [TIMEWAIT]: Move ...
195
196
  			inet_twsk_schedule(tw, &tcp_death_row, tw->tw_timeout,
  					   TCP_TIMEWAIT_LEN);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
197
  		else
696ab2d3b   Arnaldo Carvalho de Melo   [TIMEWAIT]: Move ...
198
199
  			inet_twsk_schedule(tw, &tcp_death_row, TCP_TIMEWAIT_LEN,
  					   TCP_TIMEWAIT_LEN);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
200
201
202
203
204
205
206
207
208
209
  		return TCP_TW_ACK;
  	}
  
  	/*
  	 *	Now real TIME-WAIT state.
  	 *
  	 *	RFC 1122:
  	 *	"When a connection is [...] on TIME-WAIT state [...]
  	 *	[a TCP] MAY accept a new SYN from the remote TCP to
  	 *	reopen the connection directly, if it:
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
210
  	 *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
211
212
213
214
215
  	 *	(1)  assigns its initial sequence number for the new
  	 *	connection to be larger than the largest sequence
  	 *	number it used on the previous connection incarnation,
  	 *	and
  	 *
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
216
  	 *	(2)  returns to TIME-WAIT state if the SYN turns out
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
217
218
219
220
  	 *	to be an old duplicate".
  	 */
  
  	if (!paws_reject &&
8feaf0c0a   Arnaldo Carvalho de Melo   [INET]: Generalis...
221
  	    (TCP_SKB_CB(skb)->seq == tcptw->tw_rcv_nxt &&
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
222
223
224
225
  	     (TCP_SKB_CB(skb)->seq == TCP_SKB_CB(skb)->end_seq || th->rst))) {
  		/* In window segment, it may be only reset or bare ack. */
  
  		if (th->rst) {
caa20d9ab   Stephen Hemminger   [TCP]: spelling f...
226
  			/* This is TIME_WAIT assassination, in two flavors.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
227
228
229
230
231
  			 * Oh well... nobody has a sufficient solution to this
  			 * protocol bug yet.
  			 */
  			if (sysctl_tcp_rfc1337 == 0) {
  kill:
295ff7edb   Arnaldo Carvalho de Melo   [TIMEWAIT]: Intro...
232
  				inet_twsk_deschedule(tw, &tcp_death_row);
8feaf0c0a   Arnaldo Carvalho de Melo   [INET]: Generalis...
233
  				inet_twsk_put(tw);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
234
235
236
  				return TCP_TW_SUCCESS;
  			}
  		}
696ab2d3b   Arnaldo Carvalho de Melo   [TIMEWAIT]: Move ...
237
238
  		inet_twsk_schedule(tw, &tcp_death_row, TCP_TIMEWAIT_LEN,
  				   TCP_TIMEWAIT_LEN);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
239
240
  
  		if (tmp_opt.saw_tstamp) {
8feaf0c0a   Arnaldo Carvalho de Melo   [INET]: Generalis...
241
  			tcptw->tw_ts_recent	  = tmp_opt.rcv_tsval;
9d729f72d   James Morris   [NET]: Convert xt...
242
  			tcptw->tw_ts_recent_stamp = get_seconds();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
243
  		}
8feaf0c0a   Arnaldo Carvalho de Melo   [INET]: Generalis...
244
  		inet_twsk_put(tw);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
  		return TCP_TW_SUCCESS;
  	}
  
  	/* Out of window segment.
  
  	   All the segments are ACKed immediately.
  
  	   The only exception is new SYN. We accept it, if it is
  	   not old duplicate and we are not in danger to be killed
  	   by delayed old duplicates. RFC check is that it has
  	   newer sequence number works at rates <40Mbit/sec.
  	   However, if paws works, it is reliable AND even more,
  	   we even may relax silly seq space cutoff.
  
  	   RED-PEN: we violate main RFC requirement, if this SYN will appear
  	   old duplicate (i.e. we receive RST in reply to SYN-ACK),
  	   we must return socket to time-wait state. It is not good,
  	   but not fatal yet.
  	 */
  
  	if (th->syn && !th->rst && !th->ack && !paws_reject &&
8feaf0c0a   Arnaldo Carvalho de Melo   [INET]: Generalis...
266
267
268
269
  	    (after(TCP_SKB_CB(skb)->seq, tcptw->tw_rcv_nxt) ||
  	     (tmp_opt.saw_tstamp &&
  	      (s32)(tcptw->tw_ts_recent - tmp_opt.rcv_tsval) < 0))) {
  		u32 isn = tcptw->tw_snd_nxt + 65535 + 2;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
270
271
272
273
274
275
276
  		if (isn == 0)
  			isn++;
  		TCP_SKB_CB(skb)->when = isn;
  		return TCP_TW_SYN;
  	}
  
  	if (paws_reject)
de0744af1   Pavel Emelyanov   mib: add net to N...
277
  		NET_INC_STATS_BH(twsk_net(tw), LINUX_MIB_PAWSESTABREJECTED);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
278

2de979bd7   Stephen Hemminger   [TCP]: whitespace...
279
  	if (!th->rst) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
280
281
282
283
284
285
286
  		/* In this case we must reset the TIMEWAIT timer.
  		 *
  		 * If it is ACKless SYN it may be both old duplicate
  		 * and new good SYN with random sequence number <rcv_nxt.
  		 * Do not reschedule in the last case.
  		 */
  		if (paws_reject || th->ack)
696ab2d3b   Arnaldo Carvalho de Melo   [TIMEWAIT]: Move ...
287
288
  			inet_twsk_schedule(tw, &tcp_death_row, TCP_TIMEWAIT_LEN,
  					   TCP_TIMEWAIT_LEN);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
289
290
291
292
293
294
  
  		/* Send ACK. Note, we do not put the bucket,
  		 * it will be released by caller.
  		 */
  		return TCP_TW_ACK;
  	}
8feaf0c0a   Arnaldo Carvalho de Melo   [INET]: Generalis...
295
  	inet_twsk_put(tw);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
296
297
  	return TCP_TW_SUCCESS;
  }
4bc2f18ba   Eric Dumazet   net/ipv4: EXPORT_...
298
  EXPORT_SYMBOL(tcp_timewait_state_process);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
299

e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
300
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
301
   * Move a socket to time-wait or dead fin-wait-2 state.
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
302
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
303
304
  void tcp_time_wait(struct sock *sk, int state, int timeo)
  {
8feaf0c0a   Arnaldo Carvalho de Melo   [INET]: Generalis...
305
  	struct inet_timewait_sock *tw = NULL;
8292a17a3   Arnaldo Carvalho de Melo   [ICSK]: Rename st...
306
  	const struct inet_connection_sock *icsk = inet_csk(sk);
8feaf0c0a   Arnaldo Carvalho de Melo   [INET]: Generalis...
307
  	const struct tcp_sock *tp = tcp_sk(sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
308
  	int recycle_ok = 0;
295ff7edb   Arnaldo Carvalho de Melo   [TIMEWAIT]: Intro...
309
  	if (tcp_death_row.sysctl_tw_recycle && tp->rx_opt.ts_recent_stamp)
3f419d2d4   David S. Miller   inet: Turn ->reme...
310
  		recycle_ok = tcp_remember_stamp(sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
311

295ff7edb   Arnaldo Carvalho de Melo   [TIMEWAIT]: Intro...
312
  	if (tcp_death_row.tw_count < tcp_death_row.sysctl_max_tw_buckets)
c676270bc   Arnaldo Carvalho de Melo   [INET_TWSK]: Intr...
313
  		tw = inet_twsk_alloc(sk, state);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
314

8feaf0c0a   Arnaldo Carvalho de Melo   [INET]: Generalis...
315
316
  	if (tw != NULL) {
  		struct tcp_timewait_sock *tcptw = tcp_twsk((struct sock *)tw);
463c84b97   Arnaldo Carvalho de Melo   [NET]: Introduce ...
317
  		const int rto = (icsk->icsk_rto << 2) - (icsk->icsk_rto >> 1);
8feaf0c0a   Arnaldo Carvalho de Melo   [INET]: Generalis...
318

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
319
  		tw->tw_rcv_wscale	= tp->rx_opt.rcv_wscale;
8feaf0c0a   Arnaldo Carvalho de Melo   [INET]: Generalis...
320
321
322
323
324
  		tcptw->tw_rcv_nxt	= tp->rcv_nxt;
  		tcptw->tw_snd_nxt	= tp->snd_nxt;
  		tcptw->tw_rcv_wnd	= tcp_receive_window(tp);
  		tcptw->tw_ts_recent	= tp->rx_opt.ts_recent;
  		tcptw->tw_ts_recent_stamp = tp->rx_opt.ts_recent_stamp;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
325
326
327
328
  
  #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
  		if (tw->tw_family == PF_INET6) {
  			struct ipv6_pinfo *np = inet6_sk(sk);
0fa1a53e1   Arnaldo Carvalho de Melo   [IPV6]: Introduce...
329
  			struct inet6_timewait_sock *tw6;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
330

0fa1a53e1   Arnaldo Carvalho de Melo   [IPV6]: Introduce...
331
332
333
334
  			tw->tw_ipv6_offset = inet6_tw_offset(sk->sk_prot);
  			tw6 = inet6_twsk((struct sock *)tw);
  			ipv6_addr_copy(&tw6->tw_v6_daddr, &np->daddr);
  			ipv6_addr_copy(&tw6->tw_v6_rcv_saddr, &np->rcv_saddr);
8feaf0c0a   Arnaldo Carvalho de Melo   [INET]: Generalis...
335
  			tw->tw_ipv6only = np->ipv6only;
c676270bc   Arnaldo Carvalho de Melo   [INET_TWSK]: Intr...
336
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
337
  #endif
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
  
  #ifdef CONFIG_TCP_MD5SIG
  		/*
  		 * The timewait bucket does not have the key DB from the
  		 * sock structure. We just make a quick copy of the
  		 * md5 key being used (if indeed we are using one)
  		 * so the timewait ack generating code has the key.
  		 */
  		do {
  			struct tcp_md5sig_key *key;
  			memset(tcptw->tw_md5_key, 0, sizeof(tcptw->tw_md5_key));
  			tcptw->tw_md5_keylen = 0;
  			key = tp->af_specific->md5_lookup(sk, sk);
  			if (key != NULL) {
  				memcpy(&tcptw->tw_md5_key, key->key, key->keylen);
  				tcptw->tw_md5_keylen = key->keylen;
aa1330766   Wu Fengguang   tcp: replace hard...
354
  				if (tcp_alloc_md5sig_pool(sk) == NULL)
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
355
356
  					BUG();
  			}
2de979bd7   Stephen Hemminger   [TCP]: whitespace...
357
  		} while (0);
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
358
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
359
  		/* Linkage updates. */
e48c414ee   Arnaldo Carvalho de Melo   [INET]: Generalis...
360
  		__inet_twsk_hashdance(tw, sk, &tcp_hashinfo);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
361
362
363
364
365
366
367
368
369
370
371
372
  
  		/* Get the TIME_WAIT timeout firing. */
  		if (timeo < rto)
  			timeo = rto;
  
  		if (recycle_ok) {
  			tw->tw_timeout = rto;
  		} else {
  			tw->tw_timeout = TCP_TIMEWAIT_LEN;
  			if (state == TCP_TIME_WAIT)
  				timeo = TCP_TIMEWAIT_LEN;
  		}
696ab2d3b   Arnaldo Carvalho de Melo   [TIMEWAIT]: Move ...
373
374
  		inet_twsk_schedule(tw, &tcp_death_row, timeo,
  				   TCP_TIMEWAIT_LEN);
8feaf0c0a   Arnaldo Carvalho de Melo   [INET]: Generalis...
375
  		inet_twsk_put(tw);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
376
377
378
379
380
  	} else {
  		/* Sorry, if we're out of memory, just CLOSE this
  		 * socket up.  We've got bigger problems than
  		 * non-graceful socket closings.
  		 */
67631510a   Tom Herbert   tcp: Replace time...
381
  		NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPTIMEWAITOVERFLOW);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
382
383
384
385
386
  	}
  
  	tcp_update_metrics(sk);
  	tcp_done(sk);
  }
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
387
388
  void tcp_twsk_destructor(struct sock *sk)
  {
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
389
  #ifdef CONFIG_TCP_MD5SIG
a928630a2   David S. Miller   [TCP]: Fix some w...
390
  	struct tcp_timewait_sock *twsk = tcp_twsk(sk);
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
391
  	if (twsk->tw_md5_keylen)
657e9649e   Robert Varga   tcp: fix CONFIG_T...
392
  		tcp_free_md5sig_pool();
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
393
394
  #endif
  }
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
395
  EXPORT_SYMBOL_GPL(tcp_twsk_destructor);
bdf1ee5d3   Ilpo Järvinen   [TCP]: Move code ...
396
397
398
399
400
  static inline void TCP_ECN_openreq_child(struct tcp_sock *tp,
  					 struct request_sock *req)
  {
  	tp->ecn_flags = inet_rsk(req)->ecn_ok ? TCP_ECN_OK : 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
401
402
403
404
405
406
  /* This is not only more efficient than what we used to do, it eliminates
   * a lot of code duplication between IPv4/IPv6 SYN recv processing. -DaveM
   *
   * Actually, we could lots of memory writes here. tp of listening
   * socket contains all necessary default parameters.
   */
60236fdd0   Arnaldo Carvalho de Melo   [NET] Rename open...
407
  struct sock *tcp_create_openreq_child(struct sock *sk, struct request_sock *req, struct sk_buff *skb)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
408
  {
9f1d2604c   Arnaldo Carvalho de Melo   [ICSK]: Introduce...
409
  	struct sock *newsk = inet_csk_clone(sk, req, GFP_ATOMIC);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
410

87d11ceb9   Arnaldo Carvalho de Melo   [SOCK]: Introduce...
411
  	if (newsk != NULL) {
9f1d2604c   Arnaldo Carvalho de Melo   [ICSK]: Introduce...
412
  		const struct inet_request_sock *ireq = inet_rsk(req);
2e6599cb8   Arnaldo Carvalho de Melo   [NET] Generalise ...
413
  		struct tcp_request_sock *treq = tcp_rsk(req);
a9948a7e1   Arnaldo Carvalho de Melo   [TCP]: Fix miniso...
414
  		struct inet_connection_sock *newicsk = inet_csk(newsk);
435cf559f   William Allen Simpson   TCPCT part 1d: de...
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
  		struct tcp_sock *newtp = tcp_sk(newsk);
  		struct tcp_sock *oldtp = tcp_sk(sk);
  		struct tcp_cookie_values *oldcvp = oldtp->cookie_values;
  
  		/* TCP Cookie Transactions require space for the cookie pair,
  		 * as it differs for each connection.  There is no need to
  		 * copy any s_data_payload stored at the original socket.
  		 * Failure will prevent resuming the connection.
  		 *
  		 * Presumed copied, in order of appearance:
  		 *	cookie_in_always, cookie_out_never
  		 */
  		if (oldcvp != NULL) {
  			struct tcp_cookie_values *newcvp =
  				kzalloc(sizeof(*newtp->cookie_values),
  					GFP_ATOMIC);
  
  			if (newcvp != NULL) {
  				kref_init(&newcvp->kref);
  				newcvp->cookie_desired =
  						oldcvp->cookie_desired;
  				newtp->cookie_values = newcvp;
  			} else {
  				/* Not Yet Implemented */
  				newtp->cookie_values = NULL;
  			}
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
442

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
443
  		/* Now setup tcp_sock */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
444
  		newtp->pred_flags = 0;
435cf559f   William Allen Simpson   TCPCT part 1d: de...
445
446
447
448
449
450
451
  
  		newtp->rcv_wup = newtp->copied_seq =
  		newtp->rcv_nxt = treq->rcv_isn + 1;
  
  		newtp->snd_sml = newtp->snd_una =
  		newtp->snd_nxt = newtp->snd_up =
  			treq->snt_isn + 1 + tcp_s_data_size(oldtp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
452
453
  
  		tcp_prequeue_init(newtp);
ee7537b63   Hantzis Fotis   tcp: tcp_init_wl ...
454
  		tcp_init_wl(newtp, treq->rcv_isn);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
455

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
456
457
  		newtp->srtt = 0;
  		newtp->mdev = TCP_TIMEOUT_INIT;
463c84b97   Arnaldo Carvalho de Melo   [NET]: Introduce ...
458
  		newicsk->icsk_rto = TCP_TIMEOUT_INIT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
459
460
  
  		newtp->packets_out = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
461
462
463
  		newtp->retrans_out = 0;
  		newtp->sacked_out = 0;
  		newtp->fackets_out = 0;
0b6a05c1d   Ilpo Järvinen   tcp: fix ssthresh...
464
  		newtp->snd_ssthresh = TCP_INFINITE_SSTHRESH;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
465
466
467
468
469
470
471
472
  
  		/* So many TCP implementations out there (incorrectly) count the
  		 * initial SYN frame in their delayed-ACK and congestion control
  		 * algorithms that we must have the following bandaid to talk
  		 * efficiently to them.  -DaveM
  		 */
  		newtp->snd_cwnd = 2;
  		newtp->snd_cwnd_cnt = 0;
9772efb97   Stephen Hemminger   [TCP]: Appropriat...
473
  		newtp->bytes_acked = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
474
475
476
  
  		newtp->frto_counter = 0;
  		newtp->frto_highmark = 0;
7957aed72   Stephen Hemminger   [TCP]: Set defaul...
477
  		newicsk->icsk_ca_ops = &tcp_init_congestion_ops;
317a76f9a   Stephen Hemminger   [TCP]: Add plugga...
478

6687e988d   Arnaldo Carvalho de Melo   [ICSK]: Move TCP ...
479
  		tcp_set_ca_state(newsk, TCP_CA_Open);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
480
481
  		tcp_init_xmit_timers(newsk);
  		skb_queue_head_init(&newtp->out_of_order_queue);
435cf559f   William Allen Simpson   TCPCT part 1d: de...
482
483
  		newtp->write_seq = newtp->pushed_seq =
  			treq->snt_isn + 1 + tcp_s_data_size(oldtp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
484
485
486
487
  
  		newtp->rx_opt.saw_tstamp = 0;
  
  		newtp->rx_opt.dsack = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
488
  		newtp->rx_opt.num_sacks = 0;
cabeccbd1   Ilpo Järvinen   tcp: kill eff_sac...
489

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
490
  		newtp->urg_data = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
491

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
492
  		if (sock_flag(newsk, SOCK_KEEPOPEN))
463c84b97   Arnaldo Carvalho de Melo   [NET]: Introduce ...
493
494
  			inet_csk_reset_keepalive_timer(newsk,
  						       keepalive_time_when(newtp));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
495

2e6599cb8   Arnaldo Carvalho de Melo   [NET] Generalise ...
496
  		newtp->rx_opt.tstamp_ok = ireq->tstamp_ok;
2de979bd7   Stephen Hemminger   [TCP]: whitespace...
497
  		if ((newtp->rx_opt.sack_ok = ireq->sack_ok) != 0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
498
  			if (sysctl_tcp_fack)
e60402d0a   Ilpo Järvinen   [TCP]: Move sack_...
499
  				tcp_enable_fack(newtp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
500
501
502
503
  		}
  		newtp->window_clamp = req->window_clamp;
  		newtp->rcv_ssthresh = req->rcv_wnd;
  		newtp->rcv_wnd = req->rcv_wnd;
2e6599cb8   Arnaldo Carvalho de Melo   [NET] Generalise ...
504
  		newtp->rx_opt.wscale_ok = ireq->wscale_ok;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
505
  		if (newtp->rx_opt.wscale_ok) {
2e6599cb8   Arnaldo Carvalho de Melo   [NET] Generalise ...
506
507
  			newtp->rx_opt.snd_wscale = ireq->snd_wscale;
  			newtp->rx_opt.rcv_wscale = ireq->rcv_wscale;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
508
509
510
511
  		} else {
  			newtp->rx_opt.snd_wscale = newtp->rx_opt.rcv_wscale = 0;
  			newtp->window_clamp = min(newtp->window_clamp, 65535U);
  		}
aa8223c7b   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
512
513
  		newtp->snd_wnd = (ntohs(tcp_hdr(skb)->window) <<
  				  newtp->rx_opt.snd_wscale);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
514
515
516
517
  		newtp->max_window = newtp->snd_wnd;
  
  		if (newtp->rx_opt.tstamp_ok) {
  			newtp->rx_opt.ts_recent = req->ts_recent;
9d729f72d   James Morris   [NET]: Convert xt...
518
  			newtp->rx_opt.ts_recent_stamp = get_seconds();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
519
520
521
522
523
  			newtp->tcp_header_len = sizeof(struct tcphdr) + TCPOLEN_TSTAMP_ALIGNED;
  		} else {
  			newtp->rx_opt.ts_recent_stamp = 0;
  			newtp->tcp_header_len = sizeof(struct tcphdr);
  		}
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
524
525
526
527
528
  #ifdef CONFIG_TCP_MD5SIG
  		newtp->md5sig_info = NULL;	/*XXX*/
  		if (newtp->af_specific->md5_lookup(sk, newsk))
  			newtp->tcp_header_len += TCPOLEN_MD5SIG_ALIGNED;
  #endif
bee7ca9ec   William Allen Simpson   net: TCP_MSS_DEFA...
529
  		if (skb->len >= TCP_MSS_DEFAULT + newtp->tcp_header_len)
463c84b97   Arnaldo Carvalho de Melo   [NET]: Introduce ...
530
  			newicsk->icsk_ack.last_seg_size = skb->len - newtp->tcp_header_len;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
531
532
  		newtp->rx_opt.mss_clamp = req->mss;
  		TCP_ECN_openreq_child(newtp, req);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
533

63231bddf   Pavel Emelyanov   mib: add net to T...
534
  		TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_PASSIVEOPENS);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
535
536
537
  	}
  	return newsk;
  }
4bc2f18ba   Eric Dumazet   net/ipv4: EXPORT_...
538
  EXPORT_SYMBOL(tcp_create_openreq_child);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
539

e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
540
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
541
   *	Process an incoming packet for SYN_RECV sockets represented
60236fdd0   Arnaldo Carvalho de Melo   [NET] Rename open...
542
   *	as a request_sock.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
543
   */
5a5f3a8db   Jianjun Kong   net: clean up net...
544
  struct sock *tcp_check_req(struct sock *sk, struct sk_buff *skb,
60236fdd0   Arnaldo Carvalho de Melo   [NET] Rename open...
545
546
  			   struct request_sock *req,
  			   struct request_sock **prev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
547
  {
4957faade   William Allen Simpson   TCPCT part 1g: Re...
548
549
550
  	struct tcp_options_received tmp_opt;
  	u8 *hash_location;
  	struct sock *child;
aa8223c7b   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
551
  	const struct tcphdr *th = tcp_hdr(skb);
714e85be3   Al Viro   [IPV6]: Assorted ...
552
  	__be32 flg = tcp_flag_word(th) & (TCP_FLAG_RST|TCP_FLAG_SYN|TCP_FLAG_ACK);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
553
  	int paws_reject = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
554

bb5b7c112   David S. Miller   tcp: Revert per-r...
555
556
557
  	tmp_opt.saw_tstamp = 0;
  	if (th->doff > (sizeof(struct tcphdr)>>2)) {
  		tcp_parse_options(skb, &tmp_opt, &hash_location, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
558
559
560
561
562
563
564
  
  		if (tmp_opt.saw_tstamp) {
  			tmp_opt.ts_recent = req->ts_recent;
  			/* We do not store true stamp, but it is not required,
  			 * it can be estimated (approximately)
  			 * from another data.
  			 */
9d729f72d   James Morris   [NET]: Convert xt...
565
  			tmp_opt.ts_recent_stamp = get_seconds() - ((TCP_TIMEOUT_INIT/HZ)<<req->retrans);
c887e6d2d   Ilpo Järvinen   tcp: consolidate ...
566
  			paws_reject = tcp_paws_reject(&tmp_opt, th->rst);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
567
568
569
570
  		}
  	}
  
  	/* Check for pure retransmitted SYN. */
2e6599cb8   Arnaldo Carvalho de Melo   [NET] Generalise ...
571
  	if (TCP_SKB_CB(skb)->seq == tcp_rsk(req)->rcv_isn &&
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
  	    flg == TCP_FLAG_SYN &&
  	    !paws_reject) {
  		/*
  		 * RFC793 draws (Incorrectly! It was fixed in RFC1122)
  		 * this case on figure 6 and figure 8, but formal
  		 * protocol description says NOTHING.
  		 * To be more exact, it says that we should send ACK,
  		 * because this segment (at least, if it has no data)
  		 * is out of window.
  		 *
  		 *  CONCLUSION: RFC793 (even with RFC1122) DOES NOT
  		 *  describe SYN-RECV state. All the description
  		 *  is wrong, we cannot believe to it and should
  		 *  rely only on common sense and implementation
  		 *  experience.
  		 *
  		 * Enforce "SYN-ACK" according to figure 8, figure 6
  		 * of RFC793, fixed by RFC1122.
  		 */
e6b4d1136   William Allen Simpson   TCPCT part 1a: ad...
591
  		req->rsk_ops->rtx_syn_ack(sk, req, NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
  		return NULL;
  	}
  
  	/* Further reproduces section "SEGMENT ARRIVES"
  	   for state SYN-RECEIVED of RFC793.
  	   It is broken, however, it does not work only
  	   when SYNs are crossed.
  
  	   You would think that SYN crossing is impossible here, since
  	   we should have a SYN_SENT socket (from connect()) on our end,
  	   but this is not true if the crossed SYNs were sent to both
  	   ends by a malicious third party.  We must defend against this,
  	   and to do that we first verify the ACK (as per RFC793, page
  	   36) and reset if it is invalid.  Is this a true full defense?
  	   To convince ourselves, let us consider a way in which the ACK
  	   test can still pass in this 'malicious crossed SYNs' case.
  	   Malicious sender sends identical SYNs (and thus identical sequence
  	   numbers) to both A and B:
  
  		A: gets SYN, seq=7
  		B: gets SYN, seq=7
  
  	   By our good fortune, both A and B select the same initial
  	   send sequence number of seven :-)
  
  		A: sends SYN|ACK, seq=7, ack_seq=8
  		B: sends SYN|ACK, seq=7, ack_seq=8
  
  	   So we are now A eating this SYN|ACK, ACK test passes.  So
  	   does sequence test, SYN is truncated, and thus we consider
  	   it a bare ACK.
ec0a19662   David S. Miller   tcp: Revert 'proc...
623
624
625
626
  	   If icsk->icsk_accept_queue.rskq_defer_accept, we silently drop this
  	   bare ACK.  Otherwise, we create an established connection.  Both
  	   ends (listening sockets) accept the new incoming connection and try
  	   to talk to each other. 8-)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
  
  	   Note: This case is both harmless, and rare.  Possibility is about the
  	   same as us discovering intelligent life on another plant tomorrow.
  
  	   But generally, we should (RFC lies!) to accept ACK
  	   from SYNACK both here and in tcp_rcv_state_process().
  	   tcp_rcv_state_process() does not, hence, we do not too.
  
  	   Note that the case is absolutely generic:
  	   we cannot optimize anything here without
  	   violating protocol. All the checks must be made
  	   before attempt to create socket.
  	 */
  
  	/* RFC793 page 36: "If the connection is in any non-synchronized state ...
  	 *                  and the incoming segment acknowledges something not yet
caa20d9ab   Stephen Hemminger   [TCP]: spelling f...
643
  	 *                  sent (the segment carries an unacceptable ACK) ...
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
644
645
646
647
648
  	 *                  a reset is sent."
  	 *
  	 * Invalid ACK: reset will be sent by listening socket
  	 */
  	if ((flg & TCP_FLAG_ACK) &&
435cf559f   William Allen Simpson   TCPCT part 1d: de...
649
650
  	    (TCP_SKB_CB(skb)->ack_seq !=
  	     tcp_rsk(req)->snt_isn + 1 + tcp_s_data_size(tcp_sk(sk))))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
651
652
653
654
655
656
657
658
659
660
  		return sk;
  
  	/* Also, it would be not so bad idea to check rcv_tsecr, which
  	 * is essentially ACK extension and too early or too late values
  	 * should cause reset in unsynchronized states.
  	 */
  
  	/* RFC793: "first check sequence number". */
  
  	if (paws_reject || !tcp_in_window(TCP_SKB_CB(skb)->seq, TCP_SKB_CB(skb)->end_seq,
2e6599cb8   Arnaldo Carvalho de Melo   [NET] Generalise ...
661
  					  tcp_rsk(req)->rcv_isn + 1, tcp_rsk(req)->rcv_isn + 1 + req->rcv_wnd)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
662
663
  		/* Out of window: send ACK and drop. */
  		if (!(flg & TCP_FLAG_RST))
6edafaaf6   Gui Jianfeng   tcp: Fix kernel p...
664
  			req->rsk_ops->send_ack(sk, skb, req);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
665
  		if (paws_reject)
de0744af1   Pavel Emelyanov   mib: add net to N...
666
  			NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_PAWSESTABREJECTED);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
667
668
669
670
  		return NULL;
  	}
  
  	/* In sequence, PAWS is OK. */
2e6599cb8   Arnaldo Carvalho de Melo   [NET] Generalise ...
671
  	if (tmp_opt.saw_tstamp && !after(TCP_SKB_CB(skb)->seq, tcp_rsk(req)->rcv_isn + 1))
2aaab9a0c   Adam Langley   tcp: (whitespace ...
672
  		req->ts_recent = tmp_opt.rcv_tsval;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
673

2aaab9a0c   Adam Langley   tcp: (whitespace ...
674
675
676
677
678
  	if (TCP_SKB_CB(skb)->seq == tcp_rsk(req)->rcv_isn) {
  		/* Truncate SYN, it is out of window starting
  		   at tcp_rsk(req)->rcv_isn + 1. */
  		flg &= ~TCP_FLAG_SYN;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
679

2aaab9a0c   Adam Langley   tcp: (whitespace ...
680
681
682
683
684
685
686
  	/* RFC793: "second check the RST bit" and
  	 *	   "fourth, check the SYN bit"
  	 */
  	if (flg & (TCP_FLAG_RST|TCP_FLAG_SYN)) {
  		TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_ATTEMPTFAILS);
  		goto embryonic_reset;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
687

2aaab9a0c   Adam Langley   tcp: (whitespace ...
688
689
690
691
692
  	/* ACK sequence verified above, just make sure ACK is
  	 * set.  If ACK not set, just silently drop the packet.
  	 */
  	if (!(flg & TCP_FLAG_ACK))
  		return NULL;
ec0a19662   David S. Miller   tcp: Revert 'proc...
693

d1b99ba41   Julian Anastasov   tcp: accept socke...
694
695
  	/* While TCP_DEFER_ACCEPT is active, drop bare ACK. */
  	if (req->retrans < inet_csk(sk)->icsk_accept_queue.rskq_defer_accept &&
2aaab9a0c   Adam Langley   tcp: (whitespace ...
696
697
  	    TCP_SKB_CB(skb)->end_seq == tcp_rsk(req)->rcv_isn + 1) {
  		inet_rsk(req)->acked = 1;
907cdda52   Eric Dumazet   tcp: Add SNMP cou...
698
  		NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPDEFERACCEPTDROP);
2aaab9a0c   Adam Langley   tcp: (whitespace ...
699
700
701
702
703
704
705
706
707
708
709
710
  		return NULL;
  	}
  
  	/* OK, ACK is valid, create big socket and
  	 * feed this segment to it. It will repeat all
  	 * the tests. THIS SEGMENT MUST MOVE SOCKET TO
  	 * ESTABLISHED STATE. If it will be dropped after
  	 * socket is created, wait for troubles.
  	 */
  	child = inet_csk(sk)->icsk_af_ops->syn_recv_sock(sk, skb, req, NULL);
  	if (child == NULL)
  		goto listen_overflow;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
711

2aaab9a0c   Adam Langley   tcp: (whitespace ...
712
713
  	inet_csk_reqsk_queue_unlink(sk, req, prev);
  	inet_csk_reqsk_queue_removed(sk, req);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
714

2aaab9a0c   Adam Langley   tcp: (whitespace ...
715
716
  	inet_csk_reqsk_queue_add(sk, req, child);
  	return child;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
717

2aaab9a0c   Adam Langley   tcp: (whitespace ...
718
719
720
721
722
  listen_overflow:
  	if (!sysctl_tcp_abort_on_overflow) {
  		inet_rsk(req)->acked = 1;
  		return NULL;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
723

2aaab9a0c   Adam Langley   tcp: (whitespace ...
724
725
726
727
  embryonic_reset:
  	NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_EMBRYONICRSTS);
  	if (!(flg & TCP_FLAG_RST))
  		req->rsk_ops->send_reset(sk, skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
728

2aaab9a0c   Adam Langley   tcp: (whitespace ...
729
730
  	inet_csk_reqsk_queue_drop(sk, req, prev);
  	return NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
731
  }
4bc2f18ba   Eric Dumazet   net/ipv4: EXPORT_...
732
  EXPORT_SYMBOL(tcp_check_req);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
733
734
735
736
737
738
739
740
741
742
743
744
745
746
  
  /*
   * Queue segment on the new socket if the new socket is active,
   * otherwise we just shortcircuit this and continue with
   * the new socket.
   */
  
  int tcp_child_process(struct sock *parent, struct sock *child,
  		      struct sk_buff *skb)
  {
  	int ret = 0;
  	int state = child->sk_state;
  
  	if (!sock_owned_by_user(child)) {
aa8223c7b   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
747
748
  		ret = tcp_rcv_state_process(child, skb, tcp_hdr(skb),
  					    skb->len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
749
750
751
752
753
754
755
756
  		/* Wakeup parent, send SIGIO */
  		if (state == TCP_SYN_RECV && child->sk_state != state)
  			parent->sk_data_ready(parent, 0);
  	} else {
  		/* Alas, it is possible again, because we do lookup
  		 * in main socket hash table and lock on listening
  		 * socket does not protect us more.
  		 */
a3a858ff1   Zhu Yi   net: backlog func...
757
  		__sk_add_backlog(child, skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
758
759
760
761
762
763
  	}
  
  	bh_unlock_sock(child);
  	sock_put(child);
  	return ret;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
764
  EXPORT_SYMBOL(tcp_child_process);