]> The Tcpdump Group git mirrors - tcpdump/commitdiff
initial support for Babel sub-TLVs decoding
authorDenis Ovsienko <[email protected]>
Fri, 10 May 2013 13:38:58 +0000 (17:38 +0400)
committerDenis Ovsienko <[email protected]>
Wed, 29 May 2013 09:03:23 +0000 (13:03 +0400)
Babel sub-TLVs are a work in progress, a backward-compatible extension
to Babel version 2 protocol encoding. This update implements encoding
explained by Juliusz Chroboczek to decode ChanInfo sub-TLV of the Update
TLV.

print-babel.c
tests/babel1v.out

index 8b422b3f1fea05620838c07c7e60455bc8c786a1..58faca158ebfa512f67aeb84b832aef7b7fe85ec 100644 (file)
@@ -70,6 +70,7 @@ babel_print(const u_char *cp, u_int length) {
     return;
 }
 
+/* TLVs */
 #define MESSAGE_PAD1 0
 #define MESSAGE_PADN 1
 #define MESSAGE_ACK_REQ 2
@@ -84,6 +85,18 @@ babel_print(const u_char *cp, u_int length) {
 #define MESSAGE_TSPC 11
 #define MESSAGE_HMAC 12
 
+/* sub-TLVs */
+#define MESSAGE_SUB_PAD1 0
+#define MESSAGE_SUB_PADN 1
+#define MESSAGE_SUB_CHANINFO 2
+
+/* ChanInfo sub-TLV channel codes */
+static const struct tok chaninfo_str[] = {
+    { 0,   "reserved" },
+    { 255, "all"      },
+    { 0, NULL }
+};
+
 static const char *
 format_id(const u_char *id)
 {
@@ -126,6 +139,8 @@ format_address(const u_char *prefix)
 #endif
 }
 
+/* Return number of octets consumed from the input buffer (not the prefix length
+ * in bytes), or -1 for encoding error. */
 static int
 network_prefix(int ae, int plen, unsigned int omitted,
                const unsigned char *p, const unsigned char *dp,
@@ -133,6 +148,7 @@ network_prefix(int ae, int plen, unsigned int omitted,
 {
     unsigned pb;
     unsigned char prefix[16];
+    int consumed = 0;
 
     if(plen >= 0)
         pb = (plen + 7) / 8;
@@ -156,7 +172,10 @@ network_prefix(int ae, int plen, unsigned int omitted,
             if (dp == NULL) return -1;
             memcpy(prefix, dp, 12 + omitted);
         }
-        if(pb > omitted) memcpy(prefix + 12 + omitted, p, pb - omitted);
+        if(pb > omitted) {
+            memcpy(prefix + 12 + omitted, p, pb - omitted);
+            consumed = pb - omitted;
+        }
         break;
     case 2:
         if(omitted > 16 || (pb > omitted && len < pb - omitted))
@@ -165,20 +184,26 @@ network_prefix(int ae, int plen, unsigned int omitted,
             if (dp == NULL) return -1;
             memcpy(prefix, dp, omitted);
         }
-        if(pb > omitted) memcpy(prefix + omitted, p, pb - omitted);
+        if(pb > omitted) {
+            memcpy(prefix + omitted, p, pb - omitted);
+            consumed = pb - omitted;
+        }
         break;
     case 3:
         if(pb > 8 && len < pb - 8) return -1;
         prefix[0] = 0xfe;
         prefix[1] = 0x80;
-        if(pb > 8) memcpy(prefix + 8, p, pb - 8);
+        if(pb > 8) {
+            memcpy(prefix + 8, p, pb - 8);
+            consumed = pb - 8;
+        }
         break;
     default:
         return -1;
     }
 
     memcpy(p_r, prefix, 16);
-    return 1;
+    return consumed;
 }
 
 static int
@@ -188,6 +213,71 @@ network_address(int ae, const unsigned char *a, unsigned int len,
     return network_prefix(ae, -1, 0, a, NULL, len, a_r);
 }
 
+/*
+ * Sub-TLVs consume the "extra data" of Babel TLVs (see Section 4.3 of RFC6126),
+ * their encoding is similar to the encoding of TLVs, but the type namespace is
+ * different:
+ *
+ * o Type 0 stands for Pad1 sub-TLV with the same encoding as the Pad1 TLV.
+ * o Type 1 stands for PadN sub-TLV with the same encoding as the PadN TLV.
+ * o Type 2 stands for ChanInfo sub-TLV, which propagates diversity routing
+ *   data. Its body is a variable-length sequence of 8-bit unsigned integers,
+ *   each representing per-hop number of interferring radio channel for the
+ *   prefix. Channel 0 is invalid and must not be used in the sub-TLV, channel
+ *   255 interferes with any other channel.
+ *
+ * Sub-TLV types 0 and 1 are valid for any TLV type, whether sub-TLV type 2 is
+ * only valid for TLV type 8 (Update). Note that within an Update TLV a missing
+ * ChanInfo sub-TLV is not the same as a ChanInfo sub-TLV with an empty body.
+ * The former would mean a lack of any claims about the interference, and the
+ * latter would state that interference is definitely absent. */
+static void
+subtlvs_print(const u_char *cp, const u_char *ep, const uint8_t tlv_type) {
+    uint8_t subtype, sublen;
+    const char *sep;
+
+    while (cp < ep) {
+        subtype = *cp++;
+        if(subtype == MESSAGE_SUB_PAD1) {
+            printf(" sub-pad1");
+            continue;
+        }
+        if(cp == ep)
+            goto corrupt;
+        sublen = *cp++;
+        if(cp + sublen > ep)
+            goto corrupt;
+
+        switch(subtype) {
+        case MESSAGE_SUB_PADN:
+            printf(" sub-padn");
+            cp += sublen;
+            break;
+        case MESSAGE_SUB_CHANINFO:
+            printf(" sub-chaninfo");
+            if (sublen == 0) {
+                printf(" empty");
+                break;
+            }
+            sep = " ";
+            while(sublen--) {
+                printf("%s%s", sep, tok2str(chaninfo_str, "%u", *cp++));
+                sep = "-";
+            }
+            if(tlv_type != MESSAGE_UPDATE)
+                printf(" (bogus)");
+            break;
+        default:
+            printf(" sub-unknown-0x%02x", subtype);
+            cp += sublen;
+        } /* switch */
+    } /* while */
+    return;
+
+ corrupt:
+    printf(" (corrupt)");
+}
+
 #define ICHECK(i, l) \
        if ((i) + (l) > bodylen || (i) + (l) > length) goto corrupt;
 
@@ -360,6 +450,9 @@ babel_print_v2(const u_char *cp, u_int length) {
                     else
                         memcpy(v6_prefix, prefix, 16);
                 }
+                /* extra data? */
+                if(rc < len - 10)
+                    subtlvs_print(message + 12 + rc, message + 2 + len, type);
             }
         }
             break;
index 0e1c9af736a156aa19c88b6c44b2713d7b94618b..709f71a5143b8dc9d23523296a9aabe65488b0a8 100644 (file)
@@ -3,12 +3,12 @@ IP6 (hlim 1, next-header UDP (17) payload length: 20) fe80::68d3:1235:d068:1f9e.
 IP6 (hlim 1, next-header UDP (17) payload length: 20) fe80::3428:af91:251:d626.6697 > ff02::1:6.6697: [udp sum ok] babel 2 (8)
        Hello seqno 40102 interval 2000
 IP6 (hlim 1, next-header UDP (17) payload length: 122) fe80::68d3:1235:d068:1f9e.6697 > ff02::1:6.6697: [udp sum ok] babel 2 (110)
-       Update/prefix/id 2001:660:3301:8063:218:84ff:fe1a:615d/128 metric 1 seqno 32272 interval 8000
+       Update/prefix/id 2001:660:3301:8063:218:84ff:fe1a:615d/128 metric 1 seqno 32272 interval 8000 sub-chaninfo 6
        Next Hop 192.168.4.25
-       Update 192.168.4.195/32 metric 1 seqno 32272 interval 8000
-       Update/prefix/id 2001:660:3301:8063:218:f3ff:fea9:914e/128 metric 0 seqno 40149 interval 8000
-       Update ::/0 metric 196 seqno 40149 interval 8000
-       Update 192.168.4.25/32 metric 0 seqno 40149 interval 8000
+       Update 192.168.4.195/32 metric 1 seqno 32272 interval 8000 sub-chaninfo 6
+       Update/prefix/id 2001:660:3301:8063:218:f3ff:fea9:914e/128 metric 0 seqno 40149 interval 8000 sub-chaninfo empty
+       Update ::/0 metric 196 seqno 40149 interval 8000 sub-chaninfo empty
+       Update 192.168.4.25/32 metric 0 seqno 40149 interval 8000 sub-chaninfo empty
 IP6 (hlim 1, next-header UDP (17) payload length: 36) fe80::68d3:1235:d068:1f9e.6697 > ff02::1:6.6697: [udp sum ok] babel 2 (24)
        Hello seqno 8043 interval 2000
        IHU fe80::3428:af91:251:d626 txcost 96 interval 6000
@@ -48,4 +48,4 @@ IP6 (hlim 1, next-header UDP (17) payload length: 40) fe80::68d3:1235:d068:1f9e.
 IP6 (hlim 1, next-header UDP (17) payload length: 44) fe80::3428:af91:251:d626.6697 > ff02::1:6.6697: [udp sum ok] babel 2 (32)
        MH-Request (127 hops) for 2001:660:3301:8063:218:f3ff:fea9:914e/128 seqno 40150 id 02:18:f3:ff:fe:a9:91:4e
 IP6 (hlim 64, next-header UDP (17) payload length: 188) fe80::3428:af91:251:d626.5359 > fe80::68d3:1235:d068:1f9e.5359: [udp sum ok] UDP, length 180
-IP6 (hlim 1, next-header Options (0) payload length: 56) fe80::68d3:1235:d068:1f9e > ff02::16: HBH (rtalert: 0x0000) (padn)[icmp6 sum ok] ICMP6, multicast listener report v2, 2 group record(s) [gaddr ff02::1:6 to_ex, 0 source(s)] [gaddr ff02::cca6:c0f9:e182:5359 to_ex, 0 source(s)]
+IP6 (hlim 1, next-header Options (0) payload length: 56) fe80::68d3:1235:d068:1f9e > ff02::16: HBH (rtalert: 0x0000) (padn) [icmp6 sum ok] ICMP6, multicast listener report v2, 2 group record(s) [gaddr ff02::1:6 to_ex, 0 source(s)] [gaddr ff02::cca6:c0f9:e182:5359 to_ex, 0 source(s)]