sm_make_chunk.c 60.4 KB
Newer Older
Jon Grimm's avatar
Jon Grimm committed
1 2 3
/* SCTP kernel reference Implementation
 * Copyright (c) 1999-2000 Cisco, Inc.
 * Copyright (c) 1999-2001 Motorola, Inc.
4 5
 * Copyright (c) 2001-2002 Intel Corp.
 * Copyright (c) 2001-2002 International Business Machines Corp.
Jon Grimm's avatar
Jon Grimm committed
6 7 8 9 10 11
 *
 * This file is part of the SCTP kernel reference Implementation
 *
 * This file includes 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.
Jon Grimm's avatar
Jon Grimm committed
12
 *
Jon Grimm's avatar
Jon Grimm committed
13 14 15
 * These functions work with the state functions in sctp_sm_statefuns.c
 * to implement the state operations.  These functions implement the
 * steps which require modifying existing data structures.
Jon Grimm's avatar
Jon Grimm committed
16 17 18
 *
 * The SCTP reference implementation is free software;
 * you can redistribute it and/or modify it under the terms of
Jon Grimm's avatar
Jon Grimm committed
19 20 21
 * the GNU General Public License as published by
 * the Free Software Foundation; either version 2, or (at your option)
 * any later version.
Jon Grimm's avatar
Jon Grimm committed
22 23
 *
 * The SCTP reference implementation is distributed in the hope that it
Jon Grimm's avatar
Jon Grimm committed
24 25 26 27
 * 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.
Jon Grimm's avatar
Jon Grimm committed
28
 *
Jon Grimm's avatar
Jon Grimm committed
29 30 31
 * 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,
Jon Grimm's avatar
Jon Grimm committed
32 33
 * Boston, MA 02111-1307, USA.
 *
Jon Grimm's avatar
Jon Grimm committed
34 35 36
 * Please send any bug reports or fixes you make to the
 * email address(es):
 *    lksctp developers <lksctp-developers@lists.sourceforge.net>
Jon Grimm's avatar
Jon Grimm committed
37
 *
Jon Grimm's avatar
Jon Grimm committed
38 39 40
 * Or submit a bug report through the following website:
 *    http://www.sf.net/projects/lksctp
 *
Jon Grimm's avatar
Jon Grimm committed
41
 * Written or modified by:
Jon Grimm's avatar
Jon Grimm committed
42 43 44 45 46 47 48 49
 *    La Monte H.P. Yarroll <piggy@acm.org>
 *    Karl Knutson          <karl@athena.chicago.il.us>
 *    C. Robin              <chris@hundredacre.ac.uk>
 *    Jon Grimm             <jgrimm@us.ibm.com>
 *    Xingang Guo           <xingang.guo@intel.com>
 *    Dajiang Zhang	    <dajiang.zhang@nokia.com>
 *    Sridhar Samudrala	    <sri@us.ibm.com>
 *    Daisy Chang	    <daisyc@us.ibm.com>
50
 *    Ardelle Fan	    <ardelle.fan@intel.com>
Jon Grimm's avatar
Jon Grimm committed
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
 *
 * 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/kernel.h>
#include <linux/ip.h>
#include <linux/ipv6.h>
#include <linux/net.h>
#include <linux/inet.h>
#include <net/sock.h>

#include <linux/skbuff.h>
#include <linux/random.h>	/* for get_random_bytes */
#include <net/sctp/sctp.h>
67
#include <net/sctp/sm.h>
Jon Grimm's avatar
Jon Grimm committed
68 69 70 71 72 73

/* RFC 2960 3.3.2 Initiation (INIT) (1)
 *
 * Note 2: The ECN capable field is reserved for future use of
 * Explicit Congestion Notification.
 */
74 75 76 77 78 79
static const sctp_ecn_capable_param_t ecap_param = {
	{
		SCTP_PARAM_ECN_CAPABLE,
		__constant_htons(sizeof(sctp_ecn_capable_param_t)),
	}
};
Jon Grimm's avatar
Jon Grimm committed
80 81 82 83 84

/* A helper to initilize to initilize an op error inside a
 * provided chunk, as most cause codes will be embedded inside an
 * abort chunk.
 */
85 86
void  sctp_init_cause(sctp_chunk_t *chunk, __u16 cause_code,
		      const void *payload, size_t paylen)
Jon Grimm's avatar
Jon Grimm committed
87 88 89
{
	sctp_errhdr_t err;
	int padlen;
90
	__u16 len;
Jon Grimm's avatar
Jon Grimm committed
91

92
        /* Cause code constants are now defined in network order.  */
Jon Grimm's avatar
Jon Grimm committed
93 94 95 96
	err.cause = cause_code;
	len = sizeof(sctp_errhdr_t) + paylen;
	padlen = len % 4;
	err.length  = htons(len);
97
	len += padlen;
Jon Grimm's avatar
Jon Grimm committed
98 99
	sctp_addto_chunk(chunk, sizeof(sctp_errhdr_t), &err);
	chunk->subh.err_hdr = sctp_addto_chunk(chunk, paylen, payload);
100
}
Jon Grimm's avatar
Jon Grimm committed
101 102

/* 3.3.2 Initiation (INIT) (1)
103
 *
Jon Grimm's avatar
Jon Grimm committed
104 105
 * This chunk is used to initiate a SCTP association between two
 * endpoints. The format of the INIT chunk is shown below:
106
 *
Jon Grimm's avatar
Jon Grimm committed
107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123
 *     0                   1                   2                   3
 *     0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
 *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 *    |   Type = 1    |  Chunk Flags  |      Chunk Length             |
 *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 *    |                         Initiate Tag                          |
 *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 *    |           Advertised Receiver Window Credit (a_rwnd)          |
 *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 *    |  Number of Outbound Streams   |  Number of Inbound Streams    |
 *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 *    |                          Initial TSN                          |
 *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 *    \                                                               \
 *    /              Optional/Variable-Length Parameters              /
 *    \                                                               \
 *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
124 125 126
 *
 *
 * The INIT chunk contains the following parameters. Unless otherwise
Jon Grimm's avatar
Jon Grimm committed
127
 * noted, each parameter MUST only be included once in the INIT chunk.
128
 *
Jon Grimm's avatar
Jon Grimm committed
129 130 131 132 133 134 135
 * Fixed Parameters                     Status
 * ----------------------------------------------
 * Initiate Tag                        Mandatory
 * Advertised Receiver Window Credit   Mandatory
 * Number of Outbound Streams          Mandatory
 * Number of Inbound Streams           Mandatory
 * Initial TSN                         Mandatory
136
 *
Jon Grimm's avatar
Jon Grimm committed
137 138 139 140 141 142 143 144 145
 * Variable Parameters                  Status     Type Value
 * -------------------------------------------------------------
 * IPv4 Address (Note 1)               Optional    5
 * IPv6 Address (Note 1)               Optional    6
 * Cookie Preservative                 Optional    9
 * Reserved for ECN Capable (Note 2)   Optional    32768 (0x8000)
 * Host Name Address (Note 3)          Optional    11
 * Supported Address Types (Note 4)    Optional    12
 */
146 147
sctp_chunk_t *sctp_make_init(const sctp_association_t *asoc,
			     const sctp_bind_addr_t *bp,
148
			     int priority, int vparam_len)
Jon Grimm's avatar
Jon Grimm committed
149
{
150
	sctp_inithdr_t init;
151
	union sctp_params addrs;
Jon Grimm's avatar
Jon Grimm committed
152
	size_t chunksize;
153
	sctp_chunk_t *retval = NULL;
154 155 156 157
	int num_types, addrs_len = 0;
	struct sctp_opt *sp;
	sctp_supported_addrs_param_t sat;
	__u16 types[2];
Jon Grimm's avatar
Jon Grimm committed
158 159 160 161

	/* RFC 2960 3.3.2 Initiation (INIT) (1)
	 *
	 * Note 1: The INIT chunks can contain multiple addresses that
162 163
	 * can be IPv4 and/or IPv6 in any combination.
	 */
Jon Grimm's avatar
Jon Grimm committed
164 165 166 167 168
	retval = NULL;
	addrs.v = NULL;

	/* Convert the provided bind address list to raw format */
	addrs = sctp_bind_addrs_to_raw(bp, &addrs_len, priority);
169 170 171 172 173 174 175 176
	if (!addrs.v)
		goto nodata;

	init.init_tag		   = htonl(asoc->c.my_vtag);
	init.a_rwnd		   = htonl(asoc->rwnd);
	init.num_outbound_streams  = htons(asoc->c.sinit_num_ostreams);
	init.num_inbound_streams   = htons(asoc->c.sinit_max_instreams);
	init.initial_tsn	   = htonl(asoc->c.initial_tsn);
Jon Grimm's avatar
Jon Grimm committed
177

178 179 180 181 182
	/* How many address types are needed? */
	sp = sctp_sk(asoc->base.sk);
	num_types = sp->pf->supported_addrs(sp, types);

	chunksize = sizeof(init) + addrs_len + SCTP_SAT_LEN(num_types);
Jon Grimm's avatar
Jon Grimm committed
183
	chunksize += sizeof(ecap_param);
184
	chunksize += vparam_len;
Jon Grimm's avatar
Jon Grimm committed
185 186 187 188

	/* RFC 2960 3.3.2 Initiation (INIT) (1)
	 *
	 * Note 3: An INIT chunk MUST NOT contain more than one Host
189 190 191 192 193
	 * Name address parameter. Moreover, the sender of the INIT
	 * MUST NOT combine any other address types with the Host Name
	 * address in the INIT. The receiver of INIT MUST ignore any
	 * other address types if the Host Name address parameter is
	 * present in the received INIT chunk.
Jon Grimm's avatar
Jon Grimm committed
194
	 *
195 196
	 * PLEASE DO NOT FIXME [This version does not support Host Name.]
	 */
Jon Grimm's avatar
Jon Grimm committed
197

Jon Grimm's avatar
Jon Grimm committed
198
	retval = sctp_make_chunk(asoc, SCTP_CID_INIT, 0, chunksize);
199 200
	if (!retval)
		goto nodata;
Jon Grimm's avatar
Jon Grimm committed
201

202 203 204 205
	retval->subh.init_hdr =
		sctp_addto_chunk(retval, sizeof(init), &init);
	retval->param_hdr.v =
		sctp_addto_chunk(retval, addrs_len, addrs.v);
206

207 208 209 210 211 212 213 214 215 216 217 218
	/* RFC 2960 3.3.2 Initiation (INIT) (1)
	 *
	 * Note 4: This parameter, when present, specifies all the
	 * address types the sending endpoint can support. The absence
	 * of this parameter indicates that the sending endpoint can
	 * support any address type.
	 */
	sat.param_hdr.type = SCTP_PARAM_SUPPORTED_ADDRESS_TYPES;
	sat.param_hdr.length = htons(SCTP_SAT_LEN(num_types));
	sctp_addto_chunk(retval, sizeof(sat), &sat);
	sctp_addto_chunk(retval, num_types * sizeof(__u16), &types);

Jon Grimm's avatar
Jon Grimm committed
219 220
	sctp_addto_chunk(retval, sizeof(ecap_param), &ecap_param);
nodata:
221 222 223 224
	if (addrs.v)
		kfree(addrs.v);
	return retval;
}
Jon Grimm's avatar
Jon Grimm committed
225

226 227
sctp_chunk_t *sctp_make_init_ack(const sctp_association_t *asoc,
				 const sctp_chunk_t *chunk,
228
				 int priority, int unkparam_len)
Jon Grimm's avatar
Jon Grimm committed
229
{
230 231
	sctp_inithdr_t initack;
	sctp_chunk_t *retval;
232
	union sctp_params addrs;
233 234 235
	int addrs_len;
	sctp_cookie_param_t *cookie;
	int cookie_len;
Jon Grimm's avatar
Jon Grimm committed
236
	size_t chunksize;
237

Jon Grimm's avatar
Jon Grimm committed
238
	retval = NULL;
Jon Grimm's avatar
Jon Grimm committed
239

240 241
	addrs = sctp_bind_addrs_to_raw(&asoc->base.bind_addr, &addrs_len, 
				       priority);
242 243 244 245 246 247 248 249 250
	if (!addrs.v)
		goto nomem_rawaddr;

	initack.init_tag	        = htonl(asoc->c.my_vtag);
	initack.a_rwnd			= htonl(asoc->rwnd);
	initack.num_outbound_streams	= htons(asoc->c.sinit_num_ostreams);
	initack.num_inbound_streams	= htons(asoc->c.sinit_max_instreams);
	initack.initial_tsn		= htonl(asoc->c.initial_tsn);

Jon Grimm's avatar
Jon Grimm committed
251
	/* FIXME:  We really ought to build the cookie right
252
	 * into the packet instead of allocating more fresh memory.
Jon Grimm's avatar
Jon Grimm committed
253
	 */
254
	cookie = sctp_pack_cookie(asoc->ep, asoc, chunk, &cookie_len,
Jon Grimm's avatar
Jon Grimm committed
255
				  addrs.v, addrs_len);
256 257
	if (!cookie)
		goto nomem_cookie;
Jon Grimm's avatar
Jon Grimm committed
258

259 260 261 262
	/* Calculate the total size of allocation, include the reserved
	 * space for reporting unknown parameters if it is specified.
	 */
	chunksize = sizeof(initack) + addrs_len + cookie_len + unkparam_len;
Jon Grimm's avatar
Jon Grimm committed
263

264 265
        /* Tell peer that we'll do ECN only if peer advertised such cap.  */
	if (asoc->peer.ecn_capable)
Jon Grimm's avatar
Jon Grimm committed
266 267
		chunksize += sizeof(ecap_param);

268 269 270 271
	/* Now allocate and fill out the chunk.  */
	retval = sctp_make_chunk(asoc, SCTP_CID_INIT_ACK, 0, chunksize);
	if (!retval)
		goto nomem_chunk;
Jon Grimm's avatar
Jon Grimm committed
272 273 274

	/* Per the advice in RFC 2960 6.4, send this reply to
	 * the source of the INIT packet.
275 276 277 278 279 280 281
	 */
	retval->transport = chunk->transport;
	retval->subh.init_hdr =
		sctp_addto_chunk(retval, sizeof(initack), &initack);
	retval->param_hdr.v = sctp_addto_chunk(retval, addrs_len, addrs.v);
	sctp_addto_chunk(retval, cookie_len, cookie);
	if (asoc->peer.ecn_capable)
Jon Grimm's avatar
Jon Grimm committed
282 283 284
		sctp_addto_chunk(retval, sizeof(ecap_param), &ecap_param);

	/* We need to remove the const qualifier at this point.  */
285
	retval->asoc = (sctp_association_t *) asoc;
Jon Grimm's avatar
Jon Grimm committed
286 287

	/* RFC 2960 6.4 Multi-homed SCTP Endpoints
288
	 *
Jon Grimm's avatar
Jon Grimm committed
289 290 291 292 293 294 295
	 * An endpoint SHOULD transmit reply chunks (e.g., SACK,
	 * HEARTBEAT ACK, * etc.) to the same destination transport
	 * address from which it received the DATA or control chunk
	 * to which it is replying.
	 *
	 * [INIT ACK back to where the INIT came from.]
	 */
296
	if (chunk)
Jon Grimm's avatar
Jon Grimm committed
297
		retval->transport = chunk->transport;
298

Jon Grimm's avatar
Jon Grimm committed
299
nomem_chunk:
300
	kfree(cookie);
Jon Grimm's avatar
Jon Grimm committed
301 302 303
nomem_cookie:
	kfree(addrs.v);
nomem_rawaddr:
304 305
	return retval;
}
Jon Grimm's avatar
Jon Grimm committed
306 307

/* 3.3.11 Cookie Echo (COOKIE ECHO) (10):
308
 *
Jon Grimm's avatar
Jon Grimm committed
309 310
 * This chunk is used only during the initialization of an association.
 * It is sent by the initiator of an association to its peer to complete
311
 * the initialization process. This chunk MUST precede any DATA chunk
Jon Grimm's avatar
Jon Grimm committed
312 313
 * sent within the association, but MAY be bundled with one or more DATA
 * chunks in the same packet.
314
 *
Jon Grimm's avatar
Jon Grimm committed
315 316 317 318 319 320 321 322
 *      0                   1                   2                   3
 *      0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
 *     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 *     |   Type = 10   |Chunk  Flags   |         Length                |
 *     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 *     /                     Cookie                                    /
 *     \                                                               \
 *     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
323
 *
Jon Grimm's avatar
Jon Grimm committed
324
 * Chunk Flags: 8 bit
325
 *
Jon Grimm's avatar
Jon Grimm committed
326
 *   Set to zero on transmit and ignored on receipt.
327
 *
Jon Grimm's avatar
Jon Grimm committed
328
 * Length: 16 bits (unsigned integer)
329
 *
Jon Grimm's avatar
Jon Grimm committed
330 331
 *   Set to the size of the chunk in bytes, including the 4 bytes of
 *   the chunk header and the size of the Cookie.
332
 *
Jon Grimm's avatar
Jon Grimm committed
333
 * Cookie: variable size
334 335
 *
 *   This field must contain the exact cookie received in the
Jon Grimm's avatar
Jon Grimm committed
336
 *   State Cookie parameter from the previous INIT ACK.
337
 *
Jon Grimm's avatar
Jon Grimm committed
338 339 340
 *   An implementation SHOULD make the cookie as small as possible
 *   to insure interoperability.
 */
341 342
sctp_chunk_t *sctp_make_cookie_echo(const sctp_association_t *asoc,
				    const sctp_chunk_t *chunk)
Jon Grimm's avatar
Jon Grimm committed
343
{
344
	sctp_chunk_t *retval;
Jon Grimm's avatar
Jon Grimm committed
345 346 347 348 349 350
	void *cookie;
	int cookie_len;

	cookie = asoc->peer.cookie;
	cookie_len = asoc->peer.cookie_len;

351 352 353 354 355 356 357
	/* Build a cookie echo chunk.  */
	retval = sctp_make_chunk(asoc, SCTP_CID_COOKIE_ECHO, 0, cookie_len);
	if (!retval)
		goto nodata;
	retval->subh.cookie_hdr =
		sctp_addto_chunk(retval, cookie_len, cookie);

Jon Grimm's avatar
Jon Grimm committed
358
	/* RFC 2960 6.4 Multi-homed SCTP Endpoints
359
	 *
Jon Grimm's avatar
Jon Grimm committed
360 361 362 363 364 365 366
	 * An endpoint SHOULD transmit reply chunks (e.g., SACK,
	 * HEARTBEAT ACK, * etc.) to the same destination transport
	 * address from which it * received the DATA or control chunk
	 * to which it is replying.
	 *
	 * [COOKIE ECHO back to where the INIT ACK came from.]
	 */
367
	if (chunk)
Jon Grimm's avatar
Jon Grimm committed
368 369 370
		retval->transport = chunk->transport;

nodata:
371 372
	return retval;
}
Jon Grimm's avatar
Jon Grimm committed
373 374 375 376

/* 3.3.12 Cookie Acknowledgement (COOKIE ACK) (11):
 *
 * This chunk is used only during the initialization of an
377
 * association.  It is used to acknowledge the receipt of a COOKIE
Jon Grimm's avatar
Jon Grimm committed
378 379 380
 * ECHO chunk.  This chunk MUST precede any DATA or SACK chunk sent
 * within the association, but MAY be bundled with one or more DATA
 * chunks or SACK chunk in the same SCTP packet.
381
 *
Jon Grimm's avatar
Jon Grimm committed
382 383 384 385 386
 *      0                   1                   2                   3
 *      0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
 *     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 *     |   Type = 11   |Chunk  Flags   |     Length = 4                |
 *     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
387
 *
Jon Grimm's avatar
Jon Grimm committed
388
 * Chunk Flags: 8 bits
389
 *
Jon Grimm's avatar
Jon Grimm committed
390 391
 *   Set to zero on transmit and ignored on receipt.
 */
392 393
sctp_chunk_t *sctp_make_cookie_ack(const sctp_association_t *asoc,
				   const sctp_chunk_t *chunk)
Jon Grimm's avatar
Jon Grimm committed
394
{
395
	sctp_chunk_t *retval;
Jon Grimm's avatar
Jon Grimm committed
396

397
	retval = sctp_make_chunk(asoc, SCTP_CID_COOKIE_ACK, 0, 0);
Jon Grimm's avatar
Jon Grimm committed
398 399

	/* RFC 2960 6.4 Multi-homed SCTP Endpoints
400
	 *
Jon Grimm's avatar
Jon Grimm committed
401 402 403 404 405 406 407
	 * An endpoint SHOULD transmit reply chunks (e.g., SACK,
	 * HEARTBEAT ACK, * etc.) to the same destination transport
	 * address from which it * received the DATA or control chunk
	 * to which it is replying.
	 *
	 * [COOKIE ACK back to where the COOKIE ECHO came from.]
	 */
408
	if (retval && chunk)
Jon Grimm's avatar
Jon Grimm committed
409 410
		retval->transport = chunk->transport;

411 412
	return retval;
}
Jon Grimm's avatar
Jon Grimm committed
413

414 415
/*
 *  Appendix A: Explicit Congestion Notification:
Jon Grimm's avatar
Jon Grimm committed
416
 *  CWR:
417
 *
Jon Grimm's avatar
Jon Grimm committed
418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436
 *  RFC 2481 details a specific bit for a sender to send in the header of
 *  its next outbound TCP segment to indicate to its peer that it has
 *  reduced its congestion window.  This is termed the CWR bit.  For
 *  SCTP the same indication is made by including the CWR chunk.
 *  This chunk contains one data element, i.e. the TSN number that
 *  was sent in the ECNE chunk.  This element represents the lowest
 *  TSN number in the datagram that was originally marked with the
 *  CE bit.
 *
 *     0                   1                   2                   3
 *     0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
 *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 *    | Chunk Type=13 | Flags=00000000|    Chunk Length = 8           |
 *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 *    |                      Lowest TSN Number                        |
 *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 *
 *     Note: The CWR is considered a Control chunk.
 */
437 438 439
sctp_chunk_t *sctp_make_cwr(const sctp_association_t *asoc,
			    const __u32 lowest_tsn,
			    const sctp_chunk_t *chunk)
Jon Grimm's avatar
Jon Grimm committed
440
{
441
	sctp_chunk_t *retval;
Jon Grimm's avatar
Jon Grimm committed
442
	sctp_cwrhdr_t cwr;
443

Jon Grimm's avatar
Jon Grimm committed
444
	cwr.lowest_tsn = htonl(lowest_tsn);
445 446 447 448 449
	retval = sctp_make_chunk(asoc, SCTP_CID_ECN_CWR, 0,
				 sizeof(sctp_cwrhdr_t));

	if (!retval)
		goto nodata;
Jon Grimm's avatar
Jon Grimm committed
450

451 452
	retval->subh.ecn_cwr_hdr =
		sctp_addto_chunk(retval, sizeof(cwr), &cwr);
Jon Grimm's avatar
Jon Grimm committed
453 454

	/* RFC 2960 6.4 Multi-homed SCTP Endpoints
455
	 *
Jon Grimm's avatar
Jon Grimm committed
456 457 458 459 460 461 462 463
	 * An endpoint SHOULD transmit reply chunks (e.g., SACK,
	 * HEARTBEAT ACK, * etc.) to the same destination transport
	 * address from which it * received the DATA or control chunk
	 * to which it is replying.
	 *
	 * [Report a reduced congestion window back to where the ECNE
	 * came from.]
	 */
464
	if (chunk)
Jon Grimm's avatar
Jon Grimm committed
465 466
		retval->transport = chunk->transport;

467 468 469
nodata:
	return retval;
}
Jon Grimm's avatar
Jon Grimm committed
470 471

/* Make an ECNE chunk.  This is a congestion experienced report.  */
472 473
sctp_chunk_t *sctp_make_ecne(const sctp_association_t *asoc,
			     const __u32 lowest_tsn)
Jon Grimm's avatar
Jon Grimm committed
474
{
475
	sctp_chunk_t *retval;
Jon Grimm's avatar
Jon Grimm committed
476
	sctp_ecnehdr_t ecne;
477

Jon Grimm's avatar
Jon Grimm committed
478
	ecne.lowest_tsn = htonl(lowest_tsn);
479 480 481 482 483 484
	retval = sctp_make_chunk(asoc, SCTP_CID_ECN_ECNE, 0,
				 sizeof(sctp_ecnehdr_t));
	if (!retval)
		goto nodata;
	retval->subh.ecne_hdr =
		sctp_addto_chunk(retval, sizeof(ecne), &ecne);
Jon Grimm's avatar
Jon Grimm committed
485 486

nodata:
487 488
	return retval;
}
Jon Grimm's avatar
Jon Grimm committed
489

490 491
/* Make a DATA chunk for the given association from the provided
 * parameters.  However, do not populate the data payload.
Jon Grimm's avatar
Jon Grimm committed
492
 */
493 494 495
sctp_chunk_t *sctp_make_datafrag_empty(sctp_association_t *asoc,
				       const struct sctp_sndrcvinfo *sinfo,
				       int data_len, __u8 flags, __u16 ssn)
Jon Grimm's avatar
Jon Grimm committed
496 497 498 499
{
	sctp_chunk_t *retval;
	sctp_datahdr_t dp;
	int chunk_len;
500

Jon Grimm's avatar
Jon Grimm committed
501 502 503 504 505 506 507
	/* We assign the TSN as LATE as possible, not here when
	 * creating the chunk.
	 */
	dp.tsn= 1000000;       /* This marker is a debugging aid. */
	dp.stream = htons(sinfo->sinfo_stream);
	dp.ppid   = htonl(sinfo->sinfo_ppid);
	dp.ssn    = htons(ssn);
508

509 510
	/* Set the flags for an unordered send.  */
	if (sinfo->sinfo_flags & MSG_UNORDERED)
Jon Grimm's avatar
Jon Grimm committed
511
		flags |= SCTP_DATA_UNORDERED;
512

Jon Grimm's avatar
Jon Grimm committed
513 514
	chunk_len = sizeof(dp) + data_len;
	retval = sctp_make_chunk(asoc, SCTP_CID_DATA, flags, chunk_len);
515 516 517
	if (!retval)
		goto nodata;

Jon Grimm's avatar
Jon Grimm committed
518
	retval->subh.data_hdr = sctp_addto_chunk(retval, sizeof(dp), &dp);
519
	memcpy(&retval->sinfo, sinfo, sizeof(struct sctp_sndrcvinfo));
520

Jon Grimm's avatar
Jon Grimm committed
521
nodata:
522 523
	return retval;
}
Jon Grimm's avatar
Jon Grimm committed
524 525 526 527

/* Make a DATA chunk for the given association.  Populate the data
 * payload.
 */
528 529 530 531
sctp_chunk_t *sctp_make_datafrag(sctp_association_t *asoc,
				 const struct sctp_sndrcvinfo *sinfo,
				 int data_len, const __u8 *data,
				 __u8 flags, __u16 ssn)
Jon Grimm's avatar
Jon Grimm committed
532
{
533 534 535 536 537
	sctp_chunk_t *retval;

	retval = sctp_make_datafrag_empty(asoc, sinfo, data_len, flags, ssn);
	if (retval)
		sctp_addto_chunk(retval, data_len, data);
Jon Grimm's avatar
Jon Grimm committed
538

539 540
	return retval;
}
Jon Grimm's avatar
Jon Grimm committed
541 542 543 544

/* Make a DATA chunk for the given association to ride on stream id
 * 'stream', with a payload id of 'payload', and a body of 'data'.
 */
545 546 547
sctp_chunk_t *sctp_make_data(sctp_association_t *asoc,
			     const struct sctp_sndrcvinfo *sinfo,
			     int data_len, const __u8 *data)
Jon Grimm's avatar
Jon Grimm committed
548
{
549
	sctp_chunk_t *retval = NULL;
Jon Grimm's avatar
Jon Grimm committed
550

551 552 553
	retval = sctp_make_data_empty(asoc, sinfo, data_len);
	if (retval)
		sctp_addto_chunk(retval, data_len, data);
Jon Grimm's avatar
Jon Grimm committed
554
        return retval;
555
}
Jon Grimm's avatar
Jon Grimm committed
556 557 558 559 560 561

/* Make a DATA chunk for the given association to ride on stream id
 * 'stream', with a payload id of 'payload', and a body big enough to
 * hold 'data_len' octets of data.  We use this version when we need
 * to build the message AFTER allocating memory.
 */
562 563 564
sctp_chunk_t *sctp_make_data_empty(sctp_association_t *asoc,
				   const struct sctp_sndrcvinfo *sinfo,
				   int data_len)
Jon Grimm's avatar
Jon Grimm committed
565
{
566 567
	__u8 flags = SCTP_DATA_NOT_FRAG;

568
	return sctp_make_datafrag_empty(asoc, sinfo, data_len, flags, 0);
569
}
Jon Grimm's avatar
Jon Grimm committed
570 571 572 573 574

/* Create a selective ackowledgement (SACK) for the given
 * association.  This reports on which TSN's we've seen to date,
 * including duplicates and gaps.
 */
575
sctp_chunk_t *sctp_make_sack(const sctp_association_t *asoc)
Jon Grimm's avatar
Jon Grimm committed
576
{
577 578
	sctp_chunk_t *retval;
	sctp_sackhdr_t sack;
Jon Grimm's avatar
Jon Grimm committed
579
	sctp_gap_ack_block_t gab;
580 581
	int length;
	__u32 ctsn;
Jon Grimm's avatar
Jon Grimm committed
582 583 584
	struct sctp_tsnmap_iter iter;
	__u16 num_gabs, num_dup_tsns;
	struct sctp_tsnmap *map = (struct sctp_tsnmap *)&asoc->peer.tsn_map;
Jon Grimm's avatar
Jon Grimm committed
585 586

	ctsn = sctp_tsnmap_get_ctsn(map);
Jon Grimm's avatar
Jon Grimm committed
587
	SCTP_DEBUG_PRINTK("sackCTSNAck sent is 0x%x.\n", ctsn);
Jon Grimm's avatar
Jon Grimm committed
588 589 590

	/* Count the number of Gap Ack Blocks.  */
	sctp_tsnmap_iter_init(map, &iter);
591 592
	for (num_gabs = 0;
	     sctp_tsnmap_next_gap_ack(map, &iter, &gab.start, &gab.end);
Jon Grimm's avatar
Jon Grimm committed
593 594 595 596
	     num_gabs++) {
		/* Do nothing. */
	}

Jon Grimm's avatar
Jon Grimm committed
597 598
	num_dup_tsns = sctp_tsnmap_num_dups(map);

599 600 601 602
	/* Initialize the SACK header.  */
	sack.cum_tsn_ack	    = htonl(ctsn);
	sack.a_rwnd 		    = htonl(asoc->rwnd);
	sack.num_gap_ack_blocks     = htons(num_gabs);
Jon Grimm's avatar
Jon Grimm committed
603
	sack.num_dup_tsns           = htons(num_dup_tsns);
Jon Grimm's avatar
Jon Grimm committed
604

605 606
	length = sizeof(sack)
		+ sizeof(sctp_gap_ack_block_t) * num_gabs
Jon Grimm's avatar
Jon Grimm committed
607
		+ sizeof(__u32) * num_dup_tsns;
608 609 610 611 612

	/* Create the chunk.  */
	retval = sctp_make_chunk(asoc, SCTP_CID_SACK, 0, length);
	if (!retval)
		goto nodata;
Jon Grimm's avatar
Jon Grimm committed
613 614

	/* RFC 2960 6.4 Multi-homed SCTP Endpoints
615
	 *
Jon Grimm's avatar
Jon Grimm committed
616 617 618 619 620 621
	 * An endpoint SHOULD transmit reply chunks (e.g., SACK,
	 * HEARTBEAT ACK, etc.) to the same destination transport
	 * address from which it received the DATA or control chunk to
	 * which it is replying.  This rule should also be followed if
	 * the endpoint is bundling DATA chunks together with the
	 * reply chunk.
622
	 *
Jon Grimm's avatar
Jon Grimm committed
623 624 625 626 627 628 629 630 631 632
	 * However, when acknowledging multiple DATA chunks received
	 * in packets from different source addresses in a single
	 * SACK, the SACK chunk may be transmitted to one of the
	 * destination transport addresses from which the DATA or
	 * control chunks being acknowledged were received.
	 *
	 * [BUG:  We do not implement the following paragraph.
	 * Perhaps we should remember the last transport we used for a
	 * SACK and avoid that (if possible) if we have seen any
	 * duplicates. --piggy]
633
	 *
Jon Grimm's avatar
Jon Grimm committed
634 635 636 637 638 639 640
	 * When a receiver of a duplicate DATA chunk sends a SACK to a
	 * multi- homed endpoint it MAY be beneficial to vary the
	 * destination address and not use the source address of the
	 * DATA chunk.  The reason being that receiving a duplicate
	 * from a multi-homed endpoint might indicate that the return
	 * path (as specified in the source address of the DATA chunk)
	 * for the SACK is broken.
641
	 *
Jon Grimm's avatar
Jon Grimm committed
642 643 644 645
	 * [Send to the address from which we last received a DATA chunk.]
	 */
	retval->transport = asoc->peer.last_data_from;

646 647 648 649
	retval->subh.sack_hdr =
		sctp_addto_chunk(retval, sizeof(sack), &sack);

	/* Put the Gap Ack Blocks into the chunk.  */
Jon Grimm's avatar
Jon Grimm committed
650 651 652 653
	sctp_tsnmap_iter_init(map, &iter);
	while(sctp_tsnmap_next_gap_ack(map, &iter, &gab.start, &gab.end)) {
		gab.start = htons(gab.start);
		gab.end = htons(gab.end);
Jon Grimm's avatar
Jon Grimm committed
654
		sctp_addto_chunk(retval, sizeof(sctp_gap_ack_block_t), &gab);
Jon Grimm's avatar
Jon Grimm committed
655 656
	}

657
	/* Register the duplicates.  */
Jon Grimm's avatar
Jon Grimm committed
658 659
	sctp_addto_chunk(retval, sizeof(__u32) * num_dup_tsns,
			 sctp_tsnmap_get_dups(map));
Jon Grimm's avatar
Jon Grimm committed
660

661 662 663
nodata:
	return retval;
}
Jon Grimm's avatar
Jon Grimm committed
664

Jon Grimm's avatar
Jon Grimm committed
665
/* Make a SHUTDOWN chunk. */
666
sctp_chunk_t *sctp_make_shutdown(const sctp_association_t *asoc)
Jon Grimm's avatar
Jon Grimm committed
667
{
668 669 670
	sctp_chunk_t *retval;
	sctp_shutdownhdr_t shut;
	__u32 ctsn;
Jon Grimm's avatar
Jon Grimm committed
671 672

	ctsn = sctp_tsnmap_get_ctsn(&asoc->peer.tsn_map);
673
	shut.cum_tsn_ack = htonl(ctsn);
Jon Grimm's avatar
Jon Grimm committed
674

675
	retval = sctp_make_chunk(asoc, SCTP_CID_SHUTDOWN, 0,
Jon Grimm's avatar
Jon Grimm committed
676
				 sizeof(sctp_shutdownhdr_t));
677 678
	if (!retval)
		goto nodata;
Jon Grimm's avatar
Jon Grimm committed
679

680 681 682 683 684
	retval->subh.shutdown_hdr =
		sctp_addto_chunk(retval, sizeof(shut), &shut);
nodata:
	return retval;
}
Jon Grimm's avatar
Jon Grimm committed
685

686 687
sctp_chunk_t *sctp_make_shutdown_ack(const sctp_association_t *asoc,
				     const sctp_chunk_t *chunk)
Jon Grimm's avatar
Jon Grimm committed
688
{
689
	sctp_chunk_t *retval;
Jon Grimm's avatar
Jon Grimm committed
690

691
	retval = sctp_make_chunk(asoc, SCTP_CID_SHUTDOWN_ACK, 0, 0);
Jon Grimm's avatar
Jon Grimm committed
692 693

	/* RFC 2960 6.4 Multi-homed SCTP Endpoints
694
	 *
Jon Grimm's avatar
Jon Grimm committed
695 696 697 698 699 700 701
	 * An endpoint SHOULD transmit reply chunks (e.g., SACK,
	 * HEARTBEAT ACK, * etc.) to the same destination transport
	 * address from which it * received the DATA or control chunk
	 * to which it is replying.
	 *
	 * [ACK back to where the SHUTDOWN came from.]
	 */
702
	if (retval && chunk)
Jon Grimm's avatar
Jon Grimm committed
703 704
		retval->transport = chunk->transport;

705 706
	return retval;
}
Jon Grimm's avatar
Jon Grimm committed
707

708 709
sctp_chunk_t *sctp_make_shutdown_complete(const sctp_association_t *asoc,
					  const sctp_chunk_t *chunk)
Jon Grimm's avatar
Jon Grimm committed
710
{
711 712
	sctp_chunk_t *retval;
	__u8 flags = 0;
Jon Grimm's avatar
Jon Grimm committed
713

714 715
	/* Maybe set the T-bit if we have no association. */
	flags |= asoc ? 0 : SCTP_CHUNK_FLAG_T;
Jon Grimm's avatar
Jon Grimm committed
716

717
	retval = sctp_make_chunk(asoc, SCTP_CID_SHUTDOWN_COMPLETE, flags, 0);
Jon Grimm's avatar
Jon Grimm committed
718 719

	/* RFC 2960 6.4 Multi-homed SCTP Endpoints
720
	 *
Jon Grimm's avatar
Jon Grimm committed
721 722 723 724 725 726 727 728
	 * An endpoint SHOULD transmit reply chunks (e.g., SACK,
	 * HEARTBEAT ACK, * etc.) to the same destination transport
	 * address from which it * received the DATA or control chunk
	 * to which it is replying.
	 *
	 * [Report SHUTDOWN COMPLETE back to where the SHUTDOWN ACK
	 * came from.]
	 */
729
	if (retval && chunk)
Jon Grimm's avatar
Jon Grimm committed
730 731 732
		retval->transport = chunk->transport;

        return retval;
733
}
Jon Grimm's avatar
Jon Grimm committed
734 735 736 737

/* Create an ABORT.  Note that we set the T bit if we have no
 * association.
 */
738 739 740
sctp_chunk_t *sctp_make_abort(const sctp_association_t *asoc,
			      const sctp_chunk_t *chunk,
			      const size_t hint)
Jon Grimm's avatar
Jon Grimm committed
741
{
742 743
	sctp_chunk_t *retval;
	__u8 flags = 0;
Jon Grimm's avatar
Jon Grimm committed
744

745 746
	/* Maybe set the T-bit if we have no association.  */
	flags |= asoc ? 0 : SCTP_CHUNK_FLAG_T;
Jon Grimm's avatar
Jon Grimm committed
747

748
	retval = sctp_make_chunk(asoc, SCTP_CID_ABORT, flags, hint);
Jon Grimm's avatar
Jon Grimm committed
749 750

	/* RFC 2960 6.4 Multi-homed SCTP Endpoints
751
	 *
Jon Grimm's avatar
Jon Grimm committed
752 753 754 755 756 757 758
	 * An endpoint SHOULD transmit reply chunks (e.g., SACK,
	 * HEARTBEAT ACK, * etc.) to the same destination transport
	 * address from which it * received the DATA or control chunk
	 * to which it is replying.
	 *
	 * [ABORT back to where the offender came from.]
	 */
759
	if (retval && chunk)
Jon Grimm's avatar
Jon Grimm committed
760 761
		retval->transport = chunk->transport;

762 763
	return retval;
}
Jon Grimm's avatar
Jon Grimm committed
764

765 766 767
/* Helper to create ABORT with a NO_USER_DATA error.  */
sctp_chunk_t *sctp_make_abort_no_data(const sctp_association_t *asoc,
				      const sctp_chunk_t *chunk, __u32 tsn)
Jon Grimm's avatar
Jon Grimm committed
768
{
769 770
	sctp_chunk_t *retval;
	__u32 payload;
Jon Grimm's avatar
Jon Grimm committed
771

772
	retval = sctp_make_abort(asoc, chunk, sizeof(sctp_errhdr_t)
Jon Grimm's avatar
Jon Grimm committed
773 774
				 + sizeof(tsn));

775 776
	if (!retval)
		goto no_mem;
Jon Grimm's avatar
Jon Grimm committed
777

778
	/* Put the tsn back into network byte order.  */
Jon Grimm's avatar
Jon Grimm committed
779
	payload = htonl(tsn);
780
	sctp_init_cause(retval, SCTP_ERROR_NO_DATA, (const void *)&payload,
Jon Grimm's avatar
Jon Grimm committed
781 782 783
			sizeof(payload));

	/* RFC 2960 6.4 Multi-homed SCTP Endpoints
784
	 *
Jon Grimm's avatar
Jon Grimm committed
785 786 787 788 789 790 791
	 * An endpoint SHOULD transmit reply chunks (e.g., SACK,
	 * HEARTBEAT ACK, * etc.) to the same destination transport
	 * address from which it * received the DATA or control chunk
	 * to which it is replying.
	 *
	 * [ABORT back to where the offender came from.]
	 */
792
	if (chunk)
Jon Grimm's avatar
Jon Grimm committed
793 794 795
		retval->transport = chunk->transport;

no_mem:
796 797
	return retval;
}
Jon Grimm's avatar
Jon Grimm committed
798

799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845
/* Helper to create ABORT with a SCTP_ERROR_USER_ABORT error.  */
sctp_chunk_t *sctp_make_abort_user(const sctp_association_t *asoc,
				   const sctp_chunk_t *chunk,
				   const struct msghdr *msg)
{
	sctp_chunk_t *retval;
	void *payload = NULL, *payoff;
	size_t paylen;
	struct iovec *iov = msg->msg_iov;
	int iovlen = msg->msg_iovlen;

	paylen = get_user_iov_size(iov, iovlen);
	retval = sctp_make_abort(asoc, chunk, sizeof(sctp_errhdr_t) + paylen);
	if (!retval)
		goto err_chunk;

	if (paylen) {
		/* Put the msg_iov together into payload.  */
		payload = kmalloc(paylen, GFP_ATOMIC);
		if (!payload)
			goto err_payload;
		payoff = payload;

		for (; iovlen > 0; --iovlen) {
			if (copy_from_user(payoff, iov->iov_base, iov->iov_len))
				goto err_copy;
			payoff += iov->iov_len;
			iov++;
		}
	}

	sctp_init_cause(retval, SCTP_ERROR_USER_ABORT, payload, paylen);

	if (paylen)
		kfree(payload);

	return retval;

err_copy:
	kfree(payload);
err_payload:
	sctp_free_chunk(retval);
	retval = NULL;
err_chunk:
	return retval;
}

846 847
/* Make a HEARTBEAT chunk.  */
sctp_chunk_t *sctp_make_heartbeat(const sctp_association_t *asoc,
848
				  const struct sctp_transport *transport,
849
				  const void *payload, const size_t paylen)
Jon Grimm's avatar
Jon Grimm committed
850
{
851 852 853 854 855
	sctp_chunk_t *retval = sctp_make_chunk(asoc, SCTP_CID_HEARTBEAT,
					       0, paylen);

	if (!retval)
		goto nodata;
Jon Grimm's avatar
Jon Grimm committed
856 857 858 859

	/* Cast away the 'const', as this is just telling the chunk
	 * what transport it belongs to.
	 */
860
	retval->transport = (struct sctp_transport *) transport;
Jon Grimm's avatar
Jon Grimm committed
861 862
	retval->subh.hbs_hdr = sctp_addto_chunk(retval, paylen, payload);

863 864 865
nodata:
	return retval;
}
Jon Grimm's avatar
Jon Grimm committed
866

867 868 869
sctp_chunk_t *sctp_make_heartbeat_ack(const sctp_association_t *asoc,
				      const sctp_chunk_t *chunk,
				      const void *payload, const size_t paylen)
Jon Grimm's avatar
Jon Grimm committed
870
{
871 872 873 874 875
	sctp_chunk_t *retval = sctp_make_chunk(asoc, SCTP_CID_HEARTBEAT_ACK,
					       0, paylen);

	if (!retval)
		goto nodata;
Jon Grimm's avatar
Jon Grimm committed
876 877 878
	retval->subh.hbs_hdr = sctp_addto_chunk(retval, paylen, payload);

	/* RFC 2960 6.4 Multi-homed SCTP Endpoints
879
	 *
Jon Grimm's avatar
Jon Grimm committed
880 881 882 883 884 885 886
	 * An endpoint SHOULD transmit reply chunks (e.g., SACK,
	 * HEARTBEAT ACK, * etc.) to the same destination transport
	 * address from which it * received the DATA or control chunk
	 * to which it is replying.
	 *
	 * [HBACK back to where the HEARTBEAT came from.]
	 */
887
	if (chunk)
Jon Grimm's avatar
Jon Grimm committed
888 889
		retval->transport = chunk->transport;

890 891 892
nodata:
	return retval;
}
Jon Grimm's avatar
Jon Grimm committed
893

Daisy Chang's avatar
Daisy Chang committed
894
/* Create an Operation Error chunk with the specified space reserved.
895 896
 * This routine can be used for containing multiple causes in the chunk.
 */
Daisy Chang's avatar
Daisy Chang committed
897 898
sctp_chunk_t *sctp_make_op_error_space(const sctp_association_t *asoc,
				       const sctp_chunk_t *chunk,
899 900
				       size_t size)
{
Daisy Chang's avatar
Daisy Chang committed
901 902 903
	sctp_chunk_t *retval;

	retval = sctp_make_chunk(asoc, SCTP_CID_ERROR, 0,
904 905 906
				 sizeof(sctp_errhdr_t) + size);
	if (!retval)
		goto nodata;
Daisy Chang's avatar
Daisy Chang committed
907 908 909

	/* RFC 2960 6.4 Multi-homed SCTP Endpoints
	 *
910 911 912 913 914 915 916 917 918
	 * An endpoint SHOULD transmit reply chunks (e.g., SACK,
	 * HEARTBEAT ACK, etc.) to the same destination transport
	 * address from which it received the DATA or control chunk
	 * to which it is replying.
	 *
	 */
	if (chunk)
		retval->transport = chunk->transport;

Daisy Chang's avatar
Daisy Chang committed
919 920 921
nodata:
	return retval;
}
922

923 924 925 926 927
/* Create an Operation Error chunk.  */
sctp_chunk_t *sctp_make_op_error(const sctp_association_t *asoc,
				 const sctp_chunk_t *chunk,
				 __u16 cause_code, const void *payload,
				 size_t paylen)
Jon Grimm's avatar
Jon Grimm committed
928
{
929
	sctp_chunk_t *retval = sctp_make_op_error_space(asoc, chunk, paylen);
930 931 932

	if (!retval)
		goto nodata;
Jon Grimm's avatar
Jon Grimm committed
933

934
	sctp_init_cause(retval, cause_code, payload, paylen);
Jon Grimm's avatar
Jon Grimm committed
935

936 937 938
nodata:
	return retval;
}
Jon Grimm's avatar
Jon Grimm committed
939 940 941 942 943

/********************************************************************
 * 2nd Level Abstractions
 ********************************************************************/

944
/* Turn an skb into a chunk.
Jon Grimm's avatar
Jon Grimm committed
945 946
 * FIXME: Eventually move the structure directly inside the skb->cb[].
 */
947 948
sctp_chunk_t *sctp_chunkify(struct sk_buff *skb, const sctp_association_t *asoc,
			    struct sock *sk)
Jon Grimm's avatar
Jon Grimm committed
949
{
950 951 952 953 954 955 956 957 958 959 960 961 962 963
	sctp_chunk_t *retval = t_new(sctp_chunk_t, GFP_ATOMIC);

	if (!retval)
		goto nodata;
	memset(retval, 0, sizeof(sctp_chunk_t));

	if (!sk) {
		SCTP_DEBUG_PRINTK("chunkifying skb %p w/o an sk\n", skb);
	}

	retval->skb		= skb;
	retval->asoc		= (sctp_association_t *) asoc;
	retval->num_times_sent	= 0;
	retval->has_tsn		= 0;
964
	retval->has_ssn         = 0;
965 966 967 968 969 970 971 972 973
	retval->rtt_in_progress	= 0;
	retval->sent_at	= jiffies;
	retval->singleton	= 1;
	retval->end_of_packet	= 0;
	retval->ecn_ce_done	= 0;
	retval->pdiscard	= 0;

	/* sctpimpguide-05.txt Section 2.8.2
	 * M1) Each time a new DATA chunk is transmitted
Jon Grimm's avatar
Jon Grimm committed
974
	 * set the 'TSN.Missing.Report' count for that TSN to 0. The
975
	 * 'TSN.Missing.Report' count will be used to determine missing chunks
Jon Grimm's avatar
Jon Grimm committed
976 977 978 979 980 981
	 * and when to fast retransmit.
	 */
	retval->tsn_missing_report = 0;
	retval->tsn_gap_acked = 0;
	retval->fast_retransmit = 0;

982 983
	/* Polish the bead hole.  */
	INIT_LIST_HEAD(&retval->transmitted_list);
Jon Grimm's avatar
Jon Grimm committed
984 985 986
	INIT_LIST_HEAD(&retval->frag_list);
	SCTP_DBG_OBJCNT_INC(chunk);

987 988 989
nodata:
	return retval;
}
Jon Grimm's avatar
Jon Grimm committed
990

991
/* Set chunk->source and dest based on the IP header in chunk->skb.  */
992 993
void sctp_init_addrs(sctp_chunk_t *chunk, union sctp_addr *src,
		     union sctp_addr *dest)
Jon Grimm's avatar
Jon Grimm committed
994
{
995 996
	memcpy(&chunk->source, src, sizeof(union sctp_addr));
	memcpy(&chunk->dest, dest, sizeof(union sctp_addr));
997
}
Jon Grimm's avatar
Jon Grimm committed
998 999

/* Extract the source address from a chunk.  */
Jon Grimm's avatar
Jon Grimm committed
1000
const union sctp_addr *sctp_source(const sctp_chunk_t *chunk)
Jon Grimm's avatar
Jon Grimm committed
1001 1002 1003 1004
{
	/* If we have a known transport, use that.  */
	if (chunk->transport) {
		return &chunk->transport->ipaddr;
1005 1006
	} else {
		/* Otherwise, extract it from the IP header.  */
Jon Grimm's avatar
Jon Grimm committed
1007 1008
		return &chunk->source;
	}
1009
}
Jon Grimm's avatar
Jon Grimm committed
1010 1011 1012 1013

/* Create a new chunk, setting the type and flags headers from the
 * arguments, reserving enough space for a 'paylen' byte payload.
 */
1014 1015
sctp_chunk_t *sctp_make_chunk(const sctp_association_t *asoc,
			      __u8 type, __u8 flags, int paylen)
Jon Grimm's avatar
Jon Grimm committed
1016
{
1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039
	sctp_chunk_t *retval;
	sctp_chunkhdr_t *chunk_hdr;
	struct sk_buff *skb;
	struct sock *sk;

	skb = dev_alloc_skb(WORD_ROUND(sizeof(sctp_chunkhdr_t) + paylen));
	if (!skb)
		goto nodata;

	/* Make room for the chunk header.  */
	chunk_hdr = (sctp_chunkhdr_t *)skb_put(skb, sizeof(sctp_chunkhdr_t));
	skb_pull(skb, sizeof(sctp_chunkhdr_t));

	chunk_hdr->type	  = type;
	chunk_hdr->flags  = flags;
	chunk_hdr->length = htons(sizeof(sctp_chunkhdr_t));

	/* Move the data pointer back up to the start of the chunk.  */
	skb_push(skb, sizeof(sctp_chunkhdr_t));

	sk = asoc ? asoc->base.sk : NULL;
	retval = sctp_chunkify(skb, asoc, sk);
	if (!retval) {
Jon Grimm's avatar
Jon Grimm committed
1040
		dev_kfree_skb(skb);
1041 1042 1043 1044 1045
		goto nodata;
	}

	retval->chunk_hdr = chunk_hdr;
	retval->chunk_end = ((__u8 *)chunk_hdr) + sizeof(sctp_chunkhdr_t);
Jon Grimm's avatar
Jon Grimm committed
1046 1047 1048 1049

	/* Set the skb to the belonging sock for accounting.  */
	skb->sk = sk;

1050
	return retval;
Jon Grimm's avatar
Jon Grimm committed
1051

1052 1053 1054
nodata:
	return NULL;
}
Jon Grimm's avatar
Jon Grimm committed
1055 1056

/* Release the memory occupied by a chunk.  */
1057
void sctp_free_chunk(sctp_chunk_t *chunk)
Jon Grimm's avatar
Jon Grimm committed
1058
{
1059 1060 1061
	/* Make sure that we are not on any list.  */
	skb_unlink((struct sk_buff *) chunk);
	list_del(&chunk->transmitted_list);
Jon Grimm's avatar
Jon Grimm committed
1062 1063

	/* Free the chunk skb data and the SCTP_chunk stub itself. */
1064
	dev_kfree_skb(chunk->skb);
Jon Grimm's avatar
Jon Grimm committed
1065 1066 1067

	kfree(chunk);
	SCTP_DBG_OBJCNT_DEC(chunk);
1068
}
Jon Grimm's avatar
Jon Grimm committed
1069 1070 1071 1072 1073


/* Append bytes to the end of a chunk.  Will panic if chunk is not big
 * enough.
 */
1074
void *sctp_addto_chunk(sctp_chunk_t *chunk, int len, const void *data)
Jon Grimm's avatar
Jon Grimm committed
1075
{
1076 1077
	void *target;
	void *padding;
Jon Grimm's avatar
Jon Grimm committed
1078 1079 1080 1081
	int chunklen = ntohs(chunk->chunk_hdr->length);
	int padlen = chunklen % 4;

	padding = skb_put(chunk->skb, padlen);
1082 1083
	target = skb_put(chunk->skb, len);

Jon Grimm's avatar
Jon Grimm committed
1084
	memset(padding, 0, padlen);
1085
	memcpy(target, data, len);
Jon Grimm's avatar
Jon Grimm committed
1086

1087 1088 1089
	/* Adjust the chunk length field.  */
	chunk->chunk_hdr->length = htons(chunklen + padlen + len);
	chunk->chunk_end = chunk->skb->tail;
Jon Grimm's avatar
Jon Grimm committed
1090

1091 1092
	return target;
}
Jon Grimm's avatar
Jon Grimm committed
1093 1094 1095 1096 1097

/* Append bytes from user space to the end of a chunk.  Will panic if
 * chunk is not big enough.
 * Returns a kernel err value.
 */
Jon Grimm's avatar
Jon Grimm committed
1098 1099
static int sctp_user_addto_chunk(sctp_chunk_t *chunk, int off, int len,
				 struct iovec *data)
Jon Grimm's avatar
Jon Grimm committed
1100
{
1101 1102 1103 1104
	__u8 *target;
	int err = 0;

	/* Make room in chunk for data.  */
Jon Grimm's avatar
Jon Grimm committed
1105 1106 1107
	target = skb_put(chunk->skb, len);

	/* Copy data (whole iovec) into chunk */
Jon Grimm's avatar
Jon Grimm committed
1108
	if ((err = memcpy_fromiovecend(target, data, off, len)))
Jon Grimm's avatar
Jon Grimm committed
1109 1110
		goto out;

1111 1112 1113 1114
	/* Adjust the chunk length field.  */
	chunk->chunk_hdr->length =
		htons(ntohs(chunk->chunk_hdr->length) + len);
	chunk->chunk_end = chunk->skb->tail;
Jon Grimm's avatar
Jon Grimm committed
1115

1116 1117 1118
out:
	return err;
}
Jon Grimm's avatar
Jon Grimm committed
1119

Jon Grimm's avatar
Jon Grimm committed
1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171
/* A data chunk can have a maximum payload of (2^16 - 20).  Break
 * down any such message into smaller chunks.  Opportunistically, fragment
 * the chunks down to the current MTU constraints.  We may get refragmented
 * later if the PMTU changes, but it is _much better_ to fragment immediately
 * with a reasonable guess than always doing our fragmentation on the
 * soft-interrupt.
 */


int sctp_datachunks_from_user(sctp_association_t *asoc,
			      const struct sctp_sndrcvinfo *sinfo,
			      struct msghdr *msg, int msg_len,
			      struct sk_buff_head *chunks)
{
	int max, whole, i, offset, over, err;
	int len, first_len;
	sctp_chunk_t *chunk;
	__u8 frag;

	/* What is a reasonable fragmentation point right now? */
	max = asoc->pmtu;
	if (max < SCTP_MIN_PMTU)
		max = SCTP_MIN_PMTU;
	max -= SCTP_IP_OVERHEAD;

	/* Make sure not beyond maximum chunk size. */
	if (max > SCTP_MAX_CHUNK_LEN)
		max = SCTP_MAX_CHUNK_LEN;

	/* Subtract out the overhead of a data chunk header. */
	max -= sizeof(struct sctp_data_chunk);

	whole = 0;
	first_len = max;

	/* Encourage Cookie-ECHO bundling. */
	if (asoc->state < SCTP_STATE_ESTABLISHED) {
		whole = msg_len / (max - SCTP_ARBITRARY_COOKIE_ECHO_LEN);

		/* Account for the DATA to be bundled with the COOKIE-ECHO. */
		if (whole) {
			first_len = max - SCTP_ARBITRARY_COOKIE_ECHO_LEN;
			msg_len -= first_len;
			whole = 1;
		}
	} 

	/* How many full sized?  How many bytes leftover? */
	whole += msg_len / max;
	over = msg_len % max;
	offset = 0;

1172 1173 1174
	if (whole && over)
		SCTP_INC_STATS_USER(SctpFragUsrMsgs);

Jon Grimm's avatar
Jon Grimm committed
1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241
	/* Create chunks for all the full sized DATA chunks. */
	for (i=0, len=first_len; i < whole; i++) {
		frag = SCTP_DATA_MIDDLE_FRAG;

		if (0 == i)
			frag |= SCTP_DATA_FIRST_FRAG;

		if ((i == (whole - 1)) && !over)
			frag |= SCTP_DATA_LAST_FRAG;

		chunk = sctp_make_datafrag_empty(asoc, sinfo, len, frag, 0);

		if (!chunk)
			goto nomem;
		err = sctp_user_addto_chunk(chunk, offset, len, msg->msg_iov);
		if (err < 0)
			goto errout;

		offset += len;

		/* Put the chunk->skb back into the form expected by send.  */
		__skb_pull(chunk->skb, (__u8 *)chunk->chunk_hdr
			   - (__u8 *)chunk->skb->data);

		__skb_queue_tail(chunks, (struct sk_buff *)chunk);

		/* The first chunk, the first chunk was likely short 
		 * to allow bundling, so reset to full size.
		 */
		if (0 == i)
			len = max;
	}

	/* .. now the leftover bytes. */
	if (over) {
		if (!whole)
			frag = SCTP_DATA_NOT_FRAG;
		else
			frag = SCTP_DATA_LAST_FRAG;

		chunk = sctp_make_datafrag_empty(asoc, sinfo, over, frag, 0);

		if (!chunk)
			goto nomem;

		err = sctp_user_addto_chunk(chunk, offset, over, msg->msg_iov);

		/* Put the chunk->skb back into the form expected by send.  */
		__skb_pull(chunk->skb, (__u8 *)chunk->chunk_hdr
			   - (__u8 *)chunk->skb->data);
		if (err < 0)
			goto errout;

		__skb_queue_tail(chunks, (struct sk_buff *)chunk);
	}
	err = 0;
	goto out;

nomem:
	err = -ENOMEM;
errout:
	while ((chunk = (sctp_chunk_t *)__skb_dequeue(chunks)))
		sctp_free_chunk(chunk);
out:
	return err;
}

1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257
/* Helper function to assign a TSN if needed.  This assumes that both
 * the data_hdr and association have already been assigned.
 */
void sctp_chunk_assign_ssn(sctp_chunk_t *chunk)
{
	__u16 ssn;
	__u16 sid;

	if (chunk->has_ssn)
		return;

	/* This is the last possible instant to assign a SSN. */
	if (chunk->chunk_hdr->flags & SCTP_DATA_UNORDERED) {
		ssn = 0;
	} else {
		sid = htons(chunk->subh.data_hdr->stream);
Jon Grimm's avatar
Jon Grimm committed
1258 1259 1260 1261 1262
		if (chunk->chunk_hdr->flags & SCTP_DATA_LAST_FRAG)
			ssn = sctp_ssn_next(&chunk->asoc->ssnmap->out, sid);
		else
			ssn = sctp_ssn_peek(&chunk->asoc->ssnmap->out, sid);
		ssn = htons(ssn);
1263 1264 1265 1266 1267 1268
	}

	chunk->subh.data_hdr->ssn = ssn;
	chunk->has_ssn = 1;
}

Jon Grimm's avatar
Jon Grimm committed
1269
/* Helper function to assign a TSN if needed.  This assumes that both
1270
 * the data_hdr and association have already been assigned.
Jon Grimm's avatar
Jon Grimm committed
1271
 */
1272
void sctp_chunk_assign_tsn(sctp_chunk_t *chunk)
Jon Grimm's avatar
Jon Grimm committed
1273 1274 1275 1276 1277
{
	if (!chunk->has_tsn) {
		/* This is the last possible instant to
		 * assign a TSN.
		 */
1278
		chunk->subh.data_hdr->tsn =
1279
			htonl(sctp_association_get_next_tsn(chunk->asoc));
Jon Grimm's avatar
Jon Grimm committed
1280 1281 1282 1283 1284
		chunk->has_tsn = 1;
	}
}

/* Create a CLOSED association to use with an incoming packet.  */
1285 1286 1287
sctp_association_t *sctp_make_temp_asoc(const sctp_endpoint_t *ep,
					sctp_chunk_t *chunk,
					int priority)
Jon Grimm's avatar
Jon Grimm committed
1288
{
1289
	sctp_association_t *asoc;
Jon Grimm's avatar
Jon Grimm committed
1290 1291
	sctp_scope_t scope;

1292
	/* Create the bare association.  */
Jon Grimm's avatar
Jon Grimm committed
1293
	scope = sctp_scope(sctp_source(chunk));
1294 1295 1296 1297 1298 1299 1300 1301 1302 1303
	asoc = sctp_association_new(ep, ep->base.sk, scope, priority);
	if (!asoc)
		goto nodata;

	/* Create an entry for the source address of the packet.  */
	switch (chunk->skb->nh.iph->version) {
	case 4:
		asoc->c.peer_addr.v4.sin_family     = AF_INET;
		asoc->c.peer_addr.v4.sin_port = ntohs(chunk->sctp_hdr->source);
		asoc->c.peer_addr.v4.sin_addr.s_addr =
Jon Grimm's avatar
Jon Grimm committed
1304 1305
			chunk->skb->nh.iph->saddr;
                break;
1306 1307 1308

	case 6:
		asoc->c.peer_addr.v6.sin6_family     = AF_INET6;
Jon Grimm's avatar
Jon Grimm committed
1309
		asoc->c.peer_addr.v6.sin6_port
Jon Grimm's avatar
Jon Grimm committed
1310
			= ntohs(chunk->sctp_hdr->source);
1311 1312 1313 1314 1315
		asoc->c.peer_addr.v6.sin6_flowinfo = 0; /* BUG BUG BUG */
		asoc->c.peer_addr.v6.sin6_addr = chunk->skb->nh.ipv6h->saddr;
		asoc->c.peer_addr.v6.sin6_scope_id = 0; /* BUG BUG BUG */
		break;

Jon Grimm's avatar
Jon Grimm committed
1316
        default:
1317
		/* Yikes!  I never heard of this kind of address.  */
Jon Grimm's avatar
Jon Grimm committed
1318
		goto fail;
1319
	};
Jon Grimm's avatar
Jon Grimm committed
1320 1321

nodata:
1322 1323
	return asoc;

Jon Grimm's avatar
Jon Grimm committed
1324 1325 1326
fail:
	sctp_association_free(asoc);
	return NULL;
1327
}
Jon Grimm's avatar
Jon Grimm committed
1328 1329 1330 1331

/* Build a cookie representing asoc.
 * This INCLUDES the param header needed to put the cookie in the INIT ACK.
 */
1332 1333 1334 1335 1336
sctp_cookie_param_t *sctp_pack_cookie(const sctp_endpoint_t *ep,
				      const sctp_association_t *asoc,
				      const sctp_chunk_t *init_chunk,
				      int *cookie_len,
				      const __u8 *raw_addrs, int addrs_len)
Jon Grimm's avatar
Jon Grimm committed
1337
{
1338
	sctp_cookie_param_t *retval;
Jon Grimm's avatar
Jon Grimm committed
1339
	sctp_signed_cookie_t *cookie;
1340
	int headersize, bodysize;
Jon Grimm's avatar
Jon Grimm committed
1341

1342 1343
	headersize = sizeof(sctp_paramhdr_t) + SCTP_SECRET_SIZE;
	bodysize = sizeof(sctp_cookie_t)
Jon Grimm's avatar
Jon Grimm committed
1344 1345 1346 1347 1348
		+ ntohs(init_chunk->chunk_hdr->length) + addrs_len;

	/* Pad out the cookie to a multiple to make the signature
	 * functions simpler to write.
	 */
1349
	if (bodysize % SCTP_COOKIE_MULTIPLE)
Jon Grimm's avatar
Jon Grimm committed
1350
		bodysize += SCTP_COOKIE_MULTIPLE
Jon Grimm's avatar
Jon Grimm committed
1351
			- (bodysize % SCTP_COOKIE_MULTIPLE);
1352
	*cookie_len = headersize + bodysize;
Jon Grimm's avatar
Jon Grimm committed
1353

1354 1355 1356 1357
	retval = (sctp_cookie_param_t *)
		kmalloc(*cookie_len, GFP_ATOMIC);
	if (!retval) {
		*cookie_len = 0;
Jon Grimm's avatar
Jon Grimm committed
1358
		goto nodata;
1359
	}
Jon Grimm's avatar
Jon Grimm committed
1360 1361 1362 1363 1364

	/* Clear this memory since we are sending this data structure
	 * out on the network.
	 */
	memset(retval, 0x00, *cookie_len);
1365
	cookie = (sctp_signed_cookie_t *) retval->body;
Jon Grimm's avatar
Jon Grimm committed
1366

1367 1368 1369
	/* Set up the parameter header.  */
	retval->p.type = SCTP_PARAM_STATE_COOKIE;
	retval->p.length = htons(*cookie_len);
Jon Grimm's avatar
Jon Grimm committed
1370

1371 1372
	/* Copy the cookie part of the association itself.  */
	cookie->c = asoc->c;
Jon Grimm's avatar
Jon Grimm committed
1373 1374 1375
	/* Save the raw address list length in the cookie. */
	cookie->c.raw_addr_list_len = addrs_len;

1376 1377 1378 1379 1380 1381 1382
	/* Set an expiration time for the cookie.  */
	do_gettimeofday(&cookie->c.expiration);
	tv_add(&asoc->cookie_life, &cookie->c.expiration);

	/* Copy the peer's init packet.  */
	memcpy(&cookie->c.peer_init[0], init_chunk->chunk_hdr,
	       ntohs(init_chunk->chunk_hdr->length));
Jon Grimm's avatar
Jon Grimm committed
1383 1384

	/* Copy the raw local address list of the association. */
1385 1386 1387
	memcpy((__u8 *)&cookie->c.peer_init[0] +
	       ntohs(init_chunk->chunk_hdr->length), raw_addrs,
	       addrs_len);
Jon Grimm's avatar
Jon Grimm committed
1388

1389 1390 1391 1392 1393 1394 1395
	/* Sign the message.  */
	sctp_hash_digest(ep->secret_key[ep->current_key], SCTP_SECRET_SIZE,
			 (__u8 *) &cookie->c, bodysize, cookie->signature);

nodata:
	return retval;
}
Jon Grimm's avatar
Jon Grimm committed
1396 1397

/* Unpack the cookie from COOKIE ECHO chunk, recreating the association.  */
1398 1399 1400
sctp_association_t *sctp_unpack_cookie(const sctp_endpoint_t *ep,
				       const sctp_association_t *asoc,
				       sctp_chunk_t *chunk, int priority,
1401
				       int *error, sctp_chunk_t **err_chk_p)
Jon Grimm's avatar
Jon Grimm committed
1402
{
1403 1404 1405 1406
	sctp_association_t *retval = NULL;
	sctp_signed_cookie_t *cookie;
	sctp_cookie_t *bear_cookie;
	int headersize, bodysize;
1407
	int fixed_size;
1408 1409
	__u8 digest_buf[SCTP_SIGNATURE_SIZE];
	int secret;
Jon Grimm's avatar
Jon Grimm committed
1410
	sctp_scope_t scope;
1411 1412 1413

	headersize = sizeof(sctp_chunkhdr_t) + SCTP_SECRET_SIZE;
	bodysize = ntohs(chunk->chunk_hdr->length) - headersize;
Jon Grimm's avatar
Jon Grimm committed
1414 1415
	fixed_size = headersize + sizeof(sctp_cookie_t);

1416
	/* Verify that the chunk looks like it even has a cookie.
Jon Grimm's avatar
Jon Grimm committed
1417 1418 1419
	 * There must be enough room for our cookie and our peer's
	 * INIT chunk.
	 */
1420 1421
	if (ntohs(chunk->chunk_hdr->length) <
	    (fixed_size + sizeof(sctp_chunkhdr_t)))
Jon Grimm's avatar
Jon Grimm committed
1422 1423 1424
		goto malformed;

	/* Verify that the cookie has been padded out. */
1425
	if (bodysize % SCTP_COOKIE_MULTIPLE)
Jon Grimm's avatar
Jon Grimm committed
1426 1427 1428
		goto malformed;

	/* Process the cookie.  */
1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444
	cookie = chunk->subh.cookie_hdr;
	bear_cookie = &cookie->c;

	/* Check the signature.  */
	secret = ep->current_key;
	sctp_hash_digest(ep->secret_key[secret], SCTP_SECRET_SIZE,
			 (__u8 *) bear_cookie, bodysize,
			 digest_buf);
	if (memcmp(digest_buf, cookie->signature, SCTP_SIGNATURE_SIZE)) {
		/* Try the previous key. */
		secret = ep->last_key;
		sctp_hash_digest(ep->secret_key[secret], SCTP_SECRET_SIZE,
				 (__u8 *) bear_cookie, bodysize, digest_buf);
		if (memcmp(digest_buf, cookie->signature, SCTP_SIGNATURE_SIZE)) {
			/* Yikes!  Still bad signature! */
			*error = -SCTP_IERROR_BAD_SIG;
Jon Grimm's avatar
Jon Grimm committed
1445
			goto fail;
1446 1447
		}
	}
Jon Grimm's avatar
Jon Grimm committed
1448 1449 1450 1451 1452

	/* Check to see if the cookie is stale.  If there is already
	 * an association, there is no need to check cookie's expiration
	 * for init collision case of lost COOKIE ACK.
	 */
1453
	if (!asoc && tv_lt(bear_cookie->expiration, chunk->skb->stamp)) {
1454
		__u16 len;
1455 1456 1457 1458 1459 1460 1461 1462
		/*
		 * Section 3.3.10.3 Stale Cookie Error (3)
		 *
		 * Cause of error
		 * ---------------
		 * Stale Cookie Error:  Indicates the receipt of a valid State
		 * Cookie that has expired.
		 */
1463 1464
		len = ntohs(chunk->chunk_hdr->length);
		*err_chk_p = sctp_make_op_error_space(asoc, chunk, len);
1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477
		if (*err_chk_p) {
			suseconds_t usecs = (chunk->skb->stamp.tv_sec -
				bear_cookie->expiration.tv_sec) * 1000000L +
				chunk->skb->stamp.tv_usec -
				bear_cookie->expiration.tv_usec;

			usecs = htonl(usecs);
			sctp_init_cause(*err_chk_p, SCTP_ERROR_STALE_COOKIE,
					&usecs, sizeof(usecs));
			*error = -SCTP_IERROR_STALE_COOKIE;
		} else
			*error = -SCTP_IERROR_NOMEM;

Jon Grimm's avatar
Jon Grimm committed
1478
		goto fail;
1479
	}
Jon Grimm's avatar
Jon Grimm committed
1480

1481
	/* Make a new base association.  */
Jon Grimm's avatar
Jon Grimm committed
1482
	scope = sctp_scope(sctp_source(chunk));
1483 1484 1485
	retval = sctp_association_new(ep, ep->base.sk, scope, priority);
	if (!retval) {
		*error = -SCTP_IERROR_NOMEM;
Jon Grimm's avatar
Jon Grimm committed
1486
		goto fail;
1487
	}
Jon Grimm's avatar
Jon Grimm committed
1488 1489 1490 1491

	/* Set up our peer's port number.  */
	retval->peer.port = ntohs(chunk->sctp_hdr->source);

1492 1493 1494
	/* Populate the association from the cookie.  */
	retval->c = *bear_cookie;

1495 1496
	if (sctp_assoc_set_bind_addr_from_cookie(retval, bear_cookie,
						 GFP_ATOMIC) < 0) {
Jon Grimm's avatar
Jon Grimm committed
1497 1498 1499 1500 1501
		*error = -SCTP_IERROR_NOMEM;
		goto fail;
	}

	retval->next_tsn = retval->c.initial_tsn;
1502
	retval->ctsn_ack_point = retval->next_tsn - 1;
Jon Grimm's avatar
Jon Grimm committed
1503 1504

	/* The INIT stuff will be done by the side effects.  */
1505
	return retval;
Jon Grimm's avatar
Jon Grimm committed
1506

1507 1508
fail:
	if (retval)
Jon Grimm's avatar
Jon Grimm committed
1509 1510 1511 1512
		sctp_association_free(retval);

	return NULL;

1513
malformed:
Jon Grimm's avatar
Jon Grimm committed
1514 1515 1516 1517 1518
	/* Yikes!  The packet is either corrupt or deliberately
	 * malformed.
	 */
	*error = -SCTP_IERROR_MALFORMED;
	goto fail;
1519
}
Jon Grimm's avatar
Jon Grimm committed
1520 1521 1522 1523 1524

/********************************************************************
 * 3rd Level Abstractions
 ********************************************************************/

1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575
/*
 * Report a missing mandatory parameter.
 */
struct __sctp_missing {
	__u32 num_missing;
	__u16 type;
}  __attribute__((packed));;
static int sctp_process_missing_param(const sctp_association_t *asoc,
				      sctp_param_t paramtype,
				      sctp_chunk_t *chunk,
				      sctp_chunk_t **err_chk_p)
{
	struct __sctp_missing report;
	__u16 len;

	len = WORD_ROUND(sizeof(report));

	/* Make an ERROR chunk, preparing enough room for
	 * returning multiple unknown parameters.
	 */
	if (!*err_chk_p)
		*err_chk_p = sctp_make_op_error_space(asoc, chunk, len);

	if (*err_chk_p) {
		report.num_missing = htonl(1);
		report.type = paramtype;
		sctp_init_cause(*err_chk_p, SCTP_ERROR_INV_PARAM,
				&report, sizeof(report));
	}

	/* Stop processing this chunk. */
	return 0;
}

/* Report an Invalid Mandatory Parameter.  */
static int sctp_process_inv_mandatory(const sctp_association_t *asoc,
				      sctp_chunk_t *chunk,
				      sctp_chunk_t **err_chk_p)
{
	/* Invalid Mandatory Parameter Error has no payload. */

	if (!*err_chk_p)
		*err_chk_p = sctp_make_op_error_space(asoc, chunk, 0);

	if (*err_chk_p)
		sctp_init_cause(*err_chk_p, SCTP_ERROR_INV_PARAM, NULL, 0);

	/* Stop processing this chunk. */
	return 0;
}

1576 1577
/* Do not attempt to handle the HOST_NAME parm.  However, do
 * send back an indicator to the peer.
1578
 */
1579 1580 1581 1582
static int sctp_process_hn_param(const sctp_association_t *asoc,
				 union sctp_params param,
				 sctp_chunk_t *chunk,
				 sctp_chunk_t **err_chk_p)
1583
{
1584
	__u16 len = ntohs(param.p->length);
1585

1586
	/* Make an ERROR chunk. */
1587 1588
	if (!*err_chk_p)
		*err_chk_p = sctp_make_op_error_space(asoc, chunk, len);
1589

1590 1591 1592
	if (*err_chk_p)
		sctp_init_cause(*err_chk_p, SCTP_ERROR_DNS_FAILED,
				param.v, len);
1593

1594 1595
	/* Stop processing this chunk. */
	return 0;
1596 1597 1598 1599
}

/* RFC 3.2.1 & the Implementers Guide 2.2.
 *
Daisy Chang's avatar
Daisy Chang committed
1600 1601 1602
 * The Parameter Types are encoded such that the
 * highest-order two bits specify the action that must be
 * taken if the processing endpoint does not recognize the
1603 1604
 * Parameter Type.
 *
Daisy Chang's avatar
Daisy Chang committed
1605
 * 00 - Stop processing this SCTP chunk and discard it,
1606 1607
 *	do not process any further chunks within it.
 *
Daisy Chang's avatar
Daisy Chang committed
1608
 * 01 - Stop processing this SCTP chunk and discard it,
Daisy Chang's avatar
Daisy Chang committed
1609 1610
 *	do not process any further chunks within it, and report
 *	the unrecognized parameter in an 'Unrecognized
1611 1612 1613 1614
 *	Parameter Type' (in either an ERROR or in the INIT ACK).
 *
 * 10 - Skip this parameter and continue processing.
 *
Daisy Chang's avatar
Daisy Chang committed
1615 1616 1617
 * 11 - Skip this parameter and continue processing but
 *	report the unrecognized parameter in an
 *	'Unrecognized Parameter Type' (in either an ERROR or in
1618 1619 1620 1621 1622 1623
 *	the INIT ACK).
 *
 * Return value:
 * 	0 - discard the chunk
 * 	1 - continue with the chunk
 */
1624 1625 1626 1627
static int sctp_process_unk_param(const sctp_association_t *asoc,
				  union sctp_params param,
				  sctp_chunk_t *chunk,
				  sctp_chunk_t **err_chk_p)
1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641
{
	int retval = 1;

	switch (param.p->type & SCTP_PARAM_ACTION_MASK) {
	case SCTP_PARAM_ACTION_DISCARD:
		retval =  0;
		break;
	case SCTP_PARAM_ACTION_DISCARD_ERR:
		retval =  0;
		/* Make an ERROR chunk, preparing enough room for
		 * returning multiple unknown parameters.
		 */
		if (NULL == *err_chk_p)
			*err_chk_p = sctp_make_op_error_space(asoc, chunk,
Daisy Chang's avatar
Daisy Chang committed
1642
					ntohs(chunk->chunk_hdr->length));
1643 1644 1645

		if (*err_chk_p)
			sctp_init_cause(*err_chk_p, SCTP_ERROR_UNKNOWN_PARAM,
1646
					param.v,
1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657
					WORD_ROUND(ntohs(param.p->length)));

		break;
	case SCTP_PARAM_ACTION_SKIP:
		break;
	case SCTP_PARAM_ACTION_SKIP_ERR:
		/* Make an ERROR chunk, preparing enough room for
		 * returning multiple unknown parameters.
		 */
		if (NULL == *err_chk_p)
			*err_chk_p = sctp_make_op_error_space(asoc, chunk,
Daisy Chang's avatar
Daisy Chang committed
1658
					ntohs(chunk->chunk_hdr->length));
1659 1660 1661

		if (*err_chk_p) {
			sctp_init_cause(*err_chk_p, SCTP_ERROR_UNKNOWN_PARAM,
1662
					param.v,
1663 1664
					WORD_ROUND(ntohs(param.p->length)));
		} else {
Daisy Chang's avatar
Daisy Chang committed
1665 1666
			/* If there is no memory for generating the ERROR
			 * report as specified, an ABORT will be triggered
1667 1668
			 * to the peer and the association won't be
			 * established.
1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680
			 */
			retval = 0;
		}

		break;
	default:
		break;
	}

	return retval;
}

1681 1682 1683 1684
/* Find unrecognized parameters in the chunk.
 * Return values:
 * 	0 - discard the chunk
 * 	1 - continue with the chunk
Jon Grimm's avatar
Jon Grimm committed
1685
 */
1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730
static int sctp_verify_param(const sctp_association_t *asoc,
			     union sctp_params param,
			     sctp_cid_t cid,
			     sctp_chunk_t *chunk,
			     sctp_chunk_t **err_chunk)
{
	int retval = 1;

	/* FIXME - This routine is not looking at each parameter per the
	 * chunk type, i.e., unrecognized parameters should be further
	 * identified based on the chunk id.
	 */

	switch (param.p->type) {
	case SCTP_PARAM_IPV4_ADDRESS:
	case SCTP_PARAM_IPV6_ADDRESS:
	case SCTP_PARAM_COOKIE_PRESERVATIVE:
	case SCTP_PARAM_SUPPORTED_ADDRESS_TYPES:
	case SCTP_PARAM_STATE_COOKIE:
	case SCTP_PARAM_HEARTBEAT_INFO:
	case SCTP_PARAM_UNRECOGNIZED_PARAMETERS:
	case SCTP_PARAM_ECN_CAPABLE:
		break;

	case SCTP_PARAM_HOST_NAME_ADDRESS:
		/* Tell the peer, we won't support this param.  */
		return sctp_process_hn_param(asoc, param, chunk, err_chunk);
	default:
		SCTP_DEBUG_PRINTK("Unrecognized param: %d for chunk %d.\n",
				ntohs(param.p->type), cid);
		return sctp_process_unk_param(asoc, param, chunk, err_chunk);

		break;
	}
	return retval;
}

/* Verify the INIT packet before we process it.  */
int sctp_verify_init(const sctp_association_t *asoc,
		     sctp_cid_t cid,
		     sctp_init_chunk_t *peer_init,
		     sctp_chunk_t *chunk,
		     sctp_chunk_t **err_chk_p)
{
	union sctp_params param;
1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747
	int has_cookie = 0;

	/* Verify stream values are non-zero. */
	if ((0 == peer_init->init_hdr.num_outbound_streams) ||
	    (0 == peer_init->init_hdr.num_inbound_streams)) {

		sctp_process_inv_mandatory(asoc, chunk, err_chk_p);
		return 0;
	}

	/* Check for missing mandatory parameters.  */
	sctp_walk_params(param, peer_init, init_hdr.params) {

		if (SCTP_PARAM_STATE_COOKIE == param.p->type)
			has_cookie = 1;

	} /* for (loop through all parameters) */
1748

1749 1750
	/* The only missing mandatory param possible today is
	 * the state cookie for an INIT-ACK chunk.
1751
	 */
1752 1753 1754 1755 1756 1757
	if ((SCTP_CID_INIT_ACK == cid) && !has_cookie) {

		sctp_process_missing_param(asoc, SCTP_PARAM_STATE_COOKIE,
					   chunk, err_chk_p);
		return 0;
	}
1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772

	/* Find unrecognized parameters. */

	sctp_walk_params(param, peer_init, init_hdr.params) {

		if (!sctp_verify_param(asoc, param, cid, chunk, err_chk_p))
			return 0;

	} /* for (loop through all parameters) */

	return 1;
}

/* Unpack the parameters in an INIT packet into an association.
 * Returns 0 on failure, else success.
1773
 * FIXME:  This is an association method.
1774 1775
 */
int sctp_process_init(sctp_association_t *asoc, sctp_cid_t cid,
Jon Grimm's avatar
Jon Grimm committed
1776
		      const union sctp_addr *peer_addr,
1777 1778
		      sctp_init_chunk_t *peer_init,
		      int priority)
Jon Grimm's avatar
Jon Grimm committed
1779
{
1780
	union sctp_params param;
1781
	struct sctp_transport *transport;
Rusty Russell's avatar
Rusty Russell committed
1782
	struct list_head *pos, *temp;
Jon Grimm's avatar
Jon Grimm committed
1783
	char *cookie;
Jon Grimm's avatar
Jon Grimm committed
1784

1785
	/* We must include the address that the INIT packet came from.
Jon Grimm's avatar
Jon Grimm committed
1786 1787 1788 1789 1790 1791 1792 1793 1794
	 * This is the only address that matters for an INIT packet.
	 * When processing a COOKIE ECHO, we retrieve the from address
	 * of the INIT from the cookie.
	 */

	/* This implementation defaults to making the first transport
	 * added as the primary transport.  The source address seems to
	 * be a a better choice than any of the embedded addresses.
	 */
1795
	if (peer_addr)
1796 1797
		if(!sctp_assoc_add_peer(asoc, peer_addr, priority))
			goto nomem;
Jon Grimm's avatar
Jon Grimm committed
1798

1799
	/* Process the initialization parameters.  */
1800 1801 1802

	sctp_walk_params(param, peer_init, init_hdr.params) {

1803
		if (!sctp_process_param(asoc, param, peer_addr, priority))
Jon Grimm's avatar
Jon Grimm committed
1804
                        goto clean_up;
1805
	}
Jon Grimm's avatar
Jon Grimm committed
1806 1807 1808 1809

	/* The fixed INIT headers are always in network byte
	 * order.
	 */
1810
	asoc->peer.i.init_tag =
Jon Grimm's avatar
Jon Grimm committed
1811 1812 1813
		ntohl(peer_init->init_hdr.init_tag);
	asoc->peer.i.a_rwnd =
		ntohl(peer_init->init_hdr.a_rwnd);
1814
	asoc->peer.i.num_outbound_streams =
Jon Grimm's avatar
Jon Grimm committed
1815
		ntohs(peer_init->init_hdr.num_outbound_streams);
1816
	asoc->peer.i.num_inbound_streams =
Jon Grimm's avatar
Jon Grimm committed
1817
		ntohs(peer_init->init_hdr.num_inbound_streams);
1818
	asoc->peer.i.initial_tsn =
Jon Grimm's avatar
Jon Grimm committed
1819 1820
		ntohl(peer_init->init_hdr.initial_tsn);

1821 1822
	/* Apply the upper bounds for output streams based on peer's
	 * number of inbound streams.
Jon Grimm's avatar
Jon Grimm committed
1823
	 */
1824 1825
	if (asoc->c.sinit_num_ostreams  >
	    ntohs(peer_init->init_hdr.num_inbound_streams)) {
Jon Grimm's avatar
Jon Grimm committed
1826
		asoc->c.sinit_num_ostreams =
Jon Grimm's avatar
Jon Grimm committed
1827
			ntohs(peer_init->init_hdr.num_inbound_streams);
1828
	}
Jon Grimm's avatar
Jon Grimm committed
1829

1830 1831 1832 1833 1834 1835
	if (asoc->c.sinit_max_instreams >
	    ntohs(peer_init->init_hdr.num_outbound_streams)) {
		asoc->c.sinit_max_instreams =
			ntohs(peer_init->init_hdr.num_outbound_streams);
	}

1836
	/* Copy Initiation tag from INIT to VT_peer in cookie.   */
Jon Grimm's avatar
Jon Grimm committed
1837 1838
	asoc->c.peer_vtag = asoc->peer.i.init_tag;

1839
	/* Peer Rwnd   : Current calculated value of the peer's rwnd.  */
Jon Grimm's avatar
Jon Grimm committed
1840 1841
	asoc->peer.rwnd = asoc->peer.i.a_rwnd;

Jon Grimm's avatar
Jon Grimm committed
1842 1843 1844 1845 1846 1847 1848 1849 1850
	/* Copy cookie in case we need to resend COOKIE-ECHO. */
	cookie = asoc->peer.cookie;
	if (cookie) {
		asoc->peer.cookie = kmalloc(asoc->peer.cookie_len, priority);
		if (!asoc->peer.cookie)
			goto clean_up;
		memcpy(asoc->peer.cookie, cookie, asoc->peer.cookie_len);
	}

1851
	/* RFC 2960 7.2.1 The initial value of ssthresh MAY be arbitrarily
Jon Grimm's avatar
Jon Grimm committed
1852 1853 1854 1855
	 * high (for example, implementations MAY use the size of the receiver
	 * advertised window).
	 */
	list_for_each(pos, &asoc->peer.transport_addr_list) {
1856
		transport = list_entry(pos, struct sctp_transport, transports);
Jon Grimm's avatar
Jon Grimm committed
1857 1858 1859 1860 1861 1862 1863
		transport->ssthresh = asoc->peer.i.a_rwnd;
	}

	/* Set up the TSN tracking pieces.  */
	sctp_tsnmap_init(&asoc->peer.tsn_map, SCTP_TSN_MAP_SIZE,
			 asoc->peer.i.initial_tsn);

1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878
	/* RFC 2960 6.5 Stream Identifier and Stream Sequence Number
	 *
	 * The stream sequence number in all the streams shall start
	 * from 0 when the association is established.  Also, when the
	 * stream sequence number reaches the value 65535 the next
	 * stream sequence number shall be set to 0.
	 */

	/* Allocate storage for the negotiated streams. */
	asoc->ssnmap = sctp_ssnmap_new(asoc->peer.i.num_outbound_streams,
				       asoc->c.sinit_num_ostreams,
				       priority);
	if (!asoc->ssnmap)
		goto nomem_ssnmap;

Jon Grimm's avatar
Jon Grimm committed
1879
	/* ADDIP Section 4.1 ASCONF Chunk Procedures
1880
	 *
Jon Grimm's avatar
Jon Grimm committed
1881 1882 1883 1884 1885 1886 1887 1888 1889
	 * When an endpoint has an ASCONF signaled change to be sent to the
	 * remote endpoint it should do the following:
	 * ...
	 * A2) A serial number should be assigned to the Chunk. The serial
	 * number should be a monotonically increasing number. All serial
	 * numbers are defined to be initialized at the start of the
	 * association to the same value as the Initial TSN.
	 */
	asoc->peer.addip_serial = asoc->peer.i.initial_tsn - 1;
1890
	return 1;
1891

1892
nomem_ssnmap:
1893 1894 1895
clean_up:
	/* Release the transport structures. */
	list_for_each_safe(pos, temp, &asoc->peer.transport_addr_list) {
1896
		transport = list_entry(pos, struct sctp_transport, transports);
Jon Grimm's avatar
Jon Grimm committed
1897 1898 1899
		list_del(pos);
		sctp_transport_free(transport);
	}
1900 1901
nomem:
	return 0;
1902
}
Jon Grimm's avatar
Jon Grimm committed
1903

1904

Jon Grimm's avatar
Jon Grimm committed
1905
/* Update asoc with the option described in param.
1906
 *
Jon Grimm's avatar
Jon Grimm committed
1907 1908 1909 1910 1911 1912 1913 1914 1915
 * RFC2960 3.3.2.1 Optional/Variable Length Parameters in INIT
 *
 * asoc is the association to update.
 * param is the variable length parameter to use for update.
 * cid tells us if this is an INIT, INIT ACK or COOKIE ECHO.
 * If the current packet is an INIT we want to minimize the amount of
 * work we do.  In particular, we should not build transport
 * structures for the addresses.
 */
1916
int sctp_process_param(sctp_association_t *asoc, union sctp_params param,
Jon Grimm's avatar
Jon Grimm committed
1917
		       const union sctp_addr *peer_addr, int priority)
Jon Grimm's avatar
Jon Grimm committed
1918
{
Jon Grimm's avatar
Jon Grimm committed
1919
	union sctp_addr addr;
Jon Grimm's avatar
Jon Grimm committed
1920
	int i;
1921
	__u16 sat;
Jon Grimm's avatar
Jon Grimm committed
1922 1923
	int retval = 1;
	sctp_scope_t scope;
1924
	time_t stale;
Jon Grimm's avatar
Jon Grimm committed
1925

1926 1927 1928 1929
	/* We maintain all INIT parameters in network byte order all the
	 * time.  This allows us to not worry about whether the parameters
	 * came from a fresh INIT, and INIT ACK, or were stored in a cookie.
	 */
Jon Grimm's avatar
Jon Grimm committed
1930
	switch (param.p->type) {
1931 1932 1933 1934
	case SCTP_PARAM_IPV6_ADDRESS:
		if( PF_INET6 != asoc->base.sk->family)
			break;
		/* Fall through. */
Jon Grimm's avatar
Jon Grimm committed
1935
	case SCTP_PARAM_IPV4_ADDRESS:
1936
		sctp_param2sockaddr(&addr, param.addr, asoc->peer.port);
1937 1938
		scope = sctp_scope(peer_addr);
		if (sctp_in_scope(&addr, scope))
1939 1940
			if (!sctp_assoc_add_peer(asoc, &addr, priority))
				return 0;
Jon Grimm's avatar
Jon Grimm committed
1941
		break;
1942

Jon Grimm's avatar
Jon Grimm committed
1943
	case SCTP_PARAM_COOKIE_PRESERVATIVE:
1944 1945 1946 1947 1948 1949 1950 1951 1952 1953
		if (!sctp_proto.cookie_preserve_enable)
			break;

		stale = ntohl(param.life->lifespan_increment);

		/* Suggested Cookie Life span increment's unit is msec,
		 * (1/1000sec).
		 */
		asoc->cookie_life.tv_sec += stale / 1000;
		asoc->cookie_life.tv_usec += (stale % 1000) * 1000;
Jon Grimm's avatar
Jon Grimm committed
1954
		break;
1955

Jon Grimm's avatar
Jon Grimm committed
1956
	case SCTP_PARAM_HOST_NAME_ADDRESS:
Jon Grimm's avatar
Jon Grimm committed
1957
		SCTP_DEBUG_PRINTK("unimplemented SCTP_HOST_NAME_ADDRESS\n");
1958 1959
		break;

Jon Grimm's avatar
Jon Grimm committed
1960 1961
	case SCTP_PARAM_SUPPORTED_ADDRESS_TYPES:
		/* Turn off the default values first so we'll know which
1962
		 * ones are really set by the peer.
Jon Grimm's avatar
Jon Grimm committed
1963 1964 1965 1966
		 */
		asoc->peer.ipv4_address = 0;
		asoc->peer.ipv6_address = 0;

1967 1968 1969 1970 1971 1972
		/* Cycle through address types; avoid divide by 0. */
		sat = ntohs(param.p->length) - sizeof(sctp_paramhdr_t);
		if (sat)
			sat /= sizeof(__u16);

		for (i = 0; i < sat; ++i) {
Jon Grimm's avatar
Jon Grimm committed
1973 1974 1975 1976
			switch (param.sat->types[i]) {
			case SCTP_PARAM_IPV4_ADDRESS:
				asoc->peer.ipv4_address = 1;
				break;
1977

Jon Grimm's avatar
Jon Grimm committed
1978 1979 1980
			case SCTP_PARAM_IPV6_ADDRESS:
				asoc->peer.ipv6_address = 1;
				break;
1981

Jon Grimm's avatar
Jon Grimm committed
1982 1983 1984
			case SCTP_PARAM_HOST_NAME_ADDRESS:
				asoc->peer.hostname_address = 1;
				break;
1985

Jon Grimm's avatar
Jon Grimm committed
1986 1987
			default: /* Just ignore anything else.  */
				break;
1988
			};
Jon Grimm's avatar
Jon Grimm committed
1989 1990
		}
		break;
1991

Jon Grimm's avatar
Jon Grimm committed
1992 1993
	case SCTP_PARAM_STATE_COOKIE:
		asoc->peer.cookie_len =
Jon Grimm's avatar
Jon Grimm committed
1994
			ntohs(param.p->length) - sizeof(sctp_paramhdr_t);
Jon Grimm's avatar
Jon Grimm committed
1995 1996
		asoc->peer.cookie = param.cookie->body;
		break;
1997

1998
	case SCTP_PARAM_HEARTBEAT_INFO:
1999
		/* Would be odd to receive, but it causes no problems. */
Jon Grimm's avatar
Jon Grimm committed
2000
		break;
2001

Jon Grimm's avatar
Jon Grimm committed
2002
	case SCTP_PARAM_UNRECOGNIZED_PARAMETERS:
2003
		/* Rejected during verify stage. */
Jon Grimm's avatar
Jon Grimm committed
2004
		break;
2005

Jon Grimm's avatar
Jon Grimm committed
2006
	case SCTP_PARAM_ECN_CAPABLE:
2007
		asoc->peer.ecn_capable = 1;
Jon Grimm's avatar
Jon Grimm committed
2008
		break;
2009

Jon Grimm's avatar
Jon Grimm committed
2010
	default:
2011 2012 2013 2014
		/* Any unrecognized parameters should have been caught
		 * and handled by sctp_verify_param() which should be
		 * called prior to this routine.  Simply log the error
		 * here.
Daisy Chang's avatar
Daisy Chang committed
2015
		 */
Jon Grimm's avatar
Jon Grimm committed
2016 2017 2018
		SCTP_DEBUG_PRINTK("Ignoring param: %d for association %p.\n",
				  ntohs(param.p->type), asoc);
		break;
2019
	};
Jon Grimm's avatar
Jon Grimm committed
2020

2021 2022
	return retval;
}
Jon Grimm's avatar
Jon Grimm committed
2023 2024

/* Select a new verification tag.  */
2025
__u32 sctp_generate_tag(const sctp_endpoint_t *ep)
Jon Grimm's avatar
Jon Grimm committed
2026
{
2027
	/* I believe that this random number generator complies with RFC1750.
Jon Grimm's avatar
Jon Grimm committed
2028 2029
	 * A tag of 0 is reserved for special cases (e.g. INIT).
	 */
2030
	__u32 x;
Jon Grimm's avatar
Jon Grimm committed
2031

2032 2033 2034 2035 2036 2037
	do {
		get_random_bytes(&x, sizeof(__u32));
	} while (x == 0);

	return x;
}
Jon Grimm's avatar
Jon Grimm committed
2038 2039

/* Select an initial TSN to send during startup.  */
2040
__u32 sctp_generate_tsn(const sctp_endpoint_t *ep)
Jon Grimm's avatar
Jon Grimm committed
2041
{
2042
	__u32 retval;
Jon Grimm's avatar
Jon Grimm committed
2043

2044 2045 2046
	get_random_bytes(&retval, sizeof(__u32));
	return retval;
}
Jon Grimm's avatar
Jon Grimm committed
2047 2048 2049 2050 2051

/********************************************************************
 * 4th Level Abstractions
 ********************************************************************/

Jon Grimm's avatar
Jon Grimm committed
2052 2053
/* Convert from an SCTP IP parameter to a union sctp_addr.  */
void sctp_param2sockaddr(union sctp_addr *addr, sctp_addr_param_t *param,
2054
			 __u16 port)
Jon Grimm's avatar
Jon Grimm committed
2055
{
2056
	switch(param->v4.param_hdr.type) {
Jon Grimm's avatar
Jon Grimm committed
2057 2058 2059
	case SCTP_PARAM_IPV4_ADDRESS:
		addr->v4.sin_family = AF_INET;
		addr->v4.sin_port = port;
2060
		addr->v4.sin_addr.s_addr = param->v4.addr.s_addr;
Jon Grimm's avatar
Jon Grimm committed
2061
		break;
2062

Jon Grimm's avatar
Jon Grimm committed
2063 2064 2065 2066
	case SCTP_PARAM_IPV6_ADDRESS:
		addr->v6.sin6_family = AF_INET6;
		addr->v6.sin6_port = port;
		addr->v6.sin6_flowinfo = 0; /* BUG */
2067
		addr->v6.sin6_addr = param->v6.addr;
Jon Grimm's avatar
Jon Grimm committed
2068 2069
		addr->v6.sin6_scope_id = 0; /* BUG */
		break;
2070

Jon Grimm's avatar
Jon Grimm committed
2071 2072
	default:
		SCTP_DEBUG_PRINTK("Illegal address type %d\n",
2073
				  ntohs(param->v4.param_hdr.type));
Jon Grimm's avatar
Jon Grimm committed
2074
		break;
2075 2076
	};
}
Jon Grimm's avatar
Jon Grimm committed
2077 2078 2079

/* Convert an IP address in an SCTP param into a sockaddr_in.  */
/* Returns true if a valid conversion was possible.  */
Jon Grimm's avatar
Jon Grimm committed
2080
int sctp_addr2sockaddr(union sctp_params p, union sctp_addr *sa)
Jon Grimm's avatar
Jon Grimm committed
2081
{
2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093
	switch (p.p->type) {
	case SCTP_PARAM_IPV4_ADDRESS:
		sa->v4.sin_addr = *((struct in_addr *)&p.v4->addr);
		sa->v4.sin_family = AF_INET;
		break;

	case SCTP_PARAM_IPV6_ADDRESS:
		*((struct in6_addr *)&sa->v4.sin_addr)
			= p.v6->addr;
		sa->v4.sin_family = AF_INET6;
		break;

Jon Grimm's avatar
Jon Grimm committed
2094 2095
        default:
                return 0;
2096
        };
Jon Grimm's avatar
Jon Grimm committed
2097

2098 2099
	return 1;
}
Jon Grimm's avatar
Jon Grimm committed
2100

2101
/* Convert a sockaddr_in to an IP address in an SCTP param.
2102
 * Returns len if a valid conversion was possible.
2103
 */
Jon Grimm's avatar
Jon Grimm committed
2104
int sockaddr2sctp_addr(const union sctp_addr *sa, sctp_addr_param_t *p)
Jon Grimm's avatar
Jon Grimm committed
2105
{
2106 2107 2108 2109
	int len = 0;

	switch (sa->v4.sin_family) {
	case AF_INET:
2110 2111
		p->v4.param_hdr.type = SCTP_PARAM_IPV4_ADDRESS;
		p->v4.param_hdr.length = ntohs(sizeof(sctp_ipv4addr_param_t));
2112
		len = sizeof(sctp_ipv4addr_param_t);
2113
		p->v4.addr.s_addr = sa->v4.sin_addr.s_addr;
2114 2115 2116
		break;

	case AF_INET6:
2117 2118
		p->v6.param_hdr.type = SCTP_PARAM_IPV6_ADDRESS;
		p->v6.param_hdr.length = ntohs(sizeof(sctp_ipv6addr_param_t));
2119
		len = sizeof(sctp_ipv6addr_param_t);
2120
		p->v6.addr = *(&sa->v6.sin6_addr);
2121 2122 2123
		break;

	default:
Jon Grimm's avatar
Jon Grimm committed
2124 2125
		printk(KERN_WARNING "sockaddr2sctp_addr: Illegal family %d.\n",
		       sa->v4.sin_family);
2126 2127
		return 0;
	};
Jon Grimm's avatar
Jon Grimm committed
2128

2129 2130
	return len;
}