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

📄 sm_make_chunk.c

📁 在linux环境下的流控制传输协议(sctp)的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
			sctp_addto_chunk(retval, ntohs(auth_chunks->length),					auth_chunks);	}	/* 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:	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: * *  RFC 2481 details a specific bit for a sender to send in the header of *  its next outbound TCP segment to indicate to its peer that it has *  reduced its congestion window.  This is termed the CWR bit.  For *  SCTP the same indication is made by including the CWR chunk. *  This chunk contains one data element, i.e. the TSN number that *  was sent in the ECNE chunk.  This element represents the lowest *  TSN number in the datagram that was originally marked with the *  CE bit. * *     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 *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ *    | Chunk Type=13 | Flags=00000000|    Chunk Length = 8           | *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ *    |                      Lowest TSN Number                        | *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * *     Note: The CWR is considered a Control chunk. */struct sctp_chunk *sctp_make_cwr(const struct sctp_association *asoc,			    const __u32 lowest_tsn,			    const struct sctp_chunk *chunk){	struct sctp_chunk *retval;	sctp_cwrhdr_t cwr;	cwr.lowest_tsn = htonl(lowest_tsn);	retval = sctp_make_chunk(asoc, SCTP_CID_ECN_CWR, 0,				 sizeof(sctp_cwrhdr_t));	if (!retval)		goto nodata;	retval->subh.ecn_cwr_hdr =		sctp_addto_chunk(retval, sizeof(cwr), &cwr);	/* 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.	 *	 * [Report a reduced congestion window back to where the ECNE	 * came from.]	 */	if (chunk)		retval->transport = chunk->transport;nodata:	return retval;}/* Make an ECNE chunk.  This is a congestion experienced report.  */struct sctp_chunk *sctp_make_ecne(const struct sctp_association *asoc,			     const __u32 lowest_tsn){	struct sctp_chunk *retval;	sctp_ecnehdr_t ecne;	ecne.lowest_tsn = htonl(lowest_tsn);	retval = sctp_make_chunk(asoc, SCTP_CID_ECN_ECNE, 0,				 sizeof(sctp_ecnehdr_t));	if (!retval)		goto nodata;	retval->subh.ecne_hdr =		sctp_addto_chunk(retval, sizeof(ecne), &ecne);nodata:	return retval;}/* Make a DATA chunk for the given association from the provided * parameters.  However, do not populate the data payload. */struct sctp_chunk *sctp_make_datafrag_empty(struct sctp_association *asoc,				       const struct sctp_sndrcvinfo *sinfo,				       int data_len, __u8 flags, __u16 ssn){	struct sctp_chunk *retval;	struct sctp_datahdr dp;	int chunk_len;	/* We assign the TSN as LATE as possible, not here when	 * creating the chunk.	 */	dp.tsn = 0;	dp.stream = htons(sinfo->sinfo_stream);	dp.ppid   = sinfo->sinfo_ppid;	/* Set the flags for an unordered send.  */	if (sinfo->sinfo_flags & SCTP_UNORDERED) {		flags |= SCTP_DATA_UNORDERED;		dp.ssn = 0;	} else		dp.ssn = htons(ssn);	chunk_len = sizeof(dp) + data_len;	retval = sctp_make_chunk(asoc, SCTP_CID_DATA, flags, chunk_len);	if (!retval)		goto nodata;	retval->subh.data_hdr = sctp_addto_chunk(retval, sizeof(dp), &dp);	memcpy(&retval->sinfo, sinfo, sizeof(struct sctp_sndrcvinfo));nodata:	return retval;}/* Create a selective ackowledgement (SACK) for the given * association.  This reports on which TSN's we've seen to date, * including duplicates and gaps. */struct sctp_chunk *sctp_make_sack(const struct sctp_association *asoc){	struct sctp_chunk *retval;	struct sctp_sackhdr sack;	int len;	__u32 ctsn;	__u16 num_gabs, num_dup_tsns;	struct sctp_tsnmap *map = (struct sctp_tsnmap *)&asoc->peer.tsn_map;	ctsn = sctp_tsnmap_get_ctsn(map);	SCTP_DEBUG_PRINTK("sackCTSNAck sent:  0x%x.\n", ctsn);	/* How much room is needed in the chunk? */	num_gabs = sctp_tsnmap_num_gabs(map);	num_dup_tsns = sctp_tsnmap_num_dups(map);	/* Initialize the SACK header.  */	sack.cum_tsn_ack	    = htonl(ctsn);	sack.a_rwnd 		    = htonl(asoc->a_rwnd);	sack.num_gap_ack_blocks     = htons(num_gabs);	sack.num_dup_tsns           = htons(num_dup_tsns);	len = sizeof(sack)		+ sizeof(struct sctp_gap_ack_block) * num_gabs		+ sizeof(__u32) * num_dup_tsns;	/* Create the chunk.  */	retval = sctp_make_chunk(asoc, SCTP_CID_SACK, 0, len);	if (!retval)		goto nodata;	/* 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.  This rule should also be followed if	 * the endpoint is bundling DATA chunks together with the	 * reply chunk.	 *	 * However, when acknowledging multiple DATA chunks received	 * in packets from different source addresses in a single	 * SACK, the SACK chunk may be transmitted to one of the	 * destination transport addresses from which the DATA or	 * control chunks being acknowledged were received.	 *	 * [BUG:  We do not implement the following paragraph.	 * Perhaps we should remember the last transport we used for a	 * SACK and avoid that (if possible) if we have seen any	 * duplicates. --piggy]	 *	 * When a receiver of a duplicate DATA chunk sends a SACK to a	 * multi- homed endpoint it MAY be beneficial to vary the	 * destination address and not use the source address of the	 * DATA chunk.  The reason being that receiving a duplicate	 * from a multi-homed endpoint might indicate that the return	 * path (as specified in the source address of the DATA chunk)	 * for the SACK is broken.	 *	 * [Send to the address from which we last received a DATA chunk.]	 */	retval->transport = asoc->peer.last_data_from;	retval->subh.sack_hdr =		sctp_addto_chunk(retval, sizeof(sack), &sack);	/* Add the gap ack block information.   */	if (num_gabs)		sctp_addto_chunk(retval, sizeof(__u32) * num_gabs,				 sctp_tsnmap_get_gabs(map));	/* Add the duplicate TSN information.  */	if (num_dup_tsns)		sctp_addto_chunk(retval, sizeof(__u32) * num_dup_tsns,				 sctp_tsnmap_get_dups(map));nodata:	return retval;}/* Make a SHUTDOWN chunk. */struct sctp_chunk *sctp_make_shutdown(const struct sctp_association *asoc,				      const struct sctp_chunk *chunk){	struct sctp_chunk *retval;	sctp_shutdownhdr_t shut;	__u32 ctsn;	ctsn = sctp_tsnmap_get_ctsn(&asoc->peer.tsn_map);	shut.cum_tsn_ack = htonl(ctsn);	retval = sctp_make_chunk(asoc, SCTP_CID_SHUTDOWN, 0,				 sizeof(sctp_shutdownhdr_t));	if (!retval)		goto nodata;	retval->subh.shutdown_hdr =		sctp_addto_chunk(retval, sizeof(shut), &shut);	if (chunk)		retval->transport = chunk->transport;nodata:	return retval;}struct sctp_chunk *sctp_make_shutdown_ack(const struct sctp_association *asoc,				     const struct sctp_chunk *chunk){	struct sctp_chunk *retval;	retval = sctp_make_chunk(asoc, SCTP_CID_SHUTDOWN_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.	 *	 * [ACK back to where the SHUTDOWN came from.]	 */	if (retval && chunk)		retval->transport = chunk->transport;	return retval;}struct sctp_chunk *sctp_make_shutdown_complete(	const struct sctp_association *asoc,	const struct sctp_chunk *chunk){	struct sctp_chunk *retval;	__u8 flags = 0;	/* Set the T-bit if we have no association (vtag will be	 * reflected)	 */	flags |= asoc ? 0 : SCTP_CHUNK_FLAG_T;	retval = sctp_make_chunk(asoc, SCTP_CID_SHUTDOWN_COMPLETE, flags, 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.	 *	 * [Report SHUTDOWN COMPLETE back to where the SHUTDOWN ACK	 * came from.]	 */	if (retval && chunk)		retval->transport = chunk->transport;	return retval;}/* Create an ABORT.  Note that we set the T bit if we have no * association, except when responding to an INIT (sctpimpguide 2.41). */struct sctp_chunk *sctp_make_abort(const struct sctp_association *asoc,			      const struct sctp_chunk *chunk,			      const size_t hint){	struct sctp_chunk *retval;	__u8 flags = 0;	/* Set the T-bit if we have no association and 'chunk' is not	 * an INIT (vtag will be reflected).	 */	if (!asoc) {		if (chunk && chunk->chunk_hdr &&		    chunk->chunk_hdr->type == SCTP_CID_INIT)			flags = 0;		else			flags = SCTP_CHUNK_FLAG_T;	}	retval = sctp_make_chunk(asoc, SCTP_CID_ABORT, flags, hint);	/* 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.	 *	 * [ABORT back to where the offender came from.]	 */	if (retval && chunk)		retval->transport = chunk->transport;	return retval;}/* Helper to create ABORT with a NO_USER_DATA error.  */

⌨️ 快捷键说明

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