X-Git-Url: https://git.tcpdump.org/tcpdump/blobdiff_plain/407fe834e6ed12ed0002705d4faca912104a43ed..refs/pull/1034/head:/print-802_15_4.c diff --git a/print-802_15_4.c b/print-802_15_4.c index 3e1bc8a8..1895be7c 100644 --- a/print-802_15_4.c +++ b/print-802_15_4.c @@ -26,8 +26,9 @@ #include #endif -#include +#include "netdissect-stdinc.h" +#define ND_LONGJMP_FROM_TCHECK #include "netdissect.h" #include "addrtoname.h" @@ -256,7 +257,7 @@ static const char *p_mlme_short_names[] = { "CTM IE", /* 0x32 */ "Timestamp IE", /* 0x33 */ "Timestamp Difference IE", /* 0x34 */ - "TMCTP Sepcification IE", /* 0x35 */ + "TMCTP Specification IE", /* 0x35 */ "RCC PHY Operating Mode IE", /* 0x36 */ "Reserved 0x37", /* 0x37 */ "Reserved 0x38", /* 0x38 */ @@ -419,19 +420,20 @@ static const char *mac_c_names[] = { /* * IEEE 802.15.4 CRC 16 function. This is using CCITT polynomical of 0x1021, * but the initial value is 0, and the bits are reversed for both in and out. - * See secton 7.2.10 of 802.15.4-2015 for more information. + * See section 7.2.10 of 802.15.4-2015 for more information. */ static uint16_t -ieee802_15_4_crc16(const u_char *p, - uint16_t data_len) +ieee802_15_4_crc16(netdissect_options *ndo, const u_char *p, + u_int data_len) { uint16_t crc; u_char x, y; - + crc = 0x0000; /* Note, initial value is 0x0000 not 0xffff. */ - - while (data_len--){ - y = *p++; + + while (data_len != 0){ + y = GET_U_1(p); + p++; /* Reverse bits on input */ y = (((y & 0xaa) >> 1) | ((y & 0x55) << 1)); y = (((y & 0xcc) >> 2) | ((y & 0x33) << 2)); @@ -439,10 +441,11 @@ ieee802_15_4_crc16(const u_char *p, /* Update CRC */ x = crc >> 8 ^ y; x ^= x >> 4; - crc = (crc << 8) ^ - ((unsigned short)(x << 12)) ^ - ((unsigned short)(x <<5)) ^ - ((unsigned short)x); + crc = ((uint16_t)(crc << 8)) ^ + ((uint16_t)(x << 12)) ^ + ((uint16_t)(x << 5)) ^ + ((uint16_t)x); + data_len--; } /* Reverse bits on output */ crc = (((crc & 0xaaaa) >> 1) | ((crc & 0x5555) << 1)); @@ -469,20 +472,20 @@ ieee802_15_4_reverse32(uint32_t x) /* * IEEE 802.15.4 CRC 32 function. This is using ANSI X3.66-1979 polynomical of * 0x04C11DB7, but the initial value is 0, and the bits are reversed for both - * in and out. See secton 7.2.10 of 802.15.4-2015 for more information. + * in and out. See section 7.2.10 of 802.15.4-2015 for more information. */ static uint32_t -ieee802_15_4_crc32(const u_char *p, - uint16_t data_len) +ieee802_15_4_crc32(netdissect_options *ndo, const u_char *p, + u_int data_len) { uint32_t crc, byte; - u_char x; int b; - + crc = 0x00000000; /* Note, initial value is 0x00000000 not 0xffffffff */ - - while (data_len--){ - byte = *p++; + + while (data_len != 0){ + byte = GET_U_1(p); + p++; /* Reverse bits on input */ byte = ieee802_15_4_reverse32(byte); /* Update CRC */ @@ -493,6 +496,7 @@ ieee802_15_4_crc32(const u_char *p, crc = crc << 1; byte = byte << 1; } + data_len--; } /* Reverse bits on output */ crc = ieee802_15_4_reverse32(crc); @@ -539,13 +543,12 @@ ieee802_15_4_print_addr(netdissect_options *ndo, const u_char *p, ND_PRINT("none"); break; case 2: - ND_PRINT("%04x", EXTRACT_LE_U_2(p)); + ND_PRINT("%04x", GET_LE_U_2(p)); break; case 8: - ND_PRINT("%s", le64addr_string(ndo, p)); + ND_PRINT("%s", GET_LE64ADDR_STRING(p)); break; } - return; } /* @@ -566,7 +569,7 @@ ieee802_15_4_print_superframe_specification(netdissect_options *ndo, ((ss >> 8) & 0xf)); if (CHECK_BIT(ss, 12)) { ND_PRINT(", BLE enabled"); } if (CHECK_BIT(ss, 14)) { ND_PRINT(", PAN Coordinator"); } - if (CHECK_BIT(ss, 15)) { ND_PRINT(", Assocation Permit"); } + if (CHECK_BIT(ss, 15)) { ND_PRINT(", Association Permit"); } } /* @@ -578,14 +581,15 @@ ieee802_15_4_print_superframe_specification(netdissect_options *ndo, static int ieee802_15_4_print_gts_info(netdissect_options *ndo, const u_char *p, - uint16_t data_len) + u_int data_len) { uint8_t gts_spec, gts_cnt; - int len, i; - - gts_spec = EXTRACT_U_1(p); + u_int len; + int i; + + gts_spec = GET_U_1(p); gts_cnt = gts_spec & 0x7; - + if (gts_cnt == 0) { if (ndo->ndo_vflag > 0) { ND_PRINT("\n\tGTS Descriptor Count = %d, ", gts_cnt); @@ -593,7 +597,7 @@ ieee802_15_4_print_gts_info(netdissect_options *ndo, return 1; } len = 1 + 1 + gts_cnt * 3; - + if (data_len < len) { ND_PRINT(" [ERROR: Truncated GTS Info List]"); return -1; @@ -603,14 +607,14 @@ ieee802_15_4_print_gts_info(netdissect_options *ndo, } ND_PRINT("GTS Descriptor Count = %d, ", gts_cnt); ND_PRINT("GTS Directions Mask = %02x, [ ", - EXTRACT_U_1(p + 1) & 0x7f); - + GET_U_1(p + 1) & 0x7f); + for(i = 0; i < gts_cnt; i++) { ND_PRINT("[ "); ieee802_15_4_print_addr(ndo, p + 2 + i * 3, 2); ND_PRINT(", Start slot = %d, Length = %d ] ", - EXTRACT_U_1(p + 2 + i * 3 + 1) & 0x0f, - (EXTRACT_U_1(p + 2 + i * 3 + 1) >> 4) & 0x0f); + GET_U_1(p + 2 + i * 3 + 1) & 0x0f, + (GET_U_1(p + 2 + i * 3 + 1) >> 4) & 0x0f); } ND_PRINT("]"); return len; @@ -625,11 +629,11 @@ ieee802_15_4_print_gts_info(netdissect_options *ndo, static int16_t ieee802_15_4_print_pending_addresses(netdissect_options *ndo, const u_char *p, - uint16_t data_len) + u_int data_len) { uint8_t pas, s_cnt, e_cnt, len, i; - - pas = EXTRACT_U_1(p); + + pas = GET_U_1(p); s_cnt = pas & 0x7; e_cnt = (pas >> 4) & 0x7; len = 1 + s_cnt * 2 + e_cnt * 8; @@ -653,11 +657,11 @@ ieee802_15_4_print_pending_addresses(netdissect_options *ndo, } ND_PRINT("]"); } - if (s_cnt != 0) { + if (e_cnt != 0) { ND_PRINT(", Extended address list = [ "); for(i = 0; i < e_cnt; i++) { ieee802_15_4_print_addr(ndo, p + 1 + s_cnt * 2 + - e_cnt * 8, 8); + i * 8, 8); ND_PRINT(" "); } ND_PRINT("]"); @@ -675,17 +679,17 @@ ieee802_15_4_print_header_ie(netdissect_options *ndo, int element_id) { int i; - + switch (element_id) { case 0x00: /* Vendor Specific Header IE */ if (ie_len < 3) { ND_PRINT("[ERROR: Vendor OUI missing]"); } else { - ND_PRINT("OUI = 0x%02x%02x%02x, ", EXTRACT_U_1(p), - EXTRACT_U_1(p + 1), EXTRACT_U_1(p + 2)); + ND_PRINT("OUI = 0x%02x%02x%02x, ", GET_U_1(p), + GET_U_1(p + 1), GET_U_1(p + 2)); ND_PRINT("Data = "); for(i = 3; i < ie_len; i++) { - ND_PRINT("%02x ", EXTRACT_U_1(p + i)); + ND_PRINT("%02x ", GET_U_1(p + i)); } } break; @@ -694,10 +698,10 @@ ieee802_15_4_print_header_ie(netdissect_options *ndo, ND_PRINT("[ERROR: Truncated CSL IE]"); } else { ND_PRINT("CSL Phase = %d, CSL Period = %d", - EXTRACT_LE_U_2(p), EXTRACT_LE_U_2(p + 2)); + GET_LE_U_2(p), GET_LE_U_2(p + 2)); if (ie_len >= 6) { ND_PRINT(", Rendezvous time = %d", - EXTRACT_LE_U_2(p + 4)); + GET_LE_U_2(p + 4)); } if (ie_len != 4 && ie_len != 6) { ND_PRINT(" [ERROR: CSL IE length wrong]"); @@ -709,23 +713,24 @@ ieee802_15_4_print_header_ie(netdissect_options *ndo, ND_PRINT("[ERROR: Truncated RIT IE]"); } else { ND_PRINT("Time to First Listen = %d, # of Repeat Listen = %d, Repeat Listen Interval = %d", - EXTRACT_U_1(p), - EXTRACT_U_1(p + 1), - EXTRACT_LE_U_2(p + 2)); + GET_U_1(p), + GET_U_1(p + 1), + GET_LE_U_2(p + 2)); } break; case 0x1c: /* DSME PAN Descriptor IE */ /*FALLTHROUGH*/ - case 0x21: /* Extended DSME PAN descriptior IE */ + case 0x21: /* Extended DSME PAN descriptor IE */ if (ie_len < 2) { ND_PRINT("[ERROR: Truncated DSME PAN IE]"); } else { - uint16_t ss, ptr, len; + uint16_t ss, ptr, ulen; + int16_t len; int hopping_present; - + hopping_present = 0; - - ss = EXTRACT_LE_U_2(p); + + ss = GET_LE_U_2(p); ieee802_15_4_print_superframe_specification(ndo, ss); if (ie_len < 3) { ND_PRINT("[ERROR: Truncated before pending addresses field]"); @@ -740,14 +745,14 @@ ieee802_15_4_print_header_ie(netdissect_options *ndo, break; } ptr += len; - + if (element_id == 0x21) { /* Extended version. */ if (ie_len < ptr + 2) { ND_PRINT("[ERROR: Truncated before DSME Superframe Specification]"); break; } - ss = EXTRACT_LE_U_2(p + ptr); + ss = GET_LE_U_2(p + ptr); ptr += 2; ND_PRINT("Multi-superframe Order = %d", ss & 0xff); ND_PRINT(", %s", ((ss & 0x100) ? @@ -768,7 +773,7 @@ ieee802_15_4_print_header_ie(netdissect_options *ndo, ND_PRINT("[ERROR: Truncated before DSME Superframe Specification]"); break; } - ss = EXTRACT_U_1(p + ptr); + ss = GET_U_1(p + ptr); ptr++; ND_PRINT("Multi-superframe Order = %d", ss & 0x0f); @@ -783,76 +788,77 @@ ieee802_15_4_print_header_ie(netdissect_options *ndo, } } if (ie_len < ptr + 8) { - ND_PRINT(" [ERROR: Truncated before Time syncronization specification]"); + ND_PRINT(" [ERROR: Truncated before Time synchronization specification]"); break; } ND_PRINT("Beacon timestamp = %" PRIu64 ", offset = %d", - EXTRACT_LE_U_6(p + ptr), - EXTRACT_LE_U_2(p + ptr + 6)); + GET_LE_U_6(p + ptr), + GET_LE_U_2(p + ptr + 6)); ptr += 8; if (ie_len < ptr + 4) { ND_PRINT(" [ERROR: Truncated before Beacon Bitmap]"); break; } - - len = EXTRACT_LE_U_2(p + ptr + 2); + + ulen = GET_LE_U_2(p + ptr + 2); ND_PRINT("SD Index = %d, Bitmap len = %d, ", - EXTRACT_LE_U_2(p + ptr), len); + GET_LE_U_2(p + ptr), ulen); ptr += 4; - if (ie_len < ptr + len) { + if (ie_len < ptr + ulen) { ND_PRINT(" [ERROR: Truncated in SD bitmap]"); break; } ND_PRINT(" SD Bitmap = "); - for(i = 0; i < len; i++) { - ND_PRINT("%02x ", EXTRACT_U_1(p + ptr + i)); + for(i = 0; i < ulen; i++) { + ND_PRINT("%02x ", GET_U_1(p + ptr + i)); } - ptr += len; - + ptr += ulen; + if (ie_len < ptr + 5) { ND_PRINT(" [ERROR: Truncated before Channel hopping specification]"); break; } - - len = EXTRACT_LE_U_2(p + ptr + 4); + + ulen = GET_LE_U_2(p + ptr + 4); ND_PRINT("Hopping Seq ID = %d, PAN Coordinator BSN = %d, " "Channel offset = %d, Bitmap length = %d, ", - EXTRACT_U_1(p + ptr), - EXTRACT_U_1(p + ptr + 1), - EXTRACT_LE_U_2(p + ptr + 2), - len); + GET_U_1(p + ptr), + GET_U_1(p + ptr + 1), + GET_LE_U_2(p + ptr + 2), + ulen); ptr += 5; - if (ie_len < ptr + len) { + if (ie_len < ptr + ulen) { ND_PRINT(" [ERROR: Truncated in Channel offset bitmap]"); break; } ND_PRINT(" Channel offset bitmap = "); - for(i = 0; i < len; i++) { - ND_PRINT("%02x ", EXTRACT_U_1(p + ptr + i)); + for(i = 0; i < ulen; i++) { + ND_PRINT("%02x ", GET_U_1(p + ptr + i)); } - ptr += len; + ptr += ulen; if (hopping_present) { if (ie_len < ptr + 1) { ND_PRINT(" [ERROR: Truncated in Hopping Sequence length]"); break; } - len = EXTRACT_U_1(p + ptr); + ulen = GET_U_1(p + ptr); ptr++; - ND_PRINT("Hopping Seq length = %d [ ", len); - + ND_PRINT("Hopping Seq length = %d [ ", ulen); + /* The specification is not clear how the hopping sequence is encoded, I assume two octet unsigned integers for each channel. */ - - if (ie_len < ptr + len * 2) { + + if (ie_len < ptr + ulen * 2) { ND_PRINT(" [ERROR: Truncated in Channel offset bitmap]"); break; } - for(i = 0; i < len; i++) { - ND_PRINT("%02x ", EXTRACT_LE_U_2(p + ptr + i * 2)); + for(i = 0; i < ulen; i++) { + ND_PRINT("%02x ", + GET_LE_U_2(p + ptr + i * 2)); } ND_PRINT("]"); - ptr += len * 2; + ptr += ulen * 2; } } break; @@ -861,9 +867,9 @@ ieee802_15_4_print_header_ie(netdissect_options *ndo, ND_PRINT("[ERROR: Length != 2]"); } else { uint16_t r_time, w_u_interval; - r_time = EXTRACT_LE_U_2(p); - w_u_interval = EXTRACT_LE_U_2(p + 2); - + r_time = GET_LE_U_2(p); + w_u_interval = GET_LE_U_2(p + 2); + ND_PRINT("Rendezvous time = %d, Wake-up Interval = %d", r_time, w_u_interval); } @@ -874,18 +880,18 @@ ieee802_15_4_print_header_ie(netdissect_options *ndo, } else { uint16_t val; int16_t timecorr; - - val = EXTRACT_LE_U_2(p); + + val = GET_LE_U_2(p); if (val & 0x8000) { ND_PRINT("Negative "); } val &= 0xfff; val <<= 4; timecorr = val; timecorr >>= 4; - + ND_PRINT("Ack time correction = %d, ", timecorr); } break; - case 0x22: /* Frament Sequence Content Description IE */ + case 0x22: /* Fragment Sequence Content Description IE */ /* XXX Not implemented */ case 0x23: /* Simplified Superframe Specification IE */ /* XXX Not implemented */ @@ -906,7 +912,7 @@ ieee802_15_4_print_header_ie(netdissect_options *ndo, default: ND_PRINT("IE Data = "); for(i = 0; i < ie_len; i++) { - ND_PRINT("%02x ", EXTRACT_U_1(p + i)); + ND_PRINT("%02x ", GET_U_1(p + i)); } break; } @@ -921,12 +927,12 @@ ieee802_15_4_print_header_ie(netdissect_options *ndo, static int ieee802_15_4_print_header_ie_list(netdissect_options *ndo, const u_char *p, - uint16_t caplen, + u_int caplen, int *payload_ie_present) { int len, ie, element_id, i; uint16_t ie_len; - + *payload_ie_present = 0; len = 0; do { @@ -935,7 +941,7 @@ ieee802_15_4_print_header_ie_list(netdissect_options *ndo, return -1; } /* Extract IE Header */ - ie = EXTRACT_LE_U_2(p); + ie = GET_LE_U_2(p); if (CHECK_BIT(ie, 15)) { ND_PRINT("[ERROR: Header IE with type 1] "); } @@ -953,13 +959,13 @@ ieee802_15_4_print_header_ie_list(netdissect_options *ndo, h_ie_names[element_id], ie_len); } } - if (caplen < ie_len) { + if (caplen < 2U + ie_len) { ND_PRINT("[ERROR: Truncated IE data]"); return -1; } /* Skip header */ p += 2; - + /* Parse and print content. */ if (ndo->ndo_vflag > 3 && ie_len != 0) { ieee802_15_4_print_header_ie(ndo, p, @@ -968,7 +974,7 @@ ieee802_15_4_print_header_ie_list(netdissect_options *ndo, if (ie_len != 0) { ND_PRINT("IE Data = "); for(i = 0; i < ie_len; i++) { - ND_PRINT("%02x ", EXTRACT_U_1(p + i)); + ND_PRINT("%02x ", GET_U_1(p + i)); } } } @@ -983,7 +989,7 @@ ieee802_15_4_print_header_ie_list(netdissect_options *ndo, if (element_id == 0x7f) { break; } - } while (caplen > 0); + } while (caplen != 0); return len; } @@ -996,8 +1002,9 @@ ieee802_15_4_print_mlme_ie(netdissect_options *ndo, uint16_t sub_ie_len, int sub_id) { - int i, j, len; - + int i, j; + uint16_t len; + /* Note, as there is no overlap with the long and short MLME sub IDs, we can just use one switch here. */ switch (sub_id) { @@ -1006,12 +1013,12 @@ ieee802_15_4_print_mlme_ie(netdissect_options *ndo, ND_PRINT("[ERROR: Vendor OUI missing]"); } else { ND_PRINT("OUI = 0x%02x%02x%02x, ", - EXTRACT_U_1(p), - EXTRACT_U_1(p + 1), - EXTRACT_U_1(p + 2)); + GET_U_1(p), + GET_U_1(p + 1), + GET_U_1(p + 2)); ND_PRINT("Data = "); for(i = 3; i < sub_ie_len; i++) { - ND_PRINT("%02x ", EXTRACT_U_1(p + i)); + ND_PRINT("%02x ", GET_U_1(p + i)); } } break; @@ -1019,25 +1026,25 @@ ieee802_15_4_print_mlme_ie(netdissect_options *ndo, if (sub_ie_len < 1) { ND_PRINT("[ERROR: Hopping sequence ID missing]"); } else if (sub_ie_len == 1) { - ND_PRINT("Hopping Sequence ID = %d", EXTRACT_U_1(p)); + ND_PRINT("Hopping Sequence ID = %d", GET_U_1(p)); p++; sub_ie_len--; } else { - int channel_page, number_of_channels; - - ND_PRINT("Hopping Sequence ID = %d", EXTRACT_U_1(p)); + uint16_t channel_page, number_of_channels; + + ND_PRINT("Hopping Sequence ID = %d", GET_U_1(p)); p++; sub_ie_len--; if (sub_ie_len < 7) { ND_PRINT("[ERROR: IE truncated]"); break; } - channel_page = EXTRACT_U_1(p); - number_of_channels = EXTRACT_LE_U_2(p + 1); + channel_page = GET_U_1(p); + number_of_channels = GET_LE_U_2(p + 1); ND_PRINT("Channel Page = %d, Number of Channels = %d, ", channel_page, number_of_channels); ND_PRINT("Phy Configuration = 0x%08x, ", - EXTRACT_LE_U_4(p + 3)); + GET_LE_U_4(p + 3)); p += 7; sub_ie_len -= 7; if (channel_page == 9 || channel_page == 10) { @@ -1048,7 +1055,7 @@ ieee802_15_4_print_mlme_ie(netdissect_options *ndo, } ND_PRINT("Extended bitmap = 0x"); for(i = 0; i < len; i++) { - ND_PRINT("%02x", EXTRACT_U_1(p + i)); + ND_PRINT("%02x", GET_U_1(p + i)); } ND_PRINT(", "); p += len; @@ -1058,17 +1065,17 @@ ieee802_15_4_print_mlme_ie(netdissect_options *ndo, ND_PRINT("[ERROR: IE truncated]"); break; } - len = EXTRACT_LE_U_2(p); + len = GET_LE_U_2(p); p += 2; sub_ie_len -= 2; ND_PRINT("Hopping Seq length = %d [ ", len); - + if (sub_ie_len < len * 2) { ND_PRINT(" [ERROR: IE truncated]"); break; } for(i = 0; i < len; i++) { - ND_PRINT("%02x ", EXTRACT_LE_U_2(p + i * 2)); + ND_PRINT("%02x ", GET_LE_U_2(p + i * 2)); } ND_PRINT("]"); p += len * 2; @@ -1077,26 +1084,26 @@ ieee802_15_4_print_mlme_ie(netdissect_options *ndo, ND_PRINT("[ERROR: IE truncated]"); break; } - ND_PRINT("Current hop = %d", EXTRACT_LE_U_2(p)); + ND_PRINT("Current hop = %d", GET_LE_U_2(p)); } - + break; - case 0x1a: /* TSCH Syncronization IE. */ + case 0x1a: /* TSCH Synchronization IE. */ if (sub_ie_len < 6) { ND_PRINT("[ERROR: Length != 6]"); } ND_PRINT("ASN = %010" PRIx64 ", Join Metric = %d ", - EXTRACT_LE_U_5(p), EXTRACT_U_1(p + 5)); + GET_LE_U_5(p), GET_U_1(p + 5)); break; case 0x1b: /* TSCH Slotframe and Link IE. */ { int sf_num, off, links, opts; - + if (sub_ie_len < 1) { ND_PRINT("[ERROR: Truncated IE]"); break; } - sf_num = EXTRACT_U_1(p); + sf_num = GET_U_1(p); ND_PRINT("Slotframes = %d ", sf_num); off = 1; for(i = 0; i < sf_num; i++) { @@ -1104,10 +1111,10 @@ ieee802_15_4_print_mlme_ie(netdissect_options *ndo, ND_PRINT("[ERROR: Truncated IE before slotframes]"); break; } - links = EXTRACT_U_1(p + off + 3); + links = GET_U_1(p + off + 3); ND_PRINT("\n\t\t\t[ Handle %d, size = %d, links = %d ", - EXTRACT_U_1(p + off), - EXTRACT_LE_U_2(p + off + 1), + GET_U_1(p + off), + GET_LE_U_2(p + off + 1), links); off += 4; for(j = 0; j < links; j++) { @@ -1115,10 +1122,10 @@ ieee802_15_4_print_mlme_ie(netdissect_options *ndo, ND_PRINT("[ERROR: Truncated IE links]"); break; } - opts = EXTRACT_U_1(p + off + 4); + opts = GET_U_1(p + off + 4); ND_PRINT("\n\t\t\t\t[ Timeslot = %d, Offset = %d, Options = ", - EXTRACT_LE_U_2(p + off), - EXTRACT_LE_U_2(p + off + 2)); + GET_LE_U_2(p + off), + GET_LE_U_2(p + off + 2)); if (opts & 0x1) { ND_PRINT("TX "); } if (opts & 0x2) { ND_PRINT("RX "); } if (opts & 0x4) { ND_PRINT("Shared "); } @@ -1137,42 +1144,42 @@ ieee802_15_4_print_mlme_ie(netdissect_options *ndo, break; case 0x1c: /* TSCH Timeslot IE. */ if (sub_ie_len == 1) { - ND_PRINT("Time slot ID = %d ", EXTRACT_U_1(p)); + ND_PRINT("Time slot ID = %d ", GET_U_1(p)); } else if (sub_ie_len == 25) { ND_PRINT("Time slot ID = %d, CCA Offset = %d, CCA = %d, TX Offset = %d, RX Offset = %d, RX Ack Delay = %d, TX Ack Delay = %d, RX Wait = %d, Ack Wait = %d, RX TX = %d, Max Ack = %d, Max TX = %d, Time slot Length = %d ", - EXTRACT_U_1(p), - EXTRACT_LE_U_2(p + 1), - EXTRACT_LE_U_2(p + 3), - EXTRACT_LE_U_2(p + 5), - EXTRACT_LE_U_2(p + 7), - EXTRACT_LE_U_2(p + 9), - EXTRACT_LE_U_2(p + 11), - EXTRACT_LE_U_2(p + 13), - EXTRACT_LE_U_2(p + 15), - EXTRACT_LE_U_2(p + 17), - EXTRACT_LE_U_2(p + 19), - EXTRACT_LE_U_2(p + 21), - EXTRACT_LE_U_2(p + 23)); + GET_U_1(p), + GET_LE_U_2(p + 1), + GET_LE_U_2(p + 3), + GET_LE_U_2(p + 5), + GET_LE_U_2(p + 7), + GET_LE_U_2(p + 9), + GET_LE_U_2(p + 11), + GET_LE_U_2(p + 13), + GET_LE_U_2(p + 15), + GET_LE_U_2(p + 17), + GET_LE_U_2(p + 19), + GET_LE_U_2(p + 21), + GET_LE_U_2(p + 23)); } else if (sub_ie_len == 27) { ND_PRINT("Time slot ID = %d, CCA Offset = %d, CCA = %d, TX Offset = %d, RX Offset = %d, RX Ack Delay = %d, TX Ack Delay = %d, RX Wait = %d, Ack Wait = %d, RX TX = %d, Max Ack = %d, Max TX = %d, Time slot Length = %d ", - EXTRACT_U_1(p), - EXTRACT_LE_U_2(p + 1), - EXTRACT_LE_U_2(p + 3), - EXTRACT_LE_U_2(p + 5), - EXTRACT_LE_U_2(p + 7), - EXTRACT_LE_U_2(p + 9), - EXTRACT_LE_U_2(p + 11), - EXTRACT_LE_U_2(p + 13), - EXTRACT_LE_U_2(p + 15), - EXTRACT_LE_U_2(p + 17), - EXTRACT_LE_U_2(p + 19), - EXTRACT_LE_U_3(p + 21), - EXTRACT_LE_U_3(p + 24)); + GET_U_1(p), + GET_LE_U_2(p + 1), + GET_LE_U_2(p + 3), + GET_LE_U_2(p + 5), + GET_LE_U_2(p + 7), + GET_LE_U_2(p + 9), + GET_LE_U_2(p + 11), + GET_LE_U_2(p + 13), + GET_LE_U_2(p + 15), + GET_LE_U_2(p + 17), + GET_LE_U_2(p + 19), + GET_LE_U_3(p + 21), + GET_LE_U_3(p + 24)); } else { ND_PRINT("[ERROR: Length not 1, 25, or 27]"); ND_PRINT("\n\t\t\tIE Data = "); for(i = 0; i < sub_ie_len; i++) { - ND_PRINT("%02x ", EXTRACT_U_1(p + i)); + ND_PRINT("%02x ", GET_U_1(p + i)); } } break; @@ -1206,7 +1213,7 @@ ieee802_15_4_print_mlme_ie(netdissect_options *ndo, /* XXX Not implemented */ case 0x2c: /* TVWS Device Capabilities IE */ /* XXX Not implemented */ - case 0x2d: /* TVWS Device Catagory IE */ + case 0x2d: /* TVWS Device Category IE */ /* XXX Not implemented */ case 0x2e: /* TVWS Device Identification IE */ /* XXX Not implemented */ @@ -1229,7 +1236,7 @@ ieee802_15_4_print_mlme_ie(netdissect_options *ndo, default: ND_PRINT("IE Data = "); for(i = 0; i < sub_ie_len; i++) { - ND_PRINT("%02x ", EXTRACT_U_1(p + i)); + ND_PRINT("%02x ", GET_U_1(p + i)); } break; } @@ -1246,14 +1253,14 @@ ieee802_15_4_print_mlme_ie_list(netdissect_options *ndo, { int ie, sub_id, i, type; uint16_t sub_ie_len; - + do { if (ie_len < 2) { ND_PRINT("[ERROR: Truncated MLME IE]"); return; } /* Extract IE header */ - ie = EXTRACT_LE_U_2(p); + ie = GET_LE_U_2(p); type = CHECK_BIT(ie, 15); if (type) { /* Long type */ @@ -1263,10 +1270,10 @@ ieee802_15_4_print_mlme_ie_list(netdissect_options *ndo, sub_ie_len = ie & 0xff; sub_id = (ie >> 8) & 0x7f; } - + /* Skip the IE header */ p += 2; - + if (type == 0) { ND_PRINT("\n\t\t%s [ length = %d, ", p_mlme_short_names[sub_id], sub_ie_len); @@ -1274,8 +1281,8 @@ ieee802_15_4_print_mlme_ie_list(netdissect_options *ndo, ND_PRINT("\n\t\t%s [ length = %d, ", p_mlme_long_names[sub_id], sub_ie_len); } - - if (ie_len < sub_ie_len) { + + if (ie_len < 2 + sub_ie_len) { ND_PRINT("[ERROR: Truncated IE data]"); return; } @@ -1285,7 +1292,7 @@ ieee802_15_4_print_mlme_ie_list(netdissect_options *ndo, } else if (ndo->ndo_vflag > 2) { ND_PRINT("IE Data = "); for(i = 0; i < sub_ie_len; i++) { - ND_PRINT("%02x ", EXTRACT_U_1(p + i)); + ND_PRINT("%02x ", GET_U_1(p + i)); } } } @@ -1293,7 +1300,6 @@ ieee802_15_4_print_mlme_ie_list(netdissect_options *ndo, p += sub_ie_len; ie_len -= 2 + sub_ie_len; } while (ie_len > 0); - return; } /* @@ -1315,9 +1321,9 @@ ieee802_15_4_print_mpx_ie(netdissect_options *ndo, ND_PRINT("[ERROR: Transaction control byte missing]"); return; } - - transfer_type = EXTRACT_U_1(p) & 0x7; - tid = EXTRACT_U_1(p) >> 3; + + transfer_type = GET_U_1(p) & 0x7; + tid = GET_U_1(p) >> 3; switch (transfer_type) { case 0x00: /* Full upper layer frame. */ case 0x01: /* Full upper layer frame with small Multiplex ID. */ @@ -1328,10 +1334,10 @@ ieee802_15_4_print_mpx_ie(netdissect_options *ndo, if (ie_len < 3) { ND_PRINT("[ERROR: Multiplex ID missing]"); return; - } + } data_start = 3; ND_PRINT("tid = 0x%02x, Multiplex ID = 0x%04x, ", - tid, EXTRACT_LE_U_2(p + 1)); + tid, GET_LE_U_2(p + 1)); } else { data_start = 1; ND_PRINT("Multiplex ID = 0x%04x, ", tid); @@ -1343,8 +1349,8 @@ ieee802_15_4_print_mpx_ie(netdissect_options *ndo, ND_PRINT("[ERROR: fragment number missing]"); return; } - - fragment_number = EXTRACT_U_1(p + 1); + + fragment_number = GET_U_1(p + 1); ND_PRINT("Type = %s, tid = 0x%02x, fragment = 0x%02x, ", (transfer_type == 0x02 ? (fragment_number == 0 ? @@ -1354,13 +1360,13 @@ ieee802_15_4_print_mpx_ie(netdissect_options *ndo, data_start = 2; if (fragment_number == 0) { int total_size, multiplex_id; - + if (ie_len < 6) { ND_PRINT("[ERROR: Total upper layer size or multiplex ID missing]"); return; } - total_size = EXTRACT_LE_U_2(p + 2); - multiplex_id = EXTRACT_LE_U_2(p + 4); + total_size = GET_LE_U_2(p + 2); + multiplex_id = GET_LE_U_2(p + 4); ND_PRINT("Total upper layer size = 0x%04x, Multiplex ID = 0x%04x, ", total_size, multiplex_id); data_start = 6; @@ -1372,13 +1378,13 @@ ieee802_15_4_print_mpx_ie(netdissect_options *ndo, tid); } else if (ie_len == 3) { ND_PRINT("Type = Abort, tid = 0x%02x, max size = 0x%04x", - tid, EXTRACT_LE_U_2(p + 1)); + tid, GET_LE_U_2(p + 1)); } else { ND_PRINT("Type = Abort, tid = 0x%02x, invalid length = %d (not 1 or 3)", tid, ie_len); ND_PRINT("Abort data = "); for(i = 1; i < ie_len; i++) { - ND_PRINT("%02x ", EXTRACT_U_1(p + i)); + ND_PRINT("%02x ", GET_U_1(p + i)); } } return; @@ -1395,7 +1401,7 @@ ieee802_15_4_print_mpx_ie(netdissect_options *ndo, ND_PRINT("Upper layer data = "); for(i = data_start; i < ie_len; i++) { - ND_PRINT("%02x ", EXTRACT_U_1(p + i)); + ND_PRINT("%02x ", GET_U_1(p + i)); } } @@ -1408,11 +1414,11 @@ ieee802_15_4_print_mpx_ie(netdissect_options *ndo, static int ieee802_15_4_print_payload_ie_list(netdissect_options *ndo, const u_char *p, - uint16_t caplen) + u_int caplen) { int len, ie, group_id, i; uint16_t ie_len; - + len = 0; do { if (caplen < 2) { @@ -1420,13 +1426,13 @@ ieee802_15_4_print_payload_ie_list(netdissect_options *ndo, return -1; } /* Extract IE header */ - ie = EXTRACT_LE_U_2(p); + ie = GET_LE_U_2(p); if ((CHECK_BIT(ie, 15)) == 0) { ND_PRINT("[ERROR: Payload IE with type 0] "); } ie_len = ie & 0x3ff; group_id = (ie >> 11) & 0x0f; - + /* Skip the IE header */ p += 2; if (ie_len == 0) { @@ -1435,7 +1441,7 @@ ieee802_15_4_print_payload_ie_list(netdissect_options *ndo, ND_PRINT("\n\t%s [ length = %d, ", p_ie_names[group_id], ie_len); } - if (caplen < ie_len) { + if (caplen < 2U + ie_len) { ND_PRINT("[ERROR: Truncated IE data]"); return -1; } @@ -1449,13 +1455,13 @@ ieee802_15_4_print_payload_ie_list(netdissect_options *ndo, ND_PRINT("[ERROR: Vendor OUI missing]"); } else { ND_PRINT("OUI = 0x%02x%02x%02x, ", - EXTRACT_U_1(p), - EXTRACT_U_1(p + 1), - EXTRACT_U_1(p + 2)); + GET_U_1(p), + GET_U_1(p + 1), + GET_U_1(p + 2)); ND_PRINT("Data = "); for(i = 3; i < ie_len; i++) { ND_PRINT("%02x ", - EXTRACT_U_1(p + i)); + GET_U_1(p + i)); } } break; @@ -1465,18 +1471,19 @@ ieee802_15_4_print_payload_ie_list(netdissect_options *ndo, case 0x5: /* IETF IE */ if (ie_len < 1) { ND_PRINT("[ERROR: Subtype ID missing]"); - } else { + } else { ND_PRINT("Subtype ID = 0x%02x, Subtype content = ", - EXTRACT_U_1(p)); + GET_U_1(p)); for(i = 1; i < ie_len; i++) { - ND_PRINT("%02x ", EXTRACT_U_1(p + i)); + ND_PRINT("%02x ", + GET_U_1(p + i)); } } break; default: ND_PRINT("IE Data = "); for(i = 0; i < ie_len; i++) { - ND_PRINT("%02x ", EXTRACT_U_1(p + i)); + ND_PRINT("%02x ", GET_U_1(p + i)); } break; } @@ -1484,7 +1491,7 @@ ieee802_15_4_print_payload_ie_list(netdissect_options *ndo, if (ie_len != 0) { ND_PRINT("IE Data = "); for(i = 0; i < ie_len; i++) { - ND_PRINT("%02x ", EXTRACT_U_1(p + i)); + ND_PRINT("%02x ", GET_U_1(p + i)); } } } @@ -1507,23 +1514,23 @@ ieee802_15_4_print_payload_ie_list(netdissect_options *ndo, static int ieee802_15_4_print_aux_sec_header(netdissect_options *ndo, const u_char *p, - uint16_t caplen, + u_int caplen, int *security_level) { int sc, key_id_mode, len; - + if (caplen < 1) { ND_PRINT("[ERROR: Truncated before Aux Security Header]"); return -1; } - sc = EXTRACT_U_1(p); + sc = GET_U_1(p); len = 1; *security_level = sc & 0x7; key_id_mode = (sc >> 3) & 0x3; - + caplen -= 1; p += 1; - + if (ndo->ndo_vflag > 0) { ND_PRINT("\n\tSecurity Level %d, Key Id Mode %d, ", *security_level, key_id_mode); @@ -1533,13 +1540,13 @@ ieee802_15_4_print_aux_sec_header(netdissect_options *ndo, ND_PRINT("[ERROR: Truncated before Frame Counter]"); return -1; } - len += 4; - caplen -= 4; - p += 4; if (ndo->ndo_vflag > 1) { ND_PRINT("Frame Counter 0x%08x ", - EXTRACT_LE_U_4(p + 1)); + GET_LE_U_4(p)); } + p += 4; + caplen -= 4; + len += 4; } switch (key_id_mode) { case 0x00: /* Implicit. */ @@ -1557,7 +1564,7 @@ ieee802_15_4_print_aux_sec_header(netdissect_options *ndo, } if (ndo->ndo_vflag > 1) { ND_PRINT("KeySource 0x%04x:%0x4x, ", - EXTRACT_LE_U_2(p), EXTRACT_LE_U_2(p + 2)); + GET_LE_U_2(p), GET_LE_U_2(p + 2)); } p += 4; caplen -= 4; @@ -1569,7 +1576,7 @@ ieee802_15_4_print_aux_sec_header(netdissect_options *ndo, return -1; } if (ndo->ndo_vflag > 1) { - ND_PRINT("KeySource %s, ", le64addr_string(ndo, p)); + ND_PRINT("KeySource %s, ", GET_LE64ADDR_STRING(p)); } p += 4; caplen -= 4; @@ -1581,7 +1588,7 @@ ieee802_15_4_print_aux_sec_header(netdissect_options *ndo, return -1; } if (ndo->ndo_vflag > 1) { - ND_PRINT("KeyIndex 0x%02x, ", EXTRACT_U_1(p)); + ND_PRINT("KeyIndex 0x%02x, ", GET_U_1(p)); } caplen -= 1; p += 1; @@ -1601,15 +1608,15 @@ ieee802_15_4_print_command_data(netdissect_options *ndo, u_int caplen) { u_int i; - + switch (command_id) { - case 0x01: /* Assocation Request */ + case 0x01: /* Association Request */ if (caplen != 1) { - ND_PRINT("Invalid Assocation request command length"); + ND_PRINT("Invalid Association request command length"); return -1; } else { uint8_t cap_info; - cap_info = EXTRACT_U_1(p); + cap_info = GET_U_1(p); ND_PRINT("%s%s%s%s%s%s", ((cap_info & 0x02) ? "FFD, " : "RFD, "), @@ -1626,14 +1633,14 @@ ieee802_15_4_print_command_data(netdissect_options *ndo, return caplen; } break; - case 0x02: /* Assocation Response */ + case 0x02: /* Association Response */ if (caplen != 3) { - ND_PRINT("Invalid Assocation response command length"); + ND_PRINT("Invalid Association response command length"); return -1; } else { ND_PRINT("Short address = "); ieee802_15_4_print_addr(ndo, p, 2); - switch (EXTRACT_U_1(p + 2)) { + switch (GET_U_1(p + 2)) { case 0x00: ND_PRINT(", Association successful"); break; @@ -1651,7 +1658,7 @@ ieee802_15_4_print_command_data(netdissect_options *ndo, break; default: ND_PRINT(", Status = 0x%02x", - EXTRACT_U_1(p + 2)); + GET_U_1(p + 2)); break; } return caplen; @@ -1662,7 +1669,7 @@ ieee802_15_4_print_command_data(netdissect_options *ndo, ND_PRINT("Invalid Disassociation Notification command length"); return -1; } else { - switch (EXTRACT_U_1(p)) { + switch (GET_U_1(p)) { case 0x00: ND_PRINT("Reserved"); break; @@ -1673,12 +1680,12 @@ ieee802_15_4_print_command_data(netdissect_options *ndo, ND_PRINT("Reason = The device wishes to leave the PAN"); break; default: - ND_PRINT("Reason = 0x%02x", EXTRACT_U_1(p + 2)); + ND_PRINT("Reason = 0x%02x", GET_U_1(p + 2)); break; } return caplen; } - + /* Following ones do not have any data. */ case 0x04: /* Data Request command */ case 0x05: /* PAN ID Conflict Notification command */ @@ -1692,14 +1699,14 @@ ieee802_15_4_print_command_data(netdissect_options *ndo, return -1; } else { uint16_t channel, page; - + ND_PRINT("Pan ID = 0x%04x, Coordinator short address = ", - EXTRACT_LE_U_2(p)); + GET_LE_U_2(p)); ieee802_15_4_print_addr(ndo, p + 2, 2); - channel = EXTRACT_U_1(p + 4); - + channel = GET_U_1(p + 4); + if (caplen == 8) { - page = EXTRACT_U_1(p + 7); + page = GET_U_1(p + 7); } else { page = 0x80; } @@ -1723,8 +1730,8 @@ ieee802_15_4_print_command_data(netdissect_options *ndo, return -1; } else { uint8_t gts; - - gts = EXTRACT_U_1(p); + + gts = GET_U_1(p); ND_PRINT("GTS Length = %d, %s, %s", gts & 0xf, (CHECK_BIT(gts, 4) ? @@ -1742,7 +1749,7 @@ ieee802_15_4_print_command_data(netdissect_options *ndo, /* XXX Not implemented */ case 0x16: /* DSME GTS Response command */ /* XXX Not implemented */ - case 0x17: /* DSME GTS GTS Notify command */ + case 0x17: /* DSME GTS Notify command */ /* XXX Not implemented */ case 0x18: /* DSME Information Request command */ /* XXX Not implemented */ @@ -1771,7 +1778,7 @@ ieee802_15_4_print_command_data(netdissect_options *ndo, default: ND_PRINT("Command Data = "); for(i = 0; i < caplen; i++) { - ND_PRINT("%02x ", EXTRACT_U_1(p + i)); + ND_PRINT("%02x ", GET_U_1(p + i)); } break; } @@ -1779,7 +1786,7 @@ ieee802_15_4_print_command_data(netdissect_options *ndo, } /* - * Parse and print frames folloing standard format. + * Parse and print frames following standard format. * * Returns FALSE in case of error. */ @@ -1791,12 +1798,13 @@ ieee802_15_4_std_frames(netdissect_options *ndo, int len, frame_version, pan_id_comp; int frame_type; int src_pan, dst_pan, src_addr_len, dst_addr_len; - int security_level, miclen = 0; + int security_level; + u_int miclen = 0; int payload_ie_present; uint8_t seq; uint32_t fcs, crc_check; const u_char *mic_start = NULL; - + payload_ie_present = 0; crc_check = 0; @@ -1807,15 +1815,15 @@ ieee802_15_4_std_frames(netdissect_options *ndo, fcs = 0; } else { /* Test for 4 octet FCS. */ - fcs = EXTRACT_LE_U_4(p + caplen - 4); - crc_check = ieee802_15_4_crc32(p, caplen - 4); + fcs = GET_LE_U_4(p + caplen - 4); + crc_check = ieee802_15_4_crc32(ndo, p, caplen - 4); if (crc_check == fcs) { /* Remove FCS */ caplen -= 4; } else { /* Test for 2 octet FCS. */ - fcs = EXTRACT_LE_U_2(p + caplen - 2); - crc_check = ieee802_15_4_crc16(p, caplen - 2); + fcs = GET_LE_U_2(p + caplen - 2); + crc_check = ieee802_15_4_crc16(ndo, p, caplen - 2); if (crc_check == fcs) { /* Remove FCS */ caplen -= 2; @@ -1825,12 +1833,12 @@ ieee802_15_4_std_frames(netdissect_options *ndo, } } } - + /* Frame version. */ frame_version = FC_FRAME_VERSION(fc); frame_type = FC_FRAME_TYPE(fc); ND_PRINT("v%d ", frame_version); - + if (ndo->ndo_vflag > 2) { if (CHECK_BIT(fc, 3)) { ND_PRINT("Security Enabled, "); } if (CHECK_BIT(fc, 4)) { ND_PRINT("Frame Pending, "); } @@ -1839,27 +1847,35 @@ ieee802_15_4_std_frames(netdissect_options *ndo, if (CHECK_BIT(fc, 8)) { ND_PRINT("Sequence Number Suppression, "); } if (CHECK_BIT(fc, 9)) { ND_PRINT("IE present, "); } } - - /* Check for the sequence number supression. */ + + /* Check for the sequence number suppression. */ if (CHECK_BIT(fc, 8)) { /* Sequence number is suppressed. */ if (frame_version < 2) { - /* Sequence number can only be supressed for frame + /* Sequence number can only be suppressed for frame version 2 or higher, this is invalid frame. */ ND_PRINT("[ERROR: Sequence number suppressed on frames where version < 2]"); } if (ndo->ndo_vflag) ND_PRINT("seq suppressed "); + if (caplen < 2) { + nd_print_trunc(ndo); + return 0; + } p += 2; caplen -= 2; } else { - seq = EXTRACT_U_1(p + 2); - p += 3; - caplen -= 3; + seq = GET_U_1(p + 2); if (ndo->ndo_vflag) ND_PRINT("seq %02x ", seq); + if (caplen < 3) { + nd_print_trunc(ndo); + return 0; + } + p += 3; + caplen -= 3; } - + /* See which parts of addresses we have. */ dst_addr_len = ieee802_15_4_addr_len((fc >> 10) & 0x3); src_addr_len = ieee802_15_4_addr_len((fc >> 14) & 0x3); @@ -1874,9 +1890,9 @@ ieee802_15_4_std_frames(netdissect_options *ndo, src_pan = 0; dst_pan = 0; pan_id_comp = CHECK_BIT(fc, 6); - + /* The PAN ID Compression rules are complicated. */ - + /* First check old versions, where the rules are simple. */ if (frame_version < 2) { if (pan_id_comp) { @@ -1958,14 +1974,14 @@ ieee802_15_4_std_frames(netdissect_options *ndo, #endif /* BROKEN_6TISCH_PAN_ID_COMPRESSION */ } } - + /* Print dst PAN and address. */ if (dst_pan) { if (caplen < 2) { ND_PRINT("[ERROR: Truncated before dst_pan]"); return 0; } - ND_PRINT("%04x:", EXTRACT_LE_U_2(p)); + ND_PRINT("%04x:", GET_LE_U_2(p)); p += 2; caplen -= 2; } else { @@ -1978,16 +1994,16 @@ ieee802_15_4_std_frames(netdissect_options *ndo, ieee802_15_4_print_addr(ndo, p, dst_addr_len); p += dst_addr_len; caplen -= dst_addr_len; - + ND_PRINT(" < "); - + /* Print src PAN and address. */ if (src_pan) { if (caplen < 2) { ND_PRINT("[ERROR: Truncated before dst_pan]"); return 0; } - ND_PRINT("%04x:", EXTRACT_LE_U_2(p)); + ND_PRINT("%04x:", GET_LE_U_2(p)); p += 2; caplen -= 2; } else { @@ -2002,17 +2018,25 @@ ieee802_15_4_std_frames(netdissect_options *ndo, p += src_addr_len; caplen -= src_addr_len; if (CHECK_BIT(fc, 3)) { + /* + * XXX - if frame_version is 0, this is the 2003 + * spec, and you don't have the auxiliary security + * header, you have a frame counter and key index + * for the AES-CTR and AES-CCM security suites but + * not for the AES-CBC-MAC security suite. + */ len = ieee802_15_4_print_aux_sec_header(ndo, p, caplen, &security_level); if (len < 0) { return 0; } + ND_TCHECK_LEN(p, len); p += len; caplen -= len; } else { security_level = 0; } - + switch (security_level) { case 0: /*FALLTHOUGH */ case 4: @@ -2031,17 +2055,17 @@ ieee802_15_4_std_frames(netdissect_options *ndo, miclen = 16; break; } - + /* Remove MIC */ - if (miclen > 0) { - if (caplen < (u_int) miclen) { + if (miclen != 0) { + if (caplen < miclen) { ND_PRINT("[ERROR: Truncated before MIC]"); return 0; } caplen -= miclen; mic_start = p + caplen; } - + /* Parse Information elements if present */ if (CHECK_BIT(fc, 9)) { /* Yes we have those. */ @@ -2053,7 +2077,7 @@ ieee802_15_4_std_frames(netdissect_options *ndo, p += len; caplen -= len; } - + if (payload_ie_present) { if (security_level >= 4) { ND_PRINT("Payload IEs present, but encrypted, cannot print "); @@ -2066,17 +2090,17 @@ ieee802_15_4_std_frames(netdissect_options *ndo, caplen -= len; } } - + /* Print MIC */ if (ndo->ndo_vflag > 2 && miclen != 0) { ND_PRINT("\n\tMIC "); - - for(len = 0; len < miclen; len++) { - ND_PRINT("%02x", EXTRACT_U_1(mic_start + len)); + + for (u_int micoffset = 0; micoffset < miclen; micoffset++) { + ND_PRINT("%02x", GET_U_1(mic_start + micoffset)); } ND_PRINT(" "); } - + /* Print FCS */ if (ndo->ndo_vflag > 2) { if (crc_check == fcs) { @@ -2086,7 +2110,7 @@ ieee802_15_4_std_frames(netdissect_options *ndo, fcs, crc_check); } } - + /* Payload print */ switch (frame_type) { case 0x00: /* Beacon */ @@ -2096,26 +2120,26 @@ ieee802_15_4_std_frames(netdissect_options *ndo, break; } else { uint16_t ss; - - ss = EXTRACT_LE_U_2(p); + + ss = GET_LE_U_2(p); ieee802_15_4_print_superframe_specification(ndo, ss); p += 2; caplen -= 2; - + /* GTS */ if (caplen < 1) { ND_PRINT("[ERROR: Truncated before GTS info]"); break; } - + len = ieee802_15_4_print_gts_info(ndo, p, caplen); if (len < 0) { break; } - + p += len; caplen -= len; - + /* Pending Addresses */ if (caplen < 1) { ND_PRINT("[ERROR: Truncated before pending addresses]"); @@ -2125,13 +2149,14 @@ ieee802_15_4_std_frames(netdissect_options *ndo, if (len < 0) { break; } + ND_TCHECK_LEN(p, len); p += len; caplen -= len; } } if (!ndo->ndo_suppress_default_print) ND_DEFAULTPRINT(p, caplen); - + break; case 0x01: /* Data */ case 0x02: /* Acknowledgement */ @@ -2143,8 +2168,8 @@ ieee802_15_4_std_frames(netdissect_options *ndo, ND_PRINT("[ERROR: Truncated before Command ID]"); } else { uint8_t command_id; - - command_id = EXTRACT_U_1(p); + + command_id = GET_U_1(p); if (command_id >= 0x30) { ND_PRINT("Command ID = Reserved 0x%02x ", command_id); @@ -2181,18 +2206,19 @@ ieee802_15_4_mp_frame(netdissect_options *ndo, { int len, frame_version, pan_id_present; int src_addr_len, dst_addr_len; - int security_level, miclen = 0; + int security_level; + u_int miclen = 0; int ie_present, payload_ie_present, security_enabled; uint8_t seq; uint32_t fcs, crc_check; const u_char *mic_start = NULL; - + pan_id_present = 0; ie_present = 0; payload_ie_present = 0; security_enabled = 0; crc_check = 0; - + /* Assume 2 octet FCS, the FCS length depends on the PHY, and we do not know about that. */ if (caplen < 3) { @@ -2201,40 +2227,40 @@ ieee802_15_4_mp_frame(netdissect_options *ndo, } else { if (caplen > 4) { /* Test for 4 octet FCS. */ - fcs = EXTRACT_LE_U_4(p + caplen - 4); - crc_check = ieee802_15_4_crc32(p, caplen - 4); + fcs = GET_LE_U_4(p + caplen - 4); + crc_check = ieee802_15_4_crc32(ndo, p, caplen - 4); if (crc_check == fcs) { /* Remove FCS */ caplen -= 4; } else { - fcs = EXTRACT_LE_U_2(p + caplen - 2); - crc_check = ieee802_15_4_crc16(p, caplen - 2); + fcs = GET_LE_U_2(p + caplen - 2); + crc_check = ieee802_15_4_crc16(ndo, p, caplen - 2); if (crc_check == fcs) { /* Remove FCS */ caplen -= 2; } } } else { - fcs = EXTRACT_LE_U_2(p + caplen - 2); - crc_check = ieee802_15_4_crc16(p, caplen - 2); + fcs = GET_LE_U_2(p + caplen - 2); + crc_check = ieee802_15_4_crc16(ndo, p, caplen - 2); if (crc_check == fcs) { /* Remove FCS */ caplen -= 2; } } } - + if (CHECK_BIT(fc, 3)) { /* Long Frame Control */ - + /* Frame version. */ frame_version = FC_FRAME_VERSION(fc); ND_PRINT("v%d ", frame_version); - + pan_id_present = CHECK_BIT(fc, 8); ie_present = CHECK_BIT(fc, 15); security_enabled = CHECK_BIT(fc, 9); - + if (ndo->ndo_vflag > 2) { if (security_enabled) { ND_PRINT("Security Enabled, "); } if (CHECK_BIT(fc, 11)) { ND_PRINT("Frame Pending, "); } @@ -2245,28 +2271,36 @@ ieee802_15_4_mp_frame(netdissect_options *ndo, } if (ie_present) { ND_PRINT("IE present, "); } } - - /* Check for the sequence number supression. */ + + /* Check for the sequence number suppression. */ if (CHECK_BIT(fc, 10)) { /* Sequence number is suppressed, but long version. */ + if (caplen < 2) { + nd_print_trunc(ndo); + return 0; + } p += 2; caplen -= 2; } else { - seq = EXTRACT_U_1(p + 2); - p += 3; - caplen -= 3; + seq = GET_U_1(p + 2); if (ndo->ndo_vflag) ND_PRINT("seq %02x ", seq); + if (caplen < 3) { + nd_print_trunc(ndo); + return 0; + } + p += 3; + caplen -= 3; } } else { /* Short format of header, but with seq no */ - seq = EXTRACT_U_1(p + 1); + seq = GET_U_1(p + 1); p += 2; caplen -= 2; if (ndo->ndo_vflag) ND_PRINT("seq %02x ", seq); } - + /* See which parts of addresses we have. */ dst_addr_len = ieee802_15_4_addr_len((fc >> 4) & 0x3); src_addr_len = ieee802_15_4_addr_len((fc >> 6) & 0x3); @@ -2278,14 +2312,14 @@ ieee802_15_4_mp_frame(netdissect_options *ndo, ND_PRINT("[ERROR: Invalid dst address mode]"); return 0; } - + /* Print dst PAN and address. */ if (pan_id_present) { if (caplen < 2) { ND_PRINT("[ERROR: Truncated before dst_pan]"); return 0; } - ND_PRINT("%04x:", EXTRACT_LE_U_2(p)); + ND_PRINT("%04x:", GET_LE_U_2(p)); p += 2; caplen -= 2; } else { @@ -2298,9 +2332,9 @@ ieee802_15_4_mp_frame(netdissect_options *ndo, ieee802_15_4_print_addr(ndo, p, dst_addr_len); p += dst_addr_len; caplen -= dst_addr_len; - + ND_PRINT(" < "); - + /* Print src PAN and address. */ ND_PRINT(" -:"); if (caplen < (u_int) src_addr_len) { @@ -2311,19 +2345,20 @@ ieee802_15_4_mp_frame(netdissect_options *ndo, ND_PRINT(" "); p += src_addr_len; caplen -= src_addr_len; - + if (security_enabled) { len = ieee802_15_4_print_aux_sec_header(ndo, p, caplen, &security_level); if (len < 0) { return 0; } + ND_TCHECK_LEN(p, len); p += len; caplen -= len; } else { security_level = 0; } - + switch (security_level) { case 0: /*FALLTHOUGH */ case 4: @@ -2342,17 +2377,17 @@ ieee802_15_4_mp_frame(netdissect_options *ndo, miclen = 16; break; } - + /* Remove MIC */ - if (miclen > 0) { - if (caplen < (u_int) miclen) { + if (miclen != 0) { + if (caplen < miclen) { ND_PRINT("[ERROR: Truncated before MIC]"); return 0; } caplen -= miclen; mic_start = p + caplen; } - + /* Parse Information elements if present */ if (ie_present) { /* Yes we have those. */ @@ -2364,12 +2399,13 @@ ieee802_15_4_mp_frame(netdissect_options *ndo, p += len; caplen -= len; } - + if (payload_ie_present) { if (security_level >= 4) { ND_PRINT("Payload IEs present, but encrypted, cannot print "); } else { - len = ieee802_15_4_print_payload_ie_list(ndo, p, caplen); + len = ieee802_15_4_print_payload_ie_list(ndo, p, + caplen); if (len < 0) { return 0; } @@ -2377,18 +2413,18 @@ ieee802_15_4_mp_frame(netdissect_options *ndo, caplen -= len; } } - + /* Print MIC */ if (ndo->ndo_vflag > 2 && miclen != 0) { ND_PRINT("\n\tMIC "); - - for(len = 0; len < miclen; len++) { - ND_PRINT("%02x", EXTRACT_U_1(mic_start + len)); + + for (u_int micoffset = 0; micoffset < miclen; micoffset++) { + ND_PRINT("%02x", GET_U_1(mic_start + micoffset)); } ND_PRINT(" "); } - - + + /* Print FCS */ if (ndo->ndo_vflag > 2) { if (crc_check == fcs) { @@ -2398,10 +2434,10 @@ ieee802_15_4_mp_frame(netdissect_options *ndo, fcs, crc_check); } } - + if (!ndo->ndo_suppress_default_print) ND_DEFAULTPRINT(p, caplen); - + return 1; } @@ -2424,7 +2460,7 @@ ieee802_15_4_frag_frame(netdissect_options *ndo _U_, } /* - * Interal call to dissector taking packet + len instead of pcap_pkthdr. + * Internal call to dissector taking packet + len instead of pcap_pkthdr. * * Returns FALSE in case of error. */ @@ -2434,23 +2470,23 @@ ieee802_15_4_print(netdissect_options *ndo, { int frame_type; uint16_t fc; - - ndo->ndo_protocol ="802.15.4"; + + ndo->ndo_protocol = "802.15.4"; if (caplen < 2) { nd_print_trunc(ndo); return caplen; } - - fc = EXTRACT_LE_U_2(p); - + + fc = GET_LE_U_2(p); + /* First we need to check the frame type to know how to parse the rest of the FC. Frame type is the first 3 bit of the frame control field. */ - + frame_type = FC_FRAME_TYPE(fc); ND_PRINT("IEEE 802.15.4 %s packet ", ftypes[frame_type]); - + switch (frame_type) { case 0x00: /* Beacon */ case 0x01: /* Data */ @@ -2478,18 +2514,43 @@ ieee802_15_4_print(netdissect_options *ndo, * Main function to print packets. */ -u_int +void ieee802_15_4_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h, const u_char *p) { u_int caplen = h->caplen; - ndo->ndo_protocol ="802.15.4_if"; - return ieee802_15_4_print(ndo, p, caplen); + ndo->ndo_protocol = "802.15.4"; + ndo->ndo_ll_hdr_len += ieee802_15_4_print(ndo, p, caplen); } -/* - * Local Variables: - * c-style: whitesmith - * c-basic-offset: 8 - * End: - */ +/* For DLT_IEEE802_15_4_TAP */ +/* https://github.com/jkcko/ieee802.15.4-tap */ +void +ieee802_15_4_tap_if_print(netdissect_options *ndo, + const struct pcap_pkthdr *h, const u_char *p) +{ + uint8_t version; + uint16_t length; + + ndo->ndo_protocol = "802.15.4_tap"; + if (h->caplen < 4) { + nd_print_trunc(ndo); + ndo->ndo_ll_hdr_len += h->caplen; + return; + } + + version = GET_U_1(p); + length = GET_LE_U_2(p + 2); + if (version != 0 || length < 4) { + nd_print_invalid(ndo); + return; + } + + if (h->caplen < length) { + nd_print_trunc(ndo); + ndo->ndo_ll_hdr_len += h->caplen; + return; + } + + ndo->ndo_ll_hdr_len += ieee802_15_4_print(ndo, p+length, h->caplen-length) + length; +}