162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* SCTP kernel implementation 362306a36Sopenharmony_ci * Copyright (c) 1999-2000 Cisco, Inc. 462306a36Sopenharmony_ci * Copyright (c) 1999-2001 Motorola, Inc. 562306a36Sopenharmony_ci * Copyright (c) 2001-2002 International Business Machines, Corp. 662306a36Sopenharmony_ci * Copyright (c) 2001 Intel Corp. 762306a36Sopenharmony_ci * Copyright (c) 2001 Nokia, Inc. 862306a36Sopenharmony_ci * Copyright (c) 2001 La Monte H.P. Yarroll 962306a36Sopenharmony_ci * 1062306a36Sopenharmony_ci * This file is part of the SCTP kernel implementation 1162306a36Sopenharmony_ci * 1262306a36Sopenharmony_ci * This abstraction represents an SCTP endpoint. 1362306a36Sopenharmony_ci * 1462306a36Sopenharmony_ci * Please send any bug reports or fixes you make to the 1562306a36Sopenharmony_ci * email address(es): 1662306a36Sopenharmony_ci * lksctp developers <linux-sctp@vger.kernel.org> 1762306a36Sopenharmony_ci * 1862306a36Sopenharmony_ci * Written or modified by: 1962306a36Sopenharmony_ci * La Monte H.P. Yarroll <piggy@acm.org> 2062306a36Sopenharmony_ci * Karl Knutson <karl@athena.chicago.il.us> 2162306a36Sopenharmony_ci * Jon Grimm <jgrimm@austin.ibm.com> 2262306a36Sopenharmony_ci * Daisy Chang <daisyc@us.ibm.com> 2362306a36Sopenharmony_ci * Dajiang Zhang <dajiang.zhang@nokia.com> 2462306a36Sopenharmony_ci */ 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ci#include <linux/types.h> 2762306a36Sopenharmony_ci#include <linux/slab.h> 2862306a36Sopenharmony_ci#include <linux/in.h> 2962306a36Sopenharmony_ci#include <linux/random.h> /* get_random_bytes() */ 3062306a36Sopenharmony_ci#include <net/sock.h> 3162306a36Sopenharmony_ci#include <net/ipv6.h> 3262306a36Sopenharmony_ci#include <net/sctp/sctp.h> 3362306a36Sopenharmony_ci#include <net/sctp/sm.h> 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci/* Forward declarations for internal helpers. */ 3662306a36Sopenharmony_cistatic void sctp_endpoint_bh_rcv(struct work_struct *work); 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ci/* 3962306a36Sopenharmony_ci * Initialize the base fields of the endpoint structure. 4062306a36Sopenharmony_ci */ 4162306a36Sopenharmony_cistatic struct sctp_endpoint *sctp_endpoint_init(struct sctp_endpoint *ep, 4262306a36Sopenharmony_ci struct sock *sk, 4362306a36Sopenharmony_ci gfp_t gfp) 4462306a36Sopenharmony_ci{ 4562306a36Sopenharmony_ci struct net *net = sock_net(sk); 4662306a36Sopenharmony_ci struct sctp_shared_key *null_key; 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ci ep->digest = kzalloc(SCTP_SIGNATURE_SIZE, gfp); 4962306a36Sopenharmony_ci if (!ep->digest) 5062306a36Sopenharmony_ci return NULL; 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ci ep->asconf_enable = net->sctp.addip_enable; 5362306a36Sopenharmony_ci ep->auth_enable = net->sctp.auth_enable; 5462306a36Sopenharmony_ci if (ep->auth_enable) { 5562306a36Sopenharmony_ci if (sctp_auth_init(ep, gfp)) 5662306a36Sopenharmony_ci goto nomem; 5762306a36Sopenharmony_ci if (ep->asconf_enable) { 5862306a36Sopenharmony_ci sctp_auth_ep_add_chunkid(ep, SCTP_CID_ASCONF); 5962306a36Sopenharmony_ci sctp_auth_ep_add_chunkid(ep, SCTP_CID_ASCONF_ACK); 6062306a36Sopenharmony_ci } 6162306a36Sopenharmony_ci } 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ci /* Initialize the base structure. */ 6462306a36Sopenharmony_ci /* What type of endpoint are we? */ 6562306a36Sopenharmony_ci ep->base.type = SCTP_EP_TYPE_SOCKET; 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ci /* Initialize the basic object fields. */ 6862306a36Sopenharmony_ci refcount_set(&ep->base.refcnt, 1); 6962306a36Sopenharmony_ci ep->base.dead = false; 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ci /* Create an input queue. */ 7262306a36Sopenharmony_ci sctp_inq_init(&ep->base.inqueue); 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_ci /* Set its top-half handler */ 7562306a36Sopenharmony_ci sctp_inq_set_th_handler(&ep->base.inqueue, sctp_endpoint_bh_rcv); 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ci /* Initialize the bind addr area */ 7862306a36Sopenharmony_ci sctp_bind_addr_init(&ep->base.bind_addr, 0); 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ci /* Create the lists of associations. */ 8162306a36Sopenharmony_ci INIT_LIST_HEAD(&ep->asocs); 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_ci /* Use SCTP specific send buffer space queues. */ 8462306a36Sopenharmony_ci ep->sndbuf_policy = net->sctp.sndbuf_policy; 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci sk->sk_data_ready = sctp_data_ready; 8762306a36Sopenharmony_ci sk->sk_write_space = sctp_write_space; 8862306a36Sopenharmony_ci sock_set_flag(sk, SOCK_USE_WRITE_QUEUE); 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_ci /* Get the receive buffer policy for this endpoint */ 9162306a36Sopenharmony_ci ep->rcvbuf_policy = net->sctp.rcvbuf_policy; 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci /* Initialize the secret key used with cookie. */ 9462306a36Sopenharmony_ci get_random_bytes(ep->secret_key, sizeof(ep->secret_key)); 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_ci /* SCTP-AUTH extensions*/ 9762306a36Sopenharmony_ci INIT_LIST_HEAD(&ep->endpoint_shared_keys); 9862306a36Sopenharmony_ci null_key = sctp_auth_shkey_create(0, gfp); 9962306a36Sopenharmony_ci if (!null_key) 10062306a36Sopenharmony_ci goto nomem_shkey; 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_ci list_add(&null_key->key_list, &ep->endpoint_shared_keys); 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_ci /* Add the null key to the endpoint shared keys list and 10562306a36Sopenharmony_ci * set the hmcas and chunks pointers. 10662306a36Sopenharmony_ci */ 10762306a36Sopenharmony_ci ep->prsctp_enable = net->sctp.prsctp_enable; 10862306a36Sopenharmony_ci ep->reconf_enable = net->sctp.reconf_enable; 10962306a36Sopenharmony_ci ep->ecn_enable = net->sctp.ecn_enable; 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_ci /* Remember who we are attached to. */ 11262306a36Sopenharmony_ci ep->base.sk = sk; 11362306a36Sopenharmony_ci ep->base.net = sock_net(sk); 11462306a36Sopenharmony_ci sock_hold(ep->base.sk); 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_ci return ep; 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_cinomem_shkey: 11962306a36Sopenharmony_ci sctp_auth_free(ep); 12062306a36Sopenharmony_cinomem: 12162306a36Sopenharmony_ci kfree(ep->digest); 12262306a36Sopenharmony_ci return NULL; 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ci} 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_ci/* Create a sctp_endpoint with all that boring stuff initialized. 12762306a36Sopenharmony_ci * Returns NULL if there isn't enough memory. 12862306a36Sopenharmony_ci */ 12962306a36Sopenharmony_cistruct sctp_endpoint *sctp_endpoint_new(struct sock *sk, gfp_t gfp) 13062306a36Sopenharmony_ci{ 13162306a36Sopenharmony_ci struct sctp_endpoint *ep; 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ci /* Build a local endpoint. */ 13462306a36Sopenharmony_ci ep = kzalloc(sizeof(*ep), gfp); 13562306a36Sopenharmony_ci if (!ep) 13662306a36Sopenharmony_ci goto fail; 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_ci if (!sctp_endpoint_init(ep, sk, gfp)) 13962306a36Sopenharmony_ci goto fail_init; 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_ci SCTP_DBG_OBJCNT_INC(ep); 14262306a36Sopenharmony_ci return ep; 14362306a36Sopenharmony_ci 14462306a36Sopenharmony_cifail_init: 14562306a36Sopenharmony_ci kfree(ep); 14662306a36Sopenharmony_cifail: 14762306a36Sopenharmony_ci return NULL; 14862306a36Sopenharmony_ci} 14962306a36Sopenharmony_ci 15062306a36Sopenharmony_ci/* Add an association to an endpoint. */ 15162306a36Sopenharmony_civoid sctp_endpoint_add_asoc(struct sctp_endpoint *ep, 15262306a36Sopenharmony_ci struct sctp_association *asoc) 15362306a36Sopenharmony_ci{ 15462306a36Sopenharmony_ci struct sock *sk = ep->base.sk; 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_ci /* If this is a temporary association, don't bother 15762306a36Sopenharmony_ci * since we'll be removing it shortly and don't 15862306a36Sopenharmony_ci * want anyone to find it anyway. 15962306a36Sopenharmony_ci */ 16062306a36Sopenharmony_ci if (asoc->temp) 16162306a36Sopenharmony_ci return; 16262306a36Sopenharmony_ci 16362306a36Sopenharmony_ci /* Now just add it to our list of asocs */ 16462306a36Sopenharmony_ci list_add_tail(&asoc->asocs, &ep->asocs); 16562306a36Sopenharmony_ci 16662306a36Sopenharmony_ci /* Increment the backlog value for a TCP-style listening socket. */ 16762306a36Sopenharmony_ci if (sctp_style(sk, TCP) && sctp_sstate(sk, LISTENING)) 16862306a36Sopenharmony_ci sk_acceptq_added(sk); 16962306a36Sopenharmony_ci} 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_ci/* Free the endpoint structure. Delay cleanup until 17262306a36Sopenharmony_ci * all users have released their reference count on this structure. 17362306a36Sopenharmony_ci */ 17462306a36Sopenharmony_civoid sctp_endpoint_free(struct sctp_endpoint *ep) 17562306a36Sopenharmony_ci{ 17662306a36Sopenharmony_ci ep->base.dead = true; 17762306a36Sopenharmony_ci 17862306a36Sopenharmony_ci inet_sk_set_state(ep->base.sk, SCTP_SS_CLOSED); 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_ci /* Unlink this endpoint, so we can't find it again! */ 18162306a36Sopenharmony_ci sctp_unhash_endpoint(ep); 18262306a36Sopenharmony_ci 18362306a36Sopenharmony_ci sctp_endpoint_put(ep); 18462306a36Sopenharmony_ci} 18562306a36Sopenharmony_ci 18662306a36Sopenharmony_ci/* Final destructor for endpoint. */ 18762306a36Sopenharmony_cistatic void sctp_endpoint_destroy_rcu(struct rcu_head *head) 18862306a36Sopenharmony_ci{ 18962306a36Sopenharmony_ci struct sctp_endpoint *ep = container_of(head, struct sctp_endpoint, rcu); 19062306a36Sopenharmony_ci struct sock *sk = ep->base.sk; 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_ci sctp_sk(sk)->ep = NULL; 19362306a36Sopenharmony_ci sock_put(sk); 19462306a36Sopenharmony_ci 19562306a36Sopenharmony_ci kfree(ep); 19662306a36Sopenharmony_ci SCTP_DBG_OBJCNT_DEC(ep); 19762306a36Sopenharmony_ci} 19862306a36Sopenharmony_ci 19962306a36Sopenharmony_cistatic void sctp_endpoint_destroy(struct sctp_endpoint *ep) 20062306a36Sopenharmony_ci{ 20162306a36Sopenharmony_ci struct sock *sk; 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_ci if (unlikely(!ep->base.dead)) { 20462306a36Sopenharmony_ci WARN(1, "Attempt to destroy undead endpoint %p!\n", ep); 20562306a36Sopenharmony_ci return; 20662306a36Sopenharmony_ci } 20762306a36Sopenharmony_ci 20862306a36Sopenharmony_ci /* Free the digest buffer */ 20962306a36Sopenharmony_ci kfree(ep->digest); 21062306a36Sopenharmony_ci 21162306a36Sopenharmony_ci /* SCTP-AUTH: Free up AUTH releated data such as shared keys 21262306a36Sopenharmony_ci * chunks and hmacs arrays that were allocated 21362306a36Sopenharmony_ci */ 21462306a36Sopenharmony_ci sctp_auth_destroy_keys(&ep->endpoint_shared_keys); 21562306a36Sopenharmony_ci sctp_auth_free(ep); 21662306a36Sopenharmony_ci 21762306a36Sopenharmony_ci /* Cleanup. */ 21862306a36Sopenharmony_ci sctp_inq_free(&ep->base.inqueue); 21962306a36Sopenharmony_ci sctp_bind_addr_free(&ep->base.bind_addr); 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_ci memset(ep->secret_key, 0, sizeof(ep->secret_key)); 22262306a36Sopenharmony_ci 22362306a36Sopenharmony_ci sk = ep->base.sk; 22462306a36Sopenharmony_ci /* Remove and free the port */ 22562306a36Sopenharmony_ci if (sctp_sk(sk)->bind_hash) 22662306a36Sopenharmony_ci sctp_put_port(sk); 22762306a36Sopenharmony_ci 22862306a36Sopenharmony_ci call_rcu(&ep->rcu, sctp_endpoint_destroy_rcu); 22962306a36Sopenharmony_ci} 23062306a36Sopenharmony_ci 23162306a36Sopenharmony_ci/* Hold a reference to an endpoint. */ 23262306a36Sopenharmony_ciint sctp_endpoint_hold(struct sctp_endpoint *ep) 23362306a36Sopenharmony_ci{ 23462306a36Sopenharmony_ci return refcount_inc_not_zero(&ep->base.refcnt); 23562306a36Sopenharmony_ci} 23662306a36Sopenharmony_ci 23762306a36Sopenharmony_ci/* Release a reference to an endpoint and clean up if there are 23862306a36Sopenharmony_ci * no more references. 23962306a36Sopenharmony_ci */ 24062306a36Sopenharmony_civoid sctp_endpoint_put(struct sctp_endpoint *ep) 24162306a36Sopenharmony_ci{ 24262306a36Sopenharmony_ci if (refcount_dec_and_test(&ep->base.refcnt)) 24362306a36Sopenharmony_ci sctp_endpoint_destroy(ep); 24462306a36Sopenharmony_ci} 24562306a36Sopenharmony_ci 24662306a36Sopenharmony_ci/* Is this the endpoint we are looking for? */ 24762306a36Sopenharmony_cistruct sctp_endpoint *sctp_endpoint_is_match(struct sctp_endpoint *ep, 24862306a36Sopenharmony_ci struct net *net, 24962306a36Sopenharmony_ci const union sctp_addr *laddr, 25062306a36Sopenharmony_ci int dif, int sdif) 25162306a36Sopenharmony_ci{ 25262306a36Sopenharmony_ci int bound_dev_if = READ_ONCE(ep->base.sk->sk_bound_dev_if); 25362306a36Sopenharmony_ci struct sctp_endpoint *retval = NULL; 25462306a36Sopenharmony_ci 25562306a36Sopenharmony_ci if (net_eq(ep->base.net, net) && 25662306a36Sopenharmony_ci sctp_sk_bound_dev_eq(net, bound_dev_if, dif, sdif) && 25762306a36Sopenharmony_ci (htons(ep->base.bind_addr.port) == laddr->v4.sin_port)) { 25862306a36Sopenharmony_ci if (sctp_bind_addr_match(&ep->base.bind_addr, laddr, 25962306a36Sopenharmony_ci sctp_sk(ep->base.sk))) 26062306a36Sopenharmony_ci retval = ep; 26162306a36Sopenharmony_ci } 26262306a36Sopenharmony_ci 26362306a36Sopenharmony_ci return retval; 26462306a36Sopenharmony_ci} 26562306a36Sopenharmony_ci 26662306a36Sopenharmony_ci/* Find the association that goes with this chunk. 26762306a36Sopenharmony_ci * We lookup the transport from hashtable at first, then get association 26862306a36Sopenharmony_ci * through t->assoc. 26962306a36Sopenharmony_ci */ 27062306a36Sopenharmony_cistruct sctp_association *sctp_endpoint_lookup_assoc( 27162306a36Sopenharmony_ci const struct sctp_endpoint *ep, 27262306a36Sopenharmony_ci const union sctp_addr *paddr, 27362306a36Sopenharmony_ci struct sctp_transport **transport) 27462306a36Sopenharmony_ci{ 27562306a36Sopenharmony_ci struct sctp_association *asoc = NULL; 27662306a36Sopenharmony_ci struct sctp_transport *t; 27762306a36Sopenharmony_ci 27862306a36Sopenharmony_ci *transport = NULL; 27962306a36Sopenharmony_ci 28062306a36Sopenharmony_ci /* If the local port is not set, there can't be any associations 28162306a36Sopenharmony_ci * on this endpoint. 28262306a36Sopenharmony_ci */ 28362306a36Sopenharmony_ci if (!ep->base.bind_addr.port) 28462306a36Sopenharmony_ci return NULL; 28562306a36Sopenharmony_ci 28662306a36Sopenharmony_ci rcu_read_lock(); 28762306a36Sopenharmony_ci t = sctp_epaddr_lookup_transport(ep, paddr); 28862306a36Sopenharmony_ci if (!t) 28962306a36Sopenharmony_ci goto out; 29062306a36Sopenharmony_ci 29162306a36Sopenharmony_ci *transport = t; 29262306a36Sopenharmony_ci asoc = t->asoc; 29362306a36Sopenharmony_ciout: 29462306a36Sopenharmony_ci rcu_read_unlock(); 29562306a36Sopenharmony_ci return asoc; 29662306a36Sopenharmony_ci} 29762306a36Sopenharmony_ci 29862306a36Sopenharmony_ci/* Look for any peeled off association from the endpoint that matches the 29962306a36Sopenharmony_ci * given peer address. 30062306a36Sopenharmony_ci */ 30162306a36Sopenharmony_cibool sctp_endpoint_is_peeled_off(struct sctp_endpoint *ep, 30262306a36Sopenharmony_ci const union sctp_addr *paddr) 30362306a36Sopenharmony_ci{ 30462306a36Sopenharmony_ci int bound_dev_if = READ_ONCE(ep->base.sk->sk_bound_dev_if); 30562306a36Sopenharmony_ci struct sctp_sockaddr_entry *addr; 30662306a36Sopenharmony_ci struct net *net = ep->base.net; 30762306a36Sopenharmony_ci struct sctp_bind_addr *bp; 30862306a36Sopenharmony_ci 30962306a36Sopenharmony_ci bp = &ep->base.bind_addr; 31062306a36Sopenharmony_ci /* This function is called with the socket lock held, 31162306a36Sopenharmony_ci * so the address_list can not change. 31262306a36Sopenharmony_ci */ 31362306a36Sopenharmony_ci list_for_each_entry(addr, &bp->address_list, list) { 31462306a36Sopenharmony_ci if (sctp_has_association(net, &addr->a, paddr, 31562306a36Sopenharmony_ci bound_dev_if, bound_dev_if)) 31662306a36Sopenharmony_ci return true; 31762306a36Sopenharmony_ci } 31862306a36Sopenharmony_ci 31962306a36Sopenharmony_ci return false; 32062306a36Sopenharmony_ci} 32162306a36Sopenharmony_ci 32262306a36Sopenharmony_ci/* Do delayed input processing. This is scheduled by sctp_rcv(). 32362306a36Sopenharmony_ci * This may be called on BH or task time. 32462306a36Sopenharmony_ci */ 32562306a36Sopenharmony_cistatic void sctp_endpoint_bh_rcv(struct work_struct *work) 32662306a36Sopenharmony_ci{ 32762306a36Sopenharmony_ci struct sctp_endpoint *ep = 32862306a36Sopenharmony_ci container_of(work, struct sctp_endpoint, 32962306a36Sopenharmony_ci base.inqueue.immediate); 33062306a36Sopenharmony_ci struct sctp_association *asoc; 33162306a36Sopenharmony_ci struct sock *sk; 33262306a36Sopenharmony_ci struct net *net; 33362306a36Sopenharmony_ci struct sctp_transport *transport; 33462306a36Sopenharmony_ci struct sctp_chunk *chunk; 33562306a36Sopenharmony_ci struct sctp_inq *inqueue; 33662306a36Sopenharmony_ci union sctp_subtype subtype; 33762306a36Sopenharmony_ci enum sctp_state state; 33862306a36Sopenharmony_ci int error = 0; 33962306a36Sopenharmony_ci int first_time = 1; /* is this the first time through the loop */ 34062306a36Sopenharmony_ci 34162306a36Sopenharmony_ci if (ep->base.dead) 34262306a36Sopenharmony_ci return; 34362306a36Sopenharmony_ci 34462306a36Sopenharmony_ci asoc = NULL; 34562306a36Sopenharmony_ci inqueue = &ep->base.inqueue; 34662306a36Sopenharmony_ci sk = ep->base.sk; 34762306a36Sopenharmony_ci net = sock_net(sk); 34862306a36Sopenharmony_ci 34962306a36Sopenharmony_ci while (NULL != (chunk = sctp_inq_pop(inqueue))) { 35062306a36Sopenharmony_ci subtype = SCTP_ST_CHUNK(chunk->chunk_hdr->type); 35162306a36Sopenharmony_ci 35262306a36Sopenharmony_ci /* If the first chunk in the packet is AUTH, do special 35362306a36Sopenharmony_ci * processing specified in Section 6.3 of SCTP-AUTH spec 35462306a36Sopenharmony_ci */ 35562306a36Sopenharmony_ci if (first_time && (subtype.chunk == SCTP_CID_AUTH)) { 35662306a36Sopenharmony_ci struct sctp_chunkhdr *next_hdr; 35762306a36Sopenharmony_ci 35862306a36Sopenharmony_ci next_hdr = sctp_inq_peek(inqueue); 35962306a36Sopenharmony_ci if (!next_hdr) 36062306a36Sopenharmony_ci goto normal; 36162306a36Sopenharmony_ci 36262306a36Sopenharmony_ci /* If the next chunk is COOKIE-ECHO, skip the AUTH 36362306a36Sopenharmony_ci * chunk while saving a pointer to it so we can do 36462306a36Sopenharmony_ci * Authentication later (during cookie-echo 36562306a36Sopenharmony_ci * processing). 36662306a36Sopenharmony_ci */ 36762306a36Sopenharmony_ci if (next_hdr->type == SCTP_CID_COOKIE_ECHO) { 36862306a36Sopenharmony_ci chunk->auth_chunk = skb_clone(chunk->skb, 36962306a36Sopenharmony_ci GFP_ATOMIC); 37062306a36Sopenharmony_ci chunk->auth = 1; 37162306a36Sopenharmony_ci continue; 37262306a36Sopenharmony_ci } 37362306a36Sopenharmony_ci } 37462306a36Sopenharmony_cinormal: 37562306a36Sopenharmony_ci /* We might have grown an association since last we 37662306a36Sopenharmony_ci * looked, so try again. 37762306a36Sopenharmony_ci * 37862306a36Sopenharmony_ci * This happens when we've just processed our 37962306a36Sopenharmony_ci * COOKIE-ECHO chunk. 38062306a36Sopenharmony_ci */ 38162306a36Sopenharmony_ci if (NULL == chunk->asoc) { 38262306a36Sopenharmony_ci asoc = sctp_endpoint_lookup_assoc(ep, 38362306a36Sopenharmony_ci sctp_source(chunk), 38462306a36Sopenharmony_ci &transport); 38562306a36Sopenharmony_ci chunk->asoc = asoc; 38662306a36Sopenharmony_ci chunk->transport = transport; 38762306a36Sopenharmony_ci } 38862306a36Sopenharmony_ci 38962306a36Sopenharmony_ci state = asoc ? asoc->state : SCTP_STATE_CLOSED; 39062306a36Sopenharmony_ci if (sctp_auth_recv_cid(subtype.chunk, asoc) && !chunk->auth) 39162306a36Sopenharmony_ci continue; 39262306a36Sopenharmony_ci 39362306a36Sopenharmony_ci /* Remember where the last DATA chunk came from so we 39462306a36Sopenharmony_ci * know where to send the SACK. 39562306a36Sopenharmony_ci */ 39662306a36Sopenharmony_ci if (asoc && sctp_chunk_is_data(chunk)) 39762306a36Sopenharmony_ci asoc->peer.last_data_from = chunk->transport; 39862306a36Sopenharmony_ci else { 39962306a36Sopenharmony_ci SCTP_INC_STATS(ep->base.net, SCTP_MIB_INCTRLCHUNKS); 40062306a36Sopenharmony_ci if (asoc) 40162306a36Sopenharmony_ci asoc->stats.ictrlchunks++; 40262306a36Sopenharmony_ci } 40362306a36Sopenharmony_ci 40462306a36Sopenharmony_ci if (chunk->transport) 40562306a36Sopenharmony_ci chunk->transport->last_time_heard = ktime_get(); 40662306a36Sopenharmony_ci 40762306a36Sopenharmony_ci error = sctp_do_sm(net, SCTP_EVENT_T_CHUNK, subtype, state, 40862306a36Sopenharmony_ci ep, asoc, chunk, GFP_ATOMIC); 40962306a36Sopenharmony_ci 41062306a36Sopenharmony_ci if (error && chunk) 41162306a36Sopenharmony_ci chunk->pdiscard = 1; 41262306a36Sopenharmony_ci 41362306a36Sopenharmony_ci /* Check to see if the endpoint is freed in response to 41462306a36Sopenharmony_ci * the incoming chunk. If so, get out of the while loop. 41562306a36Sopenharmony_ci */ 41662306a36Sopenharmony_ci if (!sctp_sk(sk)->ep) 41762306a36Sopenharmony_ci break; 41862306a36Sopenharmony_ci 41962306a36Sopenharmony_ci if (first_time) 42062306a36Sopenharmony_ci first_time = 0; 42162306a36Sopenharmony_ci } 42262306a36Sopenharmony_ci} 423