diff options
Diffstat (limited to 'babeld/message.c')
| -rw-r--r-- | babeld/message.c | 217 |
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, ×tamp) > 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, + ×tamp) > 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, |
