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

📄 sm_make_chunk.c

📁 在linux环境下的流控制传输协议(sctp)的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
/* SCTP kernel 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 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. * * This SCTP 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. * * This SCTP 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 <linux/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>SCTP_STATICstruct sctp_chunk *sctp_make_chunk(const struct sctp_association *asoc,				   __u8 type, __u8 flags, int paylen);static sctp_cookie_param_t *sctp_pack_cookie(const struct sctp_endpoint *ep,					const struct sctp_association *asoc,					const struct sctp_chunk *init_chunk,					int *cookie_len,					const __u8 *raw_addrs, int addrs_len);static int sctp_process_param(struct sctp_association *asoc,			      union sctp_params param,			      const union sctp_addr *peer_addr,			      gfp_t gfp);static void *sctp_addto_param(struct sctp_chunk *chunk, int len,			      const void *data);/* 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(ip_hdr(chunk->skb)->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, __be16 cause_code,		      size_t paylen){	sctp_errhdr_t err;	__u16 len;	/* Cause code constants are now defined in network order.  */	err.cause = cause_code;	len = sizeof(sctp_errhdr_t) + paylen;	err.length  = htons(len);	chunk->subh.err_hdr = sctp_addto_chunk(chunk, sizeof(sctp_errhdr_t), &err);}/* 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,			     gfp_t 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_sock *sp;	sctp_supported_addrs_param_t sat;	__be16 types[2];	sctp_adaptation_ind_param_t aiparam;	sctp_supported_ext_param_t ext_param;	int num_ext = 0;	__u8 extensions[3];	sctp_paramhdr_t *auth_chunks = NULL,			*auth_hmacs = NULL;	/* 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);	/* ADDIP: Section 4.2.7:	 *  An implementation supporting this extension [ADDIP] MUST list	 *  the ASCONF,the ASCONF-ACK, and the AUTH  chunks in its INIT and	 *  INIT-ACK parameters.	 */	if (sctp_addip_enable) {		extensions[num_ext] = SCTP_CID_ASCONF;		extensions[num_ext+1] = SCTP_CID_ASCONF_ACK;		num_ext += 2;	}	chunksize += sizeof(aiparam);	chunksize += vparam_len;	/* Account for AUTH related parameters */	if (sctp_auth_enable) {		/* Add random parameter length*/		chunksize += sizeof(asoc->c.auth_random);		/* Add HMACS parameter length if any were defined */		auth_hmacs = (sctp_paramhdr_t *)asoc->c.auth_hmacs;		if (auth_hmacs->length)			chunksize += ntohs(auth_hmacs->length);		else			auth_hmacs = NULL;		/* Add CHUNKS parameter length */		auth_chunks = (sctp_paramhdr_t *)asoc->c.auth_chunks;		if (auth_chunks->length)			chunksize += ntohs(auth_chunks->length);		else			auth_chunks = NULL;		extensions[num_ext] = SCTP_CID_AUTH;		num_ext += 1;	}	/* If we have any extensions to report, account for that */	if (num_ext)		chunksize += sizeof(sctp_supported_ext_param_t) + num_ext;	/* 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);	/* Add the supported extensions parameter.  Be nice and add this	 * fist before addiding the parameters for the extensions themselves	 */	if (num_ext) {		ext_param.param_hdr.type = SCTP_PARAM_SUPPORTED_EXT;		ext_param.param_hdr.length =			    htons(sizeof(sctp_supported_ext_param_t) + num_ext);		sctp_addto_chunk(retval, sizeof(sctp_supported_ext_param_t),				&ext_param);		sctp_addto_param(retval, num_ext, extensions);	}	if (sctp_prsctp_enable)		sctp_addto_chunk(retval, sizeof(prsctp_param), &prsctp_param);	aiparam.param_hdr.type = SCTP_PARAM_ADAPTATION_LAYER_IND;	aiparam.param_hdr.length = htons(sizeof(aiparam));	aiparam.adaptation_ind = htonl(sp->adaptation_ind);	sctp_addto_chunk(retval, sizeof(aiparam), &aiparam);	/* Add SCTP-AUTH chunks to the parameter list */	if (sctp_auth_enable) {		sctp_addto_chunk(retval, sizeof(asoc->c.auth_random),				 asoc->c.auth_random);		if (auth_hmacs)			sctp_addto_chunk(retval, ntohs(auth_hmacs->length),					auth_hmacs);		if (auth_chunks)			sctp_addto_chunk(retval, ntohs(auth_chunks->length),					auth_chunks);	}nodata:	kfree(addrs.v);	return retval;}struct sctp_chunk *sctp_make_init_ack(const struct sctp_association *asoc,				 const struct sctp_chunk *chunk,				 gfp_t 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;	sctp_adaptation_ind_param_t aiparam;	sctp_supported_ext_param_t ext_param;	int num_ext = 0;	__u8 extensions[3];	sctp_paramhdr_t *auth_chunks = NULL,			*auth_hmacs = NULL,			*auth_random = NULL;	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);	if (sctp_prsctp_enable)		chunksize += sizeof(prsctp_param);	if (sctp_addip_enable) {		extensions[num_ext] = SCTP_CID_ASCONF;		extensions[num_ext+1] = SCTP_CID_ASCONF_ACK;		num_ext += 2;	}	chunksize += sizeof(aiparam);	if (asoc->peer.auth_capable) {		auth_random = (sctp_paramhdr_t *)asoc->c.auth_random;		chunksize += ntohs(auth_random->length);		auth_hmacs = (sctp_paramhdr_t *)asoc->c.auth_hmacs;		if (auth_hmacs->length)			chunksize += ntohs(auth_hmacs->length);		else			auth_hmacs = NULL;		auth_chunks = (sctp_paramhdr_t *)asoc->c.auth_chunks;		if (auth_chunks->length)			chunksize += ntohs(auth_chunks->length);		else			auth_chunks = NULL;		extensions[num_ext] = SCTP_CID_AUTH;		num_ext += 1;	}	if (num_ext)		chunksize += sizeof(sctp_supported_ext_param_t) + num_ext;	/* 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 (num_ext) {		ext_param.param_hdr.type = SCTP_PARAM_SUPPORTED_EXT;		ext_param.param_hdr.length =			    htons(sizeof(sctp_supported_ext_param_t) + num_ext);		sctp_addto_chunk(retval, sizeof(sctp_supported_ext_param_t),				 &ext_param);		sctp_addto_param(retval, num_ext, extensions);	}	if (asoc->peer.prsctp_capable)		sctp_addto_chunk(retval, sizeof(prsctp_param), &prsctp_param);	aiparam.param_hdr.type = SCTP_PARAM_ADAPTATION_LAYER_IND;	aiparam.param_hdr.length = htons(sizeof(aiparam));	aiparam.adaptation_ind = htonl(sctp_sk(asoc->base.sk)->adaptation_ind);	sctp_addto_chunk(retval, sizeof(aiparam), &aiparam);	if (asoc->peer.auth_capable) {		sctp_addto_chunk(retval, ntohs(auth_random->length),				 auth_random);		if (auth_hmacs)			sctp_addto_chunk(retval, ntohs(auth_hmacs->length),					auth_hmacs);		if (auth_chunks)

⌨️ 快捷键说明

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