return;
}
+/* TLVs */
#define MESSAGE_PAD1 0
#define MESSAGE_PADN 1
#define MESSAGE_ACK_REQ 2
#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)
{
#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,
{
unsigned pb;
unsigned char prefix[16];
+ int consumed = 0;
if(plen >= 0)
pb = (plen + 7) / 8;
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))
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
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;
else
memcpy(v6_prefix, prefix, 16);
}
+ /* extra data? */
+ if(rc < len - 10)
+ subtlvs_print(message + 12 + rc, message + 2 + len, type);
}
}
break;
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
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)]