blob: df89a566a5a10f65a9bec3612661aaa7e4461a3e [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * INET An implementation of the TCP/IP protocol suite for the LINUX
3 * operating system. INET is implemented using the BSD Socket
4 * interface as the means of communication with the user level.
5 *
6 * Implementation of the Transmission Control Protocol(TCP).
7 *
8 * Version: $Id: tcp_ipv4.c,v 1.240 2002/02/01 22:01:04 davem Exp $
9 *
10 * IPv4 specific functions
11 *
12 *
13 * code split from:
14 * linux/ipv4/tcp.c
15 * linux/ipv4/tcp_input.c
16 * linux/ipv4/tcp_output.c
17 *
18 * See tcp.c for author information
19 *
20 * This program is free software; you can redistribute it and/or
21 * modify it under the terms of the GNU General Public License
22 * as published by the Free Software Foundation; either version
23 * 2 of the License, or (at your option) any later version.
24 */
25
26/*
27 * Changes:
28 * David S. Miller : New socket lookup architecture.
29 * This code is dedicated to John Dyson.
30 * David S. Miller : Change semantics of established hash,
31 * half is devoted to TIME_WAIT sockets
32 * and the rest go in the other half.
33 * Andi Kleen : Add support for syncookies and fixed
34 * some bugs: ip options weren't passed to
35 * the TCP layer, missed a check for an
36 * ACK bit.
37 * Andi Kleen : Implemented fast path mtu discovery.
38 * Fixed many serious bugs in the
Arnaldo Carvalho de Melo60236fd2005-06-18 22:47:21 -070039 * request_sock handling and moved
Linus Torvalds1da177e2005-04-16 15:20:36 -070040 * most of it into the af independent code.
41 * Added tail drop and some other bugfixes.
Stephen Hemmingercaa20d9a2005-11-10 17:13:47 -080042 * Added new listen semantics.
Linus Torvalds1da177e2005-04-16 15:20:36 -070043 * Mike McLagan : Routing by source
44 * Juan Jose Ciarlante: ip_dynaddr bits
45 * Andi Kleen: various fixes.
46 * Vitaly E. Lavrov : Transparent proxy revived after year
47 * coma.
48 * Andi Kleen : Fix new listen.
49 * Andi Kleen : Fix accept error reporting.
50 * YOSHIFUJI Hideaki @USAGI and: Support IPV6_V6ONLY socket option, which
51 * Alexey Kuznetsov allow both IPv4 and IPv6 sockets to bind
52 * a single port at the same time.
53 */
54
Linus Torvalds1da177e2005-04-16 15:20:36 -070055
56#include <linux/types.h>
57#include <linux/fcntl.h>
58#include <linux/module.h>
59#include <linux/random.h>
60#include <linux/cache.h>
61#include <linux/jhash.h>
62#include <linux/init.h>
63#include <linux/times.h>
64
Eric W. Biederman457c4cb2007-09-12 12:01:34 +020065#include <net/net_namespace.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070066#include <net/icmp.h>
Arnaldo Carvalho de Melo304a1612005-08-09 19:59:20 -070067#include <net/inet_hashtables.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070068#include <net/tcp.h>
Arnaldo Carvalho de Melo20380732005-08-16 02:18:02 -030069#include <net/transp_v6.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070070#include <net/ipv6.h>
71#include <net/inet_common.h>
Arnaldo Carvalho de Melo6d6ee432005-12-13 23:25:19 -080072#include <net/timewait_sock.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070073#include <net/xfrm.h>
Chris Leech1a2449a2006-05-23 18:05:53 -070074#include <net/netdma.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070075
76#include <linux/inet.h>
77#include <linux/ipv6.h>
78#include <linux/stddef.h>
79#include <linux/proc_fs.h>
80#include <linux/seq_file.h>
81
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -080082#include <linux/crypto.h>
83#include <linux/scatterlist.h>
84
Brian Haleyab32ea52006-09-22 14:15:41 -070085int sysctl_tcp_tw_reuse __read_mostly;
86int sysctl_tcp_low_latency __read_mostly;
Linus Torvalds1da177e2005-04-16 15:20:36 -070087
88/* Check TCP sequence numbers in ICMP packets. */
89#define ICMP_MIN_LENGTH 8
90
Arnaldo Carvalho de Melo8292a172005-12-13 23:15:52 -080091void tcp_v4_send_check(struct sock *sk, int len, struct sk_buff *skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -070092
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -080093#ifdef CONFIG_TCP_MD5SIG
Arnaldo Carvalho de Melo71742592006-11-17 10:57:30 -020094static struct tcp_md5sig_key *tcp_v4_md5_do_lookup(struct sock *sk,
95 __be32 addr);
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -080096static int tcp_v4_do_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key,
Arnaldo Carvalho de Melo71742592006-11-17 10:57:30 -020097 __be32 saddr, __be32 daddr,
98 struct tcphdr *th, int protocol,
YOSHIFUJI Hideaki9cb57342008-01-12 02:16:03 -080099 unsigned int tcplen);
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800100#endif
101
Arnaldo Carvalho de Melo0f7ff922005-08-09 19:59:44 -0700102struct inet_hashinfo __cacheline_aligned tcp_hashinfo = {
Arnaldo Carvalho de Melo71742592006-11-17 10:57:30 -0200103 .lhash_lock = __RW_LOCK_UNLOCKED(tcp_hashinfo.lhash_lock),
104 .lhash_users = ATOMIC_INIT(0),
105 .lhash_wait = __WAIT_QUEUE_HEAD_INITIALIZER(tcp_hashinfo.lhash_wait),
Linus Torvalds1da177e2005-04-16 15:20:36 -0700106};
107
Gerrit Renkera94f7232006-11-10 14:06:49 -0800108static inline __u32 tcp_v4_init_sequence(struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700109{
Arnaldo Carvalho de Meloeddc9ec2007-04-20 22:47:35 -0700110 return secure_tcp_sequence_number(ip_hdr(skb)->daddr,
111 ip_hdr(skb)->saddr,
Arnaldo Carvalho de Meloaa8223c2007-04-10 21:04:22 -0700112 tcp_hdr(skb)->dest,
113 tcp_hdr(skb)->source);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700114}
115
Arnaldo Carvalho de Melo6d6ee432005-12-13 23:25:19 -0800116int tcp_twsk_unique(struct sock *sk, struct sock *sktw, void *twp)
117{
118 const struct tcp_timewait_sock *tcptw = tcp_twsk(sktw);
119 struct tcp_sock *tp = tcp_sk(sk);
120
121 /* With PAWS, it is safe from the viewpoint
122 of data integrity. Even without PAWS it is safe provided sequence
123 spaces do not overlap i.e. at data rates <= 80Mbit/sec.
124
125 Actually, the idea is close to VJ's one, only timestamp cache is
126 held not per host, but per port pair and TW bucket is used as state
127 holder.
128
129 If TW bucket has been already destroyed we fall back to VJ's scheme
130 and use initial timestamp retrieved from peer table.
131 */
132 if (tcptw->tw_ts_recent_stamp &&
133 (twp == NULL || (sysctl_tcp_tw_reuse &&
James Morris9d729f72007-03-04 16:12:44 -0800134 get_seconds() - tcptw->tw_ts_recent_stamp > 1))) {
Arnaldo Carvalho de Melo6d6ee432005-12-13 23:25:19 -0800135 tp->write_seq = tcptw->tw_snd_nxt + 65535 + 2;
136 if (tp->write_seq == 0)
137 tp->write_seq = 1;
138 tp->rx_opt.ts_recent = tcptw->tw_ts_recent;
139 tp->rx_opt.ts_recent_stamp = tcptw->tw_ts_recent_stamp;
140 sock_hold(sktw);
141 return 1;
142 }
143
144 return 0;
145}
146
147EXPORT_SYMBOL_GPL(tcp_twsk_unique);
148
Linus Torvalds1da177e2005-04-16 15:20:36 -0700149/* This will initiate an outgoing connection. */
150int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
151{
152 struct inet_sock *inet = inet_sk(sk);
153 struct tcp_sock *tp = tcp_sk(sk);
154 struct sockaddr_in *usin = (struct sockaddr_in *)uaddr;
155 struct rtable *rt;
Al Virobada8ad2006-09-26 21:27:15 -0700156 __be32 daddr, nexthop;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700157 int tmp;
158 int err;
159
160 if (addr_len < sizeof(struct sockaddr_in))
161 return -EINVAL;
162
163 if (usin->sin_family != AF_INET)
164 return -EAFNOSUPPORT;
165
166 nexthop = daddr = usin->sin_addr.s_addr;
167 if (inet->opt && inet->opt->srr) {
168 if (!daddr)
169 return -EINVAL;
170 nexthop = inet->opt->faddr;
171 }
172
173 tmp = ip_route_connect(&rt, nexthop, inet->saddr,
174 RT_CONN_FLAGS(sk), sk->sk_bound_dev_if,
175 IPPROTO_TCP,
David S. Miller8eb90862007-02-08 02:09:21 -0800176 inet->sport, usin->sin_port, sk, 1);
Wei Dong584bdf82007-05-31 22:49:28 -0700177 if (tmp < 0) {
178 if (tmp == -ENETUNREACH)
179 IP_INC_STATS_BH(IPSTATS_MIB_OUTNOROUTES);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700180 return tmp;
Wei Dong584bdf82007-05-31 22:49:28 -0700181 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700182
183 if (rt->rt_flags & (RTCF_MULTICAST | RTCF_BROADCAST)) {
184 ip_rt_put(rt);
185 return -ENETUNREACH;
186 }
187
188 if (!inet->opt || !inet->opt->srr)
189 daddr = rt->rt_dst;
190
191 if (!inet->saddr)
192 inet->saddr = rt->rt_src;
193 inet->rcv_saddr = inet->saddr;
194
195 if (tp->rx_opt.ts_recent_stamp && inet->daddr != daddr) {
196 /* Reset inherited state */
197 tp->rx_opt.ts_recent = 0;
198 tp->rx_opt.ts_recent_stamp = 0;
199 tp->write_seq = 0;
200 }
201
Arnaldo Carvalho de Melo295ff7e2005-08-09 20:44:40 -0700202 if (tcp_death_row.sysctl_tw_recycle &&
Linus Torvalds1da177e2005-04-16 15:20:36 -0700203 !tp->rx_opt.ts_recent_stamp && rt->rt_dst == daddr) {
204 struct inet_peer *peer = rt_get_peer(rt);
Arnaldo Carvalho de Melo71742592006-11-17 10:57:30 -0200205 /*
206 * VJ's idea. We save last timestamp seen from
207 * the destination in peer table, when entering state
208 * TIME-WAIT * and initialize rx_opt.ts_recent from it,
209 * when trying new connection.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700210 */
Arnaldo Carvalho de Melo71742592006-11-17 10:57:30 -0200211 if (peer != NULL &&
James Morris9d729f72007-03-04 16:12:44 -0800212 peer->tcp_ts_stamp + TCP_PAWS_MSL >= get_seconds()) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700213 tp->rx_opt.ts_recent_stamp = peer->tcp_ts_stamp;
214 tp->rx_opt.ts_recent = peer->tcp_ts;
215 }
216 }
217
218 inet->dport = usin->sin_port;
219 inet->daddr = daddr;
220
Arnaldo Carvalho de Melod83d8462005-12-13 23:26:10 -0800221 inet_csk(sk)->icsk_ext_hdr_len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700222 if (inet->opt)
Arnaldo Carvalho de Melod83d8462005-12-13 23:26:10 -0800223 inet_csk(sk)->icsk_ext_hdr_len = inet->opt->optlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700224
225 tp->rx_opt.mss_clamp = 536;
226
227 /* Socket identity is still unknown (sport may be zero).
228 * However we set state to SYN-SENT and not releasing socket
229 * lock select source port, enter ourselves into the hash tables and
230 * complete initialization after this.
231 */
232 tcp_set_state(sk, TCP_SYN_SENT);
Arnaldo Carvalho de Meloa7f5e7f2005-12-13 23:25:31 -0800233 err = inet_hash_connect(&tcp_death_row, sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700234 if (err)
235 goto failure;
236
Arnaldo Carvalho de Melo71742592006-11-17 10:57:30 -0200237 err = ip_route_newports(&rt, IPPROTO_TCP,
238 inet->sport, inet->dport, sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700239 if (err)
240 goto failure;
241
242 /* OK, now commit destination to socket. */
Herbert Xubcd76112006-06-30 13:36:35 -0700243 sk->sk_gso_type = SKB_GSO_TCPV4;
Arnaldo Carvalho de Melo6cbb0df2005-08-09 19:49:02 -0700244 sk_setup_caps(sk, &rt->u.dst);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700245
246 if (!tp->write_seq)
247 tp->write_seq = secure_tcp_sequence_number(inet->saddr,
248 inet->daddr,
249 inet->sport,
250 usin->sin_port);
251
252 inet->id = tp->write_seq ^ jiffies;
253
254 err = tcp_connect(sk);
255 rt = NULL;
256 if (err)
257 goto failure;
258
259 return 0;
260
261failure:
Arnaldo Carvalho de Melo71742592006-11-17 10:57:30 -0200262 /*
263 * This unhashes the socket and releases the local port,
264 * if necessary.
265 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700266 tcp_set_state(sk, TCP_CLOSE);
267 ip_rt_put(rt);
268 sk->sk_route_caps = 0;
269 inet->dport = 0;
270 return err;
271}
272
Linus Torvalds1da177e2005-04-16 15:20:36 -0700273/*
274 * This routine does path mtu discovery as defined in RFC1191.
275 */
Stephen Hemminger40efc6f2006-01-03 16:03:49 -0800276static void do_pmtu_discovery(struct sock *sk, struct iphdr *iph, u32 mtu)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700277{
278 struct dst_entry *dst;
279 struct inet_sock *inet = inet_sk(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700280
281 /* We are not interested in TCP_LISTEN and open_requests (SYN-ACKs
282 * send out by Linux are always <576bytes so they should go through
283 * unfragmented).
284 */
285 if (sk->sk_state == TCP_LISTEN)
286 return;
287
288 /* We don't check in the destentry if pmtu discovery is forbidden
289 * on this route. We just assume that no packet_to_big packets
290 * are send back when pmtu discovery is not active.
YOSHIFUJI Hideakie905a9e2007-02-09 23:24:47 +0900291 * There is a small race when the user changes this flag in the
Linus Torvalds1da177e2005-04-16 15:20:36 -0700292 * route, but I think that's acceptable.
293 */
294 if ((dst = __sk_dst_check(sk, 0)) == NULL)
295 return;
296
297 dst->ops->update_pmtu(dst, mtu);
298
299 /* Something is about to be wrong... Remember soft error
300 * for the case, if this connection will not able to recover.
301 */
302 if (mtu < dst_mtu(dst) && ip_dont_fragment(sk, dst))
303 sk->sk_err_soft = EMSGSIZE;
304
305 mtu = dst_mtu(dst);
306
307 if (inet->pmtudisc != IP_PMTUDISC_DONT &&
Arnaldo Carvalho de Melod83d8462005-12-13 23:26:10 -0800308 inet_csk(sk)->icsk_pmtu_cookie > mtu) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700309 tcp_sync_mss(sk, mtu);
310
311 /* Resend the TCP packet because it's
312 * clear that the old packet has been
313 * dropped. This is the new "fast" path mtu
314 * discovery.
315 */
316 tcp_simple_retransmit(sk);
317 } /* else let the usual retransmit timer handle it */
318}
319
320/*
321 * This routine is called by the ICMP module when it gets some
322 * sort of error condition. If err < 0 then the socket should
323 * be closed and the error returned to the user. If err > 0
324 * it's just the icmp type << 8 | icmp code. After adjustment
325 * header points to the first 8 bytes of the tcp header. We need
326 * to find the appropriate port.
327 *
328 * The locking strategy used here is very "optimistic". When
329 * someone else accesses the socket the ICMP is just dropped
330 * and for some paths there is no check at all.
331 * A more general error queue to queue errors for later handling
332 * is probably better.
333 *
334 */
335
336void tcp_v4_err(struct sk_buff *skb, u32 info)
337{
338 struct iphdr *iph = (struct iphdr *)skb->data;
339 struct tcphdr *th = (struct tcphdr *)(skb->data + (iph->ihl << 2));
340 struct tcp_sock *tp;
341 struct inet_sock *inet;
Arnaldo Carvalho de Melo88c76642007-03-13 14:43:18 -0300342 const int type = icmp_hdr(skb)->type;
343 const int code = icmp_hdr(skb)->code;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700344 struct sock *sk;
345 __u32 seq;
346 int err;
347
348 if (skb->len < (iph->ihl << 2) + 8) {
349 ICMP_INC_STATS_BH(ICMP_MIB_INERRORS);
350 return;
351 }
352
YOSHIFUJI Hideakic346dca2008-03-25 21:47:49 +0900353 sk = inet_lookup(dev_net(skb->dev), &tcp_hashinfo, iph->daddr, th->dest,
Pavel Emelyanovc67499c2008-01-31 05:06:40 -0800354 iph->saddr, th->source, inet_iif(skb));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700355 if (!sk) {
356 ICMP_INC_STATS_BH(ICMP_MIB_INERRORS);
357 return;
358 }
359 if (sk->sk_state == TCP_TIME_WAIT) {
YOSHIFUJI Hideaki9469c7b2006-10-10 19:41:46 -0700360 inet_twsk_put(inet_twsk(sk));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700361 return;
362 }
363
364 bh_lock_sock(sk);
365 /* If too many ICMPs get dropped on busy
366 * servers this needs to be solved differently.
367 */
368 if (sock_owned_by_user(sk))
369 NET_INC_STATS_BH(LINUX_MIB_LOCKDROPPEDICMPS);
370
371 if (sk->sk_state == TCP_CLOSE)
372 goto out;
373
374 tp = tcp_sk(sk);
375 seq = ntohl(th->seq);
376 if (sk->sk_state != TCP_LISTEN &&
377 !between(seq, tp->snd_una, tp->snd_nxt)) {
Eric Dumazet06ca7192006-10-20 00:22:25 -0700378 NET_INC_STATS_BH(LINUX_MIB_OUTOFWINDOWICMPS);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700379 goto out;
380 }
381
382 switch (type) {
383 case ICMP_SOURCE_QUENCH:
384 /* Just silently ignore these. */
385 goto out;
386 case ICMP_PARAMETERPROB:
387 err = EPROTO;
388 break;
389 case ICMP_DEST_UNREACH:
390 if (code > NR_ICMP_UNREACH)
391 goto out;
392
393 if (code == ICMP_FRAG_NEEDED) { /* PMTU discovery (RFC1191) */
394 if (!sock_owned_by_user(sk))
395 do_pmtu_discovery(sk, iph, info);
396 goto out;
397 }
398
399 err = icmp_err_convert[code].errno;
400 break;
401 case ICMP_TIME_EXCEEDED:
402 err = EHOSTUNREACH;
403 break;
404 default:
405 goto out;
406 }
407
408 switch (sk->sk_state) {
Arnaldo Carvalho de Melo60236fd2005-06-18 22:47:21 -0700409 struct request_sock *req, **prev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700410 case TCP_LISTEN:
411 if (sock_owned_by_user(sk))
412 goto out;
413
Arnaldo Carvalho de Melo463c84b2005-08-09 20:10:42 -0700414 req = inet_csk_search_req(sk, &prev, th->dest,
415 iph->daddr, iph->saddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700416 if (!req)
417 goto out;
418
419 /* ICMPs are not backlogged, hence we cannot get
420 an established socket here.
421 */
422 BUG_TRAP(!req->sk);
423
Arnaldo Carvalho de Melo2e6599c2005-06-18 22:46:52 -0700424 if (seq != tcp_rsk(req)->snt_isn) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700425 NET_INC_STATS_BH(LINUX_MIB_OUTOFWINDOWICMPS);
426 goto out;
427 }
428
429 /*
430 * Still in SYN_RECV, just remove it silently.
431 * There is no good way to pass the error to the newly
432 * created socket, and POSIX does not want network
433 * errors returned from accept().
434 */
Arnaldo Carvalho de Melo463c84b2005-08-09 20:10:42 -0700435 inet_csk_reqsk_queue_drop(sk, req, prev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700436 goto out;
437
438 case TCP_SYN_SENT:
439 case TCP_SYN_RECV: /* Cannot happen.
440 It can f.e. if SYNs crossed.
441 */
442 if (!sock_owned_by_user(sk)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700443 sk->sk_err = err;
444
445 sk->sk_error_report(sk);
446
447 tcp_done(sk);
448 } else {
449 sk->sk_err_soft = err;
450 }
451 goto out;
452 }
453
454 /* If we've already connected we will keep trying
455 * until we time out, or the user gives up.
456 *
457 * rfc1122 4.2.3.9 allows to consider as hard errors
458 * only PROTO_UNREACH and PORT_UNREACH (well, FRAG_FAILED too,
459 * but it is obsoleted by pmtu discovery).
460 *
461 * Note, that in modern internet, where routing is unreliable
462 * and in each dark corner broken firewalls sit, sending random
463 * errors ordered by their masters even this two messages finally lose
464 * their original sense (even Linux sends invalid PORT_UNREACHs)
465 *
466 * Now we are in compliance with RFCs.
467 * --ANK (980905)
468 */
469
470 inet = inet_sk(sk);
471 if (!sock_owned_by_user(sk) && inet->recverr) {
472 sk->sk_err = err;
473 sk->sk_error_report(sk);
474 } else { /* Only an error on timeout */
475 sk->sk_err_soft = err;
476 }
477
478out:
479 bh_unlock_sock(sk);
480 sock_put(sk);
481}
482
483/* This routine computes an IPv4 TCP checksum. */
Arnaldo Carvalho de Melo8292a172005-12-13 23:15:52 -0800484void tcp_v4_send_check(struct sock *sk, int len, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700485{
486 struct inet_sock *inet = inet_sk(sk);
Arnaldo Carvalho de Meloaa8223c2007-04-10 21:04:22 -0700487 struct tcphdr *th = tcp_hdr(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700488
Patrick McHardy84fa7932006-08-29 16:44:56 -0700489 if (skb->ip_summed == CHECKSUM_PARTIAL) {
Frederik Deweerdtba7808e2007-02-04 20:15:27 -0800490 th->check = ~tcp_v4_check(len, inet->saddr,
491 inet->daddr, 0);
Herbert Xu663ead32007-04-09 11:59:07 -0700492 skb->csum_start = skb_transport_header(skb) - skb->head;
Al Viroff1dcad2006-11-20 18:07:29 -0800493 skb->csum_offset = offsetof(struct tcphdr, check);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700494 } else {
Frederik Deweerdtba7808e2007-02-04 20:15:27 -0800495 th->check = tcp_v4_check(len, inet->saddr, inet->daddr,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700496 csum_partial((char *)th,
497 th->doff << 2,
498 skb->csum));
499 }
500}
501
Herbert Xua430a432006-07-08 13:34:56 -0700502int tcp_v4_gso_send_check(struct sk_buff *skb)
503{
Arnaldo Carvalho de Meloeddc9ec2007-04-20 22:47:35 -0700504 const struct iphdr *iph;
Herbert Xua430a432006-07-08 13:34:56 -0700505 struct tcphdr *th;
506
507 if (!pskb_may_pull(skb, sizeof(*th)))
508 return -EINVAL;
509
Arnaldo Carvalho de Meloeddc9ec2007-04-20 22:47:35 -0700510 iph = ip_hdr(skb);
Arnaldo Carvalho de Meloaa8223c2007-04-10 21:04:22 -0700511 th = tcp_hdr(skb);
Herbert Xua430a432006-07-08 13:34:56 -0700512
513 th->check = 0;
Frederik Deweerdtba7808e2007-02-04 20:15:27 -0800514 th->check = ~tcp_v4_check(skb->len, iph->saddr, iph->daddr, 0);
Herbert Xu663ead32007-04-09 11:59:07 -0700515 skb->csum_start = skb_transport_header(skb) - skb->head;
Al Viroff1dcad2006-11-20 18:07:29 -0800516 skb->csum_offset = offsetof(struct tcphdr, check);
Patrick McHardy84fa7932006-08-29 16:44:56 -0700517 skb->ip_summed = CHECKSUM_PARTIAL;
Herbert Xua430a432006-07-08 13:34:56 -0700518 return 0;
519}
520
Linus Torvalds1da177e2005-04-16 15:20:36 -0700521/*
522 * This routine will send an RST to the other tcp.
523 *
524 * Someone asks: why I NEVER use socket parameters (TOS, TTL etc.)
525 * for reset.
526 * Answer: if a packet caused RST, it is not for a socket
527 * existing in our system, if it is matched to a socket,
528 * it is just duplicate segment or bug in other side's TCP.
529 * So that we build reply only basing on parameters
530 * arrived with segment.
531 * Exception: precedence violation. We do not implement it in any case.
532 */
533
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800534static void tcp_v4_send_reset(struct sock *sk, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700535{
Arnaldo Carvalho de Meloaa8223c2007-04-10 21:04:22 -0700536 struct tcphdr *th = tcp_hdr(skb);
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800537 struct {
538 struct tcphdr th;
539#ifdef CONFIG_TCP_MD5SIG
Al Viro714e85b2006-11-14 20:51:49 -0800540 __be32 opt[(TCPOLEN_MD5SIG_ALIGNED >> 2)];
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800541#endif
542 } rep;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700543 struct ip_reply_arg arg;
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800544#ifdef CONFIG_TCP_MD5SIG
545 struct tcp_md5sig_key *key;
546#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700547
548 /* Never send a reset in response to a reset. */
549 if (th->rst)
550 return;
551
Eric Dumazetee6b9672008-03-05 18:30:47 -0800552 if (skb->rtable->rt_type != RTN_LOCAL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700553 return;
554
555 /* Swap the send and the receive. */
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800556 memset(&rep, 0, sizeof(rep));
557 rep.th.dest = th->source;
558 rep.th.source = th->dest;
559 rep.th.doff = sizeof(struct tcphdr) / 4;
560 rep.th.rst = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700561
562 if (th->ack) {
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800563 rep.th.seq = th->ack_seq;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700564 } else {
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800565 rep.th.ack = 1;
566 rep.th.ack_seq = htonl(ntohl(th->seq) + th->syn + th->fin +
567 skb->len - (th->doff << 2));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700568 }
569
Arnaldo Carvalho de Melo71742592006-11-17 10:57:30 -0200570 memset(&arg, 0, sizeof(arg));
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800571 arg.iov[0].iov_base = (unsigned char *)&rep;
572 arg.iov[0].iov_len = sizeof(rep.th);
573
574#ifdef CONFIG_TCP_MD5SIG
Arnaldo Carvalho de Meloeddc9ec2007-04-20 22:47:35 -0700575 key = sk ? tcp_v4_md5_do_lookup(sk, ip_hdr(skb)->daddr) : NULL;
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800576 if (key) {
577 rep.opt[0] = htonl((TCPOPT_NOP << 24) |
578 (TCPOPT_NOP << 16) |
579 (TCPOPT_MD5SIG << 8) |
580 TCPOLEN_MD5SIG);
581 /* Update length and the length the header thinks exists */
582 arg.iov[0].iov_len += TCPOLEN_MD5SIG_ALIGNED;
583 rep.th.doff = arg.iov[0].iov_len / 4;
584
585 tcp_v4_do_calc_md5_hash((__u8 *)&rep.opt[1],
586 key,
Arnaldo Carvalho de Meloeddc9ec2007-04-20 22:47:35 -0700587 ip_hdr(skb)->daddr,
588 ip_hdr(skb)->saddr,
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800589 &rep.th, IPPROTO_TCP,
590 arg.iov[0].iov_len);
591 }
592#endif
Arnaldo Carvalho de Meloeddc9ec2007-04-20 22:47:35 -0700593 arg.csum = csum_tcpudp_nofold(ip_hdr(skb)->daddr,
594 ip_hdr(skb)->saddr, /* XXX */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700595 sizeof(struct tcphdr), IPPROTO_TCP, 0);
596 arg.csumoffset = offsetof(struct tcphdr, check) / 2;
597
Denis V. Lunev7feb49c2008-04-03 14:32:00 -0700598 ip_send_reply(dev_net(skb->dst->dev)->ipv4.tcp_sock, skb,
599 &arg, arg.iov[0].iov_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700600
601 TCP_INC_STATS_BH(TCP_MIB_OUTSEGS);
602 TCP_INC_STATS_BH(TCP_MIB_OUTRSTS);
603}
604
605/* The code following below sending ACKs in SYN-RECV and TIME-WAIT states
606 outside socket context is ugly, certainly. What can I do?
607 */
608
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800609static void tcp_v4_send_ack(struct tcp_timewait_sock *twsk,
610 struct sk_buff *skb, u32 seq, u32 ack,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700611 u32 win, u32 ts)
612{
Arnaldo Carvalho de Meloaa8223c2007-04-10 21:04:22 -0700613 struct tcphdr *th = tcp_hdr(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700614 struct {
615 struct tcphdr th;
Al Viro714e85b2006-11-14 20:51:49 -0800616 __be32 opt[(TCPOLEN_TSTAMP_ALIGNED >> 2)
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800617#ifdef CONFIG_TCP_MD5SIG
Al Viro714e85b2006-11-14 20:51:49 -0800618 + (TCPOLEN_MD5SIG_ALIGNED >> 2)
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800619#endif
620 ];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700621 } rep;
622 struct ip_reply_arg arg;
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800623#ifdef CONFIG_TCP_MD5SIG
624 struct tcp_md5sig_key *key;
625 struct tcp_md5sig_key tw_key;
626#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700627
628 memset(&rep.th, 0, sizeof(struct tcphdr));
Arnaldo Carvalho de Melo71742592006-11-17 10:57:30 -0200629 memset(&arg, 0, sizeof(arg));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700630
631 arg.iov[0].iov_base = (unsigned char *)&rep;
632 arg.iov[0].iov_len = sizeof(rep.th);
633 if (ts) {
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800634 rep.opt[0] = htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) |
635 (TCPOPT_TIMESTAMP << 8) |
636 TCPOLEN_TIMESTAMP);
637 rep.opt[1] = htonl(tcp_time_stamp);
638 rep.opt[2] = htonl(ts);
Craig Schlentercb48cfe2007-01-09 00:11:15 -0800639 arg.iov[0].iov_len += TCPOLEN_TSTAMP_ALIGNED;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700640 }
641
642 /* Swap the send and the receive. */
643 rep.th.dest = th->source;
644 rep.th.source = th->dest;
645 rep.th.doff = arg.iov[0].iov_len / 4;
646 rep.th.seq = htonl(seq);
647 rep.th.ack_seq = htonl(ack);
648 rep.th.ack = 1;
649 rep.th.window = htons(win);
650
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800651#ifdef CONFIG_TCP_MD5SIG
652 /*
653 * The SKB holds an imcoming packet, but may not have a valid ->sk
654 * pointer. This is especially the case when we're dealing with a
655 * TIME_WAIT ack, because the sk structure is long gone, and only
656 * the tcp_timewait_sock remains. So the md5 key is stashed in that
657 * structure, and we use it in preference. I believe that (twsk ||
658 * skb->sk) holds true, but we program defensively.
659 */
660 if (!twsk && skb->sk) {
Arnaldo Carvalho de Meloeddc9ec2007-04-20 22:47:35 -0700661 key = tcp_v4_md5_do_lookup(skb->sk, ip_hdr(skb)->daddr);
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800662 } else if (twsk && twsk->tw_md5_keylen) {
663 tw_key.key = twsk->tw_md5_key;
664 tw_key.keylen = twsk->tw_md5_keylen;
665 key = &tw_key;
Arnaldo Carvalho de Melo71742592006-11-17 10:57:30 -0200666 } else
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800667 key = NULL;
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800668
669 if (key) {
670 int offset = (ts) ? 3 : 0;
671
672 rep.opt[offset++] = htonl((TCPOPT_NOP << 24) |
673 (TCPOPT_NOP << 16) |
674 (TCPOPT_MD5SIG << 8) |
675 TCPOLEN_MD5SIG);
676 arg.iov[0].iov_len += TCPOLEN_MD5SIG_ALIGNED;
677 rep.th.doff = arg.iov[0].iov_len/4;
678
679 tcp_v4_do_calc_md5_hash((__u8 *)&rep.opt[offset],
680 key,
Arnaldo Carvalho de Meloeddc9ec2007-04-20 22:47:35 -0700681 ip_hdr(skb)->daddr,
682 ip_hdr(skb)->saddr,
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800683 &rep.th, IPPROTO_TCP,
684 arg.iov[0].iov_len);
685 }
686#endif
Arnaldo Carvalho de Meloeddc9ec2007-04-20 22:47:35 -0700687 arg.csum = csum_tcpudp_nofold(ip_hdr(skb)->daddr,
688 ip_hdr(skb)->saddr, /* XXX */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700689 arg.iov[0].iov_len, IPPROTO_TCP, 0);
690 arg.csumoffset = offsetof(struct tcphdr, check) / 2;
Patrick McHardyf0e48db2007-06-04 21:32:46 -0700691 if (twsk)
692 arg.bound_dev_if = twsk->tw_sk.tw_bound_dev_if;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700693
Denis V. Lunev7feb49c2008-04-03 14:32:00 -0700694 ip_send_reply(dev_net(skb->dev)->ipv4.tcp_sock, skb,
695 &arg, arg.iov[0].iov_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700696
697 TCP_INC_STATS_BH(TCP_MIB_OUTSEGS);
698}
699
700static void tcp_v4_timewait_ack(struct sock *sk, struct sk_buff *skb)
701{
Arnaldo Carvalho de Melo8feaf0c2005-08-09 20:09:30 -0700702 struct inet_timewait_sock *tw = inet_twsk(sk);
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800703 struct tcp_timewait_sock *tcptw = tcp_twsk(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700704
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800705 tcp_v4_send_ack(tcptw, skb, tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt,
Arnaldo Carvalho de Melo71742592006-11-17 10:57:30 -0200706 tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale,
707 tcptw->tw_ts_recent);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700708
Arnaldo Carvalho de Melo8feaf0c2005-08-09 20:09:30 -0700709 inet_twsk_put(tw);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700710}
711
Arnaldo Carvalho de Melo71742592006-11-17 10:57:30 -0200712static void tcp_v4_reqsk_send_ack(struct sk_buff *skb,
713 struct request_sock *req)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700714{
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800715 tcp_v4_send_ack(NULL, skb, tcp_rsk(req)->snt_isn + 1,
716 tcp_rsk(req)->rcv_isn + 1, req->rcv_wnd,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700717 req->ts_recent);
718}
719
Linus Torvalds1da177e2005-04-16 15:20:36 -0700720/*
Kris Katterjohn9bf1d832008-02-17 22:29:19 -0800721 * Send a SYN-ACK after having received a SYN.
Arnaldo Carvalho de Melo60236fd2005-06-18 22:47:21 -0700722 * This still operates on a request_sock only, not on a big
Linus Torvalds1da177e2005-04-16 15:20:36 -0700723 * socket.
724 */
Denis V. Lunevfd80eb92008-02-29 11:43:03 -0800725static int __tcp_v4_send_synack(struct sock *sk, struct request_sock *req,
726 struct dst_entry *dst)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700727{
Arnaldo Carvalho de Melo2e6599c2005-06-18 22:46:52 -0700728 const struct inet_request_sock *ireq = inet_rsk(req);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700729 int err = -1;
730 struct sk_buff * skb;
731
732 /* First, grab a route. */
Arnaldo Carvalho de Melo463c84b2005-08-09 20:10:42 -0700733 if (!dst && (dst = inet_csk_route_req(sk, req)) == NULL)
Denis V. Lunevfd80eb92008-02-29 11:43:03 -0800734 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700735
736 skb = tcp_make_synack(sk, dst, req);
737
738 if (skb) {
Arnaldo Carvalho de Meloaa8223c2007-04-10 21:04:22 -0700739 struct tcphdr *th = tcp_hdr(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700740
Frederik Deweerdtba7808e2007-02-04 20:15:27 -0800741 th->check = tcp_v4_check(skb->len,
Arnaldo Carvalho de Melo2e6599c2005-06-18 22:46:52 -0700742 ireq->loc_addr,
743 ireq->rmt_addr,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700744 csum_partial((char *)th, skb->len,
745 skb->csum));
746
Arnaldo Carvalho de Melo2e6599c2005-06-18 22:46:52 -0700747 err = ip_build_and_send_pkt(skb, sk, ireq->loc_addr,
748 ireq->rmt_addr,
749 ireq->opt);
Gerrit Renkerb9df3cb2006-11-14 11:21:36 -0200750 err = net_xmit_eval(err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700751 }
752
Linus Torvalds1da177e2005-04-16 15:20:36 -0700753 dst_release(dst);
754 return err;
755}
756
Denis V. Lunevfd80eb92008-02-29 11:43:03 -0800757static int tcp_v4_send_synack(struct sock *sk, struct request_sock *req)
758{
759 return __tcp_v4_send_synack(sk, req, NULL);
760}
761
Linus Torvalds1da177e2005-04-16 15:20:36 -0700762/*
Arnaldo Carvalho de Melo60236fd2005-06-18 22:47:21 -0700763 * IPv4 request_sock destructor.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700764 */
Arnaldo Carvalho de Melo60236fd2005-06-18 22:47:21 -0700765static void tcp_v4_reqsk_destructor(struct request_sock *req)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700766{
Jesper Juhla51482b2005-11-08 09:41:34 -0800767 kfree(inet_rsk(req)->opt);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700768}
769
Arnaldo Carvalho de Melo80e40da2006-01-04 01:58:06 -0200770#ifdef CONFIG_SYN_COOKIES
Stephen Hemminger40efc6f2006-01-03 16:03:49 -0800771static void syn_flood_warning(struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700772{
773 static unsigned long warntime;
774
775 if (time_after(jiffies, (warntime + HZ * 60))) {
776 warntime = jiffies;
777 printk(KERN_INFO
778 "possible SYN flooding on port %d. Sending cookies.\n",
Arnaldo Carvalho de Meloaa8223c2007-04-10 21:04:22 -0700779 ntohs(tcp_hdr(skb)->dest));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700780 }
781}
Arnaldo Carvalho de Melo80e40da2006-01-04 01:58:06 -0200782#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700783
784/*
Arnaldo Carvalho de Melo60236fd2005-06-18 22:47:21 -0700785 * Save and compile IPv4 options into the request_sock if needed.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700786 */
Stephen Hemminger40efc6f2006-01-03 16:03:49 -0800787static struct ip_options *tcp_v4_save_options(struct sock *sk,
788 struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700789{
790 struct ip_options *opt = &(IPCB(skb)->opt);
791 struct ip_options *dopt = NULL;
792
793 if (opt && opt->optlen) {
794 int opt_size = optlength(opt);
795 dopt = kmalloc(opt_size, GFP_ATOMIC);
796 if (dopt) {
797 if (ip_options_echo(dopt, skb)) {
798 kfree(dopt);
799 dopt = NULL;
800 }
801 }
802 }
803 return dopt;
804}
805
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800806#ifdef CONFIG_TCP_MD5SIG
807/*
808 * RFC2385 MD5 checksumming requires a mapping of
809 * IP address->MD5 Key.
810 * We need to maintain these in the sk structure.
811 */
812
813/* Find the Key structure for an address. */
Arnaldo Carvalho de Melo71742592006-11-17 10:57:30 -0200814static struct tcp_md5sig_key *
815 tcp_v4_md5_do_lookup(struct sock *sk, __be32 addr)
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800816{
817 struct tcp_sock *tp = tcp_sk(sk);
818 int i;
819
820 if (!tp->md5sig_info || !tp->md5sig_info->entries4)
821 return NULL;
822 for (i = 0; i < tp->md5sig_info->entries4; i++) {
823 if (tp->md5sig_info->keys4[i].addr == addr)
David S. Millerf8ab18d2007-09-28 15:18:35 -0700824 return &tp->md5sig_info->keys4[i].base;
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800825 }
826 return NULL;
827}
828
829struct tcp_md5sig_key *tcp_v4_md5_lookup(struct sock *sk,
830 struct sock *addr_sk)
831{
832 return tcp_v4_md5_do_lookup(sk, inet_sk(addr_sk)->daddr);
833}
834
835EXPORT_SYMBOL(tcp_v4_md5_lookup);
836
Adrian Bunkf5b99bc2006-11-30 17:22:29 -0800837static struct tcp_md5sig_key *tcp_v4_reqsk_md5_lookup(struct sock *sk,
838 struct request_sock *req)
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800839{
840 return tcp_v4_md5_do_lookup(sk, inet_rsk(req)->rmt_addr);
841}
842
843/* This can be called on a newly created socket, from other files */
844int tcp_v4_md5_do_add(struct sock *sk, __be32 addr,
845 u8 *newkey, u8 newkeylen)
846{
847 /* Add Key to the list */
Matthias M. Dellwegb0a713e2007-10-29 20:55:27 -0700848 struct tcp_md5sig_key *key;
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800849 struct tcp_sock *tp = tcp_sk(sk);
850 struct tcp4_md5sig_key *keys;
851
Matthias M. Dellwegb0a713e2007-10-29 20:55:27 -0700852 key = tcp_v4_md5_do_lookup(sk, addr);
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800853 if (key) {
854 /* Pre-existing entry - just update that one. */
Matthias M. Dellwegb0a713e2007-10-29 20:55:27 -0700855 kfree(key->key);
856 key->key = newkey;
857 key->keylen = newkeylen;
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800858 } else {
Arnaldo Carvalho de Melof6685932006-11-17 11:06:01 -0200859 struct tcp_md5sig_info *md5sig;
860
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800861 if (!tp->md5sig_info) {
Arnaldo Carvalho de Melof6685932006-11-17 11:06:01 -0200862 tp->md5sig_info = kzalloc(sizeof(*tp->md5sig_info),
863 GFP_ATOMIC);
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800864 if (!tp->md5sig_info) {
865 kfree(newkey);
866 return -ENOMEM;
867 }
David S. Miller3d7dbea2007-06-12 14:36:42 -0700868 sk->sk_route_caps &= ~NETIF_F_GSO_MASK;
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800869 }
870 if (tcp_alloc_md5sig_pool() == NULL) {
871 kfree(newkey);
872 return -ENOMEM;
873 }
Arnaldo Carvalho de Melof6685932006-11-17 11:06:01 -0200874 md5sig = tp->md5sig_info;
875
876 if (md5sig->alloced4 == md5sig->entries4) {
877 keys = kmalloc((sizeof(*keys) *
YOSHIFUJI Hideakie905a9e2007-02-09 23:24:47 +0900878 (md5sig->entries4 + 1)), GFP_ATOMIC);
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800879 if (!keys) {
880 kfree(newkey);
881 tcp_free_md5sig_pool();
882 return -ENOMEM;
883 }
884
Arnaldo Carvalho de Melof6685932006-11-17 11:06:01 -0200885 if (md5sig->entries4)
886 memcpy(keys, md5sig->keys4,
887 sizeof(*keys) * md5sig->entries4);
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800888
889 /* Free old key list, and reference new one */
YOSHIFUJI Hideakia80cc202007-11-20 17:30:06 -0800890 kfree(md5sig->keys4);
Arnaldo Carvalho de Melof6685932006-11-17 11:06:01 -0200891 md5sig->keys4 = keys;
892 md5sig->alloced4++;
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800893 }
Arnaldo Carvalho de Melof6685932006-11-17 11:06:01 -0200894 md5sig->entries4++;
David S. Millerf8ab18d2007-09-28 15:18:35 -0700895 md5sig->keys4[md5sig->entries4 - 1].addr = addr;
896 md5sig->keys4[md5sig->entries4 - 1].base.key = newkey;
897 md5sig->keys4[md5sig->entries4 - 1].base.keylen = newkeylen;
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800898 }
899 return 0;
900}
901
902EXPORT_SYMBOL(tcp_v4_md5_do_add);
903
904static int tcp_v4_md5_add_func(struct sock *sk, struct sock *addr_sk,
905 u8 *newkey, u8 newkeylen)
906{
907 return tcp_v4_md5_do_add(sk, inet_sk(addr_sk)->daddr,
908 newkey, newkeylen);
909}
910
911int tcp_v4_md5_do_del(struct sock *sk, __be32 addr)
912{
913 struct tcp_sock *tp = tcp_sk(sk);
914 int i;
915
916 for (i = 0; i < tp->md5sig_info->entries4; i++) {
917 if (tp->md5sig_info->keys4[i].addr == addr) {
918 /* Free the key */
David S. Millerf8ab18d2007-09-28 15:18:35 -0700919 kfree(tp->md5sig_info->keys4[i].base.key);
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800920 tp->md5sig_info->entries4--;
921
922 if (tp->md5sig_info->entries4 == 0) {
923 kfree(tp->md5sig_info->keys4);
924 tp->md5sig_info->keys4 = NULL;
Leigh Brown8228a18d2006-12-17 17:12:30 -0800925 tp->md5sig_info->alloced4 = 0;
Arnaldo Carvalho de Melo71742592006-11-17 10:57:30 -0200926 } else if (tp->md5sig_info->entries4 != i) {
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800927 /* Need to do some manipulation */
YOSHIFUJI Hideaki354faf02007-11-20 17:30:31 -0800928 memmove(&tp->md5sig_info->keys4[i],
929 &tp->md5sig_info->keys4[i+1],
930 (tp->md5sig_info->entries4 - i) *
931 sizeof(struct tcp4_md5sig_key));
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800932 }
933 tcp_free_md5sig_pool();
934 return 0;
935 }
936 }
937 return -ENOENT;
938}
939
940EXPORT_SYMBOL(tcp_v4_md5_do_del);
941
Arnaldo Carvalho de Melo71742592006-11-17 10:57:30 -0200942static void tcp_v4_clear_md5_list(struct sock *sk)
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800943{
944 struct tcp_sock *tp = tcp_sk(sk);
945
946 /* Free each key, then the set of key keys,
947 * the crypto element, and then decrement our
948 * hold on the last resort crypto.
949 */
950 if (tp->md5sig_info->entries4) {
951 int i;
952 for (i = 0; i < tp->md5sig_info->entries4; i++)
David S. Millerf8ab18d2007-09-28 15:18:35 -0700953 kfree(tp->md5sig_info->keys4[i].base.key);
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800954 tp->md5sig_info->entries4 = 0;
955 tcp_free_md5sig_pool();
956 }
957 if (tp->md5sig_info->keys4) {
958 kfree(tp->md5sig_info->keys4);
959 tp->md5sig_info->keys4 = NULL;
960 tp->md5sig_info->alloced4 = 0;
961 }
962}
963
Arnaldo Carvalho de Melo71742592006-11-17 10:57:30 -0200964static int tcp_v4_parse_md5_keys(struct sock *sk, char __user *optval,
965 int optlen)
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800966{
967 struct tcp_md5sig cmd;
968 struct sockaddr_in *sin = (struct sockaddr_in *)&cmd.tcpm_addr;
969 u8 *newkey;
970
971 if (optlen < sizeof(cmd))
972 return -EINVAL;
973
Arnaldo Carvalho de Melo71742592006-11-17 10:57:30 -0200974 if (copy_from_user(&cmd, optval, sizeof(cmd)))
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800975 return -EFAULT;
976
977 if (sin->sin_family != AF_INET)
978 return -EINVAL;
979
980 if (!cmd.tcpm_key || !cmd.tcpm_keylen) {
981 if (!tcp_sk(sk)->md5sig_info)
982 return -ENOENT;
983 return tcp_v4_md5_do_del(sk, sin->sin_addr.s_addr);
984 }
985
986 if (cmd.tcpm_keylen > TCP_MD5SIG_MAXKEYLEN)
987 return -EINVAL;
988
989 if (!tcp_sk(sk)->md5sig_info) {
990 struct tcp_sock *tp = tcp_sk(sk);
Arnaldo Carvalho de Melo71742592006-11-17 10:57:30 -0200991 struct tcp_md5sig_info *p = kzalloc(sizeof(*p), GFP_KERNEL);
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800992
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800993 if (!p)
994 return -EINVAL;
995
996 tp->md5sig_info = p;
David S. Miller3d7dbea2007-06-12 14:36:42 -0700997 sk->sk_route_caps &= ~NETIF_F_GSO_MASK;
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800998 }
999
Arnaldo Carvalho de Melof6685932006-11-17 11:06:01 -02001000 newkey = kmemdup(cmd.tcpm_key, cmd.tcpm_keylen, GFP_KERNEL);
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -08001001 if (!newkey)
1002 return -ENOMEM;
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -08001003 return tcp_v4_md5_do_add(sk, sin->sin_addr.s_addr,
1004 newkey, cmd.tcpm_keylen);
1005}
1006
1007static int tcp_v4_do_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key,
1008 __be32 saddr, __be32 daddr,
1009 struct tcphdr *th, int protocol,
YOSHIFUJI Hideaki9cb57342008-01-12 02:16:03 -08001010 unsigned int tcplen)
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -08001011{
1012 struct scatterlist sg[4];
1013 __u16 data_len;
1014 int block = 0;
Al Viro8e5200f2006-11-20 18:06:37 -08001015 __sum16 old_checksum;
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -08001016 struct tcp_md5sig_pool *hp;
1017 struct tcp4_pseudohdr *bp;
1018 struct hash_desc *desc;
1019 int err;
1020 unsigned int nbytes = 0;
1021
1022 /*
1023 * Okay, so RFC2385 is turned on for this connection,
1024 * so we need to generate the MD5 hash for the packet now.
1025 */
1026
1027 hp = tcp_get_md5sig_pool();
1028 if (!hp)
1029 goto clear_hash_noput;
1030
1031 bp = &hp->md5_blk.ip4;
1032 desc = &hp->md5_desc;
1033
1034 /*
1035 * 1. the TCP pseudo-header (in the order: source IP address,
1036 * destination IP address, zero-padded protocol number, and
1037 * segment length)
1038 */
1039 bp->saddr = saddr;
1040 bp->daddr = daddr;
1041 bp->pad = 0;
1042 bp->protocol = protocol;
1043 bp->len = htons(tcplen);
David S. Millerc7da57a2007-10-26 00:41:21 -07001044
1045 sg_init_table(sg, 4);
1046
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -08001047 sg_set_buf(&sg[block++], bp, sizeof(*bp));
1048 nbytes += sizeof(*bp);
1049
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -08001050 /* 2. the TCP header, excluding options, and assuming a
1051 * checksum of zero/
1052 */
1053 old_checksum = th->check;
1054 th->check = 0;
1055 sg_set_buf(&sg[block++], th, sizeof(struct tcphdr));
1056 nbytes += sizeof(struct tcphdr);
David S. Miller08dd1a52006-11-30 16:35:01 -08001057
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -08001058 /* 3. the TCP segment data (if any) */
1059 data_len = tcplen - (th->doff << 2);
1060 if (data_len > 0) {
1061 unsigned char *data = (unsigned char *)th + (th->doff << 2);
1062 sg_set_buf(&sg[block++], data, data_len);
1063 nbytes += data_len;
1064 }
1065
1066 /* 4. an independently-specified key or password, known to both
1067 * TCPs and presumably connection-specific
1068 */
1069 sg_set_buf(&sg[block++], key->key, key->keylen);
1070 nbytes += key->keylen;
1071
Jens Axboec46f2332007-10-31 12:06:37 +01001072 sg_mark_end(&sg[block - 1]);
David S. Millerc7da57a2007-10-26 00:41:21 -07001073
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -08001074 /* Now store the Hash into the packet */
1075 err = crypto_hash_init(desc);
1076 if (err)
1077 goto clear_hash;
1078 err = crypto_hash_update(desc, sg, nbytes);
1079 if (err)
1080 goto clear_hash;
1081 err = crypto_hash_final(desc, md5_hash);
1082 if (err)
1083 goto clear_hash;
1084
1085 /* Reset header, and free up the crypto */
1086 tcp_put_md5sig_pool();
1087 th->check = old_checksum;
1088
1089out:
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -08001090 return 0;
1091clear_hash:
1092 tcp_put_md5sig_pool();
1093clear_hash_noput:
1094 memset(md5_hash, 0, 16);
1095 goto out;
1096}
1097
1098int tcp_v4_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key,
1099 struct sock *sk,
1100 struct dst_entry *dst,
1101 struct request_sock *req,
1102 struct tcphdr *th, int protocol,
YOSHIFUJI Hideaki9cb57342008-01-12 02:16:03 -08001103 unsigned int tcplen)
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -08001104{
1105 __be32 saddr, daddr;
1106
1107 if (sk) {
1108 saddr = inet_sk(sk)->saddr;
1109 daddr = inet_sk(sk)->daddr;
1110 } else {
1111 struct rtable *rt = (struct rtable *)dst;
1112 BUG_ON(!rt);
1113 saddr = rt->rt_src;
1114 daddr = rt->rt_dst;
1115 }
1116 return tcp_v4_do_calc_md5_hash(md5_hash, key,
1117 saddr, daddr,
1118 th, protocol, tcplen);
1119}
1120
1121EXPORT_SYMBOL(tcp_v4_calc_md5_hash);
1122
Arnaldo Carvalho de Melo71742592006-11-17 10:57:30 -02001123static int tcp_v4_inbound_md5_hash(struct sock *sk, struct sk_buff *skb)
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -08001124{
1125 /*
1126 * This gets called for each TCP segment that arrives
1127 * so we want to be efficient.
1128 * We have 3 drop cases:
1129 * o No MD5 hash and one expected.
1130 * o MD5 hash and we're not expecting one.
1131 * o MD5 hash and its wrong.
1132 */
1133 __u8 *hash_location = NULL;
1134 struct tcp_md5sig_key *hash_expected;
Arnaldo Carvalho de Meloeddc9ec2007-04-20 22:47:35 -07001135 const struct iphdr *iph = ip_hdr(skb);
Arnaldo Carvalho de Meloaa8223c2007-04-10 21:04:22 -07001136 struct tcphdr *th = tcp_hdr(skb);
Arnaldo Carvalho de Melo71742592006-11-17 10:57:30 -02001137 int length = (th->doff << 2) - sizeof(struct tcphdr);
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -08001138 int genhash;
1139 unsigned char *ptr;
1140 unsigned char newhash[16];
1141
1142 hash_expected = tcp_v4_md5_do_lookup(sk, iph->saddr);
1143
1144 /*
1145 * If the TCP option length is less than the TCP_MD5SIG
1146 * option length, then we can shortcut
1147 */
1148 if (length < TCPOLEN_MD5SIG) {
1149 if (hash_expected)
1150 return 1;
1151 else
1152 return 0;
1153 }
1154
1155 /* Okay, we can't shortcut - we have to grub through the options */
1156 ptr = (unsigned char *)(th + 1);
1157 while (length > 0) {
1158 int opcode = *ptr++;
1159 int opsize;
1160
1161 switch (opcode) {
1162 case TCPOPT_EOL:
1163 goto done_opts;
1164 case TCPOPT_NOP:
1165 length--;
1166 continue;
1167 default:
1168 opsize = *ptr++;
1169 if (opsize < 2)
1170 goto done_opts;
1171 if (opsize > length)
1172 goto done_opts;
1173
1174 if (opcode == TCPOPT_MD5SIG) {
1175 hash_location = ptr;
1176 goto done_opts;
1177 }
1178 }
1179 ptr += opsize-2;
1180 length -= opsize;
1181 }
1182done_opts:
1183 /* We've parsed the options - do we have a hash? */
1184 if (!hash_expected && !hash_location)
1185 return 0;
1186
1187 if (hash_expected && !hash_location) {
Leigh Browna9fc00c2006-12-17 17:13:10 -08001188 LIMIT_NETDEBUG(KERN_INFO "MD5 Hash expected but NOT found "
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -08001189 "(" NIPQUAD_FMT ", %d)->(" NIPQUAD_FMT ", %d)\n",
Arnaldo Carvalho de Melo71742592006-11-17 10:57:30 -02001190 NIPQUAD(iph->saddr), ntohs(th->source),
1191 NIPQUAD(iph->daddr), ntohs(th->dest));
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -08001192 return 1;
1193 }
1194
1195 if (!hash_expected && hash_location) {
Arnaldo Carvalho de Melo71742592006-11-17 10:57:30 -02001196 LIMIT_NETDEBUG(KERN_INFO "MD5 Hash NOT expected but found "
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -08001197 "(" NIPQUAD_FMT ", %d)->(" NIPQUAD_FMT ", %d)\n",
Arnaldo Carvalho de Melo71742592006-11-17 10:57:30 -02001198 NIPQUAD(iph->saddr), ntohs(th->source),
1199 NIPQUAD(iph->daddr), ntohs(th->dest));
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -08001200 return 1;
1201 }
1202
1203 /* Okay, so this is hash_expected and hash_location -
1204 * so we need to calculate the checksum.
1205 */
1206 genhash = tcp_v4_do_calc_md5_hash(newhash,
1207 hash_expected,
1208 iph->saddr, iph->daddr,
1209 th, sk->sk_protocol,
1210 skb->len);
1211
1212 if (genhash || memcmp(hash_location, newhash, 16) != 0) {
1213 if (net_ratelimit()) {
1214 printk(KERN_INFO "MD5 Hash failed for "
1215 "(" NIPQUAD_FMT ", %d)->(" NIPQUAD_FMT ", %d)%s\n",
Arnaldo Carvalho de Melo71742592006-11-17 10:57:30 -02001216 NIPQUAD(iph->saddr), ntohs(th->source),
1217 NIPQUAD(iph->daddr), ntohs(th->dest),
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -08001218 genhash ? " tcp_v4_calc_md5_hash failed" : "");
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -08001219 }
1220 return 1;
1221 }
1222 return 0;
1223}
1224
1225#endif
1226
Eric Dumazet72a3eff2006-11-16 02:30:37 -08001227struct request_sock_ops tcp_request_sock_ops __read_mostly = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001228 .family = PF_INET,
Arnaldo Carvalho de Melo2e6599c2005-06-18 22:46:52 -07001229 .obj_size = sizeof(struct tcp_request_sock),
Linus Torvalds1da177e2005-04-16 15:20:36 -07001230 .rtx_syn_ack = tcp_v4_send_synack,
Arnaldo Carvalho de Melo60236fd2005-06-18 22:47:21 -07001231 .send_ack = tcp_v4_reqsk_send_ack,
1232 .destructor = tcp_v4_reqsk_destructor,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001233 .send_reset = tcp_v4_send_reset,
1234};
1235
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -08001236#ifdef CONFIG_TCP_MD5SIG
Andrew Mortonb6332e62006-11-30 19:16:28 -08001237static struct tcp_request_sock_ops tcp_request_sock_ipv4_ops = {
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -08001238 .md5_lookup = tcp_v4_reqsk_md5_lookup,
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -08001239};
Andrew Mortonb6332e62006-11-30 19:16:28 -08001240#endif
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -08001241
Arnaldo Carvalho de Melo6d6ee432005-12-13 23:25:19 -08001242static struct timewait_sock_ops tcp_timewait_sock_ops = {
1243 .twsk_obj_size = sizeof(struct tcp_timewait_sock),
1244 .twsk_unique = tcp_twsk_unique,
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -08001245 .twsk_destructor= tcp_twsk_destructor,
Arnaldo Carvalho de Melo6d6ee432005-12-13 23:25:19 -08001246};
1247
Linus Torvalds1da177e2005-04-16 15:20:36 -07001248int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
1249{
Arnaldo Carvalho de Melo2e6599c2005-06-18 22:46:52 -07001250 struct inet_request_sock *ireq;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001251 struct tcp_options_received tmp_opt;
Arnaldo Carvalho de Melo60236fd2005-06-18 22:47:21 -07001252 struct request_sock *req;
Arnaldo Carvalho de Meloeddc9ec2007-04-20 22:47:35 -07001253 __be32 saddr = ip_hdr(skb)->saddr;
1254 __be32 daddr = ip_hdr(skb)->daddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001255 __u32 isn = TCP_SKB_CB(skb)->when;
1256 struct dst_entry *dst = NULL;
1257#ifdef CONFIG_SYN_COOKIES
1258 int want_cookie = 0;
1259#else
1260#define want_cookie 0 /* Argh, why doesn't gcc optimize this :( */
1261#endif
1262
1263 /* Never answer to SYNs send to broadcast or multicast */
Eric Dumazetee6b9672008-03-05 18:30:47 -08001264 if (skb->rtable->rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001265 goto drop;
1266
1267 /* TW buckets are converted to open requests without
1268 * limitations, they conserve resources and peer is
1269 * evidently real one.
1270 */
Arnaldo Carvalho de Melo463c84b2005-08-09 20:10:42 -07001271 if (inet_csk_reqsk_queue_is_full(sk) && !isn) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001272#ifdef CONFIG_SYN_COOKIES
1273 if (sysctl_tcp_syncookies) {
1274 want_cookie = 1;
1275 } else
1276#endif
1277 goto drop;
1278 }
1279
1280 /* Accept backlog is full. If we have already queued enough
1281 * of warm entries in syn queue, drop request. It is better than
1282 * clogging syn queue with openreqs with exponentially increasing
1283 * timeout.
1284 */
Arnaldo Carvalho de Melo463c84b2005-08-09 20:10:42 -07001285 if (sk_acceptq_is_full(sk) && inet_csk_reqsk_queue_young(sk) > 1)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001286 goto drop;
1287
Arnaldo Carvalho de Melo60236fd2005-06-18 22:47:21 -07001288 req = reqsk_alloc(&tcp_request_sock_ops);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001289 if (!req)
1290 goto drop;
1291
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -08001292#ifdef CONFIG_TCP_MD5SIG
1293 tcp_rsk(req)->af_specific = &tcp_request_sock_ipv4_ops;
1294#endif
1295
Linus Torvalds1da177e2005-04-16 15:20:36 -07001296 tcp_clear_options(&tmp_opt);
1297 tmp_opt.mss_clamp = 536;
1298 tmp_opt.user_mss = tcp_sk(sk)->rx_opt.user_mss;
1299
1300 tcp_parse_options(skb, &tmp_opt, 0);
1301
1302 if (want_cookie) {
1303 tcp_clear_options(&tmp_opt);
1304 tmp_opt.saw_tstamp = 0;
1305 }
1306
1307 if (tmp_opt.saw_tstamp && !tmp_opt.rcv_tsval) {
1308 /* Some OSes (unknown ones, but I see them on web server, which
1309 * contains information interesting only for windows'
1310 * users) do not send their stamp in SYN. It is easy case.
1311 * We simply do not advertise TS support.
1312 */
1313 tmp_opt.saw_tstamp = 0;
1314 tmp_opt.tstamp_ok = 0;
1315 }
1316 tmp_opt.tstamp_ok = tmp_opt.saw_tstamp;
1317
1318 tcp_openreq_init(req, &tmp_opt, skb);
1319
Venkat Yekkirala4237c752006-07-24 23:32:50 -07001320 if (security_inet_conn_request(sk, skb, req))
1321 goto drop_and_free;
1322
Arnaldo Carvalho de Melo2e6599c2005-06-18 22:46:52 -07001323 ireq = inet_rsk(req);
1324 ireq->loc_addr = daddr;
1325 ireq->rmt_addr = saddr;
1326 ireq->opt = tcp_v4_save_options(sk, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001327 if (!want_cookie)
Arnaldo Carvalho de Meloaa8223c2007-04-10 21:04:22 -07001328 TCP_ECN_create_request(req, tcp_hdr(skb));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001329
1330 if (want_cookie) {
1331#ifdef CONFIG_SYN_COOKIES
1332 syn_flood_warning(skb);
1333#endif
1334 isn = cookie_v4_init_sequence(sk, skb, &req->mss);
1335 } else if (!isn) {
1336 struct inet_peer *peer = NULL;
1337
1338 /* VJ's idea. We save last timestamp seen
1339 * from the destination in peer table, when entering
1340 * state TIME-WAIT, and check against it before
1341 * accepting new connection request.
1342 *
1343 * If "isn" is not zero, this request hit alive
1344 * timewait bucket, so that all the necessary checks
1345 * are made in the function processing timewait state.
1346 */
1347 if (tmp_opt.saw_tstamp &&
Arnaldo Carvalho de Melo295ff7e2005-08-09 20:44:40 -07001348 tcp_death_row.sysctl_tw_recycle &&
Arnaldo Carvalho de Melo463c84b2005-08-09 20:10:42 -07001349 (dst = inet_csk_route_req(sk, req)) != NULL &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07001350 (peer = rt_get_peer((struct rtable *)dst)) != NULL &&
1351 peer->v4daddr == saddr) {
James Morris9d729f72007-03-04 16:12:44 -08001352 if (get_seconds() < peer->tcp_ts_stamp + TCP_PAWS_MSL &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07001353 (s32)(peer->tcp_ts - req->ts_recent) >
1354 TCP_PAWS_WINDOW) {
1355 NET_INC_STATS_BH(LINUX_MIB_PAWSPASSIVEREJECTED);
Denis V. Lunev7cd04fa2008-03-03 11:59:32 -08001356 goto drop_and_release;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001357 }
1358 }
1359 /* Kill the following clause, if you dislike this way. */
1360 else if (!sysctl_tcp_syncookies &&
Arnaldo Carvalho de Melo463c84b2005-08-09 20:10:42 -07001361 (sysctl_max_syn_backlog - inet_csk_reqsk_queue_len(sk) <
Linus Torvalds1da177e2005-04-16 15:20:36 -07001362 (sysctl_max_syn_backlog >> 2)) &&
1363 (!peer || !peer->tcp_ts_stamp) &&
1364 (!dst || !dst_metric(dst, RTAX_RTT))) {
1365 /* Without syncookies last quarter of
1366 * backlog is filled with destinations,
1367 * proven to be alive.
1368 * It means that we continue to communicate
1369 * to destinations, already remembered
1370 * to the moment of synflood.
1371 */
Patrick McHardy64ce2072005-08-09 20:50:53 -07001372 LIMIT_NETDEBUG(KERN_DEBUG "TCP: drop open "
1373 "request from %u.%u.%u.%u/%u\n",
1374 NIPQUAD(saddr),
Arnaldo Carvalho de Meloaa8223c2007-04-10 21:04:22 -07001375 ntohs(tcp_hdr(skb)->source));
Denis V. Lunev7cd04fa2008-03-03 11:59:32 -08001376 goto drop_and_release;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001377 }
1378
Gerrit Renkera94f7232006-11-10 14:06:49 -08001379 isn = tcp_v4_init_sequence(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001380 }
Arnaldo Carvalho de Melo2e6599c2005-06-18 22:46:52 -07001381 tcp_rsk(req)->snt_isn = isn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001382
Denis V. Lunev7cd04fa2008-03-03 11:59:32 -08001383 if (__tcp_v4_send_synack(sk, req, dst) || want_cookie)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001384 goto drop_and_free;
1385
Denis V. Lunev7cd04fa2008-03-03 11:59:32 -08001386 inet_csk_reqsk_queue_hash_add(sk, req, TCP_TIMEOUT_INIT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001387 return 0;
1388
Denis V. Lunev7cd04fa2008-03-03 11:59:32 -08001389drop_and_release:
1390 dst_release(dst);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001391drop_and_free:
Arnaldo Carvalho de Melo60236fd2005-06-18 22:47:21 -07001392 reqsk_free(req);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001393drop:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001394 return 0;
1395}
1396
1397
1398/*
1399 * The three way handshake has completed - we got a valid synack -
1400 * now create the new socket.
1401 */
1402struct sock *tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
Arnaldo Carvalho de Melo60236fd2005-06-18 22:47:21 -07001403 struct request_sock *req,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001404 struct dst_entry *dst)
1405{
Arnaldo Carvalho de Melo2e6599c2005-06-18 22:46:52 -07001406 struct inet_request_sock *ireq;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001407 struct inet_sock *newinet;
1408 struct tcp_sock *newtp;
1409 struct sock *newsk;
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -08001410#ifdef CONFIG_TCP_MD5SIG
1411 struct tcp_md5sig_key *key;
1412#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07001413
1414 if (sk_acceptq_is_full(sk))
1415 goto exit_overflow;
1416
Arnaldo Carvalho de Melo463c84b2005-08-09 20:10:42 -07001417 if (!dst && (dst = inet_csk_route_req(sk, req)) == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001418 goto exit;
1419
1420 newsk = tcp_create_openreq_child(sk, req, skb);
1421 if (!newsk)
1422 goto exit;
1423
Herbert Xubcd76112006-06-30 13:36:35 -07001424 newsk->sk_gso_type = SKB_GSO_TCPV4;
Arnaldo Carvalho de Melo6cbb0df2005-08-09 19:49:02 -07001425 sk_setup_caps(newsk, dst);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001426
1427 newtp = tcp_sk(newsk);
1428 newinet = inet_sk(newsk);
Arnaldo Carvalho de Melo2e6599c2005-06-18 22:46:52 -07001429 ireq = inet_rsk(req);
1430 newinet->daddr = ireq->rmt_addr;
1431 newinet->rcv_saddr = ireq->loc_addr;
1432 newinet->saddr = ireq->loc_addr;
1433 newinet->opt = ireq->opt;
1434 ireq->opt = NULL;
Arnaldo Carvalho de Melo463c84b2005-08-09 20:10:42 -07001435 newinet->mc_index = inet_iif(skb);
Arnaldo Carvalho de Meloeddc9ec2007-04-20 22:47:35 -07001436 newinet->mc_ttl = ip_hdr(skb)->ttl;
Arnaldo Carvalho de Melod83d8462005-12-13 23:26:10 -08001437 inet_csk(newsk)->icsk_ext_hdr_len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001438 if (newinet->opt)
Arnaldo Carvalho de Melod83d8462005-12-13 23:26:10 -08001439 inet_csk(newsk)->icsk_ext_hdr_len = newinet->opt->optlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001440 newinet->id = newtp->write_seq ^ jiffies;
1441
John Heffner5d424d52006-03-20 17:53:41 -08001442 tcp_mtup_init(newsk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001443 tcp_sync_mss(newsk, dst_mtu(dst));
1444 newtp->advmss = dst_metric(dst, RTAX_ADVMSS);
1445 tcp_initialize_rcv_mss(newsk);
1446
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -08001447#ifdef CONFIG_TCP_MD5SIG
1448 /* Copy over the MD5 key from the original socket */
1449 if ((key = tcp_v4_md5_do_lookup(sk, newinet->daddr)) != NULL) {
1450 /*
1451 * We're using one, so create a matching key
1452 * on the newsk structure. If we fail to get
1453 * memory, then we end up not copying the key
1454 * across. Shucks.
1455 */
Arnaldo Carvalho de Melof6685932006-11-17 11:06:01 -02001456 char *newkey = kmemdup(key->key, key->keylen, GFP_ATOMIC);
1457 if (newkey != NULL)
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -08001458 tcp_v4_md5_do_add(newsk, inet_sk(sk)->daddr,
1459 newkey, key->keylen);
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -08001460 }
1461#endif
1462
Arnaldo Carvalho de Meloab1e0a12008-02-03 04:06:04 -08001463 __inet_hash_nolisten(newsk);
1464 __inet_inherit_port(sk, newsk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001465
1466 return newsk;
1467
1468exit_overflow:
1469 NET_INC_STATS_BH(LINUX_MIB_LISTENOVERFLOWS);
1470exit:
1471 NET_INC_STATS_BH(LINUX_MIB_LISTENDROPS);
1472 dst_release(dst);
1473 return NULL;
1474}
1475
1476static struct sock *tcp_v4_hnd_req(struct sock *sk, struct sk_buff *skb)
1477{
Arnaldo Carvalho de Meloaa8223c2007-04-10 21:04:22 -07001478 struct tcphdr *th = tcp_hdr(skb);
Arnaldo Carvalho de Meloeddc9ec2007-04-20 22:47:35 -07001479 const struct iphdr *iph = ip_hdr(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001480 struct sock *nsk;
Arnaldo Carvalho de Melo60236fd2005-06-18 22:47:21 -07001481 struct request_sock **prev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001482 /* Find possible connection requests. */
Arnaldo Carvalho de Melo463c84b2005-08-09 20:10:42 -07001483 struct request_sock *req = inet_csk_search_req(sk, &prev, th->source,
1484 iph->saddr, iph->daddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001485 if (req)
1486 return tcp_check_req(sk, skb, req, prev);
1487
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09001488 nsk = inet_lookup_established(sock_net(sk), &tcp_hashinfo, iph->saddr,
Pavel Emelyanovc67499c2008-01-31 05:06:40 -08001489 th->source, iph->daddr, th->dest, inet_iif(skb));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001490
1491 if (nsk) {
1492 if (nsk->sk_state != TCP_TIME_WAIT) {
1493 bh_lock_sock(nsk);
1494 return nsk;
1495 }
YOSHIFUJI Hideaki9469c7b2006-10-10 19:41:46 -07001496 inet_twsk_put(inet_twsk(nsk));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001497 return NULL;
1498 }
1499
1500#ifdef CONFIG_SYN_COOKIES
1501 if (!th->rst && !th->syn && th->ack)
1502 sk = cookie_v4_check(sk, skb, &(IPCB(skb)->opt));
1503#endif
1504 return sk;
1505}
1506
Al Virob51655b2006-11-14 21:40:42 -08001507static __sum16 tcp_v4_checksum_init(struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001508{
Arnaldo Carvalho de Meloeddc9ec2007-04-20 22:47:35 -07001509 const struct iphdr *iph = ip_hdr(skb);
1510
Patrick McHardy84fa7932006-08-29 16:44:56 -07001511 if (skb->ip_summed == CHECKSUM_COMPLETE) {
Arnaldo Carvalho de Meloeddc9ec2007-04-20 22:47:35 -07001512 if (!tcp_v4_check(skb->len, iph->saddr,
1513 iph->daddr, skb->csum)) {
Herbert Xufb286bb2005-11-10 13:01:24 -08001514 skb->ip_summed = CHECKSUM_UNNECESSARY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001515 return 0;
Herbert Xufb286bb2005-11-10 13:01:24 -08001516 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001517 }
Herbert Xufb286bb2005-11-10 13:01:24 -08001518
Arnaldo Carvalho de Meloeddc9ec2007-04-20 22:47:35 -07001519 skb->csum = csum_tcpudp_nofold(iph->saddr, iph->daddr,
Herbert Xufb286bb2005-11-10 13:01:24 -08001520 skb->len, IPPROTO_TCP, 0);
1521
Linus Torvalds1da177e2005-04-16 15:20:36 -07001522 if (skb->len <= 76) {
Herbert Xufb286bb2005-11-10 13:01:24 -08001523 return __skb_checksum_complete(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001524 }
1525 return 0;
1526}
1527
1528
1529/* The socket must have it's spinlock held when we get
1530 * here.
1531 *
1532 * We have a potential double-lock case here, so even when
1533 * doing backlog processing we use the BH locking scheme.
1534 * This is because we cannot sleep with the original spinlock
1535 * held.
1536 */
1537int tcp_v4_do_rcv(struct sock *sk, struct sk_buff *skb)
1538{
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -08001539 struct sock *rsk;
1540#ifdef CONFIG_TCP_MD5SIG
1541 /*
1542 * We really want to reject the packet as early as possible
1543 * if:
1544 * o We're expecting an MD5'd packet and this is no MD5 tcp option
1545 * o There is an MD5 option and we're not expecting one
1546 */
Arnaldo Carvalho de Melo71742592006-11-17 10:57:30 -02001547 if (tcp_v4_inbound_md5_hash(sk, skb))
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -08001548 goto discard;
1549#endif
1550
Linus Torvalds1da177e2005-04-16 15:20:36 -07001551 if (sk->sk_state == TCP_ESTABLISHED) { /* Fast path */
1552 TCP_CHECK_TIMER(sk);
Arnaldo Carvalho de Meloaa8223c2007-04-10 21:04:22 -07001553 if (tcp_rcv_established(sk, skb, tcp_hdr(skb), skb->len)) {
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -08001554 rsk = sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001555 goto reset;
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -08001556 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001557 TCP_CHECK_TIMER(sk);
1558 return 0;
1559 }
1560
Arnaldo Carvalho de Meloab6a5bb2007-03-18 17:43:48 -07001561 if (skb->len < tcp_hdrlen(skb) || tcp_checksum_complete(skb))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001562 goto csum_err;
1563
1564 if (sk->sk_state == TCP_LISTEN) {
1565 struct sock *nsk = tcp_v4_hnd_req(sk, skb);
1566 if (!nsk)
1567 goto discard;
1568
1569 if (nsk != sk) {
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -08001570 if (tcp_child_process(sk, nsk, skb)) {
1571 rsk = nsk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001572 goto reset;
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -08001573 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001574 return 0;
1575 }
1576 }
1577
1578 TCP_CHECK_TIMER(sk);
Arnaldo Carvalho de Meloaa8223c2007-04-10 21:04:22 -07001579 if (tcp_rcv_state_process(sk, skb, tcp_hdr(skb), skb->len)) {
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -08001580 rsk = sk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001581 goto reset;
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -08001582 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001583 TCP_CHECK_TIMER(sk);
1584 return 0;
1585
1586reset:
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -08001587 tcp_v4_send_reset(rsk, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001588discard:
1589 kfree_skb(skb);
1590 /* Be careful here. If this function gets more complicated and
1591 * gcc suffers from register pressure on the x86, sk (in %ebx)
1592 * might be destroyed here. This current version compiles correctly,
1593 * but you have been warned.
1594 */
1595 return 0;
1596
1597csum_err:
1598 TCP_INC_STATS_BH(TCP_MIB_INERRS);
1599 goto discard;
1600}
1601
1602/*
1603 * From tcp_input.c
1604 */
1605
1606int tcp_v4_rcv(struct sk_buff *skb)
1607{
Arnaldo Carvalho de Meloeddc9ec2007-04-20 22:47:35 -07001608 const struct iphdr *iph;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001609 struct tcphdr *th;
1610 struct sock *sk;
1611 int ret;
1612
1613 if (skb->pkt_type != PACKET_HOST)
1614 goto discard_it;
1615
1616 /* Count it even if it's bad */
1617 TCP_INC_STATS_BH(TCP_MIB_INSEGS);
1618
1619 if (!pskb_may_pull(skb, sizeof(struct tcphdr)))
1620 goto discard_it;
1621
Arnaldo Carvalho de Meloaa8223c2007-04-10 21:04:22 -07001622 th = tcp_hdr(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001623
1624 if (th->doff < sizeof(struct tcphdr) / 4)
1625 goto bad_packet;
1626 if (!pskb_may_pull(skb, th->doff * 4))
1627 goto discard_it;
1628
1629 /* An explanation is required here, I think.
1630 * Packet length and doff are validated by header prediction,
Stephen Hemmingercaa20d9a2005-11-10 17:13:47 -08001631 * provided case of th->doff==0 is eliminated.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001632 * So, we defer the checks. */
Herbert Xu60476372007-04-09 11:59:39 -07001633 if (!skb_csum_unnecessary(skb) && tcp_v4_checksum_init(skb))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001634 goto bad_packet;
1635
Arnaldo Carvalho de Meloaa8223c2007-04-10 21:04:22 -07001636 th = tcp_hdr(skb);
Arnaldo Carvalho de Meloeddc9ec2007-04-20 22:47:35 -07001637 iph = ip_hdr(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001638 TCP_SKB_CB(skb)->seq = ntohl(th->seq);
1639 TCP_SKB_CB(skb)->end_seq = (TCP_SKB_CB(skb)->seq + th->syn + th->fin +
1640 skb->len - th->doff * 4);
1641 TCP_SKB_CB(skb)->ack_seq = ntohl(th->ack_seq);
1642 TCP_SKB_CB(skb)->when = 0;
Arnaldo Carvalho de Meloeddc9ec2007-04-20 22:47:35 -07001643 TCP_SKB_CB(skb)->flags = iph->tos;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001644 TCP_SKB_CB(skb)->sacked = 0;
1645
YOSHIFUJI Hideakic346dca2008-03-25 21:47:49 +09001646 sk = __inet_lookup(dev_net(skb->dev), &tcp_hashinfo, iph->saddr,
Pavel Emelyanovc67499c2008-01-31 05:06:40 -08001647 th->source, iph->daddr, th->dest, inet_iif(skb));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001648 if (!sk)
1649 goto no_tcp_socket;
1650
1651process:
1652 if (sk->sk_state == TCP_TIME_WAIT)
1653 goto do_time_wait;
1654
1655 if (!xfrm4_policy_check(sk, XFRM_POLICY_IN, skb))
1656 goto discard_and_relse;
Patrick McHardyb59c2702006-01-06 23:06:10 -08001657 nf_reset(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001658
Dmitry Mishinfda9ef52006-08-31 15:28:39 -07001659 if (sk_filter(sk, skb))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001660 goto discard_and_relse;
1661
1662 skb->dev = NULL;
1663
Ingo Molnarc6366182006-07-03 00:25:13 -07001664 bh_lock_sock_nested(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001665 ret = 0;
1666 if (!sock_owned_by_user(sk)) {
Chris Leech1a2449a2006-05-23 18:05:53 -07001667#ifdef CONFIG_NET_DMA
1668 struct tcp_sock *tp = tcp_sk(sk);
1669 if (!tp->ucopy.dma_chan && tp->ucopy.pinned_list)
1670 tp->ucopy.dma_chan = get_softnet_dma();
1671 if (tp->ucopy.dma_chan)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001672 ret = tcp_v4_do_rcv(sk, skb);
Chris Leech1a2449a2006-05-23 18:05:53 -07001673 else
1674#endif
1675 {
1676 if (!tcp_prequeue(sk, skb))
1677 ret = tcp_v4_do_rcv(sk, skb);
1678 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001679 } else
1680 sk_add_backlog(sk, skb);
1681 bh_unlock_sock(sk);
1682
1683 sock_put(sk);
1684
1685 return ret;
1686
1687no_tcp_socket:
1688 if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb))
1689 goto discard_it;
1690
1691 if (skb->len < (th->doff << 2) || tcp_checksum_complete(skb)) {
1692bad_packet:
1693 TCP_INC_STATS_BH(TCP_MIB_INERRS);
1694 } else {
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -08001695 tcp_v4_send_reset(NULL, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001696 }
1697
1698discard_it:
1699 /* Discard frame. */
1700 kfree_skb(skb);
YOSHIFUJI Hideakie905a9e2007-02-09 23:24:47 +09001701 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001702
1703discard_and_relse:
1704 sock_put(sk);
1705 goto discard_it;
1706
1707do_time_wait:
1708 if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {
YOSHIFUJI Hideaki9469c7b2006-10-10 19:41:46 -07001709 inet_twsk_put(inet_twsk(sk));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001710 goto discard_it;
1711 }
1712
1713 if (skb->len < (th->doff << 2) || tcp_checksum_complete(skb)) {
1714 TCP_INC_STATS_BH(TCP_MIB_INERRS);
YOSHIFUJI Hideaki9469c7b2006-10-10 19:41:46 -07001715 inet_twsk_put(inet_twsk(sk));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001716 goto discard_it;
1717 }
YOSHIFUJI Hideaki9469c7b2006-10-10 19:41:46 -07001718 switch (tcp_timewait_state_process(inet_twsk(sk), skb, th)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001719 case TCP_TW_SYN: {
YOSHIFUJI Hideakic346dca2008-03-25 21:47:49 +09001720 struct sock *sk2 = inet_lookup_listener(dev_net(skb->dev),
Pavel Emelyanovc67499c2008-01-31 05:06:40 -08001721 &tcp_hashinfo,
Arnaldo Carvalho de Meloeddc9ec2007-04-20 22:47:35 -07001722 iph->daddr, th->dest,
Arnaldo Carvalho de Melo463c84b2005-08-09 20:10:42 -07001723 inet_iif(skb));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001724 if (sk2) {
YOSHIFUJI Hideaki9469c7b2006-10-10 19:41:46 -07001725 inet_twsk_deschedule(inet_twsk(sk), &tcp_death_row);
1726 inet_twsk_put(inet_twsk(sk));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001727 sk = sk2;
1728 goto process;
1729 }
1730 /* Fall through to ACK */
1731 }
1732 case TCP_TW_ACK:
1733 tcp_v4_timewait_ack(sk, skb);
1734 break;
1735 case TCP_TW_RST:
1736 goto no_tcp_socket;
1737 case TCP_TW_SUCCESS:;
1738 }
1739 goto discard_it;
1740}
1741
Linus Torvalds1da177e2005-04-16 15:20:36 -07001742/* VJ's idea. Save last timestamp seen from this destination
1743 * and hold it at least for normal timewait interval to use for duplicate
1744 * segment detection in subsequent connections, before they enter synchronized
1745 * state.
1746 */
1747
1748int tcp_v4_remember_stamp(struct sock *sk)
1749{
1750 struct inet_sock *inet = inet_sk(sk);
1751 struct tcp_sock *tp = tcp_sk(sk);
1752 struct rtable *rt = (struct rtable *)__sk_dst_get(sk);
1753 struct inet_peer *peer = NULL;
1754 int release_it = 0;
1755
1756 if (!rt || rt->rt_dst != inet->daddr) {
1757 peer = inet_getpeer(inet->daddr, 1);
1758 release_it = 1;
1759 } else {
1760 if (!rt->peer)
1761 rt_bind_peer(rt, 1);
1762 peer = rt->peer;
1763 }
1764
1765 if (peer) {
1766 if ((s32)(peer->tcp_ts - tp->rx_opt.ts_recent) <= 0 ||
James Morris9d729f72007-03-04 16:12:44 -08001767 (peer->tcp_ts_stamp + TCP_PAWS_MSL < get_seconds() &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07001768 peer->tcp_ts_stamp <= tp->rx_opt.ts_recent_stamp)) {
1769 peer->tcp_ts_stamp = tp->rx_opt.ts_recent_stamp;
1770 peer->tcp_ts = tp->rx_opt.ts_recent;
1771 }
1772 if (release_it)
1773 inet_putpeer(peer);
1774 return 1;
1775 }
1776
1777 return 0;
1778}
1779
Arnaldo Carvalho de Melo8feaf0c2005-08-09 20:09:30 -07001780int tcp_v4_tw_remember_stamp(struct inet_timewait_sock *tw)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001781{
Arnaldo Carvalho de Melo8feaf0c2005-08-09 20:09:30 -07001782 struct inet_peer *peer = inet_getpeer(tw->tw_daddr, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001783
1784 if (peer) {
Arnaldo Carvalho de Melo8feaf0c2005-08-09 20:09:30 -07001785 const struct tcp_timewait_sock *tcptw = tcp_twsk((struct sock *)tw);
1786
1787 if ((s32)(peer->tcp_ts - tcptw->tw_ts_recent) <= 0 ||
James Morris9d729f72007-03-04 16:12:44 -08001788 (peer->tcp_ts_stamp + TCP_PAWS_MSL < get_seconds() &&
Arnaldo Carvalho de Melo8feaf0c2005-08-09 20:09:30 -07001789 peer->tcp_ts_stamp <= tcptw->tw_ts_recent_stamp)) {
1790 peer->tcp_ts_stamp = tcptw->tw_ts_recent_stamp;
1791 peer->tcp_ts = tcptw->tw_ts_recent;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001792 }
1793 inet_putpeer(peer);
1794 return 1;
1795 }
1796
1797 return 0;
1798}
1799
Arnaldo Carvalho de Melo8292a172005-12-13 23:15:52 -08001800struct inet_connection_sock_af_ops ipv4_specific = {
Arnaldo Carvalho de Melo543d9cf2006-03-20 22:48:35 -08001801 .queue_xmit = ip_queue_xmit,
1802 .send_check = tcp_v4_send_check,
1803 .rebuild_header = inet_sk_rebuild_header,
1804 .conn_request = tcp_v4_conn_request,
1805 .syn_recv_sock = tcp_v4_syn_recv_sock,
1806 .remember_stamp = tcp_v4_remember_stamp,
1807 .net_header_len = sizeof(struct iphdr),
1808 .setsockopt = ip_setsockopt,
1809 .getsockopt = ip_getsockopt,
1810 .addr2sockaddr = inet_csk_addr2sockaddr,
1811 .sockaddr_len = sizeof(struct sockaddr_in),
Arnaldo Carvalho de Meloab1e0a12008-02-03 04:06:04 -08001812 .bind_conflict = inet_csk_bind_conflict,
Dmitry Mishin3fdadf72006-03-20 22:45:21 -08001813#ifdef CONFIG_COMPAT
Arnaldo Carvalho de Melo543d9cf2006-03-20 22:48:35 -08001814 .compat_setsockopt = compat_ip_setsockopt,
1815 .compat_getsockopt = compat_ip_getsockopt,
Dmitry Mishin3fdadf72006-03-20 22:45:21 -08001816#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07001817};
1818
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -08001819#ifdef CONFIG_TCP_MD5SIG
Andrew Mortonb6332e62006-11-30 19:16:28 -08001820static struct tcp_sock_af_ops tcp_sock_ipv4_specific = {
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -08001821 .md5_lookup = tcp_v4_md5_lookup,
1822 .calc_md5_hash = tcp_v4_calc_md5_hash,
1823 .md5_add = tcp_v4_md5_add_func,
1824 .md5_parse = tcp_v4_parse_md5_keys,
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -08001825};
Andrew Mortonb6332e62006-11-30 19:16:28 -08001826#endif
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -08001827
Linus Torvalds1da177e2005-04-16 15:20:36 -07001828/* NOTE: A lot of things set to zero explicitly by call to
1829 * sk_alloc() so need not be done here.
1830 */
1831static int tcp_v4_init_sock(struct sock *sk)
1832{
Arnaldo Carvalho de Melo6687e982005-08-10 04:03:31 -03001833 struct inet_connection_sock *icsk = inet_csk(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001834 struct tcp_sock *tp = tcp_sk(sk);
1835
1836 skb_queue_head_init(&tp->out_of_order_queue);
1837 tcp_init_xmit_timers(sk);
1838 tcp_prequeue_init(tp);
1839
Arnaldo Carvalho de Melo6687e982005-08-10 04:03:31 -03001840 icsk->icsk_rto = TCP_TIMEOUT_INIT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001841 tp->mdev = TCP_TIMEOUT_INIT;
1842
1843 /* So many TCP implementations out there (incorrectly) count the
1844 * initial SYN frame in their delayed-ACK and congestion control
1845 * algorithms that we must have the following bandaid to talk
1846 * efficiently to them. -DaveM
1847 */
1848 tp->snd_cwnd = 2;
1849
1850 /* See draft-stevens-tcpca-spec-01 for discussion of the
1851 * initialization of these values.
1852 */
1853 tp->snd_ssthresh = 0x7fffffff; /* Infinity */
1854 tp->snd_cwnd_clamp = ~0;
David S. Millerc1b4a7e2005-07-05 15:24:38 -07001855 tp->mss_cache = 536;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001856
1857 tp->reordering = sysctl_tcp_reordering;
Arnaldo Carvalho de Melo6687e982005-08-10 04:03:31 -03001858 icsk->icsk_ca_ops = &tcp_init_congestion_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001859
1860 sk->sk_state = TCP_CLOSE;
1861
1862 sk->sk_write_space = sk_stream_write_space;
1863 sock_set_flag(sk, SOCK_USE_WRITE_QUEUE);
1864
Arnaldo Carvalho de Melo8292a172005-12-13 23:15:52 -08001865 icsk->icsk_af_ops = &ipv4_specific;
Arnaldo Carvalho de Melod83d8462005-12-13 23:26:10 -08001866 icsk->icsk_sync_mss = tcp_sync_mss;
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -08001867#ifdef CONFIG_TCP_MD5SIG
1868 tp->af_specific = &tcp_sock_ipv4_specific;
1869#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07001870
1871 sk->sk_sndbuf = sysctl_tcp_wmem[1];
1872 sk->sk_rcvbuf = sysctl_tcp_rmem[1];
1873
1874 atomic_inc(&tcp_sockets_allocated);
1875
1876 return 0;
1877}
1878
1879int tcp_v4_destroy_sock(struct sock *sk)
1880{
1881 struct tcp_sock *tp = tcp_sk(sk);
1882
1883 tcp_clear_xmit_timers(sk);
1884
Arnaldo Carvalho de Melo6687e982005-08-10 04:03:31 -03001885 tcp_cleanup_congestion_control(sk);
Stephen Hemminger317a76f2005-06-23 12:19:55 -07001886
Linus Torvalds1da177e2005-04-16 15:20:36 -07001887 /* Cleanup up the write buffer. */
David S. Millerfe067e82007-03-07 12:12:44 -08001888 tcp_write_queue_purge(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001889
1890 /* Cleans up our, hopefully empty, out_of_order_queue. */
YOSHIFUJI Hideakie905a9e2007-02-09 23:24:47 +09001891 __skb_queue_purge(&tp->out_of_order_queue);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001892
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -08001893#ifdef CONFIG_TCP_MD5SIG
1894 /* Clean up the MD5 key list, if any */
1895 if (tp->md5sig_info) {
1896 tcp_v4_clear_md5_list(sk);
1897 kfree(tp->md5sig_info);
1898 tp->md5sig_info = NULL;
1899 }
1900#endif
1901
Chris Leech1a2449a2006-05-23 18:05:53 -07001902#ifdef CONFIG_NET_DMA
1903 /* Cleans up our sk_async_wait_queue */
YOSHIFUJI Hideakie905a9e2007-02-09 23:24:47 +09001904 __skb_queue_purge(&sk->sk_async_wait_queue);
Chris Leech1a2449a2006-05-23 18:05:53 -07001905#endif
1906
Linus Torvalds1da177e2005-04-16 15:20:36 -07001907 /* Clean prequeue, it must be empty really */
1908 __skb_queue_purge(&tp->ucopy.prequeue);
1909
1910 /* Clean up a referenced TCP bind bucket. */
Arnaldo Carvalho de Melo463c84b2005-08-09 20:10:42 -07001911 if (inet_csk(sk)->icsk_bind_hash)
Arnaldo Carvalho de Meloab1e0a12008-02-03 04:06:04 -08001912 inet_put_port(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001913
1914 /*
1915 * If sendmsg cached page exists, toss it.
1916 */
1917 if (sk->sk_sndmsg_page) {
1918 __free_page(sk->sk_sndmsg_page);
1919 sk->sk_sndmsg_page = NULL;
1920 }
1921
Patrick McManusec3c09822008-03-21 16:33:01 -07001922 if (tp->defer_tcp_accept.request) {
1923 reqsk_free(tp->defer_tcp_accept.request);
1924 sock_put(tp->defer_tcp_accept.listen_sk);
1925 sock_put(sk);
1926 tp->defer_tcp_accept.listen_sk = NULL;
1927 tp->defer_tcp_accept.request = NULL;
1928 }
1929
Linus Torvalds1da177e2005-04-16 15:20:36 -07001930 atomic_dec(&tcp_sockets_allocated);
1931
1932 return 0;
1933}
1934
1935EXPORT_SYMBOL(tcp_v4_destroy_sock);
1936
1937#ifdef CONFIG_PROC_FS
1938/* Proc filesystem TCP sock list dumping. */
1939
Arnaldo Carvalho de Melo8feaf0c2005-08-09 20:09:30 -07001940static inline struct inet_timewait_sock *tw_head(struct hlist_head *head)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001941{
1942 return hlist_empty(head) ? NULL :
Arnaldo Carvalho de Melo8feaf0c2005-08-09 20:09:30 -07001943 list_entry(head->first, struct inet_timewait_sock, tw_node);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001944}
1945
Arnaldo Carvalho de Melo8feaf0c2005-08-09 20:09:30 -07001946static inline struct inet_timewait_sock *tw_next(struct inet_timewait_sock *tw)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001947{
1948 return tw->tw_node.next ?
1949 hlist_entry(tw->tw_node.next, typeof(*tw), tw_node) : NULL;
1950}
1951
1952static void *listening_get_next(struct seq_file *seq, void *cur)
1953{
Arnaldo Carvalho de Melo463c84b2005-08-09 20:10:42 -07001954 struct inet_connection_sock *icsk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001955 struct hlist_node *node;
1956 struct sock *sk = cur;
1957 struct tcp_iter_state* st = seq->private;
Daniel Lezcanof40c8172008-03-21 04:13:54 -07001958 struct net *net = st->net;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001959
1960 if (!sk) {
1961 st->bucket = 0;
Arnaldo Carvalho de Melo6e04e022005-08-09 20:07:35 -07001962 sk = sk_head(&tcp_hashinfo.listening_hash[0]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001963 goto get_sk;
1964 }
1965
1966 ++st->num;
1967
1968 if (st->state == TCP_SEQ_STATE_OPENREQ) {
Arnaldo Carvalho de Melo60236fd2005-06-18 22:47:21 -07001969 struct request_sock *req = cur;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001970
Eric Dumazet72a3eff2006-11-16 02:30:37 -08001971 icsk = inet_csk(st->syn_wait_sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001972 req = req->dl_next;
1973 while (1) {
1974 while (req) {
Daniel Lezcanof40c8172008-03-21 04:13:54 -07001975 if (req->rsk_ops->family == st->family &&
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09001976 net_eq(sock_net(req->sk), net)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001977 cur = req;
1978 goto out;
1979 }
1980 req = req->dl_next;
1981 }
Eric Dumazet72a3eff2006-11-16 02:30:37 -08001982 if (++st->sbucket >= icsk->icsk_accept_queue.listen_opt->nr_table_entries)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001983 break;
1984get_req:
Arnaldo Carvalho de Melo463c84b2005-08-09 20:10:42 -07001985 req = icsk->icsk_accept_queue.listen_opt->syn_table[st->sbucket];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001986 }
1987 sk = sk_next(st->syn_wait_sk);
1988 st->state = TCP_SEQ_STATE_LISTENING;
Arnaldo Carvalho de Melo463c84b2005-08-09 20:10:42 -07001989 read_unlock_bh(&icsk->icsk_accept_queue.syn_wait_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001990 } else {
YOSHIFUJI Hideakie905a9e2007-02-09 23:24:47 +09001991 icsk = inet_csk(sk);
Arnaldo Carvalho de Melo463c84b2005-08-09 20:10:42 -07001992 read_lock_bh(&icsk->icsk_accept_queue.syn_wait_lock);
1993 if (reqsk_queue_len(&icsk->icsk_accept_queue))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001994 goto start_req;
Arnaldo Carvalho de Melo463c84b2005-08-09 20:10:42 -07001995 read_unlock_bh(&icsk->icsk_accept_queue.syn_wait_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001996 sk = sk_next(sk);
1997 }
1998get_sk:
1999 sk_for_each_from(sk, node) {
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09002000 if (sk->sk_family == st->family && net_eq(sock_net(sk), net)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002001 cur = sk;
2002 goto out;
2003 }
YOSHIFUJI Hideakie905a9e2007-02-09 23:24:47 +09002004 icsk = inet_csk(sk);
Arnaldo Carvalho de Melo463c84b2005-08-09 20:10:42 -07002005 read_lock_bh(&icsk->icsk_accept_queue.syn_wait_lock);
2006 if (reqsk_queue_len(&icsk->icsk_accept_queue)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002007start_req:
2008 st->uid = sock_i_uid(sk);
2009 st->syn_wait_sk = sk;
2010 st->state = TCP_SEQ_STATE_OPENREQ;
2011 st->sbucket = 0;
2012 goto get_req;
2013 }
Arnaldo Carvalho de Melo463c84b2005-08-09 20:10:42 -07002014 read_unlock_bh(&icsk->icsk_accept_queue.syn_wait_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002015 }
Arnaldo Carvalho de Melo0f7ff922005-08-09 19:59:44 -07002016 if (++st->bucket < INET_LHTABLE_SIZE) {
Arnaldo Carvalho de Melo6e04e022005-08-09 20:07:35 -07002017 sk = sk_head(&tcp_hashinfo.listening_hash[st->bucket]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002018 goto get_sk;
2019 }
2020 cur = NULL;
2021out:
2022 return cur;
2023}
2024
2025static void *listening_get_idx(struct seq_file *seq, loff_t *pos)
2026{
2027 void *rc = listening_get_next(seq, NULL);
2028
2029 while (rc && *pos) {
2030 rc = listening_get_next(seq, rc);
2031 --*pos;
2032 }
2033 return rc;
2034}
2035
2036static void *established_get_first(struct seq_file *seq)
2037{
2038 struct tcp_iter_state* st = seq->private;
Daniel Lezcanof40c8172008-03-21 04:13:54 -07002039 struct net *net = st->net;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002040 void *rc = NULL;
2041
Arnaldo Carvalho de Melo6e04e022005-08-09 20:07:35 -07002042 for (st->bucket = 0; st->bucket < tcp_hashinfo.ehash_size; ++st->bucket) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002043 struct sock *sk;
2044 struct hlist_node *node;
Arnaldo Carvalho de Melo8feaf0c2005-08-09 20:09:30 -07002045 struct inet_timewait_sock *tw;
Eric Dumazet230140c2007-11-07 02:40:20 -08002046 rwlock_t *lock = inet_ehash_lockp(&tcp_hashinfo, st->bucket);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002047
Eric Dumazet230140c2007-11-07 02:40:20 -08002048 read_lock_bh(lock);
Arnaldo Carvalho de Melo6e04e022005-08-09 20:07:35 -07002049 sk_for_each(sk, node, &tcp_hashinfo.ehash[st->bucket].chain) {
Daniel Lezcanof40c8172008-03-21 04:13:54 -07002050 if (sk->sk_family != st->family ||
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09002051 !net_eq(sock_net(sk), net)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002052 continue;
2053 }
2054 rc = sk;
2055 goto out;
2056 }
2057 st->state = TCP_SEQ_STATE_TIME_WAIT;
Arnaldo Carvalho de Melo8feaf0c2005-08-09 20:09:30 -07002058 inet_twsk_for_each(tw, node,
Eric Dumazetdbca9b2752007-02-08 14:16:46 -08002059 &tcp_hashinfo.ehash[st->bucket].twchain) {
Pavel Emelyanov28518fc2008-03-21 15:52:00 -07002060 if (tw->tw_family != st->family ||
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09002061 !net_eq(twsk_net(tw), net)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002062 continue;
2063 }
2064 rc = tw;
2065 goto out;
2066 }
Eric Dumazet230140c2007-11-07 02:40:20 -08002067 read_unlock_bh(lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002068 st->state = TCP_SEQ_STATE_ESTABLISHED;
2069 }
2070out:
2071 return rc;
2072}
2073
2074static void *established_get_next(struct seq_file *seq, void *cur)
2075{
2076 struct sock *sk = cur;
Arnaldo Carvalho de Melo8feaf0c2005-08-09 20:09:30 -07002077 struct inet_timewait_sock *tw;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002078 struct hlist_node *node;
2079 struct tcp_iter_state* st = seq->private;
Daniel Lezcanof40c8172008-03-21 04:13:54 -07002080 struct net *net = st->net;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002081
2082 ++st->num;
2083
2084 if (st->state == TCP_SEQ_STATE_TIME_WAIT) {
2085 tw = cur;
2086 tw = tw_next(tw);
2087get_tw:
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09002088 while (tw && (tw->tw_family != st->family || !net_eq(twsk_net(tw), net))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002089 tw = tw_next(tw);
2090 }
2091 if (tw) {
2092 cur = tw;
2093 goto out;
2094 }
Eric Dumazet230140c2007-11-07 02:40:20 -08002095 read_unlock_bh(inet_ehash_lockp(&tcp_hashinfo, st->bucket));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002096 st->state = TCP_SEQ_STATE_ESTABLISHED;
2097
Arnaldo Carvalho de Melo6e04e022005-08-09 20:07:35 -07002098 if (++st->bucket < tcp_hashinfo.ehash_size) {
Eric Dumazet230140c2007-11-07 02:40:20 -08002099 read_lock_bh(inet_ehash_lockp(&tcp_hashinfo, st->bucket));
Arnaldo Carvalho de Melo6e04e022005-08-09 20:07:35 -07002100 sk = sk_head(&tcp_hashinfo.ehash[st->bucket].chain);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002101 } else {
2102 cur = NULL;
2103 goto out;
2104 }
2105 } else
2106 sk = sk_next(sk);
2107
2108 sk_for_each_from(sk, node) {
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09002109 if (sk->sk_family == st->family && net_eq(sock_net(sk), net))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002110 goto found;
2111 }
2112
2113 st->state = TCP_SEQ_STATE_TIME_WAIT;
Eric Dumazetdbca9b2752007-02-08 14:16:46 -08002114 tw = tw_head(&tcp_hashinfo.ehash[st->bucket].twchain);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002115 goto get_tw;
2116found:
2117 cur = sk;
2118out:
2119 return cur;
2120}
2121
2122static void *established_get_idx(struct seq_file *seq, loff_t pos)
2123{
2124 void *rc = established_get_first(seq);
2125
2126 while (rc && pos) {
2127 rc = established_get_next(seq, rc);
2128 --pos;
Arnaldo Carvalho de Melo71742592006-11-17 10:57:30 -02002129 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002130 return rc;
2131}
2132
2133static void *tcp_get_idx(struct seq_file *seq, loff_t pos)
2134{
2135 void *rc;
2136 struct tcp_iter_state* st = seq->private;
2137
Arnaldo Carvalho de Melof3f05f72005-08-09 20:08:09 -07002138 inet_listen_lock(&tcp_hashinfo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002139 st->state = TCP_SEQ_STATE_LISTENING;
2140 rc = listening_get_idx(seq, &pos);
2141
2142 if (!rc) {
Arnaldo Carvalho de Melof3f05f72005-08-09 20:08:09 -07002143 inet_listen_unlock(&tcp_hashinfo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002144 st->state = TCP_SEQ_STATE_ESTABLISHED;
2145 rc = established_get_idx(seq, pos);
2146 }
2147
2148 return rc;
2149}
2150
2151static void *tcp_seq_start(struct seq_file *seq, loff_t *pos)
2152{
2153 struct tcp_iter_state* st = seq->private;
2154 st->state = TCP_SEQ_STATE_LISTENING;
2155 st->num = 0;
2156 return *pos ? tcp_get_idx(seq, *pos - 1) : SEQ_START_TOKEN;
2157}
2158
2159static void *tcp_seq_next(struct seq_file *seq, void *v, loff_t *pos)
2160{
2161 void *rc = NULL;
2162 struct tcp_iter_state* st;
2163
2164 if (v == SEQ_START_TOKEN) {
2165 rc = tcp_get_idx(seq, 0);
2166 goto out;
2167 }
2168 st = seq->private;
2169
2170 switch (st->state) {
2171 case TCP_SEQ_STATE_OPENREQ:
2172 case TCP_SEQ_STATE_LISTENING:
2173 rc = listening_get_next(seq, v);
2174 if (!rc) {
Arnaldo Carvalho de Melof3f05f72005-08-09 20:08:09 -07002175 inet_listen_unlock(&tcp_hashinfo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002176 st->state = TCP_SEQ_STATE_ESTABLISHED;
2177 rc = established_get_first(seq);
2178 }
2179 break;
2180 case TCP_SEQ_STATE_ESTABLISHED:
2181 case TCP_SEQ_STATE_TIME_WAIT:
2182 rc = established_get_next(seq, v);
2183 break;
2184 }
2185out:
2186 ++*pos;
2187 return rc;
2188}
2189
2190static void tcp_seq_stop(struct seq_file *seq, void *v)
2191{
2192 struct tcp_iter_state* st = seq->private;
2193
2194 switch (st->state) {
2195 case TCP_SEQ_STATE_OPENREQ:
2196 if (v) {
Arnaldo Carvalho de Melo463c84b2005-08-09 20:10:42 -07002197 struct inet_connection_sock *icsk = inet_csk(st->syn_wait_sk);
2198 read_unlock_bh(&icsk->icsk_accept_queue.syn_wait_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002199 }
2200 case TCP_SEQ_STATE_LISTENING:
2201 if (v != SEQ_START_TOKEN)
Arnaldo Carvalho de Melof3f05f72005-08-09 20:08:09 -07002202 inet_listen_unlock(&tcp_hashinfo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002203 break;
2204 case TCP_SEQ_STATE_TIME_WAIT:
2205 case TCP_SEQ_STATE_ESTABLISHED:
2206 if (v)
Eric Dumazet230140c2007-11-07 02:40:20 -08002207 read_unlock_bh(inet_ehash_lockp(&tcp_hashinfo, st->bucket));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002208 break;
2209 }
2210}
2211
2212static int tcp_seq_open(struct inode *inode, struct file *file)
2213{
2214 struct tcp_seq_afinfo *afinfo = PDE(inode)->data;
2215 struct seq_file *seq;
2216 struct tcp_iter_state *s;
Daniel Lezcanof40c8172008-03-21 04:13:54 -07002217 struct net *net;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002218 int rc;
2219
2220 if (unlikely(afinfo == NULL))
2221 return -EINVAL;
2222
Panagiotis Issaris0da974f2006-07-21 14:51:30 -07002223 s = kzalloc(sizeof(*s), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002224 if (!s)
2225 return -ENOMEM;
Daniel Lezcanof40c8172008-03-21 04:13:54 -07002226
2227 rc = -ENXIO;
2228 net = get_proc_net(inode);
2229 if (!net)
2230 goto out_kfree;
2231
Linus Torvalds1da177e2005-04-16 15:20:36 -07002232 s->family = afinfo->family;
2233 s->seq_ops.start = tcp_seq_start;
2234 s->seq_ops.next = tcp_seq_next;
2235 s->seq_ops.show = afinfo->seq_show;
2236 s->seq_ops.stop = tcp_seq_stop;
Daniel Lezcanof40c8172008-03-21 04:13:54 -07002237 s->net = net;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002238
2239 rc = seq_open(file, &s->seq_ops);
2240 if (rc)
Daniel Lezcanof40c8172008-03-21 04:13:54 -07002241 goto out_put_net;
2242 seq = file->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002243 seq->private = s;
2244out:
2245 return rc;
Daniel Lezcanof40c8172008-03-21 04:13:54 -07002246out_put_net:
2247 put_net(net);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002248out_kfree:
2249 kfree(s);
2250 goto out;
2251}
2252
Daniel Lezcanof40c8172008-03-21 04:13:54 -07002253static int tcp_seq_release(struct inode *inode, struct file *file)
2254{
2255 struct seq_file *seq = file->private_data;
2256 struct tcp_iter_state *s = seq->private;
2257
2258 put_net(s->net);
2259 seq_release_private(inode, file);
2260 return 0;
2261}
2262
Daniel Lezcano6f8b13b2008-03-21 04:14:45 -07002263int tcp_proc_register(struct net *net, struct tcp_seq_afinfo *afinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002264{
2265 int rc = 0;
2266 struct proc_dir_entry *p;
2267
2268 if (!afinfo)
2269 return -EINVAL;
2270 afinfo->seq_fops->owner = afinfo->owner;
2271 afinfo->seq_fops->open = tcp_seq_open;
2272 afinfo->seq_fops->read = seq_read;
2273 afinfo->seq_fops->llseek = seq_lseek;
Daniel Lezcanof40c8172008-03-21 04:13:54 -07002274 afinfo->seq_fops->release = tcp_seq_release;
Arnaldo Carvalho de Melo71742592006-11-17 10:57:30 -02002275
Daniel Lezcano6f8b13b2008-03-21 04:14:45 -07002276 p = proc_net_fops_create(net, afinfo->name, S_IRUGO, afinfo->seq_fops);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002277 if (p)
2278 p->data = afinfo;
2279 else
2280 rc = -ENOMEM;
2281 return rc;
2282}
2283
Daniel Lezcano6f8b13b2008-03-21 04:14:45 -07002284void tcp_proc_unregister(struct net *net, struct tcp_seq_afinfo *afinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002285{
2286 if (!afinfo)
2287 return;
Daniel Lezcano6f8b13b2008-03-21 04:14:45 -07002288 proc_net_remove(net, afinfo->name);
Arnaldo Carvalho de Melo71742592006-11-17 10:57:30 -02002289 memset(afinfo->seq_fops, 0, sizeof(*afinfo->seq_fops));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002290}
2291
Arnaldo Carvalho de Melo60236fd2005-06-18 22:47:21 -07002292static void get_openreq4(struct sock *sk, struct request_sock *req,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002293 char *tmpbuf, int i, int uid)
2294{
Arnaldo Carvalho de Melo2e6599c2005-06-18 22:46:52 -07002295 const struct inet_request_sock *ireq = inet_rsk(req);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002296 int ttd = req->expires - jiffies;
2297
2298 sprintf(tmpbuf, "%4d: %08X:%04X %08X:%04X"
2299 " %02X %08X:%08X %02X:%08lX %08X %5d %8d %u %d %p",
2300 i,
Arnaldo Carvalho de Melo2e6599c2005-06-18 22:46:52 -07002301 ireq->loc_addr,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002302 ntohs(inet_sk(sk)->sport),
Arnaldo Carvalho de Melo2e6599c2005-06-18 22:46:52 -07002303 ireq->rmt_addr,
2304 ntohs(ireq->rmt_port),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002305 TCP_SYN_RECV,
2306 0, 0, /* could print option size, but that is af dependent. */
2307 1, /* timers active (only the expire timer) */
2308 jiffies_to_clock_t(ttd),
2309 req->retrans,
2310 uid,
2311 0, /* non standard timer */
2312 0, /* open_requests have no inode */
2313 atomic_read(&sk->sk_refcnt),
2314 req);
2315}
2316
Ilpo Järvinencf4c6bf2007-02-22 01:13:58 -08002317static void get_tcp4_sock(struct sock *sk, char *tmpbuf, int i)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002318{
2319 int timer_active;
2320 unsigned long timer_expires;
Ilpo Järvinencf4c6bf2007-02-22 01:13:58 -08002321 struct tcp_sock *tp = tcp_sk(sk);
2322 const struct inet_connection_sock *icsk = inet_csk(sk);
2323 struct inet_sock *inet = inet_sk(sk);
Al Viro714e85b2006-11-14 20:51:49 -08002324 __be32 dest = inet->daddr;
2325 __be32 src = inet->rcv_saddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002326 __u16 destp = ntohs(inet->dport);
2327 __u16 srcp = ntohs(inet->sport);
2328
Arnaldo Carvalho de Melo463c84b2005-08-09 20:10:42 -07002329 if (icsk->icsk_pending == ICSK_TIME_RETRANS) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002330 timer_active = 1;
Arnaldo Carvalho de Melo463c84b2005-08-09 20:10:42 -07002331 timer_expires = icsk->icsk_timeout;
2332 } else if (icsk->icsk_pending == ICSK_TIME_PROBE0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002333 timer_active = 4;
Arnaldo Carvalho de Melo463c84b2005-08-09 20:10:42 -07002334 timer_expires = icsk->icsk_timeout;
Ilpo Järvinencf4c6bf2007-02-22 01:13:58 -08002335 } else if (timer_pending(&sk->sk_timer)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002336 timer_active = 2;
Ilpo Järvinencf4c6bf2007-02-22 01:13:58 -08002337 timer_expires = sk->sk_timer.expires;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002338 } else {
2339 timer_active = 0;
2340 timer_expires = jiffies;
2341 }
2342
2343 sprintf(tmpbuf, "%4d: %08X:%04X %08X:%04X %02X %08X:%08X %02X:%08lX "
2344 "%08X %5d %8d %lu %d %p %u %u %u %u %d",
Ilpo Järvinencf4c6bf2007-02-22 01:13:58 -08002345 i, src, srcp, dest, destp, sk->sk_state,
Sridhar Samudrala47da8ee2006-06-27 13:29:00 -07002346 tp->write_seq - tp->snd_una,
Ilpo Järvinencf4c6bf2007-02-22 01:13:58 -08002347 sk->sk_state == TCP_LISTEN ? sk->sk_ack_backlog :
Arnaldo Carvalho de Melo71742592006-11-17 10:57:30 -02002348 (tp->rcv_nxt - tp->copied_seq),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002349 timer_active,
2350 jiffies_to_clock_t(timer_expires - jiffies),
Arnaldo Carvalho de Melo463c84b2005-08-09 20:10:42 -07002351 icsk->icsk_retransmits,
Ilpo Järvinencf4c6bf2007-02-22 01:13:58 -08002352 sock_i_uid(sk),
Arnaldo Carvalho de Melo6687e982005-08-10 04:03:31 -03002353 icsk->icsk_probes_out,
Ilpo Järvinencf4c6bf2007-02-22 01:13:58 -08002354 sock_i_ino(sk),
2355 atomic_read(&sk->sk_refcnt), sk,
Arnaldo Carvalho de Melo463c84b2005-08-09 20:10:42 -07002356 icsk->icsk_rto,
2357 icsk->icsk_ack.ato,
2358 (icsk->icsk_ack.quick << 1) | icsk->icsk_ack.pingpong,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002359 tp->snd_cwnd,
2360 tp->snd_ssthresh >= 0xFFFF ? -1 : tp->snd_ssthresh);
2361}
2362
Arnaldo Carvalho de Melo71742592006-11-17 10:57:30 -02002363static void get_timewait4_sock(struct inet_timewait_sock *tw,
2364 char *tmpbuf, int i)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002365{
Al Viro23f33c22006-09-27 18:43:50 -07002366 __be32 dest, src;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002367 __u16 destp, srcp;
2368 int ttd = tw->tw_ttd - jiffies;
2369
2370 if (ttd < 0)
2371 ttd = 0;
2372
2373 dest = tw->tw_daddr;
2374 src = tw->tw_rcv_saddr;
2375 destp = ntohs(tw->tw_dport);
2376 srcp = ntohs(tw->tw_sport);
2377
2378 sprintf(tmpbuf, "%4d: %08X:%04X %08X:%04X"
2379 " %02X %08X:%08X %02X:%08lX %08X %5d %8d %d %d %p",
2380 i, src, srcp, dest, destp, tw->tw_substate, 0, 0,
2381 3, jiffies_to_clock_t(ttd), 0, 0, 0, 0,
2382 atomic_read(&tw->tw_refcnt), tw);
2383}
2384
2385#define TMPSZ 150
2386
2387static int tcp4_seq_show(struct seq_file *seq, void *v)
2388{
2389 struct tcp_iter_state* st;
2390 char tmpbuf[TMPSZ + 1];
2391
2392 if (v == SEQ_START_TOKEN) {
2393 seq_printf(seq, "%-*s\n", TMPSZ - 1,
2394 " sl local_address rem_address st tx_queue "
2395 "rx_queue tr tm->when retrnsmt uid timeout "
2396 "inode");
2397 goto out;
2398 }
2399 st = seq->private;
2400
2401 switch (st->state) {
2402 case TCP_SEQ_STATE_LISTENING:
2403 case TCP_SEQ_STATE_ESTABLISHED:
2404 get_tcp4_sock(v, tmpbuf, st->num);
2405 break;
2406 case TCP_SEQ_STATE_OPENREQ:
2407 get_openreq4(st->syn_wait_sk, v, tmpbuf, st->num, st->uid);
2408 break;
2409 case TCP_SEQ_STATE_TIME_WAIT:
2410 get_timewait4_sock(v, tmpbuf, st->num);
2411 break;
2412 }
2413 seq_printf(seq, "%-*s\n", TMPSZ - 1, tmpbuf);
2414out:
2415 return 0;
2416}
2417
2418static struct file_operations tcp4_seq_fops;
2419static struct tcp_seq_afinfo tcp4_seq_afinfo = {
2420 .owner = THIS_MODULE,
2421 .name = "tcp",
2422 .family = AF_INET,
2423 .seq_show = tcp4_seq_show,
2424 .seq_fops = &tcp4_seq_fops,
2425};
2426
Pavel Emelyanov757764f2008-03-24 14:56:02 -07002427static int tcp4_proc_init_net(struct net *net)
2428{
2429 return tcp_proc_register(net, &tcp4_seq_afinfo);
2430}
2431
2432static void tcp4_proc_exit_net(struct net *net)
2433{
2434 tcp_proc_unregister(net, &tcp4_seq_afinfo);
2435}
2436
2437static struct pernet_operations tcp4_net_ops = {
2438 .init = tcp4_proc_init_net,
2439 .exit = tcp4_proc_exit_net,
2440};
2441
Linus Torvalds1da177e2005-04-16 15:20:36 -07002442int __init tcp4_proc_init(void)
2443{
Pavel Emelyanov757764f2008-03-24 14:56:02 -07002444 return register_pernet_subsys(&tcp4_net_ops);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002445}
2446
2447void tcp4_proc_exit(void)
2448{
Pavel Emelyanov757764f2008-03-24 14:56:02 -07002449 unregister_pernet_subsys(&tcp4_net_ops);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002450}
2451#endif /* CONFIG_PROC_FS */
2452
2453struct proto tcp_prot = {
2454 .name = "TCP",
2455 .owner = THIS_MODULE,
2456 .close = tcp_close,
2457 .connect = tcp_v4_connect,
2458 .disconnect = tcp_disconnect,
Arnaldo Carvalho de Melo463c84b2005-08-09 20:10:42 -07002459 .accept = inet_csk_accept,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002460 .ioctl = tcp_ioctl,
2461 .init = tcp_v4_init_sock,
2462 .destroy = tcp_v4_destroy_sock,
2463 .shutdown = tcp_shutdown,
2464 .setsockopt = tcp_setsockopt,
2465 .getsockopt = tcp_getsockopt,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002466 .recvmsg = tcp_recvmsg,
2467 .backlog_rcv = tcp_v4_do_rcv,
Arnaldo Carvalho de Meloab1e0a12008-02-03 04:06:04 -08002468 .hash = inet_hash,
2469 .unhash = inet_unhash,
2470 .get_port = inet_csk_get_port,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002471 .enter_memory_pressure = tcp_enter_memory_pressure,
2472 .sockets_allocated = &tcp_sockets_allocated,
Arnaldo Carvalho de Melo0a5578c2005-08-09 20:11:41 -07002473 .orphan_count = &tcp_orphan_count,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002474 .memory_allocated = &tcp_memory_allocated,
2475 .memory_pressure = &tcp_memory_pressure,
2476 .sysctl_mem = sysctl_tcp_mem,
2477 .sysctl_wmem = sysctl_tcp_wmem,
2478 .sysctl_rmem = sysctl_tcp_rmem,
2479 .max_header = MAX_TCP_HEADER,
2480 .obj_size = sizeof(struct tcp_sock),
Arnaldo Carvalho de Melo6d6ee432005-12-13 23:25:19 -08002481 .twsk_prot = &tcp_timewait_sock_ops,
Arnaldo Carvalho de Melo60236fd2005-06-18 22:47:21 -07002482 .rsk_prot = &tcp_request_sock_ops,
Pavel Emelyanov39d8cda2008-03-22 16:50:58 -07002483 .h.hashinfo = &tcp_hashinfo,
Arnaldo Carvalho de Melo543d9cf2006-03-20 22:48:35 -08002484#ifdef CONFIG_COMPAT
2485 .compat_setsockopt = compat_tcp_setsockopt,
2486 .compat_getsockopt = compat_tcp_getsockopt,
2487#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07002488};
2489
Denis V. Lunev046ee902008-04-03 14:31:33 -07002490
2491static int __net_init tcp_sk_init(struct net *net)
2492{
2493 return inet_ctl_sock_create(&net->ipv4.tcp_sock,
2494 PF_INET, SOCK_RAW, IPPROTO_TCP, net);
2495}
2496
2497static void __net_exit tcp_sk_exit(struct net *net)
2498{
2499 inet_ctl_sock_destroy(net->ipv4.tcp_sock);
2500}
2501
2502static struct pernet_operations __net_initdata tcp_sk_ops = {
2503 .init = tcp_sk_init,
2504 .exit = tcp_sk_exit,
2505};
2506
Denis V. Lunev9b0f9762008-02-29 11:13:15 -08002507void __init tcp_v4_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002508{
Denis V. Lunev046ee902008-04-03 14:31:33 -07002509 if (register_pernet_device(&tcp_sk_ops))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002510 panic("Failed to create the TCP control socket.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002511}
2512
2513EXPORT_SYMBOL(ipv4_specific);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002514EXPORT_SYMBOL(tcp_hashinfo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002515EXPORT_SYMBOL(tcp_prot);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002516EXPORT_SYMBOL(tcp_v4_conn_request);
2517EXPORT_SYMBOL(tcp_v4_connect);
2518EXPORT_SYMBOL(tcp_v4_do_rcv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002519EXPORT_SYMBOL(tcp_v4_remember_stamp);
2520EXPORT_SYMBOL(tcp_v4_send_check);
2521EXPORT_SYMBOL(tcp_v4_syn_recv_sock);
2522
2523#ifdef CONFIG_PROC_FS
2524EXPORT_SYMBOL(tcp_proc_register);
2525EXPORT_SYMBOL(tcp_proc_unregister);
2526#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07002527EXPORT_SYMBOL(sysctl_tcp_low_latency);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002528