Blame view

net/ipv4/tcp_ipv4.c 67.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).
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
   *		IPv4 specific functions
   *
   *
   *		code split from:
   *		linux/ipv4/tcp.c
   *		linux/ipv4/tcp_input.c
   *		linux/ipv4/tcp_output.c
   *
   *		See tcp.c for author information
   *
   *	This program is free software; you can redistribute it and/or
   *      modify it under the terms of the GNU General Public License
   *      as published by the Free Software Foundation; either version
   *      2 of the License, or (at your option) any later version.
   */
  
  /*
   * Changes:
   *		David S. Miller	:	New socket lookup architecture.
   *					This code is dedicated to John Dyson.
   *		David S. Miller :	Change semantics of established hash,
   *					half is devoted to TIME_WAIT sockets
   *					and the rest go in the other half.
   *		Andi Kleen :		Add support for syncookies and fixed
   *					some bugs: ip options weren't passed to
   *					the TCP layer, missed a check for an
   *					ACK bit.
   *		Andi Kleen :		Implemented fast path mtu discovery.
   *	     				Fixed many serious bugs in the
60236fdd0   Arnaldo Carvalho de Melo   [NET] Rename open...
37
   *					request_sock handling and moved
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
38
39
   *					most of it into the af independent code.
   *					Added tail drop and some other bugfixes.
caa20d9ab   Stephen Hemminger   [TCP]: spelling f...
40
   *					Added new listen semantics.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
41
42
43
44
45
46
47
48
49
50
51
   *		Mike McLagan	:	Routing by source
   *	Juan Jose Ciarlante:		ip_dynaddr bits
   *		Andi Kleen:		various fixes.
   *	Vitaly E. Lavrov	:	Transparent proxy revived after year
   *					coma.
   *	Andi Kleen		:	Fix new listen.
   *	Andi Kleen		:	Fix accept error reporting.
   *	YOSHIFUJI Hideaki @USAGI and:	Support IPV6_V6ONLY socket option, which
   *	Alexey Kuznetsov		allow both IPv4 and IPv6 sockets to bind
   *					a single port at the same time.
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
52

eb4dea585   Herbert Xu   net: Fix percpu c...
53
  #include <linux/bottom_half.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
54
55
56
57
58
59
60
61
  #include <linux/types.h>
  #include <linux/fcntl.h>
  #include <linux/module.h>
  #include <linux/random.h>
  #include <linux/cache.h>
  #include <linux/jhash.h>
  #include <linux/init.h>
  #include <linux/times.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
62
  #include <linux/slab.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
63

457c4cbc5   Eric W. Biederman   [NET]: Make /proc...
64
  #include <net/net_namespace.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
65
  #include <net/icmp.h>
304a16180   Arnaldo Carvalho de Melo   [INET]: Move the ...
66
  #include <net/inet_hashtables.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
67
  #include <net/tcp.h>
20380731b   Arnaldo Carvalho de Melo   [NET]: Fix sparse...
68
  #include <net/transp_v6.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
69
70
  #include <net/ipv6.h>
  #include <net/inet_common.h>
6d6ee43e0   Arnaldo Carvalho de Melo   [TWSK]: Introduce...
71
  #include <net/timewait_sock.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
72
  #include <net/xfrm.h>
1a2449a87   Chris Leech   [I/OAT]: TCP recv...
73
  #include <net/netdma.h>
6e5714eaf   David S. Miller   net: Compute prot...
74
  #include <net/secure_seq.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
75
76
77
78
79
80
  
  #include <linux/inet.h>
  #include <linux/ipv6.h>
  #include <linux/stddef.h>
  #include <linux/proc_fs.h>
  #include <linux/seq_file.h>
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
81
82
  #include <linux/crypto.h>
  #include <linux/scatterlist.h>
ab32ea5d8   Brian Haley   [NET/IPV4/IPV6]: ...
83
84
  int sysctl_tcp_tw_reuse __read_mostly;
  int sysctl_tcp_low_latency __read_mostly;
4bc2f18ba   Eric Dumazet   net/ipv4: EXPORT_...
85
  EXPORT_SYMBOL(sysctl_tcp_low_latency);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
86

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
87

cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
88
  #ifdef CONFIG_TCP_MD5SIG
7174259e6   Arnaldo Carvalho de Melo   [TCP_IPV4]: Codin...
89
90
  static struct tcp_md5sig_key *tcp_v4_md5_do_lookup(struct sock *sk,
  						   __be32 addr);
49a72dfb8   Adam Langley   tcp: Fix MD5 sign...
91
  static int tcp_v4_md5_hash_hdr(char *md5_hash, struct tcp_md5sig_key *key,
318cf7aaa   Eric Dumazet   tcp: md5: add mor...
92
  			       __be32 daddr, __be32 saddr, const struct tcphdr *th);
9501f9722   YOSHIFUJI Hideaki   tcp md5sig: Let t...
93
94
95
96
97
98
  #else
  static inline
  struct tcp_md5sig_key *tcp_v4_md5_do_lookup(struct sock *sk, __be32 addr)
  {
  	return NULL;
  }
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
99
  #endif
5caea4ea7   Eric Dumazet   net: listening_ha...
100
  struct inet_hashinfo tcp_hashinfo;
4bc2f18ba   Eric Dumazet   net/ipv4: EXPORT_...
101
  EXPORT_SYMBOL(tcp_hashinfo);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
102

cf533ea53   Eric Dumazet   tcp: add const qu...
103
  static inline __u32 tcp_v4_init_sequence(const struct sk_buff *skb)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
104
  {
eddc9ec53   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
105
106
  	return secure_tcp_sequence_number(ip_hdr(skb)->daddr,
  					  ip_hdr(skb)->saddr,
aa8223c7b   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
107
108
  					  tcp_hdr(skb)->dest,
  					  tcp_hdr(skb)->source);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
109
  }
6d6ee43e0   Arnaldo Carvalho de Melo   [TWSK]: Introduce...
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
  int tcp_twsk_unique(struct sock *sk, struct sock *sktw, void *twp)
  {
  	const struct tcp_timewait_sock *tcptw = tcp_twsk(sktw);
  	struct tcp_sock *tp = tcp_sk(sk);
  
  	/* With PAWS, it is safe from the viewpoint
  	   of data integrity. Even without PAWS it is safe provided sequence
  	   spaces do not overlap i.e. at data rates <= 80Mbit/sec.
  
  	   Actually, the idea is close to VJ's one, only timestamp cache is
  	   held not per host, but per port pair and TW bucket is used as state
  	   holder.
  
  	   If TW bucket has been already destroyed we fall back to VJ's scheme
  	   and use initial timestamp retrieved from peer table.
  	 */
  	if (tcptw->tw_ts_recent_stamp &&
  	    (twp == NULL || (sysctl_tcp_tw_reuse &&
9d729f72d   James Morris   [NET]: Convert xt...
128
  			     get_seconds() - tcptw->tw_ts_recent_stamp > 1))) {
6d6ee43e0   Arnaldo Carvalho de Melo   [TWSK]: Introduce...
129
130
131
132
133
134
135
136
137
138
139
  		tp->write_seq = tcptw->tw_snd_nxt + 65535 + 2;
  		if (tp->write_seq == 0)
  			tp->write_seq = 1;
  		tp->rx_opt.ts_recent	   = tcptw->tw_ts_recent;
  		tp->rx_opt.ts_recent_stamp = tcptw->tw_ts_recent_stamp;
  		sock_hold(sktw);
  		return 1;
  	}
  
  	return 0;
  }
6d6ee43e0   Arnaldo Carvalho de Melo   [TWSK]: Introduce...
140
  EXPORT_SYMBOL_GPL(tcp_twsk_unique);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
141
142
143
  /* This will initiate an outgoing connection. */
  int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
  {
2d7192d6c   David S. Miller   ipv4: Sanitize an...
144
  	struct sockaddr_in *usin = (struct sockaddr_in *)uaddr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
145
146
  	struct inet_sock *inet = inet_sk(sk);
  	struct tcp_sock *tp = tcp_sk(sk);
dca8b089c   David S. Miller   ipv4: Rearrange h...
147
  	__be16 orig_sport, orig_dport;
bada8adc4   Al Viro   [IPV4]: ip_route_...
148
  	__be32 daddr, nexthop;
da905bd1d   David S. Miller   tcp: Use cork flo...
149
  	struct flowi4 *fl4;
2d7192d6c   David S. Miller   ipv4: Sanitize an...
150
  	struct rtable *rt;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
151
  	int err;
f6d8bd051   Eric Dumazet   inet: add RCU pro...
152
  	struct ip_options_rcu *inet_opt;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
153
154
155
156
157
158
159
160
  
  	if (addr_len < sizeof(struct sockaddr_in))
  		return -EINVAL;
  
  	if (usin->sin_family != AF_INET)
  		return -EAFNOSUPPORT;
  
  	nexthop = daddr = usin->sin_addr.s_addr;
f6d8bd051   Eric Dumazet   inet: add RCU pro...
161
162
163
  	inet_opt = rcu_dereference_protected(inet->inet_opt,
  					     sock_owned_by_user(sk));
  	if (inet_opt && inet_opt->opt.srr) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
164
165
  		if (!daddr)
  			return -EINVAL;
f6d8bd051   Eric Dumazet   inet: add RCU pro...
166
  		nexthop = inet_opt->opt.faddr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
167
  	}
dca8b089c   David S. Miller   ipv4: Rearrange h...
168
169
  	orig_sport = inet->inet_sport;
  	orig_dport = usin->sin_port;
da905bd1d   David S. Miller   tcp: Use cork flo...
170
171
  	fl4 = &inet->cork.fl.u.ip4;
  	rt = ip_route_connect(fl4, nexthop, inet->inet_saddr,
b23dd4fe4   David S. Miller   ipv4: Make output...
172
173
174
175
176
177
  			      RT_CONN_FLAGS(sk), sk->sk_bound_dev_if,
  			      IPPROTO_TCP,
  			      orig_sport, orig_dport, sk, true);
  	if (IS_ERR(rt)) {
  		err = PTR_ERR(rt);
  		if (err == -ENETUNREACH)
7c73a6faf   Pavel Emelyanov   mib: add net to I...
178
  			IP_INC_STATS_BH(sock_net(sk), IPSTATS_MIB_OUTNOROUTES);
b23dd4fe4   David S. Miller   ipv4: Make output...
179
  		return err;
584bdf8cb   Wei Dong   [IPV4]: Fix "ipOu...
180
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
181
182
183
184
185
  
  	if (rt->rt_flags & (RTCF_MULTICAST | RTCF_BROADCAST)) {
  		ip_rt_put(rt);
  		return -ENETUNREACH;
  	}
f6d8bd051   Eric Dumazet   inet: add RCU pro...
186
  	if (!inet_opt || !inet_opt->opt.srr)
da905bd1d   David S. Miller   tcp: Use cork flo...
187
  		daddr = fl4->daddr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
188

c720c7e83   Eric Dumazet   inet: rename some...
189
  	if (!inet->inet_saddr)
da905bd1d   David S. Miller   tcp: Use cork flo...
190
  		inet->inet_saddr = fl4->saddr;
c720c7e83   Eric Dumazet   inet: rename some...
191
  	inet->inet_rcv_saddr = inet->inet_saddr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
192

c720c7e83   Eric Dumazet   inet: rename some...
193
  	if (tp->rx_opt.ts_recent_stamp && inet->inet_daddr != daddr) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
194
195
196
197
198
  		/* Reset inherited state */
  		tp->rx_opt.ts_recent	   = 0;
  		tp->rx_opt.ts_recent_stamp = 0;
  		tp->write_seq		   = 0;
  	}
295ff7edb   Arnaldo Carvalho de Melo   [TIMEWAIT]: Intro...
199
  	if (tcp_death_row.sysctl_tw_recycle &&
da905bd1d   David S. Miller   tcp: Use cork flo...
200
  	    !tp->rx_opt.ts_recent_stamp && fl4->daddr == daddr) {
ed2361e66   David S. Miller   ipv4: Pass explic...
201
  		struct inet_peer *peer = rt_get_peer(rt, fl4->daddr);
7174259e6   Arnaldo Carvalho de Melo   [TCP_IPV4]: Codin...
202
203
204
205
206
  		/*
  		 * VJ's idea. We save last timestamp seen from
  		 * the destination in peer table, when entering state
  		 * TIME-WAIT * and initialize rx_opt.ts_recent from it,
  		 * when trying new connection.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
207
  		 */
317fe0e6c   Eric Dumazet   inetpeer: restore...
208
209
210
211
212
213
  		if (peer) {
  			inet_peer_refcheck(peer);
  			if ((u32)get_seconds() - peer->tcp_ts_stamp <= TCP_PAWS_MSL) {
  				tp->rx_opt.ts_recent_stamp = peer->tcp_ts_stamp;
  				tp->rx_opt.ts_recent = peer->tcp_ts;
  			}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
214
215
  		}
  	}
c720c7e83   Eric Dumazet   inet: rename some...
216
217
  	inet->inet_dport = usin->sin_port;
  	inet->inet_daddr = daddr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
218

d83d8461f   Arnaldo Carvalho de Melo   [IP_SOCKGLUE]: Re...
219
  	inet_csk(sk)->icsk_ext_hdr_len = 0;
f6d8bd051   Eric Dumazet   inet: add RCU pro...
220
221
  	if (inet_opt)
  		inet_csk(sk)->icsk_ext_hdr_len = inet_opt->opt.optlen;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
222

bee7ca9ec   William Allen Simpson   net: TCP_MSS_DEFA...
223
  	tp->rx_opt.mss_clamp = TCP_MSS_DEFAULT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
224
225
226
227
228
229
230
  
  	/* Socket identity is still unknown (sport may be zero).
  	 * However we set state to SYN-SENT and not releasing socket
  	 * lock select source port, enter ourselves into the hash tables and
  	 * complete initialization after this.
  	 */
  	tcp_set_state(sk, TCP_SYN_SENT);
a7f5e7f16   Arnaldo Carvalho de Melo   [INET]: Generalis...
231
  	err = inet_hash_connect(&tcp_death_row, sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
232
233
  	if (err)
  		goto failure;
da905bd1d   David S. Miller   tcp: Use cork flo...
234
  	rt = ip_route_newports(fl4, rt, orig_sport, orig_dport,
b23dd4fe4   David S. Miller   ipv4: Make output...
235
236
237
238
  			       inet->inet_sport, inet->inet_dport, sk);
  	if (IS_ERR(rt)) {
  		err = PTR_ERR(rt);
  		rt = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
239
  		goto failure;
b23dd4fe4   David S. Miller   ipv4: Make output...
240
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
241
  	/* OK, now commit destination to socket.  */
bcd761111   Herbert Xu   [NET]: Generalise...
242
  	sk->sk_gso_type = SKB_GSO_TCPV4;
d8d1f30b9   Changli Gao   net-next: remove ...
243
  	sk_setup_caps(sk, &rt->dst);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
244
245
  
  	if (!tp->write_seq)
c720c7e83   Eric Dumazet   inet: rename some...
246
247
248
  		tp->write_seq = secure_tcp_sequence_number(inet->inet_saddr,
  							   inet->inet_daddr,
  							   inet->inet_sport,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
249
  							   usin->sin_port);
c720c7e83   Eric Dumazet   inet: rename some...
250
  	inet->inet_id = tp->write_seq ^ jiffies;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
251
252
253
254
255
256
257
258
259
  
  	err = tcp_connect(sk);
  	rt = NULL;
  	if (err)
  		goto failure;
  
  	return 0;
  
  failure:
7174259e6   Arnaldo Carvalho de Melo   [TCP_IPV4]: Codin...
260
261
262
263
  	/*
  	 * This unhashes the socket and releases the local port,
  	 * if necessary.
  	 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
264
265
266
  	tcp_set_state(sk, TCP_CLOSE);
  	ip_rt_put(rt);
  	sk->sk_route_caps = 0;
c720c7e83   Eric Dumazet   inet: rename some...
267
  	inet->inet_dport = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
268
269
  	return err;
  }
4bc2f18ba   Eric Dumazet   net/ipv4: EXPORT_...
270
  EXPORT_SYMBOL(tcp_v4_connect);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
271

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
272
273
274
  /*
   * This routine does path mtu discovery as defined in RFC1191.
   */
b71d1d426   Eric Dumazet   inet: constify ip...
275
  static void do_pmtu_discovery(struct sock *sk, const struct iphdr *iph, u32 mtu)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
276
277
278
  {
  	struct dst_entry *dst;
  	struct inet_sock *inet = inet_sk(sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
279
280
281
282
283
284
285
286
287
288
289
  
  	/* We are not interested in TCP_LISTEN and open_requests (SYN-ACKs
  	 * send out by Linux are always <576bytes so they should go through
  	 * unfragmented).
  	 */
  	if (sk->sk_state == TCP_LISTEN)
  		return;
  
  	/* We don't check in the destentry if pmtu discovery is forbidden
  	 * on this route. We just assume that no packet_to_big packets
  	 * are send back when pmtu discovery is not active.
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
290
  	 * There is a small race when the user changes this flag in the
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
  	 * route, but I think that's acceptable.
  	 */
  	if ((dst = __sk_dst_check(sk, 0)) == NULL)
  		return;
  
  	dst->ops->update_pmtu(dst, mtu);
  
  	/* Something is about to be wrong... Remember soft error
  	 * for the case, if this connection will not able to recover.
  	 */
  	if (mtu < dst_mtu(dst) && ip_dont_fragment(sk, dst))
  		sk->sk_err_soft = EMSGSIZE;
  
  	mtu = dst_mtu(dst);
  
  	if (inet->pmtudisc != IP_PMTUDISC_DONT &&
d83d8461f   Arnaldo Carvalho de Melo   [IP_SOCKGLUE]: Re...
307
  	    inet_csk(sk)->icsk_pmtu_cookie > mtu) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
  		tcp_sync_mss(sk, mtu);
  
  		/* Resend the TCP packet because it's
  		 * clear that the old packet has been
  		 * dropped. This is the new "fast" path mtu
  		 * discovery.
  		 */
  		tcp_simple_retransmit(sk);
  	} /* else let the usual retransmit timer handle it */
  }
  
  /*
   * This routine is called by the ICMP module when it gets some
   * sort of error condition.  If err < 0 then the socket should
   * be closed and the error returned to the user.  If err > 0
   * it's just the icmp type << 8 | icmp code.  After adjustment
   * header points to the first 8 bytes of the tcp header.  We need
   * to find the appropriate port.
   *
   * The locking strategy used here is very "optimistic". When
   * someone else accesses the socket the ICMP is just dropped
   * and for some paths there is no check at all.
   * A more general error queue to queue errors for later handling
   * is probably better.
   *
   */
4d1a2d9ec   Damian Lukowski   Revert Backoff [v...
334
  void tcp_v4_err(struct sk_buff *icmp_skb, u32 info)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
335
  {
b71d1d426   Eric Dumazet   inet: constify ip...
336
  	const struct iphdr *iph = (const struct iphdr *)icmp_skb->data;
4d1a2d9ec   Damian Lukowski   Revert Backoff [v...
337
  	struct tcphdr *th = (struct tcphdr *)(icmp_skb->data + (iph->ihl << 2));
f1ecd5d9e   Damian Lukowski   Revert Backoff [v...
338
  	struct inet_connection_sock *icsk;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
339
340
  	struct tcp_sock *tp;
  	struct inet_sock *inet;
4d1a2d9ec   Damian Lukowski   Revert Backoff [v...
341
342
  	const int type = icmp_hdr(icmp_skb)->type;
  	const int code = icmp_hdr(icmp_skb)->code;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
343
  	struct sock *sk;
f1ecd5d9e   Damian Lukowski   Revert Backoff [v...
344
  	struct sk_buff *skb;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
345
  	__u32 seq;
f1ecd5d9e   Damian Lukowski   Revert Backoff [v...
346
  	__u32 remaining;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
347
  	int err;
4d1a2d9ec   Damian Lukowski   Revert Backoff [v...
348
  	struct net *net = dev_net(icmp_skb->dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
349

4d1a2d9ec   Damian Lukowski   Revert Backoff [v...
350
  	if (icmp_skb->len < (iph->ihl << 2) + 8) {
dcfc23cac   Pavel Emelyanov   mib: add struct n...
351
  		ICMP_INC_STATS_BH(net, ICMP_MIB_INERRORS);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
352
353
  		return;
  	}
fd54d716b   Pavel Emelyanov   inet: toss struct...
354
  	sk = inet_lookup(net, &tcp_hashinfo, iph->daddr, th->dest,
4d1a2d9ec   Damian Lukowski   Revert Backoff [v...
355
  			iph->saddr, th->source, inet_iif(icmp_skb));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
356
  	if (!sk) {
dcfc23cac   Pavel Emelyanov   mib: add struct n...
357
  		ICMP_INC_STATS_BH(net, ICMP_MIB_INERRORS);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
358
359
360
  		return;
  	}
  	if (sk->sk_state == TCP_TIME_WAIT) {
9469c7b4a   YOSHIFUJI Hideaki   [NET]: Use typesa...
361
  		inet_twsk_put(inet_twsk(sk));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
362
363
364
365
366
367
368
369
  		return;
  	}
  
  	bh_lock_sock(sk);
  	/* If too many ICMPs get dropped on busy
  	 * servers this needs to be solved differently.
  	 */
  	if (sock_owned_by_user(sk))
de0744af1   Pavel Emelyanov   mib: add net to N...
370
  		NET_INC_STATS_BH(net, LINUX_MIB_LOCKDROPPEDICMPS);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
371
372
373
  
  	if (sk->sk_state == TCP_CLOSE)
  		goto out;
97e3ecd11   stephen hemminger   TCP: check min TT...
374
375
376
377
  	if (unlikely(iph->ttl < inet_sk(sk)->min_ttl)) {
  		NET_INC_STATS_BH(net, LINUX_MIB_TCPMINTTLDROP);
  		goto out;
  	}
f1ecd5d9e   Damian Lukowski   Revert Backoff [v...
378
  	icsk = inet_csk(sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
379
380
381
382
  	tp = tcp_sk(sk);
  	seq = ntohl(th->seq);
  	if (sk->sk_state != TCP_LISTEN &&
  	    !between(seq, tp->snd_una, tp->snd_nxt)) {
de0744af1   Pavel Emelyanov   mib: add net to N...
383
  		NET_INC_STATS_BH(net, LINUX_MIB_OUTOFWINDOWICMPS);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
  		goto out;
  	}
  
  	switch (type) {
  	case ICMP_SOURCE_QUENCH:
  		/* Just silently ignore these. */
  		goto out;
  	case ICMP_PARAMETERPROB:
  		err = EPROTO;
  		break;
  	case ICMP_DEST_UNREACH:
  		if (code > NR_ICMP_UNREACH)
  			goto out;
  
  		if (code == ICMP_FRAG_NEEDED) { /* PMTU discovery (RFC1191) */
  			if (!sock_owned_by_user(sk))
  				do_pmtu_discovery(sk, iph, info);
  			goto out;
  		}
  
  		err = icmp_err_convert[code].errno;
f1ecd5d9e   Damian Lukowski   Revert Backoff [v...
405
406
407
408
409
410
411
  		/* check if icmp_skb allows revert of backoff
  		 * (see draft-zimmermann-tcp-lcd) */
  		if (code != ICMP_NET_UNREACH && code != ICMP_HOST_UNREACH)
  			break;
  		if (seq != tp->snd_una  || !icsk->icsk_retransmits ||
  		    !icsk->icsk_backoff)
  			break;
8f49c2703   David S. Miller   tcp: Don't change...
412
413
  		if (sock_owned_by_user(sk))
  			break;
f1ecd5d9e   Damian Lukowski   Revert Backoff [v...
414
  		icsk->icsk_backoff--;
9ad7c049f   Jerry Chu   tcp: RFC2988bis +...
415
416
  		inet_csk(sk)->icsk_rto = (tp->srtt ? __tcp_set_rto(tp) :
  			TCP_TIMEOUT_INIT) << icsk->icsk_backoff;
f1ecd5d9e   Damian Lukowski   Revert Backoff [v...
417
418
419
420
421
422
423
424
425
426
427
  		tcp_bound_rto(sk);
  
  		skb = tcp_write_queue_head(sk);
  		BUG_ON(!skb);
  
  		remaining = icsk->icsk_rto - min(icsk->icsk_rto,
  				tcp_time_stamp - TCP_SKB_CB(skb)->when);
  
  		if (remaining) {
  			inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS,
  						  remaining, TCP_RTO_MAX);
f1ecd5d9e   Damian Lukowski   Revert Backoff [v...
428
429
430
431
432
  		} else {
  			/* RTO revert clocked out retransmission.
  			 * Will retransmit now */
  			tcp_retransmit_timer(sk);
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
433
434
435
436
437
438
439
440
441
  		break;
  	case ICMP_TIME_EXCEEDED:
  		err = EHOSTUNREACH;
  		break;
  	default:
  		goto out;
  	}
  
  	switch (sk->sk_state) {
60236fdd0   Arnaldo Carvalho de Melo   [NET] Rename open...
442
  		struct request_sock *req, **prev;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
443
444
445
  	case TCP_LISTEN:
  		if (sock_owned_by_user(sk))
  			goto out;
463c84b97   Arnaldo Carvalho de Melo   [NET]: Introduce ...
446
447
  		req = inet_csk_search_req(sk, &prev, th->dest,
  					  iph->daddr, iph->saddr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
448
449
450
451
452
453
  		if (!req)
  			goto out;
  
  		/* ICMPs are not backlogged, hence we cannot get
  		   an established socket here.
  		 */
547b792ca   Ilpo Järvinen   net: convert BUG_...
454
  		WARN_ON(req->sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
455

2e6599cb8   Arnaldo Carvalho de Melo   [NET] Generalise ...
456
  		if (seq != tcp_rsk(req)->snt_isn) {
de0744af1   Pavel Emelyanov   mib: add net to N...
457
  			NET_INC_STATS_BH(net, LINUX_MIB_OUTOFWINDOWICMPS);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
458
459
460
461
462
463
464
465
466
  			goto out;
  		}
  
  		/*
  		 * Still in SYN_RECV, just remove it silently.
  		 * There is no good way to pass the error to the newly
  		 * created socket, and POSIX does not want network
  		 * errors returned from accept().
  		 */
463c84b97   Arnaldo Carvalho de Melo   [NET]: Introduce ...
467
  		inet_csk_reqsk_queue_drop(sk, req, prev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
468
469
470
471
472
473
474
  		goto out;
  
  	case TCP_SYN_SENT:
  	case TCP_SYN_RECV:  /* Cannot happen.
  			       It can f.e. if SYNs crossed.
  			     */
  		if (!sock_owned_by_user(sk)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
  			sk->sk_err = err;
  
  			sk->sk_error_report(sk);
  
  			tcp_done(sk);
  		} else {
  			sk->sk_err_soft = err;
  		}
  		goto out;
  	}
  
  	/* If we've already connected we will keep trying
  	 * until we time out, or the user gives up.
  	 *
  	 * rfc1122 4.2.3.9 allows to consider as hard errors
  	 * only PROTO_UNREACH and PORT_UNREACH (well, FRAG_FAILED too,
  	 * but it is obsoleted by pmtu discovery).
  	 *
  	 * Note, that in modern internet, where routing is unreliable
  	 * and in each dark corner broken firewalls sit, sending random
  	 * errors ordered by their masters even this two messages finally lose
  	 * their original sense (even Linux sends invalid PORT_UNREACHs)
  	 *
  	 * Now we are in compliance with RFCs.
  	 *							--ANK (980905)
  	 */
  
  	inet = inet_sk(sk);
  	if (!sock_owned_by_user(sk) && inet->recverr) {
  		sk->sk_err = err;
  		sk->sk_error_report(sk);
  	} else	{ /* Only an error on timeout */
  		sk->sk_err_soft = err;
  	}
  
  out:
  	bh_unlock_sock(sk);
  	sock_put(sk);
  }
419f9f896   Herbert Xu   tcp: Handle CHECK...
514
515
  static void __tcp_v4_send_check(struct sk_buff *skb,
  				__be32 saddr, __be32 daddr)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
516
  {
aa8223c7b   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
517
  	struct tcphdr *th = tcp_hdr(skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
518

84fa7933a   Patrick McHardy   [NET]: Replace CH...
519
  	if (skb->ip_summed == CHECKSUM_PARTIAL) {
419f9f896   Herbert Xu   tcp: Handle CHECK...
520
  		th->check = ~tcp_v4_check(skb->len, saddr, daddr, 0);
663ead3bb   Herbert Xu   [NET]: Use csum_s...
521
  		skb->csum_start = skb_transport_header(skb) - skb->head;
ff1dcadb1   Al Viro   [NET]: Split skb-...
522
  		skb->csum_offset = offsetof(struct tcphdr, check);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
523
  	} else {
419f9f896   Herbert Xu   tcp: Handle CHECK...
524
  		th->check = tcp_v4_check(skb->len, saddr, daddr,
07f0757a6   Joe Perches   include/net net/ ...
525
  					 csum_partial(th,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
526
527
528
529
  						      th->doff << 2,
  						      skb->csum));
  	}
  }
419f9f896   Herbert Xu   tcp: Handle CHECK...
530
  /* This routine computes an IPv4 TCP checksum. */
bb2962461   Herbert Xu   inet: Remove unus...
531
  void tcp_v4_send_check(struct sock *sk, struct sk_buff *skb)
419f9f896   Herbert Xu   tcp: Handle CHECK...
532
  {
cf533ea53   Eric Dumazet   tcp: add const qu...
533
  	const struct inet_sock *inet = inet_sk(sk);
419f9f896   Herbert Xu   tcp: Handle CHECK...
534
535
536
  
  	__tcp_v4_send_check(skb, inet->inet_saddr, inet->inet_daddr);
  }
4bc2f18ba   Eric Dumazet   net/ipv4: EXPORT_...
537
  EXPORT_SYMBOL(tcp_v4_send_check);
419f9f896   Herbert Xu   tcp: Handle CHECK...
538

a430a43d0   Herbert Xu   [NET] gso: Fix up...
539
540
  int tcp_v4_gso_send_check(struct sk_buff *skb)
  {
eddc9ec53   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
541
  	const struct iphdr *iph;
a430a43d0   Herbert Xu   [NET] gso: Fix up...
542
543
544
545
  	struct tcphdr *th;
  
  	if (!pskb_may_pull(skb, sizeof(*th)))
  		return -EINVAL;
eddc9ec53   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
546
  	iph = ip_hdr(skb);
aa8223c7b   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
547
  	th = tcp_hdr(skb);
a430a43d0   Herbert Xu   [NET] gso: Fix up...
548
549
  
  	th->check = 0;
84fa7933a   Patrick McHardy   [NET]: Replace CH...
550
  	skb->ip_summed = CHECKSUM_PARTIAL;
419f9f896   Herbert Xu   tcp: Handle CHECK...
551
  	__tcp_v4_send_check(skb, iph->saddr, iph->daddr);
a430a43d0   Herbert Xu   [NET] gso: Fix up...
552
553
  	return 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
554
555
556
557
558
559
560
561
562
563
564
565
  /*
   *	This routine will send an RST to the other tcp.
   *
   *	Someone asks: why I NEVER use socket parameters (TOS, TTL etc.)
   *		      for reset.
   *	Answer: if a packet caused RST, it is not for a socket
   *		existing in our system, if it is matched to a socket,
   *		it is just duplicate segment or bug in other side's TCP.
   *		So that we build reply only basing on parameters
   *		arrived with segment.
   *	Exception: precedence violation. We do not implement it in any case.
   */
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
566
  static void tcp_v4_send_reset(struct sock *sk, struct sk_buff *skb)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
567
  {
cf533ea53   Eric Dumazet   tcp: add const qu...
568
  	const struct tcphdr *th = tcp_hdr(skb);
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
569
570
571
  	struct {
  		struct tcphdr th;
  #ifdef CONFIG_TCP_MD5SIG
714e85be3   Al Viro   [IPV6]: Assorted ...
572
  		__be32 opt[(TCPOLEN_MD5SIG_ALIGNED >> 2)];
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
573
574
  #endif
  	} rep;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
575
  	struct ip_reply_arg arg;
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
576
577
578
  #ifdef CONFIG_TCP_MD5SIG
  	struct tcp_md5sig_key *key;
  #endif
a86b1e301   Pavel Emelyanov   inet: prepare str...
579
  	struct net *net;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
580
581
582
583
  
  	/* Never send a reset in response to a reset. */
  	if (th->rst)
  		return;
511c3f92a   Eric Dumazet   net: skb->rtable ...
584
  	if (skb_rtable(skb)->rt_type != RTN_LOCAL)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
585
586
587
  		return;
  
  	/* Swap the send and the receive. */
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
588
589
590
591
592
  	memset(&rep, 0, sizeof(rep));
  	rep.th.dest   = th->source;
  	rep.th.source = th->dest;
  	rep.th.doff   = sizeof(struct tcphdr) / 4;
  	rep.th.rst    = 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
593
594
  
  	if (th->ack) {
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
595
  		rep.th.seq = th->ack_seq;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
596
  	} else {
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
597
598
599
  		rep.th.ack = 1;
  		rep.th.ack_seq = htonl(ntohl(th->seq) + th->syn + th->fin +
  				       skb->len - (th->doff << 2));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
600
  	}
7174259e6   Arnaldo Carvalho de Melo   [TCP_IPV4]: Codin...
601
  	memset(&arg, 0, sizeof(arg));
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
602
603
604
605
  	arg.iov[0].iov_base = (unsigned char *)&rep;
  	arg.iov[0].iov_len  = sizeof(rep.th);
  
  #ifdef CONFIG_TCP_MD5SIG
eddc9ec53   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
606
  	key = sk ? tcp_v4_md5_do_lookup(sk, ip_hdr(skb)->daddr) : NULL;
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
607
608
609
610
611
612
613
614
  	if (key) {
  		rep.opt[0] = htonl((TCPOPT_NOP << 24) |
  				   (TCPOPT_NOP << 16) |
  				   (TCPOPT_MD5SIG << 8) |
  				   TCPOLEN_MD5SIG);
  		/* Update length and the length the header thinks exists */
  		arg.iov[0].iov_len += TCPOLEN_MD5SIG_ALIGNED;
  		rep.th.doff = arg.iov[0].iov_len / 4;
49a72dfb8   Adam Langley   tcp: Fix MD5 sign...
615
  		tcp_v4_md5_hash_hdr((__u8 *) &rep.opt[1],
78e645cb8   Ilpo Järvinen   tcpv[46]: fix md5...
616
617
  				     key, ip_hdr(skb)->saddr,
  				     ip_hdr(skb)->daddr, &rep.th);
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
618
619
  	}
  #endif
eddc9ec53   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
620
621
  	arg.csum = csum_tcpudp_nofold(ip_hdr(skb)->daddr,
  				      ip_hdr(skb)->saddr, /* XXX */
52cd5750e   Ilpo Järvinen   tcp: fix length u...
622
  				      arg.iov[0].iov_len, IPPROTO_TCP, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
623
  	arg.csumoffset = offsetof(struct tcphdr, check) / 2;
88ef4a5a7   KOVACS Krisztian   tcp: Handle TCP S...
624
  	arg.flags = (sk && inet_sk(sk)->transparent) ? IP_REPLY_ARG_NOSRCCHECK : 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
625

adf30907d   Eric Dumazet   net: skb->dst acc...
626
  	net = dev_net(skb_dst(skb)->dev);
66b13d99d   Eric Dumazet   ipv4: tcp: fix TO...
627
  	arg.tos = ip_hdr(skb)->tos;
0a5ebb800   David S. Miller   ipv4: Pass explic...
628
  	ip_send_reply(net->ipv4.tcp_sock, skb, ip_hdr(skb)->saddr,
7feb49c82   Denis V. Lunev   [NETNS]: Use TCP ...
629
  		      &arg, arg.iov[0].iov_len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
630

63231bddf   Pavel Emelyanov   mib: add net to T...
631
632
  	TCP_INC_STATS_BH(net, TCP_MIB_OUTSEGS);
  	TCP_INC_STATS_BH(net, TCP_MIB_OUTRSTS);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
633
634
635
636
637
  }
  
  /* The code following below sending ACKs in SYN-RECV and TIME-WAIT states
     outside socket context is ugly, certainly. What can I do?
   */
9501f9722   YOSHIFUJI Hideaki   tcp md5sig: Let t...
638
639
  static void tcp_v4_send_ack(struct sk_buff *skb, u32 seq, u32 ack,
  			    u32 win, u32 ts, int oif,
88ef4a5a7   KOVACS Krisztian   tcp: Handle TCP S...
640
  			    struct tcp_md5sig_key *key,
66b13d99d   Eric Dumazet   ipv4: tcp: fix TO...
641
  			    int reply_flags, u8 tos)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
642
  {
cf533ea53   Eric Dumazet   tcp: add const qu...
643
  	const struct tcphdr *th = tcp_hdr(skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
644
645
  	struct {
  		struct tcphdr th;
714e85be3   Al Viro   [IPV6]: Assorted ...
646
  		__be32 opt[(TCPOLEN_TSTAMP_ALIGNED >> 2)
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
647
  #ifdef CONFIG_TCP_MD5SIG
714e85be3   Al Viro   [IPV6]: Assorted ...
648
  			   + (TCPOLEN_MD5SIG_ALIGNED >> 2)
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
649
650
  #endif
  			];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
651
652
  	} rep;
  	struct ip_reply_arg arg;
adf30907d   Eric Dumazet   net: skb->dst acc...
653
  	struct net *net = dev_net(skb_dst(skb)->dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
654
655
  
  	memset(&rep.th, 0, sizeof(struct tcphdr));
7174259e6   Arnaldo Carvalho de Melo   [TCP_IPV4]: Codin...
656
  	memset(&arg, 0, sizeof(arg));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
657
658
659
660
  
  	arg.iov[0].iov_base = (unsigned char *)&rep;
  	arg.iov[0].iov_len  = sizeof(rep.th);
  	if (ts) {
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
661
662
663
664
665
  		rep.opt[0] = htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) |
  				   (TCPOPT_TIMESTAMP << 8) |
  				   TCPOLEN_TIMESTAMP);
  		rep.opt[1] = htonl(tcp_time_stamp);
  		rep.opt[2] = htonl(ts);
cb48cfe80   Craig Schlenter   [TCP]: Fix iov_le...
666
  		arg.iov[0].iov_len += TCPOLEN_TSTAMP_ALIGNED;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
667
668
669
670
671
672
673
674
675
676
  	}
  
  	/* Swap the send and the receive. */
  	rep.th.dest    = th->source;
  	rep.th.source  = th->dest;
  	rep.th.doff    = arg.iov[0].iov_len / 4;
  	rep.th.seq     = htonl(seq);
  	rep.th.ack_seq = htonl(ack);
  	rep.th.ack     = 1;
  	rep.th.window  = htons(win);
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
677
  #ifdef CONFIG_TCP_MD5SIG
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
678
679
680
681
682
683
684
685
686
  	if (key) {
  		int offset = (ts) ? 3 : 0;
  
  		rep.opt[offset++] = htonl((TCPOPT_NOP << 24) |
  					  (TCPOPT_NOP << 16) |
  					  (TCPOPT_MD5SIG << 8) |
  					  TCPOLEN_MD5SIG);
  		arg.iov[0].iov_len += TCPOLEN_MD5SIG_ALIGNED;
  		rep.th.doff = arg.iov[0].iov_len/4;
49a72dfb8   Adam Langley   tcp: Fix MD5 sign...
687
  		tcp_v4_md5_hash_hdr((__u8 *) &rep.opt[offset],
90b7e1120   Adam Langley   tcp: MD5: Fix MD5...
688
689
  				    key, ip_hdr(skb)->saddr,
  				    ip_hdr(skb)->daddr, &rep.th);
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
690
691
  	}
  #endif
88ef4a5a7   KOVACS Krisztian   tcp: Handle TCP S...
692
  	arg.flags = reply_flags;
eddc9ec53   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
693
694
  	arg.csum = csum_tcpudp_nofold(ip_hdr(skb)->daddr,
  				      ip_hdr(skb)->saddr, /* XXX */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
695
696
  				      arg.iov[0].iov_len, IPPROTO_TCP, 0);
  	arg.csumoffset = offsetof(struct tcphdr, check) / 2;
9501f9722   YOSHIFUJI Hideaki   tcp md5sig: Let t...
697
698
  	if (oif)
  		arg.bound_dev_if = oif;
66b13d99d   Eric Dumazet   ipv4: tcp: fix TO...
699
  	arg.tos = tos;
0a5ebb800   David S. Miller   ipv4: Pass explic...
700
  	ip_send_reply(net->ipv4.tcp_sock, skb, ip_hdr(skb)->saddr,
7feb49c82   Denis V. Lunev   [NETNS]: Use TCP ...
701
  		      &arg, arg.iov[0].iov_len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
702

63231bddf   Pavel Emelyanov   mib: add net to T...
703
  	TCP_INC_STATS_BH(net, TCP_MIB_OUTSEGS);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
704
705
706
707
  }
  
  static void tcp_v4_timewait_ack(struct sock *sk, struct sk_buff *skb)
  {
8feaf0c0a   Arnaldo Carvalho de Melo   [INET]: Generalis...
708
  	struct inet_timewait_sock *tw = inet_twsk(sk);
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
709
  	struct tcp_timewait_sock *tcptw = tcp_twsk(sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
710

9501f9722   YOSHIFUJI Hideaki   tcp md5sig: Let t...
711
  	tcp_v4_send_ack(skb, tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt,
7174259e6   Arnaldo Carvalho de Melo   [TCP_IPV4]: Codin...
712
  			tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale,
9501f9722   YOSHIFUJI Hideaki   tcp md5sig: Let t...
713
714
  			tcptw->tw_ts_recent,
  			tw->tw_bound_dev_if,
88ef4a5a7   KOVACS Krisztian   tcp: Handle TCP S...
715
  			tcp_twsk_md5_key(tcptw),
66b13d99d   Eric Dumazet   ipv4: tcp: fix TO...
716
717
  			tw->tw_transparent ? IP_REPLY_ARG_NOSRCCHECK : 0,
  			tw->tw_tos
9501f9722   YOSHIFUJI Hideaki   tcp md5sig: Let t...
718
  			);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
719

8feaf0c0a   Arnaldo Carvalho de Melo   [INET]: Generalis...
720
  	inet_twsk_put(tw);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
721
  }
6edafaaf6   Gui Jianfeng   tcp: Fix kernel p...
722
  static void tcp_v4_reqsk_send_ack(struct sock *sk, struct sk_buff *skb,
7174259e6   Arnaldo Carvalho de Melo   [TCP_IPV4]: Codin...
723
  				  struct request_sock *req)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
724
  {
9501f9722   YOSHIFUJI Hideaki   tcp md5sig: Let t...
725
  	tcp_v4_send_ack(skb, tcp_rsk(req)->snt_isn + 1,
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
726
  			tcp_rsk(req)->rcv_isn + 1, req->rcv_wnd,
9501f9722   YOSHIFUJI Hideaki   tcp md5sig: Let t...
727
728
  			req->ts_recent,
  			0,
88ef4a5a7   KOVACS Krisztian   tcp: Handle TCP S...
729
  			tcp_v4_md5_do_lookup(sk, ip_hdr(skb)->daddr),
66b13d99d   Eric Dumazet   ipv4: tcp: fix TO...
730
731
  			inet_rsk(req)->no_srccheck ? IP_REPLY_ARG_NOSRCCHECK : 0,
  			ip_hdr(skb)->tos);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
732
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
733
  /*
9bf1d83e7   Kris Katterjohn   [TCP]: Fix tcp_v4...
734
   *	Send a SYN-ACK after having received a SYN.
60236fdd0   Arnaldo Carvalho de Melo   [NET] Rename open...
735
   *	This still operates on a request_sock only, not on a big
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
736
737
   *	socket.
   */
72659ecce   Octavian Purdila   tcp: account SYN-...
738
739
740
  static int tcp_v4_send_synack(struct sock *sk, struct dst_entry *dst,
  			      struct request_sock *req,
  			      struct request_values *rvp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
741
  {
2e6599cb8   Arnaldo Carvalho de Melo   [NET] Generalise ...
742
  	const struct inet_request_sock *ireq = inet_rsk(req);
6bd023f3d   David S. Miller   ipv4: Make caller...
743
  	struct flowi4 fl4;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
744
745
746
747
  	int err = -1;
  	struct sk_buff * skb;
  
  	/* First, grab a route. */
6bd023f3d   David S. Miller   ipv4: Make caller...
748
  	if (!dst && (dst = inet_csk_route_req(sk, &fl4, req)) == NULL)
fd80eb942   Denis V. Lunev   [INET]: Remove st...
749
  		return -1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
750

e6b4d1136   William Allen Simpson   TCPCT part 1a: ad...
751
  	skb = tcp_make_synack(sk, dst, req, rvp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
752
753
  
  	if (skb) {
419f9f896   Herbert Xu   tcp: Handle CHECK...
754
  		__tcp_v4_send_check(skb, ireq->loc_addr, ireq->rmt_addr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
755

2e6599cb8   Arnaldo Carvalho de Melo   [NET] Generalise ...
756
757
758
  		err = ip_build_and_send_pkt(skb, sk, ireq->loc_addr,
  					    ireq->rmt_addr,
  					    ireq->opt);
b9df3cb8c   Gerrit Renker   [TCP/DCCP]: Intro...
759
  		err = net_xmit_eval(err);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
760
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
761
762
763
  	dst_release(dst);
  	return err;
  }
72659ecce   Octavian Purdila   tcp: account SYN-...
764
  static int tcp_v4_rtx_synack(struct sock *sk, struct request_sock *req,
e6b4d1136   William Allen Simpson   TCPCT part 1a: ad...
765
  			      struct request_values *rvp)
fd80eb942   Denis V. Lunev   [INET]: Remove st...
766
  {
72659ecce   Octavian Purdila   tcp: account SYN-...
767
768
  	TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_RETRANSSEGS);
  	return tcp_v4_send_synack(sk, NULL, req, rvp);
fd80eb942   Denis V. Lunev   [INET]: Remove st...
769
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
770
  /*
60236fdd0   Arnaldo Carvalho de Melo   [NET] Rename open...
771
   *	IPv4 request_sock destructor.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
772
   */
60236fdd0   Arnaldo Carvalho de Melo   [NET] Rename open...
773
  static void tcp_v4_reqsk_destructor(struct request_sock *req)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
774
  {
a51482bde   Jesper Juhl   [NET]: kfree cleanup
775
  	kfree(inet_rsk(req)->opt);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
776
  }
946cedccb   Eric Dumazet   tcp: Change possi...
777
778
779
780
781
782
  /*
   * Return 1 if a syncookie should be sent
   */
  int tcp_syn_flood_action(struct sock *sk,
  			 const struct sk_buff *skb,
  			 const char *proto)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
783
  {
946cedccb   Eric Dumazet   tcp: Change possi...
784
785
786
  	const char *msg = "Dropping request";
  	int want_cookie = 0;
  	struct listen_sock *lopt;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
787

2a1d4bd46   Florian Westphal   syncookies: make ...
788
  #ifdef CONFIG_SYN_COOKIES
946cedccb   Eric Dumazet   tcp: Change possi...
789
  	if (sysctl_tcp_syncookies) {
2a1d4bd46   Florian Westphal   syncookies: make ...
790
  		msg = "Sending cookies";
946cedccb   Eric Dumazet   tcp: Change possi...
791
792
793
  		want_cookie = 1;
  		NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPREQQFULLDOCOOKIES);
  	} else
80e40daa4   Arnaldo Carvalho de Melo   [TCP]: syn_flood_...
794
  #endif
946cedccb   Eric Dumazet   tcp: Change possi...
795
796
797
798
799
800
801
802
803
804
805
  		NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPREQQFULLDROP);
  
  	lopt = inet_csk(sk)->icsk_accept_queue.listen_opt;
  	if (!lopt->synflood_warned) {
  		lopt->synflood_warned = 1;
  		pr_info("%s: Possible SYN flooding on port %d. %s. "
  			" Check SNMP counters.
  ",
  			proto, ntohs(tcp_hdr(skb)->dest), msg);
  	}
  	return want_cookie;
2a1d4bd46   Florian Westphal   syncookies: make ...
806
  }
946cedccb   Eric Dumazet   tcp: Change possi...
807
  EXPORT_SYMBOL(tcp_syn_flood_action);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
808
809
  
  /*
60236fdd0   Arnaldo Carvalho de Melo   [NET] Rename open...
810
   * Save and compile IPv4 options into the request_sock if needed.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
811
   */
f6d8bd051   Eric Dumazet   inet: add RCU pro...
812
813
  static struct ip_options_rcu *tcp_v4_save_options(struct sock *sk,
  						  struct sk_buff *skb)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
814
  {
f6d8bd051   Eric Dumazet   inet: add RCU pro...
815
816
  	const struct ip_options *opt = &(IPCB(skb)->opt);
  	struct ip_options_rcu *dopt = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
817
818
  
  	if (opt && opt->optlen) {
f6d8bd051   Eric Dumazet   inet: add RCU pro...
819
  		int opt_size = sizeof(*dopt) + opt->optlen;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
820
821
  		dopt = kmalloc(opt_size, GFP_ATOMIC);
  		if (dopt) {
f6d8bd051   Eric Dumazet   inet: add RCU pro...
822
  			if (ip_options_echo(&dopt->opt, skb)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
823
824
825
826
827
828
829
  				kfree(dopt);
  				dopt = NULL;
  			}
  		}
  	}
  	return dopt;
  }
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
830
831
832
833
834
835
836
837
  #ifdef CONFIG_TCP_MD5SIG
  /*
   * RFC2385 MD5 checksumming requires a mapping of
   * IP address->MD5 Key.
   * We need to maintain these in the sk structure.
   */
  
  /* Find the Key structure for an address.  */
7174259e6   Arnaldo Carvalho de Melo   [TCP_IPV4]: Codin...
838
839
  static struct tcp_md5sig_key *
  			tcp_v4_md5_do_lookup(struct sock *sk, __be32 addr)
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
840
841
842
843
844
845
846
847
  {
  	struct tcp_sock *tp = tcp_sk(sk);
  	int i;
  
  	if (!tp->md5sig_info || !tp->md5sig_info->entries4)
  		return NULL;
  	for (i = 0; i < tp->md5sig_info->entries4; i++) {
  		if (tp->md5sig_info->keys4[i].addr == addr)
f8ab18d2d   David S. Miller   [TCP]: Fix MD5 si...
848
  			return &tp->md5sig_info->keys4[i].base;
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
849
850
851
852
853
854
855
  	}
  	return NULL;
  }
  
  struct tcp_md5sig_key *tcp_v4_md5_lookup(struct sock *sk,
  					 struct sock *addr_sk)
  {
c720c7e83   Eric Dumazet   inet: rename some...
856
  	return tcp_v4_md5_do_lookup(sk, inet_sk(addr_sk)->inet_daddr);
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
857
  }
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
858
  EXPORT_SYMBOL(tcp_v4_md5_lookup);
f5b99bcdd   Adrian Bunk   [NET]: Possible c...
859
860
  static struct tcp_md5sig_key *tcp_v4_reqsk_md5_lookup(struct sock *sk,
  						      struct request_sock *req)
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
861
862
863
864
865
866
867
868
869
  {
  	return tcp_v4_md5_do_lookup(sk, inet_rsk(req)->rmt_addr);
  }
  
  /* This can be called on a newly created socket, from other files */
  int tcp_v4_md5_do_add(struct sock *sk, __be32 addr,
  		      u8 *newkey, u8 newkeylen)
  {
  	/* Add Key to the list */
b0a713e9e   Matthias M. Dellweg   [TCP] MD5: Remove...
870
  	struct tcp_md5sig_key *key;
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
871
872
  	struct tcp_sock *tp = tcp_sk(sk);
  	struct tcp4_md5sig_key *keys;
b0a713e9e   Matthias M. Dellweg   [TCP] MD5: Remove...
873
  	key = tcp_v4_md5_do_lookup(sk, addr);
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
874
875
  	if (key) {
  		/* Pre-existing entry - just update that one. */
b0a713e9e   Matthias M. Dellweg   [TCP] MD5: Remove...
876
877
878
  		kfree(key->key);
  		key->key = newkey;
  		key->keylen = newkeylen;
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
879
  	} else {
f6685938f   Arnaldo Carvalho de Melo   [TCP_IPV4]: Use k...
880
  		struct tcp_md5sig_info *md5sig;
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
881
  		if (!tp->md5sig_info) {
f6685938f   Arnaldo Carvalho de Melo   [TCP_IPV4]: Use k...
882
883
  			tp->md5sig_info = kzalloc(sizeof(*tp->md5sig_info),
  						  GFP_ATOMIC);
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
884
885
886
887
  			if (!tp->md5sig_info) {
  				kfree(newkey);
  				return -ENOMEM;
  			}
a465419b1   Eric Dumazet   net: Introduce sk...
888
  			sk_nocaps_add(sk, NETIF_F_GSO_MASK);
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
889
  		}
260fcbeb1   Yan, Zheng   tcp: properly han...
890
891
892
893
  
  		md5sig = tp->md5sig_info;
  		if (md5sig->entries4 == 0 &&
  		    tcp_alloc_md5sig_pool(sk) == NULL) {
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
894
895
896
  			kfree(newkey);
  			return -ENOMEM;
  		}
f6685938f   Arnaldo Carvalho de Melo   [TCP_IPV4]: Use k...
897
898
899
  
  		if (md5sig->alloced4 == md5sig->entries4) {
  			keys = kmalloc((sizeof(*keys) *
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
900
  					(md5sig->entries4 + 1)), GFP_ATOMIC);
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
901
902
  			if (!keys) {
  				kfree(newkey);
260fcbeb1   Yan, Zheng   tcp: properly han...
903
904
  				if (md5sig->entries4 == 0)
  					tcp_free_md5sig_pool();
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
905
906
  				return -ENOMEM;
  			}
f6685938f   Arnaldo Carvalho de Melo   [TCP_IPV4]: Use k...
907
908
909
  			if (md5sig->entries4)
  				memcpy(keys, md5sig->keys4,
  				       sizeof(*keys) * md5sig->entries4);
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
910
911
  
  			/* Free old key list, and reference new one */
a80cc20da   YOSHIFUJI Hideaki   [IPV4] TCPMD5: Om...
912
  			kfree(md5sig->keys4);
f6685938f   Arnaldo Carvalho de Melo   [TCP_IPV4]: Use k...
913
914
  			md5sig->keys4 = keys;
  			md5sig->alloced4++;
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
915
  		}
f6685938f   Arnaldo Carvalho de Melo   [TCP_IPV4]: Use k...
916
  		md5sig->entries4++;
f8ab18d2d   David S. Miller   [TCP]: Fix MD5 si...
917
918
919
  		md5sig->keys4[md5sig->entries4 - 1].addr        = addr;
  		md5sig->keys4[md5sig->entries4 - 1].base.key    = newkey;
  		md5sig->keys4[md5sig->entries4 - 1].base.keylen = newkeylen;
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
920
921
922
  	}
  	return 0;
  }
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
923
924
925
926
927
  EXPORT_SYMBOL(tcp_v4_md5_do_add);
  
  static int tcp_v4_md5_add_func(struct sock *sk, struct sock *addr_sk,
  			       u8 *newkey, u8 newkeylen)
  {
c720c7e83   Eric Dumazet   inet: rename some...
928
  	return tcp_v4_md5_do_add(sk, inet_sk(addr_sk)->inet_daddr,
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
929
930
931
932
933
934
935
936
937
938
939
  				 newkey, newkeylen);
  }
  
  int tcp_v4_md5_do_del(struct sock *sk, __be32 addr)
  {
  	struct tcp_sock *tp = tcp_sk(sk);
  	int i;
  
  	for (i = 0; i < tp->md5sig_info->entries4; i++) {
  		if (tp->md5sig_info->keys4[i].addr == addr) {
  			/* Free the key */
f8ab18d2d   David S. Miller   [TCP]: Fix MD5 si...
940
  			kfree(tp->md5sig_info->keys4[i].base.key);
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
941
942
943
944
945
  			tp->md5sig_info->entries4--;
  
  			if (tp->md5sig_info->entries4 == 0) {
  				kfree(tp->md5sig_info->keys4);
  				tp->md5sig_info->keys4 = NULL;
8228a18dd   Leigh Brown   [TCP]: Fix oops c...
946
  				tp->md5sig_info->alloced4 = 0;
260fcbeb1   Yan, Zheng   tcp: properly han...
947
  				tcp_free_md5sig_pool();
7174259e6   Arnaldo Carvalho de Melo   [TCP_IPV4]: Codin...
948
  			} else if (tp->md5sig_info->entries4 != i) {
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
949
  				/* Need to do some manipulation */
354faf097   YOSHIFUJI Hideaki   [IPV4] TCPMD5: Us...
950
951
952
953
  				memmove(&tp->md5sig_info->keys4[i],
  					&tp->md5sig_info->keys4[i+1],
  					(tp->md5sig_info->entries4 - i) *
  					 sizeof(struct tcp4_md5sig_key));
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
954
  			}
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
955
956
957
958
959
  			return 0;
  		}
  	}
  	return -ENOENT;
  }
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
960
  EXPORT_SYMBOL(tcp_v4_md5_do_del);
7174259e6   Arnaldo Carvalho de Melo   [TCP_IPV4]: Codin...
961
  static void tcp_v4_clear_md5_list(struct sock *sk)
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
962
963
964
965
966
967
968
969
970
971
  {
  	struct tcp_sock *tp = tcp_sk(sk);
  
  	/* Free each key, then the set of key keys,
  	 * the crypto element, and then decrement our
  	 * hold on the last resort crypto.
  	 */
  	if (tp->md5sig_info->entries4) {
  		int i;
  		for (i = 0; i < tp->md5sig_info->entries4; i++)
f8ab18d2d   David S. Miller   [TCP]: Fix MD5 si...
972
  			kfree(tp->md5sig_info->keys4[i].base.key);
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
973
974
975
976
977
978
979
980
981
  		tp->md5sig_info->entries4 = 0;
  		tcp_free_md5sig_pool();
  	}
  	if (tp->md5sig_info->keys4) {
  		kfree(tp->md5sig_info->keys4);
  		tp->md5sig_info->keys4 = NULL;
  		tp->md5sig_info->alloced4  = 0;
  	}
  }
7174259e6   Arnaldo Carvalho de Melo   [TCP_IPV4]: Codin...
982
983
  static int tcp_v4_parse_md5_keys(struct sock *sk, char __user *optval,
  				 int optlen)
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
984
985
986
987
988
989
990
  {
  	struct tcp_md5sig cmd;
  	struct sockaddr_in *sin = (struct sockaddr_in *)&cmd.tcpm_addr;
  	u8 *newkey;
  
  	if (optlen < sizeof(cmd))
  		return -EINVAL;
7174259e6   Arnaldo Carvalho de Melo   [TCP_IPV4]: Codin...
991
  	if (copy_from_user(&cmd, optval, sizeof(cmd)))
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
  		return -EFAULT;
  
  	if (sin->sin_family != AF_INET)
  		return -EINVAL;
  
  	if (!cmd.tcpm_key || !cmd.tcpm_keylen) {
  		if (!tcp_sk(sk)->md5sig_info)
  			return -ENOENT;
  		return tcp_v4_md5_do_del(sk, sin->sin_addr.s_addr);
  	}
  
  	if (cmd.tcpm_keylen > TCP_MD5SIG_MAXKEYLEN)
  		return -EINVAL;
  
  	if (!tcp_sk(sk)->md5sig_info) {
  		struct tcp_sock *tp = tcp_sk(sk);
aa1330766   Wu Fengguang   tcp: replace hard...
1008
  		struct tcp_md5sig_info *p;
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1009

aa1330766   Wu Fengguang   tcp: replace hard...
1010
  		p = kzalloc(sizeof(*p), sk->sk_allocation);
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1011
1012
1013
1014
  		if (!p)
  			return -EINVAL;
  
  		tp->md5sig_info = p;
a465419b1   Eric Dumazet   net: Introduce sk...
1015
  		sk_nocaps_add(sk, NETIF_F_GSO_MASK);
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1016
  	}
aa1330766   Wu Fengguang   tcp: replace hard...
1017
  	newkey = kmemdup(cmd.tcpm_key, cmd.tcpm_keylen, sk->sk_allocation);
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1018
1019
  	if (!newkey)
  		return -ENOMEM;
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1020
1021
1022
  	return tcp_v4_md5_do_add(sk, sin->sin_addr.s_addr,
  				 newkey, cmd.tcpm_keylen);
  }
49a72dfb8   Adam Langley   tcp: Fix MD5 sign...
1023
1024
  static int tcp_v4_md5_hash_pseudoheader(struct tcp_md5sig_pool *hp,
  					__be32 daddr, __be32 saddr, int nbytes)
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1025
  {
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1026
  	struct tcp4_pseudohdr *bp;
49a72dfb8   Adam Langley   tcp: Fix MD5 sign...
1027
  	struct scatterlist sg;
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1028
1029
  
  	bp = &hp->md5_blk.ip4;
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1030
1031
  
  	/*
49a72dfb8   Adam Langley   tcp: Fix MD5 sign...
1032
  	 * 1. the TCP pseudo-header (in the order: source IP address,
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1033
1034
1035
1036
1037
1038
  	 * destination IP address, zero-padded protocol number, and
  	 * segment length)
  	 */
  	bp->saddr = saddr;
  	bp->daddr = daddr;
  	bp->pad = 0;
076fb7223   YOSHIFUJI Hideaki   tcp md5sig: Remov...
1039
  	bp->protocol = IPPROTO_TCP;
49a72dfb8   Adam Langley   tcp: Fix MD5 sign...
1040
  	bp->len = cpu_to_be16(nbytes);
c7da57a18   David S. Miller   [TCP]: Fix scatte...
1041

49a72dfb8   Adam Langley   tcp: Fix MD5 sign...
1042
1043
1044
1045
1046
  	sg_init_one(&sg, bp, sizeof(*bp));
  	return crypto_hash_update(&hp->md5_desc, &sg, sizeof(*bp));
  }
  
  static int tcp_v4_md5_hash_hdr(char *md5_hash, struct tcp_md5sig_key *key,
318cf7aaa   Eric Dumazet   tcp: md5: add mor...
1047
  			       __be32 daddr, __be32 saddr, const struct tcphdr *th)
49a72dfb8   Adam Langley   tcp: Fix MD5 sign...
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
  {
  	struct tcp_md5sig_pool *hp;
  	struct hash_desc *desc;
  
  	hp = tcp_get_md5sig_pool();
  	if (!hp)
  		goto clear_hash_noput;
  	desc = &hp->md5_desc;
  
  	if (crypto_hash_init(desc))
  		goto clear_hash;
  	if (tcp_v4_md5_hash_pseudoheader(hp, daddr, saddr, th->doff << 2))
  		goto clear_hash;
  	if (tcp_md5_hash_header(hp, th))
  		goto clear_hash;
  	if (tcp_md5_hash_key(hp, key))
  		goto clear_hash;
  	if (crypto_hash_final(desc, md5_hash))
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1066
  		goto clear_hash;
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1067
  	tcp_put_md5sig_pool();
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1068
  	return 0;
49a72dfb8   Adam Langley   tcp: Fix MD5 sign...
1069

cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1070
1071
1072
1073
  clear_hash:
  	tcp_put_md5sig_pool();
  clear_hash_noput:
  	memset(md5_hash, 0, 16);
49a72dfb8   Adam Langley   tcp: Fix MD5 sign...
1074
  	return 1;
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1075
  }
49a72dfb8   Adam Langley   tcp: Fix MD5 sign...
1076
  int tcp_v4_md5_hash_skb(char *md5_hash, struct tcp_md5sig_key *key,
318cf7aaa   Eric Dumazet   tcp: md5: add mor...
1077
1078
  			const struct sock *sk, const struct request_sock *req,
  			const struct sk_buff *skb)
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1079
  {
49a72dfb8   Adam Langley   tcp: Fix MD5 sign...
1080
1081
  	struct tcp_md5sig_pool *hp;
  	struct hash_desc *desc;
318cf7aaa   Eric Dumazet   tcp: md5: add mor...
1082
  	const struct tcphdr *th = tcp_hdr(skb);
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1083
1084
1085
  	__be32 saddr, daddr;
  
  	if (sk) {
c720c7e83   Eric Dumazet   inet: rename some...
1086
1087
  		saddr = inet_sk(sk)->inet_saddr;
  		daddr = inet_sk(sk)->inet_daddr;
49a72dfb8   Adam Langley   tcp: Fix MD5 sign...
1088
1089
1090
  	} else if (req) {
  		saddr = inet_rsk(req)->loc_addr;
  		daddr = inet_rsk(req)->rmt_addr;
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1091
  	} else {
49a72dfb8   Adam Langley   tcp: Fix MD5 sign...
1092
1093
1094
  		const struct iphdr *iph = ip_hdr(skb);
  		saddr = iph->saddr;
  		daddr = iph->daddr;
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1095
  	}
49a72dfb8   Adam Langley   tcp: Fix MD5 sign...
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
  
  	hp = tcp_get_md5sig_pool();
  	if (!hp)
  		goto clear_hash_noput;
  	desc = &hp->md5_desc;
  
  	if (crypto_hash_init(desc))
  		goto clear_hash;
  
  	if (tcp_v4_md5_hash_pseudoheader(hp, daddr, saddr, skb->len))
  		goto clear_hash;
  	if (tcp_md5_hash_header(hp, th))
  		goto clear_hash;
  	if (tcp_md5_hash_skb_data(hp, skb, th->doff << 2))
  		goto clear_hash;
  	if (tcp_md5_hash_key(hp, key))
  		goto clear_hash;
  	if (crypto_hash_final(desc, md5_hash))
  		goto clear_hash;
  
  	tcp_put_md5sig_pool();
  	return 0;
  
  clear_hash:
  	tcp_put_md5sig_pool();
  clear_hash_noput:
  	memset(md5_hash, 0, 16);
  	return 1;
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1124
  }
49a72dfb8   Adam Langley   tcp: Fix MD5 sign...
1125
  EXPORT_SYMBOL(tcp_v4_md5_hash_skb);
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1126

318cf7aaa   Eric Dumazet   tcp: md5: add mor...
1127
  static int tcp_v4_inbound_md5_hash(struct sock *sk, const struct sk_buff *skb)
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1128
1129
1130
1131
1132
1133
1134
1135
1136
  {
  	/*
  	 * This gets called for each TCP segment that arrives
  	 * so we want to be efficient.
  	 * We have 3 drop cases:
  	 * o No MD5 hash and one expected.
  	 * o MD5 hash and we're not expecting one.
  	 * o MD5 hash and its wrong.
  	 */
cf533ea53   Eric Dumazet   tcp: add const qu...
1137
  	const __u8 *hash_location = NULL;
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1138
  	struct tcp_md5sig_key *hash_expected;
eddc9ec53   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
1139
  	const struct iphdr *iph = ip_hdr(skb);
cf533ea53   Eric Dumazet   tcp: add const qu...
1140
  	const struct tcphdr *th = tcp_hdr(skb);
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1141
  	int genhash;
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1142
1143
1144
  	unsigned char newhash[16];
  
  	hash_expected = tcp_v4_md5_do_lookup(sk, iph->saddr);
7d5d5525b   YOSHIFUJI Hideaki   tcp md5sig: Share...
1145
  	hash_location = tcp_parse_md5sig_option(th);
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1146

cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1147
1148
1149
1150
1151
  	/* We've parsed the options - do we have a hash? */
  	if (!hash_expected && !hash_location)
  		return 0;
  
  	if (hash_expected && !hash_location) {
785957d3e   David S. Miller   tcp: MD5: Use MIB...
1152
  		NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPMD5NOTFOUND);
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1153
1154
1155
1156
  		return 1;
  	}
  
  	if (!hash_expected && hash_location) {
785957d3e   David S. Miller   tcp: MD5: Use MIB...
1157
  		NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPMD5UNEXPECTED);
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1158
1159
1160
1161
1162
1163
  		return 1;
  	}
  
  	/* Okay, so this is hash_expected and hash_location -
  	 * so we need to calculate the checksum.
  	 */
49a72dfb8   Adam Langley   tcp: Fix MD5 sign...
1164
1165
1166
  	genhash = tcp_v4_md5_hash_skb(newhash,
  				      hash_expected,
  				      NULL, NULL, skb);
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1167
1168
1169
  
  	if (genhash || memcmp(hash_location, newhash, 16) != 0) {
  		if (net_ratelimit()) {
673d57e72   Harvey Harrison   net: replace NIPQ...
1170
1171
1172
1173
  			printk(KERN_INFO "MD5 Hash failed for (%pI4, %d)->(%pI4, %d)%s
  ",
  			       &iph->saddr, ntohs(th->source),
  			       &iph->daddr, ntohs(th->dest),
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1174
  			       genhash ? " tcp_v4_calc_md5_hash failed" : "");
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1175
1176
1177
1178
1179
1180
1181
  		}
  		return 1;
  	}
  	return 0;
  }
  
  #endif
72a3effaf   Eric Dumazet   [NET]: Size liste...
1182
  struct request_sock_ops tcp_request_sock_ops __read_mostly = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1183
  	.family		=	PF_INET,
2e6599cb8   Arnaldo Carvalho de Melo   [NET] Generalise ...
1184
  	.obj_size	=	sizeof(struct tcp_request_sock),
72659ecce   Octavian Purdila   tcp: account SYN-...
1185
  	.rtx_syn_ack	=	tcp_v4_rtx_synack,
60236fdd0   Arnaldo Carvalho de Melo   [NET] Rename open...
1186
1187
  	.send_ack	=	tcp_v4_reqsk_send_ack,
  	.destructor	=	tcp_v4_reqsk_destructor,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1188
  	.send_reset	=	tcp_v4_send_reset,
72659ecce   Octavian Purdila   tcp: account SYN-...
1189
  	.syn_ack_timeout = 	tcp_syn_ack_timeout,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1190
  };
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1191
  #ifdef CONFIG_TCP_MD5SIG
b2e4b3deb   Stephen Hemminger   tcp: MD5 operatio...
1192
  static const struct tcp_request_sock_ops tcp_request_sock_ipv4_ops = {
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1193
  	.md5_lookup	=	tcp_v4_reqsk_md5_lookup,
e3afe7b75   John Dykstra   tcp: Fix MD5 sign...
1194
  	.calc_md5_hash	=	tcp_v4_md5_hash_skb,
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1195
  };
b6332e6cf   Andrew Morton   [TCP]: Fix warnin...
1196
  #endif
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1197

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1198
1199
  int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
  {
4957faade   William Allen Simpson   TCPCT part 1g: Re...
1200
  	struct tcp_extend_values tmp_ext;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1201
  	struct tcp_options_received tmp_opt;
cf533ea53   Eric Dumazet   tcp: add const qu...
1202
  	const u8 *hash_location;
60236fdd0   Arnaldo Carvalho de Melo   [NET] Rename open...
1203
  	struct request_sock *req;
e6b4d1136   William Allen Simpson   TCPCT part 1a: ad...
1204
  	struct inet_request_sock *ireq;
4957faade   William Allen Simpson   TCPCT part 1g: Re...
1205
  	struct tcp_sock *tp = tcp_sk(sk);
e6b4d1136   William Allen Simpson   TCPCT part 1a: ad...
1206
  	struct dst_entry *dst = NULL;
eddc9ec53   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
1207
1208
  	__be32 saddr = ip_hdr(skb)->saddr;
  	__be32 daddr = ip_hdr(skb)->daddr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1209
  	__u32 isn = TCP_SKB_CB(skb)->when;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1210
  	int want_cookie = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1211
1212
  
  	/* Never answer to SYNs send to broadcast or multicast */
511c3f92a   Eric Dumazet   net: skb->rtable ...
1213
  	if (skb_rtable(skb)->rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1214
1215
1216
1217
1218
1219
  		goto drop;
  
  	/* TW buckets are converted to open requests without
  	 * limitations, they conserve resources and peer is
  	 * evidently real one.
  	 */
463c84b97   Arnaldo Carvalho de Melo   [NET]: Introduce ...
1220
  	if (inet_csk_reqsk_queue_is_full(sk) && !isn) {
946cedccb   Eric Dumazet   tcp: Change possi...
1221
1222
1223
  		want_cookie = tcp_syn_flood_action(sk, skb, "TCP");
  		if (!want_cookie)
  			goto drop;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1224
1225
1226
1227
1228
1229
1230
  	}
  
  	/* Accept backlog is full. If we have already queued enough
  	 * of warm entries in syn queue, drop request. It is better than
  	 * clogging syn queue with openreqs with exponentially increasing
  	 * timeout.
  	 */
463c84b97   Arnaldo Carvalho de Melo   [NET]: Introduce ...
1231
  	if (sk_acceptq_is_full(sk) && inet_csk_reqsk_queue_young(sk) > 1)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1232
  		goto drop;
ce4a7d0d4   Arnaldo Carvalho de Melo   inet{6}_request_s...
1233
  	req = inet_reqsk_alloc(&tcp_request_sock_ops);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1234
1235
  	if (!req)
  		goto drop;
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1236
1237
1238
  #ifdef CONFIG_TCP_MD5SIG
  	tcp_rsk(req)->af_specific = &tcp_request_sock_ipv4_ops;
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1239
  	tcp_clear_options(&tmp_opt);
bee7ca9ec   William Allen Simpson   net: TCP_MSS_DEFA...
1240
  	tmp_opt.mss_clamp = TCP_MSS_DEFAULT;
4957faade   William Allen Simpson   TCPCT part 1g: Re...
1241
  	tmp_opt.user_mss  = tp->rx_opt.user_mss;
bb5b7c112   David S. Miller   tcp: Revert per-r...
1242
  	tcp_parse_options(skb, &tmp_opt, &hash_location, 0);
4957faade   William Allen Simpson   TCPCT part 1g: Re...
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
  
  	if (tmp_opt.cookie_plus > 0 &&
  	    tmp_opt.saw_tstamp &&
  	    !tp->rx_opt.cookie_out_never &&
  	    (sysctl_tcp_cookie_size > 0 ||
  	     (tp->cookie_values != NULL &&
  	      tp->cookie_values->cookie_desired > 0))) {
  		u8 *c;
  		u32 *mess = &tmp_ext.cookie_bakery[COOKIE_DIGEST_WORDS];
  		int l = tmp_opt.cookie_plus - TCPOLEN_COOKIE_BASE;
  
  		if (tcp_cookie_generator(&tmp_ext.cookie_bakery[0]) != 0)
  			goto drop_and_release;
  
  		/* Secret recipe starts with IP addresses */
0eae88f31   Eric Dumazet   net: Fix various ...
1258
1259
  		*mess++ ^= (__force u32)daddr;
  		*mess++ ^= (__force u32)saddr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1260

4957faade   William Allen Simpson   TCPCT part 1g: Re...
1261
1262
1263
1264
  		/* plus variable length Initiator Cookie */
  		c = (u8 *)mess;
  		while (l-- > 0)
  			*c++ ^= *hash_location++;
4957faade   William Allen Simpson   TCPCT part 1g: Re...
1265
  		want_cookie = 0;	/* not our kind of cookie */
4957faade   William Allen Simpson   TCPCT part 1g: Re...
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
  		tmp_ext.cookie_out_never = 0; /* false */
  		tmp_ext.cookie_plus = tmp_opt.cookie_plus;
  	} else if (!tp->rx_opt.cookie_in_always) {
  		/* redundant indications, but ensure initialization. */
  		tmp_ext.cookie_out_never = 1; /* true */
  		tmp_ext.cookie_plus = 0;
  	} else {
  		goto drop_and_release;
  	}
  	tmp_ext.cookie_in_always = tp->rx_opt.cookie_in_always;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1276

4dfc28170   Florian Westphal   [Syncookies]: Add...
1277
  	if (want_cookie && !tmp_opt.saw_tstamp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1278
  		tcp_clear_options(&tmp_opt);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1279

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1280
  	tmp_opt.tstamp_ok = tmp_opt.saw_tstamp;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1281
  	tcp_openreq_init(req, &tmp_opt, skb);
bb5b7c112   David S. Miller   tcp: Revert per-r...
1282
1283
1284
1285
1286
  	ireq = inet_rsk(req);
  	ireq->loc_addr = daddr;
  	ireq->rmt_addr = saddr;
  	ireq->no_srccheck = inet_sk(sk)->transparent;
  	ireq->opt = tcp_v4_save_options(sk, skb);
284904aa7   Paul Moore   lsm: Relocate the...
1287
  	if (security_inet_conn_request(sk, skb, req))
bb5b7c112   David S. Miller   tcp: Revert per-r...
1288
  		goto drop_and_free;
284904aa7   Paul Moore   lsm: Relocate the...
1289

172d69e63   Florian Westphal   syncookies: add s...
1290
  	if (!want_cookie || tmp_opt.tstamp_ok)
aa8223c7b   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
1291
  		TCP_ECN_create_request(req, tcp_hdr(skb));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1292
1293
  
  	if (want_cookie) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1294
  		isn = cookie_v4_init_sequence(sk, skb, &req->mss);
172d69e63   Florian Westphal   syncookies: add s...
1295
  		req->cookie_ts = tmp_opt.tstamp_ok;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1296
1297
  	} else if (!isn) {
  		struct inet_peer *peer = NULL;
6bd023f3d   David S. Miller   ipv4: Make caller...
1298
  		struct flowi4 fl4;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
  
  		/* VJ's idea. We save last timestamp seen
  		 * from the destination in peer table, when entering
  		 * state TIME-WAIT, and check against it before
  		 * accepting new connection request.
  		 *
  		 * If "isn" is not zero, this request hit alive
  		 * timewait bucket, so that all the necessary checks
  		 * are made in the function processing timewait state.
  		 */
  		if (tmp_opt.saw_tstamp &&
295ff7edb   Arnaldo Carvalho de Melo   [TIMEWAIT]: Intro...
1310
  		    tcp_death_row.sysctl_tw_recycle &&
6bd023f3d   David S. Miller   ipv4: Make caller...
1311
  		    (dst = inet_csk_route_req(sk, &fl4, req)) != NULL &&
ed2361e66   David S. Miller   ipv4: Pass explic...
1312
1313
  		    fl4.daddr == saddr &&
  		    (peer = rt_get_peer((struct rtable *)dst, fl4.daddr)) != NULL) {
317fe0e6c   Eric Dumazet   inetpeer: restore...
1314
  			inet_peer_refcheck(peer);
2c1409a0a   Eric Dumazet   inetpeer: Optimiz...
1315
  			if ((u32)get_seconds() - peer->tcp_ts_stamp < TCP_PAWS_MSL &&
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1316
1317
  			    (s32)(peer->tcp_ts - req->ts_recent) >
  							TCP_PAWS_WINDOW) {
de0744af1   Pavel Emelyanov   mib: add net to N...
1318
  				NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_PAWSPASSIVEREJECTED);
7cd04fa7e   Denis V. Lunev   [TCP]: Merge exit...
1319
  				goto drop_and_release;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1320
1321
1322
1323
  			}
  		}
  		/* Kill the following clause, if you dislike this way. */
  		else if (!sysctl_tcp_syncookies &&
463c84b97   Arnaldo Carvalho de Melo   [NET]: Introduce ...
1324
  			 (sysctl_max_syn_backlog - inet_csk_reqsk_queue_len(sk) <
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
  			  (sysctl_max_syn_backlog >> 2)) &&
  			 (!peer || !peer->tcp_ts_stamp) &&
  			 (!dst || !dst_metric(dst, RTAX_RTT))) {
  			/* Without syncookies last quarter of
  			 * backlog is filled with destinations,
  			 * proven to be alive.
  			 * It means that we continue to communicate
  			 * to destinations, already remembered
  			 * to the moment of synflood.
  			 */
673d57e72   Harvey Harrison   net: replace NIPQ...
1335
1336
1337
  			LIMIT_NETDEBUG(KERN_DEBUG "TCP: drop open request from %pI4/%u
  ",
  				       &saddr, ntohs(tcp_hdr(skb)->source));
7cd04fa7e   Denis V. Lunev   [TCP]: Merge exit...
1338
  			goto drop_and_release;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1339
  		}
a94f723d5   Gerrit Renker   [TCP]: Remove dea...
1340
  		isn = tcp_v4_init_sequence(skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1341
  	}
2e6599cb8   Arnaldo Carvalho de Melo   [NET] Generalise ...
1342
  	tcp_rsk(req)->snt_isn = isn;
9ad7c049f   Jerry Chu   tcp: RFC2988bis +...
1343
  	tcp_rsk(req)->snt_synack = tcp_time_stamp;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1344

72659ecce   Octavian Purdila   tcp: account SYN-...
1345
1346
  	if (tcp_v4_send_synack(sk, dst, req,
  			       (struct request_values *)&tmp_ext) ||
4957faade   William Allen Simpson   TCPCT part 1g: Re...
1347
  	    want_cookie)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1348
  		goto drop_and_free;
7cd04fa7e   Denis V. Lunev   [TCP]: Merge exit...
1349
  	inet_csk_reqsk_queue_hash_add(sk, req, TCP_TIMEOUT_INIT);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1350
  	return 0;
7cd04fa7e   Denis V. Lunev   [TCP]: Merge exit...
1351
1352
  drop_and_release:
  	dst_release(dst);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1353
  drop_and_free:
60236fdd0   Arnaldo Carvalho de Melo   [NET] Rename open...
1354
  	reqsk_free(req);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1355
  drop:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1356
1357
  	return 0;
  }
4bc2f18ba   Eric Dumazet   net/ipv4: EXPORT_...
1358
  EXPORT_SYMBOL(tcp_v4_conn_request);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1359
1360
1361
1362
1363
1364
1365
  
  
  /*
   * The three way handshake has completed - we got a valid synack -
   * now create the new socket.
   */
  struct sock *tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
60236fdd0   Arnaldo Carvalho de Melo   [NET] Rename open...
1366
  				  struct request_sock *req,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1367
1368
  				  struct dst_entry *dst)
  {
2e6599cb8   Arnaldo Carvalho de Melo   [NET] Generalise ...
1369
  	struct inet_request_sock *ireq;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1370
1371
1372
  	struct inet_sock *newinet;
  	struct tcp_sock *newtp;
  	struct sock *newsk;
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1373
1374
1375
  #ifdef CONFIG_TCP_MD5SIG
  	struct tcp_md5sig_key *key;
  #endif
f6d8bd051   Eric Dumazet   inet: add RCU pro...
1376
  	struct ip_options_rcu *inet_opt;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1377
1378
1379
  
  	if (sk_acceptq_is_full(sk))
  		goto exit_overflow;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1380
1381
  	newsk = tcp_create_openreq_child(sk, req, skb);
  	if (!newsk)
093d28232   Balazs Scheidler   tproxy: fix hash ...
1382
  		goto exit_nonewsk;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1383

bcd761111   Herbert Xu   [NET]: Generalise...
1384
  	newsk->sk_gso_type = SKB_GSO_TCPV4;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1385
1386
1387
  
  	newtp		      = tcp_sk(newsk);
  	newinet		      = inet_sk(newsk);
2e6599cb8   Arnaldo Carvalho de Melo   [NET] Generalise ...
1388
  	ireq		      = inet_rsk(req);
c720c7e83   Eric Dumazet   inet: rename some...
1389
1390
1391
  	newinet->inet_daddr   = ireq->rmt_addr;
  	newinet->inet_rcv_saddr = ireq->loc_addr;
  	newinet->inet_saddr	      = ireq->loc_addr;
f6d8bd051   Eric Dumazet   inet: add RCU pro...
1392
1393
  	inet_opt	      = ireq->opt;
  	rcu_assign_pointer(newinet->inet_opt, inet_opt);
2e6599cb8   Arnaldo Carvalho de Melo   [NET] Generalise ...
1394
  	ireq->opt	      = NULL;
463c84b97   Arnaldo Carvalho de Melo   [NET]: Introduce ...
1395
  	newinet->mc_index     = inet_iif(skb);
eddc9ec53   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
1396
  	newinet->mc_ttl	      = ip_hdr(skb)->ttl;
d83d8461f   Arnaldo Carvalho de Melo   [IP_SOCKGLUE]: Re...
1397
  	inet_csk(newsk)->icsk_ext_hdr_len = 0;
f6d8bd051   Eric Dumazet   inet: add RCU pro...
1398
1399
  	if (inet_opt)
  		inet_csk(newsk)->icsk_ext_hdr_len = inet_opt->opt.optlen;
c720c7e83   Eric Dumazet   inet: rename some...
1400
  	newinet->inet_id = newtp->write_seq ^ jiffies;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1401

0e7344199   David S. Miller   ipv4: Use inet_cs...
1402
1403
1404
1405
  	if (!dst && (dst = inet_csk_route_child_sock(sk, newsk, req)) == NULL)
  		goto put_and_exit;
  
  	sk_setup_caps(newsk, dst);
5d424d5a6   John Heffner   [TCP]: MTU probing
1406
  	tcp_mtup_init(newsk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1407
  	tcp_sync_mss(newsk, dst_mtu(dst));
0dbaee3b3   David S. Miller   net: Abstract def...
1408
  	newtp->advmss = dst_metric_advmss(dst);
f5fff5dc8   Tom Quetchenbach   tcp: advertise MS...
1409
1410
1411
  	if (tcp_sk(sk)->rx_opt.user_mss &&
  	    tcp_sk(sk)->rx_opt.user_mss < newtp->advmss)
  		newtp->advmss = tcp_sk(sk)->rx_opt.user_mss;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1412
  	tcp_initialize_rcv_mss(newsk);
9ad7c049f   Jerry Chu   tcp: RFC2988bis +...
1413
1414
1415
1416
  	if (tcp_rsk(req)->snt_synack)
  		tcp_valid_rtt_meas(newsk,
  		    tcp_time_stamp - tcp_rsk(req)->snt_synack);
  	newtp->total_retrans = req->retrans;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1417

cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1418
1419
  #ifdef CONFIG_TCP_MD5SIG
  	/* Copy over the MD5 key from the original socket */
c720c7e83   Eric Dumazet   inet: rename some...
1420
1421
  	key = tcp_v4_md5_do_lookup(sk, newinet->inet_daddr);
  	if (key != NULL) {
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1422
1423
1424
1425
1426
1427
  		/*
  		 * We're using one, so create a matching key
  		 * on the newsk structure. If we fail to get
  		 * memory, then we end up not copying the key
  		 * across. Shucks.
  		 */
f6685938f   Arnaldo Carvalho de Melo   [TCP_IPV4]: Use k...
1428
1429
  		char *newkey = kmemdup(key->key, key->keylen, GFP_ATOMIC);
  		if (newkey != NULL)
c720c7e83   Eric Dumazet   inet: rename some...
1430
  			tcp_v4_md5_do_add(newsk, newinet->inet_daddr,
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1431
  					  newkey, key->keylen);
a465419b1   Eric Dumazet   net: Introduce sk...
1432
  		sk_nocaps_add(newsk, NETIF_F_GSO_MASK);
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1433
1434
  	}
  #endif
0e7344199   David S. Miller   ipv4: Use inet_cs...
1435
1436
  	if (__inet_inherit_port(sk, newsk) < 0)
  		goto put_and_exit;
9327f7053   Eric Dumazet   tcp: Fix a connec...
1437
  	__inet_hash_nolisten(newsk, NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1438
1439
1440
1441
  
  	return newsk;
  
  exit_overflow:
de0744af1   Pavel Emelyanov   mib: add net to N...
1442
  	NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENOVERFLOWS);
093d28232   Balazs Scheidler   tproxy: fix hash ...
1443
1444
  exit_nonewsk:
  	dst_release(dst);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1445
  exit:
de0744af1   Pavel Emelyanov   mib: add net to N...
1446
  	NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1447
  	return NULL;
0e7344199   David S. Miller   ipv4: Use inet_cs...
1448
  put_and_exit:
709e8697a   Eric Dumazet   tcp: clear xmit t...
1449
  	tcp_clear_xmit_timers(newsk);
918eb3996   Eric Dumazet   net: add missing ...
1450
  	bh_unlock_sock(newsk);
0e7344199   David S. Miller   ipv4: Use inet_cs...
1451
1452
  	sock_put(newsk);
  	goto exit;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1453
  }
4bc2f18ba   Eric Dumazet   net/ipv4: EXPORT_...
1454
  EXPORT_SYMBOL(tcp_v4_syn_recv_sock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1455
1456
1457
  
  static struct sock *tcp_v4_hnd_req(struct sock *sk, struct sk_buff *skb)
  {
aa8223c7b   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
1458
  	struct tcphdr *th = tcp_hdr(skb);
eddc9ec53   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
1459
  	const struct iphdr *iph = ip_hdr(skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1460
  	struct sock *nsk;
60236fdd0   Arnaldo Carvalho de Melo   [NET] Rename open...
1461
  	struct request_sock **prev;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1462
  	/* Find possible connection requests. */
463c84b97   Arnaldo Carvalho de Melo   [NET]: Introduce ...
1463
1464
  	struct request_sock *req = inet_csk_search_req(sk, &prev, th->source,
  						       iph->saddr, iph->daddr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1465
1466
  	if (req)
  		return tcp_check_req(sk, skb, req, prev);
3b1e0a655   YOSHIFUJI Hideaki   [NET] NETNS: Omit...
1467
  	nsk = inet_lookup_established(sock_net(sk), &tcp_hashinfo, iph->saddr,
c67499c0e   Pavel Emelyanov   [NETNS]: Tcp-v4 s...
1468
  			th->source, iph->daddr, th->dest, inet_iif(skb));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1469
1470
1471
1472
1473
1474
  
  	if (nsk) {
  		if (nsk->sk_state != TCP_TIME_WAIT) {
  			bh_lock_sock(nsk);
  			return nsk;
  		}
9469c7b4a   YOSHIFUJI Hideaki   [NET]: Use typesa...
1475
  		inet_twsk_put(inet_twsk(nsk));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1476
1477
1478
1479
  		return NULL;
  	}
  
  #ifdef CONFIG_SYN_COOKIES
af9b47385   Florian Westphal   syncookies: avoid...
1480
  	if (!th->syn)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1481
1482
1483
1484
  		sk = cookie_v4_check(sk, skb, &(IPCB(skb)->opt));
  #endif
  	return sk;
  }
b51655b95   Al Viro   [NET]: Annotate _...
1485
  static __sum16 tcp_v4_checksum_init(struct sk_buff *skb)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1486
  {
eddc9ec53   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
1487
  	const struct iphdr *iph = ip_hdr(skb);
84fa7933a   Patrick McHardy   [NET]: Replace CH...
1488
  	if (skb->ip_summed == CHECKSUM_COMPLETE) {
eddc9ec53   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
1489
1490
  		if (!tcp_v4_check(skb->len, iph->saddr,
  				  iph->daddr, skb->csum)) {
fb286bb29   Herbert Xu   [NET]: Detect har...
1491
  			skb->ip_summed = CHECKSUM_UNNECESSARY;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1492
  			return 0;
fb286bb29   Herbert Xu   [NET]: Detect har...
1493
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1494
  	}
fb286bb29   Herbert Xu   [NET]: Detect har...
1495

eddc9ec53   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
1496
  	skb->csum = csum_tcpudp_nofold(iph->saddr, iph->daddr,
fb286bb29   Herbert Xu   [NET]: Detect har...
1497
  				       skb->len, IPPROTO_TCP, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1498
  	if (skb->len <= 76) {
fb286bb29   Herbert Xu   [NET]: Detect har...
1499
  		return __skb_checksum_complete(skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
  	}
  	return 0;
  }
  
  
  /* The socket must have it's spinlock held when we get
   * here.
   *
   * We have a potential double-lock case here, so even when
   * doing backlog processing we use the BH locking scheme.
   * This is because we cannot sleep with the original spinlock
   * held.
   */
  int tcp_v4_do_rcv(struct sock *sk, struct sk_buff *skb)
  {
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1515
1516
1517
1518
1519
1520
1521
1522
  	struct sock *rsk;
  #ifdef CONFIG_TCP_MD5SIG
  	/*
  	 * We really want to reject the packet as early as possible
  	 * if:
  	 *  o We're expecting an MD5'd packet and this is no MD5 tcp option
  	 *  o There is an MD5 option and we're not expecting one
  	 */
7174259e6   Arnaldo Carvalho de Melo   [TCP_IPV4]: Codin...
1523
  	if (tcp_v4_inbound_md5_hash(sk, skb))
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1524
1525
  		goto discard;
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1526
  	if (sk->sk_state == TCP_ESTABLISHED) { /* Fast path */
bdeab9919   Tom Herbert   rps: Add flag to ...
1527
  		sock_rps_save_rxhash(sk, skb);
aa8223c7b   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
1528
  		if (tcp_rcv_established(sk, skb, tcp_hdr(skb), skb->len)) {
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1529
  			rsk = sk;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1530
  			goto reset;
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1531
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1532
1533
  		return 0;
  	}
ab6a5bb6b   Arnaldo Carvalho de Melo   [TCP]: Introduce ...
1534
  	if (skb->len < tcp_hdrlen(skb) || tcp_checksum_complete(skb))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1535
1536
1537
1538
1539
1540
1541
1542
  		goto csum_err;
  
  	if (sk->sk_state == TCP_LISTEN) {
  		struct sock *nsk = tcp_v4_hnd_req(sk, skb);
  		if (!nsk)
  			goto discard;
  
  		if (nsk != sk) {
bdeab9919   Tom Herbert   rps: Add flag to ...
1543
  			sock_rps_save_rxhash(nsk, skb);
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1544
1545
  			if (tcp_child_process(sk, nsk, skb)) {
  				rsk = nsk;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1546
  				goto reset;
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1547
  			}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1548
1549
  			return 0;
  		}
ca55158c6   Eric Dumazet   rps: tcp: fix rps...
1550
  	} else
bdeab9919   Tom Herbert   rps: Add flag to ...
1551
  		sock_rps_save_rxhash(sk, skb);
ca55158c6   Eric Dumazet   rps: tcp: fix rps...
1552

aa8223c7b   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
1553
  	if (tcp_rcv_state_process(sk, skb, tcp_hdr(skb), skb->len)) {
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1554
  		rsk = sk;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1555
  		goto reset;
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1556
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1557
1558
1559
  	return 0;
  
  reset:
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1560
  	tcp_v4_send_reset(rsk, skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
  discard:
  	kfree_skb(skb);
  	/* Be careful here. If this function gets more complicated and
  	 * gcc suffers from register pressure on the x86, sk (in %ebx)
  	 * might be destroyed here. This current version compiles correctly,
  	 * but you have been warned.
  	 */
  	return 0;
  
  csum_err:
63231bddf   Pavel Emelyanov   mib: add net to T...
1571
  	TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_INERRS);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1572
1573
  	goto discard;
  }
4bc2f18ba   Eric Dumazet   net/ipv4: EXPORT_...
1574
  EXPORT_SYMBOL(tcp_v4_do_rcv);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1575
1576
1577
1578
1579
1580
1581
  
  /*
   *	From tcp_input.c
   */
  
  int tcp_v4_rcv(struct sk_buff *skb)
  {
eddc9ec53   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
1582
  	const struct iphdr *iph;
cf533ea53   Eric Dumazet   tcp: add const qu...
1583
  	const struct tcphdr *th;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1584
1585
  	struct sock *sk;
  	int ret;
a86b1e301   Pavel Emelyanov   inet: prepare str...
1586
  	struct net *net = dev_net(skb->dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1587
1588
1589
1590
1591
  
  	if (skb->pkt_type != PACKET_HOST)
  		goto discard_it;
  
  	/* Count it even if it's bad */
63231bddf   Pavel Emelyanov   mib: add net to T...
1592
  	TCP_INC_STATS_BH(net, TCP_MIB_INSEGS);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1593
1594
1595
  
  	if (!pskb_may_pull(skb, sizeof(struct tcphdr)))
  		goto discard_it;
aa8223c7b   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
1596
  	th = tcp_hdr(skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1597
1598
1599
1600
1601
1602
1603
1604
  
  	if (th->doff < sizeof(struct tcphdr) / 4)
  		goto bad_packet;
  	if (!pskb_may_pull(skb, th->doff * 4))
  		goto discard_it;
  
  	/* An explanation is required here, I think.
  	 * Packet length and doff are validated by header prediction,
caa20d9ab   Stephen Hemminger   [TCP]: spelling f...
1605
  	 * provided case of th->doff==0 is eliminated.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1606
  	 * So, we defer the checks. */
604763722   Herbert Xu   [NET]: Treat CHEC...
1607
  	if (!skb_csum_unnecessary(skb) && tcp_v4_checksum_init(skb))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1608
  		goto bad_packet;
aa8223c7b   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
1609
  	th = tcp_hdr(skb);
eddc9ec53   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
1610
  	iph = ip_hdr(skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1611
1612
1613
1614
1615
  	TCP_SKB_CB(skb)->seq = ntohl(th->seq);
  	TCP_SKB_CB(skb)->end_seq = (TCP_SKB_CB(skb)->seq + th->syn + th->fin +
  				    skb->len - th->doff * 4);
  	TCP_SKB_CB(skb)->ack_seq = ntohl(th->ack_seq);
  	TCP_SKB_CB(skb)->when	 = 0;
b82d1bb4f   Eric Dumazet   tcp: unalias tcp_...
1616
  	TCP_SKB_CB(skb)->ip_dsfield = ipv4_get_dsfield(iph);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1617
  	TCP_SKB_CB(skb)->sacked	 = 0;
9a1f27c48   Arnaldo Carvalho de Melo   inet_hashtables: ...
1618
  	sk = __inet_lookup_skb(&tcp_hashinfo, skb, th->source, th->dest);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1619
1620
  	if (!sk)
  		goto no_tcp_socket;
bb134d5d9   Eric Dumazet   tcp: Fix tcp_v4_r...
1621
1622
1623
  process:
  	if (sk->sk_state == TCP_TIME_WAIT)
  		goto do_time_wait;
6cce09f87   Eric Dumazet   tcp: Add SNMP cou...
1624
1625
  	if (unlikely(iph->ttl < inet_sk(sk)->min_ttl)) {
  		NET_INC_STATS_BH(net, LINUX_MIB_TCPMINTTLDROP);
d218d1113   Stephen Hemminger   tcp: Generalized ...
1626
  		goto discard_and_relse;
6cce09f87   Eric Dumazet   tcp: Add SNMP cou...
1627
  	}
d218d1113   Stephen Hemminger   tcp: Generalized ...
1628

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1629
1630
  	if (!xfrm4_policy_check(sk, XFRM_POLICY_IN, skb))
  		goto discard_and_relse;
b59c27010   Patrick McHardy   [NETFILTER]: Keep...
1631
  	nf_reset(skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1632

fda9ef5d6   Dmitry Mishin   [NET]: Fix sk->sk...
1633
  	if (sk_filter(sk, skb))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1634
1635
1636
  		goto discard_and_relse;
  
  	skb->dev = NULL;
c63661848   Ingo Molnar   [PATCH] lockdep: ...
1637
  	bh_lock_sock_nested(sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1638
1639
  	ret = 0;
  	if (!sock_owned_by_user(sk)) {
1a2449a87   Chris Leech   [I/OAT]: TCP recv...
1640
1641
1642
  #ifdef CONFIG_NET_DMA
  		struct tcp_sock *tp = tcp_sk(sk);
  		if (!tp->ucopy.dma_chan && tp->ucopy.pinned_list)
f67b45999   Dan Williams   net_dma: convert ...
1643
  			tp->ucopy.dma_chan = dma_find_channel(DMA_MEMCPY);
1a2449a87   Chris Leech   [I/OAT]: TCP recv...
1644
  		if (tp->ucopy.dma_chan)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1645
  			ret = tcp_v4_do_rcv(sk, skb);
1a2449a87   Chris Leech   [I/OAT]: TCP recv...
1646
1647
1648
1649
  		else
  #endif
  		{
  			if (!tcp_prequeue(sk, skb))
ae8d7f884   Shan Wei   tcp:fix the code ...
1650
  				ret = tcp_v4_do_rcv(sk, skb);
1a2449a87   Chris Leech   [I/OAT]: TCP recv...
1651
  		}
6cce09f87   Eric Dumazet   tcp: Add SNMP cou...
1652
  	} else if (unlikely(sk_add_backlog(sk, skb))) {
6b03a53a5   Zhu Yi   tcp: use limited ...
1653
  		bh_unlock_sock(sk);
6cce09f87   Eric Dumazet   tcp: Add SNMP cou...
1654
  		NET_INC_STATS_BH(net, LINUX_MIB_TCPBACKLOGDROP);
6b03a53a5   Zhu Yi   tcp: use limited ...
1655
1656
  		goto discard_and_relse;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
  	bh_unlock_sock(sk);
  
  	sock_put(sk);
  
  	return ret;
  
  no_tcp_socket:
  	if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb))
  		goto discard_it;
  
  	if (skb->len < (th->doff << 2) || tcp_checksum_complete(skb)) {
  bad_packet:
63231bddf   Pavel Emelyanov   mib: add net to T...
1669
  		TCP_INC_STATS_BH(net, TCP_MIB_INERRS);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1670
  	} else {
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1671
  		tcp_v4_send_reset(NULL, skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1672
1673
1674
1675
1676
  	}
  
  discard_it:
  	/* Discard frame. */
  	kfree_skb(skb);
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
1677
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1678
1679
1680
1681
1682
1683
1684
  
  discard_and_relse:
  	sock_put(sk);
  	goto discard_it;
  
  do_time_wait:
  	if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {
9469c7b4a   YOSHIFUJI Hideaki   [NET]: Use typesa...
1685
  		inet_twsk_put(inet_twsk(sk));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1686
1687
1688
1689
  		goto discard_it;
  	}
  
  	if (skb->len < (th->doff << 2) || tcp_checksum_complete(skb)) {
63231bddf   Pavel Emelyanov   mib: add net to T...
1690
  		TCP_INC_STATS_BH(net, TCP_MIB_INERRS);
9469c7b4a   YOSHIFUJI Hideaki   [NET]: Use typesa...
1691
  		inet_twsk_put(inet_twsk(sk));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1692
1693
  		goto discard_it;
  	}
9469c7b4a   YOSHIFUJI Hideaki   [NET]: Use typesa...
1694
  	switch (tcp_timewait_state_process(inet_twsk(sk), skb, th)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1695
  	case TCP_TW_SYN: {
c346dca10   YOSHIFUJI Hideaki   [NET] NETNS: Omit...
1696
  		struct sock *sk2 = inet_lookup_listener(dev_net(skb->dev),
c67499c0e   Pavel Emelyanov   [NETNS]: Tcp-v4 s...
1697
  							&tcp_hashinfo,
eddc9ec53   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
1698
  							iph->daddr, th->dest,
463c84b97   Arnaldo Carvalho de Melo   [NET]: Introduce ...
1699
  							inet_iif(skb));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1700
  		if (sk2) {
9469c7b4a   YOSHIFUJI Hideaki   [NET]: Use typesa...
1701
1702
  			inet_twsk_deschedule(inet_twsk(sk), &tcp_death_row);
  			inet_twsk_put(inet_twsk(sk));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
  			sk = sk2;
  			goto process;
  		}
  		/* Fall through to ACK */
  	}
  	case TCP_TW_ACK:
  		tcp_v4_timewait_ack(sk, skb);
  		break;
  	case TCP_TW_RST:
  		goto no_tcp_socket;
  	case TCP_TW_SUCCESS:;
  	}
  	goto discard_it;
  }
3f419d2d4   David S. Miller   inet: Turn ->reme...
1717
  struct inet_peer *tcp_v4_get_peer(struct sock *sk, bool *release_it)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1718
  {
3f419d2d4   David S. Miller   inet: Turn ->reme...
1719
  	struct rtable *rt = (struct rtable *) __sk_dst_get(sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1720
  	struct inet_sock *inet = inet_sk(sk);
3f419d2d4   David S. Miller   inet: Turn ->reme...
1721
  	struct inet_peer *peer;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1722

c5216cc70   David S. Miller   tcp: Use cork flo...
1723
1724
  	if (!rt ||
  	    inet->cork.fl.u.ip4.daddr != inet->inet_daddr) {
b534ecf1c   David S. Miller   inetpeer: Make in...
1725
  		peer = inet_getpeer_v4(inet->inet_daddr, 1);
3f419d2d4   David S. Miller   inet: Turn ->reme...
1726
  		*release_it = true;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1727
1728
  	} else {
  		if (!rt->peer)
a48eff128   David S. Miller   ipv4: Pass explic...
1729
  			rt_bind_peer(rt, inet->inet_daddr, 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1730
  		peer = rt->peer;
3f419d2d4   David S. Miller   inet: Turn ->reme...
1731
  		*release_it = false;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1732
  	}
3f419d2d4   David S. Miller   inet: Turn ->reme...
1733
  	return peer;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1734
  }
3f419d2d4   David S. Miller   inet: Turn ->reme...
1735
  EXPORT_SYMBOL(tcp_v4_get_peer);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1736

ccb7c410d   David S. Miller   timewait_sock: Cr...
1737
  void *tcp_v4_tw_get_peer(struct sock *sk)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1738
  {
cf533ea53   Eric Dumazet   tcp: add const qu...
1739
  	const struct inet_timewait_sock *tw = inet_twsk(sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1740

ccb7c410d   David S. Miller   timewait_sock: Cr...
1741
  	return inet_getpeer_v4(tw->tw_daddr, 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1742
  }
ccb7c410d   David S. Miller   timewait_sock: Cr...
1743
1744
1745
1746
1747
1748
1749
1750
  EXPORT_SYMBOL(tcp_v4_tw_get_peer);
  
  static struct timewait_sock_ops tcp_timewait_sock_ops = {
  	.twsk_obj_size	= sizeof(struct tcp_timewait_sock),
  	.twsk_unique	= tcp_twsk_unique,
  	.twsk_destructor= tcp_twsk_destructor,
  	.twsk_getpeer	= tcp_v4_tw_get_peer,
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1751

3b401a81c   Stephen Hemminger   inet: inet_connec...
1752
  const struct inet_connection_sock_af_ops ipv4_specific = {
543d9cfee   Arnaldo Carvalho de Melo   [NET]: Identation...
1753
1754
1755
1756
1757
  	.queue_xmit	   = ip_queue_xmit,
  	.send_check	   = tcp_v4_send_check,
  	.rebuild_header	   = inet_sk_rebuild_header,
  	.conn_request	   = tcp_v4_conn_request,
  	.syn_recv_sock	   = tcp_v4_syn_recv_sock,
3f419d2d4   David S. Miller   inet: Turn ->reme...
1758
  	.get_peer	   = tcp_v4_get_peer,
543d9cfee   Arnaldo Carvalho de Melo   [NET]: Identation...
1759
1760
1761
1762
1763
  	.net_header_len	   = sizeof(struct iphdr),
  	.setsockopt	   = ip_setsockopt,
  	.getsockopt	   = ip_getsockopt,
  	.addr2sockaddr	   = inet_csk_addr2sockaddr,
  	.sockaddr_len	   = sizeof(struct sockaddr_in),
ab1e0a13d   Arnaldo Carvalho de Melo   [SOCK] proto: Add...
1764
  	.bind_conflict	   = inet_csk_bind_conflict,
3fdadf7d2   Dmitry Mishin   [NET]: {get|set}s...
1765
  #ifdef CONFIG_COMPAT
543d9cfee   Arnaldo Carvalho de Melo   [NET]: Identation...
1766
1767
  	.compat_setsockopt = compat_ip_setsockopt,
  	.compat_getsockopt = compat_ip_getsockopt,
3fdadf7d2   Dmitry Mishin   [NET]: {get|set}s...
1768
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1769
  };
4bc2f18ba   Eric Dumazet   net/ipv4: EXPORT_...
1770
  EXPORT_SYMBOL(ipv4_specific);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1771

cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1772
  #ifdef CONFIG_TCP_MD5SIG
b2e4b3deb   Stephen Hemminger   tcp: MD5 operatio...
1773
  static const struct tcp_sock_af_ops tcp_sock_ipv4_specific = {
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1774
  	.md5_lookup		= tcp_v4_md5_lookup,
49a72dfb8   Adam Langley   tcp: Fix MD5 sign...
1775
  	.calc_md5_hash		= tcp_v4_md5_hash_skb,
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1776
1777
  	.md5_add		= tcp_v4_md5_add_func,
  	.md5_parse		= tcp_v4_parse_md5_keys,
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1778
  };
b6332e6cf   Andrew Morton   [TCP]: Fix warnin...
1779
  #endif
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1780

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1781
1782
1783
1784
1785
  /* NOTE: A lot of things set to zero explicitly by call to
   *       sk_alloc() so need not be done here.
   */
  static int tcp_v4_init_sock(struct sock *sk)
  {
6687e988d   Arnaldo Carvalho de Melo   [ICSK]: Move TCP ...
1786
  	struct inet_connection_sock *icsk = inet_csk(sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1787
1788
1789
1790
1791
  	struct tcp_sock *tp = tcp_sk(sk);
  
  	skb_queue_head_init(&tp->out_of_order_queue);
  	tcp_init_xmit_timers(sk);
  	tcp_prequeue_init(tp);
6687e988d   Arnaldo Carvalho de Melo   [ICSK]: Move TCP ...
1792
  	icsk->icsk_rto = TCP_TIMEOUT_INIT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1793
1794
1795
1796
1797
1798
1799
  	tp->mdev = TCP_TIMEOUT_INIT;
  
  	/* 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
  	 */
9ad7c049f   Jerry Chu   tcp: RFC2988bis +...
1800
  	tp->snd_cwnd = TCP_INIT_CWND;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1801
1802
1803
1804
  
  	/* See draft-stevens-tcpca-spec-01 for discussion of the
  	 * initialization of these values.
  	 */
0b6a05c1d   Ilpo Järvinen   tcp: fix ssthresh...
1805
  	tp->snd_ssthresh = TCP_INFINITE_SSTHRESH;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1806
  	tp->snd_cwnd_clamp = ~0;
bee7ca9ec   William Allen Simpson   net: TCP_MSS_DEFA...
1807
  	tp->mss_cache = TCP_MSS_DEFAULT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1808
1809
  
  	tp->reordering = sysctl_tcp_reordering;
6687e988d   Arnaldo Carvalho de Melo   [ICSK]: Move TCP ...
1810
  	icsk->icsk_ca_ops = &tcp_init_congestion_ops;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1811
1812
1813
1814
1815
  
  	sk->sk_state = TCP_CLOSE;
  
  	sk->sk_write_space = sk_stream_write_space;
  	sock_set_flag(sk, SOCK_USE_WRITE_QUEUE);
8292a17a3   Arnaldo Carvalho de Melo   [ICSK]: Rename st...
1816
  	icsk->icsk_af_ops = &ipv4_specific;
d83d8461f   Arnaldo Carvalho de Melo   [IP_SOCKGLUE]: Re...
1817
  	icsk->icsk_sync_mss = tcp_sync_mss;
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1818
1819
1820
  #ifdef CONFIG_TCP_MD5SIG
  	tp->af_specific = &tcp_sock_ipv4_specific;
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1821

435cf559f   William Allen Simpson   TCPCT part 1d: de...
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
  	/* TCP Cookie Transactions */
  	if (sysctl_tcp_cookie_size > 0) {
  		/* Default, cookies without s_data_payload. */
  		tp->cookie_values =
  			kzalloc(sizeof(*tp->cookie_values),
  				sk->sk_allocation);
  		if (tp->cookie_values != NULL)
  			kref_init(&tp->cookie_values->kref);
  	}
  	/* Presumed zeroed, in order of appearance:
  	 *	cookie_in_always, cookie_out_never,
  	 *	s_data_constant, s_data_in, s_data_out
  	 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1835
1836
  	sk->sk_sndbuf = sysctl_tcp_wmem[1];
  	sk->sk_rcvbuf = sysctl_tcp_rmem[1];
eb4dea585   Herbert Xu   net: Fix percpu c...
1837
  	local_bh_disable();
1748376b6   Eric Dumazet   net: Use a percpu...
1838
  	percpu_counter_inc(&tcp_sockets_allocated);
eb4dea585   Herbert Xu   net: Fix percpu c...
1839
  	local_bh_enable();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1840
1841
1842
  
  	return 0;
  }
7d06b2e05   Brian Haley   net: change proto...
1843
  void tcp_v4_destroy_sock(struct sock *sk)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1844
1845
1846
1847
  {
  	struct tcp_sock *tp = tcp_sk(sk);
  
  	tcp_clear_xmit_timers(sk);
6687e988d   Arnaldo Carvalho de Melo   [ICSK]: Move TCP ...
1848
  	tcp_cleanup_congestion_control(sk);
317a76f9a   Stephen Hemminger   [TCP]: Add plugga...
1849

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1850
  	/* Cleanup up the write buffer. */
fe067e8ab   David S. Miller   [TCP]: Abstract o...
1851
  	tcp_write_queue_purge(sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1852
1853
  
  	/* Cleans up our, hopefully empty, out_of_order_queue. */
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
1854
  	__skb_queue_purge(&tp->out_of_order_queue);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1855

cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1856
1857
1858
1859
1860
1861
1862
1863
  #ifdef CONFIG_TCP_MD5SIG
  	/* Clean up the MD5 key list, if any */
  	if (tp->md5sig_info) {
  		tcp_v4_clear_md5_list(sk);
  		kfree(tp->md5sig_info);
  		tp->md5sig_info = NULL;
  	}
  #endif
1a2449a87   Chris Leech   [I/OAT]: TCP recv...
1864
1865
  #ifdef CONFIG_NET_DMA
  	/* Cleans up our sk_async_wait_queue */
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
1866
  	__skb_queue_purge(&sk->sk_async_wait_queue);
1a2449a87   Chris Leech   [I/OAT]: TCP recv...
1867
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1868
1869
1870
1871
  	/* Clean prequeue, it must be empty really */
  	__skb_queue_purge(&tp->ucopy.prequeue);
  
  	/* Clean up a referenced TCP bind bucket. */
463c84b97   Arnaldo Carvalho de Melo   [NET]: Introduce ...
1872
  	if (inet_csk(sk)->icsk_bind_hash)
ab1e0a13d   Arnaldo Carvalho de Melo   [SOCK] proto: Add...
1873
  		inet_put_port(sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1874
1875
1876
1877
1878
1879
1880
1881
  
  	/*
  	 * If sendmsg cached page exists, toss it.
  	 */
  	if (sk->sk_sndmsg_page) {
  		__free_page(sk->sk_sndmsg_page);
  		sk->sk_sndmsg_page = NULL;
  	}
435cf559f   William Allen Simpson   TCPCT part 1d: de...
1882
1883
1884
1885
1886
1887
  	/* TCP Cookie Transactions */
  	if (tp->cookie_values != NULL) {
  		kref_put(&tp->cookie_values->kref,
  			 tcp_cookie_values_release);
  		tp->cookie_values = NULL;
  	}
1748376b6   Eric Dumazet   net: Use a percpu...
1888
  	percpu_counter_dec(&tcp_sockets_allocated);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1889
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1890
1891
1892
1893
  EXPORT_SYMBOL(tcp_v4_destroy_sock);
  
  #ifdef CONFIG_PROC_FS
  /* Proc filesystem TCP sock list dumping. */
3ab5aee7f   Eric Dumazet   net: Convert TCP ...
1894
  static inline struct inet_timewait_sock *tw_head(struct hlist_nulls_head *head)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1895
  {
3ab5aee7f   Eric Dumazet   net: Convert TCP ...
1896
  	return hlist_nulls_empty(head) ? NULL :
8feaf0c0a   Arnaldo Carvalho de Melo   [INET]: Generalis...
1897
  		list_entry(head->first, struct inet_timewait_sock, tw_node);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1898
  }
8feaf0c0a   Arnaldo Carvalho de Melo   [INET]: Generalis...
1899
  static inline struct inet_timewait_sock *tw_next(struct inet_timewait_sock *tw)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1900
  {
3ab5aee7f   Eric Dumazet   net: Convert TCP ...
1901
1902
  	return !is_a_nulls(tw->tw_node.next) ?
  		hlist_nulls_entry(tw->tw_node.next, typeof(*tw), tw_node) : NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1903
  }
a8b690f98   Tom Herbert   tcp: Fix slowness...
1904
1905
1906
1907
1908
  /*
   * Get next listener socket follow cur.  If cur is NULL, get first socket
   * starting from bucket given in st->bucket; when st->bucket is zero the
   * very first socket in the hash table is returned.
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1909
1910
  static void *listening_get_next(struct seq_file *seq, void *cur)
  {
463c84b97   Arnaldo Carvalho de Melo   [NET]: Introduce ...
1911
  	struct inet_connection_sock *icsk;
c25eb3bfb   Eric Dumazet   net: Convert TCP/...
1912
  	struct hlist_nulls_node *node;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1913
  	struct sock *sk = cur;
5caea4ea7   Eric Dumazet   net: listening_ha...
1914
  	struct inet_listen_hashbucket *ilb;
5799de0b1   Jianjun Kong   net: clean up net...
1915
  	struct tcp_iter_state *st = seq->private;
a4146b1b2   Denis V. Lunev   [TCP]: Replace st...
1916
  	struct net *net = seq_file_net(seq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1917
1918
  
  	if (!sk) {
a8b690f98   Tom Herbert   tcp: Fix slowness...
1919
  		ilb = &tcp_hashinfo.listening_hash[st->bucket];
5caea4ea7   Eric Dumazet   net: listening_ha...
1920
  		spin_lock_bh(&ilb->lock);
c25eb3bfb   Eric Dumazet   net: Convert TCP/...
1921
  		sk = sk_nulls_head(&ilb->head);
a8b690f98   Tom Herbert   tcp: Fix slowness...
1922
  		st->offset = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1923
1924
  		goto get_sk;
  	}
5caea4ea7   Eric Dumazet   net: listening_ha...
1925
  	ilb = &tcp_hashinfo.listening_hash[st->bucket];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1926
  	++st->num;
a8b690f98   Tom Herbert   tcp: Fix slowness...
1927
  	++st->offset;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1928
1929
  
  	if (st->state == TCP_SEQ_STATE_OPENREQ) {
60236fdd0   Arnaldo Carvalho de Melo   [NET] Rename open...
1930
  		struct request_sock *req = cur;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1931

72a3effaf   Eric Dumazet   [NET]: Size liste...
1932
  		icsk = inet_csk(st->syn_wait_sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1933
1934
1935
  		req = req->dl_next;
  		while (1) {
  			while (req) {
bdccc4ca1   Daniel Lezcano   tcp: fix kernel p...
1936
  				if (req->rsk_ops->family == st->family) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1937
1938
1939
1940
1941
  					cur = req;
  					goto out;
  				}
  				req = req->dl_next;
  			}
72a3effaf   Eric Dumazet   [NET]: Size liste...
1942
  			if (++st->sbucket >= icsk->icsk_accept_queue.listen_opt->nr_table_entries)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1943
1944
  				break;
  get_req:
463c84b97   Arnaldo Carvalho de Melo   [NET]: Introduce ...
1945
  			req = icsk->icsk_accept_queue.listen_opt->syn_table[st->sbucket];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1946
  		}
1bde5ac49   Eric Dumazet   tcp: fix listenin...
1947
  		sk	  = sk_nulls_next(st->syn_wait_sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1948
  		st->state = TCP_SEQ_STATE_LISTENING;
463c84b97   Arnaldo Carvalho de Melo   [NET]: Introduce ...
1949
  		read_unlock_bh(&icsk->icsk_accept_queue.syn_wait_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1950
  	} else {
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
1951
  		icsk = inet_csk(sk);
463c84b97   Arnaldo Carvalho de Melo   [NET]: Introduce ...
1952
1953
  		read_lock_bh(&icsk->icsk_accept_queue.syn_wait_lock);
  		if (reqsk_queue_len(&icsk->icsk_accept_queue))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1954
  			goto start_req;
463c84b97   Arnaldo Carvalho de Melo   [NET]: Introduce ...
1955
  		read_unlock_bh(&icsk->icsk_accept_queue.syn_wait_lock);
1bde5ac49   Eric Dumazet   tcp: fix listenin...
1956
  		sk = sk_nulls_next(sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1957
1958
  	}
  get_sk:
c25eb3bfb   Eric Dumazet   net: Convert TCP/...
1959
  	sk_nulls_for_each_from(sk, node) {
8475ef9fd   Pavel Emelyanov   netns: Don't leak...
1960
1961
1962
  		if (!net_eq(sock_net(sk), net))
  			continue;
  		if (sk->sk_family == st->family) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1963
1964
1965
  			cur = sk;
  			goto out;
  		}
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
1966
  		icsk = inet_csk(sk);
463c84b97   Arnaldo Carvalho de Melo   [NET]: Introduce ...
1967
1968
  		read_lock_bh(&icsk->icsk_accept_queue.syn_wait_lock);
  		if (reqsk_queue_len(&icsk->icsk_accept_queue)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1969
1970
1971
1972
1973
1974
1975
  start_req:
  			st->uid		= sock_i_uid(sk);
  			st->syn_wait_sk = sk;
  			st->state	= TCP_SEQ_STATE_OPENREQ;
  			st->sbucket	= 0;
  			goto get_req;
  		}
463c84b97   Arnaldo Carvalho de Melo   [NET]: Introduce ...
1976
  		read_unlock_bh(&icsk->icsk_accept_queue.syn_wait_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1977
  	}
5caea4ea7   Eric Dumazet   net: listening_ha...
1978
  	spin_unlock_bh(&ilb->lock);
a8b690f98   Tom Herbert   tcp: Fix slowness...
1979
  	st->offset = 0;
0f7ff9274   Arnaldo Carvalho de Melo   [INET]: Just rena...
1980
  	if (++st->bucket < INET_LHTABLE_SIZE) {
5caea4ea7   Eric Dumazet   net: listening_ha...
1981
1982
  		ilb = &tcp_hashinfo.listening_hash[st->bucket];
  		spin_lock_bh(&ilb->lock);
c25eb3bfb   Eric Dumazet   net: Convert TCP/...
1983
  		sk = sk_nulls_head(&ilb->head);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1984
1985
1986
1987
1988
1989
1990
1991
1992
  		goto get_sk;
  	}
  	cur = NULL;
  out:
  	return cur;
  }
  
  static void *listening_get_idx(struct seq_file *seq, loff_t *pos)
  {
a8b690f98   Tom Herbert   tcp: Fix slowness...
1993
1994
1995
1996
1997
1998
  	struct tcp_iter_state *st = seq->private;
  	void *rc;
  
  	st->bucket = 0;
  	st->offset = 0;
  	rc = listening_get_next(seq, NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1999
2000
2001
2002
2003
2004
2005
  
  	while (rc && *pos) {
  		rc = listening_get_next(seq, rc);
  		--*pos;
  	}
  	return rc;
  }
6eac56040   Andi Kleen   tcp: Skip empty h...
2006
2007
  static inline int empty_bucket(struct tcp_iter_state *st)
  {
3ab5aee7f   Eric Dumazet   net: Convert TCP ...
2008
2009
  	return hlist_nulls_empty(&tcp_hashinfo.ehash[st->bucket].chain) &&
  		hlist_nulls_empty(&tcp_hashinfo.ehash[st->bucket].twchain);
6eac56040   Andi Kleen   tcp: Skip empty h...
2010
  }
a8b690f98   Tom Herbert   tcp: Fix slowness...
2011
2012
2013
2014
  /*
   * Get first established socket starting from bucket given in st->bucket.
   * If st->bucket is zero, the very first socket in the hash is returned.
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2015
2016
  static void *established_get_first(struct seq_file *seq)
  {
5799de0b1   Jianjun Kong   net: clean up net...
2017
  	struct tcp_iter_state *st = seq->private;
a4146b1b2   Denis V. Lunev   [TCP]: Replace st...
2018
  	struct net *net = seq_file_net(seq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2019
  	void *rc = NULL;
a8b690f98   Tom Herbert   tcp: Fix slowness...
2020
2021
  	st->offset = 0;
  	for (; st->bucket <= tcp_hashinfo.ehash_mask; ++st->bucket) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2022
  		struct sock *sk;
3ab5aee7f   Eric Dumazet   net: Convert TCP ...
2023
  		struct hlist_nulls_node *node;
8feaf0c0a   Arnaldo Carvalho de Melo   [INET]: Generalis...
2024
  		struct inet_timewait_sock *tw;
9db66bdcc   Eric Dumazet   net: convert TCP/...
2025
  		spinlock_t *lock = inet_ehash_lockp(&tcp_hashinfo, st->bucket);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2026

6eac56040   Andi Kleen   tcp: Skip empty h...
2027
2028
2029
  		/* Lockless fast path for the common case of empty buckets */
  		if (empty_bucket(st))
  			continue;
9db66bdcc   Eric Dumazet   net: convert TCP/...
2030
  		spin_lock_bh(lock);
3ab5aee7f   Eric Dumazet   net: Convert TCP ...
2031
  		sk_nulls_for_each(sk, node, &tcp_hashinfo.ehash[st->bucket].chain) {
f40c8174d   Daniel Lezcano   [NETNS][IPV4] tcp...
2032
  			if (sk->sk_family != st->family ||
878628fbf   YOSHIFUJI Hideaki   [NET] NETNS: Omit...
2033
  			    !net_eq(sock_net(sk), net)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2034
2035
2036
2037
2038
2039
  				continue;
  			}
  			rc = sk;
  			goto out;
  		}
  		st->state = TCP_SEQ_STATE_TIME_WAIT;
8feaf0c0a   Arnaldo Carvalho de Melo   [INET]: Generalis...
2040
  		inet_twsk_for_each(tw, node,
dbca9b275   Eric Dumazet   [NET]: change lay...
2041
  				   &tcp_hashinfo.ehash[st->bucket].twchain) {
28518fc17   Pavel Emelyanov   [NET]: NULL point...
2042
  			if (tw->tw_family != st->family ||
878628fbf   YOSHIFUJI Hideaki   [NET] NETNS: Omit...
2043
  			    !net_eq(twsk_net(tw), net)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2044
2045
2046
2047
2048
  				continue;
  			}
  			rc = tw;
  			goto out;
  		}
9db66bdcc   Eric Dumazet   net: convert TCP/...
2049
  		spin_unlock_bh(lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2050
2051
2052
2053
2054
2055
2056
2057
2058
  		st->state = TCP_SEQ_STATE_ESTABLISHED;
  	}
  out:
  	return rc;
  }
  
  static void *established_get_next(struct seq_file *seq, void *cur)
  {
  	struct sock *sk = cur;
8feaf0c0a   Arnaldo Carvalho de Melo   [INET]: Generalis...
2059
  	struct inet_timewait_sock *tw;
3ab5aee7f   Eric Dumazet   net: Convert TCP ...
2060
  	struct hlist_nulls_node *node;
5799de0b1   Jianjun Kong   net: clean up net...
2061
  	struct tcp_iter_state *st = seq->private;
a4146b1b2   Denis V. Lunev   [TCP]: Replace st...
2062
  	struct net *net = seq_file_net(seq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2063
2064
  
  	++st->num;
a8b690f98   Tom Herbert   tcp: Fix slowness...
2065
  	++st->offset;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2066
2067
2068
2069
2070
  
  	if (st->state == TCP_SEQ_STATE_TIME_WAIT) {
  		tw = cur;
  		tw = tw_next(tw);
  get_tw:
878628fbf   YOSHIFUJI Hideaki   [NET] NETNS: Omit...
2071
  		while (tw && (tw->tw_family != st->family || !net_eq(twsk_net(tw), net))) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2072
2073
2074
2075
2076
2077
  			tw = tw_next(tw);
  		}
  		if (tw) {
  			cur = tw;
  			goto out;
  		}
9db66bdcc   Eric Dumazet   net: convert TCP/...
2078
  		spin_unlock_bh(inet_ehash_lockp(&tcp_hashinfo, st->bucket));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2079
  		st->state = TCP_SEQ_STATE_ESTABLISHED;
6eac56040   Andi Kleen   tcp: Skip empty h...
2080
  		/* Look for next non empty bucket */
a8b690f98   Tom Herbert   tcp: Fix slowness...
2081
  		st->offset = 0;
f373b53b5   Eric Dumazet   tcp: replace ehas...
2082
  		while (++st->bucket <= tcp_hashinfo.ehash_mask &&
6eac56040   Andi Kleen   tcp: Skip empty h...
2083
2084
  				empty_bucket(st))
  			;
f373b53b5   Eric Dumazet   tcp: replace ehas...
2085
  		if (st->bucket > tcp_hashinfo.ehash_mask)
6eac56040   Andi Kleen   tcp: Skip empty h...
2086
  			return NULL;
9db66bdcc   Eric Dumazet   net: convert TCP/...
2087
  		spin_lock_bh(inet_ehash_lockp(&tcp_hashinfo, st->bucket));
3ab5aee7f   Eric Dumazet   net: Convert TCP ...
2088
  		sk = sk_nulls_head(&tcp_hashinfo.ehash[st->bucket].chain);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2089
  	} else
3ab5aee7f   Eric Dumazet   net: Convert TCP ...
2090
  		sk = sk_nulls_next(sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2091

3ab5aee7f   Eric Dumazet   net: Convert TCP ...
2092
  	sk_nulls_for_each_from(sk, node) {
878628fbf   YOSHIFUJI Hideaki   [NET] NETNS: Omit...
2093
  		if (sk->sk_family == st->family && net_eq(sock_net(sk), net))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2094
2095
2096
2097
  			goto found;
  	}
  
  	st->state = TCP_SEQ_STATE_TIME_WAIT;
dbca9b275   Eric Dumazet   [NET]: change lay...
2098
  	tw = tw_head(&tcp_hashinfo.ehash[st->bucket].twchain);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2099
2100
2101
2102
2103
2104
2105
2106
2107
  	goto get_tw;
  found:
  	cur = sk;
  out:
  	return cur;
  }
  
  static void *established_get_idx(struct seq_file *seq, loff_t pos)
  {
a8b690f98   Tom Herbert   tcp: Fix slowness...
2108
2109
2110
2111
2112
  	struct tcp_iter_state *st = seq->private;
  	void *rc;
  
  	st->bucket = 0;
  	rc = established_get_first(seq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2113
2114
2115
2116
  
  	while (rc && pos) {
  		rc = established_get_next(seq, rc);
  		--pos;
7174259e6   Arnaldo Carvalho de Melo   [TCP_IPV4]: Codin...
2117
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2118
2119
2120
2121
2122
2123
  	return rc;
  }
  
  static void *tcp_get_idx(struct seq_file *seq, loff_t pos)
  {
  	void *rc;
5799de0b1   Jianjun Kong   net: clean up net...
2124
  	struct tcp_iter_state *st = seq->private;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2125

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2126
2127
2128
2129
  	st->state = TCP_SEQ_STATE_LISTENING;
  	rc	  = listening_get_idx(seq, &pos);
  
  	if (!rc) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2130
2131
2132
2133
2134
2135
  		st->state = TCP_SEQ_STATE_ESTABLISHED;
  		rc	  = established_get_idx(seq, pos);
  	}
  
  	return rc;
  }
a8b690f98   Tom Herbert   tcp: Fix slowness...
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
  static void *tcp_seek_last_pos(struct seq_file *seq)
  {
  	struct tcp_iter_state *st = seq->private;
  	int offset = st->offset;
  	int orig_num = st->num;
  	void *rc = NULL;
  
  	switch (st->state) {
  	case TCP_SEQ_STATE_OPENREQ:
  	case TCP_SEQ_STATE_LISTENING:
  		if (st->bucket >= INET_LHTABLE_SIZE)
  			break;
  		st->state = TCP_SEQ_STATE_LISTENING;
  		rc = listening_get_next(seq, NULL);
  		while (offset-- && rc)
  			rc = listening_get_next(seq, rc);
  		if (rc)
  			break;
  		st->bucket = 0;
  		/* Fallthrough */
  	case TCP_SEQ_STATE_ESTABLISHED:
  	case TCP_SEQ_STATE_TIME_WAIT:
  		st->state = TCP_SEQ_STATE_ESTABLISHED;
  		if (st->bucket > tcp_hashinfo.ehash_mask)
  			break;
  		rc = established_get_first(seq);
  		while (offset-- && rc)
  			rc = established_get_next(seq, rc);
  	}
  
  	st->num = orig_num;
  
  	return rc;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2170
2171
  static void *tcp_seq_start(struct seq_file *seq, loff_t *pos)
  {
5799de0b1   Jianjun Kong   net: clean up net...
2172
  	struct tcp_iter_state *st = seq->private;
a8b690f98   Tom Herbert   tcp: Fix slowness...
2173
2174
2175
2176
2177
2178
2179
  	void *rc;
  
  	if (*pos && *pos == st->last_pos) {
  		rc = tcp_seek_last_pos(seq);
  		if (rc)
  			goto out;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2180
2181
  	st->state = TCP_SEQ_STATE_LISTENING;
  	st->num = 0;
a8b690f98   Tom Herbert   tcp: Fix slowness...
2182
2183
2184
2185
2186
2187
2188
  	st->bucket = 0;
  	st->offset = 0;
  	rc = *pos ? tcp_get_idx(seq, *pos - 1) : SEQ_START_TOKEN;
  
  out:
  	st->last_pos = *pos;
  	return rc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2189
2190
2191
2192
  }
  
  static void *tcp_seq_next(struct seq_file *seq, void *v, loff_t *pos)
  {
a8b690f98   Tom Herbert   tcp: Fix slowness...
2193
  	struct tcp_iter_state *st = seq->private;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2194
  	void *rc = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2195
2196
2197
2198
2199
  
  	if (v == SEQ_START_TOKEN) {
  		rc = tcp_get_idx(seq, 0);
  		goto out;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2200
2201
2202
2203
2204
2205
  
  	switch (st->state) {
  	case TCP_SEQ_STATE_OPENREQ:
  	case TCP_SEQ_STATE_LISTENING:
  		rc = listening_get_next(seq, v);
  		if (!rc) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2206
  			st->state = TCP_SEQ_STATE_ESTABLISHED;
a8b690f98   Tom Herbert   tcp: Fix slowness...
2207
2208
  			st->bucket = 0;
  			st->offset = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
  			rc	  = established_get_first(seq);
  		}
  		break;
  	case TCP_SEQ_STATE_ESTABLISHED:
  	case TCP_SEQ_STATE_TIME_WAIT:
  		rc = established_get_next(seq, v);
  		break;
  	}
  out:
  	++*pos;
a8b690f98   Tom Herbert   tcp: Fix slowness...
2219
  	st->last_pos = *pos;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2220
2221
2222
2223
2224
  	return rc;
  }
  
  static void tcp_seq_stop(struct seq_file *seq, void *v)
  {
5799de0b1   Jianjun Kong   net: clean up net...
2225
  	struct tcp_iter_state *st = seq->private;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2226
2227
2228
2229
  
  	switch (st->state) {
  	case TCP_SEQ_STATE_OPENREQ:
  		if (v) {
463c84b97   Arnaldo Carvalho de Melo   [NET]: Introduce ...
2230
2231
  			struct inet_connection_sock *icsk = inet_csk(st->syn_wait_sk);
  			read_unlock_bh(&icsk->icsk_accept_queue.syn_wait_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2232
2233
2234
  		}
  	case TCP_SEQ_STATE_LISTENING:
  		if (v != SEQ_START_TOKEN)
5caea4ea7   Eric Dumazet   net: listening_ha...
2235
  			spin_unlock_bh(&tcp_hashinfo.listening_hash[st->bucket].lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2236
2237
2238
2239
  		break;
  	case TCP_SEQ_STATE_TIME_WAIT:
  	case TCP_SEQ_STATE_ESTABLISHED:
  		if (v)
9db66bdcc   Eric Dumazet   net: convert TCP/...
2240
  			spin_unlock_bh(inet_ehash_lockp(&tcp_hashinfo, st->bucket));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2241
2242
2243
  		break;
  	}
  }
73cb88ecb   Arjan van de Ven   net: make the tcp...
2244
  int tcp_seq_open(struct inode *inode, struct file *file)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2245
2246
  {
  	struct tcp_seq_afinfo *afinfo = PDE(inode)->data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2247
  	struct tcp_iter_state *s;
52d6f3f11   Denis V. Lunev   [TCP]: Cleanup /p...
2248
  	int err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2249

52d6f3f11   Denis V. Lunev   [TCP]: Cleanup /p...
2250
2251
2252
2253
  	err = seq_open_net(inode, file, &afinfo->seq_ops,
  			  sizeof(struct tcp_iter_state));
  	if (err < 0)
  		return err;
f40c8174d   Daniel Lezcano   [NETNS][IPV4] tcp...
2254

52d6f3f11   Denis V. Lunev   [TCP]: Cleanup /p...
2255
  	s = ((struct seq_file *)file->private_data)->private;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2256
  	s->family		= afinfo->family;
a8b690f98   Tom Herbert   tcp: Fix slowness...
2257
  	s->last_pos 		= 0;
f40c8174d   Daniel Lezcano   [NETNS][IPV4] tcp...
2258
2259
  	return 0;
  }
73cb88ecb   Arjan van de Ven   net: make the tcp...
2260
  EXPORT_SYMBOL(tcp_seq_open);
f40c8174d   Daniel Lezcano   [NETNS][IPV4] tcp...
2261

6f8b13bcb   Daniel Lezcano   [NETNS][IPV6] tcp...
2262
  int tcp_proc_register(struct net *net, struct tcp_seq_afinfo *afinfo)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2263
2264
2265
  {
  	int rc = 0;
  	struct proc_dir_entry *p;
9427c4b36   Denis V. Lunev   [TCP]: Move seq_o...
2266
2267
2268
  	afinfo->seq_ops.start		= tcp_seq_start;
  	afinfo->seq_ops.next		= tcp_seq_next;
  	afinfo->seq_ops.stop		= tcp_seq_stop;
84841c3c6   Denis V. Lunev   ipv4: assign PDE-...
2269
  	p = proc_create_data(afinfo->name, S_IRUGO, net->proc_net,
73cb88ecb   Arjan van de Ven   net: make the tcp...
2270
  			     afinfo->seq_fops, afinfo);
84841c3c6   Denis V. Lunev   ipv4: assign PDE-...
2271
  	if (!p)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2272
2273
2274
  		rc = -ENOMEM;
  	return rc;
  }
4bc2f18ba   Eric Dumazet   net/ipv4: EXPORT_...
2275
  EXPORT_SYMBOL(tcp_proc_register);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2276

6f8b13bcb   Daniel Lezcano   [NETNS][IPV6] tcp...
2277
  void tcp_proc_unregister(struct net *net, struct tcp_seq_afinfo *afinfo)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2278
  {
6f8b13bcb   Daniel Lezcano   [NETNS][IPV6] tcp...
2279
  	proc_net_remove(net, afinfo->name);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2280
  }
4bc2f18ba   Eric Dumazet   net/ipv4: EXPORT_...
2281
  EXPORT_SYMBOL(tcp_proc_unregister);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2282

cf533ea53   Eric Dumazet   tcp: add const qu...
2283
  static void get_openreq4(const struct sock *sk, const struct request_sock *req,
5e659e4cb   Pavel Emelyanov   [NET]: Fix heavy ...
2284
  			 struct seq_file *f, int i, int uid, int *len)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2285
  {
2e6599cb8   Arnaldo Carvalho de Melo   [NET] Generalise ...
2286
  	const struct inet_request_sock *ireq = inet_rsk(req);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2287
  	int ttd = req->expires - jiffies;
5e659e4cb   Pavel Emelyanov   [NET]: Fix heavy ...
2288
  	seq_printf(f, "%4d: %08X:%04X %08X:%04X"
71338aa7d   Dan Rosenberg   net: convert %p u...
2289
  		" %02X %08X:%08X %02X:%08lX %08X %5d %8d %u %d %pK%n",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2290
  		i,
2e6599cb8   Arnaldo Carvalho de Melo   [NET] Generalise ...
2291
  		ireq->loc_addr,
c720c7e83   Eric Dumazet   inet: rename some...
2292
  		ntohs(inet_sk(sk)->inet_sport),
2e6599cb8   Arnaldo Carvalho de Melo   [NET] Generalise ...
2293
2294
  		ireq->rmt_addr,
  		ntohs(ireq->rmt_port),
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2295
2296
2297
2298
2299
2300
2301
2302
2303
  		TCP_SYN_RECV,
  		0, 0, /* could print option size, but that is af dependent. */
  		1,    /* timers active (only the expire timer) */
  		jiffies_to_clock_t(ttd),
  		req->retrans,
  		uid,
  		0,  /* non standard timer */
  		0, /* open_requests have no inode */
  		atomic_read(&sk->sk_refcnt),
5e659e4cb   Pavel Emelyanov   [NET]: Fix heavy ...
2304
2305
  		req,
  		len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2306
  }
5e659e4cb   Pavel Emelyanov   [NET]: Fix heavy ...
2307
  static void get_tcp4_sock(struct sock *sk, struct seq_file *f, int i, int *len)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2308
2309
2310
  {
  	int timer_active;
  	unsigned long timer_expires;
cf533ea53   Eric Dumazet   tcp: add const qu...
2311
  	const struct tcp_sock *tp = tcp_sk(sk);
cf4c6bf83   Ilpo Järvinen   [TCP]: struct *so...
2312
  	const struct inet_connection_sock *icsk = inet_csk(sk);
cf533ea53   Eric Dumazet   tcp: add const qu...
2313
  	const struct inet_sock *inet = inet_sk(sk);
c720c7e83   Eric Dumazet   inet: rename some...
2314
2315
2316
2317
  	__be32 dest = inet->inet_daddr;
  	__be32 src = inet->inet_rcv_saddr;
  	__u16 destp = ntohs(inet->inet_dport);
  	__u16 srcp = ntohs(inet->inet_sport);
49d090078   Eric Dumazet   tcp: diag: Dont r...
2318
  	int rx_queue;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2319

463c84b97   Arnaldo Carvalho de Melo   [NET]: Introduce ...
2320
  	if (icsk->icsk_pending == ICSK_TIME_RETRANS) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2321
  		timer_active	= 1;
463c84b97   Arnaldo Carvalho de Melo   [NET]: Introduce ...
2322
2323
  		timer_expires	= icsk->icsk_timeout;
  	} else if (icsk->icsk_pending == ICSK_TIME_PROBE0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2324
  		timer_active	= 4;
463c84b97   Arnaldo Carvalho de Melo   [NET]: Introduce ...
2325
  		timer_expires	= icsk->icsk_timeout;
cf4c6bf83   Ilpo Järvinen   [TCP]: struct *so...
2326
  	} else if (timer_pending(&sk->sk_timer)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2327
  		timer_active	= 2;
cf4c6bf83   Ilpo Järvinen   [TCP]: struct *so...
2328
  		timer_expires	= sk->sk_timer.expires;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2329
2330
2331
2332
  	} else {
  		timer_active	= 0;
  		timer_expires = jiffies;
  	}
49d090078   Eric Dumazet   tcp: diag: Dont r...
2333
2334
2335
2336
2337
2338
2339
  	if (sk->sk_state == TCP_LISTEN)
  		rx_queue = sk->sk_ack_backlog;
  	else
  		/*
  		 * because we dont lock socket, we might find a transient negative value
  		 */
  		rx_queue = max_t(int, tp->rcv_nxt - tp->copied_seq, 0);
5e659e4cb   Pavel Emelyanov   [NET]: Fix heavy ...
2340
  	seq_printf(f, "%4d: %08X:%04X %08X:%04X %02X %08X:%08X %02X:%08lX "
71338aa7d   Dan Rosenberg   net: convert %p u...
2341
  			"%08X %5d %8d %lu %d %pK %lu %lu %u %u %d%n",
cf4c6bf83   Ilpo Järvinen   [TCP]: struct *so...
2342
  		i, src, srcp, dest, destp, sk->sk_state,
47da8ee68   Sridhar Samudrala   [TCP]: Export acc...
2343
  		tp->write_seq - tp->snd_una,
49d090078   Eric Dumazet   tcp: diag: Dont r...
2344
  		rx_queue,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2345
2346
  		timer_active,
  		jiffies_to_clock_t(timer_expires - jiffies),
463c84b97   Arnaldo Carvalho de Melo   [NET]: Introduce ...
2347
  		icsk->icsk_retransmits,
cf4c6bf83   Ilpo Järvinen   [TCP]: struct *so...
2348
  		sock_i_uid(sk),
6687e988d   Arnaldo Carvalho de Melo   [ICSK]: Move TCP ...
2349
  		icsk->icsk_probes_out,
cf4c6bf83   Ilpo Järvinen   [TCP]: struct *so...
2350
2351
  		sock_i_ino(sk),
  		atomic_read(&sk->sk_refcnt), sk,
7be87351a   Stephen Hemminger   tcp: /proc/net/tc...
2352
2353
  		jiffies_to_clock_t(icsk->icsk_rto),
  		jiffies_to_clock_t(icsk->icsk_ack.ato),
463c84b97   Arnaldo Carvalho de Melo   [NET]: Introduce ...
2354
  		(icsk->icsk_ack.quick << 1) | icsk->icsk_ack.pingpong,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2355
  		tp->snd_cwnd,
0b6a05c1d   Ilpo Järvinen   tcp: fix ssthresh...
2356
  		tcp_in_initial_slowstart(tp) ? -1 : tp->snd_ssthresh,
5e659e4cb   Pavel Emelyanov   [NET]: Fix heavy ...
2357
  		len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2358
  }
cf533ea53   Eric Dumazet   tcp: add const qu...
2359
  static void get_timewait4_sock(const struct inet_timewait_sock *tw,
5e659e4cb   Pavel Emelyanov   [NET]: Fix heavy ...
2360
  			       struct seq_file *f, int i, int *len)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2361
  {
23f33c2d4   Al Viro   [IPV4]: struct in...
2362
  	__be32 dest, src;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
  	__u16 destp, srcp;
  	int ttd = tw->tw_ttd - jiffies;
  
  	if (ttd < 0)
  		ttd = 0;
  
  	dest  = tw->tw_daddr;
  	src   = tw->tw_rcv_saddr;
  	destp = ntohs(tw->tw_dport);
  	srcp  = ntohs(tw->tw_sport);
5e659e4cb   Pavel Emelyanov   [NET]: Fix heavy ...
2373
  	seq_printf(f, "%4d: %08X:%04X %08X:%04X"
71338aa7d   Dan Rosenberg   net: convert %p u...
2374
  		" %02X %08X:%08X %02X:%08lX %08X %5d %8d %d %d %pK%n",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2375
2376
  		i, src, srcp, dest, destp, tw->tw_substate, 0, 0,
  		3, jiffies_to_clock_t(ttd), 0, 0, 0, 0,
5e659e4cb   Pavel Emelyanov   [NET]: Fix heavy ...
2377
  		atomic_read(&tw->tw_refcnt), tw, len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2378
2379
2380
2381
2382
2383
  }
  
  #define TMPSZ 150
  
  static int tcp4_seq_show(struct seq_file *seq, void *v)
  {
5799de0b1   Jianjun Kong   net: clean up net...
2384
  	struct tcp_iter_state *st;
5e659e4cb   Pavel Emelyanov   [NET]: Fix heavy ...
2385
  	int len;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
  
  	if (v == SEQ_START_TOKEN) {
  		seq_printf(seq, "%-*s
  ", TMPSZ - 1,
  			   "  sl  local_address rem_address   st tx_queue "
  			   "rx_queue tr tm->when retrnsmt   uid  timeout "
  			   "inode");
  		goto out;
  	}
  	st = seq->private;
  
  	switch (st->state) {
  	case TCP_SEQ_STATE_LISTENING:
  	case TCP_SEQ_STATE_ESTABLISHED:
5e659e4cb   Pavel Emelyanov   [NET]: Fix heavy ...
2400
  		get_tcp4_sock(v, seq, st->num, &len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2401
2402
  		break;
  	case TCP_SEQ_STATE_OPENREQ:
5e659e4cb   Pavel Emelyanov   [NET]: Fix heavy ...
2403
  		get_openreq4(st->syn_wait_sk, v, seq, st->num, st->uid, &len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2404
2405
  		break;
  	case TCP_SEQ_STATE_TIME_WAIT:
5e659e4cb   Pavel Emelyanov   [NET]: Fix heavy ...
2406
  		get_timewait4_sock(v, seq, st->num, &len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2407
2408
  		break;
  	}
5e659e4cb   Pavel Emelyanov   [NET]: Fix heavy ...
2409
2410
  	seq_printf(seq, "%*s
  ", TMPSZ - 1 - len, "");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2411
2412
2413
  out:
  	return 0;
  }
73cb88ecb   Arjan van de Ven   net: make the tcp...
2414
2415
2416
2417
2418
2419
2420
  static const struct file_operations tcp_afinfo_seq_fops = {
  	.owner   = THIS_MODULE,
  	.open    = tcp_seq_open,
  	.read    = seq_read,
  	.llseek  = seq_lseek,
  	.release = seq_release_net
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2421
  static struct tcp_seq_afinfo tcp4_seq_afinfo = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2422
2423
  	.name		= "tcp",
  	.family		= AF_INET,
73cb88ecb   Arjan van de Ven   net: make the tcp...
2424
  	.seq_fops	= &tcp_afinfo_seq_fops,
9427c4b36   Denis V. Lunev   [TCP]: Move seq_o...
2425
2426
2427
  	.seq_ops	= {
  		.show		= tcp4_seq_show,
  	},
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2428
  };
2c8c1e729   Alexey Dobriyan   net: spread __net...
2429
  static int __net_init tcp4_proc_init_net(struct net *net)
757764f61   Pavel Emelyanov   [NETNS][TCP]: Reg...
2430
2431
2432
  {
  	return tcp_proc_register(net, &tcp4_seq_afinfo);
  }
2c8c1e729   Alexey Dobriyan   net: spread __net...
2433
  static void __net_exit tcp4_proc_exit_net(struct net *net)
757764f61   Pavel Emelyanov   [NETNS][TCP]: Reg...
2434
2435
2436
2437
2438
2439
2440
2441
  {
  	tcp_proc_unregister(net, &tcp4_seq_afinfo);
  }
  
  static struct pernet_operations tcp4_net_ops = {
  	.init = tcp4_proc_init_net,
  	.exit = tcp4_proc_exit_net,
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2442
2443
  int __init tcp4_proc_init(void)
  {
757764f61   Pavel Emelyanov   [NETNS][TCP]: Reg...
2444
  	return register_pernet_subsys(&tcp4_net_ops);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2445
2446
2447
2448
  }
  
  void tcp4_proc_exit(void)
  {
757764f61   Pavel Emelyanov   [NETNS][TCP]: Reg...
2449
  	unregister_pernet_subsys(&tcp4_net_ops);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2450
2451
  }
  #endif /* CONFIG_PROC_FS */
bf296b125   Herbert Xu   tcp: Add GRO support
2452
2453
  struct sk_buff **tcp4_gro_receive(struct sk_buff **head, struct sk_buff *skb)
  {
b71d1d426   Eric Dumazet   inet: constify ip...
2454
  	const struct iphdr *iph = skb_gro_network_header(skb);
bf296b125   Herbert Xu   tcp: Add GRO support
2455
2456
2457
  
  	switch (skb->ip_summed) {
  	case CHECKSUM_COMPLETE:
86911732d   Herbert Xu   gro: Avoid copyin...
2458
  		if (!tcp_v4_check(skb_gro_len(skb), iph->saddr, iph->daddr,
bf296b125   Herbert Xu   tcp: Add GRO support
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
  				  skb->csum)) {
  			skb->ip_summed = CHECKSUM_UNNECESSARY;
  			break;
  		}
  
  		/* fall through */
  	case CHECKSUM_NONE:
  		NAPI_GRO_CB(skb)->flush = 1;
  		return NULL;
  	}
  
  	return tcp_gro_receive(head, skb);
  }
bf296b125   Herbert Xu   tcp: Add GRO support
2472
2473
2474
  
  int tcp4_gro_complete(struct sk_buff *skb)
  {
b71d1d426   Eric Dumazet   inet: constify ip...
2475
  	const struct iphdr *iph = ip_hdr(skb);
bf296b125   Herbert Xu   tcp: Add GRO support
2476
2477
2478
2479
2480
2481
2482
2483
  	struct tcphdr *th = tcp_hdr(skb);
  
  	th->check = ~tcp_v4_check(skb->len - skb_transport_offset(skb),
  				  iph->saddr, iph->daddr, 0);
  	skb_shinfo(skb)->gso_type = SKB_GSO_TCPV4;
  
  	return tcp_gro_complete(skb);
  }
bf296b125   Herbert Xu   tcp: Add GRO support
2484

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2485
2486
2487
2488
2489
2490
  struct proto tcp_prot = {
  	.name			= "TCP",
  	.owner			= THIS_MODULE,
  	.close			= tcp_close,
  	.connect		= tcp_v4_connect,
  	.disconnect		= tcp_disconnect,
463c84b97   Arnaldo Carvalho de Melo   [NET]: Introduce ...
2491
  	.accept			= inet_csk_accept,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2492
2493
2494
2495
2496
2497
  	.ioctl			= tcp_ioctl,
  	.init			= tcp_v4_init_sock,
  	.destroy		= tcp_v4_destroy_sock,
  	.shutdown		= tcp_shutdown,
  	.setsockopt		= tcp_setsockopt,
  	.getsockopt		= tcp_getsockopt,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2498
  	.recvmsg		= tcp_recvmsg,
7ba429100   Changli Gao   inet, inet6: make...
2499
2500
  	.sendmsg		= tcp_sendmsg,
  	.sendpage		= tcp_sendpage,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2501
  	.backlog_rcv		= tcp_v4_do_rcv,
ab1e0a13d   Arnaldo Carvalho de Melo   [SOCK] proto: Add...
2502
2503
2504
  	.hash			= inet_hash,
  	.unhash			= inet_unhash,
  	.get_port		= inet_csk_get_port,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2505
2506
  	.enter_memory_pressure	= tcp_enter_memory_pressure,
  	.sockets_allocated	= &tcp_sockets_allocated,
0a5578cf8   Arnaldo Carvalho de Melo   [ICSK]: Generalis...
2507
  	.orphan_count		= &tcp_orphan_count,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2508
2509
2510
2511
2512
2513
2514
  	.memory_allocated	= &tcp_memory_allocated,
  	.memory_pressure	= &tcp_memory_pressure,
  	.sysctl_mem		= sysctl_tcp_mem,
  	.sysctl_wmem		= sysctl_tcp_wmem,
  	.sysctl_rmem		= sysctl_tcp_rmem,
  	.max_header		= MAX_TCP_HEADER,
  	.obj_size		= sizeof(struct tcp_sock),
3ab5aee7f   Eric Dumazet   net: Convert TCP ...
2515
  	.slab_flags		= SLAB_DESTROY_BY_RCU,
6d6ee43e0   Arnaldo Carvalho de Melo   [TWSK]: Introduce...
2516
  	.twsk_prot		= &tcp_timewait_sock_ops,
60236fdd0   Arnaldo Carvalho de Melo   [NET] Rename open...
2517
  	.rsk_prot		= &tcp_request_sock_ops,
39d8cda76   Pavel Emelyanov   [SOCK]: Add udp_h...
2518
  	.h.hashinfo		= &tcp_hashinfo,
7ba429100   Changli Gao   inet, inet6: make...
2519
  	.no_autobind		= true,
543d9cfee   Arnaldo Carvalho de Melo   [NET]: Identation...
2520
2521
2522
2523
  #ifdef CONFIG_COMPAT
  	.compat_setsockopt	= compat_tcp_setsockopt,
  	.compat_getsockopt	= compat_tcp_getsockopt,
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2524
  };
4bc2f18ba   Eric Dumazet   net/ipv4: EXPORT_...
2525
  EXPORT_SYMBOL(tcp_prot);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2526

046ee9023   Denis V. Lunev   [NETNS]: Create t...
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
  
  static int __net_init tcp_sk_init(struct net *net)
  {
  	return inet_ctl_sock_create(&net->ipv4.tcp_sock,
  				    PF_INET, SOCK_RAW, IPPROTO_TCP, net);
  }
  
  static void __net_exit tcp_sk_exit(struct net *net)
  {
  	inet_ctl_sock_destroy(net->ipv4.tcp_sock);
b099ce260   Eric W. Biederman   net: Batch inet_t...
2537
2538
2539
2540
2541
  }
  
  static void __net_exit tcp_sk_exit_batch(struct list_head *net_exit_list)
  {
  	inet_twsk_purge(&tcp_hashinfo, &tcp_death_row, AF_INET);
046ee9023   Denis V. Lunev   [NETNS]: Create t...
2542
2543
2544
  }
  
  static struct pernet_operations __net_initdata tcp_sk_ops = {
b099ce260   Eric W. Biederman   net: Batch inet_t...
2545
2546
2547
         .init	   = tcp_sk_init,
         .exit	   = tcp_sk_exit,
         .exit_batch = tcp_sk_exit_batch,
046ee9023   Denis V. Lunev   [NETNS]: Create t...
2548
  };
9b0f976f2   Denis V. Lunev   [INET]: Remove st...
2549
  void __init tcp_v4_init(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2550
  {
5caea4ea7   Eric Dumazet   net: listening_ha...
2551
  	inet_hashinfo_init(&tcp_hashinfo);
6a1b3054d   Eric W. Biederman   tcp: Like icmp us...
2552
  	if (register_pernet_subsys(&tcp_sk_ops))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2553
2554
  		panic("Failed to create the TCP control socket.
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2555
  }