summaryrefslogtreecommitdiff
path: root/babeld/message.c
diff options
context:
space:
mode:
Diffstat (limited to 'babeld/message.c')
-rw-r--r--babeld/message.c217
1 files changed, 144 insertions, 73 deletions
diff --git a/babeld/message.c b/babeld/message.c
index 0ddfda8d7b..c2ea2a2683 100644
--- a/babeld/message.c
+++ b/babeld/message.c
@@ -127,9 +127,8 @@ network_prefix(int ae, int plen, unsigned int omitted,
return ret;
}
-static void
-parse_update_subtlv(const unsigned char *a, int alen,
- unsigned char *channels)
+static bool parse_update_subtlv(const unsigned char *a, int alen,
+ unsigned char *channels)
{
int type, len, i = 0;
@@ -142,37 +141,51 @@ parse_update_subtlv(const unsigned char *a, int alen,
if(i + 1 >= alen) {
flog_err(EC_BABEL_PACKET, "Received truncated attributes.");
- return;
- }
+ return false;
+ }
len = a[i + 1];
if(i + len + 2 > alen) {
flog_err(EC_BABEL_PACKET, "Received truncated attributes.");
- return;
- }
+ return false;
+ }
- if(type == SUBTLV_PADN) {
- /* Nothing. */
- } else if(type == SUBTLV_DIVERSITY) {
- if(len > DIVERSITY_HOPS) {
- flog_err(EC_BABEL_PACKET,
- "Received overlong channel information (%d > %d).n",
- 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;
- }
- memset(channels, 0, DIVERSITY_HOPS);
- memcpy(channels, a + i + 2, len);
- } else {
- debugf(BABEL_DEBUG_COMMON,
- "Received unknown route attribute %d.", type);
- }
+ if (type & SUBTLV_MANDATORY) {
+ /*
+ * 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).
+ */
+ debugf(BABEL_DEBUG_COMMON,
+ "Received Mandatory bit set but this FRR version is not prepared to handle it at this point");
+ return true;
+ } else if (type == SUBTLV_PADN) {
+ /* Nothing. */
+ } else if (type == SUBTLV_DIVERSITY) {
+ if (len > DIVERSITY_HOPS) {
+ flog_err(
+ EC_BABEL_PACKET,
+ "Received overlong channel information (%d > %d).n",
+ 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
@@ -200,22 +213,34 @@ parse_hello_subtlv(const unsigned char *a, int alen,
return -1;
}
- if(type == SUBTLV_PADN) {
- /* 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);
- }
+ if (type & SUBTLV_MANDATORY) {
+ /*
+ * 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).
+ */
+ debugf(BABEL_DEBUG_COMMON,
+ "Received subtlv with Mandatory bit, this version of FRR is not prepared to handle this currently");
+ return -2;
+ } else if (type == SUBTLV_PADN) {
+ /* 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;
}
@@ -398,27 +423,69 @@ parse_packet(const unsigned char *from, struct interface *ifp,
format_address(from), ifp->name);
/* Nothing right now */
} else if(type == MESSAGE_HELLO) {
- unsigned short seqno, interval;
- int changed;
- unsigned int timestamp = 0;
- DO_NTOHS(seqno, message + 4);
- DO_NTOHS(interval, message + 6);
- debugf(BABEL_DEBUG_COMMON,"Received hello %d (%d) from %s on %s.",
- seqno, interval,
- format_address(from), ifp->name);
- changed = update_neighbour(neigh, seqno, interval);
- update_neighbour_metric(neigh, changed);
- if(interval > 0)
- /* Multiply by 3/2 to allow hellos to expire. */
- schedule_neighbours_check(interval * 15, 0);
- /* Sub-TLV handling. */
- if(len > 8) {
- if(parse_hello_subtlv(message + 8, len - 6, &timestamp) > 0) {
- neigh->hello_send_us = timestamp;
- neigh->hello_rtt_receive_time = babel_now;
- have_hello_rtt = 1;
- }
- }
+ unsigned short seqno, interval, flags;
+ int changed;
+ unsigned int timestamp = 0;
+
+#define BABEL_UNICAST_HELLO 0x8000
+ DO_NTOHS(flags, message + 2);
+
+ /*
+ * RFC 8966 4.6.5
+ * All other bits MUST be sent as a 0 and silently
+ * ignored on reception
+ */
+ if (CHECK_FLAG(flags, ~BABEL_UNICAST_HELLO)) {
+ debugf(BABEL_DEBUG_COMMON,
+ "Received Hello from %s on %s that does not have all 0's in the unused section of flags, ignoring",
+ format_address(from), ifp->name);
+ continue;
+ }
+
+ /*
+ * RFC 8966 Appendix F
+ * TL;DR -> Please ignore Unicast hellos until FRR's
+ * BABEL is brought up to date
+ */
+ if (CHECK_FLAG(flags, BABEL_UNICAST_HELLO)) {
+ debugf(BABEL_DEBUG_COMMON,
+ "Received Unicast Hello from %s on %s that FRR is not prepared to understand yet",
+ format_address(from), ifp->name);
+ continue;
+ }
+
+ DO_NTOHS(seqno, message + 4);
+ DO_NTOHS(interval, message + 6);
+ debugf(BABEL_DEBUG_COMMON,
+ "Received hello %d (%d) from %s on %s.", seqno, interval,
+ format_address(from), ifp->name);
+
+ /*
+ * RFC 8966 Appendix F
+ * TL;DR -> Please ignore any Hello packets with the interval
+ * field set to 0
+ */
+ if (interval == 0) {
+ debugf(BABEL_DEBUG_COMMON,
+ "Received hello from %s on %s should be ignored as that this version of FRR does not know how to properly handle interval == 0",
+ format_address(from), ifp->name);
+ continue;
+ }
+
+ changed = update_neighbour(neigh, seqno, interval);
+ update_neighbour_metric(neigh, changed);
+ if (interval > 0)
+ /* Multiply by 3/2 to allow hellos to expire. */
+ schedule_neighbours_check(interval * 15, 0);
+ /* Sub-TLV handling. */
+ if (len > 8) {
+ if (parse_hello_subtlv(message + 8, len - 6,
+ &timestamp) > 0) {
+ neigh->hello_send_us = timestamp;
+ neigh->hello_rtt_receive_time = babel_now;
+ have_hello_rtt = 1;
+ }
+ }
} else if(type == MESSAGE_IHU) {
unsigned short txcost, interval;
unsigned char address[16];
@@ -476,7 +543,9 @@ parse_packet(const unsigned char *from, struct interface *ifp,
unsigned char channels[DIVERSITY_HOPS];
unsigned short interval, seqno, metric;
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(metric, message + 10);
if(message[5] == 0 ||
@@ -562,14 +631,16 @@ parse_packet(const unsigned char *from, struct interface *ifp,
}
if(parsed_len < len)
- parse_update_subtlv(message + 2 + parsed_len,
- len - parsed_len, channels);
- }
-
- update_route(router_id, prefix, plen, seqno, metric, interval,
- neigh, nh,
- channels, channels_len(channels));
- } else if(type == MESSAGE_REQUEST) {
+ ignore_update =
+ parse_update_subtlv(message + 2 + parsed_len,
+ len - parsed_len, channels);
+ }
+
+ if (ignore_update)
+ update_route(router_id, prefix, plen, seqno, metric,
+ interval, neigh, nh, channels,
+ channels_len(channels));
+ } else if(type == MESSAGE_REQUEST) {
unsigned char prefix[16], plen;
int rc;
rc = network_prefix(message[2], message[3], 0,