sm.h 15.6 KB
Newer Older
1
/* SCTP kernel implementation
L
Linus Torvalds 已提交
2 3 4 5 6
 * (C) Copyright IBM Corp. 2001, 2004
 * Copyright (c) 1999-2000 Cisco, Inc.
 * Copyright (c) 1999-2001 Motorola, Inc.
 * Copyright (c) 2001 Intel Corp.
 *
7
 * This file is part of the SCTP kernel implementation
L
Linus Torvalds 已提交
8 9 10
 *
 * These are definitions needed by the state machine.
 *
11
 * This SCTP implementation is free software;
L
Linus Torvalds 已提交
12 13 14 15 16
 * 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.
 *
17
 * This SCTP implementation is distributed in the hope that it
L
Linus Torvalds 已提交
18 19 20 21 22 23
 * 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
24 25
 * along with GNU CC; see the file COPYING.  If not, see
 * <http://www.gnu.org/licenses/>.
L
Linus Torvalds 已提交
26 27 28
 *
 * Please send any bug reports or fixes you make to the
 * email addresses:
29
 *    lksctp developers <linux-sctp@vger.kernel.org>
L
Linus Torvalds 已提交
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
 *
 * 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>
 *    Kevin Gao <kevin.gao@intel.com>
 */

#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;

68 69
typedef sctp_disposition_t (sctp_state_fn_t) (struct net *,
					      const struct sctp_endpoint *,
L
Linus Torvalds 已提交
70
					      const struct sctp_association *,
71
					      const union sctp_subtype type,
L
Linus Torvalds 已提交
72
					      void *arg,
73
					      struct sctp_cmd_seq *);
L
Linus Torvalds 已提交
74
typedef void (sctp_timer_event_t) (unsigned long);
75
struct sctp_sm_table_entry {
L
Linus Torvalds 已提交
76 77
	sctp_state_fn_t *fn;
	const char *name;
78
};
L
Linus Torvalds 已提交
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

/* 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_operr_notify;
F
Frank Filz 已提交
107 108
sctp_state_fn_t sctp_sf_t1_init_timer_expire;
sctp_state_fn_t sctp_sf_t1_cookie_timer_expire;
L
Linus Torvalds 已提交
109 110 111 112 113 114 115 116
sctp_state_fn_t sctp_sf_t2_timer_expire;
sctp_state_fn_t sctp_sf_t4_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;
117
sctp_state_fn_t sctp_sf_do_9_2_shut_ctsn;
L
Linus Torvalds 已提交
118 119 120 121 122 123 124 125
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_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;
126
sctp_state_fn_t sctp_sf_do_5_2_3_initack;
L
Linus Torvalds 已提交
127 128 129 130 131 132
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_asconf;
sctp_state_fn_t sctp_sf_do_asconf_ack;
X
Xin Long 已提交
133
sctp_state_fn_t sctp_sf_do_reconf;
L
Linus Torvalds 已提交
134 135 136
sctp_state_fn_t sctp_sf_do_9_2_reshutack;
sctp_state_fn_t sctp_sf_eat_fwd_tsn;
sctp_state_fn_t sctp_sf_eat_fwd_tsn_fast;
137
sctp_state_fn_t sctp_sf_eat_auth;
L
Linus Torvalds 已提交
138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155

/* 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;
sctp_state_fn_t sctp_sf_do_prm_asconf;
X
Xin Long 已提交
156
sctp_state_fn_t sctp_sf_do_prm_reconf;
L
Linus Torvalds 已提交
157 158

/* Prototypes for other event state functions.  */
159
sctp_state_fn_t sctp_sf_do_no_pending_tsn;
L
Linus Torvalds 已提交
160 161 162 163 164 165 166
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;
sctp_state_fn_t sctp_sf_cookie_wait_icmp_abort;

/* Prototypes for timeout event state functions.  */
sctp_state_fn_t sctp_sf_do_6_3_3_rtx;
X
Xin Long 已提交
167
sctp_state_fn_t sctp_sf_send_reconf;
L
Linus Torvalds 已提交
168 169 170 171 172
sctp_state_fn_t sctp_sf_do_6_2_sack;
sctp_state_fn_t sctp_sf_autoclose_timer_expire;

/* Prototypes for utility support functions.  */
__u8 sctp_get_chunk_type(struct sctp_chunk *chunk);
173
const struct sctp_sm_table_entry *sctp_sm_lookup_event(
174 175 176 177
					struct net *net,
					enum sctp_event event_type,
					enum sctp_state state,
					union sctp_subtype event_subtype);
L
Linus Torvalds 已提交
178 179 180
int sctp_chunk_iif(const struct sctp_chunk *);
struct sctp_association *sctp_make_temp_asoc(const struct sctp_endpoint *,
					     struct sctp_chunk *,
A
Al Viro 已提交
181
					     gfp_t gfp);
L
Linus Torvalds 已提交
182 183 184 185 186 187
__u32 sctp_generate_verification_tag(void);
void sctp_populate_tie_tags(__u8 *cookie, __u32 curTag, __u32 hisTag);

/* Prototypes for chunk-building functions.  */
struct sctp_chunk *sctp_make_init(const struct sctp_association *,
			     const struct sctp_bind_addr *,
A
Al Viro 已提交
188
			     gfp_t gfp, int vparam_len);
L
Linus Torvalds 已提交
189 190
struct sctp_chunk *sctp_make_init_ack(const struct sctp_association *,
				 const struct sctp_chunk *,
A
Al Viro 已提交
191
				 const gfp_t gfp,
L
Linus Torvalds 已提交
192 193 194 195 196 197 198 199 200 201 202
				 const int unkparam_len);
struct sctp_chunk *sctp_make_cookie_echo(const struct sctp_association *,
				    const struct sctp_chunk *);
struct sctp_chunk *sctp_make_cookie_ack(const struct sctp_association *,
				   const struct sctp_chunk *);
struct sctp_chunk *sctp_make_cwr(const struct sctp_association *,
				 const __u32 lowest_tsn,
				 const struct sctp_chunk *);
struct sctp_chunk * sctp_make_datafrag_empty(struct sctp_association *,
					const struct sctp_sndrcvinfo *sinfo,
					int len, const __u8 flags,
203
					__u16 ssn, gfp_t gfp);
L
Linus Torvalds 已提交
204 205 206 207 208 209 210 211 212
struct sctp_chunk *sctp_make_ecne(const struct sctp_association *,
				  const __u32);
struct sctp_chunk *sctp_make_sack(const struct sctp_association *);
struct sctp_chunk *sctp_make_shutdown(const struct sctp_association *asoc,
				      const struct sctp_chunk *chunk);
struct sctp_chunk *sctp_make_shutdown_ack(const struct sctp_association *asoc,
					  const struct sctp_chunk *);
struct sctp_chunk *sctp_make_shutdown_complete(const struct sctp_association *,
					  const struct sctp_chunk *);
213
void sctp_init_cause(struct sctp_chunk *, __be16 cause, size_t);
L
Linus Torvalds 已提交
214 215 216 217 218 219 220
struct sctp_chunk *sctp_make_abort(const struct sctp_association *,
			      const struct sctp_chunk *,
			      const size_t hint);
struct sctp_chunk *sctp_make_abort_no_data(const struct sctp_association *,
				      const struct sctp_chunk *,
				      __u32 tsn);
struct sctp_chunk *sctp_make_abort_user(const struct sctp_association *,
A
Al Viro 已提交
221
					struct msghdr *, size_t msg_len);
L
Linus Torvalds 已提交
222 223 224 225
struct sctp_chunk *sctp_make_abort_violation(const struct sctp_association *,
				   const struct sctp_chunk *,
				   const __u8 *,
				   const size_t );
226 227 228
struct sctp_chunk *sctp_make_violation_paramlen(const struct sctp_association *,
				   const struct sctp_chunk *,
				   struct sctp_paramhdr *);
229 230
struct sctp_chunk *sctp_make_violation_max_retrans(const struct sctp_association *,
						   const struct sctp_chunk *);
L
Linus Torvalds 已提交
231
struct sctp_chunk *sctp_make_heartbeat(const struct sctp_association *,
232
				  const struct sctp_transport *);
L
Linus Torvalds 已提交
233 234 235 236 237 238
struct sctp_chunk *sctp_make_heartbeat_ack(const struct sctp_association *,
				      const struct sctp_chunk *,
				      const void *payload,
				      const size_t paylen);
struct sctp_chunk *sctp_make_op_error(const struct sctp_association *,
				 const struct sctp_chunk *chunk,
239
				 __be16 cause_code,
L
Linus Torvalds 已提交
240
				 const void *payload,
241 242
				 size_t paylen,
				 size_t reserve_tail);
L
Linus Torvalds 已提交
243 244 245 246

struct sctp_chunk *sctp_make_asconf_update_ip(struct sctp_association *,
					      union sctp_addr *,
					      struct sockaddr *,
247
					      int, __be16);
L
Linus Torvalds 已提交
248 249
struct sctp_chunk *sctp_make_asconf_set_prim(struct sctp_association *asoc,
					     union sctp_addr *addr);
250 251 252
bool sctp_verify_asconf(const struct sctp_association *asoc,
			struct sctp_chunk *chunk, bool addr_param_needed,
			struct sctp_paramhdr **errp);
L
Linus Torvalds 已提交
253 254 255 256 257 258 259
struct sctp_chunk *sctp_process_asconf(struct sctp_association *asoc,
				       struct sctp_chunk *asconf);
int sctp_process_asconf_ack(struct sctp_association *asoc,
			    struct sctp_chunk *asconf_ack);
struct sctp_chunk *sctp_make_fwdtsn(const struct sctp_association *asoc,
				    __u32 new_cum_tsn, size_t nstreams,
				    struct sctp_fwdtsn_skip *skiplist);
260
struct sctp_chunk *sctp_make_auth(const struct sctp_association *asoc);
261 262 263 264
struct sctp_chunk *sctp_make_strreset_req(
				const struct sctp_association *asoc,
				__u16 stream_num, __u16 *stream_list,
				bool out, bool in);
265 266
struct sctp_chunk *sctp_make_strreset_tsnreq(
				const struct sctp_association *asoc);
267 268 269
struct sctp_chunk *sctp_make_strreset_addstrm(
				const struct sctp_association *asoc,
				__u16 out, __u16 in);
270 271 272 273 274 275 276
struct sctp_chunk *sctp_make_strreset_resp(
				const struct sctp_association *asoc,
				__u32 result, __u32 sn);
struct sctp_chunk *sctp_make_strreset_tsnresp(
				struct sctp_association *asoc,
				__u32 result, __u32 sn,
				__u32 sender_tsn, __u32 receiver_tsn);
277 278 279
bool sctp_verify_reconf(const struct sctp_association *asoc,
			struct sctp_chunk *chunk,
			struct sctp_paramhdr **errp);
L
Linus Torvalds 已提交
280 281 282
void sctp_chunk_assign_tsn(struct sctp_chunk *);
void sctp_chunk_assign_ssn(struct sctp_chunk *);

283 284 285 286 287
/* Prototypes for stream-processing functions.  */
struct sctp_chunk *sctp_process_strreset_outreq(
				struct sctp_association *asoc,
				union sctp_params param,
				struct sctp_ulpevent **evp);
288 289 290 291
struct sctp_chunk *sctp_process_strreset_inreq(
				struct sctp_association *asoc,
				union sctp_params param,
				struct sctp_ulpevent **evp);
292 293 294 295
struct sctp_chunk *sctp_process_strreset_tsnreq(
				struct sctp_association *asoc,
				union sctp_params param,
				struct sctp_ulpevent **evp);
296 297 298 299
struct sctp_chunk *sctp_process_strreset_addstrm_out(
				struct sctp_association *asoc,
				union sctp_params param,
				struct sctp_ulpevent **evp);
300 301 302 303
struct sctp_chunk *sctp_process_strreset_addstrm_in(
				struct sctp_association *asoc,
				union sctp_params param,
				struct sctp_ulpevent **evp);
304 305 306 307
struct sctp_chunk *sctp_process_strreset_resp(
				struct sctp_association *asoc,
				union sctp_params param,
				struct sctp_ulpevent **evp);
308

L
Linus Torvalds 已提交
309 310
/* Prototypes for statetable processing. */

X
Xin Long 已提交
311
int sctp_do_sm(struct net *net, enum sctp_event event_type,
312
	       union sctp_subtype subtype, enum sctp_state state,
X
Xin Long 已提交
313 314
	       struct sctp_endpoint *ep, struct sctp_association *asoc,
	       void *event_arg, gfp_t gfp);
L
Linus Torvalds 已提交
315 316 317 318

/* 2nd level prototypes */
void sctp_generate_t3_rtx_event(unsigned long peer);
void sctp_generate_heartbeat_event(unsigned long peer);
X
Xin Long 已提交
319
void sctp_generate_reconf_event(unsigned long peer);
320
void sctp_generate_proto_unreach_event(unsigned long peer);
L
Linus Torvalds 已提交
321

X
Xin Long 已提交
322
void sctp_ootb_pkt_free(struct sctp_packet *packet);
L
Linus Torvalds 已提交
323

X
Xin Long 已提交
324 325 326
struct sctp_association *sctp_unpack_cookie(const struct sctp_endpoint *ep,
				       const struct sctp_association *asoc,
				       struct sctp_chunk *chunk,
A
Al Viro 已提交
327
				       gfp_t gfp, int *err,
L
Linus Torvalds 已提交
328 329 330
				       struct sctp_chunk **err_chk_p);

/* 3rd level prototypes */
X
Xin Long 已提交
331 332
__u32 sctp_generate_tag(const struct sctp_endpoint *ep);
__u32 sctp_generate_tsn(const struct sctp_endpoint *ep);
L
Linus Torvalds 已提交
333 334 335 336 337 338 339 340 341 342 343

/* Extern declarations for major data structures.  */
extern sctp_timer_event_t *sctp_timer_events[SCTP_NUM_TIMEOUT_TYPES];


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

	size = ntohs(chunk->chunk_hdr->length);
344
	size -= sizeof(struct sctp_data_chunk);
L
Linus Torvalds 已提交
345 346 347 348 349

	return size;
}

/* Compare two TSNs */
350 351 352 353
#define TSN_lt(a,b)	\
	(typecheck(__u32, a) && \
	 typecheck(__u32, b) && \
	 ((__s32)((a) - (b)) < 0))
L
Linus Torvalds 已提交
354

355 356 357 358
#define TSN_lte(a,b)	\
	(typecheck(__u32, a) && \
	 typecheck(__u32, b) && \
	 ((__s32)((a) - (b)) <= 0))
L
Linus Torvalds 已提交
359 360

/* Compare two SSNs */
361 362 363 364 365 366 367 368 369 370
#define SSN_lt(a,b)		\
	(typecheck(__u16, a) && \
	 typecheck(__u16, b) && \
	 ((__s16)((a) - (b)) < 0))

/* ADDIP 3.1.1 */
#define ADDIP_SERIAL_gte(a,b)	\
	(typecheck(__u32, a) && \
	 typecheck(__u32, b) && \
	 ((__s32)((b) - (a)) <= 0))
L
Linus Torvalds 已提交
371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388

/* Check VTAG of the packet matches the sender's own tag. */
static inline int
sctp_vtag_verify(const struct sctp_chunk *chunk,
		 const struct sctp_association *asoc)
{
	/* RFC 2960 Sec 8.5 When receiving an SCTP packet, the endpoint
	 * MUST ensure that the value in the Verification Tag field of
	 * the received SCTP packet matches its own Tag. If the received
	 * Verification Tag value does not match the receiver's own
	 * tag value, the receiver shall silently discard the packet...
	 */
        if (ntohl(chunk->sctp_hdr->vtag) == asoc->c.my_vtag)
                return 1;

	return 0;
}

389 390
/* Check VTAG of the packet matches the sender's own tag and the T bit is
 * not set, OR its peer's tag and the T bit is set in the Chunk Flags.
L
Linus Torvalds 已提交
391 392 393 394 395
 */
static inline int
sctp_vtag_verify_either(const struct sctp_chunk *chunk,
			const struct sctp_association *asoc)
{
396
        /* RFC 2960 Section 8.5.1, sctpimpguide Section 2.41
L
Linus Torvalds 已提交
397
	 *
398 399 400 401 402 403 404 405
	 * B) The receiver of a ABORT MUST accept the packet
	 *    if the Verification Tag field of the packet matches its own tag
	 *    and the T bit is not set
	 *    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.
L
Linus Torvalds 已提交
406
	 *
407 408 409 410 411 412 413 414 415
	 * C) The receiver of a SHUTDOWN COMPLETE shall accept the packet
	 *    if the Verification Tag field of the packet matches its own tag
	 *    and the T bit is not set
	 *    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.  An endpoint MUST ignore the
	 *    SHUTDOWN COMPLETE if it is not in the SHUTDOWN-ACK-SENT state.
L
Linus Torvalds 已提交
416
	 */
417 418
        if ((!sctp_test_T_bit(chunk) &&
             (ntohl(chunk->sctp_hdr->vtag) == asoc->c.my_vtag)) ||
419
	    (sctp_test_T_bit(chunk) && asoc->c.peer_vtag &&
420
	     (ntohl(chunk->sctp_hdr->vtag) == asoc->c.peer_vtag))) {
L
Linus Torvalds 已提交
421 422 423 424 425 426 427
                return 1;
	}

	return 0;
}

#endif /* __sctp_sm_h__ */