diff options
author | Russ White <russ@riw.us> | 2023-05-02 16:28:20 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-05-02 16:28:20 +0200 |
commit | c12a40fee397c14581ad482095b1a824e292f45c (patch) | |
tree | ad71a267d0c657bb024df1706532b310364f7ebe | |
parent | Merge pull request #13377 from donaldsharp/ospf_dead_interval (diff) | |
parent | babeld: add parse_request_subtlv into parse_packet (diff) | |
download | frr-c12a40fee397c14581ad482095b1a824e292f45c.tar.xz frr-c12a40fee397c14581ad482095b1a824e292f45c.zip |
Merge pull request #13354 from zmw12306/parse_request_subtlv
babeld: add parse_request_subtlv into parse_packet
-rw-r--r-- | babeld/message.c | 91 | ||||
-rw-r--r-- | babeld/message.h | 1 | ||||
-rw-r--r-- | babeld/util.h | 6 |
3 files changed, 96 insertions, 2 deletions
diff --git a/babeld/message.c b/babeld/message.c index 15d772eb4..d4ddebff0 100644 --- a/babeld/message.c +++ b/babeld/message.c @@ -48,6 +48,13 @@ static const unsigned char tlv_min_length[MESSAGE_MAX + 1] = [ MESSAGE_MH_REQUEST ] = 14, }; +/* Checks whether an AE exists or must be silently ignored */ +static bool +known_ae(int ae) +{ + return ae <= 4; +} + /* Parse a network prefix, encoded in the somewhat baroque compressed representation used by Babel. Return the number of bytes parsed. */ static int @@ -277,6 +284,62 @@ parse_ihu_subtlv(const unsigned char *a, int alen, } static int +parse_request_subtlv(int ae, const unsigned char *a, int alen, + unsigned char *src_prefix, unsigned char *src_plen) +{ + int type, len, i = 0; + int have_src_prefix = 0; + + while(i < alen) { + type = a[0]; + if(type == SUBTLV_PAD1) { + i++; + continue; + } + + if(i + 2 > alen) + goto fail; + + len = a[i + 1]; + if(i + 2 + len > alen) + goto fail; + + if(type == SUBTLV_PADN) { + /* Nothing to do. */ + } else if(type == SUBTLV_SOURCE_PREFIX) { + int rc; + if(len < 1) + goto fail; + if(a[i + 2] == 0) + goto fail; + if(have_src_prefix != 0) + goto fail; + rc = network_prefix(ae, a[i + 2], 0, a + i + 3, NULL, + len - 1, src_prefix); + if(rc < 0) + goto fail; + if(ae==1) + *src_plen = a[i + 2] + 96; + else + *src_plen = a[i + 2]; + have_src_prefix = 1; + } else { + debugf(BABEL_DEBUG_COMMON,"Received unknown%s Route Request sub-TLV %d.", + ((type & 0x80) != 0) ? " mandatory" : "", type); + if((type & 0x80) != 0) + return -1; + } + + i += len + 2; + } + return 1; + + fail: + flog_err(EC_BABEL_PACKET, "Received truncated sub-TLV on Route Request."); + return -1; +} + +static int network_address(int ae, const unsigned char *a, unsigned int len, unsigned char *a_r) { @@ -612,8 +675,14 @@ parse_packet(const unsigned char *from, struct interface *ifp, interval, neigh, nh, channels, channels_len(channels)); } else if(type == MESSAGE_REQUEST) { - unsigned char prefix[16], plen; - int rc; + unsigned char prefix[16], src_prefix[16], plen, src_plen; + int rc, is_ss; + if(len < 2) goto fail; + if(!known_ae(message[2])) { + debugf(BABEL_DEBUG_COMMON,"Received request with unknown AE %d. Ignoring.", + message[2]); + goto done; + } rc = network_prefix(message[2], message[3], 0, message + 4, NULL, len - 2, prefix); if(rc < 0) goto fail; @@ -621,8 +690,26 @@ parse_packet(const unsigned char *from, struct interface *ifp, debugf(BABEL_DEBUG_COMMON,"Received request for %s from %s on %s.", message[2] == 0 ? "any" : format_prefix(prefix, plen), format_address(from), ifp->name); + if(message[2] == 1) { + v4tov6(src_prefix, zeroes); + src_plen = 96; + } else { + memcpy(src_prefix, zeroes, 16); + src_plen = 0; + } + rc = parse_request_subtlv(message[2], message + 4 + rc, + len - 2 - rc, src_prefix, &src_plen); + if(rc < 0) + goto done; + is_ss = !is_default(src_prefix, src_plen); if(message[2] == 0) { struct babel_interface *neigh_ifp =babel_get_if_nfo(neigh->ifp); + if(is_ss) { + /* Wildcard requests don't carry a source prefix. */ + flog_err(EC_BABEL_PACKET, + "Received source-specific wildcard request."); + goto done; + } /* If a neighbour is requesting a full route dump from us, we might as well send it an IHU. */ send_ihu(neigh, NULL); diff --git a/babeld/message.h b/babeld/message.h index 0797a5a77..7cf062a88 100644 --- a/babeld/message.h +++ b/babeld/message.h @@ -34,6 +34,7 @@ Copyright (c) 2007, 2008 by Juliusz Chroboczek #define SUBTLV_PADN 1 #define SUBTLV_DIVERSITY 2 /* Also known as babelz. */ #define SUBTLV_TIMESTAMP 3 /* Used to compute RTT. */ +#define SUBTLV_SOURCE_PREFIX 128 /* Source-specific routing. */ #define SUBTLV_MANDATORY 0x80 extern unsigned short myseqno; diff --git a/babeld/util.h b/babeld/util.h index 8535d4dd6..ddc6a70d4 100644 --- a/babeld/util.h +++ b/babeld/util.h @@ -104,6 +104,12 @@ void uchar_to_in6addr(struct in6_addr *dest, const unsigned char *src); int daemonise(void); extern const unsigned char v4prefix[16]; +static inline bool +is_default(const unsigned char *prefix, int plen) +{ + return plen == 0 || (plen == 96 && v4mapped(prefix)); +} + /* If debugging is disabled, we want to avoid calling format_address for every omitted debugging message. So debug is a macro. But vararg macros are not portable. */ |