blob: 5a439e9a4c0171fc23ed49421bc6708ef8df05d8 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * TCP over IPv6
YOSHIFUJI Hideaki1ab14572007-02-09 23:24:49 +09003 * Linux INET6 implementation
Linus Torvalds1da177e2005-04-16 15:20:36 -07004 *
5 * Authors:
YOSHIFUJI Hideaki1ab14572007-02-09 23:24:49 +09006 * Pedro Roque <roque@di.fc.ul.pt>
Linus Torvalds1da177e2005-04-16 15:20:36 -07007 *
YOSHIFUJI Hideaki1ab14572007-02-09 23:24:49 +09008 * Based on:
Linus Torvalds1da177e2005-04-16 15:20:36 -07009 * linux/net/ipv4/tcp.c
10 * linux/net/ipv4/tcp_input.c
11 * linux/net/ipv4/tcp_output.c
12 *
13 * Fixes:
14 * Hideaki YOSHIFUJI : sin6_scope_id support
15 * YOSHIFUJI Hideaki @USAGI and: Support IPV6_V6ONLY socket option, which
16 * Alexey Kuznetsov allow both IPv4 and IPv6 sockets to bind
17 * a single port at the same time.
18 * YOSHIFUJI Hideaki @USAGI: convert /proc/net/tcp6 to seq_file.
19 *
20 * This program is free software; you can redistribute it and/or
21 * modify it under the terms of the GNU General Public License
22 * as published by the Free Software Foundation; either version
23 * 2 of the License, or (at your option) any later version.
24 */
25
Herbert Xueb4dea52008-12-29 23:04:08 -080026#include <linux/bottom_half.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070027#include <linux/module.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070028#include <linux/errno.h>
29#include <linux/types.h>
30#include <linux/socket.h>
31#include <linux/sockios.h>
32#include <linux/net.h>
33#include <linux/jiffies.h>
34#include <linux/in.h>
35#include <linux/in6.h>
36#include <linux/netdevice.h>
37#include <linux/init.h>
38#include <linux/jhash.h>
39#include <linux/ipsec.h>
40#include <linux/times.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090041#include <linux/slab.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070042
43#include <linux/ipv6.h>
44#include <linux/icmpv6.h>
45#include <linux/random.h>
46
47#include <net/tcp.h>
48#include <net/ndisc.h>
Arnaldo Carvalho de Melo5324a042005-08-12 09:26:18 -030049#include <net/inet6_hashtables.h>
Arnaldo Carvalho de Melo81297652005-12-13 23:15:24 -080050#include <net/inet6_connection_sock.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>
Linus Torvalds1da177e2005-04-16 15:20:36 -070059#include <net/snmp.h>
60#include <net/dsfield.h>
Arnaldo Carvalho de Melo6d6ee432005-12-13 23:25:19 -080061#include <net/timewait_sock.h>
Jeff Garzik18134be2007-10-26 22:53:14 -070062#include <net/netdma.h>
Denis V. Lunev3d58b5f2008-04-03 14:22:32 -070063#include <net/inet_common.h>
David S. Miller6e5714e2011-08-03 20:50:44 -070064#include <net/secure_seq.h>
Glauber Costad1a4c0b2011-12-11 21:47:04 +000065#include <net/tcp_memcontrol.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070066
67#include <asm/uaccess.h>
68
69#include <linux/proc_fs.h>
70#include <linux/seq_file.h>
71
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -080072#include <linux/crypto.h>
73#include <linux/scatterlist.h>
74
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -080075static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb);
Gui Jianfeng6edafaa2008-08-06 23:50:04 -070076static void tcp_v6_reqsk_send_ack(struct sock *sk, struct sk_buff *skb,
77 struct request_sock *req);
Linus Torvalds1da177e2005-04-16 15:20:36 -070078
79static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb);
Herbert Xu8ad50d92010-04-11 02:15:54 +000080static void __tcp_v6_send_check(struct sk_buff *skb,
Eric Dumazetb71d1d42011-04-22 04:53:02 +000081 const struct in6_addr *saddr,
82 const struct in6_addr *daddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -070083
Stephen Hemminger3b401a82009-09-01 19:25:04 +000084static const struct inet_connection_sock_af_ops ipv6_mapped;
85static const struct inet_connection_sock_af_ops ipv6_specific;
David S. Millera9286302006-11-14 19:53:22 -080086#ifdef CONFIG_TCP_MD5SIG
Stephen Hemmingerb2e4b3de2009-09-01 19:25:03 +000087static const struct tcp_sock_af_ops tcp_sock_ipv6_specific;
88static const struct tcp_sock_af_ops tcp_sock_ipv6_mapped_specific;
YOSHIFUJI Hideaki9501f972008-04-18 12:45:16 +090089#else
90static struct tcp_md5sig_key *tcp_v6_md5_do_lookup(struct sock *sk,
Eric Dumazetb71d1d42011-04-22 04:53:02 +000091 const struct in6_addr *addr)
YOSHIFUJI Hideaki9501f972008-04-18 12:45:16 +090092{
93 return NULL;
94}
David S. Millera9286302006-11-14 19:53:22 -080095#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -070096
Linus Torvalds1da177e2005-04-16 15:20:36 -070097static void tcp_v6_hash(struct sock *sk)
98{
99 if (sk->sk_state != TCP_CLOSE) {
Arnaldo Carvalho de Melo8292a172005-12-13 23:15:52 -0800100 if (inet_csk(sk)->icsk_af_ops == &ipv6_mapped) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700101 tcp_prot.hash(sk);
102 return;
103 }
104 local_bh_disable();
Eric Dumazet9327f702009-12-04 03:46:54 +0000105 __inet6_hash(sk, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700106 local_bh_enable();
107 }
108}
109
Herbert Xu684f2172009-01-08 10:41:23 -0800110static __inline__ __sum16 tcp_v6_check(int len,
Eric Dumazetb71d1d42011-04-22 04:53:02 +0000111 const struct in6_addr *saddr,
112 const struct in6_addr *daddr,
Al Viro868c86b2006-11-14 21:35:48 -0800113 __wsum base)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700114{
115 return csum_ipv6_magic(saddr, daddr, len, IPPROTO_TCP, base);
116}
117
Eric Dumazetcf533ea2011-10-21 05:22:42 -0400118static __u32 tcp_v6_init_sequence(const struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700119{
Arnaldo Carvalho de Melo0660e032007-04-25 17:54:47 -0700120 return secure_tcpv6_sequence_number(ipv6_hdr(skb)->daddr.s6_addr32,
121 ipv6_hdr(skb)->saddr.s6_addr32,
Arnaldo Carvalho de Meloaa8223c2007-04-10 21:04:22 -0700122 tcp_hdr(skb)->dest,
123 tcp_hdr(skb)->source);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700124}
125
YOSHIFUJI Hideaki1ab14572007-02-09 23:24:49 +0900126static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700127 int addr_len)
128{
129 struct sockaddr_in6 *usin = (struct sockaddr_in6 *) uaddr;
YOSHIFUJI Hideaki1ab14572007-02-09 23:24:49 +0900130 struct inet_sock *inet = inet_sk(sk);
Arnaldo Carvalho de Melod83d8462005-12-13 23:26:10 -0800131 struct inet_connection_sock *icsk = inet_csk(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700132 struct ipv6_pinfo *np = inet6_sk(sk);
133 struct tcp_sock *tp = tcp_sk(sk);
Arnaud Ebalard20c59de2010-06-01 21:35:01 +0000134 struct in6_addr *saddr = NULL, *final_p, final;
David S. Miller493f3772010-12-02 12:14:29 -0800135 struct rt6_info *rt;
David S. Miller4c9483b2011-03-12 16:22:43 -0500136 struct flowi6 fl6;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700137 struct dst_entry *dst;
138 int addr_type;
139 int err;
140
YOSHIFUJI Hideaki1ab14572007-02-09 23:24:49 +0900141 if (addr_len < SIN6_LEN_RFC2133)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700142 return -EINVAL;
143
YOSHIFUJI Hideaki1ab14572007-02-09 23:24:49 +0900144 if (usin->sin6_family != AF_INET6)
Eric Dumazeta02cec22010-09-22 20:43:57 +0000145 return -EAFNOSUPPORT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700146
David S. Miller4c9483b2011-03-12 16:22:43 -0500147 memset(&fl6, 0, sizeof(fl6));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700148
149 if (np->sndflow) {
David S. Miller4c9483b2011-03-12 16:22:43 -0500150 fl6.flowlabel = usin->sin6_flowinfo&IPV6_FLOWINFO_MASK;
151 IP6_ECN_flow_init(fl6.flowlabel);
152 if (fl6.flowlabel&IPV6_FLOWLABEL_MASK) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700153 struct ip6_flowlabel *flowlabel;
David S. Miller4c9483b2011-03-12 16:22:43 -0500154 flowlabel = fl6_sock_lookup(sk, fl6.flowlabel);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700155 if (flowlabel == NULL)
156 return -EINVAL;
Alexey Dobriyan4e3fd7a2011-11-21 03:39:03 +0000157 usin->sin6_addr = flowlabel->dst;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700158 fl6_sock_release(flowlabel);
159 }
160 }
161
162 /*
YOSHIFUJI Hideaki1ab14572007-02-09 23:24:49 +0900163 * connect() to INADDR_ANY means loopback (BSD'ism).
164 */
165
166 if(ipv6_addr_any(&usin->sin6_addr))
167 usin->sin6_addr.s6_addr[15] = 0x1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700168
169 addr_type = ipv6_addr_type(&usin->sin6_addr);
170
171 if(addr_type & IPV6_ADDR_MULTICAST)
172 return -ENETUNREACH;
173
174 if (addr_type&IPV6_ADDR_LINKLOCAL) {
175 if (addr_len >= sizeof(struct sockaddr_in6) &&
176 usin->sin6_scope_id) {
177 /* If interface is set while binding, indices
178 * must coincide.
179 */
180 if (sk->sk_bound_dev_if &&
181 sk->sk_bound_dev_if != usin->sin6_scope_id)
182 return -EINVAL;
183
184 sk->sk_bound_dev_if = usin->sin6_scope_id;
185 }
186
187 /* Connect to link-local address requires an interface */
188 if (!sk->sk_bound_dev_if)
189 return -EINVAL;
190 }
191
192 if (tp->rx_opt.ts_recent_stamp &&
193 !ipv6_addr_equal(&np->daddr, &usin->sin6_addr)) {
194 tp->rx_opt.ts_recent = 0;
195 tp->rx_opt.ts_recent_stamp = 0;
196 tp->write_seq = 0;
197 }
198
Alexey Dobriyan4e3fd7a2011-11-21 03:39:03 +0000199 np->daddr = usin->sin6_addr;
David S. Miller4c9483b2011-03-12 16:22:43 -0500200 np->flow_label = fl6.flowlabel;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700201
202 /*
203 * TCP over IPv4
204 */
205
206 if (addr_type == IPV6_ADDR_MAPPED) {
Arnaldo Carvalho de Melod83d8462005-12-13 23:26:10 -0800207 u32 exthdrlen = icsk->icsk_ext_hdr_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700208 struct sockaddr_in sin;
209
210 SOCK_DEBUG(sk, "connect: ipv4 mapped\n");
211
212 if (__ipv6_only_sock(sk))
213 return -ENETUNREACH;
214
215 sin.sin_family = AF_INET;
216 sin.sin_port = usin->sin6_port;
217 sin.sin_addr.s_addr = usin->sin6_addr.s6_addr32[3];
218
Arnaldo Carvalho de Melod83d8462005-12-13 23:26:10 -0800219 icsk->icsk_af_ops = &ipv6_mapped;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700220 sk->sk_backlog_rcv = tcp_v4_do_rcv;
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800221#ifdef CONFIG_TCP_MD5SIG
222 tp->af_specific = &tcp_sock_ipv6_mapped_specific;
223#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700224
225 err = tcp_v4_connect(sk, (struct sockaddr *)&sin, sizeof(sin));
226
227 if (err) {
Arnaldo Carvalho de Melod83d8462005-12-13 23:26:10 -0800228 icsk->icsk_ext_hdr_len = exthdrlen;
229 icsk->icsk_af_ops = &ipv6_specific;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700230 sk->sk_backlog_rcv = tcp_v6_do_rcv;
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800231#ifdef CONFIG_TCP_MD5SIG
232 tp->af_specific = &tcp_sock_ipv6_specific;
233#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700234 goto failure;
235 } else {
Eric Dumazetc720c7e82009-10-15 06:30:45 +0000236 ipv6_addr_set_v4mapped(inet->inet_saddr, &np->saddr);
237 ipv6_addr_set_v4mapped(inet->inet_rcv_saddr,
238 &np->rcv_saddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700239 }
240
241 return err;
242 }
243
244 if (!ipv6_addr_any(&np->rcv_saddr))
245 saddr = &np->rcv_saddr;
246
David S. Miller4c9483b2011-03-12 16:22:43 -0500247 fl6.flowi6_proto = IPPROTO_TCP;
Alexey Dobriyan4e3fd7a2011-11-21 03:39:03 +0000248 fl6.daddr = np->daddr;
249 fl6.saddr = saddr ? *saddr : np->saddr;
David S. Miller4c9483b2011-03-12 16:22:43 -0500250 fl6.flowi6_oif = sk->sk_bound_dev_if;
251 fl6.flowi6_mark = sk->sk_mark;
David S. Miller1958b852011-03-12 16:36:19 -0500252 fl6.fl6_dport = usin->sin6_port;
253 fl6.fl6_sport = inet->inet_sport;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700254
David S. Miller4c9483b2011-03-12 16:22:43 -0500255 final_p = fl6_update_dst(&fl6, np->opt, &final);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700256
David S. Miller4c9483b2011-03-12 16:22:43 -0500257 security_sk_classify_flow(sk, flowi6_to_flowi(&fl6));
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -0700258
David S. Miller4c9483b2011-03-12 16:22:43 -0500259 dst = ip6_dst_lookup_flow(sk, &fl6, final_p, true);
David S. Miller68d0c6d2011-03-01 13:19:07 -0800260 if (IS_ERR(dst)) {
261 err = PTR_ERR(dst);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700262 goto failure;
David S. Miller14e50e52007-05-24 18:17:54 -0700263 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700264
265 if (saddr == NULL) {
David S. Miller4c9483b2011-03-12 16:22:43 -0500266 saddr = &fl6.saddr;
Alexey Dobriyan4e3fd7a2011-11-21 03:39:03 +0000267 np->rcv_saddr = *saddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700268 }
269
270 /* set the source address */
Alexey Dobriyan4e3fd7a2011-11-21 03:39:03 +0000271 np->saddr = *saddr;
Eric Dumazetc720c7e82009-10-15 06:30:45 +0000272 inet->inet_rcv_saddr = LOOPBACK4_IPV6;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700273
Herbert Xuf83ef8c2006-06-30 13:37:03 -0700274 sk->sk_gso_type = SKB_GSO_TCPV6;
YOSHIFUJI Hideaki8e1ef0a2006-08-29 17:15:09 -0700275 __ip6_dst_store(sk, dst, NULL, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700276
David S. Miller493f3772010-12-02 12:14:29 -0800277 rt = (struct rt6_info *) dst;
278 if (tcp_death_row.sysctl_tw_recycle &&
279 !tp->rx_opt.ts_recent_stamp &&
David S. Miller81166dd2012-07-10 03:14:24 -0700280 ipv6_addr_equal(&rt->rt6i_dst.addr, &np->daddr))
281 tcp_fetch_timewait_stamp(sk, dst);
David S. Miller493f3772010-12-02 12:14:29 -0800282
Arnaldo Carvalho de Melod83d8462005-12-13 23:26:10 -0800283 icsk->icsk_ext_hdr_len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700284 if (np->opt)
Arnaldo Carvalho de Melod83d8462005-12-13 23:26:10 -0800285 icsk->icsk_ext_hdr_len = (np->opt->opt_flen +
286 np->opt->opt_nflen);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700287
288 tp->rx_opt.mss_clamp = IPV6_MIN_MTU - sizeof(struct tcphdr) - sizeof(struct ipv6hdr);
289
Eric Dumazetc720c7e82009-10-15 06:30:45 +0000290 inet->inet_dport = usin->sin6_port;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700291
292 tcp_set_state(sk, TCP_SYN_SENT);
Arnaldo Carvalho de Melod8313f52005-12-13 23:25:44 -0800293 err = inet6_hash_connect(&tcp_death_row, sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700294 if (err)
295 goto late_failure;
296
297 if (!tp->write_seq)
298 tp->write_seq = secure_tcpv6_sequence_number(np->saddr.s6_addr32,
299 np->daddr.s6_addr32,
Eric Dumazetc720c7e82009-10-15 06:30:45 +0000300 inet->inet_sport,
301 inet->inet_dport);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700302
303 err = tcp_connect(sk);
304 if (err)
305 goto late_failure;
306
307 return 0;
308
309late_failure:
310 tcp_set_state(sk, TCP_CLOSE);
311 __sk_dst_reset(sk);
312failure:
Eric Dumazetc720c7e82009-10-15 06:30:45 +0000313 inet->inet_dport = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700314 sk->sk_route_caps = 0;
315 return err;
316}
317
Eric Dumazet563d34d2012-07-23 09:48:52 +0200318static void tcp_v6_mtu_reduced(struct sock *sk)
319{
320 struct dst_entry *dst;
321
322 if ((1 << sk->sk_state) & (TCPF_LISTEN | TCPF_CLOSE))
323 return;
324
325 dst = inet6_csk_update_pmtu(sk, tcp_sk(sk)->mtu_info);
326 if (!dst)
327 return;
328
329 if (inet_csk(sk)->icsk_pmtu_cookie > dst_mtu(dst)) {
330 tcp_sync_mss(sk, dst_mtu(dst));
331 tcp_simple_retransmit(sk);
332 }
333}
334
Linus Torvalds1da177e2005-04-16 15:20:36 -0700335static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
Brian Haleyd5fdd6b2009-06-23 04:31:07 -0700336 u8 type, u8 code, int offset, __be32 info)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700337{
Eric Dumazetb71d1d42011-04-22 04:53:02 +0000338 const struct ipv6hdr *hdr = (const struct ipv6hdr*)skb->data;
Arnaldo Carvalho de Melo505cbfc2005-08-12 09:19:38 -0300339 const struct tcphdr *th = (struct tcphdr *)(skb->data+offset);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700340 struct ipv6_pinfo *np;
341 struct sock *sk;
342 int err;
YOSHIFUJI Hideaki1ab14572007-02-09 23:24:49 +0900343 struct tcp_sock *tp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700344 __u32 seq;
Pavel Emelyanovca12a1a2008-07-16 20:28:42 -0700345 struct net *net = dev_net(skb->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700346
Pavel Emelyanovca12a1a2008-07-16 20:28:42 -0700347 sk = inet6_lookup(net, &tcp_hashinfo, &hdr->daddr,
Pavel Emelyanovd86e0da2008-01-31 05:07:21 -0800348 th->dest, &hdr->saddr, th->source, skb->dev->ifindex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700349
350 if (sk == NULL) {
Denis V. Luneve41b5362008-10-08 10:33:26 -0700351 ICMP6_INC_STATS_BH(net, __in6_dev_get(skb->dev),
352 ICMP6_MIB_INERRORS);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700353 return;
354 }
355
356 if (sk->sk_state == TCP_TIME_WAIT) {
YOSHIFUJI Hideaki9469c7b2006-10-10 19:41:46 -0700357 inet_twsk_put(inet_twsk(sk));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700358 return;
359 }
360
361 bh_lock_sock(sk);
Eric Dumazet563d34d2012-07-23 09:48:52 +0200362 if (sock_owned_by_user(sk) && type != ICMPV6_PKT_TOOBIG)
Pavel Emelyanovde0744a2008-07-16 20:31:16 -0700363 NET_INC_STATS_BH(net, LINUX_MIB_LOCKDROPPEDICMPS);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700364
365 if (sk->sk_state == TCP_CLOSE)
366 goto out;
367
Stephen Hemmingere802af92010-04-22 15:24:53 -0700368 if (ipv6_hdr(skb)->hop_limit < inet6_sk(sk)->min_hopcount) {
369 NET_INC_STATS_BH(net, LINUX_MIB_TCPMINTTLDROP);
370 goto out;
371 }
372
Linus Torvalds1da177e2005-04-16 15:20:36 -0700373 tp = tcp_sk(sk);
YOSHIFUJI Hideaki1ab14572007-02-09 23:24:49 +0900374 seq = ntohl(th->seq);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700375 if (sk->sk_state != TCP_LISTEN &&
376 !between(seq, tp->snd_una, tp->snd_nxt)) {
Pavel Emelyanovde0744a2008-07-16 20:31:16 -0700377 NET_INC_STATS_BH(net, LINUX_MIB_OUTOFWINDOWICMPS);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700378 goto out;
379 }
380
381 np = inet6_sk(sk);
382
David S. Millerec18d9a2012-07-12 00:25:15 -0700383 if (type == NDISC_REDIRECT) {
384 struct dst_entry *dst = __sk_dst_check(sk, np->dst_cookie);
385
David S. Miller1ed5c482012-07-12 00:41:25 -0700386 if (dst)
David S. Miller6700c272012-07-17 03:29:28 -0700387 dst->ops->redirect(dst, sk, skb);
David S. Millerec18d9a2012-07-12 00:25:15 -0700388 }
389
Linus Torvalds1da177e2005-04-16 15:20:36 -0700390 if (type == ICMPV6_PKT_TOOBIG) {
Eric Dumazet563d34d2012-07-23 09:48:52 +0200391 tp->mtu_info = ntohl(info);
392 if (!sock_owned_by_user(sk))
393 tcp_v6_mtu_reduced(sk);
394 else
395 set_bit(TCP_MTU_REDUCED_DEFERRED, &tp->tsq_flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700396 goto out;
397 }
398
399 icmpv6_err_convert(type, code, &err);
400
Arnaldo Carvalho de Melo60236fd2005-06-18 22:47:21 -0700401 /* Might be for an request_sock */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700402 switch (sk->sk_state) {
Arnaldo Carvalho de Melo60236fd2005-06-18 22:47:21 -0700403 struct request_sock *req, **prev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700404 case TCP_LISTEN:
405 if (sock_owned_by_user(sk))
406 goto out;
407
Arnaldo Carvalho de Melo81297652005-12-13 23:15:24 -0800408 req = inet6_csk_search_req(sk, &prev, th->dest, &hdr->daddr,
409 &hdr->saddr, inet6_iif(skb));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700410 if (!req)
411 goto out;
412
413 /* ICMPs are not backlogged, hence we cannot get
414 * an established socket here.
415 */
Ilpo Järvinen547b7922008-07-25 21:43:18 -0700416 WARN_ON(req->sk != NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700417
Arnaldo Carvalho de Melo2e6599c2005-06-18 22:46:52 -0700418 if (seq != tcp_rsk(req)->snt_isn) {
Pavel Emelyanovde0744a2008-07-16 20:31:16 -0700419 NET_INC_STATS_BH(net, LINUX_MIB_OUTOFWINDOWICMPS);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700420 goto out;
421 }
422
Arnaldo Carvalho de Melo463c84b2005-08-09 20:10:42 -0700423 inet_csk_reqsk_queue_drop(sk, req, prev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700424 goto out;
425
426 case TCP_SYN_SENT:
427 case TCP_SYN_RECV: /* Cannot happen.
YOSHIFUJI Hideaki1ab14572007-02-09 23:24:49 +0900428 It can, it SYNs are crossed. --ANK */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700429 if (!sock_owned_by_user(sk)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700430 sk->sk_err = err;
431 sk->sk_error_report(sk); /* Wake people up to see the error (see connect in sock.c) */
432
433 tcp_done(sk);
434 } else
435 sk->sk_err_soft = err;
436 goto out;
437 }
438
439 if (!sock_owned_by_user(sk) && np->recverr) {
440 sk->sk_err = err;
441 sk->sk_error_report(sk);
442 } else
443 sk->sk_err_soft = err;
444
445out:
446 bh_unlock_sock(sk);
447 sock_put(sk);
448}
449
450
Neal Cardwell9f10d3f2012-06-28 12:34:21 +0000451static int tcp_v6_send_synack(struct sock *sk, struct dst_entry *dst,
452 struct flowi6 *fl6,
Neal Cardwell3840a062012-06-28 12:34:19 +0000453 struct request_sock *req,
Eric Dumazetfff32692012-06-01 01:47:50 +0000454 struct request_values *rvp,
455 u16 queue_mapping)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700456{
Arnaldo Carvalho de Meloca304b62005-12-13 23:15:40 -0800457 struct inet6_request_sock *treq = inet6_rsk(req);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700458 struct ipv6_pinfo *np = inet6_sk(sk);
459 struct sk_buff * skb;
Neal Cardwell94942182012-06-28 12:34:20 +0000460 int err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700461
Neal Cardwell9f10d3f2012-06-28 12:34:21 +0000462 /* First, grab a route. */
463 if (!dst && (dst = inet6_csk_route_req(sk, fl6, req)) == NULL)
Denis V. Lunevfd80eb92008-02-29 11:43:03 -0800464 goto done;
Neal Cardwell94942182012-06-28 12:34:20 +0000465
William Allen Simpsone6b4d112009-12-02 18:07:39 +0000466 skb = tcp_make_synack(sk, dst, req, rvp);
Neal Cardwell94942182012-06-28 12:34:20 +0000467
Linus Torvalds1da177e2005-04-16 15:20:36 -0700468 if (skb) {
Herbert Xu8ad50d92010-04-11 02:15:54 +0000469 __tcp_v6_send_check(skb, &treq->loc_addr, &treq->rmt_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700470
Neal Cardwell9f10d3f2012-06-28 12:34:21 +0000471 fl6->daddr = treq->rmt_addr;
Eric Dumazetfff32692012-06-01 01:47:50 +0000472 skb_set_queue_mapping(skb, queue_mapping);
RongQing.Li43264e02012-07-01 17:18:59 +0000473 err = ip6_xmit(sk, skb, fl6, np->opt, np->tclass);
Gerrit Renkerb9df3cb2006-11-14 11:21:36 -0200474 err = net_xmit_eval(err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700475 }
476
477done:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700478 return err;
479}
480
Octavian Purdila72659ec2010-01-17 19:09:39 -0800481static int tcp_v6_rtx_synack(struct sock *sk, struct request_sock *req,
482 struct request_values *rvp)
483{
Neal Cardwell9f10d3f2012-06-28 12:34:21 +0000484 struct flowi6 fl6;
485
Octavian Purdila72659ec2010-01-17 19:09:39 -0800486 TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_RETRANSSEGS);
Neal Cardwell9f10d3f2012-06-28 12:34:21 +0000487 return tcp_v6_send_synack(sk, NULL, &fl6, req, rvp, 0);
Octavian Purdila72659ec2010-01-17 19:09:39 -0800488}
489
Arnaldo Carvalho de Melo60236fd2005-06-18 22:47:21 -0700490static void tcp_v6_reqsk_destructor(struct request_sock *req)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700491{
Wei Yongjun800d55f2009-02-23 21:45:33 +0000492 kfree_skb(inet6_rsk(req)->pktopts);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700493}
494
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800495#ifdef CONFIG_TCP_MD5SIG
496static struct tcp_md5sig_key *tcp_v6_md5_do_lookup(struct sock *sk,
Eric Dumazetb71d1d42011-04-22 04:53:02 +0000497 const struct in6_addr *addr)
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800498{
Eric Dumazeta915da9b2012-01-31 05:18:33 +0000499 return tcp_md5_do_lookup(sk, (union tcp_md5_addr *)addr, AF_INET6);
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800500}
501
502static struct tcp_md5sig_key *tcp_v6_md5_lookup(struct sock *sk,
503 struct sock *addr_sk)
504{
505 return tcp_v6_md5_do_lookup(sk, &inet6_sk(addr_sk)->daddr);
506}
507
508static struct tcp_md5sig_key *tcp_v6_reqsk_md5_lookup(struct sock *sk,
509 struct request_sock *req)
510{
511 return tcp_v6_md5_do_lookup(sk, &inet6_rsk(req)->rmt_addr);
512}
513
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800514static int tcp_v6_parse_md5_keys (struct sock *sk, char __user *optval,
515 int optlen)
516{
517 struct tcp_md5sig cmd;
518 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&cmd.tcpm_addr;
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800519
520 if (optlen < sizeof(cmd))
521 return -EINVAL;
522
523 if (copy_from_user(&cmd, optval, sizeof(cmd)))
524 return -EFAULT;
525
526 if (sin6->sin6_family != AF_INET6)
527 return -EINVAL;
528
529 if (!cmd.tcpm_keylen) {
Brian Haleye773e4f2007-08-24 23:16:08 -0700530 if (ipv6_addr_v4mapped(&sin6->sin6_addr))
Eric Dumazeta915da9b2012-01-31 05:18:33 +0000531 return tcp_md5_do_del(sk, (union tcp_md5_addr *)&sin6->sin6_addr.s6_addr32[3],
532 AF_INET);
533 return tcp_md5_do_del(sk, (union tcp_md5_addr *)&sin6->sin6_addr,
534 AF_INET6);
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800535 }
536
537 if (cmd.tcpm_keylen > TCP_MD5SIG_MAXKEYLEN)
538 return -EINVAL;
539
Eric Dumazeta915da9b2012-01-31 05:18:33 +0000540 if (ipv6_addr_v4mapped(&sin6->sin6_addr))
541 return tcp_md5_do_add(sk, (union tcp_md5_addr *)&sin6->sin6_addr.s6_addr32[3],
542 AF_INET, cmd.tcpm_key, cmd.tcpm_keylen, GFP_KERNEL);
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800543
Eric Dumazeta915da9b2012-01-31 05:18:33 +0000544 return tcp_md5_do_add(sk, (union tcp_md5_addr *)&sin6->sin6_addr,
545 AF_INET6, cmd.tcpm_key, cmd.tcpm_keylen, GFP_KERNEL);
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800546}
547
Adam Langley49a72df2008-07-19 00:01:42 -0700548static int tcp_v6_md5_hash_pseudoheader(struct tcp_md5sig_pool *hp,
Eric Dumazetb71d1d42011-04-22 04:53:02 +0000549 const struct in6_addr *daddr,
550 const struct in6_addr *saddr, int nbytes)
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800551{
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800552 struct tcp6_pseudohdr *bp;
Adam Langley49a72df2008-07-19 00:01:42 -0700553 struct scatterlist sg;
YOSHIFUJI Hideaki8d26d762008-04-17 13:19:16 +0900554
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800555 bp = &hp->md5_blk.ip6;
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800556 /* 1. TCP pseudo-header (RFC2460) */
Alexey Dobriyan4e3fd7a2011-11-21 03:39:03 +0000557 bp->saddr = *saddr;
558 bp->daddr = *daddr;
Adam Langley49a72df2008-07-19 00:01:42 -0700559 bp->protocol = cpu_to_be32(IPPROTO_TCP);
Adam Langley00b13042008-07-31 21:36:07 -0700560 bp->len = cpu_to_be32(nbytes);
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800561
Adam Langley49a72df2008-07-19 00:01:42 -0700562 sg_init_one(&sg, bp, sizeof(*bp));
563 return crypto_hash_update(&hp->md5_desc, &sg, sizeof(*bp));
564}
David S. Millerc7da57a2007-10-26 00:41:21 -0700565
Adam Langley49a72df2008-07-19 00:01:42 -0700566static int tcp_v6_md5_hash_hdr(char *md5_hash, struct tcp_md5sig_key *key,
Eric Dumazetb71d1d42011-04-22 04:53:02 +0000567 const struct in6_addr *daddr, struct in6_addr *saddr,
Eric Dumazet318cf7a2011-10-24 02:46:04 -0400568 const struct tcphdr *th)
Adam Langley49a72df2008-07-19 00:01:42 -0700569{
570 struct tcp_md5sig_pool *hp;
571 struct hash_desc *desc;
572
573 hp = tcp_get_md5sig_pool();
574 if (!hp)
575 goto clear_hash_noput;
576 desc = &hp->md5_desc;
577
578 if (crypto_hash_init(desc))
579 goto clear_hash;
580 if (tcp_v6_md5_hash_pseudoheader(hp, daddr, saddr, th->doff << 2))
581 goto clear_hash;
582 if (tcp_md5_hash_header(hp, th))
583 goto clear_hash;
584 if (tcp_md5_hash_key(hp, key))
585 goto clear_hash;
586 if (crypto_hash_final(desc, md5_hash))
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800587 goto clear_hash;
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800588
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800589 tcp_put_md5sig_pool();
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800590 return 0;
Adam Langley49a72df2008-07-19 00:01:42 -0700591
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800592clear_hash:
593 tcp_put_md5sig_pool();
594clear_hash_noput:
595 memset(md5_hash, 0, 16);
Adam Langley49a72df2008-07-19 00:01:42 -0700596 return 1;
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800597}
598
Adam Langley49a72df2008-07-19 00:01:42 -0700599static int tcp_v6_md5_hash_skb(char *md5_hash, struct tcp_md5sig_key *key,
Eric Dumazet318cf7a2011-10-24 02:46:04 -0400600 const struct sock *sk,
601 const struct request_sock *req,
602 const struct sk_buff *skb)
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800603{
Eric Dumazetb71d1d42011-04-22 04:53:02 +0000604 const struct in6_addr *saddr, *daddr;
Adam Langley49a72df2008-07-19 00:01:42 -0700605 struct tcp_md5sig_pool *hp;
606 struct hash_desc *desc;
Eric Dumazet318cf7a2011-10-24 02:46:04 -0400607 const struct tcphdr *th = tcp_hdr(skb);
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800608
609 if (sk) {
610 saddr = &inet6_sk(sk)->saddr;
611 daddr = &inet6_sk(sk)->daddr;
Adam Langley49a72df2008-07-19 00:01:42 -0700612 } else if (req) {
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800613 saddr = &inet6_rsk(req)->loc_addr;
614 daddr = &inet6_rsk(req)->rmt_addr;
Adam Langley49a72df2008-07-19 00:01:42 -0700615 } else {
Eric Dumazetb71d1d42011-04-22 04:53:02 +0000616 const struct ipv6hdr *ip6h = ipv6_hdr(skb);
Adam Langley49a72df2008-07-19 00:01:42 -0700617 saddr = &ip6h->saddr;
618 daddr = &ip6h->daddr;
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800619 }
Adam Langley49a72df2008-07-19 00:01:42 -0700620
621 hp = tcp_get_md5sig_pool();
622 if (!hp)
623 goto clear_hash_noput;
624 desc = &hp->md5_desc;
625
626 if (crypto_hash_init(desc))
627 goto clear_hash;
628
629 if (tcp_v6_md5_hash_pseudoheader(hp, daddr, saddr, skb->len))
630 goto clear_hash;
631 if (tcp_md5_hash_header(hp, th))
632 goto clear_hash;
633 if (tcp_md5_hash_skb_data(hp, skb, th->doff << 2))
634 goto clear_hash;
635 if (tcp_md5_hash_key(hp, key))
636 goto clear_hash;
637 if (crypto_hash_final(desc, md5_hash))
638 goto clear_hash;
639
640 tcp_put_md5sig_pool();
641 return 0;
642
643clear_hash:
644 tcp_put_md5sig_pool();
645clear_hash_noput:
646 memset(md5_hash, 0, 16);
647 return 1;
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800648}
649
Eric Dumazet318cf7a2011-10-24 02:46:04 -0400650static int tcp_v6_inbound_md5_hash(struct sock *sk, const struct sk_buff *skb)
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800651{
Eric Dumazetcf533ea2011-10-21 05:22:42 -0400652 const __u8 *hash_location = NULL;
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800653 struct tcp_md5sig_key *hash_expected;
Eric Dumazetb71d1d42011-04-22 04:53:02 +0000654 const struct ipv6hdr *ip6h = ipv6_hdr(skb);
Eric Dumazet318cf7a2011-10-24 02:46:04 -0400655 const struct tcphdr *th = tcp_hdr(skb);
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800656 int genhash;
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800657 u8 newhash[16];
658
659 hash_expected = tcp_v6_md5_do_lookup(sk, &ip6h->saddr);
YOSHIFUJI Hideaki7d5d5522008-04-17 12:29:53 +0900660 hash_location = tcp_parse_md5sig_option(th);
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800661
David S. Miller785957d2008-07-30 03:03:15 -0700662 /* We've parsed the options - do we have a hash? */
663 if (!hash_expected && !hash_location)
664 return 0;
665
666 if (hash_expected && !hash_location) {
667 NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPMD5NOTFOUND);
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800668 return 1;
669 }
670
David S. Miller785957d2008-07-30 03:03:15 -0700671 if (!hash_expected && hash_location) {
672 NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPMD5UNEXPECTED);
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800673 return 1;
674 }
675
676 /* check the signature */
Adam Langley49a72df2008-07-19 00:01:42 -0700677 genhash = tcp_v6_md5_hash_skb(newhash,
678 hash_expected,
679 NULL, NULL, skb);
680
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800681 if (genhash || memcmp(hash_location, newhash, 16) != 0) {
Joe Perchese87cc472012-05-13 21:56:26 +0000682 net_info_ratelimited("MD5 Hash %s for [%pI6c]:%u->[%pI6c]:%u\n",
683 genhash ? "failed" : "mismatch",
684 &ip6h->saddr, ntohs(th->source),
685 &ip6h->daddr, ntohs(th->dest));
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800686 return 1;
687 }
688 return 0;
689}
690#endif
691
Glenn Griffinc6aefaf2008-02-07 21:49:26 -0800692struct request_sock_ops tcp6_request_sock_ops __read_mostly = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700693 .family = AF_INET6,
Arnaldo Carvalho de Melo2e6599c2005-06-18 22:46:52 -0700694 .obj_size = sizeof(struct tcp6_request_sock),
Octavian Purdila72659ec2010-01-17 19:09:39 -0800695 .rtx_syn_ack = tcp_v6_rtx_synack,
Arnaldo Carvalho de Melo60236fd2005-06-18 22:47:21 -0700696 .send_ack = tcp_v6_reqsk_send_ack,
697 .destructor = tcp_v6_reqsk_destructor,
Octavian Purdila72659ec2010-01-17 19:09:39 -0800698 .send_reset = tcp_v6_send_reset,
699 .syn_ack_timeout = tcp_syn_ack_timeout,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700700};
701
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800702#ifdef CONFIG_TCP_MD5SIG
Stephen Hemmingerb2e4b3de2009-09-01 19:25:03 +0000703static const struct tcp_request_sock_ops tcp_request_sock_ipv6_ops = {
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800704 .md5_lookup = tcp_v6_reqsk_md5_lookup,
John Dykstrae3afe7b2009-07-16 05:04:51 +0000705 .calc_md5_hash = tcp_v6_md5_hash_skb,
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800706};
Andrew Mortonb6332e62006-11-30 19:16:28 -0800707#endif
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800708
Herbert Xu8ad50d92010-04-11 02:15:54 +0000709static void __tcp_v6_send_check(struct sk_buff *skb,
Eric Dumazetb71d1d42011-04-22 04:53:02 +0000710 const struct in6_addr *saddr, const struct in6_addr *daddr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700711{
Arnaldo Carvalho de Meloaa8223c2007-04-10 21:04:22 -0700712 struct tcphdr *th = tcp_hdr(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700713
Patrick McHardy84fa7932006-08-29 16:44:56 -0700714 if (skb->ip_summed == CHECKSUM_PARTIAL) {
Herbert Xu8ad50d92010-04-11 02:15:54 +0000715 th->check = ~tcp_v6_check(skb->len, saddr, daddr, 0);
Herbert Xu663ead32007-04-09 11:59:07 -0700716 skb->csum_start = skb_transport_header(skb) - skb->head;
Al Viroff1dcad2006-11-20 18:07:29 -0800717 skb->csum_offset = offsetof(struct tcphdr, check);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700718 } else {
Herbert Xu8ad50d92010-04-11 02:15:54 +0000719 th->check = tcp_v6_check(skb->len, saddr, daddr,
720 csum_partial(th, th->doff << 2,
721 skb->csum));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700722 }
723}
724
Herbert Xubb296242010-04-11 02:15:55 +0000725static void tcp_v6_send_check(struct sock *sk, struct sk_buff *skb)
Herbert Xu8ad50d92010-04-11 02:15:54 +0000726{
727 struct ipv6_pinfo *np = inet6_sk(sk);
728
729 __tcp_v6_send_check(skb, &np->saddr, &np->daddr);
730}
731
Herbert Xua430a432006-07-08 13:34:56 -0700732static int tcp_v6_gso_send_check(struct sk_buff *skb)
733{
Eric Dumazetb71d1d42011-04-22 04:53:02 +0000734 const struct ipv6hdr *ipv6h;
Herbert Xua430a432006-07-08 13:34:56 -0700735 struct tcphdr *th;
736
737 if (!pskb_may_pull(skb, sizeof(*th)))
738 return -EINVAL;
739
Arnaldo Carvalho de Melo0660e032007-04-25 17:54:47 -0700740 ipv6h = ipv6_hdr(skb);
Arnaldo Carvalho de Meloaa8223c2007-04-10 21:04:22 -0700741 th = tcp_hdr(skb);
Herbert Xua430a432006-07-08 13:34:56 -0700742
743 th->check = 0;
Patrick McHardy84fa7932006-08-29 16:44:56 -0700744 skb->ip_summed = CHECKSUM_PARTIAL;
Herbert Xu8ad50d92010-04-11 02:15:54 +0000745 __tcp_v6_send_check(skb, &ipv6h->saddr, &ipv6h->daddr);
Herbert Xua430a432006-07-08 13:34:56 -0700746 return 0;
747}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700748
Herbert Xu36990672009-05-22 00:45:28 -0700749static struct sk_buff **tcp6_gro_receive(struct sk_buff **head,
750 struct sk_buff *skb)
Herbert Xu684f2172009-01-08 10:41:23 -0800751{
Eric Dumazetb71d1d42011-04-22 04:53:02 +0000752 const struct ipv6hdr *iph = skb_gro_network_header(skb);
Herbert Xu684f2172009-01-08 10:41:23 -0800753
754 switch (skb->ip_summed) {
755 case CHECKSUM_COMPLETE:
Herbert Xu86911732009-01-29 14:19:50 +0000756 if (!tcp_v6_check(skb_gro_len(skb), &iph->saddr, &iph->daddr,
Herbert Xu684f2172009-01-08 10:41:23 -0800757 skb->csum)) {
758 skb->ip_summed = CHECKSUM_UNNECESSARY;
759 break;
760 }
761
762 /* fall through */
763 case CHECKSUM_NONE:
764 NAPI_GRO_CB(skb)->flush = 1;
765 return NULL;
766 }
767
768 return tcp_gro_receive(head, skb);
769}
Herbert Xu684f2172009-01-08 10:41:23 -0800770
Herbert Xu36990672009-05-22 00:45:28 -0700771static int tcp6_gro_complete(struct sk_buff *skb)
Herbert Xu684f2172009-01-08 10:41:23 -0800772{
Eric Dumazetb71d1d42011-04-22 04:53:02 +0000773 const struct ipv6hdr *iph = ipv6_hdr(skb);
Herbert Xu684f2172009-01-08 10:41:23 -0800774 struct tcphdr *th = tcp_hdr(skb);
775
776 th->check = ~tcp_v6_check(skb->len - skb_transport_offset(skb),
777 &iph->saddr, &iph->daddr, 0);
778 skb_shinfo(skb)->gso_type = SKB_GSO_TCPV6;
779
780 return tcp_gro_complete(skb);
781}
Herbert Xu684f2172009-01-08 10:41:23 -0800782
Ilpo Järvinen626e2642008-10-09 14:42:40 -0700783static void tcp_v6_send_response(struct sk_buff *skb, u32 seq, u32 ack, u32 win,
Eric Dumazetb903d322011-10-27 00:44:35 -0400784 u32 ts, struct tcp_md5sig_key *key, int rst, u8 tclass)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700785{
Eric Dumazetcf533ea2011-10-21 05:22:42 -0400786 const struct tcphdr *th = tcp_hdr(skb);
787 struct tcphdr *t1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700788 struct sk_buff *buff;
David S. Miller4c9483b2011-03-12 16:22:43 -0500789 struct flowi6 fl6;
Eric Dumazetadf30902009-06-02 05:19:30 +0000790 struct net *net = dev_net(skb_dst(skb)->dev);
Daniel Lezcanoe5047992008-03-07 11:16:26 -0800791 struct sock *ctl_sk = net->ipv6.tcp_sk;
YOSHIFUJI Hideaki9cb57342008-01-12 02:16:03 -0800792 unsigned int tot_len = sizeof(struct tcphdr);
Eric Dumazetadf30902009-06-02 05:19:30 +0000793 struct dst_entry *dst;
Al Viroe69a4ad2006-11-14 20:56:00 -0800794 __be32 *topt;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700795
796 if (ts)
YOSHIFUJI Hideaki4244f8a2006-10-10 19:40:50 -0700797 tot_len += TCPOLEN_TSTAMP_ALIGNED;
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800798#ifdef CONFIG_TCP_MD5SIG
799 if (key)
800 tot_len += TCPOLEN_MD5SIG_ALIGNED;
801#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700802
803 buff = alloc_skb(MAX_HEADER + sizeof(struct ipv6hdr) + tot_len,
804 GFP_ATOMIC);
805 if (buff == NULL)
806 return;
807
808 skb_reserve(buff, MAX_HEADER + sizeof(struct ipv6hdr) + tot_len);
809
Ilpo Järvinen77c676d2008-10-09 14:41:38 -0700810 t1 = (struct tcphdr *) skb_push(buff, tot_len);
Herbert Xu6651ffc2010-04-21 00:47:15 -0700811 skb_reset_transport_header(buff);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700812
813 /* Swap the send and the receive. */
814 memset(t1, 0, sizeof(*t1));
815 t1->dest = th->source;
816 t1->source = th->dest;
Ilpo Järvinen77c676d2008-10-09 14:41:38 -0700817 t1->doff = tot_len / 4;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700818 t1->seq = htonl(seq);
819 t1->ack_seq = htonl(ack);
Ilpo Järvinen626e2642008-10-09 14:42:40 -0700820 t1->ack = !rst || !th->ack;
821 t1->rst = rst;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700822 t1->window = htons(win);
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800823
Al Viroe69a4ad2006-11-14 20:56:00 -0800824 topt = (__be32 *)(t1 + 1);
YOSHIFUJI Hideaki1ab14572007-02-09 23:24:49 +0900825
Linus Torvalds1da177e2005-04-16 15:20:36 -0700826 if (ts) {
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800827 *topt++ = htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) |
828 (TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP);
829 *topt++ = htonl(tcp_time_stamp);
Ilpo Järvinen53b12572008-10-08 14:36:33 -0700830 *topt++ = htonl(ts);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700831 }
832
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800833#ifdef CONFIG_TCP_MD5SIG
834 if (key) {
835 *topt++ = htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) |
836 (TCPOPT_MD5SIG << 8) | TCPOLEN_MD5SIG);
Adam Langley49a72df2008-07-19 00:01:42 -0700837 tcp_v6_md5_hash_hdr((__u8 *)topt, key,
Adam Langley90b7e112008-07-31 20:49:48 -0700838 &ipv6_hdr(skb)->saddr,
839 &ipv6_hdr(skb)->daddr, t1);
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800840 }
841#endif
842
David S. Miller4c9483b2011-03-12 16:22:43 -0500843 memset(&fl6, 0, sizeof(fl6));
Alexey Dobriyan4e3fd7a2011-11-21 03:39:03 +0000844 fl6.daddr = ipv6_hdr(skb)->saddr;
845 fl6.saddr = ipv6_hdr(skb)->daddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700846
David S. Millere5700af2010-04-21 14:59:20 -0700847 buff->ip_summed = CHECKSUM_PARTIAL;
848 buff->csum = 0;
849
David S. Miller4c9483b2011-03-12 16:22:43 -0500850 __tcp_v6_send_check(buff, &fl6.saddr, &fl6.daddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700851
David S. Miller4c9483b2011-03-12 16:22:43 -0500852 fl6.flowi6_proto = IPPROTO_TCP;
853 fl6.flowi6_oif = inet6_iif(skb);
David S. Miller1958b852011-03-12 16:36:19 -0500854 fl6.fl6_dport = t1->dest;
855 fl6.fl6_sport = t1->source;
David S. Miller4c9483b2011-03-12 16:22:43 -0500856 security_skb_classify_flow(skb, flowi6_to_flowi(&fl6));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700857
Ilpo Järvinen626e2642008-10-09 14:42:40 -0700858 /* Pass a socket to ip6_dst_lookup either it is for RST
859 * Underlying function will use this to retrieve the network
860 * namespace
861 */
David S. Miller4c9483b2011-03-12 16:22:43 -0500862 dst = ip6_dst_lookup_flow(ctl_sk, &fl6, NULL, false);
David S. Miller68d0c6d2011-03-01 13:19:07 -0800863 if (!IS_ERR(dst)) {
864 skb_dst_set(buff, dst);
Eric Dumazetb903d322011-10-27 00:44:35 -0400865 ip6_xmit(ctl_sk, buff, &fl6, NULL, tclass);
David S. Miller68d0c6d2011-03-01 13:19:07 -0800866 TCP_INC_STATS_BH(net, TCP_MIB_OUTSEGS);
867 if (rst)
868 TCP_INC_STATS_BH(net, TCP_MIB_OUTRSTS);
869 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700870 }
871
872 kfree_skb(buff);
873}
874
Ilpo Järvinen626e2642008-10-09 14:42:40 -0700875static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb)
876{
Eric Dumazetcf533ea2011-10-21 05:22:42 -0400877 const struct tcphdr *th = tcp_hdr(skb);
Ilpo Järvinen626e2642008-10-09 14:42:40 -0700878 u32 seq = 0, ack_seq = 0;
Guo-Fu Tsengfa3e5b42008-10-09 21:11:56 -0700879 struct tcp_md5sig_key *key = NULL;
Shawn Lu658ddaa2012-01-31 22:35:48 +0000880#ifdef CONFIG_TCP_MD5SIG
881 const __u8 *hash_location = NULL;
882 struct ipv6hdr *ipv6h = ipv6_hdr(skb);
883 unsigned char newhash[16];
884 int genhash;
885 struct sock *sk1 = NULL;
886#endif
Ilpo Järvinen626e2642008-10-09 14:42:40 -0700887
888 if (th->rst)
889 return;
890
891 if (!ipv6_unicast_destination(skb))
892 return;
893
894#ifdef CONFIG_TCP_MD5SIG
Shawn Lu658ddaa2012-01-31 22:35:48 +0000895 hash_location = tcp_parse_md5sig_option(th);
896 if (!sk && hash_location) {
897 /*
898 * active side is lost. Try to find listening socket through
899 * source port, and then find md5 key through listening socket.
900 * we are not loose security here:
901 * Incoming packet is checked with md5 hash with finding key,
902 * no RST generated if md5 hash doesn't match.
903 */
904 sk1 = inet6_lookup_listener(dev_net(skb_dst(skb)->dev),
905 &tcp_hashinfo, &ipv6h->daddr,
906 ntohs(th->source), inet6_iif(skb));
907 if (!sk1)
908 return;
909
910 rcu_read_lock();
911 key = tcp_v6_md5_do_lookup(sk1, &ipv6h->saddr);
912 if (!key)
913 goto release_sk1;
914
915 genhash = tcp_v6_md5_hash_skb(newhash, key, NULL, NULL, skb);
916 if (genhash || memcmp(hash_location, newhash, 16) != 0)
917 goto release_sk1;
918 } else {
919 key = sk ? tcp_v6_md5_do_lookup(sk, &ipv6h->saddr) : NULL;
920 }
Ilpo Järvinen626e2642008-10-09 14:42:40 -0700921#endif
922
923 if (th->ack)
924 seq = ntohl(th->ack_seq);
925 else
926 ack_seq = ntohl(th->seq) + th->syn + th->fin + skb->len -
927 (th->doff << 2);
928
Eric Dumazetb903d322011-10-27 00:44:35 -0400929 tcp_v6_send_response(skb, seq, ack_seq, 0, 0, key, 1, 0);
Shawn Lu658ddaa2012-01-31 22:35:48 +0000930
931#ifdef CONFIG_TCP_MD5SIG
932release_sk1:
933 if (sk1) {
934 rcu_read_unlock();
935 sock_put(sk1);
936 }
937#endif
Ilpo Järvinen626e2642008-10-09 14:42:40 -0700938}
939
940static void tcp_v6_send_ack(struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32 ts,
Eric Dumazetb903d322011-10-27 00:44:35 -0400941 struct tcp_md5sig_key *key, u8 tclass)
Ilpo Järvinen626e2642008-10-09 14:42:40 -0700942{
Eric Dumazetb903d322011-10-27 00:44:35 -0400943 tcp_v6_send_response(skb, seq, ack, win, ts, key, 0, tclass);
Ilpo Järvinen626e2642008-10-09 14:42:40 -0700944}
945
Linus Torvalds1da177e2005-04-16 15:20:36 -0700946static void tcp_v6_timewait_ack(struct sock *sk, struct sk_buff *skb)
947{
Arnaldo Carvalho de Melo8feaf0c02005-08-09 20:09:30 -0700948 struct inet_timewait_sock *tw = inet_twsk(sk);
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800949 struct tcp_timewait_sock *tcptw = tcp_twsk(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700950
YOSHIFUJI Hideaki9501f972008-04-18 12:45:16 +0900951 tcp_v6_send_ack(skb, tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt,
Arnaldo Carvalho de Melo8feaf0c02005-08-09 20:09:30 -0700952 tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale,
Eric Dumazetb903d322011-10-27 00:44:35 -0400953 tcptw->tw_ts_recent, tcp_twsk_md5_key(tcptw),
954 tw->tw_tclass);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700955
Arnaldo Carvalho de Melo8feaf0c02005-08-09 20:09:30 -0700956 inet_twsk_put(tw);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700957}
958
Gui Jianfeng6edafaa2008-08-06 23:50:04 -0700959static void tcp_v6_reqsk_send_ack(struct sock *sk, struct sk_buff *skb,
960 struct request_sock *req)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700961{
YOSHIFUJI Hideaki9501f972008-04-18 12:45:16 +0900962 tcp_v6_send_ack(skb, tcp_rsk(req)->snt_isn + 1, tcp_rsk(req)->rcv_isn + 1, req->rcv_wnd, req->ts_recent,
Eric Dumazetb903d322011-10-27 00:44:35 -0400963 tcp_v6_md5_do_lookup(sk, &ipv6_hdr(skb)->daddr), 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700964}
965
966
967static struct sock *tcp_v6_hnd_req(struct sock *sk,struct sk_buff *skb)
968{
Arnaldo Carvalho de Melo60236fd2005-06-18 22:47:21 -0700969 struct request_sock *req, **prev;
Arnaldo Carvalho de Meloaa8223c2007-04-10 21:04:22 -0700970 const struct tcphdr *th = tcp_hdr(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700971 struct sock *nsk;
972
973 /* Find possible connection requests. */
Arnaldo Carvalho de Melo81297652005-12-13 23:15:24 -0800974 req = inet6_csk_search_req(sk, &prev, th->source,
Arnaldo Carvalho de Melo0660e032007-04-25 17:54:47 -0700975 &ipv6_hdr(skb)->saddr,
976 &ipv6_hdr(skb)->daddr, inet6_iif(skb));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700977 if (req)
978 return tcp_check_req(sk, skb, req, prev);
979
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +0900980 nsk = __inet6_lookup_established(sock_net(sk), &tcp_hashinfo,
Pavel Emelyanovd86e0da2008-01-31 05:07:21 -0800981 &ipv6_hdr(skb)->saddr, th->source,
982 &ipv6_hdr(skb)->daddr, ntohs(th->dest), inet6_iif(skb));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700983
984 if (nsk) {
985 if (nsk->sk_state != TCP_TIME_WAIT) {
986 bh_lock_sock(nsk);
987 return nsk;
988 }
YOSHIFUJI Hideaki9469c7b2006-10-10 19:41:46 -0700989 inet_twsk_put(inet_twsk(nsk));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700990 return NULL;
991 }
992
Glenn Griffinc6aefaf2008-02-07 21:49:26 -0800993#ifdef CONFIG_SYN_COOKIES
Florian Westphalaf9b4732010-06-03 00:43:44 +0000994 if (!th->syn)
Glenn Griffinc6aefaf2008-02-07 21:49:26 -0800995 sk = cookie_v6_check(sk, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700996#endif
997 return sk;
998}
999
Linus Torvalds1da177e2005-04-16 15:20:36 -07001000/* FIXME: this is substantially similar to the ipv4 code.
1001 * Can some kind of merge be done? -- erics
1002 */
1003static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
1004{
William Allen Simpson4957faade2009-12-02 18:25:27 +00001005 struct tcp_extend_values tmp_ext;
William Allen Simpsone6b4d112009-12-02 18:07:39 +00001006 struct tcp_options_received tmp_opt;
Eric Dumazetcf533ea2011-10-21 05:22:42 -04001007 const u8 *hash_location;
William Allen Simpsone6b4d112009-12-02 18:07:39 +00001008 struct request_sock *req;
Arnaldo Carvalho de Meloca304b62005-12-13 23:15:40 -08001009 struct inet6_request_sock *treq;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001010 struct ipv6_pinfo *np = inet6_sk(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001011 struct tcp_sock *tp = tcp_sk(sk);
William Allen Simpsone6b4d112009-12-02 18:07:39 +00001012 __u32 isn = TCP_SKB_CB(skb)->when;
David S. Miller493f3772010-12-02 12:14:29 -08001013 struct dst_entry *dst = NULL;
Neal Cardwell3840a062012-06-28 12:34:19 +00001014 struct flowi6 fl6;
Eric Dumazeta2a385d2012-05-16 23:15:34 +00001015 bool want_cookie = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001016
1017 if (skb->protocol == htons(ETH_P_IP))
1018 return tcp_v4_conn_request(sk, skb);
1019
1020 if (!ipv6_unicast_destination(skb))
YOSHIFUJI Hideaki1ab14572007-02-09 23:24:49 +09001021 goto drop;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001022
Arnaldo Carvalho de Melo463c84b2005-08-09 20:10:42 -07001023 if (inet_csk_reqsk_queue_is_full(sk) && !isn) {
Eric Dumazet946cedc2011-08-30 03:21:44 +00001024 want_cookie = tcp_syn_flood_action(sk, skb, "TCPv6");
1025 if (!want_cookie)
1026 goto drop;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001027 }
1028
Arnaldo Carvalho de Melo463c84b2005-08-09 20:10:42 -07001029 if (sk_acceptq_is_full(sk) && inet_csk_reqsk_queue_young(sk) > 1)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001030 goto drop;
1031
Arnaldo Carvalho de Meloca304b62005-12-13 23:15:40 -08001032 req = inet6_reqsk_alloc(&tcp6_request_sock_ops);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001033 if (req == NULL)
1034 goto drop;
1035
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -08001036#ifdef CONFIG_TCP_MD5SIG
1037 tcp_rsk(req)->af_specific = &tcp_request_sock_ipv6_ops;
1038#endif
1039
Linus Torvalds1da177e2005-04-16 15:20:36 -07001040 tcp_clear_options(&tmp_opt);
1041 tmp_opt.mss_clamp = IPV6_MIN_MTU - sizeof(struct tcphdr) - sizeof(struct ipv6hdr);
1042 tmp_opt.user_mss = tp->rx_opt.user_mss;
Yuchung Cheng2100c8d2012-07-19 06:43:05 +00001043 tcp_parse_options(skb, &tmp_opt, &hash_location, 0, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001044
William Allen Simpson4957faade2009-12-02 18:25:27 +00001045 if (tmp_opt.cookie_plus > 0 &&
1046 tmp_opt.saw_tstamp &&
1047 !tp->rx_opt.cookie_out_never &&
1048 (sysctl_tcp_cookie_size > 0 ||
1049 (tp->cookie_values != NULL &&
1050 tp->cookie_values->cookie_desired > 0))) {
1051 u8 *c;
1052 u32 *d;
1053 u32 *mess = &tmp_ext.cookie_bakery[COOKIE_DIGEST_WORDS];
1054 int l = tmp_opt.cookie_plus - TCPOLEN_COOKIE_BASE;
1055
1056 if (tcp_cookie_generator(&tmp_ext.cookie_bakery[0]) != 0)
1057 goto drop_and_free;
1058
1059 /* Secret recipe starts with IP addresses */
Eric Dumazet0eae88f2010-04-20 19:06:52 -07001060 d = (__force u32 *)&ipv6_hdr(skb)->daddr.s6_addr32[0];
William Allen Simpson4957faade2009-12-02 18:25:27 +00001061 *mess++ ^= *d++;
1062 *mess++ ^= *d++;
1063 *mess++ ^= *d++;
1064 *mess++ ^= *d++;
Eric Dumazet0eae88f2010-04-20 19:06:52 -07001065 d = (__force u32 *)&ipv6_hdr(skb)->saddr.s6_addr32[0];
William Allen Simpson4957faade2009-12-02 18:25:27 +00001066 *mess++ ^= *d++;
1067 *mess++ ^= *d++;
1068 *mess++ ^= *d++;
1069 *mess++ ^= *d++;
1070
1071 /* plus variable length Initiator Cookie */
1072 c = (u8 *)mess;
1073 while (l-- > 0)
1074 *c++ ^= *hash_location++;
1075
Eric Dumazeta2a385d2012-05-16 23:15:34 +00001076 want_cookie = false; /* not our kind of cookie */
William Allen Simpson4957faade2009-12-02 18:25:27 +00001077 tmp_ext.cookie_out_never = 0; /* false */
1078 tmp_ext.cookie_plus = tmp_opt.cookie_plus;
1079 } else if (!tp->rx_opt.cookie_in_always) {
1080 /* redundant indications, but ensure initialization. */
1081 tmp_ext.cookie_out_never = 1; /* true */
1082 tmp_ext.cookie_plus = 0;
1083 } else {
1084 goto drop_and_free;
1085 }
1086 tmp_ext.cookie_in_always = tp->rx_opt.cookie_in_always;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001087
Florian Westphal4dfc2812008-04-10 03:12:40 -07001088 if (want_cookie && !tmp_opt.saw_tstamp)
Glenn Griffinc6aefaf2008-02-07 21:49:26 -08001089 tcp_clear_options(&tmp_opt);
Glenn Griffinc6aefaf2008-02-07 21:49:26 -08001090
Linus Torvalds1da177e2005-04-16 15:20:36 -07001091 tmp_opt.tstamp_ok = tmp_opt.saw_tstamp;
1092 tcp_openreq_init(req, &tmp_opt, skb);
1093
Arnaldo Carvalho de Meloca304b62005-12-13 23:15:40 -08001094 treq = inet6_rsk(req);
Alexey Dobriyan4e3fd7a2011-11-21 03:39:03 +00001095 treq->rmt_addr = ipv6_hdr(skb)->saddr;
1096 treq->loc_addr = ipv6_hdr(skb)->daddr;
Florian Westphal172d69e2010-06-21 11:48:45 +00001097 if (!want_cookie || tmp_opt.tstamp_ok)
Eric Dumazetbd14b1b2012-05-04 05:14:02 +00001098 TCP_ECN_create_request(req, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001099
Eric Dumazet4d0fe502011-11-23 17:29:23 -05001100 treq->iif = sk->sk_bound_dev_if;
1101
1102 /* So that link locals have meaning */
1103 if (!sk->sk_bound_dev_if &&
1104 ipv6_addr_type(&treq->rmt_addr) & IPV6_ADDR_LINKLOCAL)
1105 treq->iif = inet6_iif(skb);
1106
Florian Westphal2bbdf382010-06-13 11:29:39 +00001107 if (!isn) {
Glenn Griffinc6aefaf2008-02-07 21:49:26 -08001108 if (ipv6_opt_accepted(sk, skb) ||
1109 np->rxopt.bits.rxinfo || np->rxopt.bits.rxoinfo ||
1110 np->rxopt.bits.rxhlim || np->rxopt.bits.rxohlim) {
1111 atomic_inc(&skb->users);
1112 treq->pktopts = skb;
1113 }
David S. Miller493f3772010-12-02 12:14:29 -08001114
1115 if (want_cookie) {
Florian Westphal2bbdf382010-06-13 11:29:39 +00001116 isn = cookie_v6_init_sequence(sk, skb, &req->mss);
1117 req->cookie_ts = tmp_opt.tstamp_ok;
David S. Miller493f3772010-12-02 12:14:29 -08001118 goto have_isn;
Florian Westphal2bbdf382010-06-13 11:29:39 +00001119 }
David S. Miller493f3772010-12-02 12:14:29 -08001120
1121 /* VJ's idea. We save last timestamp seen
1122 * from the destination in peer table, when entering
1123 * state TIME-WAIT, and check against it before
1124 * accepting new connection request.
1125 *
1126 * If "isn" is not zero, this request hit alive
1127 * timewait bucket, so that all the necessary checks
1128 * are made in the function processing timewait state.
1129 */
1130 if (tmp_opt.saw_tstamp &&
1131 tcp_death_row.sysctl_tw_recycle &&
David S. Miller81166dd2012-07-10 03:14:24 -07001132 (dst = inet6_csk_route_req(sk, &fl6, req)) != NULL) {
1133 if (!tcp_peer_is_proven(req, dst, true)) {
David S. Miller493f3772010-12-02 12:14:29 -08001134 NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_PAWSPASSIVEREJECTED);
1135 goto drop_and_release;
1136 }
1137 }
1138 /* Kill the following clause, if you dislike this way. */
1139 else if (!sysctl_tcp_syncookies &&
1140 (sysctl_max_syn_backlog - inet_csk_reqsk_queue_len(sk) <
1141 (sysctl_max_syn_backlog >> 2)) &&
David S. Miller81166dd2012-07-10 03:14:24 -07001142 !tcp_peer_is_proven(req, dst, false)) {
David S. Miller493f3772010-12-02 12:14:29 -08001143 /* Without syncookies last quarter of
1144 * backlog is filled with destinations,
1145 * proven to be alive.
1146 * It means that we continue to communicate
1147 * to destinations, already remembered
1148 * to the moment of synflood.
1149 */
1150 LIMIT_NETDEBUG(KERN_DEBUG "TCP: drop open request from %pI6/%u\n",
1151 &treq->rmt_addr, ntohs(tcp_hdr(skb)->source));
1152 goto drop_and_release;
1153 }
1154
1155 isn = tcp_v6_init_sequence(skb);
Glenn Griffinc6aefaf2008-02-07 21:49:26 -08001156 }
David S. Miller493f3772010-12-02 12:14:29 -08001157have_isn:
Arnaldo Carvalho de Melo2e6599c2005-06-18 22:46:52 -07001158 tcp_rsk(req)->snt_isn = isn;
Jerry Chu9ad7c042011-06-08 11:08:38 +00001159 tcp_rsk(req)->snt_synack = tcp_time_stamp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001160
Neal Cardwell437c5b52012-06-23 19:22:00 +00001161 if (security_inet_conn_request(sk, skb, req))
1162 goto drop_and_release;
Venkat Yekkirala4237c752006-07-24 23:32:50 -07001163
Neal Cardwell9f10d3f2012-06-28 12:34:21 +00001164 if (tcp_v6_send_synack(sk, dst, &fl6, req,
Eric Dumazetfff32692012-06-01 01:47:50 +00001165 (struct request_values *)&tmp_ext,
1166 skb_get_queue_mapping(skb)) ||
William Allen Simpson4957faade2009-12-02 18:25:27 +00001167 want_cookie)
William Allen Simpsone6b4d112009-12-02 18:07:39 +00001168 goto drop_and_free;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001169
William Allen Simpsone6b4d112009-12-02 18:07:39 +00001170 inet6_csk_reqsk_queue_hash_add(sk, req, TCP_TIMEOUT_INIT);
1171 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001172
David S. Miller493f3772010-12-02 12:14:29 -08001173drop_and_release:
1174 dst_release(dst);
William Allen Simpsone6b4d112009-12-02 18:07:39 +00001175drop_and_free:
1176 reqsk_free(req);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001177drop:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001178 return 0; /* don't send reset */
1179}
1180
1181static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
Arnaldo Carvalho de Melo60236fd2005-06-18 22:47:21 -07001182 struct request_sock *req,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001183 struct dst_entry *dst)
1184{
Vegard Nossum78d15e82008-09-12 16:17:43 -07001185 struct inet6_request_sock *treq;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001186 struct ipv6_pinfo *newnp, *np = inet6_sk(sk);
1187 struct tcp6_sock *newtcp6sk;
1188 struct inet_sock *newinet;
1189 struct tcp_sock *newtp;
1190 struct sock *newsk;
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -08001191#ifdef CONFIG_TCP_MD5SIG
1192 struct tcp_md5sig_key *key;
1193#endif
Neal Cardwell3840a062012-06-28 12:34:19 +00001194 struct flowi6 fl6;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001195
1196 if (skb->protocol == htons(ETH_P_IP)) {
1197 /*
1198 * v6 mapped
1199 */
1200
1201 newsk = tcp_v4_syn_recv_sock(sk, skb, req, dst);
1202
YOSHIFUJI Hideaki1ab14572007-02-09 23:24:49 +09001203 if (newsk == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001204 return NULL;
1205
1206 newtcp6sk = (struct tcp6_sock *)newsk;
1207 inet_sk(newsk)->pinet6 = &newtcp6sk->inet6;
1208
1209 newinet = inet_sk(newsk);
1210 newnp = inet6_sk(newsk);
1211 newtp = tcp_sk(newsk);
1212
1213 memcpy(newnp, np, sizeof(struct ipv6_pinfo));
1214
Eric Dumazetc720c7e82009-10-15 06:30:45 +00001215 ipv6_addr_set_v4mapped(newinet->inet_daddr, &newnp->daddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001216
Eric Dumazetc720c7e82009-10-15 06:30:45 +00001217 ipv6_addr_set_v4mapped(newinet->inet_saddr, &newnp->saddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001218
Alexey Dobriyan4e3fd7a2011-11-21 03:39:03 +00001219 newnp->rcv_saddr = newnp->saddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001220
Arnaldo Carvalho de Melo8292a172005-12-13 23:15:52 -08001221 inet_csk(newsk)->icsk_af_ops = &ipv6_mapped;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001222 newsk->sk_backlog_rcv = tcp_v4_do_rcv;
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -08001223#ifdef CONFIG_TCP_MD5SIG
1224 newtp->af_specific = &tcp_sock_ipv6_mapped_specific;
1225#endif
1226
Yan, Zheng676a1182011-09-25 02:21:30 +00001227 newnp->ipv6_ac_list = NULL;
1228 newnp->ipv6_fl_list = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001229 newnp->pktoptions = NULL;
1230 newnp->opt = NULL;
Arnaldo Carvalho de Melo505cbfc2005-08-12 09:19:38 -03001231 newnp->mcast_oif = inet6_iif(skb);
Arnaldo Carvalho de Melo0660e032007-04-25 17:54:47 -07001232 newnp->mcast_hops = ipv6_hdr(skb)->hop_limit;
Jiri Benc4c507d22012-02-09 09:35:49 +00001233 newnp->rcv_tclass = ipv6_tclass(ipv6_hdr(skb));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001234
Arnaldo Carvalho de Meloe6848972005-08-09 19:45:38 -07001235 /*
1236 * No need to charge this sock to the relevant IPv6 refcnt debug socks count
1237 * here, tcp_create_openreq_child now does this for us, see the comment in
1238 * that function for the gory details. -acme
Linus Torvalds1da177e2005-04-16 15:20:36 -07001239 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001240
1241 /* It is tricky place. Until this moment IPv4 tcp
Arnaldo Carvalho de Melo8292a172005-12-13 23:15:52 -08001242 worked with IPv6 icsk.icsk_af_ops.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001243 Sync it now.
1244 */
Arnaldo Carvalho de Melod83d8462005-12-13 23:26:10 -08001245 tcp_sync_mss(newsk, inet_csk(newsk)->icsk_pmtu_cookie);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001246
1247 return newsk;
1248 }
1249
Vegard Nossum78d15e82008-09-12 16:17:43 -07001250 treq = inet6_rsk(req);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001251
1252 if (sk_acceptq_is_full(sk))
1253 goto out_overflow;
1254
David S. Miller493f3772010-12-02 12:14:29 -08001255 if (!dst) {
Neal Cardwell3840a062012-06-28 12:34:19 +00001256 dst = inet6_csk_route_req(sk, &fl6, req);
David S. Miller493f3772010-12-02 12:14:29 -08001257 if (!dst)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001258 goto out;
YOSHIFUJI Hideaki1ab14572007-02-09 23:24:49 +09001259 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001260
1261 newsk = tcp_create_openreq_child(sk, req, skb);
1262 if (newsk == NULL)
Balazs Scheidler093d2822010-10-21 13:06:43 +02001263 goto out_nonewsk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001264
Arnaldo Carvalho de Meloe6848972005-08-09 19:45:38 -07001265 /*
1266 * No need to charge this sock to the relevant IPv6 refcnt debug socks
1267 * count here, tcp_create_openreq_child now does this for us, see the
1268 * comment in that function for the gory details. -acme
1269 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001270
Stephen Hemminger59eed272006-08-25 15:55:43 -07001271 newsk->sk_gso_type = SKB_GSO_TCPV6;
YOSHIFUJI Hideaki8e1ef0a2006-08-29 17:15:09 -07001272 __ip6_dst_store(newsk, dst, NULL, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001273
1274 newtcp6sk = (struct tcp6_sock *)newsk;
1275 inet_sk(newsk)->pinet6 = &newtcp6sk->inet6;
1276
1277 newtp = tcp_sk(newsk);
1278 newinet = inet_sk(newsk);
1279 newnp = inet6_sk(newsk);
1280
1281 memcpy(newnp, np, sizeof(struct ipv6_pinfo));
1282
Alexey Dobriyan4e3fd7a2011-11-21 03:39:03 +00001283 newnp->daddr = treq->rmt_addr;
1284 newnp->saddr = treq->loc_addr;
1285 newnp->rcv_saddr = treq->loc_addr;
Arnaldo Carvalho de Melo2e6599c2005-06-18 22:46:52 -07001286 newsk->sk_bound_dev_if = treq->iif;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001287
YOSHIFUJI Hideaki1ab14572007-02-09 23:24:49 +09001288 /* Now IPv6 options...
Linus Torvalds1da177e2005-04-16 15:20:36 -07001289
1290 First: no IPv4 options.
1291 */
Eric Dumazetf6d8bd02011-04-21 09:45:37 +00001292 newinet->inet_opt = NULL;
Yan, Zheng676a1182011-09-25 02:21:30 +00001293 newnp->ipv6_ac_list = NULL;
Masayuki Nakagawad35690b2007-03-16 16:14:03 -07001294 newnp->ipv6_fl_list = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001295
1296 /* Clone RX bits */
1297 newnp->rxopt.all = np->rxopt.all;
1298
1299 /* Clone pktoptions received with SYN */
1300 newnp->pktoptions = NULL;
Arnaldo Carvalho de Melo2e6599c2005-06-18 22:46:52 -07001301 if (treq->pktopts != NULL) {
Mel Gorman99a1dec2012-07-31 16:44:14 -07001302 newnp->pktoptions = skb_clone(treq->pktopts,
1303 sk_gfp_atomic(sk, GFP_ATOMIC));
Eric Dumazetab185d72012-04-19 02:24:36 +00001304 consume_skb(treq->pktopts);
Arnaldo Carvalho de Melo2e6599c2005-06-18 22:46:52 -07001305 treq->pktopts = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001306 if (newnp->pktoptions)
1307 skb_set_owner_r(newnp->pktoptions, newsk);
1308 }
1309 newnp->opt = NULL;
Arnaldo Carvalho de Melo505cbfc2005-08-12 09:19:38 -03001310 newnp->mcast_oif = inet6_iif(skb);
Arnaldo Carvalho de Melo0660e032007-04-25 17:54:47 -07001311 newnp->mcast_hops = ipv6_hdr(skb)->hop_limit;
Jiri Benc4c507d22012-02-09 09:35:49 +00001312 newnp->rcv_tclass = ipv6_tclass(ipv6_hdr(skb));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001313
1314 /* Clone native IPv6 options from listening socket (if any)
1315
1316 Yes, keeping reference count would be much more clever,
1317 but we make one more one thing there: reattach optmem
1318 to newsk.
1319 */
RongQing.Li43264e02012-07-01 17:18:59 +00001320 if (np->opt)
1321 newnp->opt = ipv6_dup_options(newsk, np->opt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001322
Arnaldo Carvalho de Melod83d8462005-12-13 23:26:10 -08001323 inet_csk(newsk)->icsk_ext_hdr_len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001324 if (newnp->opt)
Arnaldo Carvalho de Melod83d8462005-12-13 23:26:10 -08001325 inet_csk(newsk)->icsk_ext_hdr_len = (newnp->opt->opt_nflen +
1326 newnp->opt->opt_flen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001327
John Heffner5d424d52006-03-20 17:53:41 -08001328 tcp_mtup_init(newsk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001329 tcp_sync_mss(newsk, dst_mtu(dst));
David S. Miller0dbaee32010-12-13 12:52:14 -08001330 newtp->advmss = dst_metric_advmss(dst);
Neal Cardwelld135c522012-04-22 09:45:47 +00001331 if (tcp_sk(sk)->rx_opt.user_mss &&
1332 tcp_sk(sk)->rx_opt.user_mss < newtp->advmss)
1333 newtp->advmss = tcp_sk(sk)->rx_opt.user_mss;
1334
Linus Torvalds1da177e2005-04-16 15:20:36 -07001335 tcp_initialize_rcv_mss(newsk);
Jerry Chu9ad7c042011-06-08 11:08:38 +00001336 if (tcp_rsk(req)->snt_synack)
1337 tcp_valid_rtt_meas(newsk,
1338 tcp_time_stamp - tcp_rsk(req)->snt_synack);
1339 newtp->total_retrans = req->retrans;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001340
Eric Dumazetc720c7e82009-10-15 06:30:45 +00001341 newinet->inet_daddr = newinet->inet_saddr = LOOPBACK4_IPV6;
1342 newinet->inet_rcv_saddr = LOOPBACK4_IPV6;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001343
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -08001344#ifdef CONFIG_TCP_MD5SIG
1345 /* Copy over the MD5 key from the original socket */
1346 if ((key = tcp_v6_md5_do_lookup(sk, &newnp->daddr)) != NULL) {
1347 /* We're using one, so create a matching key
1348 * on the newsk structure. If we fail to get
1349 * memory, then we end up not copying the key
1350 * across. Shucks.
1351 */
Eric Dumazeta915da9b2012-01-31 05:18:33 +00001352 tcp_md5_do_add(newsk, (union tcp_md5_addr *)&newnp->daddr,
Mel Gorman99a1dec2012-07-31 16:44:14 -07001353 AF_INET6, key->key, key->keylen,
1354 sk_gfp_atomic(sk, GFP_ATOMIC));
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -08001355 }
1356#endif
1357
Balazs Scheidler093d2822010-10-21 13:06:43 +02001358 if (__inet_inherit_port(sk, newsk) < 0) {
1359 sock_put(newsk);
1360 goto out;
1361 }
Eric Dumazet9327f702009-12-04 03:46:54 +00001362 __inet6_hash(newsk, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001363
1364 return newsk;
1365
1366out_overflow:
Pavel Emelyanovde0744a2008-07-16 20:31:16 -07001367 NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENOVERFLOWS);
Balazs Scheidler093d2822010-10-21 13:06:43 +02001368out_nonewsk:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001369 dst_release(dst);
Balazs Scheidler093d2822010-10-21 13:06:43 +02001370out:
1371 NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001372 return NULL;
1373}
1374
Al Virob51655b2006-11-14 21:40:42 -08001375static __sum16 tcp_v6_checksum_init(struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001376{
Patrick McHardy84fa7932006-08-29 16:44:56 -07001377 if (skb->ip_summed == CHECKSUM_COMPLETE) {
Herbert Xu684f2172009-01-08 10:41:23 -08001378 if (!tcp_v6_check(skb->len, &ipv6_hdr(skb)->saddr,
Arnaldo Carvalho de Melo0660e032007-04-25 17:54:47 -07001379 &ipv6_hdr(skb)->daddr, skb->csum)) {
Herbert Xufb286bb2005-11-10 13:01:24 -08001380 skb->ip_summed = CHECKSUM_UNNECESSARY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001381 return 0;
Herbert Xufb286bb2005-11-10 13:01:24 -08001382 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001383 }
Herbert Xufb286bb2005-11-10 13:01:24 -08001384
Herbert Xu684f2172009-01-08 10:41:23 -08001385 skb->csum = ~csum_unfold(tcp_v6_check(skb->len,
Arnaldo Carvalho de Melo0660e032007-04-25 17:54:47 -07001386 &ipv6_hdr(skb)->saddr,
1387 &ipv6_hdr(skb)->daddr, 0));
Herbert Xufb286bb2005-11-10 13:01:24 -08001388
Linus Torvalds1da177e2005-04-16 15:20:36 -07001389 if (skb->len <= 76) {
Herbert Xufb286bb2005-11-10 13:01:24 -08001390 return __skb_checksum_complete(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001391 }
1392 return 0;
1393}
1394
1395/* The socket must have it's spinlock held when we get
1396 * here.
1397 *
1398 * We have a potential double-lock case here, so even when
1399 * doing backlog processing we use the BH locking scheme.
1400 * This is because we cannot sleep with the original spinlock
1401 * held.
1402 */
1403static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb)
1404{
1405 struct ipv6_pinfo *np = inet6_sk(sk);
1406 struct tcp_sock *tp;
1407 struct sk_buff *opt_skb = NULL;
1408
1409 /* Imagine: socket is IPv6. IPv4 packet arrives,
1410 goes to IPv4 receive handler and backlogged.
1411 From backlog it always goes here. Kerboom...
1412 Fortunately, tcp_rcv_established and rcv_established
1413 handle them correctly, but it is not case with
1414 tcp_v6_hnd_req and tcp_v6_send_reset(). --ANK
1415 */
1416
1417 if (skb->protocol == htons(ETH_P_IP))
1418 return tcp_v4_do_rcv(sk, skb);
1419
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -08001420#ifdef CONFIG_TCP_MD5SIG
1421 if (tcp_v6_inbound_md5_hash (sk, skb))
1422 goto discard;
1423#endif
1424
Dmitry Mishinfda9ef52006-08-31 15:28:39 -07001425 if (sk_filter(sk, skb))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001426 goto discard;
1427
1428 /*
1429 * socket locking is here for SMP purposes as backlog rcv
1430 * is currently called with bh processing disabled.
1431 */
1432
1433 /* Do Stevens' IPV6_PKTOPTIONS.
1434
1435 Yes, guys, it is the only place in our code, where we
1436 may make it not affecting IPv4.
1437 The rest of code is protocol independent,
1438 and I do not like idea to uglify IPv4.
1439
1440 Actually, all the idea behind IPV6_PKTOPTIONS
1441 looks not very well thought. For now we latch
1442 options, received in the last packet, enqueued
1443 by tcp. Feel free to propose better solution.
YOSHIFUJI Hideaki1ab14572007-02-09 23:24:49 +09001444 --ANK (980728)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001445 */
1446 if (np->rxopt.all)
Mel Gorman99a1dec2012-07-31 16:44:14 -07001447 opt_skb = skb_clone(skb, sk_gfp_atomic(sk, GFP_ATOMIC));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001448
1449 if (sk->sk_state == TCP_ESTABLISHED) { /* Fast path */
Eric Dumazet5d299f32012-08-06 05:09:33 +00001450 struct dst_entry *dst = sk->sk_rx_dst;
1451
Tom Herbertbdeab992011-08-14 19:45:55 +00001452 sock_rps_save_rxhash(sk, skb);
Eric Dumazet5d299f32012-08-06 05:09:33 +00001453 if (dst) {
1454 if (inet_sk(sk)->rx_dst_ifindex != skb->skb_iif ||
1455 dst->ops->check(dst, np->rx_dst_cookie) == NULL) {
1456 dst_release(dst);
1457 sk->sk_rx_dst = NULL;
1458 }
1459 }
1460
Arnaldo Carvalho de Meloaa8223c2007-04-10 21:04:22 -07001461 if (tcp_rcv_established(sk, skb, tcp_hdr(skb), skb->len))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001462 goto reset;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001463 if (opt_skb)
1464 goto ipv6_pktoptions;
1465 return 0;
1466 }
1467
Arnaldo Carvalho de Meloab6a5bb2007-03-18 17:43:48 -07001468 if (skb->len < tcp_hdrlen(skb) || tcp_checksum_complete(skb))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001469 goto csum_err;
1470
YOSHIFUJI Hideaki1ab14572007-02-09 23:24:49 +09001471 if (sk->sk_state == TCP_LISTEN) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001472 struct sock *nsk = tcp_v6_hnd_req(sk, skb);
1473 if (!nsk)
1474 goto discard;
1475
1476 /*
1477 * Queue it on the new socket if the new socket is active,
1478 * otherwise we just shortcircuit this and continue with
1479 * the new socket..
1480 */
YOSHIFUJI Hideaki1ab14572007-02-09 23:24:49 +09001481 if(nsk != sk) {
Tom Herbertbdeab992011-08-14 19:45:55 +00001482 sock_rps_save_rxhash(nsk, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001483 if (tcp_child_process(sk, nsk, skb))
1484 goto reset;
1485 if (opt_skb)
1486 __kfree_skb(opt_skb);
1487 return 0;
1488 }
Neil Horman47482f132011-04-06 13:07:09 -07001489 } else
Tom Herbertbdeab992011-08-14 19:45:55 +00001490 sock_rps_save_rxhash(sk, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001491
Arnaldo Carvalho de Meloaa8223c2007-04-10 21:04:22 -07001492 if (tcp_rcv_state_process(sk, skb, tcp_hdr(skb), skb->len))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001493 goto reset;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001494 if (opt_skb)
1495 goto ipv6_pktoptions;
1496 return 0;
1497
1498reset:
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -08001499 tcp_v6_send_reset(sk, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001500discard:
1501 if (opt_skb)
1502 __kfree_skb(opt_skb);
1503 kfree_skb(skb);
1504 return 0;
1505csum_err:
Pavel Emelyanov63231bd2008-07-16 20:22:25 -07001506 TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_INERRS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001507 goto discard;
1508
1509
1510ipv6_pktoptions:
1511 /* Do you ask, what is it?
1512
1513 1. skb was enqueued by tcp.
1514 2. skb is added to tail of read queue, rather than out of order.
1515 3. socket is not in passive state.
1516 4. Finally, it really contains options, which user wants to receive.
1517 */
1518 tp = tcp_sk(sk);
1519 if (TCP_SKB_CB(opt_skb)->end_seq == tp->rcv_nxt &&
1520 !((1 << sk->sk_state) & (TCPF_CLOSE | TCPF_LISTEN))) {
YOSHIFUJI Hideaki333fad52005-09-08 09:59:17 +09001521 if (np->rxopt.bits.rxinfo || np->rxopt.bits.rxoinfo)
Arnaldo Carvalho de Melo505cbfc2005-08-12 09:19:38 -03001522 np->mcast_oif = inet6_iif(opt_skb);
YOSHIFUJI Hideaki333fad52005-09-08 09:59:17 +09001523 if (np->rxopt.bits.rxhlim || np->rxopt.bits.rxohlim)
Arnaldo Carvalho de Melo0660e032007-04-25 17:54:47 -07001524 np->mcast_hops = ipv6_hdr(opt_skb)->hop_limit;
Jiri Benc4c507d22012-02-09 09:35:49 +00001525 if (np->rxopt.bits.rxtclass)
1526 np->rcv_tclass = ipv6_tclass(ipv6_hdr(skb));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001527 if (ipv6_opt_accepted(sk, opt_skb)) {
1528 skb_set_owner_r(opt_skb, sk);
1529 opt_skb = xchg(&np->pktoptions, opt_skb);
1530 } else {
1531 __kfree_skb(opt_skb);
1532 opt_skb = xchg(&np->pktoptions, NULL);
1533 }
1534 }
1535
Wei Yongjun800d55f2009-02-23 21:45:33 +00001536 kfree_skb(opt_skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001537 return 0;
1538}
1539
Herbert Xue5bbef22007-10-15 12:50:28 -07001540static int tcp_v6_rcv(struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001541{
Eric Dumazetcf533ea2011-10-21 05:22:42 -04001542 const struct tcphdr *th;
Eric Dumazetb71d1d42011-04-22 04:53:02 +00001543 const struct ipv6hdr *hdr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001544 struct sock *sk;
1545 int ret;
Pavel Emelyanova86b1e32008-07-16 20:20:58 -07001546 struct net *net = dev_net(skb->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001547
1548 if (skb->pkt_type != PACKET_HOST)
1549 goto discard_it;
1550
1551 /*
1552 * Count it even if it's bad.
1553 */
Pavel Emelyanov63231bd2008-07-16 20:22:25 -07001554 TCP_INC_STATS_BH(net, TCP_MIB_INSEGS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001555
1556 if (!pskb_may_pull(skb, sizeof(struct tcphdr)))
1557 goto discard_it;
1558
Arnaldo Carvalho de Meloaa8223c2007-04-10 21:04:22 -07001559 th = tcp_hdr(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001560
1561 if (th->doff < sizeof(struct tcphdr)/4)
1562 goto bad_packet;
1563 if (!pskb_may_pull(skb, th->doff*4))
1564 goto discard_it;
1565
Herbert Xu60476372007-04-09 11:59:39 -07001566 if (!skb_csum_unnecessary(skb) && tcp_v6_checksum_init(skb))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001567 goto bad_packet;
1568
Arnaldo Carvalho de Meloaa8223c2007-04-10 21:04:22 -07001569 th = tcp_hdr(skb);
Stephen Hemmingere802af92010-04-22 15:24:53 -07001570 hdr = ipv6_hdr(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001571 TCP_SKB_CB(skb)->seq = ntohl(th->seq);
1572 TCP_SKB_CB(skb)->end_seq = (TCP_SKB_CB(skb)->seq + th->syn + th->fin +
1573 skb->len - th->doff*4);
1574 TCP_SKB_CB(skb)->ack_seq = ntohl(th->ack_seq);
1575 TCP_SKB_CB(skb)->when = 0;
Eric Dumazetb82d1bb2011-09-27 02:20:08 -04001576 TCP_SKB_CB(skb)->ip_dsfield = ipv6_get_dsfield(hdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001577 TCP_SKB_CB(skb)->sacked = 0;
1578
Arnaldo Carvalho de Melo9a1f27c2008-10-07 11:41:57 -07001579 sk = __inet6_lookup_skb(&tcp_hashinfo, skb, th->source, th->dest);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001580 if (!sk)
1581 goto no_tcp_socket;
1582
1583process:
1584 if (sk->sk_state == TCP_TIME_WAIT)
1585 goto do_time_wait;
1586
Stephen Hemmingere802af92010-04-22 15:24:53 -07001587 if (hdr->hop_limit < inet6_sk(sk)->min_hopcount) {
1588 NET_INC_STATS_BH(net, LINUX_MIB_TCPMINTTLDROP);
1589 goto discard_and_relse;
1590 }
1591
Linus Torvalds1da177e2005-04-16 15:20:36 -07001592 if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb))
1593 goto discard_and_relse;
1594
Dmitry Mishinfda9ef52006-08-31 15:28:39 -07001595 if (sk_filter(sk, skb))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001596 goto discard_and_relse;
1597
1598 skb->dev = NULL;
1599
Fabio Olive Leite293b9c42006-09-25 22:28:47 -07001600 bh_lock_sock_nested(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001601 ret = 0;
1602 if (!sock_owned_by_user(sk)) {
Chris Leech1a2449a2006-05-23 18:05:53 -07001603#ifdef CONFIG_NET_DMA
YOSHIFUJI Hideaki1ab14572007-02-09 23:24:49 +09001604 struct tcp_sock *tp = tcp_sk(sk);
David S. Millerb4caea82007-10-26 04:20:13 -07001605 if (!tp->ucopy.dma_chan && tp->ucopy.pinned_list)
Dave Jianga2bd1142012-04-04 16:10:46 -07001606 tp->ucopy.dma_chan = net_dma_find_channel();
YOSHIFUJI Hideaki1ab14572007-02-09 23:24:49 +09001607 if (tp->ucopy.dma_chan)
1608 ret = tcp_v6_do_rcv(sk, skb);
1609 else
Chris Leech1a2449a2006-05-23 18:05:53 -07001610#endif
1611 {
1612 if (!tcp_prequeue(sk, skb))
1613 ret = tcp_v6_do_rcv(sk, skb);
1614 }
Eric Dumazetda882c12012-04-22 23:38:54 +00001615 } else if (unlikely(sk_add_backlog(sk, skb,
1616 sk->sk_rcvbuf + sk->sk_sndbuf))) {
Zhu Yi6b03a532010-03-04 18:01:41 +00001617 bh_unlock_sock(sk);
Eric Dumazet6cce09f2010-03-07 23:21:57 +00001618 NET_INC_STATS_BH(net, LINUX_MIB_TCPBACKLOGDROP);
Zhu Yi6b03a532010-03-04 18:01:41 +00001619 goto discard_and_relse;
1620 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001621 bh_unlock_sock(sk);
1622
1623 sock_put(sk);
1624 return ret ? -1 : 0;
1625
1626no_tcp_socket:
1627 if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb))
1628 goto discard_it;
1629
1630 if (skb->len < (th->doff<<2) || tcp_checksum_complete(skb)) {
1631bad_packet:
Pavel Emelyanov63231bd2008-07-16 20:22:25 -07001632 TCP_INC_STATS_BH(net, TCP_MIB_INERRS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001633 } else {
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -08001634 tcp_v6_send_reset(NULL, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001635 }
1636
1637discard_it:
1638
1639 /*
1640 * Discard frame
1641 */
1642
1643 kfree_skb(skb);
1644 return 0;
1645
1646discard_and_relse:
1647 sock_put(sk);
1648 goto discard_it;
1649
1650do_time_wait:
1651 if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) {
YOSHIFUJI Hideaki9469c7b2006-10-10 19:41:46 -07001652 inet_twsk_put(inet_twsk(sk));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001653 goto discard_it;
1654 }
1655
1656 if (skb->len < (th->doff<<2) || tcp_checksum_complete(skb)) {
Pavel Emelyanov63231bd2008-07-16 20:22:25 -07001657 TCP_INC_STATS_BH(net, TCP_MIB_INERRS);
YOSHIFUJI Hideaki9469c7b2006-10-10 19:41:46 -07001658 inet_twsk_put(inet_twsk(sk));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001659 goto discard_it;
1660 }
1661
YOSHIFUJI Hideaki9469c7b2006-10-10 19:41:46 -07001662 switch (tcp_timewait_state_process(inet_twsk(sk), skb, th)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001663 case TCP_TW_SYN:
1664 {
1665 struct sock *sk2;
1666
YOSHIFUJI Hideakic346dca2008-03-25 21:47:49 +09001667 sk2 = inet6_lookup_listener(dev_net(skb->dev), &tcp_hashinfo,
Arnaldo Carvalho de Melo0660e032007-04-25 17:54:47 -07001668 &ipv6_hdr(skb)->daddr,
Arnaldo Carvalho de Melo505cbfc2005-08-12 09:19:38 -03001669 ntohs(th->dest), inet6_iif(skb));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001670 if (sk2 != NULL) {
Arnaldo Carvalho de Melo295ff7e2005-08-09 20:44:40 -07001671 struct inet_timewait_sock *tw = inet_twsk(sk);
1672 inet_twsk_deschedule(tw, &tcp_death_row);
1673 inet_twsk_put(tw);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001674 sk = sk2;
1675 goto process;
1676 }
1677 /* Fall through to ACK */
1678 }
1679 case TCP_TW_ACK:
1680 tcp_v6_timewait_ack(sk, skb);
1681 break;
1682 case TCP_TW_RST:
1683 goto no_tcp_socket;
1684 case TCP_TW_SUCCESS:;
1685 }
1686 goto discard_it;
1687}
1688
Eric Dumazetc7109982012-07-26 12:18:11 +00001689static void tcp_v6_early_demux(struct sk_buff *skb)
1690{
1691 const struct ipv6hdr *hdr;
1692 const struct tcphdr *th;
1693 struct sock *sk;
1694
1695 if (skb->pkt_type != PACKET_HOST)
1696 return;
1697
1698 if (!pskb_may_pull(skb, skb_transport_offset(skb) + sizeof(struct tcphdr)))
1699 return;
1700
1701 hdr = ipv6_hdr(skb);
1702 th = tcp_hdr(skb);
1703
1704 if (th->doff < sizeof(struct tcphdr) / 4)
1705 return;
1706
1707 sk = __inet6_lookup_established(dev_net(skb->dev), &tcp_hashinfo,
1708 &hdr->saddr, th->source,
1709 &hdr->daddr, ntohs(th->dest),
1710 inet6_iif(skb));
1711 if (sk) {
1712 skb->sk = sk;
1713 skb->destructor = sock_edemux;
1714 if (sk->sk_state != TCP_TIME_WAIT) {
1715 struct dst_entry *dst = sk->sk_rx_dst;
1716 struct inet_sock *icsk = inet_sk(sk);
1717 if (dst)
Eric Dumazet5d299f32012-08-06 05:09:33 +00001718 dst = dst_check(dst, inet6_sk(sk)->rx_dst_cookie);
Eric Dumazetc7109982012-07-26 12:18:11 +00001719 if (dst &&
Eric Dumazet5d299f32012-08-06 05:09:33 +00001720 icsk->rx_dst_ifindex == skb->skb_iif)
Eric Dumazetc7109982012-07-26 12:18:11 +00001721 skb_dst_set_noref(skb, dst);
1722 }
1723 }
1724}
1725
David S. Millerccb7c412010-12-01 18:09:13 -08001726static struct timewait_sock_ops tcp6_timewait_sock_ops = {
1727 .twsk_obj_size = sizeof(struct tcp6_timewait_sock),
1728 .twsk_unique = tcp_twsk_unique,
1729 .twsk_destructor= tcp_twsk_destructor,
David S. Millerccb7c412010-12-01 18:09:13 -08001730};
1731
Eric Dumazet5d299f32012-08-06 05:09:33 +00001732static void inet6_sk_rx_dst_set(struct sock *sk, const struct sk_buff *skb)
1733{
1734 struct dst_entry *dst = skb_dst(skb);
1735 const struct rt6_info *rt = (const struct rt6_info *)dst;
1736
1737 dst_hold(dst);
1738 sk->sk_rx_dst = dst;
1739 inet_sk(sk)->rx_dst_ifindex = skb->skb_iif;
1740 if (rt->rt6i_node)
1741 inet6_sk(sk)->rx_dst_cookie = rt->rt6i_node->fn_sernum;
1742}
1743
Stephen Hemminger3b401a82009-09-01 19:25:04 +00001744static const struct inet_connection_sock_af_ops ipv6_specific = {
Arnaldo Carvalho de Melo543d9cf2006-03-20 22:48:35 -08001745 .queue_xmit = inet6_csk_xmit,
1746 .send_check = tcp_v6_send_check,
1747 .rebuild_header = inet6_sk_rebuild_header,
Eric Dumazet5d299f32012-08-06 05:09:33 +00001748 .sk_rx_dst_set = inet6_sk_rx_dst_set,
Arnaldo Carvalho de Melo543d9cf2006-03-20 22:48:35 -08001749 .conn_request = tcp_v6_conn_request,
1750 .syn_recv_sock = tcp_v6_syn_recv_sock,
Arnaldo Carvalho de Melo543d9cf2006-03-20 22:48:35 -08001751 .net_header_len = sizeof(struct ipv6hdr),
Eric Dumazet67469602012-04-24 07:37:38 +00001752 .net_frag_header_len = sizeof(struct frag_hdr),
Arnaldo Carvalho de Melo543d9cf2006-03-20 22:48:35 -08001753 .setsockopt = ipv6_setsockopt,
1754 .getsockopt = ipv6_getsockopt,
1755 .addr2sockaddr = inet6_csk_addr2sockaddr,
1756 .sockaddr_len = sizeof(struct sockaddr_in6),
Arnaldo Carvalho de Meloab1e0a12008-02-03 04:06:04 -08001757 .bind_conflict = inet6_csk_bind_conflict,
Dmitry Mishin3fdadf72006-03-20 22:45:21 -08001758#ifdef CONFIG_COMPAT
Arnaldo Carvalho de Melo543d9cf2006-03-20 22:48:35 -08001759 .compat_setsockopt = compat_ipv6_setsockopt,
1760 .compat_getsockopt = compat_ipv6_getsockopt,
Dmitry Mishin3fdadf72006-03-20 22:45:21 -08001761#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07001762};
1763
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -08001764#ifdef CONFIG_TCP_MD5SIG
Stephen Hemmingerb2e4b3de2009-09-01 19:25:03 +00001765static const struct tcp_sock_af_ops tcp_sock_ipv6_specific = {
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -08001766 .md5_lookup = tcp_v6_md5_lookup,
Adam Langley49a72df2008-07-19 00:01:42 -07001767 .calc_md5_hash = tcp_v6_md5_hash_skb,
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -08001768 .md5_parse = tcp_v6_parse_md5_keys,
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -08001769};
David S. Millera9286302006-11-14 19:53:22 -08001770#endif
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -08001771
Linus Torvalds1da177e2005-04-16 15:20:36 -07001772/*
1773 * TCP over IPv4 via INET6 API
1774 */
1775
Stephen Hemminger3b401a82009-09-01 19:25:04 +00001776static const struct inet_connection_sock_af_ops ipv6_mapped = {
Arnaldo Carvalho de Melo543d9cf2006-03-20 22:48:35 -08001777 .queue_xmit = ip_queue_xmit,
1778 .send_check = tcp_v4_send_check,
1779 .rebuild_header = inet_sk_rebuild_header,
1780 .conn_request = tcp_v6_conn_request,
1781 .syn_recv_sock = tcp_v6_syn_recv_sock,
Arnaldo Carvalho de Melo543d9cf2006-03-20 22:48:35 -08001782 .net_header_len = sizeof(struct iphdr),
1783 .setsockopt = ipv6_setsockopt,
1784 .getsockopt = ipv6_getsockopt,
1785 .addr2sockaddr = inet6_csk_addr2sockaddr,
1786 .sockaddr_len = sizeof(struct sockaddr_in6),
Arnaldo Carvalho de Meloab1e0a12008-02-03 04:06:04 -08001787 .bind_conflict = inet6_csk_bind_conflict,
Dmitry Mishin3fdadf72006-03-20 22:45:21 -08001788#ifdef CONFIG_COMPAT
Arnaldo Carvalho de Melo543d9cf2006-03-20 22:48:35 -08001789 .compat_setsockopt = compat_ipv6_setsockopt,
1790 .compat_getsockopt = compat_ipv6_getsockopt,
Dmitry Mishin3fdadf72006-03-20 22:45:21 -08001791#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07001792};
1793
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -08001794#ifdef CONFIG_TCP_MD5SIG
Stephen Hemmingerb2e4b3de2009-09-01 19:25:03 +00001795static const struct tcp_sock_af_ops tcp_sock_ipv6_mapped_specific = {
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -08001796 .md5_lookup = tcp_v4_md5_lookup,
Adam Langley49a72df2008-07-19 00:01:42 -07001797 .calc_md5_hash = tcp_v4_md5_hash_skb,
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -08001798 .md5_parse = tcp_v6_parse_md5_keys,
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -08001799};
David S. Millera9286302006-11-14 19:53:22 -08001800#endif
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -08001801
Linus Torvalds1da177e2005-04-16 15:20:36 -07001802/* NOTE: A lot of things set to zero explicitly by call to
1803 * sk_alloc() so need not be done here.
1804 */
1805static int tcp_v6_init_sock(struct sock *sk)
1806{
Arnaldo Carvalho de Melo6687e982005-08-10 04:03:31 -03001807 struct inet_connection_sock *icsk = inet_csk(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001808
Neal Cardwell900f65d2012-04-19 09:55:21 +00001809 tcp_init_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001810
Arnaldo Carvalho de Melo8292a172005-12-13 23:15:52 -08001811 icsk->icsk_af_ops = &ipv6_specific;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001812
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -08001813#ifdef CONFIG_TCP_MD5SIG
David S. Millerac807fa2012-04-23 03:21:58 -04001814 tcp_sk(sk)->af_specific = &tcp_sock_ipv6_specific;
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -08001815#endif
1816
Linus Torvalds1da177e2005-04-16 15:20:36 -07001817 return 0;
1818}
1819
Brian Haley7d06b2e2008-06-14 17:04:49 -07001820static void tcp_v6_destroy_sock(struct sock *sk)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001821{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001822 tcp_v4_destroy_sock(sk);
Brian Haley7d06b2e2008-06-14 17:04:49 -07001823 inet6_destroy_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001824}
1825
YOSHIFUJI Hideaki952a10b2007-04-21 20:13:44 +09001826#ifdef CONFIG_PROC_FS
Linus Torvalds1da177e2005-04-16 15:20:36 -07001827/* Proc filesystem TCPv6 sock list dumping. */
YOSHIFUJI Hideaki1ab14572007-02-09 23:24:49 +09001828static void get_openreq6(struct seq_file *seq,
Eric Dumazetcf533ea2011-10-21 05:22:42 -04001829 const struct sock *sk, struct request_sock *req, int i, int uid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001830{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001831 int ttd = req->expires - jiffies;
Eric Dumazetb71d1d42011-04-22 04:53:02 +00001832 const struct in6_addr *src = &inet6_rsk(req)->loc_addr;
1833 const struct in6_addr *dest = &inet6_rsk(req)->rmt_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001834
1835 if (ttd < 0)
1836 ttd = 0;
1837
Linus Torvalds1da177e2005-04-16 15:20:36 -07001838 seq_printf(seq,
1839 "%4d: %08X%08X%08X%08X:%04X %08X%08X%08X%08X:%04X "
Dan Rosenberg71338aa2011-05-23 12:17:35 +00001840 "%02X %08X:%08X %02X:%08lX %08X %5d %8d %d %d %pK\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001841 i,
1842 src->s6_addr32[0], src->s6_addr32[1],
1843 src->s6_addr32[2], src->s6_addr32[3],
KOVACS Krisztianfd507032008-10-19 23:35:58 -07001844 ntohs(inet_rsk(req)->loc_port),
Linus Torvalds1da177e2005-04-16 15:20:36 -07001845 dest->s6_addr32[0], dest->s6_addr32[1],
1846 dest->s6_addr32[2], dest->s6_addr32[3],
Arnaldo Carvalho de Melo2e6599c2005-06-18 22:46:52 -07001847 ntohs(inet_rsk(req)->rmt_port),
Linus Torvalds1da177e2005-04-16 15:20:36 -07001848 TCP_SYN_RECV,
1849 0,0, /* could print option size, but that is af dependent. */
YOSHIFUJI Hideaki1ab14572007-02-09 23:24:49 +09001850 1, /* timers active (only the expire timer) */
1851 jiffies_to_clock_t(ttd),
Linus Torvalds1da177e2005-04-16 15:20:36 -07001852 req->retrans,
1853 uid,
YOSHIFUJI Hideaki1ab14572007-02-09 23:24:49 +09001854 0, /* non standard timer */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001855 0, /* open_requests have no inode */
1856 0, req);
1857}
1858
1859static void get_tcp6_sock(struct seq_file *seq, struct sock *sp, int i)
1860{
Eric Dumazetb71d1d42011-04-22 04:53:02 +00001861 const struct in6_addr *dest, *src;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001862 __u16 destp, srcp;
1863 int timer_active;
1864 unsigned long timer_expires;
Eric Dumazetcf533ea2011-10-21 05:22:42 -04001865 const struct inet_sock *inet = inet_sk(sp);
1866 const struct tcp_sock *tp = tcp_sk(sp);
Arnaldo Carvalho de Melo463c84b2005-08-09 20:10:42 -07001867 const struct inet_connection_sock *icsk = inet_csk(sp);
Eric Dumazetcf533ea2011-10-21 05:22:42 -04001868 const struct ipv6_pinfo *np = inet6_sk(sp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001869
1870 dest = &np->daddr;
1871 src = &np->rcv_saddr;
Eric Dumazetc720c7e82009-10-15 06:30:45 +00001872 destp = ntohs(inet->inet_dport);
1873 srcp = ntohs(inet->inet_sport);
Arnaldo Carvalho de Melo463c84b2005-08-09 20:10:42 -07001874
1875 if (icsk->icsk_pending == ICSK_TIME_RETRANS) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001876 timer_active = 1;
Arnaldo Carvalho de Melo463c84b2005-08-09 20:10:42 -07001877 timer_expires = icsk->icsk_timeout;
1878 } else if (icsk->icsk_pending == ICSK_TIME_PROBE0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001879 timer_active = 4;
Arnaldo Carvalho de Melo463c84b2005-08-09 20:10:42 -07001880 timer_expires = icsk->icsk_timeout;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001881 } else if (timer_pending(&sp->sk_timer)) {
1882 timer_active = 2;
1883 timer_expires = sp->sk_timer.expires;
1884 } else {
1885 timer_active = 0;
1886 timer_expires = jiffies;
1887 }
1888
1889 seq_printf(seq,
1890 "%4d: %08X%08X%08X%08X:%04X %08X%08X%08X%08X:%04X "
Dan Rosenberg71338aa2011-05-23 12:17:35 +00001891 "%02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %pK %lu %lu %u %u %d\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001892 i,
1893 src->s6_addr32[0], src->s6_addr32[1],
1894 src->s6_addr32[2], src->s6_addr32[3], srcp,
1895 dest->s6_addr32[0], dest->s6_addr32[1],
1896 dest->s6_addr32[2], dest->s6_addr32[3], destp,
YOSHIFUJI Hideaki1ab14572007-02-09 23:24:49 +09001897 sp->sk_state,
Sridhar Samudrala47da8ee2006-06-27 13:29:00 -07001898 tp->write_seq-tp->snd_una,
1899 (sp->sk_state == TCP_LISTEN) ? sp->sk_ack_backlog : (tp->rcv_nxt - tp->copied_seq),
Linus Torvalds1da177e2005-04-16 15:20:36 -07001900 timer_active,
1901 jiffies_to_clock_t(timer_expires - jiffies),
Arnaldo Carvalho de Melo463c84b2005-08-09 20:10:42 -07001902 icsk->icsk_retransmits,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001903 sock_i_uid(sp),
Arnaldo Carvalho de Melo6687e982005-08-10 04:03:31 -03001904 icsk->icsk_probes_out,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001905 sock_i_ino(sp),
1906 atomic_read(&sp->sk_refcnt), sp,
Stephen Hemminger7be87352008-06-27 20:00:19 -07001907 jiffies_to_clock_t(icsk->icsk_rto),
1908 jiffies_to_clock_t(icsk->icsk_ack.ato),
Arnaldo Carvalho de Melo463c84b2005-08-09 20:10:42 -07001909 (icsk->icsk_ack.quick << 1 ) | icsk->icsk_ack.pingpong,
Ilpo Järvinen0b6a05c2009-09-15 01:30:10 -07001910 tp->snd_cwnd,
1911 tcp_in_initial_slowstart(tp) ? -1 : tp->snd_ssthresh
Linus Torvalds1da177e2005-04-16 15:20:36 -07001912 );
1913}
1914
YOSHIFUJI Hideaki1ab14572007-02-09 23:24:49 +09001915static void get_timewait6_sock(struct seq_file *seq,
Arnaldo Carvalho de Melo8feaf0c02005-08-09 20:09:30 -07001916 struct inet_timewait_sock *tw, int i)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001917{
Eric Dumazetb71d1d42011-04-22 04:53:02 +00001918 const struct in6_addr *dest, *src;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001919 __u16 destp, srcp;
Eric Dumazetcf533ea2011-10-21 05:22:42 -04001920 const struct inet6_timewait_sock *tw6 = inet6_twsk((struct sock *)tw);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001921 int ttd = tw->tw_ttd - jiffies;
1922
1923 if (ttd < 0)
1924 ttd = 0;
1925
Arnaldo Carvalho de Melo0fa1a532005-12-13 23:23:09 -08001926 dest = &tw6->tw_v6_daddr;
1927 src = &tw6->tw_v6_rcv_saddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001928 destp = ntohs(tw->tw_dport);
1929 srcp = ntohs(tw->tw_sport);
1930
1931 seq_printf(seq,
1932 "%4d: %08X%08X%08X%08X:%04X %08X%08X%08X%08X:%04X "
Dan Rosenberg71338aa2011-05-23 12:17:35 +00001933 "%02X %08X:%08X %02X:%08lX %08X %5d %8d %d %d %pK\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001934 i,
1935 src->s6_addr32[0], src->s6_addr32[1],
1936 src->s6_addr32[2], src->s6_addr32[3], srcp,
1937 dest->s6_addr32[0], dest->s6_addr32[1],
1938 dest->s6_addr32[2], dest->s6_addr32[3], destp,
1939 tw->tw_substate, 0, 0,
1940 3, jiffies_to_clock_t(ttd), 0, 0, 0, 0,
1941 atomic_read(&tw->tw_refcnt), tw);
1942}
1943
Linus Torvalds1da177e2005-04-16 15:20:36 -07001944static int tcp6_seq_show(struct seq_file *seq, void *v)
1945{
1946 struct tcp_iter_state *st;
1947
1948 if (v == SEQ_START_TOKEN) {
1949 seq_puts(seq,
1950 " sl "
1951 "local_address "
1952 "remote_address "
1953 "st tx_queue rx_queue tr tm->when retrnsmt"
1954 " uid timeout inode\n");
1955 goto out;
1956 }
1957 st = seq->private;
1958
1959 switch (st->state) {
1960 case TCP_SEQ_STATE_LISTENING:
1961 case TCP_SEQ_STATE_ESTABLISHED:
1962 get_tcp6_sock(seq, v, st->num);
1963 break;
1964 case TCP_SEQ_STATE_OPENREQ:
1965 get_openreq6(seq, st->syn_wait_sk, v, st->num, st->uid);
1966 break;
1967 case TCP_SEQ_STATE_TIME_WAIT:
1968 get_timewait6_sock(seq, v, st->num);
1969 break;
1970 }
1971out:
1972 return 0;
1973}
1974
Arjan van de Ven73cb88e2011-10-30 06:46:30 +00001975static const struct file_operations tcp6_afinfo_seq_fops = {
1976 .owner = THIS_MODULE,
1977 .open = tcp_seq_open,
1978 .read = seq_read,
1979 .llseek = seq_lseek,
1980 .release = seq_release_net
1981};
1982
Linus Torvalds1da177e2005-04-16 15:20:36 -07001983static struct tcp_seq_afinfo tcp6_seq_afinfo = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001984 .name = "tcp6",
1985 .family = AF_INET6,
Arjan van de Ven73cb88e2011-10-30 06:46:30 +00001986 .seq_fops = &tcp6_afinfo_seq_fops,
Denis V. Lunev9427c4b2008-04-13 22:12:13 -07001987 .seq_ops = {
1988 .show = tcp6_seq_show,
1989 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07001990};
1991
Alexey Dobriyan2c8c1e72010-01-17 03:35:32 +00001992int __net_init tcp6_proc_init(struct net *net)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001993{
Daniel Lezcano6f8b13b2008-03-21 04:14:45 -07001994 return tcp_proc_register(net, &tcp6_seq_afinfo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001995}
1996
Daniel Lezcano6f8b13b2008-03-21 04:14:45 -07001997void tcp6_proc_exit(struct net *net)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001998{
Daniel Lezcano6f8b13b2008-03-21 04:14:45 -07001999 tcp_proc_unregister(net, &tcp6_seq_afinfo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002000}
2001#endif
2002
2003struct proto tcpv6_prot = {
2004 .name = "TCPv6",
2005 .owner = THIS_MODULE,
2006 .close = tcp_close,
2007 .connect = tcp_v6_connect,
2008 .disconnect = tcp_disconnect,
Arnaldo Carvalho de Melo463c84b2005-08-09 20:10:42 -07002009 .accept = inet_csk_accept,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002010 .ioctl = tcp_ioctl,
2011 .init = tcp_v6_init_sock,
2012 .destroy = tcp_v6_destroy_sock,
2013 .shutdown = tcp_shutdown,
2014 .setsockopt = tcp_setsockopt,
2015 .getsockopt = tcp_getsockopt,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002016 .recvmsg = tcp_recvmsg,
Changli Gao7ba42912010-07-10 20:41:55 +00002017 .sendmsg = tcp_sendmsg,
2018 .sendpage = tcp_sendpage,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002019 .backlog_rcv = tcp_v6_do_rcv,
Eric Dumazet46d3cea2012-07-11 05:50:31 +00002020 .release_cb = tcp_release_cb,
Eric Dumazet563d34d2012-07-23 09:48:52 +02002021 .mtu_reduced = tcp_v6_mtu_reduced,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002022 .hash = tcp_v6_hash,
Arnaldo Carvalho de Meloab1e0a12008-02-03 04:06:04 -08002023 .unhash = inet_unhash,
2024 .get_port = inet_csk_get_port,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002025 .enter_memory_pressure = tcp_enter_memory_pressure,
2026 .sockets_allocated = &tcp_sockets_allocated,
2027 .memory_allocated = &tcp_memory_allocated,
2028 .memory_pressure = &tcp_memory_pressure,
Arnaldo Carvalho de Melo0a5578c2005-08-09 20:11:41 -07002029 .orphan_count = &tcp_orphan_count,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002030 .sysctl_wmem = sysctl_tcp_wmem,
2031 .sysctl_rmem = sysctl_tcp_rmem,
2032 .max_header = MAX_TCP_HEADER,
2033 .obj_size = sizeof(struct tcp6_sock),
Eric Dumazet3ab5aee2008-11-16 19:40:17 -08002034 .slab_flags = SLAB_DESTROY_BY_RCU,
Arnaldo Carvalho de Melo6d6ee432005-12-13 23:25:19 -08002035 .twsk_prot = &tcp6_timewait_sock_ops,
Arnaldo Carvalho de Melo60236fd2005-06-18 22:47:21 -07002036 .rsk_prot = &tcp6_request_sock_ops,
Pavel Emelyanov39d8cda2008-03-22 16:50:58 -07002037 .h.hashinfo = &tcp_hashinfo,
Changli Gao7ba42912010-07-10 20:41:55 +00002038 .no_autobind = true,
Arnaldo Carvalho de Melo543d9cf2006-03-20 22:48:35 -08002039#ifdef CONFIG_COMPAT
2040 .compat_setsockopt = compat_tcp_setsockopt,
2041 .compat_getsockopt = compat_tcp_getsockopt,
2042#endif
Andrew Mortonc255a452012-07-31 16:43:02 -07002043#ifdef CONFIG_MEMCG_KMEM
Glauber Costad1a4c0b2011-12-11 21:47:04 +00002044 .proto_cgroup = tcp_proto_cgroup,
2045#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07002046};
2047
Alexey Dobriyan41135cc2009-09-14 12:22:28 +00002048static const struct inet6_protocol tcpv6_protocol = {
Eric Dumazetc7109982012-07-26 12:18:11 +00002049 .early_demux = tcp_v6_early_demux,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002050 .handler = tcp_v6_rcv,
2051 .err_handler = tcp_v6_err,
Herbert Xua430a432006-07-08 13:34:56 -07002052 .gso_send_check = tcp_v6_gso_send_check,
Herbert Xuadcfc7d2006-06-30 13:36:15 -07002053 .gso_segment = tcp_tso_segment,
Herbert Xu684f2172009-01-08 10:41:23 -08002054 .gro_receive = tcp6_gro_receive,
2055 .gro_complete = tcp6_gro_complete,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002056 .flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL,
2057};
2058
Linus Torvalds1da177e2005-04-16 15:20:36 -07002059static struct inet_protosw tcpv6_protosw = {
2060 .type = SOCK_STREAM,
2061 .protocol = IPPROTO_TCP,
2062 .prot = &tcpv6_prot,
2063 .ops = &inet6_stream_ops,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002064 .no_check = 0,
Arnaldo Carvalho de Melod83d8462005-12-13 23:26:10 -08002065 .flags = INET_PROTOSW_PERMANENT |
2066 INET_PROTOSW_ICSK,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002067};
2068
Alexey Dobriyan2c8c1e72010-01-17 03:35:32 +00002069static int __net_init tcpv6_net_init(struct net *net)
Daniel Lezcano93ec9262008-03-07 11:16:02 -08002070{
Denis V. Lunev56772422008-04-03 14:28:30 -07002071 return inet_ctl_sock_create(&net->ipv6.tcp_sk, PF_INET6,
2072 SOCK_RAW, IPPROTO_TCP, net);
Daniel Lezcano93ec9262008-03-07 11:16:02 -08002073}
2074
Alexey Dobriyan2c8c1e72010-01-17 03:35:32 +00002075static void __net_exit tcpv6_net_exit(struct net *net)
Daniel Lezcano93ec9262008-03-07 11:16:02 -08002076{
Denis V. Lunev56772422008-04-03 14:28:30 -07002077 inet_ctl_sock_destroy(net->ipv6.tcp_sk);
Eric W. Biedermanb099ce22009-12-03 02:29:09 +00002078}
2079
Alexey Dobriyan2c8c1e72010-01-17 03:35:32 +00002080static void __net_exit tcpv6_net_exit_batch(struct list_head *net_exit_list)
Eric W. Biedermanb099ce22009-12-03 02:29:09 +00002081{
2082 inet_twsk_purge(&tcp_hashinfo, &tcp_death_row, AF_INET6);
Daniel Lezcano93ec9262008-03-07 11:16:02 -08002083}
2084
2085static struct pernet_operations tcpv6_net_ops = {
Eric W. Biedermanb099ce22009-12-03 02:29:09 +00002086 .init = tcpv6_net_init,
2087 .exit = tcpv6_net_exit,
2088 .exit_batch = tcpv6_net_exit_batch,
Daniel Lezcano93ec9262008-03-07 11:16:02 -08002089};
2090
Daniel Lezcano7f4e4862007-12-11 02:25:35 -08002091int __init tcpv6_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002092{
Daniel Lezcano7f4e4862007-12-11 02:25:35 -08002093 int ret;
David Woodhouseae0f7d52006-01-11 15:53:04 -08002094
Daniel Lezcano7f4e4862007-12-11 02:25:35 -08002095 ret = inet6_add_protocol(&tcpv6_protocol, IPPROTO_TCP);
2096 if (ret)
2097 goto out;
2098
2099 /* register inet6 protocol */
2100 ret = inet6_register_protosw(&tcpv6_protosw);
2101 if (ret)
2102 goto out_tcpv6_protocol;
2103
Daniel Lezcano93ec9262008-03-07 11:16:02 -08002104 ret = register_pernet_subsys(&tcpv6_net_ops);
Daniel Lezcano7f4e4862007-12-11 02:25:35 -08002105 if (ret)
2106 goto out_tcpv6_protosw;
2107out:
2108 return ret;
2109
2110out_tcpv6_protocol:
2111 inet6_del_protocol(&tcpv6_protocol, IPPROTO_TCP);
2112out_tcpv6_protosw:
2113 inet6_unregister_protosw(&tcpv6_protosw);
2114 goto out;
2115}
2116
Daniel Lezcano09f77092007-12-13 05:34:58 -08002117void tcpv6_exit(void)
Daniel Lezcano7f4e4862007-12-11 02:25:35 -08002118{
Daniel Lezcano93ec9262008-03-07 11:16:02 -08002119 unregister_pernet_subsys(&tcpv6_net_ops);
Daniel Lezcano7f4e4862007-12-11 02:25:35 -08002120 inet6_unregister_protosw(&tcpv6_protosw);
2121 inet6_del_protocol(&tcpv6_protocol, IPPROTO_TCP);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002122}