Linux Audio

Check our new training course

Embedded Linux Audio

Check our new training course
with Creative Commons CC-BY-SA
lecture materials

Bootlin logo

Elixir Cross Referencer

Loading...
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
/* SCTP kernel reference Implementation
 * Copyright (c) 1999-2000 Cisco, Inc.
 * Copyright (c) 1999-2001 Motorola, Inc.
 * Copyright (c) 2001 Intel Corp.
 * Copyright (c) 2001-2002 International Business Machines Corp.
 * 
 * This file is part of the SCTP kernel reference Implementation
 * 
 * This file is part of the implementation of the add-IP extension,
 * based on <draft-ietf-tsvwg-addip-sctp-02.txt> June 29, 2001,
 * for the SCTP kernel reference Implementation.
 * 
 * These are definitions needed by the state machine.
 * 
 * The SCTP reference implementation is free software; 
 * you can redistribute it and/or modify it under the terms of 
 * the GNU General Public License as published by
 * the Free Software Foundation; either version 2, or (at your option)
 * any later version.
 * 
 * The SCTP reference implementation is distributed in the hope that it 
 * will be useful, but WITHOUT ANY WARRANTY; without even the implied
 *                 ************************
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with GNU CC; see the file COPYING.  If not, write to
 * the Free Software Foundation, 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.  
 * 
 * Please send any bug reports or fixes you make to the
 * email addresses:
 *    lksctp developers <lksctp-developers@lists.sourceforge.net>
 * 
 * Or submit a bug report through the following website:
 *    http://www.sf.net/projects/lksctp
 *
 * Written or modified by: 
 *    La Monte H.P. Yarroll <piggy@acm.org>
 *    Karl Knutson <karl@athena.chicago.il.us>
 *    Xingang Guo <xingang.guo@intel.com>
 *    Jon Grimm <jgrimm@us.ibm.com>
 *    Dajiang Zhang <dajiang.zhang@nokia.com>
 *    Sridhar Samudrala <sri@us.ibm.com>
 *    Daisy Chang <daisyc@us.ibm.com>
 *    Ardelle Fan <ardelle.fan@intel.com>
 *
 * Any bugs reported given to us we will try to fix... any fixes shared will
 * be incorporated into the next SCTP release.
 */


#include <linux/types.h>
#include <linux/compiler.h>
#include <linux/slab.h>
#include <linux/in.h>
#include <net/sctp/command.h>
#include <net/sctp/sctp.h>

#ifndef __sctp_sm_h__
#define __sctp_sm_h__

/*
 * Possible values for the disposition are:
 */
typedef enum {
	SCTP_DISPOSITION_DISCARD,	 /* No further processing.  */
	SCTP_DISPOSITION_CONSUME,	 /* Process return values normally.  */
	SCTP_DISPOSITION_NOMEM,		 /* We ran out of memory--recover.  */
	SCTP_DISPOSITION_DELETE_TCB,	 /* Close the association.  */
	SCTP_DISPOSITION_ABORT,		 /* Close the association NOW.  */
	SCTP_DISPOSITION_VIOLATION,	 /* The peer is misbehaving.  */
	SCTP_DISPOSITION_NOT_IMPL,	 /* This entry is not implemented.  */
	SCTP_DISPOSITION_ERROR,		 /* This is plain old user error.  */
	SCTP_DISPOSITION_BUG,		 /* This is a bug.  */
} sctp_disposition_t;

typedef struct {
	int name;
	int action;
} sctp_sm_command_t;

typedef sctp_disposition_t (sctp_state_fn_t) (const sctp_endpoint_t *,
					      const sctp_association_t *,
					      const sctp_subtype_t type,
					      void *arg,
					      sctp_cmd_seq_t *);
typedef void (sctp_timer_event_t) (unsigned long);
typedef struct {
	sctp_state_fn_t *fn;
	char *name;
} sctp_sm_table_entry_t;

/* A naming convention of "sctp_sf_xxx" applies to all the state functions
 * currently in use.
 */

/* Prototypes for generic state functions. */
sctp_state_fn_t sctp_sf_not_impl;
sctp_state_fn_t sctp_sf_bug;

/* Prototypes for gener timer state functions. */
sctp_state_fn_t sctp_sf_timer_ignore;

/* Prototypes for chunk state functions. */
sctp_state_fn_t sctp_sf_do_9_1_abort;
sctp_state_fn_t sctp_sf_cookie_wait_abort;
sctp_state_fn_t sctp_sf_cookie_echoed_abort;
sctp_state_fn_t sctp_sf_shutdown_pending_abort;
sctp_state_fn_t sctp_sf_shutdown_sent_abort;
sctp_state_fn_t sctp_sf_shutdown_ack_sent_abort;
sctp_state_fn_t sctp_sf_do_5_1B_init;
sctp_state_fn_t sctp_sf_do_5_1C_ack;
sctp_state_fn_t sctp_sf_do_5_1D_ce;
sctp_state_fn_t sctp_sf_do_5_1E_ca;
sctp_state_fn_t sctp_sf_do_4_C;
sctp_state_fn_t sctp_sf_eat_data_6_2;
sctp_state_fn_t sctp_sf_eat_data_fast_4_4;
sctp_state_fn_t sctp_sf_eat_sack_6_2;
sctp_state_fn_t sctp_sf_tabort_8_4_8;
sctp_state_fn_t sctp_sf_operr_notify;
sctp_state_fn_t sctp_sf_t1_timer_expire;
sctp_state_fn_t sctp_sf_t2_timer_expire;
sctp_state_fn_t sctp_sf_t5_timer_expire;
sctp_state_fn_t sctp_sf_sendbeat_8_3;
sctp_state_fn_t sctp_sf_beat_8_3;
sctp_state_fn_t sctp_sf_backbeat_8_3;
sctp_state_fn_t sctp_sf_do_9_2_final;
sctp_state_fn_t sctp_sf_do_9_2_shutdown;
sctp_state_fn_t sctp_sf_do_ecn_cwr;
sctp_state_fn_t sctp_sf_do_ecne;
sctp_state_fn_t sctp_sf_ootb;
sctp_state_fn_t sctp_sf_shut_8_4_5;
sctp_state_fn_t sctp_sf_pdiscard;
sctp_state_fn_t sctp_sf_violation;
sctp_state_fn_t sctp_sf_discard_chunk;
sctp_state_fn_t sctp_sf_do_5_2_1_siminit;
sctp_state_fn_t sctp_sf_do_5_2_2_dupinit;
sctp_state_fn_t sctp_sf_do_5_2_4_dupcook;
sctp_state_fn_t sctp_sf_unk_chunk;
sctp_state_fn_t sctp_sf_do_8_5_1_E_sa;
sctp_state_fn_t sctp_sf_cookie_echoed_err;
sctp_state_fn_t sctp_sf_do_5_2_6_stale;

/* Prototypes for primitive event state functions.  */
sctp_state_fn_t sctp_sf_do_prm_asoc;
sctp_state_fn_t sctp_sf_do_prm_send;
sctp_state_fn_t sctp_sf_do_9_2_prm_shutdown;
sctp_state_fn_t sctp_sf_cookie_wait_prm_shutdown;
sctp_state_fn_t sctp_sf_cookie_echoed_prm_shutdown;
sctp_state_fn_t sctp_sf_do_9_1_prm_abort;
sctp_state_fn_t sctp_sf_cookie_wait_prm_abort;
sctp_state_fn_t sctp_sf_cookie_echoed_prm_abort;
sctp_state_fn_t sctp_sf_shutdown_pending_prm_abort;
sctp_state_fn_t sctp_sf_shutdown_sent_prm_abort;
sctp_state_fn_t sctp_sf_shutdown_ack_sent_prm_abort;
sctp_state_fn_t sctp_sf_error_closed;
sctp_state_fn_t sctp_sf_error_shutdown;
sctp_state_fn_t sctp_sf_ignore_primitive;
sctp_state_fn_t sctp_sf_do_prm_requestheartbeat;

/* Prototypes for other event state functions.  */
sctp_state_fn_t sctp_sf_do_9_2_start_shutdown;
sctp_state_fn_t sctp_sf_do_9_2_shutdown_ack;
sctp_state_fn_t sctp_sf_ignore_other;

/* Prototypes for timeout event state functions.  */
sctp_state_fn_t sctp_sf_do_6_3_3_rtx;
sctp_state_fn_t sctp_sf_do_6_2_sack;
sctp_state_fn_t sctp_sf_autoclose_timer_expire;


/* These are state functions which are either obsolete or not in use yet.
 * If any of these functions needs to be revived, it should be renamed with
 * the "sctp_sf_xxx" prefix, and be moved to the above prototype groups.
 */

/* Prototypes for chunk state functions.  Not in use. */
sctp_state_fn_t sctp_sf_do_9_2_reshutack;
sctp_state_fn_t sctp_sf_do_9_2_reshut;
sctp_state_fn_t sctp_sf_do_9_2_shutack;

sctp_state_fn_t lucky;
sctp_state_fn_t other_stupid;

/* Prototypes for timeout event state functions.  Not in use. */
sctp_state_fn_t sctp_do_4_2_reinit;
sctp_state_fn_t sctp_do_4_3_reecho;
sctp_state_fn_t sctp_do_9_2_reshut;
sctp_state_fn_t sctp_do_9_2_reshutack;
sctp_state_fn_t sctp_do_8_3_hb_err;
sctp_state_fn_t sctp_heartoff;

/* Prototypes for addip related state functions.  Not in use. */
sctp_state_fn_t sctp_addip_do_asconf;
sctp_state_fn_t sctp_addip_do_asconf_ack;

/* Prototypes for utility support functions.  */
__u8 sctp_get_chunk_type(sctp_chunk_t *chunk);
sctp_sm_table_entry_t *sctp_sm_lookup_event(sctp_event_t event_type,
					    sctp_state_t state,
					    sctp_subtype_t event_subtype);

time_t timeval_sub(struct timeval *, struct timeval *);
sctp_association_t *sctp_make_temp_asoc(const sctp_endpoint_t *,
					sctp_chunk_t *,
					const int priority);
__u32 sctp_generate_verification_tag(void);
void sctp_populate_tie_tags(__u8 *cookie, __u32 curTag, __u32 hisTag);

/* Prototypes for chunk-building functions.  */
sctp_chunk_t *sctp_make_init(const sctp_association_t *,
			     const sctp_bind_addr_t *,
			     int priority, int vparam_len);
sctp_chunk_t *sctp_make_init_ack(const sctp_association_t *,
				 const sctp_chunk_t *,
				 const int priority,
				 const int unkparam_len);
sctp_chunk_t *sctp_make_cookie_echo(const sctp_association_t *,
				    const sctp_chunk_t *);
sctp_chunk_t *sctp_make_cookie_ack(const sctp_association_t *,
				   const sctp_chunk_t *);
sctp_chunk_t *sctp_make_cwr(const sctp_association_t *,
				 const __u32 lowest_tsn,
				 const sctp_chunk_t *);
sctp_chunk_t *sctp_make_datafrag(sctp_association_t *,
				 const struct sctp_sndrcvinfo *sinfo,
				 int len, const __u8 *data,
				 __u8 flags, __u16 ssn);
sctp_chunk_t * sctp_make_datafrag_empty(sctp_association_t *,
					const struct sctp_sndrcvinfo *sinfo,
					int len, const __u8 flags,
					__u16 ssn);
sctp_chunk_t *sctp_make_data(sctp_association_t *,
			     const struct sctp_sndrcvinfo *sinfo,
			     int len, const __u8 *data);
sctp_chunk_t *sctp_make_data_empty(sctp_association_t *,
				   const struct sctp_sndrcvinfo *, int len);
sctp_chunk_t *sctp_make_ecne(const sctp_association_t *,
				  const __u32);
sctp_chunk_t *sctp_make_sack(const sctp_association_t *);
sctp_chunk_t *sctp_make_shutdown(const sctp_association_t *asoc);
sctp_chunk_t *sctp_make_shutdown_ack(const sctp_association_t *asoc,
					  const sctp_chunk_t *);
sctp_chunk_t *sctp_make_shutdown_complete(const sctp_association_t *,
					  const sctp_chunk_t *);
void sctp_init_cause(sctp_chunk_t *, __u16 cause, const void *, size_t);
sctp_chunk_t *sctp_make_abort(const sctp_association_t *,
			      const sctp_chunk_t *,
			      const size_t hint);
sctp_chunk_t *sctp_make_abort_no_data(const sctp_association_t *,
				      const sctp_chunk_t *,
				      __u32 tsn);
sctp_chunk_t *sctp_make_abort_user(const sctp_association_t *,
				   const sctp_chunk_t *,
				   const struct msghdr *);
sctp_chunk_t *sctp_make_heartbeat(const sctp_association_t *,
				  const struct sctp_transport *,
				  const void *payload,
				  const size_t paylen);
sctp_chunk_t *sctp_make_heartbeat_ack(const sctp_association_t *,
				      const sctp_chunk_t *,
				      const void *payload,
				      const size_t paylen);
sctp_chunk_t *sctp_make_op_error(const sctp_association_t *,
				 const sctp_chunk_t *chunk,
				 __u16 cause_code,
				 const void *payload,
				 size_t paylen);
void sctp_chunk_assign_tsn(sctp_chunk_t *);
void sctp_chunk_assign_ssn(sctp_chunk_t *);
int sctp_datachunks_from_user(sctp_association_t *,
			      const struct sctp_sndrcvinfo *,
			      struct msghdr *, int len,
			      struct sk_buff_head *);


/* Prototypes for statetable processing. */

int sctp_do_sm(sctp_event_t event_type, sctp_subtype_t subtype,
	       sctp_state_t state,
               sctp_endpoint_t *,
               sctp_association_t *asoc,
               void *event_arg,
               int priority);

int sctp_side_effects(sctp_event_t event_type, sctp_subtype_t subtype,
		      sctp_state_t state,
                      sctp_endpoint_t *,
                      sctp_association_t *asoc,
                      void *event_arg,
                      sctp_disposition_t status,
		      sctp_cmd_seq_t *commands,
                      int priority);

/* 2nd level prototypes */
int
sctp_cmd_interpreter(sctp_event_t event_type, sctp_subtype_t subtype,
		     sctp_state_t state,
		     sctp_endpoint_t *ep,
		     sctp_association_t *asoc,
		     void *event_arg,
		     sctp_disposition_t status,
		     sctp_cmd_seq_t *retval,
		     int priority);


int sctp_gen_sack(sctp_association_t *, int force, sctp_cmd_seq_t *);
void sctp_do_TSNdup(sctp_association_t *, sctp_chunk_t *, long gap);

void sctp_generate_t3_rtx_event(unsigned long peer);
void sctp_generate_heartbeat_event(unsigned long peer);

sctp_sackhdr_t *sctp_sm_pull_sack(sctp_chunk_t *);
sctp_packet_t *sctp_abort_pkt_new(const sctp_endpoint_t *ep,
				  const sctp_association_t *asoc,
				  sctp_chunk_t *chunk,
				  const void *payload,
				  size_t paylen);
sctp_packet_t *sctp_ootb_pkt_new(const sctp_association_t *asoc,
				 const sctp_chunk_t *chunk);
void sctp_ootb_pkt_free(sctp_packet_t *packet);

sctp_cookie_param_t *
sctp_pack_cookie(const sctp_endpoint_t *, const sctp_association_t *,
		 const sctp_chunk_t *, int *cookie_len,
		 const __u8 *, int addrs_len);
sctp_association_t *sctp_unpack_cookie(const sctp_endpoint_t *,
				       const sctp_association_t *,
				       sctp_chunk_t *, int priority, int *err,
				       sctp_chunk_t **err_chk_p);
int sctp_addip_addr_config(sctp_association_t *, sctp_param_t,
			   struct sockaddr_storage*, int);
void sctp_send_stale_cookie_err(const sctp_endpoint_t *ep,
				const sctp_association_t *asoc,
				const sctp_chunk_t *chunk,
				sctp_cmd_seq_t *commands,
				sctp_chunk_t *err_chunk);

/* 3rd level prototypes */
__u32 sctp_generate_tag(const sctp_endpoint_t *);
__u32 sctp_generate_tsn(const sctp_endpoint_t *);

/* 4th level prototypes */
void sctp_param2sockaddr(union sctp_addr *addr, sctp_addr_param_t *,
			 __u16 port);
int sctp_addr2sockaddr(const union sctp_params, union sctp_addr *);
int sockaddr2sctp_addr(const union sctp_addr *, sctp_addr_param_t *);

/* Extern declarations for major data structures.  */
sctp_sm_table_entry_t *sctp_chunk_event_lookup(sctp_cid_t, sctp_state_t);
extern sctp_sm_table_entry_t
primitive_event_table[SCTP_NUM_PRIMITIVE_TYPES][SCTP_STATE_NUM_STATES];
extern sctp_sm_table_entry_t
other_event_table[SCTP_NUM_OTHER_TYPES][SCTP_STATE_NUM_STATES];
extern sctp_sm_table_entry_t
timeout_event_table[SCTP_NUM_TIMEOUT_TYPES][SCTP_STATE_NUM_STATES];
extern sctp_timer_event_t *sctp_timer_events[SCTP_NUM_TIMEOUT_TYPES];

/* These are some handy utility macros... */


/* Get the size of a DATA chunk payload. */
static inline __u16 sctp_data_size(sctp_chunk_t *chunk)
{
	__u16 size;

	size = ntohs(chunk->chunk_hdr->length);
	size -= sizeof(sctp_data_chunk_t);

	return size;
}

/* Compare two TSNs */

/* RFC 1982 - Serial Number Arithmetic
 *
 * 2. Comparison
 *  Then, s1 is said to be equal to s2 if and only if i1 is equal to i2,
 *  in all other cases, s1 is not equal to s2.
 *
 * s1 is said to be less than s2 if, and only if, s1 is not equal to s2,
 * and
 *
 *      (i1 < i2 and i2 - i1 < 2^(SERIAL_BITS - 1)) or
 *      (i1 > i2 and i1 - i2 > 2^(SERIAL_BITS - 1))
 *
 * s1 is said to be greater than s2 if, and only if, s1 is not equal to
 * s2, and
 *
 *      (i1 < i2 and i2 - i1 > 2^(SERIAL_BITS - 1)) or
 *      (i1 > i2 and i1 - i2 < 2^(SERIAL_BITS - 1))
 */

/*
 * RFC 2960
 *  1.6 Serial Number Arithmetic
 *
 * Comparisons and arithmetic on TSNs in this document SHOULD use Serial
 * Number Arithmetic as defined in [RFC1982] where SERIAL_BITS = 32.
 */

enum {
	TSN_SIGN_BIT = (1<<31)
};

static inline int TSN_lt(__u32 s, __u32 t)
{
	return (((s) - (t)) & TSN_SIGN_BIT);
}

static inline int TSN_lte(__u32 s, __u32 t)
{
	return (((s) == (t)) || (((s) - (t)) & TSN_SIGN_BIT));
}

/* Compare two SSNs */

/*
 * RFC 2960
 *  1.6 Serial Number Arithmetic
 *
 * Comparisons and arithmetic on Stream Sequence Numbers in this document
 * SHOULD use Serial Number Arithmetic as defined in [RFC1982] where
 * SERIAL_BITS = 16.
 */
enum {
	SSN_SIGN_BIT = (1<<15)
};

static inline int SSN_lt(__u16 s, __u16 t)
{
	return (((s) - (t)) & SSN_SIGN_BIT);
}

static inline int SSN_lte(__u16 s, __u16 t)
{
	return (((s) == (t)) || (((s) - (t)) & SSN_SIGN_BIT));
}

/* Run sctp_add_cmd() generating a BUG() if there is a failure.  */
static inline void sctp_add_cmd_sf(sctp_cmd_seq_t *seq, sctp_verb_t verb, sctp_arg_t obj)
{
	if (unlikely(!sctp_add_cmd(seq, verb, obj)))
		BUG();
}

/* Check VTAG of the packet matches the sender's own tag OR its peer's
 * tag and the T bit is set in the Chunk Flags.
 */
static inline int
sctp_vtag_verify_either(const sctp_chunk_t *chunk,
			const sctp_association_t *asoc)
{
        /* RFC 2960 Section 8.5.1, sctpimpguide-06 Section 2.13.2
	 *
	 * B) The receiver of a ABORT shall accept the packet if the
	 * Verification Tag field of the packet matches its own tag OR it
	 * is set to its peer's tag and the T bit is set in the Chunk
	 * Flags. Otherwise, the receiver MUST silently discard the packet
	 * and take no further action.
	 *
	 * (C) The receiver of a SHUTDOWN COMPLETE shall accept the
	 * packet if the Verification Tag field of the packet
	 * matches its own tag OR it is set to its peer's tag and
	 * the T bit is set in the Chunk Flags.  Otherwise, the
	 * receiver MUST silently discard the packet and take no
	 * further action....
	 *
	 */
        if ((ntohl(chunk->sctp_hdr->vtag) == asoc->c.my_vtag) ||
	    (sctp_test_T_bit(chunk) && (ntohl(chunk->sctp_hdr->vtag)
	    == asoc->c.peer_vtag))) {
                return 1;
	}

	return 0;
}

#endif /* __sctp_sm_h__ */