summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRuss White <russ@riw.us>2023-05-02 16:28:20 +0200
committerGitHub <noreply@github.com>2023-05-02 16:28:20 +0200
commitc12a40fee397c14581ad482095b1a824e292f45c (patch)
treead71a267d0c657bb024df1706532b310364f7ebe
parentMerge pull request #13377 from donaldsharp/ospf_dead_interval (diff)
parentbabeld: add parse_request_subtlv into parse_packet (diff)
downloadfrr-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.c91
-rw-r--r--babeld/message.h1
-rw-r--r--babeld/util.h6
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. */