blob: 4a4e6d30c448b1ee8ec4948e025ed0a19d505553 [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>
Wang Yufen4aa956d2014-03-29 09:27:29 +080042#include <linux/uaccess.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070043#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>
Denis V. Lunev3d58b5f2008-04-03 14:22:32 -070062#include <net/inet_common.h>
David S. Miller6e5714e2011-08-03 20:50:44 -070063#include <net/secure_seq.h>
Glauber Costad1a4c0b2011-12-11 21:47:04 +000064#include <net/tcp_memcontrol.h>
Eliezer Tamir076bb0c2013-07-10 17:13:17 +030065#include <net/busy_poll.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070066
Linus Torvalds1da177e2005-04-16 15:20:36 -070067#include <linux/proc_fs.h>
68#include <linux/seq_file.h>
69
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -080070#include <linux/crypto.h>
71#include <linux/scatterlist.h>
72
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -080073static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb);
Gui Jianfeng6edafaa2008-08-06 23:50:04 -070074static void tcp_v6_reqsk_send_ack(struct sock *sk, struct sk_buff *skb,
75 struct request_sock *req);
Linus Torvalds1da177e2005-04-16 15:20:36 -070076
77static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -070078
Stephen Hemminger3b401a82009-09-01 19:25:04 +000079static const struct inet_connection_sock_af_ops ipv6_mapped;
80static const struct inet_connection_sock_af_ops ipv6_specific;
David S. Millera9286302006-11-14 19:53:22 -080081#ifdef CONFIG_TCP_MD5SIG
Stephen Hemmingerb2e4b3d2009-09-01 19:25:03 +000082static const struct tcp_sock_af_ops tcp_sock_ipv6_specific;
83static const struct tcp_sock_af_ops tcp_sock_ipv6_mapped_specific;
YOSHIFUJI Hideaki9501f972008-04-18 12:45:16 +090084#else
85static struct tcp_md5sig_key *tcp_v6_md5_do_lookup(struct sock *sk,
Eric Dumazetb71d1d42011-04-22 04:53:02 +000086 const struct in6_addr *addr)
YOSHIFUJI Hideaki9501f972008-04-18 12:45:16 +090087{
88 return NULL;
89}
David S. Millera9286302006-11-14 19:53:22 -080090#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -070091
Neal Cardwellfae6ef82012-08-19 03:30:38 +000092static void inet6_sk_rx_dst_set(struct sock *sk, const struct sk_buff *skb)
93{
94 struct dst_entry *dst = skb_dst(skb);
Neal Cardwellfae6ef82012-08-19 03:30:38 +000095
Eric Dumazetca777ef2014-09-08 08:06:07 -070096 if (dst) {
97 const struct rt6_info *rt = (const struct rt6_info *)dst;
98
99 dst_hold(dst);
100 sk->sk_rx_dst = dst;
101 inet_sk(sk)->rx_dst_ifindex = skb->skb_iif;
102 if (rt->rt6i_node)
103 inet6_sk(sk)->rx_dst_cookie = rt->rt6i_node->fn_sernum;
104 }
Neal Cardwellfae6ef82012-08-19 03:30:38 +0000105}
106
Eric Dumazetcf533ea2011-10-21 05:22:42 -0400107static __u32 tcp_v6_init_sequence(const struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700108{
Arnaldo Carvalho de Melo0660e032007-04-25 17:54:47 -0700109 return secure_tcpv6_sequence_number(ipv6_hdr(skb)->daddr.s6_addr32,
110 ipv6_hdr(skb)->saddr.s6_addr32,
Arnaldo Carvalho de Meloaa8223c2007-04-10 21:04:22 -0700111 tcp_hdr(skb)->dest,
112 tcp_hdr(skb)->source);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700113}
114
YOSHIFUJI Hideaki1ab14572007-02-09 23:24:49 +0900115static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700116 int addr_len)
117{
118 struct sockaddr_in6 *usin = (struct sockaddr_in6 *) uaddr;
YOSHIFUJI Hideaki1ab14572007-02-09 23:24:49 +0900119 struct inet_sock *inet = inet_sk(sk);
Arnaldo Carvalho de Melod83d8462005-12-13 23:26:10 -0800120 struct inet_connection_sock *icsk = inet_csk(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700121 struct ipv6_pinfo *np = inet6_sk(sk);
122 struct tcp_sock *tp = tcp_sk(sk);
Arnaud Ebalard20c59de2010-06-01 21:35:01 +0000123 struct in6_addr *saddr = NULL, *final_p, final;
David S. Miller493f3772010-12-02 12:14:29 -0800124 struct rt6_info *rt;
David S. Miller4c9483b2011-03-12 16:22:43 -0500125 struct flowi6 fl6;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700126 struct dst_entry *dst;
127 int addr_type;
128 int err;
129
YOSHIFUJI Hideaki1ab14572007-02-09 23:24:49 +0900130 if (addr_len < SIN6_LEN_RFC2133)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700131 return -EINVAL;
132
YOSHIFUJI Hideaki1ab14572007-02-09 23:24:49 +0900133 if (usin->sin6_family != AF_INET6)
Eric Dumazeta02cec22010-09-22 20:43:57 +0000134 return -EAFNOSUPPORT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700135
David S. Miller4c9483b2011-03-12 16:22:43 -0500136 memset(&fl6, 0, sizeof(fl6));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700137
138 if (np->sndflow) {
David S. Miller4c9483b2011-03-12 16:22:43 -0500139 fl6.flowlabel = usin->sin6_flowinfo&IPV6_FLOWINFO_MASK;
140 IP6_ECN_flow_init(fl6.flowlabel);
141 if (fl6.flowlabel&IPV6_FLOWLABEL_MASK) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700142 struct ip6_flowlabel *flowlabel;
David S. Miller4c9483b2011-03-12 16:22:43 -0500143 flowlabel = fl6_sock_lookup(sk, fl6.flowlabel);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700144 if (flowlabel == NULL)
145 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700146 fl6_sock_release(flowlabel);
147 }
148 }
149
150 /*
YOSHIFUJI Hideaki1ab14572007-02-09 23:24:49 +0900151 * connect() to INADDR_ANY means loopback (BSD'ism).
152 */
153
Weilong Chen4c99aa42013-12-19 18:44:34 +0800154 if (ipv6_addr_any(&usin->sin6_addr))
YOSHIFUJI Hideaki1ab14572007-02-09 23:24:49 +0900155 usin->sin6_addr.s6_addr[15] = 0x1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700156
157 addr_type = ipv6_addr_type(&usin->sin6_addr);
158
Weilong Chen4c99aa42013-12-19 18:44:34 +0800159 if (addr_type & IPV6_ADDR_MULTICAST)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700160 return -ENETUNREACH;
161
162 if (addr_type&IPV6_ADDR_LINKLOCAL) {
163 if (addr_len >= sizeof(struct sockaddr_in6) &&
164 usin->sin6_scope_id) {
165 /* If interface is set while binding, indices
166 * must coincide.
167 */
168 if (sk->sk_bound_dev_if &&
169 sk->sk_bound_dev_if != usin->sin6_scope_id)
170 return -EINVAL;
171
172 sk->sk_bound_dev_if = usin->sin6_scope_id;
173 }
174
175 /* Connect to link-local address requires an interface */
176 if (!sk->sk_bound_dev_if)
177 return -EINVAL;
178 }
179
180 if (tp->rx_opt.ts_recent_stamp &&
Eric Dumazetefe42082013-10-03 15:42:29 -0700181 !ipv6_addr_equal(&sk->sk_v6_daddr, &usin->sin6_addr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700182 tp->rx_opt.ts_recent = 0;
183 tp->rx_opt.ts_recent_stamp = 0;
184 tp->write_seq = 0;
185 }
186
Eric Dumazetefe42082013-10-03 15:42:29 -0700187 sk->sk_v6_daddr = usin->sin6_addr;
David S. Miller4c9483b2011-03-12 16:22:43 -0500188 np->flow_label = fl6.flowlabel;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700189
190 /*
191 * TCP over IPv4
192 */
193
194 if (addr_type == IPV6_ADDR_MAPPED) {
Arnaldo Carvalho de Melod83d8462005-12-13 23:26:10 -0800195 u32 exthdrlen = icsk->icsk_ext_hdr_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700196 struct sockaddr_in sin;
197
198 SOCK_DEBUG(sk, "connect: ipv4 mapped\n");
199
200 if (__ipv6_only_sock(sk))
201 return -ENETUNREACH;
202
203 sin.sin_family = AF_INET;
204 sin.sin_port = usin->sin6_port;
205 sin.sin_addr.s_addr = usin->sin6_addr.s6_addr32[3];
206
Arnaldo Carvalho de Melod83d8462005-12-13 23:26:10 -0800207 icsk->icsk_af_ops = &ipv6_mapped;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700208 sk->sk_backlog_rcv = tcp_v4_do_rcv;
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800209#ifdef CONFIG_TCP_MD5SIG
210 tp->af_specific = &tcp_sock_ipv6_mapped_specific;
211#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700212
213 err = tcp_v4_connect(sk, (struct sockaddr *)&sin, sizeof(sin));
214
215 if (err) {
Arnaldo Carvalho de Melod83d8462005-12-13 23:26:10 -0800216 icsk->icsk_ext_hdr_len = exthdrlen;
217 icsk->icsk_af_ops = &ipv6_specific;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700218 sk->sk_backlog_rcv = tcp_v6_do_rcv;
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800219#ifdef CONFIG_TCP_MD5SIG
220 tp->af_specific = &tcp_sock_ipv6_specific;
221#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700222 goto failure;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700223 }
Eric Dumazetd1e559d2015-03-18 14:05:35 -0700224 np->saddr = sk->sk_v6_rcv_saddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700225
226 return err;
227 }
228
Eric Dumazetefe42082013-10-03 15:42:29 -0700229 if (!ipv6_addr_any(&sk->sk_v6_rcv_saddr))
230 saddr = &sk->sk_v6_rcv_saddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700231
David S. Miller4c9483b2011-03-12 16:22:43 -0500232 fl6.flowi6_proto = IPPROTO_TCP;
Eric Dumazetefe42082013-10-03 15:42:29 -0700233 fl6.daddr = sk->sk_v6_daddr;
Alexey Dobriyan4e3fd7a2011-11-21 03:39:03 +0000234 fl6.saddr = saddr ? *saddr : np->saddr;
David S. Miller4c9483b2011-03-12 16:22:43 -0500235 fl6.flowi6_oif = sk->sk_bound_dev_if;
236 fl6.flowi6_mark = sk->sk_mark;
David S. Miller1958b852011-03-12 16:36:19 -0500237 fl6.fl6_dport = usin->sin6_port;
238 fl6.fl6_sport = inet->inet_sport;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700239
David S. Miller4c9483b2011-03-12 16:22:43 -0500240 final_p = fl6_update_dst(&fl6, np->opt, &final);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700241
David S. Miller4c9483b2011-03-12 16:22:43 -0500242 security_sk_classify_flow(sk, flowi6_to_flowi(&fl6));
Venkat Yekkiralabeb8d132006-08-04 23:12:42 -0700243
Steffen Klassert0e0d44a2013-08-28 08:04:14 +0200244 dst = ip6_dst_lookup_flow(sk, &fl6, final_p);
David S. Miller68d0c6d2011-03-01 13:19:07 -0800245 if (IS_ERR(dst)) {
246 err = PTR_ERR(dst);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700247 goto failure;
David S. Miller14e50e52007-05-24 18:17:54 -0700248 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700249
250 if (saddr == NULL) {
David S. Miller4c9483b2011-03-12 16:22:43 -0500251 saddr = &fl6.saddr;
Eric Dumazetefe42082013-10-03 15:42:29 -0700252 sk->sk_v6_rcv_saddr = *saddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700253 }
254
255 /* set the source address */
Alexey Dobriyan4e3fd7a2011-11-21 03:39:03 +0000256 np->saddr = *saddr;
Eric Dumazetc720c7e2009-10-15 06:30:45 +0000257 inet->inet_rcv_saddr = LOOPBACK4_IPV6;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700258
Herbert Xuf83ef8c2006-06-30 13:37:03 -0700259 sk->sk_gso_type = SKB_GSO_TCPV6;
YOSHIFUJI Hideaki8e1ef0a2006-08-29 17:15:09 -0700260 __ip6_dst_store(sk, dst, NULL, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700261
David S. Miller493f3772010-12-02 12:14:29 -0800262 rt = (struct rt6_info *) dst;
263 if (tcp_death_row.sysctl_tw_recycle &&
264 !tp->rx_opt.ts_recent_stamp &&
Eric Dumazetefe42082013-10-03 15:42:29 -0700265 ipv6_addr_equal(&rt->rt6i_dst.addr, &sk->sk_v6_daddr))
David S. Miller81166dd2012-07-10 03:14:24 -0700266 tcp_fetch_timewait_stamp(sk, dst);
David S. Miller493f3772010-12-02 12:14:29 -0800267
Arnaldo Carvalho de Melod83d8462005-12-13 23:26:10 -0800268 icsk->icsk_ext_hdr_len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700269 if (np->opt)
Arnaldo Carvalho de Melod83d8462005-12-13 23:26:10 -0800270 icsk->icsk_ext_hdr_len = (np->opt->opt_flen +
271 np->opt->opt_nflen);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700272
273 tp->rx_opt.mss_clamp = IPV6_MIN_MTU - sizeof(struct tcphdr) - sizeof(struct ipv6hdr);
274
Eric Dumazetc720c7e2009-10-15 06:30:45 +0000275 inet->inet_dport = usin->sin6_port;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700276
277 tcp_set_state(sk, TCP_SYN_SENT);
Arnaldo Carvalho de Melod8313f52005-12-13 23:25:44 -0800278 err = inet6_hash_connect(&tcp_death_row, sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700279 if (err)
280 goto late_failure;
281
Sathya Perla9e7ceb02014-10-22 21:42:01 +0530282 ip6_set_txhash(sk);
283
Andrey Vagin2b916472012-11-22 01:13:58 +0000284 if (!tp->write_seq && likely(!tp->repair))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700285 tp->write_seq = secure_tcpv6_sequence_number(np->saddr.s6_addr32,
Eric Dumazetefe42082013-10-03 15:42:29 -0700286 sk->sk_v6_daddr.s6_addr32,
Eric Dumazetc720c7e2009-10-15 06:30:45 +0000287 inet->inet_sport,
288 inet->inet_dport);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700289
290 err = tcp_connect(sk);
291 if (err)
292 goto late_failure;
293
294 return 0;
295
296late_failure:
297 tcp_set_state(sk, TCP_CLOSE);
298 __sk_dst_reset(sk);
299failure:
Eric Dumazetc720c7e2009-10-15 06:30:45 +0000300 inet->inet_dport = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700301 sk->sk_route_caps = 0;
302 return err;
303}
304
Eric Dumazet563d34d2012-07-23 09:48:52 +0200305static void tcp_v6_mtu_reduced(struct sock *sk)
306{
307 struct dst_entry *dst;
308
309 if ((1 << sk->sk_state) & (TCPF_LISTEN | TCPF_CLOSE))
310 return;
311
312 dst = inet6_csk_update_pmtu(sk, tcp_sk(sk)->mtu_info);
313 if (!dst)
314 return;
315
316 if (inet_csk(sk)->icsk_pmtu_cookie > dst_mtu(dst)) {
317 tcp_sync_mss(sk, dst_mtu(dst));
318 tcp_simple_retransmit(sk);
319 }
320}
321
Linus Torvalds1da177e2005-04-16 15:20:36 -0700322static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
Brian Haleyd5fdd6b2009-06-23 04:31:07 -0700323 u8 type, u8 code, int offset, __be32 info)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700324{
Weilong Chen4c99aa42013-12-19 18:44:34 +0800325 const struct ipv6hdr *hdr = (const struct ipv6hdr *)skb->data;
Arnaldo Carvalho de Melo505cbfc2005-08-12 09:19:38 -0300326 const struct tcphdr *th = (struct tcphdr *)(skb->data+offset);
Eric Dumazet22150892015-03-22 10:22:23 -0700327 struct net *net = dev_net(skb->dev);
328 struct request_sock *fastopen;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700329 struct ipv6_pinfo *np;
Eric Dumazet22150892015-03-22 10:22:23 -0700330 struct tcp_sock *tp;
331 __u32 seq, snd_una;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700332 struct sock *sk;
333 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700334
Eric Dumazet22150892015-03-22 10:22:23 -0700335 sk = __inet6_lookup_established(net, &tcp_hashinfo,
336 &hdr->daddr, th->dest,
337 &hdr->saddr, ntohs(th->source),
338 skb->dev->ifindex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700339
Eric Dumazet22150892015-03-22 10:22:23 -0700340 if (!sk) {
Denis V. Luneve41b5362008-10-08 10:33:26 -0700341 ICMP6_INC_STATS_BH(net, __in6_dev_get(skb->dev),
342 ICMP6_MIB_INERRORS);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700343 return;
344 }
345
346 if (sk->sk_state == TCP_TIME_WAIT) {
YOSHIFUJI Hideaki9469c7b2006-10-10 19:41:46 -0700347 inet_twsk_put(inet_twsk(sk));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700348 return;
349 }
Eric Dumazet22150892015-03-22 10:22:23 -0700350 seq = ntohl(th->seq);
351 if (sk->sk_state == TCP_NEW_SYN_RECV)
352 return tcp_req_err(sk, seq);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700353
354 bh_lock_sock(sk);
Eric Dumazet563d34d2012-07-23 09:48:52 +0200355 if (sock_owned_by_user(sk) && type != ICMPV6_PKT_TOOBIG)
Pavel Emelyanovde0744a2008-07-16 20:31:16 -0700356 NET_INC_STATS_BH(net, LINUX_MIB_LOCKDROPPEDICMPS);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700357
358 if (sk->sk_state == TCP_CLOSE)
359 goto out;
360
Stephen Hemmingere802af92010-04-22 15:24:53 -0700361 if (ipv6_hdr(skb)->hop_limit < inet6_sk(sk)->min_hopcount) {
362 NET_INC_STATS_BH(net, LINUX_MIB_TCPMINTTLDROP);
363 goto out;
364 }
365
Linus Torvalds1da177e2005-04-16 15:20:36 -0700366 tp = tcp_sk(sk);
Yuchung Cheng0a672f72014-05-11 20:22:12 -0700367 /* XXX (TFO) - tp->snd_una should be ISN (tcp_create_openreq_child() */
368 fastopen = tp->fastopen_rsk;
369 snd_una = fastopen ? tcp_rsk(fastopen)->snt_isn : tp->snd_una;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700370 if (sk->sk_state != TCP_LISTEN &&
Yuchung Cheng0a672f72014-05-11 20:22:12 -0700371 !between(seq, snd_una, tp->snd_nxt)) {
Pavel Emelyanovde0744a2008-07-16 20:31:16 -0700372 NET_INC_STATS_BH(net, LINUX_MIB_OUTOFWINDOWICMPS);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700373 goto out;
374 }
375
376 np = inet6_sk(sk);
377
David S. Millerec18d9a2012-07-12 00:25:15 -0700378 if (type == NDISC_REDIRECT) {
379 struct dst_entry *dst = __sk_dst_check(sk, np->dst_cookie);
380
David S. Miller1ed5c482012-07-12 00:41:25 -0700381 if (dst)
David S. Miller6700c272012-07-17 03:29:28 -0700382 dst->ops->redirect(dst, sk, skb);
Christoph Paasch50a75a82013-04-07 04:53:15 +0000383 goto out;
David S. Millerec18d9a2012-07-12 00:25:15 -0700384 }
385
Linus Torvalds1da177e2005-04-16 15:20:36 -0700386 if (type == ICMPV6_PKT_TOOBIG) {
Eric Dumazet0d4f0602013-03-18 07:01:28 +0000387 /* We are not interested in TCP_LISTEN and open_requests
388 * (SYN-ACKs send out by Linux are always <576bytes so
389 * they should go through unfragmented).
390 */
391 if (sk->sk_state == TCP_LISTEN)
392 goto out;
393
Hannes Frederic Sowa93b36cf2013-12-15 03:41:14 +0100394 if (!ip6_sk_accept_pmtu(sk))
395 goto out;
396
Eric Dumazet563d34d2012-07-23 09:48:52 +0200397 tp->mtu_info = ntohl(info);
398 if (!sock_owned_by_user(sk))
399 tcp_v6_mtu_reduced(sk);
Julian Anastasovd013ef2a2012-09-05 10:53:18 +0000400 else if (!test_and_set_bit(TCP_MTU_REDUCED_DEFERRED,
401 &tp->tsq_flags))
402 sock_hold(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700403 goto out;
404 }
405
406 icmpv6_err_convert(type, code, &err);
407
Arnaldo Carvalho de Melo60236fd2005-06-18 22:47:21 -0700408 /* Might be for an request_sock */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700409 switch (sk->sk_state) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700410 case TCP_SYN_SENT:
Yuchung Cheng0a672f72014-05-11 20:22:12 -0700411 case TCP_SYN_RECV:
412 /* Only in fast or simultaneous open. If a fast open socket is
413 * is already accepted it is treated as a connected one below.
414 */
415 if (fastopen && fastopen->sk == NULL)
416 break;
417
Linus Torvalds1da177e2005-04-16 15:20:36 -0700418 if (!sock_owned_by_user(sk)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700419 sk->sk_err = err;
420 sk->sk_error_report(sk); /* Wake people up to see the error (see connect in sock.c) */
421
422 tcp_done(sk);
423 } else
424 sk->sk_err_soft = err;
425 goto out;
426 }
427
428 if (!sock_owned_by_user(sk) && np->recverr) {
429 sk->sk_err = err;
430 sk->sk_error_report(sk);
431 } else
432 sk->sk_err_soft = err;
433
434out:
435 bh_unlock_sock(sk);
436 sock_put(sk);
437}
438
439
Neal Cardwell9f10d3f2012-06-28 12:34:21 +0000440static int tcp_v6_send_synack(struct sock *sk, struct dst_entry *dst,
Octavian Purdilad6274bd2014-06-25 17:09:58 +0300441 struct flowi *fl,
Neal Cardwell3840a062012-06-28 12:34:19 +0000442 struct request_sock *req,
Daniel Lee3a19ce02014-05-11 20:22:13 -0700443 u16 queue_mapping,
444 struct tcp_fastopen_cookie *foc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700445{
Eric Dumazet634fb9792013-10-09 15:21:29 -0700446 struct inet_request_sock *ireq = inet_rsk(req);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700447 struct ipv6_pinfo *np = inet6_sk(sk);
Octavian Purdilad6274bd2014-06-25 17:09:58 +0300448 struct flowi6 *fl6 = &fl->u.ip6;
Weilong Chen4c99aa42013-12-19 18:44:34 +0800449 struct sk_buff *skb;
Neal Cardwell94942182012-06-28 12:34:20 +0000450 int err = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700451
Neal Cardwell9f10d3f2012-06-28 12:34:21 +0000452 /* First, grab a route. */
453 if (!dst && (dst = inet6_csk_route_req(sk, fl6, req)) == NULL)
Denis V. Lunevfd80eb92008-02-29 11:43:03 -0800454 goto done;
Neal Cardwell94942182012-06-28 12:34:20 +0000455
Daniel Lee3a19ce02014-05-11 20:22:13 -0700456 skb = tcp_make_synack(sk, dst, req, foc);
Neal Cardwell94942182012-06-28 12:34:20 +0000457
Linus Torvalds1da177e2005-04-16 15:20:36 -0700458 if (skb) {
Eric Dumazet634fb9792013-10-09 15:21:29 -0700459 __tcp_v6_send_check(skb, &ireq->ir_v6_loc_addr,
460 &ireq->ir_v6_rmt_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700461
Eric Dumazet634fb9792013-10-09 15:21:29 -0700462 fl6->daddr = ireq->ir_v6_rmt_addr;
Florent Fourcotdf3687f2014-01-17 17:15:03 +0100463 if (np->repflow && (ireq->pktopts != NULL))
464 fl6->flowlabel = ip6_flowlabel(ipv6_hdr(ireq->pktopts));
465
Eric Dumazetfff32692012-06-01 01:47:50 +0000466 skb_set_queue_mapping(skb, queue_mapping);
RongQing.Li43264e02012-07-01 17:18:59 +0000467 err = ip6_xmit(sk, skb, fl6, np->opt, np->tclass);
Gerrit Renkerb9df3cb2006-11-14 11:21:36 -0200468 err = net_xmit_eval(err);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700469 }
470
471done:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700472 return err;
473}
474
Octavian Purdila72659ec2010-01-17 19:09:39 -0800475
Arnaldo Carvalho de Melo60236fd2005-06-18 22:47:21 -0700476static void tcp_v6_reqsk_destructor(struct request_sock *req)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700477{
Eric Dumazet634fb9792013-10-09 15:21:29 -0700478 kfree_skb(inet_rsk(req)->pktopts);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700479}
480
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800481#ifdef CONFIG_TCP_MD5SIG
482static struct tcp_md5sig_key *tcp_v6_md5_do_lookup(struct sock *sk,
Eric Dumazetb71d1d42011-04-22 04:53:02 +0000483 const struct in6_addr *addr)
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800484{
Eric Dumazeta915da9b2012-01-31 05:18:33 +0000485 return tcp_md5_do_lookup(sk, (union tcp_md5_addr *)addr, AF_INET6);
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800486}
487
488static struct tcp_md5sig_key *tcp_v6_md5_lookup(struct sock *sk,
489 struct sock *addr_sk)
490{
Eric Dumazetefe42082013-10-03 15:42:29 -0700491 return tcp_v6_md5_do_lookup(sk, &addr_sk->sk_v6_daddr);
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800492}
493
494static struct tcp_md5sig_key *tcp_v6_reqsk_md5_lookup(struct sock *sk,
495 struct request_sock *req)
496{
Eric Dumazet634fb9792013-10-09 15:21:29 -0700497 return tcp_v6_md5_do_lookup(sk, &inet_rsk(req)->ir_v6_rmt_addr);
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800498}
499
Wang Yufen4aa956d2014-03-29 09:27:29 +0800500static int tcp_v6_parse_md5_keys(struct sock *sk, char __user *optval,
501 int optlen)
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800502{
503 struct tcp_md5sig cmd;
504 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&cmd.tcpm_addr;
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800505
506 if (optlen < sizeof(cmd))
507 return -EINVAL;
508
509 if (copy_from_user(&cmd, optval, sizeof(cmd)))
510 return -EFAULT;
511
512 if (sin6->sin6_family != AF_INET6)
513 return -EINVAL;
514
515 if (!cmd.tcpm_keylen) {
Brian Haleye773e4f2007-08-24 23:16:08 -0700516 if (ipv6_addr_v4mapped(&sin6->sin6_addr))
Eric Dumazeta915da9b2012-01-31 05:18:33 +0000517 return tcp_md5_do_del(sk, (union tcp_md5_addr *)&sin6->sin6_addr.s6_addr32[3],
518 AF_INET);
519 return tcp_md5_do_del(sk, (union tcp_md5_addr *)&sin6->sin6_addr,
520 AF_INET6);
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800521 }
522
523 if (cmd.tcpm_keylen > TCP_MD5SIG_MAXKEYLEN)
524 return -EINVAL;
525
Eric Dumazeta915da9b2012-01-31 05:18:33 +0000526 if (ipv6_addr_v4mapped(&sin6->sin6_addr))
527 return tcp_md5_do_add(sk, (union tcp_md5_addr *)&sin6->sin6_addr.s6_addr32[3],
528 AF_INET, cmd.tcpm_key, cmd.tcpm_keylen, GFP_KERNEL);
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800529
Eric Dumazeta915da9b2012-01-31 05:18:33 +0000530 return tcp_md5_do_add(sk, (union tcp_md5_addr *)&sin6->sin6_addr,
531 AF_INET6, cmd.tcpm_key, cmd.tcpm_keylen, GFP_KERNEL);
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800532}
533
Adam Langley49a72df2008-07-19 00:01:42 -0700534static int tcp_v6_md5_hash_pseudoheader(struct tcp_md5sig_pool *hp,
Eric Dumazetb71d1d42011-04-22 04:53:02 +0000535 const struct in6_addr *daddr,
536 const struct in6_addr *saddr, int nbytes)
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800537{
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800538 struct tcp6_pseudohdr *bp;
Adam Langley49a72df2008-07-19 00:01:42 -0700539 struct scatterlist sg;
YOSHIFUJI Hideaki8d26d762008-04-17 13:19:16 +0900540
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800541 bp = &hp->md5_blk.ip6;
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800542 /* 1. TCP pseudo-header (RFC2460) */
Alexey Dobriyan4e3fd7a2011-11-21 03:39:03 +0000543 bp->saddr = *saddr;
544 bp->daddr = *daddr;
Adam Langley49a72df2008-07-19 00:01:42 -0700545 bp->protocol = cpu_to_be32(IPPROTO_TCP);
Adam Langley00b13042008-07-31 21:36:07 -0700546 bp->len = cpu_to_be32(nbytes);
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800547
Adam Langley49a72df2008-07-19 00:01:42 -0700548 sg_init_one(&sg, bp, sizeof(*bp));
549 return crypto_hash_update(&hp->md5_desc, &sg, sizeof(*bp));
550}
David S. Millerc7da57a2007-10-26 00:41:21 -0700551
Adam Langley49a72df2008-07-19 00:01:42 -0700552static int tcp_v6_md5_hash_hdr(char *md5_hash, struct tcp_md5sig_key *key,
Eric Dumazetb71d1d42011-04-22 04:53:02 +0000553 const struct in6_addr *daddr, struct in6_addr *saddr,
Eric Dumazet318cf7a2011-10-24 02:46:04 -0400554 const struct tcphdr *th)
Adam Langley49a72df2008-07-19 00:01:42 -0700555{
556 struct tcp_md5sig_pool *hp;
557 struct hash_desc *desc;
558
559 hp = tcp_get_md5sig_pool();
560 if (!hp)
561 goto clear_hash_noput;
562 desc = &hp->md5_desc;
563
564 if (crypto_hash_init(desc))
565 goto clear_hash;
566 if (tcp_v6_md5_hash_pseudoheader(hp, daddr, saddr, th->doff << 2))
567 goto clear_hash;
568 if (tcp_md5_hash_header(hp, th))
569 goto clear_hash;
570 if (tcp_md5_hash_key(hp, key))
571 goto clear_hash;
572 if (crypto_hash_final(desc, md5_hash))
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800573 goto clear_hash;
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800574
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800575 tcp_put_md5sig_pool();
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800576 return 0;
Adam Langley49a72df2008-07-19 00:01:42 -0700577
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800578clear_hash:
579 tcp_put_md5sig_pool();
580clear_hash_noput:
581 memset(md5_hash, 0, 16);
Adam Langley49a72df2008-07-19 00:01:42 -0700582 return 1;
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800583}
584
Adam Langley49a72df2008-07-19 00:01:42 -0700585static int tcp_v6_md5_hash_skb(char *md5_hash, struct tcp_md5sig_key *key,
Eric Dumazet318cf7a2011-10-24 02:46:04 -0400586 const struct sock *sk,
587 const struct request_sock *req,
588 const struct sk_buff *skb)
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800589{
Eric Dumazetb71d1d42011-04-22 04:53:02 +0000590 const struct in6_addr *saddr, *daddr;
Adam Langley49a72df2008-07-19 00:01:42 -0700591 struct tcp_md5sig_pool *hp;
592 struct hash_desc *desc;
Eric Dumazet318cf7a2011-10-24 02:46:04 -0400593 const struct tcphdr *th = tcp_hdr(skb);
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800594
595 if (sk) {
596 saddr = &inet6_sk(sk)->saddr;
Eric Dumazetefe42082013-10-03 15:42:29 -0700597 daddr = &sk->sk_v6_daddr;
Adam Langley49a72df2008-07-19 00:01:42 -0700598 } else if (req) {
Eric Dumazet634fb9792013-10-09 15:21:29 -0700599 saddr = &inet_rsk(req)->ir_v6_loc_addr;
600 daddr = &inet_rsk(req)->ir_v6_rmt_addr;
Adam Langley49a72df2008-07-19 00:01:42 -0700601 } else {
Eric Dumazetb71d1d42011-04-22 04:53:02 +0000602 const struct ipv6hdr *ip6h = ipv6_hdr(skb);
Adam Langley49a72df2008-07-19 00:01:42 -0700603 saddr = &ip6h->saddr;
604 daddr = &ip6h->daddr;
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800605 }
Adam Langley49a72df2008-07-19 00:01:42 -0700606
607 hp = tcp_get_md5sig_pool();
608 if (!hp)
609 goto clear_hash_noput;
610 desc = &hp->md5_desc;
611
612 if (crypto_hash_init(desc))
613 goto clear_hash;
614
615 if (tcp_v6_md5_hash_pseudoheader(hp, daddr, saddr, skb->len))
616 goto clear_hash;
617 if (tcp_md5_hash_header(hp, th))
618 goto clear_hash;
619 if (tcp_md5_hash_skb_data(hp, skb, th->doff << 2))
620 goto clear_hash;
621 if (tcp_md5_hash_key(hp, key))
622 goto clear_hash;
623 if (crypto_hash_final(desc, md5_hash))
624 goto clear_hash;
625
626 tcp_put_md5sig_pool();
627 return 0;
628
629clear_hash:
630 tcp_put_md5sig_pool();
631clear_hash_noput:
632 memset(md5_hash, 0, 16);
633 return 1;
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800634}
635
Dmitry Popov9ea88a12014-08-07 02:38:22 +0400636static int __tcp_v6_inbound_md5_hash(struct sock *sk,
637 const struct sk_buff *skb)
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800638{
Eric Dumazetcf533ea2011-10-21 05:22:42 -0400639 const __u8 *hash_location = NULL;
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800640 struct tcp_md5sig_key *hash_expected;
Eric Dumazetb71d1d42011-04-22 04:53:02 +0000641 const struct ipv6hdr *ip6h = ipv6_hdr(skb);
Eric Dumazet318cf7a2011-10-24 02:46:04 -0400642 const struct tcphdr *th = tcp_hdr(skb);
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800643 int genhash;
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800644 u8 newhash[16];
645
646 hash_expected = tcp_v6_md5_do_lookup(sk, &ip6h->saddr);
YOSHIFUJI Hideaki7d5d5522008-04-17 12:29:53 +0900647 hash_location = tcp_parse_md5sig_option(th);
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800648
David S. Miller785957d2008-07-30 03:03:15 -0700649 /* We've parsed the options - do we have a hash? */
650 if (!hash_expected && !hash_location)
651 return 0;
652
653 if (hash_expected && !hash_location) {
654 NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPMD5NOTFOUND);
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800655 return 1;
656 }
657
David S. Miller785957d2008-07-30 03:03:15 -0700658 if (!hash_expected && hash_location) {
659 NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPMD5UNEXPECTED);
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800660 return 1;
661 }
662
663 /* check the signature */
Adam Langley49a72df2008-07-19 00:01:42 -0700664 genhash = tcp_v6_md5_hash_skb(newhash,
665 hash_expected,
666 NULL, NULL, skb);
667
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800668 if (genhash || memcmp(hash_location, newhash, 16) != 0) {
Joe Perchese87cc472012-05-13 21:56:26 +0000669 net_info_ratelimited("MD5 Hash %s for [%pI6c]:%u->[%pI6c]:%u\n",
670 genhash ? "failed" : "mismatch",
671 &ip6h->saddr, ntohs(th->source),
672 &ip6h->daddr, ntohs(th->dest));
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800673 return 1;
674 }
675 return 0;
676}
Dmitry Popov9ea88a12014-08-07 02:38:22 +0400677
678static int tcp_v6_inbound_md5_hash(struct sock *sk, const struct sk_buff *skb)
679{
680 int ret;
681
682 rcu_read_lock();
683 ret = __tcp_v6_inbound_md5_hash(sk, skb);
684 rcu_read_unlock();
685
686 return ret;
687}
688
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800689#endif
690
Octavian Purdila16bea702014-06-25 17:09:53 +0300691static void tcp_v6_init_req(struct request_sock *req, struct sock *sk,
692 struct sk_buff *skb)
693{
694 struct inet_request_sock *ireq = inet_rsk(req);
695 struct ipv6_pinfo *np = inet6_sk(sk);
696
697 ireq->ir_v6_rmt_addr = ipv6_hdr(skb)->saddr;
698 ireq->ir_v6_loc_addr = ipv6_hdr(skb)->daddr;
699
Octavian Purdila16bea702014-06-25 17:09:53 +0300700 /* So that link locals have meaning */
701 if (!sk->sk_bound_dev_if &&
702 ipv6_addr_type(&ireq->ir_v6_rmt_addr) & IPV6_ADDR_LINKLOCAL)
Eric Dumazet870c3152014-10-17 09:17:20 -0700703 ireq->ir_iif = tcp_v6_iif(skb);
Octavian Purdila16bea702014-06-25 17:09:53 +0300704
Eric Dumazet04317da2014-09-05 15:33:32 -0700705 if (!TCP_SKB_CB(skb)->tcp_tw_isn &&
Eric Dumazeta2247722014-09-27 09:50:56 -0700706 (ipv6_opt_accepted(sk, skb, &TCP_SKB_CB(skb)->header.h6) ||
707 np->rxopt.bits.rxinfo ||
Octavian Purdila16bea702014-06-25 17:09:53 +0300708 np->rxopt.bits.rxoinfo || np->rxopt.bits.rxhlim ||
709 np->rxopt.bits.rxohlim || np->repflow)) {
710 atomic_inc(&skb->users);
711 ireq->pktopts = skb;
712 }
Eric Dumazet3f66b082015-03-12 16:44:10 -0700713 ireq->ireq_family = AF_INET6;
Octavian Purdila16bea702014-06-25 17:09:53 +0300714}
715
Octavian Purdilad94e0412014-06-25 17:09:55 +0300716static struct dst_entry *tcp_v6_route_req(struct sock *sk, struct flowi *fl,
717 const struct request_sock *req,
718 bool *strict)
719{
720 if (strict)
721 *strict = true;
722 return inet6_csk_route_req(sk, &fl->u.ip6, req);
723}
724
Glenn Griffinc6aefaf2008-02-07 21:49:26 -0800725struct request_sock_ops tcp6_request_sock_ops __read_mostly = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700726 .family = AF_INET6,
Arnaldo Carvalho de Melo2e6599c2005-06-18 22:46:52 -0700727 .obj_size = sizeof(struct tcp6_request_sock),
Octavian Purdila5db92c92014-06-25 17:09:59 +0300728 .rtx_syn_ack = tcp_rtx_synack,
Arnaldo Carvalho de Melo60236fd2005-06-18 22:47:21 -0700729 .send_ack = tcp_v6_reqsk_send_ack,
730 .destructor = tcp_v6_reqsk_destructor,
Octavian Purdila72659ec2010-01-17 19:09:39 -0800731 .send_reset = tcp_v6_send_reset,
Wang Yufen4aa956d2014-03-29 09:27:29 +0800732 .syn_ack_timeout = tcp_syn_ack_timeout,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700733};
734
Stephen Hemmingerb2e4b3d2009-09-01 19:25:03 +0000735static const struct tcp_request_sock_ops tcp_request_sock_ipv6_ops = {
Octavian Purdila2aec4a22014-06-25 17:10:00 +0300736 .mss_clamp = IPV6_MIN_MTU - sizeof(struct tcphdr) -
737 sizeof(struct ipv6hdr),
Octavian Purdila16bea702014-06-25 17:09:53 +0300738#ifdef CONFIG_TCP_MD5SIG
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800739 .md5_lookup = tcp_v6_reqsk_md5_lookup,
John Dykstrae3afe7b2009-07-16 05:04:51 +0000740 .calc_md5_hash = tcp_v6_md5_hash_skb,
Andrew Mortonb6332e62006-11-30 19:16:28 -0800741#endif
Octavian Purdila16bea702014-06-25 17:09:53 +0300742 .init_req = tcp_v6_init_req,
Octavian Purdilafb7b37a2014-06-25 17:09:54 +0300743#ifdef CONFIG_SYN_COOKIES
744 .cookie_init_seq = cookie_v6_init_sequence,
745#endif
Octavian Purdilad94e0412014-06-25 17:09:55 +0300746 .route_req = tcp_v6_route_req,
Octavian Purdila936b8bd2014-06-25 17:09:57 +0300747 .init_seq = tcp_v6_init_sequence,
Octavian Purdilad6274bd2014-06-25 17:09:58 +0300748 .send_synack = tcp_v6_send_synack,
Octavian Purdila695da142014-06-25 17:10:01 +0300749 .queue_hash_add = inet6_csk_reqsk_queue_hash_add,
Octavian Purdila16bea702014-06-25 17:09:53 +0300750};
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800751
Eric Dumazet0f85fea2014-12-09 09:56:08 -0800752static void tcp_v6_send_response(struct sock *sk, struct sk_buff *skb, u32 seq,
753 u32 ack, u32 win, u32 tsval, u32 tsecr,
754 int oif, struct tcp_md5sig_key *key, int rst,
755 u8 tclass, u32 label)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700756{
Eric Dumazetcf533ea2011-10-21 05:22:42 -0400757 const struct tcphdr *th = tcp_hdr(skb);
758 struct tcphdr *t1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700759 struct sk_buff *buff;
David S. Miller4c9483b2011-03-12 16:22:43 -0500760 struct flowi6 fl6;
Eric Dumazet0f85fea2014-12-09 09:56:08 -0800761 struct net *net = sk ? sock_net(sk) : dev_net(skb_dst(skb)->dev);
Daniel Lezcanoe5047992008-03-07 11:16:26 -0800762 struct sock *ctl_sk = net->ipv6.tcp_sk;
YOSHIFUJI Hideaki9cb57342008-01-12 02:16:03 -0800763 unsigned int tot_len = sizeof(struct tcphdr);
Eric Dumazetadf30902009-06-02 05:19:30 +0000764 struct dst_entry *dst;
Al Viroe69a4ad2006-11-14 20:56:00 -0800765 __be32 *topt;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700766
Andrey Vaginee684b62013-02-11 05:50:19 +0000767 if (tsecr)
YOSHIFUJI Hideaki4244f8a2006-10-10 19:40:50 -0700768 tot_len += TCPOLEN_TSTAMP_ALIGNED;
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800769#ifdef CONFIG_TCP_MD5SIG
770 if (key)
771 tot_len += TCPOLEN_MD5SIG_ALIGNED;
772#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700773
774 buff = alloc_skb(MAX_HEADER + sizeof(struct ipv6hdr) + tot_len,
775 GFP_ATOMIC);
776 if (buff == NULL)
777 return;
778
779 skb_reserve(buff, MAX_HEADER + sizeof(struct ipv6hdr) + tot_len);
780
Ilpo Järvinen77c676d2008-10-09 14:41:38 -0700781 t1 = (struct tcphdr *) skb_push(buff, tot_len);
Herbert Xu6651ffc2010-04-21 00:47:15 -0700782 skb_reset_transport_header(buff);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700783
784 /* Swap the send and the receive. */
785 memset(t1, 0, sizeof(*t1));
786 t1->dest = th->source;
787 t1->source = th->dest;
Ilpo Järvinen77c676d2008-10-09 14:41:38 -0700788 t1->doff = tot_len / 4;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700789 t1->seq = htonl(seq);
790 t1->ack_seq = htonl(ack);
Ilpo Järvinen626e2642008-10-09 14:42:40 -0700791 t1->ack = !rst || !th->ack;
792 t1->rst = rst;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700793 t1->window = htons(win);
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800794
Al Viroe69a4ad2006-11-14 20:56:00 -0800795 topt = (__be32 *)(t1 + 1);
YOSHIFUJI Hideaki1ab14572007-02-09 23:24:49 +0900796
Andrey Vaginee684b62013-02-11 05:50:19 +0000797 if (tsecr) {
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800798 *topt++ = htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) |
799 (TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP);
Andrey Vaginee684b62013-02-11 05:50:19 +0000800 *topt++ = htonl(tsval);
801 *topt++ = htonl(tsecr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700802 }
803
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800804#ifdef CONFIG_TCP_MD5SIG
805 if (key) {
806 *topt++ = htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) |
807 (TCPOPT_MD5SIG << 8) | TCPOLEN_MD5SIG);
Adam Langley49a72df2008-07-19 00:01:42 -0700808 tcp_v6_md5_hash_hdr((__u8 *)topt, key,
Adam Langley90b7e112008-07-31 20:49:48 -0700809 &ipv6_hdr(skb)->saddr,
810 &ipv6_hdr(skb)->daddr, t1);
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800811 }
812#endif
813
David S. Miller4c9483b2011-03-12 16:22:43 -0500814 memset(&fl6, 0, sizeof(fl6));
Alexey Dobriyan4e3fd7a2011-11-21 03:39:03 +0000815 fl6.daddr = ipv6_hdr(skb)->saddr;
816 fl6.saddr = ipv6_hdr(skb)->daddr;
Florent Fourcot1d13a962014-01-16 17:21:22 +0100817 fl6.flowlabel = label;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700818
David S. Millere5700af2010-04-21 14:59:20 -0700819 buff->ip_summed = CHECKSUM_PARTIAL;
820 buff->csum = 0;
821
David S. Miller4c9483b2011-03-12 16:22:43 -0500822 __tcp_v6_send_check(buff, &fl6.saddr, &fl6.daddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700823
David S. Miller4c9483b2011-03-12 16:22:43 -0500824 fl6.flowi6_proto = IPPROTO_TCP;
Lorenzo Colittia36dbdb2014-04-11 13:19:12 +0900825 if (rt6_need_strict(&fl6.daddr) && !oif)
Eric Dumazet870c3152014-10-17 09:17:20 -0700826 fl6.flowi6_oif = tcp_v6_iif(skb);
Wang Yufen9c76a112014-03-29 09:27:31 +0800827 else
828 fl6.flowi6_oif = oif;
Lorenzo Colittie1108612014-05-13 10:17:33 -0700829 fl6.flowi6_mark = IP6_REPLY_MARK(net, skb->mark);
David S. Miller1958b852011-03-12 16:36:19 -0500830 fl6.fl6_dport = t1->dest;
831 fl6.fl6_sport = t1->source;
David S. Miller4c9483b2011-03-12 16:22:43 -0500832 security_skb_classify_flow(skb, flowi6_to_flowi(&fl6));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700833
Ilpo Järvinen626e2642008-10-09 14:42:40 -0700834 /* Pass a socket to ip6_dst_lookup either it is for RST
835 * Underlying function will use this to retrieve the network
836 * namespace
837 */
Steffen Klassert0e0d44a2013-08-28 08:04:14 +0200838 dst = ip6_dst_lookup_flow(ctl_sk, &fl6, NULL);
David S. Miller68d0c6d2011-03-01 13:19:07 -0800839 if (!IS_ERR(dst)) {
840 skb_dst_set(buff, dst);
Eric Dumazetb903d322011-10-27 00:44:35 -0400841 ip6_xmit(ctl_sk, buff, &fl6, NULL, tclass);
David S. Miller68d0c6d2011-03-01 13:19:07 -0800842 TCP_INC_STATS_BH(net, TCP_MIB_OUTSEGS);
843 if (rst)
844 TCP_INC_STATS_BH(net, TCP_MIB_OUTRSTS);
845 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700846 }
847
848 kfree_skb(buff);
849}
850
Ilpo Järvinen626e2642008-10-09 14:42:40 -0700851static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb)
852{
Eric Dumazetcf533ea2011-10-21 05:22:42 -0400853 const struct tcphdr *th = tcp_hdr(skb);
Ilpo Järvinen626e2642008-10-09 14:42:40 -0700854 u32 seq = 0, ack_seq = 0;
Guo-Fu Tsengfa3e5b42008-10-09 21:11:56 -0700855 struct tcp_md5sig_key *key = NULL;
Shawn Lu658ddaa2012-01-31 22:35:48 +0000856#ifdef CONFIG_TCP_MD5SIG
857 const __u8 *hash_location = NULL;
858 struct ipv6hdr *ipv6h = ipv6_hdr(skb);
859 unsigned char newhash[16];
860 int genhash;
861 struct sock *sk1 = NULL;
862#endif
Wang Yufen9c76a112014-03-29 09:27:31 +0800863 int oif;
Ilpo Järvinen626e2642008-10-09 14:42:40 -0700864
865 if (th->rst)
866 return;
867
Eric Dumazetc3658e82014-11-25 07:40:04 -0800868 /* If sk not NULL, it means we did a successful lookup and incoming
869 * route had to be correct. prequeue might have dropped our dst.
870 */
871 if (!sk && !ipv6_unicast_destination(skb))
Ilpo Järvinen626e2642008-10-09 14:42:40 -0700872 return;
873
874#ifdef CONFIG_TCP_MD5SIG
Shawn Lu658ddaa2012-01-31 22:35:48 +0000875 hash_location = tcp_parse_md5sig_option(th);
876 if (!sk && hash_location) {
877 /*
878 * active side is lost. Try to find listening socket through
879 * source port, and then find md5 key through listening socket.
880 * we are not loose security here:
881 * Incoming packet is checked with md5 hash with finding key,
882 * no RST generated if md5 hash doesn't match.
883 */
884 sk1 = inet6_lookup_listener(dev_net(skb_dst(skb)->dev),
Tom Herbert5ba24952013-01-22 09:50:39 +0000885 &tcp_hashinfo, &ipv6h->saddr,
886 th->source, &ipv6h->daddr,
Eric Dumazet870c3152014-10-17 09:17:20 -0700887 ntohs(th->source), tcp_v6_iif(skb));
Shawn Lu658ddaa2012-01-31 22:35:48 +0000888 if (!sk1)
889 return;
890
891 rcu_read_lock();
892 key = tcp_v6_md5_do_lookup(sk1, &ipv6h->saddr);
893 if (!key)
894 goto release_sk1;
895
896 genhash = tcp_v6_md5_hash_skb(newhash, key, NULL, NULL, skb);
897 if (genhash || memcmp(hash_location, newhash, 16) != 0)
898 goto release_sk1;
899 } else {
900 key = sk ? tcp_v6_md5_do_lookup(sk, &ipv6h->saddr) : NULL;
901 }
Ilpo Järvinen626e2642008-10-09 14:42:40 -0700902#endif
903
904 if (th->ack)
905 seq = ntohl(th->ack_seq);
906 else
907 ack_seq = ntohl(th->seq) + th->syn + th->fin + skb->len -
908 (th->doff << 2);
909
Wang Yufen9c76a112014-03-29 09:27:31 +0800910 oif = sk ? sk->sk_bound_dev_if : 0;
Eric Dumazet0f85fea2014-12-09 09:56:08 -0800911 tcp_v6_send_response(sk, skb, seq, ack_seq, 0, 0, 0, oif, key, 1, 0, 0);
Shawn Lu658ddaa2012-01-31 22:35:48 +0000912
913#ifdef CONFIG_TCP_MD5SIG
914release_sk1:
915 if (sk1) {
916 rcu_read_unlock();
917 sock_put(sk1);
918 }
919#endif
Ilpo Järvinen626e2642008-10-09 14:42:40 -0700920}
921
Eric Dumazet0f85fea2014-12-09 09:56:08 -0800922static void tcp_v6_send_ack(struct sock *sk, struct sk_buff *skb, u32 seq,
923 u32 ack, u32 win, u32 tsval, u32 tsecr, int oif,
Florent Fourcot1d13a962014-01-16 17:21:22 +0100924 struct tcp_md5sig_key *key, u8 tclass,
925 u32 label)
Ilpo Järvinen626e2642008-10-09 14:42:40 -0700926{
Eric Dumazet0f85fea2014-12-09 09:56:08 -0800927 tcp_v6_send_response(sk, skb, seq, ack, win, tsval, tsecr, oif, key, 0,
928 tclass, label);
Ilpo Järvinen626e2642008-10-09 14:42:40 -0700929}
930
Linus Torvalds1da177e2005-04-16 15:20:36 -0700931static void tcp_v6_timewait_ack(struct sock *sk, struct sk_buff *skb)
932{
Arnaldo Carvalho de Melo8feaf0c02005-08-09 20:09:30 -0700933 struct inet_timewait_sock *tw = inet_twsk(sk);
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -0800934 struct tcp_timewait_sock *tcptw = tcp_twsk(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700935
Eric Dumazet0f85fea2014-12-09 09:56:08 -0800936 tcp_v6_send_ack(sk, skb, tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt,
Arnaldo Carvalho de Melo8feaf0c02005-08-09 20:09:30 -0700937 tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale,
Andrey Vaginee684b62013-02-11 05:50:19 +0000938 tcp_time_stamp + tcptw->tw_ts_offset,
Wang Yufen9c76a112014-03-29 09:27:31 +0800939 tcptw->tw_ts_recent, tw->tw_bound_dev_if, tcp_twsk_md5_key(tcptw),
Florent Fourcot1d13a962014-01-16 17:21:22 +0100940 tw->tw_tclass, (tw->tw_flowlabel << 12));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700941
Arnaldo Carvalho de Melo8feaf0c02005-08-09 20:09:30 -0700942 inet_twsk_put(tw);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700943}
944
Gui Jianfeng6edafaa2008-08-06 23:50:04 -0700945static void tcp_v6_reqsk_send_ack(struct sock *sk, struct sk_buff *skb,
946 struct request_sock *req)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700947{
Daniel Lee3a19ce02014-05-11 20:22:13 -0700948 /* sk->sk_state == TCP_LISTEN -> for regular TCP_SYN_RECV
949 * sk->sk_state == TCP_SYN_RECV -> for Fast Open.
950 */
Eric Dumazet0f85fea2014-12-09 09:56:08 -0800951 tcp_v6_send_ack(sk, skb, (sk->sk_state == TCP_LISTEN) ?
Daniel Lee3a19ce02014-05-11 20:22:13 -0700952 tcp_rsk(req)->snt_isn + 1 : tcp_sk(sk)->snd_nxt,
Eric Dumazet0f85fea2014-12-09 09:56:08 -0800953 tcp_rsk(req)->rcv_nxt, req->rcv_wnd,
954 tcp_time_stamp, req->ts_recent, sk->sk_bound_dev_if,
Florent Fourcot1d13a962014-01-16 17:21:22 +0100955 tcp_v6_md5_do_lookup(sk, &ipv6_hdr(skb)->daddr),
956 0, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700957}
958
959
Weilong Chen4c99aa42013-12-19 18:44:34 +0800960static struct sock *tcp_v6_hnd_req(struct sock *sk, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700961{
Arnaldo Carvalho de Meloaa8223c2007-04-10 21:04:22 -0700962 const struct tcphdr *th = tcp_hdr(skb);
Eric Dumazet52452c52015-03-19 19:04:19 -0700963 struct request_sock *req;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700964 struct sock *nsk;
965
966 /* Find possible connection requests. */
Eric Dumazet52452c52015-03-19 19:04:19 -0700967 req = inet6_csk_search_req(sk, th->source,
Arnaldo Carvalho de Melo0660e032007-04-25 17:54:47 -0700968 &ipv6_hdr(skb)->saddr,
Eric Dumazet870c3152014-10-17 09:17:20 -0700969 &ipv6_hdr(skb)->daddr, tcp_v6_iif(skb));
Eric Dumazetfa76ce732015-03-19 19:04:20 -0700970 if (req) {
971 nsk = tcp_check_req(sk, skb, req, false);
972 reqsk_put(req);
973 return nsk;
974 }
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +0900975 nsk = __inet6_lookup_established(sock_net(sk), &tcp_hashinfo,
Eric Dumazet870c3152014-10-17 09:17:20 -0700976 &ipv6_hdr(skb)->saddr, th->source,
977 &ipv6_hdr(skb)->daddr, ntohs(th->dest),
978 tcp_v6_iif(skb));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700979
980 if (nsk) {
981 if (nsk->sk_state != TCP_TIME_WAIT) {
982 bh_lock_sock(nsk);
983 return nsk;
984 }
YOSHIFUJI Hideaki9469c7b2006-10-10 19:41:46 -0700985 inet_twsk_put(inet_twsk(nsk));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700986 return NULL;
987 }
988
Glenn Griffinc6aefaf2008-02-07 21:49:26 -0800989#ifdef CONFIG_SYN_COOKIES
Florian Westphalaf9b4732010-06-03 00:43:44 +0000990 if (!th->syn)
Glenn Griffinc6aefaf2008-02-07 21:49:26 -0800991 sk = cookie_v6_check(sk, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700992#endif
993 return sk;
994}
995
Linus Torvalds1da177e2005-04-16 15:20:36 -0700996static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
997{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700998 if (skb->protocol == htons(ETH_P_IP))
999 return tcp_v4_conn_request(sk, skb);
1000
1001 if (!ipv6_unicast_destination(skb))
YOSHIFUJI Hideaki1ab14572007-02-09 23:24:49 +09001002 goto drop;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001003
Octavian Purdila1fb6f152014-06-25 17:10:02 +03001004 return tcp_conn_request(&tcp6_request_sock_ops,
1005 &tcp_request_sock_ipv6_ops, sk, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001006
Linus Torvalds1da177e2005-04-16 15:20:36 -07001007drop:
Vijay Subramanian5f1e9422013-01-31 08:24:19 +00001008 NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001009 return 0; /* don't send reset */
1010}
1011
Weilong Chen4c99aa42013-12-19 18:44:34 +08001012static struct sock *tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
1013 struct request_sock *req,
1014 struct dst_entry *dst)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001015{
Eric Dumazet634fb9792013-10-09 15:21:29 -07001016 struct inet_request_sock *ireq;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001017 struct ipv6_pinfo *newnp, *np = inet6_sk(sk);
1018 struct tcp6_sock *newtcp6sk;
1019 struct inet_sock *newinet;
1020 struct tcp_sock *newtp;
1021 struct sock *newsk;
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -08001022#ifdef CONFIG_TCP_MD5SIG
1023 struct tcp_md5sig_key *key;
1024#endif
Neal Cardwell3840a062012-06-28 12:34:19 +00001025 struct flowi6 fl6;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001026
1027 if (skb->protocol == htons(ETH_P_IP)) {
1028 /*
1029 * v6 mapped
1030 */
1031
1032 newsk = tcp_v4_syn_recv_sock(sk, skb, req, dst);
1033
YOSHIFUJI Hideaki1ab14572007-02-09 23:24:49 +09001034 if (newsk == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001035 return NULL;
1036
1037 newtcp6sk = (struct tcp6_sock *)newsk;
1038 inet_sk(newsk)->pinet6 = &newtcp6sk->inet6;
1039
1040 newinet = inet_sk(newsk);
1041 newnp = inet6_sk(newsk);
1042 newtp = tcp_sk(newsk);
1043
1044 memcpy(newnp, np, sizeof(struct ipv6_pinfo));
1045
Eric Dumazetd1e559d2015-03-18 14:05:35 -07001046 newnp->saddr = newsk->sk_v6_rcv_saddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001047
Arnaldo Carvalho de Melo8292a172005-12-13 23:15:52 -08001048 inet_csk(newsk)->icsk_af_ops = &ipv6_mapped;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001049 newsk->sk_backlog_rcv = tcp_v4_do_rcv;
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -08001050#ifdef CONFIG_TCP_MD5SIG
1051 newtp->af_specific = &tcp_sock_ipv6_mapped_specific;
1052#endif
1053
Yan, Zheng676a1182011-09-25 02:21:30 +00001054 newnp->ipv6_ac_list = NULL;
1055 newnp->ipv6_fl_list = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001056 newnp->pktoptions = NULL;
1057 newnp->opt = NULL;
Eric Dumazet870c3152014-10-17 09:17:20 -07001058 newnp->mcast_oif = tcp_v6_iif(skb);
Arnaldo Carvalho de Melo0660e032007-04-25 17:54:47 -07001059 newnp->mcast_hops = ipv6_hdr(skb)->hop_limit;
Florent Fourcot1397ed32013-12-08 15:46:57 +01001060 newnp->rcv_flowinfo = ip6_flowinfo(ipv6_hdr(skb));
Florent Fourcotdf3687f2014-01-17 17:15:03 +01001061 if (np->repflow)
1062 newnp->flow_label = ip6_flowlabel(ipv6_hdr(skb));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001063
Arnaldo Carvalho de Meloe6848972005-08-09 19:45:38 -07001064 /*
1065 * No need to charge this sock to the relevant IPv6 refcnt debug socks count
1066 * here, tcp_create_openreq_child now does this for us, see the comment in
1067 * that function for the gory details. -acme
Linus Torvalds1da177e2005-04-16 15:20:36 -07001068 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001069
1070 /* It is tricky place. Until this moment IPv4 tcp
Arnaldo Carvalho de Melo8292a172005-12-13 23:15:52 -08001071 worked with IPv6 icsk.icsk_af_ops.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001072 Sync it now.
1073 */
Arnaldo Carvalho de Melod83d8462005-12-13 23:26:10 -08001074 tcp_sync_mss(newsk, inet_csk(newsk)->icsk_pmtu_cookie);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001075
1076 return newsk;
1077 }
1078
Eric Dumazet634fb9792013-10-09 15:21:29 -07001079 ireq = inet_rsk(req);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001080
1081 if (sk_acceptq_is_full(sk))
1082 goto out_overflow;
1083
David S. Miller493f3772010-12-02 12:14:29 -08001084 if (!dst) {
Neal Cardwell3840a062012-06-28 12:34:19 +00001085 dst = inet6_csk_route_req(sk, &fl6, req);
David S. Miller493f3772010-12-02 12:14:29 -08001086 if (!dst)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001087 goto out;
YOSHIFUJI Hideaki1ab14572007-02-09 23:24:49 +09001088 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001089
1090 newsk = tcp_create_openreq_child(sk, req, skb);
1091 if (newsk == NULL)
Balazs Scheidler093d2822010-10-21 13:06:43 +02001092 goto out_nonewsk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001093
Arnaldo Carvalho de Meloe6848972005-08-09 19:45:38 -07001094 /*
1095 * No need to charge this sock to the relevant IPv6 refcnt debug socks
1096 * count here, tcp_create_openreq_child now does this for us, see the
1097 * comment in that function for the gory details. -acme
1098 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001099
Stephen Hemminger59eed272006-08-25 15:55:43 -07001100 newsk->sk_gso_type = SKB_GSO_TCPV6;
YOSHIFUJI Hideaki8e1ef0a2006-08-29 17:15:09 -07001101 __ip6_dst_store(newsk, dst, NULL, NULL);
Neal Cardwellfae6ef82012-08-19 03:30:38 +00001102 inet6_sk_rx_dst_set(newsk, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001103
1104 newtcp6sk = (struct tcp6_sock *)newsk;
1105 inet_sk(newsk)->pinet6 = &newtcp6sk->inet6;
1106
1107 newtp = tcp_sk(newsk);
1108 newinet = inet_sk(newsk);
1109 newnp = inet6_sk(newsk);
1110
1111 memcpy(newnp, np, sizeof(struct ipv6_pinfo));
1112
Eric Dumazet634fb9792013-10-09 15:21:29 -07001113 newsk->sk_v6_daddr = ireq->ir_v6_rmt_addr;
1114 newnp->saddr = ireq->ir_v6_loc_addr;
1115 newsk->sk_v6_rcv_saddr = ireq->ir_v6_loc_addr;
1116 newsk->sk_bound_dev_if = ireq->ir_iif;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001117
Tom Herbertb73c3d02014-07-01 21:32:17 -07001118 ip6_set_txhash(newsk);
1119
YOSHIFUJI Hideaki1ab14572007-02-09 23:24:49 +09001120 /* Now IPv6 options...
Linus Torvalds1da177e2005-04-16 15:20:36 -07001121
1122 First: no IPv4 options.
1123 */
Eric Dumazetf6d8bd02011-04-21 09:45:37 +00001124 newinet->inet_opt = NULL;
Yan, Zheng676a1182011-09-25 02:21:30 +00001125 newnp->ipv6_ac_list = NULL;
Masayuki Nakagawad35690b2007-03-16 16:14:03 -07001126 newnp->ipv6_fl_list = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001127
1128 /* Clone RX bits */
1129 newnp->rxopt.all = np->rxopt.all;
1130
1131 /* Clone pktoptions received with SYN */
1132 newnp->pktoptions = NULL;
Eric Dumazet634fb9792013-10-09 15:21:29 -07001133 if (ireq->pktopts != NULL) {
1134 newnp->pktoptions = skb_clone(ireq->pktopts,
Mel Gorman99a1dec2012-07-31 16:44:14 -07001135 sk_gfp_atomic(sk, GFP_ATOMIC));
Eric Dumazet634fb9792013-10-09 15:21:29 -07001136 consume_skb(ireq->pktopts);
1137 ireq->pktopts = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001138 if (newnp->pktoptions)
1139 skb_set_owner_r(newnp->pktoptions, newsk);
1140 }
1141 newnp->opt = NULL;
Eric Dumazet870c3152014-10-17 09:17:20 -07001142 newnp->mcast_oif = tcp_v6_iif(skb);
Arnaldo Carvalho de Melo0660e032007-04-25 17:54:47 -07001143 newnp->mcast_hops = ipv6_hdr(skb)->hop_limit;
Florent Fourcot1397ed32013-12-08 15:46:57 +01001144 newnp->rcv_flowinfo = ip6_flowinfo(ipv6_hdr(skb));
Florent Fourcotdf3687f2014-01-17 17:15:03 +01001145 if (np->repflow)
1146 newnp->flow_label = ip6_flowlabel(ipv6_hdr(skb));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001147
1148 /* Clone native IPv6 options from listening socket (if any)
1149
1150 Yes, keeping reference count would be much more clever,
1151 but we make one more one thing there: reattach optmem
1152 to newsk.
1153 */
RongQing.Li43264e02012-07-01 17:18:59 +00001154 if (np->opt)
1155 newnp->opt = ipv6_dup_options(newsk, np->opt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001156
Arnaldo Carvalho de Melod83d8462005-12-13 23:26:10 -08001157 inet_csk(newsk)->icsk_ext_hdr_len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001158 if (newnp->opt)
Arnaldo Carvalho de Melod83d8462005-12-13 23:26:10 -08001159 inet_csk(newsk)->icsk_ext_hdr_len = (newnp->opt->opt_nflen +
1160 newnp->opt->opt_flen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001161
Daniel Borkmann81164412015-01-05 23:57:48 +01001162 tcp_ca_openreq_child(newsk, dst);
1163
Linus Torvalds1da177e2005-04-16 15:20:36 -07001164 tcp_sync_mss(newsk, dst_mtu(dst));
David S. Miller0dbaee32010-12-13 12:52:14 -08001165 newtp->advmss = dst_metric_advmss(dst);
Neal Cardwelld135c522012-04-22 09:45:47 +00001166 if (tcp_sk(sk)->rx_opt.user_mss &&
1167 tcp_sk(sk)->rx_opt.user_mss < newtp->advmss)
1168 newtp->advmss = tcp_sk(sk)->rx_opt.user_mss;
1169
Linus Torvalds1da177e2005-04-16 15:20:36 -07001170 tcp_initialize_rcv_mss(newsk);
1171
Eric Dumazetc720c7e2009-10-15 06:30:45 +00001172 newinet->inet_daddr = newinet->inet_saddr = LOOPBACK4_IPV6;
1173 newinet->inet_rcv_saddr = LOOPBACK4_IPV6;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001174
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -08001175#ifdef CONFIG_TCP_MD5SIG
1176 /* Copy over the MD5 key from the original socket */
Wang Yufen4aa956d2014-03-29 09:27:29 +08001177 key = tcp_v6_md5_do_lookup(sk, &newsk->sk_v6_daddr);
1178 if (key != NULL) {
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -08001179 /* We're using one, so create a matching key
1180 * on the newsk structure. If we fail to get
1181 * memory, then we end up not copying the key
1182 * across. Shucks.
1183 */
Eric Dumazetefe42082013-10-03 15:42:29 -07001184 tcp_md5_do_add(newsk, (union tcp_md5_addr *)&newsk->sk_v6_daddr,
Mel Gorman99a1dec2012-07-31 16:44:14 -07001185 AF_INET6, key->key, key->keylen,
1186 sk_gfp_atomic(sk, GFP_ATOMIC));
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -08001187 }
1188#endif
1189
Balazs Scheidler093d2822010-10-21 13:06:43 +02001190 if (__inet_inherit_port(sk, newsk) < 0) {
Christoph Paasche337e242012-12-14 04:07:58 +00001191 inet_csk_prepare_forced_close(newsk);
1192 tcp_done(newsk);
Balazs Scheidler093d2822010-10-21 13:06:43 +02001193 goto out;
1194 }
Eric Dumazet77a6a472015-03-18 14:05:36 -07001195 __inet_hash(newsk, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001196
1197 return newsk;
1198
1199out_overflow:
Pavel Emelyanovde0744a2008-07-16 20:31:16 -07001200 NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENOVERFLOWS);
Balazs Scheidler093d2822010-10-21 13:06:43 +02001201out_nonewsk:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001202 dst_release(dst);
Balazs Scheidler093d2822010-10-21 13:06:43 +02001203out:
1204 NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001205 return NULL;
1206}
1207
Linus Torvalds1da177e2005-04-16 15:20:36 -07001208/* The socket must have it's spinlock held when we get
1209 * here.
1210 *
1211 * We have a potential double-lock case here, so even when
1212 * doing backlog processing we use the BH locking scheme.
1213 * This is because we cannot sleep with the original spinlock
1214 * held.
1215 */
1216static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb)
1217{
1218 struct ipv6_pinfo *np = inet6_sk(sk);
1219 struct tcp_sock *tp;
1220 struct sk_buff *opt_skb = NULL;
1221
1222 /* Imagine: socket is IPv6. IPv4 packet arrives,
1223 goes to IPv4 receive handler and backlogged.
1224 From backlog it always goes here. Kerboom...
1225 Fortunately, tcp_rcv_established and rcv_established
1226 handle them correctly, but it is not case with
1227 tcp_v6_hnd_req and tcp_v6_send_reset(). --ANK
1228 */
1229
1230 if (skb->protocol == htons(ETH_P_IP))
1231 return tcp_v4_do_rcv(sk, skb);
1232
Dmitry Mishinfda9ef52006-08-31 15:28:39 -07001233 if (sk_filter(sk, skb))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001234 goto discard;
1235
1236 /*
1237 * socket locking is here for SMP purposes as backlog rcv
1238 * is currently called with bh processing disabled.
1239 */
1240
1241 /* Do Stevens' IPV6_PKTOPTIONS.
1242
1243 Yes, guys, it is the only place in our code, where we
1244 may make it not affecting IPv4.
1245 The rest of code is protocol independent,
1246 and I do not like idea to uglify IPv4.
1247
1248 Actually, all the idea behind IPV6_PKTOPTIONS
1249 looks not very well thought. For now we latch
1250 options, received in the last packet, enqueued
1251 by tcp. Feel free to propose better solution.
YOSHIFUJI Hideaki1ab14572007-02-09 23:24:49 +09001252 --ANK (980728)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001253 */
1254 if (np->rxopt.all)
Mel Gorman99a1dec2012-07-31 16:44:14 -07001255 opt_skb = skb_clone(skb, sk_gfp_atomic(sk, GFP_ATOMIC));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001256
1257 if (sk->sk_state == TCP_ESTABLISHED) { /* Fast path */
Eric Dumazet5d299f32012-08-06 05:09:33 +00001258 struct dst_entry *dst = sk->sk_rx_dst;
1259
Tom Herbertbdeab992011-08-14 19:45:55 +00001260 sock_rps_save_rxhash(sk, skb);
Eric Dumazet3d973792014-11-11 05:54:27 -08001261 sk_mark_napi_id(sk, skb);
Eric Dumazet5d299f32012-08-06 05:09:33 +00001262 if (dst) {
1263 if (inet_sk(sk)->rx_dst_ifindex != skb->skb_iif ||
1264 dst->ops->check(dst, np->rx_dst_cookie) == NULL) {
1265 dst_release(dst);
1266 sk->sk_rx_dst = NULL;
1267 }
1268 }
1269
Vijay Subramanianc995ae22013-09-03 12:23:22 -07001270 tcp_rcv_established(sk, skb, tcp_hdr(skb), skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001271 if (opt_skb)
1272 goto ipv6_pktoptions;
1273 return 0;
1274 }
1275
Arnaldo Carvalho de Meloab6a5bb2007-03-18 17:43:48 -07001276 if (skb->len < tcp_hdrlen(skb) || tcp_checksum_complete(skb))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001277 goto csum_err;
1278
YOSHIFUJI Hideaki1ab14572007-02-09 23:24:49 +09001279 if (sk->sk_state == TCP_LISTEN) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001280 struct sock *nsk = tcp_v6_hnd_req(sk, skb);
1281 if (!nsk)
1282 goto discard;
1283
1284 /*
1285 * Queue it on the new socket if the new socket is active,
1286 * otherwise we just shortcircuit this and continue with
1287 * the new socket..
1288 */
Weilong Chen4c99aa42013-12-19 18:44:34 +08001289 if (nsk != sk) {
Tom Herbertbdeab992011-08-14 19:45:55 +00001290 sock_rps_save_rxhash(nsk, skb);
Eric Dumazet3d973792014-11-11 05:54:27 -08001291 sk_mark_napi_id(sk, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001292 if (tcp_child_process(sk, nsk, skb))
1293 goto reset;
1294 if (opt_skb)
1295 __kfree_skb(opt_skb);
1296 return 0;
1297 }
Neil Horman47482f12011-04-06 13:07:09 -07001298 } else
Tom Herbertbdeab992011-08-14 19:45:55 +00001299 sock_rps_save_rxhash(sk, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001300
Arnaldo Carvalho de Meloaa8223c2007-04-10 21:04:22 -07001301 if (tcp_rcv_state_process(sk, skb, tcp_hdr(skb), skb->len))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001302 goto reset;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001303 if (opt_skb)
1304 goto ipv6_pktoptions;
1305 return 0;
1306
1307reset:
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -08001308 tcp_v6_send_reset(sk, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001309discard:
1310 if (opt_skb)
1311 __kfree_skb(opt_skb);
1312 kfree_skb(skb);
1313 return 0;
1314csum_err:
Eric Dumazet6a5dc9e2013-04-29 08:39:56 +00001315 TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_CSUMERRORS);
Pavel Emelyanov63231bd2008-07-16 20:22:25 -07001316 TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_INERRS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001317 goto discard;
1318
1319
1320ipv6_pktoptions:
1321 /* Do you ask, what is it?
1322
1323 1. skb was enqueued by tcp.
1324 2. skb is added to tail of read queue, rather than out of order.
1325 3. socket is not in passive state.
1326 4. Finally, it really contains options, which user wants to receive.
1327 */
1328 tp = tcp_sk(sk);
1329 if (TCP_SKB_CB(opt_skb)->end_seq == tp->rcv_nxt &&
1330 !((1 << sk->sk_state) & (TCPF_CLOSE | TCPF_LISTEN))) {
YOSHIFUJI Hideaki333fad52005-09-08 09:59:17 +09001331 if (np->rxopt.bits.rxinfo || np->rxopt.bits.rxoinfo)
Eric Dumazet870c3152014-10-17 09:17:20 -07001332 np->mcast_oif = tcp_v6_iif(opt_skb);
YOSHIFUJI Hideaki333fad52005-09-08 09:59:17 +09001333 if (np->rxopt.bits.rxhlim || np->rxopt.bits.rxohlim)
Arnaldo Carvalho de Melo0660e032007-04-25 17:54:47 -07001334 np->mcast_hops = ipv6_hdr(opt_skb)->hop_limit;
Florent Fourcot82e9f102013-12-08 15:46:59 +01001335 if (np->rxopt.bits.rxflow || np->rxopt.bits.rxtclass)
Florent Fourcot1397ed32013-12-08 15:46:57 +01001336 np->rcv_flowinfo = ip6_flowinfo(ipv6_hdr(opt_skb));
Florent Fourcotdf3687f2014-01-17 17:15:03 +01001337 if (np->repflow)
1338 np->flow_label = ip6_flowlabel(ipv6_hdr(opt_skb));
Eric Dumazeta2247722014-09-27 09:50:56 -07001339 if (ipv6_opt_accepted(sk, opt_skb, &TCP_SKB_CB(opt_skb)->header.h6)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001340 skb_set_owner_r(opt_skb, sk);
1341 opt_skb = xchg(&np->pktoptions, opt_skb);
1342 } else {
1343 __kfree_skb(opt_skb);
1344 opt_skb = xchg(&np->pktoptions, NULL);
1345 }
1346 }
1347
Wei Yongjun800d55f2009-02-23 21:45:33 +00001348 kfree_skb(opt_skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001349 return 0;
1350}
1351
Nicolas Dichtel2dc49d12014-12-22 18:22:48 +01001352static void tcp_v6_fill_cb(struct sk_buff *skb, const struct ipv6hdr *hdr,
1353 const struct tcphdr *th)
1354{
1355 /* This is tricky: we move IP6CB at its correct location into
1356 * TCP_SKB_CB(). It must be done after xfrm6_policy_check(), because
1357 * _decode_session6() uses IP6CB().
1358 * barrier() makes sure compiler won't play aliasing games.
1359 */
1360 memmove(&TCP_SKB_CB(skb)->header.h6, IP6CB(skb),
1361 sizeof(struct inet6_skb_parm));
1362 barrier();
1363
1364 TCP_SKB_CB(skb)->seq = ntohl(th->seq);
1365 TCP_SKB_CB(skb)->end_seq = (TCP_SKB_CB(skb)->seq + th->syn + th->fin +
1366 skb->len - th->doff*4);
1367 TCP_SKB_CB(skb)->ack_seq = ntohl(th->ack_seq);
1368 TCP_SKB_CB(skb)->tcp_flags = tcp_flag_byte(th);
1369 TCP_SKB_CB(skb)->tcp_tw_isn = 0;
1370 TCP_SKB_CB(skb)->ip_dsfield = ipv6_get_dsfield(hdr);
1371 TCP_SKB_CB(skb)->sacked = 0;
1372}
1373
Herbert Xue5bbef22007-10-15 12:50:28 -07001374static int tcp_v6_rcv(struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001375{
Eric Dumazetcf533ea2011-10-21 05:22:42 -04001376 const struct tcphdr *th;
Eric Dumazetb71d1d42011-04-22 04:53:02 +00001377 const struct ipv6hdr *hdr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001378 struct sock *sk;
1379 int ret;
Pavel Emelyanova86b1e32008-07-16 20:20:58 -07001380 struct net *net = dev_net(skb->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001381
1382 if (skb->pkt_type != PACKET_HOST)
1383 goto discard_it;
1384
1385 /*
1386 * Count it even if it's bad.
1387 */
Pavel Emelyanov63231bd2008-07-16 20:22:25 -07001388 TCP_INC_STATS_BH(net, TCP_MIB_INSEGS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001389
1390 if (!pskb_may_pull(skb, sizeof(struct tcphdr)))
1391 goto discard_it;
1392
Arnaldo Carvalho de Meloaa8223c2007-04-10 21:04:22 -07001393 th = tcp_hdr(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001394
1395 if (th->doff < sizeof(struct tcphdr)/4)
1396 goto bad_packet;
1397 if (!pskb_may_pull(skb, th->doff*4))
1398 goto discard_it;
1399
Tom Herberte4f45b72014-05-02 16:29:51 -07001400 if (skb_checksum_init(skb, IPPROTO_TCP, ip6_compute_pseudo))
Eric Dumazet6a5dc9e2013-04-29 08:39:56 +00001401 goto csum_error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001402
Arnaldo Carvalho de Meloaa8223c2007-04-10 21:04:22 -07001403 th = tcp_hdr(skb);
Stephen Hemmingere802af92010-04-22 15:24:53 -07001404 hdr = ipv6_hdr(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001405
Eric Dumazet870c3152014-10-17 09:17:20 -07001406 sk = __inet6_lookup_skb(&tcp_hashinfo, skb, th->source, th->dest,
Nicolas Dichtel2dc49d12014-12-22 18:22:48 +01001407 inet6_iif(skb));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001408 if (!sk)
1409 goto no_tcp_socket;
1410
1411process:
1412 if (sk->sk_state == TCP_TIME_WAIT)
1413 goto do_time_wait;
1414
Stephen Hemmingere802af92010-04-22 15:24:53 -07001415 if (hdr->hop_limit < inet6_sk(sk)->min_hopcount) {
1416 NET_INC_STATS_BH(net, LINUX_MIB_TCPMINTTLDROP);
1417 goto discard_and_relse;
1418 }
1419
Linus Torvalds1da177e2005-04-16 15:20:36 -07001420 if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb))
1421 goto discard_and_relse;
1422
Nicolas Dichtel2dc49d12014-12-22 18:22:48 +01001423 tcp_v6_fill_cb(skb, hdr, th);
1424
Dmitry Popov9ea88a12014-08-07 02:38:22 +04001425#ifdef CONFIG_TCP_MD5SIG
1426 if (tcp_v6_inbound_md5_hash(sk, skb))
1427 goto discard_and_relse;
1428#endif
1429
Dmitry Mishinfda9ef52006-08-31 15:28:39 -07001430 if (sk_filter(sk, skb))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001431 goto discard_and_relse;
1432
Eric Dumazet2c8c56e2014-11-11 05:54:28 -08001433 sk_incoming_cpu_update(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001434 skb->dev = NULL;
1435
Fabio Olive Leite293b9c42006-09-25 22:28:47 -07001436 bh_lock_sock_nested(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001437 ret = 0;
1438 if (!sock_owned_by_user(sk)) {
Dan Williams7bced392013-12-30 12:37:29 -08001439 if (!tcp_prequeue(sk, skb))
YOSHIFUJI Hideaki1ab14572007-02-09 23:24:49 +09001440 ret = tcp_v6_do_rcv(sk, skb);
Eric Dumazetda882c12012-04-22 23:38:54 +00001441 } else if (unlikely(sk_add_backlog(sk, skb,
1442 sk->sk_rcvbuf + sk->sk_sndbuf))) {
Zhu Yi6b03a532010-03-04 18:01:41 +00001443 bh_unlock_sock(sk);
Eric Dumazet6cce09f2010-03-07 23:21:57 +00001444 NET_INC_STATS_BH(net, LINUX_MIB_TCPBACKLOGDROP);
Zhu Yi6b03a532010-03-04 18:01:41 +00001445 goto discard_and_relse;
1446 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001447 bh_unlock_sock(sk);
1448
1449 sock_put(sk);
1450 return ret ? -1 : 0;
1451
1452no_tcp_socket:
1453 if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb))
1454 goto discard_it;
1455
Nicolas Dichtel2dc49d12014-12-22 18:22:48 +01001456 tcp_v6_fill_cb(skb, hdr, th);
1457
Linus Torvalds1da177e2005-04-16 15:20:36 -07001458 if (skb->len < (th->doff<<2) || tcp_checksum_complete(skb)) {
Eric Dumazet6a5dc9e2013-04-29 08:39:56 +00001459csum_error:
1460 TCP_INC_STATS_BH(net, TCP_MIB_CSUMERRORS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001461bad_packet:
Pavel Emelyanov63231bd2008-07-16 20:22:25 -07001462 TCP_INC_STATS_BH(net, TCP_MIB_INERRS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001463 } else {
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -08001464 tcp_v6_send_reset(NULL, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001465 }
1466
1467discard_it:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001468 kfree_skb(skb);
1469 return 0;
1470
1471discard_and_relse:
1472 sock_put(sk);
1473 goto discard_it;
1474
1475do_time_wait:
1476 if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) {
YOSHIFUJI Hideaki9469c7b2006-10-10 19:41:46 -07001477 inet_twsk_put(inet_twsk(sk));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001478 goto discard_it;
1479 }
1480
Nicolas Dichtel2dc49d12014-12-22 18:22:48 +01001481 tcp_v6_fill_cb(skb, hdr, th);
1482
Eric Dumazet6a5dc9e2013-04-29 08:39:56 +00001483 if (skb->len < (th->doff<<2)) {
YOSHIFUJI Hideaki9469c7b2006-10-10 19:41:46 -07001484 inet_twsk_put(inet_twsk(sk));
Eric Dumazet6a5dc9e2013-04-29 08:39:56 +00001485 goto bad_packet;
1486 }
1487 if (tcp_checksum_complete(skb)) {
1488 inet_twsk_put(inet_twsk(sk));
1489 goto csum_error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001490 }
1491
YOSHIFUJI Hideaki9469c7b2006-10-10 19:41:46 -07001492 switch (tcp_timewait_state_process(inet_twsk(sk), skb, th)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001493 case TCP_TW_SYN:
1494 {
1495 struct sock *sk2;
1496
YOSHIFUJI Hideakic346dca2008-03-25 21:47:49 +09001497 sk2 = inet6_lookup_listener(dev_net(skb->dev), &tcp_hashinfo,
Tom Herbert5ba24952013-01-22 09:50:39 +00001498 &ipv6_hdr(skb)->saddr, th->source,
Arnaldo Carvalho de Melo0660e032007-04-25 17:54:47 -07001499 &ipv6_hdr(skb)->daddr,
Eric Dumazet870c3152014-10-17 09:17:20 -07001500 ntohs(th->dest), tcp_v6_iif(skb));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001501 if (sk2 != NULL) {
Arnaldo Carvalho de Melo295ff7e2005-08-09 20:44:40 -07001502 struct inet_timewait_sock *tw = inet_twsk(sk);
1503 inet_twsk_deschedule(tw, &tcp_death_row);
1504 inet_twsk_put(tw);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001505 sk = sk2;
1506 goto process;
1507 }
1508 /* Fall through to ACK */
1509 }
1510 case TCP_TW_ACK:
1511 tcp_v6_timewait_ack(sk, skb);
1512 break;
1513 case TCP_TW_RST:
1514 goto no_tcp_socket;
Wang Yufen4aa956d2014-03-29 09:27:29 +08001515 case TCP_TW_SUCCESS:
1516 ;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001517 }
1518 goto discard_it;
1519}
1520
Eric Dumazetc7109982012-07-26 12:18:11 +00001521static void tcp_v6_early_demux(struct sk_buff *skb)
1522{
1523 const struct ipv6hdr *hdr;
1524 const struct tcphdr *th;
1525 struct sock *sk;
1526
1527 if (skb->pkt_type != PACKET_HOST)
1528 return;
1529
1530 if (!pskb_may_pull(skb, skb_transport_offset(skb) + sizeof(struct tcphdr)))
1531 return;
1532
1533 hdr = ipv6_hdr(skb);
1534 th = tcp_hdr(skb);
1535
1536 if (th->doff < sizeof(struct tcphdr) / 4)
1537 return;
1538
Eric Dumazet870c3152014-10-17 09:17:20 -07001539 /* Note : We use inet6_iif() here, not tcp_v6_iif() */
Eric Dumazetc7109982012-07-26 12:18:11 +00001540 sk = __inet6_lookup_established(dev_net(skb->dev), &tcp_hashinfo,
1541 &hdr->saddr, th->source,
1542 &hdr->daddr, ntohs(th->dest),
1543 inet6_iif(skb));
1544 if (sk) {
1545 skb->sk = sk;
1546 skb->destructor = sock_edemux;
Eric Dumazetf7e4eb02015-03-15 21:12:13 -07001547 if (sk_fullsock(sk)) {
Eric Dumazetc7109982012-07-26 12:18:11 +00001548 struct dst_entry *dst = sk->sk_rx_dst;
Neal Cardwellf3f12132012-10-22 21:41:48 +00001549
Eric Dumazetc7109982012-07-26 12:18:11 +00001550 if (dst)
Eric Dumazet5d299f32012-08-06 05:09:33 +00001551 dst = dst_check(dst, inet6_sk(sk)->rx_dst_cookie);
Eric Dumazetc7109982012-07-26 12:18:11 +00001552 if (dst &&
Neal Cardwellf3f12132012-10-22 21:41:48 +00001553 inet_sk(sk)->rx_dst_ifindex == skb->skb_iif)
Eric Dumazetc7109982012-07-26 12:18:11 +00001554 skb_dst_set_noref(skb, dst);
1555 }
1556 }
1557}
1558
David S. Millerccb7c412010-12-01 18:09:13 -08001559static struct timewait_sock_ops tcp6_timewait_sock_ops = {
1560 .twsk_obj_size = sizeof(struct tcp6_timewait_sock),
1561 .twsk_unique = tcp_twsk_unique,
Wang Yufen4aa956d2014-03-29 09:27:29 +08001562 .twsk_destructor = tcp_twsk_destructor,
David S. Millerccb7c412010-12-01 18:09:13 -08001563};
1564
Stephen Hemminger3b401a82009-09-01 19:25:04 +00001565static const struct inet_connection_sock_af_ops ipv6_specific = {
Arnaldo Carvalho de Melo543d9cf2006-03-20 22:48:35 -08001566 .queue_xmit = inet6_csk_xmit,
1567 .send_check = tcp_v6_send_check,
1568 .rebuild_header = inet6_sk_rebuild_header,
Eric Dumazet5d299f32012-08-06 05:09:33 +00001569 .sk_rx_dst_set = inet6_sk_rx_dst_set,
Arnaldo Carvalho de Melo543d9cf2006-03-20 22:48:35 -08001570 .conn_request = tcp_v6_conn_request,
1571 .syn_recv_sock = tcp_v6_syn_recv_sock,
Arnaldo Carvalho de Melo543d9cf2006-03-20 22:48:35 -08001572 .net_header_len = sizeof(struct ipv6hdr),
Eric Dumazet67469602012-04-24 07:37:38 +00001573 .net_frag_header_len = sizeof(struct frag_hdr),
Arnaldo Carvalho de Melo543d9cf2006-03-20 22:48:35 -08001574 .setsockopt = ipv6_setsockopt,
1575 .getsockopt = ipv6_getsockopt,
1576 .addr2sockaddr = inet6_csk_addr2sockaddr,
1577 .sockaddr_len = sizeof(struct sockaddr_in6),
Arnaldo Carvalho de Meloab1e0a12008-02-03 04:06:04 -08001578 .bind_conflict = inet6_csk_bind_conflict,
Dmitry Mishin3fdadf72006-03-20 22:45:21 -08001579#ifdef CONFIG_COMPAT
Arnaldo Carvalho de Melo543d9cf2006-03-20 22:48:35 -08001580 .compat_setsockopt = compat_ipv6_setsockopt,
1581 .compat_getsockopt = compat_ipv6_getsockopt,
Dmitry Mishin3fdadf72006-03-20 22:45:21 -08001582#endif
Neal Cardwell4fab9072014-08-14 12:40:05 -04001583 .mtu_reduced = tcp_v6_mtu_reduced,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001584};
1585
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -08001586#ifdef CONFIG_TCP_MD5SIG
Stephen Hemmingerb2e4b3d2009-09-01 19:25:03 +00001587static const struct tcp_sock_af_ops tcp_sock_ipv6_specific = {
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -08001588 .md5_lookup = tcp_v6_md5_lookup,
Adam Langley49a72df2008-07-19 00:01:42 -07001589 .calc_md5_hash = tcp_v6_md5_hash_skb,
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -08001590 .md5_parse = tcp_v6_parse_md5_keys,
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -08001591};
David S. Millera9286302006-11-14 19:53:22 -08001592#endif
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -08001593
Linus Torvalds1da177e2005-04-16 15:20:36 -07001594/*
1595 * TCP over IPv4 via INET6 API
1596 */
Stephen Hemminger3b401a82009-09-01 19:25:04 +00001597static const struct inet_connection_sock_af_ops ipv6_mapped = {
Arnaldo Carvalho de Melo543d9cf2006-03-20 22:48:35 -08001598 .queue_xmit = ip_queue_xmit,
1599 .send_check = tcp_v4_send_check,
1600 .rebuild_header = inet_sk_rebuild_header,
Eric Dumazet63d02d12012-08-09 14:11:00 +00001601 .sk_rx_dst_set = inet_sk_rx_dst_set,
Arnaldo Carvalho de Melo543d9cf2006-03-20 22:48:35 -08001602 .conn_request = tcp_v6_conn_request,
1603 .syn_recv_sock = tcp_v6_syn_recv_sock,
Arnaldo Carvalho de Melo543d9cf2006-03-20 22:48:35 -08001604 .net_header_len = sizeof(struct iphdr),
1605 .setsockopt = ipv6_setsockopt,
1606 .getsockopt = ipv6_getsockopt,
1607 .addr2sockaddr = inet6_csk_addr2sockaddr,
1608 .sockaddr_len = sizeof(struct sockaddr_in6),
Arnaldo Carvalho de Meloab1e0a12008-02-03 04:06:04 -08001609 .bind_conflict = inet6_csk_bind_conflict,
Dmitry Mishin3fdadf72006-03-20 22:45:21 -08001610#ifdef CONFIG_COMPAT
Arnaldo Carvalho de Melo543d9cf2006-03-20 22:48:35 -08001611 .compat_setsockopt = compat_ipv6_setsockopt,
1612 .compat_getsockopt = compat_ipv6_getsockopt,
Dmitry Mishin3fdadf72006-03-20 22:45:21 -08001613#endif
Neal Cardwell4fab9072014-08-14 12:40:05 -04001614 .mtu_reduced = tcp_v4_mtu_reduced,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001615};
1616
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -08001617#ifdef CONFIG_TCP_MD5SIG
Stephen Hemmingerb2e4b3d2009-09-01 19:25:03 +00001618static const struct tcp_sock_af_ops tcp_sock_ipv6_mapped_specific = {
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -08001619 .md5_lookup = tcp_v4_md5_lookup,
Adam Langley49a72df2008-07-19 00:01:42 -07001620 .calc_md5_hash = tcp_v4_md5_hash_skb,
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -08001621 .md5_parse = tcp_v6_parse_md5_keys,
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -08001622};
David S. Millera9286302006-11-14 19:53:22 -08001623#endif
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -08001624
Linus Torvalds1da177e2005-04-16 15:20:36 -07001625/* NOTE: A lot of things set to zero explicitly by call to
1626 * sk_alloc() so need not be done here.
1627 */
1628static int tcp_v6_init_sock(struct sock *sk)
1629{
Arnaldo Carvalho de Melo6687e982005-08-10 04:03:31 -03001630 struct inet_connection_sock *icsk = inet_csk(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001631
Neal Cardwell900f65d2012-04-19 09:55:21 +00001632 tcp_init_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001633
Arnaldo Carvalho de Melo8292a172005-12-13 23:15:52 -08001634 icsk->icsk_af_ops = &ipv6_specific;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001635
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -08001636#ifdef CONFIG_TCP_MD5SIG
David S. Millerac807fa2012-04-23 03:21:58 -04001637 tcp_sk(sk)->af_specific = &tcp_sock_ipv6_specific;
YOSHIFUJI Hideakicfb6eeb2006-11-14 19:07:45 -08001638#endif
1639
Linus Torvalds1da177e2005-04-16 15:20:36 -07001640 return 0;
1641}
1642
Brian Haley7d06b2e2008-06-14 17:04:49 -07001643static void tcp_v6_destroy_sock(struct sock *sk)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001644{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001645 tcp_v4_destroy_sock(sk);
Brian Haley7d06b2e2008-06-14 17:04:49 -07001646 inet6_destroy_sock(sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001647}
1648
YOSHIFUJI Hideaki952a10b2007-04-21 20:13:44 +09001649#ifdef CONFIG_PROC_FS
Linus Torvalds1da177e2005-04-16 15:20:36 -07001650/* Proc filesystem TCPv6 sock list dumping. */
YOSHIFUJI Hideaki1ab14572007-02-09 23:24:49 +09001651static void get_openreq6(struct seq_file *seq,
Eric Dumazetd4f06872015-03-12 16:44:09 -07001652 struct request_sock *req, int i, kuid_t uid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001653{
Eric Dumazetfa76ce732015-03-19 19:04:20 -07001654 long ttd = req->rsk_timer.expires - jiffies;
Eric Dumazet634fb9792013-10-09 15:21:29 -07001655 const struct in6_addr *src = &inet_rsk(req)->ir_v6_loc_addr;
1656 const struct in6_addr *dest = &inet_rsk(req)->ir_v6_rmt_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001657
1658 if (ttd < 0)
1659 ttd = 0;
1660
Linus Torvalds1da177e2005-04-16 15:20:36 -07001661 seq_printf(seq,
1662 "%4d: %08X%08X%08X%08X:%04X %08X%08X%08X%08X:%04X "
Francesco Fuscod14c5ab2013-08-15 13:42:14 +02001663 "%02X %08X:%08X %02X:%08lX %08X %5u %8d %d %d %pK\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001664 i,
1665 src->s6_addr32[0], src->s6_addr32[1],
1666 src->s6_addr32[2], src->s6_addr32[3],
Eric Dumazetb44084c2013-10-10 00:04:37 -07001667 inet_rsk(req)->ir_num,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001668 dest->s6_addr32[0], dest->s6_addr32[1],
1669 dest->s6_addr32[2], dest->s6_addr32[3],
Eric Dumazet634fb9792013-10-09 15:21:29 -07001670 ntohs(inet_rsk(req)->ir_rmt_port),
Linus Torvalds1da177e2005-04-16 15:20:36 -07001671 TCP_SYN_RECV,
Weilong Chen4c99aa42013-12-19 18:44:34 +08001672 0, 0, /* could print option size, but that is af dependent. */
YOSHIFUJI Hideaki1ab14572007-02-09 23:24:49 +09001673 1, /* timers active (only the expire timer) */
1674 jiffies_to_clock_t(ttd),
Eric Dumazete6c022a2012-10-27 23:16:46 +00001675 req->num_timeout,
Eric W. Biedermana7cb5a42012-05-24 01:10:10 -06001676 from_kuid_munged(seq_user_ns(seq), uid),
YOSHIFUJI Hideaki1ab14572007-02-09 23:24:49 +09001677 0, /* non standard timer */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001678 0, /* open_requests have no inode */
1679 0, req);
1680}
1681
1682static void get_tcp6_sock(struct seq_file *seq, struct sock *sp, int i)
1683{
Eric Dumazetb71d1d42011-04-22 04:53:02 +00001684 const struct in6_addr *dest, *src;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001685 __u16 destp, srcp;
1686 int timer_active;
1687 unsigned long timer_expires;
Eric Dumazetcf533ea2011-10-21 05:22:42 -04001688 const struct inet_sock *inet = inet_sk(sp);
1689 const struct tcp_sock *tp = tcp_sk(sp);
Arnaldo Carvalho de Melo463c84b2005-08-09 20:10:42 -07001690 const struct inet_connection_sock *icsk = inet_csk(sp);
Yuchung Cheng0a672f72014-05-11 20:22:12 -07001691 struct fastopen_queue *fastopenq = icsk->icsk_accept_queue.fastopenq;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001692
Eric Dumazetefe42082013-10-03 15:42:29 -07001693 dest = &sp->sk_v6_daddr;
1694 src = &sp->sk_v6_rcv_saddr;
Eric Dumazetc720c7e2009-10-15 06:30:45 +00001695 destp = ntohs(inet->inet_dport);
1696 srcp = ntohs(inet->inet_sport);
Arnaldo Carvalho de Melo463c84b2005-08-09 20:10:42 -07001697
1698 if (icsk->icsk_pending == ICSK_TIME_RETRANS) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001699 timer_active = 1;
Arnaldo Carvalho de Melo463c84b2005-08-09 20:10:42 -07001700 timer_expires = icsk->icsk_timeout;
1701 } else if (icsk->icsk_pending == ICSK_TIME_PROBE0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001702 timer_active = 4;
Arnaldo Carvalho de Melo463c84b2005-08-09 20:10:42 -07001703 timer_expires = icsk->icsk_timeout;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001704 } else if (timer_pending(&sp->sk_timer)) {
1705 timer_active = 2;
1706 timer_expires = sp->sk_timer.expires;
1707 } else {
1708 timer_active = 0;
1709 timer_expires = jiffies;
1710 }
1711
1712 seq_printf(seq,
1713 "%4d: %08X%08X%08X%08X:%04X %08X%08X%08X%08X:%04X "
Francesco Fuscod14c5ab2013-08-15 13:42:14 +02001714 "%02X %08X:%08X %02X:%08lX %08X %5u %8d %lu %d %pK %lu %lu %u %u %d\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001715 i,
1716 src->s6_addr32[0], src->s6_addr32[1],
1717 src->s6_addr32[2], src->s6_addr32[3], srcp,
1718 dest->s6_addr32[0], dest->s6_addr32[1],
1719 dest->s6_addr32[2], dest->s6_addr32[3], destp,
YOSHIFUJI Hideaki1ab14572007-02-09 23:24:49 +09001720 sp->sk_state,
Sridhar Samudrala47da8ee2006-06-27 13:29:00 -07001721 tp->write_seq-tp->snd_una,
1722 (sp->sk_state == TCP_LISTEN) ? sp->sk_ack_backlog : (tp->rcv_nxt - tp->copied_seq),
Linus Torvalds1da177e2005-04-16 15:20:36 -07001723 timer_active,
Eric Dumazeta399a802012-08-08 21:13:53 +00001724 jiffies_delta_to_clock_t(timer_expires - jiffies),
Arnaldo Carvalho de Melo463c84b2005-08-09 20:10:42 -07001725 icsk->icsk_retransmits,
Eric W. Biedermana7cb5a42012-05-24 01:10:10 -06001726 from_kuid_munged(seq_user_ns(seq), sock_i_uid(sp)),
Arnaldo Carvalho de Melo6687e982005-08-10 04:03:31 -03001727 icsk->icsk_probes_out,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001728 sock_i_ino(sp),
1729 atomic_read(&sp->sk_refcnt), sp,
Stephen Hemminger7be87352008-06-27 20:00:19 -07001730 jiffies_to_clock_t(icsk->icsk_rto),
1731 jiffies_to_clock_t(icsk->icsk_ack.ato),
Weilong Chen4c99aa42013-12-19 18:44:34 +08001732 (icsk->icsk_ack.quick << 1) | icsk->icsk_ack.pingpong,
Ilpo Järvinen0b6a05c2009-09-15 01:30:10 -07001733 tp->snd_cwnd,
Yuchung Cheng0a672f72014-05-11 20:22:12 -07001734 sp->sk_state == TCP_LISTEN ?
1735 (fastopenq ? fastopenq->max_qlen : 0) :
1736 (tcp_in_initial_slowstart(tp) ? -1 : tp->snd_ssthresh)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001737 );
1738}
1739
YOSHIFUJI Hideaki1ab14572007-02-09 23:24:49 +09001740static void get_timewait6_sock(struct seq_file *seq,
Arnaldo Carvalho de Melo8feaf0c02005-08-09 20:09:30 -07001741 struct inet_timewait_sock *tw, int i)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001742{
Eric Dumazetb71d1d42011-04-22 04:53:02 +00001743 const struct in6_addr *dest, *src;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001744 __u16 destp, srcp;
Eric Dumazet96f817f2013-10-03 14:27:25 -07001745 s32 delta = tw->tw_ttd - inet_tw_time_stamp();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001746
Eric Dumazetefe42082013-10-03 15:42:29 -07001747 dest = &tw->tw_v6_daddr;
1748 src = &tw->tw_v6_rcv_saddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001749 destp = ntohs(tw->tw_dport);
1750 srcp = ntohs(tw->tw_sport);
1751
1752 seq_printf(seq,
1753 "%4d: %08X%08X%08X%08X:%04X %08X%08X%08X%08X:%04X "
Dan Rosenberg71338aa2011-05-23 12:17:35 +00001754 "%02X %08X:%08X %02X:%08lX %08X %5d %8d %d %d %pK\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001755 i,
1756 src->s6_addr32[0], src->s6_addr32[1],
1757 src->s6_addr32[2], src->s6_addr32[3], srcp,
1758 dest->s6_addr32[0], dest->s6_addr32[1],
1759 dest->s6_addr32[2], dest->s6_addr32[3], destp,
1760 tw->tw_substate, 0, 0,
Eric Dumazeta399a802012-08-08 21:13:53 +00001761 3, jiffies_delta_to_clock_t(delta), 0, 0, 0, 0,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001762 atomic_read(&tw->tw_refcnt), tw);
1763}
1764
Linus Torvalds1da177e2005-04-16 15:20:36 -07001765static int tcp6_seq_show(struct seq_file *seq, void *v)
1766{
1767 struct tcp_iter_state *st;
Eric Dumazet05dbc7b2013-10-03 00:22:02 -07001768 struct sock *sk = v;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001769
1770 if (v == SEQ_START_TOKEN) {
1771 seq_puts(seq,
1772 " sl "
1773 "local_address "
1774 "remote_address "
1775 "st tx_queue rx_queue tr tm->when retrnsmt"
1776 " uid timeout inode\n");
1777 goto out;
1778 }
1779 st = seq->private;
1780
1781 switch (st->state) {
1782 case TCP_SEQ_STATE_LISTENING:
1783 case TCP_SEQ_STATE_ESTABLISHED:
Eric Dumazet05dbc7b2013-10-03 00:22:02 -07001784 if (sk->sk_state == TCP_TIME_WAIT)
1785 get_timewait6_sock(seq, v, st->num);
1786 else
1787 get_tcp6_sock(seq, v, st->num);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001788 break;
1789 case TCP_SEQ_STATE_OPENREQ:
Eric Dumazetd4f06872015-03-12 16:44:09 -07001790 get_openreq6(seq, v, st->num, st->uid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001791 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001792 }
1793out:
1794 return 0;
1795}
1796
Arjan van de Ven73cb88e2011-10-30 06:46:30 +00001797static const struct file_operations tcp6_afinfo_seq_fops = {
1798 .owner = THIS_MODULE,
1799 .open = tcp_seq_open,
1800 .read = seq_read,
1801 .llseek = seq_lseek,
1802 .release = seq_release_net
1803};
1804
Linus Torvalds1da177e2005-04-16 15:20:36 -07001805static struct tcp_seq_afinfo tcp6_seq_afinfo = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001806 .name = "tcp6",
1807 .family = AF_INET6,
Arjan van de Ven73cb88e2011-10-30 06:46:30 +00001808 .seq_fops = &tcp6_afinfo_seq_fops,
Denis V. Lunev9427c4b2008-04-13 22:12:13 -07001809 .seq_ops = {
1810 .show = tcp6_seq_show,
1811 },
Linus Torvalds1da177e2005-04-16 15:20:36 -07001812};
1813
Alexey Dobriyan2c8c1e72010-01-17 03:35:32 +00001814int __net_init tcp6_proc_init(struct net *net)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001815{
Daniel Lezcano6f8b13b2008-03-21 04:14:45 -07001816 return tcp_proc_register(net, &tcp6_seq_afinfo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001817}
1818
Daniel Lezcano6f8b13b2008-03-21 04:14:45 -07001819void tcp6_proc_exit(struct net *net)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001820{
Daniel Lezcano6f8b13b2008-03-21 04:14:45 -07001821 tcp_proc_unregister(net, &tcp6_seq_afinfo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001822}
1823#endif
1824
Eric Dumazetf77d6022013-05-09 10:28:16 +00001825static void tcp_v6_clear_sk(struct sock *sk, int size)
1826{
1827 struct inet_sock *inet = inet_sk(sk);
1828
1829 /* we do not want to clear pinet6 field, because of RCU lookups */
1830 sk_prot_clear_nulls(sk, offsetof(struct inet_sock, pinet6));
1831
1832 size -= offsetof(struct inet_sock, pinet6) + sizeof(inet->pinet6);
1833 memset(&inet->pinet6 + 1, 0, size);
1834}
1835
Linus Torvalds1da177e2005-04-16 15:20:36 -07001836struct proto tcpv6_prot = {
1837 .name = "TCPv6",
1838 .owner = THIS_MODULE,
1839 .close = tcp_close,
1840 .connect = tcp_v6_connect,
1841 .disconnect = tcp_disconnect,
Arnaldo Carvalho de Melo463c84b2005-08-09 20:10:42 -07001842 .accept = inet_csk_accept,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001843 .ioctl = tcp_ioctl,
1844 .init = tcp_v6_init_sock,
1845 .destroy = tcp_v6_destroy_sock,
1846 .shutdown = tcp_shutdown,
1847 .setsockopt = tcp_setsockopt,
1848 .getsockopt = tcp_getsockopt,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001849 .recvmsg = tcp_recvmsg,
Changli Gao7ba42912010-07-10 20:41:55 +00001850 .sendmsg = tcp_sendmsg,
1851 .sendpage = tcp_sendpage,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001852 .backlog_rcv = tcp_v6_do_rcv,
Eric Dumazet46d3cea2012-07-11 05:50:31 +00001853 .release_cb = tcp_release_cb,
Eric Dumazet77a6a472015-03-18 14:05:36 -07001854 .hash = inet_hash,
Arnaldo Carvalho de Meloab1e0a12008-02-03 04:06:04 -08001855 .unhash = inet_unhash,
1856 .get_port = inet_csk_get_port,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001857 .enter_memory_pressure = tcp_enter_memory_pressure,
Eric Dumazetc9bee3b72013-07-22 20:27:07 -07001858 .stream_memory_free = tcp_stream_memory_free,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001859 .sockets_allocated = &tcp_sockets_allocated,
1860 .memory_allocated = &tcp_memory_allocated,
1861 .memory_pressure = &tcp_memory_pressure,
Arnaldo Carvalho de Melo0a5578c2005-08-09 20:11:41 -07001862 .orphan_count = &tcp_orphan_count,
Eric W. Biedermana4fe34b2013-10-19 16:25:36 -07001863 .sysctl_mem = sysctl_tcp_mem,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001864 .sysctl_wmem = sysctl_tcp_wmem,
1865 .sysctl_rmem = sysctl_tcp_rmem,
1866 .max_header = MAX_TCP_HEADER,
1867 .obj_size = sizeof(struct tcp6_sock),
Eric Dumazet3ab5aee2008-11-16 19:40:17 -08001868 .slab_flags = SLAB_DESTROY_BY_RCU,
Arnaldo Carvalho de Melo6d6ee432005-12-13 23:25:19 -08001869 .twsk_prot = &tcp6_timewait_sock_ops,
Arnaldo Carvalho de Melo60236fd2005-06-18 22:47:21 -07001870 .rsk_prot = &tcp6_request_sock_ops,
Pavel Emelyanov39d8cda2008-03-22 16:50:58 -07001871 .h.hashinfo = &tcp_hashinfo,
Changli Gao7ba42912010-07-10 20:41:55 +00001872 .no_autobind = true,
Arnaldo Carvalho de Melo543d9cf2006-03-20 22:48:35 -08001873#ifdef CONFIG_COMPAT
1874 .compat_setsockopt = compat_tcp_setsockopt,
1875 .compat_getsockopt = compat_tcp_getsockopt,
1876#endif
Andrew Mortonc255a452012-07-31 16:43:02 -07001877#ifdef CONFIG_MEMCG_KMEM
Glauber Costad1a4c0b2011-12-11 21:47:04 +00001878 .proto_cgroup = tcp_proto_cgroup,
1879#endif
Eric Dumazetf77d6022013-05-09 10:28:16 +00001880 .clear_sk = tcp_v6_clear_sk,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001881};
1882
Alexey Dobriyan41135cc2009-09-14 12:22:28 +00001883static const struct inet6_protocol tcpv6_protocol = {
Eric Dumazetc7109982012-07-26 12:18:11 +00001884 .early_demux = tcp_v6_early_demux,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001885 .handler = tcp_v6_rcv,
1886 .err_handler = tcp_v6_err,
1887 .flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL,
1888};
1889
Linus Torvalds1da177e2005-04-16 15:20:36 -07001890static struct inet_protosw tcpv6_protosw = {
1891 .type = SOCK_STREAM,
1892 .protocol = IPPROTO_TCP,
1893 .prot = &tcpv6_prot,
1894 .ops = &inet6_stream_ops,
Arnaldo Carvalho de Melod83d8462005-12-13 23:26:10 -08001895 .flags = INET_PROTOSW_PERMANENT |
1896 INET_PROTOSW_ICSK,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001897};
1898
Alexey Dobriyan2c8c1e72010-01-17 03:35:32 +00001899static int __net_init tcpv6_net_init(struct net *net)
Daniel Lezcano93ec9262008-03-07 11:16:02 -08001900{
Denis V. Lunev56772422008-04-03 14:28:30 -07001901 return inet_ctl_sock_create(&net->ipv6.tcp_sk, PF_INET6,
1902 SOCK_RAW, IPPROTO_TCP, net);
Daniel Lezcano93ec9262008-03-07 11:16:02 -08001903}
1904
Alexey Dobriyan2c8c1e72010-01-17 03:35:32 +00001905static void __net_exit tcpv6_net_exit(struct net *net)
Daniel Lezcano93ec9262008-03-07 11:16:02 -08001906{
Denis V. Lunev56772422008-04-03 14:28:30 -07001907 inet_ctl_sock_destroy(net->ipv6.tcp_sk);
Eric W. Biedermanb099ce22009-12-03 02:29:09 +00001908}
1909
Alexey Dobriyan2c8c1e72010-01-17 03:35:32 +00001910static void __net_exit tcpv6_net_exit_batch(struct list_head *net_exit_list)
Eric W. Biedermanb099ce22009-12-03 02:29:09 +00001911{
1912 inet_twsk_purge(&tcp_hashinfo, &tcp_death_row, AF_INET6);
Daniel Lezcano93ec9262008-03-07 11:16:02 -08001913}
1914
1915static struct pernet_operations tcpv6_net_ops = {
Eric W. Biedermanb099ce22009-12-03 02:29:09 +00001916 .init = tcpv6_net_init,
1917 .exit = tcpv6_net_exit,
1918 .exit_batch = tcpv6_net_exit_batch,
Daniel Lezcano93ec9262008-03-07 11:16:02 -08001919};
1920
Daniel Lezcano7f4e4862007-12-11 02:25:35 -08001921int __init tcpv6_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001922{
Daniel Lezcano7f4e4862007-12-11 02:25:35 -08001923 int ret;
David Woodhouseae0f7d52006-01-11 15:53:04 -08001924
Vlad Yasevich33362882012-11-15 08:49:15 +00001925 ret = inet6_add_protocol(&tcpv6_protocol, IPPROTO_TCP);
1926 if (ret)
Vlad Yasevichc6b641a2012-11-15 08:49:22 +00001927 goto out;
Vlad Yasevich33362882012-11-15 08:49:15 +00001928
Daniel Lezcano7f4e4862007-12-11 02:25:35 -08001929 /* register inet6 protocol */
1930 ret = inet6_register_protosw(&tcpv6_protosw);
1931 if (ret)
1932 goto out_tcpv6_protocol;
1933
Daniel Lezcano93ec9262008-03-07 11:16:02 -08001934 ret = register_pernet_subsys(&tcpv6_net_ops);
Daniel Lezcano7f4e4862007-12-11 02:25:35 -08001935 if (ret)
1936 goto out_tcpv6_protosw;
1937out:
1938 return ret;
1939
Daniel Lezcano7f4e4862007-12-11 02:25:35 -08001940out_tcpv6_protosw:
1941 inet6_unregister_protosw(&tcpv6_protosw);
Vlad Yasevich33362882012-11-15 08:49:15 +00001942out_tcpv6_protocol:
1943 inet6_del_protocol(&tcpv6_protocol, IPPROTO_TCP);
Daniel Lezcano7f4e4862007-12-11 02:25:35 -08001944 goto out;
1945}
1946
Daniel Lezcano09f77092007-12-13 05:34:58 -08001947void tcpv6_exit(void)
Daniel Lezcano7f4e4862007-12-11 02:25:35 -08001948{
Daniel Lezcano93ec9262008-03-07 11:16:02 -08001949 unregister_pernet_subsys(&tcpv6_net_ops);
Daniel Lezcano7f4e4862007-12-11 02:25:35 -08001950 inet6_unregister_protosw(&tcpv6_protosw);
1951 inet6_del_protocol(&tcpv6_protocol, IPPROTO_TCP);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001952}