xref: /openbmc/linux/net/sctp/socket.c (revision eaa5c54dbec70e2a93d6ed412bb589bbf9c90a17)
11da177e4SLinus Torvalds /* SCTP kernel reference Implementation
21da177e4SLinus Torvalds  * (C) Copyright IBM Corp. 2001, 2004
31da177e4SLinus Torvalds  * Copyright (c) 1999-2000 Cisco, Inc.
41da177e4SLinus Torvalds  * Copyright (c) 1999-2001 Motorola, Inc.
51da177e4SLinus Torvalds  * Copyright (c) 2001-2003 Intel Corp.
61da177e4SLinus Torvalds  * Copyright (c) 2001-2002 Nokia, Inc.
71da177e4SLinus Torvalds  * Copyright (c) 2001 La Monte H.P. Yarroll
81da177e4SLinus Torvalds  *
91da177e4SLinus Torvalds  * This file is part of the SCTP kernel reference Implementation
101da177e4SLinus Torvalds  *
111da177e4SLinus Torvalds  * These functions interface with the sockets layer to implement the
121da177e4SLinus Torvalds  * SCTP Extensions for the Sockets API.
131da177e4SLinus Torvalds  *
141da177e4SLinus Torvalds  * Note that the descriptions from the specification are USER level
151da177e4SLinus Torvalds  * functions--this file is the functions which populate the struct proto
161da177e4SLinus Torvalds  * for SCTP which is the BOTTOM of the sockets interface.
171da177e4SLinus Torvalds  *
181da177e4SLinus Torvalds  * The SCTP reference implementation is free software;
191da177e4SLinus Torvalds  * you can redistribute it and/or modify it under the terms of
201da177e4SLinus Torvalds  * the GNU General Public License as published by
211da177e4SLinus Torvalds  * the Free Software Foundation; either version 2, or (at your option)
221da177e4SLinus Torvalds  * any later version.
231da177e4SLinus Torvalds  *
241da177e4SLinus Torvalds  * The SCTP reference implementation is distributed in the hope that it
251da177e4SLinus Torvalds  * will be useful, but WITHOUT ANY WARRANTY; without even the implied
261da177e4SLinus Torvalds  *                 ************************
271da177e4SLinus Torvalds  * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
281da177e4SLinus Torvalds  * See the GNU General Public License for more details.
291da177e4SLinus Torvalds  *
301da177e4SLinus Torvalds  * You should have received a copy of the GNU General Public License
311da177e4SLinus Torvalds  * along with GNU CC; see the file COPYING.  If not, write to
321da177e4SLinus Torvalds  * the Free Software Foundation, 59 Temple Place - Suite 330,
331da177e4SLinus Torvalds  * Boston, MA 02111-1307, USA.
341da177e4SLinus Torvalds  *
351da177e4SLinus Torvalds  * Please send any bug reports or fixes you make to the
361da177e4SLinus Torvalds  * email address(es):
371da177e4SLinus Torvalds  *    lksctp developers <lksctp-developers@lists.sourceforge.net>
381da177e4SLinus Torvalds  *
391da177e4SLinus Torvalds  * Or submit a bug report through the following website:
401da177e4SLinus Torvalds  *    http://www.sf.net/projects/lksctp
411da177e4SLinus Torvalds  *
421da177e4SLinus Torvalds  * Written or modified by:
431da177e4SLinus Torvalds  *    La Monte H.P. Yarroll <piggy@acm.org>
441da177e4SLinus Torvalds  *    Narasimha Budihal     <narsi@refcode.org>
451da177e4SLinus Torvalds  *    Karl Knutson          <karl@athena.chicago.il.us>
461da177e4SLinus Torvalds  *    Jon Grimm             <jgrimm@us.ibm.com>
471da177e4SLinus Torvalds  *    Xingang Guo           <xingang.guo@intel.com>
481da177e4SLinus Torvalds  *    Daisy Chang           <daisyc@us.ibm.com>
491da177e4SLinus Torvalds  *    Sridhar Samudrala     <samudrala@us.ibm.com>
501da177e4SLinus Torvalds  *    Inaky Perez-Gonzalez  <inaky.gonzalez@intel.com>
511da177e4SLinus Torvalds  *    Ardelle Fan	    <ardelle.fan@intel.com>
521da177e4SLinus Torvalds  *    Ryan Layer	    <rmlayer@us.ibm.com>
531da177e4SLinus Torvalds  *    Anup Pemmaiah         <pemmaiah@cc.usu.edu>
541da177e4SLinus Torvalds  *    Kevin Gao             <kevin.gao@intel.com>
551da177e4SLinus Torvalds  *
561da177e4SLinus Torvalds  * Any bugs reported given to us we will try to fix... any fixes shared will
571da177e4SLinus Torvalds  * be incorporated into the next SCTP release.
581da177e4SLinus Torvalds  */
591da177e4SLinus Torvalds 
601da177e4SLinus Torvalds #include <linux/config.h>
611da177e4SLinus Torvalds #include <linux/types.h>
621da177e4SLinus Torvalds #include <linux/kernel.h>
631da177e4SLinus Torvalds #include <linux/wait.h>
641da177e4SLinus Torvalds #include <linux/time.h>
651da177e4SLinus Torvalds #include <linux/ip.h>
661da177e4SLinus Torvalds #include <linux/fcntl.h>
671da177e4SLinus Torvalds #include <linux/poll.h>
681da177e4SLinus Torvalds #include <linux/init.h>
691da177e4SLinus Torvalds #include <linux/crypto.h>
701da177e4SLinus Torvalds 
711da177e4SLinus Torvalds #include <net/ip.h>
721da177e4SLinus Torvalds #include <net/icmp.h>
731da177e4SLinus Torvalds #include <net/route.h>
741da177e4SLinus Torvalds #include <net/ipv6.h>
751da177e4SLinus Torvalds #include <net/inet_common.h>
761da177e4SLinus Torvalds 
771da177e4SLinus Torvalds #include <linux/socket.h> /* for sa_family_t */
781da177e4SLinus Torvalds #include <net/sock.h>
791da177e4SLinus Torvalds #include <net/sctp/sctp.h>
801da177e4SLinus Torvalds #include <net/sctp/sm.h>
811da177e4SLinus Torvalds 
821da177e4SLinus Torvalds /* WARNING:  Please do not remove the SCTP_STATIC attribute to
831da177e4SLinus Torvalds  * any of the functions below as they are used to export functions
841da177e4SLinus Torvalds  * used by a project regression testsuite.
851da177e4SLinus Torvalds  */
861da177e4SLinus Torvalds 
871da177e4SLinus Torvalds /* Forward declarations for internal helper functions. */
881da177e4SLinus Torvalds static int sctp_writeable(struct sock *sk);
891da177e4SLinus Torvalds static void sctp_wfree(struct sk_buff *skb);
901da177e4SLinus Torvalds static int sctp_wait_for_sndbuf(struct sctp_association *, long *timeo_p,
911da177e4SLinus Torvalds 				size_t msg_len);
921da177e4SLinus Torvalds static int sctp_wait_for_packet(struct sock * sk, int *err, long *timeo_p);
931da177e4SLinus Torvalds static int sctp_wait_for_connect(struct sctp_association *, long *timeo_p);
941da177e4SLinus Torvalds static int sctp_wait_for_accept(struct sock *sk, long timeo);
951da177e4SLinus Torvalds static void sctp_wait_for_close(struct sock *sk, long timeo);
961da177e4SLinus Torvalds static struct sctp_af *sctp_sockaddr_af(struct sctp_sock *opt,
971da177e4SLinus Torvalds 					union sctp_addr *addr, int len);
981da177e4SLinus Torvalds static int sctp_bindx_add(struct sock *, struct sockaddr *, int);
991da177e4SLinus Torvalds static int sctp_bindx_rem(struct sock *, struct sockaddr *, int);
1001da177e4SLinus Torvalds static int sctp_send_asconf_add_ip(struct sock *, struct sockaddr *, int);
1011da177e4SLinus Torvalds static int sctp_send_asconf_del_ip(struct sock *, struct sockaddr *, int);
1021da177e4SLinus Torvalds static int sctp_send_asconf(struct sctp_association *asoc,
1031da177e4SLinus Torvalds 			    struct sctp_chunk *chunk);
1041da177e4SLinus Torvalds static int sctp_do_bind(struct sock *, union sctp_addr *, int);
1051da177e4SLinus Torvalds static int sctp_autobind(struct sock *sk);
1061da177e4SLinus Torvalds static void sctp_sock_migrate(struct sock *, struct sock *,
1071da177e4SLinus Torvalds 			      struct sctp_association *, sctp_socket_type_t);
1081da177e4SLinus Torvalds static char *sctp_hmac_alg = SCTP_COOKIE_HMAC_ALG;
1091da177e4SLinus Torvalds 
1101da177e4SLinus Torvalds extern kmem_cache_t *sctp_bucket_cachep;
1111da177e4SLinus Torvalds 
1121da177e4SLinus Torvalds /* Get the sndbuf space available at the time on the association.  */
1131da177e4SLinus Torvalds static inline int sctp_wspace(struct sctp_association *asoc)
1141da177e4SLinus Torvalds {
1151da177e4SLinus Torvalds 	struct sock *sk = asoc->base.sk;
1161da177e4SLinus Torvalds 	int amt = 0;
1171da177e4SLinus Torvalds 
1184eb701dfSNeil Horman 	if (asoc->ep->sndbuf_policy) {
1194eb701dfSNeil Horman 		/* make sure that no association uses more than sk_sndbuf */
1201da177e4SLinus Torvalds 		amt = sk->sk_sndbuf - asoc->sndbuf_used;
1214eb701dfSNeil Horman 	} else {
1224eb701dfSNeil Horman 		/* do socket level accounting */
1234eb701dfSNeil Horman 		amt = sk->sk_sndbuf - atomic_read(&sk->sk_wmem_alloc);
1244eb701dfSNeil Horman 	}
1254eb701dfSNeil Horman 
1261da177e4SLinus Torvalds 	if (amt < 0)
1271da177e4SLinus Torvalds 		amt = 0;
1284eb701dfSNeil Horman 
1291da177e4SLinus Torvalds 	return amt;
1301da177e4SLinus Torvalds }
1311da177e4SLinus Torvalds 
1321da177e4SLinus Torvalds /* Increment the used sndbuf space count of the corresponding association by
1331da177e4SLinus Torvalds  * the size of the outgoing data chunk.
1341da177e4SLinus Torvalds  * Also, set the skb destructor for sndbuf accounting later.
1351da177e4SLinus Torvalds  *
1361da177e4SLinus Torvalds  * Since it is always 1-1 between chunk and skb, and also a new skb is always
1371da177e4SLinus Torvalds  * allocated for chunk bundling in sctp_packet_transmit(), we can use the
1381da177e4SLinus Torvalds  * destructor in the data chunk skb for the purpose of the sndbuf space
1391da177e4SLinus Torvalds  * tracking.
1401da177e4SLinus Torvalds  */
1411da177e4SLinus Torvalds static inline void sctp_set_owner_w(struct sctp_chunk *chunk)
1421da177e4SLinus Torvalds {
1431da177e4SLinus Torvalds 	struct sctp_association *asoc = chunk->asoc;
1441da177e4SLinus Torvalds 	struct sock *sk = asoc->base.sk;
1451da177e4SLinus Torvalds 
1461da177e4SLinus Torvalds 	/* The sndbuf space is tracked per association.  */
1471da177e4SLinus Torvalds 	sctp_association_hold(asoc);
1481da177e4SLinus Torvalds 
1494eb701dfSNeil Horman 	skb_set_owner_w(chunk->skb, sk);
1504eb701dfSNeil Horman 
1511da177e4SLinus Torvalds 	chunk->skb->destructor = sctp_wfree;
1521da177e4SLinus Torvalds 	/* Save the chunk pointer in skb for sctp_wfree to use later.  */
1531da177e4SLinus Torvalds 	*((struct sctp_chunk **)(chunk->skb->cb)) = chunk;
1541da177e4SLinus Torvalds 
1554eb701dfSNeil Horman 	asoc->sndbuf_used += SCTP_DATA_SNDSIZE(chunk) +
1564eb701dfSNeil Horman 				sizeof(struct sk_buff) +
1574eb701dfSNeil Horman 				sizeof(struct sctp_chunk);
1584eb701dfSNeil Horman 
1594eb701dfSNeil Horman 	sk->sk_wmem_queued += SCTP_DATA_SNDSIZE(chunk) +
1604eb701dfSNeil Horman 				sizeof(struct sk_buff) +
1614eb701dfSNeil Horman 				sizeof(struct sctp_chunk);
1624eb701dfSNeil Horman 
1634eb701dfSNeil Horman 	atomic_add(sizeof(struct sctp_chunk), &sk->sk_wmem_alloc);
1641da177e4SLinus Torvalds }
1651da177e4SLinus Torvalds 
1661da177e4SLinus Torvalds /* Verify that this is a valid address. */
1671da177e4SLinus Torvalds static inline int sctp_verify_addr(struct sock *sk, union sctp_addr *addr,
1681da177e4SLinus Torvalds 				   int len)
1691da177e4SLinus Torvalds {
1701da177e4SLinus Torvalds 	struct sctp_af *af;
1711da177e4SLinus Torvalds 
1721da177e4SLinus Torvalds 	/* Verify basic sockaddr. */
1731da177e4SLinus Torvalds 	af = sctp_sockaddr_af(sctp_sk(sk), addr, len);
1741da177e4SLinus Torvalds 	if (!af)
1751da177e4SLinus Torvalds 		return -EINVAL;
1761da177e4SLinus Torvalds 
1771da177e4SLinus Torvalds 	/* Is this a valid SCTP address?  */
1781da177e4SLinus Torvalds 	if (!af->addr_valid(addr, sctp_sk(sk)))
1791da177e4SLinus Torvalds 		return -EINVAL;
1801da177e4SLinus Torvalds 
1811da177e4SLinus Torvalds 	if (!sctp_sk(sk)->pf->send_verify(sctp_sk(sk), (addr)))
1821da177e4SLinus Torvalds 		return -EINVAL;
1831da177e4SLinus Torvalds 
1841da177e4SLinus Torvalds 	return 0;
1851da177e4SLinus Torvalds }
1861da177e4SLinus Torvalds 
1871da177e4SLinus Torvalds /* Look up the association by its id.  If this is not a UDP-style
1881da177e4SLinus Torvalds  * socket, the ID field is always ignored.
1891da177e4SLinus Torvalds  */
1901da177e4SLinus Torvalds struct sctp_association *sctp_id2assoc(struct sock *sk, sctp_assoc_t id)
1911da177e4SLinus Torvalds {
1921da177e4SLinus Torvalds 	struct sctp_association *asoc = NULL;
1931da177e4SLinus Torvalds 
1941da177e4SLinus Torvalds 	/* If this is not a UDP-style socket, assoc id should be ignored. */
1951da177e4SLinus Torvalds 	if (!sctp_style(sk, UDP)) {
1961da177e4SLinus Torvalds 		/* Return NULL if the socket state is not ESTABLISHED. It
1971da177e4SLinus Torvalds 		 * could be a TCP-style listening socket or a socket which
1981da177e4SLinus Torvalds 		 * hasn't yet called connect() to establish an association.
1991da177e4SLinus Torvalds 		 */
2001da177e4SLinus Torvalds 		if (!sctp_sstate(sk, ESTABLISHED))
2011da177e4SLinus Torvalds 			return NULL;
2021da177e4SLinus Torvalds 
2031da177e4SLinus Torvalds 		/* Get the first and the only association from the list. */
2041da177e4SLinus Torvalds 		if (!list_empty(&sctp_sk(sk)->ep->asocs))
2051da177e4SLinus Torvalds 			asoc = list_entry(sctp_sk(sk)->ep->asocs.next,
2061da177e4SLinus Torvalds 					  struct sctp_association, asocs);
2071da177e4SLinus Torvalds 		return asoc;
2081da177e4SLinus Torvalds 	}
2091da177e4SLinus Torvalds 
2101da177e4SLinus Torvalds 	/* Otherwise this is a UDP-style socket. */
2111da177e4SLinus Torvalds 	if (!id || (id == (sctp_assoc_t)-1))
2121da177e4SLinus Torvalds 		return NULL;
2131da177e4SLinus Torvalds 
2141da177e4SLinus Torvalds 	spin_lock_bh(&sctp_assocs_id_lock);
2151da177e4SLinus Torvalds 	asoc = (struct sctp_association *)idr_find(&sctp_assocs_id, (int)id);
2161da177e4SLinus Torvalds 	spin_unlock_bh(&sctp_assocs_id_lock);
2171da177e4SLinus Torvalds 
2181da177e4SLinus Torvalds 	if (!asoc || (asoc->base.sk != sk) || asoc->base.dead)
2191da177e4SLinus Torvalds 		return NULL;
2201da177e4SLinus Torvalds 
2211da177e4SLinus Torvalds 	return asoc;
2221da177e4SLinus Torvalds }
2231da177e4SLinus Torvalds 
2241da177e4SLinus Torvalds /* Look up the transport from an address and an assoc id. If both address and
2251da177e4SLinus Torvalds  * id are specified, the associations matching the address and the id should be
2261da177e4SLinus Torvalds  * the same.
2271da177e4SLinus Torvalds  */
2281da177e4SLinus Torvalds static struct sctp_transport *sctp_addr_id2transport(struct sock *sk,
2291da177e4SLinus Torvalds 					      struct sockaddr_storage *addr,
2301da177e4SLinus Torvalds 					      sctp_assoc_t id)
2311da177e4SLinus Torvalds {
2321da177e4SLinus Torvalds 	struct sctp_association *addr_asoc = NULL, *id_asoc = NULL;
2331da177e4SLinus Torvalds 	struct sctp_transport *transport;
2341da177e4SLinus Torvalds 	union sctp_addr *laddr = (union sctp_addr *)addr;
2351da177e4SLinus Torvalds 
2361da177e4SLinus Torvalds 	laddr->v4.sin_port = ntohs(laddr->v4.sin_port);
2371da177e4SLinus Torvalds 	addr_asoc = sctp_endpoint_lookup_assoc(sctp_sk(sk)->ep,
2381da177e4SLinus Torvalds 					       (union sctp_addr *)addr,
2391da177e4SLinus Torvalds 					       &transport);
2401da177e4SLinus Torvalds 	laddr->v4.sin_port = htons(laddr->v4.sin_port);
2411da177e4SLinus Torvalds 
2421da177e4SLinus Torvalds 	if (!addr_asoc)
2431da177e4SLinus Torvalds 		return NULL;
2441da177e4SLinus Torvalds 
2451da177e4SLinus Torvalds 	id_asoc = sctp_id2assoc(sk, id);
2461da177e4SLinus Torvalds 	if (id_asoc && (id_asoc != addr_asoc))
2471da177e4SLinus Torvalds 		return NULL;
2481da177e4SLinus Torvalds 
2491da177e4SLinus Torvalds 	sctp_get_pf_specific(sk->sk_family)->addr_v4map(sctp_sk(sk),
2501da177e4SLinus Torvalds 						(union sctp_addr *)addr);
2511da177e4SLinus Torvalds 
2521da177e4SLinus Torvalds 	return transport;
2531da177e4SLinus Torvalds }
2541da177e4SLinus Torvalds 
2551da177e4SLinus Torvalds /* API 3.1.2 bind() - UDP Style Syntax
2561da177e4SLinus Torvalds  * The syntax of bind() is,
2571da177e4SLinus Torvalds  *
2581da177e4SLinus Torvalds  *   ret = bind(int sd, struct sockaddr *addr, int addrlen);
2591da177e4SLinus Torvalds  *
2601da177e4SLinus Torvalds  *   sd      - the socket descriptor returned by socket().
2611da177e4SLinus Torvalds  *   addr    - the address structure (struct sockaddr_in or struct
2621da177e4SLinus Torvalds  *             sockaddr_in6 [RFC 2553]),
2631da177e4SLinus Torvalds  *   addr_len - the size of the address structure.
2641da177e4SLinus Torvalds  */
2653f7a87d2SFrank Filz SCTP_STATIC int sctp_bind(struct sock *sk, struct sockaddr *addr, int addr_len)
2661da177e4SLinus Torvalds {
2671da177e4SLinus Torvalds 	int retval = 0;
2681da177e4SLinus Torvalds 
2691da177e4SLinus Torvalds 	sctp_lock_sock(sk);
2701da177e4SLinus Torvalds 
2713f7a87d2SFrank Filz 	SCTP_DEBUG_PRINTK("sctp_bind(sk: %p, addr: %p, addr_len: %d)\n",
2723f7a87d2SFrank Filz 			  sk, addr, addr_len);
2731da177e4SLinus Torvalds 
2741da177e4SLinus Torvalds 	/* Disallow binding twice. */
2751da177e4SLinus Torvalds 	if (!sctp_sk(sk)->ep->base.bind_addr.port)
2763f7a87d2SFrank Filz 		retval = sctp_do_bind(sk, (union sctp_addr *)addr,
2771da177e4SLinus Torvalds 				      addr_len);
2781da177e4SLinus Torvalds 	else
2791da177e4SLinus Torvalds 		retval = -EINVAL;
2801da177e4SLinus Torvalds 
2811da177e4SLinus Torvalds 	sctp_release_sock(sk);
2821da177e4SLinus Torvalds 
2831da177e4SLinus Torvalds 	return retval;
2841da177e4SLinus Torvalds }
2851da177e4SLinus Torvalds 
2861da177e4SLinus Torvalds static long sctp_get_port_local(struct sock *, union sctp_addr *);
2871da177e4SLinus Torvalds 
2881da177e4SLinus Torvalds /* Verify this is a valid sockaddr. */
2891da177e4SLinus Torvalds static struct sctp_af *sctp_sockaddr_af(struct sctp_sock *opt,
2901da177e4SLinus Torvalds 					union sctp_addr *addr, int len)
2911da177e4SLinus Torvalds {
2921da177e4SLinus Torvalds 	struct sctp_af *af;
2931da177e4SLinus Torvalds 
2941da177e4SLinus Torvalds 	/* Check minimum size.  */
2951da177e4SLinus Torvalds 	if (len < sizeof (struct sockaddr))
2961da177e4SLinus Torvalds 		return NULL;
2971da177e4SLinus Torvalds 
2981da177e4SLinus Torvalds 	/* Does this PF support this AF? */
2991da177e4SLinus Torvalds 	if (!opt->pf->af_supported(addr->sa.sa_family, opt))
3001da177e4SLinus Torvalds 		return NULL;
3011da177e4SLinus Torvalds 
3021da177e4SLinus Torvalds 	/* If we get this far, af is valid. */
3031da177e4SLinus Torvalds 	af = sctp_get_af_specific(addr->sa.sa_family);
3041da177e4SLinus Torvalds 
3051da177e4SLinus Torvalds 	if (len < af->sockaddr_len)
3061da177e4SLinus Torvalds 		return NULL;
3071da177e4SLinus Torvalds 
3081da177e4SLinus Torvalds 	return af;
3091da177e4SLinus Torvalds }
3101da177e4SLinus Torvalds 
3111da177e4SLinus Torvalds /* Bind a local address either to an endpoint or to an association.  */
3121da177e4SLinus Torvalds SCTP_STATIC int sctp_do_bind(struct sock *sk, union sctp_addr *addr, int len)
3131da177e4SLinus Torvalds {
3141da177e4SLinus Torvalds 	struct sctp_sock *sp = sctp_sk(sk);
3151da177e4SLinus Torvalds 	struct sctp_endpoint *ep = sp->ep;
3161da177e4SLinus Torvalds 	struct sctp_bind_addr *bp = &ep->base.bind_addr;
3171da177e4SLinus Torvalds 	struct sctp_af *af;
3181da177e4SLinus Torvalds 	unsigned short snum;
3191da177e4SLinus Torvalds 	int ret = 0;
3201da177e4SLinus Torvalds 
3211da177e4SLinus Torvalds 	/* Common sockaddr verification. */
3221da177e4SLinus Torvalds 	af = sctp_sockaddr_af(sp, addr, len);
3233f7a87d2SFrank Filz 	if (!af) {
3243f7a87d2SFrank Filz 		SCTP_DEBUG_PRINTK("sctp_do_bind(sk: %p, newaddr: %p, len: %d) EINVAL\n",
3253f7a87d2SFrank Filz 				  sk, addr, len);
3261da177e4SLinus Torvalds 		return -EINVAL;
3273f7a87d2SFrank Filz 	}
3283f7a87d2SFrank Filz 
3293f7a87d2SFrank Filz 	snum = ntohs(addr->v4.sin_port);
3303f7a87d2SFrank Filz 
3313f7a87d2SFrank Filz 	SCTP_DEBUG_PRINTK_IPADDR("sctp_do_bind(sk: %p, new addr: ",
3323f7a87d2SFrank Filz 				 ", port: %d, new port: %d, len: %d)\n",
3333f7a87d2SFrank Filz 				 sk,
3343f7a87d2SFrank Filz 				 addr,
3353f7a87d2SFrank Filz 				 bp->port, snum,
3363f7a87d2SFrank Filz 				 len);
3371da177e4SLinus Torvalds 
3381da177e4SLinus Torvalds 	/* PF specific bind() address verification. */
3391da177e4SLinus Torvalds 	if (!sp->pf->bind_verify(sp, addr))
3401da177e4SLinus Torvalds 		return -EADDRNOTAVAIL;
3411da177e4SLinus Torvalds 
3421da177e4SLinus Torvalds 	/* We must either be unbound, or bind to the same port.  */
3431da177e4SLinus Torvalds 	if (bp->port && (snum != bp->port)) {
3441da177e4SLinus Torvalds 		SCTP_DEBUG_PRINTK("sctp_do_bind:"
3451da177e4SLinus Torvalds 				  " New port %d does not match existing port "
3461da177e4SLinus Torvalds 				  "%d.\n", snum, bp->port);
3471da177e4SLinus Torvalds 		return -EINVAL;
3481da177e4SLinus Torvalds 	}
3491da177e4SLinus Torvalds 
3501da177e4SLinus Torvalds 	if (snum && snum < PROT_SOCK && !capable(CAP_NET_BIND_SERVICE))
3511da177e4SLinus Torvalds 		return -EACCES;
3521da177e4SLinus Torvalds 
3531da177e4SLinus Torvalds 	/* Make sure we are allowed to bind here.
3541da177e4SLinus Torvalds 	 * The function sctp_get_port_local() does duplicate address
3551da177e4SLinus Torvalds 	 * detection.
3561da177e4SLinus Torvalds 	 */
3571da177e4SLinus Torvalds 	if ((ret = sctp_get_port_local(sk, addr))) {
3581da177e4SLinus Torvalds 		if (ret == (long) sk) {
3591da177e4SLinus Torvalds 			/* This endpoint has a conflicting address. */
3601da177e4SLinus Torvalds 			return -EINVAL;
3611da177e4SLinus Torvalds 		} else {
3621da177e4SLinus Torvalds 			return -EADDRINUSE;
3631da177e4SLinus Torvalds 		}
3641da177e4SLinus Torvalds 	}
3651da177e4SLinus Torvalds 
3661da177e4SLinus Torvalds 	/* Refresh ephemeral port.  */
3671da177e4SLinus Torvalds 	if (!bp->port)
3681da177e4SLinus Torvalds 		bp->port = inet_sk(sk)->num;
3691da177e4SLinus Torvalds 
3701da177e4SLinus Torvalds 	/* Add the address to the bind address list.  */
3711da177e4SLinus Torvalds 	sctp_local_bh_disable();
3721da177e4SLinus Torvalds 	sctp_write_lock(&ep->base.addr_lock);
3731da177e4SLinus Torvalds 
3741da177e4SLinus Torvalds 	/* Use GFP_ATOMIC since BHs are disabled.  */
3751da177e4SLinus Torvalds 	addr->v4.sin_port = ntohs(addr->v4.sin_port);
3761da177e4SLinus Torvalds 	ret = sctp_add_bind_addr(bp, addr, GFP_ATOMIC);
3771da177e4SLinus Torvalds 	addr->v4.sin_port = htons(addr->v4.sin_port);
3781da177e4SLinus Torvalds 	sctp_write_unlock(&ep->base.addr_lock);
3791da177e4SLinus Torvalds 	sctp_local_bh_enable();
3801da177e4SLinus Torvalds 
3811da177e4SLinus Torvalds 	/* Copy back into socket for getsockname() use. */
3821da177e4SLinus Torvalds 	if (!ret) {
3831da177e4SLinus Torvalds 		inet_sk(sk)->sport = htons(inet_sk(sk)->num);
3841da177e4SLinus Torvalds 		af->to_sk_saddr(addr, sk);
3851da177e4SLinus Torvalds 	}
3861da177e4SLinus Torvalds 
3871da177e4SLinus Torvalds 	return ret;
3881da177e4SLinus Torvalds }
3891da177e4SLinus Torvalds 
3901da177e4SLinus Torvalds  /* ADDIP Section 4.1.1 Congestion Control of ASCONF Chunks
3911da177e4SLinus Torvalds  *
3921da177e4SLinus Torvalds  * R1) One and only one ASCONF Chunk MAY be in transit and unacknowledged
3931da177e4SLinus Torvalds  * at any one time.  If a sender, after sending an ASCONF chunk, decides
3941da177e4SLinus Torvalds  * it needs to transfer another ASCONF Chunk, it MUST wait until the
3951da177e4SLinus Torvalds  * ASCONF-ACK Chunk returns from the previous ASCONF Chunk before sending a
3961da177e4SLinus Torvalds  * subsequent ASCONF. Note this restriction binds each side, so at any
3971da177e4SLinus Torvalds  * time two ASCONF may be in-transit on any given association (one sent
3981da177e4SLinus Torvalds  * from each endpoint).
3991da177e4SLinus Torvalds  */
4001da177e4SLinus Torvalds static int sctp_send_asconf(struct sctp_association *asoc,
4011da177e4SLinus Torvalds 			    struct sctp_chunk *chunk)
4021da177e4SLinus Torvalds {
4031da177e4SLinus Torvalds 	int		retval = 0;
4041da177e4SLinus Torvalds 
4051da177e4SLinus Torvalds 	/* If there is an outstanding ASCONF chunk, queue it for later
4061da177e4SLinus Torvalds 	 * transmission.
4071da177e4SLinus Torvalds 	 */
4081da177e4SLinus Torvalds 	if (asoc->addip_last_asconf) {
40979af02c2SDavid S. Miller 		list_add_tail(&chunk->list, &asoc->addip_chunk_list);
4101da177e4SLinus Torvalds 		goto out;
4111da177e4SLinus Torvalds 	}
4121da177e4SLinus Torvalds 
4131da177e4SLinus Torvalds 	/* Hold the chunk until an ASCONF_ACK is received. */
4141da177e4SLinus Torvalds 	sctp_chunk_hold(chunk);
4151da177e4SLinus Torvalds 	retval = sctp_primitive_ASCONF(asoc, chunk);
4161da177e4SLinus Torvalds 	if (retval)
4171da177e4SLinus Torvalds 		sctp_chunk_free(chunk);
4181da177e4SLinus Torvalds 	else
4191da177e4SLinus Torvalds 		asoc->addip_last_asconf = chunk;
4201da177e4SLinus Torvalds 
4211da177e4SLinus Torvalds out:
4221da177e4SLinus Torvalds 	return retval;
4231da177e4SLinus Torvalds }
4241da177e4SLinus Torvalds 
4251da177e4SLinus Torvalds /* Add a list of addresses as bind addresses to local endpoint or
4261da177e4SLinus Torvalds  * association.
4271da177e4SLinus Torvalds  *
4281da177e4SLinus Torvalds  * Basically run through each address specified in the addrs/addrcnt
4291da177e4SLinus Torvalds  * array/length pair, determine if it is IPv6 or IPv4 and call
4301da177e4SLinus Torvalds  * sctp_do_bind() on it.
4311da177e4SLinus Torvalds  *
4321da177e4SLinus Torvalds  * If any of them fails, then the operation will be reversed and the
4331da177e4SLinus Torvalds  * ones that were added will be removed.
4341da177e4SLinus Torvalds  *
4351da177e4SLinus Torvalds  * Only sctp_setsockopt_bindx() is supposed to call this function.
4361da177e4SLinus Torvalds  */
4371da177e4SLinus Torvalds int sctp_bindx_add(struct sock *sk, struct sockaddr *addrs, int addrcnt)
4381da177e4SLinus Torvalds {
4391da177e4SLinus Torvalds 	int cnt;
4401da177e4SLinus Torvalds 	int retval = 0;
4411da177e4SLinus Torvalds 	void *addr_buf;
4421da177e4SLinus Torvalds 	struct sockaddr *sa_addr;
4431da177e4SLinus Torvalds 	struct sctp_af *af;
4441da177e4SLinus Torvalds 
4451da177e4SLinus Torvalds 	SCTP_DEBUG_PRINTK("sctp_bindx_add (sk: %p, addrs: %p, addrcnt: %d)\n",
4461da177e4SLinus Torvalds 			  sk, addrs, addrcnt);
4471da177e4SLinus Torvalds 
4481da177e4SLinus Torvalds 	addr_buf = addrs;
4491da177e4SLinus Torvalds 	for (cnt = 0; cnt < addrcnt; cnt++) {
4501da177e4SLinus Torvalds 		/* The list may contain either IPv4 or IPv6 address;
4511da177e4SLinus Torvalds 		 * determine the address length for walking thru the list.
4521da177e4SLinus Torvalds 		 */
4531da177e4SLinus Torvalds 		sa_addr = (struct sockaddr *)addr_buf;
4541da177e4SLinus Torvalds 		af = sctp_get_af_specific(sa_addr->sa_family);
4551da177e4SLinus Torvalds 		if (!af) {
4561da177e4SLinus Torvalds 			retval = -EINVAL;
4571da177e4SLinus Torvalds 			goto err_bindx_add;
4581da177e4SLinus Torvalds 		}
4591da177e4SLinus Torvalds 
4601da177e4SLinus Torvalds 		retval = sctp_do_bind(sk, (union sctp_addr *)sa_addr,
4611da177e4SLinus Torvalds 				      af->sockaddr_len);
4621da177e4SLinus Torvalds 
4631da177e4SLinus Torvalds 		addr_buf += af->sockaddr_len;
4641da177e4SLinus Torvalds 
4651da177e4SLinus Torvalds err_bindx_add:
4661da177e4SLinus Torvalds 		if (retval < 0) {
4671da177e4SLinus Torvalds 			/* Failed. Cleanup the ones that have been added */
4681da177e4SLinus Torvalds 			if (cnt > 0)
4691da177e4SLinus Torvalds 				sctp_bindx_rem(sk, addrs, cnt);
4701da177e4SLinus Torvalds 			return retval;
4711da177e4SLinus Torvalds 		}
4721da177e4SLinus Torvalds 	}
4731da177e4SLinus Torvalds 
4741da177e4SLinus Torvalds 	return retval;
4751da177e4SLinus Torvalds }
4761da177e4SLinus Torvalds 
4771da177e4SLinus Torvalds /* Send an ASCONF chunk with Add IP address parameters to all the peers of the
4781da177e4SLinus Torvalds  * associations that are part of the endpoint indicating that a list of local
4791da177e4SLinus Torvalds  * addresses are added to the endpoint.
4801da177e4SLinus Torvalds  *
4811da177e4SLinus Torvalds  * If any of the addresses is already in the bind address list of the
4821da177e4SLinus Torvalds  * association, we do not send the chunk for that association.  But it will not
4831da177e4SLinus Torvalds  * affect other associations.
4841da177e4SLinus Torvalds  *
4851da177e4SLinus Torvalds  * Only sctp_setsockopt_bindx() is supposed to call this function.
4861da177e4SLinus Torvalds  */
4871da177e4SLinus Torvalds static int sctp_send_asconf_add_ip(struct sock		*sk,
4881da177e4SLinus Torvalds 				   struct sockaddr	*addrs,
4891da177e4SLinus Torvalds 				   int 			addrcnt)
4901da177e4SLinus Torvalds {
4911da177e4SLinus Torvalds 	struct sctp_sock		*sp;
4921da177e4SLinus Torvalds 	struct sctp_endpoint		*ep;
4931da177e4SLinus Torvalds 	struct sctp_association		*asoc;
4941da177e4SLinus Torvalds 	struct sctp_bind_addr		*bp;
4951da177e4SLinus Torvalds 	struct sctp_chunk		*chunk;
4961da177e4SLinus Torvalds 	struct sctp_sockaddr_entry	*laddr;
4971da177e4SLinus Torvalds 	union sctp_addr			*addr;
4981da177e4SLinus Torvalds 	void				*addr_buf;
4991da177e4SLinus Torvalds 	struct sctp_af			*af;
5001da177e4SLinus Torvalds 	struct list_head		*pos;
5011da177e4SLinus Torvalds 	struct list_head		*p;
5021da177e4SLinus Torvalds 	int 				i;
5031da177e4SLinus Torvalds 	int 				retval = 0;
5041da177e4SLinus Torvalds 
5051da177e4SLinus Torvalds 	if (!sctp_addip_enable)
5061da177e4SLinus Torvalds 		return retval;
5071da177e4SLinus Torvalds 
5081da177e4SLinus Torvalds 	sp = sctp_sk(sk);
5091da177e4SLinus Torvalds 	ep = sp->ep;
5101da177e4SLinus Torvalds 
5111da177e4SLinus Torvalds 	SCTP_DEBUG_PRINTK("%s: (sk: %p, addrs: %p, addrcnt: %d)\n",
5121da177e4SLinus Torvalds 			  __FUNCTION__, sk, addrs, addrcnt);
5131da177e4SLinus Torvalds 
5141da177e4SLinus Torvalds 	list_for_each(pos, &ep->asocs) {
5151da177e4SLinus Torvalds 		asoc = list_entry(pos, struct sctp_association, asocs);
5161da177e4SLinus Torvalds 
5171da177e4SLinus Torvalds 		if (!asoc->peer.asconf_capable)
5181da177e4SLinus Torvalds 			continue;
5191da177e4SLinus Torvalds 
5201da177e4SLinus Torvalds 		if (asoc->peer.addip_disabled_mask & SCTP_PARAM_ADD_IP)
5211da177e4SLinus Torvalds 			continue;
5221da177e4SLinus Torvalds 
5231da177e4SLinus Torvalds 		if (!sctp_state(asoc, ESTABLISHED))
5241da177e4SLinus Torvalds 			continue;
5251da177e4SLinus Torvalds 
5261da177e4SLinus Torvalds 		/* Check if any address in the packed array of addresses is
5271da177e4SLinus Torvalds 	         * in the bind address list of the association. If so,
5281da177e4SLinus Torvalds 		 * do not send the asconf chunk to its peer, but continue with
5291da177e4SLinus Torvalds 		 * other associations.
5301da177e4SLinus Torvalds 		 */
5311da177e4SLinus Torvalds 		addr_buf = addrs;
5321da177e4SLinus Torvalds 		for (i = 0; i < addrcnt; i++) {
5331da177e4SLinus Torvalds 			addr = (union sctp_addr *)addr_buf;
5341da177e4SLinus Torvalds 			af = sctp_get_af_specific(addr->v4.sin_family);
5351da177e4SLinus Torvalds 			if (!af) {
5361da177e4SLinus Torvalds 				retval = -EINVAL;
5371da177e4SLinus Torvalds 				goto out;
5381da177e4SLinus Torvalds 			}
5391da177e4SLinus Torvalds 
5401da177e4SLinus Torvalds 			if (sctp_assoc_lookup_laddr(asoc, addr))
5411da177e4SLinus Torvalds 				break;
5421da177e4SLinus Torvalds 
5431da177e4SLinus Torvalds 			addr_buf += af->sockaddr_len;
5441da177e4SLinus Torvalds 		}
5451da177e4SLinus Torvalds 		if (i < addrcnt)
5461da177e4SLinus Torvalds 			continue;
5471da177e4SLinus Torvalds 
5481da177e4SLinus Torvalds 		/* Use the first address in bind addr list of association as
5491da177e4SLinus Torvalds 		 * Address Parameter of ASCONF CHUNK.
5501da177e4SLinus Torvalds 		 */
5511da177e4SLinus Torvalds 		sctp_read_lock(&asoc->base.addr_lock);
5521da177e4SLinus Torvalds 		bp = &asoc->base.bind_addr;
5531da177e4SLinus Torvalds 		p = bp->address_list.next;
5541da177e4SLinus Torvalds 		laddr = list_entry(p, struct sctp_sockaddr_entry, list);
5551da177e4SLinus Torvalds 		sctp_read_unlock(&asoc->base.addr_lock);
5561da177e4SLinus Torvalds 
5571da177e4SLinus Torvalds 		chunk = sctp_make_asconf_update_ip(asoc, &laddr->a, addrs,
5581da177e4SLinus Torvalds 						   addrcnt, SCTP_PARAM_ADD_IP);
5591da177e4SLinus Torvalds 		if (!chunk) {
5601da177e4SLinus Torvalds 			retval = -ENOMEM;
5611da177e4SLinus Torvalds 			goto out;
5621da177e4SLinus Torvalds 		}
5631da177e4SLinus Torvalds 
5641da177e4SLinus Torvalds 		retval = sctp_send_asconf(asoc, chunk);
5651da177e4SLinus Torvalds 
5661da177e4SLinus Torvalds 		/* FIXME: After sending the add address ASCONF chunk, we
5671da177e4SLinus Torvalds 		 * cannot append the address to the association's binding
5681da177e4SLinus Torvalds 		 * address list, because the new address may be used as the
5691da177e4SLinus Torvalds 		 * source of a message sent to the peer before the ASCONF
5701da177e4SLinus Torvalds 		 * chunk is received by the peer.  So we should wait until
5711da177e4SLinus Torvalds 		 * ASCONF_ACK is received.
5721da177e4SLinus Torvalds 		 */
5731da177e4SLinus Torvalds 	}
5741da177e4SLinus Torvalds 
5751da177e4SLinus Torvalds out:
5761da177e4SLinus Torvalds 	return retval;
5771da177e4SLinus Torvalds }
5781da177e4SLinus Torvalds 
5791da177e4SLinus Torvalds /* Remove a list of addresses from bind addresses list.  Do not remove the
5801da177e4SLinus Torvalds  * last address.
5811da177e4SLinus Torvalds  *
5821da177e4SLinus Torvalds  * Basically run through each address specified in the addrs/addrcnt
5831da177e4SLinus Torvalds  * array/length pair, determine if it is IPv6 or IPv4 and call
5841da177e4SLinus Torvalds  * sctp_del_bind() on it.
5851da177e4SLinus Torvalds  *
5861da177e4SLinus Torvalds  * If any of them fails, then the operation will be reversed and the
5871da177e4SLinus Torvalds  * ones that were removed will be added back.
5881da177e4SLinus Torvalds  *
5891da177e4SLinus Torvalds  * At least one address has to be left; if only one address is
5901da177e4SLinus Torvalds  * available, the operation will return -EBUSY.
5911da177e4SLinus Torvalds  *
5921da177e4SLinus Torvalds  * Only sctp_setsockopt_bindx() is supposed to call this function.
5931da177e4SLinus Torvalds  */
5941da177e4SLinus Torvalds int sctp_bindx_rem(struct sock *sk, struct sockaddr *addrs, int addrcnt)
5951da177e4SLinus Torvalds {
5961da177e4SLinus Torvalds 	struct sctp_sock *sp = sctp_sk(sk);
5971da177e4SLinus Torvalds 	struct sctp_endpoint *ep = sp->ep;
5981da177e4SLinus Torvalds 	int cnt;
5991da177e4SLinus Torvalds 	struct sctp_bind_addr *bp = &ep->base.bind_addr;
6001da177e4SLinus Torvalds 	int retval = 0;
6011da177e4SLinus Torvalds 	union sctp_addr saveaddr;
6021da177e4SLinus Torvalds 	void *addr_buf;
6031da177e4SLinus Torvalds 	struct sockaddr *sa_addr;
6041da177e4SLinus Torvalds 	struct sctp_af *af;
6051da177e4SLinus Torvalds 
6061da177e4SLinus Torvalds 	SCTP_DEBUG_PRINTK("sctp_bindx_rem (sk: %p, addrs: %p, addrcnt: %d)\n",
6071da177e4SLinus Torvalds 			  sk, addrs, addrcnt);
6081da177e4SLinus Torvalds 
6091da177e4SLinus Torvalds 	addr_buf = addrs;
6101da177e4SLinus Torvalds 	for (cnt = 0; cnt < addrcnt; cnt++) {
6111da177e4SLinus Torvalds 		/* If the bind address list is empty or if there is only one
6121da177e4SLinus Torvalds 		 * bind address, there is nothing more to be removed (we need
6131da177e4SLinus Torvalds 		 * at least one address here).
6141da177e4SLinus Torvalds 		 */
6151da177e4SLinus Torvalds 		if (list_empty(&bp->address_list) ||
6161da177e4SLinus Torvalds 		    (sctp_list_single_entry(&bp->address_list))) {
6171da177e4SLinus Torvalds 			retval = -EBUSY;
6181da177e4SLinus Torvalds 			goto err_bindx_rem;
6191da177e4SLinus Torvalds 		}
6201da177e4SLinus Torvalds 
6211da177e4SLinus Torvalds 		/* The list may contain either IPv4 or IPv6 address;
6221da177e4SLinus Torvalds 		 * determine the address length to copy the address to
6231da177e4SLinus Torvalds 		 * saveaddr.
6241da177e4SLinus Torvalds 		 */
6251da177e4SLinus Torvalds 		sa_addr = (struct sockaddr *)addr_buf;
6261da177e4SLinus Torvalds 		af = sctp_get_af_specific(sa_addr->sa_family);
6271da177e4SLinus Torvalds 		if (!af) {
6281da177e4SLinus Torvalds 			retval = -EINVAL;
6291da177e4SLinus Torvalds 			goto err_bindx_rem;
6301da177e4SLinus Torvalds 		}
6311da177e4SLinus Torvalds 		memcpy(&saveaddr, sa_addr, af->sockaddr_len);
6321da177e4SLinus Torvalds 		saveaddr.v4.sin_port = ntohs(saveaddr.v4.sin_port);
6331da177e4SLinus Torvalds 		if (saveaddr.v4.sin_port != bp->port) {
6341da177e4SLinus Torvalds 			retval = -EINVAL;
6351da177e4SLinus Torvalds 			goto err_bindx_rem;
6361da177e4SLinus Torvalds 		}
6371da177e4SLinus Torvalds 
6381da177e4SLinus Torvalds 		/* FIXME - There is probably a need to check if sk->sk_saddr and
6391da177e4SLinus Torvalds 		 * sk->sk_rcv_addr are currently set to one of the addresses to
6401da177e4SLinus Torvalds 		 * be removed. This is something which needs to be looked into
6411da177e4SLinus Torvalds 		 * when we are fixing the outstanding issues with multi-homing
6421da177e4SLinus Torvalds 		 * socket routing and failover schemes. Refer to comments in
6431da177e4SLinus Torvalds 		 * sctp_do_bind(). -daisy
6441da177e4SLinus Torvalds 		 */
6451da177e4SLinus Torvalds 		sctp_local_bh_disable();
6461da177e4SLinus Torvalds 		sctp_write_lock(&ep->base.addr_lock);
6471da177e4SLinus Torvalds 
6481da177e4SLinus Torvalds 		retval = sctp_del_bind_addr(bp, &saveaddr);
6491da177e4SLinus Torvalds 
6501da177e4SLinus Torvalds 		sctp_write_unlock(&ep->base.addr_lock);
6511da177e4SLinus Torvalds 		sctp_local_bh_enable();
6521da177e4SLinus Torvalds 
6531da177e4SLinus Torvalds 		addr_buf += af->sockaddr_len;
6541da177e4SLinus Torvalds err_bindx_rem:
6551da177e4SLinus Torvalds 		if (retval < 0) {
6561da177e4SLinus Torvalds 			/* Failed. Add the ones that has been removed back */
6571da177e4SLinus Torvalds 			if (cnt > 0)
6581da177e4SLinus Torvalds 				sctp_bindx_add(sk, addrs, cnt);
6591da177e4SLinus Torvalds 			return retval;
6601da177e4SLinus Torvalds 		}
6611da177e4SLinus Torvalds 	}
6621da177e4SLinus Torvalds 
6631da177e4SLinus Torvalds 	return retval;
6641da177e4SLinus Torvalds }
6651da177e4SLinus Torvalds 
6661da177e4SLinus Torvalds /* Send an ASCONF chunk with Delete IP address parameters to all the peers of
6671da177e4SLinus Torvalds  * the associations that are part of the endpoint indicating that a list of
6681da177e4SLinus Torvalds  * local addresses are removed from the endpoint.
6691da177e4SLinus Torvalds  *
6701da177e4SLinus Torvalds  * If any of the addresses is already in the bind address list of the
6711da177e4SLinus Torvalds  * association, we do not send the chunk for that association.  But it will not
6721da177e4SLinus Torvalds  * affect other associations.
6731da177e4SLinus Torvalds  *
6741da177e4SLinus Torvalds  * Only sctp_setsockopt_bindx() is supposed to call this function.
6751da177e4SLinus Torvalds  */
6761da177e4SLinus Torvalds static int sctp_send_asconf_del_ip(struct sock		*sk,
6771da177e4SLinus Torvalds 				   struct sockaddr	*addrs,
6781da177e4SLinus Torvalds 				   int			addrcnt)
6791da177e4SLinus Torvalds {
6801da177e4SLinus Torvalds 	struct sctp_sock	*sp;
6811da177e4SLinus Torvalds 	struct sctp_endpoint	*ep;
6821da177e4SLinus Torvalds 	struct sctp_association	*asoc;
6831da177e4SLinus Torvalds 	struct sctp_bind_addr	*bp;
6841da177e4SLinus Torvalds 	struct sctp_chunk	*chunk;
6851da177e4SLinus Torvalds 	union sctp_addr		*laddr;
6861da177e4SLinus Torvalds 	void			*addr_buf;
6871da177e4SLinus Torvalds 	struct sctp_af		*af;
6881da177e4SLinus Torvalds 	struct list_head	*pos;
6891da177e4SLinus Torvalds 	int 			i;
6901da177e4SLinus Torvalds 	int 			retval = 0;
6911da177e4SLinus Torvalds 
6921da177e4SLinus Torvalds 	if (!sctp_addip_enable)
6931da177e4SLinus Torvalds 		return retval;
6941da177e4SLinus Torvalds 
6951da177e4SLinus Torvalds 	sp = sctp_sk(sk);
6961da177e4SLinus Torvalds 	ep = sp->ep;
6971da177e4SLinus Torvalds 
6981da177e4SLinus Torvalds 	SCTP_DEBUG_PRINTK("%s: (sk: %p, addrs: %p, addrcnt: %d)\n",
6991da177e4SLinus Torvalds 			  __FUNCTION__, sk, addrs, addrcnt);
7001da177e4SLinus Torvalds 
7011da177e4SLinus Torvalds 	list_for_each(pos, &ep->asocs) {
7021da177e4SLinus Torvalds 		asoc = list_entry(pos, struct sctp_association, asocs);
7031da177e4SLinus Torvalds 
7041da177e4SLinus Torvalds 		if (!asoc->peer.asconf_capable)
7051da177e4SLinus Torvalds 			continue;
7061da177e4SLinus Torvalds 
7071da177e4SLinus Torvalds 		if (asoc->peer.addip_disabled_mask & SCTP_PARAM_DEL_IP)
7081da177e4SLinus Torvalds 			continue;
7091da177e4SLinus Torvalds 
7101da177e4SLinus Torvalds 		if (!sctp_state(asoc, ESTABLISHED))
7111da177e4SLinus Torvalds 			continue;
7121da177e4SLinus Torvalds 
7131da177e4SLinus Torvalds 		/* Check if any address in the packed array of addresses is
7141da177e4SLinus Torvalds 	         * not present in the bind address list of the association.
7151da177e4SLinus Torvalds 		 * If so, do not send the asconf chunk to its peer, but
7161da177e4SLinus Torvalds 		 * continue with other associations.
7171da177e4SLinus Torvalds 		 */
7181da177e4SLinus Torvalds 		addr_buf = addrs;
7191da177e4SLinus Torvalds 		for (i = 0; i < addrcnt; i++) {
7201da177e4SLinus Torvalds 			laddr = (union sctp_addr *)addr_buf;
7211da177e4SLinus Torvalds 			af = sctp_get_af_specific(laddr->v4.sin_family);
7221da177e4SLinus Torvalds 			if (!af) {
7231da177e4SLinus Torvalds 				retval = -EINVAL;
7241da177e4SLinus Torvalds 				goto out;
7251da177e4SLinus Torvalds 			}
7261da177e4SLinus Torvalds 
7271da177e4SLinus Torvalds 			if (!sctp_assoc_lookup_laddr(asoc, laddr))
7281da177e4SLinus Torvalds 				break;
7291da177e4SLinus Torvalds 
7301da177e4SLinus Torvalds 			addr_buf += af->sockaddr_len;
7311da177e4SLinus Torvalds 		}
7321da177e4SLinus Torvalds 		if (i < addrcnt)
7331da177e4SLinus Torvalds 			continue;
7341da177e4SLinus Torvalds 
7351da177e4SLinus Torvalds 		/* Find one address in the association's bind address list
7361da177e4SLinus Torvalds 		 * that is not in the packed array of addresses. This is to
7371da177e4SLinus Torvalds 		 * make sure that we do not delete all the addresses in the
7381da177e4SLinus Torvalds 		 * association.
7391da177e4SLinus Torvalds 		 */
7401da177e4SLinus Torvalds 		sctp_read_lock(&asoc->base.addr_lock);
7411da177e4SLinus Torvalds 		bp = &asoc->base.bind_addr;
7421da177e4SLinus Torvalds 		laddr = sctp_find_unmatch_addr(bp, (union sctp_addr *)addrs,
7431da177e4SLinus Torvalds 					       addrcnt, sp);
7441da177e4SLinus Torvalds 		sctp_read_unlock(&asoc->base.addr_lock);
7451da177e4SLinus Torvalds 		if (!laddr)
7461da177e4SLinus Torvalds 			continue;
7471da177e4SLinus Torvalds 
7481da177e4SLinus Torvalds 		chunk = sctp_make_asconf_update_ip(asoc, laddr, addrs, addrcnt,
7491da177e4SLinus Torvalds 						   SCTP_PARAM_DEL_IP);
7501da177e4SLinus Torvalds 		if (!chunk) {
7511da177e4SLinus Torvalds 			retval = -ENOMEM;
7521da177e4SLinus Torvalds 			goto out;
7531da177e4SLinus Torvalds 		}
7541da177e4SLinus Torvalds 
7551da177e4SLinus Torvalds 		retval = sctp_send_asconf(asoc, chunk);
7561da177e4SLinus Torvalds 
7571da177e4SLinus Torvalds 		/* FIXME: After sending the delete address ASCONF chunk, we
7581da177e4SLinus Torvalds 		 * cannot remove the addresses from the association's bind
7591da177e4SLinus Torvalds 		 * address list, because there maybe some packet send to
7601da177e4SLinus Torvalds 		 * the delete addresses, so we should wait until ASCONF_ACK
7611da177e4SLinus Torvalds 		 * packet is received.
7621da177e4SLinus Torvalds 		 */
7631da177e4SLinus Torvalds 	}
7641da177e4SLinus Torvalds out:
7651da177e4SLinus Torvalds 	return retval;
7661da177e4SLinus Torvalds }
7671da177e4SLinus Torvalds 
7681da177e4SLinus Torvalds /* Helper for tunneling sctp_bindx() requests through sctp_setsockopt()
7691da177e4SLinus Torvalds  *
7701da177e4SLinus Torvalds  * API 8.1
7711da177e4SLinus Torvalds  * int sctp_bindx(int sd, struct sockaddr *addrs, int addrcnt,
7721da177e4SLinus Torvalds  *                int flags);
7731da177e4SLinus Torvalds  *
7741da177e4SLinus Torvalds  * If sd is an IPv4 socket, the addresses passed must be IPv4 addresses.
7751da177e4SLinus Torvalds  * If the sd is an IPv6 socket, the addresses passed can either be IPv4
7761da177e4SLinus Torvalds  * or IPv6 addresses.
7771da177e4SLinus Torvalds  *
7781da177e4SLinus Torvalds  * A single address may be specified as INADDR_ANY or IN6ADDR_ANY, see
7791da177e4SLinus Torvalds  * Section 3.1.2 for this usage.
7801da177e4SLinus Torvalds  *
7811da177e4SLinus Torvalds  * addrs is a pointer to an array of one or more socket addresses. Each
7821da177e4SLinus Torvalds  * address is contained in its appropriate structure (i.e. struct
7831da177e4SLinus Torvalds  * sockaddr_in or struct sockaddr_in6) the family of the address type
7841da177e4SLinus Torvalds  * must be used to distengish the address length (note that this
7851da177e4SLinus Torvalds  * representation is termed a "packed array" of addresses). The caller
7861da177e4SLinus Torvalds  * specifies the number of addresses in the array with addrcnt.
7871da177e4SLinus Torvalds  *
7881da177e4SLinus Torvalds  * On success, sctp_bindx() returns 0. On failure, sctp_bindx() returns
7891da177e4SLinus Torvalds  * -1, and sets errno to the appropriate error code.
7901da177e4SLinus Torvalds  *
7911da177e4SLinus Torvalds  * For SCTP, the port given in each socket address must be the same, or
7921da177e4SLinus Torvalds  * sctp_bindx() will fail, setting errno to EINVAL.
7931da177e4SLinus Torvalds  *
7941da177e4SLinus Torvalds  * The flags parameter is formed from the bitwise OR of zero or more of
7951da177e4SLinus Torvalds  * the following currently defined flags:
7961da177e4SLinus Torvalds  *
7971da177e4SLinus Torvalds  * SCTP_BINDX_ADD_ADDR
7981da177e4SLinus Torvalds  *
7991da177e4SLinus Torvalds  * SCTP_BINDX_REM_ADDR
8001da177e4SLinus Torvalds  *
8011da177e4SLinus Torvalds  * SCTP_BINDX_ADD_ADDR directs SCTP to add the given addresses to the
8021da177e4SLinus Torvalds  * association, and SCTP_BINDX_REM_ADDR directs SCTP to remove the given
8031da177e4SLinus Torvalds  * addresses from the association. The two flags are mutually exclusive;
8041da177e4SLinus Torvalds  * if both are given, sctp_bindx() will fail with EINVAL. A caller may
8051da177e4SLinus Torvalds  * not remove all addresses from an association; sctp_bindx() will
8061da177e4SLinus Torvalds  * reject such an attempt with EINVAL.
8071da177e4SLinus Torvalds  *
8081da177e4SLinus Torvalds  * An application can use sctp_bindx(SCTP_BINDX_ADD_ADDR) to associate
8091da177e4SLinus Torvalds  * additional addresses with an endpoint after calling bind().  Or use
8101da177e4SLinus Torvalds  * sctp_bindx(SCTP_BINDX_REM_ADDR) to remove some addresses a listening
8111da177e4SLinus Torvalds  * socket is associated with so that no new association accepted will be
8121da177e4SLinus Torvalds  * associated with those addresses. If the endpoint supports dynamic
8131da177e4SLinus Torvalds  * address a SCTP_BINDX_REM_ADDR or SCTP_BINDX_ADD_ADDR may cause a
8141da177e4SLinus Torvalds  * endpoint to send the appropriate message to the peer to change the
8151da177e4SLinus Torvalds  * peers address lists.
8161da177e4SLinus Torvalds  *
8171da177e4SLinus Torvalds  * Adding and removing addresses from a connected association is
8181da177e4SLinus Torvalds  * optional functionality. Implementations that do not support this
8191da177e4SLinus Torvalds  * functionality should return EOPNOTSUPP.
8201da177e4SLinus Torvalds  *
8211da177e4SLinus Torvalds  * Basically do nothing but copying the addresses from user to kernel
8221da177e4SLinus Torvalds  * land and invoking either sctp_bindx_add() or sctp_bindx_rem() on the sk.
8233f7a87d2SFrank Filz  * This is used for tunneling the sctp_bindx() request through sctp_setsockopt()
8243f7a87d2SFrank Filz  * from userspace.
8251da177e4SLinus Torvalds  *
8261da177e4SLinus Torvalds  * We don't use copy_from_user() for optimization: we first do the
8271da177e4SLinus Torvalds  * sanity checks (buffer size -fast- and access check-healthy
8281da177e4SLinus Torvalds  * pointer); if all of those succeed, then we can alloc the memory
8291da177e4SLinus Torvalds  * (expensive operation) needed to copy the data to kernel. Then we do
8301da177e4SLinus Torvalds  * the copying without checking the user space area
8311da177e4SLinus Torvalds  * (__copy_from_user()).
8321da177e4SLinus Torvalds  *
8331da177e4SLinus Torvalds  * On exit there is no need to do sockfd_put(), sys_setsockopt() does
8341da177e4SLinus Torvalds  * it.
8351da177e4SLinus Torvalds  *
8361da177e4SLinus Torvalds  * sk        The sk of the socket
8371da177e4SLinus Torvalds  * addrs     The pointer to the addresses in user land
8381da177e4SLinus Torvalds  * addrssize Size of the addrs buffer
8391da177e4SLinus Torvalds  * op        Operation to perform (add or remove, see the flags of
8401da177e4SLinus Torvalds  *           sctp_bindx)
8411da177e4SLinus Torvalds  *
8421da177e4SLinus Torvalds  * Returns 0 if ok, <0 errno code on error.
8431da177e4SLinus Torvalds  */
8441da177e4SLinus Torvalds SCTP_STATIC int sctp_setsockopt_bindx(struct sock* sk,
8451da177e4SLinus Torvalds 				      struct sockaddr __user *addrs,
8461da177e4SLinus Torvalds 				      int addrs_size, int op)
8471da177e4SLinus Torvalds {
8481da177e4SLinus Torvalds 	struct sockaddr *kaddrs;
8491da177e4SLinus Torvalds 	int err;
8501da177e4SLinus Torvalds 	int addrcnt = 0;
8511da177e4SLinus Torvalds 	int walk_size = 0;
8521da177e4SLinus Torvalds 	struct sockaddr *sa_addr;
8531da177e4SLinus Torvalds 	void *addr_buf;
8541da177e4SLinus Torvalds 	struct sctp_af *af;
8551da177e4SLinus Torvalds 
8561da177e4SLinus Torvalds 	SCTP_DEBUG_PRINTK("sctp_setsocktopt_bindx: sk %p addrs %p"
8571da177e4SLinus Torvalds 			  " addrs_size %d opt %d\n", sk, addrs, addrs_size, op);
8581da177e4SLinus Torvalds 
8591da177e4SLinus Torvalds 	if (unlikely(addrs_size <= 0))
8601da177e4SLinus Torvalds 		return -EINVAL;
8611da177e4SLinus Torvalds 
8621da177e4SLinus Torvalds 	/* Check the user passed a healthy pointer.  */
8631da177e4SLinus Torvalds 	if (unlikely(!access_ok(VERIFY_READ, addrs, addrs_size)))
8641da177e4SLinus Torvalds 		return -EFAULT;
8651da177e4SLinus Torvalds 
8661da177e4SLinus Torvalds 	/* Alloc space for the address array in kernel memory.  */
8671da177e4SLinus Torvalds 	kaddrs = (struct sockaddr *)kmalloc(addrs_size, GFP_KERNEL);
8681da177e4SLinus Torvalds 	if (unlikely(!kaddrs))
8691da177e4SLinus Torvalds 		return -ENOMEM;
8701da177e4SLinus Torvalds 
8711da177e4SLinus Torvalds 	if (__copy_from_user(kaddrs, addrs, addrs_size)) {
8721da177e4SLinus Torvalds 		kfree(kaddrs);
8731da177e4SLinus Torvalds 		return -EFAULT;
8741da177e4SLinus Torvalds 	}
8751da177e4SLinus Torvalds 
8761da177e4SLinus Torvalds 	/* Walk through the addrs buffer and count the number of addresses. */
8771da177e4SLinus Torvalds 	addr_buf = kaddrs;
8781da177e4SLinus Torvalds 	while (walk_size < addrs_size) {
8791da177e4SLinus Torvalds 		sa_addr = (struct sockaddr *)addr_buf;
8801da177e4SLinus Torvalds 		af = sctp_get_af_specific(sa_addr->sa_family);
8811da177e4SLinus Torvalds 
8821da177e4SLinus Torvalds 		/* If the address family is not supported or if this address
8831da177e4SLinus Torvalds 		 * causes the address buffer to overflow return EINVAL.
8841da177e4SLinus Torvalds 		 */
8851da177e4SLinus Torvalds 		if (!af || (walk_size + af->sockaddr_len) > addrs_size) {
8861da177e4SLinus Torvalds 			kfree(kaddrs);
8871da177e4SLinus Torvalds 			return -EINVAL;
8881da177e4SLinus Torvalds 		}
8891da177e4SLinus Torvalds 		addrcnt++;
8901da177e4SLinus Torvalds 		addr_buf += af->sockaddr_len;
8911da177e4SLinus Torvalds 		walk_size += af->sockaddr_len;
8921da177e4SLinus Torvalds 	}
8931da177e4SLinus Torvalds 
8941da177e4SLinus Torvalds 	/* Do the work. */
8951da177e4SLinus Torvalds 	switch (op) {
8961da177e4SLinus Torvalds 	case SCTP_BINDX_ADD_ADDR:
8971da177e4SLinus Torvalds 		err = sctp_bindx_add(sk, kaddrs, addrcnt);
8981da177e4SLinus Torvalds 		if (err)
8991da177e4SLinus Torvalds 			goto out;
9001da177e4SLinus Torvalds 		err = sctp_send_asconf_add_ip(sk, kaddrs, addrcnt);
9011da177e4SLinus Torvalds 		break;
9021da177e4SLinus Torvalds 
9031da177e4SLinus Torvalds 	case SCTP_BINDX_REM_ADDR:
9041da177e4SLinus Torvalds 		err = sctp_bindx_rem(sk, kaddrs, addrcnt);
9051da177e4SLinus Torvalds 		if (err)
9061da177e4SLinus Torvalds 			goto out;
9071da177e4SLinus Torvalds 		err = sctp_send_asconf_del_ip(sk, kaddrs, addrcnt);
9081da177e4SLinus Torvalds 		break;
9091da177e4SLinus Torvalds 
9101da177e4SLinus Torvalds 	default:
9111da177e4SLinus Torvalds 		err = -EINVAL;
9121da177e4SLinus Torvalds 		break;
9131da177e4SLinus Torvalds         };
9141da177e4SLinus Torvalds 
9151da177e4SLinus Torvalds out:
9161da177e4SLinus Torvalds 	kfree(kaddrs);
9171da177e4SLinus Torvalds 
9181da177e4SLinus Torvalds 	return err;
9191da177e4SLinus Torvalds }
9201da177e4SLinus Torvalds 
9213f7a87d2SFrank Filz /* __sctp_connect(struct sock* sk, struct sockaddr *kaddrs, int addrs_size)
9223f7a87d2SFrank Filz  *
9233f7a87d2SFrank Filz  * Common routine for handling connect() and sctp_connectx().
9243f7a87d2SFrank Filz  * Connect will come in with just a single address.
9253f7a87d2SFrank Filz  */
9263f7a87d2SFrank Filz static int __sctp_connect(struct sock* sk,
9273f7a87d2SFrank Filz 			  struct sockaddr *kaddrs,
9283f7a87d2SFrank Filz 			  int addrs_size)
9293f7a87d2SFrank Filz {
9303f7a87d2SFrank Filz 	struct sctp_sock *sp;
9313f7a87d2SFrank Filz 	struct sctp_endpoint *ep;
9323f7a87d2SFrank Filz 	struct sctp_association *asoc = NULL;
9333f7a87d2SFrank Filz 	struct sctp_association *asoc2;
9343f7a87d2SFrank Filz 	struct sctp_transport *transport;
9353f7a87d2SFrank Filz 	union sctp_addr to;
9363f7a87d2SFrank Filz 	struct sctp_af *af;
9373f7a87d2SFrank Filz 	sctp_scope_t scope;
9383f7a87d2SFrank Filz 	long timeo;
9393f7a87d2SFrank Filz 	int err = 0;
9403f7a87d2SFrank Filz 	int addrcnt = 0;
9413f7a87d2SFrank Filz 	int walk_size = 0;
9423f7a87d2SFrank Filz 	struct sockaddr *sa_addr;
9433f7a87d2SFrank Filz 	void *addr_buf;
9443f7a87d2SFrank Filz 
9453f7a87d2SFrank Filz 	sp = sctp_sk(sk);
9463f7a87d2SFrank Filz 	ep = sp->ep;
9473f7a87d2SFrank Filz 
9483f7a87d2SFrank Filz 	/* connect() cannot be done on a socket that is already in ESTABLISHED
9493f7a87d2SFrank Filz 	 * state - UDP-style peeled off socket or a TCP-style socket that
9503f7a87d2SFrank Filz 	 * is already connected.
9513f7a87d2SFrank Filz 	 * It cannot be done even on a TCP-style listening socket.
9523f7a87d2SFrank Filz 	 */
9533f7a87d2SFrank Filz 	if (sctp_sstate(sk, ESTABLISHED) ||
9543f7a87d2SFrank Filz 	    (sctp_style(sk, TCP) && sctp_sstate(sk, LISTENING))) {
9553f7a87d2SFrank Filz 		err = -EISCONN;
9563f7a87d2SFrank Filz 		goto out_free;
9573f7a87d2SFrank Filz 	}
9583f7a87d2SFrank Filz 
9593f7a87d2SFrank Filz 	/* Walk through the addrs buffer and count the number of addresses. */
9603f7a87d2SFrank Filz 	addr_buf = kaddrs;
9613f7a87d2SFrank Filz 	while (walk_size < addrs_size) {
9623f7a87d2SFrank Filz 		sa_addr = (struct sockaddr *)addr_buf;
9633f7a87d2SFrank Filz 		af = sctp_get_af_specific(sa_addr->sa_family);
9643f7a87d2SFrank Filz 
9653f7a87d2SFrank Filz 		/* If the address family is not supported or if this address
9663f7a87d2SFrank Filz 		 * causes the address buffer to overflow return EINVAL.
9673f7a87d2SFrank Filz 		 */
9683f7a87d2SFrank Filz 		if (!af || (walk_size + af->sockaddr_len) > addrs_size) {
9693f7a87d2SFrank Filz 			err = -EINVAL;
9703f7a87d2SFrank Filz 			goto out_free;
9713f7a87d2SFrank Filz 		}
9723f7a87d2SFrank Filz 
9733f7a87d2SFrank Filz 		err = sctp_verify_addr(sk, (union sctp_addr *)sa_addr,
9743f7a87d2SFrank Filz 				       af->sockaddr_len);
9753f7a87d2SFrank Filz 		if (err)
9763f7a87d2SFrank Filz 			goto out_free;
9773f7a87d2SFrank Filz 
9783f7a87d2SFrank Filz 		memcpy(&to, sa_addr, af->sockaddr_len);
9793f7a87d2SFrank Filz 		to.v4.sin_port = ntohs(to.v4.sin_port);
9803f7a87d2SFrank Filz 
9813f7a87d2SFrank Filz 		/* Check if there already is a matching association on the
9823f7a87d2SFrank Filz 		 * endpoint (other than the one created here).
9833f7a87d2SFrank Filz 		 */
9843f7a87d2SFrank Filz 		asoc2 = sctp_endpoint_lookup_assoc(ep, &to, &transport);
9853f7a87d2SFrank Filz 		if (asoc2 && asoc2 != asoc) {
9863f7a87d2SFrank Filz 			if (asoc2->state >= SCTP_STATE_ESTABLISHED)
9873f7a87d2SFrank Filz 				err = -EISCONN;
9883f7a87d2SFrank Filz 			else
9893f7a87d2SFrank Filz 				err = -EALREADY;
9903f7a87d2SFrank Filz 			goto out_free;
9913f7a87d2SFrank Filz 		}
9923f7a87d2SFrank Filz 
9933f7a87d2SFrank Filz 		/* If we could not find a matching association on the endpoint,
9943f7a87d2SFrank Filz 		 * make sure that there is no peeled-off association matching
9953f7a87d2SFrank Filz 		 * the peer address even on another socket.
9963f7a87d2SFrank Filz 		 */
9973f7a87d2SFrank Filz 		if (sctp_endpoint_is_peeled_off(ep, &to)) {
9983f7a87d2SFrank Filz 			err = -EADDRNOTAVAIL;
9993f7a87d2SFrank Filz 			goto out_free;
10003f7a87d2SFrank Filz 		}
10013f7a87d2SFrank Filz 
10023f7a87d2SFrank Filz 		if (!asoc) {
10033f7a87d2SFrank Filz 			/* If a bind() or sctp_bindx() is not called prior to
10043f7a87d2SFrank Filz 			 * an sctp_connectx() call, the system picks an
10053f7a87d2SFrank Filz 			 * ephemeral port and will choose an address set
10063f7a87d2SFrank Filz 			 * equivalent to binding with a wildcard address.
10073f7a87d2SFrank Filz 			 */
10083f7a87d2SFrank Filz 			if (!ep->base.bind_addr.port) {
10093f7a87d2SFrank Filz 				if (sctp_autobind(sk)) {
10103f7a87d2SFrank Filz 					err = -EAGAIN;
10113f7a87d2SFrank Filz 					goto out_free;
10123f7a87d2SFrank Filz 				}
10133f7a87d2SFrank Filz 			}
10143f7a87d2SFrank Filz 
10153f7a87d2SFrank Filz 			scope = sctp_scope(&to);
10163f7a87d2SFrank Filz 			asoc = sctp_association_new(ep, sk, scope, GFP_KERNEL);
10173f7a87d2SFrank Filz 			if (!asoc) {
10183f7a87d2SFrank Filz 				err = -ENOMEM;
10193f7a87d2SFrank Filz 				goto out_free;
10203f7a87d2SFrank Filz 			}
10213f7a87d2SFrank Filz 		}
10223f7a87d2SFrank Filz 
10233f7a87d2SFrank Filz 		/* Prime the peer's transport structures.  */
10243f7a87d2SFrank Filz 		transport = sctp_assoc_add_peer(asoc, &to, GFP_KERNEL,
10253f7a87d2SFrank Filz 						SCTP_UNKNOWN);
10263f7a87d2SFrank Filz 		if (!transport) {
10273f7a87d2SFrank Filz 			err = -ENOMEM;
10283f7a87d2SFrank Filz 			goto out_free;
10293f7a87d2SFrank Filz 		}
10303f7a87d2SFrank Filz 
10313f7a87d2SFrank Filz 		addrcnt++;
10323f7a87d2SFrank Filz 		addr_buf += af->sockaddr_len;
10333f7a87d2SFrank Filz 		walk_size += af->sockaddr_len;
10343f7a87d2SFrank Filz 	}
10353f7a87d2SFrank Filz 
10363f7a87d2SFrank Filz 	err = sctp_assoc_set_bind_addr_from_ep(asoc, GFP_KERNEL);
10373f7a87d2SFrank Filz 	if (err < 0) {
10383f7a87d2SFrank Filz 		goto out_free;
10393f7a87d2SFrank Filz 	}
10403f7a87d2SFrank Filz 
10413f7a87d2SFrank Filz 	err = sctp_primitive_ASSOCIATE(asoc, NULL);
10423f7a87d2SFrank Filz 	if (err < 0) {
10433f7a87d2SFrank Filz 		goto out_free;
10443f7a87d2SFrank Filz 	}
10453f7a87d2SFrank Filz 
10463f7a87d2SFrank Filz 	/* Initialize sk's dport and daddr for getpeername() */
10473f7a87d2SFrank Filz 	inet_sk(sk)->dport = htons(asoc->peer.port);
10483f7a87d2SFrank Filz 	af = sctp_get_af_specific(to.sa.sa_family);
10493f7a87d2SFrank Filz 	af->to_sk_daddr(&to, sk);
10503f7a87d2SFrank Filz 
10513f7a87d2SFrank Filz 	timeo = sock_sndtimeo(sk, sk->sk_socket->file->f_flags & O_NONBLOCK);
10523f7a87d2SFrank Filz 	err = sctp_wait_for_connect(asoc, &timeo);
10533f7a87d2SFrank Filz 
10543f7a87d2SFrank Filz 	/* Don't free association on exit. */
10553f7a87d2SFrank Filz 	asoc = NULL;
10563f7a87d2SFrank Filz 
10573f7a87d2SFrank Filz out_free:
10583f7a87d2SFrank Filz 
10593f7a87d2SFrank Filz 	SCTP_DEBUG_PRINTK("About to exit __sctp_connect() free asoc: %p"
10603f7a87d2SFrank Filz 		          " kaddrs: %p err: %d\n",
10613f7a87d2SFrank Filz 	                  asoc, kaddrs, err);
10623f7a87d2SFrank Filz 	if (asoc)
10633f7a87d2SFrank Filz 		sctp_association_free(asoc);
10643f7a87d2SFrank Filz 	return err;
10653f7a87d2SFrank Filz }
10663f7a87d2SFrank Filz 
10673f7a87d2SFrank Filz /* Helper for tunneling sctp_connectx() requests through sctp_setsockopt()
10683f7a87d2SFrank Filz  *
10693f7a87d2SFrank Filz  * API 8.9
10703f7a87d2SFrank Filz  * int sctp_connectx(int sd, struct sockaddr *addrs, int addrcnt);
10713f7a87d2SFrank Filz  *
10723f7a87d2SFrank Filz  * If sd is an IPv4 socket, the addresses passed must be IPv4 addresses.
10733f7a87d2SFrank Filz  * If the sd is an IPv6 socket, the addresses passed can either be IPv4
10743f7a87d2SFrank Filz  * or IPv6 addresses.
10753f7a87d2SFrank Filz  *
10763f7a87d2SFrank Filz  * A single address may be specified as INADDR_ANY or IN6ADDR_ANY, see
10773f7a87d2SFrank Filz  * Section 3.1.2 for this usage.
10783f7a87d2SFrank Filz  *
10793f7a87d2SFrank Filz  * addrs is a pointer to an array of one or more socket addresses. Each
10803f7a87d2SFrank Filz  * address is contained in its appropriate structure (i.e. struct
10813f7a87d2SFrank Filz  * sockaddr_in or struct sockaddr_in6) the family of the address type
10823f7a87d2SFrank Filz  * must be used to distengish the address length (note that this
10833f7a87d2SFrank Filz  * representation is termed a "packed array" of addresses). The caller
10843f7a87d2SFrank Filz  * specifies the number of addresses in the array with addrcnt.
10853f7a87d2SFrank Filz  *
10863f7a87d2SFrank Filz  * On success, sctp_connectx() returns 0. On failure, sctp_connectx() returns
10873f7a87d2SFrank Filz  * -1, and sets errno to the appropriate error code.
10883f7a87d2SFrank Filz  *
10893f7a87d2SFrank Filz  * For SCTP, the port given in each socket address must be the same, or
10903f7a87d2SFrank Filz  * sctp_connectx() will fail, setting errno to EINVAL.
10913f7a87d2SFrank Filz  *
10923f7a87d2SFrank Filz  * An application can use sctp_connectx to initiate an association with
10933f7a87d2SFrank Filz  * an endpoint that is multi-homed.  Much like sctp_bindx() this call
10943f7a87d2SFrank Filz  * allows a caller to specify multiple addresses at which a peer can be
10953f7a87d2SFrank Filz  * reached.  The way the SCTP stack uses the list of addresses to set up
10963f7a87d2SFrank Filz  * the association is implementation dependant.  This function only
10973f7a87d2SFrank Filz  * specifies that the stack will try to make use of all the addresses in
10983f7a87d2SFrank Filz  * the list when needed.
10993f7a87d2SFrank Filz  *
11003f7a87d2SFrank Filz  * Note that the list of addresses passed in is only used for setting up
11013f7a87d2SFrank Filz  * the association.  It does not necessarily equal the set of addresses
11023f7a87d2SFrank Filz  * the peer uses for the resulting association.  If the caller wants to
11033f7a87d2SFrank Filz  * find out the set of peer addresses, it must use sctp_getpaddrs() to
11043f7a87d2SFrank Filz  * retrieve them after the association has been set up.
11053f7a87d2SFrank Filz  *
11063f7a87d2SFrank Filz  * Basically do nothing but copying the addresses from user to kernel
11073f7a87d2SFrank Filz  * land and invoking either sctp_connectx(). This is used for tunneling
11083f7a87d2SFrank Filz  * the sctp_connectx() request through sctp_setsockopt() from userspace.
11093f7a87d2SFrank Filz  *
11103f7a87d2SFrank Filz  * We don't use copy_from_user() for optimization: we first do the
11113f7a87d2SFrank Filz  * sanity checks (buffer size -fast- and access check-healthy
11123f7a87d2SFrank Filz  * pointer); if all of those succeed, then we can alloc the memory
11133f7a87d2SFrank Filz  * (expensive operation) needed to copy the data to kernel. Then we do
11143f7a87d2SFrank Filz  * the copying without checking the user space area
11153f7a87d2SFrank Filz  * (__copy_from_user()).
11163f7a87d2SFrank Filz  *
11173f7a87d2SFrank Filz  * On exit there is no need to do sockfd_put(), sys_setsockopt() does
11183f7a87d2SFrank Filz  * it.
11193f7a87d2SFrank Filz  *
11203f7a87d2SFrank Filz  * sk        The sk of the socket
11213f7a87d2SFrank Filz  * addrs     The pointer to the addresses in user land
11223f7a87d2SFrank Filz  * addrssize Size of the addrs buffer
11233f7a87d2SFrank Filz  *
11243f7a87d2SFrank Filz  * Returns 0 if ok, <0 errno code on error.
11253f7a87d2SFrank Filz  */
11263f7a87d2SFrank Filz SCTP_STATIC int sctp_setsockopt_connectx(struct sock* sk,
11273f7a87d2SFrank Filz 				      struct sockaddr __user *addrs,
11283f7a87d2SFrank Filz 				      int addrs_size)
11293f7a87d2SFrank Filz {
11303f7a87d2SFrank Filz 	int err = 0;
11313f7a87d2SFrank Filz 	struct sockaddr *kaddrs;
11323f7a87d2SFrank Filz 
11333f7a87d2SFrank Filz 	SCTP_DEBUG_PRINTK("%s - sk %p addrs %p addrs_size %d\n",
11343f7a87d2SFrank Filz 			  __FUNCTION__, sk, addrs, addrs_size);
11353f7a87d2SFrank Filz 
11363f7a87d2SFrank Filz 	if (unlikely(addrs_size <= 0))
11373f7a87d2SFrank Filz 		return -EINVAL;
11383f7a87d2SFrank Filz 
11393f7a87d2SFrank Filz 	/* Check the user passed a healthy pointer.  */
11403f7a87d2SFrank Filz 	if (unlikely(!access_ok(VERIFY_READ, addrs, addrs_size)))
11413f7a87d2SFrank Filz 		return -EFAULT;
11423f7a87d2SFrank Filz 
11433f7a87d2SFrank Filz 	/* Alloc space for the address array in kernel memory.  */
11443f7a87d2SFrank Filz 	kaddrs = (struct sockaddr *)kmalloc(addrs_size, GFP_KERNEL);
11453f7a87d2SFrank Filz 	if (unlikely(!kaddrs))
11463f7a87d2SFrank Filz 		return -ENOMEM;
11473f7a87d2SFrank Filz 
11483f7a87d2SFrank Filz 	if (__copy_from_user(kaddrs, addrs, addrs_size)) {
11493f7a87d2SFrank Filz 		err = -EFAULT;
11503f7a87d2SFrank Filz 	} else {
11513f7a87d2SFrank Filz 		err = __sctp_connect(sk, kaddrs, addrs_size);
11523f7a87d2SFrank Filz 	}
11533f7a87d2SFrank Filz 
11543f7a87d2SFrank Filz 	kfree(kaddrs);
11553f7a87d2SFrank Filz 	return err;
11563f7a87d2SFrank Filz }
11573f7a87d2SFrank Filz 
11581da177e4SLinus Torvalds /* API 3.1.4 close() - UDP Style Syntax
11591da177e4SLinus Torvalds  * Applications use close() to perform graceful shutdown (as described in
11601da177e4SLinus Torvalds  * Section 10.1 of [SCTP]) on ALL the associations currently represented
11611da177e4SLinus Torvalds  * by a UDP-style socket.
11621da177e4SLinus Torvalds  *
11631da177e4SLinus Torvalds  * The syntax is
11641da177e4SLinus Torvalds  *
11651da177e4SLinus Torvalds  *   ret = close(int sd);
11661da177e4SLinus Torvalds  *
11671da177e4SLinus Torvalds  *   sd      - the socket descriptor of the associations to be closed.
11681da177e4SLinus Torvalds  *
11691da177e4SLinus Torvalds  * To gracefully shutdown a specific association represented by the
11701da177e4SLinus Torvalds  * UDP-style socket, an application should use the sendmsg() call,
11711da177e4SLinus Torvalds  * passing no user data, but including the appropriate flag in the
11721da177e4SLinus Torvalds  * ancillary data (see Section xxxx).
11731da177e4SLinus Torvalds  *
11741da177e4SLinus Torvalds  * If sd in the close() call is a branched-off socket representing only
11751da177e4SLinus Torvalds  * one association, the shutdown is performed on that association only.
11761da177e4SLinus Torvalds  *
11771da177e4SLinus Torvalds  * 4.1.6 close() - TCP Style Syntax
11781da177e4SLinus Torvalds  *
11791da177e4SLinus Torvalds  * Applications use close() to gracefully close down an association.
11801da177e4SLinus Torvalds  *
11811da177e4SLinus Torvalds  * The syntax is:
11821da177e4SLinus Torvalds  *
11831da177e4SLinus Torvalds  *    int close(int sd);
11841da177e4SLinus Torvalds  *
11851da177e4SLinus Torvalds  *      sd      - the socket descriptor of the association to be closed.
11861da177e4SLinus Torvalds  *
11871da177e4SLinus Torvalds  * After an application calls close() on a socket descriptor, no further
11881da177e4SLinus Torvalds  * socket operations will succeed on that descriptor.
11891da177e4SLinus Torvalds  *
11901da177e4SLinus Torvalds  * API 7.1.4 SO_LINGER
11911da177e4SLinus Torvalds  *
11921da177e4SLinus Torvalds  * An application using the TCP-style socket can use this option to
11931da177e4SLinus Torvalds  * perform the SCTP ABORT primitive.  The linger option structure is:
11941da177e4SLinus Torvalds  *
11951da177e4SLinus Torvalds  *  struct  linger {
11961da177e4SLinus Torvalds  *     int     l_onoff;                // option on/off
11971da177e4SLinus Torvalds  *     int     l_linger;               // linger time
11981da177e4SLinus Torvalds  * };
11991da177e4SLinus Torvalds  *
12001da177e4SLinus Torvalds  * To enable the option, set l_onoff to 1.  If the l_linger value is set
12011da177e4SLinus Torvalds  * to 0, calling close() is the same as the ABORT primitive.  If the
12021da177e4SLinus Torvalds  * value is set to a negative value, the setsockopt() call will return
12031da177e4SLinus Torvalds  * an error.  If the value is set to a positive value linger_time, the
12041da177e4SLinus Torvalds  * close() can be blocked for at most linger_time ms.  If the graceful
12051da177e4SLinus Torvalds  * shutdown phase does not finish during this period, close() will
12061da177e4SLinus Torvalds  * return but the graceful shutdown phase continues in the system.
12071da177e4SLinus Torvalds  */
12081da177e4SLinus Torvalds SCTP_STATIC void sctp_close(struct sock *sk, long timeout)
12091da177e4SLinus Torvalds {
12101da177e4SLinus Torvalds 	struct sctp_endpoint *ep;
12111da177e4SLinus Torvalds 	struct sctp_association *asoc;
12121da177e4SLinus Torvalds 	struct list_head *pos, *temp;
12131da177e4SLinus Torvalds 
12141da177e4SLinus Torvalds 	SCTP_DEBUG_PRINTK("sctp_close(sk: 0x%p, timeout:%ld)\n", sk, timeout);
12151da177e4SLinus Torvalds 
12161da177e4SLinus Torvalds 	sctp_lock_sock(sk);
12171da177e4SLinus Torvalds 	sk->sk_shutdown = SHUTDOWN_MASK;
12181da177e4SLinus Torvalds 
12191da177e4SLinus Torvalds 	ep = sctp_sk(sk)->ep;
12201da177e4SLinus Torvalds 
12211da177e4SLinus Torvalds 	/* Walk all associations on a socket, not on an endpoint.  */
12221da177e4SLinus Torvalds 	list_for_each_safe(pos, temp, &ep->asocs) {
12231da177e4SLinus Torvalds 		asoc = list_entry(pos, struct sctp_association, asocs);
12241da177e4SLinus Torvalds 
12251da177e4SLinus Torvalds 		if (sctp_style(sk, TCP)) {
12261da177e4SLinus Torvalds 			/* A closed association can still be in the list if
12271da177e4SLinus Torvalds 			 * it belongs to a TCP-style listening socket that is
12281da177e4SLinus Torvalds 			 * not yet accepted. If so, free it. If not, send an
12291da177e4SLinus Torvalds 			 * ABORT or SHUTDOWN based on the linger options.
12301da177e4SLinus Torvalds 			 */
12311da177e4SLinus Torvalds 			if (sctp_state(asoc, CLOSED)) {
12321da177e4SLinus Torvalds 				sctp_unhash_established(asoc);
12331da177e4SLinus Torvalds 				sctp_association_free(asoc);
12341da177e4SLinus Torvalds 
12351da177e4SLinus Torvalds 			} else if (sock_flag(sk, SOCK_LINGER) &&
12361da177e4SLinus Torvalds 				   !sk->sk_lingertime)
12371da177e4SLinus Torvalds 				sctp_primitive_ABORT(asoc, NULL);
12381da177e4SLinus Torvalds 			else
12391da177e4SLinus Torvalds 				sctp_primitive_SHUTDOWN(asoc, NULL);
12401da177e4SLinus Torvalds 		} else
12411da177e4SLinus Torvalds 			sctp_primitive_SHUTDOWN(asoc, NULL);
12421da177e4SLinus Torvalds 	}
12431da177e4SLinus Torvalds 
12441da177e4SLinus Torvalds 	/* Clean up any skbs sitting on the receive queue.  */
12451da177e4SLinus Torvalds 	sctp_queue_purge_ulpevents(&sk->sk_receive_queue);
12461da177e4SLinus Torvalds 	sctp_queue_purge_ulpevents(&sctp_sk(sk)->pd_lobby);
12471da177e4SLinus Torvalds 
12481da177e4SLinus Torvalds 	/* On a TCP-style socket, block for at most linger_time if set. */
12491da177e4SLinus Torvalds 	if (sctp_style(sk, TCP) && timeout)
12501da177e4SLinus Torvalds 		sctp_wait_for_close(sk, timeout);
12511da177e4SLinus Torvalds 
12521da177e4SLinus Torvalds 	/* This will run the backlog queue.  */
12531da177e4SLinus Torvalds 	sctp_release_sock(sk);
12541da177e4SLinus Torvalds 
12551da177e4SLinus Torvalds 	/* Supposedly, no process has access to the socket, but
12561da177e4SLinus Torvalds 	 * the net layers still may.
12571da177e4SLinus Torvalds 	 */
12581da177e4SLinus Torvalds 	sctp_local_bh_disable();
12591da177e4SLinus Torvalds 	sctp_bh_lock_sock(sk);
12601da177e4SLinus Torvalds 
12611da177e4SLinus Torvalds 	/* Hold the sock, since sk_common_release() will put sock_put()
12621da177e4SLinus Torvalds 	 * and we have just a little more cleanup.
12631da177e4SLinus Torvalds 	 */
12641da177e4SLinus Torvalds 	sock_hold(sk);
12651da177e4SLinus Torvalds 	sk_common_release(sk);
12661da177e4SLinus Torvalds 
12671da177e4SLinus Torvalds 	sctp_bh_unlock_sock(sk);
12681da177e4SLinus Torvalds 	sctp_local_bh_enable();
12691da177e4SLinus Torvalds 
12701da177e4SLinus Torvalds 	sock_put(sk);
12711da177e4SLinus Torvalds 
12721da177e4SLinus Torvalds 	SCTP_DBG_OBJCNT_DEC(sock);
12731da177e4SLinus Torvalds }
12741da177e4SLinus Torvalds 
12751da177e4SLinus Torvalds /* Handle EPIPE error. */
12761da177e4SLinus Torvalds static int sctp_error(struct sock *sk, int flags, int err)
12771da177e4SLinus Torvalds {
12781da177e4SLinus Torvalds 	if (err == -EPIPE)
12791da177e4SLinus Torvalds 		err = sock_error(sk) ? : -EPIPE;
12801da177e4SLinus Torvalds 	if (err == -EPIPE && !(flags & MSG_NOSIGNAL))
12811da177e4SLinus Torvalds 		send_sig(SIGPIPE, current, 0);
12821da177e4SLinus Torvalds 	return err;
12831da177e4SLinus Torvalds }
12841da177e4SLinus Torvalds 
12851da177e4SLinus Torvalds /* API 3.1.3 sendmsg() - UDP Style Syntax
12861da177e4SLinus Torvalds  *
12871da177e4SLinus Torvalds  * An application uses sendmsg() and recvmsg() calls to transmit data to
12881da177e4SLinus Torvalds  * and receive data from its peer.
12891da177e4SLinus Torvalds  *
12901da177e4SLinus Torvalds  *  ssize_t sendmsg(int socket, const struct msghdr *message,
12911da177e4SLinus Torvalds  *                  int flags);
12921da177e4SLinus Torvalds  *
12931da177e4SLinus Torvalds  *  socket  - the socket descriptor of the endpoint.
12941da177e4SLinus Torvalds  *  message - pointer to the msghdr structure which contains a single
12951da177e4SLinus Torvalds  *            user message and possibly some ancillary data.
12961da177e4SLinus Torvalds  *
12971da177e4SLinus Torvalds  *            See Section 5 for complete description of the data
12981da177e4SLinus Torvalds  *            structures.
12991da177e4SLinus Torvalds  *
13001da177e4SLinus Torvalds  *  flags   - flags sent or received with the user message, see Section
13011da177e4SLinus Torvalds  *            5 for complete description of the flags.
13021da177e4SLinus Torvalds  *
13031da177e4SLinus Torvalds  * Note:  This function could use a rewrite especially when explicit
13041da177e4SLinus Torvalds  * connect support comes in.
13051da177e4SLinus Torvalds  */
13061da177e4SLinus Torvalds /* BUG:  We do not implement the equivalent of sk_stream_wait_memory(). */
13071da177e4SLinus Torvalds 
13081da177e4SLinus Torvalds SCTP_STATIC int sctp_msghdr_parse(const struct msghdr *, sctp_cmsgs_t *);
13091da177e4SLinus Torvalds 
13101da177e4SLinus Torvalds SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk,
13111da177e4SLinus Torvalds 			     struct msghdr *msg, size_t msg_len)
13121da177e4SLinus Torvalds {
13131da177e4SLinus Torvalds 	struct sctp_sock *sp;
13141da177e4SLinus Torvalds 	struct sctp_endpoint *ep;
13151da177e4SLinus Torvalds 	struct sctp_association *new_asoc=NULL, *asoc=NULL;
13161da177e4SLinus Torvalds 	struct sctp_transport *transport, *chunk_tp;
13171da177e4SLinus Torvalds 	struct sctp_chunk *chunk;
13181da177e4SLinus Torvalds 	union sctp_addr to;
13191da177e4SLinus Torvalds 	struct sockaddr *msg_name = NULL;
13201da177e4SLinus Torvalds 	struct sctp_sndrcvinfo default_sinfo = { 0 };
13211da177e4SLinus Torvalds 	struct sctp_sndrcvinfo *sinfo;
13221da177e4SLinus Torvalds 	struct sctp_initmsg *sinit;
13231da177e4SLinus Torvalds 	sctp_assoc_t associd = 0;
13241da177e4SLinus Torvalds 	sctp_cmsgs_t cmsgs = { NULL };
13251da177e4SLinus Torvalds 	int err;
13261da177e4SLinus Torvalds 	sctp_scope_t scope;
13271da177e4SLinus Torvalds 	long timeo;
13281da177e4SLinus Torvalds 	__u16 sinfo_flags = 0;
13291da177e4SLinus Torvalds 	struct sctp_datamsg *datamsg;
13301da177e4SLinus Torvalds 	struct list_head *pos;
13311da177e4SLinus Torvalds 	int msg_flags = msg->msg_flags;
13321da177e4SLinus Torvalds 
13331da177e4SLinus Torvalds 	SCTP_DEBUG_PRINTK("sctp_sendmsg(sk: %p, msg: %p, msg_len: %zu)\n",
13341da177e4SLinus Torvalds 			  sk, msg, msg_len);
13351da177e4SLinus Torvalds 
13361da177e4SLinus Torvalds 	err = 0;
13371da177e4SLinus Torvalds 	sp = sctp_sk(sk);
13381da177e4SLinus Torvalds 	ep = sp->ep;
13391da177e4SLinus Torvalds 
13403f7a87d2SFrank Filz 	SCTP_DEBUG_PRINTK("Using endpoint: %p.\n", ep);
13411da177e4SLinus Torvalds 
13421da177e4SLinus Torvalds 	/* We cannot send a message over a TCP-style listening socket. */
13431da177e4SLinus Torvalds 	if (sctp_style(sk, TCP) && sctp_sstate(sk, LISTENING)) {
13441da177e4SLinus Torvalds 		err = -EPIPE;
13451da177e4SLinus Torvalds 		goto out_nounlock;
13461da177e4SLinus Torvalds 	}
13471da177e4SLinus Torvalds 
13481da177e4SLinus Torvalds 	/* Parse out the SCTP CMSGs.  */
13491da177e4SLinus Torvalds 	err = sctp_msghdr_parse(msg, &cmsgs);
13501da177e4SLinus Torvalds 
13511da177e4SLinus Torvalds 	if (err) {
13521da177e4SLinus Torvalds 		SCTP_DEBUG_PRINTK("msghdr parse err = %x\n", err);
13531da177e4SLinus Torvalds 		goto out_nounlock;
13541da177e4SLinus Torvalds 	}
13551da177e4SLinus Torvalds 
13561da177e4SLinus Torvalds 	/* Fetch the destination address for this packet.  This
13571da177e4SLinus Torvalds 	 * address only selects the association--it is not necessarily
13581da177e4SLinus Torvalds 	 * the address we will send to.
13591da177e4SLinus Torvalds 	 * For a peeled-off socket, msg_name is ignored.
13601da177e4SLinus Torvalds 	 */
13611da177e4SLinus Torvalds 	if (!sctp_style(sk, UDP_HIGH_BANDWIDTH) && msg->msg_name) {
13621da177e4SLinus Torvalds 		int msg_namelen = msg->msg_namelen;
13631da177e4SLinus Torvalds 
13641da177e4SLinus Torvalds 		err = sctp_verify_addr(sk, (union sctp_addr *)msg->msg_name,
13651da177e4SLinus Torvalds 				       msg_namelen);
13661da177e4SLinus Torvalds 		if (err)
13671da177e4SLinus Torvalds 			return err;
13681da177e4SLinus Torvalds 
13691da177e4SLinus Torvalds 		if (msg_namelen > sizeof(to))
13701da177e4SLinus Torvalds 			msg_namelen = sizeof(to);
13711da177e4SLinus Torvalds 		memcpy(&to, msg->msg_name, msg_namelen);
13721da177e4SLinus Torvalds 		SCTP_DEBUG_PRINTK("Just memcpy'd. msg_name is "
13731da177e4SLinus Torvalds 				  "0x%x:%u.\n",
13741da177e4SLinus Torvalds 				  to.v4.sin_addr.s_addr, to.v4.sin_port);
13751da177e4SLinus Torvalds 
13761da177e4SLinus Torvalds 		to.v4.sin_port = ntohs(to.v4.sin_port);
13771da177e4SLinus Torvalds 		msg_name = msg->msg_name;
13781da177e4SLinus Torvalds 	}
13791da177e4SLinus Torvalds 
13801da177e4SLinus Torvalds 	sinfo = cmsgs.info;
13811da177e4SLinus Torvalds 	sinit = cmsgs.init;
13821da177e4SLinus Torvalds 
13831da177e4SLinus Torvalds 	/* Did the user specify SNDRCVINFO?  */
13841da177e4SLinus Torvalds 	if (sinfo) {
13851da177e4SLinus Torvalds 		sinfo_flags = sinfo->sinfo_flags;
13861da177e4SLinus Torvalds 		associd = sinfo->sinfo_assoc_id;
13871da177e4SLinus Torvalds 	}
13881da177e4SLinus Torvalds 
13891da177e4SLinus Torvalds 	SCTP_DEBUG_PRINTK("msg_len: %zu, sinfo_flags: 0x%x\n",
13901da177e4SLinus Torvalds 			  msg_len, sinfo_flags);
13911da177e4SLinus Torvalds 
1392*eaa5c54dSIvan Skytte Jorgensen 	/* SCTP_EOF or SCTP_ABORT cannot be set on a TCP-style socket. */
1393*eaa5c54dSIvan Skytte Jorgensen 	if (sctp_style(sk, TCP) && (sinfo_flags & (SCTP_EOF | SCTP_ABORT))) {
13941da177e4SLinus Torvalds 		err = -EINVAL;
13951da177e4SLinus Torvalds 		goto out_nounlock;
13961da177e4SLinus Torvalds 	}
13971da177e4SLinus Torvalds 
1398*eaa5c54dSIvan Skytte Jorgensen 	/* If SCTP_EOF is set, no data can be sent. Disallow sending zero
1399*eaa5c54dSIvan Skytte Jorgensen 	 * length messages when SCTP_EOF|SCTP_ABORT is not set.
1400*eaa5c54dSIvan Skytte Jorgensen 	 * If SCTP_ABORT is set, the message length could be non zero with
14011da177e4SLinus Torvalds 	 * the msg_iov set to the user abort reason.
14021da177e4SLinus Torvalds  	 */
1403*eaa5c54dSIvan Skytte Jorgensen 	if (((sinfo_flags & SCTP_EOF) && (msg_len > 0)) ||
1404*eaa5c54dSIvan Skytte Jorgensen 	    (!(sinfo_flags & (SCTP_EOF|SCTP_ABORT)) && (msg_len == 0))) {
14051da177e4SLinus Torvalds 		err = -EINVAL;
14061da177e4SLinus Torvalds 		goto out_nounlock;
14071da177e4SLinus Torvalds 	}
14081da177e4SLinus Torvalds 
1409*eaa5c54dSIvan Skytte Jorgensen 	/* If SCTP_ADDR_OVER is set, there must be an address
14101da177e4SLinus Torvalds 	 * specified in msg_name.
14111da177e4SLinus Torvalds 	 */
1412*eaa5c54dSIvan Skytte Jorgensen 	if ((sinfo_flags & SCTP_ADDR_OVER) && (!msg->msg_name)) {
14131da177e4SLinus Torvalds 		err = -EINVAL;
14141da177e4SLinus Torvalds 		goto out_nounlock;
14151da177e4SLinus Torvalds 	}
14161da177e4SLinus Torvalds 
14171da177e4SLinus Torvalds 	transport = NULL;
14181da177e4SLinus Torvalds 
14191da177e4SLinus Torvalds 	SCTP_DEBUG_PRINTK("About to look up association.\n");
14201da177e4SLinus Torvalds 
14211da177e4SLinus Torvalds 	sctp_lock_sock(sk);
14221da177e4SLinus Torvalds 
14231da177e4SLinus Torvalds 	/* If a msg_name has been specified, assume this is to be used.  */
14241da177e4SLinus Torvalds 	if (msg_name) {
14251da177e4SLinus Torvalds 		/* Look for a matching association on the endpoint. */
14261da177e4SLinus Torvalds 		asoc = sctp_endpoint_lookup_assoc(ep, &to, &transport);
14271da177e4SLinus Torvalds 		if (!asoc) {
14281da177e4SLinus Torvalds 			/* If we could not find a matching association on the
14291da177e4SLinus Torvalds 			 * endpoint, make sure that it is not a TCP-style
14301da177e4SLinus Torvalds 			 * socket that already has an association or there is
14311da177e4SLinus Torvalds 			 * no peeled-off association on another socket.
14321da177e4SLinus Torvalds 			 */
14331da177e4SLinus Torvalds 			if ((sctp_style(sk, TCP) &&
14341da177e4SLinus Torvalds 			     sctp_sstate(sk, ESTABLISHED)) ||
14351da177e4SLinus Torvalds 			    sctp_endpoint_is_peeled_off(ep, &to)) {
14361da177e4SLinus Torvalds 				err = -EADDRNOTAVAIL;
14371da177e4SLinus Torvalds 				goto out_unlock;
14381da177e4SLinus Torvalds 			}
14391da177e4SLinus Torvalds 		}
14401da177e4SLinus Torvalds 	} else {
14411da177e4SLinus Torvalds 		asoc = sctp_id2assoc(sk, associd);
14421da177e4SLinus Torvalds 		if (!asoc) {
14431da177e4SLinus Torvalds 			err = -EPIPE;
14441da177e4SLinus Torvalds 			goto out_unlock;
14451da177e4SLinus Torvalds 		}
14461da177e4SLinus Torvalds 	}
14471da177e4SLinus Torvalds 
14481da177e4SLinus Torvalds 	if (asoc) {
14491da177e4SLinus Torvalds 		SCTP_DEBUG_PRINTK("Just looked up association: %p.\n", asoc);
14501da177e4SLinus Torvalds 
14511da177e4SLinus Torvalds 		/* We cannot send a message on a TCP-style SCTP_SS_ESTABLISHED
14521da177e4SLinus Torvalds 		 * socket that has an association in CLOSED state. This can
14531da177e4SLinus Torvalds 		 * happen when an accepted socket has an association that is
14541da177e4SLinus Torvalds 		 * already CLOSED.
14551da177e4SLinus Torvalds 		 */
14561da177e4SLinus Torvalds 		if (sctp_state(asoc, CLOSED) && sctp_style(sk, TCP)) {
14571da177e4SLinus Torvalds 			err = -EPIPE;
14581da177e4SLinus Torvalds 			goto out_unlock;
14591da177e4SLinus Torvalds 		}
14601da177e4SLinus Torvalds 
1461*eaa5c54dSIvan Skytte Jorgensen 		if (sinfo_flags & SCTP_EOF) {
14621da177e4SLinus Torvalds 			SCTP_DEBUG_PRINTK("Shutting down association: %p\n",
14631da177e4SLinus Torvalds 					  asoc);
14641da177e4SLinus Torvalds 			sctp_primitive_SHUTDOWN(asoc, NULL);
14651da177e4SLinus Torvalds 			err = 0;
14661da177e4SLinus Torvalds 			goto out_unlock;
14671da177e4SLinus Torvalds 		}
1468*eaa5c54dSIvan Skytte Jorgensen 		if (sinfo_flags & SCTP_ABORT) {
14691da177e4SLinus Torvalds 			SCTP_DEBUG_PRINTK("Aborting association: %p\n", asoc);
14701da177e4SLinus Torvalds 			sctp_primitive_ABORT(asoc, msg);
14711da177e4SLinus Torvalds 			err = 0;
14721da177e4SLinus Torvalds 			goto out_unlock;
14731da177e4SLinus Torvalds 		}
14741da177e4SLinus Torvalds 	}
14751da177e4SLinus Torvalds 
14761da177e4SLinus Torvalds 	/* Do we need to create the association?  */
14771da177e4SLinus Torvalds 	if (!asoc) {
14781da177e4SLinus Torvalds 		SCTP_DEBUG_PRINTK("There is no association yet.\n");
14791da177e4SLinus Torvalds 
1480*eaa5c54dSIvan Skytte Jorgensen 		if (sinfo_flags & (SCTP_EOF | SCTP_ABORT)) {
14811da177e4SLinus Torvalds 			err = -EINVAL;
14821da177e4SLinus Torvalds 			goto out_unlock;
14831da177e4SLinus Torvalds 		}
14841da177e4SLinus Torvalds 
14851da177e4SLinus Torvalds 		/* Check for invalid stream against the stream counts,
14861da177e4SLinus Torvalds 		 * either the default or the user specified stream counts.
14871da177e4SLinus Torvalds 		 */
14881da177e4SLinus Torvalds 		if (sinfo) {
14891da177e4SLinus Torvalds 			if (!sinit || (sinit && !sinit->sinit_num_ostreams)) {
14901da177e4SLinus Torvalds 				/* Check against the defaults. */
14911da177e4SLinus Torvalds 				if (sinfo->sinfo_stream >=
14921da177e4SLinus Torvalds 				    sp->initmsg.sinit_num_ostreams) {
14931da177e4SLinus Torvalds 					err = -EINVAL;
14941da177e4SLinus Torvalds 					goto out_unlock;
14951da177e4SLinus Torvalds 				}
14961da177e4SLinus Torvalds 			} else {
14971da177e4SLinus Torvalds 				/* Check against the requested.  */
14981da177e4SLinus Torvalds 				if (sinfo->sinfo_stream >=
14991da177e4SLinus Torvalds 				    sinit->sinit_num_ostreams) {
15001da177e4SLinus Torvalds 					err = -EINVAL;
15011da177e4SLinus Torvalds 					goto out_unlock;
15021da177e4SLinus Torvalds 				}
15031da177e4SLinus Torvalds 			}
15041da177e4SLinus Torvalds 		}
15051da177e4SLinus Torvalds 
15061da177e4SLinus Torvalds 		/*
15071da177e4SLinus Torvalds 		 * API 3.1.2 bind() - UDP Style Syntax
15081da177e4SLinus Torvalds 		 * If a bind() or sctp_bindx() is not called prior to a
15091da177e4SLinus Torvalds 		 * sendmsg() call that initiates a new association, the
15101da177e4SLinus Torvalds 		 * system picks an ephemeral port and will choose an address
15111da177e4SLinus Torvalds 		 * set equivalent to binding with a wildcard address.
15121da177e4SLinus Torvalds 		 */
15131da177e4SLinus Torvalds 		if (!ep->base.bind_addr.port) {
15141da177e4SLinus Torvalds 			if (sctp_autobind(sk)) {
15151da177e4SLinus Torvalds 				err = -EAGAIN;
15161da177e4SLinus Torvalds 				goto out_unlock;
15171da177e4SLinus Torvalds 			}
15181da177e4SLinus Torvalds 		}
15191da177e4SLinus Torvalds 
15201da177e4SLinus Torvalds 		scope = sctp_scope(&to);
15211da177e4SLinus Torvalds 		new_asoc = sctp_association_new(ep, sk, scope, GFP_KERNEL);
15221da177e4SLinus Torvalds 		if (!new_asoc) {
15231da177e4SLinus Torvalds 			err = -ENOMEM;
15241da177e4SLinus Torvalds 			goto out_unlock;
15251da177e4SLinus Torvalds 		}
15261da177e4SLinus Torvalds 		asoc = new_asoc;
15271da177e4SLinus Torvalds 
15281da177e4SLinus Torvalds 		/* If the SCTP_INIT ancillary data is specified, set all
15291da177e4SLinus Torvalds 		 * the association init values accordingly.
15301da177e4SLinus Torvalds 		 */
15311da177e4SLinus Torvalds 		if (sinit) {
15321da177e4SLinus Torvalds 			if (sinit->sinit_num_ostreams) {
15331da177e4SLinus Torvalds 				asoc->c.sinit_num_ostreams =
15341da177e4SLinus Torvalds 					sinit->sinit_num_ostreams;
15351da177e4SLinus Torvalds 			}
15361da177e4SLinus Torvalds 			if (sinit->sinit_max_instreams) {
15371da177e4SLinus Torvalds 				asoc->c.sinit_max_instreams =
15381da177e4SLinus Torvalds 					sinit->sinit_max_instreams;
15391da177e4SLinus Torvalds 			}
15401da177e4SLinus Torvalds 			if (sinit->sinit_max_attempts) {
15411da177e4SLinus Torvalds 				asoc->max_init_attempts
15421da177e4SLinus Torvalds 					= sinit->sinit_max_attempts;
15431da177e4SLinus Torvalds 			}
15441da177e4SLinus Torvalds 			if (sinit->sinit_max_init_timeo) {
15451da177e4SLinus Torvalds 				asoc->max_init_timeo =
15461da177e4SLinus Torvalds 				 msecs_to_jiffies(sinit->sinit_max_init_timeo);
15471da177e4SLinus Torvalds 			}
15481da177e4SLinus Torvalds 		}
15491da177e4SLinus Torvalds 
15501da177e4SLinus Torvalds 		/* Prime the peer's transport structures.  */
15513f7a87d2SFrank Filz 		transport = sctp_assoc_add_peer(asoc, &to, GFP_KERNEL, SCTP_UNKNOWN);
15521da177e4SLinus Torvalds 		if (!transport) {
15531da177e4SLinus Torvalds 			err = -ENOMEM;
15541da177e4SLinus Torvalds 			goto out_free;
15551da177e4SLinus Torvalds 		}
15561da177e4SLinus Torvalds 		err = sctp_assoc_set_bind_addr_from_ep(asoc, GFP_KERNEL);
15571da177e4SLinus Torvalds 		if (err < 0) {
15581da177e4SLinus Torvalds 			err = -ENOMEM;
15591da177e4SLinus Torvalds 			goto out_free;
15601da177e4SLinus Torvalds 		}
15611da177e4SLinus Torvalds 	}
15621da177e4SLinus Torvalds 
15631da177e4SLinus Torvalds 	/* ASSERT: we have a valid association at this point.  */
15641da177e4SLinus Torvalds 	SCTP_DEBUG_PRINTK("We have a valid association.\n");
15651da177e4SLinus Torvalds 
15661da177e4SLinus Torvalds 	if (!sinfo) {
15671da177e4SLinus Torvalds 		/* If the user didn't specify SNDRCVINFO, make up one with
15681da177e4SLinus Torvalds 		 * some defaults.
15691da177e4SLinus Torvalds 		 */
15701da177e4SLinus Torvalds 		default_sinfo.sinfo_stream = asoc->default_stream;
15711da177e4SLinus Torvalds 		default_sinfo.sinfo_flags = asoc->default_flags;
15721da177e4SLinus Torvalds 		default_sinfo.sinfo_ppid = asoc->default_ppid;
15731da177e4SLinus Torvalds 		default_sinfo.sinfo_context = asoc->default_context;
15741da177e4SLinus Torvalds 		default_sinfo.sinfo_timetolive = asoc->default_timetolive;
15751da177e4SLinus Torvalds 		default_sinfo.sinfo_assoc_id = sctp_assoc2id(asoc);
15761da177e4SLinus Torvalds 		sinfo = &default_sinfo;
15771da177e4SLinus Torvalds 	}
15781da177e4SLinus Torvalds 
15791da177e4SLinus Torvalds 	/* API 7.1.7, the sndbuf size per association bounds the
15801da177e4SLinus Torvalds 	 * maximum size of data that can be sent in a single send call.
15811da177e4SLinus Torvalds 	 */
15821da177e4SLinus Torvalds 	if (msg_len > sk->sk_sndbuf) {
15831da177e4SLinus Torvalds 		err = -EMSGSIZE;
15841da177e4SLinus Torvalds 		goto out_free;
15851da177e4SLinus Torvalds 	}
15861da177e4SLinus Torvalds 
15871da177e4SLinus Torvalds 	/* If fragmentation is disabled and the message length exceeds the
15881da177e4SLinus Torvalds 	 * association fragmentation point, return EMSGSIZE.  The I-D
15891da177e4SLinus Torvalds 	 * does not specify what this error is, but this looks like
15901da177e4SLinus Torvalds 	 * a great fit.
15911da177e4SLinus Torvalds 	 */
15921da177e4SLinus Torvalds 	if (sctp_sk(sk)->disable_fragments && (msg_len > asoc->frag_point)) {
15931da177e4SLinus Torvalds 		err = -EMSGSIZE;
15941da177e4SLinus Torvalds 		goto out_free;
15951da177e4SLinus Torvalds 	}
15961da177e4SLinus Torvalds 
15971da177e4SLinus Torvalds 	if (sinfo) {
15981da177e4SLinus Torvalds 		/* Check for invalid stream. */
15991da177e4SLinus Torvalds 		if (sinfo->sinfo_stream >= asoc->c.sinit_num_ostreams) {
16001da177e4SLinus Torvalds 			err = -EINVAL;
16011da177e4SLinus Torvalds 			goto out_free;
16021da177e4SLinus Torvalds 		}
16031da177e4SLinus Torvalds 	}
16041da177e4SLinus Torvalds 
16051da177e4SLinus Torvalds 	timeo = sock_sndtimeo(sk, msg->msg_flags & MSG_DONTWAIT);
16061da177e4SLinus Torvalds 	if (!sctp_wspace(asoc)) {
16071da177e4SLinus Torvalds 		err = sctp_wait_for_sndbuf(asoc, &timeo, msg_len);
16081da177e4SLinus Torvalds 		if (err)
16091da177e4SLinus Torvalds 			goto out_free;
16101da177e4SLinus Torvalds 	}
16111da177e4SLinus Torvalds 
16121da177e4SLinus Torvalds 	/* If an address is passed with the sendto/sendmsg call, it is used
16131da177e4SLinus Torvalds 	 * to override the primary destination address in the TCP model, or
1614*eaa5c54dSIvan Skytte Jorgensen 	 * when SCTP_ADDR_OVER flag is set in the UDP model.
16151da177e4SLinus Torvalds 	 */
16161da177e4SLinus Torvalds 	if ((sctp_style(sk, TCP) && msg_name) ||
1617*eaa5c54dSIvan Skytte Jorgensen 	    (sinfo_flags & SCTP_ADDR_OVER)) {
16181da177e4SLinus Torvalds 		chunk_tp = sctp_assoc_lookup_paddr(asoc, &to);
16191da177e4SLinus Torvalds 		if (!chunk_tp) {
16201da177e4SLinus Torvalds 			err = -EINVAL;
16211da177e4SLinus Torvalds 			goto out_free;
16221da177e4SLinus Torvalds 		}
16231da177e4SLinus Torvalds 	} else
16241da177e4SLinus Torvalds 		chunk_tp = NULL;
16251da177e4SLinus Torvalds 
16261da177e4SLinus Torvalds 	/* Auto-connect, if we aren't connected already. */
16271da177e4SLinus Torvalds 	if (sctp_state(asoc, CLOSED)) {
16281da177e4SLinus Torvalds 		err = sctp_primitive_ASSOCIATE(asoc, NULL);
16291da177e4SLinus Torvalds 		if (err < 0)
16301da177e4SLinus Torvalds 			goto out_free;
16311da177e4SLinus Torvalds 		SCTP_DEBUG_PRINTK("We associated primitively.\n");
16321da177e4SLinus Torvalds 	}
16331da177e4SLinus Torvalds 
16341da177e4SLinus Torvalds 	/* Break the message into multiple chunks of maximum size. */
16351da177e4SLinus Torvalds 	datamsg = sctp_datamsg_from_user(asoc, sinfo, msg, msg_len);
16361da177e4SLinus Torvalds 	if (!datamsg) {
16371da177e4SLinus Torvalds 		err = -ENOMEM;
16381da177e4SLinus Torvalds 		goto out_free;
16391da177e4SLinus Torvalds 	}
16401da177e4SLinus Torvalds 
16411da177e4SLinus Torvalds 	/* Now send the (possibly) fragmented message. */
16421da177e4SLinus Torvalds 	list_for_each(pos, &datamsg->chunks) {
16431da177e4SLinus Torvalds 		chunk = list_entry(pos, struct sctp_chunk, frag_list);
16441da177e4SLinus Torvalds 		sctp_datamsg_track(chunk);
16451da177e4SLinus Torvalds 
16461da177e4SLinus Torvalds 		/* Do accounting for the write space.  */
16471da177e4SLinus Torvalds 		sctp_set_owner_w(chunk);
16481da177e4SLinus Torvalds 
16491da177e4SLinus Torvalds 		chunk->transport = chunk_tp;
16501da177e4SLinus Torvalds 
16511da177e4SLinus Torvalds 		/* Send it to the lower layers.  Note:  all chunks
16521da177e4SLinus Torvalds 		 * must either fail or succeed.   The lower layer
16531da177e4SLinus Torvalds 		 * works that way today.  Keep it that way or this
16541da177e4SLinus Torvalds 		 * breaks.
16551da177e4SLinus Torvalds 		 */
16561da177e4SLinus Torvalds 		err = sctp_primitive_SEND(asoc, chunk);
16571da177e4SLinus Torvalds 		/* Did the lower layer accept the chunk? */
16581da177e4SLinus Torvalds 		if (err)
16591da177e4SLinus Torvalds 			sctp_chunk_free(chunk);
16601da177e4SLinus Torvalds 		SCTP_DEBUG_PRINTK("We sent primitively.\n");
16611da177e4SLinus Torvalds 	}
16621da177e4SLinus Torvalds 
16631da177e4SLinus Torvalds 	sctp_datamsg_free(datamsg);
16641da177e4SLinus Torvalds 	if (err)
16651da177e4SLinus Torvalds 		goto out_free;
16661da177e4SLinus Torvalds 	else
16671da177e4SLinus Torvalds 		err = msg_len;
16681da177e4SLinus Torvalds 
16691da177e4SLinus Torvalds 	/* If we are already past ASSOCIATE, the lower
16701da177e4SLinus Torvalds 	 * layers are responsible for association cleanup.
16711da177e4SLinus Torvalds 	 */
16721da177e4SLinus Torvalds 	goto out_unlock;
16731da177e4SLinus Torvalds 
16741da177e4SLinus Torvalds out_free:
16751da177e4SLinus Torvalds 	if (new_asoc)
16761da177e4SLinus Torvalds 		sctp_association_free(asoc);
16771da177e4SLinus Torvalds out_unlock:
16781da177e4SLinus Torvalds 	sctp_release_sock(sk);
16791da177e4SLinus Torvalds 
16801da177e4SLinus Torvalds out_nounlock:
16811da177e4SLinus Torvalds 	return sctp_error(sk, msg_flags, err);
16821da177e4SLinus Torvalds 
16831da177e4SLinus Torvalds #if 0
16841da177e4SLinus Torvalds do_sock_err:
16851da177e4SLinus Torvalds 	if (msg_len)
16861da177e4SLinus Torvalds 		err = msg_len;
16871da177e4SLinus Torvalds 	else
16881da177e4SLinus Torvalds 		err = sock_error(sk);
16891da177e4SLinus Torvalds 	goto out;
16901da177e4SLinus Torvalds 
16911da177e4SLinus Torvalds do_interrupted:
16921da177e4SLinus Torvalds 	if (msg_len)
16931da177e4SLinus Torvalds 		err = msg_len;
16941da177e4SLinus Torvalds 	goto out;
16951da177e4SLinus Torvalds #endif /* 0 */
16961da177e4SLinus Torvalds }
16971da177e4SLinus Torvalds 
16981da177e4SLinus Torvalds /* This is an extended version of skb_pull() that removes the data from the
16991da177e4SLinus Torvalds  * start of a skb even when data is spread across the list of skb's in the
17001da177e4SLinus Torvalds  * frag_list. len specifies the total amount of data that needs to be removed.
17011da177e4SLinus Torvalds  * when 'len' bytes could be removed from the skb, it returns 0.
17021da177e4SLinus Torvalds  * If 'len' exceeds the total skb length,  it returns the no. of bytes that
17031da177e4SLinus Torvalds  * could not be removed.
17041da177e4SLinus Torvalds  */
17051da177e4SLinus Torvalds static int sctp_skb_pull(struct sk_buff *skb, int len)
17061da177e4SLinus Torvalds {
17071da177e4SLinus Torvalds 	struct sk_buff *list;
17081da177e4SLinus Torvalds 	int skb_len = skb_headlen(skb);
17091da177e4SLinus Torvalds 	int rlen;
17101da177e4SLinus Torvalds 
17111da177e4SLinus Torvalds 	if (len <= skb_len) {
17121da177e4SLinus Torvalds 		__skb_pull(skb, len);
17131da177e4SLinus Torvalds 		return 0;
17141da177e4SLinus Torvalds 	}
17151da177e4SLinus Torvalds 	len -= skb_len;
17161da177e4SLinus Torvalds 	__skb_pull(skb, skb_len);
17171da177e4SLinus Torvalds 
17181da177e4SLinus Torvalds 	for (list = skb_shinfo(skb)->frag_list; list; list = list->next) {
17191da177e4SLinus Torvalds 		rlen = sctp_skb_pull(list, len);
17201da177e4SLinus Torvalds 		skb->len -= (len-rlen);
17211da177e4SLinus Torvalds 		skb->data_len -= (len-rlen);
17221da177e4SLinus Torvalds 
17231da177e4SLinus Torvalds 		if (!rlen)
17241da177e4SLinus Torvalds 			return 0;
17251da177e4SLinus Torvalds 
17261da177e4SLinus Torvalds 		len = rlen;
17271da177e4SLinus Torvalds 	}
17281da177e4SLinus Torvalds 
17291da177e4SLinus Torvalds 	return len;
17301da177e4SLinus Torvalds }
17311da177e4SLinus Torvalds 
17321da177e4SLinus Torvalds /* API 3.1.3  recvmsg() - UDP Style Syntax
17331da177e4SLinus Torvalds  *
17341da177e4SLinus Torvalds  *  ssize_t recvmsg(int socket, struct msghdr *message,
17351da177e4SLinus Torvalds  *                    int flags);
17361da177e4SLinus Torvalds  *
17371da177e4SLinus Torvalds  *  socket  - the socket descriptor of the endpoint.
17381da177e4SLinus Torvalds  *  message - pointer to the msghdr structure which contains a single
17391da177e4SLinus Torvalds  *            user message and possibly some ancillary data.
17401da177e4SLinus Torvalds  *
17411da177e4SLinus Torvalds  *            See Section 5 for complete description of the data
17421da177e4SLinus Torvalds  *            structures.
17431da177e4SLinus Torvalds  *
17441da177e4SLinus Torvalds  *  flags   - flags sent or received with the user message, see Section
17451da177e4SLinus Torvalds  *            5 for complete description of the flags.
17461da177e4SLinus Torvalds  */
17471da177e4SLinus Torvalds static struct sk_buff *sctp_skb_recv_datagram(struct sock *, int, int, int *);
17481da177e4SLinus Torvalds 
17491da177e4SLinus Torvalds SCTP_STATIC int sctp_recvmsg(struct kiocb *iocb, struct sock *sk,
17501da177e4SLinus Torvalds 			     struct msghdr *msg, size_t len, int noblock,
17511da177e4SLinus Torvalds 			     int flags, int *addr_len)
17521da177e4SLinus Torvalds {
17531da177e4SLinus Torvalds 	struct sctp_ulpevent *event = NULL;
17541da177e4SLinus Torvalds 	struct sctp_sock *sp = sctp_sk(sk);
17551da177e4SLinus Torvalds 	struct sk_buff *skb;
17561da177e4SLinus Torvalds 	int copied;
17571da177e4SLinus Torvalds 	int err = 0;
17581da177e4SLinus Torvalds 	int skb_len;
17591da177e4SLinus Torvalds 
17601da177e4SLinus Torvalds 	SCTP_DEBUG_PRINTK("sctp_recvmsg(%s: %p, %s: %p, %s: %zd, %s: %d, %s: "
17611da177e4SLinus Torvalds 			  "0x%x, %s: %p)\n", "sk", sk, "msghdr", msg,
17621da177e4SLinus Torvalds 			  "len", len, "knoblauch", noblock,
17631da177e4SLinus Torvalds 			  "flags", flags, "addr_len", addr_len);
17641da177e4SLinus Torvalds 
17651da177e4SLinus Torvalds 	sctp_lock_sock(sk);
17661da177e4SLinus Torvalds 
17671da177e4SLinus Torvalds 	if (sctp_style(sk, TCP) && !sctp_sstate(sk, ESTABLISHED)) {
17681da177e4SLinus Torvalds 		err = -ENOTCONN;
17691da177e4SLinus Torvalds 		goto out;
17701da177e4SLinus Torvalds 	}
17711da177e4SLinus Torvalds 
17721da177e4SLinus Torvalds 	skb = sctp_skb_recv_datagram(sk, flags, noblock, &err);
17731da177e4SLinus Torvalds 	if (!skb)
17741da177e4SLinus Torvalds 		goto out;
17751da177e4SLinus Torvalds 
17761da177e4SLinus Torvalds 	/* Get the total length of the skb including any skb's in the
17771da177e4SLinus Torvalds 	 * frag_list.
17781da177e4SLinus Torvalds 	 */
17791da177e4SLinus Torvalds 	skb_len = skb->len;
17801da177e4SLinus Torvalds 
17811da177e4SLinus Torvalds 	copied = skb_len;
17821da177e4SLinus Torvalds 	if (copied > len)
17831da177e4SLinus Torvalds 		copied = len;
17841da177e4SLinus Torvalds 
17851da177e4SLinus Torvalds 	err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
17861da177e4SLinus Torvalds 
17871da177e4SLinus Torvalds 	event = sctp_skb2event(skb);
17881da177e4SLinus Torvalds 
17891da177e4SLinus Torvalds 	if (err)
17901da177e4SLinus Torvalds 		goto out_free;
17911da177e4SLinus Torvalds 
17921da177e4SLinus Torvalds 	sock_recv_timestamp(msg, sk, skb);
17931da177e4SLinus Torvalds 	if (sctp_ulpevent_is_notification(event)) {
17941da177e4SLinus Torvalds 		msg->msg_flags |= MSG_NOTIFICATION;
17951da177e4SLinus Torvalds 		sp->pf->event_msgname(event, msg->msg_name, addr_len);
17961da177e4SLinus Torvalds 	} else {
17971da177e4SLinus Torvalds 		sp->pf->skb_msgname(skb, msg->msg_name, addr_len);
17981da177e4SLinus Torvalds 	}
17991da177e4SLinus Torvalds 
18001da177e4SLinus Torvalds 	/* Check if we allow SCTP_SNDRCVINFO. */
18011da177e4SLinus Torvalds 	if (sp->subscribe.sctp_data_io_event)
18021da177e4SLinus Torvalds 		sctp_ulpevent_read_sndrcvinfo(event, msg);
18031da177e4SLinus Torvalds #if 0
18041da177e4SLinus Torvalds 	/* FIXME: we should be calling IP/IPv6 layers.  */
18051da177e4SLinus Torvalds 	if (sk->sk_protinfo.af_inet.cmsg_flags)
18061da177e4SLinus Torvalds 		ip_cmsg_recv(msg, skb);
18071da177e4SLinus Torvalds #endif
18081da177e4SLinus Torvalds 
18091da177e4SLinus Torvalds 	err = copied;
18101da177e4SLinus Torvalds 
18111da177e4SLinus Torvalds 	/* If skb's length exceeds the user's buffer, update the skb and
18121da177e4SLinus Torvalds 	 * push it back to the receive_queue so that the next call to
18131da177e4SLinus Torvalds 	 * recvmsg() will return the remaining data. Don't set MSG_EOR.
18141da177e4SLinus Torvalds 	 */
18151da177e4SLinus Torvalds 	if (skb_len > copied) {
18161da177e4SLinus Torvalds 		msg->msg_flags &= ~MSG_EOR;
18171da177e4SLinus Torvalds 		if (flags & MSG_PEEK)
18181da177e4SLinus Torvalds 			goto out_free;
18191da177e4SLinus Torvalds 		sctp_skb_pull(skb, copied);
18201da177e4SLinus Torvalds 		skb_queue_head(&sk->sk_receive_queue, skb);
18211da177e4SLinus Torvalds 
18221da177e4SLinus Torvalds 		/* When only partial message is copied to the user, increase
18231da177e4SLinus Torvalds 		 * rwnd by that amount. If all the data in the skb is read,
18241da177e4SLinus Torvalds 		 * rwnd is updated when the event is freed.
18251da177e4SLinus Torvalds 		 */
18261da177e4SLinus Torvalds 		sctp_assoc_rwnd_increase(event->asoc, copied);
18271da177e4SLinus Torvalds 		goto out;
18281da177e4SLinus Torvalds 	} else if ((event->msg_flags & MSG_NOTIFICATION) ||
18291da177e4SLinus Torvalds 		   (event->msg_flags & MSG_EOR))
18301da177e4SLinus Torvalds 		msg->msg_flags |= MSG_EOR;
18311da177e4SLinus Torvalds 	else
18321da177e4SLinus Torvalds 		msg->msg_flags &= ~MSG_EOR;
18331da177e4SLinus Torvalds 
18341da177e4SLinus Torvalds out_free:
18351da177e4SLinus Torvalds 	if (flags & MSG_PEEK) {
18361da177e4SLinus Torvalds 		/* Release the skb reference acquired after peeking the skb in
18371da177e4SLinus Torvalds 		 * sctp_skb_recv_datagram().
18381da177e4SLinus Torvalds 		 */
18391da177e4SLinus Torvalds 		kfree_skb(skb);
18401da177e4SLinus Torvalds 	} else {
18411da177e4SLinus Torvalds 		/* Free the event which includes releasing the reference to
18421da177e4SLinus Torvalds 		 * the owner of the skb, freeing the skb and updating the
18431da177e4SLinus Torvalds 		 * rwnd.
18441da177e4SLinus Torvalds 		 */
18451da177e4SLinus Torvalds 		sctp_ulpevent_free(event);
18461da177e4SLinus Torvalds 	}
18471da177e4SLinus Torvalds out:
18481da177e4SLinus Torvalds 	sctp_release_sock(sk);
18491da177e4SLinus Torvalds 	return err;
18501da177e4SLinus Torvalds }
18511da177e4SLinus Torvalds 
18521da177e4SLinus Torvalds /* 7.1.12 Enable/Disable message fragmentation (SCTP_DISABLE_FRAGMENTS)
18531da177e4SLinus Torvalds  *
18541da177e4SLinus Torvalds  * This option is a on/off flag.  If enabled no SCTP message
18551da177e4SLinus Torvalds  * fragmentation will be performed.  Instead if a message being sent
18561da177e4SLinus Torvalds  * exceeds the current PMTU size, the message will NOT be sent and
18571da177e4SLinus Torvalds  * instead a error will be indicated to the user.
18581da177e4SLinus Torvalds  */
18591da177e4SLinus Torvalds static int sctp_setsockopt_disable_fragments(struct sock *sk,
18601da177e4SLinus Torvalds 					    char __user *optval, int optlen)
18611da177e4SLinus Torvalds {
18621da177e4SLinus Torvalds 	int val;
18631da177e4SLinus Torvalds 
18641da177e4SLinus Torvalds 	if (optlen < sizeof(int))
18651da177e4SLinus Torvalds 		return -EINVAL;
18661da177e4SLinus Torvalds 
18671da177e4SLinus Torvalds 	if (get_user(val, (int __user *)optval))
18681da177e4SLinus Torvalds 		return -EFAULT;
18691da177e4SLinus Torvalds 
18701da177e4SLinus Torvalds 	sctp_sk(sk)->disable_fragments = (val == 0) ? 0 : 1;
18711da177e4SLinus Torvalds 
18721da177e4SLinus Torvalds 	return 0;
18731da177e4SLinus Torvalds }
18741da177e4SLinus Torvalds 
18751da177e4SLinus Torvalds static int sctp_setsockopt_events(struct sock *sk, char __user *optval,
18761da177e4SLinus Torvalds 					int optlen)
18771da177e4SLinus Torvalds {
18781da177e4SLinus Torvalds 	if (optlen != sizeof(struct sctp_event_subscribe))
18791da177e4SLinus Torvalds 		return -EINVAL;
18801da177e4SLinus Torvalds 	if (copy_from_user(&sctp_sk(sk)->subscribe, optval, optlen))
18811da177e4SLinus Torvalds 		return -EFAULT;
18821da177e4SLinus Torvalds 	return 0;
18831da177e4SLinus Torvalds }
18841da177e4SLinus Torvalds 
18851da177e4SLinus Torvalds /* 7.1.8 Automatic Close of associations (SCTP_AUTOCLOSE)
18861da177e4SLinus Torvalds  *
18871da177e4SLinus Torvalds  * This socket option is applicable to the UDP-style socket only.  When
18881da177e4SLinus Torvalds  * set it will cause associations that are idle for more than the
18891da177e4SLinus Torvalds  * specified number of seconds to automatically close.  An association
18901da177e4SLinus Torvalds  * being idle is defined an association that has NOT sent or received
18911da177e4SLinus Torvalds  * user data.  The special value of '0' indicates that no automatic
18921da177e4SLinus Torvalds  * close of any associations should be performed.  The option expects an
18931da177e4SLinus Torvalds  * integer defining the number of seconds of idle time before an
18941da177e4SLinus Torvalds  * association is closed.
18951da177e4SLinus Torvalds  */
18961da177e4SLinus Torvalds static int sctp_setsockopt_autoclose(struct sock *sk, char __user *optval,
18971da177e4SLinus Torvalds 					    int optlen)
18981da177e4SLinus Torvalds {
18991da177e4SLinus Torvalds 	struct sctp_sock *sp = sctp_sk(sk);
19001da177e4SLinus Torvalds 
19011da177e4SLinus Torvalds 	/* Applicable to UDP-style socket only */
19021da177e4SLinus Torvalds 	if (sctp_style(sk, TCP))
19031da177e4SLinus Torvalds 		return -EOPNOTSUPP;
19041da177e4SLinus Torvalds 	if (optlen != sizeof(int))
19051da177e4SLinus Torvalds 		return -EINVAL;
19061da177e4SLinus Torvalds 	if (copy_from_user(&sp->autoclose, optval, optlen))
19071da177e4SLinus Torvalds 		return -EFAULT;
19081da177e4SLinus Torvalds 
19091da177e4SLinus Torvalds 	sp->ep->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE] = sp->autoclose * HZ;
19101da177e4SLinus Torvalds 	return 0;
19111da177e4SLinus Torvalds }
19121da177e4SLinus Torvalds 
19131da177e4SLinus Torvalds /* 7.1.13 Peer Address Parameters (SCTP_PEER_ADDR_PARAMS)
19141da177e4SLinus Torvalds  *
19151da177e4SLinus Torvalds  * Applications can enable or disable heartbeats for any peer address of
19161da177e4SLinus Torvalds  * an association, modify an address's heartbeat interval, force a
19171da177e4SLinus Torvalds  * heartbeat to be sent immediately, and adjust the address's maximum
19181da177e4SLinus Torvalds  * number of retransmissions sent before an address is considered
19191da177e4SLinus Torvalds  * unreachable.  The following structure is used to access and modify an
19201da177e4SLinus Torvalds  * address's parameters:
19211da177e4SLinus Torvalds  *
19221da177e4SLinus Torvalds  *  struct sctp_paddrparams {
19231da177e4SLinus Torvalds  *      sctp_assoc_t            spp_assoc_id;
19241da177e4SLinus Torvalds  *      struct sockaddr_storage spp_address;
19251da177e4SLinus Torvalds  *      uint32_t                spp_hbinterval;
19261da177e4SLinus Torvalds  *      uint16_t                spp_pathmaxrxt;
19271da177e4SLinus Torvalds  *  };
19281da177e4SLinus Torvalds  *
19291da177e4SLinus Torvalds  *   spp_assoc_id    - (UDP style socket) This is filled in the application,
19301da177e4SLinus Torvalds  *                     and identifies the association for this query.
19311da177e4SLinus Torvalds  *   spp_address     - This specifies which address is of interest.
19321da177e4SLinus Torvalds  *   spp_hbinterval  - This contains the value of the heartbeat interval,
19331da177e4SLinus Torvalds  *                     in milliseconds.  A value of 0, when modifying the
19341da177e4SLinus Torvalds  *                     parameter, specifies that the heartbeat on this
19351da177e4SLinus Torvalds  *                     address should be disabled. A value of UINT32_MAX
19361da177e4SLinus Torvalds  *                     (4294967295), when modifying the parameter,
19371da177e4SLinus Torvalds  *                     specifies that a heartbeat should be sent
19381da177e4SLinus Torvalds  *                     immediately to the peer address, and the current
19391da177e4SLinus Torvalds  *                     interval should remain unchanged.
19401da177e4SLinus Torvalds  *   spp_pathmaxrxt  - This contains the maximum number of
19411da177e4SLinus Torvalds  *                     retransmissions before this address shall be
19421da177e4SLinus Torvalds  *                     considered unreachable.
19431da177e4SLinus Torvalds  */
19441da177e4SLinus Torvalds static int sctp_setsockopt_peer_addr_params(struct sock *sk,
19451da177e4SLinus Torvalds 					    char __user *optval, int optlen)
19461da177e4SLinus Torvalds {
19471da177e4SLinus Torvalds 	struct sctp_paddrparams params;
19481da177e4SLinus Torvalds 	struct sctp_transport *trans;
19491da177e4SLinus Torvalds 	int error;
19501da177e4SLinus Torvalds 
19511da177e4SLinus Torvalds 	if (optlen != sizeof(struct sctp_paddrparams))
19521da177e4SLinus Torvalds 		return -EINVAL;
19531da177e4SLinus Torvalds 	if (copy_from_user(&params, optval, optlen))
19541da177e4SLinus Torvalds 		return -EFAULT;
19551da177e4SLinus Torvalds 
19561da177e4SLinus Torvalds 	/*
19571da177e4SLinus Torvalds 	 * API 7. Socket Options (setting the default value for the endpoint)
19581da177e4SLinus Torvalds 	 * All options that support specific settings on an association by
19591da177e4SLinus Torvalds 	 * filling in either an association id variable or a sockaddr_storage
19601da177e4SLinus Torvalds 	 * SHOULD also support setting of the same value for the entire endpoint
19611da177e4SLinus Torvalds 	 * (i.e. future associations). To accomplish this the following logic is
19621da177e4SLinus Torvalds 	 * used when setting one of these options:
19631da177e4SLinus Torvalds 
19641da177e4SLinus Torvalds 	 * c) If neither the sockaddr_storage or association identification is
19651da177e4SLinus Torvalds 	 *    set i.e. the sockaddr_storage is set to all 0's (INADDR_ANY) and
19661da177e4SLinus Torvalds 	 *    the association identification is 0, the settings are a default
19671da177e4SLinus Torvalds 	 *    and to be applied to the endpoint (all future associations).
19681da177e4SLinus Torvalds 	 */
19691da177e4SLinus Torvalds 
19701da177e4SLinus Torvalds 	/* update default value for endpoint (all future associations) */
19711da177e4SLinus Torvalds 	if (!params.spp_assoc_id &&
19721da177e4SLinus Torvalds 	    sctp_is_any(( union sctp_addr *)&params.spp_address)) {
19731da177e4SLinus Torvalds 		/* Manual heartbeat on an endpoint is invalid. */
19741da177e4SLinus Torvalds 		if (0xffffffff == params.spp_hbinterval)
19751da177e4SLinus Torvalds 			return -EINVAL;
19761da177e4SLinus Torvalds 		else if (params.spp_hbinterval)
19771da177e4SLinus Torvalds 			sctp_sk(sk)->paddrparam.spp_hbinterval =
19781da177e4SLinus Torvalds 						params.spp_hbinterval;
19791da177e4SLinus Torvalds 		if (params.spp_pathmaxrxt)
19801da177e4SLinus Torvalds 			sctp_sk(sk)->paddrparam.spp_pathmaxrxt =
19811da177e4SLinus Torvalds 						params.spp_pathmaxrxt;
19821da177e4SLinus Torvalds 		return 0;
19831da177e4SLinus Torvalds 	}
19841da177e4SLinus Torvalds 
19851da177e4SLinus Torvalds 	trans = sctp_addr_id2transport(sk, &params.spp_address,
19861da177e4SLinus Torvalds 				       params.spp_assoc_id);
19871da177e4SLinus Torvalds 	if (!trans)
19881da177e4SLinus Torvalds 		return -EINVAL;
19891da177e4SLinus Torvalds 
19901da177e4SLinus Torvalds 	/* Applications can enable or disable heartbeats for any peer address
19911da177e4SLinus Torvalds 	 * of an association, modify an address's heartbeat interval, force a
19921da177e4SLinus Torvalds 	 * heartbeat to be sent immediately, and adjust the address's maximum
19931da177e4SLinus Torvalds 	 * number of retransmissions sent before an address is considered
19941da177e4SLinus Torvalds 	 * unreachable.
19951da177e4SLinus Torvalds 	 *
19961da177e4SLinus Torvalds 	 * The value of the heartbeat interval, in milliseconds. A value of
19971da177e4SLinus Torvalds 	 * UINT32_MAX (4294967295), when modifying the parameter, specifies
19981da177e4SLinus Torvalds 	 * that a heartbeat should be sent immediately to the peer address,
19991da177e4SLinus Torvalds 	 * and the current interval should remain unchanged.
20001da177e4SLinus Torvalds 	 */
20011da177e4SLinus Torvalds 	if (0xffffffff == params.spp_hbinterval) {
20021da177e4SLinus Torvalds 		error = sctp_primitive_REQUESTHEARTBEAT (trans->asoc, trans);
20031da177e4SLinus Torvalds 		if (error)
20041da177e4SLinus Torvalds 			return error;
20051da177e4SLinus Torvalds 	} else {
20061da177e4SLinus Torvalds 	/* The value of the heartbeat interval, in milliseconds. A value of 0,
20071da177e4SLinus Torvalds 	 * when modifying the parameter, specifies that the heartbeat on this
20081da177e4SLinus Torvalds 	 * address should be disabled.
20091da177e4SLinus Torvalds 	 */
20101da177e4SLinus Torvalds 		if (params.spp_hbinterval) {
20111da177e4SLinus Torvalds 			trans->hb_allowed = 1;
20121da177e4SLinus Torvalds 			trans->hb_interval =
20131da177e4SLinus Torvalds 				msecs_to_jiffies(params.spp_hbinterval);
20141da177e4SLinus Torvalds 		} else
20151da177e4SLinus Torvalds 			trans->hb_allowed = 0;
20161da177e4SLinus Torvalds 	}
20171da177e4SLinus Torvalds 
20181da177e4SLinus Torvalds 	/* spp_pathmaxrxt contains the maximum number of retransmissions
20191da177e4SLinus Torvalds 	 * before this address shall be considered unreachable.
20201da177e4SLinus Torvalds 	 */
20211da177e4SLinus Torvalds 	if (params.spp_pathmaxrxt)
20221da177e4SLinus Torvalds 		trans->max_retrans = params.spp_pathmaxrxt;
20231da177e4SLinus Torvalds 
20241da177e4SLinus Torvalds 	return 0;
20251da177e4SLinus Torvalds }
20261da177e4SLinus Torvalds 
20271da177e4SLinus Torvalds /* 7.1.3 Initialization Parameters (SCTP_INITMSG)
20281da177e4SLinus Torvalds  *
20291da177e4SLinus Torvalds  * Applications can specify protocol parameters for the default association
20301da177e4SLinus Torvalds  * initialization.  The option name argument to setsockopt() and getsockopt()
20311da177e4SLinus Torvalds  * is SCTP_INITMSG.
20321da177e4SLinus Torvalds  *
20331da177e4SLinus Torvalds  * Setting initialization parameters is effective only on an unconnected
20341da177e4SLinus Torvalds  * socket (for UDP-style sockets only future associations are effected
20351da177e4SLinus Torvalds  * by the change).  With TCP-style sockets, this option is inherited by
20361da177e4SLinus Torvalds  * sockets derived from a listener socket.
20371da177e4SLinus Torvalds  */
20381da177e4SLinus Torvalds static int sctp_setsockopt_initmsg(struct sock *sk, char __user *optval, int optlen)
20391da177e4SLinus Torvalds {
20401da177e4SLinus Torvalds 	struct sctp_initmsg sinit;
20411da177e4SLinus Torvalds 	struct sctp_sock *sp = sctp_sk(sk);
20421da177e4SLinus Torvalds 
20431da177e4SLinus Torvalds 	if (optlen != sizeof(struct sctp_initmsg))
20441da177e4SLinus Torvalds 		return -EINVAL;
20451da177e4SLinus Torvalds 	if (copy_from_user(&sinit, optval, optlen))
20461da177e4SLinus Torvalds 		return -EFAULT;
20471da177e4SLinus Torvalds 
20481da177e4SLinus Torvalds 	if (sinit.sinit_num_ostreams)
20491da177e4SLinus Torvalds 		sp->initmsg.sinit_num_ostreams = sinit.sinit_num_ostreams;
20501da177e4SLinus Torvalds 	if (sinit.sinit_max_instreams)
20511da177e4SLinus Torvalds 		sp->initmsg.sinit_max_instreams = sinit.sinit_max_instreams;
20521da177e4SLinus Torvalds 	if (sinit.sinit_max_attempts)
20531da177e4SLinus Torvalds 		sp->initmsg.sinit_max_attempts = sinit.sinit_max_attempts;
20541da177e4SLinus Torvalds 	if (sinit.sinit_max_init_timeo)
20551da177e4SLinus Torvalds 		sp->initmsg.sinit_max_init_timeo = sinit.sinit_max_init_timeo;
20561da177e4SLinus Torvalds 
20571da177e4SLinus Torvalds 	return 0;
20581da177e4SLinus Torvalds }
20591da177e4SLinus Torvalds 
20601da177e4SLinus Torvalds /*
20611da177e4SLinus Torvalds  * 7.1.14 Set default send parameters (SCTP_DEFAULT_SEND_PARAM)
20621da177e4SLinus Torvalds  *
20631da177e4SLinus Torvalds  *   Applications that wish to use the sendto() system call may wish to
20641da177e4SLinus Torvalds  *   specify a default set of parameters that would normally be supplied
20651da177e4SLinus Torvalds  *   through the inclusion of ancillary data.  This socket option allows
20661da177e4SLinus Torvalds  *   such an application to set the default sctp_sndrcvinfo structure.
20671da177e4SLinus Torvalds  *   The application that wishes to use this socket option simply passes
20681da177e4SLinus Torvalds  *   in to this call the sctp_sndrcvinfo structure defined in Section
20691da177e4SLinus Torvalds  *   5.2.2) The input parameters accepted by this call include
20701da177e4SLinus Torvalds  *   sinfo_stream, sinfo_flags, sinfo_ppid, sinfo_context,
20711da177e4SLinus Torvalds  *   sinfo_timetolive.  The user must provide the sinfo_assoc_id field in
20721da177e4SLinus Torvalds  *   to this call if the caller is using the UDP model.
20731da177e4SLinus Torvalds  */
20741da177e4SLinus Torvalds static int sctp_setsockopt_default_send_param(struct sock *sk,
20751da177e4SLinus Torvalds 						char __user *optval, int optlen)
20761da177e4SLinus Torvalds {
20771da177e4SLinus Torvalds 	struct sctp_sndrcvinfo info;
20781da177e4SLinus Torvalds 	struct sctp_association *asoc;
20791da177e4SLinus Torvalds 	struct sctp_sock *sp = sctp_sk(sk);
20801da177e4SLinus Torvalds 
20811da177e4SLinus Torvalds 	if (optlen != sizeof(struct sctp_sndrcvinfo))
20821da177e4SLinus Torvalds 		return -EINVAL;
20831da177e4SLinus Torvalds 	if (copy_from_user(&info, optval, optlen))
20841da177e4SLinus Torvalds 		return -EFAULT;
20851da177e4SLinus Torvalds 
20861da177e4SLinus Torvalds 	asoc = sctp_id2assoc(sk, info.sinfo_assoc_id);
20871da177e4SLinus Torvalds 	if (!asoc && info.sinfo_assoc_id && sctp_style(sk, UDP))
20881da177e4SLinus Torvalds 		return -EINVAL;
20891da177e4SLinus Torvalds 
20901da177e4SLinus Torvalds 	if (asoc) {
20911da177e4SLinus Torvalds 		asoc->default_stream = info.sinfo_stream;
20921da177e4SLinus Torvalds 		asoc->default_flags = info.sinfo_flags;
20931da177e4SLinus Torvalds 		asoc->default_ppid = info.sinfo_ppid;
20941da177e4SLinus Torvalds 		asoc->default_context = info.sinfo_context;
20951da177e4SLinus Torvalds 		asoc->default_timetolive = info.sinfo_timetolive;
20961da177e4SLinus Torvalds 	} else {
20971da177e4SLinus Torvalds 		sp->default_stream = info.sinfo_stream;
20981da177e4SLinus Torvalds 		sp->default_flags = info.sinfo_flags;
20991da177e4SLinus Torvalds 		sp->default_ppid = info.sinfo_ppid;
21001da177e4SLinus Torvalds 		sp->default_context = info.sinfo_context;
21011da177e4SLinus Torvalds 		sp->default_timetolive = info.sinfo_timetolive;
21021da177e4SLinus Torvalds 	}
21031da177e4SLinus Torvalds 
21041da177e4SLinus Torvalds 	return 0;
21051da177e4SLinus Torvalds }
21061da177e4SLinus Torvalds 
21071da177e4SLinus Torvalds /* 7.1.10 Set Primary Address (SCTP_PRIMARY_ADDR)
21081da177e4SLinus Torvalds  *
21091da177e4SLinus Torvalds  * Requests that the local SCTP stack use the enclosed peer address as
21101da177e4SLinus Torvalds  * the association primary.  The enclosed address must be one of the
21111da177e4SLinus Torvalds  * association peer's addresses.
21121da177e4SLinus Torvalds  */
21131da177e4SLinus Torvalds static int sctp_setsockopt_primary_addr(struct sock *sk, char __user *optval,
21141da177e4SLinus Torvalds 					int optlen)
21151da177e4SLinus Torvalds {
21161da177e4SLinus Torvalds 	struct sctp_prim prim;
21171da177e4SLinus Torvalds 	struct sctp_transport *trans;
21181da177e4SLinus Torvalds 
21191da177e4SLinus Torvalds 	if (optlen != sizeof(struct sctp_prim))
21201da177e4SLinus Torvalds 		return -EINVAL;
21211da177e4SLinus Torvalds 
21221da177e4SLinus Torvalds 	if (copy_from_user(&prim, optval, sizeof(struct sctp_prim)))
21231da177e4SLinus Torvalds 		return -EFAULT;
21241da177e4SLinus Torvalds 
21251da177e4SLinus Torvalds 	trans = sctp_addr_id2transport(sk, &prim.ssp_addr, prim.ssp_assoc_id);
21261da177e4SLinus Torvalds 	if (!trans)
21271da177e4SLinus Torvalds 		return -EINVAL;
21281da177e4SLinus Torvalds 
21291da177e4SLinus Torvalds 	sctp_assoc_set_primary(trans->asoc, trans);
21301da177e4SLinus Torvalds 
21311da177e4SLinus Torvalds 	return 0;
21321da177e4SLinus Torvalds }
21331da177e4SLinus Torvalds 
21341da177e4SLinus Torvalds /*
21351da177e4SLinus Torvalds  * 7.1.5 SCTP_NODELAY
21361da177e4SLinus Torvalds  *
21371da177e4SLinus Torvalds  * Turn on/off any Nagle-like algorithm.  This means that packets are
21381da177e4SLinus Torvalds  * generally sent as soon as possible and no unnecessary delays are
21391da177e4SLinus Torvalds  * introduced, at the cost of more packets in the network.  Expects an
21401da177e4SLinus Torvalds  *  integer boolean flag.
21411da177e4SLinus Torvalds  */
21421da177e4SLinus Torvalds static int sctp_setsockopt_nodelay(struct sock *sk, char __user *optval,
21431da177e4SLinus Torvalds 					int optlen)
21441da177e4SLinus Torvalds {
21451da177e4SLinus Torvalds 	int val;
21461da177e4SLinus Torvalds 
21471da177e4SLinus Torvalds 	if (optlen < sizeof(int))
21481da177e4SLinus Torvalds 		return -EINVAL;
21491da177e4SLinus Torvalds 	if (get_user(val, (int __user *)optval))
21501da177e4SLinus Torvalds 		return -EFAULT;
21511da177e4SLinus Torvalds 
21521da177e4SLinus Torvalds 	sctp_sk(sk)->nodelay = (val == 0) ? 0 : 1;
21531da177e4SLinus Torvalds 	return 0;
21541da177e4SLinus Torvalds }
21551da177e4SLinus Torvalds 
21561da177e4SLinus Torvalds /*
21571da177e4SLinus Torvalds  *
21581da177e4SLinus Torvalds  * 7.1.1 SCTP_RTOINFO
21591da177e4SLinus Torvalds  *
21601da177e4SLinus Torvalds  * The protocol parameters used to initialize and bound retransmission
21611da177e4SLinus Torvalds  * timeout (RTO) are tunable. sctp_rtoinfo structure is used to access
21621da177e4SLinus Torvalds  * and modify these parameters.
21631da177e4SLinus Torvalds  * All parameters are time values, in milliseconds.  A value of 0, when
21641da177e4SLinus Torvalds  * modifying the parameters, indicates that the current value should not
21651da177e4SLinus Torvalds  * be changed.
21661da177e4SLinus Torvalds  *
21671da177e4SLinus Torvalds  */
21681da177e4SLinus Torvalds static int sctp_setsockopt_rtoinfo(struct sock *sk, char __user *optval, int optlen) {
21691da177e4SLinus Torvalds 	struct sctp_rtoinfo rtoinfo;
21701da177e4SLinus Torvalds 	struct sctp_association *asoc;
21711da177e4SLinus Torvalds 
21721da177e4SLinus Torvalds 	if (optlen != sizeof (struct sctp_rtoinfo))
21731da177e4SLinus Torvalds 		return -EINVAL;
21741da177e4SLinus Torvalds 
21751da177e4SLinus Torvalds 	if (copy_from_user(&rtoinfo, optval, optlen))
21761da177e4SLinus Torvalds 		return -EFAULT;
21771da177e4SLinus Torvalds 
21781da177e4SLinus Torvalds 	asoc = sctp_id2assoc(sk, rtoinfo.srto_assoc_id);
21791da177e4SLinus Torvalds 
21801da177e4SLinus Torvalds 	/* Set the values to the specific association */
21811da177e4SLinus Torvalds 	if (!asoc && rtoinfo.srto_assoc_id && sctp_style(sk, UDP))
21821da177e4SLinus Torvalds 		return -EINVAL;
21831da177e4SLinus Torvalds 
21841da177e4SLinus Torvalds 	if (asoc) {
21851da177e4SLinus Torvalds 		if (rtoinfo.srto_initial != 0)
21861da177e4SLinus Torvalds 			asoc->rto_initial =
21871da177e4SLinus Torvalds 				msecs_to_jiffies(rtoinfo.srto_initial);
21881da177e4SLinus Torvalds 		if (rtoinfo.srto_max != 0)
21891da177e4SLinus Torvalds 			asoc->rto_max = msecs_to_jiffies(rtoinfo.srto_max);
21901da177e4SLinus Torvalds 		if (rtoinfo.srto_min != 0)
21911da177e4SLinus Torvalds 			asoc->rto_min = msecs_to_jiffies(rtoinfo.srto_min);
21921da177e4SLinus Torvalds 	} else {
21931da177e4SLinus Torvalds 		/* If there is no association or the association-id = 0
21941da177e4SLinus Torvalds 		 * set the values to the endpoint.
21951da177e4SLinus Torvalds 		 */
21961da177e4SLinus Torvalds 		struct sctp_sock *sp = sctp_sk(sk);
21971da177e4SLinus Torvalds 
21981da177e4SLinus Torvalds 		if (rtoinfo.srto_initial != 0)
21991da177e4SLinus Torvalds 			sp->rtoinfo.srto_initial = rtoinfo.srto_initial;
22001da177e4SLinus Torvalds 		if (rtoinfo.srto_max != 0)
22011da177e4SLinus Torvalds 			sp->rtoinfo.srto_max = rtoinfo.srto_max;
22021da177e4SLinus Torvalds 		if (rtoinfo.srto_min != 0)
22031da177e4SLinus Torvalds 			sp->rtoinfo.srto_min = rtoinfo.srto_min;
22041da177e4SLinus Torvalds 	}
22051da177e4SLinus Torvalds 
22061da177e4SLinus Torvalds 	return 0;
22071da177e4SLinus Torvalds }
22081da177e4SLinus Torvalds 
22091da177e4SLinus Torvalds /*
22101da177e4SLinus Torvalds  *
22111da177e4SLinus Torvalds  * 7.1.2 SCTP_ASSOCINFO
22121da177e4SLinus Torvalds  *
22131da177e4SLinus Torvalds  * This option is used to tune the the maximum retransmission attempts
22141da177e4SLinus Torvalds  * of the association.
22151da177e4SLinus Torvalds  * Returns an error if the new association retransmission value is
22161da177e4SLinus Torvalds  * greater than the sum of the retransmission value  of the peer.
22171da177e4SLinus Torvalds  * See [SCTP] for more information.
22181da177e4SLinus Torvalds  *
22191da177e4SLinus Torvalds  */
22201da177e4SLinus Torvalds static int sctp_setsockopt_associnfo(struct sock *sk, char __user *optval, int optlen)
22211da177e4SLinus Torvalds {
22221da177e4SLinus Torvalds 
22231da177e4SLinus Torvalds 	struct sctp_assocparams assocparams;
22241da177e4SLinus Torvalds 	struct sctp_association *asoc;
22251da177e4SLinus Torvalds 
22261da177e4SLinus Torvalds 	if (optlen != sizeof(struct sctp_assocparams))
22271da177e4SLinus Torvalds 		return -EINVAL;
22281da177e4SLinus Torvalds 	if (copy_from_user(&assocparams, optval, optlen))
22291da177e4SLinus Torvalds 		return -EFAULT;
22301da177e4SLinus Torvalds 
22311da177e4SLinus Torvalds 	asoc = sctp_id2assoc(sk, assocparams.sasoc_assoc_id);
22321da177e4SLinus Torvalds 
22331da177e4SLinus Torvalds 	if (!asoc && assocparams.sasoc_assoc_id && sctp_style(sk, UDP))
22341da177e4SLinus Torvalds 		return -EINVAL;
22351da177e4SLinus Torvalds 
22361da177e4SLinus Torvalds 	/* Set the values to the specific association */
22371da177e4SLinus Torvalds 	if (asoc) {
22381da177e4SLinus Torvalds 		if (assocparams.sasoc_asocmaxrxt != 0)
22391da177e4SLinus Torvalds 			asoc->max_retrans = assocparams.sasoc_asocmaxrxt;
22401da177e4SLinus Torvalds 		if (assocparams.sasoc_cookie_life != 0) {
22411da177e4SLinus Torvalds 			asoc->cookie_life.tv_sec =
22421da177e4SLinus Torvalds 					assocparams.sasoc_cookie_life / 1000;
22431da177e4SLinus Torvalds 			asoc->cookie_life.tv_usec =
22441da177e4SLinus Torvalds 					(assocparams.sasoc_cookie_life % 1000)
22451da177e4SLinus Torvalds 					* 1000;
22461da177e4SLinus Torvalds 		}
22471da177e4SLinus Torvalds 	} else {
22481da177e4SLinus Torvalds 		/* Set the values to the endpoint */
22491da177e4SLinus Torvalds 		struct sctp_sock *sp = sctp_sk(sk);
22501da177e4SLinus Torvalds 
22511da177e4SLinus Torvalds 		if (assocparams.sasoc_asocmaxrxt != 0)
22521da177e4SLinus Torvalds 			sp->assocparams.sasoc_asocmaxrxt =
22531da177e4SLinus Torvalds 						assocparams.sasoc_asocmaxrxt;
22541da177e4SLinus Torvalds 		if (assocparams.sasoc_cookie_life != 0)
22551da177e4SLinus Torvalds 			sp->assocparams.sasoc_cookie_life =
22561da177e4SLinus Torvalds 						assocparams.sasoc_cookie_life;
22571da177e4SLinus Torvalds 	}
22581da177e4SLinus Torvalds 	return 0;
22591da177e4SLinus Torvalds }
22601da177e4SLinus Torvalds 
22611da177e4SLinus Torvalds /*
22621da177e4SLinus Torvalds  * 7.1.16 Set/clear IPv4 mapped addresses (SCTP_I_WANT_MAPPED_V4_ADDR)
22631da177e4SLinus Torvalds  *
22641da177e4SLinus Torvalds  * This socket option is a boolean flag which turns on or off mapped V4
22651da177e4SLinus Torvalds  * addresses.  If this option is turned on and the socket is type
22661da177e4SLinus Torvalds  * PF_INET6, then IPv4 addresses will be mapped to V6 representation.
22671da177e4SLinus Torvalds  * If this option is turned off, then no mapping will be done of V4
22681da177e4SLinus Torvalds  * addresses and a user will receive both PF_INET6 and PF_INET type
22691da177e4SLinus Torvalds  * addresses on the socket.
22701da177e4SLinus Torvalds  */
22711da177e4SLinus Torvalds static int sctp_setsockopt_mappedv4(struct sock *sk, char __user *optval, int optlen)
22721da177e4SLinus Torvalds {
22731da177e4SLinus Torvalds 	int val;
22741da177e4SLinus Torvalds 	struct sctp_sock *sp = sctp_sk(sk);
22751da177e4SLinus Torvalds 
22761da177e4SLinus Torvalds 	if (optlen < sizeof(int))
22771da177e4SLinus Torvalds 		return -EINVAL;
22781da177e4SLinus Torvalds 	if (get_user(val, (int __user *)optval))
22791da177e4SLinus Torvalds 		return -EFAULT;
22801da177e4SLinus Torvalds 	if (val)
22811da177e4SLinus Torvalds 		sp->v4mapped = 1;
22821da177e4SLinus Torvalds 	else
22831da177e4SLinus Torvalds 		sp->v4mapped = 0;
22841da177e4SLinus Torvalds 
22851da177e4SLinus Torvalds 	return 0;
22861da177e4SLinus Torvalds }
22871da177e4SLinus Torvalds 
22881da177e4SLinus Torvalds /*
22891da177e4SLinus Torvalds  * 7.1.17 Set the maximum fragrmentation size (SCTP_MAXSEG)
22901da177e4SLinus Torvalds  *
22911da177e4SLinus Torvalds  * This socket option specifies the maximum size to put in any outgoing
22921da177e4SLinus Torvalds  * SCTP chunk.  If a message is larger than this size it will be
22931da177e4SLinus Torvalds  * fragmented by SCTP into the specified size.  Note that the underlying
22941da177e4SLinus Torvalds  * SCTP implementation may fragment into smaller sized chunks when the
22951da177e4SLinus Torvalds  * PMTU of the underlying association is smaller than the value set by
22961da177e4SLinus Torvalds  * the user.
22971da177e4SLinus Torvalds  */
22981da177e4SLinus Torvalds static int sctp_setsockopt_maxseg(struct sock *sk, char __user *optval, int optlen)
22991da177e4SLinus Torvalds {
23001da177e4SLinus Torvalds 	struct sctp_association *asoc;
23011da177e4SLinus Torvalds 	struct list_head *pos;
23021da177e4SLinus Torvalds 	struct sctp_sock *sp = sctp_sk(sk);
23031da177e4SLinus Torvalds 	int val;
23041da177e4SLinus Torvalds 
23051da177e4SLinus Torvalds 	if (optlen < sizeof(int))
23061da177e4SLinus Torvalds 		return -EINVAL;
23071da177e4SLinus Torvalds 	if (get_user(val, (int __user *)optval))
23081da177e4SLinus Torvalds 		return -EFAULT;
23091da177e4SLinus Torvalds 	if ((val < 8) || (val > SCTP_MAX_CHUNK_LEN))
23101da177e4SLinus Torvalds 		return -EINVAL;
23111da177e4SLinus Torvalds 	sp->user_frag = val;
23121da177e4SLinus Torvalds 
23131da177e4SLinus Torvalds 	if (val) {
23141da177e4SLinus Torvalds 		/* Update the frag_point of the existing associations. */
23151da177e4SLinus Torvalds 		list_for_each(pos, &(sp->ep->asocs)) {
23161da177e4SLinus Torvalds 			asoc = list_entry(pos, struct sctp_association, asocs);
23171da177e4SLinus Torvalds 			asoc->frag_point = sctp_frag_point(sp, asoc->pmtu);
23181da177e4SLinus Torvalds 		}
23191da177e4SLinus Torvalds 	}
23201da177e4SLinus Torvalds 
23211da177e4SLinus Torvalds 	return 0;
23221da177e4SLinus Torvalds }
23231da177e4SLinus Torvalds 
23241da177e4SLinus Torvalds 
23251da177e4SLinus Torvalds /*
23261da177e4SLinus Torvalds  *  7.1.9 Set Peer Primary Address (SCTP_SET_PEER_PRIMARY_ADDR)
23271da177e4SLinus Torvalds  *
23281da177e4SLinus Torvalds  *   Requests that the peer mark the enclosed address as the association
23291da177e4SLinus Torvalds  *   primary. The enclosed address must be one of the association's
23301da177e4SLinus Torvalds  *   locally bound addresses. The following structure is used to make a
23311da177e4SLinus Torvalds  *   set primary request:
23321da177e4SLinus Torvalds  */
23331da177e4SLinus Torvalds static int sctp_setsockopt_peer_primary_addr(struct sock *sk, char __user *optval,
23341da177e4SLinus Torvalds 					     int optlen)
23351da177e4SLinus Torvalds {
23361da177e4SLinus Torvalds 	struct sctp_sock	*sp;
23371da177e4SLinus Torvalds 	struct sctp_endpoint	*ep;
23381da177e4SLinus Torvalds 	struct sctp_association	*asoc = NULL;
23391da177e4SLinus Torvalds 	struct sctp_setpeerprim	prim;
23401da177e4SLinus Torvalds 	struct sctp_chunk	*chunk;
23411da177e4SLinus Torvalds 	int 			err;
23421da177e4SLinus Torvalds 
23431da177e4SLinus Torvalds 	sp = sctp_sk(sk);
23441da177e4SLinus Torvalds 	ep = sp->ep;
23451da177e4SLinus Torvalds 
23461da177e4SLinus Torvalds 	if (!sctp_addip_enable)
23471da177e4SLinus Torvalds 		return -EPERM;
23481da177e4SLinus Torvalds 
23491da177e4SLinus Torvalds 	if (optlen != sizeof(struct sctp_setpeerprim))
23501da177e4SLinus Torvalds 		return -EINVAL;
23511da177e4SLinus Torvalds 
23521da177e4SLinus Torvalds 	if (copy_from_user(&prim, optval, optlen))
23531da177e4SLinus Torvalds 		return -EFAULT;
23541da177e4SLinus Torvalds 
23551da177e4SLinus Torvalds 	asoc = sctp_id2assoc(sk, prim.sspp_assoc_id);
23561da177e4SLinus Torvalds 	if (!asoc)
23571da177e4SLinus Torvalds 		return -EINVAL;
23581da177e4SLinus Torvalds 
23591da177e4SLinus Torvalds 	if (!asoc->peer.asconf_capable)
23601da177e4SLinus Torvalds 		return -EPERM;
23611da177e4SLinus Torvalds 
23621da177e4SLinus Torvalds 	if (asoc->peer.addip_disabled_mask & SCTP_PARAM_SET_PRIMARY)
23631da177e4SLinus Torvalds 		return -EPERM;
23641da177e4SLinus Torvalds 
23651da177e4SLinus Torvalds 	if (!sctp_state(asoc, ESTABLISHED))
23661da177e4SLinus Torvalds 		return -ENOTCONN;
23671da177e4SLinus Torvalds 
23681da177e4SLinus Torvalds 	if (!sctp_assoc_lookup_laddr(asoc, (union sctp_addr *)&prim.sspp_addr))
23691da177e4SLinus Torvalds 		return -EADDRNOTAVAIL;
23701da177e4SLinus Torvalds 
23711da177e4SLinus Torvalds 	/* Create an ASCONF chunk with SET_PRIMARY parameter	*/
23721da177e4SLinus Torvalds 	chunk = sctp_make_asconf_set_prim(asoc,
23731da177e4SLinus Torvalds 					  (union sctp_addr *)&prim.sspp_addr);
23741da177e4SLinus Torvalds 	if (!chunk)
23751da177e4SLinus Torvalds 		return -ENOMEM;
23761da177e4SLinus Torvalds 
23771da177e4SLinus Torvalds 	err = sctp_send_asconf(asoc, chunk);
23781da177e4SLinus Torvalds 
23791da177e4SLinus Torvalds 	SCTP_DEBUG_PRINTK("We set peer primary addr primitively.\n");
23801da177e4SLinus Torvalds 
23811da177e4SLinus Torvalds 	return err;
23821da177e4SLinus Torvalds }
23831da177e4SLinus Torvalds 
23841da177e4SLinus Torvalds static int sctp_setsockopt_adaption_layer(struct sock *sk, char __user *optval,
23851da177e4SLinus Torvalds 					  int optlen)
23861da177e4SLinus Torvalds {
23871da177e4SLinus Torvalds 	__u32 val;
23881da177e4SLinus Torvalds 
23891da177e4SLinus Torvalds 	if (optlen < sizeof(__u32))
23901da177e4SLinus Torvalds 		return -EINVAL;
23911da177e4SLinus Torvalds 	if (copy_from_user(&val, optval, sizeof(__u32)))
23921da177e4SLinus Torvalds 		return -EFAULT;
23931da177e4SLinus Torvalds 
23941da177e4SLinus Torvalds 	sctp_sk(sk)->adaption_ind = val;
23951da177e4SLinus Torvalds 
23961da177e4SLinus Torvalds 	return 0;
23971da177e4SLinus Torvalds }
23981da177e4SLinus Torvalds 
23991da177e4SLinus Torvalds /* API 6.2 setsockopt(), getsockopt()
24001da177e4SLinus Torvalds  *
24011da177e4SLinus Torvalds  * Applications use setsockopt() and getsockopt() to set or retrieve
24021da177e4SLinus Torvalds  * socket options.  Socket options are used to change the default
24031da177e4SLinus Torvalds  * behavior of sockets calls.  They are described in Section 7.
24041da177e4SLinus Torvalds  *
24051da177e4SLinus Torvalds  * The syntax is:
24061da177e4SLinus Torvalds  *
24071da177e4SLinus Torvalds  *   ret = getsockopt(int sd, int level, int optname, void __user *optval,
24081da177e4SLinus Torvalds  *                    int __user *optlen);
24091da177e4SLinus Torvalds  *   ret = setsockopt(int sd, int level, int optname, const void __user *optval,
24101da177e4SLinus Torvalds  *                    int optlen);
24111da177e4SLinus Torvalds  *
24121da177e4SLinus Torvalds  *   sd      - the socket descript.
24131da177e4SLinus Torvalds  *   level   - set to IPPROTO_SCTP for all SCTP options.
24141da177e4SLinus Torvalds  *   optname - the option name.
24151da177e4SLinus Torvalds  *   optval  - the buffer to store the value of the option.
24161da177e4SLinus Torvalds  *   optlen  - the size of the buffer.
24171da177e4SLinus Torvalds  */
24181da177e4SLinus Torvalds SCTP_STATIC int sctp_setsockopt(struct sock *sk, int level, int optname,
24191da177e4SLinus Torvalds 				char __user *optval, int optlen)
24201da177e4SLinus Torvalds {
24211da177e4SLinus Torvalds 	int retval = 0;
24221da177e4SLinus Torvalds 
24231da177e4SLinus Torvalds 	SCTP_DEBUG_PRINTK("sctp_setsockopt(sk: %p... optname: %d)\n",
24241da177e4SLinus Torvalds 			  sk, optname);
24251da177e4SLinus Torvalds 
24261da177e4SLinus Torvalds 	/* I can hardly begin to describe how wrong this is.  This is
24271da177e4SLinus Torvalds 	 * so broken as to be worse than useless.  The API draft
24281da177e4SLinus Torvalds 	 * REALLY is NOT helpful here...  I am not convinced that the
24291da177e4SLinus Torvalds 	 * semantics of setsockopt() with a level OTHER THAN SOL_SCTP
24301da177e4SLinus Torvalds 	 * are at all well-founded.
24311da177e4SLinus Torvalds 	 */
24321da177e4SLinus Torvalds 	if (level != SOL_SCTP) {
24331da177e4SLinus Torvalds 		struct sctp_af *af = sctp_sk(sk)->pf->af;
24341da177e4SLinus Torvalds 		retval = af->setsockopt(sk, level, optname, optval, optlen);
24351da177e4SLinus Torvalds 		goto out_nounlock;
24361da177e4SLinus Torvalds 	}
24371da177e4SLinus Torvalds 
24381da177e4SLinus Torvalds 	sctp_lock_sock(sk);
24391da177e4SLinus Torvalds 
24401da177e4SLinus Torvalds 	switch (optname) {
24411da177e4SLinus Torvalds 	case SCTP_SOCKOPT_BINDX_ADD:
24421da177e4SLinus Torvalds 		/* 'optlen' is the size of the addresses buffer. */
24431da177e4SLinus Torvalds 		retval = sctp_setsockopt_bindx(sk, (struct sockaddr __user *)optval,
24441da177e4SLinus Torvalds 					       optlen, SCTP_BINDX_ADD_ADDR);
24451da177e4SLinus Torvalds 		break;
24461da177e4SLinus Torvalds 
24471da177e4SLinus Torvalds 	case SCTP_SOCKOPT_BINDX_REM:
24481da177e4SLinus Torvalds 		/* 'optlen' is the size of the addresses buffer. */
24491da177e4SLinus Torvalds 		retval = sctp_setsockopt_bindx(sk, (struct sockaddr __user *)optval,
24501da177e4SLinus Torvalds 					       optlen, SCTP_BINDX_REM_ADDR);
24511da177e4SLinus Torvalds 		break;
24521da177e4SLinus Torvalds 
24533f7a87d2SFrank Filz 	case SCTP_SOCKOPT_CONNECTX:
24543f7a87d2SFrank Filz 		/* 'optlen' is the size of the addresses buffer. */
24553f7a87d2SFrank Filz 		retval = sctp_setsockopt_connectx(sk, (struct sockaddr __user *)optval,
24563f7a87d2SFrank Filz 					       optlen);
24573f7a87d2SFrank Filz 		break;
24583f7a87d2SFrank Filz 
24591da177e4SLinus Torvalds 	case SCTP_DISABLE_FRAGMENTS:
24601da177e4SLinus Torvalds 		retval = sctp_setsockopt_disable_fragments(sk, optval, optlen);
24611da177e4SLinus Torvalds 		break;
24621da177e4SLinus Torvalds 
24631da177e4SLinus Torvalds 	case SCTP_EVENTS:
24641da177e4SLinus Torvalds 		retval = sctp_setsockopt_events(sk, optval, optlen);
24651da177e4SLinus Torvalds 		break;
24661da177e4SLinus Torvalds 
24671da177e4SLinus Torvalds 	case SCTP_AUTOCLOSE:
24681da177e4SLinus Torvalds 		retval = sctp_setsockopt_autoclose(sk, optval, optlen);
24691da177e4SLinus Torvalds 		break;
24701da177e4SLinus Torvalds 
24711da177e4SLinus Torvalds 	case SCTP_PEER_ADDR_PARAMS:
24721da177e4SLinus Torvalds 		retval = sctp_setsockopt_peer_addr_params(sk, optval, optlen);
24731da177e4SLinus Torvalds 		break;
24741da177e4SLinus Torvalds 
24751da177e4SLinus Torvalds 	case SCTP_INITMSG:
24761da177e4SLinus Torvalds 		retval = sctp_setsockopt_initmsg(sk, optval, optlen);
24771da177e4SLinus Torvalds 		break;
24781da177e4SLinus Torvalds 	case SCTP_DEFAULT_SEND_PARAM:
24791da177e4SLinus Torvalds 		retval = sctp_setsockopt_default_send_param(sk, optval,
24801da177e4SLinus Torvalds 							    optlen);
24811da177e4SLinus Torvalds 		break;
24821da177e4SLinus Torvalds 	case SCTP_PRIMARY_ADDR:
24831da177e4SLinus Torvalds 		retval = sctp_setsockopt_primary_addr(sk, optval, optlen);
24841da177e4SLinus Torvalds 		break;
24851da177e4SLinus Torvalds 	case SCTP_SET_PEER_PRIMARY_ADDR:
24861da177e4SLinus Torvalds 		retval = sctp_setsockopt_peer_primary_addr(sk, optval, optlen);
24871da177e4SLinus Torvalds 		break;
24881da177e4SLinus Torvalds 	case SCTP_NODELAY:
24891da177e4SLinus Torvalds 		retval = sctp_setsockopt_nodelay(sk, optval, optlen);
24901da177e4SLinus Torvalds 		break;
24911da177e4SLinus Torvalds 	case SCTP_RTOINFO:
24921da177e4SLinus Torvalds 		retval = sctp_setsockopt_rtoinfo(sk, optval, optlen);
24931da177e4SLinus Torvalds 		break;
24941da177e4SLinus Torvalds 	case SCTP_ASSOCINFO:
24951da177e4SLinus Torvalds 		retval = sctp_setsockopt_associnfo(sk, optval, optlen);
24961da177e4SLinus Torvalds 		break;
24971da177e4SLinus Torvalds 	case SCTP_I_WANT_MAPPED_V4_ADDR:
24981da177e4SLinus Torvalds 		retval = sctp_setsockopt_mappedv4(sk, optval, optlen);
24991da177e4SLinus Torvalds 		break;
25001da177e4SLinus Torvalds 	case SCTP_MAXSEG:
25011da177e4SLinus Torvalds 		retval = sctp_setsockopt_maxseg(sk, optval, optlen);
25021da177e4SLinus Torvalds 		break;
25031da177e4SLinus Torvalds 	case SCTP_ADAPTION_LAYER:
25041da177e4SLinus Torvalds 		retval = sctp_setsockopt_adaption_layer(sk, optval, optlen);
25051da177e4SLinus Torvalds 		break;
25061da177e4SLinus Torvalds 
25071da177e4SLinus Torvalds 	default:
25081da177e4SLinus Torvalds 		retval = -ENOPROTOOPT;
25091da177e4SLinus Torvalds 		break;
25101da177e4SLinus Torvalds 	};
25111da177e4SLinus Torvalds 
25121da177e4SLinus Torvalds 	sctp_release_sock(sk);
25131da177e4SLinus Torvalds 
25141da177e4SLinus Torvalds out_nounlock:
25151da177e4SLinus Torvalds 	return retval;
25161da177e4SLinus Torvalds }
25171da177e4SLinus Torvalds 
25181da177e4SLinus Torvalds /* API 3.1.6 connect() - UDP Style Syntax
25191da177e4SLinus Torvalds  *
25201da177e4SLinus Torvalds  * An application may use the connect() call in the UDP model to initiate an
25211da177e4SLinus Torvalds  * association without sending data.
25221da177e4SLinus Torvalds  *
25231da177e4SLinus Torvalds  * The syntax is:
25241da177e4SLinus Torvalds  *
25251da177e4SLinus Torvalds  * ret = connect(int sd, const struct sockaddr *nam, socklen_t len);
25261da177e4SLinus Torvalds  *
25271da177e4SLinus Torvalds  * sd: the socket descriptor to have a new association added to.
25281da177e4SLinus Torvalds  *
25291da177e4SLinus Torvalds  * nam: the address structure (either struct sockaddr_in or struct
25301da177e4SLinus Torvalds  *    sockaddr_in6 defined in RFC2553 [7]).
25311da177e4SLinus Torvalds  *
25321da177e4SLinus Torvalds  * len: the size of the address.
25331da177e4SLinus Torvalds  */
25343f7a87d2SFrank Filz SCTP_STATIC int sctp_connect(struct sock *sk, struct sockaddr *addr,
25351da177e4SLinus Torvalds 			     int addr_len)
25361da177e4SLinus Torvalds {
25371da177e4SLinus Torvalds 	int err = 0;
25383f7a87d2SFrank Filz 	struct sctp_af *af;
25391da177e4SLinus Torvalds 
25401da177e4SLinus Torvalds 	sctp_lock_sock(sk);
25411da177e4SLinus Torvalds 
25423f7a87d2SFrank Filz 	SCTP_DEBUG_PRINTK("%s - sk: %p, sockaddr: %p, addr_len: %d\n",
25433f7a87d2SFrank Filz 			  __FUNCTION__, sk, addr, addr_len);
25441da177e4SLinus Torvalds 
25453f7a87d2SFrank Filz 	/* Validate addr_len before calling common connect/connectx routine. */
25463f7a87d2SFrank Filz 	af = sctp_get_af_specific(addr->sa_family);
25473f7a87d2SFrank Filz 	if (!af || addr_len < af->sockaddr_len) {
25483f7a87d2SFrank Filz 		err = -EINVAL;
25493f7a87d2SFrank Filz 	} else {
25503f7a87d2SFrank Filz 		/* Pass correct addr len to common routine (so it knows there
25513f7a87d2SFrank Filz 		 * is only one address being passed.
25521da177e4SLinus Torvalds 		 */
25533f7a87d2SFrank Filz 		err = __sctp_connect(sk, addr, af->sockaddr_len);
25541da177e4SLinus Torvalds 	}
25551da177e4SLinus Torvalds 
25561da177e4SLinus Torvalds 	sctp_release_sock(sk);
25571da177e4SLinus Torvalds 	return err;
25581da177e4SLinus Torvalds }
25591da177e4SLinus Torvalds 
25601da177e4SLinus Torvalds /* FIXME: Write comments. */
25611da177e4SLinus Torvalds SCTP_STATIC int sctp_disconnect(struct sock *sk, int flags)
25621da177e4SLinus Torvalds {
25631da177e4SLinus Torvalds 	return -EOPNOTSUPP; /* STUB */
25641da177e4SLinus Torvalds }
25651da177e4SLinus Torvalds 
25661da177e4SLinus Torvalds /* 4.1.4 accept() - TCP Style Syntax
25671da177e4SLinus Torvalds  *
25681da177e4SLinus Torvalds  * Applications use accept() call to remove an established SCTP
25691da177e4SLinus Torvalds  * association from the accept queue of the endpoint.  A new socket
25701da177e4SLinus Torvalds  * descriptor will be returned from accept() to represent the newly
25711da177e4SLinus Torvalds  * formed association.
25721da177e4SLinus Torvalds  */
25731da177e4SLinus Torvalds SCTP_STATIC struct sock *sctp_accept(struct sock *sk, int flags, int *err)
25741da177e4SLinus Torvalds {
25751da177e4SLinus Torvalds 	struct sctp_sock *sp;
25761da177e4SLinus Torvalds 	struct sctp_endpoint *ep;
25771da177e4SLinus Torvalds 	struct sock *newsk = NULL;
25781da177e4SLinus Torvalds 	struct sctp_association *asoc;
25791da177e4SLinus Torvalds 	long timeo;
25801da177e4SLinus Torvalds 	int error = 0;
25811da177e4SLinus Torvalds 
25821da177e4SLinus Torvalds 	sctp_lock_sock(sk);
25831da177e4SLinus Torvalds 
25841da177e4SLinus Torvalds 	sp = sctp_sk(sk);
25851da177e4SLinus Torvalds 	ep = sp->ep;
25861da177e4SLinus Torvalds 
25871da177e4SLinus Torvalds 	if (!sctp_style(sk, TCP)) {
25881da177e4SLinus Torvalds 		error = -EOPNOTSUPP;
25891da177e4SLinus Torvalds 		goto out;
25901da177e4SLinus Torvalds 	}
25911da177e4SLinus Torvalds 
25921da177e4SLinus Torvalds 	if (!sctp_sstate(sk, LISTENING)) {
25931da177e4SLinus Torvalds 		error = -EINVAL;
25941da177e4SLinus Torvalds 		goto out;
25951da177e4SLinus Torvalds 	}
25961da177e4SLinus Torvalds 
25971da177e4SLinus Torvalds 	timeo = sock_rcvtimeo(sk, sk->sk_socket->file->f_flags & O_NONBLOCK);
25981da177e4SLinus Torvalds 
25991da177e4SLinus Torvalds 	error = sctp_wait_for_accept(sk, timeo);
26001da177e4SLinus Torvalds 	if (error)
26011da177e4SLinus Torvalds 		goto out;
26021da177e4SLinus Torvalds 
26031da177e4SLinus Torvalds 	/* We treat the list of associations on the endpoint as the accept
26041da177e4SLinus Torvalds 	 * queue and pick the first association on the list.
26051da177e4SLinus Torvalds 	 */
26061da177e4SLinus Torvalds 	asoc = list_entry(ep->asocs.next, struct sctp_association, asocs);
26071da177e4SLinus Torvalds 
26081da177e4SLinus Torvalds 	newsk = sp->pf->create_accept_sk(sk, asoc);
26091da177e4SLinus Torvalds 	if (!newsk) {
26101da177e4SLinus Torvalds 		error = -ENOMEM;
26111da177e4SLinus Torvalds 		goto out;
26121da177e4SLinus Torvalds 	}
26131da177e4SLinus Torvalds 
26141da177e4SLinus Torvalds 	/* Populate the fields of the newsk from the oldsk and migrate the
26151da177e4SLinus Torvalds 	 * asoc to the newsk.
26161da177e4SLinus Torvalds 	 */
26171da177e4SLinus Torvalds 	sctp_sock_migrate(sk, newsk, asoc, SCTP_SOCKET_TCP);
26181da177e4SLinus Torvalds 
26191da177e4SLinus Torvalds out:
26201da177e4SLinus Torvalds 	sctp_release_sock(sk);
26211da177e4SLinus Torvalds  	*err = error;
26221da177e4SLinus Torvalds 	return newsk;
26231da177e4SLinus Torvalds }
26241da177e4SLinus Torvalds 
26251da177e4SLinus Torvalds /* The SCTP ioctl handler. */
26261da177e4SLinus Torvalds SCTP_STATIC int sctp_ioctl(struct sock *sk, int cmd, unsigned long arg)
26271da177e4SLinus Torvalds {
26281da177e4SLinus Torvalds 	return -ENOIOCTLCMD;
26291da177e4SLinus Torvalds }
26301da177e4SLinus Torvalds 
26311da177e4SLinus Torvalds /* This is the function which gets called during socket creation to
26321da177e4SLinus Torvalds  * initialized the SCTP-specific portion of the sock.
26331da177e4SLinus Torvalds  * The sock structure should already be zero-filled memory.
26341da177e4SLinus Torvalds  */
26351da177e4SLinus Torvalds SCTP_STATIC int sctp_init_sock(struct sock *sk)
26361da177e4SLinus Torvalds {
26371da177e4SLinus Torvalds 	struct sctp_endpoint *ep;
26381da177e4SLinus Torvalds 	struct sctp_sock *sp;
26391da177e4SLinus Torvalds 
26401da177e4SLinus Torvalds 	SCTP_DEBUG_PRINTK("sctp_init_sock(sk: %p)\n", sk);
26411da177e4SLinus Torvalds 
26421da177e4SLinus Torvalds 	sp = sctp_sk(sk);
26431da177e4SLinus Torvalds 
26441da177e4SLinus Torvalds 	/* Initialize the SCTP per socket area.  */
26451da177e4SLinus Torvalds 	switch (sk->sk_type) {
26461da177e4SLinus Torvalds 	case SOCK_SEQPACKET:
26471da177e4SLinus Torvalds 		sp->type = SCTP_SOCKET_UDP;
26481da177e4SLinus Torvalds 		break;
26491da177e4SLinus Torvalds 	case SOCK_STREAM:
26501da177e4SLinus Torvalds 		sp->type = SCTP_SOCKET_TCP;
26511da177e4SLinus Torvalds 		break;
26521da177e4SLinus Torvalds 	default:
26531da177e4SLinus Torvalds 		return -ESOCKTNOSUPPORT;
26541da177e4SLinus Torvalds 	}
26551da177e4SLinus Torvalds 
26561da177e4SLinus Torvalds 	/* Initialize default send parameters. These parameters can be
26571da177e4SLinus Torvalds 	 * modified with the SCTP_DEFAULT_SEND_PARAM socket option.
26581da177e4SLinus Torvalds 	 */
26591da177e4SLinus Torvalds 	sp->default_stream = 0;
26601da177e4SLinus Torvalds 	sp->default_ppid = 0;
26611da177e4SLinus Torvalds 	sp->default_flags = 0;
26621da177e4SLinus Torvalds 	sp->default_context = 0;
26631da177e4SLinus Torvalds 	sp->default_timetolive = 0;
26641da177e4SLinus Torvalds 
26651da177e4SLinus Torvalds 	/* Initialize default setup parameters. These parameters
26661da177e4SLinus Torvalds 	 * can be modified with the SCTP_INITMSG socket option or
26671da177e4SLinus Torvalds 	 * overridden by the SCTP_INIT CMSG.
26681da177e4SLinus Torvalds 	 */
26691da177e4SLinus Torvalds 	sp->initmsg.sinit_num_ostreams   = sctp_max_outstreams;
26701da177e4SLinus Torvalds 	sp->initmsg.sinit_max_instreams  = sctp_max_instreams;
26711da177e4SLinus Torvalds 	sp->initmsg.sinit_max_attempts   = sctp_max_retrans_init;
26721da177e4SLinus Torvalds 	sp->initmsg.sinit_max_init_timeo = jiffies_to_msecs(sctp_rto_max);
26731da177e4SLinus Torvalds 
26741da177e4SLinus Torvalds 	/* Initialize default RTO related parameters.  These parameters can
26751da177e4SLinus Torvalds 	 * be modified for with the SCTP_RTOINFO socket option.
26761da177e4SLinus Torvalds 	 */
26771da177e4SLinus Torvalds 	sp->rtoinfo.srto_initial = jiffies_to_msecs(sctp_rto_initial);
26781da177e4SLinus Torvalds 	sp->rtoinfo.srto_max     = jiffies_to_msecs(sctp_rto_max);
26791da177e4SLinus Torvalds 	sp->rtoinfo.srto_min     = jiffies_to_msecs(sctp_rto_min);
26801da177e4SLinus Torvalds 
26811da177e4SLinus Torvalds 	/* Initialize default association related parameters. These parameters
26821da177e4SLinus Torvalds 	 * can be modified with the SCTP_ASSOCINFO socket option.
26831da177e4SLinus Torvalds 	 */
26841da177e4SLinus Torvalds 	sp->assocparams.sasoc_asocmaxrxt = sctp_max_retrans_association;
26851da177e4SLinus Torvalds 	sp->assocparams.sasoc_number_peer_destinations = 0;
26861da177e4SLinus Torvalds 	sp->assocparams.sasoc_peer_rwnd = 0;
26871da177e4SLinus Torvalds 	sp->assocparams.sasoc_local_rwnd = 0;
26881da177e4SLinus Torvalds 	sp->assocparams.sasoc_cookie_life =
26891da177e4SLinus Torvalds 		jiffies_to_msecs(sctp_valid_cookie_life);
26901da177e4SLinus Torvalds 
26911da177e4SLinus Torvalds 	/* Initialize default event subscriptions. By default, all the
26921da177e4SLinus Torvalds 	 * options are off.
26931da177e4SLinus Torvalds 	 */
26941da177e4SLinus Torvalds 	memset(&sp->subscribe, 0, sizeof(struct sctp_event_subscribe));
26951da177e4SLinus Torvalds 
26961da177e4SLinus Torvalds 	/* Default Peer Address Parameters.  These defaults can
26971da177e4SLinus Torvalds 	 * be modified via SCTP_PEER_ADDR_PARAMS
26981da177e4SLinus Torvalds 	 */
26991da177e4SLinus Torvalds 	sp->paddrparam.spp_hbinterval = jiffies_to_msecs(sctp_hb_interval);
27001da177e4SLinus Torvalds 	sp->paddrparam.spp_pathmaxrxt = sctp_max_retrans_path;
27011da177e4SLinus Torvalds 
27021da177e4SLinus Torvalds 	/* If enabled no SCTP message fragmentation will be performed.
27031da177e4SLinus Torvalds 	 * Configure through SCTP_DISABLE_FRAGMENTS socket option.
27041da177e4SLinus Torvalds 	 */
27051da177e4SLinus Torvalds 	sp->disable_fragments = 0;
27061da177e4SLinus Torvalds 
27071da177e4SLinus Torvalds 	/* Turn on/off any Nagle-like algorithm.  */
27081da177e4SLinus Torvalds 	sp->nodelay           = 1;
27091da177e4SLinus Torvalds 
27101da177e4SLinus Torvalds 	/* Enable by default. */
27111da177e4SLinus Torvalds 	sp->v4mapped          = 1;
27121da177e4SLinus Torvalds 
27131da177e4SLinus Torvalds 	/* Auto-close idle associations after the configured
27141da177e4SLinus Torvalds 	 * number of seconds.  A value of 0 disables this
27151da177e4SLinus Torvalds 	 * feature.  Configure through the SCTP_AUTOCLOSE socket option,
27161da177e4SLinus Torvalds 	 * for UDP-style sockets only.
27171da177e4SLinus Torvalds 	 */
27181da177e4SLinus Torvalds 	sp->autoclose         = 0;
27191da177e4SLinus Torvalds 
27201da177e4SLinus Torvalds 	/* User specified fragmentation limit. */
27211da177e4SLinus Torvalds 	sp->user_frag         = 0;
27221da177e4SLinus Torvalds 
27231da177e4SLinus Torvalds 	sp->adaption_ind = 0;
27241da177e4SLinus Torvalds 
27251da177e4SLinus Torvalds 	sp->pf = sctp_get_pf_specific(sk->sk_family);
27261da177e4SLinus Torvalds 
27271da177e4SLinus Torvalds 	/* Control variables for partial data delivery. */
27281da177e4SLinus Torvalds 	sp->pd_mode           = 0;
27291da177e4SLinus Torvalds 	skb_queue_head_init(&sp->pd_lobby);
27301da177e4SLinus Torvalds 
27311da177e4SLinus Torvalds 	/* Create a per socket endpoint structure.  Even if we
27321da177e4SLinus Torvalds 	 * change the data structure relationships, this may still
27331da177e4SLinus Torvalds 	 * be useful for storing pre-connect address information.
27341da177e4SLinus Torvalds 	 */
27351da177e4SLinus Torvalds 	ep = sctp_endpoint_new(sk, GFP_KERNEL);
27361da177e4SLinus Torvalds 	if (!ep)
27371da177e4SLinus Torvalds 		return -ENOMEM;
27381da177e4SLinus Torvalds 
27391da177e4SLinus Torvalds 	sp->ep = ep;
27401da177e4SLinus Torvalds 	sp->hmac = NULL;
27411da177e4SLinus Torvalds 
27421da177e4SLinus Torvalds 	SCTP_DBG_OBJCNT_INC(sock);
27431da177e4SLinus Torvalds 	return 0;
27441da177e4SLinus Torvalds }
27451da177e4SLinus Torvalds 
27461da177e4SLinus Torvalds /* Cleanup any SCTP per socket resources.  */
27471da177e4SLinus Torvalds SCTP_STATIC int sctp_destroy_sock(struct sock *sk)
27481da177e4SLinus Torvalds {
27491da177e4SLinus Torvalds 	struct sctp_endpoint *ep;
27501da177e4SLinus Torvalds 
27511da177e4SLinus Torvalds 	SCTP_DEBUG_PRINTK("sctp_destroy_sock(sk: %p)\n", sk);
27521da177e4SLinus Torvalds 
27531da177e4SLinus Torvalds 	/* Release our hold on the endpoint. */
27541da177e4SLinus Torvalds 	ep = sctp_sk(sk)->ep;
27551da177e4SLinus Torvalds 	sctp_endpoint_free(ep);
27561da177e4SLinus Torvalds 
27571da177e4SLinus Torvalds 	return 0;
27581da177e4SLinus Torvalds }
27591da177e4SLinus Torvalds 
27601da177e4SLinus Torvalds /* API 4.1.7 shutdown() - TCP Style Syntax
27611da177e4SLinus Torvalds  *     int shutdown(int socket, int how);
27621da177e4SLinus Torvalds  *
27631da177e4SLinus Torvalds  *     sd      - the socket descriptor of the association to be closed.
27641da177e4SLinus Torvalds  *     how     - Specifies the type of shutdown.  The  values  are
27651da177e4SLinus Torvalds  *               as follows:
27661da177e4SLinus Torvalds  *               SHUT_RD
27671da177e4SLinus Torvalds  *                     Disables further receive operations. No SCTP
27681da177e4SLinus Torvalds  *                     protocol action is taken.
27691da177e4SLinus Torvalds  *               SHUT_WR
27701da177e4SLinus Torvalds  *                     Disables further send operations, and initiates
27711da177e4SLinus Torvalds  *                     the SCTP shutdown sequence.
27721da177e4SLinus Torvalds  *               SHUT_RDWR
27731da177e4SLinus Torvalds  *                     Disables further send  and  receive  operations
27741da177e4SLinus Torvalds  *                     and initiates the SCTP shutdown sequence.
27751da177e4SLinus Torvalds  */
27761da177e4SLinus Torvalds SCTP_STATIC void sctp_shutdown(struct sock *sk, int how)
27771da177e4SLinus Torvalds {
27781da177e4SLinus Torvalds 	struct sctp_endpoint *ep;
27791da177e4SLinus Torvalds 	struct sctp_association *asoc;
27801da177e4SLinus Torvalds 
27811da177e4SLinus Torvalds 	if (!sctp_style(sk, TCP))
27821da177e4SLinus Torvalds 		return;
27831da177e4SLinus Torvalds 
27841da177e4SLinus Torvalds 	if (how & SEND_SHUTDOWN) {
27851da177e4SLinus Torvalds 		ep = sctp_sk(sk)->ep;
27861da177e4SLinus Torvalds 		if (!list_empty(&ep->asocs)) {
27871da177e4SLinus Torvalds 			asoc = list_entry(ep->asocs.next,
27881da177e4SLinus Torvalds 					  struct sctp_association, asocs);
27891da177e4SLinus Torvalds 			sctp_primitive_SHUTDOWN(asoc, NULL);
27901da177e4SLinus Torvalds 		}
27911da177e4SLinus Torvalds 	}
27921da177e4SLinus Torvalds }
27931da177e4SLinus Torvalds 
27941da177e4SLinus Torvalds /* 7.2.1 Association Status (SCTP_STATUS)
27951da177e4SLinus Torvalds 
27961da177e4SLinus Torvalds  * Applications can retrieve current status information about an
27971da177e4SLinus Torvalds  * association, including association state, peer receiver window size,
27981da177e4SLinus Torvalds  * number of unacked data chunks, and number of data chunks pending
27991da177e4SLinus Torvalds  * receipt.  This information is read-only.
28001da177e4SLinus Torvalds  */
28011da177e4SLinus Torvalds static int sctp_getsockopt_sctp_status(struct sock *sk, int len,
28021da177e4SLinus Torvalds 				       char __user *optval,
28031da177e4SLinus Torvalds 				       int __user *optlen)
28041da177e4SLinus Torvalds {
28051da177e4SLinus Torvalds 	struct sctp_status status;
28061da177e4SLinus Torvalds 	struct sctp_association *asoc = NULL;
28071da177e4SLinus Torvalds 	struct sctp_transport *transport;
28081da177e4SLinus Torvalds 	sctp_assoc_t associd;
28091da177e4SLinus Torvalds 	int retval = 0;
28101da177e4SLinus Torvalds 
28111da177e4SLinus Torvalds 	if (len != sizeof(status)) {
28121da177e4SLinus Torvalds 		retval = -EINVAL;
28131da177e4SLinus Torvalds 		goto out;
28141da177e4SLinus Torvalds 	}
28151da177e4SLinus Torvalds 
28161da177e4SLinus Torvalds 	if (copy_from_user(&status, optval, sizeof(status))) {
28171da177e4SLinus Torvalds 		retval = -EFAULT;
28181da177e4SLinus Torvalds 		goto out;
28191da177e4SLinus Torvalds 	}
28201da177e4SLinus Torvalds 
28211da177e4SLinus Torvalds 	associd = status.sstat_assoc_id;
28221da177e4SLinus Torvalds 	asoc = sctp_id2assoc(sk, associd);
28231da177e4SLinus Torvalds 	if (!asoc) {
28241da177e4SLinus Torvalds 		retval = -EINVAL;
28251da177e4SLinus Torvalds 		goto out;
28261da177e4SLinus Torvalds 	}
28271da177e4SLinus Torvalds 
28281da177e4SLinus Torvalds 	transport = asoc->peer.primary_path;
28291da177e4SLinus Torvalds 
28301da177e4SLinus Torvalds 	status.sstat_assoc_id = sctp_assoc2id(asoc);
28311da177e4SLinus Torvalds 	status.sstat_state = asoc->state;
28321da177e4SLinus Torvalds 	status.sstat_rwnd =  asoc->peer.rwnd;
28331da177e4SLinus Torvalds 	status.sstat_unackdata = asoc->unack_data;
28341da177e4SLinus Torvalds 
28351da177e4SLinus Torvalds 	status.sstat_penddata = sctp_tsnmap_pending(&asoc->peer.tsn_map);
28361da177e4SLinus Torvalds 	status.sstat_instrms = asoc->c.sinit_max_instreams;
28371da177e4SLinus Torvalds 	status.sstat_outstrms = asoc->c.sinit_num_ostreams;
28381da177e4SLinus Torvalds 	status.sstat_fragmentation_point = asoc->frag_point;
28391da177e4SLinus Torvalds 	status.sstat_primary.spinfo_assoc_id = sctp_assoc2id(transport->asoc);
28401da177e4SLinus Torvalds 	memcpy(&status.sstat_primary.spinfo_address,
28411da177e4SLinus Torvalds 	       &(transport->ipaddr), sizeof(union sctp_addr));
28421da177e4SLinus Torvalds 	/* Map ipv4 address into v4-mapped-on-v6 address.  */
28431da177e4SLinus Torvalds 	sctp_get_pf_specific(sk->sk_family)->addr_v4map(sctp_sk(sk),
28441da177e4SLinus Torvalds 		(union sctp_addr *)&status.sstat_primary.spinfo_address);
28453f7a87d2SFrank Filz 	status.sstat_primary.spinfo_state = transport->state;
28461da177e4SLinus Torvalds 	status.sstat_primary.spinfo_cwnd = transport->cwnd;
28471da177e4SLinus Torvalds 	status.sstat_primary.spinfo_srtt = transport->srtt;
28481da177e4SLinus Torvalds 	status.sstat_primary.spinfo_rto = jiffies_to_msecs(transport->rto);
28491da177e4SLinus Torvalds 	status.sstat_primary.spinfo_mtu = transport->pmtu;
28501da177e4SLinus Torvalds 
28513f7a87d2SFrank Filz 	if (status.sstat_primary.spinfo_state == SCTP_UNKNOWN)
28523f7a87d2SFrank Filz 		status.sstat_primary.spinfo_state = SCTP_ACTIVE;
28533f7a87d2SFrank Filz 
28541da177e4SLinus Torvalds 	if (put_user(len, optlen)) {
28551da177e4SLinus Torvalds 		retval = -EFAULT;
28561da177e4SLinus Torvalds 		goto out;
28571da177e4SLinus Torvalds 	}
28581da177e4SLinus Torvalds 
28591da177e4SLinus Torvalds 	SCTP_DEBUG_PRINTK("sctp_getsockopt_sctp_status(%d): %d %d %d\n",
28601da177e4SLinus Torvalds 			  len, status.sstat_state, status.sstat_rwnd,
28611da177e4SLinus Torvalds 			  status.sstat_assoc_id);
28621da177e4SLinus Torvalds 
28631da177e4SLinus Torvalds 	if (copy_to_user(optval, &status, len)) {
28641da177e4SLinus Torvalds 		retval = -EFAULT;
28651da177e4SLinus Torvalds 		goto out;
28661da177e4SLinus Torvalds 	}
28671da177e4SLinus Torvalds 
28681da177e4SLinus Torvalds out:
28691da177e4SLinus Torvalds 	return (retval);
28701da177e4SLinus Torvalds }
28711da177e4SLinus Torvalds 
28721da177e4SLinus Torvalds 
28731da177e4SLinus Torvalds /* 7.2.2 Peer Address Information (SCTP_GET_PEER_ADDR_INFO)
28741da177e4SLinus Torvalds  *
28751da177e4SLinus Torvalds  * Applications can retrieve information about a specific peer address
28761da177e4SLinus Torvalds  * of an association, including its reachability state, congestion
28771da177e4SLinus Torvalds  * window, and retransmission timer values.  This information is
28781da177e4SLinus Torvalds  * read-only.
28791da177e4SLinus Torvalds  */
28801da177e4SLinus Torvalds static int sctp_getsockopt_peer_addr_info(struct sock *sk, int len,
28811da177e4SLinus Torvalds 					  char __user *optval,
28821da177e4SLinus Torvalds 					  int __user *optlen)
28831da177e4SLinus Torvalds {
28841da177e4SLinus Torvalds 	struct sctp_paddrinfo pinfo;
28851da177e4SLinus Torvalds 	struct sctp_transport *transport;
28861da177e4SLinus Torvalds 	int retval = 0;
28871da177e4SLinus Torvalds 
28881da177e4SLinus Torvalds 	if (len != sizeof(pinfo)) {
28891da177e4SLinus Torvalds 		retval = -EINVAL;
28901da177e4SLinus Torvalds 		goto out;
28911da177e4SLinus Torvalds 	}
28921da177e4SLinus Torvalds 
28931da177e4SLinus Torvalds 	if (copy_from_user(&pinfo, optval, sizeof(pinfo))) {
28941da177e4SLinus Torvalds 		retval = -EFAULT;
28951da177e4SLinus Torvalds 		goto out;
28961da177e4SLinus Torvalds 	}
28971da177e4SLinus Torvalds 
28981da177e4SLinus Torvalds 	transport = sctp_addr_id2transport(sk, &pinfo.spinfo_address,
28991da177e4SLinus Torvalds 					   pinfo.spinfo_assoc_id);
29001da177e4SLinus Torvalds 	if (!transport)
29011da177e4SLinus Torvalds 		return -EINVAL;
29021da177e4SLinus Torvalds 
29031da177e4SLinus Torvalds 	pinfo.spinfo_assoc_id = sctp_assoc2id(transport->asoc);
29043f7a87d2SFrank Filz 	pinfo.spinfo_state = transport->state;
29051da177e4SLinus Torvalds 	pinfo.spinfo_cwnd = transport->cwnd;
29061da177e4SLinus Torvalds 	pinfo.spinfo_srtt = transport->srtt;
29071da177e4SLinus Torvalds 	pinfo.spinfo_rto = jiffies_to_msecs(transport->rto);
29081da177e4SLinus Torvalds 	pinfo.spinfo_mtu = transport->pmtu;
29091da177e4SLinus Torvalds 
29103f7a87d2SFrank Filz 	if (pinfo.spinfo_state == SCTP_UNKNOWN)
29113f7a87d2SFrank Filz 		pinfo.spinfo_state = SCTP_ACTIVE;
29123f7a87d2SFrank Filz 
29131da177e4SLinus Torvalds 	if (put_user(len, optlen)) {
29141da177e4SLinus Torvalds 		retval = -EFAULT;
29151da177e4SLinus Torvalds 		goto out;
29161da177e4SLinus Torvalds 	}
29171da177e4SLinus Torvalds 
29181da177e4SLinus Torvalds 	if (copy_to_user(optval, &pinfo, len)) {
29191da177e4SLinus Torvalds 		retval = -EFAULT;
29201da177e4SLinus Torvalds 		goto out;
29211da177e4SLinus Torvalds 	}
29221da177e4SLinus Torvalds 
29231da177e4SLinus Torvalds out:
29241da177e4SLinus Torvalds 	return (retval);
29251da177e4SLinus Torvalds }
29261da177e4SLinus Torvalds 
29271da177e4SLinus Torvalds /* 7.1.12 Enable/Disable message fragmentation (SCTP_DISABLE_FRAGMENTS)
29281da177e4SLinus Torvalds  *
29291da177e4SLinus Torvalds  * This option is a on/off flag.  If enabled no SCTP message
29301da177e4SLinus Torvalds  * fragmentation will be performed.  Instead if a message being sent
29311da177e4SLinus Torvalds  * exceeds the current PMTU size, the message will NOT be sent and
29321da177e4SLinus Torvalds  * instead a error will be indicated to the user.
29331da177e4SLinus Torvalds  */
29341da177e4SLinus Torvalds static int sctp_getsockopt_disable_fragments(struct sock *sk, int len,
29351da177e4SLinus Torvalds 					char __user *optval, int __user *optlen)
29361da177e4SLinus Torvalds {
29371da177e4SLinus Torvalds 	int val;
29381da177e4SLinus Torvalds 
29391da177e4SLinus Torvalds 	if (len < sizeof(int))
29401da177e4SLinus Torvalds 		return -EINVAL;
29411da177e4SLinus Torvalds 
29421da177e4SLinus Torvalds 	len = sizeof(int);
29431da177e4SLinus Torvalds 	val = (sctp_sk(sk)->disable_fragments == 1);
29441da177e4SLinus Torvalds 	if (put_user(len, optlen))
29451da177e4SLinus Torvalds 		return -EFAULT;
29461da177e4SLinus Torvalds 	if (copy_to_user(optval, &val, len))
29471da177e4SLinus Torvalds 		return -EFAULT;
29481da177e4SLinus Torvalds 	return 0;
29491da177e4SLinus Torvalds }
29501da177e4SLinus Torvalds 
29511da177e4SLinus Torvalds /* 7.1.15 Set notification and ancillary events (SCTP_EVENTS)
29521da177e4SLinus Torvalds  *
29531da177e4SLinus Torvalds  * This socket option is used to specify various notifications and
29541da177e4SLinus Torvalds  * ancillary data the user wishes to receive.
29551da177e4SLinus Torvalds  */
29561da177e4SLinus Torvalds static int sctp_getsockopt_events(struct sock *sk, int len, char __user *optval,
29571da177e4SLinus Torvalds 				  int __user *optlen)
29581da177e4SLinus Torvalds {
29591da177e4SLinus Torvalds 	if (len != sizeof(struct sctp_event_subscribe))
29601da177e4SLinus Torvalds 		return -EINVAL;
29611da177e4SLinus Torvalds 	if (copy_to_user(optval, &sctp_sk(sk)->subscribe, len))
29621da177e4SLinus Torvalds 		return -EFAULT;
29631da177e4SLinus Torvalds 	return 0;
29641da177e4SLinus Torvalds }
29651da177e4SLinus Torvalds 
29661da177e4SLinus Torvalds /* 7.1.8 Automatic Close of associations (SCTP_AUTOCLOSE)
29671da177e4SLinus Torvalds  *
29681da177e4SLinus Torvalds  * This socket option is applicable to the UDP-style socket only.  When
29691da177e4SLinus Torvalds  * set it will cause associations that are idle for more than the
29701da177e4SLinus Torvalds  * specified number of seconds to automatically close.  An association
29711da177e4SLinus Torvalds  * being idle is defined an association that has NOT sent or received
29721da177e4SLinus Torvalds  * user data.  The special value of '0' indicates that no automatic
29731da177e4SLinus Torvalds  * close of any associations should be performed.  The option expects an
29741da177e4SLinus Torvalds  * integer defining the number of seconds of idle time before an
29751da177e4SLinus Torvalds  * association is closed.
29761da177e4SLinus Torvalds  */
29771da177e4SLinus Torvalds static int sctp_getsockopt_autoclose(struct sock *sk, int len, char __user *optval, int __user *optlen)
29781da177e4SLinus Torvalds {
29791da177e4SLinus Torvalds 	/* Applicable to UDP-style socket only */
29801da177e4SLinus Torvalds 	if (sctp_style(sk, TCP))
29811da177e4SLinus Torvalds 		return -EOPNOTSUPP;
29821da177e4SLinus Torvalds 	if (len != sizeof(int))
29831da177e4SLinus Torvalds 		return -EINVAL;
29841da177e4SLinus Torvalds 	if (copy_to_user(optval, &sctp_sk(sk)->autoclose, len))
29851da177e4SLinus Torvalds 		return -EFAULT;
29861da177e4SLinus Torvalds 	return 0;
29871da177e4SLinus Torvalds }
29881da177e4SLinus Torvalds 
29891da177e4SLinus Torvalds /* Helper routine to branch off an association to a new socket.  */
29901da177e4SLinus Torvalds SCTP_STATIC int sctp_do_peeloff(struct sctp_association *asoc,
29911da177e4SLinus Torvalds 				struct socket **sockp)
29921da177e4SLinus Torvalds {
29931da177e4SLinus Torvalds 	struct sock *sk = asoc->base.sk;
29941da177e4SLinus Torvalds 	struct socket *sock;
29951da177e4SLinus Torvalds 	int err = 0;
29961da177e4SLinus Torvalds 
29971da177e4SLinus Torvalds 	/* An association cannot be branched off from an already peeled-off
29981da177e4SLinus Torvalds 	 * socket, nor is this supported for tcp style sockets.
29991da177e4SLinus Torvalds 	 */
30001da177e4SLinus Torvalds 	if (!sctp_style(sk, UDP))
30011da177e4SLinus Torvalds 		return -EINVAL;
30021da177e4SLinus Torvalds 
30031da177e4SLinus Torvalds 	/* Create a new socket.  */
30041da177e4SLinus Torvalds 	err = sock_create(sk->sk_family, SOCK_SEQPACKET, IPPROTO_SCTP, &sock);
30051da177e4SLinus Torvalds 	if (err < 0)
30061da177e4SLinus Torvalds 		return err;
30071da177e4SLinus Torvalds 
30081da177e4SLinus Torvalds 	/* Populate the fields of the newsk from the oldsk and migrate the
30091da177e4SLinus Torvalds 	 * asoc to the newsk.
30101da177e4SLinus Torvalds 	 */
30111da177e4SLinus Torvalds 	sctp_sock_migrate(sk, sock->sk, asoc, SCTP_SOCKET_UDP_HIGH_BANDWIDTH);
30121da177e4SLinus Torvalds 	*sockp = sock;
30131da177e4SLinus Torvalds 
30141da177e4SLinus Torvalds 	return err;
30151da177e4SLinus Torvalds }
30161da177e4SLinus Torvalds 
30171da177e4SLinus Torvalds static int sctp_getsockopt_peeloff(struct sock *sk, int len, char __user *optval, int __user *optlen)
30181da177e4SLinus Torvalds {
30191da177e4SLinus Torvalds 	sctp_peeloff_arg_t peeloff;
30201da177e4SLinus Torvalds 	struct socket *newsock;
30211da177e4SLinus Torvalds 	int retval = 0;
30221da177e4SLinus Torvalds 	struct sctp_association *asoc;
30231da177e4SLinus Torvalds 
30241da177e4SLinus Torvalds 	if (len != sizeof(sctp_peeloff_arg_t))
30251da177e4SLinus Torvalds 		return -EINVAL;
30261da177e4SLinus Torvalds 	if (copy_from_user(&peeloff, optval, len))
30271da177e4SLinus Torvalds 		return -EFAULT;
30281da177e4SLinus Torvalds 
30291da177e4SLinus Torvalds 	asoc = sctp_id2assoc(sk, peeloff.associd);
30301da177e4SLinus Torvalds 	if (!asoc) {
30311da177e4SLinus Torvalds 		retval = -EINVAL;
30321da177e4SLinus Torvalds 		goto out;
30331da177e4SLinus Torvalds 	}
30341da177e4SLinus Torvalds 
30351da177e4SLinus Torvalds 	SCTP_DEBUG_PRINTK("%s: sk: %p asoc: %p\n", __FUNCTION__, sk, asoc);
30361da177e4SLinus Torvalds 
30371da177e4SLinus Torvalds 	retval = sctp_do_peeloff(asoc, &newsock);
30381da177e4SLinus Torvalds 	if (retval < 0)
30391da177e4SLinus Torvalds 		goto out;
30401da177e4SLinus Torvalds 
30411da177e4SLinus Torvalds 	/* Map the socket to an unused fd that can be returned to the user.  */
30421da177e4SLinus Torvalds 	retval = sock_map_fd(newsock);
30431da177e4SLinus Torvalds 	if (retval < 0) {
30441da177e4SLinus Torvalds 		sock_release(newsock);
30451da177e4SLinus Torvalds 		goto out;
30461da177e4SLinus Torvalds 	}
30471da177e4SLinus Torvalds 
30481da177e4SLinus Torvalds 	SCTP_DEBUG_PRINTK("%s: sk: %p asoc: %p newsk: %p sd: %d\n",
30491da177e4SLinus Torvalds 			  __FUNCTION__, sk, asoc, newsock->sk, retval);
30501da177e4SLinus Torvalds 
30511da177e4SLinus Torvalds 	/* Return the fd mapped to the new socket.  */
30521da177e4SLinus Torvalds 	peeloff.sd = retval;
30531da177e4SLinus Torvalds 	if (copy_to_user(optval, &peeloff, len))
30541da177e4SLinus Torvalds 		retval = -EFAULT;
30551da177e4SLinus Torvalds 
30561da177e4SLinus Torvalds out:
30571da177e4SLinus Torvalds 	return retval;
30581da177e4SLinus Torvalds }
30591da177e4SLinus Torvalds 
30601da177e4SLinus Torvalds /* 7.1.13 Peer Address Parameters (SCTP_PEER_ADDR_PARAMS)
30611da177e4SLinus Torvalds  *
30621da177e4SLinus Torvalds  * Applications can enable or disable heartbeats for any peer address of
30631da177e4SLinus Torvalds  * an association, modify an address's heartbeat interval, force a
30641da177e4SLinus Torvalds  * heartbeat to be sent immediately, and adjust the address's maximum
30651da177e4SLinus Torvalds  * number of retransmissions sent before an address is considered
30661da177e4SLinus Torvalds  * unreachable.  The following structure is used to access and modify an
30671da177e4SLinus Torvalds  * address's parameters:
30681da177e4SLinus Torvalds  *
30691da177e4SLinus Torvalds  *  struct sctp_paddrparams {
30701da177e4SLinus Torvalds  *      sctp_assoc_t            spp_assoc_id;
30711da177e4SLinus Torvalds  *      struct sockaddr_storage spp_address;
30721da177e4SLinus Torvalds  *      uint32_t                spp_hbinterval;
30731da177e4SLinus Torvalds  *      uint16_t                spp_pathmaxrxt;
30741da177e4SLinus Torvalds  *  };
30751da177e4SLinus Torvalds  *
30761da177e4SLinus Torvalds  *   spp_assoc_id    - (UDP style socket) This is filled in the application,
30771da177e4SLinus Torvalds  *                     and identifies the association for this query.
30781da177e4SLinus Torvalds  *   spp_address     - This specifies which address is of interest.
30791da177e4SLinus Torvalds  *   spp_hbinterval  - This contains the value of the heartbeat interval,
30801da177e4SLinus Torvalds  *                     in milliseconds.  A value of 0, when modifying the
30811da177e4SLinus Torvalds  *                     parameter, specifies that the heartbeat on this
30821da177e4SLinus Torvalds  *                     address should be disabled. A value of UINT32_MAX
30831da177e4SLinus Torvalds  *                     (4294967295), when modifying the parameter,
30841da177e4SLinus Torvalds  *                     specifies that a heartbeat should be sent
30851da177e4SLinus Torvalds  *                     immediately to the peer address, and the current
30861da177e4SLinus Torvalds  *                     interval should remain unchanged.
30871da177e4SLinus Torvalds  *   spp_pathmaxrxt  - This contains the maximum number of
30881da177e4SLinus Torvalds  *                     retransmissions before this address shall be
30891da177e4SLinus Torvalds  *                     considered unreachable.
30901da177e4SLinus Torvalds  */
30911da177e4SLinus Torvalds static int sctp_getsockopt_peer_addr_params(struct sock *sk, int len,
30921da177e4SLinus Torvalds 						char __user *optval, int __user *optlen)
30931da177e4SLinus Torvalds {
30941da177e4SLinus Torvalds 	struct sctp_paddrparams params;
30951da177e4SLinus Torvalds 	struct sctp_transport *trans;
30961da177e4SLinus Torvalds 
30971da177e4SLinus Torvalds 	if (len != sizeof(struct sctp_paddrparams))
30981da177e4SLinus Torvalds 		return -EINVAL;
30991da177e4SLinus Torvalds 	if (copy_from_user(&params, optval, len))
31001da177e4SLinus Torvalds 		return -EFAULT;
31011da177e4SLinus Torvalds 
31021da177e4SLinus Torvalds 	/* If no association id is specified retrieve the default value
31031da177e4SLinus Torvalds 	 * for the endpoint that will be used for all future associations
31041da177e4SLinus Torvalds 	 */
31051da177e4SLinus Torvalds 	if (!params.spp_assoc_id &&
31061da177e4SLinus Torvalds 	    sctp_is_any(( union sctp_addr *)&params.spp_address)) {
31071da177e4SLinus Torvalds 		params.spp_hbinterval = sctp_sk(sk)->paddrparam.spp_hbinterval;
31081da177e4SLinus Torvalds 		params.spp_pathmaxrxt = sctp_sk(sk)->paddrparam.spp_pathmaxrxt;
31091da177e4SLinus Torvalds 
31101da177e4SLinus Torvalds 		goto done;
31111da177e4SLinus Torvalds 	}
31121da177e4SLinus Torvalds 
31131da177e4SLinus Torvalds 	trans = sctp_addr_id2transport(sk, &params.spp_address,
31141da177e4SLinus Torvalds 				       params.spp_assoc_id);
31151da177e4SLinus Torvalds 	if (!trans)
31161da177e4SLinus Torvalds 		return -EINVAL;
31171da177e4SLinus Torvalds 
31181da177e4SLinus Torvalds 	/* The value of the heartbeat interval, in milliseconds. A value of 0,
31191da177e4SLinus Torvalds 	 * when modifying the parameter, specifies that the heartbeat on this
31201da177e4SLinus Torvalds 	 * address should be disabled.
31211da177e4SLinus Torvalds 	 */
31221da177e4SLinus Torvalds 	if (!trans->hb_allowed)
31231da177e4SLinus Torvalds 		params.spp_hbinterval = 0;
31241da177e4SLinus Torvalds 	else
31251da177e4SLinus Torvalds 		params.spp_hbinterval = jiffies_to_msecs(trans->hb_interval);
31261da177e4SLinus Torvalds 
31271da177e4SLinus Torvalds 	/* spp_pathmaxrxt contains the maximum number of retransmissions
31281da177e4SLinus Torvalds 	 * before this address shall be considered unreachable.
31291da177e4SLinus Torvalds 	 */
31301da177e4SLinus Torvalds 	params.spp_pathmaxrxt = trans->max_retrans;
31311da177e4SLinus Torvalds 
31321da177e4SLinus Torvalds done:
31331da177e4SLinus Torvalds 	if (copy_to_user(optval, &params, len))
31341da177e4SLinus Torvalds 		return -EFAULT;
31351da177e4SLinus Torvalds 
31361da177e4SLinus Torvalds 	if (put_user(len, optlen))
31371da177e4SLinus Torvalds 		return -EFAULT;
31381da177e4SLinus Torvalds 
31391da177e4SLinus Torvalds 	return 0;
31401da177e4SLinus Torvalds }
31411da177e4SLinus Torvalds 
31421da177e4SLinus Torvalds /* 7.1.3 Initialization Parameters (SCTP_INITMSG)
31431da177e4SLinus Torvalds  *
31441da177e4SLinus Torvalds  * Applications can specify protocol parameters for the default association
31451da177e4SLinus Torvalds  * initialization.  The option name argument to setsockopt() and getsockopt()
31461da177e4SLinus Torvalds  * is SCTP_INITMSG.
31471da177e4SLinus Torvalds  *
31481da177e4SLinus Torvalds  * Setting initialization parameters is effective only on an unconnected
31491da177e4SLinus Torvalds  * socket (for UDP-style sockets only future associations are effected
31501da177e4SLinus Torvalds  * by the change).  With TCP-style sockets, this option is inherited by
31511da177e4SLinus Torvalds  * sockets derived from a listener socket.
31521da177e4SLinus Torvalds  */
31531da177e4SLinus Torvalds static int sctp_getsockopt_initmsg(struct sock *sk, int len, char __user *optval, int __user *optlen)
31541da177e4SLinus Torvalds {
31551da177e4SLinus Torvalds 	if (len != sizeof(struct sctp_initmsg))
31561da177e4SLinus Torvalds 		return -EINVAL;
31571da177e4SLinus Torvalds 	if (copy_to_user(optval, &sctp_sk(sk)->initmsg, len))
31581da177e4SLinus Torvalds 		return -EFAULT;
31591da177e4SLinus Torvalds 	return 0;
31601da177e4SLinus Torvalds }
31611da177e4SLinus Torvalds 
31625fe467eeSIvan Skytte Jørgensen static int sctp_getsockopt_peer_addrs_num_old(struct sock *sk, int len,
31635fe467eeSIvan Skytte Jørgensen 					      char __user *optval,
31645fe467eeSIvan Skytte Jørgensen 					      int __user *optlen)
31651da177e4SLinus Torvalds {
31661da177e4SLinus Torvalds 	sctp_assoc_t id;
31671da177e4SLinus Torvalds 	struct sctp_association *asoc;
31681da177e4SLinus Torvalds 	struct list_head *pos;
31691da177e4SLinus Torvalds 	int cnt = 0;
31701da177e4SLinus Torvalds 
31711da177e4SLinus Torvalds 	if (len != sizeof(sctp_assoc_t))
31721da177e4SLinus Torvalds 		return -EINVAL;
31731da177e4SLinus Torvalds 
31741da177e4SLinus Torvalds 	if (copy_from_user(&id, optval, sizeof(sctp_assoc_t)))
31751da177e4SLinus Torvalds 		return -EFAULT;
31761da177e4SLinus Torvalds 
31771da177e4SLinus Torvalds 	/* For UDP-style sockets, id specifies the association to query.  */
31781da177e4SLinus Torvalds 	asoc = sctp_id2assoc(sk, id);
31791da177e4SLinus Torvalds 	if (!asoc)
31801da177e4SLinus Torvalds 		return -EINVAL;
31811da177e4SLinus Torvalds 
31821da177e4SLinus Torvalds 	list_for_each(pos, &asoc->peer.transport_addr_list) {
31831da177e4SLinus Torvalds 		cnt ++;
31841da177e4SLinus Torvalds 	}
31851da177e4SLinus Torvalds 
31861da177e4SLinus Torvalds 	return cnt;
31871da177e4SLinus Torvalds }
31881da177e4SLinus Torvalds 
31895fe467eeSIvan Skytte Jørgensen /*
31905fe467eeSIvan Skytte Jørgensen  * Old API for getting list of peer addresses. Does not work for 32-bit
31915fe467eeSIvan Skytte Jørgensen  * programs running on a 64-bit kernel
31925fe467eeSIvan Skytte Jørgensen  */
31935fe467eeSIvan Skytte Jørgensen static int sctp_getsockopt_peer_addrs_old(struct sock *sk, int len,
31945fe467eeSIvan Skytte Jørgensen 					  char __user *optval,
31955fe467eeSIvan Skytte Jørgensen 					  int __user *optlen)
31961da177e4SLinus Torvalds {
31971da177e4SLinus Torvalds 	struct sctp_association *asoc;
31981da177e4SLinus Torvalds 	struct list_head *pos;
31991da177e4SLinus Torvalds 	int cnt = 0;
32005fe467eeSIvan Skytte Jørgensen 	struct sctp_getaddrs_old getaddrs;
32011da177e4SLinus Torvalds 	struct sctp_transport *from;
32021da177e4SLinus Torvalds 	void __user *to;
32031da177e4SLinus Torvalds 	union sctp_addr temp;
32041da177e4SLinus Torvalds 	struct sctp_sock *sp = sctp_sk(sk);
32051da177e4SLinus Torvalds 	int addrlen;
32061da177e4SLinus Torvalds 
32075fe467eeSIvan Skytte Jørgensen 	if (len != sizeof(struct sctp_getaddrs_old))
32081da177e4SLinus Torvalds 		return -EINVAL;
32091da177e4SLinus Torvalds 
32105fe467eeSIvan Skytte Jørgensen 	if (copy_from_user(&getaddrs, optval, sizeof(struct sctp_getaddrs_old)))
32111da177e4SLinus Torvalds 		return -EFAULT;
32121da177e4SLinus Torvalds 
32131da177e4SLinus Torvalds 	if (getaddrs.addr_num <= 0) return -EINVAL;
32141da177e4SLinus Torvalds 
32151da177e4SLinus Torvalds 	/* For UDP-style sockets, id specifies the association to query.  */
32161da177e4SLinus Torvalds 	asoc = sctp_id2assoc(sk, getaddrs.assoc_id);
32171da177e4SLinus Torvalds 	if (!asoc)
32181da177e4SLinus Torvalds 		return -EINVAL;
32191da177e4SLinus Torvalds 
32201da177e4SLinus Torvalds 	to = (void __user *)getaddrs.addrs;
32211da177e4SLinus Torvalds 	list_for_each(pos, &asoc->peer.transport_addr_list) {
32221da177e4SLinus Torvalds 		from = list_entry(pos, struct sctp_transport, transports);
32231da177e4SLinus Torvalds 		memcpy(&temp, &from->ipaddr, sizeof(temp));
32241da177e4SLinus Torvalds 		sctp_get_pf_specific(sk->sk_family)->addr_v4map(sp, &temp);
32251da177e4SLinus Torvalds 		addrlen = sctp_get_af_specific(sk->sk_family)->sockaddr_len;
32261da177e4SLinus Torvalds 		temp.v4.sin_port = htons(temp.v4.sin_port);
32271da177e4SLinus Torvalds 		if (copy_to_user(to, &temp, addrlen))
32281da177e4SLinus Torvalds 			return -EFAULT;
32291da177e4SLinus Torvalds 		to += addrlen ;
32301da177e4SLinus Torvalds 		cnt ++;
32311da177e4SLinus Torvalds 		if (cnt >= getaddrs.addr_num) break;
32321da177e4SLinus Torvalds 	}
32331da177e4SLinus Torvalds 	getaddrs.addr_num = cnt;
32345fe467eeSIvan Skytte Jørgensen 	if (copy_to_user(optval, &getaddrs, sizeof(struct sctp_getaddrs_old)))
32351da177e4SLinus Torvalds 		return -EFAULT;
32361da177e4SLinus Torvalds 
32371da177e4SLinus Torvalds 	return 0;
32381da177e4SLinus Torvalds }
32391da177e4SLinus Torvalds 
32405fe467eeSIvan Skytte Jørgensen static int sctp_getsockopt_peer_addrs(struct sock *sk, int len,
32415fe467eeSIvan Skytte Jørgensen 				      char __user *optval, int __user *optlen)
32425fe467eeSIvan Skytte Jørgensen {
32435fe467eeSIvan Skytte Jørgensen 	struct sctp_association *asoc;
32445fe467eeSIvan Skytte Jørgensen 	struct list_head *pos;
32455fe467eeSIvan Skytte Jørgensen 	int cnt = 0;
32465fe467eeSIvan Skytte Jørgensen 	struct sctp_getaddrs getaddrs;
32475fe467eeSIvan Skytte Jørgensen 	struct sctp_transport *from;
32485fe467eeSIvan Skytte Jørgensen 	void __user *to;
32495fe467eeSIvan Skytte Jørgensen 	union sctp_addr temp;
32505fe467eeSIvan Skytte Jørgensen 	struct sctp_sock *sp = sctp_sk(sk);
32515fe467eeSIvan Skytte Jørgensen 	int addrlen;
32525fe467eeSIvan Skytte Jørgensen 	size_t space_left;
32535fe467eeSIvan Skytte Jørgensen 	int bytes_copied;
32545fe467eeSIvan Skytte Jørgensen 
32555fe467eeSIvan Skytte Jørgensen 	if (len < sizeof(struct sctp_getaddrs))
32565fe467eeSIvan Skytte Jørgensen 		return -EINVAL;
32575fe467eeSIvan Skytte Jørgensen 
32585fe467eeSIvan Skytte Jørgensen 	if (copy_from_user(&getaddrs, optval, sizeof(struct sctp_getaddrs)))
32595fe467eeSIvan Skytte Jørgensen 		return -EFAULT;
32605fe467eeSIvan Skytte Jørgensen 
32615fe467eeSIvan Skytte Jørgensen 	/* For UDP-style sockets, id specifies the association to query.  */
32625fe467eeSIvan Skytte Jørgensen 	asoc = sctp_id2assoc(sk, getaddrs.assoc_id);
32635fe467eeSIvan Skytte Jørgensen 	if (!asoc)
32645fe467eeSIvan Skytte Jørgensen 		return -EINVAL;
32655fe467eeSIvan Skytte Jørgensen 
32665fe467eeSIvan Skytte Jørgensen 	to = optval + offsetof(struct sctp_getaddrs,addrs);
32675fe467eeSIvan Skytte Jørgensen 	space_left = len - sizeof(struct sctp_getaddrs) -
32685fe467eeSIvan Skytte Jørgensen 			offsetof(struct sctp_getaddrs,addrs);
32695fe467eeSIvan Skytte Jørgensen 
32705fe467eeSIvan Skytte Jørgensen 	list_for_each(pos, &asoc->peer.transport_addr_list) {
32715fe467eeSIvan Skytte Jørgensen 		from = list_entry(pos, struct sctp_transport, transports);
32725fe467eeSIvan Skytte Jørgensen 		memcpy(&temp, &from->ipaddr, sizeof(temp));
32735fe467eeSIvan Skytte Jørgensen 		sctp_get_pf_specific(sk->sk_family)->addr_v4map(sp, &temp);
32745fe467eeSIvan Skytte Jørgensen 		addrlen = sctp_get_af_specific(sk->sk_family)->sockaddr_len;
32755fe467eeSIvan Skytte Jørgensen 		if(space_left < addrlen)
32765fe467eeSIvan Skytte Jørgensen 			return -ENOMEM;
32775fe467eeSIvan Skytte Jørgensen 		temp.v4.sin_port = htons(temp.v4.sin_port);
32785fe467eeSIvan Skytte Jørgensen 		if (copy_to_user(to, &temp, addrlen))
32795fe467eeSIvan Skytte Jørgensen 			return -EFAULT;
32805fe467eeSIvan Skytte Jørgensen 		to += addrlen;
32815fe467eeSIvan Skytte Jørgensen 		cnt++;
32825fe467eeSIvan Skytte Jørgensen 		space_left -= addrlen;
32835fe467eeSIvan Skytte Jørgensen 	}
32845fe467eeSIvan Skytte Jørgensen 
32855fe467eeSIvan Skytte Jørgensen 	if (put_user(cnt, &((struct sctp_getaddrs __user *)optval)->addr_num))
32865fe467eeSIvan Skytte Jørgensen 		return -EFAULT;
32875fe467eeSIvan Skytte Jørgensen 	bytes_copied = ((char __user *)to) - optval;
32885fe467eeSIvan Skytte Jørgensen 	if (put_user(bytes_copied, optlen))
32895fe467eeSIvan Skytte Jørgensen 		return -EFAULT;
32905fe467eeSIvan Skytte Jørgensen 
32915fe467eeSIvan Skytte Jørgensen 	return 0;
32925fe467eeSIvan Skytte Jørgensen }
32935fe467eeSIvan Skytte Jørgensen 
32945fe467eeSIvan Skytte Jørgensen static int sctp_getsockopt_local_addrs_num_old(struct sock *sk, int len,
32951da177e4SLinus Torvalds 					       char __user *optval,
32961da177e4SLinus Torvalds 					       int __user *optlen)
32971da177e4SLinus Torvalds {
32981da177e4SLinus Torvalds 	sctp_assoc_t id;
32991da177e4SLinus Torvalds 	struct sctp_bind_addr *bp;
33001da177e4SLinus Torvalds 	struct sctp_association *asoc;
33011da177e4SLinus Torvalds 	struct list_head *pos;
33021da177e4SLinus Torvalds 	struct sctp_sockaddr_entry *addr;
33031da177e4SLinus Torvalds 	rwlock_t *addr_lock;
33041da177e4SLinus Torvalds 	unsigned long flags;
33051da177e4SLinus Torvalds 	int cnt = 0;
33061da177e4SLinus Torvalds 
33071da177e4SLinus Torvalds 	if (len != sizeof(sctp_assoc_t))
33081da177e4SLinus Torvalds 		return -EINVAL;
33091da177e4SLinus Torvalds 
33101da177e4SLinus Torvalds 	if (copy_from_user(&id, optval, sizeof(sctp_assoc_t)))
33111da177e4SLinus Torvalds 		return -EFAULT;
33121da177e4SLinus Torvalds 
33131da177e4SLinus Torvalds 	/*
33141da177e4SLinus Torvalds 	 *  For UDP-style sockets, id specifies the association to query.
33151da177e4SLinus Torvalds 	 *  If the id field is set to the value '0' then the locally bound
33161da177e4SLinus Torvalds 	 *  addresses are returned without regard to any particular
33171da177e4SLinus Torvalds 	 *  association.
33181da177e4SLinus Torvalds 	 */
33191da177e4SLinus Torvalds 	if (0 == id) {
33201da177e4SLinus Torvalds 		bp = &sctp_sk(sk)->ep->base.bind_addr;
33211da177e4SLinus Torvalds 		addr_lock = &sctp_sk(sk)->ep->base.addr_lock;
33221da177e4SLinus Torvalds 	} else {
33231da177e4SLinus Torvalds 		asoc = sctp_id2assoc(sk, id);
33241da177e4SLinus Torvalds 		if (!asoc)
33251da177e4SLinus Torvalds 			return -EINVAL;
33261da177e4SLinus Torvalds 		bp = &asoc->base.bind_addr;
33271da177e4SLinus Torvalds 		addr_lock = &asoc->base.addr_lock;
33281da177e4SLinus Torvalds 	}
33291da177e4SLinus Torvalds 
33301da177e4SLinus Torvalds 	sctp_read_lock(addr_lock);
33311da177e4SLinus Torvalds 
33321da177e4SLinus Torvalds 	/* If the endpoint is bound to 0.0.0.0 or ::0, count the valid
33331da177e4SLinus Torvalds 	 * addresses from the global local address list.
33341da177e4SLinus Torvalds 	 */
33351da177e4SLinus Torvalds 	if (sctp_list_single_entry(&bp->address_list)) {
33361da177e4SLinus Torvalds 		addr = list_entry(bp->address_list.next,
33371da177e4SLinus Torvalds 				  struct sctp_sockaddr_entry, list);
33381da177e4SLinus Torvalds 		if (sctp_is_any(&addr->a)) {
33391da177e4SLinus Torvalds 			sctp_spin_lock_irqsave(&sctp_local_addr_lock, flags);
33401da177e4SLinus Torvalds 			list_for_each(pos, &sctp_local_addr_list) {
33411da177e4SLinus Torvalds 				addr = list_entry(pos,
33421da177e4SLinus Torvalds 						  struct sctp_sockaddr_entry,
33431da177e4SLinus Torvalds 						  list);
33441da177e4SLinus Torvalds 				if ((PF_INET == sk->sk_family) &&
33451da177e4SLinus Torvalds 				    (AF_INET6 == addr->a.sa.sa_family))
33461da177e4SLinus Torvalds 					continue;
33471da177e4SLinus Torvalds 				cnt++;
33481da177e4SLinus Torvalds 			}
33491da177e4SLinus Torvalds 			sctp_spin_unlock_irqrestore(&sctp_local_addr_lock,
33501da177e4SLinus Torvalds 						    flags);
33511da177e4SLinus Torvalds 		} else {
33521da177e4SLinus Torvalds 			cnt = 1;
33531da177e4SLinus Torvalds 		}
33541da177e4SLinus Torvalds 		goto done;
33551da177e4SLinus Torvalds 	}
33561da177e4SLinus Torvalds 
33571da177e4SLinus Torvalds 	list_for_each(pos, &bp->address_list) {
33581da177e4SLinus Torvalds 		cnt ++;
33591da177e4SLinus Torvalds 	}
33601da177e4SLinus Torvalds 
33611da177e4SLinus Torvalds done:
33621da177e4SLinus Torvalds 	sctp_read_unlock(addr_lock);
33631da177e4SLinus Torvalds 	return cnt;
33641da177e4SLinus Torvalds }
33651da177e4SLinus Torvalds 
33661da177e4SLinus Torvalds /* Helper function that copies local addresses to user and returns the number
33671da177e4SLinus Torvalds  * of addresses copied.
33681da177e4SLinus Torvalds  */
33695fe467eeSIvan Skytte Jørgensen static int sctp_copy_laddrs_to_user_old(struct sock *sk, __u16 port, int max_addrs,
33701da177e4SLinus Torvalds 					void __user *to)
33711da177e4SLinus Torvalds {
33721da177e4SLinus Torvalds 	struct list_head *pos;
33731da177e4SLinus Torvalds 	struct sctp_sockaddr_entry *addr;
33741da177e4SLinus Torvalds 	unsigned long flags;
33751da177e4SLinus Torvalds 	union sctp_addr temp;
33761da177e4SLinus Torvalds 	int cnt = 0;
33771da177e4SLinus Torvalds 	int addrlen;
33781da177e4SLinus Torvalds 
33791da177e4SLinus Torvalds 	sctp_spin_lock_irqsave(&sctp_local_addr_lock, flags);
33801da177e4SLinus Torvalds 	list_for_each(pos, &sctp_local_addr_list) {
33811da177e4SLinus Torvalds 		addr = list_entry(pos, struct sctp_sockaddr_entry, list);
33821da177e4SLinus Torvalds 		if ((PF_INET == sk->sk_family) &&
33831da177e4SLinus Torvalds 		    (AF_INET6 == addr->a.sa.sa_family))
33841da177e4SLinus Torvalds 			continue;
33851da177e4SLinus Torvalds 		memcpy(&temp, &addr->a, sizeof(temp));
33861da177e4SLinus Torvalds 		sctp_get_pf_specific(sk->sk_family)->addr_v4map(sctp_sk(sk),
33871da177e4SLinus Torvalds 								&temp);
33881da177e4SLinus Torvalds 		addrlen = sctp_get_af_specific(temp.sa.sa_family)->sockaddr_len;
33891da177e4SLinus Torvalds 		temp.v4.sin_port = htons(port);
33901da177e4SLinus Torvalds 		if (copy_to_user(to, &temp, addrlen)) {
33911da177e4SLinus Torvalds 			sctp_spin_unlock_irqrestore(&sctp_local_addr_lock,
33921da177e4SLinus Torvalds 						    flags);
33931da177e4SLinus Torvalds 			return -EFAULT;
33941da177e4SLinus Torvalds 		}
33951da177e4SLinus Torvalds 		to += addrlen;
33961da177e4SLinus Torvalds 		cnt ++;
33971da177e4SLinus Torvalds 		if (cnt >= max_addrs) break;
33981da177e4SLinus Torvalds 	}
33991da177e4SLinus Torvalds 	sctp_spin_unlock_irqrestore(&sctp_local_addr_lock, flags);
34001da177e4SLinus Torvalds 
34011da177e4SLinus Torvalds 	return cnt;
34021da177e4SLinus Torvalds }
34031da177e4SLinus Torvalds 
34045fe467eeSIvan Skytte Jørgensen static int sctp_copy_laddrs_to_user(struct sock *sk, __u16 port,
34055fe467eeSIvan Skytte Jørgensen 				    void * __user *to, size_t space_left)
34065fe467eeSIvan Skytte Jørgensen {
34075fe467eeSIvan Skytte Jørgensen 	struct list_head *pos;
34085fe467eeSIvan Skytte Jørgensen 	struct sctp_sockaddr_entry *addr;
34095fe467eeSIvan Skytte Jørgensen 	unsigned long flags;
34105fe467eeSIvan Skytte Jørgensen 	union sctp_addr temp;
34115fe467eeSIvan Skytte Jørgensen 	int cnt = 0;
34125fe467eeSIvan Skytte Jørgensen 	int addrlen;
34135fe467eeSIvan Skytte Jørgensen 
34145fe467eeSIvan Skytte Jørgensen 	sctp_spin_lock_irqsave(&sctp_local_addr_lock, flags);
34155fe467eeSIvan Skytte Jørgensen 	list_for_each(pos, &sctp_local_addr_list) {
34165fe467eeSIvan Skytte Jørgensen 		addr = list_entry(pos, struct sctp_sockaddr_entry, list);
34175fe467eeSIvan Skytte Jørgensen 		if ((PF_INET == sk->sk_family) &&
34185fe467eeSIvan Skytte Jørgensen 		    (AF_INET6 == addr->a.sa.sa_family))
34195fe467eeSIvan Skytte Jørgensen 			continue;
34205fe467eeSIvan Skytte Jørgensen 		memcpy(&temp, &addr->a, sizeof(temp));
34215fe467eeSIvan Skytte Jørgensen 		sctp_get_pf_specific(sk->sk_family)->addr_v4map(sctp_sk(sk),
34225fe467eeSIvan Skytte Jørgensen 								&temp);
34235fe467eeSIvan Skytte Jørgensen 		addrlen = sctp_get_af_specific(temp.sa.sa_family)->sockaddr_len;
34245fe467eeSIvan Skytte Jørgensen 		if(space_left<addrlen)
34255fe467eeSIvan Skytte Jørgensen 			return -ENOMEM;
34265fe467eeSIvan Skytte Jørgensen 		temp.v4.sin_port = htons(port);
34275fe467eeSIvan Skytte Jørgensen 		if (copy_to_user(*to, &temp, addrlen)) {
34285fe467eeSIvan Skytte Jørgensen 			sctp_spin_unlock_irqrestore(&sctp_local_addr_lock,
34295fe467eeSIvan Skytte Jørgensen 						    flags);
34305fe467eeSIvan Skytte Jørgensen 			return -EFAULT;
34315fe467eeSIvan Skytte Jørgensen 		}
34325fe467eeSIvan Skytte Jørgensen 		*to += addrlen;
34335fe467eeSIvan Skytte Jørgensen 		cnt ++;
34345fe467eeSIvan Skytte Jørgensen 		space_left -= addrlen;
34355fe467eeSIvan Skytte Jørgensen 	}
34365fe467eeSIvan Skytte Jørgensen 	sctp_spin_unlock_irqrestore(&sctp_local_addr_lock, flags);
34375fe467eeSIvan Skytte Jørgensen 
34385fe467eeSIvan Skytte Jørgensen 	return cnt;
34395fe467eeSIvan Skytte Jørgensen }
34405fe467eeSIvan Skytte Jørgensen 
34415fe467eeSIvan Skytte Jørgensen /* Old API for getting list of local addresses. Does not work for 32-bit
34425fe467eeSIvan Skytte Jørgensen  * programs running on a 64-bit kernel
34435fe467eeSIvan Skytte Jørgensen  */
34445fe467eeSIvan Skytte Jørgensen static int sctp_getsockopt_local_addrs_old(struct sock *sk, int len,
34451da177e4SLinus Torvalds 					   char __user *optval, int __user *optlen)
34461da177e4SLinus Torvalds {
34471da177e4SLinus Torvalds 	struct sctp_bind_addr *bp;
34481da177e4SLinus Torvalds 	struct sctp_association *asoc;
34491da177e4SLinus Torvalds 	struct list_head *pos;
34501da177e4SLinus Torvalds 	int cnt = 0;
34515fe467eeSIvan Skytte Jørgensen 	struct sctp_getaddrs_old getaddrs;
34521da177e4SLinus Torvalds 	struct sctp_sockaddr_entry *addr;
34531da177e4SLinus Torvalds 	void __user *to;
34541da177e4SLinus Torvalds 	union sctp_addr temp;
34551da177e4SLinus Torvalds 	struct sctp_sock *sp = sctp_sk(sk);
34561da177e4SLinus Torvalds 	int addrlen;
34571da177e4SLinus Torvalds 	rwlock_t *addr_lock;
34581da177e4SLinus Torvalds 	int err = 0;
34591da177e4SLinus Torvalds 
34605fe467eeSIvan Skytte Jørgensen 	if (len != sizeof(struct sctp_getaddrs_old))
34611da177e4SLinus Torvalds 		return -EINVAL;
34621da177e4SLinus Torvalds 
34635fe467eeSIvan Skytte Jørgensen 	if (copy_from_user(&getaddrs, optval, sizeof(struct sctp_getaddrs_old)))
34641da177e4SLinus Torvalds 		return -EFAULT;
34651da177e4SLinus Torvalds 
34661da177e4SLinus Torvalds 	if (getaddrs.addr_num <= 0) return -EINVAL;
34671da177e4SLinus Torvalds 	/*
34681da177e4SLinus Torvalds 	 *  For UDP-style sockets, id specifies the association to query.
34691da177e4SLinus Torvalds 	 *  If the id field is set to the value '0' then the locally bound
34701da177e4SLinus Torvalds 	 *  addresses are returned without regard to any particular
34711da177e4SLinus Torvalds 	 *  association.
34721da177e4SLinus Torvalds 	 */
34731da177e4SLinus Torvalds 	if (0 == getaddrs.assoc_id) {
34741da177e4SLinus Torvalds 		bp = &sctp_sk(sk)->ep->base.bind_addr;
34751da177e4SLinus Torvalds 		addr_lock = &sctp_sk(sk)->ep->base.addr_lock;
34761da177e4SLinus Torvalds 	} else {
34771da177e4SLinus Torvalds 		asoc = sctp_id2assoc(sk, getaddrs.assoc_id);
34781da177e4SLinus Torvalds 		if (!asoc)
34791da177e4SLinus Torvalds 			return -EINVAL;
34801da177e4SLinus Torvalds 		bp = &asoc->base.bind_addr;
34811da177e4SLinus Torvalds 		addr_lock = &asoc->base.addr_lock;
34821da177e4SLinus Torvalds 	}
34831da177e4SLinus Torvalds 
34841da177e4SLinus Torvalds 	to = getaddrs.addrs;
34851da177e4SLinus Torvalds 
34861da177e4SLinus Torvalds 	sctp_read_lock(addr_lock);
34871da177e4SLinus Torvalds 
34881da177e4SLinus Torvalds 	/* If the endpoint is bound to 0.0.0.0 or ::0, get the valid
34891da177e4SLinus Torvalds 	 * addresses from the global local address list.
34901da177e4SLinus Torvalds 	 */
34911da177e4SLinus Torvalds 	if (sctp_list_single_entry(&bp->address_list)) {
34921da177e4SLinus Torvalds 		addr = list_entry(bp->address_list.next,
34931da177e4SLinus Torvalds 				  struct sctp_sockaddr_entry, list);
34941da177e4SLinus Torvalds 		if (sctp_is_any(&addr->a)) {
34955fe467eeSIvan Skytte Jørgensen 			cnt = sctp_copy_laddrs_to_user_old(sk, bp->port,
34965fe467eeSIvan Skytte Jørgensen 							   getaddrs.addr_num,
34975fe467eeSIvan Skytte Jørgensen 							   to);
34981da177e4SLinus Torvalds 			if (cnt < 0) {
34991da177e4SLinus Torvalds 				err = cnt;
35001da177e4SLinus Torvalds 				goto unlock;
35011da177e4SLinus Torvalds 			}
35021da177e4SLinus Torvalds 			goto copy_getaddrs;
35031da177e4SLinus Torvalds 		}
35041da177e4SLinus Torvalds 	}
35051da177e4SLinus Torvalds 
35061da177e4SLinus Torvalds 	list_for_each(pos, &bp->address_list) {
35071da177e4SLinus Torvalds 		addr = list_entry(pos, struct sctp_sockaddr_entry, list);
35081da177e4SLinus Torvalds 		memcpy(&temp, &addr->a, sizeof(temp));
35091da177e4SLinus Torvalds 		sctp_get_pf_specific(sk->sk_family)->addr_v4map(sp, &temp);
35101da177e4SLinus Torvalds 		addrlen = sctp_get_af_specific(temp.sa.sa_family)->sockaddr_len;
35111da177e4SLinus Torvalds 		temp.v4.sin_port = htons(temp.v4.sin_port);
35121da177e4SLinus Torvalds 		if (copy_to_user(to, &temp, addrlen)) {
35131da177e4SLinus Torvalds 			err = -EFAULT;
35141da177e4SLinus Torvalds 			goto unlock;
35151da177e4SLinus Torvalds 		}
35161da177e4SLinus Torvalds 		to += addrlen;
35171da177e4SLinus Torvalds 		cnt ++;
35181da177e4SLinus Torvalds 		if (cnt >= getaddrs.addr_num) break;
35191da177e4SLinus Torvalds 	}
35201da177e4SLinus Torvalds 
35211da177e4SLinus Torvalds copy_getaddrs:
35221da177e4SLinus Torvalds 	getaddrs.addr_num = cnt;
35235fe467eeSIvan Skytte Jørgensen 	if (copy_to_user(optval, &getaddrs, sizeof(struct sctp_getaddrs_old)))
35241da177e4SLinus Torvalds 		err = -EFAULT;
35251da177e4SLinus Torvalds 
35261da177e4SLinus Torvalds unlock:
35271da177e4SLinus Torvalds 	sctp_read_unlock(addr_lock);
35281da177e4SLinus Torvalds 	return err;
35291da177e4SLinus Torvalds }
35301da177e4SLinus Torvalds 
35315fe467eeSIvan Skytte Jørgensen static int sctp_getsockopt_local_addrs(struct sock *sk, int len,
35325fe467eeSIvan Skytte Jørgensen 				       char __user *optval, int __user *optlen)
35335fe467eeSIvan Skytte Jørgensen {
35345fe467eeSIvan Skytte Jørgensen 	struct sctp_bind_addr *bp;
35355fe467eeSIvan Skytte Jørgensen 	struct sctp_association *asoc;
35365fe467eeSIvan Skytte Jørgensen 	struct list_head *pos;
35375fe467eeSIvan Skytte Jørgensen 	int cnt = 0;
35385fe467eeSIvan Skytte Jørgensen 	struct sctp_getaddrs getaddrs;
35395fe467eeSIvan Skytte Jørgensen 	struct sctp_sockaddr_entry *addr;
35405fe467eeSIvan Skytte Jørgensen 	void __user *to;
35415fe467eeSIvan Skytte Jørgensen 	union sctp_addr temp;
35425fe467eeSIvan Skytte Jørgensen 	struct sctp_sock *sp = sctp_sk(sk);
35435fe467eeSIvan Skytte Jørgensen 	int addrlen;
35445fe467eeSIvan Skytte Jørgensen 	rwlock_t *addr_lock;
35455fe467eeSIvan Skytte Jørgensen 	int err = 0;
35465fe467eeSIvan Skytte Jørgensen 	size_t space_left;
35475fe467eeSIvan Skytte Jørgensen 	int bytes_copied;
35485fe467eeSIvan Skytte Jørgensen 
35495fe467eeSIvan Skytte Jørgensen 	if (len <= sizeof(struct sctp_getaddrs))
35505fe467eeSIvan Skytte Jørgensen 		return -EINVAL;
35515fe467eeSIvan Skytte Jørgensen 
35525fe467eeSIvan Skytte Jørgensen 	if (copy_from_user(&getaddrs, optval, sizeof(struct sctp_getaddrs)))
35535fe467eeSIvan Skytte Jørgensen 		return -EFAULT;
35545fe467eeSIvan Skytte Jørgensen 
35555fe467eeSIvan Skytte Jørgensen 	/*
35565fe467eeSIvan Skytte Jørgensen 	 *  For UDP-style sockets, id specifies the association to query.
35575fe467eeSIvan Skytte Jørgensen 	 *  If the id field is set to the value '0' then the locally bound
35585fe467eeSIvan Skytte Jørgensen 	 *  addresses are returned without regard to any particular
35595fe467eeSIvan Skytte Jørgensen 	 *  association.
35605fe467eeSIvan Skytte Jørgensen 	 */
35615fe467eeSIvan Skytte Jørgensen 	if (0 == getaddrs.assoc_id) {
35625fe467eeSIvan Skytte Jørgensen 		bp = &sctp_sk(sk)->ep->base.bind_addr;
35635fe467eeSIvan Skytte Jørgensen 		addr_lock = &sctp_sk(sk)->ep->base.addr_lock;
35645fe467eeSIvan Skytte Jørgensen 	} else {
35655fe467eeSIvan Skytte Jørgensen 		asoc = sctp_id2assoc(sk, getaddrs.assoc_id);
35665fe467eeSIvan Skytte Jørgensen 		if (!asoc)
35675fe467eeSIvan Skytte Jørgensen 			return -EINVAL;
35685fe467eeSIvan Skytte Jørgensen 		bp = &asoc->base.bind_addr;
35695fe467eeSIvan Skytte Jørgensen 		addr_lock = &asoc->base.addr_lock;
35705fe467eeSIvan Skytte Jørgensen 	}
35715fe467eeSIvan Skytte Jørgensen 
35725fe467eeSIvan Skytte Jørgensen 	to = optval + offsetof(struct sctp_getaddrs,addrs);
35735fe467eeSIvan Skytte Jørgensen 	space_left = len - sizeof(struct sctp_getaddrs) -
35745fe467eeSIvan Skytte Jørgensen 			 offsetof(struct sctp_getaddrs,addrs);
35755fe467eeSIvan Skytte Jørgensen 
35765fe467eeSIvan Skytte Jørgensen 	sctp_read_lock(addr_lock);
35775fe467eeSIvan Skytte Jørgensen 
35785fe467eeSIvan Skytte Jørgensen 	/* If the endpoint is bound to 0.0.0.0 or ::0, get the valid
35795fe467eeSIvan Skytte Jørgensen 	 * addresses from the global local address list.
35805fe467eeSIvan Skytte Jørgensen 	 */
35815fe467eeSIvan Skytte Jørgensen 	if (sctp_list_single_entry(&bp->address_list)) {
35825fe467eeSIvan Skytte Jørgensen 		addr = list_entry(bp->address_list.next,
35835fe467eeSIvan Skytte Jørgensen 				  struct sctp_sockaddr_entry, list);
35845fe467eeSIvan Skytte Jørgensen 		if (sctp_is_any(&addr->a)) {
35855fe467eeSIvan Skytte Jørgensen 			cnt = sctp_copy_laddrs_to_user(sk, bp->port,
35865fe467eeSIvan Skytte Jørgensen 						       &to, space_left);
35875fe467eeSIvan Skytte Jørgensen 			if (cnt < 0) {
35885fe467eeSIvan Skytte Jørgensen 				err = cnt;
35895fe467eeSIvan Skytte Jørgensen 				goto unlock;
35905fe467eeSIvan Skytte Jørgensen 			}
35915fe467eeSIvan Skytte Jørgensen 			goto copy_getaddrs;
35925fe467eeSIvan Skytte Jørgensen 		}
35935fe467eeSIvan Skytte Jørgensen 	}
35945fe467eeSIvan Skytte Jørgensen 
35955fe467eeSIvan Skytte Jørgensen 	list_for_each(pos, &bp->address_list) {
35965fe467eeSIvan Skytte Jørgensen 		addr = list_entry(pos, struct sctp_sockaddr_entry, list);
35975fe467eeSIvan Skytte Jørgensen 		memcpy(&temp, &addr->a, sizeof(temp));
35985fe467eeSIvan Skytte Jørgensen 		sctp_get_pf_specific(sk->sk_family)->addr_v4map(sp, &temp);
35995fe467eeSIvan Skytte Jørgensen 		addrlen = sctp_get_af_specific(temp.sa.sa_family)->sockaddr_len;
36005fe467eeSIvan Skytte Jørgensen 		if(space_left < addrlen)
36015fe467eeSIvan Skytte Jørgensen 			return -ENOMEM; /*fixme: right error?*/
36025fe467eeSIvan Skytte Jørgensen 		temp.v4.sin_port = htons(temp.v4.sin_port);
36035fe467eeSIvan Skytte Jørgensen 		if (copy_to_user(to, &temp, addrlen)) {
36045fe467eeSIvan Skytte Jørgensen 			err = -EFAULT;
36055fe467eeSIvan Skytte Jørgensen 			goto unlock;
36065fe467eeSIvan Skytte Jørgensen 		}
36075fe467eeSIvan Skytte Jørgensen 		to += addrlen;
36085fe467eeSIvan Skytte Jørgensen 		cnt ++;
36095fe467eeSIvan Skytte Jørgensen 		space_left -= addrlen;
36105fe467eeSIvan Skytte Jørgensen 	}
36115fe467eeSIvan Skytte Jørgensen 
36125fe467eeSIvan Skytte Jørgensen copy_getaddrs:
36135fe467eeSIvan Skytte Jørgensen 	if (put_user(cnt, &((struct sctp_getaddrs __user *)optval)->addr_num))
36145fe467eeSIvan Skytte Jørgensen 		return -EFAULT;
36155fe467eeSIvan Skytte Jørgensen 	bytes_copied = ((char __user *)to) - optval;
36165fe467eeSIvan Skytte Jørgensen 	if (put_user(bytes_copied, optlen))
36175fe467eeSIvan Skytte Jørgensen 		return -EFAULT;
36185fe467eeSIvan Skytte Jørgensen 
36195fe467eeSIvan Skytte Jørgensen unlock:
36205fe467eeSIvan Skytte Jørgensen 	sctp_read_unlock(addr_lock);
36215fe467eeSIvan Skytte Jørgensen 	return err;
36225fe467eeSIvan Skytte Jørgensen }
36235fe467eeSIvan Skytte Jørgensen 
36241da177e4SLinus Torvalds /* 7.1.10 Set Primary Address (SCTP_PRIMARY_ADDR)
36251da177e4SLinus Torvalds  *
36261da177e4SLinus Torvalds  * Requests that the local SCTP stack use the enclosed peer address as
36271da177e4SLinus Torvalds  * the association primary.  The enclosed address must be one of the
36281da177e4SLinus Torvalds  * association peer's addresses.
36291da177e4SLinus Torvalds  */
36301da177e4SLinus Torvalds static int sctp_getsockopt_primary_addr(struct sock *sk, int len,
36311da177e4SLinus Torvalds 					char __user *optval, int __user *optlen)
36321da177e4SLinus Torvalds {
36331da177e4SLinus Torvalds 	struct sctp_prim prim;
36341da177e4SLinus Torvalds 	struct sctp_association *asoc;
36351da177e4SLinus Torvalds 	struct sctp_sock *sp = sctp_sk(sk);
36361da177e4SLinus Torvalds 
36371da177e4SLinus Torvalds 	if (len != sizeof(struct sctp_prim))
36381da177e4SLinus Torvalds 		return -EINVAL;
36391da177e4SLinus Torvalds 
36401da177e4SLinus Torvalds 	if (copy_from_user(&prim, optval, sizeof(struct sctp_prim)))
36411da177e4SLinus Torvalds 		return -EFAULT;
36421da177e4SLinus Torvalds 
36431da177e4SLinus Torvalds 	asoc = sctp_id2assoc(sk, prim.ssp_assoc_id);
36441da177e4SLinus Torvalds 	if (!asoc)
36451da177e4SLinus Torvalds 		return -EINVAL;
36461da177e4SLinus Torvalds 
36471da177e4SLinus Torvalds 	if (!asoc->peer.primary_path)
36481da177e4SLinus Torvalds 		return -ENOTCONN;
36491da177e4SLinus Torvalds 
36501da177e4SLinus Torvalds 	asoc->peer.primary_path->ipaddr.v4.sin_port =
36511da177e4SLinus Torvalds 		htons(asoc->peer.primary_path->ipaddr.v4.sin_port);
36521da177e4SLinus Torvalds 	memcpy(&prim.ssp_addr, &asoc->peer.primary_path->ipaddr,
36531da177e4SLinus Torvalds 	       sizeof(union sctp_addr));
36541da177e4SLinus Torvalds 	asoc->peer.primary_path->ipaddr.v4.sin_port =
36551da177e4SLinus Torvalds 		ntohs(asoc->peer.primary_path->ipaddr.v4.sin_port);
36561da177e4SLinus Torvalds 
36571da177e4SLinus Torvalds 	sctp_get_pf_specific(sk->sk_family)->addr_v4map(sp,
36581da177e4SLinus Torvalds 			(union sctp_addr *)&prim.ssp_addr);
36591da177e4SLinus Torvalds 
36601da177e4SLinus Torvalds 	if (copy_to_user(optval, &prim, sizeof(struct sctp_prim)))
36611da177e4SLinus Torvalds 		return -EFAULT;
36621da177e4SLinus Torvalds 
36631da177e4SLinus Torvalds 	return 0;
36641da177e4SLinus Torvalds }
36651da177e4SLinus Torvalds 
36661da177e4SLinus Torvalds /*
36671da177e4SLinus Torvalds  * 7.1.11  Set Adaption Layer Indicator (SCTP_ADAPTION_LAYER)
36681da177e4SLinus Torvalds  *
36691da177e4SLinus Torvalds  * Requests that the local endpoint set the specified Adaption Layer
36701da177e4SLinus Torvalds  * Indication parameter for all future INIT and INIT-ACK exchanges.
36711da177e4SLinus Torvalds  */
36721da177e4SLinus Torvalds static int sctp_getsockopt_adaption_layer(struct sock *sk, int len,
36731da177e4SLinus Torvalds 				  char __user *optval, int __user *optlen)
36741da177e4SLinus Torvalds {
36751da177e4SLinus Torvalds 	__u32 val;
36761da177e4SLinus Torvalds 
36771da177e4SLinus Torvalds 	if (len < sizeof(__u32))
36781da177e4SLinus Torvalds 		return -EINVAL;
36791da177e4SLinus Torvalds 
36801da177e4SLinus Torvalds 	len = sizeof(__u32);
36811da177e4SLinus Torvalds 	val = sctp_sk(sk)->adaption_ind;
36821da177e4SLinus Torvalds 	if (put_user(len, optlen))
36831da177e4SLinus Torvalds 		return -EFAULT;
36841da177e4SLinus Torvalds 	if (copy_to_user(optval, &val, len))
36851da177e4SLinus Torvalds 		return -EFAULT;
36861da177e4SLinus Torvalds 	return 0;
36871da177e4SLinus Torvalds }
36881da177e4SLinus Torvalds 
36891da177e4SLinus Torvalds /*
36901da177e4SLinus Torvalds  *
36911da177e4SLinus Torvalds  * 7.1.14 Set default send parameters (SCTP_DEFAULT_SEND_PARAM)
36921da177e4SLinus Torvalds  *
36931da177e4SLinus Torvalds  *   Applications that wish to use the sendto() system call may wish to
36941da177e4SLinus Torvalds  *   specify a default set of parameters that would normally be supplied
36951da177e4SLinus Torvalds  *   through the inclusion of ancillary data.  This socket option allows
36961da177e4SLinus Torvalds  *   such an application to set the default sctp_sndrcvinfo structure.
36971da177e4SLinus Torvalds 
36981da177e4SLinus Torvalds 
36991da177e4SLinus Torvalds  *   The application that wishes to use this socket option simply passes
37001da177e4SLinus Torvalds  *   in to this call the sctp_sndrcvinfo structure defined in Section
37011da177e4SLinus Torvalds  *   5.2.2) The input parameters accepted by this call include
37021da177e4SLinus Torvalds  *   sinfo_stream, sinfo_flags, sinfo_ppid, sinfo_context,
37031da177e4SLinus Torvalds  *   sinfo_timetolive.  The user must provide the sinfo_assoc_id field in
37041da177e4SLinus Torvalds  *   to this call if the caller is using the UDP model.
37051da177e4SLinus Torvalds  *
37061da177e4SLinus Torvalds  *   For getsockopt, it get the default sctp_sndrcvinfo structure.
37071da177e4SLinus Torvalds  */
37081da177e4SLinus Torvalds static int sctp_getsockopt_default_send_param(struct sock *sk,
37091da177e4SLinus Torvalds 					int len, char __user *optval,
37101da177e4SLinus Torvalds 					int __user *optlen)
37111da177e4SLinus Torvalds {
37121da177e4SLinus Torvalds 	struct sctp_sndrcvinfo info;
37131da177e4SLinus Torvalds 	struct sctp_association *asoc;
37141da177e4SLinus Torvalds 	struct sctp_sock *sp = sctp_sk(sk);
37151da177e4SLinus Torvalds 
37161da177e4SLinus Torvalds 	if (len != sizeof(struct sctp_sndrcvinfo))
37171da177e4SLinus Torvalds 		return -EINVAL;
37181da177e4SLinus Torvalds 	if (copy_from_user(&info, optval, sizeof(struct sctp_sndrcvinfo)))
37191da177e4SLinus Torvalds 		return -EFAULT;
37201da177e4SLinus Torvalds 
37211da177e4SLinus Torvalds 	asoc = sctp_id2assoc(sk, info.sinfo_assoc_id);
37221da177e4SLinus Torvalds 	if (!asoc && info.sinfo_assoc_id && sctp_style(sk, UDP))
37231da177e4SLinus Torvalds 		return -EINVAL;
37241da177e4SLinus Torvalds 
37251da177e4SLinus Torvalds 	if (asoc) {
37261da177e4SLinus Torvalds 		info.sinfo_stream = asoc->default_stream;
37271da177e4SLinus Torvalds 		info.sinfo_flags = asoc->default_flags;
37281da177e4SLinus Torvalds 		info.sinfo_ppid = asoc->default_ppid;
37291da177e4SLinus Torvalds 		info.sinfo_context = asoc->default_context;
37301da177e4SLinus Torvalds 		info.sinfo_timetolive = asoc->default_timetolive;
37311da177e4SLinus Torvalds 	} else {
37321da177e4SLinus Torvalds 		info.sinfo_stream = sp->default_stream;
37331da177e4SLinus Torvalds 		info.sinfo_flags = sp->default_flags;
37341da177e4SLinus Torvalds 		info.sinfo_ppid = sp->default_ppid;
37351da177e4SLinus Torvalds 		info.sinfo_context = sp->default_context;
37361da177e4SLinus Torvalds 		info.sinfo_timetolive = sp->default_timetolive;
37371da177e4SLinus Torvalds 	}
37381da177e4SLinus Torvalds 
37391da177e4SLinus Torvalds 	if (copy_to_user(optval, &info, sizeof(struct sctp_sndrcvinfo)))
37401da177e4SLinus Torvalds 		return -EFAULT;
37411da177e4SLinus Torvalds 
37421da177e4SLinus Torvalds 	return 0;
37431da177e4SLinus Torvalds }
37441da177e4SLinus Torvalds 
37451da177e4SLinus Torvalds /*
37461da177e4SLinus Torvalds  *
37471da177e4SLinus Torvalds  * 7.1.5 SCTP_NODELAY
37481da177e4SLinus Torvalds  *
37491da177e4SLinus Torvalds  * Turn on/off any Nagle-like algorithm.  This means that packets are
37501da177e4SLinus Torvalds  * generally sent as soon as possible and no unnecessary delays are
37511da177e4SLinus Torvalds  * introduced, at the cost of more packets in the network.  Expects an
37521da177e4SLinus Torvalds  * integer boolean flag.
37531da177e4SLinus Torvalds  */
37541da177e4SLinus Torvalds 
37551da177e4SLinus Torvalds static int sctp_getsockopt_nodelay(struct sock *sk, int len,
37561da177e4SLinus Torvalds 				   char __user *optval, int __user *optlen)
37571da177e4SLinus Torvalds {
37581da177e4SLinus Torvalds 	int val;
37591da177e4SLinus Torvalds 
37601da177e4SLinus Torvalds 	if (len < sizeof(int))
37611da177e4SLinus Torvalds 		return -EINVAL;
37621da177e4SLinus Torvalds 
37631da177e4SLinus Torvalds 	len = sizeof(int);
37641da177e4SLinus Torvalds 	val = (sctp_sk(sk)->nodelay == 1);
37651da177e4SLinus Torvalds 	if (put_user(len, optlen))
37661da177e4SLinus Torvalds 		return -EFAULT;
37671da177e4SLinus Torvalds 	if (copy_to_user(optval, &val, len))
37681da177e4SLinus Torvalds 		return -EFAULT;
37691da177e4SLinus Torvalds 	return 0;
37701da177e4SLinus Torvalds }
37711da177e4SLinus Torvalds 
37721da177e4SLinus Torvalds /*
37731da177e4SLinus Torvalds  *
37741da177e4SLinus Torvalds  * 7.1.1 SCTP_RTOINFO
37751da177e4SLinus Torvalds  *
37761da177e4SLinus Torvalds  * The protocol parameters used to initialize and bound retransmission
37771da177e4SLinus Torvalds  * timeout (RTO) are tunable. sctp_rtoinfo structure is used to access
37781da177e4SLinus Torvalds  * and modify these parameters.
37791da177e4SLinus Torvalds  * All parameters are time values, in milliseconds.  A value of 0, when
37801da177e4SLinus Torvalds  * modifying the parameters, indicates that the current value should not
37811da177e4SLinus Torvalds  * be changed.
37821da177e4SLinus Torvalds  *
37831da177e4SLinus Torvalds  */
37841da177e4SLinus Torvalds static int sctp_getsockopt_rtoinfo(struct sock *sk, int len,
37851da177e4SLinus Torvalds 				char __user *optval,
37861da177e4SLinus Torvalds 				int __user *optlen) {
37871da177e4SLinus Torvalds 	struct sctp_rtoinfo rtoinfo;
37881da177e4SLinus Torvalds 	struct sctp_association *asoc;
37891da177e4SLinus Torvalds 
37901da177e4SLinus Torvalds 	if (len != sizeof (struct sctp_rtoinfo))
37911da177e4SLinus Torvalds 		return -EINVAL;
37921da177e4SLinus Torvalds 
37931da177e4SLinus Torvalds 	if (copy_from_user(&rtoinfo, optval, sizeof (struct sctp_rtoinfo)))
37941da177e4SLinus Torvalds 		return -EFAULT;
37951da177e4SLinus Torvalds 
37961da177e4SLinus Torvalds 	asoc = sctp_id2assoc(sk, rtoinfo.srto_assoc_id);
37971da177e4SLinus Torvalds 
37981da177e4SLinus Torvalds 	if (!asoc && rtoinfo.srto_assoc_id && sctp_style(sk, UDP))
37991da177e4SLinus Torvalds 		return -EINVAL;
38001da177e4SLinus Torvalds 
38011da177e4SLinus Torvalds 	/* Values corresponding to the specific association. */
38021da177e4SLinus Torvalds 	if (asoc) {
38031da177e4SLinus Torvalds 		rtoinfo.srto_initial = jiffies_to_msecs(asoc->rto_initial);
38041da177e4SLinus Torvalds 		rtoinfo.srto_max = jiffies_to_msecs(asoc->rto_max);
38051da177e4SLinus Torvalds 		rtoinfo.srto_min = jiffies_to_msecs(asoc->rto_min);
38061da177e4SLinus Torvalds 	} else {
38071da177e4SLinus Torvalds 		/* Values corresponding to the endpoint. */
38081da177e4SLinus Torvalds 		struct sctp_sock *sp = sctp_sk(sk);
38091da177e4SLinus Torvalds 
38101da177e4SLinus Torvalds 		rtoinfo.srto_initial = sp->rtoinfo.srto_initial;
38111da177e4SLinus Torvalds 		rtoinfo.srto_max = sp->rtoinfo.srto_max;
38121da177e4SLinus Torvalds 		rtoinfo.srto_min = sp->rtoinfo.srto_min;
38131da177e4SLinus Torvalds 	}
38141da177e4SLinus Torvalds 
38151da177e4SLinus Torvalds 	if (put_user(len, optlen))
38161da177e4SLinus Torvalds 		return -EFAULT;
38171da177e4SLinus Torvalds 
38181da177e4SLinus Torvalds 	if (copy_to_user(optval, &rtoinfo, len))
38191da177e4SLinus Torvalds 		return -EFAULT;
38201da177e4SLinus Torvalds 
38211da177e4SLinus Torvalds 	return 0;
38221da177e4SLinus Torvalds }
38231da177e4SLinus Torvalds 
38241da177e4SLinus Torvalds /*
38251da177e4SLinus Torvalds  *
38261da177e4SLinus Torvalds  * 7.1.2 SCTP_ASSOCINFO
38271da177e4SLinus Torvalds  *
38281da177e4SLinus Torvalds  * This option is used to tune the the maximum retransmission attempts
38291da177e4SLinus Torvalds  * of the association.
38301da177e4SLinus Torvalds  * Returns an error if the new association retransmission value is
38311da177e4SLinus Torvalds  * greater than the sum of the retransmission value  of the peer.
38321da177e4SLinus Torvalds  * See [SCTP] for more information.
38331da177e4SLinus Torvalds  *
38341da177e4SLinus Torvalds  */
38351da177e4SLinus Torvalds static int sctp_getsockopt_associnfo(struct sock *sk, int len,
38361da177e4SLinus Torvalds 				     char __user *optval,
38371da177e4SLinus Torvalds 				     int __user *optlen)
38381da177e4SLinus Torvalds {
38391da177e4SLinus Torvalds 
38401da177e4SLinus Torvalds 	struct sctp_assocparams assocparams;
38411da177e4SLinus Torvalds 	struct sctp_association *asoc;
38421da177e4SLinus Torvalds 	struct list_head *pos;
38431da177e4SLinus Torvalds 	int cnt = 0;
38441da177e4SLinus Torvalds 
38451da177e4SLinus Torvalds 	if (len != sizeof (struct sctp_assocparams))
38461da177e4SLinus Torvalds 		return -EINVAL;
38471da177e4SLinus Torvalds 
38481da177e4SLinus Torvalds 	if (copy_from_user(&assocparams, optval,
38491da177e4SLinus Torvalds 			sizeof (struct sctp_assocparams)))
38501da177e4SLinus Torvalds 		return -EFAULT;
38511da177e4SLinus Torvalds 
38521da177e4SLinus Torvalds 	asoc = sctp_id2assoc(sk, assocparams.sasoc_assoc_id);
38531da177e4SLinus Torvalds 
38541da177e4SLinus Torvalds 	if (!asoc && assocparams.sasoc_assoc_id && sctp_style(sk, UDP))
38551da177e4SLinus Torvalds 		return -EINVAL;
38561da177e4SLinus Torvalds 
38571da177e4SLinus Torvalds 	/* Values correspoinding to the specific association */
385817337216SVladislav Yasevich 	if (asoc) {
38591da177e4SLinus Torvalds 		assocparams.sasoc_asocmaxrxt = asoc->max_retrans;
38601da177e4SLinus Torvalds 		assocparams.sasoc_peer_rwnd = asoc->peer.rwnd;
38611da177e4SLinus Torvalds 		assocparams.sasoc_local_rwnd = asoc->a_rwnd;
38621da177e4SLinus Torvalds 		assocparams.sasoc_cookie_life = (asoc->cookie_life.tv_sec
38631da177e4SLinus Torvalds 						* 1000) +
38641da177e4SLinus Torvalds 						(asoc->cookie_life.tv_usec
38651da177e4SLinus Torvalds 						/ 1000);
38661da177e4SLinus Torvalds 
38671da177e4SLinus Torvalds 		list_for_each(pos, &asoc->peer.transport_addr_list) {
38681da177e4SLinus Torvalds 			cnt ++;
38691da177e4SLinus Torvalds 		}
38701da177e4SLinus Torvalds 
38711da177e4SLinus Torvalds 		assocparams.sasoc_number_peer_destinations = cnt;
38721da177e4SLinus Torvalds 	} else {
38731da177e4SLinus Torvalds 		/* Values corresponding to the endpoint */
38741da177e4SLinus Torvalds 		struct sctp_sock *sp = sctp_sk(sk);
38751da177e4SLinus Torvalds 
38761da177e4SLinus Torvalds 		assocparams.sasoc_asocmaxrxt = sp->assocparams.sasoc_asocmaxrxt;
38771da177e4SLinus Torvalds 		assocparams.sasoc_peer_rwnd = sp->assocparams.sasoc_peer_rwnd;
38781da177e4SLinus Torvalds 		assocparams.sasoc_local_rwnd = sp->assocparams.sasoc_local_rwnd;
38791da177e4SLinus Torvalds 		assocparams.sasoc_cookie_life =
38801da177e4SLinus Torvalds 					sp->assocparams.sasoc_cookie_life;
38811da177e4SLinus Torvalds 		assocparams.sasoc_number_peer_destinations =
38821da177e4SLinus Torvalds 					sp->assocparams.
38831da177e4SLinus Torvalds 					sasoc_number_peer_destinations;
38841da177e4SLinus Torvalds 	}
38851da177e4SLinus Torvalds 
38861da177e4SLinus Torvalds 	if (put_user(len, optlen))
38871da177e4SLinus Torvalds 		return -EFAULT;
38881da177e4SLinus Torvalds 
38891da177e4SLinus Torvalds 	if (copy_to_user(optval, &assocparams, len))
38901da177e4SLinus Torvalds 		return -EFAULT;
38911da177e4SLinus Torvalds 
38921da177e4SLinus Torvalds 	return 0;
38931da177e4SLinus Torvalds }
38941da177e4SLinus Torvalds 
38951da177e4SLinus Torvalds /*
38961da177e4SLinus Torvalds  * 7.1.16 Set/clear IPv4 mapped addresses (SCTP_I_WANT_MAPPED_V4_ADDR)
38971da177e4SLinus Torvalds  *
38981da177e4SLinus Torvalds  * This socket option is a boolean flag which turns on or off mapped V4
38991da177e4SLinus Torvalds  * addresses.  If this option is turned on and the socket is type
39001da177e4SLinus Torvalds  * PF_INET6, then IPv4 addresses will be mapped to V6 representation.
39011da177e4SLinus Torvalds  * If this option is turned off, then no mapping will be done of V4
39021da177e4SLinus Torvalds  * addresses and a user will receive both PF_INET6 and PF_INET type
39031da177e4SLinus Torvalds  * addresses on the socket.
39041da177e4SLinus Torvalds  */
39051da177e4SLinus Torvalds static int sctp_getsockopt_mappedv4(struct sock *sk, int len,
39061da177e4SLinus Torvalds 				    char __user *optval, int __user *optlen)
39071da177e4SLinus Torvalds {
39081da177e4SLinus Torvalds 	int val;
39091da177e4SLinus Torvalds 	struct sctp_sock *sp = sctp_sk(sk);
39101da177e4SLinus Torvalds 
39111da177e4SLinus Torvalds 	if (len < sizeof(int))
39121da177e4SLinus Torvalds 		return -EINVAL;
39131da177e4SLinus Torvalds 
39141da177e4SLinus Torvalds 	len = sizeof(int);
39151da177e4SLinus Torvalds 	val = sp->v4mapped;
39161da177e4SLinus Torvalds 	if (put_user(len, optlen))
39171da177e4SLinus Torvalds 		return -EFAULT;
39181da177e4SLinus Torvalds 	if (copy_to_user(optval, &val, len))
39191da177e4SLinus Torvalds 		return -EFAULT;
39201da177e4SLinus Torvalds 
39211da177e4SLinus Torvalds 	return 0;
39221da177e4SLinus Torvalds }
39231da177e4SLinus Torvalds 
39241da177e4SLinus Torvalds /*
39251da177e4SLinus Torvalds  * 7.1.17 Set the maximum fragrmentation size (SCTP_MAXSEG)
39261da177e4SLinus Torvalds  *
39271da177e4SLinus Torvalds  * This socket option specifies the maximum size to put in any outgoing
39281da177e4SLinus Torvalds  * SCTP chunk.  If a message is larger than this size it will be
39291da177e4SLinus Torvalds  * fragmented by SCTP into the specified size.  Note that the underlying
39301da177e4SLinus Torvalds  * SCTP implementation may fragment into smaller sized chunks when the
39311da177e4SLinus Torvalds  * PMTU of the underlying association is smaller than the value set by
39321da177e4SLinus Torvalds  * the user.
39331da177e4SLinus Torvalds  */
39341da177e4SLinus Torvalds static int sctp_getsockopt_maxseg(struct sock *sk, int len,
39351da177e4SLinus Torvalds 				  char __user *optval, int __user *optlen)
39361da177e4SLinus Torvalds {
39371da177e4SLinus Torvalds 	int val;
39381da177e4SLinus Torvalds 
39391da177e4SLinus Torvalds 	if (len < sizeof(int))
39401da177e4SLinus Torvalds 		return -EINVAL;
39411da177e4SLinus Torvalds 
39421da177e4SLinus Torvalds 	len = sizeof(int);
39431da177e4SLinus Torvalds 
39441da177e4SLinus Torvalds 	val = sctp_sk(sk)->user_frag;
39451da177e4SLinus Torvalds 	if (put_user(len, optlen))
39461da177e4SLinus Torvalds 		return -EFAULT;
39471da177e4SLinus Torvalds 	if (copy_to_user(optval, &val, len))
39481da177e4SLinus Torvalds 		return -EFAULT;
39491da177e4SLinus Torvalds 
39501da177e4SLinus Torvalds 	return 0;
39511da177e4SLinus Torvalds }
39521da177e4SLinus Torvalds 
39531da177e4SLinus Torvalds SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname,
39541da177e4SLinus Torvalds 				char __user *optval, int __user *optlen)
39551da177e4SLinus Torvalds {
39561da177e4SLinus Torvalds 	int retval = 0;
39571da177e4SLinus Torvalds 	int len;
39581da177e4SLinus Torvalds 
39593f7a87d2SFrank Filz 	SCTP_DEBUG_PRINTK("sctp_getsockopt(sk: %p... optname: %d)\n",
39603f7a87d2SFrank Filz 			  sk, optname);
39611da177e4SLinus Torvalds 
39621da177e4SLinus Torvalds 	/* I can hardly begin to describe how wrong this is.  This is
39631da177e4SLinus Torvalds 	 * so broken as to be worse than useless.  The API draft
39641da177e4SLinus Torvalds 	 * REALLY is NOT helpful here...  I am not convinced that the
39651da177e4SLinus Torvalds 	 * semantics of getsockopt() with a level OTHER THAN SOL_SCTP
39661da177e4SLinus Torvalds 	 * are at all well-founded.
39671da177e4SLinus Torvalds 	 */
39681da177e4SLinus Torvalds 	if (level != SOL_SCTP) {
39691da177e4SLinus Torvalds 		struct sctp_af *af = sctp_sk(sk)->pf->af;
39701da177e4SLinus Torvalds 
39711da177e4SLinus Torvalds 		retval = af->getsockopt(sk, level, optname, optval, optlen);
39721da177e4SLinus Torvalds 		return retval;
39731da177e4SLinus Torvalds 	}
39741da177e4SLinus Torvalds 
39751da177e4SLinus Torvalds 	if (get_user(len, optlen))
39761da177e4SLinus Torvalds 		return -EFAULT;
39771da177e4SLinus Torvalds 
39781da177e4SLinus Torvalds 	sctp_lock_sock(sk);
39791da177e4SLinus Torvalds 
39801da177e4SLinus Torvalds 	switch (optname) {
39811da177e4SLinus Torvalds 	case SCTP_STATUS:
39821da177e4SLinus Torvalds 		retval = sctp_getsockopt_sctp_status(sk, len, optval, optlen);
39831da177e4SLinus Torvalds 		break;
39841da177e4SLinus Torvalds 	case SCTP_DISABLE_FRAGMENTS:
39851da177e4SLinus Torvalds 		retval = sctp_getsockopt_disable_fragments(sk, len, optval,
39861da177e4SLinus Torvalds 							   optlen);
39871da177e4SLinus Torvalds 		break;
39881da177e4SLinus Torvalds 	case SCTP_EVENTS:
39891da177e4SLinus Torvalds 		retval = sctp_getsockopt_events(sk, len, optval, optlen);
39901da177e4SLinus Torvalds 		break;
39911da177e4SLinus Torvalds 	case SCTP_AUTOCLOSE:
39921da177e4SLinus Torvalds 		retval = sctp_getsockopt_autoclose(sk, len, optval, optlen);
39931da177e4SLinus Torvalds 		break;
39941da177e4SLinus Torvalds 	case SCTP_SOCKOPT_PEELOFF:
39951da177e4SLinus Torvalds 		retval = sctp_getsockopt_peeloff(sk, len, optval, optlen);
39961da177e4SLinus Torvalds 		break;
39971da177e4SLinus Torvalds 	case SCTP_PEER_ADDR_PARAMS:
39981da177e4SLinus Torvalds 		retval = sctp_getsockopt_peer_addr_params(sk, len, optval,
39991da177e4SLinus Torvalds 							  optlen);
40001da177e4SLinus Torvalds 		break;
40011da177e4SLinus Torvalds 	case SCTP_INITMSG:
40021da177e4SLinus Torvalds 		retval = sctp_getsockopt_initmsg(sk, len, optval, optlen);
40031da177e4SLinus Torvalds 		break;
40045fe467eeSIvan Skytte Jørgensen 	case SCTP_GET_PEER_ADDRS_NUM_OLD:
40055fe467eeSIvan Skytte Jørgensen 		retval = sctp_getsockopt_peer_addrs_num_old(sk, len, optval,
40061da177e4SLinus Torvalds 							    optlen);
40071da177e4SLinus Torvalds 		break;
40085fe467eeSIvan Skytte Jørgensen 	case SCTP_GET_LOCAL_ADDRS_NUM_OLD:
40095fe467eeSIvan Skytte Jørgensen 		retval = sctp_getsockopt_local_addrs_num_old(sk, len, optval,
40105fe467eeSIvan Skytte Jørgensen 							     optlen);
40115fe467eeSIvan Skytte Jørgensen 		break;
40125fe467eeSIvan Skytte Jørgensen 	case SCTP_GET_PEER_ADDRS_OLD:
40135fe467eeSIvan Skytte Jørgensen 		retval = sctp_getsockopt_peer_addrs_old(sk, len, optval,
40145fe467eeSIvan Skytte Jørgensen 							optlen);
40155fe467eeSIvan Skytte Jørgensen 		break;
40165fe467eeSIvan Skytte Jørgensen 	case SCTP_GET_LOCAL_ADDRS_OLD:
40175fe467eeSIvan Skytte Jørgensen 		retval = sctp_getsockopt_local_addrs_old(sk, len, optval,
40181da177e4SLinus Torvalds 							 optlen);
40191da177e4SLinus Torvalds 		break;
40201da177e4SLinus Torvalds 	case SCTP_GET_PEER_ADDRS:
40211da177e4SLinus Torvalds 		retval = sctp_getsockopt_peer_addrs(sk, len, optval,
40221da177e4SLinus Torvalds 						    optlen);
40231da177e4SLinus Torvalds 		break;
40241da177e4SLinus Torvalds 	case SCTP_GET_LOCAL_ADDRS:
40251da177e4SLinus Torvalds 		retval = sctp_getsockopt_local_addrs(sk, len, optval,
40261da177e4SLinus Torvalds 						     optlen);
40271da177e4SLinus Torvalds 		break;
40281da177e4SLinus Torvalds 	case SCTP_DEFAULT_SEND_PARAM:
40291da177e4SLinus Torvalds 		retval = sctp_getsockopt_default_send_param(sk, len,
40301da177e4SLinus Torvalds 							    optval, optlen);
40311da177e4SLinus Torvalds 		break;
40321da177e4SLinus Torvalds 	case SCTP_PRIMARY_ADDR:
40331da177e4SLinus Torvalds 		retval = sctp_getsockopt_primary_addr(sk, len, optval, optlen);
40341da177e4SLinus Torvalds 		break;
40351da177e4SLinus Torvalds 	case SCTP_NODELAY:
40361da177e4SLinus Torvalds 		retval = sctp_getsockopt_nodelay(sk, len, optval, optlen);
40371da177e4SLinus Torvalds 		break;
40381da177e4SLinus Torvalds 	case SCTP_RTOINFO:
40391da177e4SLinus Torvalds 		retval = sctp_getsockopt_rtoinfo(sk, len, optval, optlen);
40401da177e4SLinus Torvalds 		break;
40411da177e4SLinus Torvalds 	case SCTP_ASSOCINFO:
40421da177e4SLinus Torvalds 		retval = sctp_getsockopt_associnfo(sk, len, optval, optlen);
40431da177e4SLinus Torvalds 		break;
40441da177e4SLinus Torvalds 	case SCTP_I_WANT_MAPPED_V4_ADDR:
40451da177e4SLinus Torvalds 		retval = sctp_getsockopt_mappedv4(sk, len, optval, optlen);
40461da177e4SLinus Torvalds 		break;
40471da177e4SLinus Torvalds 	case SCTP_MAXSEG:
40481da177e4SLinus Torvalds 		retval = sctp_getsockopt_maxseg(sk, len, optval, optlen);
40491da177e4SLinus Torvalds 		break;
40501da177e4SLinus Torvalds 	case SCTP_GET_PEER_ADDR_INFO:
40511da177e4SLinus Torvalds 		retval = sctp_getsockopt_peer_addr_info(sk, len, optval,
40521da177e4SLinus Torvalds 							optlen);
40531da177e4SLinus Torvalds 		break;
40541da177e4SLinus Torvalds 	case SCTP_ADAPTION_LAYER:
40551da177e4SLinus Torvalds 		retval = sctp_getsockopt_adaption_layer(sk, len, optval,
40561da177e4SLinus Torvalds 							optlen);
40571da177e4SLinus Torvalds 		break;
40581da177e4SLinus Torvalds 	default:
40591da177e4SLinus Torvalds 		retval = -ENOPROTOOPT;
40601da177e4SLinus Torvalds 		break;
40611da177e4SLinus Torvalds 	};
40621da177e4SLinus Torvalds 
40631da177e4SLinus Torvalds 	sctp_release_sock(sk);
40641da177e4SLinus Torvalds 	return retval;
40651da177e4SLinus Torvalds }
40661da177e4SLinus Torvalds 
40671da177e4SLinus Torvalds static void sctp_hash(struct sock *sk)
40681da177e4SLinus Torvalds {
40691da177e4SLinus Torvalds 	/* STUB */
40701da177e4SLinus Torvalds }
40711da177e4SLinus Torvalds 
40721da177e4SLinus Torvalds static void sctp_unhash(struct sock *sk)
40731da177e4SLinus Torvalds {
40741da177e4SLinus Torvalds 	/* STUB */
40751da177e4SLinus Torvalds }
40761da177e4SLinus Torvalds 
40771da177e4SLinus Torvalds /* Check if port is acceptable.  Possibly find first available port.
40781da177e4SLinus Torvalds  *
40791da177e4SLinus Torvalds  * The port hash table (contained in the 'global' SCTP protocol storage
40801da177e4SLinus Torvalds  * returned by struct sctp_protocol *sctp_get_protocol()). The hash
40811da177e4SLinus Torvalds  * table is an array of 4096 lists (sctp_bind_hashbucket). Each
40821da177e4SLinus Torvalds  * list (the list number is the port number hashed out, so as you
40831da177e4SLinus Torvalds  * would expect from a hash function, all the ports in a given list have
40841da177e4SLinus Torvalds  * such a number that hashes out to the same list number; you were
40851da177e4SLinus Torvalds  * expecting that, right?); so each list has a set of ports, with a
40861da177e4SLinus Torvalds  * link to the socket (struct sock) that uses it, the port number and
40871da177e4SLinus Torvalds  * a fastreuse flag (FIXME: NPI ipg).
40881da177e4SLinus Torvalds  */
40891da177e4SLinus Torvalds static struct sctp_bind_bucket *sctp_bucket_create(
40901da177e4SLinus Torvalds 	struct sctp_bind_hashbucket *head, unsigned short snum);
40911da177e4SLinus Torvalds 
40921da177e4SLinus Torvalds static long sctp_get_port_local(struct sock *sk, union sctp_addr *addr)
40931da177e4SLinus Torvalds {
40941da177e4SLinus Torvalds 	struct sctp_bind_hashbucket *head; /* hash list */
40951da177e4SLinus Torvalds 	struct sctp_bind_bucket *pp; /* hash list port iterator */
40961da177e4SLinus Torvalds 	unsigned short snum;
40971da177e4SLinus Torvalds 	int ret;
40981da177e4SLinus Torvalds 
40991da177e4SLinus Torvalds 	/* NOTE:  Remember to put this back to net order. */
41001da177e4SLinus Torvalds 	addr->v4.sin_port = ntohs(addr->v4.sin_port);
41011da177e4SLinus Torvalds 	snum = addr->v4.sin_port;
41021da177e4SLinus Torvalds 
41031da177e4SLinus Torvalds 	SCTP_DEBUG_PRINTK("sctp_get_port() begins, snum=%d\n", snum);
41041da177e4SLinus Torvalds 	sctp_local_bh_disable();
41051da177e4SLinus Torvalds 
41061da177e4SLinus Torvalds 	if (snum == 0) {
41071da177e4SLinus Torvalds 		/* Search for an available port.
41081da177e4SLinus Torvalds 		 *
41091da177e4SLinus Torvalds 		 * 'sctp_port_rover' was the last port assigned, so
41101da177e4SLinus Torvalds 		 * we start to search from 'sctp_port_rover +
41111da177e4SLinus Torvalds 		 * 1'. What we do is first check if port 'rover' is
41121da177e4SLinus Torvalds 		 * already in the hash table; if not, we use that; if
41131da177e4SLinus Torvalds 		 * it is, we try next.
41141da177e4SLinus Torvalds 		 */
41151da177e4SLinus Torvalds 		int low = sysctl_local_port_range[0];
41161da177e4SLinus Torvalds 		int high = sysctl_local_port_range[1];
41171da177e4SLinus Torvalds 		int remaining = (high - low) + 1;
41181da177e4SLinus Torvalds 		int rover;
41191da177e4SLinus Torvalds 		int index;
41201da177e4SLinus Torvalds 
41211da177e4SLinus Torvalds 		sctp_spin_lock(&sctp_port_alloc_lock);
41221da177e4SLinus Torvalds 		rover = sctp_port_rover;
41231da177e4SLinus Torvalds 		do {
41241da177e4SLinus Torvalds 			rover++;
41251da177e4SLinus Torvalds 			if ((rover < low) || (rover > high))
41261da177e4SLinus Torvalds 				rover = low;
41271da177e4SLinus Torvalds 			index = sctp_phashfn(rover);
41281da177e4SLinus Torvalds 			head = &sctp_port_hashtable[index];
41291da177e4SLinus Torvalds 			sctp_spin_lock(&head->lock);
41301da177e4SLinus Torvalds 			for (pp = head->chain; pp; pp = pp->next)
41311da177e4SLinus Torvalds 				if (pp->port == rover)
41321da177e4SLinus Torvalds 					goto next;
41331da177e4SLinus Torvalds 			break;
41341da177e4SLinus Torvalds 		next:
41351da177e4SLinus Torvalds 			sctp_spin_unlock(&head->lock);
41361da177e4SLinus Torvalds 		} while (--remaining > 0);
41371da177e4SLinus Torvalds 		sctp_port_rover = rover;
41381da177e4SLinus Torvalds 		sctp_spin_unlock(&sctp_port_alloc_lock);
41391da177e4SLinus Torvalds 
41401da177e4SLinus Torvalds 		/* Exhausted local port range during search? */
41411da177e4SLinus Torvalds 		ret = 1;
41421da177e4SLinus Torvalds 		if (remaining <= 0)
41431da177e4SLinus Torvalds 			goto fail;
41441da177e4SLinus Torvalds 
41451da177e4SLinus Torvalds 		/* OK, here is the one we will use.  HEAD (the port
41461da177e4SLinus Torvalds 		 * hash table list entry) is non-NULL and we hold it's
41471da177e4SLinus Torvalds 		 * mutex.
41481da177e4SLinus Torvalds 		 */
41491da177e4SLinus Torvalds 		snum = rover;
41501da177e4SLinus Torvalds 	} else {
41511da177e4SLinus Torvalds 		/* We are given an specific port number; we verify
41521da177e4SLinus Torvalds 		 * that it is not being used. If it is used, we will
41531da177e4SLinus Torvalds 		 * exahust the search in the hash list corresponding
41541da177e4SLinus Torvalds 		 * to the port number (snum) - we detect that with the
41551da177e4SLinus Torvalds 		 * port iterator, pp being NULL.
41561da177e4SLinus Torvalds 		 */
41571da177e4SLinus Torvalds 		head = &sctp_port_hashtable[sctp_phashfn(snum)];
41581da177e4SLinus Torvalds 		sctp_spin_lock(&head->lock);
41591da177e4SLinus Torvalds 		for (pp = head->chain; pp; pp = pp->next) {
41601da177e4SLinus Torvalds 			if (pp->port == snum)
41611da177e4SLinus Torvalds 				goto pp_found;
41621da177e4SLinus Torvalds 		}
41631da177e4SLinus Torvalds 	}
41641da177e4SLinus Torvalds 	pp = NULL;
41651da177e4SLinus Torvalds 	goto pp_not_found;
41661da177e4SLinus Torvalds pp_found:
41671da177e4SLinus Torvalds 	if (!hlist_empty(&pp->owner)) {
41681da177e4SLinus Torvalds 		/* We had a port hash table hit - there is an
41691da177e4SLinus Torvalds 		 * available port (pp != NULL) and it is being
41701da177e4SLinus Torvalds 		 * used by other socket (pp->owner not empty); that other
41711da177e4SLinus Torvalds 		 * socket is going to be sk2.
41721da177e4SLinus Torvalds 		 */
41731da177e4SLinus Torvalds 		int reuse = sk->sk_reuse;
41741da177e4SLinus Torvalds 		struct sock *sk2;
41751da177e4SLinus Torvalds 		struct hlist_node *node;
41761da177e4SLinus Torvalds 
41771da177e4SLinus Torvalds 		SCTP_DEBUG_PRINTK("sctp_get_port() found a possible match\n");
41781da177e4SLinus Torvalds 		if (pp->fastreuse && sk->sk_reuse)
41791da177e4SLinus Torvalds 			goto success;
41801da177e4SLinus Torvalds 
41811da177e4SLinus Torvalds 		/* Run through the list of sockets bound to the port
41821da177e4SLinus Torvalds 		 * (pp->port) [via the pointers bind_next and
41831da177e4SLinus Torvalds 		 * bind_pprev in the struct sock *sk2 (pp->sk)]. On each one,
41841da177e4SLinus Torvalds 		 * we get the endpoint they describe and run through
41851da177e4SLinus Torvalds 		 * the endpoint's list of IP (v4 or v6) addresses,
41861da177e4SLinus Torvalds 		 * comparing each of the addresses with the address of
41871da177e4SLinus Torvalds 		 * the socket sk. If we find a match, then that means
41881da177e4SLinus Torvalds 		 * that this port/socket (sk) combination are already
41891da177e4SLinus Torvalds 		 * in an endpoint.
41901da177e4SLinus Torvalds 		 */
41911da177e4SLinus Torvalds 		sk_for_each_bound(sk2, node, &pp->owner) {
41921da177e4SLinus Torvalds 			struct sctp_endpoint *ep2;
41931da177e4SLinus Torvalds 			ep2 = sctp_sk(sk2)->ep;
41941da177e4SLinus Torvalds 
41951da177e4SLinus Torvalds 			if (reuse && sk2->sk_reuse)
41961da177e4SLinus Torvalds 				continue;
41971da177e4SLinus Torvalds 
41981da177e4SLinus Torvalds 			if (sctp_bind_addr_match(&ep2->base.bind_addr, addr,
41991da177e4SLinus Torvalds 						 sctp_sk(sk))) {
42001da177e4SLinus Torvalds 				ret = (long)sk2;
42011da177e4SLinus Torvalds 				goto fail_unlock;
42021da177e4SLinus Torvalds 			}
42031da177e4SLinus Torvalds 		}
42041da177e4SLinus Torvalds 		SCTP_DEBUG_PRINTK("sctp_get_port(): Found a match\n");
42051da177e4SLinus Torvalds 	}
42061da177e4SLinus Torvalds pp_not_found:
42071da177e4SLinus Torvalds 	/* If there was a hash table miss, create a new port.  */
42081da177e4SLinus Torvalds 	ret = 1;
42091da177e4SLinus Torvalds 	if (!pp && !(pp = sctp_bucket_create(head, snum)))
42101da177e4SLinus Torvalds 		goto fail_unlock;
42111da177e4SLinus Torvalds 
42121da177e4SLinus Torvalds 	/* In either case (hit or miss), make sure fastreuse is 1 only
42131da177e4SLinus Torvalds 	 * if sk->sk_reuse is too (that is, if the caller requested
42141da177e4SLinus Torvalds 	 * SO_REUSEADDR on this socket -sk-).
42151da177e4SLinus Torvalds 	 */
42161da177e4SLinus Torvalds 	if (hlist_empty(&pp->owner))
42171da177e4SLinus Torvalds 		pp->fastreuse = sk->sk_reuse ? 1 : 0;
42181da177e4SLinus Torvalds 	else if (pp->fastreuse && !sk->sk_reuse)
42191da177e4SLinus Torvalds 		pp->fastreuse = 0;
42201da177e4SLinus Torvalds 
42211da177e4SLinus Torvalds 	/* We are set, so fill up all the data in the hash table
42221da177e4SLinus Torvalds 	 * entry, tie the socket list information with the rest of the
42231da177e4SLinus Torvalds 	 * sockets FIXME: Blurry, NPI (ipg).
42241da177e4SLinus Torvalds 	 */
42251da177e4SLinus Torvalds success:
42261da177e4SLinus Torvalds 	inet_sk(sk)->num = snum;
42271da177e4SLinus Torvalds 	if (!sctp_sk(sk)->bind_hash) {
42281da177e4SLinus Torvalds 		sk_add_bind_node(sk, &pp->owner);
42291da177e4SLinus Torvalds 		sctp_sk(sk)->bind_hash = pp;
42301da177e4SLinus Torvalds 	}
42311da177e4SLinus Torvalds 	ret = 0;
42321da177e4SLinus Torvalds 
42331da177e4SLinus Torvalds fail_unlock:
42341da177e4SLinus Torvalds 	sctp_spin_unlock(&head->lock);
42351da177e4SLinus Torvalds 
42361da177e4SLinus Torvalds fail:
42371da177e4SLinus Torvalds 	sctp_local_bh_enable();
42381da177e4SLinus Torvalds 	addr->v4.sin_port = htons(addr->v4.sin_port);
42391da177e4SLinus Torvalds 	return ret;
42401da177e4SLinus Torvalds }
42411da177e4SLinus Torvalds 
42421da177e4SLinus Torvalds /* Assign a 'snum' port to the socket.  If snum == 0, an ephemeral
42431da177e4SLinus Torvalds  * port is requested.
42441da177e4SLinus Torvalds  */
42451da177e4SLinus Torvalds static int sctp_get_port(struct sock *sk, unsigned short snum)
42461da177e4SLinus Torvalds {
42471da177e4SLinus Torvalds 	long ret;
42481da177e4SLinus Torvalds 	union sctp_addr addr;
42491da177e4SLinus Torvalds 	struct sctp_af *af = sctp_sk(sk)->pf->af;
42501da177e4SLinus Torvalds 
42511da177e4SLinus Torvalds 	/* Set up a dummy address struct from the sk. */
42521da177e4SLinus Torvalds 	af->from_sk(&addr, sk);
42531da177e4SLinus Torvalds 	addr.v4.sin_port = htons(snum);
42541da177e4SLinus Torvalds 
42551da177e4SLinus Torvalds 	/* Note: sk->sk_num gets filled in if ephemeral port request. */
42561da177e4SLinus Torvalds 	ret = sctp_get_port_local(sk, &addr);
42571da177e4SLinus Torvalds 
42581da177e4SLinus Torvalds 	return (ret ? 1 : 0);
42591da177e4SLinus Torvalds }
42601da177e4SLinus Torvalds 
42611da177e4SLinus Torvalds /*
42621da177e4SLinus Torvalds  * 3.1.3 listen() - UDP Style Syntax
42631da177e4SLinus Torvalds  *
42641da177e4SLinus Torvalds  *   By default, new associations are not accepted for UDP style sockets.
42651da177e4SLinus Torvalds  *   An application uses listen() to mark a socket as being able to
42661da177e4SLinus Torvalds  *   accept new associations.
42671da177e4SLinus Torvalds  */
42681da177e4SLinus Torvalds SCTP_STATIC int sctp_seqpacket_listen(struct sock *sk, int backlog)
42691da177e4SLinus Torvalds {
42701da177e4SLinus Torvalds 	struct sctp_sock *sp = sctp_sk(sk);
42711da177e4SLinus Torvalds 	struct sctp_endpoint *ep = sp->ep;
42721da177e4SLinus Torvalds 
42731da177e4SLinus Torvalds 	/* Only UDP style sockets that are not peeled off are allowed to
42741da177e4SLinus Torvalds 	 * listen().
42751da177e4SLinus Torvalds 	 */
42761da177e4SLinus Torvalds 	if (!sctp_style(sk, UDP))
42771da177e4SLinus Torvalds 		return -EINVAL;
42781da177e4SLinus Torvalds 
42791da177e4SLinus Torvalds 	/* If backlog is zero, disable listening. */
42801da177e4SLinus Torvalds 	if (!backlog) {
42811da177e4SLinus Torvalds 		if (sctp_sstate(sk, CLOSED))
42821da177e4SLinus Torvalds 			return 0;
42831da177e4SLinus Torvalds 
42841da177e4SLinus Torvalds 		sctp_unhash_endpoint(ep);
42851da177e4SLinus Torvalds 		sk->sk_state = SCTP_SS_CLOSED;
42861da177e4SLinus Torvalds 	}
42871da177e4SLinus Torvalds 
42881da177e4SLinus Torvalds 	/* Return if we are already listening. */
42891da177e4SLinus Torvalds 	if (sctp_sstate(sk, LISTENING))
42901da177e4SLinus Torvalds 		return 0;
42911da177e4SLinus Torvalds 
42921da177e4SLinus Torvalds 	/*
42931da177e4SLinus Torvalds 	 * If a bind() or sctp_bindx() is not called prior to a listen()
42941da177e4SLinus Torvalds 	 * call that allows new associations to be accepted, the system
42951da177e4SLinus Torvalds 	 * picks an ephemeral port and will choose an address set equivalent
42961da177e4SLinus Torvalds 	 * to binding with a wildcard address.
42971da177e4SLinus Torvalds 	 *
42981da177e4SLinus Torvalds 	 * This is not currently spelled out in the SCTP sockets
42991da177e4SLinus Torvalds 	 * extensions draft, but follows the practice as seen in TCP
43001da177e4SLinus Torvalds 	 * sockets.
43011da177e4SLinus Torvalds 	 */
43021da177e4SLinus Torvalds 	if (!ep->base.bind_addr.port) {
43031da177e4SLinus Torvalds 		if (sctp_autobind(sk))
43041da177e4SLinus Torvalds 			return -EAGAIN;
43051da177e4SLinus Torvalds 	}
43061da177e4SLinus Torvalds 	sk->sk_state = SCTP_SS_LISTENING;
43071da177e4SLinus Torvalds 	sctp_hash_endpoint(ep);
43081da177e4SLinus Torvalds 	return 0;
43091da177e4SLinus Torvalds }
43101da177e4SLinus Torvalds 
43111da177e4SLinus Torvalds /*
43121da177e4SLinus Torvalds  * 4.1.3 listen() - TCP Style Syntax
43131da177e4SLinus Torvalds  *
43141da177e4SLinus Torvalds  *   Applications uses listen() to ready the SCTP endpoint for accepting
43151da177e4SLinus Torvalds  *   inbound associations.
43161da177e4SLinus Torvalds  */
43171da177e4SLinus Torvalds SCTP_STATIC int sctp_stream_listen(struct sock *sk, int backlog)
43181da177e4SLinus Torvalds {
43191da177e4SLinus Torvalds 	struct sctp_sock *sp = sctp_sk(sk);
43201da177e4SLinus Torvalds 	struct sctp_endpoint *ep = sp->ep;
43211da177e4SLinus Torvalds 
43221da177e4SLinus Torvalds 	/* If backlog is zero, disable listening. */
43231da177e4SLinus Torvalds 	if (!backlog) {
43241da177e4SLinus Torvalds 		if (sctp_sstate(sk, CLOSED))
43251da177e4SLinus Torvalds 			return 0;
43261da177e4SLinus Torvalds 
43271da177e4SLinus Torvalds 		sctp_unhash_endpoint(ep);
43281da177e4SLinus Torvalds 		sk->sk_state = SCTP_SS_CLOSED;
43291da177e4SLinus Torvalds 	}
43301da177e4SLinus Torvalds 
43311da177e4SLinus Torvalds 	if (sctp_sstate(sk, LISTENING))
43321da177e4SLinus Torvalds 		return 0;
43331da177e4SLinus Torvalds 
43341da177e4SLinus Torvalds 	/*
43351da177e4SLinus Torvalds 	 * If a bind() or sctp_bindx() is not called prior to a listen()
43361da177e4SLinus Torvalds 	 * call that allows new associations to be accepted, the system
43371da177e4SLinus Torvalds 	 * picks an ephemeral port and will choose an address set equivalent
43381da177e4SLinus Torvalds 	 * to binding with a wildcard address.
43391da177e4SLinus Torvalds 	 *
43401da177e4SLinus Torvalds 	 * This is not currently spelled out in the SCTP sockets
43411da177e4SLinus Torvalds 	 * extensions draft, but follows the practice as seen in TCP
43421da177e4SLinus Torvalds 	 * sockets.
43431da177e4SLinus Torvalds 	 */
43441da177e4SLinus Torvalds 	if (!ep->base.bind_addr.port) {
43451da177e4SLinus Torvalds 		if (sctp_autobind(sk))
43461da177e4SLinus Torvalds 			return -EAGAIN;
43471da177e4SLinus Torvalds 	}
43481da177e4SLinus Torvalds 	sk->sk_state = SCTP_SS_LISTENING;
43491da177e4SLinus Torvalds 	sk->sk_max_ack_backlog = backlog;
43501da177e4SLinus Torvalds 	sctp_hash_endpoint(ep);
43511da177e4SLinus Torvalds 	return 0;
43521da177e4SLinus Torvalds }
43531da177e4SLinus Torvalds 
43541da177e4SLinus Torvalds /*
43551da177e4SLinus Torvalds  *  Move a socket to LISTENING state.
43561da177e4SLinus Torvalds  */
43571da177e4SLinus Torvalds int sctp_inet_listen(struct socket *sock, int backlog)
43581da177e4SLinus Torvalds {
43591da177e4SLinus Torvalds 	struct sock *sk = sock->sk;
43601da177e4SLinus Torvalds 	struct crypto_tfm *tfm=NULL;
43611da177e4SLinus Torvalds 	int err = -EINVAL;
43621da177e4SLinus Torvalds 
43631da177e4SLinus Torvalds 	if (unlikely(backlog < 0))
43641da177e4SLinus Torvalds 		goto out;
43651da177e4SLinus Torvalds 
43661da177e4SLinus Torvalds 	sctp_lock_sock(sk);
43671da177e4SLinus Torvalds 
43681da177e4SLinus Torvalds 	if (sock->state != SS_UNCONNECTED)
43691da177e4SLinus Torvalds 		goto out;
43701da177e4SLinus Torvalds 
43711da177e4SLinus Torvalds 	/* Allocate HMAC for generating cookie. */
43721da177e4SLinus Torvalds 	if (sctp_hmac_alg) {
43731da177e4SLinus Torvalds 		tfm = sctp_crypto_alloc_tfm(sctp_hmac_alg, 0);
43741da177e4SLinus Torvalds 		if (!tfm) {
43751da177e4SLinus Torvalds 			err = -ENOSYS;
43761da177e4SLinus Torvalds 			goto out;
43771da177e4SLinus Torvalds 		}
43781da177e4SLinus Torvalds 	}
43791da177e4SLinus Torvalds 
43801da177e4SLinus Torvalds 	switch (sock->type) {
43811da177e4SLinus Torvalds 	case SOCK_SEQPACKET:
43821da177e4SLinus Torvalds 		err = sctp_seqpacket_listen(sk, backlog);
43831da177e4SLinus Torvalds 		break;
43841da177e4SLinus Torvalds 	case SOCK_STREAM:
43851da177e4SLinus Torvalds 		err = sctp_stream_listen(sk, backlog);
43861da177e4SLinus Torvalds 		break;
43871da177e4SLinus Torvalds 	default:
43881da177e4SLinus Torvalds 		break;
43891da177e4SLinus Torvalds 	};
43901da177e4SLinus Torvalds 	if (err)
43911da177e4SLinus Torvalds 		goto cleanup;
43921da177e4SLinus Torvalds 
43931da177e4SLinus Torvalds 	/* Store away the transform reference. */
43941da177e4SLinus Torvalds 	sctp_sk(sk)->hmac = tfm;
43951da177e4SLinus Torvalds out:
43961da177e4SLinus Torvalds 	sctp_release_sock(sk);
43971da177e4SLinus Torvalds 	return err;
43981da177e4SLinus Torvalds cleanup:
43991da177e4SLinus Torvalds 	sctp_crypto_free_tfm(tfm);
44001da177e4SLinus Torvalds 	goto out;
44011da177e4SLinus Torvalds }
44021da177e4SLinus Torvalds 
44031da177e4SLinus Torvalds /*
44041da177e4SLinus Torvalds  * This function is done by modeling the current datagram_poll() and the
44051da177e4SLinus Torvalds  * tcp_poll().  Note that, based on these implementations, we don't
44061da177e4SLinus Torvalds  * lock the socket in this function, even though it seems that,
44071da177e4SLinus Torvalds  * ideally, locking or some other mechanisms can be used to ensure
44081da177e4SLinus Torvalds  * the integrity of the counters (sndbuf and wmem_queued) used
44091da177e4SLinus Torvalds  * in this place.  We assume that we don't need locks either until proven
44101da177e4SLinus Torvalds  * otherwise.
44111da177e4SLinus Torvalds  *
44121da177e4SLinus Torvalds  * Another thing to note is that we include the Async I/O support
44131da177e4SLinus Torvalds  * here, again, by modeling the current TCP/UDP code.  We don't have
44141da177e4SLinus Torvalds  * a good way to test with it yet.
44151da177e4SLinus Torvalds  */
44161da177e4SLinus Torvalds unsigned int sctp_poll(struct file *file, struct socket *sock, poll_table *wait)
44171da177e4SLinus Torvalds {
44181da177e4SLinus Torvalds 	struct sock *sk = sock->sk;
44191da177e4SLinus Torvalds 	struct sctp_sock *sp = sctp_sk(sk);
44201da177e4SLinus Torvalds 	unsigned int mask;
44211da177e4SLinus Torvalds 
44221da177e4SLinus Torvalds 	poll_wait(file, sk->sk_sleep, wait);
44231da177e4SLinus Torvalds 
44241da177e4SLinus Torvalds 	/* A TCP-style listening socket becomes readable when the accept queue
44251da177e4SLinus Torvalds 	 * is not empty.
44261da177e4SLinus Torvalds 	 */
44271da177e4SLinus Torvalds 	if (sctp_style(sk, TCP) && sctp_sstate(sk, LISTENING))
44281da177e4SLinus Torvalds 		return (!list_empty(&sp->ep->asocs)) ?
44291da177e4SLinus Torvalds 		       	(POLLIN | POLLRDNORM) : 0;
44301da177e4SLinus Torvalds 
44311da177e4SLinus Torvalds 	mask = 0;
44321da177e4SLinus Torvalds 
44331da177e4SLinus Torvalds 	/* Is there any exceptional events?  */
44341da177e4SLinus Torvalds 	if (sk->sk_err || !skb_queue_empty(&sk->sk_error_queue))
44351da177e4SLinus Torvalds 		mask |= POLLERR;
44361da177e4SLinus Torvalds 	if (sk->sk_shutdown == SHUTDOWN_MASK)
44371da177e4SLinus Torvalds 		mask |= POLLHUP;
44381da177e4SLinus Torvalds 
44391da177e4SLinus Torvalds 	/* Is it readable?  Reconsider this code with TCP-style support.  */
44401da177e4SLinus Torvalds 	if (!skb_queue_empty(&sk->sk_receive_queue) ||
44411da177e4SLinus Torvalds 	    (sk->sk_shutdown & RCV_SHUTDOWN))
44421da177e4SLinus Torvalds 		mask |= POLLIN | POLLRDNORM;
44431da177e4SLinus Torvalds 
44441da177e4SLinus Torvalds 	/* The association is either gone or not ready.  */
44451da177e4SLinus Torvalds 	if (!sctp_style(sk, UDP) && sctp_sstate(sk, CLOSED))
44461da177e4SLinus Torvalds 		return mask;
44471da177e4SLinus Torvalds 
44481da177e4SLinus Torvalds 	/* Is it writable?  */
44491da177e4SLinus Torvalds 	if (sctp_writeable(sk)) {
44501da177e4SLinus Torvalds 		mask |= POLLOUT | POLLWRNORM;
44511da177e4SLinus Torvalds 	} else {
44521da177e4SLinus Torvalds 		set_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags);
44531da177e4SLinus Torvalds 		/*
44541da177e4SLinus Torvalds 		 * Since the socket is not locked, the buffer
44551da177e4SLinus Torvalds 		 * might be made available after the writeable check and
44561da177e4SLinus Torvalds 		 * before the bit is set.  This could cause a lost I/O
44571da177e4SLinus Torvalds 		 * signal.  tcp_poll() has a race breaker for this race
44581da177e4SLinus Torvalds 		 * condition.  Based on their implementation, we put
44591da177e4SLinus Torvalds 		 * in the following code to cover it as well.
44601da177e4SLinus Torvalds 		 */
44611da177e4SLinus Torvalds 		if (sctp_writeable(sk))
44621da177e4SLinus Torvalds 			mask |= POLLOUT | POLLWRNORM;
44631da177e4SLinus Torvalds 	}
44641da177e4SLinus Torvalds 	return mask;
44651da177e4SLinus Torvalds }
44661da177e4SLinus Torvalds 
44671da177e4SLinus Torvalds /********************************************************************
44681da177e4SLinus Torvalds  * 2nd Level Abstractions
44691da177e4SLinus Torvalds  ********************************************************************/
44701da177e4SLinus Torvalds 
44711da177e4SLinus Torvalds static struct sctp_bind_bucket *sctp_bucket_create(
44721da177e4SLinus Torvalds 	struct sctp_bind_hashbucket *head, unsigned short snum)
44731da177e4SLinus Torvalds {
44741da177e4SLinus Torvalds 	struct sctp_bind_bucket *pp;
44751da177e4SLinus Torvalds 
44761da177e4SLinus Torvalds 	pp = kmem_cache_alloc(sctp_bucket_cachep, SLAB_ATOMIC);
44771da177e4SLinus Torvalds 	SCTP_DBG_OBJCNT_INC(bind_bucket);
44781da177e4SLinus Torvalds 	if (pp) {
44791da177e4SLinus Torvalds 		pp->port = snum;
44801da177e4SLinus Torvalds 		pp->fastreuse = 0;
44811da177e4SLinus Torvalds 		INIT_HLIST_HEAD(&pp->owner);
44821da177e4SLinus Torvalds 		if ((pp->next = head->chain) != NULL)
44831da177e4SLinus Torvalds 			pp->next->pprev = &pp->next;
44841da177e4SLinus Torvalds 		head->chain = pp;
44851da177e4SLinus Torvalds 		pp->pprev = &head->chain;
44861da177e4SLinus Torvalds 	}
44871da177e4SLinus Torvalds 	return pp;
44881da177e4SLinus Torvalds }
44891da177e4SLinus Torvalds 
44901da177e4SLinus Torvalds /* Caller must hold hashbucket lock for this tb with local BH disabled */
44911da177e4SLinus Torvalds static void sctp_bucket_destroy(struct sctp_bind_bucket *pp)
44921da177e4SLinus Torvalds {
44931da177e4SLinus Torvalds 	if (hlist_empty(&pp->owner)) {
44941da177e4SLinus Torvalds 		if (pp->next)
44951da177e4SLinus Torvalds 			pp->next->pprev = pp->pprev;
44961da177e4SLinus Torvalds 		*(pp->pprev) = pp->next;
44971da177e4SLinus Torvalds 		kmem_cache_free(sctp_bucket_cachep, pp);
44981da177e4SLinus Torvalds 		SCTP_DBG_OBJCNT_DEC(bind_bucket);
44991da177e4SLinus Torvalds 	}
45001da177e4SLinus Torvalds }
45011da177e4SLinus Torvalds 
45021da177e4SLinus Torvalds /* Release this socket's reference to a local port.  */
45031da177e4SLinus Torvalds static inline void __sctp_put_port(struct sock *sk)
45041da177e4SLinus Torvalds {
45051da177e4SLinus Torvalds 	struct sctp_bind_hashbucket *head =
45061da177e4SLinus Torvalds 		&sctp_port_hashtable[sctp_phashfn(inet_sk(sk)->num)];
45071da177e4SLinus Torvalds 	struct sctp_bind_bucket *pp;
45081da177e4SLinus Torvalds 
45091da177e4SLinus Torvalds 	sctp_spin_lock(&head->lock);
45101da177e4SLinus Torvalds 	pp = sctp_sk(sk)->bind_hash;
45111da177e4SLinus Torvalds 	__sk_del_bind_node(sk);
45121da177e4SLinus Torvalds 	sctp_sk(sk)->bind_hash = NULL;
45131da177e4SLinus Torvalds 	inet_sk(sk)->num = 0;
45141da177e4SLinus Torvalds 	sctp_bucket_destroy(pp);
45151da177e4SLinus Torvalds 	sctp_spin_unlock(&head->lock);
45161da177e4SLinus Torvalds }
45171da177e4SLinus Torvalds 
45181da177e4SLinus Torvalds void sctp_put_port(struct sock *sk)
45191da177e4SLinus Torvalds {
45201da177e4SLinus Torvalds 	sctp_local_bh_disable();
45211da177e4SLinus Torvalds 	__sctp_put_port(sk);
45221da177e4SLinus Torvalds 	sctp_local_bh_enable();
45231da177e4SLinus Torvalds }
45241da177e4SLinus Torvalds 
45251da177e4SLinus Torvalds /*
45261da177e4SLinus Torvalds  * The system picks an ephemeral port and choose an address set equivalent
45271da177e4SLinus Torvalds  * to binding with a wildcard address.
45281da177e4SLinus Torvalds  * One of those addresses will be the primary address for the association.
45291da177e4SLinus Torvalds  * This automatically enables the multihoming capability of SCTP.
45301da177e4SLinus Torvalds  */
45311da177e4SLinus Torvalds static int sctp_autobind(struct sock *sk)
45321da177e4SLinus Torvalds {
45331da177e4SLinus Torvalds 	union sctp_addr autoaddr;
45341da177e4SLinus Torvalds 	struct sctp_af *af;
45351da177e4SLinus Torvalds 	unsigned short port;
45361da177e4SLinus Torvalds 
45371da177e4SLinus Torvalds 	/* Initialize a local sockaddr structure to INADDR_ANY. */
45381da177e4SLinus Torvalds 	af = sctp_sk(sk)->pf->af;
45391da177e4SLinus Torvalds 
45401da177e4SLinus Torvalds 	port = htons(inet_sk(sk)->num);
45411da177e4SLinus Torvalds 	af->inaddr_any(&autoaddr, port);
45421da177e4SLinus Torvalds 
45431da177e4SLinus Torvalds 	return sctp_do_bind(sk, &autoaddr, af->sockaddr_len);
45441da177e4SLinus Torvalds }
45451da177e4SLinus Torvalds 
45461da177e4SLinus Torvalds /* Parse out IPPROTO_SCTP CMSG headers.  Perform only minimal validation.
45471da177e4SLinus Torvalds  *
45481da177e4SLinus Torvalds  * From RFC 2292
45491da177e4SLinus Torvalds  * 4.2 The cmsghdr Structure *
45501da177e4SLinus Torvalds  *
45511da177e4SLinus Torvalds  * When ancillary data is sent or received, any number of ancillary data
45521da177e4SLinus Torvalds  * objects can be specified by the msg_control and msg_controllen members of
45531da177e4SLinus Torvalds  * the msghdr structure, because each object is preceded by
45541da177e4SLinus Torvalds  * a cmsghdr structure defining the object's length (the cmsg_len member).
45551da177e4SLinus Torvalds  * Historically Berkeley-derived implementations have passed only one object
45561da177e4SLinus Torvalds  * at a time, but this API allows multiple objects to be
45571da177e4SLinus Torvalds  * passed in a single call to sendmsg() or recvmsg(). The following example
45581da177e4SLinus Torvalds  * shows two ancillary data objects in a control buffer.
45591da177e4SLinus Torvalds  *
45601da177e4SLinus Torvalds  *   |<--------------------------- msg_controllen -------------------------->|
45611da177e4SLinus Torvalds  *   |                                                                       |
45621da177e4SLinus Torvalds  *
45631da177e4SLinus Torvalds  *   |<----- ancillary data object ----->|<----- ancillary data object ----->|
45641da177e4SLinus Torvalds  *
45651da177e4SLinus Torvalds  *   |<---------- CMSG_SPACE() --------->|<---------- CMSG_SPACE() --------->|
45661da177e4SLinus Torvalds  *   |                                   |                                   |
45671da177e4SLinus Torvalds  *
45681da177e4SLinus Torvalds  *   |<---------- cmsg_len ---------->|  |<--------- cmsg_len ----------->|  |
45691da177e4SLinus Torvalds  *
45701da177e4SLinus Torvalds  *   |<--------- CMSG_LEN() --------->|  |<-------- CMSG_LEN() ---------->|  |
45711da177e4SLinus Torvalds  *   |                                |  |                                |  |
45721da177e4SLinus Torvalds  *
45731da177e4SLinus Torvalds  *   +-----+-----+-----+--+-----------+--+-----+-----+-----+--+-----------+--+
45741da177e4SLinus Torvalds  *   |cmsg_|cmsg_|cmsg_|XX|           |XX|cmsg_|cmsg_|cmsg_|XX|           |XX|
45751da177e4SLinus Torvalds  *
45761da177e4SLinus Torvalds  *   |len  |level|type |XX|cmsg_data[]|XX|len  |level|type |XX|cmsg_data[]|XX|
45771da177e4SLinus Torvalds  *
45781da177e4SLinus Torvalds  *   +-----+-----+-----+--+-----------+--+-----+-----+-----+--+-----------+--+
45791da177e4SLinus Torvalds  *    ^
45801da177e4SLinus Torvalds  *    |
45811da177e4SLinus Torvalds  *
45821da177e4SLinus Torvalds  * msg_control
45831da177e4SLinus Torvalds  * points here
45841da177e4SLinus Torvalds  */
45851da177e4SLinus Torvalds SCTP_STATIC int sctp_msghdr_parse(const struct msghdr *msg,
45861da177e4SLinus Torvalds 				  sctp_cmsgs_t *cmsgs)
45871da177e4SLinus Torvalds {
45881da177e4SLinus Torvalds 	struct cmsghdr *cmsg;
45891da177e4SLinus Torvalds 
45901da177e4SLinus Torvalds 	for (cmsg = CMSG_FIRSTHDR(msg);
45911da177e4SLinus Torvalds 	     cmsg != NULL;
45921da177e4SLinus Torvalds 	     cmsg = CMSG_NXTHDR((struct msghdr*)msg, cmsg)) {
45931da177e4SLinus Torvalds 		if (!CMSG_OK(msg, cmsg))
45941da177e4SLinus Torvalds 			return -EINVAL;
45951da177e4SLinus Torvalds 
45961da177e4SLinus Torvalds 		/* Should we parse this header or ignore?  */
45971da177e4SLinus Torvalds 		if (cmsg->cmsg_level != IPPROTO_SCTP)
45981da177e4SLinus Torvalds 			continue;
45991da177e4SLinus Torvalds 
46001da177e4SLinus Torvalds 		/* Strictly check lengths following example in SCM code.  */
46011da177e4SLinus Torvalds 		switch (cmsg->cmsg_type) {
46021da177e4SLinus Torvalds 		case SCTP_INIT:
46031da177e4SLinus Torvalds 			/* SCTP Socket API Extension
46041da177e4SLinus Torvalds 			 * 5.2.1 SCTP Initiation Structure (SCTP_INIT)
46051da177e4SLinus Torvalds 			 *
46061da177e4SLinus Torvalds 			 * This cmsghdr structure provides information for
46071da177e4SLinus Torvalds 			 * initializing new SCTP associations with sendmsg().
46081da177e4SLinus Torvalds 			 * The SCTP_INITMSG socket option uses this same data
46091da177e4SLinus Torvalds 			 * structure.  This structure is not used for
46101da177e4SLinus Torvalds 			 * recvmsg().
46111da177e4SLinus Torvalds 			 *
46121da177e4SLinus Torvalds 			 * cmsg_level    cmsg_type      cmsg_data[]
46131da177e4SLinus Torvalds 			 * ------------  ------------   ----------------------
46141da177e4SLinus Torvalds 			 * IPPROTO_SCTP  SCTP_INIT      struct sctp_initmsg
46151da177e4SLinus Torvalds 			 */
46161da177e4SLinus Torvalds 			if (cmsg->cmsg_len !=
46171da177e4SLinus Torvalds 			    CMSG_LEN(sizeof(struct sctp_initmsg)))
46181da177e4SLinus Torvalds 				return -EINVAL;
46191da177e4SLinus Torvalds 			cmsgs->init = (struct sctp_initmsg *)CMSG_DATA(cmsg);
46201da177e4SLinus Torvalds 			break;
46211da177e4SLinus Torvalds 
46221da177e4SLinus Torvalds 		case SCTP_SNDRCV:
46231da177e4SLinus Torvalds 			/* SCTP Socket API Extension
46241da177e4SLinus Torvalds 			 * 5.2.2 SCTP Header Information Structure(SCTP_SNDRCV)
46251da177e4SLinus Torvalds 			 *
46261da177e4SLinus Torvalds 			 * This cmsghdr structure specifies SCTP options for
46271da177e4SLinus Torvalds 			 * sendmsg() and describes SCTP header information
46281da177e4SLinus Torvalds 			 * about a received message through recvmsg().
46291da177e4SLinus Torvalds 			 *
46301da177e4SLinus Torvalds 			 * cmsg_level    cmsg_type      cmsg_data[]
46311da177e4SLinus Torvalds 			 * ------------  ------------   ----------------------
46321da177e4SLinus Torvalds 			 * IPPROTO_SCTP  SCTP_SNDRCV    struct sctp_sndrcvinfo
46331da177e4SLinus Torvalds 			 */
46341da177e4SLinus Torvalds 			if (cmsg->cmsg_len !=
46351da177e4SLinus Torvalds 			    CMSG_LEN(sizeof(struct sctp_sndrcvinfo)))
46361da177e4SLinus Torvalds 				return -EINVAL;
46371da177e4SLinus Torvalds 
46381da177e4SLinus Torvalds 			cmsgs->info =
46391da177e4SLinus Torvalds 				(struct sctp_sndrcvinfo *)CMSG_DATA(cmsg);
46401da177e4SLinus Torvalds 
46411da177e4SLinus Torvalds 			/* Minimally, validate the sinfo_flags. */
46421da177e4SLinus Torvalds 			if (cmsgs->info->sinfo_flags &
4643*eaa5c54dSIvan Skytte Jorgensen 			    ~(SCTP_UNORDERED | SCTP_ADDR_OVER |
4644*eaa5c54dSIvan Skytte Jorgensen 			      SCTP_ABORT | SCTP_EOF))
46451da177e4SLinus Torvalds 				return -EINVAL;
46461da177e4SLinus Torvalds 			break;
46471da177e4SLinus Torvalds 
46481da177e4SLinus Torvalds 		default:
46491da177e4SLinus Torvalds 			return -EINVAL;
46501da177e4SLinus Torvalds 		};
46511da177e4SLinus Torvalds 	}
46521da177e4SLinus Torvalds 	return 0;
46531da177e4SLinus Torvalds }
46541da177e4SLinus Torvalds 
46551da177e4SLinus Torvalds /*
46561da177e4SLinus Torvalds  * Wait for a packet..
46571da177e4SLinus Torvalds  * Note: This function is the same function as in core/datagram.c
46581da177e4SLinus Torvalds  * with a few modifications to make lksctp work.
46591da177e4SLinus Torvalds  */
46601da177e4SLinus Torvalds static int sctp_wait_for_packet(struct sock * sk, int *err, long *timeo_p)
46611da177e4SLinus Torvalds {
46621da177e4SLinus Torvalds 	int error;
46631da177e4SLinus Torvalds 	DEFINE_WAIT(wait);
46641da177e4SLinus Torvalds 
46651da177e4SLinus Torvalds 	prepare_to_wait_exclusive(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);
46661da177e4SLinus Torvalds 
46671da177e4SLinus Torvalds 	/* Socket errors? */
46681da177e4SLinus Torvalds 	error = sock_error(sk);
46691da177e4SLinus Torvalds 	if (error)
46701da177e4SLinus Torvalds 		goto out;
46711da177e4SLinus Torvalds 
46721da177e4SLinus Torvalds 	if (!skb_queue_empty(&sk->sk_receive_queue))
46731da177e4SLinus Torvalds 		goto ready;
46741da177e4SLinus Torvalds 
46751da177e4SLinus Torvalds 	/* Socket shut down?  */
46761da177e4SLinus Torvalds 	if (sk->sk_shutdown & RCV_SHUTDOWN)
46771da177e4SLinus Torvalds 		goto out;
46781da177e4SLinus Torvalds 
46791da177e4SLinus Torvalds 	/* Sequenced packets can come disconnected.  If so we report the
46801da177e4SLinus Torvalds 	 * problem.
46811da177e4SLinus Torvalds 	 */
46821da177e4SLinus Torvalds 	error = -ENOTCONN;
46831da177e4SLinus Torvalds 
46841da177e4SLinus Torvalds 	/* Is there a good reason to think that we may receive some data?  */
46851da177e4SLinus Torvalds 	if (list_empty(&sctp_sk(sk)->ep->asocs) && !sctp_sstate(sk, LISTENING))
46861da177e4SLinus Torvalds 		goto out;
46871da177e4SLinus Torvalds 
46881da177e4SLinus Torvalds 	/* Handle signals.  */
46891da177e4SLinus Torvalds 	if (signal_pending(current))
46901da177e4SLinus Torvalds 		goto interrupted;
46911da177e4SLinus Torvalds 
46921da177e4SLinus Torvalds 	/* Let another process have a go.  Since we are going to sleep
46931da177e4SLinus Torvalds 	 * anyway.  Note: This may cause odd behaviors if the message
46941da177e4SLinus Torvalds 	 * does not fit in the user's buffer, but this seems to be the
46951da177e4SLinus Torvalds 	 * only way to honor MSG_DONTWAIT realistically.
46961da177e4SLinus Torvalds 	 */
46971da177e4SLinus Torvalds 	sctp_release_sock(sk);
46981da177e4SLinus Torvalds 	*timeo_p = schedule_timeout(*timeo_p);
46991da177e4SLinus Torvalds 	sctp_lock_sock(sk);
47001da177e4SLinus Torvalds 
47011da177e4SLinus Torvalds ready:
47021da177e4SLinus Torvalds 	finish_wait(sk->sk_sleep, &wait);
47031da177e4SLinus Torvalds 	return 0;
47041da177e4SLinus Torvalds 
47051da177e4SLinus Torvalds interrupted:
47061da177e4SLinus Torvalds 	error = sock_intr_errno(*timeo_p);
47071da177e4SLinus Torvalds 
47081da177e4SLinus Torvalds out:
47091da177e4SLinus Torvalds 	finish_wait(sk->sk_sleep, &wait);
47101da177e4SLinus Torvalds 	*err = error;
47111da177e4SLinus Torvalds 	return error;
47121da177e4SLinus Torvalds }
47131da177e4SLinus Torvalds 
47141da177e4SLinus Torvalds /* Receive a datagram.
47151da177e4SLinus Torvalds  * Note: This is pretty much the same routine as in core/datagram.c
47161da177e4SLinus Torvalds  * with a few changes to make lksctp work.
47171da177e4SLinus Torvalds  */
47181da177e4SLinus Torvalds static struct sk_buff *sctp_skb_recv_datagram(struct sock *sk, int flags,
47191da177e4SLinus Torvalds 					      int noblock, int *err)
47201da177e4SLinus Torvalds {
47211da177e4SLinus Torvalds 	int error;
47221da177e4SLinus Torvalds 	struct sk_buff *skb;
47231da177e4SLinus Torvalds 	long timeo;
47241da177e4SLinus Torvalds 
47251da177e4SLinus Torvalds 	/* Caller is allowed not to check sk->sk_err before calling.  */
47261da177e4SLinus Torvalds 	error = sock_error(sk);
47271da177e4SLinus Torvalds 	if (error)
47281da177e4SLinus Torvalds 		goto no_packet;
47291da177e4SLinus Torvalds 
47301da177e4SLinus Torvalds 	timeo = sock_rcvtimeo(sk, noblock);
47311da177e4SLinus Torvalds 
47321da177e4SLinus Torvalds 	SCTP_DEBUG_PRINTK("Timeout: timeo: %ld, MAX: %ld.\n",
47331da177e4SLinus Torvalds 			  timeo, MAX_SCHEDULE_TIMEOUT);
47341da177e4SLinus Torvalds 
47351da177e4SLinus Torvalds 	do {
47361da177e4SLinus Torvalds 		/* Again only user level code calls this function,
47371da177e4SLinus Torvalds 		 * so nothing interrupt level
47381da177e4SLinus Torvalds 		 * will suddenly eat the receive_queue.
47391da177e4SLinus Torvalds 		 *
47401da177e4SLinus Torvalds 		 *  Look at current nfs client by the way...
47411da177e4SLinus Torvalds 		 *  However, this function was corrent in any case. 8)
47421da177e4SLinus Torvalds 		 */
47431da177e4SLinus Torvalds 		if (flags & MSG_PEEK) {
47441e061ab2SHerbert Xu 			spin_lock_bh(&sk->sk_receive_queue.lock);
47451da177e4SLinus Torvalds 			skb = skb_peek(&sk->sk_receive_queue);
47461da177e4SLinus Torvalds 			if (skb)
47471da177e4SLinus Torvalds 				atomic_inc(&skb->users);
47481e061ab2SHerbert Xu 			spin_unlock_bh(&sk->sk_receive_queue.lock);
47491da177e4SLinus Torvalds 		} else {
47501da177e4SLinus Torvalds 			skb = skb_dequeue(&sk->sk_receive_queue);
47511da177e4SLinus Torvalds 		}
47521da177e4SLinus Torvalds 
47531da177e4SLinus Torvalds 		if (skb)
47541da177e4SLinus Torvalds 			return skb;
47551da177e4SLinus Torvalds 
47561da177e4SLinus Torvalds 		if (sk->sk_shutdown & RCV_SHUTDOWN)
47571da177e4SLinus Torvalds 			break;
47581da177e4SLinus Torvalds 
47591da177e4SLinus Torvalds 		/* User doesn't want to wait.  */
47601da177e4SLinus Torvalds 		error = -EAGAIN;
47611da177e4SLinus Torvalds 		if (!timeo)
47621da177e4SLinus Torvalds 			goto no_packet;
47631da177e4SLinus Torvalds 	} while (sctp_wait_for_packet(sk, err, &timeo) == 0);
47641da177e4SLinus Torvalds 
47651da177e4SLinus Torvalds 	return NULL;
47661da177e4SLinus Torvalds 
47671da177e4SLinus Torvalds no_packet:
47681da177e4SLinus Torvalds 	*err = error;
47691da177e4SLinus Torvalds 	return NULL;
47701da177e4SLinus Torvalds }
47711da177e4SLinus Torvalds 
47721da177e4SLinus Torvalds /* If sndbuf has changed, wake up per association sndbuf waiters.  */
47731da177e4SLinus Torvalds static void __sctp_write_space(struct sctp_association *asoc)
47741da177e4SLinus Torvalds {
47751da177e4SLinus Torvalds 	struct sock *sk = asoc->base.sk;
47761da177e4SLinus Torvalds 	struct socket *sock = sk->sk_socket;
47771da177e4SLinus Torvalds 
47781da177e4SLinus Torvalds 	if ((sctp_wspace(asoc) > 0) && sock) {
47791da177e4SLinus Torvalds 		if (waitqueue_active(&asoc->wait))
47801da177e4SLinus Torvalds 			wake_up_interruptible(&asoc->wait);
47811da177e4SLinus Torvalds 
47821da177e4SLinus Torvalds 		if (sctp_writeable(sk)) {
47831da177e4SLinus Torvalds 			if (sk->sk_sleep && waitqueue_active(sk->sk_sleep))
47841da177e4SLinus Torvalds 				wake_up_interruptible(sk->sk_sleep);
47851da177e4SLinus Torvalds 
47861da177e4SLinus Torvalds 			/* Note that we try to include the Async I/O support
47871da177e4SLinus Torvalds 			 * here by modeling from the current TCP/UDP code.
47881da177e4SLinus Torvalds 			 * We have not tested with it yet.
47891da177e4SLinus Torvalds 			 */
47901da177e4SLinus Torvalds 			if (sock->fasync_list &&
47911da177e4SLinus Torvalds 			    !(sk->sk_shutdown & SEND_SHUTDOWN))
47921da177e4SLinus Torvalds 				sock_wake_async(sock, 2, POLL_OUT);
47931da177e4SLinus Torvalds 		}
47941da177e4SLinus Torvalds 	}
47951da177e4SLinus Torvalds }
47961da177e4SLinus Torvalds 
47971da177e4SLinus Torvalds /* Do accounting for the sndbuf space.
47981da177e4SLinus Torvalds  * Decrement the used sndbuf space of the corresponding association by the
47991da177e4SLinus Torvalds  * data size which was just transmitted(freed).
48001da177e4SLinus Torvalds  */
48011da177e4SLinus Torvalds static void sctp_wfree(struct sk_buff *skb)
48021da177e4SLinus Torvalds {
48031da177e4SLinus Torvalds 	struct sctp_association *asoc;
48041da177e4SLinus Torvalds 	struct sctp_chunk *chunk;
48051da177e4SLinus Torvalds 	struct sock *sk;
48061da177e4SLinus Torvalds 
48071da177e4SLinus Torvalds 	/* Get the saved chunk pointer.  */
48081da177e4SLinus Torvalds 	chunk = *((struct sctp_chunk **)(skb->cb));
48091da177e4SLinus Torvalds 	asoc = chunk->asoc;
48101da177e4SLinus Torvalds 	sk = asoc->base.sk;
48114eb701dfSNeil Horman 	asoc->sndbuf_used -= SCTP_DATA_SNDSIZE(chunk) +
48124eb701dfSNeil Horman 				sizeof(struct sk_buff) +
48134eb701dfSNeil Horman 				sizeof(struct sctp_chunk);
48144eb701dfSNeil Horman 
48154eb701dfSNeil Horman 	sk->sk_wmem_queued -= SCTP_DATA_SNDSIZE(chunk) +
48164eb701dfSNeil Horman 				sizeof(struct sk_buff) +
48174eb701dfSNeil Horman 				sizeof(struct sctp_chunk);
48184eb701dfSNeil Horman 
48194eb701dfSNeil Horman 	atomic_sub(sizeof(struct sctp_chunk), &sk->sk_wmem_alloc);
48204eb701dfSNeil Horman 
48214eb701dfSNeil Horman 	sock_wfree(skb);
48221da177e4SLinus Torvalds 	__sctp_write_space(asoc);
48231da177e4SLinus Torvalds 
48241da177e4SLinus Torvalds 	sctp_association_put(asoc);
48251da177e4SLinus Torvalds }
48261da177e4SLinus Torvalds 
48271da177e4SLinus Torvalds /* Helper function to wait for space in the sndbuf.  */
48281da177e4SLinus Torvalds static int sctp_wait_for_sndbuf(struct sctp_association *asoc, long *timeo_p,
48291da177e4SLinus Torvalds 				size_t msg_len)
48301da177e4SLinus Torvalds {
48311da177e4SLinus Torvalds 	struct sock *sk = asoc->base.sk;
48321da177e4SLinus Torvalds 	int err = 0;
48331da177e4SLinus Torvalds 	long current_timeo = *timeo_p;
48341da177e4SLinus Torvalds 	DEFINE_WAIT(wait);
48351da177e4SLinus Torvalds 
48361da177e4SLinus Torvalds 	SCTP_DEBUG_PRINTK("wait_for_sndbuf: asoc=%p, timeo=%ld, msg_len=%zu\n",
48371da177e4SLinus Torvalds 	                  asoc, (long)(*timeo_p), msg_len);
48381da177e4SLinus Torvalds 
48391da177e4SLinus Torvalds 	/* Increment the association's refcnt.  */
48401da177e4SLinus Torvalds 	sctp_association_hold(asoc);
48411da177e4SLinus Torvalds 
48421da177e4SLinus Torvalds 	/* Wait on the association specific sndbuf space. */
48431da177e4SLinus Torvalds 	for (;;) {
48441da177e4SLinus Torvalds 		prepare_to_wait_exclusive(&asoc->wait, &wait,
48451da177e4SLinus Torvalds 					  TASK_INTERRUPTIBLE);
48461da177e4SLinus Torvalds 		if (!*timeo_p)
48471da177e4SLinus Torvalds 			goto do_nonblock;
48481da177e4SLinus Torvalds 		if (sk->sk_err || asoc->state >= SCTP_STATE_SHUTDOWN_PENDING ||
48491da177e4SLinus Torvalds 		    asoc->base.dead)
48501da177e4SLinus Torvalds 			goto do_error;
48511da177e4SLinus Torvalds 		if (signal_pending(current))
48521da177e4SLinus Torvalds 			goto do_interrupted;
48531da177e4SLinus Torvalds 		if (msg_len <= sctp_wspace(asoc))
48541da177e4SLinus Torvalds 			break;
48551da177e4SLinus Torvalds 
48561da177e4SLinus Torvalds 		/* Let another process have a go.  Since we are going
48571da177e4SLinus Torvalds 		 * to sleep anyway.
48581da177e4SLinus Torvalds 		 */
48591da177e4SLinus Torvalds 		sctp_release_sock(sk);
48601da177e4SLinus Torvalds 		current_timeo = schedule_timeout(current_timeo);
48611da177e4SLinus Torvalds 		sctp_lock_sock(sk);
48621da177e4SLinus Torvalds 
48631da177e4SLinus Torvalds 		*timeo_p = current_timeo;
48641da177e4SLinus Torvalds 	}
48651da177e4SLinus Torvalds 
48661da177e4SLinus Torvalds out:
48671da177e4SLinus Torvalds 	finish_wait(&asoc->wait, &wait);
48681da177e4SLinus Torvalds 
48691da177e4SLinus Torvalds 	/* Release the association's refcnt.  */
48701da177e4SLinus Torvalds 	sctp_association_put(asoc);
48711da177e4SLinus Torvalds 
48721da177e4SLinus Torvalds 	return err;
48731da177e4SLinus Torvalds 
48741da177e4SLinus Torvalds do_error:
48751da177e4SLinus Torvalds 	err = -EPIPE;
48761da177e4SLinus Torvalds 	goto out;
48771da177e4SLinus Torvalds 
48781da177e4SLinus Torvalds do_interrupted:
48791da177e4SLinus Torvalds 	err = sock_intr_errno(*timeo_p);
48801da177e4SLinus Torvalds 	goto out;
48811da177e4SLinus Torvalds 
48821da177e4SLinus Torvalds do_nonblock:
48831da177e4SLinus Torvalds 	err = -EAGAIN;
48841da177e4SLinus Torvalds 	goto out;
48851da177e4SLinus Torvalds }
48861da177e4SLinus Torvalds 
48871da177e4SLinus Torvalds /* If socket sndbuf has changed, wake up all per association waiters.  */
48881da177e4SLinus Torvalds void sctp_write_space(struct sock *sk)
48891da177e4SLinus Torvalds {
48901da177e4SLinus Torvalds 	struct sctp_association *asoc;
48911da177e4SLinus Torvalds 	struct list_head *pos;
48921da177e4SLinus Torvalds 
48931da177e4SLinus Torvalds 	/* Wake up the tasks in each wait queue.  */
48941da177e4SLinus Torvalds 	list_for_each(pos, &((sctp_sk(sk))->ep->asocs)) {
48951da177e4SLinus Torvalds 		asoc = list_entry(pos, struct sctp_association, asocs);
48961da177e4SLinus Torvalds 		__sctp_write_space(asoc);
48971da177e4SLinus Torvalds 	}
48981da177e4SLinus Torvalds }
48991da177e4SLinus Torvalds 
49001da177e4SLinus Torvalds /* Is there any sndbuf space available on the socket?
49011da177e4SLinus Torvalds  *
49021da177e4SLinus Torvalds  * Note that wmem_queued is the sum of the send buffers on all of the
49031da177e4SLinus Torvalds  * associations on the same socket.  For a UDP-style socket with
49041da177e4SLinus Torvalds  * multiple associations, it is possible for it to be "unwriteable"
49051da177e4SLinus Torvalds  * prematurely.  I assume that this is acceptable because
49061da177e4SLinus Torvalds  * a premature "unwriteable" is better than an accidental "writeable" which
49071da177e4SLinus Torvalds  * would cause an unwanted block under certain circumstances.  For the 1-1
49081da177e4SLinus Torvalds  * UDP-style sockets or TCP-style sockets, this code should work.
49091da177e4SLinus Torvalds  *  - Daisy
49101da177e4SLinus Torvalds  */
49111da177e4SLinus Torvalds static int sctp_writeable(struct sock *sk)
49121da177e4SLinus Torvalds {
49131da177e4SLinus Torvalds 	int amt = 0;
49141da177e4SLinus Torvalds 
49151da177e4SLinus Torvalds 	amt = sk->sk_sndbuf - sk->sk_wmem_queued;
49161da177e4SLinus Torvalds 	if (amt < 0)
49171da177e4SLinus Torvalds 		amt = 0;
49181da177e4SLinus Torvalds 	return amt;
49191da177e4SLinus Torvalds }
49201da177e4SLinus Torvalds 
49211da177e4SLinus Torvalds /* Wait for an association to go into ESTABLISHED state. If timeout is 0,
49221da177e4SLinus Torvalds  * returns immediately with EINPROGRESS.
49231da177e4SLinus Torvalds  */
49241da177e4SLinus Torvalds static int sctp_wait_for_connect(struct sctp_association *asoc, long *timeo_p)
49251da177e4SLinus Torvalds {
49261da177e4SLinus Torvalds 	struct sock *sk = asoc->base.sk;
49271da177e4SLinus Torvalds 	int err = 0;
49281da177e4SLinus Torvalds 	long current_timeo = *timeo_p;
49291da177e4SLinus Torvalds 	DEFINE_WAIT(wait);
49301da177e4SLinus Torvalds 
49311da177e4SLinus Torvalds 	SCTP_DEBUG_PRINTK("%s: asoc=%p, timeo=%ld\n", __FUNCTION__, asoc,
49321da177e4SLinus Torvalds 			  (long)(*timeo_p));
49331da177e4SLinus Torvalds 
49341da177e4SLinus Torvalds 	/* Increment the association's refcnt.  */
49351da177e4SLinus Torvalds 	sctp_association_hold(asoc);
49361da177e4SLinus Torvalds 
49371da177e4SLinus Torvalds 	for (;;) {
49381da177e4SLinus Torvalds 		prepare_to_wait_exclusive(&asoc->wait, &wait,
49391da177e4SLinus Torvalds 					  TASK_INTERRUPTIBLE);
49401da177e4SLinus Torvalds 		if (!*timeo_p)
49411da177e4SLinus Torvalds 			goto do_nonblock;
49421da177e4SLinus Torvalds 		if (sk->sk_shutdown & RCV_SHUTDOWN)
49431da177e4SLinus Torvalds 			break;
49441da177e4SLinus Torvalds 		if (sk->sk_err || asoc->state >= SCTP_STATE_SHUTDOWN_PENDING ||
49451da177e4SLinus Torvalds 		    asoc->base.dead)
49461da177e4SLinus Torvalds 			goto do_error;
49471da177e4SLinus Torvalds 		if (signal_pending(current))
49481da177e4SLinus Torvalds 			goto do_interrupted;
49491da177e4SLinus Torvalds 
49501da177e4SLinus Torvalds 		if (sctp_state(asoc, ESTABLISHED))
49511da177e4SLinus Torvalds 			break;
49521da177e4SLinus Torvalds 
49531da177e4SLinus Torvalds 		/* Let another process have a go.  Since we are going
49541da177e4SLinus Torvalds 		 * to sleep anyway.
49551da177e4SLinus Torvalds 		 */
49561da177e4SLinus Torvalds 		sctp_release_sock(sk);
49571da177e4SLinus Torvalds 		current_timeo = schedule_timeout(current_timeo);
49581da177e4SLinus Torvalds 		sctp_lock_sock(sk);
49591da177e4SLinus Torvalds 
49601da177e4SLinus Torvalds 		*timeo_p = current_timeo;
49611da177e4SLinus Torvalds 	}
49621da177e4SLinus Torvalds 
49631da177e4SLinus Torvalds out:
49641da177e4SLinus Torvalds 	finish_wait(&asoc->wait, &wait);
49651da177e4SLinus Torvalds 
49661da177e4SLinus Torvalds 	/* Release the association's refcnt.  */
49671da177e4SLinus Torvalds 	sctp_association_put(asoc);
49681da177e4SLinus Torvalds 
49691da177e4SLinus Torvalds 	return err;
49701da177e4SLinus Torvalds 
49711da177e4SLinus Torvalds do_error:
49723f7a87d2SFrank Filz 	if (asoc->init_err_counter + 1 >= asoc->max_init_attempts)
49731da177e4SLinus Torvalds 		err = -ETIMEDOUT;
49741da177e4SLinus Torvalds 	else
49751da177e4SLinus Torvalds 		err = -ECONNREFUSED;
49761da177e4SLinus Torvalds 	goto out;
49771da177e4SLinus Torvalds 
49781da177e4SLinus Torvalds do_interrupted:
49791da177e4SLinus Torvalds 	err = sock_intr_errno(*timeo_p);
49801da177e4SLinus Torvalds 	goto out;
49811da177e4SLinus Torvalds 
49821da177e4SLinus Torvalds do_nonblock:
49831da177e4SLinus Torvalds 	err = -EINPROGRESS;
49841da177e4SLinus Torvalds 	goto out;
49851da177e4SLinus Torvalds }
49861da177e4SLinus Torvalds 
49871da177e4SLinus Torvalds static int sctp_wait_for_accept(struct sock *sk, long timeo)
49881da177e4SLinus Torvalds {
49891da177e4SLinus Torvalds 	struct sctp_endpoint *ep;
49901da177e4SLinus Torvalds 	int err = 0;
49911da177e4SLinus Torvalds 	DEFINE_WAIT(wait);
49921da177e4SLinus Torvalds 
49931da177e4SLinus Torvalds 	ep = sctp_sk(sk)->ep;
49941da177e4SLinus Torvalds 
49951da177e4SLinus Torvalds 
49961da177e4SLinus Torvalds 	for (;;) {
49971da177e4SLinus Torvalds 		prepare_to_wait_exclusive(sk->sk_sleep, &wait,
49981da177e4SLinus Torvalds 					  TASK_INTERRUPTIBLE);
49991da177e4SLinus Torvalds 
50001da177e4SLinus Torvalds 		if (list_empty(&ep->asocs)) {
50011da177e4SLinus Torvalds 			sctp_release_sock(sk);
50021da177e4SLinus Torvalds 			timeo = schedule_timeout(timeo);
50031da177e4SLinus Torvalds 			sctp_lock_sock(sk);
50041da177e4SLinus Torvalds 		}
50051da177e4SLinus Torvalds 
50061da177e4SLinus Torvalds 		err = -EINVAL;
50071da177e4SLinus Torvalds 		if (!sctp_sstate(sk, LISTENING))
50081da177e4SLinus Torvalds 			break;
50091da177e4SLinus Torvalds 
50101da177e4SLinus Torvalds 		err = 0;
50111da177e4SLinus Torvalds 		if (!list_empty(&ep->asocs))
50121da177e4SLinus Torvalds 			break;
50131da177e4SLinus Torvalds 
50141da177e4SLinus Torvalds 		err = sock_intr_errno(timeo);
50151da177e4SLinus Torvalds 		if (signal_pending(current))
50161da177e4SLinus Torvalds 			break;
50171da177e4SLinus Torvalds 
50181da177e4SLinus Torvalds 		err = -EAGAIN;
50191da177e4SLinus Torvalds 		if (!timeo)
50201da177e4SLinus Torvalds 			break;
50211da177e4SLinus Torvalds 	}
50221da177e4SLinus Torvalds 
50231da177e4SLinus Torvalds 	finish_wait(sk->sk_sleep, &wait);
50241da177e4SLinus Torvalds 
50251da177e4SLinus Torvalds 	return err;
50261da177e4SLinus Torvalds }
50271da177e4SLinus Torvalds 
50281da177e4SLinus Torvalds void sctp_wait_for_close(struct sock *sk, long timeout)
50291da177e4SLinus Torvalds {
50301da177e4SLinus Torvalds 	DEFINE_WAIT(wait);
50311da177e4SLinus Torvalds 
50321da177e4SLinus Torvalds 	do {
50331da177e4SLinus Torvalds 		prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);
50341da177e4SLinus Torvalds 		if (list_empty(&sctp_sk(sk)->ep->asocs))
50351da177e4SLinus Torvalds 			break;
50361da177e4SLinus Torvalds 		sctp_release_sock(sk);
50371da177e4SLinus Torvalds 		timeout = schedule_timeout(timeout);
50381da177e4SLinus Torvalds 		sctp_lock_sock(sk);
50391da177e4SLinus Torvalds 	} while (!signal_pending(current) && timeout);
50401da177e4SLinus Torvalds 
50411da177e4SLinus Torvalds 	finish_wait(sk->sk_sleep, &wait);
50421da177e4SLinus Torvalds }
50431da177e4SLinus Torvalds 
50441da177e4SLinus Torvalds /* Populate the fields of the newsk from the oldsk and migrate the assoc
50451da177e4SLinus Torvalds  * and its messages to the newsk.
50461da177e4SLinus Torvalds  */
50471da177e4SLinus Torvalds static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk,
50481da177e4SLinus Torvalds 			      struct sctp_association *assoc,
50491da177e4SLinus Torvalds 			      sctp_socket_type_t type)
50501da177e4SLinus Torvalds {
50511da177e4SLinus Torvalds 	struct sctp_sock *oldsp = sctp_sk(oldsk);
50521da177e4SLinus Torvalds 	struct sctp_sock *newsp = sctp_sk(newsk);
50531da177e4SLinus Torvalds 	struct sctp_bind_bucket *pp; /* hash list port iterator */
50541da177e4SLinus Torvalds 	struct sctp_endpoint *newep = newsp->ep;
50551da177e4SLinus Torvalds 	struct sk_buff *skb, *tmp;
50561da177e4SLinus Torvalds 	struct sctp_ulpevent *event;
50574243cac1SVladislav Yasevich 	int flags = 0;
50581da177e4SLinus Torvalds 
50591da177e4SLinus Torvalds 	/* Migrate socket buffer sizes and all the socket level options to the
50601da177e4SLinus Torvalds 	 * new socket.
50611da177e4SLinus Torvalds 	 */
50621da177e4SLinus Torvalds 	newsk->sk_sndbuf = oldsk->sk_sndbuf;
50631da177e4SLinus Torvalds 	newsk->sk_rcvbuf = oldsk->sk_rcvbuf;
50641da177e4SLinus Torvalds 	/* Brute force copy old sctp opt. */
50651da177e4SLinus Torvalds 	inet_sk_copy_descendant(newsk, oldsk);
50661da177e4SLinus Torvalds 
50671da177e4SLinus Torvalds 	/* Restore the ep value that was overwritten with the above structure
50681da177e4SLinus Torvalds 	 * copy.
50691da177e4SLinus Torvalds 	 */
50701da177e4SLinus Torvalds 	newsp->ep = newep;
50711da177e4SLinus Torvalds 	newsp->hmac = NULL;
50721da177e4SLinus Torvalds 
50731da177e4SLinus Torvalds 	/* Hook this new socket in to the bind_hash list. */
50741da177e4SLinus Torvalds 	pp = sctp_sk(oldsk)->bind_hash;
50751da177e4SLinus Torvalds 	sk_add_bind_node(newsk, &pp->owner);
50761da177e4SLinus Torvalds 	sctp_sk(newsk)->bind_hash = pp;
50771da177e4SLinus Torvalds 	inet_sk(newsk)->num = inet_sk(oldsk)->num;
50781da177e4SLinus Torvalds 
50794243cac1SVladislav Yasevich 	/* Copy the bind_addr list from the original endpoint to the new
50804243cac1SVladislav Yasevich 	 * endpoint so that we can handle restarts properly
50814243cac1SVladislav Yasevich 	 */
50824243cac1SVladislav Yasevich 	if (assoc->peer.ipv4_address)
50834243cac1SVladislav Yasevich 		flags |= SCTP_ADDR4_PEERSUPP;
50844243cac1SVladislav Yasevich 	if (assoc->peer.ipv6_address)
50854243cac1SVladislav Yasevich 		flags |= SCTP_ADDR6_PEERSUPP;
50864243cac1SVladislav Yasevich 	sctp_bind_addr_copy(&newsp->ep->base.bind_addr,
50874243cac1SVladislav Yasevich 			     &oldsp->ep->base.bind_addr,
50884243cac1SVladislav Yasevich 			     SCTP_SCOPE_GLOBAL, GFP_KERNEL, flags);
50894243cac1SVladislav Yasevich 
50901da177e4SLinus Torvalds 	/* Move any messages in the old socket's receive queue that are for the
50911da177e4SLinus Torvalds 	 * peeled off association to the new socket's receive queue.
50921da177e4SLinus Torvalds 	 */
50931da177e4SLinus Torvalds 	sctp_skb_for_each(skb, &oldsk->sk_receive_queue, tmp) {
50941da177e4SLinus Torvalds 		event = sctp_skb2event(skb);
50951da177e4SLinus Torvalds 		if (event->asoc == assoc) {
50968728b834SDavid S. Miller 			__skb_unlink(skb, &oldsk->sk_receive_queue);
50971da177e4SLinus Torvalds 			__skb_queue_tail(&newsk->sk_receive_queue, skb);
50981da177e4SLinus Torvalds 		}
50991da177e4SLinus Torvalds 	}
51001da177e4SLinus Torvalds 
51011da177e4SLinus Torvalds 	/* Clean up any messages pending delivery due to partial
51021da177e4SLinus Torvalds 	 * delivery.   Three cases:
51031da177e4SLinus Torvalds 	 * 1) No partial deliver;  no work.
51041da177e4SLinus Torvalds 	 * 2) Peeling off partial delivery; keep pd_lobby in new pd_lobby.
51051da177e4SLinus Torvalds 	 * 3) Peeling off non-partial delivery; move pd_lobby to receive_queue.
51061da177e4SLinus Torvalds 	 */
51071da177e4SLinus Torvalds 	skb_queue_head_init(&newsp->pd_lobby);
51081da177e4SLinus Torvalds 	sctp_sk(newsk)->pd_mode = assoc->ulpq.pd_mode;
51091da177e4SLinus Torvalds 
51101da177e4SLinus Torvalds 	if (sctp_sk(oldsk)->pd_mode) {
51111da177e4SLinus Torvalds 		struct sk_buff_head *queue;
51121da177e4SLinus Torvalds 
51131da177e4SLinus Torvalds 		/* Decide which queue to move pd_lobby skbs to. */
51141da177e4SLinus Torvalds 		if (assoc->ulpq.pd_mode) {
51151da177e4SLinus Torvalds 			queue = &newsp->pd_lobby;
51161da177e4SLinus Torvalds 		} else
51171da177e4SLinus Torvalds 			queue = &newsk->sk_receive_queue;
51181da177e4SLinus Torvalds 
51191da177e4SLinus Torvalds 		/* Walk through the pd_lobby, looking for skbs that
51201da177e4SLinus Torvalds 		 * need moved to the new socket.
51211da177e4SLinus Torvalds 		 */
51221da177e4SLinus Torvalds 		sctp_skb_for_each(skb, &oldsp->pd_lobby, tmp) {
51231da177e4SLinus Torvalds 			event = sctp_skb2event(skb);
51241da177e4SLinus Torvalds 			if (event->asoc == assoc) {
51258728b834SDavid S. Miller 				__skb_unlink(skb, &oldsp->pd_lobby);
51261da177e4SLinus Torvalds 				__skb_queue_tail(queue, skb);
51271da177e4SLinus Torvalds 			}
51281da177e4SLinus Torvalds 		}
51291da177e4SLinus Torvalds 
51301da177e4SLinus Torvalds 		/* Clear up any skbs waiting for the partial
51311da177e4SLinus Torvalds 		 * delivery to finish.
51321da177e4SLinus Torvalds 		 */
51331da177e4SLinus Torvalds 		if (assoc->ulpq.pd_mode)
51341da177e4SLinus Torvalds 			sctp_clear_pd(oldsk);
51351da177e4SLinus Torvalds 
51361da177e4SLinus Torvalds 	}
51371da177e4SLinus Torvalds 
51381da177e4SLinus Torvalds 	/* Set the type of socket to indicate that it is peeled off from the
51391da177e4SLinus Torvalds 	 * original UDP-style socket or created with the accept() call on a
51401da177e4SLinus Torvalds 	 * TCP-style socket..
51411da177e4SLinus Torvalds 	 */
51421da177e4SLinus Torvalds 	newsp->type = type;
51431da177e4SLinus Torvalds 
51441da177e4SLinus Torvalds 	/* Migrate the association to the new socket. */
51451da177e4SLinus Torvalds 	sctp_assoc_migrate(assoc, newsk);
51461da177e4SLinus Torvalds 
51471da177e4SLinus Torvalds 	/* If the association on the newsk is already closed before accept()
51481da177e4SLinus Torvalds 	 * is called, set RCV_SHUTDOWN flag.
51491da177e4SLinus Torvalds 	 */
51501da177e4SLinus Torvalds 	if (sctp_state(assoc, CLOSED) && sctp_style(newsk, TCP))
51511da177e4SLinus Torvalds 		newsk->sk_shutdown |= RCV_SHUTDOWN;
51521da177e4SLinus Torvalds 
51531da177e4SLinus Torvalds 	newsk->sk_state = SCTP_SS_ESTABLISHED;
51541da177e4SLinus Torvalds }
51551da177e4SLinus Torvalds 
51561da177e4SLinus Torvalds /* This proto struct describes the ULP interface for SCTP.  */
51571da177e4SLinus Torvalds struct proto sctp_prot = {
51581da177e4SLinus Torvalds 	.name        =	"SCTP",
51591da177e4SLinus Torvalds 	.owner       =	THIS_MODULE,
51601da177e4SLinus Torvalds 	.close       =	sctp_close,
51611da177e4SLinus Torvalds 	.connect     =	sctp_connect,
51621da177e4SLinus Torvalds 	.disconnect  =	sctp_disconnect,
51631da177e4SLinus Torvalds 	.accept      =	sctp_accept,
51641da177e4SLinus Torvalds 	.ioctl       =	sctp_ioctl,
51651da177e4SLinus Torvalds 	.init        =	sctp_init_sock,
51661da177e4SLinus Torvalds 	.destroy     =	sctp_destroy_sock,
51671da177e4SLinus Torvalds 	.shutdown    =	sctp_shutdown,
51681da177e4SLinus Torvalds 	.setsockopt  =	sctp_setsockopt,
51691da177e4SLinus Torvalds 	.getsockopt  =	sctp_getsockopt,
51701da177e4SLinus Torvalds 	.sendmsg     =	sctp_sendmsg,
51711da177e4SLinus Torvalds 	.recvmsg     =	sctp_recvmsg,
51721da177e4SLinus Torvalds 	.bind        =	sctp_bind,
51731da177e4SLinus Torvalds 	.backlog_rcv =	sctp_backlog_rcv,
51741da177e4SLinus Torvalds 	.hash        =	sctp_hash,
51751da177e4SLinus Torvalds 	.unhash      =	sctp_unhash,
51761da177e4SLinus Torvalds 	.get_port    =	sctp_get_port,
51771da177e4SLinus Torvalds 	.obj_size    =  sizeof(struct sctp_sock),
51781da177e4SLinus Torvalds };
51791da177e4SLinus Torvalds 
51801da177e4SLinus Torvalds #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
51811da177e4SLinus Torvalds struct proto sctpv6_prot = {
51821da177e4SLinus Torvalds 	.name		= "SCTPv6",
51831da177e4SLinus Torvalds 	.owner		= THIS_MODULE,
51841da177e4SLinus Torvalds 	.close		= sctp_close,
51851da177e4SLinus Torvalds 	.connect	= sctp_connect,
51861da177e4SLinus Torvalds 	.disconnect	= sctp_disconnect,
51871da177e4SLinus Torvalds 	.accept		= sctp_accept,
51881da177e4SLinus Torvalds 	.ioctl		= sctp_ioctl,
51891da177e4SLinus Torvalds 	.init		= sctp_init_sock,
51901da177e4SLinus Torvalds 	.destroy	= sctp_destroy_sock,
51911da177e4SLinus Torvalds 	.shutdown	= sctp_shutdown,
51921da177e4SLinus Torvalds 	.setsockopt	= sctp_setsockopt,
51931da177e4SLinus Torvalds 	.getsockopt	= sctp_getsockopt,
51941da177e4SLinus Torvalds 	.sendmsg	= sctp_sendmsg,
51951da177e4SLinus Torvalds 	.recvmsg	= sctp_recvmsg,
51961da177e4SLinus Torvalds 	.bind		= sctp_bind,
51971da177e4SLinus Torvalds 	.backlog_rcv	= sctp_backlog_rcv,
51981da177e4SLinus Torvalds 	.hash		= sctp_hash,
51991da177e4SLinus Torvalds 	.unhash		= sctp_unhash,
52001da177e4SLinus Torvalds 	.get_port	= sctp_get_port,
52011da177e4SLinus Torvalds 	.obj_size	= sizeof(struct sctp6_sock),
52021da177e4SLinus Torvalds };
52031da177e4SLinus Torvalds #endif /* defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */
5204