⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sm_make_chunk.c

📁 Linux Kernel 2.6.9 for OMAP1710
💻 C
📖 第 1 页 / 共 5 页
字号:
/* SCTP kernel reference Implementation * (C) Copyright IBM Corp. 2001, 2004 * Copyright (c) 1999-2000 Cisco, Inc. * Copyright (c) 1999-2001 Motorola, Inc. * Copyright (c) 2001-2002 Intel Corp. * * This file is part of the SCTP kernel reference Implementation * * 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. * * The SCTP reference implementation is free software; * you can redistribute it and/or modify it under the terms of * the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * The SCTP reference implementation is distributed in the hope that it * will be useful, but WITHOUT ANY WARRANTY; without even the implied *                 ************************ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with GNU CC; see the file COPYING.  If not, write to * the Free Software Foundation, 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. * * Please send any bug reports or fixes you make to the * email address(es): *    lksctp developers <lksctp-developers@lists.sourceforge.net> * * Or submit a bug report through the following website: *    http://www.sf.net/projects/lksctp * * Written or modified by: *    La Monte H.P. Yarroll <piggy@acm.org> *    Karl Knutson          <karl@athena.chicago.il.us> *    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> *    Ardelle Fan	    <ardelle.fan@intel.com> *    Kevin Gao             <kevin.gao@intel.com> * * Any bugs reported given to us we will try to fix... any fixes shared will * be incorporated into the next SCTP release. */#include <linux/types.h>#include <linux/kernel.h>#include <linux/ip.h>#include <linux/ipv6.h>#include <linux/net.h>#include <linux/inet.h>#include <asm/scatterlist.h>#include <linux/crypto.h>#include <net/sock.h>#include <linux/skbuff.h>#include <linux/random.h>	/* for get_random_bytes */#include <net/sctp/sctp.h>#include <net/sctp/sm.h>extern kmem_cache_t *sctp_chunk_cachep;/* What was the inbound interface for this chunk? */int sctp_chunk_iif(const struct sctp_chunk *chunk){	struct sctp_af *af;	int iif = 0;	af = sctp_get_af_specific(ipver2af(chunk->skb->nh.iph->version));	if (af)		iif = af->skb_iif(chunk->skb);	return iif;}/* RFC 2960 3.3.2 Initiation (INIT) (1) * * Note 2: The ECN capable field is reserved for future use of * Explicit Congestion Notification. */static const struct sctp_paramhdr ecap_param = {	SCTP_PARAM_ECN_CAPABLE,	__constant_htons(sizeof(struct sctp_paramhdr)),};static const struct sctp_paramhdr prsctp_param = {	SCTP_PARAM_FWD_TSN_SUPPORT,	__constant_htons(sizeof(struct sctp_paramhdr)),};/* A helper to initialize to initialize an op error inside a * provided chunk, as most cause codes will be embedded inside an * abort chunk. */void  sctp_init_cause(struct sctp_chunk *chunk, __u16 cause_code,		      const void *payload, size_t paylen){	sctp_errhdr_t err;	int padlen;	__u16 len;        /* Cause code constants are now defined in network order.  */	err.cause = cause_code;	len = sizeof(sctp_errhdr_t) + paylen;	padlen = len % 4;	err.length  = htons(len);	len += padlen;	sctp_addto_chunk(chunk, sizeof(sctp_errhdr_t), &err);	chunk->subh.err_hdr = sctp_addto_chunk(chunk, paylen, payload);}/* 3.3.2 Initiation (INIT) (1) * * This chunk is used to initiate a SCTP association between two * endpoints. The format of the INIT chunk is shown below: * *     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              / *    \                                                               \ *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * * * The INIT chunk contains the following parameters. Unless otherwise * noted, each parameter MUST only be included once in the INIT chunk. * * Fixed Parameters                     Status * ---------------------------------------------- * Initiate Tag                        Mandatory * Advertised Receiver Window Credit   Mandatory * Number of Outbound Streams          Mandatory * Number of Inbound Streams           Mandatory * Initial TSN                         Mandatory * * 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 */struct sctp_chunk *sctp_make_init(const struct sctp_association *asoc,			     const struct sctp_bind_addr *bp,			     int gfp, int vparam_len){	sctp_inithdr_t init;	union sctp_params addrs;	size_t chunksize;	struct sctp_chunk *retval = NULL;	int num_types, addrs_len = 0;	struct sctp_opt *sp;	sctp_supported_addrs_param_t sat;	__u16 types[2];	/* RFC 2960 3.3.2 Initiation (INIT) (1)	 *	 * Note 1: The INIT chunks can contain multiple addresses that	 * can be IPv4 and/or IPv6 in any combination.	 */	retval = NULL;	/* Convert the provided bind address list to raw format. */	addrs = sctp_bind_addrs_to_raw(bp, &addrs_len, gfp);	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);	/* 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);	chunksize += sizeof(ecap_param);	if (sctp_prsctp_enable)		chunksize += sizeof(prsctp_param);	chunksize += vparam_len;	/* RFC 2960 3.3.2 Initiation (INIT) (1)	 *	 * Note 3: An INIT chunk MUST NOT contain more than one Host	 * 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.	 *	 * PLEASE DO NOT FIXME [This version does not support Host Name.]	 */	retval = sctp_make_chunk(asoc, SCTP_CID_INIT, 0, chunksize);	if (!retval)		goto nodata;	retval->subh.init_hdr =		sctp_addto_chunk(retval, sizeof(init), &init);	retval->param_hdr.v =		sctp_addto_chunk(retval, addrs_len, addrs.v);	/* 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);	sctp_addto_chunk(retval, sizeof(ecap_param), &ecap_param);	if (sctp_prsctp_enable)		sctp_addto_chunk(retval, sizeof(prsctp_param), &prsctp_param);nodata:	if (addrs.v)		kfree(addrs.v);	return retval;}struct sctp_chunk *sctp_make_init_ack(const struct sctp_association *asoc,				 const struct sctp_chunk *chunk,				 int gfp, int unkparam_len){	sctp_inithdr_t initack;	struct sctp_chunk *retval;	union sctp_params addrs;	int addrs_len;	sctp_cookie_param_t *cookie;	int cookie_len;	size_t chunksize;	retval = NULL;	/* Note: there may be no addresses to embed. */	addrs = sctp_bind_addrs_to_raw(&asoc->base.bind_addr, &addrs_len, gfp);	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);	/* FIXME:  We really ought to build the cookie right	 * into the packet instead of allocating more fresh memory.	 */	cookie = sctp_pack_cookie(asoc->ep, asoc, chunk, &cookie_len,				  addrs.v, addrs_len);	if (!cookie)		goto nomem_cookie;	/* 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;        /* Tell peer that we'll do ECN only if peer advertised such cap.  */	if (asoc->peer.ecn_capable)		chunksize += sizeof(ecap_param);        /* Tell peer that we'll do PR-SCTP only if peer advertised.  */	if (asoc->peer.prsctp_capable)		chunksize += sizeof(prsctp_param);	/* Now allocate and fill out the chunk.  */	retval = sctp_make_chunk(asoc, SCTP_CID_INIT_ACK, 0, chunksize);	if (!retval)		goto nomem_chunk;	/* Per the advice in RFC 2960 6.4, send this reply to	 * the source of the INIT packet.	 */	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)		sctp_addto_chunk(retval, sizeof(ecap_param), &ecap_param);	if (asoc->peer.prsctp_capable)		sctp_addto_chunk(retval, sizeof(prsctp_param), &prsctp_param);	/* We need to remove the const qualifier at this point.  */	retval->asoc = (struct sctp_association *) asoc;	/* RFC 2960 6.4 Multi-homed SCTP Endpoints	 *	 * 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.]	 */	if (chunk)		retval->transport = chunk->transport;nomem_chunk:	kfree(cookie);nomem_cookie:	if (addrs.v)		kfree(addrs.v);	return retval;}/* 3.3.11 Cookie Echo (COOKIE ECHO) (10): * * 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 * the initialization process. This chunk MUST precede any DATA chunk * sent within the association, but MAY be bundled with one or more DATA * chunks in the same packet. * *      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                                    / *     \                                                               \ *     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * * Chunk Flags: 8 bit * *   Set to zero on transmit and ignored on receipt. * * Length: 16 bits (unsigned integer) * *   Set to the size of the chunk in bytes, including the 4 bytes of *   the chunk header and the size of the Cookie. * * Cookie: variable size * *   This field must contain the exact cookie received in the *   State Cookie parameter from the previous INIT ACK. * *   An implementation SHOULD make the cookie as small as possible *   to insure interoperability. */struct sctp_chunk *sctp_make_cookie_echo(const struct sctp_association *asoc,				    const struct sctp_chunk *chunk){	struct sctp_chunk *retval;	void *cookie;	int cookie_len;	cookie = asoc->peer.cookie;	cookie_len = asoc->peer.cookie_len;	/* 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);	/* RFC 2960 6.4 Multi-homed SCTP Endpoints	 *	 * 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.]	 */	if (chunk)		retval->transport = chunk->transport;nodata:	return retval;}/* 3.3.12 Cookie Acknowledgement (COOKIE ACK) (11): * * This chunk is used only during the initialization of an * association.  It is used to acknowledge the receipt of a COOKIE * 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. * *      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                | *     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * * Chunk Flags: 8 bits * *   Set to zero on transmit and ignored on receipt. */struct sctp_chunk *sctp_make_cookie_ack(const struct sctp_association *asoc,				   const struct sctp_chunk *chunk){	struct sctp_chunk *retval;	retval = sctp_make_chunk(asoc, SCTP_CID_COOKIE_ACK, 0, 0);	/* RFC 2960 6.4 Multi-homed SCTP Endpoints	 *	 * 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.]	 */	if (retval && chunk)		retval->transport = chunk->transport;	return retval;}/* *  Appendix A: Explicit Congestion Notification: *  CWR: *

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -