OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [net/] [sctp/] [endpointola.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/* 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. */
64
static void sctp_endpoint_bh_rcv(struct sctp_endpoint *ep);
65
 
66
/* Create a sctp_endpoint with all that boring stuff initialized.
67
 * Returns NULL if there isn't enough memory.
68
 */
69
struct sctp_endpoint *sctp_endpoint_new(struct sock *sk, int gfp)
70
{
71
        struct sctp_endpoint *ep;
72
 
73
        /* Build a local endpoint. */
74
        ep = t_new(struct sctp_endpoint, gfp);
75
        if (!ep)
76
                goto fail;
77
        if (!sctp_endpoint_init(ep, sk, gfp))
78
                goto fail_init;
79
        ep->base.malloced = 1;
80
        SCTP_DBG_OBJCNT_INC(ep);
81
        return ep;
82
 
83
fail_init:
84
        kfree(ep);
85
fail:
86
        return NULL;
87
}
88
 
89
/*
90
 * Initialize the base fields of the endpoint structure.
91
 */
92
struct sctp_endpoint *sctp_endpoint_init(struct sctp_endpoint *ep,
93
                                         struct sock *sk, int gfp)
94
{
95
        struct sctp_opt *sp = sctp_sk(sk);
96
        memset(ep, 0, sizeof(struct sctp_endpoint));
97
 
98
        /* Initialize the base structure. */
99
        /* What type of endpoint are we?  */
100
        ep->base.type = SCTP_EP_TYPE_SOCKET;
101
 
102
        /* Initialize the basic object fields. */
103
        atomic_set(&ep->base.refcnt, 1);
104
        ep->base.dead = 0;
105
        ep->base.malloced = 1;
106
 
107
        /* Create an input queue.  */
108
        sctp_inq_init(&ep->base.inqueue);
109
 
110
        /* Set its top-half handler */
111
        sctp_inq_set_th_handler(&ep->base.inqueue,
112
                                (void (*)(void *))sctp_endpoint_bh_rcv, ep);
113
 
114
        /* Initialize the bind addr area */
115
        sctp_bind_addr_init(&ep->base.bind_addr, 0);
116
        ep->base.addr_lock = RW_LOCK_UNLOCKED;
117
 
118
        /* Remember who we are attached to.  */
119
        ep->base.sk = sk;
120
        sock_hold(ep->base.sk);
121
 
122
        /* Create the lists of associations.  */
123
        INIT_LIST_HEAD(&ep->asocs);
124
 
125
        /* Set up the base timeout information.  */
126
        ep->timeouts[SCTP_EVENT_TIMEOUT_NONE] = 0;
127
        ep->timeouts[SCTP_EVENT_TIMEOUT_T1_COOKIE] =
128
                SCTP_DEFAULT_TIMEOUT_T1_COOKIE;
129
        ep->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT] =
130
                SCTP_DEFAULT_TIMEOUT_T1_INIT;
131
        ep->timeouts[SCTP_EVENT_TIMEOUT_T2_SHUTDOWN] =
132
                SCTP_MSECS_TO_JIFFIES(sp->rtoinfo.srto_initial);
133
        ep->timeouts[SCTP_EVENT_TIMEOUT_T3_RTX] = 0;
134
        ep->timeouts[SCTP_EVENT_TIMEOUT_T4_RTO] = 0;
135
 
136
        /* sctpimpguide-05 Section 2.12.2
137
         * If the 'T5-shutdown-guard' timer is used, it SHOULD be set to the
138
         * recommended value of 5 times 'RTO.Max'.
139
         */
140
        ep->timeouts[SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD]
141
                = 5 * SCTP_MSECS_TO_JIFFIES(sp->rtoinfo.srto_max);
142
 
143
        ep->timeouts[SCTP_EVENT_TIMEOUT_HEARTBEAT] =
144
                SCTP_DEFAULT_TIMEOUT_HEARTBEAT;
145
        ep->timeouts[SCTP_EVENT_TIMEOUT_SACK] =
146
                SCTP_DEFAULT_TIMEOUT_SACK;
147
        ep->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE] =
148
                sp->autoclose * HZ;
149
 
150
        /* Use SCTP specific send buffer space queues.  */
151
        sk->sk_write_space = sctp_write_space;
152
        sk->sk_use_write_queue = 1;
153
 
154
        /* Initialize the secret key used with cookie. */
155
        get_random_bytes(&ep->secret_key[0], SCTP_SECRET_SIZE);
156
        ep->last_key = ep->current_key = 0;
157
        ep->key_changed_at = jiffies;
158
 
159
        ep->debug_name = "unnamedEndpoint";
160
        return ep;
161
}
162
 
163
/* Add an association to an endpoint.  */
164
void 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->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
 */
180
void 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.  */
187
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->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. */
220
void 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
 */
228
void 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?  */
235
struct 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
 
251
out:
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
 */
260
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.  */
288
struct 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
 */
305
int 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
 */
329
static 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.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
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.