From 8964c0b1bc8c99f3d83eeeb70b4425fcc006f2a8 Mon Sep 17 00:00:00 2001 From: Erik Boasson Date: Wed, 21 Aug 2019 12:11:23 +0200 Subject: [PATCH] Handle malformed pre-emptive ACKNACK from FastRTPS The pre-emptive ACKNACK messages from FastRTPS have a base sequence number of 0, which is malformed and must be rejected according to DDSI 8.3.7.1 / 8.3.5.5. Signed-off-by: Erik Boasson --- src/core/ddsi/include/dds/ddsi/ddsi_vendor.h | 3 +++ src/core/ddsi/src/ddsi_vendor.c | 1 + src/core/ddsi/src/q_receive.c | 13 ++++++++++--- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/core/ddsi/include/dds/ddsi/ddsi_vendor.h b/src/core/ddsi/include/dds/ddsi/ddsi_vendor.h index 02c277b..c6faa62 100644 --- a/src/core/ddsi/include/dds/ddsi/ddsi_vendor.h +++ b/src/core/ddsi/include/dds/ddsi/ddsi_vendor.h @@ -60,6 +60,9 @@ inline bool vendor_is_opensplice (nn_vendorid_t vendor) { inline bool vendor_is_twinoaks (nn_vendorid_t vendor) { return vendor_equals (vendor, (nn_vendorid_t) {{ 0x01, NN_VENDORID_MINOR_TWINOAKS }}); } +inline bool vendor_is_eprosima (nn_vendorid_t vendor) { + return vendor_equals (vendor, (nn_vendorid_t) {{ 0x01, NN_VENDORID_MINOR_EPROSIMA }}); +} inline bool vendor_is_cloud (nn_vendorid_t vendor) { return vendor_equals (vendor, (nn_vendorid_t) {{ 0x01, NN_VENDORID_MINOR_PRISMTECH_CLOUD }}); } diff --git a/src/core/ddsi/src/ddsi_vendor.c b/src/core/ddsi/src/ddsi_vendor.c index 2fea95b..6d1dfaf 100644 --- a/src/core/ddsi/src/ddsi_vendor.c +++ b/src/core/ddsi/src/ddsi_vendor.c @@ -16,6 +16,7 @@ extern inline bool vendor_equals (nn_vendorid_t a, nn_vendorid_t b); extern inline bool vendor_is_rti (nn_vendorid_t vendor); extern inline bool vendor_is_twinoaks (nn_vendorid_t vendor); +extern inline bool vendor_is_eprosima (nn_vendorid_t vendor); extern inline bool vendor_is_prismtech (nn_vendorid_t vendor); extern inline bool vendor_is_opensplice (nn_vendorid_t vendor); extern inline bool vendor_is_cloud (nn_vendorid_t vendor); diff --git a/src/core/ddsi/src/q_receive.c b/src/core/ddsi/src/q_receive.c index 0c1eff8..00b678c 100644 --- a/src/core/ddsi/src/q_receive.c +++ b/src/core/ddsi/src/q_receive.c @@ -113,7 +113,7 @@ static int valid_fragment_number_set (const nn_fragment_number_set_header_t *fns return (fnset->bitmap_base > 0 && fnset->numbits <= 256); } -static int valid_AckNack (AckNack_t *msg, size_t size, int byteswap) +static int valid_AckNack (const struct receiver_state *rst, AckNack_t *msg, size_t size, int byteswap) { nn_count_t *count; /* this should've preceded the bitmap */ if (size < ACKNACK_SIZE (0)) @@ -129,7 +129,14 @@ static int valid_AckNack (AckNack_t *msg, size_t size, int byteswap) msg->writerId = nn_ntoh_entityid (msg->writerId); /* Validation following 8.3.7.1.3 + 8.3.5.5 */ if (!valid_sequence_number_set (&msg->readerSNState)) - return 0; + { + /* FastRTPS sends invalid pre-emptive ACKs -- patch the message so we can process it */ + if (! NN_STRICT_P (rst->gv->config) && vendor_is_eprosima (rst->vendor) && + fromSN (msg->readerSNState.bitmap_base) == 0 && msg->readerSNState.numbits == 0) + msg->readerSNState.bitmap_base = toSN (1); + else + return 0; + } /* Given the number of bits, we can compute the size of the AckNack submessage, and verify that the submessage is large enough */ if (size < ACKNACK_SIZE (msg->readerSNState.numbits)) @@ -2677,7 +2684,7 @@ static int handle_submsg_sequence break; case SMID_ACKNACK: state = "parse:acknack"; - if (!valid_AckNack (&sm->acknack, submsg_size, byteswap)) + if (!valid_AckNack (rst, &sm->acknack, submsg_size, byteswap)) goto malformed; handle_AckNack (rst, tnowE, &sm->acknack, ts_for_latmeas ? timestamp : NN_WCTIME_INVALID); ts_for_latmeas = 0;