blob: 246414b27d0e37bcdf3b53ddb502899f0bdb1958 [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;
117 int rover;
118
Arnaldo Carvalho de Melo6e04e022005-08-09 20:07:35 -0700119 spin_lock(&tcp_hashinfo.portalloc_lock);
120 if (tcp_hashinfo.port_rover < low)
Folkert van Heusdenc3924c702005-05-03 14:36:45 -0700121 rover = low;
122 else
Arnaldo Carvalho de Melo6e04e022005-08-09 20:07:35 -0700123 rover = tcp_hashinfo.port_rover;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700124 do { rover++;
Folkert van Heusdenc3924c702005-05-03 14:36:45 -0700125 if (rover > high)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700126 rover = low;
Arnaldo Carvalho de Melo6e04e022005-08-09 20:07:35 -0700127 head = &tcp_hashinfo.bhash[inet_bhashfn(rover, tcp_hashinfo.bhash_size)];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700128 spin_lock(&head->lock);
Arnaldo Carvalho de Melo0f7ff922005-08-09 19:59:44 -0700129 inet_bind_bucket_for_each(tb, node, &head->chain)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700130 if (tb->port == rover)
131 goto next;
132 break;
133 next:
134 spin_unlock(&head->lock);
135 } while (--remaining > 0);
Arnaldo Carvalho de Melo6e04e022005-08-09 20:07:35 -0700136 tcp_hashinfo.port_rover = rover;
137 spin_unlock(&tcp_hashinfo.portalloc_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700138
David S. Millerd5d28372005-08-23 10:49:54 -0700139 /* Exhausted local port range during search? It is not
140 * possible for us to be holding one of the bind hash
141 * locks if this test triggers, because if 'remaining'
142 * drops to zero, we broke out of the do/while loop at
143 * the top level, not from the 'break;' statement.
144 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700145 ret = 1;
David S. Millerd5d28372005-08-23 10:49:54 -0700146 if (unlikely(remaining <= 0))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700147 goto fail;
148
149 /* OK, here is the one we will use. */
150 snum = rover;
151 } else {
Arnaldo Carvalho de Melo6e04e022005-08-09 20:07:35 -0700152 head = &tcp_hashinfo.bhash[inet_bhashfn(snum, tcp_hashinfo.bhash_size)];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700153 spin_lock(&head->lock);
Arnaldo Carvalho de Melo0f7ff922005-08-09 19:59:44 -0700154 inet_bind_bucket_for_each(tb, node, &head->chain)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700155 if (tb->port == snum)
156 goto tb_found;
157 }
158 tb = NULL;
159 goto tb_not_found;
160tb_found:
161 if (tb && !hlist_empty(&tb->owners)) {
162 if (tb->fastreuse > 0 && sk->sk_reuse &&
163 sk->sk_state != TCP_LISTEN) {
164 goto success;
165 } else {
166 ret = 1;
167 if (tcp_v6_bind_conflict(sk, tb))
168 goto fail_unlock;
169 }
170 }
171tb_not_found:
172 ret = 1;
Arnaldo Carvalho de Melo6e04e022005-08-09 20:07:35 -0700173 if (tb == NULL) {
174 tb = inet_bind_bucket_create(tcp_hashinfo.bind_bucket_cachep, head, snum);
175 if (tb == NULL)
176 goto fail_unlock;
177 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700178 if (hlist_empty(&tb->owners)) {
179 if (sk->sk_reuse && sk->sk_state != TCP_LISTEN)
180 tb->fastreuse = 1;
181 else
182 tb->fastreuse = 0;
183 } else if (tb->fastreuse &&
184 (!sk->sk_reuse || sk->sk_state == TCP_LISTEN))
185 tb->fastreuse = 0;
186
187success:
Arnaldo Carvalho de Melo463c84b2005-08-09 20:10:42 -0700188 if (!inet_csk(sk)->icsk_bind_hash)
Arnaldo Carvalho de Melo2d8c4ce2005-08-09 20:07:13 -0700189 inet_bind_hash(sk, tb, snum);
Arnaldo Carvalho de Melo463c84b2005-08-09 20:10:42 -0700190 BUG_TRAP(inet_csk(sk)->icsk_bind_hash == tb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700191 ret = 0;
192
193fail_unlock:
194 spin_unlock(&head->lock);
195fail:
196 local_bh_enable();
197 return ret;
198}
199
200static __inline__ void __tcp_v6_hash(struct sock *sk)
201{
202 struct hlist_head *list;
203 rwlock_t *lock;
204
205 BUG_TRAP(sk_unhashed(sk));
206
207 if (sk->sk_state == TCP_LISTEN) {
Arnaldo Carvalho de Melo6e04e022005-08-09 20:07:35 -0700208 list = &tcp_hashinfo.listening_hash[inet_sk_listen_hashfn(sk)];
209 lock = &tcp_hashinfo.lhash_lock;
Arnaldo Carvalho de Melof3f05f72005-08-09 20:08:09 -0700210 inet_listen_wlock(&tcp_hashinfo);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700211 } else {
Arnaldo Carvalho de Melo505cbfc2005-08-12 09:19:38 -0300212 sk->sk_hashent = inet6_sk_ehashfn(sk, tcp_hashinfo.ehash_size);
Arnaldo Carvalho de Melo6e04e022005-08-09 20:07:35 -0700213 list = &tcp_hashinfo.ehash[sk->sk_hashent].chain;
214 lock = &tcp_hashinfo.ehash[sk->sk_hashent].lock;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700215 write_lock(lock);
216 }
217
218 __sk_add_node(sk, list);
219 sock_prot_inc_use(sk->sk_prot);
220 write_unlock(lock);
221}
222
223
224static void tcp_v6_hash(struct sock *sk)
225{
226 if (sk->sk_state != TCP_CLOSE) {
227 struct tcp_sock *tp = tcp_sk(sk);
228
229 if (tp->af_specific == &ipv6_mapped) {
230 tcp_prot.hash(sk);
231 return;
232 }
233 local_bh_disable();
234 __tcp_v6_hash(sk);
235 local_bh_enable();
236 }
237}
238
Linus Torvalds1da177e2005-04-16 15:20:36 -0700239/*
240 * Open request hash tables.
241 */
242
Arnaldo Carvalho de Melo463c84b2005-08-09 20:10:42 -0700243static u32 tcp_v6_synq_hash(const struct in6_addr *raddr, const u16 rport, const u32 rnd)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700244{
245 u32 a, b, c;
246
247 a = raddr->s6_addr32[0];
248 b = raddr->s6_addr32[1];
249 c = raddr->s6_addr32[2];
250
251 a += JHASH_GOLDEN_RATIO;
252 b += JHASH_GOLDEN_RATIO;
253 c += rnd;
254 __jhash_mix(a, b, c);
255
256 a += raddr->s6_addr32[3];
257 b += (u32) rport;
258 __jhash_mix(a, b, c);
259
260 return c & (TCP_SYNQ_HSIZE - 1);
261}
262
Arnaldo Carvalho de Melo463c84b2005-08-09 20:10:42 -0700263static struct request_sock *tcp_v6_search_req(const struct sock *sk,
Arnaldo Carvalho de Melo60236fd2005-06-18 22:47:21 -0700264 struct request_sock ***prevp,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700265 __u16 rport,
266 struct in6_addr *raddr,
267 struct in6_addr *laddr,
268 int iif)
269{
Arnaldo Carvalho de Melo463c84b2005-08-09 20:10:42 -0700270 const struct inet_connection_sock *icsk = inet_csk(sk);
271 struct listen_sock *lopt = icsk->icsk_accept_queue.listen_opt;
Arnaldo Carvalho de Melo60236fd2005-06-18 22:47:21 -0700272 struct request_sock *req, **prev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700273
274 for (prev = &lopt->syn_table[tcp_v6_synq_hash(raddr, rport, lopt->hash_rnd)];
275 (req = *prev) != NULL;
276 prev = &req->dl_next) {
Arnaldo Carvalho de Melo2e6599c2005-06-18 22:46:52 -0700277 const struct tcp6_request_sock *treq = tcp6_rsk(req);
278
279 if (inet_rsk(req)->rmt_port == rport &&
Arnaldo Carvalho de Melo60236fd2005-06-18 22:47:21 -0700280 req->rsk_ops->family == AF_INET6 &&
Arnaldo Carvalho de Melo2e6599c2005-06-18 22:46:52 -0700281 ipv6_addr_equal(&treq->rmt_addr, raddr) &&
282 ipv6_addr_equal(&treq->loc_addr, laddr) &&
283 (!treq->iif || treq->iif == iif)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700284 BUG_TRAP(req->sk == NULL);
285 *prevp = prev;
286 return req;
287 }
288 }
289
290 return NULL;
291}
292
293static __inline__ u16 tcp_v6_check(struct tcphdr *th, int len,
294 struct in6_addr *saddr,
295 struct in6_addr *daddr,
296 unsigned long base)
297{
298 return csum_ipv6_magic(saddr, daddr, len, IPPROTO_TCP, base);
299}
300
301static __u32 tcp_v6_init_sequence(struct sock *sk, struct sk_buff *skb)
302{
303 if (skb->protocol == htons(ETH_P_IPV6)) {
304 return secure_tcpv6_sequence_number(skb->nh.ipv6h->daddr.s6_addr32,
305 skb->nh.ipv6h->saddr.s6_addr32,
306 skb->h.th->dest,
307 skb->h.th->source);
308 } else {
309 return secure_tcp_sequence_number(skb->nh.iph->daddr,
310 skb->nh.iph->saddr,
311 skb->h.th->dest,
312 skb->h.th->source);
313 }
314}
315
Arnaldo Carvalho de Melo505cbfc2005-08-12 09:19:38 -0300316static int __tcp_v6_check_established(struct sock *sk, const __u16 lport,
Arnaldo Carvalho de Melo8feaf0c02005-08-09 20:09:30 -0700317 struct inet_timewait_sock **twp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700318{
319 struct inet_sock *inet = inet_sk(sk);
Arnaldo Carvalho de Melo505cbfc2005-08-12 09:19:38 -0300320 const struct ipv6_pinfo *np = inet6_sk(sk);
321 const struct in6_addr *daddr = &np->rcv_saddr;
322 const struct in6_addr *saddr = &np->daddr;
323 const int dif = sk->sk_bound_dev_if;
Arnaldo Carvalho de Melo8feaf0c02005-08-09 20:09:30 -0700324 const u32 ports = INET_COMBINED_PORTS(inet->dport, lport);
Arnaldo Carvalho de Melo505cbfc2005-08-12 09:19:38 -0300325 const int hash = inet6_ehashfn(daddr, inet->num, saddr, inet->dport,
326 tcp_hashinfo.ehash_size);
Arnaldo Carvalho de Melo6e04e022005-08-09 20:07:35 -0700327 struct inet_ehash_bucket *head = &tcp_hashinfo.ehash[hash];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700328 struct sock *sk2;
Arnaldo Carvalho de Melo8feaf0c02005-08-09 20:09:30 -0700329 const struct hlist_node *node;
330 struct inet_timewait_sock *tw;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700331
332 write_lock(&head->lock);
333
334 /* Check TIME-WAIT sockets first. */
Arnaldo Carvalho de Melo6e04e022005-08-09 20:07:35 -0700335 sk_for_each(sk2, node, &(head + tcp_hashinfo.ehash_size)->chain) {
Arnaldo Carvalho de Melo8feaf0c02005-08-09 20:09:30 -0700336 const struct tcp6_timewait_sock *tcp6tw = tcp6_twsk(sk2);
337
338 tw = inet_twsk(sk2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700339
340 if(*((__u32 *)&(tw->tw_dport)) == ports &&
341 sk2->sk_family == PF_INET6 &&
Arnaldo Carvalho de Melo8feaf0c02005-08-09 20:09:30 -0700342 ipv6_addr_equal(&tcp6tw->tw_v6_daddr, saddr) &&
343 ipv6_addr_equal(&tcp6tw->tw_v6_rcv_saddr, daddr) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -0700344 sk2->sk_bound_dev_if == sk->sk_bound_dev_if) {
Arnaldo Carvalho de Melo8feaf0c02005-08-09 20:09:30 -0700345 const struct tcp_timewait_sock *tcptw = tcp_twsk(sk2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700346 struct tcp_sock *tp = tcp_sk(sk);
347
Arnaldo Carvalho de Melo8feaf0c02005-08-09 20:09:30 -0700348 if (tcptw->tw_ts_recent_stamp &&
349 (!twp ||
350 (sysctl_tcp_tw_reuse &&
351 xtime.tv_sec - tcptw->tw_ts_recent_stamp > 1))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700352 /* See comment in tcp_ipv4.c */
Arnaldo Carvalho de Melo8feaf0c02005-08-09 20:09:30 -0700353 tp->write_seq = tcptw->tw_snd_nxt + 65535 + 2;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700354 if (!tp->write_seq)
355 tp->write_seq = 1;
Arnaldo Carvalho de Melo8feaf0c02005-08-09 20:09:30 -0700356 tp->rx_opt.ts_recent = tcptw->tw_ts_recent;
357 tp->rx_opt.ts_recent_stamp = tcptw->tw_ts_recent_stamp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700358 sock_hold(sk2);
359 goto unique;
360 } else
361 goto not_unique;
362 }
363 }
364 tw = NULL;
365
366 /* And established part... */
367 sk_for_each(sk2, node, &head->chain) {
Arnaldo Carvalho de Melo8feaf0c02005-08-09 20:09:30 -0700368 if (INET6_MATCH(sk2, saddr, daddr, ports, dif))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700369 goto not_unique;
370 }
371
372unique:
373 BUG_TRAP(sk_unhashed(sk));
374 __sk_add_node(sk, &head->chain);
375 sk->sk_hashent = hash;
376 sock_prot_inc_use(sk->sk_prot);
377 write_unlock(&head->lock);
378
379 if (twp) {
380 *twp = tw;
381 NET_INC_STATS_BH(LINUX_MIB_TIMEWAITRECYCLED);
382 } else if (tw) {
383 /* Silly. Should hash-dance instead... */
Arnaldo Carvalho de Melo295ff7e2005-08-09 20:44:40 -0700384 inet_twsk_deschedule(tw, &tcp_death_row);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700385 NET_INC_STATS_BH(LINUX_MIB_TIMEWAITRECYCLED);
386
Arnaldo Carvalho de Melo8feaf0c02005-08-09 20:09:30 -0700387 inet_twsk_put(tw);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700388 }
389 return 0;
390
391not_unique:
392 write_unlock(&head->lock);
393 return -EADDRNOTAVAIL;
394}
395
396static inline u32 tcpv6_port_offset(const struct sock *sk)
397{
398 const struct inet_sock *inet = inet_sk(sk);
399 const struct ipv6_pinfo *np = inet6_sk(sk);
400
401 return secure_tcpv6_port_ephemeral(np->rcv_saddr.s6_addr32,
402 np->daddr.s6_addr32,
403 inet->dport);
404}
405
406static int tcp_v6_hash_connect(struct sock *sk)
407{
408 unsigned short snum = inet_sk(sk)->num;
Arnaldo Carvalho de Melo0f7ff922005-08-09 19:59:44 -0700409 struct inet_bind_hashbucket *head;
410 struct inet_bind_bucket *tb;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700411 int ret;
412
413 if (!snum) {
414 int low = sysctl_local_port_range[0];
415 int high = sysctl_local_port_range[1];
416 int range = high - low;
417 int i;
418 int port;
419 static u32 hint;
420 u32 offset = hint + tcpv6_port_offset(sk);
421 struct hlist_node *node;
Arnaldo Carvalho de Melo8feaf0c02005-08-09 20:09:30 -0700422 struct inet_timewait_sock *tw = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700423
424 local_bh_disable();
425 for (i = 1; i <= range; i++) {
426 port = low + (i + offset) % range;
Arnaldo Carvalho de Melo6e04e022005-08-09 20:07:35 -0700427 head = &tcp_hashinfo.bhash[inet_bhashfn(port, tcp_hashinfo.bhash_size)];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700428 spin_lock(&head->lock);
429
430 /* Does not bother with rcv_saddr checks,
431 * because the established check is already
432 * unique enough.
433 */
Arnaldo Carvalho de Melo0f7ff922005-08-09 19:59:44 -0700434 inet_bind_bucket_for_each(tb, node, &head->chain) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700435 if (tb->port == port) {
436 BUG_TRAP(!hlist_empty(&tb->owners));
437 if (tb->fastreuse >= 0)
438 goto next_port;
439 if (!__tcp_v6_check_established(sk,
440 port,
441 &tw))
442 goto ok;
443 goto next_port;
444 }
445 }
446
Arnaldo Carvalho de Melo6e04e022005-08-09 20:07:35 -0700447 tb = inet_bind_bucket_create(tcp_hashinfo.bind_bucket_cachep, head, port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700448 if (!tb) {
449 spin_unlock(&head->lock);
450 break;
451 }
452 tb->fastreuse = -1;
453 goto ok;
454
455 next_port:
456 spin_unlock(&head->lock);
457 }
458 local_bh_enable();
459
460 return -EADDRNOTAVAIL;
461
462ok:
463 hint += i;
464
465 /* Head lock still held and bh's disabled */
Arnaldo Carvalho de Melo2d8c4ce2005-08-09 20:07:13 -0700466 inet_bind_hash(sk, tb, port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700467 if (sk_unhashed(sk)) {
468 inet_sk(sk)->sport = htons(port);
469 __tcp_v6_hash(sk);
470 }
471 spin_unlock(&head->lock);
472
473 if (tw) {
Arnaldo Carvalho de Melo295ff7e2005-08-09 20:44:40 -0700474 inet_twsk_deschedule(tw, &tcp_death_row);
Arnaldo Carvalho de Melo8feaf0c02005-08-09 20:09:30 -0700475 inet_twsk_put(tw);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700476 }
477
478 ret = 0;
479 goto out;
480 }
481
Arnaldo Carvalho de Melo6e04e022005-08-09 20:07:35 -0700482 head = &tcp_hashinfo.bhash[inet_bhashfn(snum, tcp_hashinfo.bhash_size)];
Arnaldo Carvalho de Melo463c84b2005-08-09 20:10:42 -0700483 tb = inet_csk(sk)->icsk_bind_hash;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700484 spin_lock_bh(&head->lock);
485
486 if (sk_head(&tb->owners) == sk && !sk->sk_bind_node.next) {
487 __tcp_v6_hash(sk);
488 spin_unlock_bh(&head->lock);
489 return 0;
490 } else {
491 spin_unlock(&head->lock);
492 /* No definite answer... Walk to established hash table */
493 ret = __tcp_v6_check_established(sk, snum, NULL);
494out:
495 local_bh_enable();
496 return ret;
497 }
498}
499
Linus Torvalds1da177e2005-04-16 15:20:36 -0700500static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
501 int addr_len)
502{
503 struct sockaddr_in6 *usin = (struct sockaddr_in6 *) uaddr;
504 struct inet_sock *inet = inet_sk(sk);
505 struct ipv6_pinfo *np = inet6_sk(sk);
506 struct tcp_sock *tp = tcp_sk(sk);
507 struct in6_addr *saddr = NULL, *final_p = NULL, final;
508 struct flowi fl;
509 struct dst_entry *dst;
510 int addr_type;
511 int err;
512
513 if (addr_len < SIN6_LEN_RFC2133)
514 return -EINVAL;
515
516 if (usin->sin6_family != AF_INET6)
517 return(-EAFNOSUPPORT);
518
519 memset(&fl, 0, sizeof(fl));
520
521 if (np->sndflow) {
522 fl.fl6_flowlabel = usin->sin6_flowinfo&IPV6_FLOWINFO_MASK;
523 IP6_ECN_flow_init(fl.fl6_flowlabel);
524 if (fl.fl6_flowlabel&IPV6_FLOWLABEL_MASK) {
525 struct ip6_flowlabel *flowlabel;
526 flowlabel = fl6_sock_lookup(sk, fl.fl6_flowlabel);
527 if (flowlabel == NULL)
528 return -EINVAL;
529 ipv6_addr_copy(&usin->sin6_addr, &flowlabel->dst);
530 fl6_sock_release(flowlabel);
531 }
532 }
533
534 /*
535 * connect() to INADDR_ANY means loopback (BSD'ism).
536 */
537
538 if(ipv6_addr_any(&usin->sin6_addr))
539 usin->sin6_addr.s6_addr[15] = 0x1;
540
541 addr_type = ipv6_addr_type(&usin->sin6_addr);
542
543 if(addr_type & IPV6_ADDR_MULTICAST)
544 return -ENETUNREACH;
545
546 if (addr_type&IPV6_ADDR_LINKLOCAL) {
547 if (addr_len >= sizeof(struct sockaddr_in6) &&
548 usin->sin6_scope_id) {
549 /* If interface is set while binding, indices
550 * must coincide.
551 */
552 if (sk->sk_bound_dev_if &&
553 sk->sk_bound_dev_if != usin->sin6_scope_id)
554 return -EINVAL;
555
556 sk->sk_bound_dev_if = usin->sin6_scope_id;
557 }
558
559 /* Connect to link-local address requires an interface */
560 if (!sk->sk_bound_dev_if)
561 return -EINVAL;
562 }
563
564 if (tp->rx_opt.ts_recent_stamp &&
565 !ipv6_addr_equal(&np->daddr, &usin->sin6_addr)) {
566 tp->rx_opt.ts_recent = 0;
567 tp->rx_opt.ts_recent_stamp = 0;
568 tp->write_seq = 0;
569 }
570
571 ipv6_addr_copy(&np->daddr, &usin->sin6_addr);
572 np->flow_label = fl.fl6_flowlabel;
573
574 /*
575 * TCP over IPv4
576 */
577
578 if (addr_type == IPV6_ADDR_MAPPED) {
579 u32 exthdrlen = tp->ext_header_len;
580 struct sockaddr_in sin;
581
582 SOCK_DEBUG(sk, "connect: ipv4 mapped\n");
583
584 if (__ipv6_only_sock(sk))
585 return -ENETUNREACH;
586
587 sin.sin_family = AF_INET;
588 sin.sin_port = usin->sin6_port;
589 sin.sin_addr.s_addr = usin->sin6_addr.s6_addr32[3];
590
591 tp->af_specific = &ipv6_mapped;
592 sk->sk_backlog_rcv = tcp_v4_do_rcv;
593
594 err = tcp_v4_connect(sk, (struct sockaddr *)&sin, sizeof(sin));
595
596 if (err) {
597 tp->ext_header_len = exthdrlen;
598 tp->af_specific = &ipv6_specific;
599 sk->sk_backlog_rcv = tcp_v6_do_rcv;
600 goto failure;
601 } else {
602 ipv6_addr_set(&np->saddr, 0, 0, htonl(0x0000FFFF),
603 inet->saddr);
604 ipv6_addr_set(&np->rcv_saddr, 0, 0, htonl(0x0000FFFF),
605 inet->rcv_saddr);
606 }
607
608 return err;
609 }
610
611 if (!ipv6_addr_any(&np->rcv_saddr))
612 saddr = &np->rcv_saddr;
613
614 fl.proto = IPPROTO_TCP;
615 ipv6_addr_copy(&fl.fl6_dst, &np->daddr);
616 ipv6_addr_copy(&fl.fl6_src,
617 (saddr ? saddr : &np->saddr));
618 fl.oif = sk->sk_bound_dev_if;
619 fl.fl_ip_dport = usin->sin6_port;
620 fl.fl_ip_sport = inet->sport;
621
622 if (np->opt && np->opt->srcrt) {
623 struct rt0_hdr *rt0 = (struct rt0_hdr *)np->opt->srcrt;
624 ipv6_addr_copy(&final, &fl.fl6_dst);
625 ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
626 final_p = &final;
627 }
628
629 err = ip6_dst_lookup(sk, &dst, &fl);
630 if (err)
631 goto failure;
632 if (final_p)
633 ipv6_addr_copy(&fl.fl6_dst, final_p);
634
635 if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) {
636 dst_release(dst);
637 goto failure;
638 }
639
640 if (saddr == NULL) {
641 saddr = &fl.fl6_src;
642 ipv6_addr_copy(&np->rcv_saddr, saddr);
643 }
644
645 /* set the source address */
646 ipv6_addr_copy(&np->saddr, saddr);
647 inet->rcv_saddr = LOOPBACK4_IPV6;
648
649 ip6_dst_store(sk, dst, NULL);
650 sk->sk_route_caps = dst->dev->features &
651 ~(NETIF_F_IP_CSUM | NETIF_F_TSO);
652
653 tp->ext_header_len = 0;
654 if (np->opt)
655 tp->ext_header_len = np->opt->opt_flen + np->opt->opt_nflen;
656
657 tp->rx_opt.mss_clamp = IPV6_MIN_MTU - sizeof(struct tcphdr) - sizeof(struct ipv6hdr);
658
659 inet->dport = usin->sin6_port;
660
661 tcp_set_state(sk, TCP_SYN_SENT);
662 err = tcp_v6_hash_connect(sk);
663 if (err)
664 goto late_failure;
665
666 if (!tp->write_seq)
667 tp->write_seq = secure_tcpv6_sequence_number(np->saddr.s6_addr32,
668 np->daddr.s6_addr32,
669 inet->sport,
670 inet->dport);
671
672 err = tcp_connect(sk);
673 if (err)
674 goto late_failure;
675
676 return 0;
677
678late_failure:
679 tcp_set_state(sk, TCP_CLOSE);
680 __sk_dst_reset(sk);
681failure:
682 inet->dport = 0;
683 sk->sk_route_caps = 0;
684 return err;
685}
686
687static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
688 int type, int code, int offset, __u32 info)
689{
690 struct ipv6hdr *hdr = (struct ipv6hdr*)skb->data;
Arnaldo Carvalho de Melo505cbfc2005-08-12 09:19:38 -0300691 const struct tcphdr *th = (struct tcphdr *)(skb->data+offset);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700692 struct ipv6_pinfo *np;
693 struct sock *sk;
694 int err;
695 struct tcp_sock *tp;
696 __u32 seq;
697
Arnaldo Carvalho de Melo505cbfc2005-08-12 09:19:38 -0300698 sk = inet6_lookup(&tcp_hashinfo, &hdr->daddr, th->dest, &hdr->saddr,
699 th->source, skb->dev->ifindex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700700
701 if (sk == NULL) {
702 ICMP6_INC_STATS_BH(__in6_dev_get(skb->dev), ICMP6_MIB_INERRORS);
703 return;
704 }
705
706 if (sk->sk_state == TCP_TIME_WAIT) {
Arnaldo Carvalho de Melo8feaf0c02005-08-09 20:09:30 -0700707 inet_twsk_put((struct inet_timewait_sock *)sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700708 return;
709 }
710
711 bh_lock_sock(sk);
712 if (sock_owned_by_user(sk))
713 NET_INC_STATS_BH(LINUX_MIB_LOCKDROPPEDICMPS);
714
715 if (sk->sk_state == TCP_CLOSE)
716 goto out;
717
718 tp = tcp_sk(sk);
719 seq = ntohl(th->seq);
720 if (sk->sk_state != TCP_LISTEN &&
721 !between(seq, tp->snd_una, tp->snd_nxt)) {
722 NET_INC_STATS_BH(LINUX_MIB_OUTOFWINDOWICMPS);
723 goto out;
724 }
725
726 np = inet6_sk(sk);
727
728 if (type == ICMPV6_PKT_TOOBIG) {
729 struct dst_entry *dst = NULL;
730
731 if (sock_owned_by_user(sk))
732 goto out;
733 if ((1 << sk->sk_state) & (TCPF_LISTEN | TCPF_CLOSE))
734 goto out;
735
736 /* icmp should have updated the destination cache entry */
737 dst = __sk_dst_check(sk, np->dst_cookie);
738
739 if (dst == NULL) {
740 struct inet_sock *inet = inet_sk(sk);
741 struct flowi fl;
742
743 /* BUGGG_FUTURE: Again, it is not clear how
744 to handle rthdr case. Ignore this complexity
745 for now.
746 */
747 memset(&fl, 0, sizeof(fl));
748 fl.proto = IPPROTO_TCP;
749 ipv6_addr_copy(&fl.fl6_dst, &np->daddr);
750 ipv6_addr_copy(&fl.fl6_src, &np->saddr);
751 fl.oif = sk->sk_bound_dev_if;
752 fl.fl_ip_dport = inet->dport;
753 fl.fl_ip_sport = inet->sport;
754
755 if ((err = ip6_dst_lookup(sk, &dst, &fl))) {
756 sk->sk_err_soft = -err;
757 goto out;
758 }
759
760 if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) {
761 sk->sk_err_soft = -err;
762 goto out;
763 }
764
765 } else
766 dst_hold(dst);
767
768 if (tp->pmtu_cookie > dst_mtu(dst)) {
769 tcp_sync_mss(sk, dst_mtu(dst));
770 tcp_simple_retransmit(sk);
771 } /* else let the usual retransmit timer handle it */
772 dst_release(dst);
773 goto out;
774 }
775
776 icmpv6_err_convert(type, code, &err);
777
Arnaldo Carvalho de Melo60236fd2005-06-18 22:47:21 -0700778 /* Might be for an request_sock */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700779 switch (sk->sk_state) {
Arnaldo Carvalho de Melo60236fd2005-06-18 22:47:21 -0700780 struct request_sock *req, **prev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700781 case TCP_LISTEN:
782 if (sock_owned_by_user(sk))
783 goto out;
784
Arnaldo Carvalho de Melo463c84b2005-08-09 20:10:42 -0700785 req = tcp_v6_search_req(sk, &prev, th->dest, &hdr->daddr,
Arnaldo Carvalho de Melo505cbfc2005-08-12 09:19:38 -0300786 &hdr->saddr, inet6_iif(skb));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700787 if (!req)
788 goto out;
789
790 /* ICMPs are not backlogged, hence we cannot get
791 * an established socket here.
792 */
793 BUG_TRAP(req->sk == NULL);
794
Arnaldo Carvalho de Melo2e6599c2005-06-18 22:46:52 -0700795 if (seq != tcp_rsk(req)->snt_isn) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700796 NET_INC_STATS_BH(LINUX_MIB_OUTOFWINDOWICMPS);
797 goto out;
798 }
799
Arnaldo Carvalho de Melo463c84b2005-08-09 20:10:42 -0700800 inet_csk_reqsk_queue_drop(sk, req, prev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700801 goto out;
802
803 case TCP_SYN_SENT:
804 case TCP_SYN_RECV: /* Cannot happen.
805 It can, it SYNs are crossed. --ANK */
806 if (!sock_owned_by_user(sk)) {
807 TCP_INC_STATS_BH(TCP_MIB_ATTEMPTFAILS);
808 sk->sk_err = err;
809 sk->sk_error_report(sk); /* Wake people up to see the error (see connect in sock.c) */
810
811 tcp_done(sk);
812 } else
813 sk->sk_err_soft = err;
814 goto out;
815 }
816
817 if (!sock_owned_by_user(sk) && np->recverr) {
818 sk->sk_err = err;
819 sk->sk_error_report(sk);
820 } else
821 sk->sk_err_soft = err;
822
823out:
824 bh_unlock_sock(sk);
825 sock_put(sk);
826}
827
828
Arnaldo Carvalho de Melo60236fd2005-06-18 22:47:21 -0700829static int tcp_v6_send_synack(struct sock *sk, struct request_sock *req,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700830 struct dst_entry *dst)
831{
Arnaldo Carvalho de Melo2e6599c2005-06-18 22:46:52 -0700832 struct tcp6_request_sock *treq = tcp6_rsk(req);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700833 struct ipv6_pinfo *np = inet6_sk(sk);
834 struct sk_buff * skb;
835 struct ipv6_txoptions *opt = NULL;
836 struct in6_addr * final_p = NULL, final;
837 struct flowi fl;
838 int err = -1;
839
840 memset(&fl, 0, sizeof(fl));
841 fl.proto = IPPROTO_TCP;
Arnaldo Carvalho de Melo2e6599c2005-06-18 22:46:52 -0700842 ipv6_addr_copy(&fl.fl6_dst, &treq->rmt_addr);
843 ipv6_addr_copy(&fl.fl6_src, &treq->loc_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700844 fl.fl6_flowlabel = 0;
Arnaldo Carvalho de Melo2e6599c2005-06-18 22:46:52 -0700845 fl.oif = treq->iif;
846 fl.fl_ip_dport = inet_rsk(req)->rmt_port;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700847 fl.fl_ip_sport = inet_sk(sk)->sport;
848
849 if (dst == NULL) {
850 opt = np->opt;
851 if (opt == NULL &&
YOSHIFUJI Hideaki333fad52005-09-08 09:59:17 +0900852 np->rxopt.bits.osrcrt == 2 &&
Arnaldo Carvalho de Melo2e6599c2005-06-18 22:46:52 -0700853 treq->pktopts) {
854 struct sk_buff *pktopts = treq->pktopts;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700855 struct inet6_skb_parm *rxopt = IP6CB(pktopts);
856 if (rxopt->srcrt)
857 opt = ipv6_invert_rthdr(sk, (struct ipv6_rt_hdr*)(pktopts->nh.raw + rxopt->srcrt));
858 }
859
860 if (opt && opt->srcrt) {
861 struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt;
862 ipv6_addr_copy(&final, &fl.fl6_dst);
863 ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
864 final_p = &final;
865 }
866
867 err = ip6_dst_lookup(sk, &dst, &fl);
868 if (err)
869 goto done;
870 if (final_p)
871 ipv6_addr_copy(&fl.fl6_dst, final_p);
872 if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0)
873 goto done;
874 }
875
876 skb = tcp_make_synack(sk, dst, req);
877 if (skb) {
878 struct tcphdr *th = skb->h.th;
879
880 th->check = tcp_v6_check(th, skb->len,
Arnaldo Carvalho de Melo2e6599c2005-06-18 22:46:52 -0700881 &treq->loc_addr, &treq->rmt_addr,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700882 csum_partial((char *)th, skb->len, skb->csum));
883
Arnaldo Carvalho de Melo2e6599c2005-06-18 22:46:52 -0700884 ipv6_addr_copy(&fl.fl6_dst, &treq->rmt_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700885 err = ip6_xmit(sk, skb, &fl, opt, 0);
886 if (err == NET_XMIT_CN)
887 err = 0;
888 }
889
890done:
891 dst_release(dst);
892 if (opt && opt != np->opt)
893 sock_kfree_s(sk, opt, opt->tot_len);
894 return err;
895}
896
Arnaldo Carvalho de Melo60236fd2005-06-18 22:47:21 -0700897static void tcp_v6_reqsk_destructor(struct request_sock *req)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700898{
Arnaldo Carvalho de Melo2e6599c2005-06-18 22:46:52 -0700899 if (tcp6_rsk(req)->pktopts)
900 kfree_skb(tcp6_rsk(req)->pktopts);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700901}
902
Arnaldo Carvalho de Melo60236fd2005-06-18 22:47:21 -0700903static struct request_sock_ops tcp6_request_sock_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700904 .family = AF_INET6,
Arnaldo Carvalho de Melo2e6599c2005-06-18 22:46:52 -0700905 .obj_size = sizeof(struct tcp6_request_sock),
Linus Torvalds1da177e2005-04-16 15:20:36 -0700906 .rtx_syn_ack = tcp_v6_send_synack,
Arnaldo Carvalho de Melo60236fd2005-06-18 22:47:21 -0700907 .send_ack = tcp_v6_reqsk_send_ack,
908 .destructor = tcp_v6_reqsk_destructor,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700909 .send_reset = tcp_v6_send_reset
910};
911
912static int ipv6_opt_accepted(struct sock *sk, struct sk_buff *skb)
913{
914 struct ipv6_pinfo *np = inet6_sk(sk);
915 struct inet6_skb_parm *opt = IP6CB(skb);
916
917 if (np->rxopt.all) {
YOSHIFUJI Hideaki333fad52005-09-08 09:59:17 +0900918 if ((opt->hop && (np->rxopt.bits.hopopts || np->rxopt.bits.ohopopts)) ||
919 ((IPV6_FLOWINFO_MASK & *(u32*)skb->nh.raw) && np->rxopt.bits.rxflow) ||
920 (opt->srcrt && (np->rxopt.bits.srcrt || np->rxopt.bits.osrcrt)) ||
921 ((opt->dst1 || opt->dst0) && (np->rxopt.bits.dstopts || np->rxopt.bits.odstopts)))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700922 return 1;
923 }
924 return 0;
925}
926
927
928static void tcp_v6_send_check(struct sock *sk, struct tcphdr *th, int len,
929 struct sk_buff *skb)
930{
931 struct ipv6_pinfo *np = inet6_sk(sk);
932
933 if (skb->ip_summed == CHECKSUM_HW) {
934 th->check = ~csum_ipv6_magic(&np->saddr, &np->daddr, len, IPPROTO_TCP, 0);
935 skb->csum = offsetof(struct tcphdr, check);
936 } else {
937 th->check = csum_ipv6_magic(&np->saddr, &np->daddr, len, IPPROTO_TCP,
938 csum_partial((char *)th, th->doff<<2,
939 skb->csum));
940 }
941}
942
943
944static void tcp_v6_send_reset(struct sk_buff *skb)
945{
946 struct tcphdr *th = skb->h.th, *t1;
947 struct sk_buff *buff;
948 struct flowi fl;
949
950 if (th->rst)
951 return;
952
953 if (!ipv6_unicast_destination(skb))
954 return;
955
956 /*
957 * We need to grab some memory, and put together an RST,
958 * and then put it into the queue to be sent.
959 */
960
961 buff = alloc_skb(MAX_HEADER + sizeof(struct ipv6hdr) + sizeof(struct tcphdr),
962 GFP_ATOMIC);
963 if (buff == NULL)
964 return;
965
966 skb_reserve(buff, MAX_HEADER + sizeof(struct ipv6hdr) + sizeof(struct tcphdr));
967
968 t1 = (struct tcphdr *) skb_push(buff,sizeof(struct tcphdr));
969
970 /* Swap the send and the receive. */
971 memset(t1, 0, sizeof(*t1));
972 t1->dest = th->source;
973 t1->source = th->dest;
974 t1->doff = sizeof(*t1)/4;
975 t1->rst = 1;
976
977 if(th->ack) {
978 t1->seq = th->ack_seq;
979 } else {
980 t1->ack = 1;
981 t1->ack_seq = htonl(ntohl(th->seq) + th->syn + th->fin
982 + skb->len - (th->doff<<2));
983 }
984
985 buff->csum = csum_partial((char *)t1, sizeof(*t1), 0);
986
987 memset(&fl, 0, sizeof(fl));
988 ipv6_addr_copy(&fl.fl6_dst, &skb->nh.ipv6h->saddr);
989 ipv6_addr_copy(&fl.fl6_src, &skb->nh.ipv6h->daddr);
990
991 t1->check = csum_ipv6_magic(&fl.fl6_src, &fl.fl6_dst,
992 sizeof(*t1), IPPROTO_TCP,
993 buff->csum);
994
995 fl.proto = IPPROTO_TCP;
Arnaldo Carvalho de Melo505cbfc2005-08-12 09:19:38 -0300996 fl.oif = inet6_iif(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700997 fl.fl_ip_dport = t1->dest;
998 fl.fl_ip_sport = t1->source;
999
1000 /* sk = NULL, but it is safe for now. RST socket required. */
1001 if (!ip6_dst_lookup(NULL, &buff->dst, &fl)) {
1002
1003 if ((xfrm_lookup(&buff->dst, &fl, NULL, 0)) < 0) {
1004 dst_release(buff->dst);
1005 return;
1006 }
1007
1008 ip6_xmit(NULL, buff, &fl, NULL, 0);
1009 TCP_INC_STATS_BH(TCP_MIB_OUTSEGS);
1010 TCP_INC_STATS_BH(TCP_MIB_OUTRSTS);
1011 return;
1012 }
1013
1014 kfree_skb(buff);
1015}
1016
1017static void tcp_v6_send_ack(struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32 ts)
1018{
1019 struct tcphdr *th = skb->h.th, *t1;
1020 struct sk_buff *buff;
1021 struct flowi fl;
1022 int tot_len = sizeof(struct tcphdr);
1023
1024 if (ts)
1025 tot_len += 3*4;
1026
1027 buff = alloc_skb(MAX_HEADER + sizeof(struct ipv6hdr) + tot_len,
1028 GFP_ATOMIC);
1029 if (buff == NULL)
1030 return;
1031
1032 skb_reserve(buff, MAX_HEADER + sizeof(struct ipv6hdr) + tot_len);
1033
1034 t1 = (struct tcphdr *) skb_push(buff,tot_len);
1035
1036 /* Swap the send and the receive. */
1037 memset(t1, 0, sizeof(*t1));
1038 t1->dest = th->source;
1039 t1->source = th->dest;
1040 t1->doff = tot_len/4;
1041 t1->seq = htonl(seq);
1042 t1->ack_seq = htonl(ack);
1043 t1->ack = 1;
1044 t1->window = htons(win);
1045
1046 if (ts) {
1047 u32 *ptr = (u32*)(t1 + 1);
1048 *ptr++ = htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) |
1049 (TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP);
1050 *ptr++ = htonl(tcp_time_stamp);
1051 *ptr = htonl(ts);
1052 }
1053
1054 buff->csum = csum_partial((char *)t1, tot_len, 0);
1055
1056 memset(&fl, 0, sizeof(fl));
1057 ipv6_addr_copy(&fl.fl6_dst, &skb->nh.ipv6h->saddr);
1058 ipv6_addr_copy(&fl.fl6_src, &skb->nh.ipv6h->daddr);
1059
1060 t1->check = csum_ipv6_magic(&fl.fl6_src, &fl.fl6_dst,
1061 tot_len, IPPROTO_TCP,
1062 buff->csum);
1063
1064 fl.proto = IPPROTO_TCP;
Arnaldo Carvalho de Melo505cbfc2005-08-12 09:19:38 -03001065 fl.oif = inet6_iif(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001066 fl.fl_ip_dport = t1->dest;
1067 fl.fl_ip_sport = t1->source;
1068
1069 if (!ip6_dst_lookup(NULL, &buff->dst, &fl)) {
1070 if ((xfrm_lookup(&buff->dst, &fl, NULL, 0)) < 0) {
1071 dst_release(buff->dst);
1072 return;
1073 }
1074 ip6_xmit(NULL, buff, &fl, NULL, 0);
1075 TCP_INC_STATS_BH(TCP_MIB_OUTSEGS);
1076 return;
1077 }
1078
1079 kfree_skb(buff);
1080}
1081
1082static void tcp_v6_timewait_ack(struct sock *sk, struct sk_buff *skb)
1083{
Arnaldo Carvalho de Melo8feaf0c02005-08-09 20:09:30 -07001084 struct inet_timewait_sock *tw = inet_twsk(sk);
1085 const struct tcp_timewait_sock *tcptw = tcp_twsk(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001086
Arnaldo Carvalho de Melo8feaf0c02005-08-09 20:09:30 -07001087 tcp_v6_send_ack(skb, tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt,
1088 tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale,
1089 tcptw->tw_ts_recent);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001090
Arnaldo Carvalho de Melo8feaf0c02005-08-09 20:09:30 -07001091 inet_twsk_put(tw);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001092}
1093
Arnaldo Carvalho de Melo60236fd2005-06-18 22:47:21 -07001094static void tcp_v6_reqsk_send_ack(struct sk_buff *skb, struct request_sock *req)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001095{
Arnaldo Carvalho de Melo2e6599c2005-06-18 22:46:52 -07001096 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 -07001097}
1098
1099
1100static struct sock *tcp_v6_hnd_req(struct sock *sk,struct sk_buff *skb)
1101{
Arnaldo Carvalho de Melo60236fd2005-06-18 22:47:21 -07001102 struct request_sock *req, **prev;
Arnaldo Carvalho de Melo505cbfc2005-08-12 09:19:38 -03001103 const struct tcphdr *th = skb->h.th;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001104 struct sock *nsk;
1105
1106 /* Find possible connection requests. */
Arnaldo Carvalho de Melo463c84b2005-08-09 20:10:42 -07001107 req = tcp_v6_search_req(sk, &prev, th->source, &skb->nh.ipv6h->saddr,
Arnaldo Carvalho de Melo505cbfc2005-08-12 09:19:38 -03001108 &skb->nh.ipv6h->daddr, inet6_iif(skb));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001109 if (req)
1110 return tcp_check_req(sk, skb, req, prev);
1111
Arnaldo Carvalho de Melo505cbfc2005-08-12 09:19:38 -03001112 nsk = __inet6_lookup_established(&tcp_hashinfo, &skb->nh.ipv6h->saddr,
1113 th->source, &skb->nh.ipv6h->daddr,
1114 ntohs(th->dest), inet6_iif(skb));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001115
1116 if (nsk) {
1117 if (nsk->sk_state != TCP_TIME_WAIT) {
1118 bh_lock_sock(nsk);
1119 return nsk;
1120 }
Arnaldo Carvalho de Melo8feaf0c02005-08-09 20:09:30 -07001121 inet_twsk_put((struct inet_timewait_sock *)nsk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001122 return NULL;
1123 }
1124
1125#if 0 /*def CONFIG_SYN_COOKIES*/
1126 if (!th->rst && !th->syn && th->ack)
1127 sk = cookie_v6_check(sk, skb, &(IPCB(skb)->opt));
1128#endif
1129 return sk;
1130}
1131
Arnaldo Carvalho de Melo60236fd2005-06-18 22:47:21 -07001132static void tcp_v6_synq_add(struct sock *sk, struct request_sock *req)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001133{
Arnaldo Carvalho de Melo463c84b2005-08-09 20:10:42 -07001134 struct inet_connection_sock *icsk = inet_csk(sk);
1135 struct listen_sock *lopt = icsk->icsk_accept_queue.listen_opt;
1136 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 -07001137
Arnaldo Carvalho de Melo463c84b2005-08-09 20:10:42 -07001138 reqsk_queue_hash_req(&icsk->icsk_accept_queue, h, req, TCP_TIMEOUT_INIT);
1139 inet_csk_reqsk_queue_added(sk, TCP_TIMEOUT_INIT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001140}
1141
1142
1143/* FIXME: this is substantially similar to the ipv4 code.
1144 * Can some kind of merge be done? -- erics
1145 */
1146static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
1147{
Arnaldo Carvalho de Melo2e6599c2005-06-18 22:46:52 -07001148 struct tcp6_request_sock *treq;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001149 struct ipv6_pinfo *np = inet6_sk(sk);
1150 struct tcp_options_received tmp_opt;
1151 struct tcp_sock *tp = tcp_sk(sk);
Arnaldo Carvalho de Melo60236fd2005-06-18 22:47:21 -07001152 struct request_sock *req = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001153 __u32 isn = TCP_SKB_CB(skb)->when;
1154
1155 if (skb->protocol == htons(ETH_P_IP))
1156 return tcp_v4_conn_request(sk, skb);
1157
1158 if (!ipv6_unicast_destination(skb))
1159 goto drop;
1160
1161 /*
1162 * There are no SYN attacks on IPv6, yet...
1163 */
Arnaldo Carvalho de Melo463c84b2005-08-09 20:10:42 -07001164 if (inet_csk_reqsk_queue_is_full(sk) && !isn) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001165 if (net_ratelimit())
1166 printk(KERN_INFO "TCPv6: dropping request, synflood is possible\n");
1167 goto drop;
1168 }
1169
Arnaldo Carvalho de Melo463c84b2005-08-09 20:10:42 -07001170 if (sk_acceptq_is_full(sk) && inet_csk_reqsk_queue_young(sk) > 1)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001171 goto drop;
1172
Arnaldo Carvalho de Melo60236fd2005-06-18 22:47:21 -07001173 req = reqsk_alloc(&tcp6_request_sock_ops);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001174 if (req == NULL)
1175 goto drop;
1176
1177 tcp_clear_options(&tmp_opt);
1178 tmp_opt.mss_clamp = IPV6_MIN_MTU - sizeof(struct tcphdr) - sizeof(struct ipv6hdr);
1179 tmp_opt.user_mss = tp->rx_opt.user_mss;
1180
1181 tcp_parse_options(skb, &tmp_opt, 0);
1182
1183 tmp_opt.tstamp_ok = tmp_opt.saw_tstamp;
1184 tcp_openreq_init(req, &tmp_opt, skb);
1185
Arnaldo Carvalho de Melo2e6599c2005-06-18 22:46:52 -07001186 treq = tcp6_rsk(req);
1187 ipv6_addr_copy(&treq->rmt_addr, &skb->nh.ipv6h->saddr);
1188 ipv6_addr_copy(&treq->loc_addr, &skb->nh.ipv6h->daddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001189 TCP_ECN_create_request(req, skb->h.th);
Arnaldo Carvalho de Melo2e6599c2005-06-18 22:46:52 -07001190 treq->pktopts = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001191 if (ipv6_opt_accepted(sk, skb) ||
YOSHIFUJI Hideaki333fad52005-09-08 09:59:17 +09001192 np->rxopt.bits.rxinfo || np->rxopt.bits.rxoinfo ||
1193 np->rxopt.bits.rxhlim || np->rxopt.bits.rxohlim) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001194 atomic_inc(&skb->users);
Arnaldo Carvalho de Melo2e6599c2005-06-18 22:46:52 -07001195 treq->pktopts = skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001196 }
Arnaldo Carvalho de Melo2e6599c2005-06-18 22:46:52 -07001197 treq->iif = sk->sk_bound_dev_if;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001198
1199 /* So that link locals have meaning */
1200 if (!sk->sk_bound_dev_if &&
Arnaldo Carvalho de Melo2e6599c2005-06-18 22:46:52 -07001201 ipv6_addr_type(&treq->rmt_addr) & IPV6_ADDR_LINKLOCAL)
Arnaldo Carvalho de Melo505cbfc2005-08-12 09:19:38 -03001202 treq->iif = inet6_iif(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001203
1204 if (isn == 0)
1205 isn = tcp_v6_init_sequence(sk,skb);
1206
Arnaldo Carvalho de Melo2e6599c2005-06-18 22:46:52 -07001207 tcp_rsk(req)->snt_isn = isn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001208
1209 if (tcp_v6_send_synack(sk, req, NULL))
1210 goto drop;
1211
1212 tcp_v6_synq_add(sk, req);
1213
1214 return 0;
1215
1216drop:
1217 if (req)
Arnaldo Carvalho de Melo60236fd2005-06-18 22:47:21 -07001218 reqsk_free(req);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001219
1220 TCP_INC_STATS_BH(TCP_MIB_ATTEMPTFAILS);
1221 return 0; /* don't send reset */
1222}
1223
1224static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
Arnaldo Carvalho de Melo60236fd2005-06-18 22:47:21 -07001225 struct request_sock *req,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001226 struct dst_entry *dst)
1227{
Arnaldo Carvalho de Melo2e6599c2005-06-18 22:46:52 -07001228 struct tcp6_request_sock *treq = tcp6_rsk(req);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001229 struct ipv6_pinfo *newnp, *np = inet6_sk(sk);
1230 struct tcp6_sock *newtcp6sk;
1231 struct inet_sock *newinet;
1232 struct tcp_sock *newtp;
1233 struct sock *newsk;
1234 struct ipv6_txoptions *opt;
1235
1236 if (skb->protocol == htons(ETH_P_IP)) {
1237 /*
1238 * v6 mapped
1239 */
1240
1241 newsk = tcp_v4_syn_recv_sock(sk, skb, req, dst);
1242
1243 if (newsk == NULL)
1244 return NULL;
1245
1246 newtcp6sk = (struct tcp6_sock *)newsk;
1247 inet_sk(newsk)->pinet6 = &newtcp6sk->inet6;
1248
1249 newinet = inet_sk(newsk);
1250 newnp = inet6_sk(newsk);
1251 newtp = tcp_sk(newsk);
1252
1253 memcpy(newnp, np, sizeof(struct ipv6_pinfo));
1254
1255 ipv6_addr_set(&newnp->daddr, 0, 0, htonl(0x0000FFFF),
1256 newinet->daddr);
1257
1258 ipv6_addr_set(&newnp->saddr, 0, 0, htonl(0x0000FFFF),
1259 newinet->saddr);
1260
1261 ipv6_addr_copy(&newnp->rcv_saddr, &newnp->saddr);
1262
1263 newtp->af_specific = &ipv6_mapped;
1264 newsk->sk_backlog_rcv = tcp_v4_do_rcv;
1265 newnp->pktoptions = NULL;
1266 newnp->opt = NULL;
Arnaldo Carvalho de Melo505cbfc2005-08-12 09:19:38 -03001267 newnp->mcast_oif = inet6_iif(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001268 newnp->mcast_hops = skb->nh.ipv6h->hop_limit;
1269
Arnaldo Carvalho de Meloe6848972005-08-09 19:45:38 -07001270 /*
1271 * No need to charge this sock to the relevant IPv6 refcnt debug socks count
1272 * here, tcp_create_openreq_child now does this for us, see the comment in
1273 * that function for the gory details. -acme
Linus Torvalds1da177e2005-04-16 15:20:36 -07001274 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001275
1276 /* It is tricky place. Until this moment IPv4 tcp
1277 worked with IPv6 af_tcp.af_specific.
1278 Sync it now.
1279 */
1280 tcp_sync_mss(newsk, newtp->pmtu_cookie);
1281
1282 return newsk;
1283 }
1284
1285 opt = np->opt;
1286
1287 if (sk_acceptq_is_full(sk))
1288 goto out_overflow;
1289
YOSHIFUJI Hideaki333fad52005-09-08 09:59:17 +09001290 if (np->rxopt.bits.osrcrt == 2 &&
Arnaldo Carvalho de Melo2e6599c2005-06-18 22:46:52 -07001291 opt == NULL && treq->pktopts) {
1292 struct inet6_skb_parm *rxopt = IP6CB(treq->pktopts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001293 if (rxopt->srcrt)
Arnaldo Carvalho de Melo2e6599c2005-06-18 22:46:52 -07001294 opt = ipv6_invert_rthdr(sk, (struct ipv6_rt_hdr *)(treq->pktopts->nh.raw + rxopt->srcrt));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001295 }
1296
1297 if (dst == NULL) {
1298 struct in6_addr *final_p = NULL, final;
1299 struct flowi fl;
1300
1301 memset(&fl, 0, sizeof(fl));
1302 fl.proto = IPPROTO_TCP;
Arnaldo Carvalho de Melo2e6599c2005-06-18 22:46:52 -07001303 ipv6_addr_copy(&fl.fl6_dst, &treq->rmt_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001304 if (opt && opt->srcrt) {
1305 struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt;
1306 ipv6_addr_copy(&final, &fl.fl6_dst);
1307 ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
1308 final_p = &final;
1309 }
Arnaldo Carvalho de Melo2e6599c2005-06-18 22:46:52 -07001310 ipv6_addr_copy(&fl.fl6_src, &treq->loc_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001311 fl.oif = sk->sk_bound_dev_if;
Arnaldo Carvalho de Melo2e6599c2005-06-18 22:46:52 -07001312 fl.fl_ip_dport = inet_rsk(req)->rmt_port;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001313 fl.fl_ip_sport = inet_sk(sk)->sport;
1314
1315 if (ip6_dst_lookup(sk, &dst, &fl))
1316 goto out;
1317
1318 if (final_p)
1319 ipv6_addr_copy(&fl.fl6_dst, final_p);
1320
1321 if ((xfrm_lookup(&dst, &fl, sk, 0)) < 0)
1322 goto out;
1323 }
1324
1325 newsk = tcp_create_openreq_child(sk, req, skb);
1326 if (newsk == NULL)
1327 goto out;
1328
Arnaldo Carvalho de Meloe6848972005-08-09 19:45:38 -07001329 /*
1330 * No need to charge this sock to the relevant IPv6 refcnt debug socks
1331 * count here, tcp_create_openreq_child now does this for us, see the
1332 * comment in that function for the gory details. -acme
1333 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001334
1335 ip6_dst_store(newsk, dst, NULL);
1336 newsk->sk_route_caps = dst->dev->features &
1337 ~(NETIF_F_IP_CSUM | NETIF_F_TSO);
1338
1339 newtcp6sk = (struct tcp6_sock *)newsk;
1340 inet_sk(newsk)->pinet6 = &newtcp6sk->inet6;
1341
1342 newtp = tcp_sk(newsk);
1343 newinet = inet_sk(newsk);
1344 newnp = inet6_sk(newsk);
1345
1346 memcpy(newnp, np, sizeof(struct ipv6_pinfo));
1347
Arnaldo Carvalho de Melo2e6599c2005-06-18 22:46:52 -07001348 ipv6_addr_copy(&newnp->daddr, &treq->rmt_addr);
1349 ipv6_addr_copy(&newnp->saddr, &treq->loc_addr);
1350 ipv6_addr_copy(&newnp->rcv_saddr, &treq->loc_addr);
1351 newsk->sk_bound_dev_if = treq->iif;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001352
1353 /* Now IPv6 options...
1354
1355 First: no IPv4 options.
1356 */
1357 newinet->opt = NULL;
1358
1359 /* Clone RX bits */
1360 newnp->rxopt.all = np->rxopt.all;
1361
1362 /* Clone pktoptions received with SYN */
1363 newnp->pktoptions = NULL;
Arnaldo Carvalho de Melo2e6599c2005-06-18 22:46:52 -07001364 if (treq->pktopts != NULL) {
1365 newnp->pktoptions = skb_clone(treq->pktopts, GFP_ATOMIC);
1366 kfree_skb(treq->pktopts);
1367 treq->pktopts = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001368 if (newnp->pktoptions)
1369 skb_set_owner_r(newnp->pktoptions, newsk);
1370 }
1371 newnp->opt = NULL;
Arnaldo Carvalho de Melo505cbfc2005-08-12 09:19:38 -03001372 newnp->mcast_oif = inet6_iif(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001373 newnp->mcast_hops = skb->nh.ipv6h->hop_limit;
1374
1375 /* Clone native IPv6 options from listening socket (if any)
1376
1377 Yes, keeping reference count would be much more clever,
1378 but we make one more one thing there: reattach optmem
1379 to newsk.
1380 */
1381 if (opt) {
1382 newnp->opt = ipv6_dup_options(newsk, opt);
1383 if (opt != np->opt)
1384 sock_kfree_s(sk, opt, opt->tot_len);
1385 }
1386
1387 newtp->ext_header_len = 0;
1388 if (newnp->opt)
1389 newtp->ext_header_len = newnp->opt->opt_nflen +
1390 newnp->opt->opt_flen;
1391
1392 tcp_sync_mss(newsk, dst_mtu(dst));
1393 newtp->advmss = dst_metric(dst, RTAX_ADVMSS);
1394 tcp_initialize_rcv_mss(newsk);
1395
1396 newinet->daddr = newinet->saddr = newinet->rcv_saddr = LOOPBACK4_IPV6;
1397
1398 __tcp_v6_hash(newsk);
Arnaldo Carvalho de Melo2d8c4ce2005-08-09 20:07:13 -07001399 inet_inherit_port(&tcp_hashinfo, sk, newsk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001400
1401 return newsk;
1402
1403out_overflow:
1404 NET_INC_STATS_BH(LINUX_MIB_LISTENOVERFLOWS);
1405out:
1406 NET_INC_STATS_BH(LINUX_MIB_LISTENDROPS);
1407 if (opt && opt != np->opt)
1408 sock_kfree_s(sk, opt, opt->tot_len);
1409 dst_release(dst);
1410 return NULL;
1411}
1412
1413static int tcp_v6_checksum_init(struct sk_buff *skb)
1414{
1415 if (skb->ip_summed == CHECKSUM_HW) {
1416 skb->ip_summed = CHECKSUM_UNNECESSARY;
1417 if (!tcp_v6_check(skb->h.th,skb->len,&skb->nh.ipv6h->saddr,
1418 &skb->nh.ipv6h->daddr,skb->csum))
1419 return 0;
Patrick McHardy64ce2072005-08-09 20:50:53 -07001420 LIMIT_NETDEBUG(KERN_DEBUG "hw tcp v6 csum failed\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001421 }
1422 if (skb->len <= 76) {
1423 if (tcp_v6_check(skb->h.th,skb->len,&skb->nh.ipv6h->saddr,
1424 &skb->nh.ipv6h->daddr,skb_checksum(skb, 0, skb->len, 0)))
1425 return -1;
1426 skb->ip_summed = CHECKSUM_UNNECESSARY;
1427 } else {
1428 skb->csum = ~tcp_v6_check(skb->h.th,skb->len,&skb->nh.ipv6h->saddr,
1429 &skb->nh.ipv6h->daddr,0);
1430 }
1431 return 0;
1432}
1433
1434/* The socket must have it's spinlock held when we get
1435 * here.
1436 *
1437 * We have a potential double-lock case here, so even when
1438 * doing backlog processing we use the BH locking scheme.
1439 * This is because we cannot sleep with the original spinlock
1440 * held.
1441 */
1442static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb)
1443{
1444 struct ipv6_pinfo *np = inet6_sk(sk);
1445 struct tcp_sock *tp;
1446 struct sk_buff *opt_skb = NULL;
1447
1448 /* Imagine: socket is IPv6. IPv4 packet arrives,
1449 goes to IPv4 receive handler and backlogged.
1450 From backlog it always goes here. Kerboom...
1451 Fortunately, tcp_rcv_established and rcv_established
1452 handle them correctly, but it is not case with
1453 tcp_v6_hnd_req and tcp_v6_send_reset(). --ANK
1454 */
1455
1456 if (skb->protocol == htons(ETH_P_IP))
1457 return tcp_v4_do_rcv(sk, skb);
1458
1459 if (sk_filter(sk, skb, 0))
1460 goto discard;
1461
1462 /*
1463 * socket locking is here for SMP purposes as backlog rcv
1464 * is currently called with bh processing disabled.
1465 */
1466
1467 /* Do Stevens' IPV6_PKTOPTIONS.
1468
1469 Yes, guys, it is the only place in our code, where we
1470 may make it not affecting IPv4.
1471 The rest of code is protocol independent,
1472 and I do not like idea to uglify IPv4.
1473
1474 Actually, all the idea behind IPV6_PKTOPTIONS
1475 looks not very well thought. For now we latch
1476 options, received in the last packet, enqueued
1477 by tcp. Feel free to propose better solution.
1478 --ANK (980728)
1479 */
1480 if (np->rxopt.all)
1481 opt_skb = skb_clone(skb, GFP_ATOMIC);
1482
1483 if (sk->sk_state == TCP_ESTABLISHED) { /* Fast path */
1484 TCP_CHECK_TIMER(sk);
1485 if (tcp_rcv_established(sk, skb, skb->h.th, skb->len))
1486 goto reset;
1487 TCP_CHECK_TIMER(sk);
1488 if (opt_skb)
1489 goto ipv6_pktoptions;
1490 return 0;
1491 }
1492
1493 if (skb->len < (skb->h.th->doff<<2) || tcp_checksum_complete(skb))
1494 goto csum_err;
1495
1496 if (sk->sk_state == TCP_LISTEN) {
1497 struct sock *nsk = tcp_v6_hnd_req(sk, skb);
1498 if (!nsk)
1499 goto discard;
1500
1501 /*
1502 * Queue it on the new socket if the new socket is active,
1503 * otherwise we just shortcircuit this and continue with
1504 * the new socket..
1505 */
1506 if(nsk != sk) {
1507 if (tcp_child_process(sk, nsk, skb))
1508 goto reset;
1509 if (opt_skb)
1510 __kfree_skb(opt_skb);
1511 return 0;
1512 }
1513 }
1514
1515 TCP_CHECK_TIMER(sk);
1516 if (tcp_rcv_state_process(sk, skb, skb->h.th, skb->len))
1517 goto reset;
1518 TCP_CHECK_TIMER(sk);
1519 if (opt_skb)
1520 goto ipv6_pktoptions;
1521 return 0;
1522
1523reset:
1524 tcp_v6_send_reset(skb);
1525discard:
1526 if (opt_skb)
1527 __kfree_skb(opt_skb);
1528 kfree_skb(skb);
1529 return 0;
1530csum_err:
1531 TCP_INC_STATS_BH(TCP_MIB_INERRS);
1532 goto discard;
1533
1534
1535ipv6_pktoptions:
1536 /* Do you ask, what is it?
1537
1538 1. skb was enqueued by tcp.
1539 2. skb is added to tail of read queue, rather than out of order.
1540 3. socket is not in passive state.
1541 4. Finally, it really contains options, which user wants to receive.
1542 */
1543 tp = tcp_sk(sk);
1544 if (TCP_SKB_CB(opt_skb)->end_seq == tp->rcv_nxt &&
1545 !((1 << sk->sk_state) & (TCPF_CLOSE | TCPF_LISTEN))) {
YOSHIFUJI Hideaki333fad52005-09-08 09:59:17 +09001546 if (np->rxopt.bits.rxinfo || np->rxopt.bits.rxoinfo)
Arnaldo Carvalho de Melo505cbfc2005-08-12 09:19:38 -03001547 np->mcast_oif = inet6_iif(opt_skb);
YOSHIFUJI Hideaki333fad52005-09-08 09:59:17 +09001548 if (np->rxopt.bits.rxhlim || np->rxopt.bits.rxohlim)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001549 np->mcast_hops = opt_skb->nh.ipv6h->hop_limit;
1550 if (ipv6_opt_accepted(sk, opt_skb)) {
1551 skb_set_owner_r(opt_skb, sk);
1552 opt_skb = xchg(&np->pktoptions, opt_skb);
1553 } else {
1554 __kfree_skb(opt_skb);
1555 opt_skb = xchg(&np->pktoptions, NULL);
1556 }
1557 }
1558
1559 if (opt_skb)
1560 kfree_skb(opt_skb);
1561 return 0;
1562}
1563
1564static int tcp_v6_rcv(struct sk_buff **pskb, unsigned int *nhoffp)
1565{
1566 struct sk_buff *skb = *pskb;
1567 struct tcphdr *th;
1568 struct sock *sk;
1569 int ret;
1570
1571 if (skb->pkt_type != PACKET_HOST)
1572 goto discard_it;
1573
1574 /*
1575 * Count it even if it's bad.
1576 */
1577 TCP_INC_STATS_BH(TCP_MIB_INSEGS);
1578
1579 if (!pskb_may_pull(skb, sizeof(struct tcphdr)))
1580 goto discard_it;
1581
1582 th = skb->h.th;
1583
1584 if (th->doff < sizeof(struct tcphdr)/4)
1585 goto bad_packet;
1586 if (!pskb_may_pull(skb, th->doff*4))
1587 goto discard_it;
1588
1589 if ((skb->ip_summed != CHECKSUM_UNNECESSARY &&
1590 tcp_v6_checksum_init(skb) < 0))
1591 goto bad_packet;
1592
1593 th = skb->h.th;
1594 TCP_SKB_CB(skb)->seq = ntohl(th->seq);
1595 TCP_SKB_CB(skb)->end_seq = (TCP_SKB_CB(skb)->seq + th->syn + th->fin +
1596 skb->len - th->doff*4);
1597 TCP_SKB_CB(skb)->ack_seq = ntohl(th->ack_seq);
1598 TCP_SKB_CB(skb)->when = 0;
1599 TCP_SKB_CB(skb)->flags = ipv6_get_dsfield(skb->nh.ipv6h);
1600 TCP_SKB_CB(skb)->sacked = 0;
1601
Arnaldo Carvalho de Melo505cbfc2005-08-12 09:19:38 -03001602 sk = __inet6_lookup(&tcp_hashinfo, &skb->nh.ipv6h->saddr, th->source,
1603 &skb->nh.ipv6h->daddr, ntohs(th->dest),
1604 inet6_iif(skb));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001605
1606 if (!sk)
1607 goto no_tcp_socket;
1608
1609process:
1610 if (sk->sk_state == TCP_TIME_WAIT)
1611 goto do_time_wait;
1612
1613 if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb))
1614 goto discard_and_relse;
1615
1616 if (sk_filter(sk, skb, 0))
1617 goto discard_and_relse;
1618
1619 skb->dev = NULL;
1620
1621 bh_lock_sock(sk);
1622 ret = 0;
1623 if (!sock_owned_by_user(sk)) {
1624 if (!tcp_prequeue(sk, skb))
1625 ret = tcp_v6_do_rcv(sk, skb);
1626 } else
1627 sk_add_backlog(sk, skb);
1628 bh_unlock_sock(sk);
1629
1630 sock_put(sk);
1631 return ret ? -1 : 0;
1632
1633no_tcp_socket:
1634 if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb))
1635 goto discard_it;
1636
1637 if (skb->len < (th->doff<<2) || tcp_checksum_complete(skb)) {
1638bad_packet:
1639 TCP_INC_STATS_BH(TCP_MIB_INERRS);
1640 } else {
1641 tcp_v6_send_reset(skb);
1642 }
1643
1644discard_it:
1645
1646 /*
1647 * Discard frame
1648 */
1649
1650 kfree_skb(skb);
1651 return 0;
1652
1653discard_and_relse:
1654 sock_put(sk);
1655 goto discard_it;
1656
1657do_time_wait:
1658 if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) {
Arnaldo Carvalho de Melo8feaf0c02005-08-09 20:09:30 -07001659 inet_twsk_put((struct inet_timewait_sock *)sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001660 goto discard_it;
1661 }
1662
1663 if (skb->len < (th->doff<<2) || tcp_checksum_complete(skb)) {
1664 TCP_INC_STATS_BH(TCP_MIB_INERRS);
Arnaldo Carvalho de Melo8feaf0c02005-08-09 20:09:30 -07001665 inet_twsk_put((struct inet_timewait_sock *)sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001666 goto discard_it;
1667 }
1668
Arnaldo Carvalho de Melo8feaf0c02005-08-09 20:09:30 -07001669 switch (tcp_timewait_state_process((struct inet_timewait_sock *)sk,
1670 skb, th)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001671 case TCP_TW_SYN:
1672 {
1673 struct sock *sk2;
1674
Arnaldo Carvalho de Melo505cbfc2005-08-12 09:19:38 -03001675 sk2 = inet6_lookup_listener(&tcp_hashinfo,
1676 &skb->nh.ipv6h->daddr,
1677 ntohs(th->dest), inet6_iif(skb));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001678 if (sk2 != NULL) {
Arnaldo Carvalho de Melo295ff7e2005-08-09 20:44:40 -07001679 struct inet_timewait_sock *tw = inet_twsk(sk);
1680 inet_twsk_deschedule(tw, &tcp_death_row);
1681 inet_twsk_put(tw);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001682 sk = sk2;
1683 goto process;
1684 }
1685 /* Fall through to ACK */
1686 }
1687 case TCP_TW_ACK:
1688 tcp_v6_timewait_ack(sk, skb);
1689 break;
1690 case TCP_TW_RST:
1691 goto no_tcp_socket;
1692 case TCP_TW_SUCCESS:;
1693 }
1694 goto discard_it;
1695}
1696
1697static int tcp_v6_rebuild_header(struct sock *sk)
1698{
1699 int err;
1700 struct dst_entry *dst;
1701 struct ipv6_pinfo *np = inet6_sk(sk);
1702
1703 dst = __sk_dst_check(sk, np->dst_cookie);
1704
1705 if (dst == NULL) {
1706 struct inet_sock *inet = inet_sk(sk);
1707 struct in6_addr *final_p = NULL, final;
1708 struct flowi fl;
1709
1710 memset(&fl, 0, sizeof(fl));
1711 fl.proto = IPPROTO_TCP;
1712 ipv6_addr_copy(&fl.fl6_dst, &np->daddr);
1713 ipv6_addr_copy(&fl.fl6_src, &np->saddr);
1714 fl.fl6_flowlabel = np->flow_label;
1715 fl.oif = sk->sk_bound_dev_if;
1716 fl.fl_ip_dport = inet->dport;
1717 fl.fl_ip_sport = inet->sport;
1718
1719 if (np->opt && np->opt->srcrt) {
1720 struct rt0_hdr *rt0 = (struct rt0_hdr *) np->opt->srcrt;
1721 ipv6_addr_copy(&final, &fl.fl6_dst);
1722 ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
1723 final_p = &final;
1724 }
1725
1726 err = ip6_dst_lookup(sk, &dst, &fl);
1727 if (err) {
1728 sk->sk_route_caps = 0;
1729 return err;
1730 }
1731 if (final_p)
1732 ipv6_addr_copy(&fl.fl6_dst, final_p);
1733
1734 if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) {
1735 sk->sk_err_soft = -err;
1736 dst_release(dst);
1737 return err;
1738 }
1739
1740 ip6_dst_store(sk, dst, NULL);
1741 sk->sk_route_caps = dst->dev->features &
1742 ~(NETIF_F_IP_CSUM | NETIF_F_TSO);
1743 }
1744
1745 return 0;
1746}
1747
1748static int tcp_v6_xmit(struct sk_buff *skb, int ipfragok)
1749{
1750 struct sock *sk = skb->sk;
1751 struct inet_sock *inet = inet_sk(sk);
1752 struct ipv6_pinfo *np = inet6_sk(sk);
1753 struct flowi fl;
1754 struct dst_entry *dst;
1755 struct in6_addr *final_p = NULL, final;
1756
1757 memset(&fl, 0, sizeof(fl));
1758 fl.proto = IPPROTO_TCP;
1759 ipv6_addr_copy(&fl.fl6_dst, &np->daddr);
1760 ipv6_addr_copy(&fl.fl6_src, &np->saddr);
1761 fl.fl6_flowlabel = np->flow_label;
1762 IP6_ECN_flow_xmit(sk, fl.fl6_flowlabel);
1763 fl.oif = sk->sk_bound_dev_if;
1764 fl.fl_ip_sport = inet->sport;
1765 fl.fl_ip_dport = inet->dport;
1766
1767 if (np->opt && np->opt->srcrt) {
1768 struct rt0_hdr *rt0 = (struct rt0_hdr *) np->opt->srcrt;
1769 ipv6_addr_copy(&final, &fl.fl6_dst);
1770 ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
1771 final_p = &final;
1772 }
1773
1774 dst = __sk_dst_check(sk, np->dst_cookie);
1775
1776 if (dst == NULL) {
1777 int err = ip6_dst_lookup(sk, &dst, &fl);
1778
1779 if (err) {
1780 sk->sk_err_soft = -err;
1781 return err;
1782 }
1783
1784 if (final_p)
1785 ipv6_addr_copy(&fl.fl6_dst, final_p);
1786
1787 if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) {
1788 sk->sk_route_caps = 0;
1789 dst_release(dst);
1790 return err;
1791 }
1792
1793 ip6_dst_store(sk, dst, NULL);
1794 sk->sk_route_caps = dst->dev->features &
1795 ~(NETIF_F_IP_CSUM | NETIF_F_TSO);
1796 }
1797
1798 skb->dst = dst_clone(dst);
1799
1800 /* Restore final destination back after routing done */
1801 ipv6_addr_copy(&fl.fl6_dst, &np->daddr);
1802
1803 return ip6_xmit(sk, skb, &fl, np->opt, 0);
1804}
1805
1806static void v6_addr2sockaddr(struct sock *sk, struct sockaddr * uaddr)
1807{
1808 struct ipv6_pinfo *np = inet6_sk(sk);
1809 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) uaddr;
1810
1811 sin6->sin6_family = AF_INET6;
1812 ipv6_addr_copy(&sin6->sin6_addr, &np->daddr);
1813 sin6->sin6_port = inet_sk(sk)->dport;
1814 /* We do not store received flowlabel for TCP */
1815 sin6->sin6_flowinfo = 0;
1816 sin6->sin6_scope_id = 0;
1817 if (sk->sk_bound_dev_if &&
1818 ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_LINKLOCAL)
1819 sin6->sin6_scope_id = sk->sk_bound_dev_if;
1820}
1821
1822static int tcp_v6_remember_stamp(struct sock *sk)
1823{
1824 /* Alas, not yet... */
1825 return 0;
1826}
1827
1828static struct tcp_func ipv6_specific = {
1829 .queue_xmit = tcp_v6_xmit,
1830 .send_check = tcp_v6_send_check,
1831 .rebuild_header = tcp_v6_rebuild_header,
1832 .conn_request = tcp_v6_conn_request,
1833 .syn_recv_sock = tcp_v6_syn_recv_sock,
1834 .remember_stamp = tcp_v6_remember_stamp,
1835 .net_header_len = sizeof(struct ipv6hdr),
1836
1837 .setsockopt = ipv6_setsockopt,
1838 .getsockopt = ipv6_getsockopt,
1839 .addr2sockaddr = v6_addr2sockaddr,
1840 .sockaddr_len = sizeof(struct sockaddr_in6)
1841};
1842
1843/*
1844 * TCP over IPv4 via INET6 API
1845 */
1846
1847static struct tcp_func ipv6_mapped = {
1848 .queue_xmit = ip_queue_xmit,
1849 .send_check = tcp_v4_send_check,
Arnaldo Carvalho de Melo32519f12005-08-09 19:50:02 -07001850 .rebuild_header = inet_sk_rebuild_header,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001851 .conn_request = tcp_v6_conn_request,
1852 .syn_recv_sock = tcp_v6_syn_recv_sock,
1853 .remember_stamp = tcp_v4_remember_stamp,
1854 .net_header_len = sizeof(struct iphdr),
1855
1856 .setsockopt = ipv6_setsockopt,
1857 .getsockopt = ipv6_getsockopt,
1858 .addr2sockaddr = v6_addr2sockaddr,
1859 .sockaddr_len = sizeof(struct sockaddr_in6)
1860};
1861
1862
1863
1864/* NOTE: A lot of things set to zero explicitly by call to
1865 * sk_alloc() so need not be done here.
1866 */
1867static int tcp_v6_init_sock(struct sock *sk)
1868{
Arnaldo Carvalho de Melo6687e982005-08-10 04:03:31 -03001869 struct inet_connection_sock *icsk = inet_csk(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001870 struct tcp_sock *tp = tcp_sk(sk);
1871
1872 skb_queue_head_init(&tp->out_of_order_queue);
1873 tcp_init_xmit_timers(sk);
1874 tcp_prequeue_init(tp);
1875
Arnaldo Carvalho de Melo6687e982005-08-10 04:03:31 -03001876 icsk->icsk_rto = TCP_TIMEOUT_INIT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001877 tp->mdev = TCP_TIMEOUT_INIT;
1878
1879 /* So many TCP implementations out there (incorrectly) count the
1880 * initial SYN frame in their delayed-ACK and congestion control
1881 * algorithms that we must have the following bandaid to talk
1882 * efficiently to them. -DaveM
1883 */
1884 tp->snd_cwnd = 2;
1885
1886 /* See draft-stevens-tcpca-spec-01 for discussion of the
1887 * initialization of these values.
1888 */
1889 tp->snd_ssthresh = 0x7fffffff;
1890 tp->snd_cwnd_clamp = ~0;
David S. Millerc1b4a7e2005-07-05 15:24:38 -07001891 tp->mss_cache = 536;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001892
1893 tp->reordering = sysctl_tcp_reordering;
1894
1895 sk->sk_state = TCP_CLOSE;
1896
1897 tp->af_specific = &ipv6_specific;
Arnaldo Carvalho de Melo6687e982005-08-10 04:03:31 -03001898 icsk->icsk_ca_ops = &tcp_init_congestion_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001899 sk->sk_write_space = sk_stream_write_space;
1900 sock_set_flag(sk, SOCK_USE_WRITE_QUEUE);
1901
1902 sk->sk_sndbuf = sysctl_tcp_wmem[1];
1903 sk->sk_rcvbuf = sysctl_tcp_rmem[1];
1904
1905 atomic_inc(&tcp_sockets_allocated);
1906
1907 return 0;
1908}
1909
1910static int tcp_v6_destroy_sock(struct sock *sk)
1911{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001912 tcp_v4_destroy_sock(sk);
1913 return inet6_destroy_sock(sk);
1914}
1915
1916/* Proc filesystem TCPv6 sock list dumping. */
1917static void get_openreq6(struct seq_file *seq,
Arnaldo Carvalho de Melo60236fd2005-06-18 22:47:21 -07001918 struct sock *sk, struct request_sock *req, int i, int uid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001919{
1920 struct in6_addr *dest, *src;
1921 int ttd = req->expires - jiffies;
1922
1923 if (ttd < 0)
1924 ttd = 0;
1925
Arnaldo Carvalho de Melo2e6599c2005-06-18 22:46:52 -07001926 src = &tcp6_rsk(req)->loc_addr;
1927 dest = &tcp6_rsk(req)->rmt_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001928 seq_printf(seq,
1929 "%4d: %08X%08X%08X%08X:%04X %08X%08X%08X%08X:%04X "
1930 "%02X %08X:%08X %02X:%08lX %08X %5d %8d %d %d %p\n",
1931 i,
1932 src->s6_addr32[0], src->s6_addr32[1],
1933 src->s6_addr32[2], src->s6_addr32[3],
1934 ntohs(inet_sk(sk)->sport),
1935 dest->s6_addr32[0], dest->s6_addr32[1],
1936 dest->s6_addr32[2], dest->s6_addr32[3],
Arnaldo Carvalho de Melo2e6599c2005-06-18 22:46:52 -07001937 ntohs(inet_rsk(req)->rmt_port),
Linus Torvalds1da177e2005-04-16 15:20:36 -07001938 TCP_SYN_RECV,
1939 0,0, /* could print option size, but that is af dependent. */
1940 1, /* timers active (only the expire timer) */
1941 jiffies_to_clock_t(ttd),
1942 req->retrans,
1943 uid,
1944 0, /* non standard timer */
1945 0, /* open_requests have no inode */
1946 0, req);
1947}
1948
1949static void get_tcp6_sock(struct seq_file *seq, struct sock *sp, int i)
1950{
1951 struct in6_addr *dest, *src;
1952 __u16 destp, srcp;
1953 int timer_active;
1954 unsigned long timer_expires;
1955 struct inet_sock *inet = inet_sk(sp);
1956 struct tcp_sock *tp = tcp_sk(sp);
Arnaldo Carvalho de Melo463c84b2005-08-09 20:10:42 -07001957 const struct inet_connection_sock *icsk = inet_csk(sp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001958 struct ipv6_pinfo *np = inet6_sk(sp);
1959
1960 dest = &np->daddr;
1961 src = &np->rcv_saddr;
1962 destp = ntohs(inet->dport);
1963 srcp = ntohs(inet->sport);
Arnaldo Carvalho de Melo463c84b2005-08-09 20:10:42 -07001964
1965 if (icsk->icsk_pending == ICSK_TIME_RETRANS) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001966 timer_active = 1;
Arnaldo Carvalho de Melo463c84b2005-08-09 20:10:42 -07001967 timer_expires = icsk->icsk_timeout;
1968 } else if (icsk->icsk_pending == ICSK_TIME_PROBE0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001969 timer_active = 4;
Arnaldo Carvalho de Melo463c84b2005-08-09 20:10:42 -07001970 timer_expires = icsk->icsk_timeout;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001971 } else if (timer_pending(&sp->sk_timer)) {
1972 timer_active = 2;
1973 timer_expires = sp->sk_timer.expires;
1974 } else {
1975 timer_active = 0;
1976 timer_expires = jiffies;
1977 }
1978
1979 seq_printf(seq,
1980 "%4d: %08X%08X%08X%08X:%04X %08X%08X%08X%08X:%04X "
1981 "%02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %p %u %u %u %u %d\n",
1982 i,
1983 src->s6_addr32[0], src->s6_addr32[1],
1984 src->s6_addr32[2], src->s6_addr32[3], srcp,
1985 dest->s6_addr32[0], dest->s6_addr32[1],
1986 dest->s6_addr32[2], dest->s6_addr32[3], destp,
1987 sp->sk_state,
1988 tp->write_seq-tp->snd_una, tp->rcv_nxt-tp->copied_seq,
1989 timer_active,
1990 jiffies_to_clock_t(timer_expires - jiffies),
Arnaldo Carvalho de Melo463c84b2005-08-09 20:10:42 -07001991 icsk->icsk_retransmits,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001992 sock_i_uid(sp),
Arnaldo Carvalho de Melo6687e982005-08-10 04:03:31 -03001993 icsk->icsk_probes_out,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001994 sock_i_ino(sp),
1995 atomic_read(&sp->sk_refcnt), sp,
Arnaldo Carvalho de Melo463c84b2005-08-09 20:10:42 -07001996 icsk->icsk_rto,
1997 icsk->icsk_ack.ato,
1998 (icsk->icsk_ack.quick << 1 ) | icsk->icsk_ack.pingpong,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001999 tp->snd_cwnd, tp->snd_ssthresh>=0xFFFF?-1:tp->snd_ssthresh
2000 );
2001}
2002
2003static void get_timewait6_sock(struct seq_file *seq,
Arnaldo Carvalho de Melo8feaf0c02005-08-09 20:09:30 -07002004 struct inet_timewait_sock *tw, int i)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002005{
2006 struct in6_addr *dest, *src;
2007 __u16 destp, srcp;
Arnaldo Carvalho de Melo8feaf0c02005-08-09 20:09:30 -07002008 struct tcp6_timewait_sock *tcp6tw = tcp6_twsk((struct sock *)tw);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002009 int ttd = tw->tw_ttd - jiffies;
2010
2011 if (ttd < 0)
2012 ttd = 0;
2013
Arnaldo Carvalho de Melo8feaf0c02005-08-09 20:09:30 -07002014 dest = &tcp6tw->tw_v6_daddr;
2015 src = &tcp6tw->tw_v6_rcv_saddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002016 destp = ntohs(tw->tw_dport);
2017 srcp = ntohs(tw->tw_sport);
2018
2019 seq_printf(seq,
2020 "%4d: %08X%08X%08X%08X:%04X %08X%08X%08X%08X:%04X "
2021 "%02X %08X:%08X %02X:%08lX %08X %5d %8d %d %d %p\n",
2022 i,
2023 src->s6_addr32[0], src->s6_addr32[1],
2024 src->s6_addr32[2], src->s6_addr32[3], srcp,
2025 dest->s6_addr32[0], dest->s6_addr32[1],
2026 dest->s6_addr32[2], dest->s6_addr32[3], destp,
2027 tw->tw_substate, 0, 0,
2028 3, jiffies_to_clock_t(ttd), 0, 0, 0, 0,
2029 atomic_read(&tw->tw_refcnt), tw);
2030}
2031
2032#ifdef CONFIG_PROC_FS
2033static int tcp6_seq_show(struct seq_file *seq, void *v)
2034{
2035 struct tcp_iter_state *st;
2036
2037 if (v == SEQ_START_TOKEN) {
2038 seq_puts(seq,
2039 " sl "
2040 "local_address "
2041 "remote_address "
2042 "st tx_queue rx_queue tr tm->when retrnsmt"
2043 " uid timeout inode\n");
2044 goto out;
2045 }
2046 st = seq->private;
2047
2048 switch (st->state) {
2049 case TCP_SEQ_STATE_LISTENING:
2050 case TCP_SEQ_STATE_ESTABLISHED:
2051 get_tcp6_sock(seq, v, st->num);
2052 break;
2053 case TCP_SEQ_STATE_OPENREQ:
2054 get_openreq6(seq, st->syn_wait_sk, v, st->num, st->uid);
2055 break;
2056 case TCP_SEQ_STATE_TIME_WAIT:
2057 get_timewait6_sock(seq, v, st->num);
2058 break;
2059 }
2060out:
2061 return 0;
2062}
2063
2064static struct file_operations tcp6_seq_fops;
2065static struct tcp_seq_afinfo tcp6_seq_afinfo = {
2066 .owner = THIS_MODULE,
2067 .name = "tcp6",
2068 .family = AF_INET6,
2069 .seq_show = tcp6_seq_show,
2070 .seq_fops = &tcp6_seq_fops,
2071};
2072
2073int __init tcp6_proc_init(void)
2074{
2075 return tcp_proc_register(&tcp6_seq_afinfo);
2076}
2077
2078void tcp6_proc_exit(void)
2079{
2080 tcp_proc_unregister(&tcp6_seq_afinfo);
2081}
2082#endif
2083
2084struct proto tcpv6_prot = {
2085 .name = "TCPv6",
2086 .owner = THIS_MODULE,
2087 .close = tcp_close,
2088 .connect = tcp_v6_connect,
2089 .disconnect = tcp_disconnect,
Arnaldo Carvalho de Melo463c84b2005-08-09 20:10:42 -07002090 .accept = inet_csk_accept,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002091 .ioctl = tcp_ioctl,
2092 .init = tcp_v6_init_sock,
2093 .destroy = tcp_v6_destroy_sock,
2094 .shutdown = tcp_shutdown,
2095 .setsockopt = tcp_setsockopt,
2096 .getsockopt = tcp_getsockopt,
2097 .sendmsg = tcp_sendmsg,
2098 .recvmsg = tcp_recvmsg,
2099 .backlog_rcv = tcp_v6_do_rcv,
2100 .hash = tcp_v6_hash,
2101 .unhash = tcp_unhash,
2102 .get_port = tcp_v6_get_port,
2103 .enter_memory_pressure = tcp_enter_memory_pressure,
2104 .sockets_allocated = &tcp_sockets_allocated,
2105 .memory_allocated = &tcp_memory_allocated,
2106 .memory_pressure = &tcp_memory_pressure,
Arnaldo Carvalho de Melo0a5578c2005-08-09 20:11:41 -07002107 .orphan_count = &tcp_orphan_count,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002108 .sysctl_mem = sysctl_tcp_mem,
2109 .sysctl_wmem = sysctl_tcp_wmem,
2110 .sysctl_rmem = sysctl_tcp_rmem,
2111 .max_header = MAX_TCP_HEADER,
2112 .obj_size = sizeof(struct tcp6_sock),
Arnaldo Carvalho de Melo8feaf0c02005-08-09 20:09:30 -07002113 .twsk_obj_size = sizeof(struct tcp6_timewait_sock),
Arnaldo Carvalho de Melo60236fd2005-06-18 22:47:21 -07002114 .rsk_prot = &tcp6_request_sock_ops,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002115};
2116
2117static struct inet6_protocol tcpv6_protocol = {
2118 .handler = tcp_v6_rcv,
2119 .err_handler = tcp_v6_err,
2120 .flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL,
2121};
2122
Linus Torvalds1da177e2005-04-16 15:20:36 -07002123static struct inet_protosw tcpv6_protosw = {
2124 .type = SOCK_STREAM,
2125 .protocol = IPPROTO_TCP,
2126 .prot = &tcpv6_prot,
2127 .ops = &inet6_stream_ops,
2128 .capability = -1,
2129 .no_check = 0,
2130 .flags = INET_PROTOSW_PERMANENT,
2131};
2132
2133void __init tcpv6_init(void)
2134{
2135 /* register inet6 protocol */
2136 if (inet6_add_protocol(&tcpv6_protocol, IPPROTO_TCP) < 0)
2137 printk(KERN_ERR "tcpv6_init: Could not register protocol\n");
2138 inet6_register_protosw(&tcpv6_protosw);
2139}