162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
262306a36Sopenharmony_ci/* SCTP kernel implementation
362306a36Sopenharmony_ci * Copyright (c) 1999-2000 Cisco, Inc.
462306a36Sopenharmony_ci * Copyright (c) 1999-2001 Motorola, Inc.
562306a36Sopenharmony_ci * Copyright (c) 2001-2003 International Business Machines, Corp.
662306a36Sopenharmony_ci * Copyright (c) 2001 Intel Corp.
762306a36Sopenharmony_ci * Copyright (c) 2001 Nokia, Inc.
862306a36Sopenharmony_ci * Copyright (c) 2001 La Monte H.P. Yarroll
962306a36Sopenharmony_ci *
1062306a36Sopenharmony_ci * This file is part of the SCTP kernel implementation
1162306a36Sopenharmony_ci *
1262306a36Sopenharmony_ci * These functions handle all input from the IP layer into SCTP.
1362306a36Sopenharmony_ci *
1462306a36Sopenharmony_ci * Please send any bug reports or fixes you make to the
1562306a36Sopenharmony_ci * email address(es):
1662306a36Sopenharmony_ci *    lksctp developers <linux-sctp@vger.kernel.org>
1762306a36Sopenharmony_ci *
1862306a36Sopenharmony_ci * Written or modified by:
1962306a36Sopenharmony_ci *    La Monte H.P. Yarroll <piggy@acm.org>
2062306a36Sopenharmony_ci *    Karl Knutson <karl@athena.chicago.il.us>
2162306a36Sopenharmony_ci *    Xingang Guo <xingang.guo@intel.com>
2262306a36Sopenharmony_ci *    Jon Grimm <jgrimm@us.ibm.com>
2362306a36Sopenharmony_ci *    Hui Huang <hui.huang@nokia.com>
2462306a36Sopenharmony_ci *    Daisy Chang <daisyc@us.ibm.com>
2562306a36Sopenharmony_ci *    Sridhar Samudrala <sri@us.ibm.com>
2662306a36Sopenharmony_ci *    Ardelle Fan <ardelle.fan@intel.com>
2762306a36Sopenharmony_ci */
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_ci#include <linux/types.h>
3062306a36Sopenharmony_ci#include <linux/list.h> /* For struct list_head */
3162306a36Sopenharmony_ci#include <linux/socket.h>
3262306a36Sopenharmony_ci#include <linux/ip.h>
3362306a36Sopenharmony_ci#include <linux/time.h> /* For struct timeval */
3462306a36Sopenharmony_ci#include <linux/slab.h>
3562306a36Sopenharmony_ci#include <net/ip.h>
3662306a36Sopenharmony_ci#include <net/icmp.h>
3762306a36Sopenharmony_ci#include <net/snmp.h>
3862306a36Sopenharmony_ci#include <net/sock.h>
3962306a36Sopenharmony_ci#include <net/xfrm.h>
4062306a36Sopenharmony_ci#include <net/sctp/sctp.h>
4162306a36Sopenharmony_ci#include <net/sctp/sm.h>
4262306a36Sopenharmony_ci#include <net/sctp/checksum.h>
4362306a36Sopenharmony_ci#include <net/net_namespace.h>
4462306a36Sopenharmony_ci#include <linux/rhashtable.h>
4562306a36Sopenharmony_ci#include <net/sock_reuseport.h>
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_ci/* Forward declarations for internal helpers. */
4862306a36Sopenharmony_cistatic int sctp_rcv_ootb(struct sk_buff *);
4962306a36Sopenharmony_cistatic struct sctp_association *__sctp_rcv_lookup(struct net *net,
5062306a36Sopenharmony_ci				      struct sk_buff *skb,
5162306a36Sopenharmony_ci				      const union sctp_addr *paddr,
5262306a36Sopenharmony_ci				      const union sctp_addr *laddr,
5362306a36Sopenharmony_ci				      struct sctp_transport **transportp,
5462306a36Sopenharmony_ci				      int dif, int sdif);
5562306a36Sopenharmony_cistatic struct sctp_endpoint *__sctp_rcv_lookup_endpoint(
5662306a36Sopenharmony_ci					struct net *net, struct sk_buff *skb,
5762306a36Sopenharmony_ci					const union sctp_addr *laddr,
5862306a36Sopenharmony_ci					const union sctp_addr *daddr,
5962306a36Sopenharmony_ci					int dif, int sdif);
6062306a36Sopenharmony_cistatic struct sctp_association *__sctp_lookup_association(
6162306a36Sopenharmony_ci					struct net *net,
6262306a36Sopenharmony_ci					const union sctp_addr *local,
6362306a36Sopenharmony_ci					const union sctp_addr *peer,
6462306a36Sopenharmony_ci					struct sctp_transport **pt,
6562306a36Sopenharmony_ci					int dif, int sdif);
6662306a36Sopenharmony_ci
6762306a36Sopenharmony_cistatic int sctp_add_backlog(struct sock *sk, struct sk_buff *skb);
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_ci/* Calculate the SCTP checksum of an SCTP packet.  */
7162306a36Sopenharmony_cistatic inline int sctp_rcv_checksum(struct net *net, struct sk_buff *skb)
7262306a36Sopenharmony_ci{
7362306a36Sopenharmony_ci	struct sctphdr *sh = sctp_hdr(skb);
7462306a36Sopenharmony_ci	__le32 cmp = sh->checksum;
7562306a36Sopenharmony_ci	__le32 val = sctp_compute_cksum(skb, 0);
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_ci	if (val != cmp) {
7862306a36Sopenharmony_ci		/* CRC failure, dump it. */
7962306a36Sopenharmony_ci		__SCTP_INC_STATS(net, SCTP_MIB_CHECKSUMERRORS);
8062306a36Sopenharmony_ci		return -1;
8162306a36Sopenharmony_ci	}
8262306a36Sopenharmony_ci	return 0;
8362306a36Sopenharmony_ci}
8462306a36Sopenharmony_ci
8562306a36Sopenharmony_ci/*
8662306a36Sopenharmony_ci * This is the routine which IP calls when receiving an SCTP packet.
8762306a36Sopenharmony_ci */
8862306a36Sopenharmony_ciint sctp_rcv(struct sk_buff *skb)
8962306a36Sopenharmony_ci{
9062306a36Sopenharmony_ci	struct sock *sk;
9162306a36Sopenharmony_ci	struct sctp_association *asoc;
9262306a36Sopenharmony_ci	struct sctp_endpoint *ep = NULL;
9362306a36Sopenharmony_ci	struct sctp_ep_common *rcvr;
9462306a36Sopenharmony_ci	struct sctp_transport *transport = NULL;
9562306a36Sopenharmony_ci	struct sctp_chunk *chunk;
9662306a36Sopenharmony_ci	union sctp_addr src;
9762306a36Sopenharmony_ci	union sctp_addr dest;
9862306a36Sopenharmony_ci	int family;
9962306a36Sopenharmony_ci	struct sctp_af *af;
10062306a36Sopenharmony_ci	struct net *net = dev_net(skb->dev);
10162306a36Sopenharmony_ci	bool is_gso = skb_is_gso(skb) && skb_is_gso_sctp(skb);
10262306a36Sopenharmony_ci	int dif, sdif;
10362306a36Sopenharmony_ci
10462306a36Sopenharmony_ci	if (skb->pkt_type != PACKET_HOST)
10562306a36Sopenharmony_ci		goto discard_it;
10662306a36Sopenharmony_ci
10762306a36Sopenharmony_ci	__SCTP_INC_STATS(net, SCTP_MIB_INSCTPPACKS);
10862306a36Sopenharmony_ci
10962306a36Sopenharmony_ci	/* If packet is too small to contain a single chunk, let's not
11062306a36Sopenharmony_ci	 * waste time on it anymore.
11162306a36Sopenharmony_ci	 */
11262306a36Sopenharmony_ci	if (skb->len < sizeof(struct sctphdr) + sizeof(struct sctp_chunkhdr) +
11362306a36Sopenharmony_ci		       skb_transport_offset(skb))
11462306a36Sopenharmony_ci		goto discard_it;
11562306a36Sopenharmony_ci
11662306a36Sopenharmony_ci	/* If the packet is fragmented and we need to do crc checking,
11762306a36Sopenharmony_ci	 * it's better to just linearize it otherwise crc computing
11862306a36Sopenharmony_ci	 * takes longer.
11962306a36Sopenharmony_ci	 */
12062306a36Sopenharmony_ci	if ((!is_gso && skb_linearize(skb)) ||
12162306a36Sopenharmony_ci	    !pskb_may_pull(skb, sizeof(struct sctphdr)))
12262306a36Sopenharmony_ci		goto discard_it;
12362306a36Sopenharmony_ci
12462306a36Sopenharmony_ci	/* Pull up the IP header. */
12562306a36Sopenharmony_ci	__skb_pull(skb, skb_transport_offset(skb));
12662306a36Sopenharmony_ci
12762306a36Sopenharmony_ci	skb->csum_valid = 0; /* Previous value not applicable */
12862306a36Sopenharmony_ci	if (skb_csum_unnecessary(skb))
12962306a36Sopenharmony_ci		__skb_decr_checksum_unnecessary(skb);
13062306a36Sopenharmony_ci	else if (!sctp_checksum_disable &&
13162306a36Sopenharmony_ci		 !is_gso &&
13262306a36Sopenharmony_ci		 sctp_rcv_checksum(net, skb) < 0)
13362306a36Sopenharmony_ci		goto discard_it;
13462306a36Sopenharmony_ci	skb->csum_valid = 1;
13562306a36Sopenharmony_ci
13662306a36Sopenharmony_ci	__skb_pull(skb, sizeof(struct sctphdr));
13762306a36Sopenharmony_ci
13862306a36Sopenharmony_ci	family = ipver2af(ip_hdr(skb)->version);
13962306a36Sopenharmony_ci	af = sctp_get_af_specific(family);
14062306a36Sopenharmony_ci	if (unlikely(!af))
14162306a36Sopenharmony_ci		goto discard_it;
14262306a36Sopenharmony_ci	SCTP_INPUT_CB(skb)->af = af;
14362306a36Sopenharmony_ci
14462306a36Sopenharmony_ci	/* Initialize local addresses for lookups. */
14562306a36Sopenharmony_ci	af->from_skb(&src, skb, 1);
14662306a36Sopenharmony_ci	af->from_skb(&dest, skb, 0);
14762306a36Sopenharmony_ci	dif = af->skb_iif(skb);
14862306a36Sopenharmony_ci	sdif = af->skb_sdif(skb);
14962306a36Sopenharmony_ci
15062306a36Sopenharmony_ci	/* If the packet is to or from a non-unicast address,
15162306a36Sopenharmony_ci	 * silently discard the packet.
15262306a36Sopenharmony_ci	 *
15362306a36Sopenharmony_ci	 * This is not clearly defined in the RFC except in section
15462306a36Sopenharmony_ci	 * 8.4 - OOTB handling.  However, based on the book "Stream Control
15562306a36Sopenharmony_ci	 * Transmission Protocol" 2.1, "It is important to note that the
15662306a36Sopenharmony_ci	 * IP address of an SCTP transport address must be a routable
15762306a36Sopenharmony_ci	 * unicast address.  In other words, IP multicast addresses and
15862306a36Sopenharmony_ci	 * IP broadcast addresses cannot be used in an SCTP transport
15962306a36Sopenharmony_ci	 * address."
16062306a36Sopenharmony_ci	 */
16162306a36Sopenharmony_ci	if (!af->addr_valid(&src, NULL, skb) ||
16262306a36Sopenharmony_ci	    !af->addr_valid(&dest, NULL, skb))
16362306a36Sopenharmony_ci		goto discard_it;
16462306a36Sopenharmony_ci
16562306a36Sopenharmony_ci	asoc = __sctp_rcv_lookup(net, skb, &src, &dest, &transport, dif, sdif);
16662306a36Sopenharmony_ci
16762306a36Sopenharmony_ci	if (!asoc)
16862306a36Sopenharmony_ci		ep = __sctp_rcv_lookup_endpoint(net, skb, &dest, &src, dif, sdif);
16962306a36Sopenharmony_ci
17062306a36Sopenharmony_ci	/* Retrieve the common input handling substructure. */
17162306a36Sopenharmony_ci	rcvr = asoc ? &asoc->base : &ep->base;
17262306a36Sopenharmony_ci	sk = rcvr->sk;
17362306a36Sopenharmony_ci
17462306a36Sopenharmony_ci	/*
17562306a36Sopenharmony_ci	 * RFC 2960, 8.4 - Handle "Out of the blue" Packets.
17662306a36Sopenharmony_ci	 * An SCTP packet is called an "out of the blue" (OOTB)
17762306a36Sopenharmony_ci	 * packet if it is correctly formed, i.e., passed the
17862306a36Sopenharmony_ci	 * receiver's checksum check, but the receiver is not
17962306a36Sopenharmony_ci	 * able to identify the association to which this
18062306a36Sopenharmony_ci	 * packet belongs.
18162306a36Sopenharmony_ci	 */
18262306a36Sopenharmony_ci	if (!asoc) {
18362306a36Sopenharmony_ci		if (sctp_rcv_ootb(skb)) {
18462306a36Sopenharmony_ci			__SCTP_INC_STATS(net, SCTP_MIB_OUTOFBLUES);
18562306a36Sopenharmony_ci			goto discard_release;
18662306a36Sopenharmony_ci		}
18762306a36Sopenharmony_ci	}
18862306a36Sopenharmony_ci
18962306a36Sopenharmony_ci	if (!xfrm_policy_check(sk, XFRM_POLICY_IN, skb, family))
19062306a36Sopenharmony_ci		goto discard_release;
19162306a36Sopenharmony_ci	nf_reset_ct(skb);
19262306a36Sopenharmony_ci
19362306a36Sopenharmony_ci	if (sk_filter(sk, skb))
19462306a36Sopenharmony_ci		goto discard_release;
19562306a36Sopenharmony_ci
19662306a36Sopenharmony_ci	/* Create an SCTP packet structure. */
19762306a36Sopenharmony_ci	chunk = sctp_chunkify(skb, asoc, sk, GFP_ATOMIC);
19862306a36Sopenharmony_ci	if (!chunk)
19962306a36Sopenharmony_ci		goto discard_release;
20062306a36Sopenharmony_ci	SCTP_INPUT_CB(skb)->chunk = chunk;
20162306a36Sopenharmony_ci
20262306a36Sopenharmony_ci	/* Remember what endpoint is to handle this packet. */
20362306a36Sopenharmony_ci	chunk->rcvr = rcvr;
20462306a36Sopenharmony_ci
20562306a36Sopenharmony_ci	/* Remember the SCTP header. */
20662306a36Sopenharmony_ci	chunk->sctp_hdr = sctp_hdr(skb);
20762306a36Sopenharmony_ci
20862306a36Sopenharmony_ci	/* Set the source and destination addresses of the incoming chunk.  */
20962306a36Sopenharmony_ci	sctp_init_addrs(chunk, &src, &dest);
21062306a36Sopenharmony_ci
21162306a36Sopenharmony_ci	/* Remember where we came from.  */
21262306a36Sopenharmony_ci	chunk->transport = transport;
21362306a36Sopenharmony_ci
21462306a36Sopenharmony_ci	/* Acquire access to the sock lock. Note: We are safe from other
21562306a36Sopenharmony_ci	 * bottom halves on this lock, but a user may be in the lock too,
21662306a36Sopenharmony_ci	 * so check if it is busy.
21762306a36Sopenharmony_ci	 */
21862306a36Sopenharmony_ci	bh_lock_sock(sk);
21962306a36Sopenharmony_ci
22062306a36Sopenharmony_ci	if (sk != rcvr->sk) {
22162306a36Sopenharmony_ci		/* Our cached sk is different from the rcvr->sk.  This is
22262306a36Sopenharmony_ci		 * because migrate()/accept() may have moved the association
22362306a36Sopenharmony_ci		 * to a new socket and released all the sockets.  So now we
22462306a36Sopenharmony_ci		 * are holding a lock on the old socket while the user may
22562306a36Sopenharmony_ci		 * be doing something with the new socket.  Switch our veiw
22662306a36Sopenharmony_ci		 * of the current sk.
22762306a36Sopenharmony_ci		 */
22862306a36Sopenharmony_ci		bh_unlock_sock(sk);
22962306a36Sopenharmony_ci		sk = rcvr->sk;
23062306a36Sopenharmony_ci		bh_lock_sock(sk);
23162306a36Sopenharmony_ci	}
23262306a36Sopenharmony_ci
23362306a36Sopenharmony_ci	if (sock_owned_by_user(sk) || !sctp_newsk_ready(sk)) {
23462306a36Sopenharmony_ci		if (sctp_add_backlog(sk, skb)) {
23562306a36Sopenharmony_ci			bh_unlock_sock(sk);
23662306a36Sopenharmony_ci			sctp_chunk_free(chunk);
23762306a36Sopenharmony_ci			skb = NULL; /* sctp_chunk_free already freed the skb */
23862306a36Sopenharmony_ci			goto discard_release;
23962306a36Sopenharmony_ci		}
24062306a36Sopenharmony_ci		__SCTP_INC_STATS(net, SCTP_MIB_IN_PKT_BACKLOG);
24162306a36Sopenharmony_ci	} else {
24262306a36Sopenharmony_ci		__SCTP_INC_STATS(net, SCTP_MIB_IN_PKT_SOFTIRQ);
24362306a36Sopenharmony_ci		sctp_inq_push(&chunk->rcvr->inqueue, chunk);
24462306a36Sopenharmony_ci	}
24562306a36Sopenharmony_ci
24662306a36Sopenharmony_ci	bh_unlock_sock(sk);
24762306a36Sopenharmony_ci
24862306a36Sopenharmony_ci	/* Release the asoc/ep ref we took in the lookup calls. */
24962306a36Sopenharmony_ci	if (transport)
25062306a36Sopenharmony_ci		sctp_transport_put(transport);
25162306a36Sopenharmony_ci	else
25262306a36Sopenharmony_ci		sctp_endpoint_put(ep);
25362306a36Sopenharmony_ci
25462306a36Sopenharmony_ci	return 0;
25562306a36Sopenharmony_ci
25662306a36Sopenharmony_cidiscard_it:
25762306a36Sopenharmony_ci	__SCTP_INC_STATS(net, SCTP_MIB_IN_PKT_DISCARDS);
25862306a36Sopenharmony_ci	kfree_skb(skb);
25962306a36Sopenharmony_ci	return 0;
26062306a36Sopenharmony_ci
26162306a36Sopenharmony_cidiscard_release:
26262306a36Sopenharmony_ci	/* Release the asoc/ep ref we took in the lookup calls. */
26362306a36Sopenharmony_ci	if (transport)
26462306a36Sopenharmony_ci		sctp_transport_put(transport);
26562306a36Sopenharmony_ci	else
26662306a36Sopenharmony_ci		sctp_endpoint_put(ep);
26762306a36Sopenharmony_ci
26862306a36Sopenharmony_ci	goto discard_it;
26962306a36Sopenharmony_ci}
27062306a36Sopenharmony_ci
27162306a36Sopenharmony_ci/* Process the backlog queue of the socket.  Every skb on
27262306a36Sopenharmony_ci * the backlog holds a ref on an association or endpoint.
27362306a36Sopenharmony_ci * We hold this ref throughout the state machine to make
27462306a36Sopenharmony_ci * sure that the structure we need is still around.
27562306a36Sopenharmony_ci */
27662306a36Sopenharmony_ciint sctp_backlog_rcv(struct sock *sk, struct sk_buff *skb)
27762306a36Sopenharmony_ci{
27862306a36Sopenharmony_ci	struct sctp_chunk *chunk = SCTP_INPUT_CB(skb)->chunk;
27962306a36Sopenharmony_ci	struct sctp_inq *inqueue = &chunk->rcvr->inqueue;
28062306a36Sopenharmony_ci	struct sctp_transport *t = chunk->transport;
28162306a36Sopenharmony_ci	struct sctp_ep_common *rcvr = NULL;
28262306a36Sopenharmony_ci	int backloged = 0;
28362306a36Sopenharmony_ci
28462306a36Sopenharmony_ci	rcvr = chunk->rcvr;
28562306a36Sopenharmony_ci
28662306a36Sopenharmony_ci	/* If the rcvr is dead then the association or endpoint
28762306a36Sopenharmony_ci	 * has been deleted and we can safely drop the chunk
28862306a36Sopenharmony_ci	 * and refs that we are holding.
28962306a36Sopenharmony_ci	 */
29062306a36Sopenharmony_ci	if (rcvr->dead) {
29162306a36Sopenharmony_ci		sctp_chunk_free(chunk);
29262306a36Sopenharmony_ci		goto done;
29362306a36Sopenharmony_ci	}
29462306a36Sopenharmony_ci
29562306a36Sopenharmony_ci	if (unlikely(rcvr->sk != sk)) {
29662306a36Sopenharmony_ci		/* In this case, the association moved from one socket to
29762306a36Sopenharmony_ci		 * another.  We are currently sitting on the backlog of the
29862306a36Sopenharmony_ci		 * old socket, so we need to move.
29962306a36Sopenharmony_ci		 * However, since we are here in the process context we
30062306a36Sopenharmony_ci		 * need to take make sure that the user doesn't own
30162306a36Sopenharmony_ci		 * the new socket when we process the packet.
30262306a36Sopenharmony_ci		 * If the new socket is user-owned, queue the chunk to the
30362306a36Sopenharmony_ci		 * backlog of the new socket without dropping any refs.
30462306a36Sopenharmony_ci		 * Otherwise, we can safely push the chunk on the inqueue.
30562306a36Sopenharmony_ci		 */
30662306a36Sopenharmony_ci
30762306a36Sopenharmony_ci		sk = rcvr->sk;
30862306a36Sopenharmony_ci		local_bh_disable();
30962306a36Sopenharmony_ci		bh_lock_sock(sk);
31062306a36Sopenharmony_ci
31162306a36Sopenharmony_ci		if (sock_owned_by_user(sk) || !sctp_newsk_ready(sk)) {
31262306a36Sopenharmony_ci			if (sk_add_backlog(sk, skb, READ_ONCE(sk->sk_rcvbuf)))
31362306a36Sopenharmony_ci				sctp_chunk_free(chunk);
31462306a36Sopenharmony_ci			else
31562306a36Sopenharmony_ci				backloged = 1;
31662306a36Sopenharmony_ci		} else
31762306a36Sopenharmony_ci			sctp_inq_push(inqueue, chunk);
31862306a36Sopenharmony_ci
31962306a36Sopenharmony_ci		bh_unlock_sock(sk);
32062306a36Sopenharmony_ci		local_bh_enable();
32162306a36Sopenharmony_ci
32262306a36Sopenharmony_ci		/* If the chunk was backloged again, don't drop refs */
32362306a36Sopenharmony_ci		if (backloged)
32462306a36Sopenharmony_ci			return 0;
32562306a36Sopenharmony_ci	} else {
32662306a36Sopenharmony_ci		if (!sctp_newsk_ready(sk)) {
32762306a36Sopenharmony_ci			if (!sk_add_backlog(sk, skb, READ_ONCE(sk->sk_rcvbuf)))
32862306a36Sopenharmony_ci				return 0;
32962306a36Sopenharmony_ci			sctp_chunk_free(chunk);
33062306a36Sopenharmony_ci		} else {
33162306a36Sopenharmony_ci			sctp_inq_push(inqueue, chunk);
33262306a36Sopenharmony_ci		}
33362306a36Sopenharmony_ci	}
33462306a36Sopenharmony_ci
33562306a36Sopenharmony_cidone:
33662306a36Sopenharmony_ci	/* Release the refs we took in sctp_add_backlog */
33762306a36Sopenharmony_ci	if (SCTP_EP_TYPE_ASSOCIATION == rcvr->type)
33862306a36Sopenharmony_ci		sctp_transport_put(t);
33962306a36Sopenharmony_ci	else if (SCTP_EP_TYPE_SOCKET == rcvr->type)
34062306a36Sopenharmony_ci		sctp_endpoint_put(sctp_ep(rcvr));
34162306a36Sopenharmony_ci	else
34262306a36Sopenharmony_ci		BUG();
34362306a36Sopenharmony_ci
34462306a36Sopenharmony_ci	return 0;
34562306a36Sopenharmony_ci}
34662306a36Sopenharmony_ci
34762306a36Sopenharmony_cistatic int sctp_add_backlog(struct sock *sk, struct sk_buff *skb)
34862306a36Sopenharmony_ci{
34962306a36Sopenharmony_ci	struct sctp_chunk *chunk = SCTP_INPUT_CB(skb)->chunk;
35062306a36Sopenharmony_ci	struct sctp_transport *t = chunk->transport;
35162306a36Sopenharmony_ci	struct sctp_ep_common *rcvr = chunk->rcvr;
35262306a36Sopenharmony_ci	int ret;
35362306a36Sopenharmony_ci
35462306a36Sopenharmony_ci	ret = sk_add_backlog(sk, skb, READ_ONCE(sk->sk_rcvbuf));
35562306a36Sopenharmony_ci	if (!ret) {
35662306a36Sopenharmony_ci		/* Hold the assoc/ep while hanging on the backlog queue.
35762306a36Sopenharmony_ci		 * This way, we know structures we need will not disappear
35862306a36Sopenharmony_ci		 * from us
35962306a36Sopenharmony_ci		 */
36062306a36Sopenharmony_ci		if (SCTP_EP_TYPE_ASSOCIATION == rcvr->type)
36162306a36Sopenharmony_ci			sctp_transport_hold(t);
36262306a36Sopenharmony_ci		else if (SCTP_EP_TYPE_SOCKET == rcvr->type)
36362306a36Sopenharmony_ci			sctp_endpoint_hold(sctp_ep(rcvr));
36462306a36Sopenharmony_ci		else
36562306a36Sopenharmony_ci			BUG();
36662306a36Sopenharmony_ci	}
36762306a36Sopenharmony_ci	return ret;
36862306a36Sopenharmony_ci
36962306a36Sopenharmony_ci}
37062306a36Sopenharmony_ci
37162306a36Sopenharmony_ci/* Handle icmp frag needed error. */
37262306a36Sopenharmony_civoid sctp_icmp_frag_needed(struct sock *sk, struct sctp_association *asoc,
37362306a36Sopenharmony_ci			   struct sctp_transport *t, __u32 pmtu)
37462306a36Sopenharmony_ci{
37562306a36Sopenharmony_ci	if (!t ||
37662306a36Sopenharmony_ci	    (t->pathmtu <= pmtu &&
37762306a36Sopenharmony_ci	     t->pl.probe_size + sctp_transport_pl_hlen(t) <= pmtu))
37862306a36Sopenharmony_ci		return;
37962306a36Sopenharmony_ci
38062306a36Sopenharmony_ci	if (sock_owned_by_user(sk)) {
38162306a36Sopenharmony_ci		atomic_set(&t->mtu_info, pmtu);
38262306a36Sopenharmony_ci		asoc->pmtu_pending = 1;
38362306a36Sopenharmony_ci		t->pmtu_pending = 1;
38462306a36Sopenharmony_ci		return;
38562306a36Sopenharmony_ci	}
38662306a36Sopenharmony_ci
38762306a36Sopenharmony_ci	if (!(t->param_flags & SPP_PMTUD_ENABLE))
38862306a36Sopenharmony_ci		/* We can't allow retransmitting in such case, as the
38962306a36Sopenharmony_ci		 * retransmission would be sized just as before, and thus we
39062306a36Sopenharmony_ci		 * would get another icmp, and retransmit again.
39162306a36Sopenharmony_ci		 */
39262306a36Sopenharmony_ci		return;
39362306a36Sopenharmony_ci
39462306a36Sopenharmony_ci	/* Update transports view of the MTU. Return if no update was needed.
39562306a36Sopenharmony_ci	 * If an update wasn't needed/possible, it also doesn't make sense to
39662306a36Sopenharmony_ci	 * try to retransmit now.
39762306a36Sopenharmony_ci	 */
39862306a36Sopenharmony_ci	if (!sctp_transport_update_pmtu(t, pmtu))
39962306a36Sopenharmony_ci		return;
40062306a36Sopenharmony_ci
40162306a36Sopenharmony_ci	/* Update association pmtu. */
40262306a36Sopenharmony_ci	sctp_assoc_sync_pmtu(asoc);
40362306a36Sopenharmony_ci
40462306a36Sopenharmony_ci	/* Retransmit with the new pmtu setting. */
40562306a36Sopenharmony_ci	sctp_retransmit(&asoc->outqueue, t, SCTP_RTXR_PMTUD);
40662306a36Sopenharmony_ci}
40762306a36Sopenharmony_ci
40862306a36Sopenharmony_civoid sctp_icmp_redirect(struct sock *sk, struct sctp_transport *t,
40962306a36Sopenharmony_ci			struct sk_buff *skb)
41062306a36Sopenharmony_ci{
41162306a36Sopenharmony_ci	struct dst_entry *dst;
41262306a36Sopenharmony_ci
41362306a36Sopenharmony_ci	if (sock_owned_by_user(sk) || !t)
41462306a36Sopenharmony_ci		return;
41562306a36Sopenharmony_ci	dst = sctp_transport_dst_check(t);
41662306a36Sopenharmony_ci	if (dst)
41762306a36Sopenharmony_ci		dst->ops->redirect(dst, sk, skb);
41862306a36Sopenharmony_ci}
41962306a36Sopenharmony_ci
42062306a36Sopenharmony_ci/*
42162306a36Sopenharmony_ci * SCTP Implementer's Guide, 2.37 ICMP handling procedures
42262306a36Sopenharmony_ci *
42362306a36Sopenharmony_ci * ICMP8) If the ICMP code is a "Unrecognized next header type encountered"
42462306a36Sopenharmony_ci *        or a "Protocol Unreachable" treat this message as an abort
42562306a36Sopenharmony_ci *        with the T bit set.
42662306a36Sopenharmony_ci *
42762306a36Sopenharmony_ci * This function sends an event to the state machine, which will abort the
42862306a36Sopenharmony_ci * association.
42962306a36Sopenharmony_ci *
43062306a36Sopenharmony_ci */
43162306a36Sopenharmony_civoid sctp_icmp_proto_unreachable(struct sock *sk,
43262306a36Sopenharmony_ci			   struct sctp_association *asoc,
43362306a36Sopenharmony_ci			   struct sctp_transport *t)
43462306a36Sopenharmony_ci{
43562306a36Sopenharmony_ci	if (sock_owned_by_user(sk)) {
43662306a36Sopenharmony_ci		if (timer_pending(&t->proto_unreach_timer))
43762306a36Sopenharmony_ci			return;
43862306a36Sopenharmony_ci		else {
43962306a36Sopenharmony_ci			if (!mod_timer(&t->proto_unreach_timer,
44062306a36Sopenharmony_ci						jiffies + (HZ/20)))
44162306a36Sopenharmony_ci				sctp_transport_hold(t);
44262306a36Sopenharmony_ci		}
44362306a36Sopenharmony_ci	} else {
44462306a36Sopenharmony_ci		struct net *net = sock_net(sk);
44562306a36Sopenharmony_ci
44662306a36Sopenharmony_ci		pr_debug("%s: unrecognized next header type "
44762306a36Sopenharmony_ci			 "encountered!\n", __func__);
44862306a36Sopenharmony_ci
44962306a36Sopenharmony_ci		if (del_timer(&t->proto_unreach_timer))
45062306a36Sopenharmony_ci			sctp_transport_put(t);
45162306a36Sopenharmony_ci
45262306a36Sopenharmony_ci		sctp_do_sm(net, SCTP_EVENT_T_OTHER,
45362306a36Sopenharmony_ci			   SCTP_ST_OTHER(SCTP_EVENT_ICMP_PROTO_UNREACH),
45462306a36Sopenharmony_ci			   asoc->state, asoc->ep, asoc, t,
45562306a36Sopenharmony_ci			   GFP_ATOMIC);
45662306a36Sopenharmony_ci	}
45762306a36Sopenharmony_ci}
45862306a36Sopenharmony_ci
45962306a36Sopenharmony_ci/* Common lookup code for icmp/icmpv6 error handler. */
46062306a36Sopenharmony_cistruct sock *sctp_err_lookup(struct net *net, int family, struct sk_buff *skb,
46162306a36Sopenharmony_ci			     struct sctphdr *sctphdr,
46262306a36Sopenharmony_ci			     struct sctp_association **app,
46362306a36Sopenharmony_ci			     struct sctp_transport **tpp)
46462306a36Sopenharmony_ci{
46562306a36Sopenharmony_ci	struct sctp_init_chunk *chunkhdr, _chunkhdr;
46662306a36Sopenharmony_ci	union sctp_addr saddr;
46762306a36Sopenharmony_ci	union sctp_addr daddr;
46862306a36Sopenharmony_ci	struct sctp_af *af;
46962306a36Sopenharmony_ci	struct sock *sk = NULL;
47062306a36Sopenharmony_ci	struct sctp_association *asoc;
47162306a36Sopenharmony_ci	struct sctp_transport *transport = NULL;
47262306a36Sopenharmony_ci	__u32 vtag = ntohl(sctphdr->vtag);
47362306a36Sopenharmony_ci	int sdif = inet_sdif(skb);
47462306a36Sopenharmony_ci	int dif = inet_iif(skb);
47562306a36Sopenharmony_ci
47662306a36Sopenharmony_ci	*app = NULL; *tpp = NULL;
47762306a36Sopenharmony_ci
47862306a36Sopenharmony_ci	af = sctp_get_af_specific(family);
47962306a36Sopenharmony_ci	if (unlikely(!af)) {
48062306a36Sopenharmony_ci		return NULL;
48162306a36Sopenharmony_ci	}
48262306a36Sopenharmony_ci
48362306a36Sopenharmony_ci	/* Initialize local addresses for lookups. */
48462306a36Sopenharmony_ci	af->from_skb(&saddr, skb, 1);
48562306a36Sopenharmony_ci	af->from_skb(&daddr, skb, 0);
48662306a36Sopenharmony_ci
48762306a36Sopenharmony_ci	/* Look for an association that matches the incoming ICMP error
48862306a36Sopenharmony_ci	 * packet.
48962306a36Sopenharmony_ci	 */
49062306a36Sopenharmony_ci	asoc = __sctp_lookup_association(net, &saddr, &daddr, &transport, dif, sdif);
49162306a36Sopenharmony_ci	if (!asoc)
49262306a36Sopenharmony_ci		return NULL;
49362306a36Sopenharmony_ci
49462306a36Sopenharmony_ci	sk = asoc->base.sk;
49562306a36Sopenharmony_ci
49662306a36Sopenharmony_ci	/* RFC 4960, Appendix C. ICMP Handling
49762306a36Sopenharmony_ci	 *
49862306a36Sopenharmony_ci	 * ICMP6) An implementation MUST validate that the Verification Tag
49962306a36Sopenharmony_ci	 * contained in the ICMP message matches the Verification Tag of
50062306a36Sopenharmony_ci	 * the peer.  If the Verification Tag is not 0 and does NOT
50162306a36Sopenharmony_ci	 * match, discard the ICMP message.  If it is 0 and the ICMP
50262306a36Sopenharmony_ci	 * message contains enough bytes to verify that the chunk type is
50362306a36Sopenharmony_ci	 * an INIT chunk and that the Initiate Tag matches the tag of the
50462306a36Sopenharmony_ci	 * peer, continue with ICMP7.  If the ICMP message is too short
50562306a36Sopenharmony_ci	 * or the chunk type or the Initiate Tag does not match, silently
50662306a36Sopenharmony_ci	 * discard the packet.
50762306a36Sopenharmony_ci	 */
50862306a36Sopenharmony_ci	if (vtag == 0) {
50962306a36Sopenharmony_ci		/* chunk header + first 4 octects of init header */
51062306a36Sopenharmony_ci		chunkhdr = skb_header_pointer(skb, skb_transport_offset(skb) +
51162306a36Sopenharmony_ci					      sizeof(struct sctphdr),
51262306a36Sopenharmony_ci					      sizeof(struct sctp_chunkhdr) +
51362306a36Sopenharmony_ci					      sizeof(__be32), &_chunkhdr);
51462306a36Sopenharmony_ci		if (!chunkhdr ||
51562306a36Sopenharmony_ci		    chunkhdr->chunk_hdr.type != SCTP_CID_INIT ||
51662306a36Sopenharmony_ci		    ntohl(chunkhdr->init_hdr.init_tag) != asoc->c.my_vtag)
51762306a36Sopenharmony_ci			goto out;
51862306a36Sopenharmony_ci
51962306a36Sopenharmony_ci	} else if (vtag != asoc->c.peer_vtag) {
52062306a36Sopenharmony_ci		goto out;
52162306a36Sopenharmony_ci	}
52262306a36Sopenharmony_ci
52362306a36Sopenharmony_ci	bh_lock_sock(sk);
52462306a36Sopenharmony_ci
52562306a36Sopenharmony_ci	/* If too many ICMPs get dropped on busy
52662306a36Sopenharmony_ci	 * servers this needs to be solved differently.
52762306a36Sopenharmony_ci	 */
52862306a36Sopenharmony_ci	if (sock_owned_by_user(sk))
52962306a36Sopenharmony_ci		__NET_INC_STATS(net, LINUX_MIB_LOCKDROPPEDICMPS);
53062306a36Sopenharmony_ci
53162306a36Sopenharmony_ci	*app = asoc;
53262306a36Sopenharmony_ci	*tpp = transport;
53362306a36Sopenharmony_ci	return sk;
53462306a36Sopenharmony_ci
53562306a36Sopenharmony_ciout:
53662306a36Sopenharmony_ci	sctp_transport_put(transport);
53762306a36Sopenharmony_ci	return NULL;
53862306a36Sopenharmony_ci}
53962306a36Sopenharmony_ci
54062306a36Sopenharmony_ci/* Common cleanup code for icmp/icmpv6 error handler. */
54162306a36Sopenharmony_civoid sctp_err_finish(struct sock *sk, struct sctp_transport *t)
54262306a36Sopenharmony_ci	__releases(&((__sk)->sk_lock.slock))
54362306a36Sopenharmony_ci{
54462306a36Sopenharmony_ci	bh_unlock_sock(sk);
54562306a36Sopenharmony_ci	sctp_transport_put(t);
54662306a36Sopenharmony_ci}
54762306a36Sopenharmony_ci
54862306a36Sopenharmony_cistatic void sctp_v4_err_handle(struct sctp_transport *t, struct sk_buff *skb,
54962306a36Sopenharmony_ci			       __u8 type, __u8 code, __u32 info)
55062306a36Sopenharmony_ci{
55162306a36Sopenharmony_ci	struct sctp_association *asoc = t->asoc;
55262306a36Sopenharmony_ci	struct sock *sk = asoc->base.sk;
55362306a36Sopenharmony_ci	int err = 0;
55462306a36Sopenharmony_ci
55562306a36Sopenharmony_ci	switch (type) {
55662306a36Sopenharmony_ci	case ICMP_PARAMETERPROB:
55762306a36Sopenharmony_ci		err = EPROTO;
55862306a36Sopenharmony_ci		break;
55962306a36Sopenharmony_ci	case ICMP_DEST_UNREACH:
56062306a36Sopenharmony_ci		if (code > NR_ICMP_UNREACH)
56162306a36Sopenharmony_ci			return;
56262306a36Sopenharmony_ci		if (code == ICMP_FRAG_NEEDED) {
56362306a36Sopenharmony_ci			sctp_icmp_frag_needed(sk, asoc, t, SCTP_TRUNC4(info));
56462306a36Sopenharmony_ci			return;
56562306a36Sopenharmony_ci		}
56662306a36Sopenharmony_ci		if (code == ICMP_PROT_UNREACH) {
56762306a36Sopenharmony_ci			sctp_icmp_proto_unreachable(sk, asoc, t);
56862306a36Sopenharmony_ci			return;
56962306a36Sopenharmony_ci		}
57062306a36Sopenharmony_ci		err = icmp_err_convert[code].errno;
57162306a36Sopenharmony_ci		break;
57262306a36Sopenharmony_ci	case ICMP_TIME_EXCEEDED:
57362306a36Sopenharmony_ci		if (code == ICMP_EXC_FRAGTIME)
57462306a36Sopenharmony_ci			return;
57562306a36Sopenharmony_ci
57662306a36Sopenharmony_ci		err = EHOSTUNREACH;
57762306a36Sopenharmony_ci		break;
57862306a36Sopenharmony_ci	case ICMP_REDIRECT:
57962306a36Sopenharmony_ci		sctp_icmp_redirect(sk, t, skb);
58062306a36Sopenharmony_ci		return;
58162306a36Sopenharmony_ci	default:
58262306a36Sopenharmony_ci		return;
58362306a36Sopenharmony_ci	}
58462306a36Sopenharmony_ci	if (!sock_owned_by_user(sk) && inet_test_bit(RECVERR, sk)) {
58562306a36Sopenharmony_ci		sk->sk_err = err;
58662306a36Sopenharmony_ci		sk_error_report(sk);
58762306a36Sopenharmony_ci	} else {  /* Only an error on timeout */
58862306a36Sopenharmony_ci		WRITE_ONCE(sk->sk_err_soft, err);
58962306a36Sopenharmony_ci	}
59062306a36Sopenharmony_ci}
59162306a36Sopenharmony_ci
59262306a36Sopenharmony_ci/*
59362306a36Sopenharmony_ci * This routine is called by the ICMP module when it gets some
59462306a36Sopenharmony_ci * sort of error condition.  If err < 0 then the socket should
59562306a36Sopenharmony_ci * be closed and the error returned to the user.  If err > 0
59662306a36Sopenharmony_ci * it's just the icmp type << 8 | icmp code.  After adjustment
59762306a36Sopenharmony_ci * header points to the first 8 bytes of the sctp header.  We need
59862306a36Sopenharmony_ci * to find the appropriate port.
59962306a36Sopenharmony_ci *
60062306a36Sopenharmony_ci * The locking strategy used here is very "optimistic". When
60162306a36Sopenharmony_ci * someone else accesses the socket the ICMP is just dropped
60262306a36Sopenharmony_ci * and for some paths there is no check at all.
60362306a36Sopenharmony_ci * A more general error queue to queue errors for later handling
60462306a36Sopenharmony_ci * is probably better.
60562306a36Sopenharmony_ci *
60662306a36Sopenharmony_ci */
60762306a36Sopenharmony_ciint sctp_v4_err(struct sk_buff *skb, __u32 info)
60862306a36Sopenharmony_ci{
60962306a36Sopenharmony_ci	const struct iphdr *iph = (const struct iphdr *)skb->data;
61062306a36Sopenharmony_ci	const int type = icmp_hdr(skb)->type;
61162306a36Sopenharmony_ci	const int code = icmp_hdr(skb)->code;
61262306a36Sopenharmony_ci	struct net *net = dev_net(skb->dev);
61362306a36Sopenharmony_ci	struct sctp_transport *transport;
61462306a36Sopenharmony_ci	struct sctp_association *asoc;
61562306a36Sopenharmony_ci	__u16 saveip, savesctp;
61662306a36Sopenharmony_ci	struct sock *sk;
61762306a36Sopenharmony_ci
61862306a36Sopenharmony_ci	/* Fix up skb to look at the embedded net header. */
61962306a36Sopenharmony_ci	saveip = skb->network_header;
62062306a36Sopenharmony_ci	savesctp = skb->transport_header;
62162306a36Sopenharmony_ci	skb_reset_network_header(skb);
62262306a36Sopenharmony_ci	skb_set_transport_header(skb, iph->ihl * 4);
62362306a36Sopenharmony_ci	sk = sctp_err_lookup(net, AF_INET, skb, sctp_hdr(skb), &asoc, &transport);
62462306a36Sopenharmony_ci	/* Put back, the original values. */
62562306a36Sopenharmony_ci	skb->network_header = saveip;
62662306a36Sopenharmony_ci	skb->transport_header = savesctp;
62762306a36Sopenharmony_ci	if (!sk) {
62862306a36Sopenharmony_ci		__ICMP_INC_STATS(net, ICMP_MIB_INERRORS);
62962306a36Sopenharmony_ci		return -ENOENT;
63062306a36Sopenharmony_ci	}
63162306a36Sopenharmony_ci
63262306a36Sopenharmony_ci	sctp_v4_err_handle(transport, skb, type, code, info);
63362306a36Sopenharmony_ci	sctp_err_finish(sk, transport);
63462306a36Sopenharmony_ci
63562306a36Sopenharmony_ci	return 0;
63662306a36Sopenharmony_ci}
63762306a36Sopenharmony_ci
63862306a36Sopenharmony_ciint sctp_udp_v4_err(struct sock *sk, struct sk_buff *skb)
63962306a36Sopenharmony_ci{
64062306a36Sopenharmony_ci	struct net *net = dev_net(skb->dev);
64162306a36Sopenharmony_ci	struct sctp_association *asoc;
64262306a36Sopenharmony_ci	struct sctp_transport *t;
64362306a36Sopenharmony_ci	struct icmphdr *hdr;
64462306a36Sopenharmony_ci	__u32 info = 0;
64562306a36Sopenharmony_ci
64662306a36Sopenharmony_ci	skb->transport_header += sizeof(struct udphdr);
64762306a36Sopenharmony_ci	sk = sctp_err_lookup(net, AF_INET, skb, sctp_hdr(skb), &asoc, &t);
64862306a36Sopenharmony_ci	if (!sk) {
64962306a36Sopenharmony_ci		__ICMP_INC_STATS(net, ICMP_MIB_INERRORS);
65062306a36Sopenharmony_ci		return -ENOENT;
65162306a36Sopenharmony_ci	}
65262306a36Sopenharmony_ci
65362306a36Sopenharmony_ci	skb->transport_header -= sizeof(struct udphdr);
65462306a36Sopenharmony_ci	hdr = (struct icmphdr *)(skb_network_header(skb) - sizeof(struct icmphdr));
65562306a36Sopenharmony_ci	if (hdr->type == ICMP_REDIRECT) {
65662306a36Sopenharmony_ci		/* can't be handled without outer iphdr known, leave it to udp_err */
65762306a36Sopenharmony_ci		sctp_err_finish(sk, t);
65862306a36Sopenharmony_ci		return 0;
65962306a36Sopenharmony_ci	}
66062306a36Sopenharmony_ci	if (hdr->type == ICMP_DEST_UNREACH && hdr->code == ICMP_FRAG_NEEDED)
66162306a36Sopenharmony_ci		info = ntohs(hdr->un.frag.mtu);
66262306a36Sopenharmony_ci	sctp_v4_err_handle(t, skb, hdr->type, hdr->code, info);
66362306a36Sopenharmony_ci
66462306a36Sopenharmony_ci	sctp_err_finish(sk, t);
66562306a36Sopenharmony_ci	return 1;
66662306a36Sopenharmony_ci}
66762306a36Sopenharmony_ci
66862306a36Sopenharmony_ci/*
66962306a36Sopenharmony_ci * RFC 2960, 8.4 - Handle "Out of the blue" Packets.
67062306a36Sopenharmony_ci *
67162306a36Sopenharmony_ci * This function scans all the chunks in the OOTB packet to determine if
67262306a36Sopenharmony_ci * the packet should be discarded right away.  If a response might be needed
67362306a36Sopenharmony_ci * for this packet, or, if further processing is possible, the packet will
67462306a36Sopenharmony_ci * be queued to a proper inqueue for the next phase of handling.
67562306a36Sopenharmony_ci *
67662306a36Sopenharmony_ci * Output:
67762306a36Sopenharmony_ci * Return 0 - If further processing is needed.
67862306a36Sopenharmony_ci * Return 1 - If the packet can be discarded right away.
67962306a36Sopenharmony_ci */
68062306a36Sopenharmony_cistatic int sctp_rcv_ootb(struct sk_buff *skb)
68162306a36Sopenharmony_ci{
68262306a36Sopenharmony_ci	struct sctp_chunkhdr *ch, _ch;
68362306a36Sopenharmony_ci	int ch_end, offset = 0;
68462306a36Sopenharmony_ci
68562306a36Sopenharmony_ci	/* Scan through all the chunks in the packet.  */
68662306a36Sopenharmony_ci	do {
68762306a36Sopenharmony_ci		/* Make sure we have at least the header there */
68862306a36Sopenharmony_ci		if (offset + sizeof(_ch) > skb->len)
68962306a36Sopenharmony_ci			break;
69062306a36Sopenharmony_ci
69162306a36Sopenharmony_ci		ch = skb_header_pointer(skb, offset, sizeof(*ch), &_ch);
69262306a36Sopenharmony_ci
69362306a36Sopenharmony_ci		/* Break out if chunk length is less then minimal. */
69462306a36Sopenharmony_ci		if (!ch || ntohs(ch->length) < sizeof(_ch))
69562306a36Sopenharmony_ci			break;
69662306a36Sopenharmony_ci
69762306a36Sopenharmony_ci		ch_end = offset + SCTP_PAD4(ntohs(ch->length));
69862306a36Sopenharmony_ci		if (ch_end > skb->len)
69962306a36Sopenharmony_ci			break;
70062306a36Sopenharmony_ci
70162306a36Sopenharmony_ci		/* RFC 8.4, 2) If the OOTB packet contains an ABORT chunk, the
70262306a36Sopenharmony_ci		 * receiver MUST silently discard the OOTB packet and take no
70362306a36Sopenharmony_ci		 * further action.
70462306a36Sopenharmony_ci		 */
70562306a36Sopenharmony_ci		if (SCTP_CID_ABORT == ch->type)
70662306a36Sopenharmony_ci			goto discard;
70762306a36Sopenharmony_ci
70862306a36Sopenharmony_ci		/* RFC 8.4, 6) If the packet contains a SHUTDOWN COMPLETE
70962306a36Sopenharmony_ci		 * chunk, the receiver should silently discard the packet
71062306a36Sopenharmony_ci		 * and take no further action.
71162306a36Sopenharmony_ci		 */
71262306a36Sopenharmony_ci		if (SCTP_CID_SHUTDOWN_COMPLETE == ch->type)
71362306a36Sopenharmony_ci			goto discard;
71462306a36Sopenharmony_ci
71562306a36Sopenharmony_ci		/* RFC 4460, 2.11.2
71662306a36Sopenharmony_ci		 * This will discard packets with INIT chunk bundled as
71762306a36Sopenharmony_ci		 * subsequent chunks in the packet.  When INIT is first,
71862306a36Sopenharmony_ci		 * the normal INIT processing will discard the chunk.
71962306a36Sopenharmony_ci		 */
72062306a36Sopenharmony_ci		if (SCTP_CID_INIT == ch->type && (void *)ch != skb->data)
72162306a36Sopenharmony_ci			goto discard;
72262306a36Sopenharmony_ci
72362306a36Sopenharmony_ci		offset = ch_end;
72462306a36Sopenharmony_ci	} while (ch_end < skb->len);
72562306a36Sopenharmony_ci
72662306a36Sopenharmony_ci	return 0;
72762306a36Sopenharmony_ci
72862306a36Sopenharmony_cidiscard:
72962306a36Sopenharmony_ci	return 1;
73062306a36Sopenharmony_ci}
73162306a36Sopenharmony_ci
73262306a36Sopenharmony_ci/* Insert endpoint into the hash table.  */
73362306a36Sopenharmony_cistatic int __sctp_hash_endpoint(struct sctp_endpoint *ep)
73462306a36Sopenharmony_ci{
73562306a36Sopenharmony_ci	struct sock *sk = ep->base.sk;
73662306a36Sopenharmony_ci	struct net *net = sock_net(sk);
73762306a36Sopenharmony_ci	struct sctp_hashbucket *head;
73862306a36Sopenharmony_ci
73962306a36Sopenharmony_ci	ep->hashent = sctp_ep_hashfn(net, ep->base.bind_addr.port);
74062306a36Sopenharmony_ci	head = &sctp_ep_hashtable[ep->hashent];
74162306a36Sopenharmony_ci
74262306a36Sopenharmony_ci	if (sk->sk_reuseport) {
74362306a36Sopenharmony_ci		bool any = sctp_is_ep_boundall(sk);
74462306a36Sopenharmony_ci		struct sctp_endpoint *ep2;
74562306a36Sopenharmony_ci		struct list_head *list;
74662306a36Sopenharmony_ci		int cnt = 0, err = 1;
74762306a36Sopenharmony_ci
74862306a36Sopenharmony_ci		list_for_each(list, &ep->base.bind_addr.address_list)
74962306a36Sopenharmony_ci			cnt++;
75062306a36Sopenharmony_ci
75162306a36Sopenharmony_ci		sctp_for_each_hentry(ep2, &head->chain) {
75262306a36Sopenharmony_ci			struct sock *sk2 = ep2->base.sk;
75362306a36Sopenharmony_ci
75462306a36Sopenharmony_ci			if (!net_eq(sock_net(sk2), net) || sk2 == sk ||
75562306a36Sopenharmony_ci			    !uid_eq(sock_i_uid(sk2), sock_i_uid(sk)) ||
75662306a36Sopenharmony_ci			    !sk2->sk_reuseport)
75762306a36Sopenharmony_ci				continue;
75862306a36Sopenharmony_ci
75962306a36Sopenharmony_ci			err = sctp_bind_addrs_check(sctp_sk(sk2),
76062306a36Sopenharmony_ci						    sctp_sk(sk), cnt);
76162306a36Sopenharmony_ci			if (!err) {
76262306a36Sopenharmony_ci				err = reuseport_add_sock(sk, sk2, any);
76362306a36Sopenharmony_ci				if (err)
76462306a36Sopenharmony_ci					return err;
76562306a36Sopenharmony_ci				break;
76662306a36Sopenharmony_ci			} else if (err < 0) {
76762306a36Sopenharmony_ci				return err;
76862306a36Sopenharmony_ci			}
76962306a36Sopenharmony_ci		}
77062306a36Sopenharmony_ci
77162306a36Sopenharmony_ci		if (err) {
77262306a36Sopenharmony_ci			err = reuseport_alloc(sk, any);
77362306a36Sopenharmony_ci			if (err)
77462306a36Sopenharmony_ci				return err;
77562306a36Sopenharmony_ci		}
77662306a36Sopenharmony_ci	}
77762306a36Sopenharmony_ci
77862306a36Sopenharmony_ci	write_lock(&head->lock);
77962306a36Sopenharmony_ci	hlist_add_head(&ep->node, &head->chain);
78062306a36Sopenharmony_ci	write_unlock(&head->lock);
78162306a36Sopenharmony_ci	return 0;
78262306a36Sopenharmony_ci}
78362306a36Sopenharmony_ci
78462306a36Sopenharmony_ci/* Add an endpoint to the hash. Local BH-safe. */
78562306a36Sopenharmony_ciint sctp_hash_endpoint(struct sctp_endpoint *ep)
78662306a36Sopenharmony_ci{
78762306a36Sopenharmony_ci	int err;
78862306a36Sopenharmony_ci
78962306a36Sopenharmony_ci	local_bh_disable();
79062306a36Sopenharmony_ci	err = __sctp_hash_endpoint(ep);
79162306a36Sopenharmony_ci	local_bh_enable();
79262306a36Sopenharmony_ci
79362306a36Sopenharmony_ci	return err;
79462306a36Sopenharmony_ci}
79562306a36Sopenharmony_ci
79662306a36Sopenharmony_ci/* Remove endpoint from the hash table.  */
79762306a36Sopenharmony_cistatic void __sctp_unhash_endpoint(struct sctp_endpoint *ep)
79862306a36Sopenharmony_ci{
79962306a36Sopenharmony_ci	struct sock *sk = ep->base.sk;
80062306a36Sopenharmony_ci	struct sctp_hashbucket *head;
80162306a36Sopenharmony_ci
80262306a36Sopenharmony_ci	ep->hashent = sctp_ep_hashfn(sock_net(sk), ep->base.bind_addr.port);
80362306a36Sopenharmony_ci
80462306a36Sopenharmony_ci	head = &sctp_ep_hashtable[ep->hashent];
80562306a36Sopenharmony_ci
80662306a36Sopenharmony_ci	if (rcu_access_pointer(sk->sk_reuseport_cb))
80762306a36Sopenharmony_ci		reuseport_detach_sock(sk);
80862306a36Sopenharmony_ci
80962306a36Sopenharmony_ci	write_lock(&head->lock);
81062306a36Sopenharmony_ci	hlist_del_init(&ep->node);
81162306a36Sopenharmony_ci	write_unlock(&head->lock);
81262306a36Sopenharmony_ci}
81362306a36Sopenharmony_ci
81462306a36Sopenharmony_ci/* Remove endpoint from the hash.  Local BH-safe. */
81562306a36Sopenharmony_civoid sctp_unhash_endpoint(struct sctp_endpoint *ep)
81662306a36Sopenharmony_ci{
81762306a36Sopenharmony_ci	local_bh_disable();
81862306a36Sopenharmony_ci	__sctp_unhash_endpoint(ep);
81962306a36Sopenharmony_ci	local_bh_enable();
82062306a36Sopenharmony_ci}
82162306a36Sopenharmony_ci
82262306a36Sopenharmony_cistatic inline __u32 sctp_hashfn(const struct net *net, __be16 lport,
82362306a36Sopenharmony_ci				const union sctp_addr *paddr, __u32 seed)
82462306a36Sopenharmony_ci{
82562306a36Sopenharmony_ci	__u32 addr;
82662306a36Sopenharmony_ci
82762306a36Sopenharmony_ci	if (paddr->sa.sa_family == AF_INET6)
82862306a36Sopenharmony_ci		addr = jhash(&paddr->v6.sin6_addr, 16, seed);
82962306a36Sopenharmony_ci	else
83062306a36Sopenharmony_ci		addr = (__force __u32)paddr->v4.sin_addr.s_addr;
83162306a36Sopenharmony_ci
83262306a36Sopenharmony_ci	return  jhash_3words(addr, ((__force __u32)paddr->v4.sin_port) << 16 |
83362306a36Sopenharmony_ci			     (__force __u32)lport, net_hash_mix(net), seed);
83462306a36Sopenharmony_ci}
83562306a36Sopenharmony_ci
83662306a36Sopenharmony_ci/* Look up an endpoint. */
83762306a36Sopenharmony_cistatic struct sctp_endpoint *__sctp_rcv_lookup_endpoint(
83862306a36Sopenharmony_ci					struct net *net, struct sk_buff *skb,
83962306a36Sopenharmony_ci					const union sctp_addr *laddr,
84062306a36Sopenharmony_ci					const union sctp_addr *paddr,
84162306a36Sopenharmony_ci					int dif, int sdif)
84262306a36Sopenharmony_ci{
84362306a36Sopenharmony_ci	struct sctp_hashbucket *head;
84462306a36Sopenharmony_ci	struct sctp_endpoint *ep;
84562306a36Sopenharmony_ci	struct sock *sk;
84662306a36Sopenharmony_ci	__be16 lport;
84762306a36Sopenharmony_ci	int hash;
84862306a36Sopenharmony_ci
84962306a36Sopenharmony_ci	lport = laddr->v4.sin_port;
85062306a36Sopenharmony_ci	hash = sctp_ep_hashfn(net, ntohs(lport));
85162306a36Sopenharmony_ci	head = &sctp_ep_hashtable[hash];
85262306a36Sopenharmony_ci	read_lock(&head->lock);
85362306a36Sopenharmony_ci	sctp_for_each_hentry(ep, &head->chain) {
85462306a36Sopenharmony_ci		if (sctp_endpoint_is_match(ep, net, laddr, dif, sdif))
85562306a36Sopenharmony_ci			goto hit;
85662306a36Sopenharmony_ci	}
85762306a36Sopenharmony_ci
85862306a36Sopenharmony_ci	ep = sctp_sk(net->sctp.ctl_sock)->ep;
85962306a36Sopenharmony_ci
86062306a36Sopenharmony_cihit:
86162306a36Sopenharmony_ci	sk = ep->base.sk;
86262306a36Sopenharmony_ci	if (sk->sk_reuseport) {
86362306a36Sopenharmony_ci		__u32 phash = sctp_hashfn(net, lport, paddr, 0);
86462306a36Sopenharmony_ci
86562306a36Sopenharmony_ci		sk = reuseport_select_sock(sk, phash, skb,
86662306a36Sopenharmony_ci					   sizeof(struct sctphdr));
86762306a36Sopenharmony_ci		if (sk)
86862306a36Sopenharmony_ci			ep = sctp_sk(sk)->ep;
86962306a36Sopenharmony_ci	}
87062306a36Sopenharmony_ci	sctp_endpoint_hold(ep);
87162306a36Sopenharmony_ci	read_unlock(&head->lock);
87262306a36Sopenharmony_ci	return ep;
87362306a36Sopenharmony_ci}
87462306a36Sopenharmony_ci
87562306a36Sopenharmony_ci/* rhashtable for transport */
87662306a36Sopenharmony_cistruct sctp_hash_cmp_arg {
87762306a36Sopenharmony_ci	const union sctp_addr	*paddr;
87862306a36Sopenharmony_ci	const struct net	*net;
87962306a36Sopenharmony_ci	__be16			lport;
88062306a36Sopenharmony_ci};
88162306a36Sopenharmony_ci
88262306a36Sopenharmony_cistatic inline int sctp_hash_cmp(struct rhashtable_compare_arg *arg,
88362306a36Sopenharmony_ci				const void *ptr)
88462306a36Sopenharmony_ci{
88562306a36Sopenharmony_ci	struct sctp_transport *t = (struct sctp_transport *)ptr;
88662306a36Sopenharmony_ci	const struct sctp_hash_cmp_arg *x = arg->key;
88762306a36Sopenharmony_ci	int err = 1;
88862306a36Sopenharmony_ci
88962306a36Sopenharmony_ci	if (!sctp_cmp_addr_exact(&t->ipaddr, x->paddr))
89062306a36Sopenharmony_ci		return err;
89162306a36Sopenharmony_ci	if (!sctp_transport_hold(t))
89262306a36Sopenharmony_ci		return err;
89362306a36Sopenharmony_ci
89462306a36Sopenharmony_ci	if (!net_eq(t->asoc->base.net, x->net))
89562306a36Sopenharmony_ci		goto out;
89662306a36Sopenharmony_ci	if (x->lport != htons(t->asoc->base.bind_addr.port))
89762306a36Sopenharmony_ci		goto out;
89862306a36Sopenharmony_ci
89962306a36Sopenharmony_ci	err = 0;
90062306a36Sopenharmony_ciout:
90162306a36Sopenharmony_ci	sctp_transport_put(t);
90262306a36Sopenharmony_ci	return err;
90362306a36Sopenharmony_ci}
90462306a36Sopenharmony_ci
90562306a36Sopenharmony_cistatic inline __u32 sctp_hash_obj(const void *data, u32 len, u32 seed)
90662306a36Sopenharmony_ci{
90762306a36Sopenharmony_ci	const struct sctp_transport *t = data;
90862306a36Sopenharmony_ci
90962306a36Sopenharmony_ci	return sctp_hashfn(t->asoc->base.net,
91062306a36Sopenharmony_ci			   htons(t->asoc->base.bind_addr.port),
91162306a36Sopenharmony_ci			   &t->ipaddr, seed);
91262306a36Sopenharmony_ci}
91362306a36Sopenharmony_ci
91462306a36Sopenharmony_cistatic inline __u32 sctp_hash_key(const void *data, u32 len, u32 seed)
91562306a36Sopenharmony_ci{
91662306a36Sopenharmony_ci	const struct sctp_hash_cmp_arg *x = data;
91762306a36Sopenharmony_ci
91862306a36Sopenharmony_ci	return sctp_hashfn(x->net, x->lport, x->paddr, seed);
91962306a36Sopenharmony_ci}
92062306a36Sopenharmony_ci
92162306a36Sopenharmony_cistatic const struct rhashtable_params sctp_hash_params = {
92262306a36Sopenharmony_ci	.head_offset		= offsetof(struct sctp_transport, node),
92362306a36Sopenharmony_ci	.hashfn			= sctp_hash_key,
92462306a36Sopenharmony_ci	.obj_hashfn		= sctp_hash_obj,
92562306a36Sopenharmony_ci	.obj_cmpfn		= sctp_hash_cmp,
92662306a36Sopenharmony_ci	.automatic_shrinking	= true,
92762306a36Sopenharmony_ci};
92862306a36Sopenharmony_ci
92962306a36Sopenharmony_ciint sctp_transport_hashtable_init(void)
93062306a36Sopenharmony_ci{
93162306a36Sopenharmony_ci	return rhltable_init(&sctp_transport_hashtable, &sctp_hash_params);
93262306a36Sopenharmony_ci}
93362306a36Sopenharmony_ci
93462306a36Sopenharmony_civoid sctp_transport_hashtable_destroy(void)
93562306a36Sopenharmony_ci{
93662306a36Sopenharmony_ci	rhltable_destroy(&sctp_transport_hashtable);
93762306a36Sopenharmony_ci}
93862306a36Sopenharmony_ci
93962306a36Sopenharmony_ciint sctp_hash_transport(struct sctp_transport *t)
94062306a36Sopenharmony_ci{
94162306a36Sopenharmony_ci	struct sctp_transport *transport;
94262306a36Sopenharmony_ci	struct rhlist_head *tmp, *list;
94362306a36Sopenharmony_ci	struct sctp_hash_cmp_arg arg;
94462306a36Sopenharmony_ci	int err;
94562306a36Sopenharmony_ci
94662306a36Sopenharmony_ci	if (t->asoc->temp)
94762306a36Sopenharmony_ci		return 0;
94862306a36Sopenharmony_ci
94962306a36Sopenharmony_ci	arg.net   = t->asoc->base.net;
95062306a36Sopenharmony_ci	arg.paddr = &t->ipaddr;
95162306a36Sopenharmony_ci	arg.lport = htons(t->asoc->base.bind_addr.port);
95262306a36Sopenharmony_ci
95362306a36Sopenharmony_ci	rcu_read_lock();
95462306a36Sopenharmony_ci	list = rhltable_lookup(&sctp_transport_hashtable, &arg,
95562306a36Sopenharmony_ci			       sctp_hash_params);
95662306a36Sopenharmony_ci
95762306a36Sopenharmony_ci	rhl_for_each_entry_rcu(transport, tmp, list, node)
95862306a36Sopenharmony_ci		if (transport->asoc->ep == t->asoc->ep) {
95962306a36Sopenharmony_ci			rcu_read_unlock();
96062306a36Sopenharmony_ci			return -EEXIST;
96162306a36Sopenharmony_ci		}
96262306a36Sopenharmony_ci	rcu_read_unlock();
96362306a36Sopenharmony_ci
96462306a36Sopenharmony_ci	err = rhltable_insert_key(&sctp_transport_hashtable, &arg,
96562306a36Sopenharmony_ci				  &t->node, sctp_hash_params);
96662306a36Sopenharmony_ci	if (err)
96762306a36Sopenharmony_ci		pr_err_once("insert transport fail, errno %d\n", err);
96862306a36Sopenharmony_ci
96962306a36Sopenharmony_ci	return err;
97062306a36Sopenharmony_ci}
97162306a36Sopenharmony_ci
97262306a36Sopenharmony_civoid sctp_unhash_transport(struct sctp_transport *t)
97362306a36Sopenharmony_ci{
97462306a36Sopenharmony_ci	if (t->asoc->temp)
97562306a36Sopenharmony_ci		return;
97662306a36Sopenharmony_ci
97762306a36Sopenharmony_ci	rhltable_remove(&sctp_transport_hashtable, &t->node,
97862306a36Sopenharmony_ci			sctp_hash_params);
97962306a36Sopenharmony_ci}
98062306a36Sopenharmony_ci
98162306a36Sopenharmony_cibool sctp_sk_bound_dev_eq(struct net *net, int bound_dev_if, int dif, int sdif)
98262306a36Sopenharmony_ci{
98362306a36Sopenharmony_ci	bool l3mdev_accept = true;
98462306a36Sopenharmony_ci
98562306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_NET_L3_MASTER_DEV)
98662306a36Sopenharmony_ci	l3mdev_accept = !!READ_ONCE(net->sctp.l3mdev_accept);
98762306a36Sopenharmony_ci#endif
98862306a36Sopenharmony_ci	return inet_bound_dev_eq(l3mdev_accept, bound_dev_if, dif, sdif);
98962306a36Sopenharmony_ci}
99062306a36Sopenharmony_ci
99162306a36Sopenharmony_ci/* return a transport with holding it */
99262306a36Sopenharmony_cistruct sctp_transport *sctp_addrs_lookup_transport(
99362306a36Sopenharmony_ci				struct net *net,
99462306a36Sopenharmony_ci				const union sctp_addr *laddr,
99562306a36Sopenharmony_ci				const union sctp_addr *paddr,
99662306a36Sopenharmony_ci				int dif, int sdif)
99762306a36Sopenharmony_ci{
99862306a36Sopenharmony_ci	struct rhlist_head *tmp, *list;
99962306a36Sopenharmony_ci	struct sctp_transport *t;
100062306a36Sopenharmony_ci	int bound_dev_if;
100162306a36Sopenharmony_ci	struct sctp_hash_cmp_arg arg = {
100262306a36Sopenharmony_ci		.paddr = paddr,
100362306a36Sopenharmony_ci		.net   = net,
100462306a36Sopenharmony_ci		.lport = laddr->v4.sin_port,
100562306a36Sopenharmony_ci	};
100662306a36Sopenharmony_ci
100762306a36Sopenharmony_ci	list = rhltable_lookup(&sctp_transport_hashtable, &arg,
100862306a36Sopenharmony_ci			       sctp_hash_params);
100962306a36Sopenharmony_ci
101062306a36Sopenharmony_ci	rhl_for_each_entry_rcu(t, tmp, list, node) {
101162306a36Sopenharmony_ci		if (!sctp_transport_hold(t))
101262306a36Sopenharmony_ci			continue;
101362306a36Sopenharmony_ci
101462306a36Sopenharmony_ci		bound_dev_if = READ_ONCE(t->asoc->base.sk->sk_bound_dev_if);
101562306a36Sopenharmony_ci		if (sctp_sk_bound_dev_eq(net, bound_dev_if, dif, sdif) &&
101662306a36Sopenharmony_ci		    sctp_bind_addr_match(&t->asoc->base.bind_addr,
101762306a36Sopenharmony_ci					 laddr, sctp_sk(t->asoc->base.sk)))
101862306a36Sopenharmony_ci			return t;
101962306a36Sopenharmony_ci		sctp_transport_put(t);
102062306a36Sopenharmony_ci	}
102162306a36Sopenharmony_ci
102262306a36Sopenharmony_ci	return NULL;
102362306a36Sopenharmony_ci}
102462306a36Sopenharmony_ci
102562306a36Sopenharmony_ci/* return a transport without holding it, as it's only used under sock lock */
102662306a36Sopenharmony_cistruct sctp_transport *sctp_epaddr_lookup_transport(
102762306a36Sopenharmony_ci				const struct sctp_endpoint *ep,
102862306a36Sopenharmony_ci				const union sctp_addr *paddr)
102962306a36Sopenharmony_ci{
103062306a36Sopenharmony_ci	struct rhlist_head *tmp, *list;
103162306a36Sopenharmony_ci	struct sctp_transport *t;
103262306a36Sopenharmony_ci	struct sctp_hash_cmp_arg arg = {
103362306a36Sopenharmony_ci		.paddr = paddr,
103462306a36Sopenharmony_ci		.net   = ep->base.net,
103562306a36Sopenharmony_ci		.lport = htons(ep->base.bind_addr.port),
103662306a36Sopenharmony_ci	};
103762306a36Sopenharmony_ci
103862306a36Sopenharmony_ci	list = rhltable_lookup(&sctp_transport_hashtable, &arg,
103962306a36Sopenharmony_ci			       sctp_hash_params);
104062306a36Sopenharmony_ci
104162306a36Sopenharmony_ci	rhl_for_each_entry_rcu(t, tmp, list, node)
104262306a36Sopenharmony_ci		if (ep == t->asoc->ep)
104362306a36Sopenharmony_ci			return t;
104462306a36Sopenharmony_ci
104562306a36Sopenharmony_ci	return NULL;
104662306a36Sopenharmony_ci}
104762306a36Sopenharmony_ci
104862306a36Sopenharmony_ci/* Look up an association. */
104962306a36Sopenharmony_cistatic struct sctp_association *__sctp_lookup_association(
105062306a36Sopenharmony_ci					struct net *net,
105162306a36Sopenharmony_ci					const union sctp_addr *local,
105262306a36Sopenharmony_ci					const union sctp_addr *peer,
105362306a36Sopenharmony_ci					struct sctp_transport **pt,
105462306a36Sopenharmony_ci					int dif, int sdif)
105562306a36Sopenharmony_ci{
105662306a36Sopenharmony_ci	struct sctp_transport *t;
105762306a36Sopenharmony_ci	struct sctp_association *asoc = NULL;
105862306a36Sopenharmony_ci
105962306a36Sopenharmony_ci	t = sctp_addrs_lookup_transport(net, local, peer, dif, sdif);
106062306a36Sopenharmony_ci	if (!t)
106162306a36Sopenharmony_ci		goto out;
106262306a36Sopenharmony_ci
106362306a36Sopenharmony_ci	asoc = t->asoc;
106462306a36Sopenharmony_ci	*pt = t;
106562306a36Sopenharmony_ci
106662306a36Sopenharmony_ciout:
106762306a36Sopenharmony_ci	return asoc;
106862306a36Sopenharmony_ci}
106962306a36Sopenharmony_ci
107062306a36Sopenharmony_ci/* Look up an association. protected by RCU read lock */
107162306a36Sopenharmony_cistatic
107262306a36Sopenharmony_cistruct sctp_association *sctp_lookup_association(struct net *net,
107362306a36Sopenharmony_ci						 const union sctp_addr *laddr,
107462306a36Sopenharmony_ci						 const union sctp_addr *paddr,
107562306a36Sopenharmony_ci						 struct sctp_transport **transportp,
107662306a36Sopenharmony_ci						 int dif, int sdif)
107762306a36Sopenharmony_ci{
107862306a36Sopenharmony_ci	struct sctp_association *asoc;
107962306a36Sopenharmony_ci
108062306a36Sopenharmony_ci	rcu_read_lock();
108162306a36Sopenharmony_ci	asoc = __sctp_lookup_association(net, laddr, paddr, transportp, dif, sdif);
108262306a36Sopenharmony_ci	rcu_read_unlock();
108362306a36Sopenharmony_ci
108462306a36Sopenharmony_ci	return asoc;
108562306a36Sopenharmony_ci}
108662306a36Sopenharmony_ci
108762306a36Sopenharmony_ci/* Is there an association matching the given local and peer addresses? */
108862306a36Sopenharmony_cibool sctp_has_association(struct net *net,
108962306a36Sopenharmony_ci			  const union sctp_addr *laddr,
109062306a36Sopenharmony_ci			  const union sctp_addr *paddr,
109162306a36Sopenharmony_ci			  int dif, int sdif)
109262306a36Sopenharmony_ci{
109362306a36Sopenharmony_ci	struct sctp_transport *transport;
109462306a36Sopenharmony_ci
109562306a36Sopenharmony_ci	if (sctp_lookup_association(net, laddr, paddr, &transport, dif, sdif)) {
109662306a36Sopenharmony_ci		sctp_transport_put(transport);
109762306a36Sopenharmony_ci		return true;
109862306a36Sopenharmony_ci	}
109962306a36Sopenharmony_ci
110062306a36Sopenharmony_ci	return false;
110162306a36Sopenharmony_ci}
110262306a36Sopenharmony_ci
110362306a36Sopenharmony_ci/*
110462306a36Sopenharmony_ci * SCTP Implementors Guide, 2.18 Handling of address
110562306a36Sopenharmony_ci * parameters within the INIT or INIT-ACK.
110662306a36Sopenharmony_ci *
110762306a36Sopenharmony_ci * D) When searching for a matching TCB upon reception of an INIT
110862306a36Sopenharmony_ci *    or INIT-ACK chunk the receiver SHOULD use not only the
110962306a36Sopenharmony_ci *    source address of the packet (containing the INIT or
111062306a36Sopenharmony_ci *    INIT-ACK) but the receiver SHOULD also use all valid
111162306a36Sopenharmony_ci *    address parameters contained within the chunk.
111262306a36Sopenharmony_ci *
111362306a36Sopenharmony_ci * 2.18.3 Solution description
111462306a36Sopenharmony_ci *
111562306a36Sopenharmony_ci * This new text clearly specifies to an implementor the need
111662306a36Sopenharmony_ci * to look within the INIT or INIT-ACK. Any implementation that
111762306a36Sopenharmony_ci * does not do this, may not be able to establish associations
111862306a36Sopenharmony_ci * in certain circumstances.
111962306a36Sopenharmony_ci *
112062306a36Sopenharmony_ci */
112162306a36Sopenharmony_cistatic struct sctp_association *__sctp_rcv_init_lookup(struct net *net,
112262306a36Sopenharmony_ci	struct sk_buff *skb,
112362306a36Sopenharmony_ci	const union sctp_addr *laddr, struct sctp_transport **transportp,
112462306a36Sopenharmony_ci	int dif, int sdif)
112562306a36Sopenharmony_ci{
112662306a36Sopenharmony_ci	struct sctp_association *asoc;
112762306a36Sopenharmony_ci	union sctp_addr addr;
112862306a36Sopenharmony_ci	union sctp_addr *paddr = &addr;
112962306a36Sopenharmony_ci	struct sctphdr *sh = sctp_hdr(skb);
113062306a36Sopenharmony_ci	union sctp_params params;
113162306a36Sopenharmony_ci	struct sctp_init_chunk *init;
113262306a36Sopenharmony_ci	struct sctp_af *af;
113362306a36Sopenharmony_ci
113462306a36Sopenharmony_ci	/*
113562306a36Sopenharmony_ci	 * This code will NOT touch anything inside the chunk--it is
113662306a36Sopenharmony_ci	 * strictly READ-ONLY.
113762306a36Sopenharmony_ci	 *
113862306a36Sopenharmony_ci	 * RFC 2960 3  SCTP packet Format
113962306a36Sopenharmony_ci	 *
114062306a36Sopenharmony_ci	 * Multiple chunks can be bundled into one SCTP packet up to
114162306a36Sopenharmony_ci	 * the MTU size, except for the INIT, INIT ACK, and SHUTDOWN
114262306a36Sopenharmony_ci	 * COMPLETE chunks.  These chunks MUST NOT be bundled with any
114362306a36Sopenharmony_ci	 * other chunk in a packet.  See Section 6.10 for more details
114462306a36Sopenharmony_ci	 * on chunk bundling.
114562306a36Sopenharmony_ci	 */
114662306a36Sopenharmony_ci
114762306a36Sopenharmony_ci	/* Find the start of the TLVs and the end of the chunk.  This is
114862306a36Sopenharmony_ci	 * the region we search for address parameters.
114962306a36Sopenharmony_ci	 */
115062306a36Sopenharmony_ci	init = (struct sctp_init_chunk *)skb->data;
115162306a36Sopenharmony_ci
115262306a36Sopenharmony_ci	/* Walk the parameters looking for embedded addresses. */
115362306a36Sopenharmony_ci	sctp_walk_params(params, init) {
115462306a36Sopenharmony_ci
115562306a36Sopenharmony_ci		/* Note: Ignoring hostname addresses. */
115662306a36Sopenharmony_ci		af = sctp_get_af_specific(param_type2af(params.p->type));
115762306a36Sopenharmony_ci		if (!af)
115862306a36Sopenharmony_ci			continue;
115962306a36Sopenharmony_ci
116062306a36Sopenharmony_ci		if (!af->from_addr_param(paddr, params.addr, sh->source, 0))
116162306a36Sopenharmony_ci			continue;
116262306a36Sopenharmony_ci
116362306a36Sopenharmony_ci		asoc = __sctp_lookup_association(net, laddr, paddr, transportp, dif, sdif);
116462306a36Sopenharmony_ci		if (asoc)
116562306a36Sopenharmony_ci			return asoc;
116662306a36Sopenharmony_ci	}
116762306a36Sopenharmony_ci
116862306a36Sopenharmony_ci	return NULL;
116962306a36Sopenharmony_ci}
117062306a36Sopenharmony_ci
117162306a36Sopenharmony_ci/* ADD-IP, Section 5.2
117262306a36Sopenharmony_ci * When an endpoint receives an ASCONF Chunk from the remote peer
117362306a36Sopenharmony_ci * special procedures may be needed to identify the association the
117462306a36Sopenharmony_ci * ASCONF Chunk is associated with. To properly find the association
117562306a36Sopenharmony_ci * the following procedures SHOULD be followed:
117662306a36Sopenharmony_ci *
117762306a36Sopenharmony_ci * D2) If the association is not found, use the address found in the
117862306a36Sopenharmony_ci * Address Parameter TLV combined with the port number found in the
117962306a36Sopenharmony_ci * SCTP common header. If found proceed to rule D4.
118062306a36Sopenharmony_ci *
118162306a36Sopenharmony_ci * D2-ext) If more than one ASCONF Chunks are packed together, use the
118262306a36Sopenharmony_ci * address found in the ASCONF Address Parameter TLV of each of the
118362306a36Sopenharmony_ci * subsequent ASCONF Chunks. If found, proceed to rule D4.
118462306a36Sopenharmony_ci */
118562306a36Sopenharmony_cistatic struct sctp_association *__sctp_rcv_asconf_lookup(
118662306a36Sopenharmony_ci					struct net *net,
118762306a36Sopenharmony_ci					struct sctp_chunkhdr *ch,
118862306a36Sopenharmony_ci					const union sctp_addr *laddr,
118962306a36Sopenharmony_ci					__be16 peer_port,
119062306a36Sopenharmony_ci					struct sctp_transport **transportp,
119162306a36Sopenharmony_ci					int dif, int sdif)
119262306a36Sopenharmony_ci{
119362306a36Sopenharmony_ci	struct sctp_addip_chunk *asconf = (struct sctp_addip_chunk *)ch;
119462306a36Sopenharmony_ci	struct sctp_af *af;
119562306a36Sopenharmony_ci	union sctp_addr_param *param;
119662306a36Sopenharmony_ci	union sctp_addr paddr;
119762306a36Sopenharmony_ci
119862306a36Sopenharmony_ci	if (ntohs(ch->length) < sizeof(*asconf) + sizeof(struct sctp_paramhdr))
119962306a36Sopenharmony_ci		return NULL;
120062306a36Sopenharmony_ci
120162306a36Sopenharmony_ci	/* Skip over the ADDIP header and find the Address parameter */
120262306a36Sopenharmony_ci	param = (union sctp_addr_param *)(asconf + 1);
120362306a36Sopenharmony_ci
120462306a36Sopenharmony_ci	af = sctp_get_af_specific(param_type2af(param->p.type));
120562306a36Sopenharmony_ci	if (unlikely(!af))
120662306a36Sopenharmony_ci		return NULL;
120762306a36Sopenharmony_ci
120862306a36Sopenharmony_ci	if (!af->from_addr_param(&paddr, param, peer_port, 0))
120962306a36Sopenharmony_ci		return NULL;
121062306a36Sopenharmony_ci
121162306a36Sopenharmony_ci	return __sctp_lookup_association(net, laddr, &paddr, transportp, dif, sdif);
121262306a36Sopenharmony_ci}
121362306a36Sopenharmony_ci
121462306a36Sopenharmony_ci
121562306a36Sopenharmony_ci/* SCTP-AUTH, Section 6.3:
121662306a36Sopenharmony_ci*    If the receiver does not find a STCB for a packet containing an AUTH
121762306a36Sopenharmony_ci*    chunk as the first chunk and not a COOKIE-ECHO chunk as the second
121862306a36Sopenharmony_ci*    chunk, it MUST use the chunks after the AUTH chunk to look up an existing
121962306a36Sopenharmony_ci*    association.
122062306a36Sopenharmony_ci*
122162306a36Sopenharmony_ci* This means that any chunks that can help us identify the association need
122262306a36Sopenharmony_ci* to be looked at to find this association.
122362306a36Sopenharmony_ci*/
122462306a36Sopenharmony_cistatic struct sctp_association *__sctp_rcv_walk_lookup(struct net *net,
122562306a36Sopenharmony_ci				      struct sk_buff *skb,
122662306a36Sopenharmony_ci				      const union sctp_addr *laddr,
122762306a36Sopenharmony_ci				      struct sctp_transport **transportp,
122862306a36Sopenharmony_ci				      int dif, int sdif)
122962306a36Sopenharmony_ci{
123062306a36Sopenharmony_ci	struct sctp_association *asoc = NULL;
123162306a36Sopenharmony_ci	struct sctp_chunkhdr *ch;
123262306a36Sopenharmony_ci	int have_auth = 0;
123362306a36Sopenharmony_ci	unsigned int chunk_num = 1;
123462306a36Sopenharmony_ci	__u8 *ch_end;
123562306a36Sopenharmony_ci
123662306a36Sopenharmony_ci	/* Walk through the chunks looking for AUTH or ASCONF chunks
123762306a36Sopenharmony_ci	 * to help us find the association.
123862306a36Sopenharmony_ci	 */
123962306a36Sopenharmony_ci	ch = (struct sctp_chunkhdr *)skb->data;
124062306a36Sopenharmony_ci	do {
124162306a36Sopenharmony_ci		/* Break out if chunk length is less then minimal. */
124262306a36Sopenharmony_ci		if (ntohs(ch->length) < sizeof(*ch))
124362306a36Sopenharmony_ci			break;
124462306a36Sopenharmony_ci
124562306a36Sopenharmony_ci		ch_end = ((__u8 *)ch) + SCTP_PAD4(ntohs(ch->length));
124662306a36Sopenharmony_ci		if (ch_end > skb_tail_pointer(skb))
124762306a36Sopenharmony_ci			break;
124862306a36Sopenharmony_ci
124962306a36Sopenharmony_ci		switch (ch->type) {
125062306a36Sopenharmony_ci		case SCTP_CID_AUTH:
125162306a36Sopenharmony_ci			have_auth = chunk_num;
125262306a36Sopenharmony_ci			break;
125362306a36Sopenharmony_ci
125462306a36Sopenharmony_ci		case SCTP_CID_COOKIE_ECHO:
125562306a36Sopenharmony_ci			/* If a packet arrives containing an AUTH chunk as
125662306a36Sopenharmony_ci			 * a first chunk, a COOKIE-ECHO chunk as the second
125762306a36Sopenharmony_ci			 * chunk, and possibly more chunks after them, and
125862306a36Sopenharmony_ci			 * the receiver does not have an STCB for that
125962306a36Sopenharmony_ci			 * packet, then authentication is based on
126062306a36Sopenharmony_ci			 * the contents of the COOKIE- ECHO chunk.
126162306a36Sopenharmony_ci			 */
126262306a36Sopenharmony_ci			if (have_auth == 1 && chunk_num == 2)
126362306a36Sopenharmony_ci				return NULL;
126462306a36Sopenharmony_ci			break;
126562306a36Sopenharmony_ci
126662306a36Sopenharmony_ci		case SCTP_CID_ASCONF:
126762306a36Sopenharmony_ci			if (have_auth || net->sctp.addip_noauth)
126862306a36Sopenharmony_ci				asoc = __sctp_rcv_asconf_lookup(
126962306a36Sopenharmony_ci						net, ch, laddr,
127062306a36Sopenharmony_ci						sctp_hdr(skb)->source,
127162306a36Sopenharmony_ci						transportp, dif, sdif);
127262306a36Sopenharmony_ci			break;
127362306a36Sopenharmony_ci		default:
127462306a36Sopenharmony_ci			break;
127562306a36Sopenharmony_ci		}
127662306a36Sopenharmony_ci
127762306a36Sopenharmony_ci		if (asoc)
127862306a36Sopenharmony_ci			break;
127962306a36Sopenharmony_ci
128062306a36Sopenharmony_ci		ch = (struct sctp_chunkhdr *)ch_end;
128162306a36Sopenharmony_ci		chunk_num++;
128262306a36Sopenharmony_ci	} while (ch_end + sizeof(*ch) < skb_tail_pointer(skb));
128362306a36Sopenharmony_ci
128462306a36Sopenharmony_ci	return asoc;
128562306a36Sopenharmony_ci}
128662306a36Sopenharmony_ci
128762306a36Sopenharmony_ci/*
128862306a36Sopenharmony_ci * There are circumstances when we need to look inside the SCTP packet
128962306a36Sopenharmony_ci * for information to help us find the association.   Examples
129062306a36Sopenharmony_ci * include looking inside of INIT/INIT-ACK chunks or after the AUTH
129162306a36Sopenharmony_ci * chunks.
129262306a36Sopenharmony_ci */
129362306a36Sopenharmony_cistatic struct sctp_association *__sctp_rcv_lookup_harder(struct net *net,
129462306a36Sopenharmony_ci				      struct sk_buff *skb,
129562306a36Sopenharmony_ci				      const union sctp_addr *laddr,
129662306a36Sopenharmony_ci				      struct sctp_transport **transportp,
129762306a36Sopenharmony_ci				      int dif, int sdif)
129862306a36Sopenharmony_ci{
129962306a36Sopenharmony_ci	struct sctp_chunkhdr *ch;
130062306a36Sopenharmony_ci
130162306a36Sopenharmony_ci	/* We do not allow GSO frames here as we need to linearize and
130262306a36Sopenharmony_ci	 * then cannot guarantee frame boundaries. This shouldn't be an
130362306a36Sopenharmony_ci	 * issue as packets hitting this are mostly INIT or INIT-ACK and
130462306a36Sopenharmony_ci	 * those cannot be on GSO-style anyway.
130562306a36Sopenharmony_ci	 */
130662306a36Sopenharmony_ci	if (skb_is_gso(skb) && skb_is_gso_sctp(skb))
130762306a36Sopenharmony_ci		return NULL;
130862306a36Sopenharmony_ci
130962306a36Sopenharmony_ci	ch = (struct sctp_chunkhdr *)skb->data;
131062306a36Sopenharmony_ci
131162306a36Sopenharmony_ci	/* The code below will attempt to walk the chunk and extract
131262306a36Sopenharmony_ci	 * parameter information.  Before we do that, we need to verify
131362306a36Sopenharmony_ci	 * that the chunk length doesn't cause overflow.  Otherwise, we'll
131462306a36Sopenharmony_ci	 * walk off the end.
131562306a36Sopenharmony_ci	 */
131662306a36Sopenharmony_ci	if (SCTP_PAD4(ntohs(ch->length)) > skb->len)
131762306a36Sopenharmony_ci		return NULL;
131862306a36Sopenharmony_ci
131962306a36Sopenharmony_ci	/* If this is INIT/INIT-ACK look inside the chunk too. */
132062306a36Sopenharmony_ci	if (ch->type == SCTP_CID_INIT || ch->type == SCTP_CID_INIT_ACK)
132162306a36Sopenharmony_ci		return __sctp_rcv_init_lookup(net, skb, laddr, transportp, dif, sdif);
132262306a36Sopenharmony_ci
132362306a36Sopenharmony_ci	return __sctp_rcv_walk_lookup(net, skb, laddr, transportp, dif, sdif);
132462306a36Sopenharmony_ci}
132562306a36Sopenharmony_ci
132662306a36Sopenharmony_ci/* Lookup an association for an inbound skb. */
132762306a36Sopenharmony_cistatic struct sctp_association *__sctp_rcv_lookup(struct net *net,
132862306a36Sopenharmony_ci				      struct sk_buff *skb,
132962306a36Sopenharmony_ci				      const union sctp_addr *paddr,
133062306a36Sopenharmony_ci				      const union sctp_addr *laddr,
133162306a36Sopenharmony_ci				      struct sctp_transport **transportp,
133262306a36Sopenharmony_ci				      int dif, int sdif)
133362306a36Sopenharmony_ci{
133462306a36Sopenharmony_ci	struct sctp_association *asoc;
133562306a36Sopenharmony_ci
133662306a36Sopenharmony_ci	asoc = __sctp_lookup_association(net, laddr, paddr, transportp, dif, sdif);
133762306a36Sopenharmony_ci	if (asoc)
133862306a36Sopenharmony_ci		goto out;
133962306a36Sopenharmony_ci
134062306a36Sopenharmony_ci	/* Further lookup for INIT/INIT-ACK packets.
134162306a36Sopenharmony_ci	 * SCTP Implementors Guide, 2.18 Handling of address
134262306a36Sopenharmony_ci	 * parameters within the INIT or INIT-ACK.
134362306a36Sopenharmony_ci	 */
134462306a36Sopenharmony_ci	asoc = __sctp_rcv_lookup_harder(net, skb, laddr, transportp, dif, sdif);
134562306a36Sopenharmony_ci	if (asoc)
134662306a36Sopenharmony_ci		goto out;
134762306a36Sopenharmony_ci
134862306a36Sopenharmony_ci	if (paddr->sa.sa_family == AF_INET)
134962306a36Sopenharmony_ci		pr_debug("sctp: asoc not found for src:%pI4:%d dst:%pI4:%d\n",
135062306a36Sopenharmony_ci			 &laddr->v4.sin_addr, ntohs(laddr->v4.sin_port),
135162306a36Sopenharmony_ci			 &paddr->v4.sin_addr, ntohs(paddr->v4.sin_port));
135262306a36Sopenharmony_ci	else
135362306a36Sopenharmony_ci		pr_debug("sctp: asoc not found for src:%pI6:%d dst:%pI6:%d\n",
135462306a36Sopenharmony_ci			 &laddr->v6.sin6_addr, ntohs(laddr->v6.sin6_port),
135562306a36Sopenharmony_ci			 &paddr->v6.sin6_addr, ntohs(paddr->v6.sin6_port));
135662306a36Sopenharmony_ci
135762306a36Sopenharmony_ciout:
135862306a36Sopenharmony_ci	return asoc;
135962306a36Sopenharmony_ci}
1360