#include "netdissect-stdinc.h"
+#define ND_LONGJMP_FROM_TCHECK
#include "netdissect.h"
#include "addrtoname.h"
"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 */
/*
* 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;
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));
/*
* 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;
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 */
ND_PRINT("%s", GET_LE64ADDR_STRING(p));
break;
}
- return;
}
/*
((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"); }
}
/*
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 {
}
}
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",
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 */
h_ie_names[element_id], ie_len);
}
}
- if (caplen < ie_len) {
+ if (caplen < 2U + ie_len) {
ND_PRINT("[ERROR: Truncated IE data]");
return -1;
}
if (element_id == 0x7f) {
break;
}
- } while (caplen > 0);
+ } while (caplen != 0);
return len;
}
}
break;
- case 0x1a: /* TSCH Syncronization IE. */
+ case 0x1a: /* TSCH Synchronization IE. */
if (sub_ie_len < 6) {
ND_PRINT("[ERROR: Length != 6]");
}
/* 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 */
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;
}
p += sub_ie_len;
ie_len -= 2 + sub_ie_len;
} while (ie_len > 0);
- return;
}
/*
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;
}
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;
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 = ");
}
/*
- * Parse and print frames folloing standard format.
+ * Parse and print frames following standard format.
*
* Returns FALSE in case of error.
*/
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;
} 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;
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. */
if (len < 0) {
return 0;
}
+ ND_TCHECK_LEN(p, len);
p += len;
caplen -= len;
} else {
}
/* Remove MIC */
- if (miclen > 0) {
- if (caplen < (u_int) miclen) {
+ if (miclen != 0) {
+ if (caplen < miclen) {
ND_PRINT("[ERROR: Truncated before MIC]");
return 0;
}
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(" ");
}
if (len < 0) {
break;
}
+ ND_TCHECK_LEN(p, len);
p += len;
caplen -= len;
}
{
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;
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;
}
} 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;
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 */
if (len < 0) {
return 0;
}
+ ND_TCHECK_LEN(p, len);
p += len;
caplen -= len;
} else {
}
/* Remove MIC */
- if (miclen > 0) {
- if (caplen < (u_int) miclen) {
+ if (miclen != 0) {
+ if (caplen < miclen) {
ND_PRINT("[ERROR: Truncated before MIC]");
return 0;
}
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(" ");
}
}
/*
- * 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.
*/
const struct pcap_pkthdr *h, const u_char *p)
{
u_int caplen = h->caplen;
- ndo->ndo_protocol = "802.15.4_if";
+ ndo->ndo_protocol = "802.15.4";
ndo->ndo_ll_hdr_len += ieee802_15_4_print(ndo, p, caplen);
}