7096 lines · 199.8 KB · C
RawDownload
/* 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. * * This SCTP implementation is free software; * you can redistribute it and/or modify it under the terms of * the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This SCTP implementation is distributed in the hope that it * will be useful, but WITHOUT ANY WARRANTY; without even the implied *                 ************************ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with GNU CC; see the file COPYING.  If not, write to * the Free Software Foundation, 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. * * 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/ip.h>#include <linux/capability.h>#include <linux/fcntl.h>#include <linux/poll.h>#include <linux/init.h>#include <linux/crypto.h>#include <linux/slab.h>#include <linux/file.h> #include <net/ip.h>#include <net/icmp.h>#include <net/route.h>#include <net/ipv6.h>#include <net/inet_common.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> /* Forward declarations for internal helper functions. */static int sctp_writeable(struct sock *sk);static void sctp_wfree(struct sk_buff *skb);static int sctp_wait_for_sndbuf(struct sctp_association *, 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 void sctp_sock_migrate(struct sock *, struct sock *,			      struct sctp_association *, sctp_socket_type_t); extern struct kmem_cache *sctp_bucket_cachep;extern long sysctl_sctp_mem[3];extern int sysctl_sctp_rmem[3];extern int sysctl_sctp_wmem[3]; static int sctp_memory_pressure;static atomic_long_t sctp_memory_allocated;struct percpu_counter sctp_sockets_allocated; static void sctp_enter_memory_pressure(struct sock *sk){	sctp_memory_pressure = 1;}  /* Get the sndbuf space available at the time on the association.  */static inline int sctp_wspace(struct sctp_association *asoc){	int amt; 	if (asoc->ep->sndbuf_policy)		amt = asoc->sndbuf_used;	else		amt = sk_wmem_alloc_get(asoc->base.sk); 	if (amt >= asoc->base.sk->sk_sndbuf) {		if (asoc->base.sk->sk_userlocks & SOCK_SNDBUF_LOCK)			amt = 0;		else {			amt = sk_stream_wspace(asoc->base.sk);			if (amt < 0)				amt = 0;		}	} else {		amt = asoc->base.sk->sk_sndbuf - amt;	}	return amt;} /* 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); 	skb_set_owner_w(chunk->skb, sk); 	chunk->skb->destructor = sctp_wfree;	/* Save the chunk pointer in skb for sctp_wfree to use later.  */	*((struct sctp_chunk **)(chunk->skb->cb)) = chunk; 	asoc->sndbuf_used += SCTP_DATA_SNDSIZE(chunk) +				sizeof(struct sk_buff) +				sizeof(struct sctp_chunk); 	atomic_add(sizeof(struct sctp_chunk), &sk->sk_wmem_alloc);	sk->sk_wmem_queued += chunk->skb->truesize;	sk_mem_charge(sk, chunk->skb->truesize);} /* 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))			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 || (id == (sctp_assoc_t)-1))		return NULL; 	spin_lock_bh(&sctp_assocs_id_lock);	asoc = (struct sctp_association *)idr_find(&sctp_assocs_id, (int)id);	spin_unlock_bh(&sctp_assocs_id_lock); 	if (!asoc || (asoc->base.sk != sk) || asoc->base.dead)		return NULL; 	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_transport *transport;	union sctp_addr *laddr = (union sctp_addr *)addr; 	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_v4map(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 *addr, int addr_len){	int retval = 0; 	sctp_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; 	sctp_release_sock(sk); 	return retval;} static long 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; 	/* V4 mapped address are really of AF_INET family */	if (addr->sa.sa_family == AF_INET6 &&	    ipv6_addr_v4mapped(&addr->v6.sin6_addr)) {		if (!opt->pf->af_supported(AF_INET, opt))			return NULL;	} else {		/* Does this PF support this AF? */		if (!opt->pf->af_supported(addr->sa.sa_family, 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;} /* 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 && snum < PROT_SOCK &&	    !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 ((ret = sctp_get_port_local(sk, addr))) {		return -EADDRINUSE;	} 	/* Refresh ephemeral port.  */	if (!bp->port)		bp->port = inet_sk(sk)->inet_num; 	/* Add the address to the bind address list.	 * Use GFP_ATOMIC since BHs will be disabled.	 */	ret = sctp_add_bind_addr(bp, addr, SCTP_ADDR_SRC, GFP_ATOMIC); 	/* Copy back into socket for getsockname() use. */	if (!ret) {		inet_sk(sk)->inet_sport = htons(inet_sk(sk)->inet_num);		af->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){	struct net 	*net = sock_net(asoc->base.sk);	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(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. * * If any of them fails, then the operation will be reversed and the * ones that were added will be removed. * * Only sctp_setsockopt_bindx() is supposed to call this function. */static int sctp_bindx_add(struct sock *sk, struct sockaddr *addrs, int addrcnt){	int cnt;	int retval = 0;	void *addr_buf;	struct sockaddr *sa_addr;	struct sctp_af *af; 	pr_debug("%s: sk:%p, addrs:%p, addrcnt:%d\n", __func__, sk,		 addrs, addrcnt); 	addr_buf = addrs;	for (cnt = 0; cnt < addrcnt; cnt++) {		/* The list may contain either IPv4 or IPv6 address;		 * determine the address length for walking thru the list.		 */		sa_addr = addr_buf;		af = sctp_get_af_specific(sa_addr->sa_family);		if (!af) {			retval = -EINVAL;			goto err_bindx_add;		} 		retval = sctp_do_bind(sk, (union sctp_addr *)sa_addr,				      af->sockaddr_len); 		addr_buf += af->sockaddr_len; err_bindx_add:		if (retval < 0) {			/* Failed. Cleanup the ones that have been added */			if (cnt > 0)				sctp_bindx_rem(sk, addrs, cnt);			return retval;		}	} 	return retval;} /* Send an ASCONF chunk with Add IP address parameters to all the peers of the * associations that are part of the endpoint indicating that a list of local * addresses are added to the endpoint. * * If any of the addresses is already in the bind address list of the * association, we do not send the chunk for that association.  But it will not * affect other associations. * * Only sctp_setsockopt_bindx() is supposed to call this function.

Lines 1–500 of 7096.