Blame view

net/ipv4/tcp_ipv4.c 63.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.
   */
afd465030   Joe Perches   net: ipv4: Standa...
52
  #define pr_fmt(fmt) "TCP: " fmt
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
53

eb4dea585   Herbert Xu   net: Fix percpu c...
54
  #include <linux/bottom_half.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
55
56
57
58
59
60
61
62
  #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: ...
63
  #include <linux/slab.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
64

457c4cbc5   Eric W. Biederman   [NET]: Make /proc...
65
  #include <net/net_namespace.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
66
  #include <net/icmp.h>
304a16180   Arnaldo Carvalho de Melo   [INET]: Move the ...
67
  #include <net/inet_hashtables.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
68
  #include <net/tcp.h>
20380731b   Arnaldo Carvalho de Melo   [NET]: Fix sparse...
69
  #include <net/transp_v6.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
70
71
  #include <net/ipv6.h>
  #include <net/inet_common.h>
6d6ee43e0   Arnaldo Carvalho de Melo   [TWSK]: Introduce...
72
  #include <net/timewait_sock.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
73
  #include <net/xfrm.h>
6e5714eaf   David S. Miller   net: Compute prot...
74
  #include <net/secure_seq.h>
076bb0c82   Eliezer Tamir   net: rename inclu...
75
  #include <net/busy_poll.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
76
77
78
79
80
81
  
  #include <linux/inet.h>
  #include <linux/ipv6.h>
  #include <linux/stddef.h>
  #include <linux/proc_fs.h>
  #include <linux/seq_file.h>
cf80e0e47   Herbert Xu   tcp: Use ahash
82
  #include <crypto/hash.h>
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
83
  #include <linux/scatterlist.h>
ab32ea5d8   Brian Haley   [NET/IPV4/IPV6]: ...
84
85
  int sysctl_tcp_tw_reuse __read_mostly;
  int sysctl_tcp_low_latency __read_mostly;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
86

cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
87
  #ifdef CONFIG_TCP_MD5SIG
a915da9b6   Eric Dumazet   tcp: md5: rcu con...
88
  static int tcp_v4_md5_hash_hdr(char *md5_hash, const struct tcp_md5sig_key *key,
318cf7aaa   Eric Dumazet   tcp: md5: add mor...
89
  			       __be32 daddr, __be32 saddr, const struct tcphdr *th);
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
90
  #endif
5caea4ea7   Eric Dumazet   net: listening_ha...
91
  struct inet_hashinfo tcp_hashinfo;
4bc2f18ba   Eric Dumazet   net/ipv4: EXPORT_...
92
  EXPORT_SYMBOL(tcp_hashinfo);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
93

936b8bdb5   Octavian Purdila   tcp: add init_seq...
94
  static  __u32 tcp_v4_init_sequence(const struct sk_buff *skb)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
95
  {
eddc9ec53   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
96
97
  	return secure_tcp_sequence_number(ip_hdr(skb)->daddr,
  					  ip_hdr(skb)->saddr,
aa8223c7b   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
98
99
  					  tcp_hdr(skb)->dest,
  					  tcp_hdr(skb)->source);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
100
  }
6d6ee43e0   Arnaldo Carvalho de Melo   [TWSK]: Introduce...
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
  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 &&
51456b291   Ian Morris   ipv4: coding styl...
118
  	    (!twp || (sysctl_tcp_tw_reuse &&
9d729f72d   James Morris   [NET]: Convert xt...
119
  			     get_seconds() - tcptw->tw_ts_recent_stamp > 1))) {
6d6ee43e0   Arnaldo Carvalho de Melo   [TWSK]: Introduce...
120
121
122
123
124
125
126
127
128
129
130
  		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...
131
  EXPORT_SYMBOL_GPL(tcp_twsk_unique);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
132
133
134
  /* 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...
135
  	struct sockaddr_in *usin = (struct sockaddr_in *)uaddr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
136
137
  	struct inet_sock *inet = inet_sk(sk);
  	struct tcp_sock *tp = tcp_sk(sk);
dca8b089c   David S. Miller   ipv4: Rearrange h...
138
  	__be16 orig_sport, orig_dport;
bada8adc4   Al Viro   [IPV4]: ip_route_...
139
  	__be32 daddr, nexthop;
da905bd1d   David S. Miller   tcp: Use cork flo...
140
  	struct flowi4 *fl4;
2d7192d6c   David S. Miller   ipv4: Sanitize an...
141
  	struct rtable *rt;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
142
  	int err;
f6d8bd051   Eric Dumazet   inet: add RCU pro...
143
  	struct ip_options_rcu *inet_opt;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
144
145
146
147
148
149
150
151
  
  	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...
152
  	inet_opt = rcu_dereference_protected(inet->inet_opt,
1e1d04e67   Hannes Frederic Sowa   net: introduce lo...
153
  					     lockdep_sock_is_held(sk));
f6d8bd051   Eric Dumazet   inet: add RCU pro...
154
  	if (inet_opt && inet_opt->opt.srr) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
155
156
  		if (!daddr)
  			return -EINVAL;
f6d8bd051   Eric Dumazet   inet: add RCU pro...
157
  		nexthop = inet_opt->opt.faddr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
158
  	}
dca8b089c   David S. Miller   ipv4: Rearrange h...
159
160
  	orig_sport = inet->inet_sport;
  	orig_dport = usin->sin_port;
da905bd1d   David S. Miller   tcp: Use cork flo...
161
162
  	fl4 = &inet->cork.fl.u.ip4;
  	rt = ip_route_connect(fl4, nexthop, inet->inet_saddr,
b23dd4fe4   David S. Miller   ipv4: Make output...
163
164
  			      RT_CONN_FLAGS(sk), sk->sk_bound_dev_if,
  			      IPPROTO_TCP,
0e0d44ab4   Steffen Klassert   net: Remove FLOWI...
165
  			      orig_sport, orig_dport, sk);
b23dd4fe4   David S. Miller   ipv4: Make output...
166
167
168
  	if (IS_ERR(rt)) {
  		err = PTR_ERR(rt);
  		if (err == -ENETUNREACH)
f1d8cba61   Eric Dumazet   inet: fix possibl...
169
  			IP_INC_STATS(sock_net(sk), IPSTATS_MIB_OUTNOROUTES);
b23dd4fe4   David S. Miller   ipv4: Make output...
170
  		return err;
584bdf8cb   Wei Dong   [IPV4]: Fix "ipOu...
171
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
172
173
174
175
176
  
  	if (rt->rt_flags & (RTCF_MULTICAST | RTCF_BROADCAST)) {
  		ip_rt_put(rt);
  		return -ENETUNREACH;
  	}
f6d8bd051   Eric Dumazet   inet: add RCU pro...
177
  	if (!inet_opt || !inet_opt->opt.srr)
da905bd1d   David S. Miller   tcp: Use cork flo...
178
  		daddr = fl4->daddr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
179

c720c7e83   Eric Dumazet   inet: rename some...
180
  	if (!inet->inet_saddr)
da905bd1d   David S. Miller   tcp: Use cork flo...
181
  		inet->inet_saddr = fl4->saddr;
d1e559d0b   Eric Dumazet   inet: add IPv6 su...
182
  	sk_rcv_saddr_set(sk, inet->inet_saddr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
183

c720c7e83   Eric Dumazet   inet: rename some...
184
  	if (tp->rx_opt.ts_recent_stamp && inet->inet_daddr != daddr) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
185
186
187
  		/* Reset inherited state */
  		tp->rx_opt.ts_recent	   = 0;
  		tp->rx_opt.ts_recent_stamp = 0;
ee9952831   Pavel Emelyanov   tcp: Initial repa...
188
189
  		if (likely(!tp->repair))
  			tp->write_seq	   = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
190
  	}
295ff7edb   Arnaldo Carvalho de Melo   [TIMEWAIT]: Intro...
191
  	if (tcp_death_row.sysctl_tw_recycle &&
81166dd6f   David S. Miller   tcp: Move timesta...
192
193
  	    !tp->rx_opt.ts_recent_stamp && fl4->daddr == daddr)
  		tcp_fetch_timewait_stamp(sk, &rt->dst);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
194

c720c7e83   Eric Dumazet   inet: rename some...
195
  	inet->inet_dport = usin->sin_port;
d1e559d0b   Eric Dumazet   inet: add IPv6 su...
196
  	sk_daddr_set(sk, daddr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
197

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

bee7ca9ec   William Allen Simpson   net: TCP_MSS_DEFA...
202
  	tp->rx_opt.mss_clamp = TCP_MSS_DEFAULT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
203
204
205
206
207
208
209
  
  	/* 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...
210
  	err = inet_hash_connect(&tcp_death_row, sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
211
212
  	if (err)
  		goto failure;
877d1f629   Tom Herbert   net: Set sk_txhas...
213
  	sk_set_txhash(sk);
9e7ceb060   Sathya Perla   net: fix saving T...
214

da905bd1d   David S. Miller   tcp: Use cork flo...
215
  	rt = ip_route_newports(fl4, rt, orig_sport, orig_dport,
b23dd4fe4   David S. Miller   ipv4: Make output...
216
217
218
219
  			       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
220
  		goto failure;
b23dd4fe4   David S. Miller   ipv4: Make output...
221
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
222
  	/* OK, now commit destination to socket.  */
bcd761111   Herbert Xu   [NET]: Generalise...
223
  	sk->sk_gso_type = SKB_GSO_TCPV4;
d8d1f30b9   Changli Gao   net-next: remove ...
224
  	sk_setup_caps(sk, &rt->dst);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
225

ee9952831   Pavel Emelyanov   tcp: Initial repa...
226
  	if (!tp->write_seq && likely(!tp->repair))
c720c7e83   Eric Dumazet   inet: rename some...
227
228
229
  		tp->write_seq = secure_tcp_sequence_number(inet->inet_saddr,
  							   inet->inet_daddr,
  							   inet->inet_sport,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
230
  							   usin->sin_port);
c720c7e83   Eric Dumazet   inet: rename some...
231
  	inet->inet_id = tp->write_seq ^ jiffies;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
232

2b9164771   Andrey Vagin   ipv6: adapt conne...
233
  	err = tcp_connect(sk);
ee9952831   Pavel Emelyanov   tcp: Initial repa...
234

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
235
236
237
238
239
240
241
  	rt = NULL;
  	if (err)
  		goto failure;
  
  	return 0;
  
  failure:
7174259e6   Arnaldo Carvalho de Melo   [TCP_IPV4]: Codin...
242
243
244
245
  	/*
  	 * This unhashes the socket and releases the local port,
  	 * if necessary.
  	 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
246
247
248
  	tcp_set_state(sk, TCP_CLOSE);
  	ip_rt_put(rt);
  	sk->sk_route_caps = 0;
c720c7e83   Eric Dumazet   inet: rename some...
249
  	inet->inet_dport = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
250
251
  	return err;
  }
4bc2f18ba   Eric Dumazet   net/ipv4: EXPORT_...
252
  EXPORT_SYMBOL(tcp_v4_connect);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
253

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
254
  /*
563d34d05   Eric Dumazet   tcp: dont drop MT...
255
256
257
   * This routine reacts to ICMP_FRAG_NEEDED mtu indications as defined in RFC1191.
   * It can be called through tcp_release_cb() if socket was owned by user
   * at the time tcp_v4_err() was called to handle ICMP message.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
258
   */
4fab90719   Neal Cardwell   tcp: fix tcp_rele...
259
  void tcp_v4_mtu_reduced(struct sock *sk)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
260
261
262
  {
  	struct dst_entry *dst;
  	struct inet_sock *inet = inet_sk(sk);
563d34d05   Eric Dumazet   tcp: dont drop MT...
263
  	u32 mtu = tcp_sk(sk)->mtu_info;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
264

80d0a69fc   David S. Miller   ipv4: Add helper ...
265
266
  	dst = inet_csk_update_pmtu(sk, mtu);
  	if (!dst)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
267
  		return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
268
269
270
271
272
273
274
275
276
  	/* 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 &&
482fc6094   Hannes Frederic Sowa   ipv4: introduce n...
277
  	    ip_sk_accept_pmtu(sk) &&
d83d8461f   Arnaldo Carvalho de Melo   [IP_SOCKGLUE]: Re...
278
  	    inet_csk(sk)->icsk_pmtu_cookie > mtu) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
279
280
281
282
283
284
285
286
287
288
  		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 */
  }
4fab90719   Neal Cardwell   tcp: fix tcp_rele...
289
  EXPORT_SYMBOL(tcp_v4_mtu_reduced);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
290

55be7a9c6   David S. Miller   ipv4: Add redirec...
291
292
293
  static void do_redirect(struct sk_buff *skb, struct sock *sk)
  {
  	struct dst_entry *dst = __sk_dst_check(sk, 0);
1ed5c48f2   David S. Miller   net: Remove check...
294
  	if (dst)
6700c2709   David S. Miller   net: Pass optiona...
295
  		dst->ops->redirect(dst, sk, skb);
55be7a9c6   David S. Miller   ipv4: Add redirec...
296
  }
26e373609   Eric Dumazet   ipv4: tcp: handle...
297
298
  
  /* handle ICMP messages on TCP_NEW_SYN_RECV request sockets */
9cf749036   Eric Dumazet   tcp: do not drop ...
299
  void tcp_req_err(struct sock *sk, u32 seq, bool abort)
26e373609   Eric Dumazet   ipv4: tcp: handle...
300
301
302
303
304
305
306
  {
  	struct request_sock *req = inet_reqsk(sk);
  	struct net *net = sock_net(sk);
  
  	/* ICMPs are not backlogged, hence we cannot get
  	 * an established socket here.
  	 */
26e373609   Eric Dumazet   ipv4: tcp: handle...
307
  	if (seq != tcp_rsk(req)->snt_isn) {
02a1d6e7a   Eric Dumazet   net: rename NET_{...
308
  		__NET_INC_STATS(net, LINUX_MIB_OUTOFWINDOWICMPS);
9cf749036   Eric Dumazet   tcp: do not drop ...
309
  	} else if (abort) {
26e373609   Eric Dumazet   ipv4: tcp: handle...
310
311
312
313
314
315
  		/*
  		 * 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().
  		 */
c69736696   Fan Du   inet: fix double ...
316
  		inet_csk_reqsk_queue_drop(req->rsk_listener, req);
9caad8641   Eric Dumazet   tcp: increment sk...
317
  		tcp_listendrop(req->rsk_listener);
26e373609   Eric Dumazet   ipv4: tcp: handle...
318
  	}
ef84d8ce5   Eric Dumazet   Revert "inet: fix...
319
  	reqsk_put(req);
26e373609   Eric Dumazet   ipv4: tcp: handle...
320
321
  }
  EXPORT_SYMBOL(tcp_req_err);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
  /*
   * 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...
337
  void tcp_v4_err(struct sk_buff *icmp_skb, u32 info)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
338
  {
b71d1d426   Eric Dumazet   inet: constify ip...
339
  	const struct iphdr *iph = (const struct iphdr *)icmp_skb->data;
4d1a2d9ec   Damian Lukowski   Revert Backoff [v...
340
  	struct tcphdr *th = (struct tcphdr *)(icmp_skb->data + (iph->ihl << 2));
f1ecd5d9e   Damian Lukowski   Revert Backoff [v...
341
  	struct inet_connection_sock *icsk;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
342
343
  	struct tcp_sock *tp;
  	struct inet_sock *inet;
4d1a2d9ec   Damian Lukowski   Revert Backoff [v...
344
345
  	const int type = icmp_hdr(icmp_skb)->type;
  	const int code = icmp_hdr(icmp_skb)->code;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
346
  	struct sock *sk;
f1ecd5d9e   Damian Lukowski   Revert Backoff [v...
347
  	struct sk_buff *skb;
0a672f741   Yuchung Cheng   tcp: improve fast...
348
349
  	struct request_sock *fastopen;
  	__u32 seq, snd_una;
f1ecd5d9e   Damian Lukowski   Revert Backoff [v...
350
  	__u32 remaining;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
351
  	int err;
4d1a2d9ec   Damian Lukowski   Revert Backoff [v...
352
  	struct net *net = dev_net(icmp_skb->dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
353

26e373609   Eric Dumazet   ipv4: tcp: handle...
354
355
356
  	sk = __inet_lookup_established(net, &tcp_hashinfo, iph->daddr,
  				       th->dest, iph->saddr, ntohs(th->source),
  				       inet_iif(icmp_skb));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
357
  	if (!sk) {
5d3848bc3   Eric Dumazet   net: rename ICMP_...
358
  		__ICMP_INC_STATS(net, ICMP_MIB_INERRORS);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
359
360
361
  		return;
  	}
  	if (sk->sk_state == TCP_TIME_WAIT) {
9469c7b4a   YOSHIFUJI Hideaki   [NET]: Use typesa...
362
  		inet_twsk_put(inet_twsk(sk));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
363
364
  		return;
  	}
26e373609   Eric Dumazet   ipv4: tcp: handle...
365
366
  	seq = ntohl(th->seq);
  	if (sk->sk_state == TCP_NEW_SYN_RECV)
9cf749036   Eric Dumazet   tcp: do not drop ...
367
368
369
370
371
372
  		return tcp_req_err(sk, seq,
  				  type == ICMP_PARAMETERPROB ||
  				  type == ICMP_TIME_EXCEEDED ||
  				  (type == ICMP_DEST_UNREACH &&
  				   (code == ICMP_NET_UNREACH ||
  				    code == ICMP_HOST_UNREACH)));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
373
374
375
376
  
  	bh_lock_sock(sk);
  	/* If too many ICMPs get dropped on busy
  	 * servers this needs to be solved differently.
563d34d05   Eric Dumazet   tcp: dont drop MT...
377
378
  	 * We do take care of PMTU discovery (RFC1191) special case :
  	 * we can receive locally generated ICMP messages while socket is held.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
379
  	 */
b74aa930e   Eric Dumazet   tcp: fix incorrec...
380
381
  	if (sock_owned_by_user(sk)) {
  		if (!(type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED))
02a1d6e7a   Eric Dumazet   net: rename NET_{...
382
  			__NET_INC_STATS(net, LINUX_MIB_LOCKDROPPEDICMPS);
b74aa930e   Eric Dumazet   tcp: fix incorrec...
383
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
384
385
  	if (sk->sk_state == TCP_CLOSE)
  		goto out;
97e3ecd11   stephen hemminger   TCP: check min TT...
386
  	if (unlikely(iph->ttl < inet_sk(sk)->min_ttl)) {
02a1d6e7a   Eric Dumazet   net: rename NET_{...
387
  		__NET_INC_STATS(net, LINUX_MIB_TCPMINTTLDROP);
97e3ecd11   stephen hemminger   TCP: check min TT...
388
389
  		goto out;
  	}
f1ecd5d9e   Damian Lukowski   Revert Backoff [v...
390
  	icsk = inet_csk(sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
391
  	tp = tcp_sk(sk);
0a672f741   Yuchung Cheng   tcp: improve fast...
392
393
394
  	/* XXX (TFO) - tp->snd_una should be ISN (tcp_create_openreq_child() */
  	fastopen = tp->fastopen_rsk;
  	snd_una = fastopen ? tcp_rsk(fastopen)->snt_isn : tp->snd_una;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
395
  	if (sk->sk_state != TCP_LISTEN &&
0a672f741   Yuchung Cheng   tcp: improve fast...
396
  	    !between(seq, snd_una, tp->snd_nxt)) {
02a1d6e7a   Eric Dumazet   net: rename NET_{...
397
  		__NET_INC_STATS(net, LINUX_MIB_OUTOFWINDOWICMPS);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
398
399
400
401
  		goto out;
  	}
  
  	switch (type) {
55be7a9c6   David S. Miller   ipv4: Add redirec...
402
403
404
  	case ICMP_REDIRECT:
  		do_redirect(icmp_skb, sk);
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
405
406
407
408
409
410
411
412
413
414
415
  	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) */
0d4f06086   Eric Dumazet   tcp: dont handle ...
416
417
418
419
420
421
  			/* 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)
  				goto out;
563d34d05   Eric Dumazet   tcp: dont drop MT...
422
  			tp->mtu_info = info;
144d56e91   Eric Dumazet   tcp: fix possible...
423
  			if (!sock_owned_by_user(sk)) {
563d34d05   Eric Dumazet   tcp: dont drop MT...
424
  				tcp_v4_mtu_reduced(sk);
144d56e91   Eric Dumazet   tcp: fix possible...
425
426
427
428
  			} else {
  				if (!test_and_set_bit(TCP_MTU_REDUCED_DEFERRED, &tp->tsq_flags))
  					sock_hold(sk);
  			}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
429
430
431
432
  			goto out;
  		}
  
  		err = icmp_err_convert[code].errno;
f1ecd5d9e   Damian Lukowski   Revert Backoff [v...
433
434
435
436
437
  		/* 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 ||
0a672f741   Yuchung Cheng   tcp: improve fast...
438
  		    !icsk->icsk_backoff || fastopen)
f1ecd5d9e   Damian Lukowski   Revert Backoff [v...
439
  			break;
8f49c2703   David S. Miller   tcp: Don't change...
440
441
  		if (sock_owned_by_user(sk))
  			break;
f1ecd5d9e   Damian Lukowski   Revert Backoff [v...
442
  		icsk->icsk_backoff--;
fcdd1cf4d   Eric Dumazet   tcp: avoid possib...
443
444
445
  		icsk->icsk_rto = tp->srtt_us ? __tcp_set_rto(tp) :
  					       TCP_TIMEOUT_INIT;
  		icsk->icsk_rto = inet_csk_rto_backoff(icsk, TCP_RTO_MAX);
f1ecd5d9e   Damian Lukowski   Revert Backoff [v...
446
447
448
  
  		skb = tcp_write_queue_head(sk);
  		BUG_ON(!skb);
7faee5c0d   Eric Dumazet   tcp: remove TCP_S...
449
450
451
  		remaining = icsk->icsk_rto -
  			    min(icsk->icsk_rto,
  				tcp_time_stamp - tcp_skb_timestamp(skb));
f1ecd5d9e   Damian Lukowski   Revert Backoff [v...
452
453
454
455
  
  		if (remaining) {
  			inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS,
  						  remaining, TCP_RTO_MAX);
f1ecd5d9e   Damian Lukowski   Revert Backoff [v...
456
457
458
459
460
  		} else {
  			/* RTO revert clocked out retransmission.
  			 * Will retransmit now */
  			tcp_retransmit_timer(sk);
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
461
462
463
464
465
466
467
468
469
  		break;
  	case ICMP_TIME_EXCEEDED:
  		err = EHOSTUNREACH;
  		break;
  	default:
  		goto out;
  	}
  
  	switch (sk->sk_state) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
470
  	case TCP_SYN_SENT:
0a672f741   Yuchung Cheng   tcp: improve fast...
471
472
473
474
  	case TCP_SYN_RECV:
  		/* Only in fast or simultaneous open. If a fast open socket is
  		 * is already accepted it is treated as a connected one below.
  		 */
51456b291   Ian Morris   ipv4: coding styl...
475
  		if (fastopen && !fastopen->sk)
0a672f741   Yuchung Cheng   tcp: improve fast...
476
  			break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
477
  		if (!sock_owned_by_user(sk)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
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
514
515
516
  			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);
  }
28850dc7c   Daniel Borkmann   net: tcp: move GR...
517
  void __tcp_v4_send_check(struct sk_buff *skb, __be32 saddr, __be32 daddr)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
518
  {
aa8223c7b   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
519
  	struct tcphdr *th = tcp_hdr(skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
520

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

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
541
542
543
544
545
546
547
548
549
550
551
552
  /*
   *	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.
   */
a00e74442   Eric Dumazet   tcp/dccp: constif...
553
  static void tcp_v4_send_reset(const struct sock *sk, struct sk_buff *skb)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
554
  {
cf533ea53   Eric Dumazet   tcp: add const qu...
555
  	const struct tcphdr *th = tcp_hdr(skb);
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
556
557
558
  	struct {
  		struct tcphdr th;
  #ifdef CONFIG_TCP_MD5SIG
714e85be3   Al Viro   [IPV6]: Assorted ...
559
  		__be32 opt[(TCPOLEN_MD5SIG_ALIGNED >> 2)];
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
560
561
  #endif
  	} rep;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
562
  	struct ip_reply_arg arg;
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
563
  #ifdef CONFIG_TCP_MD5SIG
e46787f0d   Florian Westphal   tcp: send_reset: ...
564
  	struct tcp_md5sig_key *key = NULL;
658ddaaf6   Shawn Lu   tcp: md5: RST: ge...
565
566
567
568
  	const __u8 *hash_location = NULL;
  	unsigned char newhash[16];
  	int genhash;
  	struct sock *sk1 = NULL;
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
569
  #endif
a86b1e301   Pavel Emelyanov   inet: prepare str...
570
  	struct net *net;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
571
572
573
574
  
  	/* Never send a reset in response to a reset. */
  	if (th->rst)
  		return;
c3658e8d0   Eric Dumazet   tcp: fix possible...
575
576
577
578
  	/* If sk not NULL, it means we did a successful lookup and incoming
  	 * route had to be correct. prequeue might have dropped our dst.
  	 */
  	if (!sk && skb_rtable(skb)->rt_type != RTN_LOCAL)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
579
580
581
  		return;
  
  	/* Swap the send and the receive. */
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
582
583
584
585
586
  	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
587
588
  
  	if (th->ack) {
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
589
  		rep.th.seq = th->ack_seq;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
590
  	} else {
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
591
592
593
  		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
594
  	}
7174259e6   Arnaldo Carvalho de Melo   [TCP_IPV4]: Codin...
595
  	memset(&arg, 0, sizeof(arg));
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
596
597
  	arg.iov[0].iov_base = (unsigned char *)&rep;
  	arg.iov[0].iov_len  = sizeof(rep.th);
0f85feae6   Eric Dumazet   tcp: fix more NUL...
598
  	net = sk ? sock_net(sk) : dev_net(skb_dst(skb)->dev);
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
599
  #ifdef CONFIG_TCP_MD5SIG
3b24d854c   Eric Dumazet   tcp/dccp: do not ...
600
  	rcu_read_lock();
658ddaaf6   Shawn Lu   tcp: md5: RST: ge...
601
  	hash_location = tcp_parse_md5sig_option(th);
271c3b9b7   Florian Westphal   tcp: honour SO_BI...
602
  	if (sk && sk_fullsock(sk)) {
e46787f0d   Florian Westphal   tcp: send_reset: ...
603
604
605
  		key = tcp_md5_do_lookup(sk, (union tcp_md5_addr *)
  					&ip_hdr(skb)->saddr, AF_INET);
  	} else if (hash_location) {
658ddaaf6   Shawn Lu   tcp: md5: RST: ge...
606
607
608
609
610
611
612
  		/*
  		 * active side is lost. Try to find listening socket through
  		 * source port, and then find md5 key through listening socket.
  		 * we are not loose security here:
  		 * Incoming packet is checked with md5 hash with finding key,
  		 * no RST generated if md5 hash doesn't match.
  		 */
a583636a8   Craig Gallek   inet: refactor in...
613
614
  		sk1 = __inet_lookup_listener(net, &tcp_hashinfo, NULL, 0,
  					     ip_hdr(skb)->saddr,
da5e36308   Tom Herbert   soreuseport: TCP/...
615
  					     th->source, ip_hdr(skb)->daddr,
658ddaaf6   Shawn Lu   tcp: md5: RST: ge...
616
617
618
  					     ntohs(th->source), inet_iif(skb));
  		/* don't send rst if it can't find key */
  		if (!sk1)
3b24d854c   Eric Dumazet   tcp/dccp: do not ...
619
  			goto out;
658ddaaf6   Shawn Lu   tcp: md5: RST: ge...
620
621
622
  		key = tcp_md5_do_lookup(sk1, (union tcp_md5_addr *)
  					&ip_hdr(skb)->saddr, AF_INET);
  		if (!key)
3b24d854c   Eric Dumazet   tcp/dccp: do not ...
623
  			goto out;
658ddaaf6   Shawn Lu   tcp: md5: RST: ge...
624

39f8e58e5   Eric Dumazet   tcp: md5: remove ...
625
  		genhash = tcp_v4_md5_hash_skb(newhash, key, NULL, skb);
658ddaaf6   Shawn Lu   tcp: md5: RST: ge...
626
  		if (genhash || memcmp(hash_location, newhash, 16) != 0)
3b24d854c   Eric Dumazet   tcp/dccp: do not ...
627
  			goto out;
658ddaaf6   Shawn Lu   tcp: md5: RST: ge...
628
  	}
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
629
630
631
632
633
634
635
636
  	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...
637
  		tcp_v4_md5_hash_hdr((__u8 *) &rep.opt[1],
78e645cb8   Ilpo Järvinen   tcpv[46]: fix md5...
638
639
  				     key, ip_hdr(skb)->saddr,
  				     ip_hdr(skb)->daddr, &rep.th);
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
640
641
  	}
  #endif
eddc9ec53   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
642
643
  	arg.csum = csum_tcpudp_nofold(ip_hdr(skb)->daddr,
  				      ip_hdr(skb)->saddr, /* XXX */
52cd5750e   Ilpo Järvinen   tcp: fix length u...
644
  				      arg.iov[0].iov_len, IPPROTO_TCP, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
645
  	arg.csumoffset = offsetof(struct tcphdr, check) / 2;
271c3b9b7   Florian Westphal   tcp: honour SO_BI...
646
  	arg.flags = (sk && inet_sk_transparent(sk)) ? IP_REPLY_ARG_NOSRCCHECK : 0;
e2446eaab   Shawn Lu   tcp_v4_send_reset...
647
  	/* When socket is gone, all binding information is lost.
4c6752584   Alexey Kuznetsov   tcp: resets are m...
648
649
  	 * routing might fail in this case. No choice here, if we choose to force
  	 * input interface, we will misroute in case of asymmetric route.
e2446eaab   Shawn Lu   tcp_v4_send_reset...
650
  	 */
4c6752584   Alexey Kuznetsov   tcp: resets are m...
651
652
  	if (sk)
  		arg.bound_dev_if = sk->sk_bound_dev_if;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
653

271c3b9b7   Florian Westphal   tcp: honour SO_BI...
654
655
  	BUILD_BUG_ON(offsetof(struct sock, sk_bound_dev_if) !=
  		     offsetof(struct inet_timewait_sock, tw_bound_dev_if));
66b13d99d   Eric Dumazet   ipv4: tcp: fix TO...
656
  	arg.tos = ip_hdr(skb)->tos;
47dcc20a3   Eric Dumazet   ipv4: tcp: ip_sen...
657
  	local_bh_disable();
bdbbb8527   Eric Dumazet   ipv4: tcp: get ri...
658
659
  	ip_send_unicast_reply(*this_cpu_ptr(net->ipv4.tcp_sk),
  			      skb, &TCP_SKB_CB(skb)->header.h4.opt,
24a2d43d8   Eric Dumazet   ipv4: rename ip_o...
660
661
  			      ip_hdr(skb)->saddr, ip_hdr(skb)->daddr,
  			      &arg, arg.iov[0].iov_len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
662

90bbcc608   Eric Dumazet   net: tcp: rename ...
663
664
  	__TCP_INC_STATS(net, TCP_MIB_OUTSEGS);
  	__TCP_INC_STATS(net, TCP_MIB_OUTRSTS);
47dcc20a3   Eric Dumazet   ipv4: tcp: ip_sen...
665
  	local_bh_enable();
658ddaaf6   Shawn Lu   tcp: md5: RST: ge...
666
667
  
  #ifdef CONFIG_TCP_MD5SIG
3b24d854c   Eric Dumazet   tcp/dccp: do not ...
668
669
  out:
  	rcu_read_unlock();
658ddaaf6   Shawn Lu   tcp: md5: RST: ge...
670
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
671
672
673
674
675
  }
  
  /* The code following below sending ACKs in SYN-RECV and TIME-WAIT states
     outside socket context is ugly, certainly. What can I do?
   */
e62a123b8   Eric Dumazet   tcp: fix NULL der...
676
677
  static void tcp_v4_send_ack(struct net *net,
  			    struct sk_buff *skb, u32 seq, u32 ack,
ee684b6f2   Andrey Vagin   tcp: send packets...
678
  			    u32 win, u32 tsval, u32 tsecr, int oif,
88ef4a5a7   KOVACS Krisztian   tcp: Handle TCP S...
679
  			    struct tcp_md5sig_key *key,
66b13d99d   Eric Dumazet   ipv4: tcp: fix TO...
680
  			    int reply_flags, u8 tos)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
681
  {
cf533ea53   Eric Dumazet   tcp: add const qu...
682
  	const struct tcphdr *th = tcp_hdr(skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
683
684
  	struct {
  		struct tcphdr th;
714e85be3   Al Viro   [IPV6]: Assorted ...
685
  		__be32 opt[(TCPOLEN_TSTAMP_ALIGNED >> 2)
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
686
  #ifdef CONFIG_TCP_MD5SIG
714e85be3   Al Viro   [IPV6]: Assorted ...
687
  			   + (TCPOLEN_MD5SIG_ALIGNED >> 2)
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
688
689
  #endif
  			];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
690
691
692
693
  	} rep;
  	struct ip_reply_arg arg;
  
  	memset(&rep.th, 0, sizeof(struct tcphdr));
7174259e6   Arnaldo Carvalho de Melo   [TCP_IPV4]: Codin...
694
  	memset(&arg, 0, sizeof(arg));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
695
696
697
  
  	arg.iov[0].iov_base = (unsigned char *)&rep;
  	arg.iov[0].iov_len  = sizeof(rep.th);
ee684b6f2   Andrey Vagin   tcp: send packets...
698
  	if (tsecr) {
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
699
700
701
  		rep.opt[0] = htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) |
  				   (TCPOPT_TIMESTAMP << 8) |
  				   TCPOLEN_TIMESTAMP);
ee684b6f2   Andrey Vagin   tcp: send packets...
702
703
  		rep.opt[1] = htonl(tsval);
  		rep.opt[2] = htonl(tsecr);
cb48cfe80   Craig Schlenter   [TCP]: Fix iov_le...
704
  		arg.iov[0].iov_len += TCPOLEN_TSTAMP_ALIGNED;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
705
706
707
708
709
710
711
712
713
714
  	}
  
  	/* 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...
715
  #ifdef CONFIG_TCP_MD5SIG
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
716
  	if (key) {
ee684b6f2   Andrey Vagin   tcp: send packets...
717
  		int offset = (tsecr) ? 3 : 0;
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
718
719
720
721
722
723
724
  
  		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...
725
  		tcp_v4_md5_hash_hdr((__u8 *) &rep.opt[offset],
90b7e1120   Adam Langley   tcp: MD5: Fix MD5...
726
727
  				    key, ip_hdr(skb)->saddr,
  				    ip_hdr(skb)->daddr, &rep.th);
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
728
729
  	}
  #endif
88ef4a5a7   KOVACS Krisztian   tcp: Handle TCP S...
730
  	arg.flags = reply_flags;
eddc9ec53   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
731
732
  	arg.csum = csum_tcpudp_nofold(ip_hdr(skb)->daddr,
  				      ip_hdr(skb)->saddr, /* XXX */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
733
734
  				      arg.iov[0].iov_len, IPPROTO_TCP, 0);
  	arg.csumoffset = offsetof(struct tcphdr, check) / 2;
9501f9722   YOSHIFUJI Hideaki   tcp md5sig: Let t...
735
736
  	if (oif)
  		arg.bound_dev_if = oif;
66b13d99d   Eric Dumazet   ipv4: tcp: fix TO...
737
  	arg.tos = tos;
47dcc20a3   Eric Dumazet   ipv4: tcp: ip_sen...
738
  	local_bh_disable();
bdbbb8527   Eric Dumazet   ipv4: tcp: get ri...
739
740
  	ip_send_unicast_reply(*this_cpu_ptr(net->ipv4.tcp_sk),
  			      skb, &TCP_SKB_CB(skb)->header.h4.opt,
24a2d43d8   Eric Dumazet   ipv4: rename ip_o...
741
742
  			      ip_hdr(skb)->saddr, ip_hdr(skb)->daddr,
  			      &arg, arg.iov[0].iov_len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
743

90bbcc608   Eric Dumazet   net: tcp: rename ...
744
  	__TCP_INC_STATS(net, TCP_MIB_OUTSEGS);
47dcc20a3   Eric Dumazet   ipv4: tcp: ip_sen...
745
  	local_bh_enable();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
746
747
748
749
  }
  
  static void tcp_v4_timewait_ack(struct sock *sk, struct sk_buff *skb)
  {
8feaf0c0a   Arnaldo Carvalho de Melo   [INET]: Generalis...
750
  	struct inet_timewait_sock *tw = inet_twsk(sk);
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
751
  	struct tcp_timewait_sock *tcptw = tcp_twsk(sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
752

e62a123b8   Eric Dumazet   tcp: fix NULL der...
753
754
  	tcp_v4_send_ack(sock_net(sk), skb,
  			tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt,
7174259e6   Arnaldo Carvalho de Melo   [TCP_IPV4]: Codin...
755
  			tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale,
ee684b6f2   Andrey Vagin   tcp: send packets...
756
  			tcp_time_stamp + tcptw->tw_ts_offset,
9501f9722   YOSHIFUJI Hideaki   tcp md5sig: Let t...
757
758
  			tcptw->tw_ts_recent,
  			tw->tw_bound_dev_if,
88ef4a5a7   KOVACS Krisztian   tcp: Handle TCP S...
759
  			tcp_twsk_md5_key(tcptw),
66b13d99d   Eric Dumazet   ipv4: tcp: fix TO...
760
761
  			tw->tw_transparent ? IP_REPLY_ARG_NOSRCCHECK : 0,
  			tw->tw_tos
9501f9722   YOSHIFUJI Hideaki   tcp md5sig: Let t...
762
  			);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
763

8feaf0c0a   Arnaldo Carvalho de Melo   [INET]: Generalis...
764
  	inet_twsk_put(tw);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
765
  }
a00e74442   Eric Dumazet   tcp/dccp: constif...
766
  static void tcp_v4_reqsk_send_ack(const struct sock *sk, struct sk_buff *skb,
7174259e6   Arnaldo Carvalho de Melo   [TCP_IPV4]: Codin...
767
  				  struct request_sock *req)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
768
  {
168a8f580   Jerry Chu   tcp: TCP Fast Ope...
769
770
771
  	/* sk->sk_state == TCP_LISTEN -> for regular TCP_SYN_RECV
  	 * sk->sk_state == TCP_SYN_RECV -> for Fast Open.
  	 */
e62a123b8   Eric Dumazet   tcp: fix NULL der...
772
773
  	u32 seq = (sk->sk_state == TCP_LISTEN) ? tcp_rsk(req)->snt_isn + 1 :
  					     tcp_sk(sk)->snd_nxt;
20a2b49fc   Eric Dumazet   tcp: properly sca...
774
775
776
777
778
  	/* RFC 7323 2.3
  	 * The window field (SEG.WND) of every outgoing segment, with the
  	 * exception of <SYN> segments, MUST be right-shifted by
  	 * Rcv.Wind.Shift bits:
  	 */
e62a123b8   Eric Dumazet   tcp: fix NULL der...
779
  	tcp_v4_send_ack(sock_net(sk), skb, seq,
20a2b49fc   Eric Dumazet   tcp: properly sca...
780
781
  			tcp_rsk(req)->rcv_nxt,
  			req->rsk_rcv_wnd >> inet_rsk(req)->rcv_wscale,
ee684b6f2   Andrey Vagin   tcp: send packets...
782
  			tcp_time_stamp,
9501f9722   YOSHIFUJI Hideaki   tcp md5sig: Let t...
783
784
  			req->ts_recent,
  			0,
a915da9b6   Eric Dumazet   tcp: md5: rcu con...
785
786
  			tcp_md5_do_lookup(sk, (union tcp_md5_addr *)&ip_hdr(skb)->daddr,
  					  AF_INET),
66b13d99d   Eric Dumazet   ipv4: tcp: fix TO...
787
788
  			inet_rsk(req)->no_srccheck ? IP_REPLY_ARG_NOSRCCHECK : 0,
  			ip_hdr(skb)->tos);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
789
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
790
  /*
9bf1d83e7   Kris Katterjohn   [TCP]: Fix tcp_v4...
791
   *	Send a SYN-ACK after having received a SYN.
60236fdd0   Arnaldo Carvalho de Melo   [NET] Rename open...
792
   *	This still operates on a request_sock only, not on a big
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
793
794
   *	socket.
   */
0f935dbed   Eric Dumazet   tcp: constify tcp...
795
  static int tcp_v4_send_synack(const struct sock *sk, struct dst_entry *dst,
d6274bd8d   Octavian Purdila   tcp: add send_syn...
796
  			      struct flowi *fl,
72659ecce   Octavian Purdila   tcp: account SYN-...
797
  			      struct request_sock *req,
ca6fb0651   Eric Dumazet   tcp: attach SYNAC...
798
  			      struct tcp_fastopen_cookie *foc,
b3d051477   Eric Dumazet   tcp: do not mess ...
799
  			      enum tcp_synack_type synack_type)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
800
  {
2e6599cb8   Arnaldo Carvalho de Melo   [NET] Generalise ...
801
  	const struct inet_request_sock *ireq = inet_rsk(req);
6bd023f3d   David S. Miller   ipv4: Make caller...
802
  	struct flowi4 fl4;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
803
  	int err = -1;
d41db5af2   Weilong Chen   ipv4: fix checkpa...
804
  	struct sk_buff *skb;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
805
806
  
  	/* First, grab a route. */
ba3f7f04e   David S. Miller   ipv4: Kill FLOWI_...
807
  	if (!dst && (dst = inet_csk_route_req(sk, &fl4, req)) == NULL)
fd80eb942   Denis V. Lunev   [INET]: Remove st...
808
  		return -1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
809

b3d051477   Eric Dumazet   tcp: do not mess ...
810
  	skb = tcp_make_synack(sk, dst, req, foc, synack_type);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
811
812
  
  	if (skb) {
634fb979e   Eric Dumazet   inet: includes a ...
813
  		__tcp_v4_send_check(skb, ireq->ir_loc_addr, ireq->ir_rmt_addr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
814

634fb979e   Eric Dumazet   inet: includes a ...
815
816
  		err = ip_build_and_send_pkt(skb, sk, ireq->ir_loc_addr,
  					    ireq->ir_rmt_addr,
2e6599cb8   Arnaldo Carvalho de Melo   [NET] Generalise ...
817
  					    ireq->opt);
b9df3cb8c   Gerrit Renker   [TCP/DCCP]: Intro...
818
  		err = net_xmit_eval(err);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
819
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
820
821
822
823
  	return err;
  }
  
  /*
60236fdd0   Arnaldo Carvalho de Melo   [NET] Rename open...
824
   *	IPv4 request_sock destructor.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
825
   */
60236fdd0   Arnaldo Carvalho de Melo   [NET] Rename open...
826
  static void tcp_v4_reqsk_destructor(struct request_sock *req)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
827
  {
a51482bde   Jesper Juhl   [NET]: kfree cleanup
828
  	kfree(inet_rsk(req)->opt);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
829
  }
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.  */
b83e3deb9   Eric Dumazet   tcp: md5: constif...
838
  struct tcp_md5sig_key *tcp_md5_do_lookup(const struct sock *sk,
a915da9b6   Eric Dumazet   tcp: md5: rcu con...
839
840
  					 const union tcp_md5_addr *addr,
  					 int family)
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
841
  {
fd3a154a0   Eric Dumazet   tcp: md5: get rid...
842
  	const struct tcp_sock *tp = tcp_sk(sk);
a915da9b6   Eric Dumazet   tcp: md5: rcu con...
843
  	struct tcp_md5sig_key *key;
a915da9b6   Eric Dumazet   tcp: md5: rcu con...
844
  	unsigned int size = sizeof(struct in_addr);
fd3a154a0   Eric Dumazet   tcp: md5: get rid...
845
  	const struct tcp_md5sig_info *md5sig;
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
846

a8afca032   Eric Dumazet   tcp: md5: protect...
847
848
  	/* caller either holds rcu_read_lock() or socket lock */
  	md5sig = rcu_dereference_check(tp->md5sig_info,
1e1d04e67   Hannes Frederic Sowa   net: introduce lo...
849
  				       lockdep_sock_is_held(sk));
a8afca032   Eric Dumazet   tcp: md5: protect...
850
  	if (!md5sig)
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
851
  		return NULL;
a915da9b6   Eric Dumazet   tcp: md5: rcu con...
852
853
854
855
  #if IS_ENABLED(CONFIG_IPV6)
  	if (family == AF_INET6)
  		size = sizeof(struct in6_addr);
  #endif
b67bfe0d4   Sasha Levin   hlist: drop the n...
856
  	hlist_for_each_entry_rcu(key, &md5sig->head, node) {
a915da9b6   Eric Dumazet   tcp: md5: rcu con...
857
858
859
860
  		if (key->family != family)
  			continue;
  		if (!memcmp(&key->addr, addr, size))
  			return key;
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
861
862
863
  	}
  	return NULL;
  }
a915da9b6   Eric Dumazet   tcp: md5: rcu con...
864
  EXPORT_SYMBOL(tcp_md5_do_lookup);
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
865

b83e3deb9   Eric Dumazet   tcp: md5: constif...
866
  struct tcp_md5sig_key *tcp_v4_md5_lookup(const struct sock *sk,
fd3a154a0   Eric Dumazet   tcp: md5: get rid...
867
  					 const struct sock *addr_sk)
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
868
  {
b52e69217   Eric Dumazet   tcp: md5: fix a t...
869
  	const union tcp_md5_addr *addr;
a915da9b6   Eric Dumazet   tcp: md5: rcu con...
870

b52e69217   Eric Dumazet   tcp: md5: fix a t...
871
  	addr = (const union tcp_md5_addr *)&addr_sk->sk_daddr;
a915da9b6   Eric Dumazet   tcp: md5: rcu con...
872
  	return tcp_md5_do_lookup(sk, addr, AF_INET);
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
873
  }
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
874
  EXPORT_SYMBOL(tcp_v4_md5_lookup);
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
875
  /* This can be called on a newly created socket, from other files */
a915da9b6   Eric Dumazet   tcp: md5: rcu con...
876
877
  int tcp_md5_do_add(struct sock *sk, const union tcp_md5_addr *addr,
  		   int family, const u8 *newkey, u8 newkeylen, gfp_t gfp)
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
878
879
  {
  	/* Add Key to the list */
b0a713e9e   Matthias M. Dellweg   [TCP] MD5: Remove...
880
  	struct tcp_md5sig_key *key;
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
881
  	struct tcp_sock *tp = tcp_sk(sk);
a915da9b6   Eric Dumazet   tcp: md5: rcu con...
882
  	struct tcp_md5sig_info *md5sig;
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
883

c0353c7b5   Aydin Arik   ipv4: Fixed MD5 k...
884
  	key = tcp_md5_do_lookup(sk, addr, family);
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
885
886
  	if (key) {
  		/* Pre-existing entry - just update that one. */
a915da9b6   Eric Dumazet   tcp: md5: rcu con...
887
  		memcpy(key->key, newkey, newkeylen);
b0a713e9e   Matthias M. Dellweg   [TCP] MD5: Remove...
888
  		key->keylen = newkeylen;
a915da9b6   Eric Dumazet   tcp: md5: rcu con...
889
890
  		return 0;
  	}
260fcbeb1   Yan, Zheng   tcp: properly han...
891

a8afca032   Eric Dumazet   tcp: md5: protect...
892
  	md5sig = rcu_dereference_protected(tp->md5sig_info,
1e1d04e67   Hannes Frederic Sowa   net: introduce lo...
893
  					   lockdep_sock_is_held(sk));
a915da9b6   Eric Dumazet   tcp: md5: rcu con...
894
895
896
  	if (!md5sig) {
  		md5sig = kmalloc(sizeof(*md5sig), gfp);
  		if (!md5sig)
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
897
  			return -ENOMEM;
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
898

a915da9b6   Eric Dumazet   tcp: md5: rcu con...
899
900
  		sk_nocaps_add(sk, NETIF_F_GSO_MASK);
  		INIT_HLIST_HEAD(&md5sig->head);
a8afca032   Eric Dumazet   tcp: md5: protect...
901
  		rcu_assign_pointer(tp->md5sig_info, md5sig);
a915da9b6   Eric Dumazet   tcp: md5: rcu con...
902
  	}
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
903

5f3d9cb29   Eric Dumazet   tcp: md5: use soc...
904
  	key = sock_kmalloc(sk, sizeof(*key), gfp);
a915da9b6   Eric Dumazet   tcp: md5: rcu con...
905
906
  	if (!key)
  		return -ENOMEM;
71cea17ed   Eric Dumazet   tcp: md5: remove ...
907
  	if (!tcp_alloc_md5sig_pool()) {
5f3d9cb29   Eric Dumazet   tcp: md5: use soc...
908
  		sock_kfree_s(sk, key, sizeof(*key));
a915da9b6   Eric Dumazet   tcp: md5: rcu con...
909
  		return -ENOMEM;
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
910
  	}
a915da9b6   Eric Dumazet   tcp: md5: rcu con...
911
912
913
914
915
916
917
918
  
  	memcpy(key->key, newkey, newkeylen);
  	key->keylen = newkeylen;
  	key->family = family;
  	memcpy(&key->addr, addr,
  	       (family == AF_INET6) ? sizeof(struct in6_addr) :
  				      sizeof(struct in_addr));
  	hlist_add_head_rcu(&key->node, &md5sig->head);
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
919
920
  	return 0;
  }
a915da9b6   Eric Dumazet   tcp: md5: rcu con...
921
  EXPORT_SYMBOL(tcp_md5_do_add);
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
922

a915da9b6   Eric Dumazet   tcp: md5: rcu con...
923
  int tcp_md5_do_del(struct sock *sk, const union tcp_md5_addr *addr, int family)
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
924
  {
a915da9b6   Eric Dumazet   tcp: md5: rcu con...
925
  	struct tcp_md5sig_key *key;
c0353c7b5   Aydin Arik   ipv4: Fixed MD5 k...
926
  	key = tcp_md5_do_lookup(sk, addr, family);
a915da9b6   Eric Dumazet   tcp: md5: rcu con...
927
928
929
  	if (!key)
  		return -ENOENT;
  	hlist_del_rcu(&key->node);
5f3d9cb29   Eric Dumazet   tcp: md5: use soc...
930
  	atomic_sub(sizeof(*key), &sk->sk_omem_alloc);
a915da9b6   Eric Dumazet   tcp: md5: rcu con...
931
  	kfree_rcu(key, rcu);
a915da9b6   Eric Dumazet   tcp: md5: rcu con...
932
  	return 0;
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
933
  }
a915da9b6   Eric Dumazet   tcp: md5: rcu con...
934
  EXPORT_SYMBOL(tcp_md5_do_del);
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
935

e0683e707   stephen hemminger   tcp: make tcp_cle...
936
  static void tcp_clear_md5_list(struct sock *sk)
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
937
938
  {
  	struct tcp_sock *tp = tcp_sk(sk);
a915da9b6   Eric Dumazet   tcp: md5: rcu con...
939
  	struct tcp_md5sig_key *key;
b67bfe0d4   Sasha Levin   hlist: drop the n...
940
  	struct hlist_node *n;
a8afca032   Eric Dumazet   tcp: md5: protect...
941
  	struct tcp_md5sig_info *md5sig;
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
942

a8afca032   Eric Dumazet   tcp: md5: protect...
943
  	md5sig = rcu_dereference_protected(tp->md5sig_info, 1);
b67bfe0d4   Sasha Levin   hlist: drop the n...
944
  	hlist_for_each_entry_safe(key, n, &md5sig->head, node) {
a915da9b6   Eric Dumazet   tcp: md5: rcu con...
945
  		hlist_del_rcu(&key->node);
5f3d9cb29   Eric Dumazet   tcp: md5: use soc...
946
  		atomic_sub(sizeof(*key), &sk->sk_omem_alloc);
a915da9b6   Eric Dumazet   tcp: md5: rcu con...
947
  		kfree_rcu(key, rcu);
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
948
949
  	}
  }
7174259e6   Arnaldo Carvalho de Melo   [TCP_IPV4]: Codin...
950
951
  static int tcp_v4_parse_md5_keys(struct sock *sk, char __user *optval,
  				 int optlen)
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
952
953
954
  {
  	struct tcp_md5sig cmd;
  	struct sockaddr_in *sin = (struct sockaddr_in *)&cmd.tcpm_addr;
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
955
956
957
  
  	if (optlen < sizeof(cmd))
  		return -EINVAL;
7174259e6   Arnaldo Carvalho de Melo   [TCP_IPV4]: Codin...
958
  	if (copy_from_user(&cmd, optval, sizeof(cmd)))
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
959
960
961
962
  		return -EFAULT;
  
  	if (sin->sin_family != AF_INET)
  		return -EINVAL;
64a124edc   Dmitry Popov   tcp: md5: remove ...
963
  	if (!cmd.tcpm_keylen)
a915da9b6   Eric Dumazet   tcp: md5: rcu con...
964
965
  		return tcp_md5_do_del(sk, (union tcp_md5_addr *)&sin->sin_addr.s_addr,
  				      AF_INET);
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
966
967
968
  
  	if (cmd.tcpm_keylen > TCP_MD5SIG_MAXKEYLEN)
  		return -EINVAL;
a915da9b6   Eric Dumazet   tcp: md5: rcu con...
969
970
971
  	return tcp_md5_do_add(sk, (union tcp_md5_addr *)&sin->sin_addr.s_addr,
  			      AF_INET, cmd.tcpm_key, cmd.tcpm_keylen,
  			      GFP_KERNEL);
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
972
  }
19689e38e   Eric Dumazet   tcp: md5: use kma...
973
974
975
  static int tcp_v4_md5_hash_headers(struct tcp_md5sig_pool *hp,
  				   __be32 daddr, __be32 saddr,
  				   const struct tcphdr *th, int nbytes)
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
976
  {
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
977
  	struct tcp4_pseudohdr *bp;
49a72dfb8   Adam Langley   tcp: Fix MD5 sign...
978
  	struct scatterlist sg;
19689e38e   Eric Dumazet   tcp: md5: use kma...
979
  	struct tcphdr *_th;
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
980

19689e38e   Eric Dumazet   tcp: md5: use kma...
981
  	bp = hp->scratch;
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
982
983
984
  	bp->saddr = saddr;
  	bp->daddr = daddr;
  	bp->pad = 0;
076fb7223   YOSHIFUJI Hideaki   tcp md5sig: Remov...
985
  	bp->protocol = IPPROTO_TCP;
49a72dfb8   Adam Langley   tcp: Fix MD5 sign...
986
  	bp->len = cpu_to_be16(nbytes);
c7da57a18   David S. Miller   [TCP]: Fix scatte...
987

19689e38e   Eric Dumazet   tcp: md5: use kma...
988
989
990
991
992
993
994
  	_th = (struct tcphdr *)(bp + 1);
  	memcpy(_th, th, sizeof(*th));
  	_th->check = 0;
  
  	sg_init_one(&sg, bp, sizeof(*bp) + sizeof(*th));
  	ahash_request_set_crypt(hp->md5_req, &sg, NULL,
  				sizeof(*bp) + sizeof(*th));
cf80e0e47   Herbert Xu   tcp: Use ahash
995
  	return crypto_ahash_update(hp->md5_req);
49a72dfb8   Adam Langley   tcp: Fix MD5 sign...
996
  }
a915da9b6   Eric Dumazet   tcp: md5: rcu con...
997
  static int tcp_v4_md5_hash_hdr(char *md5_hash, const struct tcp_md5sig_key *key,
318cf7aaa   Eric Dumazet   tcp: md5: add mor...
998
  			       __be32 daddr, __be32 saddr, const struct tcphdr *th)
49a72dfb8   Adam Langley   tcp: Fix MD5 sign...
999
1000
  {
  	struct tcp_md5sig_pool *hp;
cf80e0e47   Herbert Xu   tcp: Use ahash
1001
  	struct ahash_request *req;
49a72dfb8   Adam Langley   tcp: Fix MD5 sign...
1002
1003
1004
1005
  
  	hp = tcp_get_md5sig_pool();
  	if (!hp)
  		goto clear_hash_noput;
cf80e0e47   Herbert Xu   tcp: Use ahash
1006
  	req = hp->md5_req;
49a72dfb8   Adam Langley   tcp: Fix MD5 sign...
1007

cf80e0e47   Herbert Xu   tcp: Use ahash
1008
  	if (crypto_ahash_init(req))
49a72dfb8   Adam Langley   tcp: Fix MD5 sign...
1009
  		goto clear_hash;
19689e38e   Eric Dumazet   tcp: md5: use kma...
1010
  	if (tcp_v4_md5_hash_headers(hp, daddr, saddr, th, th->doff << 2))
49a72dfb8   Adam Langley   tcp: Fix MD5 sign...
1011
1012
1013
  		goto clear_hash;
  	if (tcp_md5_hash_key(hp, key))
  		goto clear_hash;
cf80e0e47   Herbert Xu   tcp: Use ahash
1014
1015
  	ahash_request_set_crypt(req, NULL, md5_hash, 0);
  	if (crypto_ahash_final(req))
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1016
  		goto clear_hash;
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1017
  	tcp_put_md5sig_pool();
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1018
  	return 0;
49a72dfb8   Adam Langley   tcp: Fix MD5 sign...
1019

cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1020
1021
1022
1023
  clear_hash:
  	tcp_put_md5sig_pool();
  clear_hash_noput:
  	memset(md5_hash, 0, 16);
49a72dfb8   Adam Langley   tcp: Fix MD5 sign...
1024
  	return 1;
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1025
  }
39f8e58e5   Eric Dumazet   tcp: md5: remove ...
1026
1027
  int tcp_v4_md5_hash_skb(char *md5_hash, const struct tcp_md5sig_key *key,
  			const struct sock *sk,
318cf7aaa   Eric Dumazet   tcp: md5: add mor...
1028
  			const struct sk_buff *skb)
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1029
  {
49a72dfb8   Adam Langley   tcp: Fix MD5 sign...
1030
  	struct tcp_md5sig_pool *hp;
cf80e0e47   Herbert Xu   tcp: Use ahash
1031
  	struct ahash_request *req;
318cf7aaa   Eric Dumazet   tcp: md5: add mor...
1032
  	const struct tcphdr *th = tcp_hdr(skb);
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1033
  	__be32 saddr, daddr;
39f8e58e5   Eric Dumazet   tcp: md5: remove ...
1034
1035
1036
  	if (sk) { /* valid for establish/request sockets */
  		saddr = sk->sk_rcv_saddr;
  		daddr = sk->sk_daddr;
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1037
  	} else {
49a72dfb8   Adam Langley   tcp: Fix MD5 sign...
1038
1039
1040
  		const struct iphdr *iph = ip_hdr(skb);
  		saddr = iph->saddr;
  		daddr = iph->daddr;
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1041
  	}
49a72dfb8   Adam Langley   tcp: Fix MD5 sign...
1042
1043
1044
1045
  
  	hp = tcp_get_md5sig_pool();
  	if (!hp)
  		goto clear_hash_noput;
cf80e0e47   Herbert Xu   tcp: Use ahash
1046
  	req = hp->md5_req;
49a72dfb8   Adam Langley   tcp: Fix MD5 sign...
1047

cf80e0e47   Herbert Xu   tcp: Use ahash
1048
  	if (crypto_ahash_init(req))
49a72dfb8   Adam Langley   tcp: Fix MD5 sign...
1049
  		goto clear_hash;
19689e38e   Eric Dumazet   tcp: md5: use kma...
1050
  	if (tcp_v4_md5_hash_headers(hp, daddr, saddr, th, skb->len))
49a72dfb8   Adam Langley   tcp: Fix MD5 sign...
1051
1052
1053
1054
1055
  		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;
cf80e0e47   Herbert Xu   tcp: Use ahash
1056
1057
  	ahash_request_set_crypt(req, NULL, md5_hash, 0);
  	if (crypto_ahash_final(req))
49a72dfb8   Adam Langley   tcp: Fix MD5 sign...
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
  		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...
1068
  }
49a72dfb8   Adam Langley   tcp: Fix MD5 sign...
1069
  EXPORT_SYMBOL(tcp_v4_md5_hash_skb);
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1070

ba8e275a4   Eric Dumazet   tcp: cleanup tcp_...
1071
  #endif
ff74e23f7   Eric Dumazet   tcp: md5: input p...
1072
  /* Called with rcu_read_lock() */
ba8e275a4   Eric Dumazet   tcp: cleanup tcp_...
1073
  static bool tcp_v4_inbound_md5_hash(const struct sock *sk,
ff74e23f7   Eric Dumazet   tcp: md5: input p...
1074
  				    const struct sk_buff *skb)
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1075
  {
ba8e275a4   Eric Dumazet   tcp: cleanup tcp_...
1076
  #ifdef CONFIG_TCP_MD5SIG
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1077
1078
1079
1080
1081
1082
1083
1084
  	/*
  	 * 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...
1085
  	const __u8 *hash_location = NULL;
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1086
  	struct tcp_md5sig_key *hash_expected;
eddc9ec53   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
1087
  	const struct iphdr *iph = ip_hdr(skb);
cf533ea53   Eric Dumazet   tcp: add const qu...
1088
  	const struct tcphdr *th = tcp_hdr(skb);
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1089
  	int genhash;
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1090
  	unsigned char newhash[16];
a915da9b6   Eric Dumazet   tcp: md5: rcu con...
1091
1092
  	hash_expected = tcp_md5_do_lookup(sk, (union tcp_md5_addr *)&iph->saddr,
  					  AF_INET);
7d5d5525b   YOSHIFUJI Hideaki   tcp md5sig: Share...
1093
  	hash_location = tcp_parse_md5sig_option(th);
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1094

cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1095
1096
  	/* We've parsed the options - do we have a hash? */
  	if (!hash_expected && !hash_location)
a2a385d62   Eric Dumazet   tcp: bool convers...
1097
  		return false;
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1098
1099
  
  	if (hash_expected && !hash_location) {
c10d9310e   Eric Dumazet   tcp: do not assum...
1100
  		NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPMD5NOTFOUND);
a2a385d62   Eric Dumazet   tcp: bool convers...
1101
  		return true;
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1102
1103
1104
  	}
  
  	if (!hash_expected && hash_location) {
c10d9310e   Eric Dumazet   tcp: do not assum...
1105
  		NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPMD5UNEXPECTED);
a2a385d62   Eric Dumazet   tcp: bool convers...
1106
  		return true;
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1107
1108
1109
1110
1111
  	}
  
  	/* Okay, so this is hash_expected and hash_location -
  	 * so we need to calculate the checksum.
  	 */
49a72dfb8   Adam Langley   tcp: Fix MD5 sign...
1112
1113
  	genhash = tcp_v4_md5_hash_skb(newhash,
  				      hash_expected,
39f8e58e5   Eric Dumazet   tcp: md5: remove ...
1114
  				      NULL, skb);
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1115
1116
  
  	if (genhash || memcmp(hash_location, newhash, 16) != 0) {
72145a68e   Eric Dumazet   tcp: md5: add LIN...
1117
  		NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPMD5FAILURE);
e87cc4728   Joe Perches   net: Convert net_...
1118
1119
1120
1121
1122
1123
  		net_info_ratelimited("MD5 Hash failed for (%pI4, %d)->(%pI4, %d)%s
  ",
  				     &iph->saddr, ntohs(th->source),
  				     &iph->daddr, ntohs(th->dest),
  				     genhash ? " tcp_v4_calc_md5_hash failed"
  				     : "");
a2a385d62   Eric Dumazet   tcp: bool convers...
1124
  		return true;
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1125
  	}
a2a385d62   Eric Dumazet   tcp: bool convers...
1126
  	return false;
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1127
  #endif
ba8e275a4   Eric Dumazet   tcp: cleanup tcp_...
1128
1129
  	return false;
  }
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1130

b40cf18ef   Eric Dumazet   tcp: constify lis...
1131
1132
  static void tcp_v4_init_req(struct request_sock *req,
  			    const struct sock *sk_listener,
16bea70aa   Octavian Purdila   tcp: add init_req...
1133
1134
1135
  			    struct sk_buff *skb)
  {
  	struct inet_request_sock *ireq = inet_rsk(req);
08d2cc3b2   Eric Dumazet   inet: request soc...
1136
1137
  	sk_rcv_saddr_set(req_to_sk(req), ip_hdr(skb)->daddr);
  	sk_daddr_set(req_to_sk(req), ip_hdr(skb)->saddr);
16bea70aa   Octavian Purdila   tcp: add init_req...
1138
1139
  	ireq->opt = tcp_v4_save_options(skb);
  }
f964629e3   Eric Dumazet   tcp: constify tcp...
1140
1141
  static struct dst_entry *tcp_v4_route_req(const struct sock *sk,
  					  struct flowi *fl,
d94e0417a   Octavian Purdila   tcp: add route_re...
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
  					  const struct request_sock *req,
  					  bool *strict)
  {
  	struct dst_entry *dst = inet_csk_route_req(sk, &fl->u.ip4, req);
  
  	if (strict) {
  		if (fl->u.ip4.daddr == inet_rsk(req)->ir_rmt_addr)
  			*strict = true;
  		else
  			*strict = false;
  	}
  
  	return dst;
  }
72a3effaf   Eric Dumazet   [NET]: Size liste...
1156
  struct request_sock_ops tcp_request_sock_ops __read_mostly = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1157
  	.family		=	PF_INET,
2e6599cb8   Arnaldo Carvalho de Melo   [NET] Generalise ...
1158
  	.obj_size	=	sizeof(struct tcp_request_sock),
5db92c994   Octavian Purdila   tcp: unify tcp_v4...
1159
  	.rtx_syn_ack	=	tcp_rtx_synack,
60236fdd0   Arnaldo Carvalho de Melo   [NET] Rename open...
1160
1161
  	.send_ack	=	tcp_v4_reqsk_send_ack,
  	.destructor	=	tcp_v4_reqsk_destructor,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1162
  	.send_reset	=	tcp_v4_send_reset,
688d1945b   stephen hemminger   tcp: whitespace f...
1163
  	.syn_ack_timeout =	tcp_syn_ack_timeout,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1164
  };
b2e4b3deb   Stephen Hemminger   tcp: MD5 operatio...
1165
  static const struct tcp_request_sock_ops tcp_request_sock_ipv4_ops = {
2aec4a297   Octavian Purdila   tcp: add mss_clam...
1166
  	.mss_clamp	=	TCP_MSS_DEFAULT,
16bea70aa   Octavian Purdila   tcp: add init_req...
1167
  #ifdef CONFIG_TCP_MD5SIG
fd3a154a0   Eric Dumazet   tcp: md5: get rid...
1168
  	.req_md5_lookup	=	tcp_v4_md5_lookup,
e3afe7b75   John Dykstra   tcp: Fix MD5 sign...
1169
  	.calc_md5_hash	=	tcp_v4_md5_hash_skb,
b6332e6cf   Andrew Morton   [TCP]: Fix warnin...
1170
  #endif
16bea70aa   Octavian Purdila   tcp: add init_req...
1171
  	.init_req	=	tcp_v4_init_req,
fb7b37a7f   Octavian Purdila   tcp: add init_coo...
1172
1173
1174
  #ifdef CONFIG_SYN_COOKIES
  	.cookie_init_seq =	cookie_v4_init_sequence,
  #endif
d94e0417a   Octavian Purdila   tcp: add route_re...
1175
  	.route_req	=	tcp_v4_route_req,
936b8bdb5   Octavian Purdila   tcp: add init_seq...
1176
  	.init_seq	=	tcp_v4_init_sequence,
d6274bd8d   Octavian Purdila   tcp: add send_syn...
1177
  	.send_synack	=	tcp_v4_send_synack,
16bea70aa   Octavian Purdila   tcp: add init_req...
1178
  };
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1179

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1180
1181
  int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1182
  	/* Never answer to SYNs send to broadcast or multicast */
511c3f92a   Eric Dumazet   net: skb->rtable ...
1183
  	if (skb_rtable(skb)->rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1184
  		goto drop;
1fb6f159f   Octavian Purdila   tcp: add tcp_conn...
1185
1186
  	return tcp_conn_request(&tcp_request_sock_ops,
  				&tcp_request_sock_ipv4_ops, sk, skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1187

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1188
  drop:
9caad8641   Eric Dumazet   tcp: increment sk...
1189
  	tcp_listendrop(sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1190
1191
  	return 0;
  }
4bc2f18ba   Eric Dumazet   net/ipv4: EXPORT_...
1192
  EXPORT_SYMBOL(tcp_v4_conn_request);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1193
1194
1195
1196
1197
1198
  
  
  /*
   * The three way handshake has completed - we got a valid synack -
   * now create the new socket.
   */
0c27171e6   Eric Dumazet   tcp/dccp: constif...
1199
  struct sock *tcp_v4_syn_recv_sock(const struct sock *sk, struct sk_buff *skb,
60236fdd0   Arnaldo Carvalho de Melo   [NET] Rename open...
1200
  				  struct request_sock *req,
5e0724d02   Eric Dumazet   tcp/dccp: fix has...
1201
1202
1203
  				  struct dst_entry *dst,
  				  struct request_sock *req_unhash,
  				  bool *own_req)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1204
  {
2e6599cb8   Arnaldo Carvalho de Melo   [NET] Generalise ...
1205
  	struct inet_request_sock *ireq;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1206
1207
1208
  	struct inet_sock *newinet;
  	struct tcp_sock *newtp;
  	struct sock *newsk;
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1209
1210
1211
  #ifdef CONFIG_TCP_MD5SIG
  	struct tcp_md5sig_key *key;
  #endif
f6d8bd051   Eric Dumazet   inet: add RCU pro...
1212
  	struct ip_options_rcu *inet_opt;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1213
1214
1215
  
  	if (sk_acceptq_is_full(sk))
  		goto exit_overflow;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1216
1217
  	newsk = tcp_create_openreq_child(sk, req, skb);
  	if (!newsk)
093d28232   Balazs Scheidler   tproxy: fix hash ...
1218
  		goto exit_nonewsk;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1219

bcd761111   Herbert Xu   [NET]: Generalise...
1220
  	newsk->sk_gso_type = SKB_GSO_TCPV4;
fae6ef87f   Neal Cardwell   net: tcp: move sk...
1221
  	inet_sk_rx_dst_set(newsk, skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1222
1223
1224
  
  	newtp		      = tcp_sk(newsk);
  	newinet		      = inet_sk(newsk);
2e6599cb8   Arnaldo Carvalho de Melo   [NET] Generalise ...
1225
  	ireq		      = inet_rsk(req);
d1e559d0b   Eric Dumazet   inet: add IPv6 su...
1226
1227
  	sk_daddr_set(newsk, ireq->ir_rmt_addr);
  	sk_rcv_saddr_set(newsk, ireq->ir_loc_addr);
6dd9a14e9   David Ahern   net: Allow accept...
1228
  	newsk->sk_bound_dev_if = ireq->ir_iif;
634fb979e   Eric Dumazet   inet: includes a ...
1229
  	newinet->inet_saddr	      = ireq->ir_loc_addr;
f6d8bd051   Eric Dumazet   inet: add RCU pro...
1230
1231
  	inet_opt	      = ireq->opt;
  	rcu_assign_pointer(newinet->inet_opt, inet_opt);
2e6599cb8   Arnaldo Carvalho de Melo   [NET] Generalise ...
1232
  	ireq->opt	      = NULL;
463c84b97   Arnaldo Carvalho de Melo   [NET]: Introduce ...
1233
  	newinet->mc_index     = inet_iif(skb);
eddc9ec53   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
1234
  	newinet->mc_ttl	      = ip_hdr(skb)->ttl;
4c507d289   Jiri Benc   net: implement IP...
1235
  	newinet->rcv_tos      = ip_hdr(skb)->tos;
d83d8461f   Arnaldo Carvalho de Melo   [IP_SOCKGLUE]: Re...
1236
  	inet_csk(newsk)->icsk_ext_hdr_len = 0;
f6d8bd051   Eric Dumazet   inet: add RCU pro...
1237
1238
  	if (inet_opt)
  		inet_csk(newsk)->icsk_ext_hdr_len = inet_opt->opt.optlen;
c720c7e83   Eric Dumazet   inet: rename some...
1239
  	newinet->inet_id = newtp->write_seq ^ jiffies;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1240

dfd25ffff   Eric Dumazet   tcp: fix syncooki...
1241
1242
1243
1244
1245
1246
1247
  	if (!dst) {
  		dst = inet_csk_route_child_sock(sk, newsk, req);
  		if (!dst)
  			goto put_and_exit;
  	} else {
  		/* syncookie case : see end of cookie_v4_check() */
  	}
0e7344199   David S. Miller   ipv4: Use inet_cs...
1248
  	sk_setup_caps(newsk, dst);
81164413a   Daniel Borkmann   net: tcp: add per...
1249
  	tcp_ca_openreq_child(newsk, dst);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1250
  	tcp_sync_mss(newsk, dst_mtu(dst));
0dbaee3b3   David S. Miller   net: Abstract def...
1251
  	newtp->advmss = dst_metric_advmss(dst);
f5fff5dc8   Tom Quetchenbach   tcp: advertise MS...
1252
1253
1254
  	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
1255
  	tcp_initialize_rcv_mss(newsk);
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1256
1257
  #ifdef CONFIG_TCP_MD5SIG
  	/* Copy over the MD5 key from the original socket */
a915da9b6   Eric Dumazet   tcp: md5: rcu con...
1258
1259
  	key = tcp_md5_do_lookup(sk, (union tcp_md5_addr *)&newinet->inet_daddr,
  				AF_INET);
00db41243   Ian Morris   ipv4: coding styl...
1260
  	if (key) {
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1261
1262
1263
1264
1265
1266
  		/*
  		 * 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.
  		 */
a915da9b6   Eric Dumazet   tcp: md5: rcu con...
1267
1268
  		tcp_md5_do_add(newsk, (union tcp_md5_addr *)&newinet->inet_daddr,
  			       AF_INET, key->key, key->keylen, GFP_ATOMIC);
a465419b1   Eric Dumazet   net: Introduce sk...
1269
  		sk_nocaps_add(newsk, NETIF_F_GSO_MASK);
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1270
1271
  	}
  #endif
0e7344199   David S. Miller   ipv4: Use inet_cs...
1272
1273
  	if (__inet_inherit_port(sk, newsk) < 0)
  		goto put_and_exit;
5e0724d02   Eric Dumazet   tcp/dccp: fix has...
1274
  	*own_req = inet_ehash_nolisten(newsk, req_to_sk(req_unhash));
805c4bc05   Eric Dumazet   tcp: fix req->sav...
1275
  	if (*own_req)
49a496c97   Eric Dumazet   tcp: use correct ...
1276
  		tcp_move_syn(newtp, req);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1277
1278
1279
1280
  
  	return newsk;
  
  exit_overflow:
c10d9310e   Eric Dumazet   tcp: do not assum...
1281
  	NET_INC_STATS(sock_net(sk), LINUX_MIB_LISTENOVERFLOWS);
093d28232   Balazs Scheidler   tproxy: fix hash ...
1282
1283
  exit_nonewsk:
  	dst_release(dst);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1284
  exit:
9caad8641   Eric Dumazet   tcp: increment sk...
1285
  	tcp_listendrop(sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1286
  	return NULL;
0e7344199   David S. Miller   ipv4: Use inet_cs...
1287
  put_and_exit:
e337e24d6   Christoph Paasch   inet: Fix kmemlea...
1288
1289
  	inet_csk_prepare_forced_close(newsk);
  	tcp_done(newsk);
0e7344199   David S. Miller   ipv4: Use inet_cs...
1290
  	goto exit;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1291
  }
4bc2f18ba   Eric Dumazet   net/ipv4: EXPORT_...
1292
  EXPORT_SYMBOL(tcp_v4_syn_recv_sock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1293

079096f10   Eric Dumazet   tcp/dccp: install...
1294
  static struct sock *tcp_v4_cookie_check(struct sock *sk, struct sk_buff *skb)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1295
  {
079096f10   Eric Dumazet   tcp/dccp: install...
1296
  #ifdef CONFIG_SYN_COOKIES
52452c542   Eric Dumazet   inet: drop prev p...
1297
  	const struct tcphdr *th = tcp_hdr(skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1298

af9b47385   Florian Westphal   syncookies: avoid...
1299
  	if (!th->syn)
461b74c39   Cong Wang   ipv4: clean up co...
1300
  		sk = cookie_v4_check(sk, skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1301
1302
1303
  #endif
  	return sk;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1304
  /* The socket must have it's spinlock held when we get
e994b2f0f   Eric Dumazet   tcp: do not lock ...
1305
   * here, unless it is a TCP_LISTEN socket.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1306
1307
1308
1309
1310
1311
1312
1313
   *
   * 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...
1314
  	struct sock *rsk;
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1315

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1316
  	if (sk->sk_state == TCP_ESTABLISHED) { /* Fast path */
404e0a8b6   Eric Dumazet   net: ipv4: fix RC...
1317
  		struct dst_entry *dst = sk->sk_rx_dst;
bdeab9919   Tom Herbert   rps: Add flag to ...
1318
  		sock_rps_save_rxhash(sk, skb);
3d97379a6   Eric Dumazet   tcp: move sk_mark...
1319
  		sk_mark_napi_id(sk, skb);
404e0a8b6   Eric Dumazet   net: ipv4: fix RC...
1320
  		if (dst) {
505fbcf03   Eric Dumazet   ipv4: fix TCP ear...
1321
  			if (inet_sk(sk)->rx_dst_ifindex != skb->skb_iif ||
51456b291   Ian Morris   ipv4: coding styl...
1322
  			    !dst->ops->check(dst, 0)) {
92101b3b2   David S. Miller   ipv4: Prepare for...
1323
1324
1325
1326
  				dst_release(dst);
  				sk->sk_rx_dst = NULL;
  			}
  		}
c995ae225   Vijay Subramanian   tcp: Change retur...
1327
  		tcp_rcv_established(sk, skb, tcp_hdr(skb), skb->len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1328
1329
  		return 0;
  	}
12e25e104   Eric Dumazet   tcp: remove redun...
1330
  	if (tcp_checksum_complete(skb))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1331
1332
1333
  		goto csum_err;
  
  	if (sk->sk_state == TCP_LISTEN) {
079096f10   Eric Dumazet   tcp/dccp: install...
1334
  		struct sock *nsk = tcp_v4_cookie_check(sk, skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1335
1336
  		if (!nsk)
  			goto discard;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1337
  		if (nsk != sk) {
bdeab9919   Tom Herbert   rps: Add flag to ...
1338
  			sock_rps_save_rxhash(nsk, skb);
38cb52455   Eric Dumazet   tcp: call sk_mark...
1339
  			sk_mark_napi_id(nsk, skb);
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1340
1341
  			if (tcp_child_process(sk, nsk, skb)) {
  				rsk = nsk;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1342
  				goto reset;
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1343
  			}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1344
1345
  			return 0;
  		}
ca55158c6   Eric Dumazet   rps: tcp: fix rps...
1346
  	} else
bdeab9919   Tom Herbert   rps: Add flag to ...
1347
  		sock_rps_save_rxhash(sk, skb);
ca55158c6   Eric Dumazet   rps: tcp: fix rps...
1348

72ab4a86f   Eric Dumazet   tcp: remove tcp_r...
1349
  	if (tcp_rcv_state_process(sk, skb)) {
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1350
  		rsk = sk;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1351
  		goto reset;
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1352
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1353
1354
1355
  	return 0;
  
  reset:
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1356
  	tcp_v4_send_reset(rsk, skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
  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:
c10d9310e   Eric Dumazet   tcp: do not assum...
1367
1368
  	TCP_INC_STATS(sock_net(sk), TCP_MIB_CSUMERRORS);
  	TCP_INC_STATS(sock_net(sk), TCP_MIB_INERRS);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1369
1370
  	goto discard;
  }
4bc2f18ba   Eric Dumazet   net/ipv4: EXPORT_...
1371
  EXPORT_SYMBOL(tcp_v4_do_rcv);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1372

160eb5a6b   David S. Miller   ipv4: Kill early ...
1373
  void tcp_v4_early_demux(struct sk_buff *skb)
41063e9dd   David S. Miller   ipv4: Early TCP s...
1374
  {
41063e9dd   David S. Miller   ipv4: Early TCP s...
1375
1376
1377
  	const struct iphdr *iph;
  	const struct tcphdr *th;
  	struct sock *sk;
41063e9dd   David S. Miller   ipv4: Early TCP s...
1378

41063e9dd   David S. Miller   ipv4: Early TCP s...
1379
  	if (skb->pkt_type != PACKET_HOST)
160eb5a6b   David S. Miller   ipv4: Kill early ...
1380
  		return;
41063e9dd   David S. Miller   ipv4: Early TCP s...
1381

45f00f99d   Eric Dumazet   ipv4: tcp: clean ...
1382
  	if (!pskb_may_pull(skb, skb_transport_offset(skb) + sizeof(struct tcphdr)))
160eb5a6b   David S. Miller   ipv4: Kill early ...
1383
  		return;
41063e9dd   David S. Miller   ipv4: Early TCP s...
1384
1385
  
  	iph = ip_hdr(skb);
45f00f99d   Eric Dumazet   ipv4: tcp: clean ...
1386
  	th = tcp_hdr(skb);
41063e9dd   David S. Miller   ipv4: Early TCP s...
1387
1388
  
  	if (th->doff < sizeof(struct tcphdr) / 4)
160eb5a6b   David S. Miller   ipv4: Kill early ...
1389
  		return;
41063e9dd   David S. Miller   ipv4: Early TCP s...
1390

45f00f99d   Eric Dumazet   ipv4: tcp: clean ...
1391
  	sk = __inet_lookup_established(dev_net(skb->dev), &tcp_hashinfo,
41063e9dd   David S. Miller   ipv4: Early TCP s...
1392
  				       iph->saddr, th->source,
7011d0851   Vijay Subramanian   tcp: Fix bug in t...
1393
  				       iph->daddr, ntohs(th->dest),
9cb429d69   Eric Dumazet   tcp: early_demux ...
1394
  				       skb->skb_iif);
41063e9dd   David S. Miller   ipv4: Early TCP s...
1395
1396
1397
  	if (sk) {
  		skb->sk = sk;
  		skb->destructor = sock_edemux;
f7e4eb03f   Eric Dumazet   inet: ip early de...
1398
  		if (sk_fullsock(sk)) {
d0c294c53   Michal Kubeček   tcp: prevent fetc...
1399
  			struct dst_entry *dst = READ_ONCE(sk->sk_rx_dst);
505fbcf03   Eric Dumazet   ipv4: fix TCP ear...
1400

41063e9dd   David S. Miller   ipv4: Early TCP s...
1401
1402
  			if (dst)
  				dst = dst_check(dst, 0);
92101b3b2   David S. Miller   ipv4: Prepare for...
1403
  			if (dst &&
505fbcf03   Eric Dumazet   ipv4: fix TCP ear...
1404
  			    inet_sk(sk)->rx_dst_ifindex == skb->skb_iif)
92101b3b2   David S. Miller   ipv4: Prepare for...
1405
  				skb_dst_set_noref(skb, dst);
41063e9dd   David S. Miller   ipv4: Early TCP s...
1406
1407
  		}
  	}
41063e9dd   David S. Miller   ipv4: Early TCP s...
1408
  }
b2fb4f54e   Eric Dumazet   tcp: uninline tcp...
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
  /* Packet is added to VJ-style prequeue for processing in process
   * context, if a reader task is waiting. Apparently, this exciting
   * idea (VJ's mail "Re: query about TCP header on tcp-ip" of 07 Sep 93)
   * failed somewhere. Latency? Burstiness? Well, at least now we will
   * see, why it failed. 8)8)				  --ANK
   *
   */
  bool tcp_prequeue(struct sock *sk, struct sk_buff *skb)
  {
  	struct tcp_sock *tp = tcp_sk(sk);
  
  	if (sysctl_tcp_low_latency || !tp->ucopy.task)
  		return false;
  
  	if (skb->len <= tcp_hdrlen(skb) &&
  	    skb_queue_len(&tp->ucopy.prequeue) == 0)
  		return false;
ca777eff5   Eric Dumazet   tcp: remove dst r...
1426
1427
1428
1429
1430
1431
1432
1433
1434
  	/* Before escaping RCU protected region, we need to take care of skb
  	 * dst. Prequeue is only enabled for established sockets.
  	 * For such sockets, we might need the skb dst only to set sk->sk_rx_dst
  	 * Instead of doing full sk_rx_dst validity here, let's perform
  	 * an optimistic check.
  	 */
  	if (likely(sk->sk_rx_dst))
  		skb_dst_drop(skb);
  	else
5037e9ef9   Eric Dumazet   net: fix IP early...
1435
  		skb_dst_force_safe(skb);
ca777eff5   Eric Dumazet   tcp: remove dst r...
1436

b2fb4f54e   Eric Dumazet   tcp: uninline tcp...
1437
1438
  	__skb_queue_tail(&tp->ucopy.prequeue, skb);
  	tp->ucopy.memory += skb->truesize;
0cef6a4c3   Eric Dumazet   tcp: give prequeu...
1439
1440
  	if (skb_queue_len(&tp->ucopy.prequeue) >= 32 ||
  	    tp->ucopy.memory + atomic_read(&sk->sk_rmem_alloc) > sk->sk_rcvbuf) {
b2fb4f54e   Eric Dumazet   tcp: uninline tcp...
1441
1442
1443
  		struct sk_buff *skb1;
  
  		BUG_ON(sock_owned_by_user(sk));
0cef6a4c3   Eric Dumazet   tcp: give prequeu...
1444
1445
  		__NET_ADD_STATS(sock_net(sk), LINUX_MIB_TCPPREQUEUEDROPPED,
  				skb_queue_len(&tp->ucopy.prequeue));
b2fb4f54e   Eric Dumazet   tcp: uninline tcp...
1446

0cef6a4c3   Eric Dumazet   tcp: give prequeu...
1447
  		while ((skb1 = __skb_dequeue(&tp->ucopy.prequeue)) != NULL)
b2fb4f54e   Eric Dumazet   tcp: uninline tcp...
1448
  			sk_backlog_rcv(sk, skb1);
b2fb4f54e   Eric Dumazet   tcp: uninline tcp...
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
  
  		tp->ucopy.memory = 0;
  	} else if (skb_queue_len(&tp->ucopy.prequeue) == 1) {
  		wake_up_interruptible_sync_poll(sk_sleep(sk),
  					   POLLIN | POLLRDNORM | POLLRDBAND);
  		if (!inet_csk_ack_scheduled(sk))
  			inet_csk_reset_xmit_timer(sk, ICSK_TIME_DACK,
  						  (3 * tcp_rto_min(sk)) / 4,
  						  TCP_RTO_MAX);
  	}
  	return true;
  }
  EXPORT_SYMBOL(tcp_prequeue);
c9c332125   Eric Dumazet   tcp: add tcp_add_...
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
  bool tcp_add_backlog(struct sock *sk, struct sk_buff *skb)
  {
  	u32 limit = sk->sk_rcvbuf + sk->sk_sndbuf;
  
  	/* Only socket owner can try to collapse/prune rx queues
  	 * to reduce memory overhead, so add a little headroom here.
  	 * Few sockets backlog are possibly concurrently non empty.
  	 */
  	limit += 64*1024;
  
  	/* In case all data was pulled from skb frags (in __pskb_pull_tail()),
  	 * we can fix skb->truesize to its real value to avoid future drops.
  	 * This is valid because skb is not yet charged to the socket.
  	 * It has been noticed pure SACK packets were sometimes dropped
  	 * (if cooked by drivers without copybreak feature).
  	 */
  	if (!skb->data_len)
  		skb->truesize = SKB_TRUESIZE(skb_end_offset(skb));
  
  	if (unlikely(sk_add_backlog(sk, skb, limit))) {
  		bh_unlock_sock(sk);
  		__NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPBACKLOGDROP);
  		return true;
  	}
  	return false;
  }
  EXPORT_SYMBOL(tcp_add_backlog);
ac6e78007   Eric Dumazet   tcp: take care of...
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
  int tcp_filter(struct sock *sk, struct sk_buff *skb)
  {
  	struct tcphdr *th = (struct tcphdr *)skb->data;
  	unsigned int eaten = skb->len;
  	int err;
  
  	err = sk_filter_trim_cap(sk, skb, th->doff * 4);
  	if (!err) {
  		eaten -= skb->len;
  		TCP_SKB_CB(skb)->end_seq -= eaten;
  	}
  	return err;
  }
  EXPORT_SYMBOL(tcp_filter);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1503
1504
1505
1506
1507
1508
  /*
   *	From tcp_input.c
   */
  
  int tcp_v4_rcv(struct sk_buff *skb)
  {
3b24d854c   Eric Dumazet   tcp/dccp: do not ...
1509
  	struct net *net = dev_net(skb->dev);
eddc9ec53   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
1510
  	const struct iphdr *iph;
cf533ea53   Eric Dumazet   tcp: add const qu...
1511
  	const struct tcphdr *th;
3b24d854c   Eric Dumazet   tcp/dccp: do not ...
1512
  	bool refcounted;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1513
1514
1515
1516
1517
1518
1519
  	struct sock *sk;
  	int ret;
  
  	if (skb->pkt_type != PACKET_HOST)
  		goto discard_it;
  
  	/* Count it even if it's bad */
90bbcc608   Eric Dumazet   net: tcp: rename ...
1520
  	__TCP_INC_STATS(net, TCP_MIB_INSEGS);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1521
1522
1523
  
  	if (!pskb_may_pull(skb, sizeof(struct tcphdr)))
  		goto discard_it;
ea1627c20   Eric Dumazet   tcp: minor optimi...
1524
  	th = (const struct tcphdr *)skb->data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1525

ea1627c20   Eric Dumazet   tcp: minor optimi...
1526
  	if (unlikely(th->doff < sizeof(struct tcphdr) / 4))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1527
1528
1529
1530
1531
1532
  		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...
1533
  	 * provided case of th->doff==0 is eliminated.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1534
  	 * So, we defer the checks. */
ed70fcfce   Tom Herbert   net: Call skb_che...
1535
1536
  
  	if (skb_checksum_init(skb, IPPROTO_TCP, inet_compute_pseudo))
6a5dc9e59   Eric Dumazet   net: Add MIB coun...
1537
  		goto csum_error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1538

ea1627c20   Eric Dumazet   tcp: minor optimi...
1539
  	th = (const struct tcphdr *)skb->data;
eddc9ec53   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
1540
  	iph = ip_hdr(skb);
971f10eca   Eric Dumazet   tcp: better TCP_S...
1541
1542
1543
1544
1545
1546
  	/* This is tricky : We move IPCB at its correct location into TCP_SKB_CB()
  	 * barrier() makes sure compiler wont play fool^Waliasing games.
  	 */
  	memmove(&TCP_SKB_CB(skb)->header.h4, IPCB(skb),
  		sizeof(struct inet_skb_parm));
  	barrier();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1547
1548
1549
1550
  	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);
e11ecddf5   Eric Dumazet   tcp: use TCP_SKB_...
1551
  	TCP_SKB_CB(skb)->tcp_flags = tcp_flag_byte(th);
04317dafd   Eric Dumazet   tcp: introduce TC...
1552
  	TCP_SKB_CB(skb)->tcp_tw_isn = 0;
b82d1bb4f   Eric Dumazet   tcp: unalias tcp_...
1553
  	TCP_SKB_CB(skb)->ip_dsfield = ipv4_get_dsfield(iph);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1554
  	TCP_SKB_CB(skb)->sacked	 = 0;
4bdc3d661   Eric Dumazet   tcp/dccp: fix beh...
1555
  lookup:
a583636a8   Craig Gallek   inet: refactor in...
1556
  	sk = __inet_lookup_skb(&tcp_hashinfo, skb, __tcp_hdrlen(th), th->source,
3b24d854c   Eric Dumazet   tcp/dccp: do not ...
1557
  			       th->dest, &refcounted);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1558
1559
  	if (!sk)
  		goto no_tcp_socket;
bb134d5d9   Eric Dumazet   tcp: Fix tcp_v4_r...
1560
1561
1562
  process:
  	if (sk->sk_state == TCP_TIME_WAIT)
  		goto do_time_wait;
079096f10   Eric Dumazet   tcp/dccp: install...
1563
1564
  	if (sk->sk_state == TCP_NEW_SYN_RECV) {
  		struct request_sock *req = inet_reqsk(sk);
7716682cc   Eric Dumazet   tcp/dccp: fix ano...
1565
  		struct sock *nsk;
079096f10   Eric Dumazet   tcp/dccp: install...
1566
1567
  
  		sk = req->rsk_listener;
729235554   Eric Dumazet   tcp: md5: release...
1568
  		if (unlikely(tcp_v4_inbound_md5_hash(sk, skb))) {
e65c332de   Eric Dumazet   tcp: md5: increme...
1569
  			sk_drops_add(sk, skb);
729235554   Eric Dumazet   tcp: md5: release...
1570
1571
1572
  			reqsk_put(req);
  			goto discard_it;
  		}
7716682cc   Eric Dumazet   tcp/dccp: fix ano...
1573
  		if (unlikely(sk->sk_state != TCP_LISTEN)) {
f03f2e154   Eric Dumazet   tcp/dccp: add ine...
1574
  			inet_csk_reqsk_queue_drop_and_put(sk, req);
4bdc3d661   Eric Dumazet   tcp/dccp: fix beh...
1575
1576
  			goto lookup;
  		}
3b24d854c   Eric Dumazet   tcp/dccp: do not ...
1577
1578
1579
  		/* We own a reference on the listener, increase it again
  		 * as we might lose it too soon.
  		 */
7716682cc   Eric Dumazet   tcp/dccp: fix ano...
1580
  		sock_hold(sk);
3b24d854c   Eric Dumazet   tcp/dccp: do not ...
1581
  		refcounted = true;
7716682cc   Eric Dumazet   tcp/dccp: fix ano...
1582
  		nsk = tcp_check_req(sk, skb, req, false);
079096f10   Eric Dumazet   tcp/dccp: install...
1583
1584
  		if (!nsk) {
  			reqsk_put(req);
7716682cc   Eric Dumazet   tcp/dccp: fix ano...
1585
  			goto discard_and_relse;
079096f10   Eric Dumazet   tcp/dccp: install...
1586
1587
  		}
  		if (nsk == sk) {
079096f10   Eric Dumazet   tcp/dccp: install...
1588
1589
1590
  			reqsk_put(req);
  		} else if (tcp_child_process(sk, nsk, skb)) {
  			tcp_v4_send_reset(nsk, skb);
7716682cc   Eric Dumazet   tcp/dccp: fix ano...
1591
  			goto discard_and_relse;
079096f10   Eric Dumazet   tcp/dccp: install...
1592
  		} else {
7716682cc   Eric Dumazet   tcp/dccp: fix ano...
1593
  			sock_put(sk);
079096f10   Eric Dumazet   tcp/dccp: install...
1594
1595
1596
  			return 0;
  		}
  	}
6cce09f87   Eric Dumazet   tcp: Add SNMP cou...
1597
  	if (unlikely(iph->ttl < inet_sk(sk)->min_ttl)) {
02a1d6e7a   Eric Dumazet   net: rename NET_{...
1598
  		__NET_INC_STATS(net, LINUX_MIB_TCPMINTTLDROP);
d218d1113   Stephen Hemminger   tcp: Generalized ...
1599
  		goto discard_and_relse;
6cce09f87   Eric Dumazet   tcp: Add SNMP cou...
1600
  	}
d218d1113   Stephen Hemminger   tcp: Generalized ...
1601

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1602
1603
  	if (!xfrm4_policy_check(sk, XFRM_POLICY_IN, skb))
  		goto discard_and_relse;
9ea88a153   Dmitry Popov   tcp: md5: check m...
1604

9ea88a153   Dmitry Popov   tcp: md5: check m...
1605
1606
  	if (tcp_v4_inbound_md5_hash(sk, skb))
  		goto discard_and_relse;
9ea88a153   Dmitry Popov   tcp: md5: check m...
1607

b59c27010   Patrick McHardy   [NETFILTER]: Keep...
1608
  	nf_reset(skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1609

ac6e78007   Eric Dumazet   tcp: take care of...
1610
  	if (tcp_filter(sk, skb))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1611
  		goto discard_and_relse;
ac6e78007   Eric Dumazet   tcp: take care of...
1612
1613
  	th = (const struct tcphdr *)skb->data;
  	iph = ip_hdr(skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1614
1615
  
  	skb->dev = NULL;
e994b2f0f   Eric Dumazet   tcp: do not lock ...
1616
1617
1618
1619
1620
1621
  	if (sk->sk_state == TCP_LISTEN) {
  		ret = tcp_v4_do_rcv(sk, skb);
  		goto put_and_return;
  	}
  
  	sk_incoming_cpu_update(sk);
c63661848   Ingo Molnar   [PATCH] lockdep: ...
1622
  	bh_lock_sock_nested(sk);
a44d6eacd   Martin KaFai Lau   tcp: Add RFC4898 ...
1623
  	tcp_segs_in(tcp_sk(sk), skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1624
1625
  	ret = 0;
  	if (!sock_owned_by_user(sk)) {
7bced3975   Dan Williams   net_dma: simple r...
1626
  		if (!tcp_prequeue(sk, skb))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1627
  			ret = tcp_v4_do_rcv(sk, skb);
c9c332125   Eric Dumazet   tcp: add tcp_add_...
1628
  	} else if (tcp_add_backlog(sk, skb)) {
6b03a53a5   Zhu Yi   tcp: use limited ...
1629
1630
  		goto discard_and_relse;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1631
  	bh_unlock_sock(sk);
e994b2f0f   Eric Dumazet   tcp: do not lock ...
1632
  put_and_return:
3b24d854c   Eric Dumazet   tcp/dccp: do not ...
1633
1634
  	if (refcounted)
  		sock_put(sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1635
1636
1637
1638
1639
1640
  
  	return ret;
  
  no_tcp_socket:
  	if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb))
  		goto discard_it;
12e25e104   Eric Dumazet   tcp: remove redun...
1641
  	if (tcp_checksum_complete(skb)) {
6a5dc9e59   Eric Dumazet   net: Add MIB coun...
1642
  csum_error:
90bbcc608   Eric Dumazet   net: tcp: rename ...
1643
  		__TCP_INC_STATS(net, TCP_MIB_CSUMERRORS);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1644
  bad_packet:
90bbcc608   Eric Dumazet   net: tcp: rename ...
1645
  		__TCP_INC_STATS(net, TCP_MIB_INERRS);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1646
  	} else {
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1647
  		tcp_v4_send_reset(NULL, skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1648
1649
1650
1651
1652
  	}
  
  discard_it:
  	/* Discard frame. */
  	kfree_skb(skb);
e905a9eda   YOSHIFUJI Hideaki   [NET] IPV4: Fix w...
1653
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1654
1655
  
  discard_and_relse:
532182cd6   Eric Dumazet   tcp: increment sk...
1656
  	sk_drops_add(sk, skb);
3b24d854c   Eric Dumazet   tcp/dccp: do not ...
1657
1658
  	if (refcounted)
  		sock_put(sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1659
1660
1661
1662
  	goto discard_it;
  
  do_time_wait:
  	if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {
9469c7b4a   YOSHIFUJI Hideaki   [NET]: Use typesa...
1663
  		inet_twsk_put(inet_twsk(sk));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1664
1665
  		goto discard_it;
  	}
6a5dc9e59   Eric Dumazet   net: Add MIB coun...
1666
1667
1668
  	if (tcp_checksum_complete(skb)) {
  		inet_twsk_put(inet_twsk(sk));
  		goto csum_error;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1669
  	}
9469c7b4a   YOSHIFUJI Hideaki   [NET]: Use typesa...
1670
  	switch (tcp_timewait_state_process(inet_twsk(sk), skb, th)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1671
  	case TCP_TW_SYN: {
c346dca10   YOSHIFUJI Hideaki   [NET] NETNS: Omit...
1672
  		struct sock *sk2 = inet_lookup_listener(dev_net(skb->dev),
a583636a8   Craig Gallek   inet: refactor in...
1673
1674
  							&tcp_hashinfo, skb,
  							__tcp_hdrlen(th),
da5e36308   Tom Herbert   soreuseport: TCP/...
1675
  							iph->saddr, th->source,
eddc9ec53   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
1676
  							iph->daddr, th->dest,
463c84b97   Arnaldo Carvalho de Melo   [NET]: Introduce ...
1677
  							inet_iif(skb));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1678
  		if (sk2) {
dbe7faa40   Eric Dumazet   inet: inet_twsk_d...
1679
  			inet_twsk_deschedule_put(inet_twsk(sk));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1680
  			sk = sk2;
3b24d854c   Eric Dumazet   tcp/dccp: do not ...
1681
  			refcounted = false;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1682
1683
1684
1685
1686
1687
1688
1689
  			goto process;
  		}
  		/* Fall through to ACK */
  	}
  	case TCP_TW_ACK:
  		tcp_v4_timewait_ack(sk, skb);
  		break;
  	case TCP_TW_RST:
271c3b9b7   Florian Westphal   tcp: honour SO_BI...
1690
1691
1692
  		tcp_v4_send_reset(sk, skb);
  		inet_twsk_deschedule_put(inet_twsk(sk));
  		goto discard_it;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1693
1694
1695
1696
  	case TCP_TW_SUCCESS:;
  	}
  	goto discard_it;
  }
ccb7c410d   David S. Miller   timewait_sock: Cr...
1697
1698
1699
1700
  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,
ccb7c410d   David S. Miller   timewait_sock: Cr...
1701
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1702

63d02d157   Eric Dumazet   net: tcp: ipv6_ma...
1703
  void inet_sk_rx_dst_set(struct sock *sk, const struct sk_buff *skb)
5d299f3d3   Eric Dumazet   net: ipv6: fix TC...
1704
1705
  {
  	struct dst_entry *dst = skb_dst(skb);
5037e9ef9   Eric Dumazet   net: fix IP early...
1706
  	if (dst && dst_hold_safe(dst)) {
ca777eff5   Eric Dumazet   tcp: remove dst r...
1707
1708
1709
  		sk->sk_rx_dst = dst;
  		inet_sk(sk)->rx_dst_ifindex = skb->skb_iif;
  	}
5d299f3d3   Eric Dumazet   net: ipv6: fix TC...
1710
  }
63d02d157   Eric Dumazet   net: tcp: ipv6_ma...
1711
  EXPORT_SYMBOL(inet_sk_rx_dst_set);
5d299f3d3   Eric Dumazet   net: ipv6: fix TC...
1712

3b401a81c   Stephen Hemminger   inet: inet_connec...
1713
  const struct inet_connection_sock_af_ops ipv4_specific = {
543d9cfee   Arnaldo Carvalho de Melo   [NET]: Identation...
1714
1715
1716
  	.queue_xmit	   = ip_queue_xmit,
  	.send_check	   = tcp_v4_send_check,
  	.rebuild_header	   = inet_sk_rebuild_header,
5d299f3d3   Eric Dumazet   net: ipv6: fix TC...
1717
  	.sk_rx_dst_set	   = inet_sk_rx_dst_set,
543d9cfee   Arnaldo Carvalho de Melo   [NET]: Identation...
1718
1719
  	.conn_request	   = tcp_v4_conn_request,
  	.syn_recv_sock	   = tcp_v4_syn_recv_sock,
543d9cfee   Arnaldo Carvalho de Melo   [NET]: Identation...
1720
1721
1722
1723
1724
  	.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...
1725
  	.bind_conflict	   = inet_csk_bind_conflict,
3fdadf7d2   Dmitry Mishin   [NET]: {get|set}s...
1726
  #ifdef CONFIG_COMPAT
543d9cfee   Arnaldo Carvalho de Melo   [NET]: Identation...
1727
1728
  	.compat_setsockopt = compat_ip_setsockopt,
  	.compat_getsockopt = compat_ip_getsockopt,
3fdadf7d2   Dmitry Mishin   [NET]: {get|set}s...
1729
  #endif
4fab90719   Neal Cardwell   tcp: fix tcp_rele...
1730
  	.mtu_reduced	   = tcp_v4_mtu_reduced,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1731
  };
4bc2f18ba   Eric Dumazet   net/ipv4: EXPORT_...
1732
  EXPORT_SYMBOL(ipv4_specific);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1733

cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1734
  #ifdef CONFIG_TCP_MD5SIG
b2e4b3deb   Stephen Hemminger   tcp: MD5 operatio...
1735
  static const struct tcp_sock_af_ops tcp_sock_ipv4_specific = {
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1736
  	.md5_lookup		= tcp_v4_md5_lookup,
49a72dfb8   Adam Langley   tcp: Fix MD5 sign...
1737
  	.calc_md5_hash		= tcp_v4_md5_hash_skb,
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1738
  	.md5_parse		= tcp_v4_parse_md5_keys,
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1739
  };
b6332e6cf   Andrew Morton   [TCP]: Fix warnin...
1740
  #endif
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1741

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1742
1743
1744
1745
1746
  /* 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 ...
1747
  	struct inet_connection_sock *icsk = inet_csk(sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1748

900f65d36   Neal Cardwell   tcp: move duplica...
1749
  	tcp_init_sock(sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1750

8292a17a3   Arnaldo Carvalho de Melo   [ICSK]: Rename st...
1751
  	icsk->icsk_af_ops = &ipv4_specific;
900f65d36   Neal Cardwell   tcp: move duplica...
1752

cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1753
  #ifdef CONFIG_TCP_MD5SIG
ac807fa8e   David S. Miller   tcp: Fix build wa...
1754
  	tcp_sk(sk)->af_specific = &tcp_sock_ipv4_specific;
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1755
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1756

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1757
1758
  	return 0;
  }
7d06b2e05   Brian Haley   net: change proto...
1759
  void tcp_v4_destroy_sock(struct sock *sk)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1760
1761
1762
1763
  {
  	struct tcp_sock *tp = tcp_sk(sk);
  
  	tcp_clear_xmit_timers(sk);
6687e988d   Arnaldo Carvalho de Melo   [ICSK]: Move TCP ...
1764
  	tcp_cleanup_congestion_control(sk);
317a76f9a   Stephen Hemminger   [TCP]: Add plugga...
1765

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1766
  	/* Cleanup up the write buffer. */
fe067e8ab   David S. Miller   [TCP]: Abstract o...
1767
  	tcp_write_queue_purge(sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1768
1769
  
  	/* Cleans up our, hopefully empty, out_of_order_queue. */
9f5afeae5   Yaogong Wang   tcp: use an RB tr...
1770
  	skb_rbtree_purge(&tp->out_of_order_queue);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1771

cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1772
1773
1774
  #ifdef CONFIG_TCP_MD5SIG
  	/* Clean up the MD5 key list, if any */
  	if (tp->md5sig_info) {
a915da9b6   Eric Dumazet   tcp: md5: rcu con...
1775
  		tcp_clear_md5_list(sk);
a8afca032   Eric Dumazet   tcp: md5: protect...
1776
  		kfree_rcu(tp->md5sig_info, rcu);
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1777
1778
1779
  		tp->md5sig_info = NULL;
  	}
  #endif
1a2449a87   Chris Leech   [I/OAT]: TCP recv...
1780

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1781
1782
1783
1784
  	/* 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 ...
1785
  	if (inet_csk(sk)->icsk_bind_hash)
ab1e0a13d   Arnaldo Carvalho de Melo   [SOCK] proto: Add...
1786
  		inet_put_port(sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1787

00db41243   Ian Morris   ipv4: coding styl...
1788
  	BUG_ON(tp->fastopen_rsk);
435cf559f   William Allen Simpson   TCPCT part 1d: de...
1789

cf60af03c   Yuchung Cheng   net-tcp: Fast Ope...
1790
1791
  	/* If socket is aborted during connect operation */
  	tcp_free_fastopen_req(tp);
cd8ae8529   Eric Dumazet   tcp: provide SYN ...
1792
  	tcp_saved_syn_free(tp);
cf60af03c   Yuchung Cheng   net-tcp: Fast Ope...
1793

777c6ae57   Eric Dumazet   tcp: two more mis...
1794
  	local_bh_disable();
180d8cd94   Glauber Costa   foundations of pe...
1795
  	sk_sockets_allocated_dec(sk);
777c6ae57   Eric Dumazet   tcp: two more mis...
1796
  	local_bh_enable();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1797
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1798
1799
1800
1801
  EXPORT_SYMBOL(tcp_v4_destroy_sock);
  
  #ifdef CONFIG_PROC_FS
  /* Proc filesystem TCP sock list dumping. */
a8b690f98   Tom Herbert   tcp: Fix slowness...
1802
1803
1804
1805
1806
  /*
   * 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
1807
1808
  static void *listening_get_next(struct seq_file *seq, void *cur)
  {
5799de0b1   Jianjun Kong   net: clean up net...
1809
  	struct tcp_iter_state *st = seq->private;
a4146b1b2   Denis V. Lunev   [TCP]: Replace st...
1810
  	struct net *net = seq_file_net(seq);
3b24d854c   Eric Dumazet   tcp/dccp: do not ...
1811
  	struct inet_listen_hashbucket *ilb;
3b24d854c   Eric Dumazet   tcp/dccp: do not ...
1812
  	struct sock *sk = cur;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1813
1814
  
  	if (!sk) {
3b24d854c   Eric Dumazet   tcp/dccp: do not ...
1815
  get_head:
a8b690f98   Tom Herbert   tcp: Fix slowness...
1816
  		ilb = &tcp_hashinfo.listening_hash[st->bucket];
5caea4ea7   Eric Dumazet   net: listening_ha...
1817
  		spin_lock_bh(&ilb->lock);
3b24d854c   Eric Dumazet   tcp/dccp: do not ...
1818
  		sk = sk_head(&ilb->head);
a8b690f98   Tom Herbert   tcp: Fix slowness...
1819
  		st->offset = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1820
1821
  		goto get_sk;
  	}
5caea4ea7   Eric Dumazet   net: listening_ha...
1822
  	ilb = &tcp_hashinfo.listening_hash[st->bucket];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1823
  	++st->num;
a8b690f98   Tom Herbert   tcp: Fix slowness...
1824
  	++st->offset;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1825

3b24d854c   Eric Dumazet   tcp/dccp: do not ...
1826
  	sk = sk_next(sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1827
  get_sk:
3b24d854c   Eric Dumazet   tcp/dccp: do not ...
1828
  	sk_for_each_from(sk) {
8475ef9fd   Pavel Emelyanov   netns: Don't leak...
1829
1830
  		if (!net_eq(sock_net(sk), net))
  			continue;
3b24d854c   Eric Dumazet   tcp/dccp: do not ...
1831
1832
  		if (sk->sk_family == st->family)
  			return sk;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1833
  	}
5caea4ea7   Eric Dumazet   net: listening_ha...
1834
  	spin_unlock_bh(&ilb->lock);
a8b690f98   Tom Herbert   tcp: Fix slowness...
1835
  	st->offset = 0;
3b24d854c   Eric Dumazet   tcp/dccp: do not ...
1836
1837
1838
  	if (++st->bucket < INET_LHTABLE_SIZE)
  		goto get_head;
  	return NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1839
1840
1841
1842
  }
  
  static void *listening_get_idx(struct seq_file *seq, loff_t *pos)
  {
a8b690f98   Tom Herbert   tcp: Fix slowness...
1843
1844
1845
1846
1847
1848
  	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
1849
1850
1851
1852
1853
1854
1855
  
  	while (rc && *pos) {
  		rc = listening_get_next(seq, rc);
  		--*pos;
  	}
  	return rc;
  }
05dbc7b59   Eric Dumazet   tcp/dccp: remove ...
1856
  static inline bool empty_bucket(const struct tcp_iter_state *st)
6eac56040   Andi Kleen   tcp: Skip empty h...
1857
  {
05dbc7b59   Eric Dumazet   tcp/dccp: remove ...
1858
  	return hlist_nulls_empty(&tcp_hashinfo.ehash[st->bucket].chain);
6eac56040   Andi Kleen   tcp: Skip empty h...
1859
  }
a8b690f98   Tom Herbert   tcp: Fix slowness...
1860
1861
1862
1863
  /*
   * 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
1864
1865
  static void *established_get_first(struct seq_file *seq)
  {
5799de0b1   Jianjun Kong   net: clean up net...
1866
  	struct tcp_iter_state *st = seq->private;
a4146b1b2   Denis V. Lunev   [TCP]: Replace st...
1867
  	struct net *net = seq_file_net(seq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1868
  	void *rc = NULL;
a8b690f98   Tom Herbert   tcp: Fix slowness...
1869
1870
  	st->offset = 0;
  	for (; st->bucket <= tcp_hashinfo.ehash_mask; ++st->bucket) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1871
  		struct sock *sk;
3ab5aee7f   Eric Dumazet   net: Convert TCP ...
1872
  		struct hlist_nulls_node *node;
9db66bdcc   Eric Dumazet   net: convert TCP/...
1873
  		spinlock_t *lock = inet_ehash_lockp(&tcp_hashinfo, st->bucket);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1874

6eac56040   Andi Kleen   tcp: Skip empty h...
1875
1876
1877
  		/* Lockless fast path for the common case of empty buckets */
  		if (empty_bucket(st))
  			continue;
9db66bdcc   Eric Dumazet   net: convert TCP/...
1878
  		spin_lock_bh(lock);
3ab5aee7f   Eric Dumazet   net: Convert TCP ...
1879
  		sk_nulls_for_each(sk, node, &tcp_hashinfo.ehash[st->bucket].chain) {
f40c8174d   Daniel Lezcano   [NETNS][IPV4] tcp...
1880
  			if (sk->sk_family != st->family ||
878628fbf   YOSHIFUJI Hideaki   [NET] NETNS: Omit...
1881
  			    !net_eq(sock_net(sk), net)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1882
1883
1884
1885
1886
  				continue;
  			}
  			rc = sk;
  			goto out;
  		}
9db66bdcc   Eric Dumazet   net: convert TCP/...
1887
  		spin_unlock_bh(lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1888
1889
1890
1891
1892
1893
1894
1895
  	}
  out:
  	return rc;
  }
  
  static void *established_get_next(struct seq_file *seq, void *cur)
  {
  	struct sock *sk = cur;
3ab5aee7f   Eric Dumazet   net: Convert TCP ...
1896
  	struct hlist_nulls_node *node;
5799de0b1   Jianjun Kong   net: clean up net...
1897
  	struct tcp_iter_state *st = seq->private;
a4146b1b2   Denis V. Lunev   [TCP]: Replace st...
1898
  	struct net *net = seq_file_net(seq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1899
1900
  
  	++st->num;
a8b690f98   Tom Herbert   tcp: Fix slowness...
1901
  	++st->offset;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1902

05dbc7b59   Eric Dumazet   tcp/dccp: remove ...
1903
  	sk = sk_nulls_next(sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1904

3ab5aee7f   Eric Dumazet   net: Convert TCP ...
1905
  	sk_nulls_for_each_from(sk, node) {
878628fbf   YOSHIFUJI Hideaki   [NET] NETNS: Omit...
1906
  		if (sk->sk_family == st->family && net_eq(sock_net(sk), net))
05dbc7b59   Eric Dumazet   tcp/dccp: remove ...
1907
  			return sk;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1908
  	}
05dbc7b59   Eric Dumazet   tcp/dccp: remove ...
1909
1910
1911
  	spin_unlock_bh(inet_ehash_lockp(&tcp_hashinfo, st->bucket));
  	++st->bucket;
  	return established_get_first(seq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1912
1913
1914
1915
  }
  
  static void *established_get_idx(struct seq_file *seq, loff_t pos)
  {
a8b690f98   Tom Herbert   tcp: Fix slowness...
1916
1917
1918
1919
1920
  	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
1921
1922
1923
1924
  
  	while (rc && pos) {
  		rc = established_get_next(seq, rc);
  		--pos;
7174259e6   Arnaldo Carvalho de Melo   [TCP_IPV4]: Codin...
1925
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1926
1927
1928
1929
1930
1931
  	return rc;
  }
  
  static void *tcp_get_idx(struct seq_file *seq, loff_t pos)
  {
  	void *rc;
5799de0b1   Jianjun Kong   net: clean up net...
1932
  	struct tcp_iter_state *st = seq->private;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1933

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1934
1935
1936
1937
  	st->state = TCP_SEQ_STATE_LISTENING;
  	rc	  = listening_get_idx(seq, &pos);
  
  	if (!rc) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1938
1939
1940
1941
1942
1943
  		st->state = TCP_SEQ_STATE_ESTABLISHED;
  		rc	  = established_get_idx(seq, pos);
  	}
  
  	return rc;
  }
a8b690f98   Tom Herbert   tcp: Fix slowness...
1944
1945
1946
1947
1948
1949
1950
1951
  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) {
a8b690f98   Tom Herbert   tcp: Fix slowness...
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
  	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;
05dbc7b59   Eric Dumazet   tcp/dccp: remove ...
1962
  		st->state = TCP_SEQ_STATE_ESTABLISHED;
a8b690f98   Tom Herbert   tcp: Fix slowness...
1963
1964
  		/* Fallthrough */
  	case TCP_SEQ_STATE_ESTABLISHED:
a8b690f98   Tom Herbert   tcp: Fix slowness...
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
  		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
1976
1977
  static void *tcp_seq_start(struct seq_file *seq, loff_t *pos)
  {
5799de0b1   Jianjun Kong   net: clean up net...
1978
  	struct tcp_iter_state *st = seq->private;
a8b690f98   Tom Herbert   tcp: Fix slowness...
1979
1980
1981
1982
1983
1984
1985
  	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
1986
1987
  	st->state = TCP_SEQ_STATE_LISTENING;
  	st->num = 0;
a8b690f98   Tom Herbert   tcp: Fix slowness...
1988
1989
1990
1991
1992
1993
1994
  	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
1995
1996
1997
1998
  }
  
  static void *tcp_seq_next(struct seq_file *seq, void *v, loff_t *pos)
  {
a8b690f98   Tom Herbert   tcp: Fix slowness...
1999
  	struct tcp_iter_state *st = seq->private;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2000
  	void *rc = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2001
2002
2003
2004
2005
  
  	if (v == SEQ_START_TOKEN) {
  		rc = tcp_get_idx(seq, 0);
  		goto out;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2006
2007
  
  	switch (st->state) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2008
2009
2010
  	case TCP_SEQ_STATE_LISTENING:
  		rc = listening_get_next(seq, v);
  		if (!rc) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2011
  			st->state = TCP_SEQ_STATE_ESTABLISHED;
a8b690f98   Tom Herbert   tcp: Fix slowness...
2012
2013
  			st->bucket = 0;
  			st->offset = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2014
2015
2016
2017
  			rc	  = established_get_first(seq);
  		}
  		break;
  	case TCP_SEQ_STATE_ESTABLISHED:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2018
2019
2020
2021
2022
  		rc = established_get_next(seq, v);
  		break;
  	}
  out:
  	++*pos;
a8b690f98   Tom Herbert   tcp: Fix slowness...
2023
  	st->last_pos = *pos;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2024
2025
2026
2027
2028
  	return rc;
  }
  
  static void tcp_seq_stop(struct seq_file *seq, void *v)
  {
5799de0b1   Jianjun Kong   net: clean up net...
2029
  	struct tcp_iter_state *st = seq->private;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2030
2031
  
  	switch (st->state) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2032
2033
  	case TCP_SEQ_STATE_LISTENING:
  		if (v != SEQ_START_TOKEN)
5caea4ea7   Eric Dumazet   net: listening_ha...
2034
  			spin_unlock_bh(&tcp_hashinfo.listening_hash[st->bucket].lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2035
  		break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2036
2037
  	case TCP_SEQ_STATE_ESTABLISHED:
  		if (v)
9db66bdcc   Eric Dumazet   net: convert TCP/...
2038
  			spin_unlock_bh(inet_ehash_lockp(&tcp_hashinfo, st->bucket));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2039
2040
2041
  		break;
  	}
  }
73cb88ecb   Arjan van de Ven   net: make the tcp...
2042
  int tcp_seq_open(struct inode *inode, struct file *file)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2043
  {
d9dda78ba   Al Viro   procfs: new helpe...
2044
  	struct tcp_seq_afinfo *afinfo = PDE_DATA(inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2045
  	struct tcp_iter_state *s;
52d6f3f11   Denis V. Lunev   [TCP]: Cleanup /p...
2046
  	int err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2047

52d6f3f11   Denis V. Lunev   [TCP]: Cleanup /p...
2048
2049
2050
2051
  	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...
2052

52d6f3f11   Denis V. Lunev   [TCP]: Cleanup /p...
2053
  	s = ((struct seq_file *)file->private_data)->private;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2054
  	s->family		= afinfo->family;
688d1945b   stephen hemminger   tcp: whitespace f...
2055
  	s->last_pos		= 0;
f40c8174d   Daniel Lezcano   [NETNS][IPV4] tcp...
2056
2057
  	return 0;
  }
73cb88ecb   Arjan van de Ven   net: make the tcp...
2058
  EXPORT_SYMBOL(tcp_seq_open);
f40c8174d   Daniel Lezcano   [NETNS][IPV4] tcp...
2059

6f8b13bcb   Daniel Lezcano   [NETNS][IPV6] tcp...
2060
  int tcp_proc_register(struct net *net, struct tcp_seq_afinfo *afinfo)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2061
2062
2063
  {
  	int rc = 0;
  	struct proc_dir_entry *p;
9427c4b36   Denis V. Lunev   [TCP]: Move seq_o...
2064
2065
2066
  	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-...
2067
  	p = proc_create_data(afinfo->name, S_IRUGO, net->proc_net,
73cb88ecb   Arjan van de Ven   net: make the tcp...
2068
  			     afinfo->seq_fops, afinfo);
84841c3c6   Denis V. Lunev   ipv4: assign PDE-...
2069
  	if (!p)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2070
2071
2072
  		rc = -ENOMEM;
  	return rc;
  }
4bc2f18ba   Eric Dumazet   net/ipv4: EXPORT_...
2073
  EXPORT_SYMBOL(tcp_proc_register);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2074

6f8b13bcb   Daniel Lezcano   [NETNS][IPV6] tcp...
2075
  void tcp_proc_unregister(struct net *net, struct tcp_seq_afinfo *afinfo)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2076
  {
ece31ffd5   Gao feng   net: proc: change...
2077
  	remove_proc_entry(afinfo->name, net->proc_net);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2078
  }
4bc2f18ba   Eric Dumazet   net/ipv4: EXPORT_...
2079
  EXPORT_SYMBOL(tcp_proc_unregister);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2080

d4f06873b   Eric Dumazet   inet: get_openreq...
2081
  static void get_openreq4(const struct request_sock *req,
aa3a0c8ce   Eric Dumazet   tcp: get_openreq[...
2082
  			 struct seq_file *f, int i)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2083
  {
2e6599cb8   Arnaldo Carvalho de Melo   [NET] Generalise ...
2084
  	const struct inet_request_sock *ireq = inet_rsk(req);
fa76ce732   Eric Dumazet   inet: get rid of ...
2085
  	long delta = req->rsk_timer.expires - jiffies;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2086

5e659e4cb   Pavel Emelyanov   [NET]: Fix heavy ...
2087
  	seq_printf(f, "%4d: %08X:%04X %08X:%04X"
652586df9   Tetsuo Handa   seq_file: remove ...
2088
  		" %02X %08X:%08X %02X:%08lX %08X %5u %8d %u %d %pK",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2089
  		i,
634fb979e   Eric Dumazet   inet: includes a ...
2090
  		ireq->ir_loc_addr,
d4f06873b   Eric Dumazet   inet: get_openreq...
2091
  		ireq->ir_num,
634fb979e   Eric Dumazet   inet: includes a ...
2092
2093
  		ireq->ir_rmt_addr,
  		ntohs(ireq->ir_rmt_port),
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2094
2095
2096
  		TCP_SYN_RECV,
  		0, 0, /* could print option size, but that is af dependent. */
  		1,    /* timers active (only the expire timer) */
a399a8053   Eric Dumazet   time: jiffies_del...
2097
  		jiffies_delta_to_clock_t(delta),
e6c022a4f   Eric Dumazet   tcp: better retra...
2098
  		req->num_timeout,
aa3a0c8ce   Eric Dumazet   tcp: get_openreq[...
2099
2100
  		from_kuid_munged(seq_user_ns(f),
  				 sock_i_uid(req->rsk_listener)),
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2101
2102
  		0,  /* non standard timer */
  		0, /* open_requests have no inode */
d4f06873b   Eric Dumazet   inet: get_openreq...
2103
  		0,
652586df9   Tetsuo Handa   seq_file: remove ...
2104
  		req);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2105
  }
652586df9   Tetsuo Handa   seq_file: remove ...
2106
  static void get_tcp4_sock(struct sock *sk, struct seq_file *f, int i)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2107
2108
2109
  {
  	int timer_active;
  	unsigned long timer_expires;
cf533ea53   Eric Dumazet   tcp: add const qu...
2110
  	const struct tcp_sock *tp = tcp_sk(sk);
cf4c6bf83   Ilpo Järvinen   [TCP]: struct *so...
2111
  	const struct inet_connection_sock *icsk = inet_csk(sk);
cf533ea53   Eric Dumazet   tcp: add const qu...
2112
  	const struct inet_sock *inet = inet_sk(sk);
0536fcc03   Eric Dumazet   tcp: prepare fast...
2113
  	const struct fastopen_queue *fastopenq = &icsk->icsk_accept_queue.fastopenq;
c720c7e83   Eric Dumazet   inet: rename some...
2114
2115
2116
2117
  	__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...
2118
  	int rx_queue;
00fd38d93   Eric Dumazet   tcp: ensure prope...
2119
  	int state;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2120

6ba8a3b19   Nandita Dukkipati   tcp: Tail loss pr...
2121
2122
2123
  	if (icsk->icsk_pending == ICSK_TIME_RETRANS ||
  	    icsk->icsk_pending == ICSK_TIME_EARLY_RETRANS ||
  	    icsk->icsk_pending == ICSK_TIME_LOSS_PROBE) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2124
  		timer_active	= 1;
463c84b97   Arnaldo Carvalho de Melo   [NET]: Introduce ...
2125
2126
  		timer_expires	= icsk->icsk_timeout;
  	} else if (icsk->icsk_pending == ICSK_TIME_PROBE0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2127
  		timer_active	= 4;
463c84b97   Arnaldo Carvalho de Melo   [NET]: Introduce ...
2128
  		timer_expires	= icsk->icsk_timeout;
cf4c6bf83   Ilpo Järvinen   [TCP]: struct *so...
2129
  	} else if (timer_pending(&sk->sk_timer)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2130
  		timer_active	= 2;
cf4c6bf83   Ilpo Järvinen   [TCP]: struct *so...
2131
  		timer_expires	= sk->sk_timer.expires;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2132
2133
2134
2135
  	} else {
  		timer_active	= 0;
  		timer_expires = jiffies;
  	}
00fd38d93   Eric Dumazet   tcp: ensure prope...
2136
2137
  	state = sk_state_load(sk);
  	if (state == TCP_LISTEN)
49d090078   Eric Dumazet   tcp: diag: Dont r...
2138
2139
  		rx_queue = sk->sk_ack_backlog;
  	else
00fd38d93   Eric Dumazet   tcp: ensure prope...
2140
2141
  		/* Because we don't lock the socket,
  		 * we might find a transient negative value.
49d090078   Eric Dumazet   tcp: diag: Dont r...
2142
2143
  		 */
  		rx_queue = max_t(int, tp->rcv_nxt - tp->copied_seq, 0);
5e659e4cb   Pavel Emelyanov   [NET]: Fix heavy ...
2144
  	seq_printf(f, "%4d: %08X:%04X %08X:%04X %02X %08X:%08X %02X:%08lX "
652586df9   Tetsuo Handa   seq_file: remove ...
2145
  			"%08X %5u %8d %lu %d %pK %lu %lu %u %u %d",
00fd38d93   Eric Dumazet   tcp: ensure prope...
2146
  		i, src, srcp, dest, destp, state,
47da8ee68   Sridhar Samudrala   [TCP]: Export acc...
2147
  		tp->write_seq - tp->snd_una,
49d090078   Eric Dumazet   tcp: diag: Dont r...
2148
  		rx_queue,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2149
  		timer_active,
a399a8053   Eric Dumazet   time: jiffies_del...
2150
  		jiffies_delta_to_clock_t(timer_expires - jiffies),
463c84b97   Arnaldo Carvalho de Melo   [NET]: Introduce ...
2151
  		icsk->icsk_retransmits,
a7cb5a49b   Eric W. Biederman   userns: Print out...
2152
  		from_kuid_munged(seq_user_ns(f), sock_i_uid(sk)),
6687e988d   Arnaldo Carvalho de Melo   [ICSK]: Move TCP ...
2153
  		icsk->icsk_probes_out,
cf4c6bf83   Ilpo Järvinen   [TCP]: struct *so...
2154
2155
  		sock_i_ino(sk),
  		atomic_read(&sk->sk_refcnt), sk,
7be87351a   Stephen Hemminger   tcp: /proc/net/tc...
2156
2157
  		jiffies_to_clock_t(icsk->icsk_rto),
  		jiffies_to_clock_t(icsk->icsk_ack.ato),
463c84b97   Arnaldo Carvalho de Melo   [NET]: Introduce ...
2158
  		(icsk->icsk_ack.quick << 1) | icsk->icsk_ack.pingpong,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2159
  		tp->snd_cwnd,
00fd38d93   Eric Dumazet   tcp: ensure prope...
2160
2161
  		state == TCP_LISTEN ?
  		    fastopenq->max_qlen :
652586df9   Tetsuo Handa   seq_file: remove ...
2162
  		    (tcp_in_initial_slowstart(tp) ? -1 : tp->snd_ssthresh));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2163
  }
cf533ea53   Eric Dumazet   tcp: add const qu...
2164
  static void get_timewait4_sock(const struct inet_timewait_sock *tw,
652586df9   Tetsuo Handa   seq_file: remove ...
2165
  			       struct seq_file *f, int i)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2166
  {
789f558cf   Eric Dumazet   tcp/dccp: get rid...
2167
  	long delta = tw->tw_timer.expires - jiffies;
23f33c2d4   Al Viro   [IPV4]: struct in...
2168
  	__be32 dest, src;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2169
  	__u16 destp, srcp;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2170
2171
2172
2173
2174
  
  	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 ...
2175
  	seq_printf(f, "%4d: %08X:%04X %08X:%04X"
652586df9   Tetsuo Handa   seq_file: remove ...
2176
  		" %02X %08X:%08X %02X:%08lX %08X %5d %8d %d %d %pK",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2177
  		i, src, srcp, dest, destp, tw->tw_substate, 0, 0,
a399a8053   Eric Dumazet   time: jiffies_del...
2178
  		3, jiffies_delta_to_clock_t(delta), 0, 0, 0, 0,
652586df9   Tetsuo Handa   seq_file: remove ...
2179
  		atomic_read(&tw->tw_refcnt), tw);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2180
2181
2182
2183
2184
2185
  }
  
  #define TMPSZ 150
  
  static int tcp4_seq_show(struct seq_file *seq, void *v)
  {
5799de0b1   Jianjun Kong   net: clean up net...
2186
  	struct tcp_iter_state *st;
05dbc7b59   Eric Dumazet   tcp/dccp: remove ...
2187
  	struct sock *sk = v;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2188

652586df9   Tetsuo Handa   seq_file: remove ...
2189
  	seq_setwidth(seq, TMPSZ - 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2190
  	if (v == SEQ_START_TOKEN) {
652586df9   Tetsuo Handa   seq_file: remove ...
2191
  		seq_puts(seq, "  sl  local_address rem_address   st tx_queue "
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2192
2193
2194
2195
2196
  			   "rx_queue tr tm->when retrnsmt   uid  timeout "
  			   "inode");
  		goto out;
  	}
  	st = seq->private;
079096f10   Eric Dumazet   tcp/dccp: install...
2197
2198
2199
  	if (sk->sk_state == TCP_TIME_WAIT)
  		get_timewait4_sock(v, seq, st->num);
  	else if (sk->sk_state == TCP_NEW_SYN_RECV)
aa3a0c8ce   Eric Dumazet   tcp: get_openreq[...
2200
  		get_openreq4(v, seq, st->num);
079096f10   Eric Dumazet   tcp/dccp: install...
2201
2202
  	else
  		get_tcp4_sock(v, seq, st->num);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2203
  out:
652586df9   Tetsuo Handa   seq_file: remove ...
2204
2205
  	seq_pad(seq, '
  ');
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2206
2207
  	return 0;
  }
73cb88ecb   Arjan van de Ven   net: make the tcp...
2208
2209
2210
2211
2212
2213
2214
  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
2215
  static struct tcp_seq_afinfo tcp4_seq_afinfo = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2216
2217
  	.name		= "tcp",
  	.family		= AF_INET,
73cb88ecb   Arjan van de Ven   net: make the tcp...
2218
  	.seq_fops	= &tcp_afinfo_seq_fops,
9427c4b36   Denis V. Lunev   [TCP]: Move seq_o...
2219
2220
2221
  	.seq_ops	= {
  		.show		= tcp4_seq_show,
  	},
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2222
  };
2c8c1e729   Alexey Dobriyan   net: spread __net...
2223
  static int __net_init tcp4_proc_init_net(struct net *net)
757764f61   Pavel Emelyanov   [NETNS][TCP]: Reg...
2224
2225
2226
  {
  	return tcp_proc_register(net, &tcp4_seq_afinfo);
  }
2c8c1e729   Alexey Dobriyan   net: spread __net...
2227
  static void __net_exit tcp4_proc_exit_net(struct net *net)
757764f61   Pavel Emelyanov   [NETNS][TCP]: Reg...
2228
2229
2230
2231
2232
2233
2234
2235
  {
  	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
2236
2237
  int __init tcp4_proc_init(void)
  {
757764f61   Pavel Emelyanov   [NETNS][TCP]: Reg...
2238
  	return register_pernet_subsys(&tcp4_net_ops);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2239
2240
2241
2242
  }
  
  void tcp4_proc_exit(void)
  {
757764f61   Pavel Emelyanov   [NETNS][TCP]: Reg...
2243
  	unregister_pernet_subsys(&tcp4_net_ops);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2244
2245
2246
2247
2248
2249
2250
2251
2252
  }
  #endif /* CONFIG_PROC_FS */
  
  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 ...
2253
  	.accept			= inet_csk_accept,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2254
2255
2256
2257
2258
2259
  	.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
2260
  	.recvmsg		= tcp_recvmsg,
7ba429100   Changli Gao   inet, inet6: make...
2261
2262
  	.sendmsg		= tcp_sendmsg,
  	.sendpage		= tcp_sendpage,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2263
  	.backlog_rcv		= tcp_v4_do_rcv,
46d3ceabd   Eric Dumazet   tcp: TCP Small Qu...
2264
  	.release_cb		= tcp_release_cb,
ab1e0a13d   Arnaldo Carvalho de Melo   [SOCK] proto: Add...
2265
2266
2267
  	.hash			= inet_hash,
  	.unhash			= inet_unhash,
  	.get_port		= inet_csk_get_port,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2268
  	.enter_memory_pressure	= tcp_enter_memory_pressure,
c9bee3b7f   Eric Dumazet   tcp: TCP_NOTSENT_...
2269
  	.stream_memory_free	= tcp_stream_memory_free,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2270
  	.sockets_allocated	= &tcp_sockets_allocated,
0a5578cf8   Arnaldo Carvalho de Melo   [ICSK]: Generalis...
2271
  	.orphan_count		= &tcp_orphan_count,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2272
2273
  	.memory_allocated	= &tcp_memory_allocated,
  	.memory_pressure	= &tcp_memory_pressure,
a4fe34bf9   Eric W. Biederman   tcp_memcontrol: R...
2274
  	.sysctl_mem		= sysctl_tcp_mem,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2275
2276
2277
2278
  	.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 ...
2279
  	.slab_flags		= SLAB_DESTROY_BY_RCU,
6d6ee43e0   Arnaldo Carvalho de Melo   [TWSK]: Introduce...
2280
  	.twsk_prot		= &tcp_timewait_sock_ops,
60236fdd0   Arnaldo Carvalho de Melo   [NET] Rename open...
2281
  	.rsk_prot		= &tcp_request_sock_ops,
39d8cda76   Pavel Emelyanov   [SOCK]: Add udp_h...
2282
  	.h.hashinfo		= &tcp_hashinfo,
7ba429100   Changli Gao   inet, inet6: make...
2283
  	.no_autobind		= true,
543d9cfee   Arnaldo Carvalho de Melo   [NET]: Identation...
2284
2285
2286
2287
  #ifdef CONFIG_COMPAT
  	.compat_setsockopt	= compat_tcp_setsockopt,
  	.compat_getsockopt	= compat_tcp_getsockopt,
  #endif
c1e64e298   Lorenzo Colitti   net: diag: Suppor...
2288
  	.diag_destroy		= tcp_abort,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2289
  };
4bc2f18ba   Eric Dumazet   net/ipv4: EXPORT_...
2290
  EXPORT_SYMBOL(tcp_prot);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2291

bdbbb8527   Eric Dumazet   ipv4: tcp: get ri...
2292
2293
2294
2295
2296
2297
2298
2299
  static void __net_exit tcp_sk_exit(struct net *net)
  {
  	int cpu;
  
  	for_each_possible_cpu(cpu)
  		inet_ctl_sock_destroy(*per_cpu_ptr(net->ipv4.tcp_sk, cpu));
  	free_percpu(net->ipv4.tcp_sk);
  }
046ee9023   Denis V. Lunev   [NETNS]: Create t...
2300
2301
  static int __net_init tcp_sk_init(struct net *net)
  {
bdbbb8527   Eric Dumazet   ipv4: tcp: get ri...
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
  	int res, cpu;
  
  	net->ipv4.tcp_sk = alloc_percpu(struct sock *);
  	if (!net->ipv4.tcp_sk)
  		return -ENOMEM;
  
  	for_each_possible_cpu(cpu) {
  		struct sock *sk;
  
  		res = inet_ctl_sock_create(&sk, PF_INET, SOCK_RAW,
  					   IPPROTO_TCP, net);
  		if (res)
  			goto fail;
a9d6532b5   Eric Dumazet   ipv4: tcp: set SO...
2315
  		sock_set_flag(sk, SOCK_USE_WRITE_QUEUE);
bdbbb8527   Eric Dumazet   ipv4: tcp: get ri...
2316
2317
  		*per_cpu_ptr(net->ipv4.tcp_sk, cpu) = sk;
  	}
492135557   Daniel Borkmann   tcp: add rfc3168,...
2318

5d134f1c1   Hannes Frederic Sowa   tcp: make sysctl_...
2319
  	net->ipv4.sysctl_tcp_ecn = 2;
492135557   Daniel Borkmann   tcp: add rfc3168,...
2320
  	net->ipv4.sysctl_tcp_ecn_fallback = 1;
b0f9ca53c   Fan Du   ipv4: Namespecify...
2321
  	net->ipv4.sysctl_tcp_base_mss = TCP_BASE_MSS;
6b58e0a5f   Fan Du   ipv4: Use binary ...
2322
  	net->ipv4.sysctl_tcp_probe_threshold = TCP_PROBE_THRESHOLD;
05cbc0db0   Fan Du   ipv4: Create prob...
2323
  	net->ipv4.sysctl_tcp_probe_interval = TCP_PROBE_INTERVAL;
046ee9023   Denis V. Lunev   [NETNS]: Create t...
2324

13b287e8d   Nikolay Borisov   ipv4: Namespaceif...
2325
  	net->ipv4.sysctl_tcp_keepalive_time = TCP_KEEPALIVE_TIME;
9bd6861bd   Nikolay Borisov   ipv4: Namespecify...
2326
  	net->ipv4.sysctl_tcp_keepalive_probes = TCP_KEEPALIVE_PROBES;
b840d15d3   Nikolay Borisov   ipv4: Namespecify...
2327
  	net->ipv4.sysctl_tcp_keepalive_intvl = TCP_KEEPALIVE_INTVL;
13b287e8d   Nikolay Borisov   ipv4: Namespaceif...
2328

6fa251663   Nikolay Borisov   ipv4: Namespaceif...
2329
  	net->ipv4.sysctl_tcp_syn_retries = TCP_SYN_RETRIES;
7c083ecb3   Nikolay Borisov   ipv4: Namespaceif...
2330
  	net->ipv4.sysctl_tcp_synack_retries = TCP_SYNACK_RETRIES;
0aca737d4   David S. Miller   tcp: Fix syncooki...
2331
  	net->ipv4.sysctl_tcp_syncookies = 1;
1043e25ff   Nikolay Borisov   ipv4: Namespaceif...
2332
  	net->ipv4.sysctl_tcp_reordering = TCP_FASTRETRANS_THRESH;
ae5c3f406   Nikolay Borisov   ipv4: Namespaceif...
2333
  	net->ipv4.sysctl_tcp_retries1 = TCP_RETR1;
c6214a97c   Nikolay Borisov   ipv4: Namespaceif...
2334
  	net->ipv4.sysctl_tcp_retries2 = TCP_RETR2;
c402d9bef   Nikolay Borisov   ipv4: Namespaceif...
2335
  	net->ipv4.sysctl_tcp_orphan_retries = 0;
1e579caa1   Nikolay Borisov   ipv4: Namespaceif...
2336
  	net->ipv4.sysctl_tcp_fin_timeout = TCP_FIN_TIMEOUT;
4979f2d9f   Nikolay Borisov   ipv4: Namespaceif...
2337
  	net->ipv4.sysctl_tcp_notsent_lowat = UINT_MAX;
12ed8244e   Nikolay Borisov   ipv4: Namespaceif...
2338

492135557   Daniel Borkmann   tcp: add rfc3168,...
2339
  	return 0;
bdbbb8527   Eric Dumazet   ipv4: tcp: get ri...
2340
2341
2342
2343
  fail:
  	tcp_sk_exit(net);
  
  	return res;
b099ce260   Eric W. Biederman   net: Batch inet_t...
2344
2345
2346
2347
2348
  }
  
  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...
2349
2350
2351
  }
  
  static struct pernet_operations __net_initdata tcp_sk_ops = {
b099ce260   Eric W. Biederman   net: Batch inet_t...
2352
2353
2354
         .init	   = tcp_sk_init,
         .exit	   = tcp_sk_exit,
         .exit_batch = tcp_sk_exit_batch,
046ee9023   Denis V. Lunev   [NETNS]: Create t...
2355
  };
9b0f976f2   Denis V. Lunev   [INET]: Remove st...
2356
  void __init tcp_v4_init(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2357
  {
5caea4ea7   Eric Dumazet   net: listening_ha...
2358
  	inet_hashinfo_init(&tcp_hashinfo);
6a1b3054d   Eric W. Biederman   tcp: Like icmp us...
2359
  	if (register_pernet_subsys(&tcp_sk_ops))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2360
2361
  		panic("Failed to create the TCP control socket.
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2362
  }