tcp_ipv6.c 54.4 KB
Newer Older
Linus Torvalds's avatar
Linus Torvalds committed
1 2
/*
 *	TCP over IPv6
3
 *	Linux INET6 implementation
Linus Torvalds's avatar
Linus Torvalds committed
4 5
 *
 *	Authors:
6
 *	Pedro Roque		<roque@di.fc.ul.pt>
Linus Torvalds's avatar
Linus Torvalds committed
7
 *
8
 *	Based on:
Linus Torvalds's avatar
Linus Torvalds committed
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
 *	linux/net/ipv4/tcp.c
 *	linux/net/ipv4/tcp_input.c
 *	linux/net/ipv4/tcp_output.c
 *
 *	Fixes:
 *	Hideaki YOSHIFUJI	:	sin6_scope_id support
 *	YOSHIFUJI Hideaki @USAGI and:	Support IPV6_V6ONLY socket option, which
 *	Alexey Kuznetsov		allow both IPv4 and IPv6 sockets to bind
 *					a single port at the same time.
 *	YOSHIFUJI Hideaki @USAGI:	convert /proc/net/tcp6 to seq_file.
 *
 *	This program is free software; you can redistribute it and/or
 *      modify it under the terms of the GNU General Public License
 *      as published by the Free Software Foundation; either version
 *      2 of the License, or (at your option) any later version.
 */

Herbert Xu's avatar
Herbert Xu committed
26
#include <linux/bottom_half.h>
Linus Torvalds's avatar
Linus Torvalds committed
27 28 29 30 31 32 33 34 35 36 37 38 39 40
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/socket.h>
#include <linux/sockios.h>
#include <linux/net.h>
#include <linux/jiffies.h>
#include <linux/in.h>
#include <linux/in6.h>
#include <linux/netdevice.h>
#include <linux/init.h>
#include <linux/jhash.h>
#include <linux/ipsec.h>
#include <linux/times.h>
41
#include <linux/slab.h>
Linus Torvalds's avatar
Linus Torvalds committed
42 43 44 45 46 47 48

#include <linux/ipv6.h>
#include <linux/icmpv6.h>
#include <linux/random.h>

#include <net/tcp.h>
#include <net/ndisc.h>
49
#include <net/inet6_hashtables.h>
50
#include <net/inet6_connection_sock.h>
Linus Torvalds's avatar
Linus Torvalds committed
51 52 53 54 55 56 57 58 59 60
#include <net/ipv6.h>
#include <net/transp_v6.h>
#include <net/addrconf.h>
#include <net/ip6_route.h>
#include <net/ip6_checksum.h>
#include <net/inet_ecn.h>
#include <net/protocol.h>
#include <net/xfrm.h>
#include <net/snmp.h>
#include <net/dsfield.h>
61
#include <net/timewait_sock.h>
62
#include <net/netdma.h>
63
#include <net/inet_common.h>
64
#include <net/secure_seq.h>
Glauber Costa's avatar
Glauber Costa committed
65
#include <net/tcp_memcontrol.h>
Linus Torvalds's avatar
Linus Torvalds committed
66 67 68 69 70 71

#include <asm/uaccess.h>

#include <linux/proc_fs.h>
#include <linux/seq_file.h>

72 73 74 75
#include <linux/crypto.h>
#include <linux/scatterlist.h>

static void	tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb);
76 77
static void	tcp_v6_reqsk_send_ack(struct sock *sk, struct sk_buff *skb,
				      struct request_sock *req);
Linus Torvalds's avatar
Linus Torvalds committed
78 79

static int	tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb);
80
static void	__tcp_v6_send_check(struct sk_buff *skb,
81 82
				    const struct in6_addr *saddr,
				    const struct in6_addr *daddr);
Linus Torvalds's avatar
Linus Torvalds committed
83

84 85
static const struct inet_connection_sock_af_ops ipv6_mapped;
static const struct inet_connection_sock_af_ops ipv6_specific;
86
#ifdef CONFIG_TCP_MD5SIG
87 88
static const struct tcp_sock_af_ops tcp_sock_ipv6_specific;
static const struct tcp_sock_af_ops tcp_sock_ipv6_mapped_specific;
89 90
#else
static struct tcp_md5sig_key *tcp_v6_md5_do_lookup(struct sock *sk,
91
						   const struct in6_addr *addr)
92 93 94
{
	return NULL;
}
95
#endif
Linus Torvalds's avatar
Linus Torvalds committed
96 97 98 99

static void tcp_v6_hash(struct sock *sk)
{
	if (sk->sk_state != TCP_CLOSE) {
100
		if (inet_csk(sk)->icsk_af_ops == &ipv6_mapped) {
Linus Torvalds's avatar
Linus Torvalds committed
101 102 103 104
			tcp_prot.hash(sk);
			return;
		}
		local_bh_disable();
105
		__inet6_hash(sk, NULL);
Linus Torvalds's avatar
Linus Torvalds committed
106 107 108 109
		local_bh_enable();
	}
}

Herbert Xu's avatar
Herbert Xu committed
110
static __inline__ __sum16 tcp_v6_check(int len,
111 112
				   const struct in6_addr *saddr,
				   const struct in6_addr *daddr,
113
				   __wsum base)
Linus Torvalds's avatar
Linus Torvalds committed
114 115 116 117
{
	return csum_ipv6_magic(saddr, daddr, len, IPPROTO_TCP, base);
}

118
static __u32 tcp_v6_init_sequence(const struct sk_buff *skb)
Linus Torvalds's avatar
Linus Torvalds committed
119
{
120 121
	return secure_tcpv6_sequence_number(ipv6_hdr(skb)->daddr.s6_addr32,
					    ipv6_hdr(skb)->saddr.s6_addr32,
122 123
					    tcp_hdr(skb)->dest,
					    tcp_hdr(skb)->source);
Linus Torvalds's avatar
Linus Torvalds committed
124 125
}

126
static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
Linus Torvalds's avatar
Linus Torvalds committed
127 128 129
			  int addr_len)
{
	struct sockaddr_in6 *usin = (struct sockaddr_in6 *) uaddr;
130
	struct inet_sock *inet = inet_sk(sk);
131
	struct inet_connection_sock *icsk = inet_csk(sk);
Linus Torvalds's avatar
Linus Torvalds committed
132 133
	struct ipv6_pinfo *np = inet6_sk(sk);
	struct tcp_sock *tp = tcp_sk(sk);
134
	struct in6_addr *saddr = NULL, *final_p, final;
135
	struct rt6_info *rt;
136
	struct flowi6 fl6;
Linus Torvalds's avatar
Linus Torvalds committed
137 138 139 140
	struct dst_entry *dst;
	int addr_type;
	int err;

141
	if (addr_len < SIN6_LEN_RFC2133)
Linus Torvalds's avatar
Linus Torvalds committed
142 143
		return -EINVAL;

144
	if (usin->sin6_family != AF_INET6)
Eric Dumazet's avatar
Eric Dumazet committed
145
		return -EAFNOSUPPORT;
Linus Torvalds's avatar
Linus Torvalds committed
146

147
	memset(&fl6, 0, sizeof(fl6));
Linus Torvalds's avatar
Linus Torvalds committed
148 149

	if (np->sndflow) {
150 151 152
		fl6.flowlabel = usin->sin6_flowinfo&IPV6_FLOWINFO_MASK;
		IP6_ECN_flow_init(fl6.flowlabel);
		if (fl6.flowlabel&IPV6_FLOWLABEL_MASK) {
Linus Torvalds's avatar
Linus Torvalds committed
153
			struct ip6_flowlabel *flowlabel;
154
			flowlabel = fl6_sock_lookup(sk, fl6.flowlabel);
Linus Torvalds's avatar
Linus Torvalds committed
155 156
			if (flowlabel == NULL)
				return -EINVAL;
Alexey Dobriyan's avatar
Alexey Dobriyan committed
157
			usin->sin6_addr = flowlabel->dst;
Linus Torvalds's avatar
Linus Torvalds committed
158 159 160 161 162
			fl6_sock_release(flowlabel);
		}
	}

	/*
163 164 165 166 167
	 *	connect() to INADDR_ANY means loopback (BSD'ism).
	 */

	if(ipv6_addr_any(&usin->sin6_addr))
		usin->sin6_addr.s6_addr[15] = 0x1;
Linus Torvalds's avatar
Linus Torvalds committed
168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198

	addr_type = ipv6_addr_type(&usin->sin6_addr);

	if(addr_type & IPV6_ADDR_MULTICAST)
		return -ENETUNREACH;

	if (addr_type&IPV6_ADDR_LINKLOCAL) {
		if (addr_len >= sizeof(struct sockaddr_in6) &&
		    usin->sin6_scope_id) {
			/* If interface is set while binding, indices
			 * must coincide.
			 */
			if (sk->sk_bound_dev_if &&
			    sk->sk_bound_dev_if != usin->sin6_scope_id)
				return -EINVAL;

			sk->sk_bound_dev_if = usin->sin6_scope_id;
		}

		/* Connect to link-local address requires an interface */
		if (!sk->sk_bound_dev_if)
			return -EINVAL;
	}

	if (tp->rx_opt.ts_recent_stamp &&
	    !ipv6_addr_equal(&np->daddr, &usin->sin6_addr)) {
		tp->rx_opt.ts_recent = 0;
		tp->rx_opt.ts_recent_stamp = 0;
		tp->write_seq = 0;
	}

Alexey Dobriyan's avatar
Alexey Dobriyan committed
199
	np->daddr = usin->sin6_addr;
200
	np->flow_label = fl6.flowlabel;
Linus Torvalds's avatar
Linus Torvalds committed
201 202 203 204 205 206

	/*
	 *	TCP over IPv4
	 */

	if (addr_type == IPV6_ADDR_MAPPED) {
207
		u32 exthdrlen = icsk->icsk_ext_hdr_len;
Linus Torvalds's avatar
Linus Torvalds committed
208 209 210 211 212 213 214 215 216 217 218
		struct sockaddr_in sin;

		SOCK_DEBUG(sk, "connect: ipv4 mapped\n");

		if (__ipv6_only_sock(sk))
			return -ENETUNREACH;

		sin.sin_family = AF_INET;
		sin.sin_port = usin->sin6_port;
		sin.sin_addr.s_addr = usin->sin6_addr.s6_addr32[3];

219
		icsk->icsk_af_ops = &ipv6_mapped;
Linus Torvalds's avatar
Linus Torvalds committed
220
		sk->sk_backlog_rcv = tcp_v4_do_rcv;
221 222 223
#ifdef CONFIG_TCP_MD5SIG
		tp->af_specific = &tcp_sock_ipv6_mapped_specific;
#endif
Linus Torvalds's avatar
Linus Torvalds committed
224 225 226 227

		err = tcp_v4_connect(sk, (struct sockaddr *)&sin, sizeof(sin));

		if (err) {
228 229
			icsk->icsk_ext_hdr_len = exthdrlen;
			icsk->icsk_af_ops = &ipv6_specific;
Linus Torvalds's avatar
Linus Torvalds committed
230
			sk->sk_backlog_rcv = tcp_v6_do_rcv;
231 232 233
#ifdef CONFIG_TCP_MD5SIG
			tp->af_specific = &tcp_sock_ipv6_specific;
#endif
Linus Torvalds's avatar
Linus Torvalds committed
234 235
			goto failure;
		} else {
236 237 238
			ipv6_addr_set_v4mapped(inet->inet_saddr, &np->saddr);
			ipv6_addr_set_v4mapped(inet->inet_rcv_saddr,
					       &np->rcv_saddr);
Linus Torvalds's avatar
Linus Torvalds committed
239 240 241 242 243 244 245 246
		}

		return err;
	}

	if (!ipv6_addr_any(&np->rcv_saddr))
		saddr = &np->rcv_saddr;

247
	fl6.flowi6_proto = IPPROTO_TCP;
Alexey Dobriyan's avatar
Alexey Dobriyan committed
248 249
	fl6.daddr = np->daddr;
	fl6.saddr = saddr ? *saddr : np->saddr;
250 251
	fl6.flowi6_oif = sk->sk_bound_dev_if;
	fl6.flowi6_mark = sk->sk_mark;
252 253
	fl6.fl6_dport = usin->sin6_port;
	fl6.fl6_sport = inet->inet_sport;
Linus Torvalds's avatar
Linus Torvalds committed
254

255
	final_p = fl6_update_dst(&fl6, np->opt, &final);
Linus Torvalds's avatar
Linus Torvalds committed
256

257
	security_sk_classify_flow(sk, flowi6_to_flowi(&fl6));
258

259
	dst = ip6_dst_lookup_flow(sk, &fl6, final_p, true);
260 261
	if (IS_ERR(dst)) {
		err = PTR_ERR(dst);
Linus Torvalds's avatar
Linus Torvalds committed
262
		goto failure;
263
	}
Linus Torvalds's avatar
Linus Torvalds committed
264 265

	if (saddr == NULL) {
266
		saddr = &fl6.saddr;
Alexey Dobriyan's avatar
Alexey Dobriyan committed
267
		np->rcv_saddr = *saddr;
Linus Torvalds's avatar
Linus Torvalds committed
268 269 270
	}

	/* set the source address */
Alexey Dobriyan's avatar
Alexey Dobriyan committed
271
	np->saddr = *saddr;
272
	inet->inet_rcv_saddr = LOOPBACK4_IPV6;
Linus Torvalds's avatar
Linus Torvalds committed
273

274
	sk->sk_gso_type = SKB_GSO_TCPV6;
275
	__ip6_dst_store(sk, dst, NULL, NULL);
Linus Torvalds's avatar
Linus Torvalds committed
276

277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296
	rt = (struct rt6_info *) dst;
	if (tcp_death_row.sysctl_tw_recycle &&
	    !tp->rx_opt.ts_recent_stamp &&
	    ipv6_addr_equal(&rt->rt6i_dst.addr, &np->daddr)) {
		struct inet_peer *peer = rt6_get_peer(rt);
		/*
		 * VJ's idea. We save last timestamp seen from
		 * the destination in peer table, when entering state
		 * TIME-WAIT * and initialize rx_opt.ts_recent from it,
		 * when trying new connection.
		 */
		if (peer) {
			inet_peer_refcheck(peer);
			if ((u32)get_seconds() - peer->tcp_ts_stamp <= TCP_PAWS_MSL) {
				tp->rx_opt.ts_recent_stamp = peer->tcp_ts_stamp;
				tp->rx_opt.ts_recent = peer->tcp_ts;
			}
		}
	}

297
	icsk->icsk_ext_hdr_len = 0;
Linus Torvalds's avatar
Linus Torvalds committed
298
	if (np->opt)
299 300
		icsk->icsk_ext_hdr_len = (np->opt->opt_flen +
					  np->opt->opt_nflen);
Linus Torvalds's avatar
Linus Torvalds committed
301 302 303

	tp->rx_opt.mss_clamp = IPV6_MIN_MTU - sizeof(struct tcphdr) - sizeof(struct ipv6hdr);

304
	inet->inet_dport = usin->sin6_port;
Linus Torvalds's avatar
Linus Torvalds committed
305 306

	tcp_set_state(sk, TCP_SYN_SENT);
307
	err = inet6_hash_connect(&tcp_death_row, sk);
Linus Torvalds's avatar
Linus Torvalds committed
308 309 310 311 312 313
	if (err)
		goto late_failure;

	if (!tp->write_seq)
		tp->write_seq = secure_tcpv6_sequence_number(np->saddr.s6_addr32,
							     np->daddr.s6_addr32,
314 315
							     inet->inet_sport,
							     inet->inet_dport);
Linus Torvalds's avatar
Linus Torvalds committed
316 317 318 319 320 321 322 323 324 325 326

	err = tcp_connect(sk);
	if (err)
		goto late_failure;

	return 0;

late_failure:
	tcp_set_state(sk, TCP_CLOSE);
	__sk_dst_reset(sk);
failure:
327
	inet->inet_dport = 0;
Linus Torvalds's avatar
Linus Torvalds committed
328 329 330 331 332
	sk->sk_route_caps = 0;
	return err;
}

static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
333
		u8 type, u8 code, int offset, __be32 info)
Linus Torvalds's avatar
Linus Torvalds committed
334
{
335
	const struct ipv6hdr *hdr = (const struct ipv6hdr*)skb->data;
336
	const struct tcphdr *th = (struct tcphdr *)(skb->data+offset);
Linus Torvalds's avatar
Linus Torvalds committed
337 338 339
	struct ipv6_pinfo *np;
	struct sock *sk;
	int err;
340
	struct tcp_sock *tp;
Linus Torvalds's avatar
Linus Torvalds committed
341
	__u32 seq;
342
	struct net *net = dev_net(skb->dev);
Linus Torvalds's avatar
Linus Torvalds committed
343

344
	sk = inet6_lookup(net, &tcp_hashinfo, &hdr->daddr,
345
			th->dest, &hdr->saddr, th->source, skb->dev->ifindex);
Linus Torvalds's avatar
Linus Torvalds committed
346 347

	if (sk == NULL) {
348 349
		ICMP6_INC_STATS_BH(net, __in6_dev_get(skb->dev),
				   ICMP6_MIB_INERRORS);
Linus Torvalds's avatar
Linus Torvalds committed
350 351 352 353
		return;
	}

	if (sk->sk_state == TCP_TIME_WAIT) {
354
		inet_twsk_put(inet_twsk(sk));
Linus Torvalds's avatar
Linus Torvalds committed
355 356 357 358 359
		return;
	}

	bh_lock_sock(sk);
	if (sock_owned_by_user(sk))
360
		NET_INC_STATS_BH(net, LINUX_MIB_LOCKDROPPEDICMPS);
Linus Torvalds's avatar
Linus Torvalds committed
361 362 363 364

	if (sk->sk_state == TCP_CLOSE)
		goto out;

365 366 367 368 369
	if (ipv6_hdr(skb)->hop_limit < inet6_sk(sk)->min_hopcount) {
		NET_INC_STATS_BH(net, LINUX_MIB_TCPMINTTLDROP);
		goto out;
	}

Linus Torvalds's avatar
Linus Torvalds committed
370
	tp = tcp_sk(sk);
371
	seq = ntohl(th->seq);
Linus Torvalds's avatar
Linus Torvalds committed
372 373
	if (sk->sk_state != TCP_LISTEN &&
	    !between(seq, tp->snd_una, tp->snd_nxt)) {
374
		NET_INC_STATS_BH(net, LINUX_MIB_OUTOFWINDOWICMPS);
Linus Torvalds's avatar
Linus Torvalds committed
375 376 377 378 379 380
		goto out;
	}

	np = inet6_sk(sk);

	if (type == ICMPV6_PKT_TOOBIG) {
381
		struct dst_entry *dst;
Linus Torvalds's avatar
Linus Torvalds committed
382 383 384 385 386 387 388 389 390 391 392

		if (sock_owned_by_user(sk))
			goto out;
		if ((1 << sk->sk_state) & (TCPF_LISTEN | TCPF_CLOSE))
			goto out;

		/* icmp should have updated the destination cache entry */
		dst = __sk_dst_check(sk, np->dst_cookie);

		if (dst == NULL) {
			struct inet_sock *inet = inet_sk(sk);
393
			struct flowi6 fl6;
Linus Torvalds's avatar
Linus Torvalds committed
394 395 396 397 398

			/* BUGGG_FUTURE: Again, it is not clear how
			   to handle rthdr case. Ignore this complexity
			   for now.
			 */
399 400
			memset(&fl6, 0, sizeof(fl6));
			fl6.flowi6_proto = IPPROTO_TCP;
Alexey Dobriyan's avatar
Alexey Dobriyan committed
401 402
			fl6.daddr = np->daddr;
			fl6.saddr = np->saddr;
403 404
			fl6.flowi6_oif = sk->sk_bound_dev_if;
			fl6.flowi6_mark = sk->sk_mark;
405 406
			fl6.fl6_dport = inet->inet_dport;
			fl6.fl6_sport = inet->inet_sport;
407 408 409
			security_skb_classify_flow(skb, flowi6_to_flowi(&fl6));

			dst = ip6_dst_lookup_flow(sk, &fl6, NULL, false);
410 411
			if (IS_ERR(dst)) {
				sk->sk_err_soft = -PTR_ERR(dst);
Linus Torvalds's avatar
Linus Torvalds committed
412 413 414 415 416 417
				goto out;
			}

		} else
			dst_hold(dst);

418
		if (inet_csk(sk)->icsk_pmtu_cookie > dst_mtu(dst)) {
Linus Torvalds's avatar
Linus Torvalds committed
419 420 421 422 423 424 425 426 427
			tcp_sync_mss(sk, dst_mtu(dst));
			tcp_simple_retransmit(sk);
		} /* else let the usual retransmit timer handle it */
		dst_release(dst);
		goto out;
	}

	icmpv6_err_convert(type, code, &err);

428
	/* Might be for an request_sock */
Linus Torvalds's avatar
Linus Torvalds committed
429
	switch (sk->sk_state) {
430
		struct request_sock *req, **prev;
Linus Torvalds's avatar
Linus Torvalds committed
431 432 433 434
	case TCP_LISTEN:
		if (sock_owned_by_user(sk))
			goto out;

435 436
		req = inet6_csk_search_req(sk, &prev, th->dest, &hdr->daddr,
					   &hdr->saddr, inet6_iif(skb));
Linus Torvalds's avatar
Linus Torvalds committed
437 438 439 440 441 442
		if (!req)
			goto out;

		/* ICMPs are not backlogged, hence we cannot get
		 * an established socket here.
		 */
443
		WARN_ON(req->sk != NULL);
Linus Torvalds's avatar
Linus Torvalds committed
444

445
		if (seq != tcp_rsk(req)->snt_isn) {
446
			NET_INC_STATS_BH(net, LINUX_MIB_OUTOFWINDOWICMPS);
Linus Torvalds's avatar
Linus Torvalds committed
447 448 449
			goto out;
		}

450
		inet_csk_reqsk_queue_drop(sk, req, prev);
Linus Torvalds's avatar
Linus Torvalds committed
451 452 453 454
		goto out;

	case TCP_SYN_SENT:
	case TCP_SYN_RECV:  /* Cannot happen.
455
			       It can, it SYNs are crossed. --ANK */
Linus Torvalds's avatar
Linus Torvalds committed
456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477
		if (!sock_owned_by_user(sk)) {
			sk->sk_err = err;
			sk->sk_error_report(sk);		/* Wake people up to see the error (see connect in sock.c) */

			tcp_done(sk);
		} else
			sk->sk_err_soft = err;
		goto out;
	}

	if (!sock_owned_by_user(sk) && np->recverr) {
		sk->sk_err = err;
		sk->sk_error_report(sk);
	} else
		sk->sk_err_soft = err;

out:
	bh_unlock_sock(sk);
	sock_put(sk);
}


478
static int tcp_v6_send_synack(struct sock *sk, struct request_sock *req,
479 480
			      struct request_values *rvp,
			      u16 queue_mapping)
Linus Torvalds's avatar
Linus Torvalds committed
481
{
482
	struct inet6_request_sock *treq = inet6_rsk(req);
Linus Torvalds's avatar
Linus Torvalds committed
483 484 485
	struct ipv6_pinfo *np = inet6_sk(sk);
	struct sk_buff * skb;
	struct ipv6_txoptions *opt = NULL;
486
	struct in6_addr * final_p, final;
487
	struct flowi6 fl6;
488
	struct dst_entry *dst;
489
	int err;
Linus Torvalds's avatar
Linus Torvalds committed
490

491 492
	memset(&fl6, 0, sizeof(fl6));
	fl6.flowi6_proto = IPPROTO_TCP;
Alexey Dobriyan's avatar
Alexey Dobriyan committed
493 494
	fl6.daddr = treq->rmt_addr;
	fl6.saddr = treq->loc_addr;
495 496 497
	fl6.flowlabel = 0;
	fl6.flowi6_oif = treq->iif;
	fl6.flowi6_mark = sk->sk_mark;
498 499
	fl6.fl6_dport = inet_rsk(req)->rmt_port;
	fl6.fl6_sport = inet_rsk(req)->loc_port;
500
	security_req_classify_flow(req, flowi6_to_flowi(&fl6));
Linus Torvalds's avatar
Linus Torvalds committed
501

502
	opt = np->opt;
503
	final_p = fl6_update_dst(&fl6, opt, &final);
Linus Torvalds's avatar
Linus Torvalds committed
504

505
	dst = ip6_dst_lookup_flow(sk, &fl6, final_p, false);
506 507
	if (IS_ERR(dst)) {
		err = PTR_ERR(dst);
508
		dst = NULL;
509
		goto done;
510
	}
511
	skb = tcp_make_synack(sk, dst, req, rvp);
512
	err = -ENOMEM;
Linus Torvalds's avatar
Linus Torvalds committed
513
	if (skb) {
514
		__tcp_v6_send_check(skb, &treq->loc_addr, &treq->rmt_addr);
Linus Torvalds's avatar
Linus Torvalds committed
515

Alexey Dobriyan's avatar
Alexey Dobriyan committed
516
		fl6.daddr = treq->rmt_addr;
517
		skb_set_queue_mapping(skb, queue_mapping);
518
		err = ip6_xmit(sk, skb, &fl6, opt, np->tclass);
519
		err = net_xmit_eval(err);
Linus Torvalds's avatar
Linus Torvalds committed
520 521 522
	}

done:
523
	if (opt && opt != np->opt)
Linus Torvalds's avatar
Linus Torvalds committed
524
		sock_kfree_s(sk, opt, opt->tot_len);
525
	dst_release(dst);
Linus Torvalds's avatar
Linus Torvalds committed
526 527 528
	return err;
}

529 530 531 532
static int tcp_v6_rtx_synack(struct sock *sk, struct request_sock *req,
			     struct request_values *rvp)
{
	TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_RETRANSSEGS);
533
	return tcp_v6_send_synack(sk, req, rvp, 0);
534 535
}

536
static void tcp_v6_reqsk_destructor(struct request_sock *req)
Linus Torvalds's avatar
Linus Torvalds committed
537
{
538
	kfree_skb(inet6_rsk(req)->pktopts);
Linus Torvalds's avatar
Linus Torvalds committed
539 540
}

541 542
#ifdef CONFIG_TCP_MD5SIG
static struct tcp_md5sig_key *tcp_v6_md5_do_lookup(struct sock *sk,
543
						   const struct in6_addr *addr)
544
{
Eric Dumazet's avatar
Eric Dumazet committed
545
	return tcp_md5_do_lookup(sk, (union tcp_md5_addr *)addr, AF_INET6);
546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575
}

static struct tcp_md5sig_key *tcp_v6_md5_lookup(struct sock *sk,
						struct sock *addr_sk)
{
	return tcp_v6_md5_do_lookup(sk, &inet6_sk(addr_sk)->daddr);
}

static struct tcp_md5sig_key *tcp_v6_reqsk_md5_lookup(struct sock *sk,
						      struct request_sock *req)
{
	return tcp_v6_md5_do_lookup(sk, &inet6_rsk(req)->rmt_addr);
}

static int tcp_v6_parse_md5_keys (struct sock *sk, char __user *optval,
				  int optlen)
{
	struct tcp_md5sig cmd;
	struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&cmd.tcpm_addr;

	if (optlen < sizeof(cmd))
		return -EINVAL;

	if (copy_from_user(&cmd, optval, sizeof(cmd)))
		return -EFAULT;

	if (sin6->sin6_family != AF_INET6)
		return -EINVAL;

	if (!cmd.tcpm_keylen) {
576
		if (ipv6_addr_v4mapped(&sin6->sin6_addr))
Eric Dumazet's avatar
Eric Dumazet committed
577 578 579 580
			return tcp_md5_do_del(sk, (union tcp_md5_addr *)&sin6->sin6_addr.s6_addr32[3],
					      AF_INET);
		return tcp_md5_do_del(sk, (union tcp_md5_addr *)&sin6->sin6_addr,
				      AF_INET6);
581 582 583 584 585
	}

	if (cmd.tcpm_keylen > TCP_MD5SIG_MAXKEYLEN)
		return -EINVAL;

Eric Dumazet's avatar
Eric Dumazet committed
586 587 588
	if (ipv6_addr_v4mapped(&sin6->sin6_addr))
		return tcp_md5_do_add(sk, (union tcp_md5_addr *)&sin6->sin6_addr.s6_addr32[3],
				      AF_INET, cmd.tcpm_key, cmd.tcpm_keylen, GFP_KERNEL);
589

Eric Dumazet's avatar
Eric Dumazet committed
590 591
	return tcp_md5_do_add(sk, (union tcp_md5_addr *)&sin6->sin6_addr,
			      AF_INET6, cmd.tcpm_key, cmd.tcpm_keylen, GFP_KERNEL);
592 593
}

594
static int tcp_v6_md5_hash_pseudoheader(struct tcp_md5sig_pool *hp,
595 596
					const struct in6_addr *daddr,
					const struct in6_addr *saddr, int nbytes)
597 598
{
	struct tcp6_pseudohdr *bp;
599
	struct scatterlist sg;
600

601 602
	bp = &hp->md5_blk.ip6;
	/* 1. TCP pseudo-header (RFC2460) */
Alexey Dobriyan's avatar
Alexey Dobriyan committed
603 604
	bp->saddr = *saddr;
	bp->daddr = *daddr;
605
	bp->protocol = cpu_to_be32(IPPROTO_TCP);
Adam Langley's avatar
Adam Langley committed
606
	bp->len = cpu_to_be32(nbytes);
607

608 609 610
	sg_init_one(&sg, bp, sizeof(*bp));
	return crypto_hash_update(&hp->md5_desc, &sg, sizeof(*bp));
}
611

612
static int tcp_v6_md5_hash_hdr(char *md5_hash, struct tcp_md5sig_key *key,
613
			       const struct in6_addr *daddr, struct in6_addr *saddr,
614
			       const struct tcphdr *th)
615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632
{
	struct tcp_md5sig_pool *hp;
	struct hash_desc *desc;

	hp = tcp_get_md5sig_pool();
	if (!hp)
		goto clear_hash_noput;
	desc = &hp->md5_desc;

	if (crypto_hash_init(desc))
		goto clear_hash;
	if (tcp_v6_md5_hash_pseudoheader(hp, daddr, saddr, th->doff << 2))
		goto clear_hash;
	if (tcp_md5_hash_header(hp, th))
		goto clear_hash;
	if (tcp_md5_hash_key(hp, key))
		goto clear_hash;
	if (crypto_hash_final(desc, md5_hash))
633 634 635 636
		goto clear_hash;

	tcp_put_md5sig_pool();
	return 0;
637

638 639 640 641
clear_hash:
	tcp_put_md5sig_pool();
clear_hash_noput:
	memset(md5_hash, 0, 16);
642
	return 1;
643 644
}

645
static int tcp_v6_md5_hash_skb(char *md5_hash, struct tcp_md5sig_key *key,
646 647 648
			       const struct sock *sk,
			       const struct request_sock *req,
			       const struct sk_buff *skb)
649
{
650
	const struct in6_addr *saddr, *daddr;
651 652
	struct tcp_md5sig_pool *hp;
	struct hash_desc *desc;
653
	const struct tcphdr *th = tcp_hdr(skb);
654 655 656 657

	if (sk) {
		saddr = &inet6_sk(sk)->saddr;
		daddr = &inet6_sk(sk)->daddr;
658
	} else if (req) {
659 660
		saddr = &inet6_rsk(req)->loc_addr;
		daddr = &inet6_rsk(req)->rmt_addr;
661
	} else {
662
		const struct ipv6hdr *ip6h = ipv6_hdr(skb);
663 664
		saddr = &ip6h->saddr;
		daddr = &ip6h->daddr;
665
	}
666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693

	hp = tcp_get_md5sig_pool();
	if (!hp)
		goto clear_hash_noput;
	desc = &hp->md5_desc;

	if (crypto_hash_init(desc))
		goto clear_hash;

	if (tcp_v6_md5_hash_pseudoheader(hp, daddr, saddr, skb->len))
		goto clear_hash;
	if (tcp_md5_hash_header(hp, th))
		goto clear_hash;
	if (tcp_md5_hash_skb_data(hp, skb, th->doff << 2))
		goto clear_hash;
	if (tcp_md5_hash_key(hp, key))
		goto clear_hash;
	if (crypto_hash_final(desc, md5_hash))
		goto clear_hash;

	tcp_put_md5sig_pool();
	return 0;

clear_hash:
	tcp_put_md5sig_pool();
clear_hash_noput:
	memset(md5_hash, 0, 16);
	return 1;
694 695
}

696
static int tcp_v6_inbound_md5_hash(struct sock *sk, const struct sk_buff *skb)
697
{
698
	const __u8 *hash_location = NULL;
699
	struct tcp_md5sig_key *hash_expected;
700
	const struct ipv6hdr *ip6h = ipv6_hdr(skb);
701
	const struct tcphdr *th = tcp_hdr(skb);
702 703 704 705
	int genhash;
	u8 newhash[16];

	hash_expected = tcp_v6_md5_do_lookup(sk, &ip6h->saddr);
706
	hash_location = tcp_parse_md5sig_option(th);
707

708 709 710 711 712 713
	/* We've parsed the options - do we have a hash? */
	if (!hash_expected && !hash_location)
		return 0;

	if (hash_expected && !hash_location) {
		NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPMD5NOTFOUND);
714 715 716
		return 1;
	}

717 718
	if (!hash_expected && hash_location) {
		NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPMD5UNEXPECTED);
719 720 721 722
		return 1;
	}

	/* check the signature */
723 724 725 726
	genhash = tcp_v6_md5_hash_skb(newhash,
				      hash_expected,
				      NULL, NULL, skb);

727
	if (genhash || memcmp(hash_location, newhash, 16) != 0) {
728 729 730 731
		net_info_ratelimited("MD5 Hash %s for [%pI6c]:%u->[%pI6c]:%u\n",
				     genhash ? "failed" : "mismatch",
				     &ip6h->saddr, ntohs(th->source),
				     &ip6h->daddr, ntohs(th->dest));
732 733 734 735 736 737
		return 1;
	}
	return 0;
}
#endif

738
struct request_sock_ops tcp6_request_sock_ops __read_mostly = {
Linus Torvalds's avatar
Linus Torvalds committed
739
	.family		=	AF_INET6,
740
	.obj_size	=	sizeof(struct tcp6_request_sock),
741
	.rtx_syn_ack	=	tcp_v6_rtx_synack,
742 743
	.send_ack	=	tcp_v6_reqsk_send_ack,
	.destructor	=	tcp_v6_reqsk_destructor,
744 745
	.send_reset	=	tcp_v6_send_reset,
	.syn_ack_timeout = 	tcp_syn_ack_timeout,
Linus Torvalds's avatar
Linus Torvalds committed
746 747
};

748
#ifdef CONFIG_TCP_MD5SIG
749
static const struct tcp_request_sock_ops tcp_request_sock_ipv6_ops = {
750
	.md5_lookup	=	tcp_v6_reqsk_md5_lookup,
751
	.calc_md5_hash	=	tcp_v6_md5_hash_skb,
752
};
753
#endif
754

755
static void __tcp_v6_send_check(struct sk_buff *skb,
756
				const struct in6_addr *saddr, const struct in6_addr *daddr)
Linus Torvalds's avatar
Linus Torvalds committed
757
{
758
	struct tcphdr *th = tcp_hdr(skb);
Linus Torvalds's avatar
Linus Torvalds committed
759

760
	if (skb->ip_summed == CHECKSUM_PARTIAL) {
761
		th->check = ~tcp_v6_check(skb->len, saddr, daddr, 0);
762
		skb->csum_start = skb_transport_header(skb) - skb->head;
Al Viro's avatar
Al Viro committed
763
		skb->csum_offset = offsetof(struct tcphdr, check);
Linus Torvalds's avatar
Linus Torvalds committed
764
	} else {
765 766 767
		th->check = tcp_v6_check(skb->len, saddr, daddr,
					 csum_partial(th, th->doff << 2,
						      skb->csum));
Linus Torvalds's avatar
Linus Torvalds committed
768 769 770
	}
}

771
static void tcp_v6_send_check(struct sock *sk, struct sk_buff *skb)
772 773 774 775 776 777
{
	struct ipv6_pinfo *np = inet6_sk(sk);

	__tcp_v6_send_check(skb, &np->saddr, &np->daddr);
}

778 779
static int tcp_v6_gso_send_check(struct sk_buff *skb)
{
780
	const struct ipv6hdr *ipv6h;
781 782 783 784 785
	struct tcphdr *th;

	if (!pskb_may_pull(skb, sizeof(*th)))
		return -EINVAL;

786
	ipv6h = ipv6_hdr(skb);
787
	th = tcp_hdr(skb);
788 789

	th->check = 0;
790
	skb->ip_summed = CHECKSUM_PARTIAL;
791
	__tcp_v6_send_check(skb, &ipv6h->saddr, &ipv6h->daddr);
792 793
	return 0;
}
Linus Torvalds's avatar
Linus Torvalds committed
794

Herbert Xu's avatar
Herbert Xu committed
795 796
static struct sk_buff **tcp6_gro_receive(struct sk_buff **head,
					 struct sk_buff *skb)
Herbert Xu's avatar
Herbert Xu committed
797
{
798
	const struct ipv6hdr *iph = skb_gro_network_header(skb);
Herbert Xu's avatar
Herbert Xu committed
799 800 801

	switch (skb->ip_summed) {
	case CHECKSUM_COMPLETE:
802
		if (!tcp_v6_check(skb_gro_len(skb), &iph->saddr, &iph->daddr,
Herbert Xu's avatar
Herbert Xu committed
803 804 805 806 807 808 809 810 811 812 813 814 815 816
				  skb->csum)) {
			skb->ip_summed = CHECKSUM_UNNECESSARY;
			break;
		}

		/* fall through */
	case CHECKSUM_NONE:
		NAPI_GRO_CB(skb)->flush = 1;
		return NULL;
	}

	return tcp_gro_receive(head, skb);
}

Herbert Xu's avatar
Herbert Xu committed
817
static int tcp6_gro_complete(struct sk_buff *skb)
Herbert Xu's avatar
Herbert Xu committed
818
{
819
	const struct ipv6hdr *iph = ipv6_hdr(skb);
Herbert Xu's avatar
Herbert Xu committed
820 821 822 823 824 825 826 827 828
	struct tcphdr *th = tcp_hdr(skb);

	th->check = ~tcp_v6_check(skb->len - skb_transport_offset(skb),
				  &iph->saddr, &iph->daddr, 0);
	skb_shinfo(skb)->gso_type = SKB_GSO_TCPV6;

	return tcp_gro_complete(skb);
}

829
static void tcp_v6_send_response(struct sk_buff *skb, u32 seq, u32 ack, u32 win,
830
				 u32 ts, struct tcp_md5sig_key *key, int rst, u8 tclass)
Linus Torvalds's avatar
Linus Torvalds committed
831
{
832 833
	const struct tcphdr *th = tcp_hdr(skb);
	struct tcphdr *t1;
Linus Torvalds's avatar
Linus Torvalds committed
834
	struct sk_buff *buff;
835
	struct flowi6 fl6;
Eric Dumazet's avatar
Eric Dumazet committed
836
	struct net *net = dev_net(skb_dst(skb)->dev);
837
	struct sock *ctl_sk = net->ipv6.tcp_sk;
838
	unsigned int tot_len = sizeof(struct tcphdr);
Eric Dumazet's avatar
Eric Dumazet committed
839
	struct dst_entry *dst;
840
	__be32 *topt;
Linus Torvalds's avatar
Linus Torvalds committed
841

842 843
	if (ts)
		tot_len += TCPOLEN_TSTAMP_ALIGNED;
844 845 846 847 848 849
#ifdef CONFIG_TCP_MD5SIG
	if (key)
		tot_len += TCPOLEN_MD5SIG_ALIGNED;
#endif

	buff = alloc_skb(MAX_HEADER + sizeof(struct ipv6hdr) + tot_len,
Linus Torvalds's avatar
Linus Torvalds committed
850
			 GFP_ATOMIC);
851 852
	if (buff == NULL)
		return;
Linus Torvalds's avatar
Linus Torvalds committed
853

854
	skb_reserve(buff, MAX_HEADER + sizeof(struct ipv6hdr) + tot_len);
Linus Torvalds's avatar
Linus Torvalds committed
855

856
	t1 = (struct tcphdr *) skb_push(buff, tot_len);
857
	skb_reset_transport_header(buff);
Linus Torvalds's avatar
Linus Torvalds committed
858 859 860 861 862

	/* Swap the send and the receive. */
	memset(t1, 0, sizeof(*t1));
	t1->dest = th->source;
	t1->source = th->dest;
863
	t1->doff = tot_len / 4;
864 865 866 867 868
	t1->seq = htonl(seq);
	t1->ack_seq = htonl(ack);
	t1->ack = !rst || !th->ack;
	t1->rst = rst;
	t1->window = htons(win);
Linus Torvalds's avatar
Linus Torvalds committed
869

870 871
	topt = (__be32 *)(t1 + 1);

872 873 874 875 876 877 878
	if (ts) {
		*topt++ = htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) |
				(TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP);
		*topt++ = htonl(tcp_time_stamp);
		*topt++ = htonl(ts);
	}

879 880
#ifdef CONFIG_TCP_MD5SIG
	if (key) {
881 882 883
		*topt++ = htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) |
				(TCPOPT_MD5SIG << 8) | TCPOLEN_MD5SIG);
		tcp_v6_md5_hash_hdr((__u8 *)topt, key,
884 885
				    &ipv6_hdr(skb)->saddr,
				    &ipv6_hdr(skb)->daddr, t1);
886 887 888
	}
#endif

889
	memset(&fl6, 0, sizeof(fl6));
Alexey Dobriyan's avatar
Alexey Dobriyan committed
890 891
	fl6.daddr = ipv6_hdr(skb)->saddr;
	fl6.saddr = ipv6_hdr(skb)->daddr;
Linus Torvalds's avatar
Linus Torvalds committed
892

893 894 895
	buff->ip_summed = CHECKSUM_PARTIAL;
	buff->csum = 0;

896
	__tcp_v6_send_check(buff, &fl6.saddr, &fl6.daddr);
Linus Torvalds's avatar
Linus Torvalds committed
897

898 899
	fl6.flowi6_proto = IPPROTO_TCP;
	fl6.flowi6_oif = inet6_iif(skb);
900 901
	fl6.fl6_dport = t1->dest;
	fl6.fl6_sport = t1->source;
902
	security_skb_classify_flow(skb, flowi6_to_flowi(&fl6));
Linus Torvalds's avatar
Linus Torvalds committed
903

904 905 906 907
	/* Pass a socket to ip6_dst_lookup either it is for RST
	 * Underlying function will use this to retrieve the network
	 * namespace
	 */
908
	dst = ip6_dst_lookup_flow(ctl_sk, &fl6, NULL, false);
909 910
	if (!IS_ERR(dst)) {
		skb_dst_set(buff, dst);
911
		ip6_xmit(ctl_sk, buff, &fl6, NULL, tclass);
912 913 914 915
		TCP_INC_STATS_BH(net, TCP_MIB_OUTSEGS);
		if (rst)
			TCP_INC_STATS_BH(net, TCP_MIB_OUTRSTS);
		return;
Linus Torvalds's avatar
Linus Torvalds committed
916 917 918 919 920
	}

	kfree_skb(buff);
}

921
static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb)
Linus Torvalds's avatar
Linus Torvalds committed
922
{
923
	const struct tcphdr *th = tcp_hdr(skb);
924
	u32 seq = 0, ack_seq = 0;
925
	struct tcp_md5sig_key *key = NULL;
926 927 928 929 930 931 932
#ifdef CONFIG_TCP_MD5SIG
	const __u8 *hash_location = NULL;
	struct ipv6hdr *ipv6h = ipv6_hdr(skb);
	unsigned char newhash[16];
	int genhash;
	struct sock *sk1 = NULL;
#endif
Linus Torvalds's avatar
Linus Torvalds committed
933

934
	if (th->rst)
Linus Torvalds's avatar
Linus Torvalds committed
935 936
		return;

937 938
	if (!ipv6_unicast_destination(skb))
		return;
Linus Torvalds's avatar
Linus Torvalds committed
939

940
#ifdef CONFIG_TCP_MD5SIG