]> The Tcpdump Group git mirrors - tcpdump/blobdiff - print-802_15_4.c
Makefile.in: don't remove configure and config.h.in in make distclean.
[tcpdump] / print-802_15_4.c
index 37f111bc85f7af27d854847c212e66fe6a4dd65f..1895be7ca19b9a8a420ffb0fd3c4723088180d2a 100644 (file)
@@ -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 */
@@ -543,10 +546,9 @@ ieee802_15_4_print_addr(netdissect_options *ndo, const u_char *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;
 }
 
 /*
@@ -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;
                }
@@ -1575,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;
@@ -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.
  */
@@ -2449,7 +2471,7 @@ 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);
@@ -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;
 }