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

📄 sm_make_chunk.c

📁 在linux环境下的流控制传输协议(sctp)的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	char		error[] = "The following parameter had invalid length:";	size_t		payload_len = WORD_ROUND(sizeof(error)) +						sizeof(sctp_paramhdr_t);	/* This is a fatal error.  Any accumulated non-fatal errors are	 * not reported.	 */	if (*errp)		sctp_chunk_free(*errp);	/* Create an error chunk and fill it in with our payload. */	*errp = sctp_make_op_error_space(asoc, chunk, payload_len);	if (*errp) {		sctp_init_cause(*errp, SCTP_ERROR_PROTO_VIOLATION,				sizeof(error) + sizeof(sctp_paramhdr_t));		sctp_addto_chunk(*errp, sizeof(error), error);		sctp_addto_param(*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);	/* Processing of the HOST_NAME parameter will generate an	 * ABORT.  If we've accumulated any non-fatal errors, they	 * would be unrecognized parameters and we should not include	 * them in the ABORT.	 */	if (*errp)		sctp_chunk_free(*errp);	*errp = sctp_make_op_error_space(asoc, chunk, len);	if (*errp) {		sctp_init_cause(*errp, SCTP_ERROR_DNS_FAILED, len);		sctp_addto_chunk(*errp, len, param.v);	}	/* Stop processing this chunk. */	return 0;}static int sctp_verify_ext_param(union sctp_params param){	__u16 num_ext = ntohs(param.p->length) - sizeof(sctp_paramhdr_t);	int have_auth = 0;	int have_asconf = 0;	int i;	for (i = 0; i < num_ext; i++) {		switch (param.ext->chunks[i]) {		    case SCTP_CID_AUTH:			    have_auth = 1;			    break;		    case SCTP_CID_ASCONF:		    case SCTP_CID_ASCONF_ACK:			    have_asconf = 1;			    break;		}	}	/* ADD-IP Security: The draft requires us to ABORT or ignore the	 * INIT/INIT-ACK if ADD-IP is listed, but AUTH is not.  Do this	 * only if ADD-IP is turned on and we are not backward-compatible	 * mode.	 */	if (sctp_addip_noauth)		return 1;	if (sctp_addip_enable && !have_auth && have_asconf)		return 0;	return 1;}static void sctp_process_ext_param(struct sctp_association *asoc,				    union sctp_params param){	__u16 num_ext = ntohs(param.p->length) - sizeof(sctp_paramhdr_t);	int i;	for (i = 0; i < num_ext; i++) {		switch (param.ext->chunks[i]) {		    case SCTP_CID_FWD_TSN:			    if (sctp_prsctp_enable &&				!asoc->peer.prsctp_capable)				    asoc->peer.prsctp_capable = 1;			    break;		    case SCTP_CID_AUTH:			    /* if the peer reports AUTH, assume that he			     * supports AUTH.			     */			    asoc->peer.auth_capable = 1;			    break;		    case SCTP_CID_ASCONF:		    case SCTP_CID_ASCONF_ACK:			    asoc->peer.asconf_capable = 1;			    break;		    default:			    break;		}	}}/* 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 parameter; do not process any further * 	parameters within this chunk * * 01 - Stop processing this parameter, do not process any further *	parameters within this chunk, and report the unrecognized *	parameter in an 'Unrecognized Parameter' ERROR chunk. * * 10 - Skip this parameter and continue processing. * * 11 - Skip this parameter and continue processing but *	report the unrecognized parameter in an *	'Unrecognized Parameter' ERROR chunk. * * Return value: * 	SCTP_IERROR_NO_ERROR - continue with the chunk * 	SCTP_IERROR_ERROR    - stop and report an error. * 	SCTP_IERROR_NOMEME   - out of memory. */static sctp_ierror_t sctp_process_unk_param(const struct sctp_association *asoc,					    union sctp_params param,					    struct sctp_chunk *chunk,					    struct sctp_chunk **errp){	int retval = SCTP_IERROR_NO_ERROR;	switch (param.p->type & SCTP_PARAM_ACTION_MASK) {	case SCTP_PARAM_ACTION_DISCARD:		retval =  SCTP_IERROR_ERROR;		break;	case SCTP_PARAM_ACTION_SKIP:		break;	case SCTP_PARAM_ACTION_DISCARD_ERR:		retval =  SCTP_IERROR_ERROR;		/* Fall through */	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,					WORD_ROUND(ntohs(param.p->length)));			sctp_addto_chunk(*errp,					WORD_ROUND(ntohs(param.p->length)),					param.v);		} 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 = SCTP_IERROR_NOMEM;		}		break;	default:		break;	}	return retval;}/* Verify variable length parameters * Return values: * 	SCTP_IERROR_ABORT - trigger an ABORT * 	SCTP_IERROR_NOMEM - out of memory (abort) *	SCTP_IERROR_ERROR - stop processing, trigger an ERROR * 	SCTP_IERROR_NO_ERROR - continue with the chunk */static sctp_ierror_t 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){	struct sctp_hmac_algo_param *hmacs;	int retval = SCTP_IERROR_NO_ERROR;	__u16 n_elt, id = 0;	int i;	/* 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_ADAPTATION_LAYER_IND:		break;	case SCTP_PARAM_SUPPORTED_EXT:		if (!sctp_verify_ext_param(param))			return SCTP_IERROR_ABORT;		break;	case SCTP_PARAM_SET_PRIMARY:		if (sctp_addip_enable)			break;		goto fallthrough;	case SCTP_PARAM_HOST_NAME_ADDRESS:		/* Tell the peer, we won't support this param.  */		sctp_process_hn_param(asoc, param, chunk, err_chunk);		retval = SCTP_IERROR_ABORT;		break;	case SCTP_PARAM_FWD_TSN_SUPPORT:		if (sctp_prsctp_enable)			break;		goto fallthrough;	case SCTP_PARAM_RANDOM:		if (!sctp_auth_enable)			goto fallthrough;		/* SCTP-AUTH: Secion 6.1		 * If the random number is not 32 byte long the association		 * MUST be aborted.  The ABORT chunk SHOULD contain the error		 * cause 'Protocol Violation'.		 */		if (SCTP_AUTH_RANDOM_LENGTH !=			ntohs(param.p->length) - sizeof(sctp_paramhdr_t)) {			sctp_process_inv_paramlength(asoc, param.p,							chunk, err_chunk);			retval = SCTP_IERROR_ABORT;		}		break;	case SCTP_PARAM_CHUNKS:		if (!sctp_auth_enable)			goto fallthrough;		/* SCTP-AUTH: Section 3.2		 * The CHUNKS parameter MUST be included once in the INIT or		 *  INIT-ACK chunk if the sender wants to receive authenticated		 *  chunks.  Its maximum length is 260 bytes.		 */		if (260 < ntohs(param.p->length)) {			sctp_process_inv_paramlength(asoc, param.p,						     chunk, err_chunk);			retval = SCTP_IERROR_ABORT;		}		break;	case SCTP_PARAM_HMAC_ALGO:		if (!sctp_auth_enable)			goto fallthrough;		hmacs = (struct sctp_hmac_algo_param *)param.p;		n_elt = (ntohs(param.p->length) - sizeof(sctp_paramhdr_t)) >> 1;		/* SCTP-AUTH: Section 6.1		 * The HMAC algorithm based on SHA-1 MUST be supported and		 * included in the HMAC-ALGO parameter.		 */		for (i = 0; i < n_elt; i++) {			id = ntohs(hmacs->hmac_ids[i]);			if (id == SCTP_AUTH_HMAC_ID_SHA1)				break;		}		if (id != SCTP_AUTH_HMAC_ID_SHA1) {			sctp_process_inv_paramlength(asoc, param.p, chunk,						     err_chunk);			retval = SCTP_IERROR_ABORT;		}		break;fallthrough:	default:		SCTP_DEBUG_PRINTK("Unrecognized param: %d for chunk %d.\n",				ntohs(param.p->type), cid);		retval = 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;	int result;	/* Verify stream values are non-zero. */	if ((0 == peer_init->init_hdr.num_outbound_streams) ||	    (0 == peer_init->init_hdr.num_inbound_streams) ||	    (0 == peer_init->init_hdr.init_tag) ||	    (SCTP_DEFAULT_MINWINDOW > ntohl(peer_init->init_hdr.a_rwnd))) {		return sctp_process_inv_mandatory(asoc, chunk, errp);	}	/* 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) */	/* There is a possibility that a parameter length was bad and	 * in that case we would have stoped walking the parameters.	 * The current param.p would point at the bad one.	 * Current consensus on the mailing list is to generate a PROTOCOL	 * VIOLATION error.  We build the ERROR chunk here and let the normal	 * error handling code build and send the packet.	 */	if (param.v != (void*)chunk->chunk_end)		return sctp_process_inv_paramlength(asoc, param.p, chunk, errp);	/* The only missing mandatory param possible today is	 * the state cookie for an INIT-ACK chunk.	 */	if ((SCTP_CID_INIT_ACK == cid) && !has_cookie)		return sctp_process_missing_param(asoc, SCTP_PARAM_STATE_COOKIE,						  chunk, errp);	/* Verify all the variable length parameters */	sctp_walk_params(param, peer_init, init_hdr.params) {		result = sctp_verify_param(asoc, param, cid, chunk, errp);		switch (result) {		    case SCTP_IERROR_ABORT:		    case SCTP_IERROR_NOMEM:				return 0;		    case SCTP_IERROR_ERROR:				return 1;		    case SCTP_IERROR_NO_ERROR:		    default:				break;		}	} /* 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, gfp_t 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.	 */	/* 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.	 */	if (peer_addr) {		if(!sctp_assoc_add_peer(asoc, peer_addr, gfp, SCTP_ACTIVE))			goto nomem;	}	/* Process the initialization parameters.  */	sctp_walk_params(param, peer_init, init_hdr.params) {		if (!sctp_process_param(asoc, param, peer_addr, gfp))			goto clean_up;	}	/* AUTH: After processing the parameters, make sure that we	 * have all the required info to potentially do authentications.	 */	if (asoc->peer.auth_capable && (!asoc->peer.peer_random ||					!asoc->peer.peer_hmacs))		asoc->peer.auth_capable = 0;	/* In a non-backward compatible mode, if the peer claims	 * support for ADD-IP but not AUTH,  the ADD-IP spec states	 * that we MUST ABORT the association. Section 6.  The section	 * also give us an option to silently ignore the packet, which	 * is what we'll do here.	 */	if (!sctp_addip_noauth &&	     (asoc->peer.asconf_capable && !asoc->peer.auth_capable)) {		asoc->peer.addip_disabled_mask |= (SCTP_PARAM_ADD_IP |						  SCTP_PARAM_DEL_IP |						  SCTP_PARAM_SET_PRIMARY);		asoc->peer.asconf_capable = 0;		goto clean_up;	}	/* Walk list of transports, removing transports in the UNKNOWN state. */	list_for_each_safe(pos, temp, &asoc->peer.transport_addr_list) {		transport = list_entry(pos, struct sctp_transport, transports);		if (transport->state == SCTP_UNKNOWN) {			sctp_assoc_rm_peer(asoc, transport);		}	}	/* The fixed INIT headers are always in network byte	 * order.	 */	asoc->pee

⌨️ 快捷键说明

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