160c778b2SVlad Yasevich /* SCTP kernel implementation 21da177e4SLinus Torvalds * Copyright (c) 1999-2000 Cisco, Inc. 31da177e4SLinus Torvalds * Copyright (c) 1999-2001 Motorola, Inc. 41da177e4SLinus Torvalds * Copyright (c) 2001-2002 International Business Machines, Corp. 51da177e4SLinus Torvalds * Copyright (c) 2001 Intel Corp. 61da177e4SLinus Torvalds * Copyright (c) 2001 Nokia, Inc. 71da177e4SLinus Torvalds * Copyright (c) 2001 La Monte H.P. Yarroll 81da177e4SLinus Torvalds * 960c778b2SVlad Yasevich * This file is part of the SCTP kernel implementation 101da177e4SLinus Torvalds * 111da177e4SLinus Torvalds * This abstraction represents an SCTP endpoint. 121da177e4SLinus Torvalds * 1360c778b2SVlad Yasevich * The SCTP implementation is free software; 141da177e4SLinus Torvalds * you can redistribute it and/or modify it under the terms of 151da177e4SLinus Torvalds * the GNU General Public License as published by 161da177e4SLinus Torvalds * the Free Software Foundation; either version 2, or (at your option) 171da177e4SLinus Torvalds * any later version. 181da177e4SLinus Torvalds * 1960c778b2SVlad Yasevich * The SCTP implementation is distributed in the hope that it 201da177e4SLinus Torvalds * will be useful, but WITHOUT ANY WARRANTY; without even the implied 211da177e4SLinus Torvalds * ************************ 221da177e4SLinus Torvalds * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 231da177e4SLinus Torvalds * See the GNU General Public License for more details. 241da177e4SLinus Torvalds * 251da177e4SLinus Torvalds * You should have received a copy of the GNU General Public License 261da177e4SLinus Torvalds * along with GNU CC; see the file COPYING. If not, write to 271da177e4SLinus Torvalds * the Free Software Foundation, 59 Temple Place - Suite 330, 281da177e4SLinus Torvalds * Boston, MA 02111-1307, USA. 291da177e4SLinus Torvalds * 301da177e4SLinus Torvalds * Please send any bug reports or fixes you make to the 311da177e4SLinus Torvalds * email address(es): 321da177e4SLinus Torvalds * lksctp developers <lksctp-developers@lists.sourceforge.net> 331da177e4SLinus Torvalds * 341da177e4SLinus Torvalds * Or submit a bug report through the following website: 351da177e4SLinus Torvalds * http://www.sf.net/projects/lksctp 361da177e4SLinus Torvalds * 371da177e4SLinus Torvalds * Written or modified by: 381da177e4SLinus Torvalds * La Monte H.P. Yarroll <piggy@acm.org> 391da177e4SLinus Torvalds * Karl Knutson <karl@athena.chicago.il.us> 401da177e4SLinus Torvalds * Jon Grimm <jgrimm@austin.ibm.com> 411da177e4SLinus Torvalds * Daisy Chang <daisyc@us.ibm.com> 421da177e4SLinus Torvalds * Dajiang Zhang <dajiang.zhang@nokia.com> 431da177e4SLinus Torvalds * 441da177e4SLinus Torvalds * Any bugs reported given to us we will try to fix... any fixes shared will 451da177e4SLinus Torvalds * be incorporated into the next SCTP release. 461da177e4SLinus Torvalds */ 471da177e4SLinus Torvalds 481da177e4SLinus Torvalds #include <linux/types.h> 491da177e4SLinus Torvalds #include <linux/slab.h> 501da177e4SLinus Torvalds #include <linux/in.h> 511da177e4SLinus Torvalds #include <linux/random.h> /* get_random_bytes() */ 521da177e4SLinus Torvalds #include <linux/crypto.h> 531da177e4SLinus Torvalds #include <net/sock.h> 541da177e4SLinus Torvalds #include <net/ipv6.h> 551da177e4SLinus Torvalds #include <net/sctp/sctp.h> 561da177e4SLinus Torvalds #include <net/sctp/sm.h> 571da177e4SLinus Torvalds 581da177e4SLinus Torvalds /* Forward declarations for internal helpers. */ 59c4028958SDavid Howells static void sctp_endpoint_bh_rcv(struct work_struct *work); 601da177e4SLinus Torvalds 611da177e4SLinus Torvalds /* 621da177e4SLinus Torvalds * Initialize the base fields of the endpoint structure. 631da177e4SLinus Torvalds */ 641da177e4SLinus Torvalds static struct sctp_endpoint *sctp_endpoint_init(struct sctp_endpoint *ep, 653182cd84SAlexey Dobriyan struct sock *sk, 66dd0fc66fSAl Viro gfp_t gfp) 671da177e4SLinus Torvalds { 68e1fc3b14SEric W. Biederman struct net *net = sock_net(sk); 69a29a5bd4SVlad Yasevich struct sctp_hmac_algo_param *auth_hmacs = NULL; 70a29a5bd4SVlad Yasevich struct sctp_chunks_param *auth_chunks = NULL; 71a29a5bd4SVlad Yasevich struct sctp_shared_key *null_key; 72a29a5bd4SVlad Yasevich int err; 73a29a5bd4SVlad Yasevich 74b68dbcabSVlad Yasevich ep->digest = kzalloc(SCTP_SIGNATURE_SIZE, gfp); 75b68dbcabSVlad Yasevich if (!ep->digest) 76b68dbcabSVlad Yasevich return NULL; 77b68dbcabSVlad Yasevich 78e1fc3b14SEric W. Biederman if (net->sctp.auth_enable) { 79a29a5bd4SVlad Yasevich /* Allocate space for HMACS and CHUNKS authentication 80a29a5bd4SVlad Yasevich * variables. There are arrays that we encode directly 81a29a5bd4SVlad Yasevich * into parameters to make the rest of the operations easier. 82a29a5bd4SVlad Yasevich */ 83a29a5bd4SVlad Yasevich auth_hmacs = kzalloc(sizeof(sctp_hmac_algo_param_t) + 84a29a5bd4SVlad Yasevich sizeof(__u16) * SCTP_AUTH_NUM_HMACS, gfp); 85a29a5bd4SVlad Yasevich if (!auth_hmacs) 86a29a5bd4SVlad Yasevich goto nomem; 87a29a5bd4SVlad Yasevich 88a29a5bd4SVlad Yasevich auth_chunks = kzalloc(sizeof(sctp_chunks_param_t) + 89a29a5bd4SVlad Yasevich SCTP_NUM_CHUNK_TYPES, gfp); 90a29a5bd4SVlad Yasevich if (!auth_chunks) 91a29a5bd4SVlad Yasevich goto nomem; 92a29a5bd4SVlad Yasevich 93a29a5bd4SVlad Yasevich /* Initialize the HMACS parameter. 94a29a5bd4SVlad Yasevich * SCTP-AUTH: Section 3.3 95a29a5bd4SVlad Yasevich * Every endpoint supporting SCTP chunk authentication MUST 96a29a5bd4SVlad Yasevich * support the HMAC based on the SHA-1 algorithm. 97a29a5bd4SVlad Yasevich */ 98a29a5bd4SVlad Yasevich auth_hmacs->param_hdr.type = SCTP_PARAM_HMAC_ALGO; 99a29a5bd4SVlad Yasevich auth_hmacs->param_hdr.length = 100a29a5bd4SVlad Yasevich htons(sizeof(sctp_paramhdr_t) + 2); 101a29a5bd4SVlad Yasevich auth_hmacs->hmac_ids[0] = htons(SCTP_AUTH_HMAC_ID_SHA1); 102a29a5bd4SVlad Yasevich 103a29a5bd4SVlad Yasevich /* Initialize the CHUNKS parameter */ 104a29a5bd4SVlad Yasevich auth_chunks->param_hdr.type = SCTP_PARAM_CHUNKS; 1055e739d17SVlad Yasevich auth_chunks->param_hdr.length = htons(sizeof(sctp_paramhdr_t)); 106a29a5bd4SVlad Yasevich 107a29a5bd4SVlad Yasevich /* If the Add-IP functionality is enabled, we must 108a29a5bd4SVlad Yasevich * authenticate, ASCONF and ASCONF-ACK chunks 109a29a5bd4SVlad Yasevich */ 110e1fc3b14SEric W. Biederman if (net->sctp.addip_enable) { 111a29a5bd4SVlad Yasevich auth_chunks->chunks[0] = SCTP_CID_ASCONF; 112a29a5bd4SVlad Yasevich auth_chunks->chunks[1] = SCTP_CID_ASCONF_ACK; 113cb0dc77dSAl Viro auth_chunks->param_hdr.length = 114cb0dc77dSAl Viro htons(sizeof(sctp_paramhdr_t) + 2); 115a29a5bd4SVlad Yasevich } 116a29a5bd4SVlad Yasevich } 117a29a5bd4SVlad Yasevich 1181da177e4SLinus Torvalds /* Initialize the base structure. */ 1191da177e4SLinus Torvalds /* What type of endpoint are we? */ 1201da177e4SLinus Torvalds ep->base.type = SCTP_EP_TYPE_SOCKET; 1211da177e4SLinus Torvalds 1221da177e4SLinus Torvalds /* Initialize the basic object fields. */ 1231da177e4SLinus Torvalds atomic_set(&ep->base.refcnt, 1); 1240022d2ddSDaniel Borkmann ep->base.dead = false; 1251da177e4SLinus Torvalds 1261da177e4SLinus Torvalds /* Create an input queue. */ 1271da177e4SLinus Torvalds sctp_inq_init(&ep->base.inqueue); 1281da177e4SLinus Torvalds 1291da177e4SLinus Torvalds /* Set its top-half handler */ 130c4028958SDavid Howells sctp_inq_set_th_handler(&ep->base.inqueue, sctp_endpoint_bh_rcv); 1311da177e4SLinus Torvalds 1321da177e4SLinus Torvalds /* Initialize the bind addr area */ 1331da177e4SLinus Torvalds sctp_bind_addr_init(&ep->base.bind_addr, 0); 1341da177e4SLinus Torvalds 1351da177e4SLinus Torvalds /* Remember who we are attached to. */ 1361da177e4SLinus Torvalds ep->base.sk = sk; 1371da177e4SLinus Torvalds sock_hold(ep->base.sk); 1381da177e4SLinus Torvalds 1391da177e4SLinus Torvalds /* Create the lists of associations. */ 1401da177e4SLinus Torvalds INIT_LIST_HEAD(&ep->asocs); 1411da177e4SLinus Torvalds 1421da177e4SLinus Torvalds /* Use SCTP specific send buffer space queues. */ 143e1fc3b14SEric W. Biederman ep->sndbuf_policy = net->sctp.sndbuf_policy; 1444d93df0aSNeil Horman 145561b1733SWei Yongjun sk->sk_data_ready = sctp_data_ready; 1461da177e4SLinus Torvalds sk->sk_write_space = sctp_write_space; 1471da177e4SLinus Torvalds sock_set_flag(sk, SOCK_USE_WRITE_QUEUE); 1481da177e4SLinus Torvalds 149049b3ff5SNeil Horman /* Get the receive buffer policy for this endpoint */ 150e1fc3b14SEric W. Biederman ep->rcvbuf_policy = net->sctp.rcvbuf_policy; 151049b3ff5SNeil Horman 1521da177e4SLinus Torvalds /* Initialize the secret key used with cookie. */ 153570617e7SDaniel Borkmann get_random_bytes(ep->secret_key, sizeof(ep->secret_key)); 1541da177e4SLinus Torvalds 155a29a5bd4SVlad Yasevich /* SCTP-AUTH extensions*/ 156a29a5bd4SVlad Yasevich INIT_LIST_HEAD(&ep->endpoint_shared_keys); 15781ce0dbcSDan Carpenter null_key = sctp_auth_shkey_create(0, gfp); 158a29a5bd4SVlad Yasevich if (!null_key) 159a29a5bd4SVlad Yasevich goto nomem; 160a29a5bd4SVlad Yasevich 161a29a5bd4SVlad Yasevich list_add(&null_key->key_list, &ep->endpoint_shared_keys); 162a29a5bd4SVlad Yasevich 16302582e9bSMasanari Iida /* Allocate and initialize transorms arrays for supported HMACs. */ 164a29a5bd4SVlad Yasevich err = sctp_auth_init_hmacs(ep, gfp); 165a29a5bd4SVlad Yasevich if (err) 166a29a5bd4SVlad Yasevich goto nomem_hmacs; 167a29a5bd4SVlad Yasevich 168a29a5bd4SVlad Yasevich /* Add the null key to the endpoint shared keys list and 169a29a5bd4SVlad Yasevich * set the hmcas and chunks pointers. 170a29a5bd4SVlad Yasevich */ 171a29a5bd4SVlad Yasevich ep->auth_hmacs_list = auth_hmacs; 172a29a5bd4SVlad Yasevich ep->auth_chunk_list = auth_chunks; 173a29a5bd4SVlad Yasevich 1741da177e4SLinus Torvalds return ep; 175a29a5bd4SVlad Yasevich 176a29a5bd4SVlad Yasevich nomem_hmacs: 177a29a5bd4SVlad Yasevich sctp_auth_destroy_keys(&ep->endpoint_shared_keys); 178a29a5bd4SVlad Yasevich nomem: 179a29a5bd4SVlad Yasevich /* Free all allocations */ 180a29a5bd4SVlad Yasevich kfree(auth_hmacs); 181a29a5bd4SVlad Yasevich kfree(auth_chunks); 182a29a5bd4SVlad Yasevich kfree(ep->digest); 183a29a5bd4SVlad Yasevich return NULL; 184a29a5bd4SVlad Yasevich 1851da177e4SLinus Torvalds } 1861da177e4SLinus Torvalds 1871da177e4SLinus Torvalds /* Create a sctp_endpoint with all that boring stuff initialized. 1881da177e4SLinus Torvalds * Returns NULL if there isn't enough memory. 1891da177e4SLinus Torvalds */ 190dd0fc66fSAl Viro struct sctp_endpoint *sctp_endpoint_new(struct sock *sk, gfp_t gfp) 1911da177e4SLinus Torvalds { 1921da177e4SLinus Torvalds struct sctp_endpoint *ep; 1931da177e4SLinus Torvalds 1941da177e4SLinus Torvalds /* Build a local endpoint. */ 1951da177e4SLinus Torvalds ep = t_new(struct sctp_endpoint, gfp); 1961da177e4SLinus Torvalds if (!ep) 1971da177e4SLinus Torvalds goto fail; 1981da177e4SLinus Torvalds if (!sctp_endpoint_init(ep, sk, gfp)) 1991da177e4SLinus Torvalds goto fail_init; 200ff2266cdSDaniel Borkmann 2011da177e4SLinus Torvalds SCTP_DBG_OBJCNT_INC(ep); 2021da177e4SLinus Torvalds return ep; 2031da177e4SLinus Torvalds 2041da177e4SLinus Torvalds fail_init: 2051da177e4SLinus Torvalds kfree(ep); 2061da177e4SLinus Torvalds fail: 2071da177e4SLinus Torvalds return NULL; 2081da177e4SLinus Torvalds } 2091da177e4SLinus Torvalds 2101da177e4SLinus Torvalds /* Add an association to an endpoint. */ 2111da177e4SLinus Torvalds void sctp_endpoint_add_asoc(struct sctp_endpoint *ep, 2121da177e4SLinus Torvalds struct sctp_association *asoc) 2131da177e4SLinus Torvalds { 2141da177e4SLinus Torvalds struct sock *sk = ep->base.sk; 2151da177e4SLinus Torvalds 216de76e695SVlad Yasevich /* If this is a temporary association, don't bother 217de76e695SVlad Yasevich * since we'll be removing it shortly and don't 218de76e695SVlad Yasevich * want anyone to find it anyway. 219de76e695SVlad Yasevich */ 220de76e695SVlad Yasevich if (asoc->temp) 221de76e695SVlad Yasevich return; 222de76e695SVlad Yasevich 2231da177e4SLinus Torvalds /* Now just add it to our list of asocs */ 2241da177e4SLinus Torvalds list_add_tail(&asoc->asocs, &ep->asocs); 2251da177e4SLinus Torvalds 2261da177e4SLinus Torvalds /* Increment the backlog value for a TCP-style listening socket. */ 2271da177e4SLinus Torvalds if (sctp_style(sk, TCP) && sctp_sstate(sk, LISTENING)) 2281da177e4SLinus Torvalds sk->sk_ack_backlog++; 2291da177e4SLinus Torvalds } 2301da177e4SLinus Torvalds 2311da177e4SLinus Torvalds /* Free the endpoint structure. Delay cleanup until 2321da177e4SLinus Torvalds * all users have released their reference count on this structure. 2331da177e4SLinus Torvalds */ 2341da177e4SLinus Torvalds void sctp_endpoint_free(struct sctp_endpoint *ep) 2351da177e4SLinus Torvalds { 2360022d2ddSDaniel Borkmann ep->base.dead = true; 237cfdeef32SVlad Yasevich 238cfdeef32SVlad Yasevich ep->base.sk->sk_state = SCTP_SS_CLOSED; 239cfdeef32SVlad Yasevich 240cfdeef32SVlad Yasevich /* Unlink this endpoint, so we can't find it again! */ 241cfdeef32SVlad Yasevich sctp_unhash_endpoint(ep); 242cfdeef32SVlad Yasevich 2431da177e4SLinus Torvalds sctp_endpoint_put(ep); 2441da177e4SLinus Torvalds } 2451da177e4SLinus Torvalds 2461da177e4SLinus Torvalds /* Final destructor for endpoint. */ 2471da177e4SLinus Torvalds static void sctp_endpoint_destroy(struct sctp_endpoint *ep) 2481da177e4SLinus Torvalds { 2491da177e4SLinus Torvalds SCTP_ASSERT(ep->base.dead, "Endpoint is not dead", return); 2501da177e4SLinus Torvalds 2511da177e4SLinus Torvalds /* Free up the HMAC transform. */ 2521b489e11SHerbert Xu crypto_free_hash(sctp_sk(ep->base.sk)->hmac); 2531da177e4SLinus Torvalds 254b68dbcabSVlad Yasevich /* Free the digest buffer */ 255b68dbcabSVlad Yasevich kfree(ep->digest); 256b68dbcabSVlad Yasevich 257a29a5bd4SVlad Yasevich /* SCTP-AUTH: Free up AUTH releated data such as shared keys 258a29a5bd4SVlad Yasevich * chunks and hmacs arrays that were allocated 259a29a5bd4SVlad Yasevich */ 260a29a5bd4SVlad Yasevich sctp_auth_destroy_keys(&ep->endpoint_shared_keys); 261a29a5bd4SVlad Yasevich kfree(ep->auth_hmacs_list); 262a29a5bd4SVlad Yasevich kfree(ep->auth_chunk_list); 263a29a5bd4SVlad Yasevich 264a29a5bd4SVlad Yasevich /* AUTH - Free any allocated HMAC transform containers */ 265a29a5bd4SVlad Yasevich sctp_auth_destroy_hmacs(ep->auth_hmacs); 266a29a5bd4SVlad Yasevich 2671da177e4SLinus Torvalds /* Cleanup. */ 2681da177e4SLinus Torvalds sctp_inq_free(&ep->base.inqueue); 2691da177e4SLinus Torvalds sctp_bind_addr_free(&ep->base.bind_addr); 2701da177e4SLinus Torvalds 271570617e7SDaniel Borkmann memset(ep->secret_key, 0, sizeof(ep->secret_key)); 272b5c37fe6SDaniel Borkmann 2731da177e4SLinus Torvalds /* Remove and free the port */ 2741da177e4SLinus Torvalds if (sctp_sk(ep->base.sk)->bind_hash) 2751da177e4SLinus Torvalds sctp_put_port(ep->base.sk); 2761da177e4SLinus Torvalds 2771da177e4SLinus Torvalds /* Give up our hold on the sock. */ 2781da177e4SLinus Torvalds if (ep->base.sk) 2791da177e4SLinus Torvalds sock_put(ep->base.sk); 2801da177e4SLinus Torvalds 2811da177e4SLinus Torvalds kfree(ep); 2821da177e4SLinus Torvalds SCTP_DBG_OBJCNT_DEC(ep); 2831da177e4SLinus Torvalds } 2841da177e4SLinus Torvalds 2851da177e4SLinus Torvalds /* Hold a reference to an endpoint. */ 2861da177e4SLinus Torvalds void sctp_endpoint_hold(struct sctp_endpoint *ep) 2871da177e4SLinus Torvalds { 2881da177e4SLinus Torvalds atomic_inc(&ep->base.refcnt); 2891da177e4SLinus Torvalds } 2901da177e4SLinus Torvalds 2911da177e4SLinus Torvalds /* Release a reference to an endpoint and clean up if there are 2921da177e4SLinus Torvalds * no more references. 2931da177e4SLinus Torvalds */ 2941da177e4SLinus Torvalds void sctp_endpoint_put(struct sctp_endpoint *ep) 2951da177e4SLinus Torvalds { 2961da177e4SLinus Torvalds if (atomic_dec_and_test(&ep->base.refcnt)) 2971da177e4SLinus Torvalds sctp_endpoint_destroy(ep); 2981da177e4SLinus Torvalds } 2991da177e4SLinus Torvalds 3001da177e4SLinus Torvalds /* Is this the endpoint we are looking for? */ 3011da177e4SLinus Torvalds struct sctp_endpoint *sctp_endpoint_is_match(struct sctp_endpoint *ep, 3024cdadcbcSEric W. Biederman struct net *net, 3031da177e4SLinus Torvalds const union sctp_addr *laddr) 3041da177e4SLinus Torvalds { 305559cf710SVlad Yasevich struct sctp_endpoint *retval = NULL; 3061da177e4SLinus Torvalds 3074cdadcbcSEric W. Biederman if ((htons(ep->base.bind_addr.port) == laddr->v4.sin_port) && 3084cdadcbcSEric W. Biederman net_eq(sock_net(ep->base.sk), net)) { 3091da177e4SLinus Torvalds if (sctp_bind_addr_match(&ep->base.bind_addr, laddr, 310559cf710SVlad Yasevich sctp_sk(ep->base.sk))) 3111da177e4SLinus Torvalds retval = ep; 3121da177e4SLinus Torvalds } 3131da177e4SLinus Torvalds 3141da177e4SLinus Torvalds return retval; 3151da177e4SLinus Torvalds } 3161da177e4SLinus Torvalds 3171da177e4SLinus Torvalds /* Find the association that goes with this chunk. 3181da177e4SLinus Torvalds * We do a linear search of the associations for this endpoint. 3191da177e4SLinus Torvalds * We return the matching transport address too. 3201da177e4SLinus Torvalds */ 3211da177e4SLinus Torvalds static struct sctp_association *__sctp_endpoint_lookup_assoc( 3221da177e4SLinus Torvalds const struct sctp_endpoint *ep, 3231da177e4SLinus Torvalds const union sctp_addr *paddr, 3241da177e4SLinus Torvalds struct sctp_transport **transport) 3251da177e4SLinus Torvalds { 326123ed979SVlad Yasevich struct sctp_association *asoc = NULL; 327deb85a6eSVlad Yasevich struct sctp_association *tmp; 328123ed979SVlad Yasevich struct sctp_transport *t = NULL; 329123ed979SVlad Yasevich struct sctp_hashbucket *head; 330123ed979SVlad Yasevich struct sctp_ep_common *epb; 331123ed979SVlad Yasevich int hash; 3321da177e4SLinus Torvalds int rport; 3331da177e4SLinus Torvalds 3341da177e4SLinus Torvalds *transport = NULL; 335deb85a6eSVlad Yasevich 336deb85a6eSVlad Yasevich /* If the local port is not set, there can't be any associations 337deb85a6eSVlad Yasevich * on this endpoint. 338deb85a6eSVlad Yasevich */ 339deb85a6eSVlad Yasevich if (!ep->base.bind_addr.port) 340deb85a6eSVlad Yasevich goto out; 341deb85a6eSVlad Yasevich 342123ed979SVlad Yasevich rport = ntohs(paddr->v4.sin_port); 343123ed979SVlad Yasevich 3444110cc25SEric W. Biederman hash = sctp_assoc_hashfn(sock_net(ep->base.sk), ep->base.bind_addr.port, 3454110cc25SEric W. Biederman rport); 346123ed979SVlad Yasevich head = &sctp_assoc_hashtable[hash]; 347123ed979SVlad Yasevich read_lock(&head->lock); 348b67bfe0dSSasha Levin sctp_for_each_hentry(epb, &head->chain) { 349deb85a6eSVlad Yasevich tmp = sctp_assoc(epb); 350deb85a6eSVlad Yasevich if (tmp->ep != ep || rport != tmp->peer.port) 351deb85a6eSVlad Yasevich continue; 352123ed979SVlad Yasevich 353deb85a6eSVlad Yasevich t = sctp_assoc_lookup_paddr(tmp, paddr); 354123ed979SVlad Yasevich if (t) { 355deb85a6eSVlad Yasevich asoc = tmp; 356123ed979SVlad Yasevich *transport = t; 357123ed979SVlad Yasevich break; 358123ed979SVlad Yasevich } 359123ed979SVlad Yasevich } 360123ed979SVlad Yasevich read_unlock(&head->lock); 361deb85a6eSVlad Yasevich out: 362123ed979SVlad Yasevich return asoc; 3631da177e4SLinus Torvalds } 3641da177e4SLinus Torvalds 3651da177e4SLinus Torvalds /* Lookup association on an endpoint based on a peer address. BH-safe. */ 3661da177e4SLinus Torvalds struct sctp_association *sctp_endpoint_lookup_assoc( 3671da177e4SLinus Torvalds const struct sctp_endpoint *ep, 3681da177e4SLinus Torvalds const union sctp_addr *paddr, 3691da177e4SLinus Torvalds struct sctp_transport **transport) 3701da177e4SLinus Torvalds { 3711da177e4SLinus Torvalds struct sctp_association *asoc; 3721da177e4SLinus Torvalds 3731da177e4SLinus Torvalds sctp_local_bh_disable(); 3741da177e4SLinus Torvalds asoc = __sctp_endpoint_lookup_assoc(ep, paddr, transport); 3751da177e4SLinus Torvalds sctp_local_bh_enable(); 3761da177e4SLinus Torvalds 3771da177e4SLinus Torvalds return asoc; 3781da177e4SLinus Torvalds } 3791da177e4SLinus Torvalds 3801da177e4SLinus Torvalds /* Look for any peeled off association from the endpoint that matches the 3811da177e4SLinus Torvalds * given peer address. 3821da177e4SLinus Torvalds */ 3831da177e4SLinus Torvalds int sctp_endpoint_is_peeled_off(struct sctp_endpoint *ep, 3841da177e4SLinus Torvalds const union sctp_addr *paddr) 3851da177e4SLinus Torvalds { 3861da177e4SLinus Torvalds struct sctp_sockaddr_entry *addr; 3871da177e4SLinus Torvalds struct sctp_bind_addr *bp; 3884110cc25SEric W. Biederman struct net *net = sock_net(ep->base.sk); 3891da177e4SLinus Torvalds 3901da177e4SLinus Torvalds bp = &ep->base.bind_addr; 391559cf710SVlad Yasevich /* This function is called with the socket lock held, 392559cf710SVlad Yasevich * so the address_list can not change. 393559cf710SVlad Yasevich */ 394559cf710SVlad Yasevich list_for_each_entry(addr, &bp->address_list, list) { 3954110cc25SEric W. Biederman if (sctp_has_association(net, &addr->a, paddr)) 3961da177e4SLinus Torvalds return 1; 3971da177e4SLinus Torvalds } 3981da177e4SLinus Torvalds 3991da177e4SLinus Torvalds return 0; 4001da177e4SLinus Torvalds } 4011da177e4SLinus Torvalds 4021da177e4SLinus Torvalds /* Do delayed input processing. This is scheduled by sctp_rcv(). 4031da177e4SLinus Torvalds * This may be called on BH or task time. 4041da177e4SLinus Torvalds */ 405c4028958SDavid Howells static void sctp_endpoint_bh_rcv(struct work_struct *work) 4061da177e4SLinus Torvalds { 407c4028958SDavid Howells struct sctp_endpoint *ep = 408c4028958SDavid Howells container_of(work, struct sctp_endpoint, 409c4028958SDavid Howells base.inqueue.immediate); 4101da177e4SLinus Torvalds struct sctp_association *asoc; 4111da177e4SLinus Torvalds struct sock *sk; 41255e26eb9SEric W. Biederman struct net *net; 4131da177e4SLinus Torvalds struct sctp_transport *transport; 4141da177e4SLinus Torvalds struct sctp_chunk *chunk; 4151da177e4SLinus Torvalds struct sctp_inq *inqueue; 4161da177e4SLinus Torvalds sctp_subtype_t subtype; 4171da177e4SLinus Torvalds sctp_state_t state; 4181da177e4SLinus Torvalds int error = 0; 41942b2aa86SJustin P. Mattock int first_time = 1; /* is this the first time through the loop */ 4201da177e4SLinus Torvalds 4211da177e4SLinus Torvalds if (ep->base.dead) 4221da177e4SLinus Torvalds return; 4231da177e4SLinus Torvalds 4241da177e4SLinus Torvalds asoc = NULL; 4251da177e4SLinus Torvalds inqueue = &ep->base.inqueue; 4261da177e4SLinus Torvalds sk = ep->base.sk; 42755e26eb9SEric W. Biederman net = sock_net(sk); 4281da177e4SLinus Torvalds 4291da177e4SLinus Torvalds while (NULL != (chunk = sctp_inq_pop(inqueue))) { 4301da177e4SLinus Torvalds subtype = SCTP_ST_CHUNK(chunk->chunk_hdr->type); 4311da177e4SLinus Torvalds 432bbd0d598SVlad Yasevich /* If the first chunk in the packet is AUTH, do special 433bbd0d598SVlad Yasevich * processing specified in Section 6.3 of SCTP-AUTH spec 434bbd0d598SVlad Yasevich */ 435bbd0d598SVlad Yasevich if (first_time && (subtype.chunk == SCTP_CID_AUTH)) { 436bbd0d598SVlad Yasevich struct sctp_chunkhdr *next_hdr; 437bbd0d598SVlad Yasevich 438bbd0d598SVlad Yasevich next_hdr = sctp_inq_peek(inqueue); 439bbd0d598SVlad Yasevich if (!next_hdr) 440bbd0d598SVlad Yasevich goto normal; 441bbd0d598SVlad Yasevich 442bbd0d598SVlad Yasevich /* If the next chunk is COOKIE-ECHO, skip the AUTH 443bbd0d598SVlad Yasevich * chunk while saving a pointer to it so we can do 444bbd0d598SVlad Yasevich * Authentication later (during cookie-echo 445bbd0d598SVlad Yasevich * processing). 446bbd0d598SVlad Yasevich */ 447bbd0d598SVlad Yasevich if (next_hdr->type == SCTP_CID_COOKIE_ECHO) { 448bbd0d598SVlad Yasevich chunk->auth_chunk = skb_clone(chunk->skb, 449bbd0d598SVlad Yasevich GFP_ATOMIC); 450bbd0d598SVlad Yasevich chunk->auth = 1; 451bbd0d598SVlad Yasevich continue; 452bbd0d598SVlad Yasevich } 453bbd0d598SVlad Yasevich } 454bbd0d598SVlad Yasevich normal: 4551da177e4SLinus Torvalds /* We might have grown an association since last we 4561da177e4SLinus Torvalds * looked, so try again. 4571da177e4SLinus Torvalds * 4581da177e4SLinus Torvalds * This happens when we've just processed our 4591da177e4SLinus Torvalds * COOKIE-ECHO chunk. 4601da177e4SLinus Torvalds */ 4611da177e4SLinus Torvalds if (NULL == chunk->asoc) { 4621da177e4SLinus Torvalds asoc = sctp_endpoint_lookup_assoc(ep, 4631da177e4SLinus Torvalds sctp_source(chunk), 4641da177e4SLinus Torvalds &transport); 4651da177e4SLinus Torvalds chunk->asoc = asoc; 4661da177e4SLinus Torvalds chunk->transport = transport; 4671da177e4SLinus Torvalds } 4681da177e4SLinus Torvalds 4691da177e4SLinus Torvalds state = asoc ? asoc->state : SCTP_STATE_CLOSED; 470bbd0d598SVlad Yasevich if (sctp_auth_recv_cid(subtype.chunk, asoc) && !chunk->auth) 471bbd0d598SVlad Yasevich continue; 4721da177e4SLinus Torvalds 4731da177e4SLinus Torvalds /* Remember where the last DATA chunk came from so we 4741da177e4SLinus Torvalds * know where to send the SACK. 4751da177e4SLinus Torvalds */ 4761da177e4SLinus Torvalds if (asoc && sctp_chunk_is_data(chunk)) 4771da177e4SLinus Torvalds asoc->peer.last_data_from = chunk->transport; 478196d6759SMichele Baldessari else { 479b01a2407SEric W. Biederman SCTP_INC_STATS(sock_net(ep->base.sk), SCTP_MIB_INCTRLCHUNKS); 480196d6759SMichele Baldessari if (asoc) 481196d6759SMichele Baldessari asoc->stats.ictrlchunks++; 482196d6759SMichele Baldessari } 4831da177e4SLinus Torvalds 4841da177e4SLinus Torvalds if (chunk->transport) 4851da177e4SLinus Torvalds chunk->transport->last_time_heard = jiffies; 4861da177e4SLinus Torvalds 48755e26eb9SEric W. Biederman error = sctp_do_sm(net, SCTP_EVENT_T_CHUNK, subtype, state, 4881da177e4SLinus Torvalds ep, asoc, chunk, GFP_ATOMIC); 4891da177e4SLinus Torvalds 4901da177e4SLinus Torvalds if (error && chunk) 4911da177e4SLinus Torvalds chunk->pdiscard = 1; 4921da177e4SLinus Torvalds 4931da177e4SLinus Torvalds /* Check to see if the endpoint is freed in response to 4941da177e4SLinus Torvalds * the incoming chunk. If so, get out of the while loop. 4951da177e4SLinus Torvalds */ 4961da177e4SLinus Torvalds if (!sctp_sk(sk)->ep) 4971da177e4SLinus Torvalds break; 498bbd0d598SVlad Yasevich 499bbd0d598SVlad Yasevich if (first_time) 500bbd0d598SVlad Yasevich first_time = 0; 5011da177e4SLinus Torvalds } 5021da177e4SLinus Torvalds } 503