linux/net/sctp/input.c

// SPDX-License-Identifier: GPL-2.0-or-later
/* SCTP kernel implementation
 * Copyright (c) 1999-2000 Cisco, Inc.
 * Copyright (c) 1999-2001 Motorola, Inc.
 * Copyright (c) 2001-2003 International Business Machines, Corp.
 * Copyright (c) 2001 Intel Corp.
 * Copyright (c) 2001 Nokia, Inc.
 * Copyright (c) 2001 La Monte H.P. Yarroll
 *
 * This file is part of the SCTP kernel implementation
 *
 * These functions handle all input from the IP layer into SCTP.
 *
 * Please send any bug reports or fixes you make to the
 * email address(es):
 *    lksctp developers <[email protected]>
 *
 * Written or modified by:
 *    La Monte H.P. Yarroll <[email protected]>
 *    Karl Knutson <[email protected]>
 *    Xingang Guo <[email protected]>
 *    Jon Grimm <[email protected]>
 *    Hui Huang <[email protected]>
 *    Daisy Chang <[email protected]>
 *    Sridhar Samudrala <[email protected]>
 *    Ardelle Fan <[email protected]>
 */

#include <linux/types.h>
#include <linux/list.h> /* For struct list_head */
#include <linux/socket.h>
#include <linux/ip.h>
#include <linux/time.h> /* For struct timeval */
#include <linux/slab.h>
#include <net/ip.h>
#include <net/icmp.h>
#include <net/snmp.h>
#include <net/sock.h>
#include <net/xfrm.h>
#include <net/sctp/sctp.h>
#include <net/sctp/sm.h>
#include <net/sctp/checksum.h>
#include <net/net_namespace.h>
#include <linux/rhashtable.h>
#include <net/sock_reuseport.h>

/* Forward declarations for internal helpers. */
static int sctp_rcv_ootb(struct sk_buff *);
static struct sctp_association *__sctp_rcv_lookup(struct net *net,
				      struct sk_buff *skb,
				      const union sctp_addr *paddr,
				      const union sctp_addr *laddr,
				      struct sctp_transport **transportp,
				      int dif, int sdif);
static struct sctp_endpoint *__sctp_rcv_lookup_endpoint(
					struct net *net, struct sk_buff *skb,
					const union sctp_addr *laddr,
					const union sctp_addr *daddr,
					int dif, int sdif);
static struct sctp_association *__sctp_lookup_association(
					struct net *net,
					const union sctp_addr *local,
					const union sctp_addr *peer,
					struct sctp_transport **pt,
					int dif, int sdif);

static int sctp_add_backlog(struct sock *sk, struct sk_buff *skb);


/* Calculate the SCTP checksum of an SCTP packet.  */
static inline int sctp_rcv_checksum(struct net *net, struct sk_buff *skb)
{}

/*
 * This is the routine which IP calls when receiving an SCTP packet.
 */
int sctp_rcv(struct sk_buff *skb)
{}

/* Process the backlog queue of the socket.  Every skb on
 * the backlog holds a ref on an association or endpoint.
 * We hold this ref throughout the state machine to make
 * sure that the structure we need is still around.
 */
int sctp_backlog_rcv(struct sock *sk, struct sk_buff *skb)
{}

static int sctp_add_backlog(struct sock *sk, struct sk_buff *skb)
{}

/* Handle icmp frag needed error. */
void sctp_icmp_frag_needed(struct sock *sk, struct sctp_association *asoc,
			   struct sctp_transport *t, __u32 pmtu)
{}

void sctp_icmp_redirect(struct sock *sk, struct sctp_transport *t,
			struct sk_buff *skb)
{}

/*
 * SCTP Implementer's Guide, 2.37 ICMP handling procedures
 *
 * ICMP8) If the ICMP code is a "Unrecognized next header type encountered"
 *        or a "Protocol Unreachable" treat this message as an abort
 *        with the T bit set.
 *
 * This function sends an event to the state machine, which will abort the
 * association.
 *
 */
void sctp_icmp_proto_unreachable(struct sock *sk,
			   struct sctp_association *asoc,
			   struct sctp_transport *t)
{}

/* Common lookup code for icmp/icmpv6 error handler. */
struct sock *sctp_err_lookup(struct net *net, int family, struct sk_buff *skb,
			     struct sctphdr *sctphdr,
			     struct sctp_association **app,
			     struct sctp_transport **tpp)
{}

/* Common cleanup code for icmp/icmpv6 error handler. */
void sctp_err_finish(struct sock *sk, struct sctp_transport *t)
	__releases(&((__sk)->sk_lock.slock))
{}

static void sctp_v4_err_handle(struct sctp_transport *t, struct sk_buff *skb,
			       __u8 type, __u8 code, __u32 info)
{}

/*
 * This routine is called by the ICMP module when it gets some
 * sort of error condition.  If err < 0 then the socket should
 * be closed and the error returned to the user.  If err > 0
 * it's just the icmp type << 8 | icmp code.  After adjustment
 * header points to the first 8 bytes of the sctp header.  We need
 * to find the appropriate port.
 *
 * The locking strategy used here is very "optimistic". When
 * someone else accesses the socket the ICMP is just dropped
 * and for some paths there is no check at all.
 * A more general error queue to queue errors for later handling
 * is probably better.
 *
 */
int sctp_v4_err(struct sk_buff *skb, __u32 info)
{}

int sctp_udp_v4_err(struct sock *sk, struct sk_buff *skb)
{}

/*
 * RFC 2960, 8.4 - Handle "Out of the blue" Packets.
 *
 * This function scans all the chunks in the OOTB packet to determine if
 * the packet should be discarded right away.  If a response might be needed
 * for this packet, or, if further processing is possible, the packet will
 * be queued to a proper inqueue for the next phase of handling.
 *
 * Output:
 * Return 0 - If further processing is needed.
 * Return 1 - If the packet can be discarded right away.
 */
static int sctp_rcv_ootb(struct sk_buff *skb)
{}

/* Insert endpoint into the hash table.  */
static int __sctp_hash_endpoint(struct sctp_endpoint *ep)
{}

/* Add an endpoint to the hash. Local BH-safe. */
int sctp_hash_endpoint(struct sctp_endpoint *ep)
{}

/* Remove endpoint from the hash table.  */
static void __sctp_unhash_endpoint(struct sctp_endpoint *ep)
{}

/* Remove endpoint from the hash.  Local BH-safe. */
void sctp_unhash_endpoint(struct sctp_endpoint *ep)
{}

static inline __u32 sctp_hashfn(const struct net *net, __be16 lport,
				const union sctp_addr *paddr, __u32 seed)
{}

/* Look up an endpoint. */
static struct sctp_endpoint *__sctp_rcv_lookup_endpoint(
					struct net *net, struct sk_buff *skb,
					const union sctp_addr *laddr,
					const union sctp_addr *paddr,
					int dif, int sdif)
{}

/* rhashtable for transport */
struct sctp_hash_cmp_arg {};

static inline int sctp_hash_cmp(struct rhashtable_compare_arg *arg,
				const void *ptr)
{}

static inline __u32 sctp_hash_obj(const void *data, u32 len, u32 seed)
{}

static inline __u32 sctp_hash_key(const void *data, u32 len, u32 seed)
{}

static const struct rhashtable_params sctp_hash_params =;

int sctp_transport_hashtable_init(void)
{}

void sctp_transport_hashtable_destroy(void)
{}

int sctp_hash_transport(struct sctp_transport *t)
{}

void sctp_unhash_transport(struct sctp_transport *t)
{}

bool sctp_sk_bound_dev_eq(struct net *net, int bound_dev_if, int dif, int sdif)
{}

/* return a transport with holding it */
struct sctp_transport *sctp_addrs_lookup_transport(
				struct net *net,
				const union sctp_addr *laddr,
				const union sctp_addr *paddr,
				int dif, int sdif)
{}

/* return a transport without holding it, as it's only used under sock lock */
struct sctp_transport *sctp_epaddr_lookup_transport(
				const struct sctp_endpoint *ep,
				const union sctp_addr *paddr)
{}

/* Look up an association. */
static struct sctp_association *__sctp_lookup_association(
					struct net *net,
					const union sctp_addr *local,
					const union sctp_addr *peer,
					struct sctp_transport **pt,
					int dif, int sdif)
{}

/* Look up an association. protected by RCU read lock */
static
struct sctp_association *sctp_lookup_association(struct net *net,
						 const union sctp_addr *laddr,
						 const union sctp_addr *paddr,
						 struct sctp_transport **transportp,
						 int dif, int sdif)
{}

/* Is there an association matching the given local and peer addresses? */
bool sctp_has_association(struct net *net,
			  const union sctp_addr *laddr,
			  const union sctp_addr *paddr,
			  int dif, int sdif)
{}

/*
 * SCTP Implementors Guide, 2.18 Handling of address
 * parameters within the INIT or INIT-ACK.
 *
 * D) When searching for a matching TCB upon reception of an INIT
 *    or INIT-ACK chunk the receiver SHOULD use not only the
 *    source address of the packet (containing the INIT or
 *    INIT-ACK) but the receiver SHOULD also use all valid
 *    address parameters contained within the chunk.
 *
 * 2.18.3 Solution description
 *
 * This new text clearly specifies to an implementor the need
 * to look within the INIT or INIT-ACK. Any implementation that
 * does not do this, may not be able to establish associations
 * in certain circumstances.
 *
 */
static struct sctp_association *__sctp_rcv_init_lookup(struct net *net,
	struct sk_buff *skb,
	const union sctp_addr *laddr, struct sctp_transport **transportp,
	int dif, int sdif)
{}

/* ADD-IP, Section 5.2
 * When an endpoint receives an ASCONF Chunk from the remote peer
 * special procedures may be needed to identify the association the
 * ASCONF Chunk is associated with. To properly find the association
 * the following procedures SHOULD be followed:
 *
 * D2) If the association is not found, use the address found in the
 * Address Parameter TLV combined with the port number found in the
 * SCTP common header. If found proceed to rule D4.
 *
 * D2-ext) If more than one ASCONF Chunks are packed together, use the
 * address found in the ASCONF Address Parameter TLV of each of the
 * subsequent ASCONF Chunks. If found, proceed to rule D4.
 */
static struct sctp_association *__sctp_rcv_asconf_lookup(
					struct net *net,
					struct sctp_chunkhdr *ch,
					const union sctp_addr *laddr,
					__be16 peer_port,
					struct sctp_transport **transportp,
					int dif, int sdif)
{}


/* SCTP-AUTH, Section 6.3:
*    If the receiver does not find a STCB for a packet containing an AUTH
*    chunk as the first chunk and not a COOKIE-ECHO chunk as the second
*    chunk, it MUST use the chunks after the AUTH chunk to look up an existing
*    association.
*
* This means that any chunks that can help us identify the association need
* to be looked at to find this association.
*/
static struct sctp_association *__sctp_rcv_walk_lookup(struct net *net,
				      struct sk_buff *skb,
				      const union sctp_addr *laddr,
				      struct sctp_transport **transportp,
				      int dif, int sdif)
{}

/*
 * There are circumstances when we need to look inside the SCTP packet
 * for information to help us find the association.   Examples
 * include looking inside of INIT/INIT-ACK chunks or after the AUTH
 * chunks.
 */
static struct sctp_association *__sctp_rcv_lookup_harder(struct net *net,
				      struct sk_buff *skb,
				      const union sctp_addr *laddr,
				      struct sctp_transport **transportp,
				      int dif, int sdif)
{}

/* Lookup an association for an inbound skb. */
static struct sctp_association *__sctp_rcv_lookup(struct net *net,
				      struct sk_buff *skb,
				      const union sctp_addr *paddr,
				      const union sctp_addr *laddr,
				      struct sctp_transport **transportp,
				      int dif, int sdif)
{}