blob: 62c0e5bd931c7aa458083b00e2d81850f8c1b4e0 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * TCP over IPv6
3 * Linux INET6 implementation
4 *
5 * Authors:
6 * Pedro Roque <roque@di.fc.ul.pt>
7 *
8 * $Id: tcp_ipv6.c,v 1.144 2002/02/01 22:01:04 davem Exp $
9 *
10 * Based on:
11 * linux/net/ipv4/tcp.c
12 * linux/net/ipv4/tcp_input.c
13 * linux/net/ipv4/tcp_output.c
14 *
15 * Fixes:
16 * Hideaki YOSHIFUJI : sin6_scope_id support
17 * YOSHIFUJI Hideaki @USAGI and: Support IPV6_V6ONLY socket option, which
18 * Alexey Kuznetsov allow both IPv4 and IPv6 sockets to bind
19 * a single port at the same time.
20 * YOSHIFUJI Hideaki @USAGI: convert /proc/net/tcp6 to seq_file.
21 *
22 * This program is free software; you can redistribute it and/or
23 * modify it under the terms of the GNU General Public License
24 * as published by the Free Software Foundation; either version
25 * 2 of the License, or (at your option) any later version.
26 */
27
28#include <linux/module.h>
29#include <linux/config.h>
30#include <linux/errno.h>
31#include <linux/types.h>
32#include <linux/socket.h>
33#include <linux/sockios.h>
34#include <linux/net.h>
35#include <linux/jiffies.h>
36#include <linux/in.h>
37#include <linux/in6.h>
38#include <linux/netdevice.h>
39#include <linux/init.h>
40#include <linux/jhash.h>
41#include <linux/ipsec.h>
42#include <linux/times.h>
43
44#include <linux/ipv6.h>
45#include <linux/icmpv6.h>
46#include <linux/random.h>
47
48#include <net/tcp.h>
49#include <net/ndisc.h>
Arnaldo Carvalho de Melo5324a042005-08-12 09:26:18 -030050#include <net/inet6_hashtables.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070051#include <net/ipv6.h>
52#include <net/transp_v6.h>
53#include <net/addrconf.h>
54#include <net/ip6_route.h>
55#include <net/ip6_checksum.h>
56#include <net/inet_ecn.h>
57#include <net/protocol.h>
58#include <net/xfrm.h>
59#include <net/addrconf.h>
60#include <net/snmp.h>
61#include <net/dsfield.h>
62
63#include <asm/uaccess.h>
64
65#include <linux/proc_fs.h>
66#include <linux/seq_file.h>
67
68static void tcp_v6_send_reset(struct sk_buff *skb);
Arnaldo Carvalho de Melo60236fd2005-06-18 22:47:21 -070069static void tcp_v6_reqsk_send_ack(struct sk_buff *skb, struct request_sock *req);
Linus Torvalds1da177e2005-04-16 15:20:36 -070070static void tcp_v6_send_check(struct sock *sk, struct tcphdr *th, int len,
71 struct sk_buff *skb);
72
73static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb);
74static int tcp_v6_xmit(struct sk_buff *skb, int ipfragok);
75
76static struct tcp_func ipv6_mapped;
77static struct tcp_func ipv6_specific;
78
Arnaldo Carvalho de Melo0f7ff922005-08-09 19:59:44 -070079static inline int tcp_v6_bind_conflict(const struct sock *sk,
80 const struct inet_bind_bucket *tb)
Linus Torvalds1da177e2005-04-16 15:20:36 -070081{
Arnaldo Carvalho de Melo0f7ff922005-08-09 19:59:44 -070082 const struct sock *sk2;
83 const struct hlist_node *node;
Linus Torvalds1da177e2005-04-16 15:20:36 -070084
85 /* We must walk the whole port owner list in this case. -DaveM */
86 sk_for_each_bound(sk2, node, &tb->owners) {
87 if (sk != sk2 &&
88 (!sk->sk_bound_dev_if ||
89 !sk2->sk_bound_dev_if ||
90 sk->sk_bound_dev_if == sk2->sk_bound_dev_if) &&
91 (!sk->sk_reuse || !sk2->sk_reuse ||
92 sk2->sk_state == TCP_LISTEN) &&
93 ipv6_rcv_saddr_equal(sk, sk2))
94 break;
95 }
96
97 return node != NULL;
98}
99
100/* Grrr, addr_type already calculated by caller, but I don't want
101 * to add some silly "cookie" argument to this method just for that.
102 * But it doesn't matter, the recalculation is in the rarest path
103 * this function ever takes.
104 */
105static int tcp_v6_get_port(struct sock *sk, unsigned short snum)
106{
Arnaldo Carvalho de Melo0f7ff922005-08-09 19:59:44 -0700107 struct inet_bind_hashbucket *head;
108 struct inet_bind_bucket *tb;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700109 struct hlist_node *node;
110 int ret;
111
112 local_bh_disable();
113 if (snum == 0) {
114 int low = sysctl_local_port_range[0];
115 int high = sysctl_local_port_range[1];
116 int remaining = (high - low) + 1;
Stephen Hemminger6df71632005-11-03 16:33:23 -0800117 int rover = net_random() % (high - low) + low;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700118
Stephen Hemminger6df71632005-11-03 16:33:23 -0800119 do {
Arnaldo Carvalho de Melo6e04e022005-08-09 20:07:35 -0700120 head = &tcp_hashinfo.bhash[inet_bhashfn(rover, tcp_hashinfo.bhash_size)];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700121 spin_lock(&head->lock);
Arnaldo Carvalho de Melo0f7ff922005-08-09 19:59:44 -0700122 inet_bind_bucket_for_each(tb, node, &head->chain)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700123 if (tb->port == rover)
124 goto next;
125 break;
126 next:
127 spin_unlock(&head->lock);
Stephen Hemminger6df71632005-11-03 16:33:23 -0800128 if (++rover > high)
129 rover = low;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700130 } while (--remaining > 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700131
David S. Millerd5d28372005-08-23 10:49:54 -0700132 /* Exhausted local port range during search? It is not
133 * possible for us to be holding one of the bind hash
134 * locks if this test triggers, because if 'remaining'
135 * drops to zero, we broke out of the do/while loop at
136 * the top level, not from the 'break;' statement.
137 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700138 ret = 1;
David S. Millerd5d28372005-08-23 10:49:54 -0700139 if (unlikely(remaining <= 0))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700140 goto fail;
141
142 /* OK, here is the one we will use. */
143 snum = rover;
144 } else {
Arnaldo Carvalho de Melo6e04e022005-08-09 20:07:35 -0700145 head = &tcp_hashinfo.bhash[inet_bhashfn(snum, tcp_hashinfo.bhash_size)];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700146 spin_lock(&head->lock);
Arnaldo Carvalho de Melo0f7ff922005-08-09 19:59:44 -0700147 inet_bind_bucket_for_each(tb, node, &head->chain)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700148 if (tb->port == snum)
149 goto tb_found;
150 }
151 tb = NULL;
152 goto tb_not_found;
153tb_found:
154 if (tb && !hlist_empty(&tb->owners)) {
155 if (tb->fastreuse > 0 && sk->sk_reuse &&
156 sk->sk_state != TCP_LISTEN) {
157 goto success;
158 } else {
159 ret = 1;
160 if (tcp_v6_bind_conflict(sk, tb))
161 goto fail_unlock;
162 }
163 }
164tb_not_found:
165 ret = 1;
Arnaldo Carvalho de Melo6e04e022005-08-09 20:07:35 -0700166 if (tb == NULL) {
167 tb = inet_bind_bucket_create(tcp_hashinfo.bind_bucket_cachep, head, snum);
168 if (tb == NULL)
169 goto fail_unlock;
170 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700171 if (hlist_empty(&tb->owners)) {
172 if (sk->sk_reuse && sk->sk_state != TCP_LISTEN)
173 tb->fastreuse = 1;
174 else
175 tb->fastreuse = 0;
176 } else if (tb->fastreuse &&
177 (!sk->sk_reuse || sk->sk_state == TCP_LISTEN))
178 tb->fastreuse = 0;
179
180success:
Arnaldo Carvalho de Melo463c84b2005-08-09 20:10:42 -0700181 if (!inet_csk(sk)->icsk_bind_hash)
Arnaldo Carvalho de Melo2d8c4ce2005-08-09 20:07:13 -0700182 inet_bind_hash(sk, tb, snum);
Arnaldo Carvalho de Melo463c84b2005-08-09 20:10:42 -0700183 BUG_TRAP(inet_csk(sk)->icsk_bind_hash == tb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700184 ret = 0;
185
186fail_unlock:
187 spin_unlock(&head->lock);
188fail:
189 local_bh_enable();
190 return ret;
191}
192
193static __inline__ void __tcp_v6_hash(struct sock *sk)
194{
195 struct hlist_head *list;
196 rwlock_t *lock;
197
198 BUG_TRAP(sk_unhashed(sk));
199
200 if (sk->sk_state == TCP_LISTEN) {
Arnaldo Carvalho de Melo6e04e022005-08-09 20:07:35 -0700201 list = &tcp_hashinfo.listening_hash[inet_sk_listen_hashfn(sk)];
202 lock = &tcp_hashinfo.lhash_lock;
Arnaldo Carvalho de Melof3f05f72005-08-09 20:08:09 -0700203 inet_listen_wlock(&tcp_hashinfo);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700204 } else {
Eric Dumazet81c3d542005-10-03 14:13:38 -0700205 unsigned int hash;
206 sk->sk_hash = hash = inet6_sk_ehashfn(sk);
207 hash &= (tcp_hashinfo.ehash_size - 1);
208 list = &tcp_hashinfo.ehash[hash].chain;
209 lock = &tcp_hashinfo.ehash[hash].lock;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700210 write_lock(lock);
211 }
212
213 __sk_add_node(sk, list);
214 sock_prot_inc_use(sk->sk_prot);
215 write_unlock(lock);
216}
217
218
219static void tcp_v6_hash(struct sock *sk)
220{
221 if (sk->sk_state != TCP_CLOSE) {
222 struct tcp_sock *tp = tcp_sk(sk);
223
224 if (tp->af_specific == &ipv6_mapped) {
225 tcp_prot.hash(sk);
226 return;
227 }
228 local_bh_disable();
229 __tcp_v6_hash(sk);
230 local_bh_enable();
231 }
232}
233
Linus Torvalds1da177e2005-04-16 15:20:36 -0700234/*
235 * Open request hash tables.
236 */
237
Arnaldo Carvalho de Melo463c84b2005-08-09 20:10:42 -0700238static u32 tcp_v6_synq_hash(const struct in6_addr *raddr, const u16 rport, const u32 rnd)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700239{
240 u32 a, b, c;
241
242 a = raddr->s6_addr32[0];
243 b = raddr->s6_addr32[1];
244 c = raddr->s6_addr32[2];
245
246 a += JHASH_GOLDEN_RATIO;
247 b += JHASH_GOLDEN_RATIO;
248 c += rnd;
249 __jhash_mix(a, b, c);
250
251 a += raddr->s6_addr32[3];
252 b += (u32) rport;
253 __jhash_mix(a, b, c);
254
255 return c & (TCP_SYNQ_HSIZE - 1);
256}
257
Arnaldo Carvalho de Melo463c84b2005-08-09 20:10:42 -0700258static struct request_sock *tcp_v6_search_req(const struct sock *sk,
Arnaldo Carvalho de Melo60236fd2005-06-18 22:47:21 -0700259 struct request_sock ***prevp,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700260 __u16 rport,
261 struct in6_addr *raddr,
262 struct in6_addr *laddr,
263 int iif)
264{
Arnaldo Carvalho de Melo463c84b2005-08-09 20:10:42 -0700265 const struct inet_connection_sock *icsk = inet_csk(sk);
266 struct listen_sock *lopt = icsk->icsk_accept_queue.listen_opt;
Arnaldo Carvalho de Melo60236fd2005-06-18 22:47:21 -0700267 struct request_sock *req, **prev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700268
269 for (prev = &lopt->syn_table[tcp_v6_synq_hash(raddr, rport, lopt->hash_rnd)];
270 (req = *prev) != NULL;
271 prev = &req->dl_next) {
Arnaldo Carvalho de Melo2e6599c2005-06-18 22:46:52 -0700272 const struct tcp6_request_sock *treq = tcp6_rsk(req);
273
274 if (inet_rsk(req)->rmt_port == rport &&
Arnaldo Carvalho de Melo60236fd2005-06-18 22:47:21 -0700275 req->rsk_ops->family == AF_INET6 &&
Arnaldo Carvalho de Melo2e6599c2005-06-18 22:46:52 -0700276 ipv6_addr_equal(&treq->rmt_addr, raddr) &&
277 ipv6_addr_equal(&treq->loc_addr, laddr) &&
278 (!treq->iif || treq->iif == iif)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700279 BUG_TRAP(req->sk == NULL);
280 *prevp = prev;
281 return req;
282 }
283 }
284
285 return NULL;
286}
287
288static __inline__ u16 tcp_v6_check(struct tcphdr *th, int len,
289 struct in6_addr *saddr,
290 struct in6_addr *daddr,
291 unsigned long base)
292{
293 return csum_ipv6_magic(saddr, daddr, len, IPPROTO_TCP, base);
294}
295
296static __u32 tcp_v6_init_sequence(struct sock *sk, struct sk_buff *skb)
297{
298 if (skb->protocol == htons(ETH_P_IPV6)) {
299 return secure_tcpv6_sequence_number(skb->nh.ipv6h->daddr.s6_addr32,
300 skb->nh.ipv6h->saddr.s6_addr32,
301 skb->h.th->dest,
302 skb->h.th->source);
303 } else {
304 return secure_tcp_sequence_number(skb->nh.iph->daddr,
305 skb->nh.iph->saddr,
306 skb->h.th->dest,
307 skb->h.th->source);
308 }
309}
310
Arnaldo Carvalho de Melo505cbfc2005-08-12 09:19:38 -0300311static int __tcp_v6_check_established(struct sock *sk, const __u16 lport,
Arnaldo Carvalho de Melo8feaf0c02005-08-09 20:09:30 -0700312 struct inet_timewait_sock **twp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700313{
314 struct inet_sock *inet = inet_sk(sk);
Arnaldo Carvalho de Melo505cbfc2005-08-12 09:19:38 -0300315 const struct ipv6_pinfo *np = inet6_sk(sk);
316 const struct in6_addr *daddr = &np->rcv_saddr;
317 const struct in6_addr *saddr = &np->daddr;
318 const int dif = sk->sk_bound_dev_if;
Arnaldo Carvalho de Melo8feaf0c02005-08-09 20:09:30 -0700319 const u32 ports = INET_COMBINED_PORTS(inet->dport, lport);
Eric Dumazet81c3d542005-10-03 14:13:38 -0700320 unsigned int hash = inet6_ehashfn(daddr, inet->num, saddr, inet->dport);
321 struct inet_ehash_bucket *head = inet_ehash_bucket(&tcp_hashinfo, hash);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700322 struct sock *sk2;
Arnaldo Carvalho de Melo8feaf0c02005-08-09 20:09:30 -0700323 const struct hlist_node *node;
324 struct inet_timewait_sock *tw;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700325
Eric Dumazet81c3d542005-10-03 14:13:38 -0700326 prefetch(head->chain.first);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700327 write_lock(&head->lock);
328
329 /* Check TIME-WAIT sockets first. */
Arnaldo Carvalho de Melo6e04e022005-08-09 20:07:35 -0700330 sk_for_each(sk2, node, &(head + tcp_hashinfo.ehash_size)->chain) {
Arnaldo Carvalho de Melo8feaf0c02005-08-09 20:09:30 -0700331 const struct tcp6_timewait_sock *tcp6tw = tcp6_twsk(sk2);
332
333 tw = inet_twsk(sk2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700334
335 if(*((__u32 *)&(tw->tw_dport)) == ports &&
336 sk2->sk_family == PF_INET6 &&
Arnaldo Carvalho de Melo8feaf0c02005-08-09 20:09:30 -0700337 ipv6_addr_equal(&tcp6tw->tw_v6_daddr, saddr) &&
338 ipv6_addr_equal(&tcp6tw->tw_v6_rcv_saddr, daddr) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -0700339 sk2->sk_bound_dev_if == sk->sk_bound_dev_if) {
Arnaldo Carvalho de Melo8feaf0c02005-08-09 20:09:30 -0700340 const struct tcp_timewait_sock *tcptw = tcp_twsk(sk2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700341 struct tcp_sock *tp = tcp_sk(sk);
342
Arnaldo Carvalho de Melo8feaf0c02005-08-09 20:09:30 -0700343 if (tcptw->tw_ts_recent_stamp &&
344 (!twp ||
345 (sysctl_tcp_tw_reuse &&
346 xtime.tv_sec - tcptw->tw_ts_recent_stamp > 1))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700347 /* See comment in tcp_ipv4.c */
Arnaldo Carvalho de Melo8feaf0c02005-08-09 20:09:30 -0700348 tp->write_seq = tcptw->tw_snd_nxt + 65535 + 2;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700349 if (!tp->write_seq)
350 tp->write_seq = 1;
Arnaldo Carvalho de Melo8feaf0c02005-08-09 20:09:30 -0700351 tp->rx_opt.ts_recent = tcptw->tw_ts_recent;
352 tp->rx_opt.ts_recent_stamp = tcptw->tw_ts_recent_stamp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700353 sock_hold(sk2);
354 goto unique;
355 } else
356 goto not_unique;
357 }
358 }
359 tw = NULL;
360
361 /* And established part... */
362 sk_for_each(sk2, node, &head->chain) {
Eric Dumazet81c3d542005-10-03 14:13:38 -0700363 if (INET6_MATCH(sk2, hash, saddr, daddr, ports, dif))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700364 goto not_unique;
365 }
366
367unique:
368 BUG_TRAP(sk_unhashed(sk));
369 __sk_add_node(sk, &head->chain);
Eric Dumazet81c3d542005-10-03 14:13:38 -0700370 sk->sk_hash = hash;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700371 sock_prot_inc_use(sk->sk_prot);
372 write_unlock(&head->lock);
373
374 if (twp) {
375 *twp = tw;
376 NET_INC_STATS_BH(LINUX_MIB_TIMEWAITRECYCLED);
377 } else if (tw) {
378 /* Silly. Should hash-dance instead... */
Arnaldo Carvalho de Melo295ff7e2005-08-09 20:44:40 -0700379 inet_twsk_deschedule(tw, &tcp_death_row);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700380 NET_INC_STATS_BH(LINUX_MIB_TIMEWAITRECYCLED);
381
Arnaldo Carvalho de Melo8feaf0c02005-08-09 20:09:30 -0700382 inet_twsk_put(tw);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700383 }
384 return 0;
385
386not_unique:
387 write_unlock(&head->lock);
388 return -EADDRNOTAVAIL;
389}
390
391static inline u32 tcpv6_port_offset(const struct sock *sk)
392{
393 const struct inet_sock *inet = inet_sk(sk);
394 const struct ipv6_pinfo *np = inet6_sk(sk);
395
396 return secure_tcpv6_port_ephemeral(np->rcv_saddr.s6_addr32,
397 np->daddr.s6_addr32,
398 inet->dport);
399}
400
401static int tcp_v6_hash_connect(struct sock *sk)
402{
403 unsigned short snum = inet_sk(sk)->num;
Arnaldo Carvalho de Melo0f7ff922005-08-09 19:59:44 -0700404 struct inet_bind_hashbucket *head;
405 struct inet_bind_bucket *tb;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700406 int ret;
407
408 if (!snum) {
409 int low = sysctl_local_port_range[0];
410 int high = sysctl_local_port_range[1];
411 int range = high - low;
412 int i;
413 int port;
414 static u32 hint;
415 u32 offset = hint + tcpv6_port_offset(sk);
416 struct hlist_node *node;
Arnaldo Carvalho de Melo8feaf0c02005-08-09 20:09:30 -0700417 struct inet_timewait_sock *tw = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700418
419 local_bh_disable();
420 for (i = 1; i <= range; i++) {
421 port = low + (i + offset) % range;
Arnaldo Carvalho de Melo6e04e022005-08-09 20:07:35 -0700422 head = &tcp_hashinfo.bhash[inet_bhashfn(port, tcp_hashinfo.bhash_size)];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700423 spin_lock(&head->lock);
424
425 /* Does not bother with rcv_saddr checks,
426 * because the established check is already
427 * unique enough.
428 */
Arnaldo Carvalho de Melo0f7ff922005-08-09 19:59:44 -0700429 inet_bind_bucket_for_each(tb, node, &head->chain) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700430 if (tb->port == port) {
431 BUG_TRAP(!hlist_empty(&tb->owners));
432 if (tb->fastreuse >= 0)
433 goto next_port;
434 if (!__tcp_v6_check_established(sk,
435 port,
436 &tw))
437 goto ok;
438 goto next_port;
439 }
440 }
441
Arnaldo Carvalho de Melo6e04e022005-08-09 20:07:35 -0700442 tb = inet_bind_bucket_create(tcp_hashinfo.bind_bucket_cachep, head, port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700443 if (!tb) {
444 spin_unlock(&head->lock);
445 break;
446 }
447 tb->fastreuse = -1;
448 goto ok;
449
450 next_port:
451 spin_unlock(&head->lock);
452 }
453 local_bh_enable();
454
455 return -EADDRNOTAVAIL;
456
457ok:
458 hint += i;
459
460 /* Head lock still held and bh's disabled */
Arnaldo Carvalho de Melo2d8c4ce2005-08-09 20:07:13 -0700461 inet_bind_hash(sk, tb, port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700462 if (sk_unhashed(sk)) {
463 inet_sk(sk)->sport = htons(port);
464 __tcp_v6_hash(sk);
465 }
466 spin_unlock(&head->lock);
467
468 if (tw) {
Arnaldo Carvalho de Melo295ff7e2005-08-09 20:44:40 -0700469 inet_twsk_deschedule(tw, &tcp_death_row);
Arnaldo Carvalho de Melo8feaf0c02005-08-09 20:09:30 -0700470 inet_twsk_put(tw);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700471 }
472
473 ret = 0;
474 goto out;
475 }
476
Arnaldo Carvalho de Melo6e04e022005-08-09 20:07:35 -0700477 head = &tcp_hashinfo.bhash[inet_bhashfn(snum, tcp_hashinfo.bhash_size)];
Arnaldo Carvalho de Melo463c84b2005-08-09 20:10:42 -0700478 tb = inet_csk(sk)->icsk_bind_hash;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700479 spin_lock_bh(&head->lock);
480
481 if (sk_head(&tb->owners) == sk && !sk->sk_bind_node.next) {
482 __tcp_v6_hash(sk);
483 spin_unlock_bh(&head->lock);
484 return 0;
485 } else {
486 spin_unlock(&head->lock);
487 /* No definite answer... Walk to established hash table */
488 ret = __tcp_v6_check_established(sk, snum, NULL);
489out:
490 local_bh_enable();
491 return ret;
492 }
493}
494
Linus Torvalds1da177e2005-04-16 15:20:36 -0700495static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
496 int addr_len)
497{
498 struct sockaddr_in6 *usin = (struct sockaddr_in6 *) uaddr;
499 struct inet_sock *inet = inet_sk(sk);
500 struct ipv6_pinfo *np = inet6_sk(sk);
501 struct tcp_sock *tp = tcp_sk(sk);
502 struct in6_addr *saddr = NULL, *final_p = NULL, final;
503 struct flowi fl;
504 struct dst_entry *dst;
505 int addr_type;
506 int err;
507
508 if (addr_len < SIN6_LEN_RFC2133)
509 return -EINVAL;
510
511 if (usin->sin6_family != AF_INET6)
512 return(-EAFNOSUPPORT);
513
514 memset(&fl, 0, sizeof(fl));
515
516 if (np->sndflow) {
517 fl.fl6_flowlabel = usin->sin6_flowinfo&IPV6_FLOWINFO_MASK;
518 IP6_ECN_flow_init(fl.fl6_flowlabel);
519 if (fl.fl6_flowlabel&IPV6_FLOWLABEL_MASK) {
520 struct ip6_flowlabel *flowlabel;
521 flowlabel = fl6_sock_lookup(sk, fl.fl6_flowlabel);
522 if (flowlabel == NULL)
523 return -EINVAL;
524 ipv6_addr_copy(&usin->sin6_addr, &flowlabel->dst);
525 fl6_sock_release(flowlabel);
526 }
527 }
528
529 /*
530 * connect() to INADDR_ANY means loopback (BSD'ism).
531 */
532
533 if(ipv6_addr_any(&usin->sin6_addr))
534 usin->sin6_addr.s6_addr[15] = 0x1;
535
536 addr_type = ipv6_addr_type(&usin->sin6_addr);
537
538 if(addr_type & IPV6_ADDR_MULTICAST)
539 return -ENETUNREACH;
540
541 if (addr_type&IPV6_ADDR_LINKLOCAL) {
542 if (addr_len >= sizeof(struct sockaddr_in6) &&
543 usin->sin6_scope_id) {
544 /* If interface is set while binding, indices
545 * must coincide.
546 */
547 if (sk->sk_bound_dev_if &&
548 sk->sk_bound_dev_if != usin->sin6_scope_id)
549 return -EINVAL;
550
551 sk->sk_bound_dev_if = usin->sin6_scope_id;
552 }
553
554 /* Connect to link-local address requires an interface */
555 if (!sk->sk_bound_dev_if)
556 return -EINVAL;
557 }
558
559 if (tp->rx_opt.ts_recent_stamp &&
560 !ipv6_addr_equal(&np->daddr, &usin->sin6_addr)) {
561 tp->rx_opt.ts_recent = 0;
562 tp->rx_opt.ts_recent_stamp = 0;
563 tp->write_seq = 0;
564 }
565
566 ipv6_addr_copy(&np->daddr, &usin->sin6_addr);
567 np->flow_label = fl.fl6_flowlabel;
568
569 /*
570 * TCP over IPv4
571 */
572
573 if (addr_type == IPV6_ADDR_MAPPED) {
574 u32 exthdrlen = tp->ext_header_len;
575 struct sockaddr_in sin;
576
577 SOCK_DEBUG(sk, "connect: ipv4 mapped\n");
578
579 if (__ipv6_only_sock(sk))
580 return -ENETUNREACH;
581
582 sin.sin_family = AF_INET;
583 sin.sin_port = usin->sin6_port;
584 sin.sin_addr.s_addr = usin->sin6_addr.s6_addr32[3];
585
586 tp->af_specific = &ipv6_mapped;
587 sk->sk_backlog_rcv = tcp_v4_do_rcv;
588
589 err = tcp_v4_connect(sk, (struct sockaddr *)&sin, sizeof(sin));
590
591 if (err) {
592 tp->ext_header_len = exthdrlen;
593 tp->af_specific = &ipv6_specific;
594 sk->sk_backlog_rcv = tcp_v6_do_rcv;
595 goto failure;
596 } else {
597 ipv6_addr_set(&np->saddr, 0, 0, htonl(0x0000FFFF),
598 inet->saddr);
599 ipv6_addr_set(&np->rcv_saddr, 0, 0, htonl(0x0000FFFF),
600 inet->rcv_saddr);
601 }
602
603 return err;
604 }
605
606 if (!ipv6_addr_any(&np->rcv_saddr))
607 saddr = &np->rcv_saddr;
608
609 fl.proto = IPPROTO_TCP;
610 ipv6_addr_copy(&fl.fl6_dst, &np->daddr);
611 ipv6_addr_copy(&fl.fl6_src,
612 (saddr ? saddr : &np->saddr));
613 fl.oif = sk->sk_bound_dev_if;
614 fl.fl_ip_dport = usin->sin6_port;
615 fl.fl_ip_sport = inet->sport;
616
617 if (np->opt && np->opt->srcrt) {
618 struct rt0_hdr *rt0 = (struct rt0_hdr *)np->opt->srcrt;
619 ipv6_addr_copy(&final, &fl.fl6_dst);
620 ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
621 final_p = &final;
622 }
623
624 err = ip6_dst_lookup(sk, &dst, &fl);
625 if (err)
626 goto failure;
627 if (final_p)
628 ipv6_addr_copy(&fl.fl6_dst, final_p);
629
Patrick McHardye104411b2005-09-08 15:11:55 -0700630 if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700631 goto failure;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700632
633 if (saddr == NULL) {
634 saddr = &fl.fl6_src;
635 ipv6_addr_copy(&np->rcv_saddr, saddr);
636 }
637
638 /* set the source address */
639 ipv6_addr_copy(&np->saddr, saddr);
640 inet->rcv_saddr = LOOPBACK4_IPV6;
641
642 ip6_dst_store(sk, dst, NULL);
643 sk->sk_route_caps = dst->dev->features &
644 ~(NETIF_F_IP_CSUM | NETIF_F_TSO);
645
646 tp->ext_header_len = 0;
647 if (np->opt)
648 tp->ext_header_len = np->opt->opt_flen + np->opt->opt_nflen;
649
650 tp->rx_opt.mss_clamp = IPV6_MIN_MTU - sizeof(struct tcphdr) - sizeof(struct ipv6hdr);
651
652 inet->dport = usin->sin6_port;
653
654 tcp_set_state(sk, TCP_SYN_SENT);
655 err = tcp_v6_hash_connect(sk);
656 if (err)
657 goto late_failure;
658
659 if (!tp->write_seq)
660 tp->write_seq = secure_tcpv6_sequence_number(np->saddr.s6_addr32,
661 np->daddr.s6_addr32,
662 inet->sport,
663 inet->dport);
664
665 err = tcp_connect(sk);
666 if (err)
667 goto late_failure;
668
669 return 0;
670
671late_failure:
672 tcp_set_state(sk, TCP_CLOSE);
673 __sk_dst_reset(sk);
674failure:
675 inet->dport = 0;
676 sk->sk_route_caps = 0;
677 return err;
678}
679
680static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
681 int type, int code, int offset, __u32 info)
682{
683 struct ipv6hdr *hdr = (struct ipv6hdr*)skb->data;
Arnaldo Carvalho de Melo505cbfc2005-08-12 09:19:38 -0300684 const struct tcphdr *th = (struct tcphdr *)(skb->data+offset);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700685 struct ipv6_pinfo *np;
686 struct sock *sk;
687 int err;
688 struct tcp_sock *tp;
689 __u32 seq;
690
Arnaldo Carvalho de Melo505cbfc2005-08-12 09:19:38 -0300691 sk = inet6_lookup(&tcp_hashinfo, &hdr->daddr, th->dest, &hdr->saddr,
692 th->source, skb->dev->ifindex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700693
694 if (sk == NULL) {
695 ICMP6_INC_STATS_BH(__in6_dev_get(skb->dev), ICMP6_MIB_INERRORS);
696 return;
697 }
698
699 if (sk->sk_state == TCP_TIME_WAIT) {
Arnaldo Carvalho de Melo8feaf0c02005-08-09 20:09:30 -0700700 inet_twsk_put((struct inet_timewait_sock *)sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700701 return;
702 }
703
704 bh_lock_sock(sk);
705 if (sock_owned_by_user(sk))
706 NET_INC_STATS_BH(LINUX_MIB_LOCKDROPPEDICMPS);
707
708 if (sk->sk_state == TCP_CLOSE)
709 goto out;
710
711 tp = tcp_sk(sk);
712 seq = ntohl(th->seq);
713 if (sk->sk_state != TCP_LISTEN &&
714 !between(seq, tp->snd_una, tp->snd_nxt)) {
715 NET_INC_STATS_BH(LINUX_MIB_OUTOFWINDOWICMPS);
716 goto out;
717 }
718
719 np = inet6_sk(sk);
720
721 if (type == ICMPV6_PKT_TOOBIG) {
722 struct dst_entry *dst = NULL;
723
724 if (sock_owned_by_user(sk))
725 goto out;
726 if ((1 << sk->sk_state) & (TCPF_LISTEN | TCPF_CLOSE))
727 goto out;
728
729 /* icmp should have updated the destination cache entry */
730 dst = __sk_dst_check(sk, np->dst_cookie);
731
732 if (dst == NULL) {
733 struct inet_sock *inet = inet_sk(sk);
734 struct flowi fl;
735
736 /* BUGGG_FUTURE: Again, it is not clear how
737 to handle rthdr case. Ignore this complexity
738 for now.
739 */
740 memset(&fl, 0, sizeof(fl));
741 fl.proto = IPPROTO_TCP;
742 ipv6_addr_copy(&fl.fl6_dst, &np->daddr);
743 ipv6_addr_copy(&fl.fl6_src, &np->saddr);
744 fl.oif = sk->sk_bound_dev_if;
745 fl.fl_ip_dport = inet->dport;
746 fl.fl_ip_sport = inet->sport;
747
748 if ((err = ip6_dst_lookup(sk, &dst, &fl))) {
749 sk->sk_err_soft = -err;
750 goto out;
751 }
752
753 if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) {
754 sk->sk_err_soft = -err;
755 goto out;
756 }
757
758 } else
759 dst_hold(dst);
760
761 if (tp->pmtu_cookie > dst_mtu(dst)) {
762 tcp_sync_mss(sk, dst_mtu(dst));
763 tcp_simple_retransmit(sk);
764 } /* else let the usual retransmit timer handle it */
765 dst_release(dst);
766 goto out;
767 }
768
769 icmpv6_err_convert(type, code, &err);
770
Arnaldo Carvalho de Melo60236fd2005-06-18 22:47:21 -0700771 /* Might be for an request_sock */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700772 switch (sk->sk_state) {
Arnaldo Carvalho de Melo60236fd2005-06-18 22:47:21 -0700773 struct request_sock *req, **prev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700774 case TCP_LISTEN:
775 if (sock_owned_by_user(sk))
776 goto out;
777
Arnaldo Carvalho de Melo463c84b2005-08-09 20:10:42 -0700778 req = tcp_v6_search_req(sk, &prev, th->dest, &hdr->daddr,
Arnaldo Carvalho de Melo505cbfc2005-08-12 09:19:38 -0300779 &hdr->saddr, inet6_iif(skb));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700780 if (!req)
781 goto out;
782
783 /* ICMPs are not backlogged, hence we cannot get
784 * an established socket here.
785 */
786 BUG_TRAP(req->sk == NULL);
787
Arnaldo Carvalho de Melo2e6599c2005-06-18 22:46:52 -0700788 if (seq != tcp_rsk(req)->snt_isn) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700789 NET_INC_STATS_BH(LINUX_MIB_OUTOFWINDOWICMPS);
790 goto out;
791 }
792
Arnaldo Carvalho de Melo463c84b2005-08-09 20:10:42 -0700793 inet_csk_reqsk_queue_drop(sk, req, prev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700794 goto out;
795
796 case TCP_SYN_SENT:
797 case TCP_SYN_RECV: /* Cannot happen.
798 It can, it SYNs are crossed. --ANK */
799 if (!sock_owned_by_user(sk)) {
800 TCP_INC_STATS_BH(TCP_MIB_ATTEMPTFAILS);
801 sk->sk_err = err;
802 sk->sk_error_report(sk); /* Wake people up to see the error (see connect in sock.c) */
803
804 tcp_done(sk);
805 } else
806 sk->sk_err_soft = err;
807 goto out;
808 }
809
810 if (!sock_owned_by_user(sk) && np->recverr) {
811 sk->sk_err = err;
812 sk->sk_error_report(sk);
813 } else
814 sk->sk_err_soft = err;
815
816out:
817 bh_unlock_sock(sk);
818 sock_put(sk);
819}
820
821
Arnaldo Carvalho de Melo60236fd2005-06-18 22:47:21 -0700822static int tcp_v6_send_synack(struct sock *sk, struct request_sock *req,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700823 struct dst_entry *dst)
824{
Arnaldo Carvalho de Melo2e6599c2005-06-18 22:46:52 -0700825 struct tcp6_request_sock *treq = tcp6_rsk(req);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700826 struct ipv6_pinfo *np = inet6_sk(sk);
827 struct sk_buff * skb;
828 struct ipv6_txoptions *opt = NULL;
829 struct in6_addr * final_p = NULL, final;
830 struct flowi fl;
831 int err = -1;
832
833 memset(&fl, 0, sizeof(fl));
834 fl.proto = IPPROTO_TCP;
Arnaldo Carvalho de Melo2e6599c2005-06-18 22:46:52 -0700835 ipv6_addr_copy(&fl.fl6_dst, &treq->rmt_addr);
836 ipv6_addr_copy(&fl.fl6_src, &treq->loc_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700837 fl.fl6_flowlabel = 0;
Arnaldo Carvalho de Melo2e6599c2005-06-18 22:46:52 -0700838 fl.oif = treq->iif;
839 fl.fl_ip_dport = inet_rsk(req)->rmt_port;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700840 fl.fl_ip_sport = inet_sk(sk)->sport;
841
842 if (dst == NULL) {
843 opt = np->opt;
844 if (opt == NULL &&
YOSHIFUJI Hideaki333fad52005-09-08 09:59:17 +0900845 np->rxopt.bits.osrcrt == 2 &&
Arnaldo Carvalho de Melo2e6599c2005-06-18 22:46:52 -0700846 treq->pktopts) {
847 struct sk_buff *pktopts = treq->pktopts;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700848 struct inet6_skb_parm *rxopt = IP6CB(pktopts);
849 if (rxopt->srcrt)
850 opt = ipv6_invert_rthdr(sk, (struct ipv6_rt_hdr*)(pktopts->nh.raw + rxopt->srcrt));
851 }
852
853 if (opt && opt->srcrt) {
854 struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt;
855 ipv6_addr_copy(&final, &fl.fl6_dst);
856 ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
857 final_p = &final;
858 }
859
860 err = ip6_dst_lookup(sk, &dst, &fl);
861 if (err)
862 goto done;
863 if (final_p)
864 ipv6_addr_copy(&fl.fl6_dst, final_p);
865 if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0)
866 goto done;
867 }
868
869 skb = tcp_make_synack(sk, dst, req);
870 if (skb) {
871 struct tcphdr *th = skb->h.th;
872
873 th->check = tcp_v6_check(th, skb->len,
Arnaldo Carvalho de Melo2e6599c2005-06-18 22:46:52 -0700874 &treq->loc_addr, &treq->rmt_addr,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700875 csum_partial((char *)th, skb->len, skb->csum));
876
Arnaldo Carvalho de Melo2e6599c2005-06-18 22:46:52 -0700877 ipv6_addr_copy(&fl.fl6_dst, &treq->rmt_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700878 err = ip6_xmit(sk, skb, &fl, opt, 0);
879 if (err == NET_XMIT_CN)
880 err = 0;
881 }
882
883done:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700884 if (opt && opt != np->opt)
885 sock_kfree_s(sk, opt, opt->tot_len);
886 return err;
887}
888
Arnaldo Carvalho de Melo60236fd2005-06-18 22:47:21 -0700889static void tcp_v6_reqsk_destructor(struct request_sock *req)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700890{
Arnaldo Carvalho de Melo2e6599c2005-06-18 22:46:52 -0700891 if (tcp6_rsk(req)->pktopts)
892 kfree_skb(tcp6_rsk(req)->pktopts);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700893}
894
Arnaldo Carvalho de Melo60236fd2005-06-18 22:47:21 -0700895static struct request_sock_ops tcp6_request_sock_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700896 .family = AF_INET6,
Arnaldo Carvalho de Melo2e6599c2005-06-18 22:46:52 -0700897 .obj_size = sizeof(struct tcp6_request_sock),
Linus Torvalds1da177e2005-04-16 15:20:36 -0700898 .rtx_syn_ack = tcp_v6_send_synack,
Arnaldo Carvalho de Melo60236fd2005-06-18 22:47:21 -0700899 .send_ack = tcp_v6_reqsk_send_ack,
900 .destructor = tcp_v6_reqsk_destructor,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700901 .send_reset = tcp_v6_send_reset
902};
903
904static int ipv6_opt_accepted(struct sock *sk, struct sk_buff *skb)
905{
906 struct ipv6_pinfo *np = inet6_sk(sk);
907 struct inet6_skb_parm *opt = IP6CB(skb);
908
909 if (np->rxopt.all) {
YOSHIFUJI Hideaki333fad52005-09-08 09:59:17 +0900910 if ((opt->hop && (np->rxopt.bits.hopopts || np->rxopt.bits.ohopopts)) ||
911 ((IPV6_FLOWINFO_MASK & *(u32*)skb->nh.raw) && np->rxopt.bits.rxflow) ||
912 (opt->srcrt && (np->rxopt.bits.srcrt || np->rxopt.bits.osrcrt)) ||
913 ((opt->dst1 || opt->dst0) && (np->rxopt.bits.dstopts || np->rxopt.bits.odstopts)))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700914 return 1;
915 }
916 return 0;
917}
918
919
920static void tcp_v6_send_check(struct sock *sk, struct tcphdr *th, int len,
921 struct sk_buff *skb)
922{
923 struct ipv6_pinfo *np = inet6_sk(sk);
924
925 if (skb->ip_summed == CHECKSUM_HW) {
926 th->check = ~csum_ipv6_magic(&np->saddr, &np->daddr, len, IPPROTO_TCP, 0);
927 skb->csum = offsetof(struct tcphdr, check);
928 } else {
929 th->check = csum_ipv6_magic(&np->saddr, &np->daddr, len, IPPROTO_TCP,
930 csum_partial((char *)th, th->doff<<2,
931 skb->csum));
932 }
933}
934
935
936static void tcp_v6_send_reset(struct sk_buff *skb)
937{
938 struct tcphdr *th = skb->h.th, *t1;
939 struct sk_buff *buff;
940 struct flowi fl;
941
942 if (th->rst)
943 return;
944
945 if (!ipv6_unicast_destination(skb))
946 return;
947
948 /*
949 * We need to grab some memory, and put together an RST,
950 * and then put it into the queue to be sent.
951 */
952
953 buff = alloc_skb(MAX_HEADER + sizeof(struct ipv6hdr) + sizeof(struct tcphdr),
954 GFP_ATOMIC);
955 if (buff == NULL)
956 return;
957
958 skb_reserve(buff, MAX_HEADER + sizeof(struct ipv6hdr) + sizeof(struct tcphdr));
959
960 t1 = (struct tcphdr *) skb_push(buff,sizeof(struct tcphdr));
961
962 /* Swap the send and the receive. */
963 memset(t1, 0, sizeof(*t1));
964 t1->dest = th->source;
965 t1->source = th->dest;
966 t1->doff = sizeof(*t1)/4;
967 t1->rst = 1;
968
969 if(th->ack) {
970 t1->seq = th->ack_seq;
971 } else {
972 t1->ack = 1;
973 t1->ack_seq = htonl(ntohl(th->seq) + th->syn + th->fin
974 + skb->len - (th->doff<<2));
975 }
976
977 buff->csum = csum_partial((char *)t1, sizeof(*t1), 0);
978
979 memset(&fl, 0, sizeof(fl));
980 ipv6_addr_copy(&fl.fl6_dst, &skb->nh.ipv6h->saddr);
981 ipv6_addr_copy(&fl.fl6_src, &skb->nh.ipv6h->daddr);
982
983 t1->check = csum_ipv6_magic(&fl.fl6_src, &fl.fl6_dst,
984 sizeof(*t1), IPPROTO_TCP,
985 buff->csum);
986
987 fl.proto = IPPROTO_TCP;
Arnaldo Carvalho de Melo505cbfc2005-08-12 09:19:38 -0300988 fl.oif = inet6_iif(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700989 fl.fl_ip_dport = t1->dest;
990 fl.fl_ip_sport = t1->source;
991
992 /* sk = NULL, but it is safe for now. RST socket required. */
993 if (!ip6_dst_lookup(NULL, &buff->dst, &fl)) {
994
Patrick McHardye104411b2005-09-08 15:11:55 -0700995 if ((xfrm_lookup(&buff->dst, &fl, NULL, 0)) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700996 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700997
998 ip6_xmit(NULL, buff, &fl, NULL, 0);
999 TCP_INC_STATS_BH(TCP_MIB_OUTSEGS);
1000 TCP_INC_STATS_BH(TCP_MIB_OUTRSTS);
1001 return;
1002 }
1003
1004 kfree_skb(buff);
1005}
1006
1007static void tcp_v6_send_ack(struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32 ts)
1008{
1009 struct tcphdr *th = skb->h.th, *t1;
1010 struct sk_buff *buff;
1011 struct flowi fl;
1012 int tot_len = sizeof(struct tcphdr);
1013
1014 if (ts)
1015 tot_len += 3*4;
1016
1017 buff = alloc_skb(MAX_HEADER + sizeof(struct ipv6hdr) + tot_len,
1018 GFP_ATOMIC);
1019 if (buff == NULL)
1020 return;
1021
1022 skb_reserve(buff, MAX_HEADER + sizeof(struct ipv6hdr) + tot_len);
1023
1024 t1 = (struct tcphdr *) skb_push(buff,tot_len);
1025
1026 /* Swap the send and the receive. */
1027 memset(t1, 0, sizeof(*t1));
1028 t1->dest = th->source;
1029 t1->source = th->dest;
1030 t1->doff = tot_len/4;
1031 t1->seq = htonl(seq);
1032 t1->ack_seq = htonl(ack);
1033 t1->ack = 1;
1034 t1->window = htons(win);
1035
1036 if (ts) {
1037 u32 *ptr = (u32*)(t1 + 1);
1038 *ptr++ = htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) |
1039 (TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP);
1040 *ptr++ = htonl(tcp_time_stamp);
1041 *ptr = htonl(ts);
1042 }
1043
1044 buff->csum = csum_partial((char *)t1, tot_len, 0);
1045
1046 memset(&fl, 0, sizeof(fl));
1047 ipv6_addr_copy(&fl.fl6_dst, &skb->nh.ipv6h->saddr);
1048 ipv6_addr_copy(&fl.fl6_src, &skb->nh.ipv6h->daddr);
1049
1050 t1->check = csum_ipv6_magic(&fl.fl6_src, &fl.fl6_dst,
1051 tot_len, IPPROTO_TCP,
1052 buff->csum);
1053
1054 fl.proto = IPPROTO_TCP;
Arnaldo Carvalho de Melo505cbfc2005-08-12 09:19:38 -03001055 fl.oif = inet6_iif(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001056 fl.fl_ip_dport = t1->dest;
1057 fl.fl_ip_sport = t1->source;
1058
1059 if (!ip6_dst_lookup(NULL, &buff->dst, &fl)) {
Patrick McHardye104411b2005-09-08 15:11:55 -07001060 if ((xfrm_lookup(&buff->dst, &fl, NULL, 0)) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001061 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001062 ip6_xmit(NULL, buff, &fl, NULL, 0);
1063 TCP_INC_STATS_BH(TCP_MIB_OUTSEGS);
1064 return;
1065 }
1066
1067 kfree_skb(buff);
1068}
1069
1070static void tcp_v6_timewait_ack(struct sock *sk, struct sk_buff *skb)
1071{
Arnaldo Carvalho de Melo8feaf0c02005-08-09 20:09:30 -07001072 struct inet_timewait_sock *tw = inet_twsk(sk);
1073 const struct tcp_timewait_sock *tcptw = tcp_twsk(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001074
Arnaldo Carvalho de Melo8feaf0c02005-08-09 20:09:30 -07001075 tcp_v6_send_ack(skb, tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt,
1076 tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale,
1077 tcptw->tw_ts_recent);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001078
Arnaldo Carvalho de Melo8feaf0c02005-08-09 20:09:30 -07001079 inet_twsk_put(tw);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001080}
1081
Arnaldo Carvalho de Melo60236fd2005-06-18 22:47:21 -07001082static void tcp_v6_reqsk_send_ack(struct sk_buff *skb, struct request_sock *req)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001083{
Arnaldo Carvalho de Melo2e6599c2005-06-18 22:46:52 -07001084 tcp_v6_send_ack(skb, tcp_rsk(req)->snt_isn + 1, tcp_rsk(req)->rcv_isn + 1, req->rcv_wnd, req->ts_recent);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001085}
1086
1087
1088static struct sock *tcp_v6_hnd_req(struct sock *sk,struct sk_buff *skb)
1089{
Arnaldo Carvalho de Melo60236fd2005-06-18 22:47:21 -07001090 struct request_sock *req, **prev;
Arnaldo Carvalho de Melo505cbfc2005-08-12 09:19:38 -03001091 const struct tcphdr *th = skb->h.th;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001092 struct sock *nsk;
1093
1094 /* Find possible connection requests. */
Arnaldo Carvalho de Melo463c84b2005-08-09 20:10:42 -07001095 req = tcp_v6_search_req(sk, &prev, th->source, &skb->nh.ipv6h->saddr,
Arnaldo Carvalho de Melo505cbfc2005-08-12 09:19:38 -03001096 &skb->nh.ipv6h->daddr, inet6_iif(skb));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001097 if (req)
1098 return tcp_check_req(sk, skb, req, prev);
1099
Arnaldo Carvalho de Melo505cbfc2005-08-12 09:19:38 -03001100 nsk = __inet6_lookup_established(&tcp_hashinfo, &skb->nh.ipv6h->saddr,
1101 th->source, &skb->nh.ipv6h->daddr,
1102 ntohs(th->dest), inet6_iif(skb));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001103
1104 if (nsk) {
1105 if (nsk->sk_state != TCP_TIME_WAIT) {
1106 bh_lock_sock(nsk);
1107 return nsk;
1108 }
Arnaldo Carvalho de Melo8feaf0c02005-08-09 20:09:30 -07001109 inet_twsk_put((struct inet_timewait_sock *)nsk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001110 return NULL;
1111 }
1112
1113#if 0 /*def CONFIG_SYN_COOKIES*/
1114 if (!th->rst && !th->syn && th->ack)
1115 sk = cookie_v6_check(sk, skb, &(IPCB(skb)->opt));
1116#endif
1117 return sk;
1118}
1119
Arnaldo Carvalho de Melo60236fd2005-06-18 22:47:21 -07001120static void tcp_v6_synq_add(struct sock *sk, struct request_sock *req)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001121{
Arnaldo Carvalho de Melo463c84b2005-08-09 20:10:42 -07001122 struct inet_connection_sock *icsk = inet_csk(sk);
1123 struct listen_sock *lopt = icsk->icsk_accept_queue.listen_opt;
1124 const u32 h = tcp_v6_synq_hash(&tcp6_rsk(req)->rmt_addr, inet_rsk(req)->rmt_port, lopt->hash_rnd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001125
Arnaldo Carvalho de Melo463c84b2005-08-09 20:10:42 -07001126 reqsk_queue_hash_req(&icsk->icsk_accept_queue, h, req, TCP_TIMEOUT_INIT);
1127 inet_csk_reqsk_queue_added(sk, TCP_TIMEOUT_INIT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001128}
1129
1130
1131/* FIXME: this is substantially similar to the ipv4 code.
1132 * Can some kind of merge be done? -- erics
1133 */
1134static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
1135{
Arnaldo Carvalho de Melo2e6599c2005-06-18 22:46:52 -07001136 struct tcp6_request_sock *treq;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001137 struct ipv6_pinfo *np = inet6_sk(sk);
1138 struct tcp_options_received tmp_opt;
1139 struct tcp_sock *tp = tcp_sk(sk);
Arnaldo Carvalho de Melo60236fd2005-06-18 22:47:21 -07001140 struct request_sock *req = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001141 __u32 isn = TCP_SKB_CB(skb)->when;
1142
1143 if (skb->protocol == htons(ETH_P_IP))
1144 return tcp_v4_conn_request(sk, skb);
1145
1146 if (!ipv6_unicast_destination(skb))
1147 goto drop;
1148
1149 /*
1150 * There are no SYN attacks on IPv6, yet...
1151 */
Arnaldo Carvalho de Melo463c84b2005-08-09 20:10:42 -07001152 if (inet_csk_reqsk_queue_is_full(sk) && !isn) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001153 if (net_ratelimit())
1154 printk(KERN_INFO "TCPv6: dropping request, synflood is possible\n");
1155 goto drop;
1156 }
1157
Arnaldo Carvalho de Melo463c84b2005-08-09 20:10:42 -07001158 if (sk_acceptq_is_full(sk) && inet_csk_reqsk_queue_young(sk) > 1)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001159 goto drop;
1160
Arnaldo Carvalho de Melo60236fd2005-06-18 22:47:21 -07001161 req = reqsk_alloc(&tcp6_request_sock_ops);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001162 if (req == NULL)
1163 goto drop;
1164
1165 tcp_clear_options(&tmp_opt);
1166 tmp_opt.mss_clamp = IPV6_MIN_MTU - sizeof(struct tcphdr) - sizeof(struct ipv6hdr);
1167 tmp_opt.user_mss = tp->rx_opt.user_mss;
1168
1169 tcp_parse_options(skb, &tmp_opt, 0);
1170
1171 tmp_opt.tstamp_ok = tmp_opt.saw_tstamp;
1172 tcp_openreq_init(req, &tmp_opt, skb);
1173
Arnaldo Carvalho de Melo2e6599c2005-06-18 22:46:52 -07001174 treq = tcp6_rsk(req);
1175 ipv6_addr_copy(&treq->rmt_addr, &skb->nh.ipv6h->saddr);
1176 ipv6_addr_copy(&treq->loc_addr, &skb->nh.ipv6h->daddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001177 TCP_ECN_create_request(req, skb->h.th);
Arnaldo Carvalho de Melo2e6599c2005-06-18 22:46:52 -07001178 treq->pktopts = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001179 if (ipv6_opt_accepted(sk, skb) ||
YOSHIFUJI Hideaki333fad52005-09-08 09:59:17 +09001180 np->rxopt.bits.rxinfo || np->rxopt.bits.rxoinfo ||
1181 np->rxopt.bits.rxhlim || np->rxopt.bits.rxohlim) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001182 atomic_inc(&skb->users);
Arnaldo Carvalho de Melo2e6599c2005-06-18 22:46:52 -07001183 treq->pktopts = skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001184 }
Arnaldo Carvalho de Melo2e6599c2005-06-18 22:46:52 -07001185 treq->iif = sk->sk_bound_dev_if;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001186
1187 /* So that link locals have meaning */
1188 if (!sk->sk_bound_dev_if &&
Arnaldo Carvalho de Melo2e6599c2005-06-18 22:46:52 -07001189 ipv6_addr_type(&treq->rmt_addr) & IPV6_ADDR_LINKLOCAL)
Arnaldo Carvalho de Melo505cbfc2005-08-12 09:19:38 -03001190 treq->iif = inet6_iif(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001191
1192 if (isn == 0)
1193 isn = tcp_v6_init_sequence(sk,skb);
1194
Arnaldo Carvalho de Melo2e6599c2005-06-18 22:46:52 -07001195 tcp_rsk(req)->snt_isn = isn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001196
1197 if (tcp_v6_send_synack(sk, req, NULL))
1198 goto drop;
1199
1200 tcp_v6_synq_add(sk, req);
1201
1202 return 0;
1203
1204drop:
1205 if (req)
Arnaldo Carvalho de Melo60236fd2005-06-18 22:47:21 -07001206 reqsk_free(req);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001207
1208 TCP_INC_STATS_BH(TCP_MIB_ATTEMPTFAILS);
1209 return 0; /* don't send reset */
1210}
1211
1212static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
Arnaldo Carvalho de Melo60236fd2005-06-18 22:47:21 -07001213 struct request_sock *req,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001214 struct dst_entry *dst)
1215{
Arnaldo Carvalho de Melo2e6599c2005-06-18 22:46:52 -07001216 struct tcp6_request_sock *treq = tcp6_rsk(req);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001217 struct ipv6_pinfo *newnp, *np = inet6_sk(sk);
1218 struct tcp6_sock *newtcp6sk;
1219 struct inet_sock *newinet;
1220 struct tcp_sock *newtp;
1221 struct sock *newsk;
1222 struct ipv6_txoptions *opt;
1223
1224 if (skb->protocol == htons(ETH_P_IP)) {
1225 /*
1226 * v6 mapped
1227 */
1228
1229 newsk = tcp_v4_syn_recv_sock(sk, skb, req, dst);
1230
1231 if (newsk == NULL)
1232 return NULL;
1233
1234 newtcp6sk = (struct tcp6_sock *)newsk;
1235 inet_sk(newsk)->pinet6 = &newtcp6sk->inet6;
1236
1237 newinet = inet_sk(newsk);
1238 newnp = inet6_sk(newsk);
1239 newtp = tcp_sk(newsk);
1240
1241 memcpy(newnp, np, sizeof(struct ipv6_pinfo));
1242
1243 ipv6_addr_set(&newnp->daddr, 0, 0, htonl(0x0000FFFF),
1244 newinet->daddr);
1245
1246 ipv6_addr_set(&newnp->saddr, 0, 0, htonl(0x0000FFFF),
1247 newinet->saddr);
1248
1249 ipv6_addr_copy(&newnp->rcv_saddr, &newnp->saddr);
1250
1251 newtp->af_specific = &ipv6_mapped;
1252 newsk->sk_backlog_rcv = tcp_v4_do_rcv;
1253 newnp->pktoptions = NULL;
1254 newnp->opt = NULL;
Arnaldo Carvalho de Melo505cbfc2005-08-12 09:19:38 -03001255 newnp->mcast_oif = inet6_iif(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001256 newnp->mcast_hops = skb->nh.ipv6h->hop_limit;
1257
Arnaldo Carvalho de Meloe6848972005-08-09 19:45:38 -07001258 /*
1259 * No need to charge this sock to the relevant IPv6 refcnt debug socks count
1260 * here, tcp_create_openreq_child now does this for us, see the comment in
1261 * that function for the gory details. -acme
Linus Torvalds1da177e2005-04-16 15:20:36 -07001262 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001263
1264 /* It is tricky place. Until this moment IPv4 tcp
1265 worked with IPv6 af_tcp.af_specific.
1266 Sync it now.
1267 */
1268 tcp_sync_mss(newsk, newtp->pmtu_cookie);
1269
1270 return newsk;
1271 }
1272
1273 opt = np->opt;
1274
1275 if (sk_acceptq_is_full(sk))
1276 goto out_overflow;
1277
YOSHIFUJI Hideaki333fad52005-09-08 09:59:17 +09001278 if (np->rxopt.bits.osrcrt == 2 &&
Arnaldo Carvalho de Melo2e6599c2005-06-18 22:46:52 -07001279 opt == NULL && treq->pktopts) {
1280 struct inet6_skb_parm *rxopt = IP6CB(treq->pktopts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001281 if (rxopt->srcrt)
Arnaldo Carvalho de Melo2e6599c2005-06-18 22:46:52 -07001282 opt = ipv6_invert_rthdr(sk, (struct ipv6_rt_hdr *)(treq->pktopts->nh.raw + rxopt->srcrt));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001283 }
1284
1285 if (dst == NULL) {
1286 struct in6_addr *final_p = NULL, final;
1287 struct flowi fl;
1288
1289 memset(&fl, 0, sizeof(fl));
1290 fl.proto = IPPROTO_TCP;
Arnaldo Carvalho de Melo2e6599c2005-06-18 22:46:52 -07001291 ipv6_addr_copy(&fl.fl6_dst, &treq->rmt_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001292 if (opt && opt->srcrt) {
1293 struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt;
1294 ipv6_addr_copy(&final, &fl.fl6_dst);
1295 ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
1296 final_p = &final;
1297 }
Arnaldo Carvalho de Melo2e6599c2005-06-18 22:46:52 -07001298 ipv6_addr_copy(&fl.fl6_src, &treq->loc_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001299 fl.oif = sk->sk_bound_dev_if;
Arnaldo Carvalho de Melo2e6599c2005-06-18 22:46:52 -07001300 fl.fl_ip_dport = inet_rsk(req)->rmt_port;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001301 fl.fl_ip_sport = inet_sk(sk)->sport;
1302
1303 if (ip6_dst_lookup(sk, &dst, &fl))
1304 goto out;
1305
1306 if (final_p)
1307 ipv6_addr_copy(&fl.fl6_dst, final_p);
1308
1309 if ((xfrm_lookup(&dst, &fl, sk, 0)) < 0)
1310 goto out;
1311 }
1312
1313 newsk = tcp_create_openreq_child(sk, req, skb);
1314 if (newsk == NULL)
1315 goto out;
1316
Arnaldo Carvalho de Meloe6848972005-08-09 19:45:38 -07001317 /*
1318 * No need to charge this sock to the relevant IPv6 refcnt debug socks
1319 * count here, tcp_create_openreq_child now does this for us, see the
1320 * comment in that function for the gory details. -acme
1321 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001322
1323 ip6_dst_store(newsk, dst, NULL);
1324 newsk->sk_route_caps = dst->dev->features &
1325 ~(NETIF_F_IP_CSUM | NETIF_F_TSO);
1326
1327 newtcp6sk = (struct tcp6_sock *)newsk;
1328 inet_sk(newsk)->pinet6 = &newtcp6sk->inet6;
1329
1330 newtp = tcp_sk(newsk);
1331 newinet = inet_sk(newsk);
1332 newnp = inet6_sk(newsk);
1333
1334 memcpy(newnp, np, sizeof(struct ipv6_pinfo));
1335
Arnaldo Carvalho de Melo2e6599c2005-06-18 22:46:52 -07001336 ipv6_addr_copy(&newnp->daddr, &treq->rmt_addr);
1337 ipv6_addr_copy(&newnp->saddr, &treq->loc_addr);
1338 ipv6_addr_copy(&newnp->rcv_saddr, &treq->loc_addr);
1339 newsk->sk_bound_dev_if = treq->iif;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001340
1341 /* Now IPv6 options...
1342
1343 First: no IPv4 options.
1344 */
1345 newinet->opt = NULL;
1346
1347 /* Clone RX bits */
1348 newnp->rxopt.all = np->rxopt.all;
1349
1350 /* Clone pktoptions received with SYN */
1351 newnp->pktoptions = NULL;
Arnaldo Carvalho de Melo2e6599c2005-06-18 22:46:52 -07001352 if (treq->pktopts != NULL) {
1353 newnp->pktoptions = skb_clone(treq->pktopts, GFP_ATOMIC);
1354 kfree_skb(treq->pktopts);
1355 treq->pktopts = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001356 if (newnp->pktoptions)
1357 skb_set_owner_r(newnp->pktoptions, newsk);
1358 }
1359 newnp->opt = NULL;
Arnaldo Carvalho de Melo505cbfc2005-08-12 09:19:38 -03001360 newnp->mcast_oif = inet6_iif(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001361 newnp->mcast_hops = skb->nh.ipv6h->hop_limit;
1362
1363 /* Clone native IPv6 options from listening socket (if any)
1364
1365 Yes, keeping reference count would be much more clever,
1366 but we make one more one thing there: reattach optmem
1367 to newsk.
1368 */
1369 if (opt) {
1370 newnp->opt = ipv6_dup_options(newsk, opt);
1371 if (opt != np->opt)
1372 sock_kfree_s(sk, opt, opt->tot_len);
1373 }
1374
1375 newtp->ext_header_len = 0;
1376 if (newnp->opt)
1377 newtp->ext_header_len = newnp->opt->opt_nflen +
1378 newnp->opt->opt_flen;
1379
1380 tcp_sync_mss(newsk, dst_mtu(dst));
1381 newtp->advmss = dst_metric(dst, RTAX_ADVMSS);
1382 tcp_initialize_rcv_mss(newsk);
1383
1384 newinet->daddr = newinet->saddr = newinet->rcv_saddr = LOOPBACK4_IPV6;
1385
1386 __tcp_v6_hash(newsk);
Arnaldo Carvalho de Melo2d8c4ce2005-08-09 20:07:13 -07001387 inet_inherit_port(&tcp_hashinfo, sk, newsk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001388
1389 return newsk;
1390
1391out_overflow:
1392 NET_INC_STATS_BH(LINUX_MIB_LISTENOVERFLOWS);
1393out:
1394 NET_INC_STATS_BH(LINUX_MIB_LISTENDROPS);
1395 if (opt && opt != np->opt)
1396 sock_kfree_s(sk, opt, opt->tot_len);
1397 dst_release(dst);
1398 return NULL;
1399}
1400
1401static int tcp_v6_checksum_init(struct sk_buff *skb)
1402{
1403 if (skb->ip_summed == CHECKSUM_HW) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001404 if (!tcp_v6_check(skb->h.th,skb->len,&skb->nh.ipv6h->saddr,
Herbert Xufb286bb2005-11-10 13:01:24 -08001405 &skb->nh.ipv6h->daddr,skb->csum)) {
1406 skb->ip_summed = CHECKSUM_UNNECESSARY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001407 return 0;
Herbert Xufb286bb2005-11-10 13:01:24 -08001408 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001409 }
Herbert Xufb286bb2005-11-10 13:01:24 -08001410
1411 skb->csum = ~tcp_v6_check(skb->h.th,skb->len,&skb->nh.ipv6h->saddr,
1412 &skb->nh.ipv6h->daddr, 0);
1413
Linus Torvalds1da177e2005-04-16 15:20:36 -07001414 if (skb->len <= 76) {
Herbert Xufb286bb2005-11-10 13:01:24 -08001415 return __skb_checksum_complete(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001416 }
1417 return 0;
1418}
1419
1420/* The socket must have it's spinlock held when we get
1421 * here.
1422 *
1423 * We have a potential double-lock case here, so even when
1424 * doing backlog processing we use the BH locking scheme.
1425 * This is because we cannot sleep with the original spinlock
1426 * held.
1427 */
1428static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb)
1429{
1430 struct ipv6_pinfo *np = inet6_sk(sk);
1431 struct tcp_sock *tp;
1432 struct sk_buff *opt_skb = NULL;
1433
1434 /* Imagine: socket is IPv6. IPv4 packet arrives,
1435 goes to IPv4 receive handler and backlogged.
1436 From backlog it always goes here. Kerboom...
1437 Fortunately, tcp_rcv_established and rcv_established
1438 handle them correctly, but it is not case with
1439 tcp_v6_hnd_req and tcp_v6_send_reset(). --ANK
1440 */
1441
1442 if (skb->protocol == htons(ETH_P_IP))
1443 return tcp_v4_do_rcv(sk, skb);
1444
1445 if (sk_filter(sk, skb, 0))
1446 goto discard;
1447
1448 /*
1449 * socket locking is here for SMP purposes as backlog rcv
1450 * is currently called with bh processing disabled.
1451 */
1452
1453 /* Do Stevens' IPV6_PKTOPTIONS.
1454
1455 Yes, guys, it is the only place in our code, where we
1456 may make it not affecting IPv4.
1457 The rest of code is protocol independent,
1458 and I do not like idea to uglify IPv4.
1459
1460 Actually, all the idea behind IPV6_PKTOPTIONS
1461 looks not very well thought. For now we latch
1462 options, received in the last packet, enqueued
1463 by tcp. Feel free to propose better solution.
1464 --ANK (980728)
1465 */
1466 if (np->rxopt.all)
1467 opt_skb = skb_clone(skb, GFP_ATOMIC);
1468
1469 if (sk->sk_state == TCP_ESTABLISHED) { /* Fast path */
1470 TCP_CHECK_TIMER(sk);
1471 if (tcp_rcv_established(sk, skb, skb->h.th, skb->len))
1472 goto reset;
1473 TCP_CHECK_TIMER(sk);
1474 if (opt_skb)
1475 goto ipv6_pktoptions;
1476 return 0;
1477 }
1478
1479 if (skb->len < (skb->h.th->doff<<2) || tcp_checksum_complete(skb))
1480 goto csum_err;
1481
1482 if (sk->sk_state == TCP_LISTEN) {
1483 struct sock *nsk = tcp_v6_hnd_req(sk, skb);
1484 if (!nsk)
1485 goto discard;
1486
1487 /*
1488 * Queue it on the new socket if the new socket is active,
1489 * otherwise we just shortcircuit this and continue with
1490 * the new socket..
1491 */
1492 if(nsk != sk) {
1493 if (tcp_child_process(sk, nsk, skb))
1494 goto reset;
1495 if (opt_skb)
1496 __kfree_skb(opt_skb);
1497 return 0;
1498 }
1499 }
1500
1501 TCP_CHECK_TIMER(sk);
1502 if (tcp_rcv_state_process(sk, skb, skb->h.th, skb->len))
1503 goto reset;
1504 TCP_CHECK_TIMER(sk);
1505 if (opt_skb)
1506 goto ipv6_pktoptions;
1507 return 0;
1508
1509reset:
1510 tcp_v6_send_reset(skb);
1511discard:
1512 if (opt_skb)
1513 __kfree_skb(opt_skb);
1514 kfree_skb(skb);
1515 return 0;
1516csum_err:
1517 TCP_INC_STATS_BH(TCP_MIB_INERRS);
1518 goto discard;
1519
1520
1521ipv6_pktoptions:
1522 /* Do you ask, what is it?
1523
1524 1. skb was enqueued by tcp.
1525 2. skb is added to tail of read queue, rather than out of order.
1526 3. socket is not in passive state.
1527 4. Finally, it really contains options, which user wants to receive.
1528 */
1529 tp = tcp_sk(sk);
1530 if (TCP_SKB_CB(opt_skb)->end_seq == tp->rcv_nxt &&
1531 !((1 << sk->sk_state) & (TCPF_CLOSE | TCPF_LISTEN))) {
YOSHIFUJI Hideaki333fad52005-09-08 09:59:17 +09001532 if (np->rxopt.bits.rxinfo || np->rxopt.bits.rxoinfo)
Arnaldo Carvalho de Melo505cbfc2005-08-12 09:19:38 -03001533 np->mcast_oif = inet6_iif(opt_skb);
YOSHIFUJI Hideaki333fad52005-09-08 09:59:17 +09001534 if (np->rxopt.bits.rxhlim || np->rxopt.bits.rxohlim)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001535 np->mcast_hops = opt_skb->nh.ipv6h->hop_limit;
1536 if (ipv6_opt_accepted(sk, opt_skb)) {
1537 skb_set_owner_r(opt_skb, sk);
1538 opt_skb = xchg(&np->pktoptions, opt_skb);
1539 } else {
1540 __kfree_skb(opt_skb);
1541 opt_skb = xchg(&np->pktoptions, NULL);
1542 }
1543 }
1544
1545 if (opt_skb)
1546 kfree_skb(opt_skb);
1547 return 0;
1548}
1549
1550static int tcp_v6_rcv(struct sk_buff **pskb, unsigned int *nhoffp)
1551{
1552 struct sk_buff *skb = *pskb;
1553 struct tcphdr *th;
1554 struct sock *sk;
1555 int ret;
1556
1557 if (skb->pkt_type != PACKET_HOST)
1558 goto discard_it;
1559
1560 /*
1561 * Count it even if it's bad.
1562 */
1563 TCP_INC_STATS_BH(TCP_MIB_INSEGS);
1564
1565 if (!pskb_may_pull(skb, sizeof(struct tcphdr)))
1566 goto discard_it;
1567
1568 th = skb->h.th;
1569
1570 if (th->doff < sizeof(struct tcphdr)/4)
1571 goto bad_packet;
1572 if (!pskb_may_pull(skb, th->doff*4))
1573 goto discard_it;
1574
1575 if ((skb->ip_summed != CHECKSUM_UNNECESSARY &&
Herbert Xufb286bb2005-11-10 13:01:24 -08001576 tcp_v6_checksum_init(skb)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001577 goto bad_packet;
1578
1579 th = skb->h.th;
1580 TCP_SKB_CB(skb)->seq = ntohl(th->seq);
1581 TCP_SKB_CB(skb)->end_seq = (TCP_SKB_CB(skb)->seq + th->syn + th->fin +
1582 skb->len - th->doff*4);
1583 TCP_SKB_CB(skb)->ack_seq = ntohl(th->ack_seq);
1584 TCP_SKB_CB(skb)->when = 0;
1585 TCP_SKB_CB(skb)->flags = ipv6_get_dsfield(skb->nh.ipv6h);
1586 TCP_SKB_CB(skb)->sacked = 0;
1587
Arnaldo Carvalho de Melo505cbfc2005-08-12 09:19:38 -03001588 sk = __inet6_lookup(&tcp_hashinfo, &skb->nh.ipv6h->saddr, th->source,
1589 &skb->nh.ipv6h->daddr, ntohs(th->dest),
1590 inet6_iif(skb));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001591
1592 if (!sk)
1593 goto no_tcp_socket;
1594
1595process:
1596 if (sk->sk_state == TCP_TIME_WAIT)
1597 goto do_time_wait;
1598
1599 if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb))
1600 goto discard_and_relse;
1601
1602 if (sk_filter(sk, skb, 0))
1603 goto discard_and_relse;
1604
1605 skb->dev = NULL;
1606
1607 bh_lock_sock(sk);
1608 ret = 0;
1609 if (!sock_owned_by_user(sk)) {
1610 if (!tcp_prequeue(sk, skb))
1611 ret = tcp_v6_do_rcv(sk, skb);
1612 } else
1613 sk_add_backlog(sk, skb);
1614 bh_unlock_sock(sk);
1615
1616 sock_put(sk);
1617 return ret ? -1 : 0;
1618
1619no_tcp_socket:
1620 if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb))
1621 goto discard_it;
1622
1623 if (skb->len < (th->doff<<2) || tcp_checksum_complete(skb)) {
1624bad_packet:
1625 TCP_INC_STATS_BH(TCP_MIB_INERRS);
1626 } else {
1627 tcp_v6_send_reset(skb);
1628 }
1629
1630discard_it:
1631
1632 /*
1633 * Discard frame
1634 */
1635
1636 kfree_skb(skb);
1637 return 0;
1638
1639discard_and_relse:
1640 sock_put(sk);
1641 goto discard_it;
1642
1643do_time_wait:
1644 if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) {
Arnaldo Carvalho de Melo8feaf0c02005-08-09 20:09:30 -07001645 inet_twsk_put((struct inet_timewait_sock *)sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001646 goto discard_it;
1647 }
1648
1649 if (skb->len < (th->doff<<2) || tcp_checksum_complete(skb)) {
1650 TCP_INC_STATS_BH(TCP_MIB_INERRS);
Arnaldo Carvalho de Melo8feaf0c02005-08-09 20:09:30 -07001651 inet_twsk_put((struct inet_timewait_sock *)sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001652 goto discard_it;
1653 }
1654
Arnaldo Carvalho de Melo8feaf0c02005-08-09 20:09:30 -07001655 switch (tcp_timewait_state_process((struct inet_timewait_sock *)sk,
1656 skb, th)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001657 case TCP_TW_SYN:
1658 {
1659 struct sock *sk2;
1660
Arnaldo Carvalho de Melo505cbfc2005-08-12 09:19:38 -03001661 sk2 = inet6_lookup_listener(&tcp_hashinfo,
1662 &skb->nh.ipv6h->daddr,
1663 ntohs(th->dest), inet6_iif(skb));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001664 if (sk2 != NULL) {
Arnaldo Carvalho de Melo295ff7e2005-08-09 20:44:40 -07001665 struct inet_timewait_sock *tw = inet_twsk(sk);
1666 inet_twsk_deschedule(tw, &tcp_death_row);
1667 inet_twsk_put(tw);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001668 sk = sk2;
1669 goto process;
1670 }
1671 /* Fall through to ACK */
1672 }
1673 case TCP_TW_ACK:
1674 tcp_v6_timewait_ack(sk, skb);
1675 break;
1676 case TCP_TW_RST:
1677 goto no_tcp_socket;
1678 case TCP_TW_SUCCESS:;
1679 }
1680 goto discard_it;
1681}
1682
1683static int tcp_v6_rebuild_header(struct sock *sk)
1684{
1685 int err;
1686 struct dst_entry *dst;
1687 struct ipv6_pinfo *np = inet6_sk(sk);
1688
1689 dst = __sk_dst_check(sk, np->dst_cookie);
1690
1691 if (dst == NULL) {
1692 struct inet_sock *inet = inet_sk(sk);
1693 struct in6_addr *final_p = NULL, final;
1694 struct flowi fl;
1695
1696 memset(&fl, 0, sizeof(fl));
1697 fl.proto = IPPROTO_TCP;
1698 ipv6_addr_copy(&fl.fl6_dst, &np->daddr);
1699 ipv6_addr_copy(&fl.fl6_src, &np->saddr);
1700 fl.fl6_flowlabel = np->flow_label;
1701 fl.oif = sk->sk_bound_dev_if;
1702 fl.fl_ip_dport = inet->dport;
1703 fl.fl_ip_sport = inet->sport;
1704
1705 if (np->opt && np->opt->srcrt) {
1706 struct rt0_hdr *rt0 = (struct rt0_hdr *) np->opt->srcrt;
1707 ipv6_addr_copy(&final, &fl.fl6_dst);
1708 ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
1709 final_p = &final;
1710 }
1711
1712 err = ip6_dst_lookup(sk, &dst, &fl);
1713 if (err) {
1714 sk->sk_route_caps = 0;
1715 return err;
1716 }
1717 if (final_p)
1718 ipv6_addr_copy(&fl.fl6_dst, final_p);
1719
1720 if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) {
1721 sk->sk_err_soft = -err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001722 return err;
1723 }
1724
1725 ip6_dst_store(sk, dst, NULL);
1726 sk->sk_route_caps = dst->dev->features &
1727 ~(NETIF_F_IP_CSUM | NETIF_F_TSO);
1728 }
1729
1730 return 0;
1731}
1732
1733static int tcp_v6_xmit(struct sk_buff *skb, int ipfragok)
1734{
1735 struct sock *sk = skb->sk;
1736 struct inet_sock *inet = inet_sk(sk);
1737 struct ipv6_pinfo *np = inet6_sk(sk);
1738 struct flowi fl;
1739 struct dst_entry *dst;
1740 struct in6_addr *final_p = NULL, final;
1741
1742 memset(&fl, 0, sizeof(fl));
1743 fl.proto = IPPROTO_TCP;
1744 ipv6_addr_copy(&fl.fl6_dst, &np->daddr);
1745 ipv6_addr_copy(&fl.fl6_src, &np->saddr);
1746 fl.fl6_flowlabel = np->flow_label;
1747 IP6_ECN_flow_xmit(sk, fl.fl6_flowlabel);
1748 fl.oif = sk->sk_bound_dev_if;
1749 fl.fl_ip_sport = inet->sport;
1750 fl.fl_ip_dport = inet->dport;
1751
1752 if (np->opt && np->opt->srcrt) {
1753 struct rt0_hdr *rt0 = (struct rt0_hdr *) np->opt->srcrt;
1754 ipv6_addr_copy(&final, &fl.fl6_dst);
1755 ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
1756 final_p = &final;
1757 }
1758
1759 dst = __sk_dst_check(sk, np->dst_cookie);
1760
1761 if (dst == NULL) {
1762 int err = ip6_dst_lookup(sk, &dst, &fl);
1763
1764 if (err) {
1765 sk->sk_err_soft = -err;
1766 return err;
1767 }
1768
1769 if (final_p)
1770 ipv6_addr_copy(&fl.fl6_dst, final_p);
1771
1772 if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) {
1773 sk->sk_route_caps = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001774 return err;
1775 }
1776
1777 ip6_dst_store(sk, dst, NULL);
1778 sk->sk_route_caps = dst->dev->features &
1779 ~(NETIF_F_IP_CSUM | NETIF_F_TSO);
1780 }
1781
1782 skb->dst = dst_clone(dst);
1783
1784 /* Restore final destination back after routing done */
1785 ipv6_addr_copy(&fl.fl6_dst, &np->daddr);
1786
1787 return ip6_xmit(sk, skb, &fl, np->opt, 0);
1788}
1789
1790static void v6_addr2sockaddr(struct sock *sk, struct sockaddr * uaddr)
1791{
1792 struct ipv6_pinfo *np = inet6_sk(sk);
1793 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) uaddr;
1794
1795 sin6->sin6_family = AF_INET6;
1796 ipv6_addr_copy(&sin6->sin6_addr, &np->daddr);
1797 sin6->sin6_port = inet_sk(sk)->dport;
1798 /* We do not store received flowlabel for TCP */
1799 sin6->sin6_flowinfo = 0;
1800 sin6->sin6_scope_id = 0;
1801 if (sk->sk_bound_dev_if &&
1802 ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_LINKLOCAL)
1803 sin6->sin6_scope_id = sk->sk_bound_dev_if;
1804}
1805
1806static int tcp_v6_remember_stamp(struct sock *sk)
1807{
1808 /* Alas, not yet... */
1809 return 0;
1810}
1811
1812static struct tcp_func ipv6_specific = {
1813 .queue_xmit = tcp_v6_xmit,
1814 .send_check = tcp_v6_send_check,
1815 .rebuild_header = tcp_v6_rebuild_header,
1816 .conn_request = tcp_v6_conn_request,
1817 .syn_recv_sock = tcp_v6_syn_recv_sock,
1818 .remember_stamp = tcp_v6_remember_stamp,
1819 .net_header_len = sizeof(struct ipv6hdr),
1820
1821 .setsockopt = ipv6_setsockopt,
1822 .getsockopt = ipv6_getsockopt,
1823 .addr2sockaddr = v6_addr2sockaddr,
1824 .sockaddr_len = sizeof(struct sockaddr_in6)
1825};
1826
1827/*
1828 * TCP over IPv4 via INET6 API
1829 */
1830
1831static struct tcp_func ipv6_mapped = {
1832 .queue_xmit = ip_queue_xmit,
1833 .send_check = tcp_v4_send_check,
Arnaldo Carvalho de Melo32519f12005-08-09 19:50:02 -07001834 .rebuild_header = inet_sk_rebuild_header,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001835 .conn_request = tcp_v6_conn_request,
1836 .syn_recv_sock = tcp_v6_syn_recv_sock,
1837 .remember_stamp = tcp_v4_remember_stamp,
1838 .net_header_len = sizeof(struct iphdr),
1839
1840 .setsockopt = ipv6_setsockopt,
1841 .getsockopt = ipv6_getsockopt,
1842 .addr2sockaddr = v6_addr2sockaddr,
1843 .sockaddr_len = sizeof(struct sockaddr_in6)
1844};
1845
1846
1847
1848/* NOTE: A lot of things set to zero explicitly by call to
1849 * sk_alloc() so need not be done here.
1850 */
1851static int tcp_v6_init_sock(struct sock *sk)
1852{
Arnaldo Carvalho de Melo6687e982005-08-10 04:03:31 -03001853 struct inet_connection_sock *icsk = inet_csk(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001854 struct tcp_sock *tp = tcp_sk(sk);
1855
1856 skb_queue_head_init(&tp->out_of_order_queue);
1857 tcp_init_xmit_timers(sk);
1858 tcp_prequeue_init(tp);
1859
Arnaldo Carvalho de Melo6687e982005-08-10 04:03:31 -03001860 icsk->icsk_rto = TCP_TIMEOUT_INIT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001861 tp->mdev = TCP_TIMEOUT_INIT;
1862
1863 /* So many TCP implementations out there (incorrectly) count the
1864 * initial SYN frame in their delayed-ACK and congestion control
1865 * algorithms that we must have the following bandaid to talk
1866 * efficiently to them. -DaveM
1867 */
1868 tp->snd_cwnd = 2;
1869
1870 /* See draft-stevens-tcpca-spec-01 for discussion of the
1871 * initialization of these values.
1872 */
1873 tp->snd_ssthresh = 0x7fffffff;
1874 tp->snd_cwnd_clamp = ~0;
David S. Millerc1b4a7e2005-07-05 15:24:38 -07001875 tp->mss_cache = 536;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001876
1877 tp->reordering = sysctl_tcp_reordering;
1878
1879 sk->sk_state = TCP_CLOSE;
1880
1881 tp->af_specific = &ipv6_specific;
Arnaldo Carvalho de Melo6687e982005-08-10 04:03:31 -03001882 icsk->icsk_ca_ops = &tcp_init_congestion_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001883 sk->sk_write_space = sk_stream_write_space;
1884 sock_set_flag(sk, SOCK_USE_WRITE_QUEUE);
1885
1886 sk->sk_sndbuf = sysctl_tcp_wmem[1];
1887 sk->sk_rcvbuf = sysctl_tcp_rmem[1];
1888
1889 atomic_inc(&tcp_sockets_allocated);
1890
1891 return 0;
1892}
1893
1894static int tcp_v6_destroy_sock(struct sock *sk)
1895{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001896 tcp_v4_destroy_sock(sk);
1897 return inet6_destroy_sock(sk);
1898}
1899
1900/* Proc filesystem TCPv6 sock list dumping. */
1901static void get_openreq6(struct seq_file *seq,
Arnaldo Carvalho de Melo60236fd2005-06-18 22:47:21 -07001902 struct sock *sk, struct request_sock *req, int i, int uid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001903{
1904 struct in6_addr *dest, *src;
1905 int ttd = req->expires - jiffies;
1906
1907 if (ttd < 0)
1908 ttd = 0;
1909
Arnaldo Carvalho de Melo2e6599c2005-06-18 22:46:52 -07001910 src = &tcp6_rsk(req)->loc_addr;
1911 dest = &tcp6_rsk(req)->rmt_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001912 seq_printf(seq,
1913 "%4d: %08X%08X%08X%08X:%04X %08X%08X%08X%08X:%04X "
1914 "%02X %08X:%08X %02X:%08lX %08X %5d %8d %d %d %p\n",
1915 i,
1916 src->s6_addr32[0], src->s6_addr32[1],
1917 src->s6_addr32[2], src->s6_addr32[3],
1918 ntohs(inet_sk(sk)->sport),
1919 dest->s6_addr32[0], dest->s6_addr32[1],
1920 dest->s6_addr32[2], dest->s6_addr32[3],
Arnaldo Carvalho de Melo2e6599c2005-06-18 22:46:52 -07001921 ntohs(inet_rsk(req)->rmt_port),
Linus Torvalds1da177e2005-04-16 15:20:36 -07001922 TCP_SYN_RECV,
1923 0,0, /* could print option size, but that is af dependent. */
1924 1, /* timers active (only the expire timer) */
1925 jiffies_to_clock_t(ttd),
1926 req->retrans,
1927 uid,
1928 0, /* non standard timer */
1929 0, /* open_requests have no inode */
1930 0, req);
1931}
1932
1933static void get_tcp6_sock(struct seq_file *seq, struct sock *sp, int i)
1934{
1935 struct in6_addr *dest, *src;
1936 __u16 destp, srcp;
1937 int timer_active;
1938 unsigned long timer_expires;
1939 struct inet_sock *inet = inet_sk(sp);
1940 struct tcp_sock *tp = tcp_sk(sp);
Arnaldo Carvalho de Melo463c84b2005-08-09 20:10:42 -07001941 const struct inet_connection_sock *icsk = inet_csk(sp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001942 struct ipv6_pinfo *np = inet6_sk(sp);
1943
1944 dest = &np->daddr;
1945 src = &np->rcv_saddr;
1946 destp = ntohs(inet->dport);
1947 srcp = ntohs(inet->sport);
Arnaldo Carvalho de Melo463c84b2005-08-09 20:10:42 -07001948
1949 if (icsk->icsk_pending == ICSK_TIME_RETRANS) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001950 timer_active = 1;
Arnaldo Carvalho de Melo463c84b2005-08-09 20:10:42 -07001951 timer_expires = icsk->icsk_timeout;
1952 } else if (icsk->icsk_pending == ICSK_TIME_PROBE0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001953 timer_active = 4;
Arnaldo Carvalho de Melo463c84b2005-08-09 20:10:42 -07001954 timer_expires = icsk->icsk_timeout;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001955 } else if (timer_pending(&sp->sk_timer)) {
1956 timer_active = 2;
1957 timer_expires = sp->sk_timer.expires;
1958 } else {
1959 timer_active = 0;
1960 timer_expires = jiffies;
1961 }
1962
1963 seq_printf(seq,
1964 "%4d: %08X%08X%08X%08X:%04X %08X%08X%08X%08X:%04X "
1965 "%02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %p %u %u %u %u %d\n",
1966 i,
1967 src->s6_addr32[0], src->s6_addr32[1],
1968 src->s6_addr32[2], src->s6_addr32[3], srcp,
1969 dest->s6_addr32[0], dest->s6_addr32[1],
1970 dest->s6_addr32[2], dest->s6_addr32[3], destp,
1971 sp->sk_state,
1972 tp->write_seq-tp->snd_una, tp->rcv_nxt-tp->copied_seq,
1973 timer_active,
1974 jiffies_to_clock_t(timer_expires - jiffies),
Arnaldo Carvalho de Melo463c84b2005-08-09 20:10:42 -07001975 icsk->icsk_retransmits,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001976 sock_i_uid(sp),
Arnaldo Carvalho de Melo6687e982005-08-10 04:03:31 -03001977 icsk->icsk_probes_out,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001978 sock_i_ino(sp),
1979 atomic_read(&sp->sk_refcnt), sp,
Arnaldo Carvalho de Melo463c84b2005-08-09 20:10:42 -07001980 icsk->icsk_rto,
1981 icsk->icsk_ack.ato,
1982 (icsk->icsk_ack.quick << 1 ) | icsk->icsk_ack.pingpong,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001983 tp->snd_cwnd, tp->snd_ssthresh>=0xFFFF?-1:tp->snd_ssthresh
1984 );
1985}
1986
1987static void get_timewait6_sock(struct seq_file *seq,
Arnaldo Carvalho de Melo8feaf0c02005-08-09 20:09:30 -07001988 struct inet_timewait_sock *tw, int i)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001989{
1990 struct in6_addr *dest, *src;
1991 __u16 destp, srcp;
Arnaldo Carvalho de Melo8feaf0c02005-08-09 20:09:30 -07001992 struct tcp6_timewait_sock *tcp6tw = tcp6_twsk((struct sock *)tw);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001993 int ttd = tw->tw_ttd - jiffies;
1994
1995 if (ttd < 0)
1996 ttd = 0;
1997
Arnaldo Carvalho de Melo8feaf0c02005-08-09 20:09:30 -07001998 dest = &tcp6tw->tw_v6_daddr;
1999 src = &tcp6tw->tw_v6_rcv_saddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002000 destp = ntohs(tw->tw_dport);
2001 srcp = ntohs(tw->tw_sport);
2002
2003 seq_printf(seq,
2004 "%4d: %08X%08X%08X%08X:%04X %08X%08X%08X%08X:%04X "
2005 "%02X %08X:%08X %02X:%08lX %08X %5d %8d %d %d %p\n",
2006 i,
2007 src->s6_addr32[0], src->s6_addr32[1],
2008 src->s6_addr32[2], src->s6_addr32[3], srcp,
2009 dest->s6_addr32[0], dest->s6_addr32[1],
2010 dest->s6_addr32[2], dest->s6_addr32[3], destp,
2011 tw->tw_substate, 0, 0,
2012 3, jiffies_to_clock_t(ttd), 0, 0, 0, 0,
2013 atomic_read(&tw->tw_refcnt), tw);
2014}
2015
2016#ifdef CONFIG_PROC_FS
2017static int tcp6_seq_show(struct seq_file *seq, void *v)
2018{
2019 struct tcp_iter_state *st;
2020
2021 if (v == SEQ_START_TOKEN) {
2022 seq_puts(seq,
2023 " sl "
2024 "local_address "
2025 "remote_address "
2026 "st tx_queue rx_queue tr tm->when retrnsmt"
2027 " uid timeout inode\n");
2028 goto out;
2029 }
2030 st = seq->private;
2031
2032 switch (st->state) {
2033 case TCP_SEQ_STATE_LISTENING:
2034 case TCP_SEQ_STATE_ESTABLISHED:
2035 get_tcp6_sock(seq, v, st->num);
2036 break;
2037 case TCP_SEQ_STATE_OPENREQ:
2038 get_openreq6(seq, st->syn_wait_sk, v, st->num, st->uid);
2039 break;
2040 case TCP_SEQ_STATE_TIME_WAIT:
2041 get_timewait6_sock(seq, v, st->num);
2042 break;
2043 }
2044out:
2045 return 0;
2046}
2047
2048static struct file_operations tcp6_seq_fops;
2049static struct tcp_seq_afinfo tcp6_seq_afinfo = {
2050 .owner = THIS_MODULE,
2051 .name = "tcp6",
2052 .family = AF_INET6,
2053 .seq_show = tcp6_seq_show,
2054 .seq_fops = &tcp6_seq_fops,
2055};
2056
2057int __init tcp6_proc_init(void)
2058{
2059 return tcp_proc_register(&tcp6_seq_afinfo);
2060}
2061
2062void tcp6_proc_exit(void)
2063{
2064 tcp_proc_unregister(&tcp6_seq_afinfo);
2065}
2066#endif
2067
2068struct proto tcpv6_prot = {
2069 .name = "TCPv6",
2070 .owner = THIS_MODULE,
2071 .close = tcp_close,
2072 .connect = tcp_v6_connect,
2073 .disconnect = tcp_disconnect,
Arnaldo Carvalho de Melo463c84b2005-08-09 20:10:42 -07002074 .accept = inet_csk_accept,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002075 .ioctl = tcp_ioctl,
2076 .init = tcp_v6_init_sock,
2077 .destroy = tcp_v6_destroy_sock,
2078 .shutdown = tcp_shutdown,
2079 .setsockopt = tcp_setsockopt,
2080 .getsockopt = tcp_getsockopt,
2081 .sendmsg = tcp_sendmsg,
2082 .recvmsg = tcp_recvmsg,
2083 .backlog_rcv = tcp_v6_do_rcv,
2084 .hash = tcp_v6_hash,
2085 .unhash = tcp_unhash,
2086 .get_port = tcp_v6_get_port,
2087 .enter_memory_pressure = tcp_enter_memory_pressure,
2088 .sockets_allocated = &tcp_sockets_allocated,
2089 .memory_allocated = &tcp_memory_allocated,
2090 .memory_pressure = &tcp_memory_pressure,
Arnaldo Carvalho de Melo0a5578c2005-08-09 20:11:41 -07002091 .orphan_count = &tcp_orphan_count,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002092 .sysctl_mem = sysctl_tcp_mem,
2093 .sysctl_wmem = sysctl_tcp_wmem,
2094 .sysctl_rmem = sysctl_tcp_rmem,
2095 .max_header = MAX_TCP_HEADER,
2096 .obj_size = sizeof(struct tcp6_sock),
Arnaldo Carvalho de Melo8feaf0c02005-08-09 20:09:30 -07002097 .twsk_obj_size = sizeof(struct tcp6_timewait_sock),
Arnaldo Carvalho de Melo60236fd2005-06-18 22:47:21 -07002098 .rsk_prot = &tcp6_request_sock_ops,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002099};
2100
2101static struct inet6_protocol tcpv6_protocol = {
2102 .handler = tcp_v6_rcv,
2103 .err_handler = tcp_v6_err,
2104 .flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL,
2105};
2106
Linus Torvalds1da177e2005-04-16 15:20:36 -07002107static struct inet_protosw tcpv6_protosw = {
2108 .type = SOCK_STREAM,
2109 .protocol = IPPROTO_TCP,
2110 .prot = &tcpv6_prot,
2111 .ops = &inet6_stream_ops,
2112 .capability = -1,
2113 .no_check = 0,
2114 .flags = INET_PROTOSW_PERMANENT,
2115};
2116
2117void __init tcpv6_init(void)
2118{
2119 /* register inet6 protocol */
2120 if (inet6_add_protocol(&tcpv6_protocol, IPPROTO_TCP) < 0)
2121 printk(KERN_ERR "tcpv6_init: Could not register protocol\n");
2122 inet6_register_protosw(&tcpv6_protosw);
2123}