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

📄 sm_make_chunk.c

📁 一种在UDP协议中实现了拥赛控制和重传机制的协议
💻 C
📖 第 1 页 / 共 5 页
字号:
	/* Save adaption indication in the cookie. */	cookie->c.adaption_ind = asoc->peer.adaption_ind;	/* Set an expiration time for the cookie.  */	do_gettimeofday(&cookie->c.expiration);	TIMEVAL_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));	/* Copy the raw local address list of the association. */	memcpy((__u8 *)&cookie->c.peer_init[0] +	       ntohs(init_chunk->chunk_hdr->length), raw_addrs, addrs_len);  	if (sctp_sk(ep->base.sk)->hmac) {		/* Sign the message.  */		sg.page = virt_to_page(&cookie->c);		sg.offset = (unsigned long)(&cookie->c) % PAGE_SIZE;		sg.length = bodysize;		keylen = SCTP_SECRET_SIZE;		key = (char *)ep->secret_key[ep->current_key];		sctp_crypto_hmac(sctp_sk(ep->base.sk)->hmac, key, &keylen,				 &sg, 1, cookie->signature);	}nodata:	return retval;}/* Unpack the cookie from COOKIE ECHO chunk, recreating the association.  */struct sctp_association *sctp_unpack_cookie(	const struct sctp_endpoint *ep,	const struct sctp_association *asoc,	struct sctp_chunk *chunk, int gfp,	int *error, struct sctp_chunk **errp){	struct sctp_association *retval = NULL;	struct sctp_signed_cookie *cookie;	struct sctp_cookie *bear_cookie;	int headersize, bodysize, fixed_size;	__u8 digest[SCTP_SIGNATURE_SIZE];	struct scatterlist sg;	unsigned int keylen, len;	char *key;	sctp_scope_t scope;	struct sk_buff *skb = chunk->skb;	headersize = sizeof(sctp_chunkhdr_t) + SCTP_SECRET_SIZE;	bodysize = ntohs(chunk->chunk_hdr->length) - headersize;	fixed_size = headersize + sizeof(struct sctp_cookie);	/* Verify that the chunk looks like it even has a cookie.	 * There must be enough room for our cookie and our peer's	 * INIT chunk.	 */	len = ntohs(chunk->chunk_hdr->length);	if (len < fixed_size + sizeof(struct sctp_chunkhdr))		goto malformed;	/* Verify that the cookie has been padded out. */	if (bodysize % SCTP_COOKIE_MULTIPLE)		goto malformed;	/* Process the cookie.  */	cookie = chunk->subh.cookie_hdr;	bear_cookie = &cookie->c;	if (!sctp_sk(ep->base.sk)->hmac)		goto no_hmac;	/* Check the signature.  */	keylen = SCTP_SECRET_SIZE;	sg.page = virt_to_page(bear_cookie);	sg.offset = (unsigned long)(bear_cookie) % PAGE_SIZE;	sg.length = bodysize;	key = (char *)ep->secret_key[ep->current_key];	memset(digest, 0x00, sizeof(digest));	sctp_crypto_hmac(sctp_sk(ep->base.sk)->hmac, key, &keylen, &sg,			 1, digest);	if (memcmp(digest, cookie->signature, SCTP_SIGNATURE_SIZE)) {		/* Try the previous key. */		key = (char *)ep->secret_key[ep->last_key];		memset(digest, 0x00, sizeof(digest));		sctp_crypto_hmac(sctp_sk(ep->base.sk)->hmac, key, &keylen,				 &sg, 1, digest);		if (memcmp(digest, cookie->signature, SCTP_SIGNATURE_SIZE)) {			/* Yikes!  Still bad signature! */			*error = -SCTP_IERROR_BAD_SIG;			goto fail;		}	}no_hmac:	/* IG Section 2.35.2:	 *  3) Compare the port numbers and the verification tag contained	 *     within the COOKIE ECHO chunk to the actual port numbers and the	 *     verification tag within the SCTP common header of the received	 *     packet. If these values do not match the packet MUST be silently	 *     discarded,	 */	if (ntohl(chunk->sctp_hdr->vtag) != bear_cookie->my_vtag) {		*error = -SCTP_IERROR_BAD_TAG;		goto fail;	}	if (ntohs(chunk->sctp_hdr->source) != bear_cookie->peer_addr.v4.sin_port ||	    ntohs(chunk->sctp_hdr->dest) != bear_cookie->my_port) {		*error = -SCTP_IERROR_BAD_PORTS;		goto fail;	}	/* 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.	 */	if (!asoc && tv_lt(bear_cookie->expiration, skb->stamp)) {		__u16 len;		/*		 * 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.		 */		len = ntohs(chunk->chunk_hdr->length);		*errp = sctp_make_op_error_space(asoc, chunk, len);		if (*errp) {			suseconds_t usecs = (skb->stamp.tv_sec -				bear_cookie->expiration.tv_sec) * 1000000L +				skb->stamp.tv_usec -				bear_cookie->expiration.tv_usec;			usecs = htonl(usecs);			sctp_init_cause(*errp, SCTP_ERROR_STALE_COOKIE,					&usecs, sizeof(usecs));			*error = -SCTP_IERROR_STALE_COOKIE;		} else			*error = -SCTP_IERROR_NOMEM;		goto fail;	}	/* Make a new base association.  */	scope = sctp_scope(sctp_source(chunk));	retval = sctp_association_new(ep, ep->base.sk, scope, gfp);	if (!retval) {		*error = -SCTP_IERROR_NOMEM;		goto fail;	}	/* Set up our peer's port number.  */	retval->peer.port = ntohs(chunk->sctp_hdr->source);	/* Populate the association from the cookie.  */	memcpy(&retval->c, bear_cookie, sizeof(*bear_cookie));	if (sctp_assoc_set_bind_addr_from_cookie(retval, bear_cookie,						 GFP_ATOMIC) < 0) {		*error = -SCTP_IERROR_NOMEM;		goto fail;	}	/* Also, add the destination address. */	if (list_empty(&retval->base.bind_addr.address_list)) {		sctp_add_bind_addr(&retval->base.bind_addr, &chunk->dest,				   GFP_ATOMIC);	}	retval->next_tsn = retval->c.initial_tsn;	retval->ctsn_ack_point = retval->next_tsn - 1;	retval->addip_serial = retval->c.initial_tsn;	retval->adv_peer_ack_point = retval->ctsn_ack_point;	retval->peer.prsctp_capable = retval->c.prsctp_capable;	retval->peer.adaption_ind = retval->c.adaption_ind;	/* The INIT stuff will be done by the side effects.  */	return retval;fail:	if (retval)		sctp_association_free(retval);	return NULL;malformed:	/* Yikes!  The packet is either corrupt or deliberately	 * malformed.	 */	*error = -SCTP_IERROR_MALFORMED;	goto fail;}/******************************************************************** * 3rd Level Abstractions ********************************************************************/struct __sctp_missing {	__u32 num_missing;	__u16 type;}  __attribute__((packed));/* * Report a missing mandatory parameter. */static int sctp_process_missing_param(const struct sctp_association *asoc,				      sctp_param_t paramtype,				      struct sctp_chunk *chunk,				      struct sctp_chunk **errp){	struct __sctp_missing report;	__u16 len;	len = WORD_ROUND(sizeof(report));	/* Make an ERROR chunk, preparing enough room for	 * returning multiple unknown parameters.	 */	if (!*errp)		*errp = sctp_make_op_error_space(asoc, chunk, len);	if (*errp) {		report.num_missing = htonl(1);		report.type = paramtype;		sctp_init_cause(*errp, 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 struct sctp_association *asoc,				      struct sctp_chunk *chunk,				      struct sctp_chunk **errp){	/* Invalid Mandatory Parameter Error has no payload. */	if (!*errp)		*errp = sctp_make_op_error_space(asoc, chunk, 0);	if (*errp)		sctp_init_cause(*errp, SCTP_ERROR_INV_PARAM, NULL, 0);	/* Stop processing this chunk. */	return 0;}static int sctp_process_inv_paramlength(const struct sctp_association *asoc,					struct sctp_paramhdr *param,					const struct sctp_chunk *chunk,					struct sctp_chunk **errp){	char		error[] = "The following parameter had invalid length:";	size_t		payload_len = WORD_ROUND(sizeof(error)) + 						sizeof(sctp_paramhdr_t);	/* Create an error chunk and fill it in with our payload. */	if (!*errp)		*errp = sctp_make_op_error_space(asoc, chunk, payload_len);	if (*errp) {		sctp_init_cause(*errp, SCTP_ERROR_PROTO_VIOLATION, error,				sizeof(error));		sctp_addto_chunk(*errp, sizeof(sctp_paramhdr_t), param);	}	return 0;}/* Do not attempt to handle the HOST_NAME parm.  However, do * send back an indicator to the peer. */static int sctp_process_hn_param(const struct sctp_association *asoc,				 union sctp_params param,				 struct sctp_chunk *chunk,				 struct sctp_chunk **errp){	__u16 len = ntohs(param.p->length);	/* Make an ERROR chunk. */	if (!*errp)		*errp = sctp_make_op_error_space(asoc, chunk, len);	if (*errp)		sctp_init_cause(*errp, SCTP_ERROR_DNS_FAILED,				param.v, len);	/* Stop processing this chunk. */	return 0;}/* RFC 3.2.1 & the Implementers Guide 2.2. * * 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 * Parameter Type. * * 00 - Stop processing this SCTP chunk and discard it, *	do not process any further chunks within it. * * 01 - Stop processing this SCTP chunk and discard it, *	do not process any further chunks within it, and report *	the unrecognized parameter in an 'Unrecognized *	Parameter Type' (in either an ERROR or in the INIT ACK). * * 10 - Skip this parameter and continue processing. * * 11 - Skip this parameter and continue processing but *	report the unrecognized parameter in an *	'Unrecognized Parameter Type' (in either an ERROR or in *	the INIT ACK). * * Return value: * 	0 - discard the chunk * 	1 - continue with the chunk */static int sctp_process_unk_param(const struct sctp_association *asoc,				  union sctp_params param,				  struct sctp_chunk *chunk,				  struct sctp_chunk **errp){	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 == *errp)			*errp = sctp_make_op_error_space(asoc, chunk,					ntohs(chunk->chunk_hdr->length));		if (*errp)			sctp_init_cause(*errp, SCTP_ERROR_UNKNOWN_PARAM,					param.v,					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 == *errp)			*errp = sctp_make_op_error_space(asoc, chunk,					ntohs(chunk->chunk_hdr->length));		if (*errp) {			sctp_init_cause(*errp, SCTP_ERROR_UNKNOWN_PARAM,					param.v,					WORD_ROUND(ntohs(param.p->length)));		} else {			/* If there is no memory for generating the ERROR			 * report as specified, an ABORT will be triggered			 * to the peer and the association won't be			 * established.			 */			retval = 0;		}		break;	default:		break;	}	return retval;}/* Find unrecognized parameters in the chunk. * Return values: * 	0 - discard the chunk * 	1 - continue with the chunk */static int sctp_verify_param(const struct sctp_association *asoc,			     union sctp_params param,			     sctp_cid_t cid,			     struct sctp_chunk *chunk,			     struct sctp_chunk **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:	case SCTP_PARAM_ADAPTION_LAYER_IND:		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);	case SCTP_PARAM_FWD_TSN_SUPPORT:		if (sctp_prsctp_enable)			break;		/* Fall Through */ 	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 struct sctp_association *asoc,		     sctp_cid_t cid,		     sctp_init_chunk_t *peer_init,		     struct sctp_chunk *chunk,		     struct sctp_chunk **errp){

⌨️ 快捷键说明

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