From 7100df8844c40b5635e26364090f823b3003bea0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Ca=C3=B1uelo=20Navarro?= Date: Thu, 13 Aug 2026 14:12:12 +0200 Subject: [PATCH] sctp: fix outgoing SACK corruption on DATA chunk reception MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On libpeer's own SCTP implementation, reception of a DATA chunk may result in a call to the "onmessage" callback, if available. Before running the callback, sctp_incoming_data() prepares a SACK chunk that is meant to be sent after the callback is done, but if the callback sends any data as a response, it'll overwrite the already formatted SACK chunk header, corrupting the SACK. Fix it by sending moving the SACK send before the callback. Signed-off-by: Ricardo CaƱuelo Navarro --- src/sctp.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/sctp.c b/src/sctp.c index 644f8d8e..acb68cc3 100644 --- a/src/sctp.c +++ b/src/sctp.c @@ -273,8 +273,24 @@ void sctp_incoming_data(Sctp* sctp, char* buf, size_t len) { length += ntohs(data_chunk->length); } else if (ntohl(data_chunk->ppid) == DATA_CHANNEL_PPID_DOMSTRING || ntohl(data_chunk->ppid) == DATA_CHANNEL_PPID_BINARY) { if (sctp->onmessage) { + /* + * In case the "onmessage" callback sends a DATA chunk, we + * send the SACK first, and stop the processing after the + * callback. + */ + out_packet->header.source_port = htons(sctp->local_port); + out_packet->header.destination_port = htons(sctp->remote_port); + out_packet->header.verification_tag = sctp->verification_tag; + out_packet->header.checksum = 0x00; + if (length > 0) { + // padding 4 + length = (4 * ((length + 3) / 4)); + out_packet->header.checksum = sctp_get_checksum(sctp, sctp->buf, length); + dtls_srtp_write(sctp->dtls_srtp, sctp->buf, length); + } sctp->onmessage((char*)data_chunk->data, ntohs(data_chunk->length) - sizeof(SctpDataChunk), sctp->userdata, ntohs(data_chunk->sid)); + return; } } pos = len; // Do not handle other msg