标准定义的ABORT格式如下:
ABORT chunk:
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 = 6 |Reserved |T| Length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
\ \
/ zero or more Error Causes /
\ \
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
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 = 6 |Reserved |T| Length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
\ \
/ zero or more Error Causes /
\ \
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Error Cause:
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
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Cause Code | Cause Length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
/ Cause-Specific Information /
\ \
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
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
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Cause Code | Cause Length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
/ Cause-Specific Information /
\ \
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Cause Code
Value Cause Code
--------- ----------------
1 Invalid Stream Identifier
2 Missing Mandatory Parameter
3 Stale Cookie Error
4 Out of Resource
5 Unresolvable Address
6 Unrecognized Chunk Type
7 Invalid Mandatory Parameter
8 Unrecognized Parameters
9 No User Data
10 Cookie Received While Shutting Down
11 Restart of an Association with New Addresses
12 User Initiated Abort
13 Protocol Violation
Value Cause Code
--------- ----------------
1 Invalid Stream Identifier
2 Missing Mandatory Parameter
3 Stale Cookie Error
4 Out of Resource
5 Unresolvable Address
6 Unrecognized Chunk Type
7 Invalid Mandatory Parameter
8 Unrecognized Parameters
9 No User Data
10 Cookie Received While Shutting Down
11 Restart of an Association with New Addresses
12 User Initiated Abort
13 Protocol Violation
有一点需要注意:SCTP协议在linux的实现中,当ASSOCIATION的连续重传次数超过门限之后,只会将ASSOCIATION在本地关闭(即释放ASSOCIATION的相关内存),而不会向对端发送ABORT(和freeBSD的处理不同)。那何时向对端发送ABORT呢?要等收到对端的SCTP包之后,此时由于找不到对应的ASSOCIATION,会作为收到“Out of the Blue”的SCTP包而回ABORT。以下列出linux内核中触发abort的地方:
*************************1**************************************************
sctp_make_abort_no_data(asoc, chunk, tsn);
sctp_make_abort(asoc, chunk, sizeof(sctp_errhdr_t) + sizeof(tsn))
payload = htonl(tsn);
sctp_init_cause(retval, SCTP_ERROR_NO_DATA, sizeof(payload));
err.cause = cause_code;
len = sizeof(sctp_errhdr_t) + paylen;
err.length = htons(len);
sctp_addto_chunk(retval, sizeof(payload), (const void *)&payload);
sctp_make_abort(asoc, chunk, sizeof(sctp_errhdr_t) + sizeof(tsn))
payload = htonl(tsn);
sctp_init_cause(retval, SCTP_ERROR_NO_DATA, sizeof(payload));
err.cause = cause_code;
len = sizeof(sctp_errhdr_t) + paylen;
err.length = htons(len);
sctp_addto_chunk(retval, sizeof(payload), (const void *)&payload);
sctp_close(struct sock *sk, long timeout)
sctp_make_abort_user(asoc, NULL, 0);
sctp_make_abort(asoc, NULL, sizeof(sctp_errhdr_t) + paylen);
sctp_init_cause(retval, SCTP_ERROR_USER_ABORT, paylen);
err.cause = cause_code;
len = sizeof(sctp_errhdr_t) + paylen;
err.length = htons(len);
sctp_make_abort_user(asoc, NULL, 0);
sctp_make_abort(asoc, NULL, sizeof(sctp_errhdr_t) + paylen);
sctp_init_cause(retval, SCTP_ERROR_USER_ABORT, paylen);
err.cause = cause_code;
len = sizeof(sctp_errhdr_t) + paylen;
err.length = htons(len);
*************************3**************************************************
sctp_sf_abort_violation()
sctp_make_abort_violation(*chunk, *payload, size_t paylen)
retval = sctp_make_abort(asoc, chunk, sizeof(sctp_errhdr_t) + paylen + sizeof(sctp_paramhdr_t));
sctp_init_cause(retval, SCTP_ERROR_PROTO_VIOLATION, paylen + sizeof(sctp_paramhdr_t));
err.cause = cause_code;
len = sizeof(sctp_errhdr_t) + paylen;
err.length = htons(len);
phdr.type = htons(chunk->chunk_hdr->type);
phdr.length = chunk->chunk_hdr->length;
sctp_addto_chunk(retval, paylen, payload);
sctp_addto_param(retval, sizeof(sctp_paramhdr_t), &phdr);
sctp_make_abort_violation(*chunk, *payload, size_t paylen)
retval = sctp_make_abort(asoc, chunk, sizeof(sctp_errhdr_t) + paylen + sizeof(sctp_paramhdr_t));
sctp_init_cause(retval, SCTP_ERROR_PROTO_VIOLATION, paylen + sizeof(sctp_paramhdr_t));
err.cause = cause_code;
len = sizeof(sctp_errhdr_t) + paylen;
err.length = htons(len);
phdr.type = htons(chunk->chunk_hdr->type);
phdr.length = chunk->chunk_hdr->length;
sctp_addto_chunk(retval, paylen, payload);
sctp_addto_param(retval, sizeof(sctp_paramhdr_t), &phdr);
*************************4**************************************************
sctp_process_inv_paramlength()
sctp_make_violation_paramlen()
retval = sctp_make_abort(asoc, chunk, payload_len);
sctp_init_cause(retval, SCTP_ERROR_PROTO_VIOLATION, sizeof(error) + sizeof(sctp_paramhdr_t));
err.cause = cause_code;
len = sizeof(sctp_errhdr_t) + paylen;
err.length = htons(len);
sctp_addto_chunk(retval, sizeof(error), error);
sctp_addto_param(retval, sizeof(sctp_paramhdr_t), param);
sctp_make_violation_paramlen()
retval = sctp_make_abort(asoc, chunk, payload_len);
sctp_init_cause(retval, SCTP_ERROR_PROTO_VIOLATION, sizeof(error) + sizeof(sctp_paramhdr_t));
err.cause = cause_code;
len = sizeof(sctp_errhdr_t) + paylen;
err.length = htons(len);
sctp_addto_chunk(retval, sizeof(error), error);
sctp_addto_param(retval, sizeof(sctp_paramhdr_t), param);
*************************5**************************************************
sctp_sf_violation_paramlen() // only for ASCONF ASCONF_ACK
sctp_make_violation_paramlen()
retval = sctp_make_abort(asoc, chunk, payload_len);
sctp_init_cause(retval, SCTP_ERROR_PROTO_VIOLATION, sizeof(error) + sizeof(sctp_paramhdr_t));
err.cause = cause_code;
len = sizeof(sctp_errhdr_t) + paylen;
err.length = htons(len);
sctp_addto_chunk(retval, sizeof(error), error);
sctp_addto_param(retval, sizeof(sctp_paramhdr_t), param);
sctp_make_violation_paramlen()
retval = sctp_make_abort(asoc, chunk, payload_len);
sctp_init_cause(retval, SCTP_ERROR_PROTO_VIOLATION, sizeof(error) + sizeof(sctp_paramhdr_t));
err.cause = cause_code;
len = sizeof(sctp_errhdr_t) + paylen;
err.length = htons(len);
sctp_addto_chunk(retval, sizeof(error), error);
sctp_addto_param(retval, sizeof(sctp_paramhdr_t), param);
*************************6**************************************************
/*
* Generate an ABORT in response to a packet.
*
* Section: 8.4 Handle "Out of the blue" Packets, sctpimpguide 2.41
*
* 8) The receiver should respond to the sender of the OOTB packet with
* an ABORT. When sending the ABORT, the receiver of the OOTB packet
* MUST fill in the Verification Tag field of the outbound packet
* with the value found in the Verification Tag field of the OOTB
* packet and set the T-bit in the Chunk Flags to indicate that the
* Verification Tag is reflected. After sending this ABORT, the
* receiver of the OOTB packet shall discard the OOTB packet and take
* no further action.
*
* Verification Tag:
*
* The return value is the disposition of the chunk.
*/
sctp_sf_tabort_8_4_8()
sctp_make_abort(asoc, chunk, 0);
*************************7**************************************************
sctp_sf_do_asconf_ack()
abort = sctp_make_abort(asoc, asconf_ack,
sizeof(sctp_errhdr_t));
if (abort) {
sctp_init_cause(abort, SCTP_ERROR_ASCONF_ACK, 0);
sctp_add_cmd_sf(commands, SCTP_CMD_REPLY,
SCTP_CHUNK(abort));
}
* Generate an ABORT in response to a packet.
*
* Section: 8.4 Handle "Out of the blue" Packets, sctpimpguide 2.41
*
* 8) The receiver should respond to the sender of the OOTB packet with
* an ABORT. When sending the ABORT, the receiver of the OOTB packet
* MUST fill in the Verification Tag field of the outbound packet
* with the value found in the Verification Tag field of the OOTB
* packet and set the T-bit in the Chunk Flags to indicate that the
* Verification Tag is reflected. After sending this ABORT, the
* receiver of the OOTB packet shall discard the OOTB packet and take
* no further action.
*
* Verification Tag:
*
* The return value is the disposition of the chunk.
*/
sctp_sf_tabort_8_4_8()
sctp_make_abort(asoc, chunk, 0);
*************************7**************************************************
sctp_sf_do_asconf_ack()
abort = sctp_make_abort(asoc, asconf_ack,
sizeof(sctp_errhdr_t));
if (abort) {
sctp_init_cause(abort, SCTP_ERROR_ASCONF_ACK, 0);
sctp_add_cmd_sf(commands, SCTP_CMD_REPLY,
SCTP_CHUNK(abort));
}
*************************8**************************************************
sctp_sf_do_asconf_ack()
abort = sctp_make_abort(asoc, asconf_ack,
sizeof(sctp_errhdr_t));
if (abort) {
sctp_init_cause(abort, SCTP_ERROR_RSRC_LOW, 0);
sctp_add_cmd_sf(commands, SCTP_CMD_REPLY,
SCTP_CHUNK(abort));
}
abort = sctp_make_abort(asoc, asconf_ack,
sizeof(sctp_errhdr_t));
if (abort) {
sctp_init_cause(abort, SCTP_ERROR_RSRC_LOW, 0);
sctp_add_cmd_sf(commands, SCTP_CMD_REPLY,
SCTP_CHUNK(abort));
}
*************************9**************************************************
/* sctpimpguide-05 Section 2.12.2
* The sender of the SHUTDOWN MAY also start an overall guard timer
* 'T5-shutdown-guard' to bound the overall time for shutdown sequence.
* At the expiration of this timer the sender SHOULD abort the association
* by sending an ABORT chunk.
*/
sctp_sf_t5_timer_expire()
reply = sctp_make_abort(asoc, NULL, 0);
* The sender of the SHUTDOWN MAY also start an overall guard timer
* 'T5-shutdown-guard' to bound the overall time for shutdown sequence.
* At the expiration of this timer the sender SHOULD abort the association
* by sending an ABORT chunk.
*/
sctp_sf_t5_timer_expire()
reply = sctp_make_abort(asoc, NULL, 0);