sctp: improve sending of packets containing an INIT ACK chunk

If the peer announced support of zero checksums, do so when sending
packets containing an INIT ACK chunk.

MFC after:	1 week
This commit is contained in:
Michael Tuexen 2024-02-24 19:16:36 +01:00
parent 038699a8f1
commit 644cffe67f
3 changed files with 36 additions and 6 deletions

View file

@ -406,7 +406,7 @@ sctp_process_init_ack(struct mbuf *m, int iphlen, int offset,
op_err = sctp_arethere_unrecognized_parameters(m,
(offset + sizeof(struct sctp_init_chunk)),
&abort_flag, (struct sctp_chunkhdr *)cp,
&nat_friendly, &cookie_found);
&nat_friendly, &cookie_found, NULL);
if (abort_flag) {
/* Send an abort and notify peer */
sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen,

View file

@ -4918,7 +4918,8 @@ sctp_arethere_unrecognized_parameters(struct mbuf *in_initpkt,
int param_offset, int *abort_processing,
struct sctp_chunkhdr *cp,
int *nat_friendly,
int *cookie_found)
int *cookie_found,
uint32_t *edmid)
{
/*
* Given a mbuf containing an INIT or INIT-ACK with the param_offset
@ -4934,8 +4935,8 @@ sctp_arethere_unrecognized_parameters(struct mbuf *in_initpkt,
* hoped that this routine may be reused in the future by new
* features.
*/
struct sctp_zero_checksum_acceptable zero_chksum, *zero_chksum_p;
struct sctp_paramhdr *phdr, params;
struct mbuf *mat, *m_tmp, *op_err, *op_err_last;
int at, limit, pad_needed;
uint16_t ptype, plen, padded_size;
@ -4944,6 +4945,9 @@ sctp_arethere_unrecognized_parameters(struct mbuf *in_initpkt,
if (cookie_found != NULL) {
*cookie_found = 0;
}
if (edmid != NULL) {
*edmid = SCTP_EDMID_NONE;
}
mat = in_initpkt;
limit = ntohs(cp->chunk_length) - sizeof(struct sctp_init_chunk);
at = param_offset;
@ -4999,6 +5003,22 @@ sctp_arethere_unrecognized_parameters(struct mbuf *in_initpkt,
}
at += padded_size;
break;
case SCTP_ZERO_CHECKSUM_ACCEPTABLE:
if (padded_size != sizeof(struct sctp_zero_checksum_acceptable)) {
SCTPDBG(SCTP_DEBUG_OUTPUT1, "Invalid size - error checksum acceptable %d\n", plen);
goto invalid_size;
}
if (edmid != NULL) {
phdr = sctp_get_next_param(mat, at,
(struct sctp_paramhdr *)&zero_chksum,
sizeof(struct sctp_zero_checksum_acceptable));
if (phdr != NULL) {
zero_chksum_p = (struct sctp_zero_checksum_acceptable *)phdr;
*edmid = ntohl(zero_chksum_p->edmid);
}
}
at += padded_size;
break;
case SCTP_RANDOM:
if (padded_size > (sizeof(struct sctp_auth_random) + SCTP_RANDOM_MAX_SIZE)) {
SCTPDBG(SCTP_DEBUG_OUTPUT1, "Invalid size - error random %d\n", plen);
@ -5513,7 +5533,9 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
int nat_friendly = 0;
int error;
struct socket *so;
uint32_t edmid;
uint16_t num_ext, chunk_len, padding_len, parameter_len;
bool use_zero_crc;
if (stcb) {
asoc = &stcb->asoc;
@ -5554,7 +5576,7 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
(offset + sizeof(struct sctp_init_chunk)),
&abort_flag,
(struct sctp_chunkhdr *)init_chk,
&nat_friendly, NULL);
&nat_friendly, NULL, &edmid);
if (abort_flag) {
do_a_abort:
if (op_err == NULL) {
@ -6155,12 +6177,18 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
over_addr = NULL;
}
if (asoc != NULL) {
use_zero_crc = (asoc->rcv_edmid != SCTP_EDMID_NONE) && (asoc->rcv_edmid == edmid);
} else {
use_zero_crc = (inp->rcv_edmid != SCTP_EDMID_NONE) && (inp->rcv_edmid == edmid);
}
if ((error = sctp_lowlevel_chunk_output(inp, NULL, NULL, to, m, 0, NULL, 0, 0,
0, 0,
inp->sctp_lport, sh->src_port, init_chk->init.initiate_tag,
port, over_addr,
mflowtype, mflowid,
false, /* XXXMT: Improve this! */
use_zero_crc,
SCTP_SO_NOT_LOCKED))) {
SCTPDBG(SCTP_DEBUG_OUTPUT4, "Gak send error %d\n", error);
if (error == ENOBUFS) {

View file

@ -80,7 +80,9 @@ sctp_send_initiate_ack(struct sctp_inpcb *, struct sctp_tcb *,
struct mbuf *
sctp_arethere_unrecognized_parameters(struct mbuf *, int, int *,
struct sctp_chunkhdr *, int *, int *);
struct sctp_chunkhdr *, int *, int *,
uint32_t *);
void sctp_queue_op_err(struct sctp_tcb *, struct mbuf *);
int