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(¶ms, 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 *)¶ms.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, ¶ms.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(¶ms, 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 *)¶ms.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, ¶ms.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, ¶ms, 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