Blame view

net/ipv6/tcp_ipv6.c 58.2 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
  /*
   *	TCP over IPv6
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
3
   *	Linux INET6 implementation
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4
5
   *
   *	Authors:
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
6
   *	Pedro Roque		<roque@di.fc.ul.pt>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
7
   *
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
8
   *	Based on:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
   *	linux/net/ipv4/tcp.c
   *	linux/net/ipv4/tcp_input.c
   *	linux/net/ipv4/tcp_output.c
   *
   *	Fixes:
   *	Hideaki YOSHIFUJI	:	sin6_scope_id support
   *	YOSHIFUJI Hideaki @USAGI and:	Support IPV6_V6ONLY socket option, which
   *	Alexey Kuznetsov		allow both IPv4 and IPv6 sockets to bind
   *					a single port at the same time.
   *	YOSHIFUJI Hideaki @USAGI:	convert /proc/net/tcp6 to seq_file.
   *
   *	This program is free software; you can redistribute it and/or
   *      modify it under the terms of the GNU General Public License
   *      as published by the Free Software Foundation; either version
   *      2 of the License, or (at your option) any later version.
   */
eb4dea585   Herbert Xu   net: Fix percpu c...
25
  #include <linux/bottom_half.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
26
  #include <linux/module.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
27
28
29
30
31
32
33
34
35
36
37
38
39
  #include <linux/errno.h>
  #include <linux/types.h>
  #include <linux/socket.h>
  #include <linux/sockios.h>
  #include <linux/net.h>
  #include <linux/jiffies.h>
  #include <linux/in.h>
  #include <linux/in6.h>
  #include <linux/netdevice.h>
  #include <linux/init.h>
  #include <linux/jhash.h>
  #include <linux/ipsec.h>
  #include <linux/times.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
40
  #include <linux/slab.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
41
42
43
44
45
46
47
  
  #include <linux/ipv6.h>
  #include <linux/icmpv6.h>
  #include <linux/random.h>
  
  #include <net/tcp.h>
  #include <net/ndisc.h>
5324a040c   Arnaldo Carvalho de Melo   [INET6_HASHTABLES...
48
  #include <net/inet6_hashtables.h>
8129765ac   Arnaldo Carvalho de Melo   [IPV6]: Generalis...
49
  #include <net/inet6_connection_sock.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
50
51
52
53
54
55
56
57
  #include <net/ipv6.h>
  #include <net/transp_v6.h>
  #include <net/addrconf.h>
  #include <net/ip6_route.h>
  #include <net/ip6_checksum.h>
  #include <net/inet_ecn.h>
  #include <net/protocol.h>
  #include <net/xfrm.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
58
59
  #include <net/snmp.h>
  #include <net/dsfield.h>
6d6ee43e0   Arnaldo Carvalho de Melo   [TWSK]: Introduce...
60
  #include <net/timewait_sock.h>
18134bed0   Jeff Garzik   [TCP] IPV6: fix s...
61
  #include <net/netdma.h>
3d58b5fa8   Denis V. Lunev   [INET]: Rename in...
62
  #include <net/inet_common.h>
6e5714eaf   David S. Miller   net: Compute prot...
63
  #include <net/secure_seq.h>
d1a4c0b37   Glauber Costa   tcp memory pressu...
64
  #include <net/tcp_memcontrol.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
65
66
67
68
69
  
  #include <asm/uaccess.h>
  
  #include <linux/proc_fs.h>
  #include <linux/seq_file.h>
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
70
71
  #include <linux/crypto.h>
  #include <linux/scatterlist.h>
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
72
  static void	tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb);
6edafaaf6   Gui Jianfeng   tcp: Fix kernel p...
73
74
  static void	tcp_v6_reqsk_send_ack(struct sock *sk, struct sk_buff *skb,
  				      struct request_sock *req);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
75
76
  
  static int	tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb);
8ad50d96d   Herbert Xu   tcp: Handle CHECK...
77
  static void	__tcp_v6_send_check(struct sk_buff *skb,
b71d1d426   Eric Dumazet   inet: constify ip...
78
79
  				    const struct in6_addr *saddr,
  				    const struct in6_addr *daddr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
80

3b401a81c   Stephen Hemminger   inet: inet_connec...
81
82
  static const struct inet_connection_sock_af_ops ipv6_mapped;
  static const struct inet_connection_sock_af_ops ipv6_specific;
a928630a2   David S. Miller   [TCP]: Fix some w...
83
  #ifdef CONFIG_TCP_MD5SIG
b2e4b3deb   Stephen Hemminger   tcp: MD5 operatio...
84
85
  static const struct tcp_sock_af_ops tcp_sock_ipv6_specific;
  static const struct tcp_sock_af_ops tcp_sock_ipv6_mapped_specific;
9501f9722   YOSHIFUJI Hideaki   tcp md5sig: Let t...
86
87
  #else
  static struct tcp_md5sig_key *tcp_v6_md5_do_lookup(struct sock *sk,
b71d1d426   Eric Dumazet   inet: constify ip...
88
  						   const struct in6_addr *addr)
9501f9722   YOSHIFUJI Hideaki   tcp md5sig: Let t...
89
90
91
  {
  	return NULL;
  }
a928630a2   David S. Miller   [TCP]: Fix some w...
92
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
93

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
94
95
96
  static void tcp_v6_hash(struct sock *sk)
  {
  	if (sk->sk_state != TCP_CLOSE) {
8292a17a3   Arnaldo Carvalho de Melo   [ICSK]: Rename st...
97
  		if (inet_csk(sk)->icsk_af_ops == &ipv6_mapped) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
98
99
100
101
  			tcp_prot.hash(sk);
  			return;
  		}
  		local_bh_disable();
9327f7053   Eric Dumazet   tcp: Fix a connec...
102
  		__inet6_hash(sk, NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
103
104
105
  		local_bh_enable();
  	}
  }
684f21760   Herbert Xu   tcp6: Add GRO sup...
106
  static __inline__ __sum16 tcp_v6_check(int len,
b71d1d426   Eric Dumazet   inet: constify ip...
107
108
  				   const struct in6_addr *saddr,
  				   const struct in6_addr *daddr,
868c86bcb   Al Viro   [NET]: annotate c...
109
  				   __wsum base)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
110
111
112
  {
  	return csum_ipv6_magic(saddr, daddr, len, IPPROTO_TCP, base);
  }
cf533ea53   Eric Dumazet   tcp: add const qu...
113
  static __u32 tcp_v6_init_sequence(const struct sk_buff *skb)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
114
  {
0660e03f6   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
115
116
  	return secure_tcpv6_sequence_number(ipv6_hdr(skb)->daddr.s6_addr32,
  					    ipv6_hdr(skb)->saddr.s6_addr32,
aa8223c7b   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
117
118
  					    tcp_hdr(skb)->dest,
  					    tcp_hdr(skb)->source);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
119
  }
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
120
  static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
121
122
123
  			  int addr_len)
  {
  	struct sockaddr_in6 *usin = (struct sockaddr_in6 *) uaddr;
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
124
  	struct inet_sock *inet = inet_sk(sk);
d83d8461f   Arnaldo Carvalho de Melo   [IP_SOCKGLUE]: Re...
125
  	struct inet_connection_sock *icsk = inet_csk(sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
126
127
  	struct ipv6_pinfo *np = inet6_sk(sk);
  	struct tcp_sock *tp = tcp_sk(sk);
20c59de2e   Arnaud Ebalard   ipv6: Refactor up...
128
  	struct in6_addr *saddr = NULL, *final_p, final;
493f377d6   David S. Miller   tcp: Add timewait...
129
  	struct rt6_info *rt;
4c9483b2f   David S. Miller   ipv6: Convert to ...
130
  	struct flowi6 fl6;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
131
132
133
  	struct dst_entry *dst;
  	int addr_type;
  	int err;
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
134
  	if (addr_len < SIN6_LEN_RFC2133)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
135
  		return -EINVAL;
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
136
  	if (usin->sin6_family != AF_INET6)
a02cec215   Eric Dumazet   net: return opera...
137
  		return -EAFNOSUPPORT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
138

4c9483b2f   David S. Miller   ipv6: Convert to ...
139
  	memset(&fl6, 0, sizeof(fl6));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
140
141
  
  	if (np->sndflow) {
4c9483b2f   David S. Miller   ipv6: Convert to ...
142
143
144
  		fl6.flowlabel = usin->sin6_flowinfo&IPV6_FLOWINFO_MASK;
  		IP6_ECN_flow_init(fl6.flowlabel);
  		if (fl6.flowlabel&IPV6_FLOWLABEL_MASK) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
145
  			struct ip6_flowlabel *flowlabel;
4c9483b2f   David S. Miller   ipv6: Convert to ...
146
  			flowlabel = fl6_sock_lookup(sk, fl6.flowlabel);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
147
148
  			if (flowlabel == NULL)
  				return -EINVAL;
4e3fd7a06   Alexey Dobriyan   net: remove ipv6_...
149
  			usin->sin6_addr = flowlabel->dst;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
150
151
152
153
154
  			fl6_sock_release(flowlabel);
  		}
  	}
  
  	/*
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
155
156
157
158
159
  	 *	connect() to INADDR_ANY means loopback (BSD'ism).
  	 */
  
  	if(ipv6_addr_any(&usin->sin6_addr))
  		usin->sin6_addr.s6_addr[15] = 0x1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
  
  	addr_type = ipv6_addr_type(&usin->sin6_addr);
  
  	if(addr_type & IPV6_ADDR_MULTICAST)
  		return -ENETUNREACH;
  
  	if (addr_type&IPV6_ADDR_LINKLOCAL) {
  		if (addr_len >= sizeof(struct sockaddr_in6) &&
  		    usin->sin6_scope_id) {
  			/* If interface is set while binding, indices
  			 * must coincide.
  			 */
  			if (sk->sk_bound_dev_if &&
  			    sk->sk_bound_dev_if != usin->sin6_scope_id)
  				return -EINVAL;
  
  			sk->sk_bound_dev_if = usin->sin6_scope_id;
  		}
  
  		/* Connect to link-local address requires an interface */
  		if (!sk->sk_bound_dev_if)
  			return -EINVAL;
  	}
  
  	if (tp->rx_opt.ts_recent_stamp &&
  	    !ipv6_addr_equal(&np->daddr, &usin->sin6_addr)) {
  		tp->rx_opt.ts_recent = 0;
  		tp->rx_opt.ts_recent_stamp = 0;
  		tp->write_seq = 0;
  	}
4e3fd7a06   Alexey Dobriyan   net: remove ipv6_...
190
  	np->daddr = usin->sin6_addr;
4c9483b2f   David S. Miller   ipv6: Convert to ...
191
  	np->flow_label = fl6.flowlabel;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
192
193
194
195
196
197
  
  	/*
  	 *	TCP over IPv4
  	 */
  
  	if (addr_type == IPV6_ADDR_MAPPED) {
d83d8461f   Arnaldo Carvalho de Melo   [IP_SOCKGLUE]: Re...
198
  		u32 exthdrlen = icsk->icsk_ext_hdr_len;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
199
200
201
202
203
204
205
206
207
208
209
  		struct sockaddr_in sin;
  
  		SOCK_DEBUG(sk, "connect: ipv4 mapped
  ");
  
  		if (__ipv6_only_sock(sk))
  			return -ENETUNREACH;
  
  		sin.sin_family = AF_INET;
  		sin.sin_port = usin->sin6_port;
  		sin.sin_addr.s_addr = usin->sin6_addr.s6_addr32[3];
d83d8461f   Arnaldo Carvalho de Melo   [IP_SOCKGLUE]: Re...
210
  		icsk->icsk_af_ops = &ipv6_mapped;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
211
  		sk->sk_backlog_rcv = tcp_v4_do_rcv;
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
212
213
214
  #ifdef CONFIG_TCP_MD5SIG
  		tp->af_specific = &tcp_sock_ipv6_mapped_specific;
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
215
216
217
218
  
  		err = tcp_v4_connect(sk, (struct sockaddr *)&sin, sizeof(sin));
  
  		if (err) {
d83d8461f   Arnaldo Carvalho de Melo   [IP_SOCKGLUE]: Re...
219
220
  			icsk->icsk_ext_hdr_len = exthdrlen;
  			icsk->icsk_af_ops = &ipv6_specific;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
221
  			sk->sk_backlog_rcv = tcp_v6_do_rcv;
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
222
223
224
  #ifdef CONFIG_TCP_MD5SIG
  			tp->af_specific = &tcp_sock_ipv6_specific;
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
225
226
  			goto failure;
  		} else {
c720c7e83   Eric Dumazet   inet: rename some...
227
228
229
  			ipv6_addr_set_v4mapped(inet->inet_saddr, &np->saddr);
  			ipv6_addr_set_v4mapped(inet->inet_rcv_saddr,
  					       &np->rcv_saddr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
230
231
232
233
234
235
236
  		}
  
  		return err;
  	}
  
  	if (!ipv6_addr_any(&np->rcv_saddr))
  		saddr = &np->rcv_saddr;
4c9483b2f   David S. Miller   ipv6: Convert to ...
237
  	fl6.flowi6_proto = IPPROTO_TCP;
4e3fd7a06   Alexey Dobriyan   net: remove ipv6_...
238
239
  	fl6.daddr = np->daddr;
  	fl6.saddr = saddr ? *saddr : np->saddr;
4c9483b2f   David S. Miller   ipv6: Convert to ...
240
241
  	fl6.flowi6_oif = sk->sk_bound_dev_if;
  	fl6.flowi6_mark = sk->sk_mark;
1958b856c   David S. Miller   net: Put fl6_* ma...
242
243
  	fl6.fl6_dport = usin->sin6_port;
  	fl6.fl6_sport = inet->inet_sport;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
244

4c9483b2f   David S. Miller   ipv6: Convert to ...
245
  	final_p = fl6_update_dst(&fl6, np->opt, &final);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
246

4c9483b2f   David S. Miller   ipv6: Convert to ...
247
  	security_sk_classify_flow(sk, flowi6_to_flowi(&fl6));
beb8d13be   Venkat Yekkirala   [MLSXFRM]: Add fl...
248

4c9483b2f   David S. Miller   ipv6: Convert to ...
249
  	dst = ip6_dst_lookup_flow(sk, &fl6, final_p, true);
68d0c6d34   David S. Miller   ipv6: Consolidate...
250
251
  	if (IS_ERR(dst)) {
  		err = PTR_ERR(dst);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
252
  		goto failure;
14e50e57a   David S. Miller   [XFRM]: Allow pac...
253
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
254
255
  
  	if (saddr == NULL) {
4c9483b2f   David S. Miller   ipv6: Convert to ...
256
  		saddr = &fl6.saddr;
4e3fd7a06   Alexey Dobriyan   net: remove ipv6_...
257
  		np->rcv_saddr = *saddr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
258
259
260
  	}
  
  	/* set the source address */
4e3fd7a06   Alexey Dobriyan   net: remove ipv6_...
261
  	np->saddr = *saddr;
c720c7e83   Eric Dumazet   inet: rename some...
262
  	inet->inet_rcv_saddr = LOOPBACK4_IPV6;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
263

f83ef8c0b   Herbert Xu   [IPV6]: Added GSO...
264
  	sk->sk_gso_type = SKB_GSO_TCPV6;
8e1ef0a95   YOSHIFUJI Hideaki   [IPV6]: Cache sou...
265
  	__ip6_dst_store(sk, dst, NULL, NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
266

493f377d6   David S. Miller   tcp: Add timewait...
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
  	rt = (struct rt6_info *) dst;
  	if (tcp_death_row.sysctl_tw_recycle &&
  	    !tp->rx_opt.ts_recent_stamp &&
  	    ipv6_addr_equal(&rt->rt6i_dst.addr, &np->daddr)) {
  		struct inet_peer *peer = rt6_get_peer(rt);
  		/*
  		 * VJ's idea. We save last timestamp seen from
  		 * the destination in peer table, when entering state
  		 * TIME-WAIT * and initialize rx_opt.ts_recent from it,
  		 * when trying new connection.
  		 */
  		if (peer) {
  			inet_peer_refcheck(peer);
  			if ((u32)get_seconds() - peer->tcp_ts_stamp <= TCP_PAWS_MSL) {
  				tp->rx_opt.ts_recent_stamp = peer->tcp_ts_stamp;
  				tp->rx_opt.ts_recent = peer->tcp_ts;
  			}
  		}
  	}
d83d8461f   Arnaldo Carvalho de Melo   [IP_SOCKGLUE]: Re...
286
  	icsk->icsk_ext_hdr_len = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
287
  	if (np->opt)
d83d8461f   Arnaldo Carvalho de Melo   [IP_SOCKGLUE]: Re...
288
289
  		icsk->icsk_ext_hdr_len = (np->opt->opt_flen +
  					  np->opt->opt_nflen);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
290
291
  
  	tp->rx_opt.mss_clamp = IPV6_MIN_MTU - sizeof(struct tcphdr) - sizeof(struct ipv6hdr);
c720c7e83   Eric Dumazet   inet: rename some...
292
  	inet->inet_dport = usin->sin6_port;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
293
294
  
  	tcp_set_state(sk, TCP_SYN_SENT);
d8313f5ca   Arnaldo Carvalho de Melo   [INET6]: Generali...
295
  	err = inet6_hash_connect(&tcp_death_row, sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
296
297
298
299
300
301
  	if (err)
  		goto late_failure;
  
  	if (!tp->write_seq)
  		tp->write_seq = secure_tcpv6_sequence_number(np->saddr.s6_addr32,
  							     np->daddr.s6_addr32,
c720c7e83   Eric Dumazet   inet: rename some...
302
303
  							     inet->inet_sport,
  							     inet->inet_dport);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
304
305
306
307
308
309
310
311
312
313
314
  
  	err = tcp_connect(sk);
  	if (err)
  		goto late_failure;
  
  	return 0;
  
  late_failure:
  	tcp_set_state(sk, TCP_CLOSE);
  	__sk_dst_reset(sk);
  failure:
c720c7e83   Eric Dumazet   inet: rename some...
315
  	inet->inet_dport = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
316
317
318
319
320
  	sk->sk_route_caps = 0;
  	return err;
  }
  
  static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
d5fdd6bab   Brian Haley   ipv6: Use correct...
321
  		u8 type, u8 code, int offset, __be32 info)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
322
  {
b71d1d426   Eric Dumazet   inet: constify ip...
323
  	const struct ipv6hdr *hdr = (const struct ipv6hdr*)skb->data;
505cbfc57   Arnaldo Carvalho de Melo   [IPV6]: Generalis...
324
  	const struct tcphdr *th = (struct tcphdr *)(skb->data+offset);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
325
326
327
  	struct ipv6_pinfo *np;
  	struct sock *sk;
  	int err;
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
328
  	struct tcp_sock *tp;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
329
  	__u32 seq;
ca12a1a44   Pavel Emelyanov   inet: prepare net...
330
  	struct net *net = dev_net(skb->dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
331

ca12a1a44   Pavel Emelyanov   inet: prepare net...
332
  	sk = inet6_lookup(net, &tcp_hashinfo, &hdr->daddr,
d86e0dac2   Pavel Emelyanov   [NETNS]: Tcp-v6 s...
333
  			th->dest, &hdr->saddr, th->source, skb->dev->ifindex);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
334
335
  
  	if (sk == NULL) {
e41b5368e   Denis V. Lunev   ipv6: added net a...
336
337
  		ICMP6_INC_STATS_BH(net, __in6_dev_get(skb->dev),
  				   ICMP6_MIB_INERRORS);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
338
339
340
341
  		return;
  	}
  
  	if (sk->sk_state == TCP_TIME_WAIT) {
9469c7b4a   YOSHIFUJI Hideaki   [NET]: Use typesa...
342
  		inet_twsk_put(inet_twsk(sk));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
343
344
345
346
347
  		return;
  	}
  
  	bh_lock_sock(sk);
  	if (sock_owned_by_user(sk))
de0744af1   Pavel Emelyanov   mib: add net to N...
348
  		NET_INC_STATS_BH(net, LINUX_MIB_LOCKDROPPEDICMPS);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
349
350
351
  
  	if (sk->sk_state == TCP_CLOSE)
  		goto out;
e802af9ca   Stephen Hemminger   IPv6: Generic TTL...
352
353
354
355
  	if (ipv6_hdr(skb)->hop_limit < inet6_sk(sk)->min_hopcount) {
  		NET_INC_STATS_BH(net, LINUX_MIB_TCPMINTTLDROP);
  		goto out;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
356
  	tp = tcp_sk(sk);
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
357
  	seq = ntohl(th->seq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
358
359
  	if (sk->sk_state != TCP_LISTEN &&
  	    !between(seq, tp->snd_una, tp->snd_nxt)) {
de0744af1   Pavel Emelyanov   mib: add net to N...
360
  		NET_INC_STATS_BH(net, LINUX_MIB_OUTOFWINDOWICMPS);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
361
362
363
364
365
366
  		goto out;
  	}
  
  	np = inet6_sk(sk);
  
  	if (type == ICMPV6_PKT_TOOBIG) {
68d0c6d34   David S. Miller   ipv6: Consolidate...
367
  		struct dst_entry *dst;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
368
369
370
371
372
373
374
375
376
377
378
  
  		if (sock_owned_by_user(sk))
  			goto out;
  		if ((1 << sk->sk_state) & (TCPF_LISTEN | TCPF_CLOSE))
  			goto out;
  
  		/* icmp should have updated the destination cache entry */
  		dst = __sk_dst_check(sk, np->dst_cookie);
  
  		if (dst == NULL) {
  			struct inet_sock *inet = inet_sk(sk);
4c9483b2f   David S. Miller   ipv6: Convert to ...
379
  			struct flowi6 fl6;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
380
381
382
383
384
  
  			/* BUGGG_FUTURE: Again, it is not clear how
  			   to handle rthdr case. Ignore this complexity
  			   for now.
  			 */
4c9483b2f   David S. Miller   ipv6: Convert to ...
385
386
  			memset(&fl6, 0, sizeof(fl6));
  			fl6.flowi6_proto = IPPROTO_TCP;
4e3fd7a06   Alexey Dobriyan   net: remove ipv6_...
387
388
  			fl6.daddr = np->daddr;
  			fl6.saddr = np->saddr;
4c9483b2f   David S. Miller   ipv6: Convert to ...
389
390
  			fl6.flowi6_oif = sk->sk_bound_dev_if;
  			fl6.flowi6_mark = sk->sk_mark;
1958b856c   David S. Miller   net: Put fl6_* ma...
391
392
  			fl6.fl6_dport = inet->inet_dport;
  			fl6.fl6_sport = inet->inet_sport;
4c9483b2f   David S. Miller   ipv6: Convert to ...
393
394
395
  			security_skb_classify_flow(skb, flowi6_to_flowi(&fl6));
  
  			dst = ip6_dst_lookup_flow(sk, &fl6, NULL, false);
68d0c6d34   David S. Miller   ipv6: Consolidate...
396
397
  			if (IS_ERR(dst)) {
  				sk->sk_err_soft = -PTR_ERR(dst);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
398
399
400
401
402
  				goto out;
  			}
  
  		} else
  			dst_hold(dst);
d83d8461f   Arnaldo Carvalho de Melo   [IP_SOCKGLUE]: Re...
403
  		if (inet_csk(sk)->icsk_pmtu_cookie > dst_mtu(dst)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
404
405
406
407
408
409
410
411
  			tcp_sync_mss(sk, dst_mtu(dst));
  			tcp_simple_retransmit(sk);
  		} /* else let the usual retransmit timer handle it */
  		dst_release(dst);
  		goto out;
  	}
  
  	icmpv6_err_convert(type, code, &err);
60236fdd0   Arnaldo Carvalho de Melo   [NET] Rename open...
412
  	/* Might be for an request_sock */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
413
  	switch (sk->sk_state) {
60236fdd0   Arnaldo Carvalho de Melo   [NET] Rename open...
414
  		struct request_sock *req, **prev;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
415
416
417
  	case TCP_LISTEN:
  		if (sock_owned_by_user(sk))
  			goto out;
8129765ac   Arnaldo Carvalho de Melo   [IPV6]: Generalis...
418
419
  		req = inet6_csk_search_req(sk, &prev, th->dest, &hdr->daddr,
  					   &hdr->saddr, inet6_iif(skb));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
420
421
422
423
424
425
  		if (!req)
  			goto out;
  
  		/* ICMPs are not backlogged, hence we cannot get
  		 * an established socket here.
  		 */
547b792ca   Ilpo Järvinen   net: convert BUG_...
426
  		WARN_ON(req->sk != NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
427

2e6599cb8   Arnaldo Carvalho de Melo   [NET] Generalise ...
428
  		if (seq != tcp_rsk(req)->snt_isn) {
de0744af1   Pavel Emelyanov   mib: add net to N...
429
  			NET_INC_STATS_BH(net, LINUX_MIB_OUTOFWINDOWICMPS);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
430
431
  			goto out;
  		}
463c84b97   Arnaldo Carvalho de Melo   [NET]: Introduce ...
432
  		inet_csk_reqsk_queue_drop(sk, req, prev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
433
434
435
436
  		goto out;
  
  	case TCP_SYN_SENT:
  	case TCP_SYN_RECV:  /* Cannot happen.
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
437
  			       It can, it SYNs are crossed. --ANK */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
438
  		if (!sock_owned_by_user(sk)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
  			sk->sk_err = err;
  			sk->sk_error_report(sk);		/* Wake people up to see the error (see connect in sock.c) */
  
  			tcp_done(sk);
  		} else
  			sk->sk_err_soft = err;
  		goto out;
  	}
  
  	if (!sock_owned_by_user(sk) && np->recverr) {
  		sk->sk_err = err;
  		sk->sk_error_report(sk);
  	} else
  		sk->sk_err_soft = err;
  
  out:
  	bh_unlock_sock(sk);
  	sock_put(sk);
  }
e6b4d1136   William Allen Simpson   TCPCT part 1a: ad...
458
459
  static int tcp_v6_send_synack(struct sock *sk, struct request_sock *req,
  			      struct request_values *rvp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
460
  {
ca304b610   Arnaldo Carvalho de Melo   [IPV6]: Introduce...
461
  	struct inet6_request_sock *treq = inet6_rsk(req);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
462
463
464
  	struct ipv6_pinfo *np = inet6_sk(sk);
  	struct sk_buff * skb;
  	struct ipv6_txoptions *opt = NULL;
20c59de2e   Arnaud Ebalard   ipv6: Refactor up...
465
  	struct in6_addr * final_p, final;
4c9483b2f   David S. Miller   ipv6: Convert to ...
466
  	struct flowi6 fl6;
fd80eb942   Denis V. Lunev   [INET]: Remove st...
467
  	struct dst_entry *dst;
68d0c6d34   David S. Miller   ipv6: Consolidate...
468
  	int err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
469

4c9483b2f   David S. Miller   ipv6: Convert to ...
470
471
  	memset(&fl6, 0, sizeof(fl6));
  	fl6.flowi6_proto = IPPROTO_TCP;
4e3fd7a06   Alexey Dobriyan   net: remove ipv6_...
472
473
  	fl6.daddr = treq->rmt_addr;
  	fl6.saddr = treq->loc_addr;
4c9483b2f   David S. Miller   ipv6: Convert to ...
474
475
476
  	fl6.flowlabel = 0;
  	fl6.flowi6_oif = treq->iif;
  	fl6.flowi6_mark = sk->sk_mark;
1958b856c   David S. Miller   net: Put fl6_* ma...
477
478
  	fl6.fl6_dport = inet_rsk(req)->rmt_port;
  	fl6.fl6_sport = inet_rsk(req)->loc_port;
4c9483b2f   David S. Miller   ipv6: Convert to ...
479
  	security_req_classify_flow(req, flowi6_to_flowi(&fl6));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
480

fd80eb942   Denis V. Lunev   [INET]: Remove st...
481
  	opt = np->opt;
4c9483b2f   David S. Miller   ipv6: Convert to ...
482
  	final_p = fl6_update_dst(&fl6, opt, &final);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
483

4c9483b2f   David S. Miller   ipv6: Convert to ...
484
  	dst = ip6_dst_lookup_flow(sk, &fl6, final_p, false);
68d0c6d34   David S. Miller   ipv6: Consolidate...
485
486
  	if (IS_ERR(dst)) {
  		err = PTR_ERR(dst);
738faca34   Boris Ostrovsky   ipv6: Don't pass ...
487
  		dst = NULL;
fd80eb942   Denis V. Lunev   [INET]: Remove st...
488
  		goto done;
68d0c6d34   David S. Miller   ipv6: Consolidate...
489
  	}
e6b4d1136   William Allen Simpson   TCPCT part 1a: ad...
490
  	skb = tcp_make_synack(sk, dst, req, rvp);
68d0c6d34   David S. Miller   ipv6: Consolidate...
491
  	err = -ENOMEM;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
492
  	if (skb) {
8ad50d96d   Herbert Xu   tcp: Handle CHECK...
493
  		__tcp_v6_send_check(skb, &treq->loc_addr, &treq->rmt_addr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
494

4e3fd7a06   Alexey Dobriyan   net: remove ipv6_...
495
  		fl6.daddr = treq->rmt_addr;
b903d324b   Eric Dumazet   ipv6: tcp: fix TC...
496
  		err = ip6_xmit(sk, skb, &fl6, opt, np->tclass);
b9df3cb8c   Gerrit Renker   [TCP/DCCP]: Intro...
497
  		err = net_xmit_eval(err);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
498
499
500
  	}
  
  done:
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
501
  	if (opt && opt != np->opt)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
502
  		sock_kfree_s(sk, opt, opt->tot_len);
78b910429   Eric W. Biederman   [IPV6] tcp_v6_sen...
503
  	dst_release(dst);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
504
505
  	return err;
  }
72659ecce   Octavian Purdila   tcp: account SYN-...
506
507
508
509
510
511
  static int tcp_v6_rtx_synack(struct sock *sk, struct request_sock *req,
  			     struct request_values *rvp)
  {
  	TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_RETRANSSEGS);
  	return tcp_v6_send_synack(sk, req, rvp);
  }
60236fdd0   Arnaldo Carvalho de Melo   [NET] Rename open...
512
  static void tcp_v6_reqsk_destructor(struct request_sock *req)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
513
  {
800d55f14   Wei Yongjun   ipv6: Remove some...
514
  	kfree_skb(inet6_rsk(req)->pktopts);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
515
  }
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
516
517
  #ifdef CONFIG_TCP_MD5SIG
  static struct tcp_md5sig_key *tcp_v6_md5_do_lookup(struct sock *sk,
b71d1d426   Eric Dumazet   inet: constify ip...
518
  						   const struct in6_addr *addr)
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
519
520
521
522
523
524
525
526
527
528
  {
  	struct tcp_sock *tp = tcp_sk(sk);
  	int i;
  
  	BUG_ON(tp == NULL);
  
  	if (!tp->md5sig_info || !tp->md5sig_info->entries6)
  		return NULL;
  
  	for (i = 0; i < tp->md5sig_info->entries6; i++) {
caad295fe   YOSHIFUJI Hideaki   [IPV6]: Use ipv6_...
529
  		if (ipv6_addr_equal(&tp->md5sig_info->keys6[i].addr, addr))
f8ab18d2d   David S. Miller   [TCP]: Fix MD5 si...
530
  			return &tp->md5sig_info->keys6[i].base;
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
  	}
  	return NULL;
  }
  
  static struct tcp_md5sig_key *tcp_v6_md5_lookup(struct sock *sk,
  						struct sock *addr_sk)
  {
  	return tcp_v6_md5_do_lookup(sk, &inet6_sk(addr_sk)->daddr);
  }
  
  static struct tcp_md5sig_key *tcp_v6_reqsk_md5_lookup(struct sock *sk,
  						      struct request_sock *req)
  {
  	return tcp_v6_md5_do_lookup(sk, &inet6_rsk(req)->rmt_addr);
  }
b71d1d426   Eric Dumazet   inet: constify ip...
546
  static int tcp_v6_md5_do_add(struct sock *sk, const struct in6_addr *peer,
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
547
548
549
  			     char *newkey, u8 newkeylen)
  {
  	/* Add key to the list */
b0a713e9e   Matthias M. Dellweg   [TCP] MD5: Remove...
550
  	struct tcp_md5sig_key *key;
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
551
552
  	struct tcp_sock *tp = tcp_sk(sk);
  	struct tcp6_md5sig_key *keys;
b0a713e9e   Matthias M. Dellweg   [TCP] MD5: Remove...
553
  	key = tcp_v6_md5_do_lookup(sk, peer);
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
554
555
  	if (key) {
  		/* modify existing entry - just update that one */
b0a713e9e   Matthias M. Dellweg   [TCP] MD5: Remove...
556
557
558
  		kfree(key->key);
  		key->key = newkey;
  		key->keylen = newkeylen;
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
559
560
561
562
563
564
565
566
  	} else {
  		/* reallocate new list if current one is full. */
  		if (!tp->md5sig_info) {
  			tp->md5sig_info = kzalloc(sizeof(*tp->md5sig_info), GFP_ATOMIC);
  			if (!tp->md5sig_info) {
  				kfree(newkey);
  				return -ENOMEM;
  			}
a465419b1   Eric Dumazet   net: Introduce sk...
567
  			sk_nocaps_add(sk, NETIF_F_GSO_MASK);
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
568
  		}
260fcbeb1   Yan, Zheng   tcp: properly han...
569
570
  		if (tp->md5sig_info->entries6 == 0 &&
  			tcp_alloc_md5sig_pool(sk) == NULL) {
aacbe8c88   YOSHIFUJI Hideaki   [IPV6] TCPMD5: Ch...
571
572
573
  			kfree(newkey);
  			return -ENOMEM;
  		}
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
574
575
576
577
578
  		if (tp->md5sig_info->alloced6 == tp->md5sig_info->entries6) {
  			keys = kmalloc((sizeof (tp->md5sig_info->keys6[0]) *
  				       (tp->md5sig_info->entries6 + 1)), GFP_ATOMIC);
  
  			if (!keys) {
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
579
  				kfree(newkey);
260fcbeb1   Yan, Zheng   tcp: properly han...
580
581
  				if (tp->md5sig_info->entries6 == 0)
  					tcp_free_md5sig_pool();
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
582
583
584
585
586
587
588
589
590
591
592
593
  				return -ENOMEM;
  			}
  
  			if (tp->md5sig_info->entries6)
  				memmove(keys, tp->md5sig_info->keys6,
  					(sizeof (tp->md5sig_info->keys6[0]) *
  					 tp->md5sig_info->entries6));
  
  			kfree(tp->md5sig_info->keys6);
  			tp->md5sig_info->keys6 = keys;
  			tp->md5sig_info->alloced6++;
  		}
4e3fd7a06   Alexey Dobriyan   net: remove ipv6_...
594
  		tp->md5sig_info->keys6[tp->md5sig_info->entries6].addr = *peer;
f8ab18d2d   David S. Miller   [TCP]: Fix MD5 si...
595
596
  		tp->md5sig_info->keys6[tp->md5sig_info->entries6].base.key = newkey;
  		tp->md5sig_info->keys6[tp->md5sig_info->entries6].base.keylen = newkeylen;
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
597
598
599
600
601
602
603
604
605
606
607
608
  
  		tp->md5sig_info->entries6++;
  	}
  	return 0;
  }
  
  static int tcp_v6_md5_add_func(struct sock *sk, struct sock *addr_sk,
  			       u8 *newkey, __u8 newkeylen)
  {
  	return tcp_v6_md5_do_add(sk, &inet6_sk(addr_sk)->daddr,
  				 newkey, newkeylen);
  }
b71d1d426   Eric Dumazet   inet: constify ip...
609
  static int tcp_v6_md5_do_del(struct sock *sk, const struct in6_addr *peer)
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
610
611
612
613
614
  {
  	struct tcp_sock *tp = tcp_sk(sk);
  	int i;
  
  	for (i = 0; i < tp->md5sig_info->entries6; i++) {
caad295fe   YOSHIFUJI Hideaki   [IPV6]: Use ipv6_...
615
  		if (ipv6_addr_equal(&tp->md5sig_info->keys6[i].addr, peer)) {
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
616
  			/* Free the key */
f8ab18d2d   David S. Miller   [TCP]: Fix MD5 si...
617
  			kfree(tp->md5sig_info->keys6[i].base.key);
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
618
619
620
621
622
  			tp->md5sig_info->entries6--;
  
  			if (tp->md5sig_info->entries6 == 0) {
  				kfree(tp->md5sig_info->keys6);
  				tp->md5sig_info->keys6 = NULL;
ca983cefd   YOSHIFUJI Hideaki   [TCPv6] MD5SIG: E...
623
  				tp->md5sig_info->alloced6 = 0;
260fcbeb1   Yan, Zheng   tcp: properly han...
624
  				tcp_free_md5sig_pool();
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
625
626
627
628
629
630
631
632
  			} else {
  				/* shrink the database */
  				if (tp->md5sig_info->entries6 != i)
  					memmove(&tp->md5sig_info->keys6[i],
  						&tp->md5sig_info->keys6[i+1],
  						(tp->md5sig_info->entries6 - i)
  						* sizeof (tp->md5sig_info->keys6[0]));
  			}
77adefdc9   YOSHIFUJI Hideaki   [IPV6] TCPMD5: Fi...
633
  			return 0;
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
634
635
636
637
638
639
640
641
642
643
644
645
  		}
  	}
  	return -ENOENT;
  }
  
  static void tcp_v6_clear_md5_list (struct sock *sk)
  {
  	struct tcp_sock *tp = tcp_sk(sk);
  	int i;
  
  	if (tp->md5sig_info->entries6) {
  		for (i = 0; i < tp->md5sig_info->entries6; i++)
f8ab18d2d   David S. Miller   [TCP]: Fix MD5 si...
646
  			kfree(tp->md5sig_info->keys6[i].base.key);
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
647
648
649
650
651
652
653
654
655
656
  		tp->md5sig_info->entries6 = 0;
  		tcp_free_md5sig_pool();
  	}
  
  	kfree(tp->md5sig_info->keys6);
  	tp->md5sig_info->keys6 = NULL;
  	tp->md5sig_info->alloced6 = 0;
  
  	if (tp->md5sig_info->entries4) {
  		for (i = 0; i < tp->md5sig_info->entries4; i++)
f8ab18d2d   David S. Miller   [TCP]: Fix MD5 si...
657
  			kfree(tp->md5sig_info->keys4[i].base.key);
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
  		tp->md5sig_info->entries4 = 0;
  		tcp_free_md5sig_pool();
  	}
  
  	kfree(tp->md5sig_info->keys4);
  	tp->md5sig_info->keys4 = NULL;
  	tp->md5sig_info->alloced4 = 0;
  }
  
  static int tcp_v6_parse_md5_keys (struct sock *sk, char __user *optval,
  				  int optlen)
  {
  	struct tcp_md5sig cmd;
  	struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&cmd.tcpm_addr;
  	u8 *newkey;
  
  	if (optlen < sizeof(cmd))
  		return -EINVAL;
  
  	if (copy_from_user(&cmd, optval, sizeof(cmd)))
  		return -EFAULT;
  
  	if (sin6->sin6_family != AF_INET6)
  		return -EINVAL;
  
  	if (!cmd.tcpm_keylen) {
  		if (!tcp_sk(sk)->md5sig_info)
  			return -ENOENT;
e773e4faa   Brian Haley   [IPV6]: Add v4map...
686
  		if (ipv6_addr_v4mapped(&sin6->sin6_addr))
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
  			return tcp_v4_md5_do_del(sk, sin6->sin6_addr.s6_addr32[3]);
  		return tcp_v6_md5_do_del(sk, &sin6->sin6_addr);
  	}
  
  	if (cmd.tcpm_keylen > TCP_MD5SIG_MAXKEYLEN)
  		return -EINVAL;
  
  	if (!tcp_sk(sk)->md5sig_info) {
  		struct tcp_sock *tp = tcp_sk(sk);
  		struct tcp_md5sig_info *p;
  
  		p = kzalloc(sizeof(struct tcp_md5sig_info), GFP_KERNEL);
  		if (!p)
  			return -ENOMEM;
  
  		tp->md5sig_info = p;
a465419b1   Eric Dumazet   net: Introduce sk...
703
  		sk_nocaps_add(sk, NETIF_F_GSO_MASK);
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
704
  	}
af879cc70   Arnaldo Carvalho de Melo   [IPV6]: Use kmemdup
705
  	newkey = kmemdup(cmd.tcpm_key, cmd.tcpm_keylen, GFP_KERNEL);
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
706
707
  	if (!newkey)
  		return -ENOMEM;
e773e4faa   Brian Haley   [IPV6]: Add v4map...
708
  	if (ipv6_addr_v4mapped(&sin6->sin6_addr)) {
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
709
710
711
712
713
  		return tcp_v4_md5_do_add(sk, sin6->sin6_addr.s6_addr32[3],
  					 newkey, cmd.tcpm_keylen);
  	}
  	return tcp_v6_md5_do_add(sk, &sin6->sin6_addr, newkey, cmd.tcpm_keylen);
  }
49a72dfb8   Adam Langley   tcp: Fix MD5 sign...
714
  static int tcp_v6_md5_hash_pseudoheader(struct tcp_md5sig_pool *hp,
b71d1d426   Eric Dumazet   inet: constify ip...
715
716
  					const struct in6_addr *daddr,
  					const struct in6_addr *saddr, int nbytes)
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
717
  {
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
718
  	struct tcp6_pseudohdr *bp;
49a72dfb8   Adam Langley   tcp: Fix MD5 sign...
719
  	struct scatterlist sg;
8d26d76dd   YOSHIFUJI Hideaki   tcp md5sig: Share...
720

cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
721
  	bp = &hp->md5_blk.ip6;
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
722
  	/* 1. TCP pseudo-header (RFC2460) */
4e3fd7a06   Alexey Dobriyan   net: remove ipv6_...
723
724
  	bp->saddr = *saddr;
  	bp->daddr = *daddr;
49a72dfb8   Adam Langley   tcp: Fix MD5 sign...
725
  	bp->protocol = cpu_to_be32(IPPROTO_TCP);
00b1304c4   Adam Langley   tcp: MD5: Fix IPv...
726
  	bp->len = cpu_to_be32(nbytes);
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
727

49a72dfb8   Adam Langley   tcp: Fix MD5 sign...
728
729
730
  	sg_init_one(&sg, bp, sizeof(*bp));
  	return crypto_hash_update(&hp->md5_desc, &sg, sizeof(*bp));
  }
c7da57a18   David S. Miller   [TCP]: Fix scatte...
731

49a72dfb8   Adam Langley   tcp: Fix MD5 sign...
732
  static int tcp_v6_md5_hash_hdr(char *md5_hash, struct tcp_md5sig_key *key,
b71d1d426   Eric Dumazet   inet: constify ip...
733
  			       const struct in6_addr *daddr, struct in6_addr *saddr,
318cf7aaa   Eric Dumazet   tcp: md5: add mor...
734
  			       const struct tcphdr *th)
49a72dfb8   Adam Langley   tcp: Fix MD5 sign...
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
  {
  	struct tcp_md5sig_pool *hp;
  	struct hash_desc *desc;
  
  	hp = tcp_get_md5sig_pool();
  	if (!hp)
  		goto clear_hash_noput;
  	desc = &hp->md5_desc;
  
  	if (crypto_hash_init(desc))
  		goto clear_hash;
  	if (tcp_v6_md5_hash_pseudoheader(hp, daddr, saddr, th->doff << 2))
  		goto clear_hash;
  	if (tcp_md5_hash_header(hp, th))
  		goto clear_hash;
  	if (tcp_md5_hash_key(hp, key))
  		goto clear_hash;
  	if (crypto_hash_final(desc, md5_hash))
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
753
  		goto clear_hash;
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
754

cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
755
  	tcp_put_md5sig_pool();
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
756
  	return 0;
49a72dfb8   Adam Langley   tcp: Fix MD5 sign...
757

cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
758
759
760
761
  clear_hash:
  	tcp_put_md5sig_pool();
  clear_hash_noput:
  	memset(md5_hash, 0, 16);
49a72dfb8   Adam Langley   tcp: Fix MD5 sign...
762
  	return 1;
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
763
  }
49a72dfb8   Adam Langley   tcp: Fix MD5 sign...
764
  static int tcp_v6_md5_hash_skb(char *md5_hash, struct tcp_md5sig_key *key,
318cf7aaa   Eric Dumazet   tcp: md5: add mor...
765
766
767
  			       const struct sock *sk,
  			       const struct request_sock *req,
  			       const struct sk_buff *skb)
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
768
  {
b71d1d426   Eric Dumazet   inet: constify ip...
769
  	const struct in6_addr *saddr, *daddr;
49a72dfb8   Adam Langley   tcp: Fix MD5 sign...
770
771
  	struct tcp_md5sig_pool *hp;
  	struct hash_desc *desc;
318cf7aaa   Eric Dumazet   tcp: md5: add mor...
772
  	const struct tcphdr *th = tcp_hdr(skb);
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
773
774
775
776
  
  	if (sk) {
  		saddr = &inet6_sk(sk)->saddr;
  		daddr = &inet6_sk(sk)->daddr;
49a72dfb8   Adam Langley   tcp: Fix MD5 sign...
777
  	} else if (req) {
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
778
779
  		saddr = &inet6_rsk(req)->loc_addr;
  		daddr = &inet6_rsk(req)->rmt_addr;
49a72dfb8   Adam Langley   tcp: Fix MD5 sign...
780
  	} else {
b71d1d426   Eric Dumazet   inet: constify ip...
781
  		const struct ipv6hdr *ip6h = ipv6_hdr(skb);
49a72dfb8   Adam Langley   tcp: Fix MD5 sign...
782
783
  		saddr = &ip6h->saddr;
  		daddr = &ip6h->daddr;
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
784
  	}
49a72dfb8   Adam Langley   tcp: Fix MD5 sign...
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
  
  	hp = tcp_get_md5sig_pool();
  	if (!hp)
  		goto clear_hash_noput;
  	desc = &hp->md5_desc;
  
  	if (crypto_hash_init(desc))
  		goto clear_hash;
  
  	if (tcp_v6_md5_hash_pseudoheader(hp, daddr, saddr, skb->len))
  		goto clear_hash;
  	if (tcp_md5_hash_header(hp, th))
  		goto clear_hash;
  	if (tcp_md5_hash_skb_data(hp, skb, th->doff << 2))
  		goto clear_hash;
  	if (tcp_md5_hash_key(hp, key))
  		goto clear_hash;
  	if (crypto_hash_final(desc, md5_hash))
  		goto clear_hash;
  
  	tcp_put_md5sig_pool();
  	return 0;
  
  clear_hash:
  	tcp_put_md5sig_pool();
  clear_hash_noput:
  	memset(md5_hash, 0, 16);
  	return 1;
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
813
  }
318cf7aaa   Eric Dumazet   tcp: md5: add mor...
814
  static int tcp_v6_inbound_md5_hash(struct sock *sk, const struct sk_buff *skb)
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
815
  {
cf533ea53   Eric Dumazet   tcp: add const qu...
816
  	const __u8 *hash_location = NULL;
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
817
  	struct tcp_md5sig_key *hash_expected;
b71d1d426   Eric Dumazet   inet: constify ip...
818
  	const struct ipv6hdr *ip6h = ipv6_hdr(skb);
318cf7aaa   Eric Dumazet   tcp: md5: add mor...
819
  	const struct tcphdr *th = tcp_hdr(skb);
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
820
  	int genhash;
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
821
822
823
  	u8 newhash[16];
  
  	hash_expected = tcp_v6_md5_do_lookup(sk, &ip6h->saddr);
7d5d5525b   YOSHIFUJI Hideaki   tcp md5sig: Share...
824
  	hash_location = tcp_parse_md5sig_option(th);
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
825

785957d3e   David S. Miller   tcp: MD5: Use MIB...
826
827
828
829
830
831
  	/* We've parsed the options - do we have a hash? */
  	if (!hash_expected && !hash_location)
  		return 0;
  
  	if (hash_expected && !hash_location) {
  		NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPMD5NOTFOUND);
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
832
833
  		return 1;
  	}
785957d3e   David S. Miller   tcp: MD5: Use MIB...
834
835
  	if (!hash_expected && hash_location) {
  		NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPMD5UNEXPECTED);
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
836
837
838
839
  		return 1;
  	}
  
  	/* check the signature */
49a72dfb8   Adam Langley   tcp: Fix MD5 sign...
840
841
842
  	genhash = tcp_v6_md5_hash_skb(newhash,
  				      hash_expected,
  				      NULL, NULL, skb);
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
843
844
  	if (genhash || memcmp(hash_location, newhash, 16) != 0) {
  		if (net_ratelimit()) {
5856b606e   Joe Perches   net/ipv6/tcp_ipv6...
845
846
  			printk(KERN_INFO "MD5 Hash %s for [%pI6c]:%u->[%pI6c]:%u
  ",
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
847
  			       genhash ? "failed" : "mismatch",
0c6ce78ab   Harvey Harrison   net: replace uses...
848
849
  			       &ip6h->saddr, ntohs(th->source),
  			       &ip6h->daddr, ntohs(th->dest));
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
850
851
852
853
854
855
  		}
  		return 1;
  	}
  	return 0;
  }
  #endif
c6aefafb7   Glenn Griffin   [TCP]: Add IPv6 s...
856
  struct request_sock_ops tcp6_request_sock_ops __read_mostly = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
857
  	.family		=	AF_INET6,
2e6599cb8   Arnaldo Carvalho de Melo   [NET] Generalise ...
858
  	.obj_size	=	sizeof(struct tcp6_request_sock),
72659ecce   Octavian Purdila   tcp: account SYN-...
859
  	.rtx_syn_ack	=	tcp_v6_rtx_synack,
60236fdd0   Arnaldo Carvalho de Melo   [NET] Rename open...
860
861
  	.send_ack	=	tcp_v6_reqsk_send_ack,
  	.destructor	=	tcp_v6_reqsk_destructor,
72659ecce   Octavian Purdila   tcp: account SYN-...
862
863
  	.send_reset	=	tcp_v6_send_reset,
  	.syn_ack_timeout = 	tcp_syn_ack_timeout,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
864
  };
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
865
  #ifdef CONFIG_TCP_MD5SIG
b2e4b3deb   Stephen Hemminger   tcp: MD5 operatio...
866
  static const struct tcp_request_sock_ops tcp_request_sock_ipv6_ops = {
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
867
  	.md5_lookup	=	tcp_v6_reqsk_md5_lookup,
e3afe7b75   John Dykstra   tcp: Fix MD5 sign...
868
  	.calc_md5_hash	=	tcp_v6_md5_hash_skb,
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
869
  };
b6332e6cf   Andrew Morton   [TCP]: Fix warnin...
870
  #endif
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
871

8ad50d96d   Herbert Xu   tcp: Handle CHECK...
872
  static void __tcp_v6_send_check(struct sk_buff *skb,
b71d1d426   Eric Dumazet   inet: constify ip...
873
  				const struct in6_addr *saddr, const struct in6_addr *daddr)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
874
  {
aa8223c7b   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
875
  	struct tcphdr *th = tcp_hdr(skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
876

84fa7933a   Patrick McHardy   [NET]: Replace CH...
877
  	if (skb->ip_summed == CHECKSUM_PARTIAL) {
8ad50d96d   Herbert Xu   tcp: Handle CHECK...
878
  		th->check = ~tcp_v6_check(skb->len, saddr, daddr, 0);
663ead3bb   Herbert Xu   [NET]: Use csum_s...
879
  		skb->csum_start = skb_transport_header(skb) - skb->head;
ff1dcadb1   Al Viro   [NET]: Split skb-...
880
  		skb->csum_offset = offsetof(struct tcphdr, check);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
881
  	} else {
8ad50d96d   Herbert Xu   tcp: Handle CHECK...
882
883
884
  		th->check = tcp_v6_check(skb->len, saddr, daddr,
  					 csum_partial(th, th->doff << 2,
  						      skb->csum));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
885
886
  	}
  }
bb2962461   Herbert Xu   inet: Remove unus...
887
  static void tcp_v6_send_check(struct sock *sk, struct sk_buff *skb)
8ad50d96d   Herbert Xu   tcp: Handle CHECK...
888
889
890
891
892
  {
  	struct ipv6_pinfo *np = inet6_sk(sk);
  
  	__tcp_v6_send_check(skb, &np->saddr, &np->daddr);
  }
a430a43d0   Herbert Xu   [NET] gso: Fix up...
893
894
  static int tcp_v6_gso_send_check(struct sk_buff *skb)
  {
b71d1d426   Eric Dumazet   inet: constify ip...
895
  	const struct ipv6hdr *ipv6h;
a430a43d0   Herbert Xu   [NET] gso: Fix up...
896
897
898
899
  	struct tcphdr *th;
  
  	if (!pskb_may_pull(skb, sizeof(*th)))
  		return -EINVAL;
0660e03f6   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
900
  	ipv6h = ipv6_hdr(skb);
aa8223c7b   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
901
  	th = tcp_hdr(skb);
a430a43d0   Herbert Xu   [NET] gso: Fix up...
902
903
  
  	th->check = 0;
84fa7933a   Patrick McHardy   [NET]: Replace CH...
904
  	skb->ip_summed = CHECKSUM_PARTIAL;
8ad50d96d   Herbert Xu   tcp: Handle CHECK...
905
  	__tcp_v6_send_check(skb, &ipv6h->saddr, &ipv6h->daddr);
a430a43d0   Herbert Xu   [NET] gso: Fix up...
906
907
  	return 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
908

369906738   Herbert Xu   tcp: Unexport TCP...
909
910
  static struct sk_buff **tcp6_gro_receive(struct sk_buff **head,
  					 struct sk_buff *skb)
684f21760   Herbert Xu   tcp6: Add GRO sup...
911
  {
b71d1d426   Eric Dumazet   inet: constify ip...
912
  	const struct ipv6hdr *iph = skb_gro_network_header(skb);
684f21760   Herbert Xu   tcp6: Add GRO sup...
913
914
915
  
  	switch (skb->ip_summed) {
  	case CHECKSUM_COMPLETE:
86911732d   Herbert Xu   gro: Avoid copyin...
916
  		if (!tcp_v6_check(skb_gro_len(skb), &iph->saddr, &iph->daddr,
684f21760   Herbert Xu   tcp6: Add GRO sup...
917
918
919
920
921
922
923
924
925
926
927
928
929
  				  skb->csum)) {
  			skb->ip_summed = CHECKSUM_UNNECESSARY;
  			break;
  		}
  
  		/* fall through */
  	case CHECKSUM_NONE:
  		NAPI_GRO_CB(skb)->flush = 1;
  		return NULL;
  	}
  
  	return tcp_gro_receive(head, skb);
  }
684f21760   Herbert Xu   tcp6: Add GRO sup...
930

369906738   Herbert Xu   tcp: Unexport TCP...
931
  static int tcp6_gro_complete(struct sk_buff *skb)
684f21760   Herbert Xu   tcp6: Add GRO sup...
932
  {
b71d1d426   Eric Dumazet   inet: constify ip...
933
  	const struct ipv6hdr *iph = ipv6_hdr(skb);
684f21760   Herbert Xu   tcp6: Add GRO sup...
934
935
936
937
938
939
940
941
  	struct tcphdr *th = tcp_hdr(skb);
  
  	th->check = ~tcp_v6_check(skb->len - skb_transport_offset(skb),
  				  &iph->saddr, &iph->daddr, 0);
  	skb_shinfo(skb)->gso_type = SKB_GSO_TCPV6;
  
  	return tcp_gro_complete(skb);
  }
684f21760   Herbert Xu   tcp6: Add GRO sup...
942

626e264dd   Ilpo Järvinen   tcpv6: combine tc...
943
  static void tcp_v6_send_response(struct sk_buff *skb, u32 seq, u32 ack, u32 win,
b903d324b   Eric Dumazet   ipv6: tcp: fix TC...
944
  				 u32 ts, struct tcp_md5sig_key *key, int rst, u8 tclass)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
945
  {
cf533ea53   Eric Dumazet   tcp: add const qu...
946
947
  	const struct tcphdr *th = tcp_hdr(skb);
  	struct tcphdr *t1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
948
  	struct sk_buff *buff;
4c9483b2f   David S. Miller   ipv6: Convert to ...
949
  	struct flowi6 fl6;
adf30907d   Eric Dumazet   net: skb->dst acc...
950
  	struct net *net = dev_net(skb_dst(skb)->dev);
e50479927   Daniel Lezcano   [NETNS][IPV6] tcp...
951
  	struct sock *ctl_sk = net->ipv6.tcp_sk;
77c676da1   Ilpo Järvinen   tcpv6: trivial fo...
952
  	unsigned int tot_len = sizeof(struct tcphdr);
adf30907d   Eric Dumazet   net: skb->dst acc...
953
  	struct dst_entry *dst;
81ada62d7   Ilpo Järvinen   tcpv6: convert op...
954
  	__be32 *topt;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
955

626e264dd   Ilpo Järvinen   tcpv6: combine tc...
956
957
  	if (ts)
  		tot_len += TCPOLEN_TSTAMP_ALIGNED;
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
958
  #ifdef CONFIG_TCP_MD5SIG
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
959
960
961
  	if (key)
  		tot_len += TCPOLEN_MD5SIG_ALIGNED;
  #endif
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
962
  	buff = alloc_skb(MAX_HEADER + sizeof(struct ipv6hdr) + tot_len,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
963
  			 GFP_ATOMIC);
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
964
965
  	if (buff == NULL)
  		return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
966

cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
967
  	skb_reserve(buff, MAX_HEADER + sizeof(struct ipv6hdr) + tot_len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
968

cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
969
  	t1 = (struct tcphdr *) skb_push(buff, tot_len);
6651ffc8e   Herbert Xu   ipv6: Fix tcp_v6_...
970
  	skb_reset_transport_header(buff);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
971
972
973
974
975
  
  	/* Swap the send and the receive. */
  	memset(t1, 0, sizeof(*t1));
  	t1->dest = th->source;
  	t1->source = th->dest;
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
976
  	t1->doff = tot_len / 4;
626e264dd   Ilpo Järvinen   tcpv6: combine tc...
977
978
979
980
981
  	t1->seq = htonl(seq);
  	t1->ack_seq = htonl(ack);
  	t1->ack = !rst || !th->ack;
  	t1->rst = rst;
  	t1->window = htons(win);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
982

81ada62d7   Ilpo Järvinen   tcpv6: convert op...
983
  	topt = (__be32 *)(t1 + 1);
626e264dd   Ilpo Järvinen   tcpv6: combine tc...
984
985
986
987
988
989
  	if (ts) {
  		*topt++ = htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) |
  				(TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP);
  		*topt++ = htonl(tcp_time_stamp);
  		*topt++ = htonl(ts);
  	}
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
990
991
  #ifdef CONFIG_TCP_MD5SIG
  	if (key) {
81ada62d7   Ilpo Järvinen   tcpv6: convert op...
992
993
994
  		*topt++ = htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) |
  				(TCPOPT_MD5SIG << 8) | TCPOLEN_MD5SIG);
  		tcp_v6_md5_hash_hdr((__u8 *)topt, key,
78e645cb8   Ilpo Järvinen   tcpv[46]: fix md5...
995
996
  				    &ipv6_hdr(skb)->saddr,
  				    &ipv6_hdr(skb)->daddr, t1);
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
997
998
  	}
  #endif
4c9483b2f   David S. Miller   ipv6: Convert to ...
999
  	memset(&fl6, 0, sizeof(fl6));
4e3fd7a06   Alexey Dobriyan   net: remove ipv6_...
1000
1001
  	fl6.daddr = ipv6_hdr(skb)->saddr;
  	fl6.saddr = ipv6_hdr(skb)->daddr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1002

e5700aff1   David S. Miller   tcp: Mark v6 resp...
1003
1004
  	buff->ip_summed = CHECKSUM_PARTIAL;
  	buff->csum = 0;
4c9483b2f   David S. Miller   ipv6: Convert to ...
1005
  	__tcp_v6_send_check(buff, &fl6.saddr, &fl6.daddr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1006

4c9483b2f   David S. Miller   ipv6: Convert to ...
1007
1008
  	fl6.flowi6_proto = IPPROTO_TCP;
  	fl6.flowi6_oif = inet6_iif(skb);
1958b856c   David S. Miller   net: Put fl6_* ma...
1009
1010
  	fl6.fl6_dport = t1->dest;
  	fl6.fl6_sport = t1->source;
4c9483b2f   David S. Miller   ipv6: Convert to ...
1011
  	security_skb_classify_flow(skb, flowi6_to_flowi(&fl6));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1012

c20121ae8   Daniel Lezcano   [NETNS][IPV6] rou...
1013
1014
1015
1016
  	/* Pass a socket to ip6_dst_lookup either it is for RST
  	 * Underlying function will use this to retrieve the network
  	 * namespace
  	 */
4c9483b2f   David S. Miller   ipv6: Convert to ...
1017
  	dst = ip6_dst_lookup_flow(ctl_sk, &fl6, NULL, false);
68d0c6d34   David S. Miller   ipv6: Consolidate...
1018
1019
  	if (!IS_ERR(dst)) {
  		skb_dst_set(buff, dst);
b903d324b   Eric Dumazet   ipv6: tcp: fix TC...
1020
  		ip6_xmit(ctl_sk, buff, &fl6, NULL, tclass);
68d0c6d34   David S. Miller   ipv6: Consolidate...
1021
1022
1023
1024
  		TCP_INC_STATS_BH(net, TCP_MIB_OUTSEGS);
  		if (rst)
  			TCP_INC_STATS_BH(net, TCP_MIB_OUTRSTS);
  		return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1025
1026
1027
1028
  	}
  
  	kfree_skb(buff);
  }
626e264dd   Ilpo Järvinen   tcpv6: combine tc...
1029
  static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1030
  {
cf533ea53   Eric Dumazet   tcp: add const qu...
1031
  	const struct tcphdr *th = tcp_hdr(skb);
626e264dd   Ilpo Järvinen   tcpv6: combine tc...
1032
  	u32 seq = 0, ack_seq = 0;
fa3e5b4eb   Guo-Fu Tseng   tcpv6: fix error ...
1033
  	struct tcp_md5sig_key *key = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1034

626e264dd   Ilpo Järvinen   tcpv6: combine tc...
1035
  	if (th->rst)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1036
  		return;
626e264dd   Ilpo Järvinen   tcpv6: combine tc...
1037
1038
  	if (!ipv6_unicast_destination(skb))
  		return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1039

cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1040
  #ifdef CONFIG_TCP_MD5SIG
626e264dd   Ilpo Järvinen   tcpv6: combine tc...
1041
1042
  	if (sk)
  		key = tcp_v6_md5_do_lookup(sk, &ipv6_hdr(skb)->daddr);
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1043
  #endif
626e264dd   Ilpo Järvinen   tcpv6: combine tc...
1044
1045
1046
1047
1048
  	if (th->ack)
  		seq = ntohl(th->ack_seq);
  	else
  		ack_seq = ntohl(th->seq) + th->syn + th->fin + skb->len -
  			  (th->doff << 2);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1049

b903d324b   Eric Dumazet   ipv6: tcp: fix TC...
1050
  	tcp_v6_send_response(skb, seq, ack_seq, 0, 0, key, 1, 0);
626e264dd   Ilpo Järvinen   tcpv6: combine tc...
1051
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1052

626e264dd   Ilpo Järvinen   tcpv6: combine tc...
1053
  static void tcp_v6_send_ack(struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32 ts,
b903d324b   Eric Dumazet   ipv6: tcp: fix TC...
1054
  			    struct tcp_md5sig_key *key, u8 tclass)
626e264dd   Ilpo Järvinen   tcpv6: combine tc...
1055
  {
b903d324b   Eric Dumazet   ipv6: tcp: fix TC...
1056
  	tcp_v6_send_response(skb, seq, ack, win, ts, key, 0, tclass);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1057
1058
1059
1060
  }
  
  static void tcp_v6_timewait_ack(struct sock *sk, struct sk_buff *skb)
  {
8feaf0c0a   Arnaldo Carvalho de Melo   [INET]: Generalis...
1061
  	struct inet_timewait_sock *tw = inet_twsk(sk);
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1062
  	struct tcp_timewait_sock *tcptw = tcp_twsk(sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1063

9501f9722   YOSHIFUJI Hideaki   tcp md5sig: Let t...
1064
  	tcp_v6_send_ack(skb, tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt,
8feaf0c0a   Arnaldo Carvalho de Melo   [INET]: Generalis...
1065
  			tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale,
b903d324b   Eric Dumazet   ipv6: tcp: fix TC...
1066
1067
  			tcptw->tw_ts_recent, tcp_twsk_md5_key(tcptw),
  			tw->tw_tclass);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1068

8feaf0c0a   Arnaldo Carvalho de Melo   [INET]: Generalis...
1069
  	inet_twsk_put(tw);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1070
  }
6edafaaf6   Gui Jianfeng   tcp: Fix kernel p...
1071
1072
  static void tcp_v6_reqsk_send_ack(struct sock *sk, struct sk_buff *skb,
  				  struct request_sock *req)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1073
  {
9501f9722   YOSHIFUJI Hideaki   tcp md5sig: Let t...
1074
  	tcp_v6_send_ack(skb, tcp_rsk(req)->snt_isn + 1, tcp_rsk(req)->rcv_isn + 1, req->rcv_wnd, req->ts_recent,
b903d324b   Eric Dumazet   ipv6: tcp: fix TC...
1075
  			tcp_v6_md5_do_lookup(sk, &ipv6_hdr(skb)->daddr), 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1076
1077
1078
1079
1080
  }
  
  
  static struct sock *tcp_v6_hnd_req(struct sock *sk,struct sk_buff *skb)
  {
60236fdd0   Arnaldo Carvalho de Melo   [NET] Rename open...
1081
  	struct request_sock *req, **prev;
aa8223c7b   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
1082
  	const struct tcphdr *th = tcp_hdr(skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1083
1084
1085
  	struct sock *nsk;
  
  	/* Find possible connection requests. */
8129765ac   Arnaldo Carvalho de Melo   [IPV6]: Generalis...
1086
  	req = inet6_csk_search_req(sk, &prev, th->source,
0660e03f6   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
1087
1088
  				   &ipv6_hdr(skb)->saddr,
  				   &ipv6_hdr(skb)->daddr, inet6_iif(skb));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1089
1090
  	if (req)
  		return tcp_check_req(sk, skb, req, prev);
3b1e0a655   YOSHIFUJI Hideaki   [NET] NETNS: Omit...
1091
  	nsk = __inet6_lookup_established(sock_net(sk), &tcp_hashinfo,
d86e0dac2   Pavel Emelyanov   [NETNS]: Tcp-v6 s...
1092
1093
  			&ipv6_hdr(skb)->saddr, th->source,
  			&ipv6_hdr(skb)->daddr, ntohs(th->dest), inet6_iif(skb));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1094
1095
1096
1097
1098
1099
  
  	if (nsk) {
  		if (nsk->sk_state != TCP_TIME_WAIT) {
  			bh_lock_sock(nsk);
  			return nsk;
  		}
9469c7b4a   YOSHIFUJI Hideaki   [NET]: Use typesa...
1100
  		inet_twsk_put(inet_twsk(nsk));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1101
1102
  		return NULL;
  	}
c6aefafb7   Glenn Griffin   [TCP]: Add IPv6 s...
1103
  #ifdef CONFIG_SYN_COOKIES
af9b47385   Florian Westphal   syncookies: avoid...
1104
  	if (!th->syn)
c6aefafb7   Glenn Griffin   [TCP]: Add IPv6 s...
1105
  		sk = cookie_v6_check(sk, skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1106
1107
1108
  #endif
  	return sk;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1109
1110
1111
1112
1113
  /* FIXME: this is substantially similar to the ipv4 code.
   * Can some kind of merge be done? -- erics
   */
  static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
  {
4957faade   William Allen Simpson   TCPCT part 1g: Re...
1114
  	struct tcp_extend_values tmp_ext;
e6b4d1136   William Allen Simpson   TCPCT part 1a: ad...
1115
  	struct tcp_options_received tmp_opt;
cf533ea53   Eric Dumazet   tcp: add const qu...
1116
  	const u8 *hash_location;
e6b4d1136   William Allen Simpson   TCPCT part 1a: ad...
1117
  	struct request_sock *req;
ca304b610   Arnaldo Carvalho de Melo   [IPV6]: Introduce...
1118
  	struct inet6_request_sock *treq;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1119
  	struct ipv6_pinfo *np = inet6_sk(sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1120
  	struct tcp_sock *tp = tcp_sk(sk);
e6b4d1136   William Allen Simpson   TCPCT part 1a: ad...
1121
  	__u32 isn = TCP_SKB_CB(skb)->when;
493f377d6   David S. Miller   tcp: Add timewait...
1122
  	struct dst_entry *dst = NULL;
c6aefafb7   Glenn Griffin   [TCP]: Add IPv6 s...
1123
  	int want_cookie = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1124
1125
1126
1127
1128
  
  	if (skb->protocol == htons(ETH_P_IP))
  		return tcp_v4_conn_request(sk, skb);
  
  	if (!ipv6_unicast_destination(skb))
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
1129
  		goto drop;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1130

463c84b97   Arnaldo Carvalho de Melo   [NET]: Introduce ...
1131
  	if (inet_csk_reqsk_queue_is_full(sk) && !isn) {
946cedccb   Eric Dumazet   tcp: Change possi...
1132
1133
1134
  		want_cookie = tcp_syn_flood_action(sk, skb, "TCPv6");
  		if (!want_cookie)
  			goto drop;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1135
  	}
463c84b97   Arnaldo Carvalho de Melo   [NET]: Introduce ...
1136
  	if (sk_acceptq_is_full(sk) && inet_csk_reqsk_queue_young(sk) > 1)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1137
  		goto drop;
ca304b610   Arnaldo Carvalho de Melo   [IPV6]: Introduce...
1138
  	req = inet6_reqsk_alloc(&tcp6_request_sock_ops);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1139
1140
  	if (req == NULL)
  		goto drop;
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1141
1142
1143
  #ifdef CONFIG_TCP_MD5SIG
  	tcp_rsk(req)->af_specific = &tcp_request_sock_ipv6_ops;
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1144
1145
1146
  	tcp_clear_options(&tmp_opt);
  	tmp_opt.mss_clamp = IPV6_MIN_MTU - sizeof(struct tcphdr) - sizeof(struct ipv6hdr);
  	tmp_opt.user_mss = tp->rx_opt.user_mss;
bb5b7c112   David S. Miller   tcp: Revert per-r...
1147
  	tcp_parse_options(skb, &tmp_opt, &hash_location, 0);
4957faade   William Allen Simpson   TCPCT part 1g: Re...
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
  
  	if (tmp_opt.cookie_plus > 0 &&
  	    tmp_opt.saw_tstamp &&
  	    !tp->rx_opt.cookie_out_never &&
  	    (sysctl_tcp_cookie_size > 0 ||
  	     (tp->cookie_values != NULL &&
  	      tp->cookie_values->cookie_desired > 0))) {
  		u8 *c;
  		u32 *d;
  		u32 *mess = &tmp_ext.cookie_bakery[COOKIE_DIGEST_WORDS];
  		int l = tmp_opt.cookie_plus - TCPOLEN_COOKIE_BASE;
  
  		if (tcp_cookie_generator(&tmp_ext.cookie_bakery[0]) != 0)
  			goto drop_and_free;
  
  		/* Secret recipe starts with IP addresses */
0eae88f31   Eric Dumazet   net: Fix various ...
1164
  		d = (__force u32 *)&ipv6_hdr(skb)->daddr.s6_addr32[0];
4957faade   William Allen Simpson   TCPCT part 1g: Re...
1165
1166
1167
1168
  		*mess++ ^= *d++;
  		*mess++ ^= *d++;
  		*mess++ ^= *d++;
  		*mess++ ^= *d++;
0eae88f31   Eric Dumazet   net: Fix various ...
1169
  		d = (__force u32 *)&ipv6_hdr(skb)->saddr.s6_addr32[0];
4957faade   William Allen Simpson   TCPCT part 1g: Re...
1170
1171
1172
1173
1174
1175
1176
1177
1178
  		*mess++ ^= *d++;
  		*mess++ ^= *d++;
  		*mess++ ^= *d++;
  		*mess++ ^= *d++;
  
  		/* plus variable length Initiator Cookie */
  		c = (u8 *)mess;
  		while (l-- > 0)
  			*c++ ^= *hash_location++;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1179

4957faade   William Allen Simpson   TCPCT part 1g: Re...
1180
  		want_cookie = 0;	/* not our kind of cookie */
4957faade   William Allen Simpson   TCPCT part 1g: Re...
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
  		tmp_ext.cookie_out_never = 0; /* false */
  		tmp_ext.cookie_plus = tmp_opt.cookie_plus;
  	} else if (!tp->rx_opt.cookie_in_always) {
  		/* redundant indications, but ensure initialization. */
  		tmp_ext.cookie_out_never = 1; /* true */
  		tmp_ext.cookie_plus = 0;
  	} else {
  		goto drop_and_free;
  	}
  	tmp_ext.cookie_in_always = tp->rx_opt.cookie_in_always;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1191

4dfc28170   Florian Westphal   [Syncookies]: Add...
1192
  	if (want_cookie && !tmp_opt.saw_tstamp)
c6aefafb7   Glenn Griffin   [TCP]: Add IPv6 s...
1193
  		tcp_clear_options(&tmp_opt);
c6aefafb7   Glenn Griffin   [TCP]: Add IPv6 s...
1194

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1195
1196
  	tmp_opt.tstamp_ok = tmp_opt.saw_tstamp;
  	tcp_openreq_init(req, &tmp_opt, skb);
ca304b610   Arnaldo Carvalho de Melo   [IPV6]: Introduce...
1197
  	treq = inet6_rsk(req);
4e3fd7a06   Alexey Dobriyan   net: remove ipv6_...
1198
1199
  	treq->rmt_addr = ipv6_hdr(skb)->saddr;
  	treq->loc_addr = ipv6_hdr(skb)->daddr;
172d69e63   Florian Westphal   syncookies: add s...
1200
  	if (!want_cookie || tmp_opt.tstamp_ok)
c6aefafb7   Glenn Griffin   [TCP]: Add IPv6 s...
1201
  		TCP_ECN_create_request(req, tcp_hdr(skb));
4d0fe50c7   Eric Dumazet   ipv6: tcp: fix tc...
1202
1203
1204
1205
1206
1207
  	treq->iif = sk->sk_bound_dev_if;
  
  	/* So that link locals have meaning */
  	if (!sk->sk_bound_dev_if &&
  	    ipv6_addr_type(&treq->rmt_addr) & IPV6_ADDR_LINKLOCAL)
  		treq->iif = inet6_iif(skb);
2bbdf389a   Florian Westphal   ipv6: syncookies:...
1208
  	if (!isn) {
493f377d6   David S. Miller   tcp: Add timewait...
1209
  		struct inet_peer *peer = NULL;
c6aefafb7   Glenn Griffin   [TCP]: Add IPv6 s...
1210
1211
1212
1213
1214
1215
  		if (ipv6_opt_accepted(sk, skb) ||
  		    np->rxopt.bits.rxinfo || np->rxopt.bits.rxoinfo ||
  		    np->rxopt.bits.rxhlim || np->rxopt.bits.rxohlim) {
  			atomic_inc(&skb->users);
  			treq->pktopts = skb;
  		}
493f377d6   David S. Miller   tcp: Add timewait...
1216
1217
  
  		if (want_cookie) {
2bbdf389a   Florian Westphal   ipv6: syncookies:...
1218
1219
  			isn = cookie_v6_init_sequence(sk, skb, &req->mss);
  			req->cookie_ts = tmp_opt.tstamp_ok;
493f377d6   David S. Miller   tcp: Add timewait...
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
  			goto have_isn;
  		}
  
  		/* VJ's idea. We save last timestamp seen
  		 * from the destination in peer table, when entering
  		 * state TIME-WAIT, and check against it before
  		 * accepting new connection request.
  		 *
  		 * If "isn" is not zero, this request hit alive
  		 * timewait bucket, so that all the necessary checks
  		 * are made in the function processing timewait state.
  		 */
  		if (tmp_opt.saw_tstamp &&
  		    tcp_death_row.sysctl_tw_recycle &&
  		    (dst = inet6_csk_route_req(sk, req)) != NULL &&
  		    (peer = rt6_get_peer((struct rt6_info *)dst)) != NULL &&
7a71ed899   David S. Miller   inetpeer: Abstrac...
1236
  		    ipv6_addr_equal((struct in6_addr *)peer->daddr.addr.a6,
493f377d6   David S. Miller   tcp: Add timewait...
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
  				    &treq->rmt_addr)) {
  			inet_peer_refcheck(peer);
  			if ((u32)get_seconds() - peer->tcp_ts_stamp < TCP_PAWS_MSL &&
  			    (s32)(peer->tcp_ts - req->ts_recent) >
  							TCP_PAWS_WINDOW) {
  				NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_PAWSPASSIVEREJECTED);
  				goto drop_and_release;
  			}
  		}
  		/* Kill the following clause, if you dislike this way. */
  		else if (!sysctl_tcp_syncookies &&
  			 (sysctl_max_syn_backlog - inet_csk_reqsk_queue_len(sk) <
  			  (sysctl_max_syn_backlog >> 2)) &&
  			 (!peer || !peer->tcp_ts_stamp) &&
  			 (!dst || !dst_metric(dst, RTAX_RTT))) {
  			/* Without syncookies last quarter of
  			 * backlog is filled with destinations,
  			 * proven to be alive.
  			 * It means that we continue to communicate
  			 * to destinations, already remembered
  			 * to the moment of synflood.
  			 */
  			LIMIT_NETDEBUG(KERN_DEBUG "TCP: drop open request from %pI6/%u
  ",
  				       &treq->rmt_addr, ntohs(tcp_hdr(skb)->source));
  			goto drop_and_release;
2bbdf389a   Florian Westphal   ipv6: syncookies:...
1263
  		}
493f377d6   David S. Miller   tcp: Add timewait...
1264
1265
  
  		isn = tcp_v6_init_sequence(skb);
c6aefafb7   Glenn Griffin   [TCP]: Add IPv6 s...
1266
  	}
493f377d6   David S. Miller   tcp: Add timewait...
1267
  have_isn:
2e6599cb8   Arnaldo Carvalho de Melo   [NET] Generalise ...
1268
  	tcp_rsk(req)->snt_isn = isn;
9ad7c049f   Jerry Chu   tcp: RFC2988bis +...
1269
  	tcp_rsk(req)->snt_synack = tcp_time_stamp;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1270

4237c75c0   Venkat Yekkirala   [MLSXFRM]: Auto-l...
1271
  	security_inet_conn_request(sk, skb, req);
4957faade   William Allen Simpson   TCPCT part 1g: Re...
1272
1273
1274
  	if (tcp_v6_send_synack(sk, req,
  			       (struct request_values *)&tmp_ext) ||
  	    want_cookie)
e6b4d1136   William Allen Simpson   TCPCT part 1a: ad...
1275
  		goto drop_and_free;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1276

e6b4d1136   William Allen Simpson   TCPCT part 1a: ad...
1277
1278
  	inet6_csk_reqsk_queue_hash_add(sk, req, TCP_TIMEOUT_INIT);
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1279

493f377d6   David S. Miller   tcp: Add timewait...
1280
1281
  drop_and_release:
  	dst_release(dst);
e6b4d1136   William Allen Simpson   TCPCT part 1a: ad...
1282
1283
  drop_and_free:
  	reqsk_free(req);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1284
  drop:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1285
1286
1287
1288
  	return 0; /* don't send reset */
  }
  
  static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
60236fdd0   Arnaldo Carvalho de Melo   [NET] Rename open...
1289
  					  struct request_sock *req,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1290
1291
  					  struct dst_entry *dst)
  {
78d15e827   Vegard Nossum   tcp_ipv6: fix use...
1292
  	struct inet6_request_sock *treq;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1293
1294
1295
1296
1297
1298
  	struct ipv6_pinfo *newnp, *np = inet6_sk(sk);
  	struct tcp6_sock *newtcp6sk;
  	struct inet_sock *newinet;
  	struct tcp_sock *newtp;
  	struct sock *newsk;
  	struct ipv6_txoptions *opt;
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1299
1300
1301
  #ifdef CONFIG_TCP_MD5SIG
  	struct tcp_md5sig_key *key;
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1302
1303
1304
1305
1306
1307
1308
  
  	if (skb->protocol == htons(ETH_P_IP)) {
  		/*
  		 *	v6 mapped
  		 */
  
  		newsk = tcp_v4_syn_recv_sock(sk, skb, req, dst);
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
1309
  		if (newsk == NULL)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
  			return NULL;
  
  		newtcp6sk = (struct tcp6_sock *)newsk;
  		inet_sk(newsk)->pinet6 = &newtcp6sk->inet6;
  
  		newinet = inet_sk(newsk);
  		newnp = inet6_sk(newsk);
  		newtp = tcp_sk(newsk);
  
  		memcpy(newnp, np, sizeof(struct ipv6_pinfo));
c720c7e83   Eric Dumazet   inet: rename some...
1320
  		ipv6_addr_set_v4mapped(newinet->inet_daddr, &newnp->daddr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1321

c720c7e83   Eric Dumazet   inet: rename some...
1322
  		ipv6_addr_set_v4mapped(newinet->inet_saddr, &newnp->saddr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1323

4e3fd7a06   Alexey Dobriyan   net: remove ipv6_...
1324
  		newnp->rcv_saddr = newnp->saddr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1325

8292a17a3   Arnaldo Carvalho de Melo   [ICSK]: Rename st...
1326
  		inet_csk(newsk)->icsk_af_ops = &ipv6_mapped;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1327
  		newsk->sk_backlog_rcv = tcp_v4_do_rcv;
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1328
1329
1330
  #ifdef CONFIG_TCP_MD5SIG
  		newtp->af_specific = &tcp_sock_ipv6_mapped_specific;
  #endif
676a1184e   Yan, Zheng   ipv6: nullify ipv...
1331
1332
  		newnp->ipv6_ac_list = NULL;
  		newnp->ipv6_fl_list = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1333
1334
  		newnp->pktoptions  = NULL;
  		newnp->opt	   = NULL;
505cbfc57   Arnaldo Carvalho de Melo   [IPV6]: Generalis...
1335
  		newnp->mcast_oif   = inet6_iif(skb);
0660e03f6   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
1336
  		newnp->mcast_hops  = ipv6_hdr(skb)->hop_limit;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1337

e6848976b   Arnaldo Carvalho de Melo   [NET]: Cleanup IN...
1338
1339
1340
1341
  		/*
  		 * No need to charge this sock to the relevant IPv6 refcnt debug socks count
  		 * here, tcp_create_openreq_child now does this for us, see the comment in
  		 * that function for the gory details. -acme
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1342
  		 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1343
1344
  
  		/* It is tricky place. Until this moment IPv4 tcp
8292a17a3   Arnaldo Carvalho de Melo   [ICSK]: Rename st...
1345
  		   worked with IPv6 icsk.icsk_af_ops.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1346
1347
  		   Sync it now.
  		 */
d83d8461f   Arnaldo Carvalho de Melo   [IP_SOCKGLUE]: Re...
1348
  		tcp_sync_mss(newsk, inet_csk(newsk)->icsk_pmtu_cookie);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1349
1350
1351
  
  		return newsk;
  	}
78d15e827   Vegard Nossum   tcp_ipv6: fix use...
1352
  	treq = inet6_rsk(req);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1353
1354
1355
1356
  	opt = np->opt;
  
  	if (sk_acceptq_is_full(sk))
  		goto out_overflow;
493f377d6   David S. Miller   tcp: Add timewait...
1357
1358
1359
  	if (!dst) {
  		dst = inet6_csk_route_req(sk, req);
  		if (!dst)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1360
  			goto out;
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
1361
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1362
1363
1364
  
  	newsk = tcp_create_openreq_child(sk, req, skb);
  	if (newsk == NULL)
093d28232   Balazs Scheidler   tproxy: fix hash ...
1365
  		goto out_nonewsk;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1366

e6848976b   Arnaldo Carvalho de Melo   [NET]: Cleanup IN...
1367
1368
1369
1370
1371
  	/*
  	 * No need to charge this sock to the relevant IPv6 refcnt debug socks
  	 * count here, tcp_create_openreq_child now does this for us, see the
  	 * comment in that function for the gory details. -acme
  	 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1372

59eed279c   Stephen Hemminger   [IPV6]: Segmentat...
1373
  	newsk->sk_gso_type = SKB_GSO_TCPV6;
8e1ef0a95   YOSHIFUJI Hideaki   [IPV6]: Cache sou...
1374
  	__ip6_dst_store(newsk, dst, NULL, NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1375
1376
1377
1378
1379
1380
1381
1382
1383
  
  	newtcp6sk = (struct tcp6_sock *)newsk;
  	inet_sk(newsk)->pinet6 = &newtcp6sk->inet6;
  
  	newtp = tcp_sk(newsk);
  	newinet = inet_sk(newsk);
  	newnp = inet6_sk(newsk);
  
  	memcpy(newnp, np, sizeof(struct ipv6_pinfo));
4e3fd7a06   Alexey Dobriyan   net: remove ipv6_...
1384
1385
1386
  	newnp->daddr = treq->rmt_addr;
  	newnp->saddr = treq->loc_addr;
  	newnp->rcv_saddr = treq->loc_addr;
2e6599cb8   Arnaldo Carvalho de Melo   [NET] Generalise ...
1387
  	newsk->sk_bound_dev_if = treq->iif;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1388

1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
1389
  	/* Now IPv6 options...
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1390
1391
1392
  
  	   First: no IPv4 options.
  	 */
f6d8bd051   Eric Dumazet   inet: add RCU pro...
1393
  	newinet->inet_opt = NULL;
676a1184e   Yan, Zheng   ipv6: nullify ipv...
1394
  	newnp->ipv6_ac_list = NULL;
d35690bed   Masayuki Nakagawa   [IPV6]: ipv6_fl_s...
1395
  	newnp->ipv6_fl_list = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1396
1397
1398
1399
1400
1401
  
  	/* Clone RX bits */
  	newnp->rxopt.all = np->rxopt.all;
  
  	/* Clone pktoptions received with SYN */
  	newnp->pktoptions = NULL;
2e6599cb8   Arnaldo Carvalho de Melo   [NET] Generalise ...
1402
1403
1404
1405
  	if (treq->pktopts != NULL) {
  		newnp->pktoptions = skb_clone(treq->pktopts, GFP_ATOMIC);
  		kfree_skb(treq->pktopts);
  		treq->pktopts = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1406
1407
1408
1409
  		if (newnp->pktoptions)
  			skb_set_owner_r(newnp->pktoptions, newsk);
  	}
  	newnp->opt	  = NULL;
505cbfc57   Arnaldo Carvalho de Melo   [IPV6]: Generalis...
1410
  	newnp->mcast_oif  = inet6_iif(skb);
0660e03f6   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
1411
  	newnp->mcast_hops = ipv6_hdr(skb)->hop_limit;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
  
  	/* Clone native IPv6 options from listening socket (if any)
  
  	   Yes, keeping reference count would be much more clever,
  	   but we make one more one thing there: reattach optmem
  	   to newsk.
  	 */
  	if (opt) {
  		newnp->opt = ipv6_dup_options(newsk, opt);
  		if (opt != np->opt)
  			sock_kfree_s(sk, opt, opt->tot_len);
  	}
d83d8461f   Arnaldo Carvalho de Melo   [IP_SOCKGLUE]: Re...
1424
  	inet_csk(newsk)->icsk_ext_hdr_len = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1425
  	if (newnp->opt)
d83d8461f   Arnaldo Carvalho de Melo   [IP_SOCKGLUE]: Re...
1426
1427
  		inet_csk(newsk)->icsk_ext_hdr_len = (newnp->opt->opt_nflen +
  						     newnp->opt->opt_flen);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1428

5d424d5a6   John Heffner   [TCP]: MTU probing
1429
  	tcp_mtup_init(newsk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1430
  	tcp_sync_mss(newsk, dst_mtu(dst));
0dbaee3b3   David S. Miller   net: Abstract def...
1431
  	newtp->advmss = dst_metric_advmss(dst);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1432
  	tcp_initialize_rcv_mss(newsk);
9ad7c049f   Jerry Chu   tcp: RFC2988bis +...
1433
1434
1435
1436
  	if (tcp_rsk(req)->snt_synack)
  		tcp_valid_rtt_meas(newsk,
  		    tcp_time_stamp - tcp_rsk(req)->snt_synack);
  	newtp->total_retrans = req->retrans;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1437

c720c7e83   Eric Dumazet   inet: rename some...
1438
1439
  	newinet->inet_daddr = newinet->inet_saddr = LOOPBACK4_IPV6;
  	newinet->inet_rcv_saddr = LOOPBACK4_IPV6;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1440

cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1441
1442
1443
1444
1445
1446
1447
1448
  #ifdef CONFIG_TCP_MD5SIG
  	/* Copy over the MD5 key from the original socket */
  	if ((key = tcp_v6_md5_do_lookup(sk, &newnp->daddr)) != NULL) {
  		/* We're using one, so create a matching key
  		 * on the newsk structure. If we fail to get
  		 * memory, then we end up not copying the key
  		 * across. Shucks.
  		 */
af879cc70   Arnaldo Carvalho de Melo   [IPV6]: Use kmemdup
1449
1450
  		char *newkey = kmemdup(key->key, key->keylen, GFP_ATOMIC);
  		if (newkey != NULL)
e547bc1ec   John Dykstra   tcp: Use correct ...
1451
  			tcp_v6_md5_do_add(newsk, &newnp->daddr,
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1452
  					  newkey, key->keylen);
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1453
1454
  	}
  #endif
093d28232   Balazs Scheidler   tproxy: fix hash ...
1455
1456
1457
1458
  	if (__inet_inherit_port(sk, newsk) < 0) {
  		sock_put(newsk);
  		goto out;
  	}
9327f7053   Eric Dumazet   tcp: Fix a connec...
1459
  	__inet6_hash(newsk, NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1460
1461
1462
1463
  
  	return newsk;
  
  out_overflow:
de0744af1   Pavel Emelyanov   mib: add net to N...
1464
  	NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENOVERFLOWS);
093d28232   Balazs Scheidler   tproxy: fix hash ...
1465
  out_nonewsk:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1466
1467
1468
  	if (opt && opt != np->opt)
  		sock_kfree_s(sk, opt, opt->tot_len);
  	dst_release(dst);
093d28232   Balazs Scheidler   tproxy: fix hash ...
1469
1470
  out:
  	NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1471
1472
  	return NULL;
  }
b51655b95   Al Viro   [NET]: Annotate _...
1473
  static __sum16 tcp_v6_checksum_init(struct sk_buff *skb)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1474
  {
84fa7933a   Patrick McHardy   [NET]: Replace CH...
1475
  	if (skb->ip_summed == CHECKSUM_COMPLETE) {
684f21760   Herbert Xu   tcp6: Add GRO sup...
1476
  		if (!tcp_v6_check(skb->len, &ipv6_hdr(skb)->saddr,
0660e03f6   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
1477
  				  &ipv6_hdr(skb)->daddr, skb->csum)) {
fb286bb29   Herbert Xu   [NET]: Detect har...
1478
  			skb->ip_summed = CHECKSUM_UNNECESSARY;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1479
  			return 0;
fb286bb29   Herbert Xu   [NET]: Detect har...
1480
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1481
  	}
fb286bb29   Herbert Xu   [NET]: Detect har...
1482

684f21760   Herbert Xu   tcp6: Add GRO sup...
1483
  	skb->csum = ~csum_unfold(tcp_v6_check(skb->len,
0660e03f6   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
1484
1485
  					      &ipv6_hdr(skb)->saddr,
  					      &ipv6_hdr(skb)->daddr, 0));
fb286bb29   Herbert Xu   [NET]: Detect har...
1486

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1487
  	if (skb->len <= 76) {
fb286bb29   Herbert Xu   [NET]: Detect har...
1488
  		return __skb_checksum_complete(skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
  	}
  	return 0;
  }
  
  /* The socket must have it's spinlock held when we get
   * here.
   *
   * We have a potential double-lock case here, so even when
   * doing backlog processing we use the BH locking scheme.
   * This is because we cannot sleep with the original spinlock
   * held.
   */
  static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb)
  {
  	struct ipv6_pinfo *np = inet6_sk(sk);
  	struct tcp_sock *tp;
  	struct sk_buff *opt_skb = NULL;
  
  	/* Imagine: socket is IPv6. IPv4 packet arrives,
  	   goes to IPv4 receive handler and backlogged.
  	   From backlog it always goes here. Kerboom...
  	   Fortunately, tcp_rcv_established and rcv_established
  	   handle them correctly, but it is not case with
  	   tcp_v6_hnd_req and tcp_v6_send_reset().   --ANK
  	 */
  
  	if (skb->protocol == htons(ETH_P_IP))
  		return tcp_v4_do_rcv(sk, skb);
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1517
1518
1519
1520
  #ifdef CONFIG_TCP_MD5SIG
  	if (tcp_v6_inbound_md5_hash (sk, skb))
  		goto discard;
  #endif
fda9ef5d6   Dmitry Mishin   [NET]: Fix sk->sk...
1521
  	if (sk_filter(sk, skb))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
  		goto discard;
  
  	/*
  	 *	socket locking is here for SMP purposes as backlog rcv
  	 *	is currently called with bh processing disabled.
  	 */
  
  	/* Do Stevens' IPV6_PKTOPTIONS.
  
  	   Yes, guys, it is the only place in our code, where we
  	   may make it not affecting IPv4.
  	   The rest of code is protocol independent,
  	   and I do not like idea to uglify IPv4.
  
  	   Actually, all the idea behind IPV6_PKTOPTIONS
  	   looks not very well thought. For now we latch
  	   options, received in the last packet, enqueued
  	   by tcp. Feel free to propose better solution.
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
1540
  					       --ANK (980728)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1541
1542
1543
1544
1545
  	 */
  	if (np->rxopt.all)
  		opt_skb = skb_clone(skb, GFP_ATOMIC);
  
  	if (sk->sk_state == TCP_ESTABLISHED) { /* Fast path */
bdeab9919   Tom Herbert   rps: Add flag to ...
1546
  		sock_rps_save_rxhash(sk, skb);
aa8223c7b   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
1547
  		if (tcp_rcv_established(sk, skb, tcp_hdr(skb), skb->len))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1548
  			goto reset;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1549
1550
1551
1552
  		if (opt_skb)
  			goto ipv6_pktoptions;
  		return 0;
  	}
ab6a5bb6b   Arnaldo Carvalho de Melo   [TCP]: Introduce ...
1553
  	if (skb->len < tcp_hdrlen(skb) || tcp_checksum_complete(skb))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1554
  		goto csum_err;
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
1555
  	if (sk->sk_state == TCP_LISTEN) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1556
1557
1558
1559
1560
1561
1562
1563
1564
  		struct sock *nsk = tcp_v6_hnd_req(sk, skb);
  		if (!nsk)
  			goto discard;
  
  		/*
  		 * Queue it on the new socket if the new socket is active,
  		 * otherwise we just shortcircuit this and continue with
  		 * the new socket..
  		 */
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
1565
  		if(nsk != sk) {
bdeab9919   Tom Herbert   rps: Add flag to ...
1566
  			sock_rps_save_rxhash(nsk, skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1567
1568
1569
1570
1571
1572
  			if (tcp_child_process(sk, nsk, skb))
  				goto reset;
  			if (opt_skb)
  				__kfree_skb(opt_skb);
  			return 0;
  		}
47482f132   Neil Horman   ipv6: Enable RFS ...
1573
  	} else
bdeab9919   Tom Herbert   rps: Add flag to ...
1574
  		sock_rps_save_rxhash(sk, skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1575

aa8223c7b   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
1576
  	if (tcp_rcv_state_process(sk, skb, tcp_hdr(skb), skb->len))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1577
  		goto reset;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1578
1579
1580
1581
1582
  	if (opt_skb)
  		goto ipv6_pktoptions;
  	return 0;
  
  reset:
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1583
  	tcp_v6_send_reset(sk, skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1584
1585
1586
1587
1588
1589
  discard:
  	if (opt_skb)
  		__kfree_skb(opt_skb);
  	kfree_skb(skb);
  	return 0;
  csum_err:
63231bddf   Pavel Emelyanov   mib: add net to T...
1590
  	TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_INERRS);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
  	goto discard;
  
  
  ipv6_pktoptions:
  	/* Do you ask, what is it?
  
  	   1. skb was enqueued by tcp.
  	   2. skb is added to tail of read queue, rather than out of order.
  	   3. socket is not in passive state.
  	   4. Finally, it really contains options, which user wants to receive.
  	 */
  	tp = tcp_sk(sk);
  	if (TCP_SKB_CB(opt_skb)->end_seq == tp->rcv_nxt &&
  	    !((1 << sk->sk_state) & (TCPF_CLOSE | TCPF_LISTEN))) {
333fad536   YOSHIFUJI Hideaki   [IPV6]: Support s...
1605
  		if (np->rxopt.bits.rxinfo || np->rxopt.bits.rxoinfo)
505cbfc57   Arnaldo Carvalho de Melo   [IPV6]: Generalis...
1606
  			np->mcast_oif = inet6_iif(opt_skb);
333fad536   YOSHIFUJI Hideaki   [IPV6]: Support s...
1607
  		if (np->rxopt.bits.rxhlim || np->rxopt.bits.rxohlim)
0660e03f6   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
1608
  			np->mcast_hops = ipv6_hdr(opt_skb)->hop_limit;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1609
1610
1611
1612
1613
1614
1615
1616
  		if (ipv6_opt_accepted(sk, opt_skb)) {
  			skb_set_owner_r(opt_skb, sk);
  			opt_skb = xchg(&np->pktoptions, opt_skb);
  		} else {
  			__kfree_skb(opt_skb);
  			opt_skb = xchg(&np->pktoptions, NULL);
  		}
  	}
800d55f14   Wei Yongjun   ipv6: Remove some...
1617
  	kfree_skb(opt_skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1618
1619
  	return 0;
  }
e5bbef20e   Herbert Xu   [IPV6]: Replace s...
1620
  static int tcp_v6_rcv(struct sk_buff *skb)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1621
  {
cf533ea53   Eric Dumazet   tcp: add const qu...
1622
  	const struct tcphdr *th;
b71d1d426   Eric Dumazet   inet: constify ip...
1623
  	const struct ipv6hdr *hdr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1624
1625
  	struct sock *sk;
  	int ret;
a86b1e301   Pavel Emelyanov   inet: prepare str...
1626
  	struct net *net = dev_net(skb->dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1627
1628
1629
1630
1631
1632
1633
  
  	if (skb->pkt_type != PACKET_HOST)
  		goto discard_it;
  
  	/*
  	 *	Count it even if it's bad.
  	 */
63231bddf   Pavel Emelyanov   mib: add net to T...
1634
  	TCP_INC_STATS_BH(net, TCP_MIB_INSEGS);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1635
1636
1637
  
  	if (!pskb_may_pull(skb, sizeof(struct tcphdr)))
  		goto discard_it;
aa8223c7b   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
1638
  	th = tcp_hdr(skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1639
1640
1641
1642
1643
  
  	if (th->doff < sizeof(struct tcphdr)/4)
  		goto bad_packet;
  	if (!pskb_may_pull(skb, th->doff*4))
  		goto discard_it;
604763722   Herbert Xu   [NET]: Treat CHEC...
1644
  	if (!skb_csum_unnecessary(skb) && tcp_v6_checksum_init(skb))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1645
  		goto bad_packet;
aa8223c7b   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
1646
  	th = tcp_hdr(skb);
e802af9ca   Stephen Hemminger   IPv6: Generic TTL...
1647
  	hdr = ipv6_hdr(skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1648
1649
1650
1651
1652
  	TCP_SKB_CB(skb)->seq = ntohl(th->seq);
  	TCP_SKB_CB(skb)->end_seq = (TCP_SKB_CB(skb)->seq + th->syn + th->fin +
  				    skb->len - th->doff*4);
  	TCP_SKB_CB(skb)->ack_seq = ntohl(th->ack_seq);
  	TCP_SKB_CB(skb)->when = 0;
b82d1bb4f   Eric Dumazet   tcp: unalias tcp_...
1653
  	TCP_SKB_CB(skb)->ip_dsfield = ipv6_get_dsfield(hdr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1654
  	TCP_SKB_CB(skb)->sacked = 0;
9a1f27c48   Arnaldo Carvalho de Melo   inet_hashtables: ...
1655
  	sk = __inet6_lookup_skb(&tcp_hashinfo, skb, th->source, th->dest);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1656
1657
1658
1659
1660
1661
  	if (!sk)
  		goto no_tcp_socket;
  
  process:
  	if (sk->sk_state == TCP_TIME_WAIT)
  		goto do_time_wait;
e802af9ca   Stephen Hemminger   IPv6: Generic TTL...
1662
1663
1664
1665
  	if (hdr->hop_limit < inet6_sk(sk)->min_hopcount) {
  		NET_INC_STATS_BH(net, LINUX_MIB_TCPMINTTLDROP);
  		goto discard_and_relse;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1666
1667
  	if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb))
  		goto discard_and_relse;
fda9ef5d6   Dmitry Mishin   [NET]: Fix sk->sk...
1668
  	if (sk_filter(sk, skb))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1669
1670
1671
  		goto discard_and_relse;
  
  	skb->dev = NULL;
293b9c425   Fabio Olive Leite   [IPV6]: bh_lock_s...
1672
  	bh_lock_sock_nested(sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1673
1674
  	ret = 0;
  	if (!sock_owned_by_user(sk)) {
1a2449a87   Chris Leech   [I/OAT]: TCP recv...
1675
  #ifdef CONFIG_NET_DMA
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
1676
  		struct tcp_sock *tp = tcp_sk(sk);
b4caea8aa   David S. Miller   [TCP]: Add missin...
1677
  		if (!tp->ucopy.dma_chan && tp->ucopy.pinned_list)
f67b45999   Dan Williams   net_dma: convert ...
1678
  			tp->ucopy.dma_chan = dma_find_channel(DMA_MEMCPY);
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
1679
1680
1681
  		if (tp->ucopy.dma_chan)
  			ret = tcp_v6_do_rcv(sk, skb);
  		else
1a2449a87   Chris Leech   [I/OAT]: TCP recv...
1682
1683
1684
1685
1686
  #endif
  		{
  			if (!tcp_prequeue(sk, skb))
  				ret = tcp_v6_do_rcv(sk, skb);
  		}
6cce09f87   Eric Dumazet   tcp: Add SNMP cou...
1687
  	} else if (unlikely(sk_add_backlog(sk, skb))) {
6b03a53a5   Zhu Yi   tcp: use limited ...
1688
  		bh_unlock_sock(sk);
6cce09f87   Eric Dumazet   tcp: Add SNMP cou...
1689
  		NET_INC_STATS_BH(net, LINUX_MIB_TCPBACKLOGDROP);
6b03a53a5   Zhu Yi   tcp: use limited ...
1690
1691
  		goto discard_and_relse;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
  	bh_unlock_sock(sk);
  
  	sock_put(sk);
  	return ret ? -1 : 0;
  
  no_tcp_socket:
  	if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb))
  		goto discard_it;
  
  	if (skb->len < (th->doff<<2) || tcp_checksum_complete(skb)) {
  bad_packet:
63231bddf   Pavel Emelyanov   mib: add net to T...
1703
  		TCP_INC_STATS_BH(net, TCP_MIB_INERRS);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1704
  	} else {
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1705
  		tcp_v6_send_reset(NULL, skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
  	}
  
  discard_it:
  
  	/*
  	 *	Discard frame
  	 */
  
  	kfree_skb(skb);
  	return 0;
  
  discard_and_relse:
  	sock_put(sk);
  	goto discard_it;
  
  do_time_wait:
  	if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) {
9469c7b4a   YOSHIFUJI Hideaki   [NET]: Use typesa...
1723
  		inet_twsk_put(inet_twsk(sk));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1724
1725
1726
1727
  		goto discard_it;
  	}
  
  	if (skb->len < (th->doff<<2) || tcp_checksum_complete(skb)) {
63231bddf   Pavel Emelyanov   mib: add net to T...
1728
  		TCP_INC_STATS_BH(net, TCP_MIB_INERRS);
9469c7b4a   YOSHIFUJI Hideaki   [NET]: Use typesa...
1729
  		inet_twsk_put(inet_twsk(sk));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1730
1731
  		goto discard_it;
  	}
9469c7b4a   YOSHIFUJI Hideaki   [NET]: Use typesa...
1732
  	switch (tcp_timewait_state_process(inet_twsk(sk), skb, th)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1733
1734
1735
  	case TCP_TW_SYN:
  	{
  		struct sock *sk2;
c346dca10   YOSHIFUJI Hideaki   [NET] NETNS: Omit...
1736
  		sk2 = inet6_lookup_listener(dev_net(skb->dev), &tcp_hashinfo,
0660e03f6   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
1737
  					    &ipv6_hdr(skb)->daddr,
505cbfc57   Arnaldo Carvalho de Melo   [IPV6]: Generalis...
1738
  					    ntohs(th->dest), inet6_iif(skb));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1739
  		if (sk2 != NULL) {
295ff7edb   Arnaldo Carvalho de Melo   [TIMEWAIT]: Intro...
1740
1741
1742
  			struct inet_timewait_sock *tw = inet_twsk(sk);
  			inet_twsk_deschedule(tw, &tcp_death_row);
  			inet_twsk_put(tw);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
  			sk = sk2;
  			goto process;
  		}
  		/* Fall through to ACK */
  	}
  	case TCP_TW_ACK:
  		tcp_v6_timewait_ack(sk, skb);
  		break;
  	case TCP_TW_RST:
  		goto no_tcp_socket;
  	case TCP_TW_SUCCESS:;
  	}
  	goto discard_it;
  }
ccb7c410d   David S. Miller   timewait_sock: Cr...
1757
1758
  static struct inet_peer *tcp_v6_get_peer(struct sock *sk, bool *release_it)
  {
db3949c45   David S. Miller   tcp: Implement ip...
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
  	struct rt6_info *rt = (struct rt6_info *) __sk_dst_get(sk);
  	struct ipv6_pinfo *np = inet6_sk(sk);
  	struct inet_peer *peer;
  
  	if (!rt ||
  	    !ipv6_addr_equal(&np->daddr, &rt->rt6i_dst.addr)) {
  		peer = inet_getpeer_v6(&np->daddr, 1);
  		*release_it = true;
  	} else {
  		if (!rt->rt6i_peer)
  			rt6_bind_peer(rt, 1);
  		peer = rt->rt6i_peer;
457de4383   David S. Miller   ipv6: Fix 'releas...
1771
  		*release_it = false;
db3949c45   David S. Miller   tcp: Implement ip...
1772
1773
1774
  	}
  
  	return peer;
ccb7c410d   David S. Miller   timewait_sock: Cr...
1775
1776
1777
  }
  
  static void *tcp_v6_tw_get_peer(struct sock *sk)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1778
  {
cf533ea53   Eric Dumazet   tcp: add const qu...
1779
1780
  	const struct inet6_timewait_sock *tw6 = inet6_twsk(sk);
  	const struct inet_timewait_sock *tw = inet_twsk(sk);
ccb7c410d   David S. Miller   timewait_sock: Cr...
1781
1782
1783
  
  	if (tw->tw_family == AF_INET)
  		return tcp_v4_tw_get_peer(sk);
db3949c45   David S. Miller   tcp: Implement ip...
1784
  	return inet_getpeer_v6(&tw6->tw_v6_daddr, 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1785
  }
ccb7c410d   David S. Miller   timewait_sock: Cr...
1786
1787
1788
1789
1790
1791
  static struct timewait_sock_ops tcp6_timewait_sock_ops = {
  	.twsk_obj_size	= sizeof(struct tcp6_timewait_sock),
  	.twsk_unique	= tcp_twsk_unique,
  	.twsk_destructor= tcp_twsk_destructor,
  	.twsk_getpeer	= tcp_v6_tw_get_peer,
  };
3b401a81c   Stephen Hemminger   inet: inet_connec...
1792
  static const struct inet_connection_sock_af_ops ipv6_specific = {
543d9cfee   Arnaldo Carvalho de Melo   [NET]: Identation...
1793
1794
1795
1796
1797
  	.queue_xmit	   = inet6_csk_xmit,
  	.send_check	   = tcp_v6_send_check,
  	.rebuild_header	   = inet6_sk_rebuild_header,
  	.conn_request	   = tcp_v6_conn_request,
  	.syn_recv_sock	   = tcp_v6_syn_recv_sock,
3f419d2d4   David S. Miller   inet: Turn ->reme...
1798
  	.get_peer	   = tcp_v6_get_peer,
543d9cfee   Arnaldo Carvalho de Melo   [NET]: Identation...
1799
1800
1801
1802
1803
  	.net_header_len	   = sizeof(struct ipv6hdr),
  	.setsockopt	   = ipv6_setsockopt,
  	.getsockopt	   = ipv6_getsockopt,
  	.addr2sockaddr	   = inet6_csk_addr2sockaddr,
  	.sockaddr_len	   = sizeof(struct sockaddr_in6),
ab1e0a13d   Arnaldo Carvalho de Melo   [SOCK] proto: Add...
1804
  	.bind_conflict	   = inet6_csk_bind_conflict,
3fdadf7d2   Dmitry Mishin   [NET]: {get|set}s...
1805
  #ifdef CONFIG_COMPAT
543d9cfee   Arnaldo Carvalho de Melo   [NET]: Identation...
1806
1807
  	.compat_setsockopt = compat_ipv6_setsockopt,
  	.compat_getsockopt = compat_ipv6_getsockopt,
3fdadf7d2   Dmitry Mishin   [NET]: {get|set}s...
1808
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1809
  };
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1810
  #ifdef CONFIG_TCP_MD5SIG
b2e4b3deb   Stephen Hemminger   tcp: MD5 operatio...
1811
  static const struct tcp_sock_af_ops tcp_sock_ipv6_specific = {
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1812
  	.md5_lookup	=	tcp_v6_md5_lookup,
49a72dfb8   Adam Langley   tcp: Fix MD5 sign...
1813
  	.calc_md5_hash	=	tcp_v6_md5_hash_skb,
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1814
1815
  	.md5_add	=	tcp_v6_md5_add_func,
  	.md5_parse	=	tcp_v6_parse_md5_keys,
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1816
  };
a928630a2   David S. Miller   [TCP]: Fix some w...
1817
  #endif
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1818

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1819
1820
1821
  /*
   *	TCP over IPv4 via INET6 API
   */
3b401a81c   Stephen Hemminger   inet: inet_connec...
1822
  static const struct inet_connection_sock_af_ops ipv6_mapped = {
543d9cfee   Arnaldo Carvalho de Melo   [NET]: Identation...
1823
1824
1825
1826
1827
  	.queue_xmit	   = ip_queue_xmit,
  	.send_check	   = tcp_v4_send_check,
  	.rebuild_header	   = inet_sk_rebuild_header,
  	.conn_request	   = tcp_v6_conn_request,
  	.syn_recv_sock	   = tcp_v6_syn_recv_sock,
3f419d2d4   David S. Miller   inet: Turn ->reme...
1828
  	.get_peer	   = tcp_v4_get_peer,
543d9cfee   Arnaldo Carvalho de Melo   [NET]: Identation...
1829
1830
1831
1832
1833
  	.net_header_len	   = sizeof(struct iphdr),
  	.setsockopt	   = ipv6_setsockopt,
  	.getsockopt	   = ipv6_getsockopt,
  	.addr2sockaddr	   = inet6_csk_addr2sockaddr,
  	.sockaddr_len	   = sizeof(struct sockaddr_in6),
ab1e0a13d   Arnaldo Carvalho de Melo   [SOCK] proto: Add...
1834
  	.bind_conflict	   = inet6_csk_bind_conflict,
3fdadf7d2   Dmitry Mishin   [NET]: {get|set}s...
1835
  #ifdef CONFIG_COMPAT
543d9cfee   Arnaldo Carvalho de Melo   [NET]: Identation...
1836
1837
  	.compat_setsockopt = compat_ipv6_setsockopt,
  	.compat_getsockopt = compat_ipv6_getsockopt,
3fdadf7d2   Dmitry Mishin   [NET]: {get|set}s...
1838
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1839
  };
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1840
  #ifdef CONFIG_TCP_MD5SIG
b2e4b3deb   Stephen Hemminger   tcp: MD5 operatio...
1841
  static const struct tcp_sock_af_ops tcp_sock_ipv6_mapped_specific = {
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1842
  	.md5_lookup	=	tcp_v4_md5_lookup,
49a72dfb8   Adam Langley   tcp: Fix MD5 sign...
1843
  	.calc_md5_hash	=	tcp_v4_md5_hash_skb,
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1844
1845
  	.md5_add	=	tcp_v6_md5_add_func,
  	.md5_parse	=	tcp_v6_parse_md5_keys,
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1846
  };
a928630a2   David S. Miller   [TCP]: Fix some w...
1847
  #endif
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1848

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1849
1850
1851
1852
1853
  /* NOTE: A lot of things set to zero explicitly by call to
   *       sk_alloc() so need not be done here.
   */
  static int tcp_v6_init_sock(struct sock *sk)
  {
6687e988d   Arnaldo Carvalho de Melo   [ICSK]: Move TCP ...
1854
  	struct inet_connection_sock *icsk = inet_csk(sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1855
1856
1857
1858
1859
  	struct tcp_sock *tp = tcp_sk(sk);
  
  	skb_queue_head_init(&tp->out_of_order_queue);
  	tcp_init_xmit_timers(sk);
  	tcp_prequeue_init(tp);
6687e988d   Arnaldo Carvalho de Melo   [ICSK]: Move TCP ...
1860
  	icsk->icsk_rto = TCP_TIMEOUT_INIT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
  	tp->mdev = TCP_TIMEOUT_INIT;
  
  	/* So many TCP implementations out there (incorrectly) count the
  	 * initial SYN frame in their delayed-ACK and congestion control
  	 * algorithms that we must have the following bandaid to talk
  	 * efficiently to them.  -DaveM
  	 */
  	tp->snd_cwnd = 2;
  
  	/* See draft-stevens-tcpca-spec-01 for discussion of the
  	 * initialization of these values.
  	 */
0b6a05c1d   Ilpo Järvinen   tcp: fix ssthresh...
1873
  	tp->snd_ssthresh = TCP_INFINITE_SSTHRESH;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1874
  	tp->snd_cwnd_clamp = ~0;
bee7ca9ec   William Allen Simpson   net: TCP_MSS_DEFA...
1875
  	tp->mss_cache = TCP_MSS_DEFAULT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1876
1877
1878
1879
  
  	tp->reordering = sysctl_tcp_reordering;
  
  	sk->sk_state = TCP_CLOSE;
8292a17a3   Arnaldo Carvalho de Melo   [ICSK]: Rename st...
1880
  	icsk->icsk_af_ops = &ipv6_specific;
6687e988d   Arnaldo Carvalho de Melo   [ICSK]: Move TCP ...
1881
  	icsk->icsk_ca_ops = &tcp_init_congestion_ops;
d83d8461f   Arnaldo Carvalho de Melo   [IP_SOCKGLUE]: Re...
1882
  	icsk->icsk_sync_mss = tcp_sync_mss;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1883
1884
  	sk->sk_write_space = sk_stream_write_space;
  	sock_set_flag(sk, SOCK_USE_WRITE_QUEUE);
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1885
1886
1887
  #ifdef CONFIG_TCP_MD5SIG
  	tp->af_specific = &tcp_sock_ipv6_specific;
  #endif
435cf559f   William Allen Simpson   TCPCT part 1d: de...
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
  	/* TCP Cookie Transactions */
  	if (sysctl_tcp_cookie_size > 0) {
  		/* Default, cookies without s_data_payload. */
  		tp->cookie_values =
  			kzalloc(sizeof(*tp->cookie_values),
  				sk->sk_allocation);
  		if (tp->cookie_values != NULL)
  			kref_init(&tp->cookie_values->kref);
  	}
  	/* Presumed zeroed, in order of appearance:
  	 *	cookie_in_always, cookie_out_never,
  	 *	s_data_constant, s_data_in, s_data_out
  	 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1901
1902
  	sk->sk_sndbuf = sysctl_tcp_wmem[1];
  	sk->sk_rcvbuf = sysctl_tcp_rmem[1];
eb4dea585   Herbert Xu   net: Fix percpu c...
1903
  	local_bh_disable();
d1a4c0b37   Glauber Costa   tcp memory pressu...
1904
  	sock_update_memcg(sk);
180d8cd94   Glauber Costa   foundations of pe...
1905
  	sk_sockets_allocated_inc(sk);
eb4dea585   Herbert Xu   net: Fix percpu c...
1906
  	local_bh_enable();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1907
1908
1909
  
  	return 0;
  }
7d06b2e05   Brian Haley   net: change proto...
1910
  static void tcp_v6_destroy_sock(struct sock *sk)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1911
  {
cfb6eeb4c   YOSHIFUJI Hideaki   [TCP]: MD5 Signat...
1912
1913
1914
1915
1916
  #ifdef CONFIG_TCP_MD5SIG
  	/* Clean up the MD5 key list */
  	if (tcp_sk(sk)->md5sig_info)
  		tcp_v6_clear_md5_list(sk);
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1917
  	tcp_v4_destroy_sock(sk);
7d06b2e05   Brian Haley   net: change proto...
1918
  	inet6_destroy_sock(sk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1919
  }
952a10be3   YOSHIFUJI Hideaki   [IPV6] SNMP: Fix ...
1920
  #ifdef CONFIG_PROC_FS
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1921
  /* Proc filesystem TCPv6 sock list dumping. */
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
1922
  static void get_openreq6(struct seq_file *seq,
cf533ea53   Eric Dumazet   tcp: add const qu...
1923
  			 const struct sock *sk, struct request_sock *req, int i, int uid)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1924
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1925
  	int ttd = req->expires - jiffies;
b71d1d426   Eric Dumazet   inet: constify ip...
1926
1927
  	const struct in6_addr *src = &inet6_rsk(req)->loc_addr;
  	const struct in6_addr *dest = &inet6_rsk(req)->rmt_addr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1928
1929
1930
  
  	if (ttd < 0)
  		ttd = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1931
1932
  	seq_printf(seq,
  		   "%4d: %08X%08X%08X%08X:%04X %08X%08X%08X%08X:%04X "
71338aa7d   Dan Rosenberg   net: convert %p u...
1933
1934
  		   "%02X %08X:%08X %02X:%08lX %08X %5d %8d %d %d %pK
  ",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1935
1936
1937
  		   i,
  		   src->s6_addr32[0], src->s6_addr32[1],
  		   src->s6_addr32[2], src->s6_addr32[3],
fd5070370   KOVACS Krisztian   tcp: Fix IPv6 fal...
1938
  		   ntohs(inet_rsk(req)->loc_port),
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1939
1940
  		   dest->s6_addr32[0], dest->s6_addr32[1],
  		   dest->s6_addr32[2], dest->s6_addr32[3],
2e6599cb8   Arnaldo Carvalho de Melo   [NET] Generalise ...
1941
  		   ntohs(inet_rsk(req)->rmt_port),
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1942
1943
  		   TCP_SYN_RECV,
  		   0,0, /* could print option size, but that is af dependent. */
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
1944
1945
  		   1,   /* timers active (only the expire timer) */
  		   jiffies_to_clock_t(ttd),
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1946
1947
  		   req->retrans,
  		   uid,
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
1948
  		   0,  /* non standard timer */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1949
1950
1951
1952
1953
1954
  		   0, /* open_requests have no inode */
  		   0, req);
  }
  
  static void get_tcp6_sock(struct seq_file *seq, struct sock *sp, int i)
  {
b71d1d426   Eric Dumazet   inet: constify ip...
1955
  	const struct in6_addr *dest, *src;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1956
1957
1958
  	__u16 destp, srcp;
  	int timer_active;
  	unsigned long timer_expires;
cf533ea53   Eric Dumazet   tcp: add const qu...
1959
1960
  	const struct inet_sock *inet = inet_sk(sp);
  	const struct tcp_sock *tp = tcp_sk(sp);
463c84b97   Arnaldo Carvalho de Melo   [NET]: Introduce ...
1961
  	const struct inet_connection_sock *icsk = inet_csk(sp);
cf533ea53   Eric Dumazet   tcp: add const qu...
1962
  	const struct ipv6_pinfo *np = inet6_sk(sp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1963
1964
1965
  
  	dest  = &np->daddr;
  	src   = &np->rcv_saddr;
c720c7e83   Eric Dumazet   inet: rename some...
1966
1967
  	destp = ntohs(inet->inet_dport);
  	srcp  = ntohs(inet->inet_sport);
463c84b97   Arnaldo Carvalho de Melo   [NET]: Introduce ...
1968
1969
  
  	if (icsk->icsk_pending == ICSK_TIME_RETRANS) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1970
  		timer_active	= 1;
463c84b97   Arnaldo Carvalho de Melo   [NET]: Introduce ...
1971
1972
  		timer_expires	= icsk->icsk_timeout;
  	} else if (icsk->icsk_pending == ICSK_TIME_PROBE0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1973
  		timer_active	= 4;
463c84b97   Arnaldo Carvalho de Melo   [NET]: Introduce ...
1974
  		timer_expires	= icsk->icsk_timeout;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
  	} else if (timer_pending(&sp->sk_timer)) {
  		timer_active	= 2;
  		timer_expires	= sp->sk_timer.expires;
  	} else {
  		timer_active	= 0;
  		timer_expires = jiffies;
  	}
  
  	seq_printf(seq,
  		   "%4d: %08X%08X%08X%08X:%04X %08X%08X%08X%08X:%04X "
71338aa7d   Dan Rosenberg   net: convert %p u...
1985
1986
  		   "%02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %pK %lu %lu %u %u %d
  ",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1987
1988
1989
1990
1991
  		   i,
  		   src->s6_addr32[0], src->s6_addr32[1],
  		   src->s6_addr32[2], src->s6_addr32[3], srcp,
  		   dest->s6_addr32[0], dest->s6_addr32[1],
  		   dest->s6_addr32[2], dest->s6_addr32[3], destp,
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
1992
  		   sp->sk_state,
47da8ee68   Sridhar Samudrala   [TCP]: Export acc...
1993
1994
  		   tp->write_seq-tp->snd_una,
  		   (sp->sk_state == TCP_LISTEN) ? sp->sk_ack_backlog : (tp->rcv_nxt - tp->copied_seq),
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1995
1996
  		   timer_active,
  		   jiffies_to_clock_t(timer_expires - jiffies),
463c84b97   Arnaldo Carvalho de Melo   [NET]: Introduce ...
1997
  		   icsk->icsk_retransmits,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1998
  		   sock_i_uid(sp),
6687e988d   Arnaldo Carvalho de Melo   [ICSK]: Move TCP ...
1999
  		   icsk->icsk_probes_out,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2000
2001
  		   sock_i_ino(sp),
  		   atomic_read(&sp->sk_refcnt), sp,
7be87351a   Stephen Hemminger   tcp: /proc/net/tc...
2002
2003
  		   jiffies_to_clock_t(icsk->icsk_rto),
  		   jiffies_to_clock_t(icsk->icsk_ack.ato),
463c84b97   Arnaldo Carvalho de Melo   [NET]: Introduce ...
2004
  		   (icsk->icsk_ack.quick << 1 ) | icsk->icsk_ack.pingpong,
0b6a05c1d   Ilpo Järvinen   tcp: fix ssthresh...
2005
2006
  		   tp->snd_cwnd,
  		   tcp_in_initial_slowstart(tp) ? -1 : tp->snd_ssthresh
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2007
2008
  		   );
  }
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
2009
  static void get_timewait6_sock(struct seq_file *seq,
8feaf0c0a   Arnaldo Carvalho de Melo   [INET]: Generalis...
2010
  			       struct inet_timewait_sock *tw, int i)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2011
  {
b71d1d426   Eric Dumazet   inet: constify ip...
2012
  	const struct in6_addr *dest, *src;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2013
  	__u16 destp, srcp;
cf533ea53   Eric Dumazet   tcp: add const qu...
2014
  	const struct inet6_timewait_sock *tw6 = inet6_twsk((struct sock *)tw);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2015
2016
2017
2018
  	int ttd = tw->tw_ttd - jiffies;
  
  	if (ttd < 0)
  		ttd = 0;
0fa1a53e1   Arnaldo Carvalho de Melo   [IPV6]: Introduce...
2019
2020
  	dest = &tw6->tw_v6_daddr;
  	src  = &tw6->tw_v6_rcv_saddr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2021
2022
2023
2024
2025
  	destp = ntohs(tw->tw_dport);
  	srcp  = ntohs(tw->tw_sport);
  
  	seq_printf(seq,
  		   "%4d: %08X%08X%08X%08X:%04X %08X%08X%08X%08X:%04X "
71338aa7d   Dan Rosenberg   net: convert %p u...
2026
2027
  		   "%02X %08X:%08X %02X:%08lX %08X %5d %8d %d %d %pK
  ",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2028
2029
2030
2031
2032
2033
2034
2035
2036
  		   i,
  		   src->s6_addr32[0], src->s6_addr32[1],
  		   src->s6_addr32[2], src->s6_addr32[3], srcp,
  		   dest->s6_addr32[0], dest->s6_addr32[1],
  		   dest->s6_addr32[2], dest->s6_addr32[3], destp,
  		   tw->tw_substate, 0, 0,
  		   3, jiffies_to_clock_t(ttd), 0, 0, 0, 0,
  		   atomic_read(&tw->tw_refcnt), tw);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
  static int tcp6_seq_show(struct seq_file *seq, void *v)
  {
  	struct tcp_iter_state *st;
  
  	if (v == SEQ_START_TOKEN) {
  		seq_puts(seq,
  			 "  sl  "
  			 "local_address                         "
  			 "remote_address                        "
  			 "st tx_queue rx_queue tr tm->when retrnsmt"
  			 "   uid  timeout inode
  ");
  		goto out;
  	}
  	st = seq->private;
  
  	switch (st->state) {
  	case TCP_SEQ_STATE_LISTENING:
  	case TCP_SEQ_STATE_ESTABLISHED:
  		get_tcp6_sock(seq, v, st->num);
  		break;
  	case TCP_SEQ_STATE_OPENREQ:
  		get_openreq6(seq, st->syn_wait_sk, v, st->num, st->uid);
  		break;
  	case TCP_SEQ_STATE_TIME_WAIT:
  		get_timewait6_sock(seq, v, st->num);
  		break;
  	}
  out:
  	return 0;
  }
73cb88ecb   Arjan van de Ven   net: make the tcp...
2068
2069
2070
2071
2072
2073
2074
  static const struct file_operations tcp6_afinfo_seq_fops = {
  	.owner   = THIS_MODULE,
  	.open    = tcp_seq_open,
  	.read    = seq_read,
  	.llseek  = seq_lseek,
  	.release = seq_release_net
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2075
  static struct tcp_seq_afinfo tcp6_seq_afinfo = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2076
2077
  	.name		= "tcp6",
  	.family		= AF_INET6,
73cb88ecb   Arjan van de Ven   net: make the tcp...
2078
  	.seq_fops	= &tcp6_afinfo_seq_fops,
9427c4b36   Denis V. Lunev   [TCP]: Move seq_o...
2079
2080
2081
  	.seq_ops	= {
  		.show		= tcp6_seq_show,
  	},
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2082
  };
2c8c1e729   Alexey Dobriyan   net: spread __net...
2083
  int __net_init tcp6_proc_init(struct net *net)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2084
  {
6f8b13bcb   Daniel Lezcano   [NETNS][IPV6] tcp...
2085
  	return tcp_proc_register(net, &tcp6_seq_afinfo);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2086
  }
6f8b13bcb   Daniel Lezcano   [NETNS][IPV6] tcp...
2087
  void tcp6_proc_exit(struct net *net)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2088
  {
6f8b13bcb   Daniel Lezcano   [NETNS][IPV6] tcp...
2089
  	tcp_proc_unregister(net, &tcp6_seq_afinfo);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2090
2091
2092
2093
2094
2095
2096
2097
2098
  }
  #endif
  
  struct proto tcpv6_prot = {
  	.name			= "TCPv6",
  	.owner			= THIS_MODULE,
  	.close			= tcp_close,
  	.connect		= tcp_v6_connect,
  	.disconnect		= tcp_disconnect,
463c84b97   Arnaldo Carvalho de Melo   [NET]: Introduce ...
2099
  	.accept			= inet_csk_accept,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2100
2101
2102
2103
2104
2105
  	.ioctl			= tcp_ioctl,
  	.init			= tcp_v6_init_sock,
  	.destroy		= tcp_v6_destroy_sock,
  	.shutdown		= tcp_shutdown,
  	.setsockopt		= tcp_setsockopt,
  	.getsockopt		= tcp_getsockopt,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2106
  	.recvmsg		= tcp_recvmsg,
7ba429100   Changli Gao   inet, inet6: make...
2107
2108
  	.sendmsg		= tcp_sendmsg,
  	.sendpage		= tcp_sendpage,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2109
2110
  	.backlog_rcv		= tcp_v6_do_rcv,
  	.hash			= tcp_v6_hash,
ab1e0a13d   Arnaldo Carvalho de Melo   [SOCK] proto: Add...
2111
2112
  	.unhash			= inet_unhash,
  	.get_port		= inet_csk_get_port,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2113
2114
2115
2116
  	.enter_memory_pressure	= tcp_enter_memory_pressure,
  	.sockets_allocated	= &tcp_sockets_allocated,
  	.memory_allocated	= &tcp_memory_allocated,
  	.memory_pressure	= &tcp_memory_pressure,
0a5578cf8   Arnaldo Carvalho de Melo   [ICSK]: Generalis...
2117
  	.orphan_count		= &tcp_orphan_count,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2118
2119
2120
2121
  	.sysctl_wmem		= sysctl_tcp_wmem,
  	.sysctl_rmem		= sysctl_tcp_rmem,
  	.max_header		= MAX_TCP_HEADER,
  	.obj_size		= sizeof(struct tcp6_sock),
3ab5aee7f   Eric Dumazet   net: Convert TCP ...
2122
  	.slab_flags		= SLAB_DESTROY_BY_RCU,
6d6ee43e0   Arnaldo Carvalho de Melo   [TWSK]: Introduce...
2123
  	.twsk_prot		= &tcp6_timewait_sock_ops,
60236fdd0   Arnaldo Carvalho de Melo   [NET] Rename open...
2124
  	.rsk_prot		= &tcp6_request_sock_ops,
39d8cda76   Pavel Emelyanov   [SOCK]: Add udp_h...
2125
  	.h.hashinfo		= &tcp_hashinfo,
7ba429100   Changli Gao   inet, inet6: make...
2126
  	.no_autobind		= true,
543d9cfee   Arnaldo Carvalho de Melo   [NET]: Identation...
2127
2128
2129
2130
  #ifdef CONFIG_COMPAT
  	.compat_setsockopt	= compat_tcp_setsockopt,
  	.compat_getsockopt	= compat_tcp_getsockopt,
  #endif
d1a4c0b37   Glauber Costa   tcp memory pressu...
2131
2132
2133
  #ifdef CONFIG_CGROUP_MEM_RES_CTLR_KMEM
  	.proto_cgroup		= tcp_proto_cgroup,
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2134
  };
41135cc83   Alexey Dobriyan   net: constify str...
2135
  static const struct inet6_protocol tcpv6_protocol = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2136
2137
  	.handler	=	tcp_v6_rcv,
  	.err_handler	=	tcp_v6_err,
a430a43d0   Herbert Xu   [NET] gso: Fix up...
2138
  	.gso_send_check	=	tcp_v6_gso_send_check,
adcfc7d0b   Herbert Xu   [IPV6]: Added GSO...
2139
  	.gso_segment	=	tcp_tso_segment,
684f21760   Herbert Xu   tcp6: Add GRO sup...
2140
2141
  	.gro_receive	=	tcp6_gro_receive,
  	.gro_complete	=	tcp6_gro_complete,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2142
2143
  	.flags		=	INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL,
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2144
2145
2146
2147
2148
  static struct inet_protosw tcpv6_protosw = {
  	.type		=	SOCK_STREAM,
  	.protocol	=	IPPROTO_TCP,
  	.prot		=	&tcpv6_prot,
  	.ops		=	&inet6_stream_ops,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2149
  	.no_check	=	0,
d83d8461f   Arnaldo Carvalho de Melo   [IP_SOCKGLUE]: Re...
2150
2151
  	.flags		=	INET_PROTOSW_PERMANENT |
  				INET_PROTOSW_ICSK,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2152
  };
2c8c1e729   Alexey Dobriyan   net: spread __net...
2153
  static int __net_init tcpv6_net_init(struct net *net)
93ec926b0   Daniel Lezcano   [NETNS][IPV6] tcp...
2154
  {
5677242f4   Denis V. Lunev   [NETNS]: Inet con...
2155
2156
  	return inet_ctl_sock_create(&net->ipv6.tcp_sk, PF_INET6,
  				    SOCK_RAW, IPPROTO_TCP, net);
93ec926b0   Daniel Lezcano   [NETNS][IPV6] tcp...
2157
  }
2c8c1e729   Alexey Dobriyan   net: spread __net...
2158
  static void __net_exit tcpv6_net_exit(struct net *net)
93ec926b0   Daniel Lezcano   [NETNS][IPV6] tcp...
2159
  {
5677242f4   Denis V. Lunev   [NETNS]: Inet con...
2160
  	inet_ctl_sock_destroy(net->ipv6.tcp_sk);
b099ce260   Eric W. Biederman   net: Batch inet_t...
2161
  }
2c8c1e729   Alexey Dobriyan   net: spread __net...
2162
  static void __net_exit tcpv6_net_exit_batch(struct list_head *net_exit_list)
b099ce260   Eric W. Biederman   net: Batch inet_t...
2163
2164
  {
  	inet_twsk_purge(&tcp_hashinfo, &tcp_death_row, AF_INET6);
93ec926b0   Daniel Lezcano   [NETNS][IPV6] tcp...
2165
2166
2167
  }
  
  static struct pernet_operations tcpv6_net_ops = {
b099ce260   Eric W. Biederman   net: Batch inet_t...
2168
2169
2170
  	.init	    = tcpv6_net_init,
  	.exit	    = tcpv6_net_exit,
  	.exit_batch = tcpv6_net_exit_batch,
93ec926b0   Daniel Lezcano   [NETNS][IPV6] tcp...
2171
  };
7f4e4868f   Daniel Lezcano   [IPV6]: make the ...
2172
  int __init tcpv6_init(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2173
  {
7f4e4868f   Daniel Lezcano   [IPV6]: make the ...
2174
2175
2176
2177
2178
  	int ret;
  
  	ret = inet6_add_protocol(&tcpv6_protocol, IPPROTO_TCP);
  	if (ret)
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2179
  	/* register inet6 protocol */
7f4e4868f   Daniel Lezcano   [IPV6]: make the ...
2180
2181
2182
  	ret = inet6_register_protosw(&tcpv6_protosw);
  	if (ret)
  		goto out_tcpv6_protocol;
93ec926b0   Daniel Lezcano   [NETNS][IPV6] tcp...
2183
  	ret = register_pernet_subsys(&tcpv6_net_ops);
7f4e4868f   Daniel Lezcano   [IPV6]: make the ...
2184
2185
2186
2187
  	if (ret)
  		goto out_tcpv6_protosw;
  out:
  	return ret;
ae0f7d5f8   David Woodhouse   [IPV6]: Avoid cal...
2188

7f4e4868f   Daniel Lezcano   [IPV6]: make the ...
2189
2190
2191
2192
2193
2194
  out_tcpv6_protocol:
  	inet6_del_protocol(&tcpv6_protocol, IPPROTO_TCP);
  out_tcpv6_protosw:
  	inet6_unregister_protosw(&tcpv6_protosw);
  	goto out;
  }
09f7709f4   Daniel Lezcano   [IPV6]: fix secti...
2195
  void tcpv6_exit(void)
7f4e4868f   Daniel Lezcano   [IPV6]: make the ...
2196
  {
93ec926b0   Daniel Lezcano   [NETNS][IPV6] tcp...
2197
  	unregister_pernet_subsys(&tcpv6_net_ops);
7f4e4868f   Daniel Lezcano   [IPV6]: make the ...
2198
2199
  	inet6_unregister_protosw(&tcpv6_protosw);
  	inet6_del_protocol(&tcpv6_protocol, IPPROTO_TCP);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2200
  }