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

📄 sm_make_chunk.c

📁 Linux Kernel 2.6.9 for OMAP1710
💻 C
📖 第 1 页 / 共 5 页
字号:
		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:	/* 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;	/* 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;}/* 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:		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){	union sctp_params param;	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, errp);		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) */	/* The only missing mandatory param possible today is	 * the state cookie for an INIT-ACK chunk.	 */	if ((SCTP_CID_INIT_ACK == cid) && !has_cookie) {		sctp_process_missing_param(asoc, SCTP_PARAM_STATE_COOKIE,					   chunk, errp);		return 0;	}	/* Find unrecognized parameters. */	sctp_walk_params(param, peer_init, init_hdr.params) {		if (!sctp_verify_param(asoc, param, cid, chunk, errp)) {			if (SCTP_PARAM_HOST_NAME_ADDRESS == param.p->type)				return 0;			else				return 1;		}	} /* for (loop through all parameters) */	return 1;}/* Unpack the parameters in an INIT packet into an association. * Returns 0 on failure, else success. * FIXME:  This is an association method. */int sctp_process_init(struct sctp_association *asoc, sctp_cid_t cid,		      const union sctp_addr *peer_addr,		      sctp_init_chunk_t *peer_init, int gfp){	union sctp_params param;	struct sctp_transport *transport;	struct list_head *pos, *temp;	char *cookie;	/* We must include the address that the INIT packet came from.	 * 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.	 */

⌨️ 快捷键说明

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