X-Git-Url: https://git.tcpdump.org/tcpdump/blobdiff_plain/6313179f4be2da576d604786334fdb41d80c346f..d2777156522f139a858bd6b5b51e364826bc95a7:/print-802_15_4.c diff --git a/print-802_15_4.c b/print-802_15_4.c index 4b512799..1895be7c 100644 --- a/print-802_15_4.c +++ b/print-802_15_4.c @@ -28,6 +28,7 @@ #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,10 +420,10 @@ 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, +ieee802_15_4_crc16(netdissect_options *ndo, const u_char *p, u_int data_len) { uint16_t crc; @@ -431,7 +432,8 @@ ieee802_15_4_crc16(const u_char *p, crc = 0x0000; /* Note, initial value is 0x0000 not 0xffff. */ while (data_len != 0){ - y = *p++; + y = GET_U_1(p); + p++; /* Reverse bits on input */ y = (((y & 0xaa) >> 1) | ((y & 0x55) << 1)); y = (((y & 0xcc) >> 2) | ((y & 0x33) << 2)); @@ -470,10 +472,10 @@ 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, +ieee802_15_4_crc32(netdissect_options *ndo, const u_char *p, u_int data_len) { uint32_t crc, byte; @@ -482,7 +484,8 @@ ieee802_15_4_crc32(const u_char *p, crc = 0x00000000; /* Note, initial value is 0x00000000 not 0xffffffff */ while (data_len != 0){ - byte = *p++; + byte = GET_U_1(p); + p++; /* Reverse bits on input */ byte = ieee802_15_4_reverse32(byte); /* Update CRC */ @@ -546,7 +549,6 @@ ieee802_15_4_print_addr(netdissect_options *ndo, const u_char *p, ND_PRINT("%s", GET_LE64ADDR_STRING(p)); break; } - return; } /* @@ -567,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"); } } /* @@ -655,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("]"); @@ -718,7 +720,7 @@ ieee802_15_4_print_header_ie(netdissect_options *ndo, 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 { @@ -786,7 +788,7 @@ 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", @@ -889,7 +891,7 @@ ieee802_15_4_print_header_ie(netdissect_options *ndo, 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 */ @@ -957,7 +959,7 @@ 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; } @@ -987,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; } @@ -1086,7 +1088,7 @@ ieee802_15_4_print_mlme_ie(netdissect_options *ndo, } break; - case 0x1a: /* TSCH Syncronization IE. */ + case 0x1a: /* TSCH Synchronization IE. */ if (sub_ie_len < 6) { ND_PRINT("[ERROR: Length != 6]"); } @@ -1211,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 */ @@ -1280,7 +1282,7 @@ ieee802_15_4_print_mlme_ie_list(netdissect_options *ndo, 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; } @@ -1298,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; } /* @@ -1440,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; } @@ -1609,9 +1610,9 @@ ieee802_15_4_print_command_data(netdissect_options *ndo, 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; @@ -1632,9 +1633,9 @@ 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 = "); @@ -1748,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 */ @@ -1785,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. */ @@ -1797,7 +1798,8 @@ 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; @@ -1814,14 +1816,14 @@ ieee802_15_4_std_frames(netdissect_options *ndo, } else { /* Test for 4 octet FCS. */ fcs = GET_LE_U_4(p + caplen - 4); - crc_check = ieee802_15_4_crc32(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 = GET_LE_U_2(p + caplen - 2); - crc_check = ieee802_15_4_crc16(p, caplen - 2); + crc_check = ieee802_15_4_crc16(ndo, p, caplen - 2); if (crc_check == fcs) { /* Remove FCS */ caplen -= 2; @@ -1846,24 +1848,32 @@ ieee802_15_4_std_frames(netdissect_options *ndo, 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 = GET_U_1(p + 2); - p += 3; - caplen -= 3; 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. */ @@ -2020,6 +2030,7 @@ ieee802_15_4_std_frames(netdissect_options *ndo, if (len < 0) { return 0; } + ND_TCHECK_LEN(p, len); p += len; caplen -= len; } else { @@ -2046,8 +2057,8 @@ ieee802_15_4_std_frames(netdissect_options *ndo, } /* Remove MIC */ - if (miclen > 0) { - if (caplen < (u_int) miclen) { + if (miclen != 0) { + if (caplen < miclen) { ND_PRINT("[ERROR: Truncated before MIC]"); return 0; } @@ -2084,8 +2095,8 @@ ieee802_15_4_std_frames(netdissect_options *ndo, if (ndo->ndo_vflag > 2 && miclen != 0) { ND_PRINT("\n\tMIC "); - for(len = 0; len < miclen; len++) { - ND_PRINT("%02x", GET_U_1(mic_start + len)); + for (u_int micoffset = 0; micoffset < miclen; micoffset++) { + ND_PRINT("%02x", GET_U_1(mic_start + micoffset)); } ND_PRINT(" "); } @@ -2138,6 +2149,7 @@ ieee802_15_4_std_frames(netdissect_options *ndo, if (len < 0) { break; } + ND_TCHECK_LEN(p, len); p += len; caplen -= len; } @@ -2194,7 +2206,8 @@ 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; @@ -2215,13 +2228,13 @@ ieee802_15_4_mp_frame(netdissect_options *ndo, if (caplen > 4) { /* Test for 4 octet FCS. */ fcs = GET_LE_U_4(p + caplen - 4); - crc_check = ieee802_15_4_crc32(p, caplen - 4); + crc_check = ieee802_15_4_crc32(ndo, p, caplen - 4); if (crc_check == fcs) { /* Remove FCS */ caplen -= 4; } else { fcs = GET_LE_U_2(p + caplen - 2); - crc_check = ieee802_15_4_crc16(p, caplen - 2); + crc_check = ieee802_15_4_crc16(ndo, p, caplen - 2); if (crc_check == fcs) { /* Remove FCS */ caplen -= 2; @@ -2229,7 +2242,7 @@ ieee802_15_4_mp_frame(netdissect_options *ndo, } } else { fcs = GET_LE_U_2(p + caplen - 2); - crc_check = ieee802_15_4_crc16(p, caplen - 2); + crc_check = ieee802_15_4_crc16(ndo, p, caplen - 2); if (crc_check == fcs) { /* Remove FCS */ caplen -= 2; @@ -2259,17 +2272,25 @@ 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 = GET_U_1(p + 2); - p += 3; - caplen -= 3; 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 */ @@ -2331,6 +2352,7 @@ ieee802_15_4_mp_frame(netdissect_options *ndo, if (len < 0) { return 0; } + ND_TCHECK_LEN(p, len); p += len; caplen -= len; } else { @@ -2357,8 +2379,8 @@ ieee802_15_4_mp_frame(netdissect_options *ndo, } /* Remove MIC */ - if (miclen > 0) { - if (caplen < (u_int) miclen) { + if (miclen != 0) { + if (caplen < miclen) { ND_PRINT("[ERROR: Truncated before MIC]"); return 0; } @@ -2396,8 +2418,8 @@ ieee802_15_4_mp_frame(netdissect_options *ndo, if (ndo->ndo_vflag > 2 && miclen != 0) { ND_PRINT("\n\tMIC "); - for(len = 0; len < miclen; len++) { - ND_PRINT("%02x", GET_U_1(mic_start + len)); + for (u_int micoffset = 0; micoffset < miclen; micoffset++) { + ND_PRINT("%02x", GET_U_1(mic_start + micoffset)); } ND_PRINT(" "); } @@ -2438,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. */ @@ -2492,18 +2514,18 @@ 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); } /* For DLT_IEEE802_15_4_TAP */ /* https://github.com/jkcko/ieee802.15.4-tap */ -u_int +void ieee802_15_4_tap_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h, const u_char *p) { @@ -2513,20 +2535,22 @@ ieee802_15_4_tap_if_print(netdissect_options *ndo, ndo->ndo_protocol = "802.15.4_tap"; if (h->caplen < 4) { nd_print_trunc(ndo); - return h->caplen; + 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 0; + return; } if (h->caplen < length) { nd_print_trunc(ndo); - return h->caplen; + ndo->ndo_ll_hdr_len += h->caplen; + return; } - return ieee802_15_4_print(ndo, p+length, h->caplen-length) + length; + ndo->ndo_ll_hdr_len += ieee802_15_4_print(ndo, p+length, h->caplen-length) + length; }