From: Denis Ovsienko Date: Fri, 10 May 2013 13:38:58 +0000 (+0400) Subject: initial support for Babel sub-TLVs decoding X-Git-Tag: tcpdump-4.5.0~73^2~14 X-Git-Url: https://git.tcpdump.org/tcpdump/commitdiff_plain/cac189b9e31afe141f8c60c70bc90ce8f595f63d initial support for Babel sub-TLVs decoding 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. --- diff --git a/print-babel.c b/print-babel.c index 8b422b3f..58faca15 100644 --- a/print-babel.c +++ b/print-babel.c @@ -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; diff --git a/tests/babel1v.out b/tests/babel1v.out index 0e1c9af7..709f71a5 100644 --- a/tests/babel1v.out +++ b/tests/babel1v.out @@ -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)]