9747 lines · 265.5 KB · C
RawDownload
// SPDX-License-Identifier: GPL-2.0-or-later/* SCTP kernel implementation * (C) Copyright IBM Corp. 2001, 2004 * Copyright (c) 1999-2000 Cisco, Inc. * Copyright (c) 1999-2001 Motorola, Inc. * Copyright (c) 2001-2003 Intel Corp. * Copyright (c) 2001-2002 Nokia, Inc. * Copyright (c) 2001 La Monte H.P. Yarroll * * This file is part of the SCTP kernel implementation * * These functions interface with the sockets layer to implement the * SCTP Extensions for the Sockets API. * * Note that the descriptions from the specification are USER level * functions--this file is the functions which populate the struct proto * for SCTP which is the BOTTOM of the sockets interface. * * Please send any bug reports or fixes you make to the * email address(es): *    lksctp developers <linux-sctp@vger.kernel.org> * * Written or modified by: *    La Monte H.P. Yarroll <piggy@acm.org> *    Narasimha Budihal     <narsi@refcode.org> *    Karl Knutson          <karl@athena.chicago.il.us> *    Jon Grimm             <jgrimm@us.ibm.com> *    Xingang Guo           <xingang.guo@intel.com> *    Daisy Chang           <daisyc@us.ibm.com> *    Sridhar Samudrala     <samudrala@us.ibm.com> *    Inaky Perez-Gonzalez  <inaky.gonzalez@intel.com> *    Ardelle Fan	    <ardelle.fan@intel.com> *    Ryan Layer	    <rmlayer@us.ibm.com> *    Anup Pemmaiah         <pemmaiah@cc.usu.edu> *    Kevin Gao             <kevin.gao@intel.com> */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include <linux/types.h>#include <linux/kernel.h>#include <linux/wait.h>#include <linux/time.h>#include <linux/sched/signal.h>#include <linux/ip.h>#include <linux/capability.h>#include <linux/fcntl.h>#include <linux/poll.h>#include <linux/init.h>#include <linux/slab.h>#include <linux/file.h>#include <linux/compat.h>#include <linux/rhashtable.h> #include <net/ip.h>#include <net/icmp.h>#include <net/route.h>#include <net/ipv6.h>#include <net/inet_common.h>#include <net/busy_poll.h>#include <trace/events/sock.h> #include <linux/socket.h> /* for sa_family_t */#include <linux/export.h>#include <net/sock.h>#include <net/sctp/sctp.h>#include <net/sctp/sm.h>#include <net/sctp/stream_sched.h>#include <net/rps.h> /* Forward declarations for internal helper functions. */static bool sctp_writeable(const struct sock *sk);static void sctp_wfree(struct sk_buff *skb);static int sctp_wait_for_sndbuf(struct sctp_association *asoc,				struct sctp_transport *transport,				long *timeo_p, size_t msg_len);static int sctp_wait_for_packet(struct sock *sk, int *err, long *timeo_p);static int sctp_wait_for_connect(struct sctp_association *, long *timeo_p);static int sctp_wait_for_accept(struct sock *sk, long timeo);static void sctp_wait_for_close(struct sock *sk, long timeo);static void sctp_destruct_sock(struct sock *sk);static struct sctp_af *sctp_sockaddr_af(struct sctp_sock *opt,					union sctp_addr *addr, int len);static int sctp_bindx_add(struct sock *, struct sockaddr *, int);static int sctp_bindx_rem(struct sock *, struct sockaddr *, int);static int sctp_send_asconf_add_ip(struct sock *, struct sockaddr *, int);static int sctp_send_asconf_del_ip(struct sock *, struct sockaddr *, int);static int sctp_send_asconf(struct sctp_association *asoc,			    struct sctp_chunk *chunk);static int sctp_do_bind(struct sock *, union sctp_addr *, int);static int sctp_autobind(struct sock *sk);static int sctp_sock_migrate(struct sock *oldsk, struct sock *newsk,			     struct sctp_association *assoc,			     enum sctp_socket_type type); static unsigned long sctp_memory_pressure;static atomic_long_t sctp_memory_allocated;static DEFINE_PER_CPU(int, sctp_memory_per_cpu_fw_alloc);struct percpu_counter sctp_sockets_allocated; static void sctp_enter_memory_pressure(struct sock *sk){	WRITE_ONCE(sctp_memory_pressure, 1);}  /* Get the sndbuf space available at the time on the association.  */static inline int sctp_wspace(struct sctp_association *asoc){	struct sock *sk = asoc->base.sk; 	return asoc->ep->sndbuf_policy ? sk->sk_sndbuf - asoc->sndbuf_used				       : sk_stream_wspace(sk);} /* Increment the used sndbuf space count of the corresponding association by * the size of the outgoing data chunk. * Also, set the skb destructor for sndbuf accounting later. * * Since it is always 1-1 between chunk and skb, and also a new skb is always * allocated for chunk bundling in sctp_packet_transmit(), we can use the * destructor in the data chunk skb for the purpose of the sndbuf space * tracking. */static inline void sctp_set_owner_w(struct sctp_chunk *chunk){	struct sctp_association *asoc = chunk->asoc;	struct sock *sk = asoc->base.sk; 	/* The sndbuf space is tracked per association.  */	sctp_association_hold(asoc); 	if (chunk->shkey)		sctp_auth_shkey_hold(chunk->shkey); 	skb_set_owner_w(chunk->skb, sk); 	chunk->skb->destructor = sctp_wfree;	/* Save the chunk pointer in skb for sctp_wfree to use later.  */	skb_shinfo(chunk->skb)->destructor_arg = chunk; 	refcount_add(sizeof(struct sctp_chunk), &sk->sk_wmem_alloc);	asoc->sndbuf_used += chunk->skb->truesize + sizeof(struct sctp_chunk);	sk_wmem_queued_add(sk, chunk->skb->truesize + sizeof(struct sctp_chunk));	sk_mem_charge(sk, chunk->skb->truesize);} static void sctp_clear_owner_w(struct sctp_chunk *chunk){	skb_orphan(chunk->skb);} #define traverse_and_process()	\do {				\	msg = chunk->msg;	\	if (msg == prev_msg)	\		continue;	\	list_for_each_entry(c, &msg->chunks, frag_list) {	\		if ((clear && asoc->base.sk == c->skb->sk) ||	\		    (!clear && asoc->base.sk != c->skb->sk))	\			cb(c);	\	}			\	prev_msg = msg;		\} while (0) static void sctp_for_each_tx_datachunk(struct sctp_association *asoc,				       bool clear,				       void (*cb)(struct sctp_chunk *)) {	struct sctp_datamsg *msg, *prev_msg = NULL;	struct sctp_outq *q = &asoc->outqueue;	struct sctp_chunk *chunk, *c;	struct sctp_transport *t; 	list_for_each_entry(t, &asoc->peer.transport_addr_list, transports)		list_for_each_entry(chunk, &t->transmitted, transmitted_list)			traverse_and_process(); 	list_for_each_entry(chunk, &q->retransmit, transmitted_list)		traverse_and_process(); 	list_for_each_entry(chunk, &q->sacked, transmitted_list)		traverse_and_process(); 	list_for_each_entry(chunk, &q->abandoned, transmitted_list)		traverse_and_process(); 	list_for_each_entry(chunk, &q->out_chunk_list, list)		traverse_and_process();} static void sctp_for_each_rx_skb(struct sctp_association *asoc, struct sock *sk,				 void (*cb)(struct sk_buff *, struct sock *)) {	struct sk_buff *skb, *tmp; 	sctp_skb_for_each(skb, &asoc->ulpq.lobby, tmp)		cb(skb, sk); 	sctp_skb_for_each(skb, &asoc->ulpq.reasm, tmp)		cb(skb, sk); 	sctp_skb_for_each(skb, &asoc->ulpq.reasm_uo, tmp)		cb(skb, sk);} /* Verify that this is a valid address. */static inline int sctp_verify_addr(struct sock *sk, union sctp_addr *addr,				   int len){	struct sctp_af *af; 	/* Verify basic sockaddr. */	af = sctp_sockaddr_af(sctp_sk(sk), addr, len);	if (!af)		return -EINVAL; 	/* Is this a valid SCTP address?  */	if (!af->addr_valid(addr, sctp_sk(sk), NULL))		return -EINVAL; 	if (!sctp_sk(sk)->pf->send_verify(sctp_sk(sk), (addr)))		return -EINVAL; 	return 0;} /* Look up the association by its id.  If this is not a UDP-style * socket, the ID field is always ignored. */struct sctp_association *sctp_id2assoc(struct sock *sk, sctp_assoc_t id){	struct sctp_association *asoc = NULL; 	/* If this is not a UDP-style socket, assoc id should be ignored. */	if (!sctp_style(sk, UDP)) {		/* Return NULL if the socket state is not ESTABLISHED. It		 * could be a TCP-style listening socket or a socket which		 * hasn't yet called connect() to establish an association.		 */		if (!sctp_sstate(sk, ESTABLISHED) && !sctp_sstate(sk, CLOSING))			return NULL; 		/* Get the first and the only association from the list. */		if (!list_empty(&sctp_sk(sk)->ep->asocs))			asoc = list_entry(sctp_sk(sk)->ep->asocs.next,					  struct sctp_association, asocs);		return asoc;	} 	/* Otherwise this is a UDP-style socket. */	if (id <= SCTP_ALL_ASSOC)		return NULL; 	spin_lock_bh(&sctp_assocs_id_lock);	asoc = (struct sctp_association *)idr_find(&sctp_assocs_id, (int)id);	if (asoc && (asoc->base.sk != sk || asoc->base.dead))		asoc = NULL;	spin_unlock_bh(&sctp_assocs_id_lock); 	return asoc;} /* Look up the transport from an address and an assoc id. If both address and * id are specified, the associations matching the address and the id should be * the same. */static struct sctp_transport *sctp_addr_id2transport(struct sock *sk,					      struct sockaddr_storage *addr,					      sctp_assoc_t id){	struct sctp_association *addr_asoc = NULL, *id_asoc = NULL;	struct sctp_af *af = sctp_get_af_specific(addr->ss_family);	union sctp_addr *laddr = (union sctp_addr *)addr;	struct sctp_transport *transport; 	if (!af || sctp_verify_addr(sk, laddr, af->sockaddr_len))		return NULL; 	addr_asoc = sctp_endpoint_lookup_assoc(sctp_sk(sk)->ep,					       laddr,					       &transport); 	if (!addr_asoc)		return NULL; 	id_asoc = sctp_id2assoc(sk, id);	if (id_asoc && (id_asoc != addr_asoc))		return NULL; 	sctp_get_pf_specific(sk->sk_family)->addr_to_user(sctp_sk(sk),						(union sctp_addr *)addr); 	return transport;} /* API 3.1.2 bind() - UDP Style Syntax * The syntax of bind() is, * *   ret = bind(int sd, struct sockaddr *addr, int addrlen); * *   sd      - the socket descriptor returned by socket(). *   addr    - the address structure (struct sockaddr_in or struct *             sockaddr_in6 [RFC 2553]), *   addr_len - the size of the address structure. */static int sctp_bind(struct sock *sk, struct sockaddr_unsized *addr,		     int addr_len){	int retval = 0; 	lock_sock(sk); 	pr_debug("%s: sk:%p, addr:%p, addr_len:%d\n", __func__, sk,		 addr, addr_len); 	/* Disallow binding twice. */	if (!sctp_sk(sk)->ep->base.bind_addr.port)		retval = sctp_do_bind(sk, (union sctp_addr *)addr,				      addr_len);	else		retval = -EINVAL; 	release_sock(sk); 	return retval;} static int sctp_get_port_local(struct sock *, union sctp_addr *); /* Verify this is a valid sockaddr. */static struct sctp_af *sctp_sockaddr_af(struct sctp_sock *opt,					union sctp_addr *addr, int len){	struct sctp_af *af; 	/* Check minimum size.  */	if (len < sizeof (struct sockaddr))		return NULL; 	if (!opt->pf->af_supported(addr->sa.sa_family, opt))		return NULL; 	if (addr->sa.sa_family == AF_INET6) {		if (len < SIN6_LEN_RFC2133)			return NULL;		/* V4 mapped address are really of AF_INET family */		if (ipv6_addr_v4mapped(&addr->v6.sin6_addr) &&		    !opt->pf->af_supported(AF_INET, opt))			return NULL;	} 	/* If we get this far, af is valid. */	af = sctp_get_af_specific(addr->sa.sa_family); 	if (len < af->sockaddr_len)		return NULL; 	return af;} static void sctp_auto_asconf_init(struct sctp_sock *sp){	struct net *net = sock_net(&sp->inet.sk); 	if (net->sctp.default_auto_asconf) {		spin_lock_bh(&net->sctp.addr_wq_lock);		list_add_tail(&sp->auto_asconf_list, &net->sctp.auto_asconf_splist);		spin_unlock_bh(&net->sctp.addr_wq_lock);		sp->do_auto_asconf = 1;	}} /* Bind a local address either to an endpoint or to an association.  */static int sctp_do_bind(struct sock *sk, union sctp_addr *addr, int len){	struct net *net = sock_net(sk);	struct sctp_sock *sp = sctp_sk(sk);	struct sctp_endpoint *ep = sp->ep;	struct sctp_bind_addr *bp = &ep->base.bind_addr;	struct sctp_af *af;	unsigned short snum;	int ret = 0; 	/* Common sockaddr verification. */	af = sctp_sockaddr_af(sp, addr, len);	if (!af) {		pr_debug("%s: sk:%p, newaddr:%p, len:%d EINVAL\n",			 __func__, sk, addr, len);		return -EINVAL;	} 	snum = ntohs(addr->v4.sin_port); 	pr_debug("%s: sk:%p, new addr:%pISc, port:%d, new port:%d, len:%d\n",		 __func__, sk, &addr->sa, bp->port, snum, len); 	/* PF specific bind() address verification. */	if (!sp->pf->bind_verify(sp, addr))		return -EADDRNOTAVAIL; 	/* We must either be unbound, or bind to the same port.	 * It's OK to allow 0 ports if we are already bound.	 * We'll just inhert an already bound port in this case	 */	if (bp->port) {		if (!snum)			snum = bp->port;		else if (snum != bp->port) {			pr_debug("%s: new port %d doesn't match existing port "				 "%d\n", __func__, snum, bp->port);			return -EINVAL;		}	} 	if (snum && inet_port_requires_bind_service(net, snum) &&	    !ns_capable(net->user_ns, CAP_NET_BIND_SERVICE))		return -EACCES; 	/* See if the address matches any of the addresses we may have	 * already bound before checking against other endpoints.	 */	if (sctp_bind_addr_match(bp, addr, sp))		return -EINVAL; 	/* Make sure we are allowed to bind here.	 * The function sctp_get_port_local() does duplicate address	 * detection.	 */	addr->v4.sin_port = htons(snum);	if (sctp_get_port_local(sk, addr))		return -EADDRINUSE; 	/* Refresh ephemeral port.  */	if (!bp->port) {		bp->port = inet_sk(sk)->inet_num;		sctp_auto_asconf_init(sp);	} 	/* Add the address to the bind address list.	 * Use GFP_ATOMIC since BHs will be disabled.	 */	ret = sctp_add_bind_addr(bp, addr, af->sockaddr_len,				 SCTP_ADDR_SRC, GFP_ATOMIC); 	if (ret) {		sctp_put_port(sk);		return ret;	}	/* Copy back into socket for getsockname() use. */	inet_sk(sk)->inet_sport = htons(inet_sk(sk)->inet_num);	sp->pf->to_sk_saddr(addr, sk); 	return ret;}  /* ADDIP Section 4.1.1 Congestion Control of ASCONF Chunks * * R1) One and only one ASCONF Chunk MAY be in transit and unacknowledged * at any one time.  If a sender, after sending an ASCONF chunk, decides * it needs to transfer another ASCONF Chunk, it MUST wait until the * ASCONF-ACK Chunk returns from the previous ASCONF Chunk before sending a * subsequent ASCONF. Note this restriction binds each side, so at any * time two ASCONF may be in-transit on any given association (one sent * from each endpoint). */static int sctp_send_asconf(struct sctp_association *asoc,			    struct sctp_chunk *chunk){	int retval = 0; 	/* If there is an outstanding ASCONF chunk, queue it for later	 * transmission.	 */	if (asoc->addip_last_asconf) {		list_add_tail(&chunk->list, &asoc->addip_chunk_list);		goto out;	} 	/* Hold the chunk until an ASCONF_ACK is received. */	sctp_chunk_hold(chunk);	retval = sctp_primitive_ASCONF(asoc->base.net, asoc, chunk);	if (retval)		sctp_chunk_free(chunk);	else		asoc->addip_last_asconf = chunk; out:	return retval;} /* Add a list of addresses as bind addresses to local endpoint or * association. * * Basically run through each address specified in the addrs/addrcnt * array/length pair, determine if it is IPv6 or IPv4 and call * sctp_do_bind() on it. *

Lines 1–500 of 9747.