]> git.proxmox.com Git - mirror_frr.git/commitdiff
babeld: add parse_request_subtlv into parse_packet
authorzmw12306 <zmw12306@gmail.com>
Sat, 22 Apr 2023 13:01:54 +0000 (09:01 -0400)
committerzmw12306 <zmw12306@gmail.com>
Sat, 22 Apr 2023 13:01:54 +0000 (09:01 -0400)
when type is MESSAGE_REQUEST, babel should be able to handle sub_tlvs
Signed-off-by: zmw12306 <zmw12306@gmail.com>
babeld/message.c
babeld/message.h
babeld/util.h

index b5c2a589848f97eab66d45686d6d50fc668f9062..65ff0e4f83fd3d1ceb33f247a6a52e1998e1c635 100644 (file)
@@ -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
@@ -276,6 +283,62 @@ parse_ihu_subtlv(const unsigned char *a, int alen,
     return ret;
 }
 
+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)
@@ -624,8 +687,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;
@@ -633,8 +702,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);
index 0797a5a77de465c91456249555603f9973f87e0e..7cf062a88824c533aae6bb66918d7ba8c9fa9eac 100644 (file)
@@ -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;
index 8535d4dd6a173aa605bb5b2c853cd1b46e99179f..ddc6a70d43b5de8bb38bc49c2d1627006c800e41 100644 (file)
@@ -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. */