babeld: Ignore sub-tlv's with mandatory bit set

RFC 8966 4.4

   If the mandatory bit is set, then the
   whole enclosing TLV MUST be silently ignored (except for updating the
   parser state by a Router-Id, Next Hop, or Update TLV, as described in
   the next section).

Fixes: #11349
Signed-off-by: Donald Sharp <sharpd@nvidia.com>
This commit is contained in:
Donald Sharp 2022-06-08 09:01:31 -04:00
parent 54a3e60b3e
commit a76cf7e49e
2 changed files with 81 additions and 51 deletions

View File

@ -127,9 +127,8 @@ network_prefix(int ae, int plen, unsigned int omitted,
return ret; return ret;
} }
static void static bool parse_update_subtlv(const unsigned char *a, int alen,
parse_update_subtlv(const unsigned char *a, int alen, unsigned char *channels)
unsigned char *channels)
{ {
int type, len, i = 0; int type, len, i = 0;
@ -142,37 +141,51 @@ parse_update_subtlv(const unsigned char *a, int alen,
if(i + 1 >= alen) { if(i + 1 >= alen) {
flog_err(EC_BABEL_PACKET, "Received truncated attributes."); flog_err(EC_BABEL_PACKET, "Received truncated attributes.");
return; return false;
} }
len = a[i + 1]; len = a[i + 1];
if(i + len + 2 > alen) { if(i + len + 2 > alen) {
flog_err(EC_BABEL_PACKET, "Received truncated attributes."); flog_err(EC_BABEL_PACKET, "Received truncated attributes.");
return; return false;
} }
if(type == SUBTLV_PADN) { if (type & SUBTLV_MANDATORY) {
/* Nothing. */ /*
} else if(type == SUBTLV_DIVERSITY) { * RFC 8966 - 4.4
if(len > DIVERSITY_HOPS) { * If the mandatory bit is set, then the whole enclosing
flog_err(EC_BABEL_PACKET, * TLV MUST be silently ignored (except for updating the
"Received overlong channel information (%d > %d).n", * parser state by a Router-Id, Next Hop, or Update TLV,
len, DIVERSITY_HOPS); * as described in the next section).
len = DIVERSITY_HOPS; */
} debugf(BABEL_DEBUG_COMMON,
if(memchr(a + i + 2, 0, len) != NULL) { "Received Mandatory bit set but this FRR version is not prepared to handle it at this point");
/* 0 is reserved. */ return true;
flog_err(EC_BABEL_PACKET, "Channel information contains 0!"); } else if (type == SUBTLV_PADN) {
return; /* Nothing. */
} } else if (type == SUBTLV_DIVERSITY) {
memset(channels, 0, DIVERSITY_HOPS); if (len > DIVERSITY_HOPS) {
memcpy(channels, a + i + 2, len); flog_err(
} else { EC_BABEL_PACKET,
debugf(BABEL_DEBUG_COMMON, "Received overlong channel information (%d > %d).n",
"Received unknown route attribute %d.", type); len, DIVERSITY_HOPS);
} len = DIVERSITY_HOPS;
}
if (memchr(a + i + 2, 0, len) != NULL) {
/* 0 is reserved. */
flog_err(EC_BABEL_PACKET,
"Channel information contains 0!");
return false;
}
memset(channels, 0, DIVERSITY_HOPS);
memcpy(channels, a + i + 2, len);
} else {
debugf(BABEL_DEBUG_COMMON,
"Received unknown route attribute %d.", type);
}
i += len + 2; i += len + 2;
} }
return false;
} }
static int static int
@ -200,22 +213,34 @@ parse_hello_subtlv(const unsigned char *a, int alen,
return -1; return -1;
} }
if(type == SUBTLV_PADN) { if (type & SUBTLV_MANDATORY) {
/* Nothing to do. */ /*
} else if(type == SUBTLV_TIMESTAMP) { * RFC 8966 4.4
if(len >= 4) { * If the mandatory bit is set, then the whole enclosing
DO_NTOHL(*hello_send_us, a + i + 2); * TLV MUST be silently ignored (except for updating the
ret = 1; * parser state by a Router-Id, Next Hop, or Update TLV, as
} else { * described in the next section).
flog_err(EC_BABEL_PACKET, */
"Received incorrect RTT sub-TLV on Hello message."); debugf(BABEL_DEBUG_COMMON,
} "Received subtlv with Mandatory bit, this version of FRR is not prepared to handle this currently");
} else { return -2;
debugf(BABEL_DEBUG_COMMON, } else if (type == SUBTLV_PADN) {
"Received unknown Hello sub-TLV type %d.", type); /* Nothing to do. */
} } else if (type == SUBTLV_TIMESTAMP) {
if (len >= 4) {
DO_NTOHL(*hello_send_us, a + i + 2);
ret = 1;
} else {
flog_err(
EC_BABEL_PACKET,
"Received incorrect RTT sub-TLV on Hello message.");
}
} else {
debugf(BABEL_DEBUG_COMMON,
"Received unknown Hello sub-TLV type %d.", type);
}
i += len + 2; i += len + 2;
} }
return ret; return ret;
} }
@ -518,7 +543,9 @@ parse_packet(const unsigned char *from, struct interface *ifp,
unsigned char channels[DIVERSITY_HOPS]; unsigned char channels[DIVERSITY_HOPS];
unsigned short interval, seqno, metric; unsigned short interval, seqno, metric;
int rc, parsed_len; int rc, parsed_len;
DO_NTOHS(interval, message + 6); bool ignore_update = false;
DO_NTOHS(interval, message + 6);
DO_NTOHS(seqno, message + 8); DO_NTOHS(seqno, message + 8);
DO_NTOHS(metric, message + 10); DO_NTOHS(metric, message + 10);
if(message[5] == 0 || if(message[5] == 0 ||
@ -604,14 +631,16 @@ parse_packet(const unsigned char *from, struct interface *ifp,
} }
if(parsed_len < len) if(parsed_len < len)
parse_update_subtlv(message + 2 + parsed_len, ignore_update =
len - parsed_len, channels); parse_update_subtlv(message + 2 + parsed_len,
} len - parsed_len, channels);
}
update_route(router_id, prefix, plen, seqno, metric, interval, if (ignore_update)
neigh, nh, update_route(router_id, prefix, plen, seqno, metric,
channels, channels_len(channels)); interval, neigh, nh, channels,
} else if(type == MESSAGE_REQUEST) { channels_len(channels));
} else if(type == MESSAGE_REQUEST) {
unsigned char prefix[16], plen; unsigned char prefix[16], plen;
int rc; int rc;
rc = network_prefix(message[2], message[3], 0, rc = network_prefix(message[2], message[3], 0,

View File

@ -51,6 +51,7 @@ THE SOFTWARE.
#define SUBTLV_PADN 1 #define SUBTLV_PADN 1
#define SUBTLV_DIVERSITY 2 /* Also known as babelz. */ #define SUBTLV_DIVERSITY 2 /* Also known as babelz. */
#define SUBTLV_TIMESTAMP 3 /* Used to compute RTT. */ #define SUBTLV_TIMESTAMP 3 /* Used to compute RTT. */
#define SUBTLV_MANDATORY 0x80
extern unsigned short myseqno; extern unsigned short myseqno;