linux-old/net/sctp/endpointola.c
<<
>>
Prefs
   1/* SCTP kernel reference Implementation
   2 * Copyright (c) 1999-2000 Cisco, Inc.
   3 * Copyright (c) 1999-2001 Motorola, Inc.
   4 * Copyright (c) 2001-2002 International Business Machines, Corp.
   5 * Copyright (c) 2001 Intel Corp.
   6 * Copyright (c) 2001 Nokia, Inc.
   7 * Copyright (c) 2001 La Monte H.P. Yarroll
   8 *
   9 * This file is part of the SCTP kernel reference Implementation
  10 *
  11 * This abstraction represents an SCTP endpoint.
  12 *
  13 * This file is part of the implementation of the add-IP extension,
  14 * based on <draft-ietf-tsvwg-addip-sctp-02.txt> June 29, 2001,
  15 * for the SCTP kernel reference Implementation.
  16 *
  17 * The SCTP reference implementation is free software;
  18 * you can redistribute it and/or modify it under the terms of
  19 * the GNU General Public License as published by
  20 * the Free Software Foundation; either version 2, or (at your option)
  21 * any later version.
  22 *
  23 * The SCTP reference implementation is distributed in the hope that it
  24 * will be useful, but WITHOUT ANY WARRANTY; without even the implied
  25 *                 ************************
  26 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  27 * See the GNU General Public License for more details.
  28 *
  29 * You should have received a copy of the GNU General Public License
  30 * along with GNU CC; see the file COPYING.  If not, write to
  31 * the Free Software Foundation, 59 Temple Place - Suite 330,
  32 * Boston, MA 02111-1307, USA.
  33 *
  34 * Please send any bug reports or fixes you make to the
  35 * email address(es):
  36 *    lksctp developers <lksctp-developers@lists.sourceforge.net>
  37 *
  38 * Or submit a bug report through the following website:
  39 *    http://www.sf.net/projects/lksctp
  40 *
  41 * Written or modified by:
  42 *    La Monte H.P. Yarroll <piggy@acm.org>
  43 *    Karl Knutson <karl@athena.chicago.il.us>
  44 *    Jon Grimm <jgrimm@austin.ibm.com>
  45 *    Daisy Chang <daisyc@us.ibm.com>
  46 *    Dajiang Zhang <dajiang.zhang@nokia.com>
  47 *
  48 * Any bugs reported given to us we will try to fix... any fixes shared will
  49 * be incorporated into the next SCTP release.
  50 */
  51
  52#include <linux/types.h>
  53#include <linux/sched.h>
  54#include <linux/slab.h>
  55#include <linux/in.h>
  56#include <linux/random.h>       /* get_random_bytes() */
  57#include <linux/crypto.h>
  58#include <net/sock.h>
  59#include <net/ipv6.h>
  60#include <net/sctp/sctp.h>
  61#include <net/sctp/sm.h>
  62
  63/* Forward declarations for internal helpers. */
  64static void sctp_endpoint_bh_rcv(struct sctp_endpoint *ep);
  65
  66/*
  67 * Initialize the base fields of the endpoint structure.
  68 */
  69static struct sctp_endpoint *sctp_endpoint_init(struct sctp_endpoint *ep,
  70                                                struct sock *sk, int gfp)
  71{
  72        struct sctp_opt *sp = sctp_sk(sk);
  73        memset(ep, 0, sizeof(struct sctp_endpoint));
  74
  75        /* Initialize the base structure. */
  76        /* What type of endpoint are we?  */
  77        ep->base.type = SCTP_EP_TYPE_SOCKET;
  78
  79        /* Initialize the basic object fields. */
  80        atomic_set(&ep->base.refcnt, 1);
  81        ep->base.dead = 0;
  82        ep->base.malloced = 1;
  83
  84        /* Create an input queue.  */
  85        sctp_inq_init(&ep->base.inqueue);
  86
  87        /* Set its top-half handler */
  88        sctp_inq_set_th_handler(&ep->base.inqueue,
  89                                (void (*)(void *))sctp_endpoint_bh_rcv, ep);
  90
  91        /* Initialize the bind addr area */
  92        sctp_bind_addr_init(&ep->base.bind_addr, 0);
  93        ep->base.addr_lock = RW_LOCK_UNLOCKED;
  94
  95        /* Remember who we are attached to.  */
  96        ep->base.sk = sk;
  97        sock_hold(ep->base.sk);
  98
  99        /* Create the lists of associations.  */
 100        INIT_LIST_HEAD(&ep->asocs);
 101
 102        /* Set up the base timeout information.  */
 103        ep->timeouts[SCTP_EVENT_TIMEOUT_NONE] = 0;
 104        ep->timeouts[SCTP_EVENT_TIMEOUT_T1_COOKIE] =
 105                SCTP_DEFAULT_TIMEOUT_T1_COOKIE;
 106        ep->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT] =
 107                SCTP_DEFAULT_TIMEOUT_T1_INIT;
 108        ep->timeouts[SCTP_EVENT_TIMEOUT_T2_SHUTDOWN] =
 109                SCTP_MSECS_TO_JIFFIES(sp->rtoinfo.srto_initial);
 110        ep->timeouts[SCTP_EVENT_TIMEOUT_T3_RTX] = 0;
 111        ep->timeouts[SCTP_EVENT_TIMEOUT_T4_RTO] = 0;
 112
 113        /* sctpimpguide-05 Section 2.12.2
 114         * If the 'T5-shutdown-guard' timer is used, it SHOULD be set to the
 115         * recommended value of 5 times 'RTO.Max'.
 116         */
 117        ep->timeouts[SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD]
 118                = 5 * SCTP_MSECS_TO_JIFFIES(sp->rtoinfo.srto_max);
 119
 120        ep->timeouts[SCTP_EVENT_TIMEOUT_HEARTBEAT] =
 121                SCTP_DEFAULT_TIMEOUT_HEARTBEAT;
 122        ep->timeouts[SCTP_EVENT_TIMEOUT_SACK] =
 123                SCTP_DEFAULT_TIMEOUT_SACK;
 124        ep->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE] =
 125                sp->autoclose * HZ;
 126
 127        /* Use SCTP specific send buffer space queues.  */
 128        sk->write_space = sctp_write_space;
 129        sk->use_write_queue = 1;
 130
 131        /* Initialize the secret key used with cookie. */
 132        get_random_bytes(&ep->secret_key[0], SCTP_SECRET_SIZE);
 133        ep->last_key = ep->current_key = 0;
 134        ep->key_changed_at = jiffies;
 135
 136        ep->debug_name = "unnamedEndpoint";
 137        return ep;
 138}
 139
 140/* Create a sctp_endpoint with all that boring stuff initialized.
 141 * Returns NULL if there isn't enough memory.
 142 */
 143struct sctp_endpoint *sctp_endpoint_new(struct sock *sk, int gfp)
 144{
 145        struct sctp_endpoint *ep;
 146
 147        /* Build a local endpoint. */
 148        ep = t_new(struct sctp_endpoint, gfp);
 149        if (!ep)
 150                goto fail;
 151        if (!sctp_endpoint_init(ep, sk, gfp))
 152                goto fail_init;
 153        ep->base.malloced = 1;
 154        SCTP_DBG_OBJCNT_INC(ep);
 155        return ep;
 156
 157fail_init:
 158        kfree(ep);
 159fail:
 160        return NULL;
 161}
 162
 163/* Add an association to an endpoint.  */
 164void sctp_endpoint_add_asoc(struct sctp_endpoint *ep,
 165                            struct sctp_association *asoc)
 166{
 167        struct sock *sk = ep->base.sk;
 168
 169        /* Now just add it to our list of asocs */
 170        list_add_tail(&asoc->asocs, &ep->asocs);
 171
 172        /* Increment the backlog value for a TCP-style listening socket. */
 173        if (sctp_style(sk, TCP) && sctp_sstate(sk, LISTENING))
 174                sk->ack_backlog++;
 175}
 176
 177/* Free the endpoint structure.  Delay cleanup until
 178 * all users have released their reference count on this structure.
 179 */
 180void sctp_endpoint_free(struct sctp_endpoint *ep)
 181{
 182        ep->base.dead = 1;
 183        sctp_endpoint_put(ep);
 184}
 185
 186/* Final destructor for endpoint.  */
 187static void sctp_endpoint_destroy(struct sctp_endpoint *ep)
 188{
 189        SCTP_ASSERT(ep->base.dead, "Endpoint is not dead", return);
 190
 191        ep->base.sk->state = SCTP_SS_CLOSED;
 192
 193        /* Unlink this endpoint, so we can't find it again! */
 194        sctp_unhash_endpoint(ep);
 195
 196        /* Free up the HMAC transform. */
 197        if (sctp_sk(ep->base.sk)->hmac)
 198                sctp_crypto_free_tfm(sctp_sk(ep->base.sk)->hmac);
 199
 200        /* Cleanup. */
 201        sctp_inq_free(&ep->base.inqueue);
 202        sctp_bind_addr_free(&ep->base.bind_addr);
 203
 204        /* Remove and free the port */
 205        if (ep->base.sk->prev != NULL)
 206                sctp_put_port(ep->base.sk);
 207
 208        /* Give up our hold on the sock. */
 209        if (ep->base.sk)
 210                sock_put(ep->base.sk);
 211
 212        /* Finally, free up our memory. */
 213        if (ep->base.malloced) {
 214                kfree(ep);
 215                SCTP_DBG_OBJCNT_DEC(ep);
 216        }
 217}
 218
 219/* Hold a reference to an endpoint. */
 220void sctp_endpoint_hold(struct sctp_endpoint *ep)
 221{
 222        atomic_inc(&ep->base.refcnt);
 223}
 224
 225/* Release a reference to an endpoint and clean up if there are
 226 * no more references.
 227 */
 228void sctp_endpoint_put(struct sctp_endpoint *ep)
 229{
 230        if (atomic_dec_and_test(&ep->base.refcnt))
 231                sctp_endpoint_destroy(ep);
 232}
 233
 234/* Is this the endpoint we are looking for?  */
 235struct sctp_endpoint *sctp_endpoint_is_match(struct sctp_endpoint *ep,
 236                                               const union sctp_addr *laddr)
 237{
 238        struct sctp_endpoint *retval;
 239
 240        sctp_read_lock(&ep->base.addr_lock);
 241        if (ep->base.bind_addr.port == laddr->v4.sin_port) {
 242                if (sctp_bind_addr_match(&ep->base.bind_addr, laddr,
 243                                         sctp_sk(ep->base.sk))) {
 244                        retval = ep;
 245                        goto out;
 246                }
 247        }
 248
 249        retval = NULL;
 250
 251out:
 252        sctp_read_unlock(&ep->base.addr_lock);
 253        return retval;
 254}
 255
 256/* Find the association that goes with this chunk.
 257 * We do a linear search of the associations for this endpoint.
 258 * We return the matching transport address too.
 259 */
 260static struct sctp_association *__sctp_endpoint_lookup_assoc(
 261        const struct sctp_endpoint *ep,
 262        const union sctp_addr *paddr,
 263        struct sctp_transport **transport)
 264{
 265        int rport;
 266        struct sctp_association *asoc;
 267        struct list_head *pos;
 268
 269        rport = paddr->v4.sin_port;
 270
 271        list_for_each(pos, &ep->asocs) {
 272                asoc = list_entry(pos, struct sctp_association, asocs);
 273                if (rport == asoc->peer.port) {
 274                        sctp_read_lock(&asoc->base.addr_lock);
 275                        *transport = sctp_assoc_lookup_paddr(asoc, paddr);
 276                        sctp_read_unlock(&asoc->base.addr_lock);
 277
 278                        if (*transport)
 279                                return asoc;
 280                }
 281        }
 282
 283        *transport = NULL;
 284        return NULL;
 285}
 286
 287/* Lookup association on an endpoint based on a peer address.  BH-safe.  */
 288struct sctp_association *sctp_endpoint_lookup_assoc(
 289        const struct sctp_endpoint *ep,
 290        const union sctp_addr *paddr,
 291        struct sctp_transport **transport)
 292{
 293        struct sctp_association *asoc;
 294
 295        sctp_local_bh_disable();
 296        asoc = __sctp_endpoint_lookup_assoc(ep, paddr, transport);
 297        sctp_local_bh_enable();
 298
 299        return asoc;
 300}
 301
 302/* Look for any peeled off association from the endpoint that matches the
 303 * given peer address.
 304 */
 305int sctp_endpoint_is_peeled_off(struct sctp_endpoint *ep,
 306                                const union sctp_addr *paddr)
 307{
 308        struct list_head *pos;
 309        struct sctp_sockaddr_entry *addr;
 310        struct sctp_bind_addr *bp;
 311
 312        sctp_read_lock(&ep->base.addr_lock);
 313        bp = &ep->base.bind_addr;
 314        list_for_each(pos, &bp->address_list) {
 315                addr = list_entry(pos, struct sctp_sockaddr_entry, list);
 316                if (sctp_has_association(&addr->a, paddr)) {
 317                        sctp_read_unlock(&ep->base.addr_lock);
 318                        return 1;
 319                }
 320        }
 321        sctp_read_unlock(&ep->base.addr_lock);
 322
 323        return 0;
 324}
 325
 326/* Do delayed input processing.  This is scheduled by sctp_rcv().
 327 * This may be called on BH or task time.
 328 */
 329static void sctp_endpoint_bh_rcv(struct sctp_endpoint *ep)
 330{
 331        struct sctp_association *asoc;
 332        struct sock *sk;
 333        struct sctp_transport *transport;
 334        struct sctp_chunk *chunk;
 335        struct sctp_inq *inqueue;
 336        sctp_subtype_t subtype;
 337        sctp_state_t state;
 338        int error = 0;
 339
 340        if (ep->base.dead)
 341                return;
 342
 343        asoc = NULL;
 344        inqueue = &ep->base.inqueue;
 345        sk = ep->base.sk;
 346
 347        while (NULL != (chunk = sctp_inq_pop(inqueue))) {
 348                subtype = SCTP_ST_CHUNK(chunk->chunk_hdr->type);
 349
 350                /* We might have grown an association since last we
 351                 * looked, so try again.
 352                 *
 353                 * This happens when we've just processed our
 354                 * COOKIE-ECHO chunk.
 355                 */
 356                if (NULL == chunk->asoc) {
 357                        asoc = sctp_endpoint_lookup_assoc(ep,
 358                                                          sctp_source(chunk),
 359                                                          &transport);
 360                        chunk->asoc = asoc;
 361                        chunk->transport = transport;
 362                }
 363
 364                state = asoc ? asoc->state : SCTP_STATE_CLOSED;
 365
 366                /* Remember where the last DATA chunk came from so we
 367                 * know where to send the SACK.
 368                 */
 369                if (asoc && sctp_chunk_is_data(chunk))
 370                        asoc->peer.last_data_from = chunk->transport;
 371                else
 372                        SCTP_INC_STATS(SctpInCtrlChunks);
 373
 374                if (chunk->transport)
 375                        chunk->transport->last_time_heard = jiffies;
 376
 377                error = sctp_do_sm(SCTP_EVENT_T_CHUNK, subtype, state,
 378                                   ep, asoc, chunk, GFP_ATOMIC);
 379
 380                if (error && chunk)
 381                        chunk->pdiscard = 1;
 382
 383                /* Check to see if the endpoint is freed in response to
 384                 * the incoming chunk. If so, get out of the while loop.
 385                 */
 386                if (!sctp_sk(sk)->ep)
 387                        break;
 388        }
 389}
 390
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.