X-Git-Url: https://git.tcpdump.org/tcpdump/blobdiff_plain/78a8be4700cb6003281b47c5b6760b4aafe43220..47fc89d711eec0a073d9b3b293a1af901b5bd791:/print-babel.c diff --git a/print-babel.c b/print-babel.c index 58aa61c9..4f128b32 100644 --- a/print-babel.c +++ b/print-babel.c @@ -39,6 +39,8 @@ #include "interface.h" #include "extract.h" +static const char tstr[] = "[|babel]"; + static void babel_print_v2(const u_char *cp, u_int length); void @@ -66,10 +68,11 @@ babel_print(const u_char *cp, u_int length) { return; trunc: - printf(" [|babel]"); + printf(" %s", tstr); return; } +/* TLVs */ #define MESSAGE_PAD1 0 #define MESSAGE_PADN 1 #define MESSAGE_ACK_REQ 2 @@ -81,8 +84,20 @@ babel_print(const u_char *cp, u_int length) { #define MESSAGE_UPDATE 8 #define MESSAGE_REQUEST 9 #define MESSAGE_MH_REQUEST 10 -#define MESSAGE_PCTS 11 -#define MESSAGE_HD 12 +#define MESSAGE_TSPC 11 +#define MESSAGE_HMAC 12 + +/* sub-TLVs */ +#define MESSAGE_SUB_PAD1 0 +#define MESSAGE_SUB_PADN 1 +#define MESSAGE_SUB_DIVERSITY 2 + +/* Diversity sub-TLV channel codes */ +static const struct tok diversity_str[] = { + { 0, "reserved" }, + { 255, "all" }, + { 0, NULL } +}; static const char * format_id(const u_char *id) @@ -104,7 +119,11 @@ format_prefix(const u_char *prefix, unsigned char plen) if(plen >= 96 && memcmp(prefix, v4prefix, 12) == 0) snprintf(buf, 50, "%s/%u", ipaddr_string(prefix + 12), plen - 96); else +#ifdef INET6 snprintf(buf, 50, "%s/%u", ip6addr_string(prefix), plen); +#else + snprintf(buf, 50, "IPv6 addresses not supported"); +#endif buf[49] = '\0'; return buf; } @@ -115,9 +134,32 @@ format_address(const u_char *prefix) if(memcmp(prefix, v4prefix, 12) == 0) return ipaddr_string(prefix + 12); else +#ifdef INET6 return ip6addr_string(prefix); +#else + return "IPv6 addresses not supported"; +#endif +} + +static const char * +format_interval(const u_int16_t i) +{ + static char buf[sizeof("0000.0s")]; + + if (i == 0) + return "0.0s (bogus)"; + snprintf(buf, sizeof(buf), "%u.%us", i / 10, i % 10); + return buf; } +static const char * +format_interval_update(const u_int16_t i) +{ + return i == 0xFFFF ? "infinity" : format_interval(i); +} + +/* 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, @@ -125,6 +167,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; @@ -148,7 +191,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)) @@ -157,20 +203,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 @@ -180,6 +232,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 Diversity 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 + * Diversity sub-TLV is not the same as a Diversity 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_DIVERSITY: + printf(" sub-diversity"); + if (sublen == 0) { + printf(" empty"); + break; + } + sep = " "; + while(sublen--) { + printf("%s%s", sep, tok2str(diversity_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; @@ -201,26 +318,25 @@ babel_print_v2(const u_char *cp, u_int length) { i = 0; while(i < bodylen) { const u_char *message; - u_char type, len; + u_int type, len; message = cp + 4 + i; + + TCHECK2(*message, 1); + if((type = message[0]) == MESSAGE_PAD1) { + printf(vflag ? "\n\tPad 1" : " pad1"); + i += 1; + continue; + } + TCHECK2(*message, 2); ICHECK(i, 2); - type = message[0]; len = message[1]; TCHECK2(*message, 2 + len); ICHECK(i, 2 + len); switch(type) { - case MESSAGE_PAD1: { - if(!vflag) - printf(" pad1"); - else - printf("\n\tPad 1"); - } - break; - case MESSAGE_PADN: { if(!vflag) printf(" padN"); @@ -238,7 +354,7 @@ babel_print_v2(const u_char *cp, u_int length) { if(len < 6) goto corrupt; nonce = EXTRACT_16BITS(message + 4); interval = EXTRACT_16BITS(message + 6); - printf("%04x %d", nonce, interval); + printf("%04x %s", nonce, format_interval(interval)); } } break; @@ -265,7 +381,7 @@ babel_print_v2(const u_char *cp, u_int length) { if(len < 6) goto corrupt; seqno = EXTRACT_16BITS(message + 4); interval = EXTRACT_16BITS(message + 6); - printf("seqno %u interval %u", seqno, interval); + printf("seqno %u interval %s", seqno, format_interval(interval)); } } break; @@ -282,9 +398,9 @@ babel_print_v2(const u_char *cp, u_int length) { txcost = EXTRACT_16BITS(message + 4); interval = EXTRACT_16BITS(message + 6); rc = network_address(message[2], message + 8, len - 6, address); - if(rc < 0) { printf("[|babel]"); break; } - printf("%s txcost %u interval %d", - format_address(address), txcost, interval); + if(rc < 0) { printf("%s", tstr); break; } + printf("%s txcost %u interval %s", + format_address(address), txcost, format_interval(interval)); } } break; @@ -341,18 +457,21 @@ babel_print_v2(const u_char *cp, u_int length) { interval = EXTRACT_16BITS(message + 6); seqno = EXTRACT_16BITS(message + 8); metric = EXTRACT_16BITS(message + 10); - printf("%s%s%s %s metric %u seqno %u interval %u", + printf("%s%s%s %s metric %u seqno %u interval %s", (message[3] & 0x80) ? "/prefix": "", (message[3] & 0x40) ? "/id" : "", (message[3] & 0x3f) ? "/unknown" : "", format_prefix(prefix, plen), - metric, seqno, interval); + metric, seqno, format_interval_update(interval)); if(message[3] & 0x80) { if(message[2] == 1) memcpy(v4_prefix, prefix, 16); else memcpy(v6_prefix, prefix, 16); } + /* extra data? */ + if((u_int)rc < len - 10) + subtlvs_print(message + 12 + rc, message + 2 + len, type); } } break; @@ -396,27 +515,26 @@ babel_print_v2(const u_char *cp, u_int length) { } } break; - case MESSAGE_PCTS : + case MESSAGE_TSPC : if(!vflag) - printf(" pcts"); + printf(" tspc"); else { - printf("\n\tPC/TS "); - if(len != 6) goto corrupt; - printf("packet counter %u timestamp %u", EXTRACT_16BITS(message + 2), - EXTRACT_32BITS (message + 4)); + printf("\n\tTS/PC "); + if(len < 6) goto corrupt; + printf("timestamp %u packetcounter %u", EXTRACT_32BITS (message + 4), + EXTRACT_16BITS(message + 2)); } break; - case MESSAGE_HD : { + case MESSAGE_HMAC : { if(!vflag) - printf(" hd"); + printf(" hmac"); else { - unsigned i; - printf("\n\tHash Digest "); + unsigned j; + printf("\n\tHMAC "); if(len < 18) goto corrupt; - printf("key ID %u digest-%u '", EXTRACT_16BITS(message + 2), len - 2); - for (i = 0; i < len - 2; i++) - printf ("%02X", message[4 + i]); - printf("'"); + printf("key-id %u digest-%u ", EXTRACT_16BITS(message + 2), len - 2); + for (j = 0; j < len - 2; j++) + printf ("%02X", message[4 + j]); } } break; @@ -431,7 +549,7 @@ babel_print_v2(const u_char *cp, u_int length) { return; trunc: - printf(" [|babel]"); + printf(" %s", tstr); return; corrupt: