Home | History | Annotate | Line # | Download | only in dist
      1 /*
      2  * Copyright (c) 2009
      3  *	Siemens AG, All rights reserved.
      4  *	Dmitry Eremin-Solenikov (dbaryshkov (at) gmail.com)
      5  *
      6  * Redistribution and use in source and binary forms, with or without
      7  * modification, are permitted provided that: (1) source code distributions
      8  * retain the above copyright notice and this paragraph in its entirety, (2)
      9  * distributions including binary code include the above copyright notice and
     10  * this paragraph in its entirety in the documentation or other materials
     11  * provided with the distribution, and (3) all advertising materials mentioning
     12  * features or use of this software display the following acknowledgement:
     13  * ``This product includes software developed by the University of California,
     14  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
     15  * the University nor the names of its contributors may be used to endorse
     16  * or promote products derived from this software without specific prior
     17  * written permission.
     18  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
     19  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
     20  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
     21  */
     22 
     23 #include <sys/cdefs.h>
     24 #ifndef lint
     25 __RCSID("$NetBSD: print-802_15_4.c,v 1.6 2024/09/02 16:15:30 christos Exp $");
     26 #endif
     27 
     28 /* \summary: IEEE 802.15.4 printer */
     29 
     30 #include <config.h>
     31 
     32 #include "netdissect-stdinc.h"
     33 
     34 #define ND_LONGJMP_FROM_TCHECK
     35 #include "netdissect.h"
     36 #include "addrtoname.h"
     37 
     38 #include "extract.h"
     39 
     40 #define CHECK_BIT(num,bit) (((num) >> (bit)) & 0x1)
     41 
     42 #define BROKEN_6TISCH_PAN_ID_COMPRESSION 0
     43 
     44 /* Frame types from Table 7-1 of 802.15.4-2015 */
     45 static const char *ftypes[] = {
     46 	"Beacon",			/* 0 */
     47 	"Data",				/* 1 */
     48 	"ACK",				/* 2 */
     49 	"Command",			/* 3 */
     50 	"Reserved",			/* 4 */
     51 	"Multipurpose",			/* 5 */
     52 	"Fragment",			/* 6 */
     53 	"Extended"			/* 7 */
     54 };
     55 
     56 /* Element IDs for Header IEs from Table 7-7 of 802.15.4-2015 */
     57 static const char *h_ie_names[] = {
     58 	"Vendor Specific Header IE",			/* 0x00 */
     59 	"Reserved 0x01",				/* 0x01 */
     60 	"Reserved 0x02",				/* 0x02 */
     61 	"Reserved 0x03",				/* 0x03 */
     62 	"Reserved 0x04",				/* 0x04 */
     63 	"Reserved 0x05",				/* 0x05 */
     64 	"Reserved 0x06",				/* 0x06 */
     65 	"Reserved 0x07",				/* 0x07 */
     66 	"Reserved 0x08",				/* 0x08 */
     67 	"Reserved 0x09",				/* 0x09 */
     68 	"Reserved 0x0a",				/* 0x0a */
     69 	"Reserved 0x0b",				/* 0x0b */
     70 	"Reserved 0x0c",				/* 0x0c */
     71 	"Reserved 0x0d",				/* 0x0d */
     72 	"Reserved 0x0e",				/* 0x0e */
     73 	"Reserved 0x0f",				/* 0x0f */
     74 	"Reserved 0x10",				/* 0x10 */
     75 	"Reserved 0x11",				/* 0x11 */
     76 	"Reserved 0x12",				/* 0x12 */
     77 	"Reserved 0x13",				/* 0x13 */
     78 	"Reserved 0x14",				/* 0x14 */
     79 	"Reserved 0x15",				/* 0x15 */
     80 	"Reserved 0x16",				/* 0x16 */
     81 	"Reserved 0x17",				/* 0x17 */
     82 	"Reserved 0x18",				/* 0x18 */
     83 	"Reserved 0x19",				/* 0x19 */
     84 	"LE CSL IE",					/* 0x1a */
     85 	"LE RIT IE",					/* 0x1b */
     86 	"DSME PAN descriptor IE",			/* 0x1c */
     87 	"Rendezvous Time IE",				/* 0x1d */
     88 	"Time Correction IE",				/* 0x1e */
     89 	"Reserved 0x1f",				/* 0x1f */
     90 	"Reserved 0x20",				/* 0x20 */
     91 	"Extended DSME PAN descriptor IE",		/* 0x21 */
     92 	"Fragment Sequence Context Description IE",	/* 0x22 */
     93 	"Simplified Superframe Specification IE",	/* 0x23 */
     94 	"Simplified GTS Specification IE",		/* 0x24 */
     95 	"LECIM Capabilities IE",			/* 0x25 */
     96 	"TRLE Descriptor IE",				/* 0x26 */
     97 	"RCC Capabilities IE",				/* 0x27 */
     98 	"RCCN Descriptor IE",				/* 0x28 */
     99 	"Global Time IE",				/* 0x29 */
    100 	"Omnibus Header IE",				/* 0x2a */
    101 	"DA IE",					/* 0x2b */
    102 	"Reserved 0x2c",				/* 0x2c */
    103 	"Reserved 0x2d",				/* 0x2d */
    104 	"Reserved 0x2e",				/* 0x2e */
    105 	"Reserved 0x2f",				/* 0x2f */
    106 	"Reserved 0x30",				/* 0x30 */
    107 	"Reserved 0x31",				/* 0x31 */
    108 	"Reserved 0x32",				/* 0x32 */
    109 	"Reserved 0x33",				/* 0x33 */
    110 	"Reserved 0x34",				/* 0x34 */
    111 	"Reserved 0x35",				/* 0x35 */
    112 	"Reserved 0x36",				/* 0x36 */
    113 	"Reserved 0x37",				/* 0x37 */
    114 	"Reserved 0x38",				/* 0x38 */
    115 	"Reserved 0x39",				/* 0x39 */
    116 	"Reserved 0x3a",				/* 0x3a */
    117 	"Reserved 0x3b",				/* 0x3b */
    118 	"Reserved 0x3c",				/* 0x3c */
    119 	"Reserved 0x3d",				/* 0x3d */
    120 	"Reserved 0x3e",				/* 0x3e */
    121 	"Reserved 0x3f",				/* 0x3f */
    122 	"Reserved 0x40",				/* 0x40 */
    123 	"Reserved 0x41",				/* 0x41 */
    124 	"Reserved 0x42",				/* 0x42 */
    125 	"Reserved 0x43",				/* 0x43 */
    126 	"Reserved 0x44",				/* 0x44 */
    127 	"Reserved 0x45",				/* 0x45 */
    128 	"Reserved 0x46",				/* 0x46 */
    129 	"Reserved 0x47",				/* 0x47 */
    130 	"Reserved 0x48",				/* 0x48 */
    131 	"Reserved 0x49",				/* 0x49 */
    132 	"Reserved 0x4a",				/* 0x4a */
    133 	"Reserved 0x4b",				/* 0x4b */
    134 	"Reserved 0x4c",				/* 0x4c */
    135 	"Reserved 0x4d",				/* 0x4d */
    136 	"Reserved 0x4e",				/* 0x4e */
    137 	"Reserved 0x4f",				/* 0x4f */
    138 	"Reserved 0x50",				/* 0x50 */
    139 	"Reserved 0x51",				/* 0x51 */
    140 	"Reserved 0x52",				/* 0x52 */
    141 	"Reserved 0x53",				/* 0x53 */
    142 	"Reserved 0x54",				/* 0x54 */
    143 	"Reserved 0x55",				/* 0x55 */
    144 	"Reserved 0x56",				/* 0x56 */
    145 	"Reserved 0x57",				/* 0x57 */
    146 	"Reserved 0x58",				/* 0x58 */
    147 	"Reserved 0x59",				/* 0x59 */
    148 	"Reserved 0x5a",				/* 0x5a */
    149 	"Reserved 0x5b",				/* 0x5b */
    150 	"Reserved 0x5c",				/* 0x5c */
    151 	"Reserved 0x5d",				/* 0x5d */
    152 	"Reserved 0x5e",				/* 0x5e */
    153 	"Reserved 0x5f",				/* 0x5f */
    154 	"Reserved 0x60",				/* 0x60 */
    155 	"Reserved 0x61",				/* 0x61 */
    156 	"Reserved 0x62",				/* 0x62 */
    157 	"Reserved 0x63",				/* 0x63 */
    158 	"Reserved 0x64",				/* 0x64 */
    159 	"Reserved 0x65",				/* 0x65 */
    160 	"Reserved 0x66",				/* 0x66 */
    161 	"Reserved 0x67",				/* 0x67 */
    162 	"Reserved 0x68",				/* 0x68 */
    163 	"Reserved 0x69",				/* 0x69 */
    164 	"Reserved 0x6a",				/* 0x6a */
    165 	"Reserved 0x6b",				/* 0x6b */
    166 	"Reserved 0x6c",				/* 0x6c */
    167 	"Reserved 0x6d",				/* 0x6d */
    168 	"Reserved 0x6e",				/* 0x6e */
    169 	"Reserved 0x6f",				/* 0x6f */
    170 	"Reserved 0x70",				/* 0x70 */
    171 	"Reserved 0x71",				/* 0x71 */
    172 	"Reserved 0x72",				/* 0x72 */
    173 	"Reserved 0x73",				/* 0x73 */
    174 	"Reserved 0x74",				/* 0x74 */
    175 	"Reserved 0x75",				/* 0x75 */
    176 	"Reserved 0x76",				/* 0x76 */
    177 	"Reserved 0x77",				/* 0x77 */
    178 	"Reserved 0x78",				/* 0x78 */
    179 	"Reserved 0x79",				/* 0x79 */
    180 	"Reserved 0x7a",				/* 0x7a */
    181 	"Reserved 0x7b",				/* 0x7b */
    182 	"Reserved 0x7c",				/* 0x7c */
    183 	"Reserved 0x7d",				/* 0x7d */
    184 	"Header Termination 1 IE",			/* 0x7e */
    185 	"Header Termination 2 IE"			/* 0x7f */
    186 };
    187 
    188 /* Payload IE Group IDs from Table 7-15 of 802.15.4-2015 */
    189 static const char *p_ie_names[] = {
    190 	"ESDU IE",			/* 0x00 */
    191 	"MLME IE",			/* 0x01 */
    192 	"Vendor Specific Nested IE",	/* 0x02 */
    193 	"Multiplexed IE (802.15.9)",	/* 0x03 */
    194 	"Omnibus Payload Group IE",	/* 0x04 */
    195 	"IETF IE",			/* 0x05 */
    196 	"Reserved 0x06",		/* 0x06 */
    197 	"Reserved 0x07",		/* 0x07 */
    198 	"Reserved 0x08",		/* 0x08 */
    199 	"Reserved 0x09",		/* 0x09 */
    200 	"Reserved 0x0a",		/* 0x0a */
    201 	"Reserved 0x0b",		/* 0x0b */
    202 	"Reserved 0x0c",		/* 0x0c */
    203 	"Reserved 0x0d",		/* 0x0d */
    204 	"Reserved 0x0e",		/* 0x0e */
    205 	"List termination"		/* 0x0f */
    206 };
    207 
    208 /* Sub-ID for short format from Table 7-16 of 802.15.4-2015 */
    209 static const char *p_mlme_short_names[] = {
    210 	"Reserved for long format 0x0",			/* 0x00 */
    211 	"Reserved for long format 0x1",			/* 0x01 */
    212 	"Reserved for long format 0x2",			/* 0x02 */
    213 	"Reserved for long format 0x3",			/* 0x03 */
    214 	"Reserved for long format 0x4",			/* 0x04 */
    215 	"Reserved for long format 0x5",			/* 0x05 */
    216 	"Reserved for long format 0x6",			/* 0x06 */
    217 	"Reserved for long format 0x7",			/* 0x07 */
    218 	"Reserved for long format 0x8",			/* 0x08 */
    219 	"Reserved for long format 0x9",			/* 0x09 */
    220 	"Reserved for long format 0xa",			/* 0x0a */
    221 	"Reserved for long format 0xb",			/* 0x0b */
    222 	"Reserved for long format 0xc",			/* 0x0c */
    223 	"Reserved for long format 0xd",			/* 0x0d */
    224 	"Reserved for long format 0xe",			/* 0x0e */
    225 	"Reserved for long format 0xf",			/* 0x0f */
    226 	"Reserved 0x10",				/* 0x10 */
    227 	"Reserved 0x11",				/* 0x11 */
    228 	"Reserved 0x12",				/* 0x12 */
    229 	"Reserved 0x13",				/* 0x13 */
    230 	"Reserved 0x14",				/* 0x14 */
    231 	"Reserved 0x15",				/* 0x15 */
    232 	"Reserved 0x16",				/* 0x16 */
    233 	"Reserved 0x17",				/* 0x17 */
    234 	"Reserved 0x18",				/* 0x18 */
    235 	"Reserved 0x19",				/* 0x19 */
    236 	"TSCH Synchronization IE",			/* 0x1a */
    237 	"TSCH Slotframe and Link IE",			/* 0x1b */
    238 	"TSCH Timeslot IE",				/* 0x1c */
    239 	"Hopping timing IE",				/* 0x1d */
    240 	"Enhanced Beacon Filter IE",			/* 0x1e */
    241 	"MAC Metrics IE",				/* 0x1f */
    242 	"All MAC Metrics IE",				/* 0x20 */
    243 	"Coexistence Specification IE",			/* 0x21 */
    244 	"SUN Device Capabilities IE",			/* 0x22 */
    245 	"SUN FSK Generic PHY IE",			/* 0x23 */
    246 	"Mode Switch Parameter IE",			/* 0x24 */
    247 	"PHY Parameter Change IE",			/* 0x25 */
    248 	"O-QPSK PHY Mode IE",				/* 0x26 */
    249 	"PCA Allocation IE",				/* 0x27 */
    250 	"LECIM DSSS Operating Mode IE",			/* 0x28 */
    251 	"LECIM FSK Operating Mode IE",			/* 0x29 */
    252 	"Reserved 0x2a",				/* 0x2a */
    253 	"TVWS PHY Operating Mode Description IE",	/* 0x2b */
    254 	"TVWS Device Capabilities IE",			/* 0x2c */
    255 	"TVWS Device Category IE",			/* 0x2d */
    256 	"TVWS Device Identification IE",		/* 0x2e */
    257 	"TVWS Device Location IE",			/* 0x2f */
    258 	"TVWS Channel Information Query IE",		/* 0x30 */
    259 	"TVWS Channel Information Source IE",		/* 0x31 */
    260 	"CTM IE",					/* 0x32 */
    261 	"Timestamp IE",					/* 0x33 */
    262 	"Timestamp Difference IE",			/* 0x34 */
    263 	"TMCTP Specification IE",			/* 0x35 */
    264 	"RCC PHY Operating Mode IE",			/* 0x36 */
    265 	"Reserved 0x37",				/* 0x37 */
    266 	"Reserved 0x38",				/* 0x38 */
    267 	"Reserved 0x39",				/* 0x39 */
    268 	"Reserved 0x3a",				/* 0x3a */
    269 	"Reserved 0x3b",				/* 0x3b */
    270 	"Reserved 0x3c",				/* 0x3c */
    271 	"Reserved 0x3d",				/* 0x3d */
    272 	"Reserved 0x3e",				/* 0x3e */
    273 	"Reserved 0x3f",				/* 0x3f */
    274 	"Reserved 0x40",				/* 0x40 */
    275 	"Reserved 0x41",				/* 0x41 */
    276 	"Reserved 0x42",				/* 0x42 */
    277 	"Reserved 0x43",				/* 0x43 */
    278 	"Reserved 0x44",				/* 0x44 */
    279 	"Reserved 0x45",				/* 0x45 */
    280 	"Reserved 0x46",				/* 0x46 */
    281 	"Reserved 0x47",				/* 0x47 */
    282 	"Reserved 0x48",				/* 0x48 */
    283 	"Reserved 0x49",				/* 0x49 */
    284 	"Reserved 0x4a",				/* 0x4a */
    285 	"Reserved 0x4b",				/* 0x4b */
    286 	"Reserved 0x4c",				/* 0x4c */
    287 	"Reserved 0x4d",				/* 0x4d */
    288 	"Reserved 0x4e",				/* 0x4e */
    289 	"Reserved 0x4f",				/* 0x4f */
    290 	"Reserved 0x50",				/* 0x50 */
    291 	"Reserved 0x51",				/* 0x51 */
    292 	"Reserved 0x52",				/* 0x52 */
    293 	"Reserved 0x53",				/* 0x53 */
    294 	"Reserved 0x54",				/* 0x54 */
    295 	"Reserved 0x55",				/* 0x55 */
    296 	"Reserved 0x56",				/* 0x56 */
    297 	"Reserved 0x57",				/* 0x57 */
    298 	"Reserved 0x58",				/* 0x58 */
    299 	"Reserved 0x59",				/* 0x59 */
    300 	"Reserved 0x5a",				/* 0x5a */
    301 	"Reserved 0x5b",				/* 0x5b */
    302 	"Reserved 0x5c",				/* 0x5c */
    303 	"Reserved 0x5d",				/* 0x5d */
    304 	"Reserved 0x5e",				/* 0x5e */
    305 	"Reserved 0x5f",				/* 0x5f */
    306 	"Reserved 0x60",				/* 0x60 */
    307 	"Reserved 0x61",				/* 0x61 */
    308 	"Reserved 0x62",				/* 0x62 */
    309 	"Reserved 0x63",				/* 0x63 */
    310 	"Reserved 0x64",				/* 0x64 */
    311 	"Reserved 0x65",				/* 0x65 */
    312 	"Reserved 0x66",				/* 0x66 */
    313 	"Reserved 0x67",				/* 0x67 */
    314 	"Reserved 0x68",				/* 0x68 */
    315 	"Reserved 0x69",				/* 0x69 */
    316 	"Reserved 0x6a",				/* 0x6a */
    317 	"Reserved 0x6b",				/* 0x6b */
    318 	"Reserved 0x6c",				/* 0x6c */
    319 	"Reserved 0x6d",				/* 0x6d */
    320 	"Reserved 0x6e",				/* 0x6e */
    321 	"Reserved 0x6f",				/* 0x6f */
    322 	"Reserved 0x70",				/* 0x70 */
    323 	"Reserved 0x71",				/* 0x71 */
    324 	"Reserved 0x72",				/* 0x72 */
    325 	"Reserved 0x73",				/* 0x73 */
    326 	"Reserved 0x74",				/* 0x74 */
    327 	"Reserved 0x75",				/* 0x75 */
    328 	"Reserved 0x76",				/* 0x76 */
    329 	"Reserved 0x77",				/* 0x77 */
    330 	"Reserved 0x78",				/* 0x78 */
    331 	"Reserved 0x79",				/* 0x79 */
    332 	"Reserved 0x7a",				/* 0x7a */
    333 	"Reserved 0x7b",				/* 0x7b */
    334 	"Reserved 0x7c",				/* 0x7c */
    335 	"Reserved 0x7d",				/* 0x7d */
    336 	"Reserved 0x7e",				/* 0x7e */
    337 	"Reserved 0x7f"					/* 0x7f */
    338 };
    339 
    340 /* Sub-ID for long format from Table 7-17 of 802.15.4-2015 */
    341 static const char *p_mlme_long_names[] = {
    342 	"Reserved 0x00",			/* 0x00 */
    343 	"Reserved 0x01",			/* 0x01 */
    344 	"Reserved 0x02",			/* 0x02 */
    345 	"Reserved 0x03",			/* 0x03 */
    346 	"Reserved 0x04",			/* 0x04 */
    347 	"Reserved 0x05",			/* 0x05 */
    348 	"Reserved 0x06",			/* 0x06 */
    349 	"Reserved 0x07",			/* 0x07 */
    350 	"Vendor Specific MLME Nested IE",	/* 0x08 */
    351 	"Channel Hopping IE",			/* 0x09 */
    352 	"Reserved 0x0a",			/* 0x0a */
    353 	"Reserved 0x0b",			/* 0x0b */
    354 	"Reserved 0x0c",			/* 0x0c */
    355 	"Reserved 0x0d",			/* 0x0d */
    356 	"Reserved 0x0e",			/* 0x0e */
    357 	"Reserved 0x0f"				/* 0x0f */
    358 };
    359 
    360 /* MAC commands from Table 7-49 of 802.15.4-2015 */
    361 static const char *mac_c_names[] = {
    362 	"Reserved 0x00",				/* 0x00 */
    363 	"Association Request command",			/* 0x01 */
    364 	"Association Response command",			/* 0x02 */
    365 	"Disassociation Notification command",		/* 0x03 */
    366 	"Data Request command",				/* 0x04 */
    367 	"PAN ID Conflict Notification command",		/* 0x05 */
    368 	"Orphan Notification command",			/* 0x06 */
    369 	"Beacon Request command",			/* 0x07 */
    370 	"Coordinator realignment command",		/* 0x08 */
    371 	"GTS request command",				/* 0x09 */
    372 	"TRLE Management Request command",		/* 0x0a */
    373 	"TRLE Management Response command",		/* 0x0b */
    374 	"Reserved 0x0c",				/* 0x0c */
    375 	"Reserved 0x0d",				/* 0x0d */
    376 	"Reserved 0x0e",				/* 0x0e */
    377 	"Reserved 0x0f",				/* 0x0f */
    378 	"Reserved 0x10",				/* 0x10 */
    379 	"Reserved 0x11",				/* 0x11 */
    380 	"Reserved 0x12",				/* 0x12 */
    381 	"DSME Association Request command",		/* 0x13 */
    382 	"DSME Association Response command",		/* 0x14 */
    383 	"DSME GTS Request command",			/* 0x15 */
    384 	"DSME GTS Response command",			/* 0x16 */
    385 	"DSME GTS Notify command",			/* 0x17 */
    386 	"DSME Information Request command",		/* 0x18 */
    387 	"DSME Information Response command",		/* 0x19 */
    388 	"DSME Beacon Allocation Notification command",	/* 0x1a */
    389 	"DSME Beacon Collision Notification command",	/* 0x1b */
    390 	"DSME Link Report command",			/* 0x1c */
    391 	"Reserved 0x1d",				/* 0x1d */
    392 	"Reserved 0x1e",				/* 0x1e */
    393 	"Reserved 0x1f",				/* 0x1f */
    394 	"RIT Data Request command",			/* 0x20 */
    395 	"DBS Request command",				/* 0x21 */
    396 	"DBS Response command",				/* 0x22 */
    397 	"RIT Data Response command",			/* 0x23 */
    398 	"Vendor Specific command",			/* 0x24 */
    399 	"Reserved 0x25",				/* 0x25 */
    400 	"Reserved 0x26",				/* 0x26 */
    401 	"Reserved 0x27",				/* 0x27 */
    402 	"Reserved 0x28",				/* 0x28 */
    403 	"Reserved 0x29",				/* 0x29 */
    404 	"Reserved 0x2a",				/* 0x2a */
    405 	"Reserved 0x2b",				/* 0x2b */
    406 	"Reserved 0x2c",				/* 0x2c */
    407 	"Reserved 0x2d",				/* 0x2d */
    408 	"Reserved 0x2e",				/* 0x2e */
    409 	"Reserved 0x2f"					/* 0x2f */
    410 };
    411 
    412 /*
    413  * Frame Control subfields.
    414  */
    415 #define FC_FRAME_TYPE(fc)              ((fc) & 0x7)
    416 #define FC_FRAME_VERSION(fc)           (((fc) >> 12) & 0x3)
    417 
    418 #define FC_ADDRESSING_MODE_NONE         0x00
    419 #define FC_ADDRESSING_MODE_RESERVED     0x01
    420 #define FC_ADDRESSING_MODE_SHORT        0x02
    421 #define FC_ADDRESSING_MODE_LONG         0x03
    422 
    423 /*
    424  * IEEE 802.15.4 CRC 16 function. This is using the CCITT polynomial of 0x1021,
    425  * but the initial value is 0, and the bits are reversed for both in and out.
    426  * See section 7.2.10 of 802.15.4-2015 for more information.
    427  */
    428 static uint16_t
    429 ieee802_15_4_crc16(netdissect_options *ndo, const u_char *p,
    430 		   u_int data_len)
    431 {
    432 	uint16_t crc;
    433 	u_char x, y;
    434 
    435 	crc = 0x0000; /* Note, initial value is 0x0000 not 0xffff. */
    436 
    437 	while (data_len != 0){
    438 		y = GET_U_1(p);
    439 		p++;
    440 		/* Reverse bits on input */
    441 		y = (((y & 0xaa) >> 1) | ((y & 0x55) << 1));
    442 		y = (((y & 0xcc) >> 2) | ((y & 0x33) << 2));
    443 		y = (((y & 0xf0) >> 4) | ((y & 0x0f) << 4));
    444 		/* Update CRC */
    445 		x = crc >> 8 ^ y;
    446 		x ^= x >> 4;
    447 		crc = ((uint16_t)(crc << 8)) ^
    448 			((uint16_t)(x << 12)) ^
    449 			((uint16_t)(x << 5)) ^
    450 			((uint16_t)x);
    451 		data_len--;
    452 	}
    453 	/* Reverse bits on output */
    454 	crc = (((crc & 0xaaaa) >> 1) | ((crc & 0x5555) << 1));
    455 	crc = (((crc & 0xcccc) >> 2) | ((crc & 0x3333) << 2));
    456 	crc = (((crc & 0xf0f0) >> 4) | ((crc & 0x0f0f) << 4));
    457 	crc = (((crc & 0xff00) >> 8) | ((crc & 0x00ff) << 8));
    458 	return crc;
    459 }
    460 
    461 /*
    462  * Reverses the bits of the 32-bit word.
    463  */
    464 static uint32_t
    465 ieee802_15_4_reverse32(uint32_t x)
    466 {
    467 	x = ((x & 0x55555555) <<  1) | ((x >>  1) & 0x55555555);
    468 	x = ((x & 0x33333333) <<  2) | ((x >>  2) & 0x33333333);
    469 	x = ((x & 0x0F0F0F0F) <<  4) | ((x >>  4) & 0x0F0F0F0F);
    470 	x = (x << 24) | ((x & 0xFF00) << 8) |
    471 		((x >> 8) & 0xFF00) | (x >> 24);
    472 	return x;
    473 }
    474 
    475 /*
    476  * IEEE 802.15.4 CRC 32 function. This is using the ANSI X3.66-1979 polynomial of
    477  * 0x04C11DB7, but the initial value is 0, and the bits are reversed for both
    478  * in and out. See section 7.2.10 of 802.15.4-2015 for more information.
    479  */
    480 static uint32_t
    481 ieee802_15_4_crc32(netdissect_options *ndo, const u_char *p,
    482 		   u_int data_len)
    483 {
    484 	uint32_t crc, byte;
    485 	int b;
    486 
    487 	crc = 0x00000000; /* Note, initial value is 0x00000000 not 0xffffffff */
    488 
    489 	while (data_len != 0){
    490 		byte = GET_U_1(p);
    491 		p++;
    492 		/* Reverse bits on input */
    493 		byte = ieee802_15_4_reverse32(byte);
    494 		/* Update CRC */
    495 		for(b = 0; b <= 7; b++) {
    496 		  if ((int) (crc ^ byte) < 0)
    497 		    crc = (crc << 1) ^ 0x04C11DB7;
    498 		  else
    499 		    crc = crc << 1;
    500 		  byte = byte << 1;
    501 		}
    502 		data_len--;
    503 	}
    504 	/* Reverse bits on output */
    505 	crc = ieee802_15_4_reverse32(crc);
    506 	return crc;
    507 }
    508 
    509 /*
    510  * Find out the address length based on the address type. See table 7-3 of
    511  * 802.15.4-2015. Returns the address length.
    512  */
    513 static int
    514 ieee802_15_4_addr_len(uint16_t addr_type)
    515 {
    516 	switch (addr_type) {
    517 	case FC_ADDRESSING_MODE_NONE: /* None. */
    518 		return 0;
    519 		break;
    520 	case FC_ADDRESSING_MODE_RESERVED: /* Reserved, there used to be 8-bit
    521 					   * address type in one amendment, but
    522 					   * that and the feature using it was
    523 					   * removed during 802.15.4-2015
    524 					   * maintenance process. */
    525 		return -1;
    526 		break;
    527 	case FC_ADDRESSING_MODE_SHORT: /* Short. */
    528 		return 2;
    529 		break;
    530 	case FC_ADDRESSING_MODE_LONG: /* Extended. */
    531 		return 8;
    532 		break;
    533 	}
    534 	return 0;
    535 }
    536 
    537 /*
    538  * Print out the ieee 802.15.4 address.
    539  */
    540 static void
    541 ieee802_15_4_print_addr(netdissect_options *ndo, const u_char *p,
    542 			int dst_addr_len)
    543 {
    544 	switch (dst_addr_len) {
    545 	case 0:
    546 		ND_PRINT("none");
    547 		break;
    548 	case 2:
    549 		ND_PRINT("%04x", GET_LE_U_2(p));
    550 		break;
    551 	case 8:
    552 		ND_PRINT("%s", GET_LE64ADDR_STRING(p));
    553 		break;
    554 	}
    555 }
    556 
    557 /*
    558  * Beacon frame superframe specification structure. Used in the old Beacon
    559  * frames, and in the DSME PAN Descriptor IE. See section 7.3.1.3 of the
    560  * 802.15.4-2015.
    561  */
    562 static void
    563 ieee802_15_4_print_superframe_specification(netdissect_options *ndo,
    564 					    uint16_t ss)
    565 {
    566 	if (ndo->ndo_vflag < 1) {
    567 		return;
    568 	}
    569 	ND_PRINT("\n\tBeacon order = %d, Superframe order = %d, ",
    570 		 (ss & 0xf), ((ss >> 4) & 0xf));
    571 	ND_PRINT("Final CAP Slot = %d",
    572 		 ((ss >> 8) & 0xf));
    573 	if (CHECK_BIT(ss, 12)) { ND_PRINT(", BLE enabled"); }
    574 	if (CHECK_BIT(ss, 14)) { ND_PRINT(", PAN Coordinator"); }
    575 	if (CHECK_BIT(ss, 15)) { ND_PRINT(", Association Permit"); }
    576 }
    577 
    578 /*
    579  * Beacon frame gts info structure. Used in the old Beacon frames, and
    580  * in the DSME PAN Descriptor IE. See section 7.3.1.4 of 802.15.4-2015.
    581  *
    582  * Returns number of byts consumed from the packet or -1 in case of error.
    583  */
    584 static int
    585 ieee802_15_4_print_gts_info(netdissect_options *ndo,
    586 			    const u_char *p,
    587 			    u_int data_len)
    588 {
    589 	uint8_t gts_spec, gts_cnt;
    590 	u_int len;
    591 	int i;
    592 
    593 	gts_spec = GET_U_1(p);
    594 	gts_cnt = gts_spec & 0x7;
    595 
    596 	if (gts_cnt == 0) {
    597 		if (ndo->ndo_vflag > 0) {
    598 			ND_PRINT("\n\tGTS Descriptor Count = %d, ", gts_cnt);
    599 		}
    600 		return 1;
    601 	}
    602 	len = 1 + 1 + gts_cnt * 3;
    603 
    604 	if (data_len < len) {
    605 		ND_PRINT(" [ERROR: Truncated GTS Info List]");
    606 		return -1;
    607 	}
    608 	if (ndo->ndo_vflag < 2) {
    609 		return len;
    610 	}
    611 	ND_PRINT("GTS Descriptor Count = %d, ", gts_cnt);
    612 	ND_PRINT("GTS Directions Mask = %02x, [ ",
    613 		 GET_U_1(p + 1) & 0x7f);
    614 
    615 	for(i = 0; i < gts_cnt; i++) {
    616 		ND_PRINT("[ ");
    617 		ieee802_15_4_print_addr(ndo, p + 2 + i * 3, 2);
    618 		ND_PRINT(", Start slot = %d, Length = %d ] ",
    619 			 GET_U_1(p + 2 + i * 3 + 1) & 0x0f,
    620 			 (GET_U_1(p + 2 + i * 3 + 1) >> 4) & 0x0f);
    621 	}
    622 	ND_PRINT("]");
    623 	return len;
    624 }
    625 
    626 /*
    627  * Beacon frame pending address structure. Used in the old Beacon frames, and
    628  * in the DSME PAN Descriptor IE. See section 7.3.1.5 of 802.15.4-2015.
    629  *
    630  * Returns number of byts consumed from the packet or -1 in case of error.
    631  */
    632 static int16_t
    633 ieee802_15_4_print_pending_addresses(netdissect_options *ndo,
    634 				     const u_char *p,
    635 				     u_int data_len)
    636 {
    637 	uint8_t pas, s_cnt, e_cnt, len, i;
    638 
    639 	pas = GET_U_1(p);
    640 	s_cnt = pas & 0x7;
    641 	e_cnt = (pas >> 4) & 0x7;
    642 	len = 1 + s_cnt * 2 + e_cnt * 8;
    643 	if (ndo->ndo_vflag > 0) {
    644 		ND_PRINT("\n\tPending address list, "
    645 			 "# short addresses = %d, # extended addresses = %d",
    646 			 s_cnt, e_cnt);
    647 	}
    648 	if (data_len < len) {
    649 		ND_PRINT(" [ERROR: Pending address list truncated]");
    650 		return -1;
    651 	}
    652 	if (ndo->ndo_vflag < 2) {
    653 		return len;
    654 	}
    655 	if (s_cnt != 0) {
    656 		ND_PRINT(", Short address list = [ ");
    657 		for(i = 0; i < s_cnt; i++) {
    658 			ieee802_15_4_print_addr(ndo, p + 1 + i * 2, 2);
    659 			ND_PRINT(" ");
    660 		}
    661 		ND_PRINT("]");
    662 	}
    663 	if (e_cnt != 0) {
    664 		ND_PRINT(", Extended address list = [ ");
    665 		for(i = 0; i < e_cnt; i++) {
    666 			ieee802_15_4_print_addr(ndo, p + 1 + s_cnt * 2 +
    667 						i * 8, 8);
    668 			ND_PRINT(" ");
    669 		}
    670 		ND_PRINT("]");
    671 	}
    672 	return len;
    673 }
    674 
    675 /*
    676  * Print header ie content.
    677  */
    678 static void
    679 ieee802_15_4_print_header_ie(netdissect_options *ndo,
    680 			     const u_char *p,
    681 			     uint16_t ie_len,
    682 			     int element_id)
    683 {
    684 	int i;
    685 
    686 	switch (element_id) {
    687 	case 0x00: /* Vendor Specific Header IE */
    688 		if (ie_len < 3) {
    689 			ND_PRINT("[ERROR: Vendor OUI missing]");
    690 		} else {
    691 			ND_PRINT("OUI = 0x%02x%02x%02x, ", GET_U_1(p),
    692 				 GET_U_1(p + 1), GET_U_1(p + 2));
    693 			ND_PRINT("Data = ");
    694 			for(i = 3; i < ie_len; i++) {
    695 				ND_PRINT("%02x ", GET_U_1(p + i));
    696 			}
    697 		}
    698 		break;
    699 	case 0x1a: /* LE CSL IE */
    700 		if (ie_len < 4) {
    701 			ND_PRINT("[ERROR: Truncated CSL IE]");
    702 		} else {
    703 			ND_PRINT("CSL Phase = %d, CSL Period = %d",
    704 				 GET_LE_U_2(p), GET_LE_U_2(p + 2));
    705 			if (ie_len >= 6) {
    706 				ND_PRINT(", Rendezvous time = %d",
    707 					 GET_LE_U_2(p + 4));
    708 			}
    709 			if (ie_len != 4 && ie_len != 6) {
    710 				ND_PRINT(" [ERROR: CSL IE length wrong]");
    711 			}
    712 		}
    713 		break;
    714 	case 0x1b: /* LE RIT IE */
    715 		if (ie_len < 4) {
    716 			ND_PRINT("[ERROR: Truncated RIT IE]");
    717 		} else {
    718 			ND_PRINT("Time to First Listen = %d, # of Repeat Listen = %d, Repeat Listen Interval = %d",
    719 				 GET_U_1(p),
    720 				 GET_U_1(p + 1),
    721 				 GET_LE_U_2(p + 2));
    722 		}
    723 		break;
    724 	case 0x1c: /* DSME PAN Descriptor IE */
    725 		/*FALLTHROUGH*/
    726 	case 0x21: /* Extended DSME PAN descriptor IE */
    727 		if (ie_len < 2) {
    728 			ND_PRINT("[ERROR: Truncated DSME PAN IE]");
    729 		} else {
    730 			uint16_t ss, ptr, ulen;
    731 			int16_t len;
    732 			int hopping_present;
    733 
    734 			hopping_present = 0;
    735 
    736 			ss = GET_LE_U_2(p);
    737 			ieee802_15_4_print_superframe_specification(ndo, ss);
    738 			if (ie_len < 3) {
    739 				ND_PRINT("[ERROR: Truncated before pending addresses field]");
    740 				break;
    741 			}
    742 			ptr = 2;
    743 			len = ieee802_15_4_print_pending_addresses(ndo,
    744 								   p + ptr,
    745 								   ie_len -
    746 								   ptr);
    747 			if (len < 0) {
    748 				break;
    749 			}
    750 			ptr += len;
    751 
    752 			if (element_id == 0x21) {
    753 				/* Extended version. */
    754 				if (ie_len < ptr + 2) {
    755 					ND_PRINT("[ERROR: Truncated before DSME Superframe Specification]");
    756 					break;
    757 				}
    758 				ss = GET_LE_U_2(p + ptr);
    759 				ptr += 2;
    760 				ND_PRINT("Multi-superframe Order = %d", ss & 0xff);
    761 				ND_PRINT(", %s", ((ss & 0x100) ?
    762 						  "Channel hopping mode" :
    763 						  "Channel adaptation mode"));
    764 				if (ss & 0x400) {
    765 					ND_PRINT(", CAP reduction enabled");
    766 				}
    767 				if (ss & 0x800) {
    768 					ND_PRINT(", Deferred beacon enabled");
    769 				}
    770 				if (ss & 0x1000) {
    771 					ND_PRINT(", Hopping Sequence Present");
    772 					hopping_present = 1;
    773 				}
    774 			} else {
    775 				if (ie_len < ptr + 1) {
    776 					ND_PRINT("[ERROR: Truncated before DSME Superframe Specification]");
    777 					break;
    778 				}
    779 				ss = GET_U_1(p + ptr);
    780 				ptr++;
    781 				ND_PRINT("Multi-superframe Order = %d",
    782 					 ss & 0x0f);
    783 				ND_PRINT(", %s", ((ss & 0x10) ?
    784 						  "Channel hopping mode" :
    785 						  "Channel adaptation mode"));
    786 				if (ss & 0x40) {
    787 					ND_PRINT(", CAP reduction enabled");
    788 				}
    789 				if (ss & 0x80) {
    790 					ND_PRINT(", Deferred beacon enabled");
    791 				}
    792 			}
    793 			if (ie_len < ptr + 8) {
    794 				ND_PRINT(" [ERROR: Truncated before Time synchronization specification]");
    795 				break;
    796 			}
    797 			ND_PRINT("Beacon timestamp = %" PRIu64 ", offset = %d",
    798 				 GET_LE_U_6(p + ptr),
    799 				 GET_LE_U_2(p + ptr + 6));
    800 			ptr += 8;
    801 			if (ie_len < ptr + 4) {
    802 				ND_PRINT(" [ERROR: Truncated before Beacon Bitmap]");
    803 				break;
    804 			}
    805 
    806 			ulen = GET_LE_U_2(p + ptr + 2);
    807 			ND_PRINT("SD Index = %d, Bitmap len = %d, ",
    808 				 GET_LE_U_2(p + ptr), ulen);
    809 			ptr += 4;
    810 			if (ie_len < ptr + ulen) {
    811 				ND_PRINT(" [ERROR: Truncated in SD bitmap]");
    812 				break;
    813 			}
    814 			ND_PRINT(" SD Bitmap = ");
    815 			for(i = 0; i < ulen; i++) {
    816 				ND_PRINT("%02x ", GET_U_1(p + ptr + i));
    817 			}
    818 			ptr += ulen;
    819 
    820 			if (ie_len < ptr + 5) {
    821 				ND_PRINT(" [ERROR: Truncated before Channel hopping specification]");
    822 				break;
    823 			}
    824 
    825 			ulen = GET_LE_U_2(p + ptr + 4);
    826 			ND_PRINT("Hopping Seq ID = %d, PAN Coordinator BSN = %d, "
    827 				 "Channel offset = %d, Bitmap length = %d, ",
    828 				 GET_U_1(p + ptr),
    829 				 GET_U_1(p + ptr + 1),
    830 				 GET_LE_U_2(p + ptr + 2),
    831 				 ulen);
    832 			ptr += 5;
    833 			if (ie_len < ptr + ulen) {
    834 				ND_PRINT(" [ERROR: Truncated in Channel offset bitmap]");
    835 				break;
    836 			}
    837 			ND_PRINT(" Channel offset bitmap = ");
    838 			for(i = 0; i < ulen; i++) {
    839 				ND_PRINT("%02x ", GET_U_1(p + ptr + i));
    840 			}
    841 			ptr += ulen;
    842 			if (hopping_present) {
    843 				if (ie_len < ptr + 1) {
    844 					ND_PRINT(" [ERROR: Truncated in Hopping Sequence length]");
    845 					break;
    846 				}
    847 				ulen = GET_U_1(p + ptr);
    848 				ptr++;
    849 				ND_PRINT("Hopping Seq length = %d [ ", ulen);
    850 
    851 				/* The specification is not clear how the
    852 				   hopping sequence is encoded, I assume two
    853 				   octet unsigned integers for each channel. */
    854 
    855 				if (ie_len < ptr + ulen * 2) {
    856 					ND_PRINT(" [ERROR: Truncated in Channel offset bitmap]");
    857 					break;
    858 				}
    859 				for(i = 0; i < ulen; i++) {
    860 					ND_PRINT("%02x ",
    861 						 GET_LE_U_2(p + ptr + i * 2));
    862 				}
    863 				ND_PRINT("]");
    864 				ptr += ulen * 2;
    865 			}
    866 		}
    867 		break;
    868 	case 0x1d: /* Rendezvous Tome IE */
    869 		if (ie_len != 4) {
    870 			ND_PRINT("[ERROR: Length != 2]");
    871 		} else {
    872 			uint16_t r_time, w_u_interval;
    873 			r_time = GET_LE_U_2(p);
    874 			w_u_interval = GET_LE_U_2(p + 2);
    875 
    876 			ND_PRINT("Rendezvous time = %d, Wake-up Interval = %d",
    877 				 r_time, w_u_interval);
    878 		}
    879 		break;
    880 	case 0x1e: /* Time correction IE */
    881 		if (ie_len != 2) {
    882 			ND_PRINT("[ERROR: Length != 2]");
    883 		} else {
    884 			uint16_t val;
    885 			int16_t timecorr;
    886 
    887 			val = GET_LE_U_2(p);
    888 			if (val & 0x8000) { ND_PRINT("Negative "); }
    889 			val &= 0xfff;
    890 			val <<= 4;
    891 			timecorr = val;
    892 			timecorr >>= 4;
    893 
    894 			ND_PRINT("Ack time correction = %d, ", timecorr);
    895 		}
    896 		break;
    897 	case 0x22: /* Fragment Sequence Content Description IE */
    898 		/* XXX Not implemented */
    899 	case 0x23: /* Simplified Superframe Specification IE */
    900 		/* XXX Not implemented */
    901 	case 0x24: /* Simplified GTS Specification IE */
    902 		/* XXX Not implemented */
    903 	case 0x25: /* LECIM Capabilities IE */
    904 		/* XXX Not implemented */
    905 	case 0x26: /* TRLE Descriptor IE */
    906 		/* XXX Not implemented */
    907 	case 0x27: /* RCC Capabilities IE */
    908 		/* XXX Not implemented */
    909 	case 0x28: /* RCCN Descriptor IE */
    910 		/* XXX Not implemented */
    911 	case 0x29: /* Global Time IE */
    912 		/* XXX Not implemented */
    913 	case 0x2b: /* DA IE */
    914 		/* XXX Not implemented */
    915 	default:
    916 		ND_PRINT("IE Data = ");
    917 		for(i = 0; i < ie_len; i++) {
    918 			ND_PRINT("%02x ", GET_U_1(p + i));
    919 		}
    920 		break;
    921 	}
    922 }
    923 
    924 /*
    925  * Parse and print Header IE list. See 7.4.2 of 802.15.4-2015 for
    926  * more information.
    927  *
    928  * Returns number of byts consumed from the packet or -1 in case of error.
    929  */
    930 static int
    931 ieee802_15_4_print_header_ie_list(netdissect_options *ndo,
    932 				  const u_char *p,
    933 				  u_int caplen,
    934 				  int *payload_ie_present)
    935 {
    936 	int len, ie, element_id, i;
    937 	uint16_t ie_len;
    938 
    939 	*payload_ie_present = 0;
    940 	len = 0;
    941 	do {
    942 		if (caplen < 2) {
    943 			ND_PRINT("[ERROR: Truncated header IE]");
    944 			return -1;
    945 		}
    946 		/* Extract IE Header */
    947 		ie = GET_LE_U_2(p);
    948 		if (CHECK_BIT(ie, 15)) {
    949 			ND_PRINT("[ERROR: Header IE with type 1] ");
    950 		}
    951 		/* Get length and Element ID */
    952 		ie_len = ie & 0x7f;
    953 		element_id = (ie >> 7) & 0xff;
    954 		if (element_id > 127) {
    955 			ND_PRINT("Reserved Element ID %02x, length = %d ",
    956 				 element_id, ie_len);
    957 		} else {
    958 			if (ie_len == 0) {
    959 				ND_PRINT("\n\t%s [", h_ie_names[element_id]);
    960 			} else {
    961 				ND_PRINT("\n\t%s [ length = %d, ",
    962 					 h_ie_names[element_id], ie_len);
    963 			}
    964 		}
    965 		if (caplen < 2U + ie_len) {
    966 			ND_PRINT("[ERROR: Truncated IE data]");
    967 			return -1;
    968 		}
    969 		/* Skip header */
    970 		p += 2;
    971 
    972 		/* Parse and print content. */
    973 		if (ndo->ndo_vflag > 3 && ie_len != 0) {
    974 			ieee802_15_4_print_header_ie(ndo, p,
    975 						     ie_len, element_id);
    976 		} else {
    977 			if (ie_len != 0) {
    978 				ND_PRINT("IE Data = ");
    979 				for(i = 0; i < ie_len; i++) {
    980 					ND_PRINT("%02x ", GET_U_1(p + i));
    981 				}
    982 			}
    983 		}
    984 		ND_PRINT("] ");
    985 		len += 2 + ie_len;
    986 		p += ie_len;
    987 		caplen -= 2 + ie_len;
    988 		if (element_id == 0x7e) {
    989 			*payload_ie_present = 1;
    990 			break;
    991 		}
    992 		if (element_id == 0x7f) {
    993 			break;
    994 		}
    995 	} while (caplen != 0);
    996 	return len;
    997 }
    998 
    999 /*
   1000  * Print MLME ie content.
   1001  */
   1002 static void
   1003 ieee802_15_4_print_mlme_ie(netdissect_options *ndo,
   1004 			   const u_char *p,
   1005 			   uint16_t sub_ie_len,
   1006 			   int sub_id)
   1007 {
   1008 	int i, j;
   1009 	uint16_t len;
   1010 
   1011 	/* Note, as there is no overlap with the long and short
   1012 	   MLME sub IDs, we can just use one switch here. */
   1013 	switch (sub_id) {
   1014 	case 0x08: /* Vendor Specific Nested IE */
   1015 		if (sub_ie_len < 3) {
   1016 			ND_PRINT("[ERROR: Vendor OUI missing]");
   1017 		} else {
   1018 			ND_PRINT("OUI = 0x%02x%02x%02x, ",
   1019 				 GET_U_1(p),
   1020 				 GET_U_1(p + 1),
   1021 				 GET_U_1(p + 2));
   1022 			ND_PRINT("Data = ");
   1023 			for(i = 3; i < sub_ie_len; i++) {
   1024 				ND_PRINT("%02x ", GET_U_1(p + i));
   1025 			}
   1026 		}
   1027 		break;
   1028 	case 0x09: /* Channel Hopping IE */
   1029 		if (sub_ie_len < 1) {
   1030 			ND_PRINT("[ERROR: Hopping sequence ID missing]");
   1031 		} else if (sub_ie_len == 1) {
   1032 			ND_PRINT("Hopping Sequence ID = %d", GET_U_1(p));
   1033 			p++;
   1034 			sub_ie_len--;
   1035 		} else {
   1036 			uint16_t channel_page, number_of_channels;
   1037 
   1038 			ND_PRINT("Hopping Sequence ID = %d", GET_U_1(p));
   1039 			p++;
   1040 			sub_ie_len--;
   1041 			if (sub_ie_len < 7) {
   1042 				ND_PRINT("[ERROR: IE truncated]");
   1043 				break;
   1044 			}
   1045 			channel_page = GET_U_1(p);
   1046 			number_of_channels = GET_LE_U_2(p + 1);
   1047 			ND_PRINT("Channel Page = %d, Number of Channels = %d, ",
   1048 				 channel_page, number_of_channels);
   1049 			ND_PRINT("Phy Configuration = 0x%08x, ",
   1050 				 GET_LE_U_4(p + 3));
   1051 			p += 7;
   1052 			sub_ie_len -= 7;
   1053 			if (channel_page == 9 || channel_page == 10) {
   1054 				len = (number_of_channels + 7) / 8;
   1055 				if (sub_ie_len < len) {
   1056 					ND_PRINT("[ERROR: IE truncated]");
   1057 					break;
   1058 				}
   1059 				ND_PRINT("Extended bitmap = 0x");
   1060 				for(i = 0; i < len; i++) {
   1061 					ND_PRINT("%02x", GET_U_1(p + i));
   1062 				}
   1063 				ND_PRINT(", ");
   1064 				p += len;
   1065 				sub_ie_len -= len;
   1066 			}
   1067 			if (sub_ie_len < 2) {
   1068 				ND_PRINT("[ERROR: IE truncated]");
   1069 				break;
   1070 			}
   1071 			len = GET_LE_U_2(p);
   1072 			p += 2;
   1073 			sub_ie_len -= 2;
   1074 			ND_PRINT("Hopping Seq length = %d [ ", len);
   1075 
   1076 			if (sub_ie_len < len * 2) {
   1077 				ND_PRINT(" [ERROR: IE truncated]");
   1078 				break;
   1079 			}
   1080 			for(i = 0; i < len; i++) {
   1081 				ND_PRINT("%02x ", GET_LE_U_2(p + i * 2));
   1082 			}
   1083 			ND_PRINT("]");
   1084 			p += len * 2;
   1085 			sub_ie_len -= len * 2;
   1086 			if (sub_ie_len < 2) {
   1087 				ND_PRINT("[ERROR: IE truncated]");
   1088 				break;
   1089 			}
   1090 			ND_PRINT("Current hop = %d", GET_LE_U_2(p));
   1091 		}
   1092 
   1093 		break;
   1094 	case 0x1a: /* TSCH Synchronization IE. */
   1095 		if (sub_ie_len < 6) {
   1096 			ND_PRINT("[ERROR: Length != 6]");
   1097 		}
   1098 		ND_PRINT("ASN = %010" PRIx64 ", Join Metric = %d ",
   1099 			 GET_LE_U_5(p), GET_U_1(p + 5));
   1100 		break;
   1101 	case 0x1b: /* TSCH Slotframe and Link IE. */
   1102 		{
   1103 			int sf_num, off, links, opts;
   1104 
   1105 			if (sub_ie_len < 1) {
   1106 				ND_PRINT("[ERROR: Truncated IE]");
   1107 				break;
   1108 			}
   1109 			sf_num = GET_U_1(p);
   1110 			ND_PRINT("Slotframes = %d ", sf_num);
   1111 			off = 1;
   1112 			for(i = 0; i < sf_num; i++) {
   1113 				if (sub_ie_len < off + 4) {
   1114 					ND_PRINT("[ERROR: Truncated IE before slotframes]");
   1115 					break;
   1116 				}
   1117 				links = GET_U_1(p + off + 3);
   1118 				ND_PRINT("\n\t\t\t[ Handle %d, size = %d, links = %d ",
   1119 					 GET_U_1(p + off),
   1120 					 GET_LE_U_2(p + off + 1),
   1121 					 links);
   1122 				off += 4;
   1123 				for(j = 0; j < links; j++) {
   1124 					if (sub_ie_len < off + 5) {
   1125 						ND_PRINT("[ERROR: Truncated IE links]");
   1126 						break;
   1127 					}
   1128 					opts = GET_U_1(p + off + 4);
   1129 					ND_PRINT("\n\t\t\t\t[ Timeslot =  %d, Offset = %d, Options = ",
   1130 						 GET_LE_U_2(p + off),
   1131 						 GET_LE_U_2(p + off + 2));
   1132 					if (opts & 0x1) { ND_PRINT("TX "); }
   1133 					if (opts & 0x2) { ND_PRINT("RX "); }
   1134 					if (opts & 0x4) { ND_PRINT("Shared "); }
   1135 					if (opts & 0x8) {
   1136 						ND_PRINT("Timekeeping ");
   1137 					}
   1138 					if (opts & 0x10) {
   1139 						ND_PRINT("Priority ");
   1140 					}
   1141 					off += 5;
   1142 					ND_PRINT("] ");
   1143 				}
   1144 				ND_PRINT("] ");
   1145 			}
   1146 		}
   1147 		break;
   1148 	case 0x1c: /* TSCH Timeslot IE. */
   1149 		if (sub_ie_len == 1) {
   1150 			ND_PRINT("Time slot ID = %d ", GET_U_1(p));
   1151 		} else if (sub_ie_len == 25) {
   1152 			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 ",
   1153 				 GET_U_1(p),
   1154 				 GET_LE_U_2(p + 1),
   1155 				 GET_LE_U_2(p + 3),
   1156 				 GET_LE_U_2(p + 5),
   1157 				 GET_LE_U_2(p + 7),
   1158 				 GET_LE_U_2(p + 9),
   1159 				 GET_LE_U_2(p + 11),
   1160 				 GET_LE_U_2(p + 13),
   1161 				 GET_LE_U_2(p + 15),
   1162 				 GET_LE_U_2(p + 17),
   1163 				 GET_LE_U_2(p + 19),
   1164 				 GET_LE_U_2(p + 21),
   1165 				 GET_LE_U_2(p + 23));
   1166 		} else if (sub_ie_len == 27) {
   1167 			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 ",
   1168 				 GET_U_1(p),
   1169 				 GET_LE_U_2(p + 1),
   1170 				 GET_LE_U_2(p + 3),
   1171 				 GET_LE_U_2(p + 5),
   1172 				 GET_LE_U_2(p + 7),
   1173 				 GET_LE_U_2(p + 9),
   1174 				 GET_LE_U_2(p + 11),
   1175 				 GET_LE_U_2(p + 13),
   1176 				 GET_LE_U_2(p + 15),
   1177 				 GET_LE_U_2(p + 17),
   1178 				 GET_LE_U_2(p + 19),
   1179 				 GET_LE_U_3(p + 21),
   1180 				 GET_LE_U_3(p + 24));
   1181 		} else {
   1182 			ND_PRINT("[ERROR: Length not 1, 25, or 27]");
   1183 			ND_PRINT("\n\t\t\tIE Data = ");
   1184 			for(i = 0; i < sub_ie_len; i++) {
   1185 				ND_PRINT("%02x ", GET_U_1(p + i));
   1186 			}
   1187 		}
   1188 		break;
   1189 	case 0x1d: /* Hopping timing IE */
   1190 		/* XXX Not implemented */
   1191 	case 0x1e: /* Enhanced Beacon Filter IE */
   1192 		/* XXX Not implemented */
   1193 	case 0x1f: /* MAC Metrics IE */
   1194 		/* XXX Not implemented */
   1195 	case 0x20: /* All MAC Metrics IE */
   1196 		/* XXX Not implemented */
   1197 	case 0x21: /* Coexistence Specification IE */
   1198 		/* XXX Not implemented */
   1199 	case 0x22: /* SUN Device Capabilities IE */
   1200 		/* XXX Not implemented */
   1201 	case 0x23: /* SUN FSK Generic PHY IE */
   1202 		/* XXX Not implemented */
   1203 	case 0x24: /* Mode Switch Parameter IE */
   1204 		/* XXX Not implemented */
   1205 	case 0x25: /* PHY Parameter Change IE */
   1206 		/* XXX Not implemented */
   1207 	case 0x26: /* O-QPSK PHY Mode IE */
   1208 		/* XXX Not implemented */
   1209 	case 0x27: /* PCA Allocation IE */
   1210 		/* XXX Not implemented */
   1211 	case 0x28: /* LECIM DSSS Operating Mode IE */
   1212 		/* XXX Not implemented */
   1213 	case 0x29: /* LECIM FSK Operating Mode IE */
   1214 		/* XXX Not implemented */
   1215 	case 0x2b: /* TVWS PHY Operating Mode Description IE */
   1216 		/* XXX Not implemented */
   1217 	case 0x2c: /* TVWS Device Capabilities IE */
   1218 		/* XXX Not implemented */
   1219 	case 0x2d: /* TVWS Device Category IE */
   1220 		/* XXX Not implemented */
   1221 	case 0x2e: /* TVWS Device Identification IE */
   1222 		/* XXX Not implemented */
   1223 	case 0x2f: /* TVWS Device Location IE */
   1224 		/* XXX Not implemented */
   1225 	case 0x30: /* TVWS Channel Information Query IE */
   1226 		/* XXX Not implemented */
   1227 	case 0x31: /* TVWS Channel Information Source IE */
   1228 		/* XXX Not implemented */
   1229 	case 0x32: /* CTM IE */
   1230 		/* XXX Not implemented */
   1231 	case 0x33: /* Timestamp IE */
   1232 		/* XXX Not implemented */
   1233 	case 0x34: /* Timestamp Difference IE */
   1234 		/* XXX Not implemented */
   1235 	case 0x35: /* TMCTP Specification IE */
   1236 		/* XXX Not implemented */
   1237 	case 0x36: /* TCC PHY Operating Mode IE */
   1238 		/* XXX Not implemented */
   1239 	default:
   1240 		ND_PRINT("IE Data = ");
   1241 		for(i = 0; i < sub_ie_len; i++) {
   1242 			ND_PRINT("%02x ", GET_U_1(p + i));
   1243 		}
   1244 		break;
   1245 	}
   1246 }
   1247 
   1248 /*
   1249  * MLME IE list parsing and printing. See 7.4.3.2 of 802.15.4-2015
   1250  * for more information.
   1251  */
   1252 static void
   1253 ieee802_15_4_print_mlme_ie_list(netdissect_options *ndo,
   1254 				const u_char *p,
   1255 				uint16_t ie_len)
   1256 {
   1257 	int ie, sub_id, i, type;
   1258 	uint16_t sub_ie_len;
   1259 
   1260 	do {
   1261 		if (ie_len < 2) {
   1262 			ND_PRINT("[ERROR: Truncated MLME IE]");
   1263 			return;
   1264 		}
   1265 		/* Extract IE header */
   1266 		ie = GET_LE_U_2(p);
   1267 		type = CHECK_BIT(ie, 15);
   1268 		if (type) {
   1269 			/* Long type */
   1270 			sub_ie_len = ie & 0x3ff;
   1271 			sub_id = (ie >> 11) & 0x0f;
   1272 		} else {
   1273 			sub_ie_len = ie & 0xff;
   1274 			sub_id = (ie >> 8) & 0x7f;
   1275 		}
   1276 
   1277 		/* Skip the IE header */
   1278 		p += 2;
   1279 
   1280 		if (type == 0) {
   1281 			ND_PRINT("\n\t\t%s [ length = %d, ",
   1282 				 p_mlme_short_names[sub_id], sub_ie_len);
   1283 		} else {
   1284 			ND_PRINT("\n\t\t%s [ length = %d, ",
   1285 				 p_mlme_long_names[sub_id], sub_ie_len);
   1286 		}
   1287 
   1288 		if (ie_len < 2 + sub_ie_len) {
   1289 			ND_PRINT("[ERROR: Truncated IE data]");
   1290 			return;
   1291 		}
   1292 		if (sub_ie_len != 0) {
   1293 			if (ndo->ndo_vflag > 3) {
   1294 				ieee802_15_4_print_mlme_ie(ndo, p, sub_ie_len, sub_id);
   1295 			} else if (ndo->ndo_vflag > 2) {
   1296 				ND_PRINT("IE Data = ");
   1297 				for(i = 0; i < sub_ie_len; i++) {
   1298 					ND_PRINT("%02x ", GET_U_1(p + i));
   1299 				}
   1300 			}
   1301 		}
   1302 		ND_PRINT("] ");
   1303 		p += sub_ie_len;
   1304 		ie_len -= 2 + sub_ie_len;
   1305 	} while (ie_len != 0);
   1306 }
   1307 
   1308 /*
   1309  * Multiplexed IE (802.15.9) parsing and printing.
   1310  *
   1311  * Returns number of bytes consumed from packet or -1 in case of error.
   1312  */
   1313 static void
   1314 ieee802_15_4_print_mpx_ie(netdissect_options *ndo,
   1315 			  const u_char *p,
   1316 			  uint16_t ie_len)
   1317 {
   1318 	int transfer_type, tid;
   1319 	int fragment_number, data_start;
   1320 	int i;
   1321 
   1322 	data_start = 0;
   1323 	if (ie_len < 1) {
   1324 		ND_PRINT("[ERROR: Transaction control byte missing]");
   1325 		return;
   1326 	}
   1327 
   1328 	transfer_type = GET_U_1(p) & 0x7;
   1329 	tid = GET_U_1(p) >> 3;
   1330 	switch (transfer_type) {
   1331 	case 0x00: /* Full upper layer frame. */
   1332 	case 0x01: /* Full upper layer frame with small Multiplex ID. */
   1333 		ND_PRINT("Type = Full upper layer fragment%s, ",
   1334 			 (transfer_type == 0x01 ?
   1335 			  " with small Multiplex ID" : ""));
   1336 		if (transfer_type == 0x00) {
   1337 			if (ie_len < 3) {
   1338 				ND_PRINT("[ERROR: Multiplex ID missing]");
   1339 				return;
   1340 			}
   1341 			data_start = 3;
   1342 			ND_PRINT("tid = 0x%02x, Multiplex ID = 0x%04x, ",
   1343 				 tid, GET_LE_U_2(p + 1));
   1344 		} else {
   1345 			data_start = 1;
   1346 			ND_PRINT("Multiplex ID = 0x%04x, ", tid);
   1347 		}
   1348 		break;
   1349 	case 0x02: /* First, or middle, Fragments */
   1350 	case 0x04: /* Last fragment */
   1351 		if (ie_len < 2) {
   1352 			ND_PRINT("[ERROR: fragment number missing]");
   1353 			return;
   1354 		}
   1355 
   1356 		fragment_number = GET_U_1(p + 1);
   1357 		ND_PRINT("Type = %s, tid = 0x%02x, fragment = 0x%02x, ",
   1358 			 (transfer_type == 0x02 ?
   1359 			  (fragment_number == 0 ?
   1360 			   "First fragment" : "Middle fragment") :
   1361 			  "Last fragment"), tid,
   1362 			 fragment_number);
   1363 		data_start = 2;
   1364 		if (fragment_number == 0) {
   1365 			int total_size, multiplex_id;
   1366 
   1367 			if (ie_len < 6) {
   1368 				ND_PRINT("[ERROR: Total upper layer size or multiplex ID missing]");
   1369 				return;
   1370 			}
   1371 			total_size = GET_LE_U_2(p + 2);
   1372 			multiplex_id = GET_LE_U_2(p + 4);
   1373 			ND_PRINT("Total upper layer size = 0x%04x, Multiplex ID = 0x%04x, ",
   1374 				 total_size, multiplex_id);
   1375 			data_start = 6;
   1376 		}
   1377 		break;
   1378 	case 0x06: /* Abort code */
   1379 		if (ie_len == 1) {
   1380 			ND_PRINT("Type = Abort, tid = 0x%02x, no max size given",
   1381 				 tid);
   1382 		} else if (ie_len == 3) {
   1383 			ND_PRINT("Type = Abort, tid = 0x%02x, max size = 0x%04x",
   1384 				 tid, GET_LE_U_2(p + 1));
   1385 		} else {
   1386 			ND_PRINT("Type = Abort, tid = 0x%02x, invalid length = %d (not 1 or 3)",
   1387 				 tid, ie_len);
   1388 			ND_PRINT("Abort data = ");
   1389 			for(i = 1; i < ie_len; i++) {
   1390 				ND_PRINT("%02x ", GET_U_1(p + i));
   1391 			}
   1392 		}
   1393 		return;
   1394 		/* NOTREACHED */
   1395 		break;
   1396 	case 0x03: /* Reserved */
   1397 	case 0x05: /* Reserved */
   1398 	case 0x07: /* Reserved */
   1399 		ND_PRINT("Type = %d (Reserved), tid = 0x%02x, ",
   1400 			 transfer_type, tid);
   1401 		data_start = 1;
   1402 		break;
   1403 	}
   1404 
   1405 	ND_PRINT("Upper layer data = ");
   1406 	for(i = data_start; i < ie_len; i++) {
   1407 		ND_PRINT("%02x ", GET_U_1(p + i));
   1408 	}
   1409 }
   1410 
   1411 /*
   1412  * Payload IE list parsing and printing. See 7.4.3 of 802.15.4-2015
   1413  * for more information.
   1414  *
   1415  * Returns number of byts consumed from the packet or -1 in case of error.
   1416  */
   1417 static int
   1418 ieee802_15_4_print_payload_ie_list(netdissect_options *ndo,
   1419 				   const u_char *p,
   1420 				   u_int caplen)
   1421 {
   1422 	int len, ie, group_id, i;
   1423 	uint16_t ie_len;
   1424 
   1425 	len = 0;
   1426 	do {
   1427 		if (caplen < 2) {
   1428 			ND_PRINT("[ERROR: Truncated header IE]");
   1429 			return -1;
   1430 		}
   1431 		/* Extract IE header */
   1432 		ie = GET_LE_U_2(p);
   1433 		if ((CHECK_BIT(ie, 15)) == 0) {
   1434 			ND_PRINT("[ERROR: Payload IE with type 0] ");
   1435 		}
   1436 		ie_len = ie & 0x3ff;
   1437 		group_id = (ie >> 11) & 0x0f;
   1438 
   1439 		/* Skip the IE header */
   1440 		p += 2;
   1441 		if (ie_len == 0) {
   1442 			ND_PRINT("\n\t%s [", p_ie_names[group_id]);
   1443 		} else {
   1444 			ND_PRINT("\n\t%s [ length = %d, ",
   1445 				 p_ie_names[group_id], ie_len);
   1446 		}
   1447 		if (caplen < 2U + ie_len) {
   1448 			ND_PRINT("[ERROR: Truncated IE data]");
   1449 			return -1;
   1450 		}
   1451 		if (ndo->ndo_vflag > 3 && ie_len != 0) {
   1452 			switch (group_id) {
   1453 			case 0x1: /* MLME IE */
   1454 				ieee802_15_4_print_mlme_ie_list(ndo, p, ie_len);
   1455 				break;
   1456 			case 0x2: /* Vendor Specific Nested IE */
   1457 				if (ie_len < 3) {
   1458 					ND_PRINT("[ERROR: Vendor OUI missing]");
   1459 				} else {
   1460 					ND_PRINT("OUI = 0x%02x%02x%02x, ",
   1461 						 GET_U_1(p),
   1462 						 GET_U_1(p + 1),
   1463 						 GET_U_1(p + 2));
   1464 					ND_PRINT("Data = ");
   1465 					for(i = 3; i < ie_len; i++) {
   1466 						ND_PRINT("%02x ",
   1467 							 GET_U_1(p + i));
   1468 					}
   1469 				}
   1470 				break;
   1471 			case 0x3: /* Multiplexed IE (802.15.9) */
   1472 				ieee802_15_4_print_mpx_ie(ndo, p, ie_len);
   1473 				break;
   1474 			case 0x5: /* IETF IE */
   1475 				if (ie_len < 1) {
   1476 					ND_PRINT("[ERROR: Subtype ID missing]");
   1477 				} else {
   1478 					ND_PRINT("Subtype ID = 0x%02x, Subtype content = ",
   1479 						 GET_U_1(p));
   1480 					for(i = 1; i < ie_len; i++) {
   1481 						ND_PRINT("%02x ",
   1482 							 GET_U_1(p + i));
   1483 					}
   1484 				}
   1485 				break;
   1486 			default:
   1487 				ND_PRINT("IE Data = ");
   1488 				for(i = 0; i < ie_len; i++) {
   1489 					ND_PRINT("%02x ", GET_U_1(p + i));
   1490 				}
   1491 				break;
   1492 			}
   1493 		} else {
   1494 			if (ie_len != 0) {
   1495 				ND_PRINT("IE Data = ");
   1496 				for(i = 0; i < ie_len; i++) {
   1497 					ND_PRINT("%02x ", GET_U_1(p + i));
   1498 				}
   1499 			}
   1500 		}
   1501 		ND_PRINT("]\n\t");
   1502 		len += 2 + ie_len;
   1503 		p += ie_len;
   1504 		caplen -= 2 + ie_len;
   1505 		if (group_id == 0xf) {
   1506 			break;
   1507 		}
   1508 	} while (caplen != 0);
   1509 	return len;
   1510 }
   1511 
   1512 /*
   1513  * Parse and print auxiliary security header.
   1514  *
   1515  * Returns number of byts consumed from the packet or -1 in case of error.
   1516  */
   1517 static int
   1518 ieee802_15_4_print_aux_sec_header(netdissect_options *ndo,
   1519 				  const u_char *p,
   1520 				  u_int caplen,
   1521 				  int *security_level)
   1522 {
   1523 	int sc, key_id_mode, len;
   1524 
   1525 	if (caplen < 1) {
   1526 		ND_PRINT("[ERROR: Truncated before Aux Security Header]");
   1527 		return -1;
   1528 	}
   1529 	sc = GET_U_1(p);
   1530 	len = 1;
   1531 	*security_level = sc & 0x7;
   1532 	key_id_mode = (sc >> 3) & 0x3;
   1533 
   1534 	caplen -= 1;
   1535 	p += 1;
   1536 
   1537 	if (ndo->ndo_vflag > 0) {
   1538 		ND_PRINT("\n\tSecurity Level %d, Key Id Mode %d, ",
   1539 			 *security_level, key_id_mode);
   1540 	}
   1541 	if ((CHECK_BIT(sc, 5)) == 0) {
   1542 		if (caplen < 4) {
   1543 			ND_PRINT("[ERROR: Truncated before Frame Counter]");
   1544 			return -1;
   1545 		}
   1546 		if (ndo->ndo_vflag > 1) {
   1547 			ND_PRINT("Frame Counter 0x%08x ",
   1548 				 GET_LE_U_4(p));
   1549 		}
   1550 		p += 4;
   1551 		caplen -= 4;
   1552 		len += 4;
   1553 	}
   1554 	switch (key_id_mode) {
   1555 	case 0x00: /* Implicit. */
   1556 		if (ndo->ndo_vflag > 1) {
   1557 			ND_PRINT("Implicit");
   1558 		}
   1559 		return len;
   1560 		break;
   1561 	case 0x01: /* Key Index, nothing to print here. */
   1562 		break;
   1563 	case 0x02: /* PAN and Short address Key Source, and Key Index. */
   1564 		if (caplen < 4) {
   1565 			ND_PRINT("[ERROR: Truncated before Key Source]");
   1566 			return -1;
   1567 		}
   1568 		if (ndo->ndo_vflag > 1) {
   1569 			ND_PRINT("KeySource 0x%04x:%0x4x, ",
   1570 				 GET_LE_U_2(p), GET_LE_U_2(p + 2));
   1571 		}
   1572 		p += 4;
   1573 		caplen -= 4;
   1574 		len += 4;
   1575 		break;
   1576 	case 0x03: /* Extended address and Key Index. */
   1577 		if (caplen < 8) {
   1578 			ND_PRINT("[ERROR: Truncated before Key Source]");
   1579 			return -1;
   1580 		}
   1581 		if (ndo->ndo_vflag > 1) {
   1582 			ND_PRINT("KeySource %s, ", GET_LE64ADDR_STRING(p));
   1583 		}
   1584 		p += 4;
   1585 		caplen -= 4;
   1586 		len += 4;
   1587 		break;
   1588 	}
   1589 	if (caplen < 1) {
   1590 		ND_PRINT("[ERROR: Truncated before Key Index]");
   1591 		return -1;
   1592 	}
   1593 	if (ndo->ndo_vflag > 1) {
   1594 		ND_PRINT("KeyIndex 0x%02x, ", GET_U_1(p));
   1595 	}
   1596 	caplen -= 1;
   1597 	p += 1;
   1598 	len += 1;
   1599 	return len;
   1600 }
   1601 
   1602 /*
   1603  * Print command data.
   1604  *
   1605  * Returns number of byts consumed from the packet or -1 in case of error.
   1606  */
   1607 static int
   1608 ieee802_15_4_print_command_data(netdissect_options *ndo,
   1609 				uint8_t command_id,
   1610 				const u_char *p,
   1611 				u_int caplen)
   1612 {
   1613 	u_int i;
   1614 
   1615 	switch (command_id) {
   1616 	case 0x01: /* Association Request */
   1617 		if (caplen != 1) {
   1618 			ND_PRINT("Invalid Association request command length");
   1619 			return -1;
   1620 		} else {
   1621 			uint8_t cap_info;
   1622 			cap_info = GET_U_1(p);
   1623 			ND_PRINT("%s%s%s%s%s%s",
   1624 				 ((cap_info & 0x02) ?
   1625 				  "FFD, " : "RFD, "),
   1626 				 ((cap_info & 0x04) ?
   1627 				  "AC powered, " : ""),
   1628 				 ((cap_info & 0x08) ?
   1629 				  "Receiver on when idle, " : ""),
   1630 				 ((cap_info & 0x10) ?
   1631 				  "Fast association, " : ""),
   1632 				 ((cap_info & 0x40) ?
   1633 				  "Security supported, " : ""),
   1634 				 ((cap_info & 0x80) ?
   1635 				  "Allocate address, " : ""));
   1636 			return caplen;
   1637 		}
   1638 		break;
   1639 	case 0x02: /* Association Response */
   1640 		if (caplen != 3) {
   1641 			ND_PRINT("Invalid Association response command length");
   1642 			return -1;
   1643 		} else {
   1644 			ND_PRINT("Short address = ");
   1645 			ieee802_15_4_print_addr(ndo, p, 2);
   1646 			switch (GET_U_1(p + 2)) {
   1647 			case 0x00:
   1648 				ND_PRINT(", Association successful");
   1649 				break;
   1650 			case 0x01:
   1651 				ND_PRINT(", PAN at capacity");
   1652 				break;
   1653 			case 0x02:
   1654 				ND_PRINT(", PAN access denied");
   1655 				break;
   1656 			case 0x03:
   1657 				ND_PRINT(", Hooping sequence offset duplication");
   1658 				break;
   1659 			case 0x80:
   1660 				ND_PRINT(", Fast association successful");
   1661 				break;
   1662 			default:
   1663 				ND_PRINT(", Status = 0x%02x",
   1664 					 GET_U_1(p + 2));
   1665 				break;
   1666 			}
   1667 			return caplen;
   1668 		}
   1669 		break;
   1670 	case 0x03: /* Disassociation Notification command */
   1671 		if (caplen != 1) {
   1672 			ND_PRINT("Invalid Disassociation Notification command length");
   1673 			return -1;
   1674 		} else {
   1675 			switch (GET_U_1(p)) {
   1676 			case 0x00:
   1677 				ND_PRINT("Reserved");
   1678 				break;
   1679 			case 0x01:
   1680 				ND_PRINT("Reason = The coordinator wishes the device to leave PAN");
   1681 				break;
   1682 			case 0x02:
   1683 				ND_PRINT("Reason = The device wishes to leave the PAN");
   1684 				break;
   1685 			default:
   1686 				ND_PRINT("Reason = 0x%02x", GET_U_1(p + 2));
   1687 				break;
   1688 			}
   1689 			return caplen;
   1690 		}
   1691 
   1692 		/* Following ones do not have any data. */
   1693 	case 0x04: /* Data Request command */
   1694 	case 0x05: /* PAN ID Conflict Notification command */
   1695 	case 0x06: /* Orphan Notification command */
   1696 	case 0x07: /* Beacon Request command */
   1697 		/* Should not have any data. */
   1698 		return 0;
   1699 	case 0x08: /* Coordinator Realignment command */
   1700 		if (caplen < 7 || caplen > 8) {
   1701 			ND_PRINT("Invalid Coordinator Realignment command length");
   1702 			return -1;
   1703 		} else {
   1704 			uint16_t channel, page;
   1705 
   1706 			ND_PRINT("Pan ID = 0x%04x, Coordinator short address = ",
   1707 				 GET_LE_U_2(p));
   1708 			ieee802_15_4_print_addr(ndo, p + 2, 2);
   1709 			channel = GET_U_1(p + 4);
   1710 
   1711 			if (caplen == 8) {
   1712 				page = GET_U_1(p + 7);
   1713 			} else {
   1714 				page = 0x80;
   1715 			}
   1716 			if (CHECK_BIT(page, 7)) {
   1717 				/* No page present, instead we have msb of
   1718 				   channel in the page. */
   1719 				channel |= (page & 0x7f) << 8;
   1720 				ND_PRINT(", Channel Number = %d", channel);
   1721 			} else {
   1722 				ND_PRINT(", Channel Number = %d, page = %d",
   1723 					 channel, page);
   1724 			}
   1725 			ND_PRINT(", Short address = ");
   1726 			ieee802_15_4_print_addr(ndo, p + 5, 2);
   1727 			return caplen;
   1728 		}
   1729 		break;
   1730 	case 0x09: /* GTS Request command */
   1731 		if (caplen != 1) {
   1732 			ND_PRINT("Invalid GTS Request command length");
   1733 			return -1;
   1734 		} else {
   1735 			uint8_t gts;
   1736 
   1737 			gts = GET_U_1(p);
   1738 			ND_PRINT("GTS Length = %d, %s, %s",
   1739 				 gts & 0xf,
   1740 				 (CHECK_BIT(gts, 4) ?
   1741 				  "Receive-only GTS" : "Transmit-only GTS"),
   1742 				 (CHECK_BIT(gts, 5) ?
   1743 				  "GTS allocation" : "GTS deallocations"));
   1744 			return caplen;
   1745 		}
   1746 		break;
   1747 	case 0x13: /* DSME Association Request command */
   1748 		/* XXX Not implemented */
   1749 	case 0x14: /* DSME Association Response command */
   1750 		/* XXX Not implemented */
   1751 	case 0x15: /* DSME GTS Request command */
   1752 		/* XXX Not implemented */
   1753 	case 0x16: /* DSME GTS Response command */
   1754 		/* XXX Not implemented */
   1755 	case 0x17: /* DSME GTS Notify command */
   1756 		/* XXX Not implemented */
   1757 	case 0x18: /* DSME Information Request command */
   1758 		/* XXX Not implemented */
   1759 	case 0x19: /* DSME Information Response command */
   1760 		/* XXX Not implemented */
   1761 	case 0x1a: /* DSME Beacon Allocation Notification command */
   1762 		/* XXX Not implemented */
   1763 	case 0x1b: /* DSME Beacon Collision Notification command */
   1764 		/* XXX Not implemented */
   1765 	case 0x1c: /* DSME Link Report command */
   1766 		/* XXX Not implemented */
   1767 	case 0x20: /* RIT Data Request command */
   1768 		/* XXX Not implemented */
   1769 	case 0x21: /* DBS Request command */
   1770 		/* XXX Not implemented */
   1771 	case 0x22: /* DBS Response command */
   1772 		/* XXX Not implemented */
   1773 	case 0x23: /* RIT Data Response command */
   1774 		/* XXX Not implemented */
   1775 	case 0x24: /* Vendor Specific command */
   1776 		/* XXX Not implemented */
   1777 	case 0x0a: /* TRLE Management Request command */
   1778 		/* XXX Not implemented */
   1779 	case 0x0b: /* TRLE Management Response command */
   1780 		/* XXX Not implemented */
   1781 	default:
   1782 		ND_PRINT("Command Data = ");
   1783 		for(i = 0; i < caplen; i++) {
   1784 			ND_PRINT("%02x ", GET_U_1(p + i));
   1785 		}
   1786 		break;
   1787 	}
   1788 	return 0;
   1789 }
   1790 
   1791 /*
   1792  * Parse and print frames following standard format.
   1793  *
   1794  * Returns FALSE in case of error.
   1795  */
   1796 static u_int
   1797 ieee802_15_4_std_frames(netdissect_options *ndo,
   1798 			const u_char *p, u_int caplen,
   1799 			uint16_t fc)
   1800 {
   1801 	int len, frame_version, pan_id_comp;
   1802 	int frame_type;
   1803 	int src_pan, dst_pan, src_addr_len, dst_addr_len;
   1804 	int security_level;
   1805 	u_int miclen = 0;
   1806 	int payload_ie_present;
   1807 	uint8_t seq;
   1808 	uint32_t fcs, crc_check;
   1809 	const u_char *mic_start = NULL;
   1810 
   1811 	payload_ie_present = 0;
   1812 
   1813 	crc_check = 0;
   1814 	/* Assume 2 octet FCS, the FCS length depends on the PHY, and we do not
   1815 	   know about that. */
   1816 	if (caplen < 4) {
   1817 		/* Cannot have FCS, assume no FCS. */
   1818 		fcs = 0;
   1819 	} else {
   1820 		/* Test for 4 octet FCS. */
   1821 		fcs = GET_LE_U_4(p + caplen - 4);
   1822 		crc_check = ieee802_15_4_crc32(ndo, p, caplen - 4);
   1823 		if (crc_check == fcs) {
   1824 			/* Remove FCS */
   1825 			caplen -= 4;
   1826 		} else {
   1827 			/* Test for 2 octet FCS. */
   1828 			fcs = GET_LE_U_2(p + caplen - 2);
   1829 			crc_check = ieee802_15_4_crc16(ndo, p, caplen - 2);
   1830 			if (crc_check == fcs) {
   1831 				/* Remove FCS */
   1832 				caplen -= 2;
   1833 			} else {
   1834 				/* Wrong FCS, FCS might not be included in the
   1835 				   captured frame, do not remove it. */
   1836 			}
   1837 		}
   1838 	}
   1839 
   1840 	/* Frame version. */
   1841 	frame_version = FC_FRAME_VERSION(fc);
   1842 	frame_type = FC_FRAME_TYPE(fc);
   1843 	ND_PRINT("v%d ", frame_version);
   1844 
   1845 	if (ndo->ndo_vflag > 2) {
   1846 		if (CHECK_BIT(fc, 3)) { ND_PRINT("Security Enabled, "); }
   1847 		if (CHECK_BIT(fc, 4)) { ND_PRINT("Frame Pending, "); }
   1848 		if (CHECK_BIT(fc, 5)) { ND_PRINT("AR, "); }
   1849 		if (CHECK_BIT(fc, 6)) { ND_PRINT("PAN ID Compression, "); }
   1850 		if (CHECK_BIT(fc, 8)) { ND_PRINT("Sequence Number Suppression, "); }
   1851 		if (CHECK_BIT(fc, 9)) { ND_PRINT("IE present, "); }
   1852 	}
   1853 
   1854 	/* Check for the sequence number suppression. */
   1855 	if (CHECK_BIT(fc, 8)) {
   1856 		/* Sequence number is suppressed. */
   1857 		if (frame_version < 2) {
   1858 			/* Sequence number can only be suppressed for frame
   1859 			   version 2 or higher, this is invalid frame. */
   1860 			ND_PRINT("[ERROR: Sequence number suppressed on frames where version < 2]");
   1861 		}
   1862 		if (ndo->ndo_vflag)
   1863 			ND_PRINT("seq suppressed ");
   1864 		if (caplen < 2) {
   1865 			nd_print_trunc(ndo);
   1866 			return 0;
   1867 		}
   1868 		p += 2;
   1869 		caplen -= 2;
   1870 	} else {
   1871 		seq = GET_U_1(p + 2);
   1872 		if (ndo->ndo_vflag)
   1873 			ND_PRINT("seq %02x ", seq);
   1874 		if (caplen < 3) {
   1875 			nd_print_trunc(ndo);
   1876 			return 0;
   1877 		}
   1878 		p += 3;
   1879 		caplen -= 3;
   1880 	}
   1881 
   1882 	/* See which parts of addresses we have. */
   1883 	dst_addr_len = ieee802_15_4_addr_len((fc >> 10) & 0x3);
   1884 	src_addr_len = ieee802_15_4_addr_len((fc >> 14) & 0x3);
   1885 	if (src_addr_len < 0) {
   1886 		ND_PRINT("[ERROR: Invalid src address mode]");
   1887 		return 0;
   1888 	}
   1889 	if (dst_addr_len < 0) {
   1890 		ND_PRINT("[ERROR: Invalid dst address mode]");
   1891 		return 0;
   1892 	}
   1893 	src_pan = 0;
   1894 	dst_pan = 0;
   1895 	pan_id_comp = CHECK_BIT(fc, 6);
   1896 
   1897 	/* The PAN ID Compression rules are complicated. */
   1898 
   1899 	/* First check old versions, where the rules are simple. */
   1900 	if (frame_version < 2) {
   1901 		if (pan_id_comp) {
   1902 			src_pan = 0;
   1903 			dst_pan = 1;
   1904 			if (dst_addr_len <= 0 || src_addr_len <= 0) {
   1905 				/* Invalid frame, PAN ID Compression must be 0
   1906 				   if only one address in the frame. */
   1907 				ND_PRINT("[ERROR: PAN ID Compression != 0, and only one address with frame version < 2]");
   1908 			}
   1909 		} else {
   1910 			src_pan = 1;
   1911 			dst_pan = 1;
   1912 		}
   1913 		if (dst_addr_len <= 0) {
   1914 			dst_pan = 0;
   1915 		}
   1916 		if (src_addr_len <= 0) {
   1917 			src_pan = 0;
   1918 		}
   1919 	} else {
   1920 		/* Frame version 2 rules are more complicated, and they depend
   1921 		   on the address modes of the frame, generic rules are same,
   1922 		   but then there are some special cases. */
   1923 		if (pan_id_comp) {
   1924 			src_pan = 0;
   1925 			dst_pan = 1;
   1926 		} else {
   1927 			src_pan = 1;
   1928 			dst_pan = 1;
   1929 		}
   1930 		if (dst_addr_len <= 0) {
   1931 			dst_pan = 0;
   1932 		}
   1933 		if (src_addr_len <= 0) {
   1934 			src_pan = 0;
   1935 		}
   1936 		if (pan_id_comp) {
   1937 			if (src_addr_len == 0 &&
   1938 			    dst_addr_len == 0) {
   1939 				/* Both addresses are missing, but PAN ID
   1940 				   compression set, special case we have
   1941 				   destination PAN but no addresses. */
   1942 				dst_pan = 1;
   1943 			} else if ((src_addr_len == 0 &&
   1944 				    dst_addr_len > 0) ||
   1945 				   (src_addr_len > 0 &&
   1946 				    dst_addr_len == 0)) {
   1947 				/* Only one address present, and PAN ID
   1948 				   compression is set, we do not have PAN id at
   1949 				   all. */
   1950 				dst_pan = 0;
   1951 				src_pan = 0;
   1952 			} else if (src_addr_len == 8 &&
   1953 				   dst_addr_len == 8) {
   1954 				/* Both addresses are Extended, and PAN ID
   1955 				   compression set, we do not have PAN ID at
   1956 				   all. */
   1957 				dst_pan = 0;
   1958 				src_pan = 0;
   1959 			}
   1960 		} else {
   1961 			/* Special cases where PAN ID Compression is not set. */
   1962 			if (src_addr_len == 8 &&
   1963 			    dst_addr_len == 8) {
   1964 				/* Both addresses are Extended, and PAN ID
   1965 				   compression not set, we do have only one PAN
   1966 				   ID (destination). */
   1967 				dst_pan = 1;
   1968 				src_pan = 0;
   1969 			}
   1970 #ifdef BROKEN_6TISCH_PAN_ID_COMPRESSION
   1971 			if (src_addr_len == 8 &&
   1972 			    dst_addr_len == 2) {
   1973 				/* Special case for the broken 6tisch
   1974 				   implementations. */
   1975 				src_pan = 0;
   1976 			}
   1977 #endif /* BROKEN_6TISCH_PAN_ID_COMPRESSION */
   1978 		}
   1979 	}
   1980 
   1981 	/* Print dst PAN and address. */
   1982 	if (dst_pan) {
   1983 		if (caplen < 2) {
   1984 			ND_PRINT("[ERROR: Truncated before dst_pan]");
   1985 			return 0;
   1986 		}
   1987 		ND_PRINT("%04x:", GET_LE_U_2(p));
   1988 		p += 2;
   1989 		caplen -= 2;
   1990 	} else {
   1991 		ND_PRINT("-:");
   1992 	}
   1993 	if (caplen < (u_int) dst_addr_len) {
   1994 		ND_PRINT("[ERROR: Truncated before dst_addr]");
   1995 		return 0;
   1996 	}
   1997 	ieee802_15_4_print_addr(ndo, p, dst_addr_len);
   1998 	p += dst_addr_len;
   1999 	caplen -= dst_addr_len;
   2000 
   2001 	ND_PRINT(" < ");
   2002 
   2003 	/* Print src PAN and address. */
   2004 	if (src_pan) {
   2005 		if (caplen < 2) {
   2006 			ND_PRINT("[ERROR: Truncated before dst_pan]");
   2007 			return 0;
   2008 		}
   2009 		ND_PRINT("%04x:", GET_LE_U_2(p));
   2010 		p += 2;
   2011 		caplen -= 2;
   2012 	} else {
   2013 		ND_PRINT("-:");
   2014 	}
   2015 	if (caplen < (u_int) src_addr_len) {
   2016 		ND_PRINT("[ERROR: Truncated before dst_addr]");
   2017 		return 0;
   2018 	}
   2019 	ieee802_15_4_print_addr(ndo, p, src_addr_len);
   2020 	ND_PRINT(" ");
   2021 	p += src_addr_len;
   2022 	caplen -= src_addr_len;
   2023 	if (CHECK_BIT(fc, 3)) {
   2024 		/*
   2025 		 * XXX - if frame_version is 0, this is the 2003
   2026 		 * spec, and you don't have the auxiliary security
   2027 		 * header, you have a frame counter and key index
   2028 		 * for the AES-CTR and AES-CCM security suites but
   2029 		 * not for the AES-CBC-MAC security suite.
   2030 		 */
   2031 		len = ieee802_15_4_print_aux_sec_header(ndo, p, caplen,
   2032 							&security_level);
   2033 		if (len < 0) {
   2034 			return 0;
   2035 		}
   2036 		ND_TCHECK_LEN(p, len);
   2037 		p += len;
   2038 		caplen -= len;
   2039 	} else {
   2040 		security_level = 0;
   2041 	}
   2042 
   2043 	switch (security_level) {
   2044 	case 0: /*FALLTHROUGH */
   2045 	case 4:
   2046 		miclen = 0;
   2047 		break;
   2048 	case 1: /*FALLTHROUGH */
   2049 	case 5:
   2050 		miclen = 4;
   2051 		break;
   2052 	case 2: /*FALLTHROUGH */
   2053 	case 6:
   2054 		miclen = 8;
   2055 		break;
   2056 	case 3: /*FALLTHROUGH */
   2057 	case 7:
   2058 		miclen = 16;
   2059 		break;
   2060 	}
   2061 
   2062 	/* Remove MIC */
   2063 	if (miclen != 0) {
   2064 		if (caplen < miclen) {
   2065 			ND_PRINT("[ERROR: Truncated before MIC]");
   2066 			return 0;
   2067 		}
   2068 		caplen -= miclen;
   2069 		mic_start = p + caplen;
   2070 	}
   2071 
   2072 	/* Parse Information elements if present */
   2073 	if (CHECK_BIT(fc, 9)) {
   2074 		/* Yes we have those. */
   2075 		len = ieee802_15_4_print_header_ie_list(ndo, p, caplen,
   2076 							&payload_ie_present);
   2077 		if (len < 0) {
   2078 			return 0;
   2079 		}
   2080 		p += len;
   2081 		caplen -= len;
   2082 	}
   2083 
   2084 	if (payload_ie_present) {
   2085 		if (security_level >= 4) {
   2086 			ND_PRINT("Payload IEs present, but encrypted, cannot print ");
   2087 		} else {
   2088 			len = ieee802_15_4_print_payload_ie_list(ndo, p, caplen);
   2089 			if (len < 0) {
   2090 				return 0;
   2091 			}
   2092 			p += len;
   2093 			caplen -= len;
   2094 		}
   2095 	}
   2096 
   2097 	/* Print MIC */
   2098 	if (ndo->ndo_vflag > 2 && miclen != 0) {
   2099 		ND_PRINT("\n\tMIC ");
   2100 
   2101 		for (u_int micoffset = 0; micoffset < miclen; micoffset++) {
   2102 			ND_PRINT("%02x", GET_U_1(mic_start + micoffset));
   2103 		}
   2104 		ND_PRINT(" ");
   2105 	}
   2106 
   2107 	/* Print FCS */
   2108 	if (ndo->ndo_vflag > 2) {
   2109 		if (crc_check == fcs) {
   2110 			ND_PRINT("FCS %x ", fcs);
   2111 		} else {
   2112 			ND_PRINT("wrong FCS %x vs %x (assume no FCS stored) ",
   2113 				 fcs, crc_check);
   2114 		}
   2115 	}
   2116 
   2117 	/* Payload print */
   2118 	switch (frame_type) {
   2119 	case 0x00: /* Beacon */
   2120 		if (frame_version < 2) {
   2121 			if (caplen < 2) {
   2122 				ND_PRINT("[ERROR: Truncated before beacon information]");
   2123 				break;
   2124 			} else {
   2125 				uint16_t ss;
   2126 
   2127 				ss = GET_LE_U_2(p);
   2128 				ieee802_15_4_print_superframe_specification(ndo, ss);
   2129 				p += 2;
   2130 				caplen -= 2;
   2131 
   2132 				/* GTS */
   2133 				if (caplen < 1) {
   2134 					ND_PRINT("[ERROR: Truncated before GTS info]");
   2135 					break;
   2136 				}
   2137 
   2138 				len = ieee802_15_4_print_gts_info(ndo, p, caplen);
   2139 				if (len < 0) {
   2140 					break;
   2141 				}
   2142 
   2143 				p += len;
   2144 				caplen -= len;
   2145 
   2146 				/* Pending Addresses */
   2147 				if (caplen < 1) {
   2148 					ND_PRINT("[ERROR: Truncated before pending addresses]");
   2149 					break;
   2150 				}
   2151 				len = ieee802_15_4_print_pending_addresses(ndo, p, caplen);
   2152 				if (len < 0) {
   2153 					break;
   2154 				}
   2155 				ND_TCHECK_LEN(p, len);
   2156 				p += len;
   2157 				caplen -= len;
   2158 			}
   2159 		}
   2160 		if (!ndo->ndo_suppress_default_print)
   2161 			ND_DEFAULTPRINT(p, caplen);
   2162 
   2163 		break;
   2164 	case 0x01: /* Data */
   2165 	case 0x02: /* Acknowledgement */
   2166 		if (!ndo->ndo_suppress_default_print)
   2167 			ND_DEFAULTPRINT(p, caplen);
   2168 		break;
   2169 	case 0x03: /* MAC Command */
   2170 		if (caplen < 1) {
   2171 			ND_PRINT("[ERROR: Truncated before Command ID]");
   2172 		} else {
   2173 			uint8_t command_id;
   2174 
   2175 			command_id = GET_U_1(p);
   2176 			if (command_id >= 0x30) {
   2177 				ND_PRINT("Command ID = Reserved 0x%02x ",
   2178 					 command_id);
   2179 			} else {
   2180 				ND_PRINT("Command ID = %s ",
   2181 					 mac_c_names[command_id]);
   2182 			}
   2183 			p++;
   2184 			caplen--;
   2185 			if (caplen != 0) {
   2186 				len = ieee802_15_4_print_command_data(ndo, command_id, p, caplen);
   2187 				if (len >= 0) {
   2188 					p += len;
   2189 					caplen -= len;
   2190 				}
   2191 			}
   2192 		}
   2193 		if (!ndo->ndo_suppress_default_print)
   2194 			ND_DEFAULTPRINT(p, caplen);
   2195 		break;
   2196 	}
   2197 	return 1;
   2198 }
   2199 
   2200 /*
   2201  * Print and parse Multipurpose frames.
   2202  *
   2203  * Returns FALSE in case of error.
   2204  */
   2205 static u_int
   2206 ieee802_15_4_mp_frame(netdissect_options *ndo,
   2207 		      const u_char *p, u_int caplen,
   2208 		      uint16_t fc)
   2209 {
   2210 	int len, frame_version, pan_id_present;
   2211 	int src_addr_len, dst_addr_len;
   2212 	int security_level;
   2213 	u_int miclen = 0;
   2214 	int ie_present, payload_ie_present, security_enabled;
   2215 	uint8_t seq;
   2216 	uint32_t fcs, crc_check;
   2217 	const u_char *mic_start = NULL;
   2218 
   2219 	pan_id_present = 0;
   2220 	ie_present = 0;
   2221 	payload_ie_present = 0;
   2222 	security_enabled = 0;
   2223 	crc_check = 0;
   2224 
   2225 	/* Assume 2 octet FCS, the FCS length depends on the PHY, and we do not
   2226 	   know about that. */
   2227 	if (caplen < 3) {
   2228 		/* Cannot have FCS, assume no FCS. */
   2229 		fcs = 0;
   2230 	} else {
   2231 		if (caplen > 4) {
   2232 			/* Test for 4 octet FCS. */
   2233 			fcs = GET_LE_U_4(p + caplen - 4);
   2234 			crc_check = ieee802_15_4_crc32(ndo, p, caplen - 4);
   2235 			if (crc_check == fcs) {
   2236 				/* Remove FCS */
   2237 				caplen -= 4;
   2238 			} else {
   2239 				fcs = GET_LE_U_2(p + caplen - 2);
   2240 				crc_check = ieee802_15_4_crc16(ndo, p, caplen - 2);
   2241 				if (crc_check == fcs) {
   2242 					/* Remove FCS */
   2243 					caplen -= 2;
   2244 				}
   2245 			}
   2246 		} else {
   2247 			fcs = GET_LE_U_2(p + caplen - 2);
   2248 			crc_check = ieee802_15_4_crc16(ndo, p, caplen - 2);
   2249 			if (crc_check == fcs) {
   2250 				/* Remove FCS */
   2251 				caplen -= 2;
   2252 			}
   2253 		}
   2254 	}
   2255 
   2256 	if (CHECK_BIT(fc, 3)) {
   2257 		/* Long Frame Control */
   2258 
   2259 		/* Frame version. */
   2260 		frame_version = FC_FRAME_VERSION(fc);
   2261 		ND_PRINT("v%d ", frame_version);
   2262 
   2263 		pan_id_present = CHECK_BIT(fc, 8);
   2264 		ie_present = CHECK_BIT(fc, 15);
   2265 		security_enabled = CHECK_BIT(fc, 9);
   2266 
   2267 		if (ndo->ndo_vflag > 2) {
   2268 			if (security_enabled) { ND_PRINT("Security Enabled, "); }
   2269 			if (CHECK_BIT(fc, 11)) { ND_PRINT("Frame Pending, "); }
   2270 			if (CHECK_BIT(fc, 14)) { ND_PRINT("AR, "); }
   2271 			if (pan_id_present) { ND_PRINT("PAN ID Present, "); }
   2272 			if (CHECK_BIT(fc, 10)) {
   2273 				ND_PRINT("Sequence Number Suppression, ");
   2274 			}
   2275 			if (ie_present) { ND_PRINT("IE present, "); }
   2276 		}
   2277 
   2278 		/* Check for the sequence number suppression. */
   2279 		if (CHECK_BIT(fc, 10)) {
   2280 			/* Sequence number is suppressed, but long version. */
   2281 			if (caplen < 2) {
   2282 				nd_print_trunc(ndo);
   2283 				return 0;
   2284 			}
   2285 			p += 2;
   2286 			caplen -= 2;
   2287 		} else {
   2288 			seq = GET_U_1(p + 2);
   2289 			if (ndo->ndo_vflag)
   2290 				ND_PRINT("seq %02x ", seq);
   2291 			if (caplen < 3) {
   2292 				nd_print_trunc(ndo);
   2293 				return 0;
   2294 			}
   2295 			p += 3;
   2296 			caplen -= 3;
   2297 		}
   2298 	} else {
   2299 		/* Short format of header, but with seq no */
   2300 		seq = GET_U_1(p + 1);
   2301 		p += 2;
   2302 		caplen -= 2;
   2303 		if (ndo->ndo_vflag)
   2304 			ND_PRINT("seq %02x ", seq);
   2305 	}
   2306 
   2307 	/* See which parts of addresses we have. */
   2308 	dst_addr_len = ieee802_15_4_addr_len((fc >> 4) & 0x3);
   2309 	src_addr_len = ieee802_15_4_addr_len((fc >> 6) & 0x3);
   2310 	if (src_addr_len < 0) {
   2311 		ND_PRINT("[ERROR: Invalid src address mode]");
   2312 		return 0;
   2313 	}
   2314 	if (dst_addr_len < 0) {
   2315 		ND_PRINT("[ERROR: Invalid dst address mode]");
   2316 		return 0;
   2317 	}
   2318 
   2319 	/* Print dst PAN and address. */
   2320 	if (pan_id_present) {
   2321 		if (caplen < 2) {
   2322 			ND_PRINT("[ERROR: Truncated before dst_pan]");
   2323 			return 0;
   2324 		}
   2325 		ND_PRINT("%04x:", GET_LE_U_2(p));
   2326 		p += 2;
   2327 		caplen -= 2;
   2328 	} else {
   2329 		ND_PRINT("-:");
   2330 	}
   2331 	if (caplen < (u_int) dst_addr_len) {
   2332 		ND_PRINT("[ERROR: Truncated before dst_addr]");
   2333 		return 0;
   2334 	}
   2335 	ieee802_15_4_print_addr(ndo, p, dst_addr_len);
   2336 	p += dst_addr_len;
   2337 	caplen -= dst_addr_len;
   2338 
   2339 	ND_PRINT(" < ");
   2340 
   2341 	/* Print src PAN and address. */
   2342 	ND_PRINT(" -:");
   2343 	if (caplen < (u_int) src_addr_len) {
   2344 		ND_PRINT("[ERROR: Truncated before dst_addr]");
   2345 		return 0;
   2346 	}
   2347 	ieee802_15_4_print_addr(ndo, p, src_addr_len);
   2348 	ND_PRINT(" ");
   2349 	p += src_addr_len;
   2350 	caplen -= src_addr_len;
   2351 
   2352 	if (security_enabled) {
   2353 		len = ieee802_15_4_print_aux_sec_header(ndo, p, caplen,
   2354 							&security_level);
   2355 		if (len < 0) {
   2356 			return 0;
   2357 		}
   2358 		ND_TCHECK_LEN(p, len);
   2359 		p += len;
   2360 		caplen -= len;
   2361 	} else {
   2362 		security_level = 0;
   2363 	}
   2364 
   2365 	switch (security_level) {
   2366 	case 0: /*FALLTHROUGH */
   2367 	case 4:
   2368 		miclen = 0;
   2369 		break;
   2370 	case 1: /*FALLTHROUGH */
   2371 	case 5:
   2372 		miclen = 4;
   2373 		break;
   2374 	case 2: /*FALLTHROUGH */
   2375 	case 6:
   2376 		miclen = 8;
   2377 		break;
   2378 	case 3: /*FALLTHROUGH */
   2379 	case 7:
   2380 		miclen = 16;
   2381 		break;
   2382 	}
   2383 
   2384 	/* Remove MIC */
   2385 	if (miclen != 0) {
   2386 		if (caplen < miclen) {
   2387 			ND_PRINT("[ERROR: Truncated before MIC]");
   2388 			return 0;
   2389 		}
   2390 		caplen -= miclen;
   2391 		mic_start = p + caplen;
   2392 	}
   2393 
   2394 	/* Parse Information elements if present */
   2395 	if (ie_present) {
   2396 		/* Yes we have those. */
   2397 		len = ieee802_15_4_print_header_ie_list(ndo, p, caplen,
   2398 							&payload_ie_present);
   2399 		if (len < 0) {
   2400 			return 0;
   2401 		}
   2402 		p += len;
   2403 		caplen -= len;
   2404 	}
   2405 
   2406 	if (payload_ie_present) {
   2407 		if (security_level >= 4) {
   2408 			ND_PRINT("Payload IEs present, but encrypted, cannot print ");
   2409 		} else {
   2410 			len = ieee802_15_4_print_payload_ie_list(ndo, p,
   2411 								 caplen);
   2412 			if (len < 0) {
   2413 				return 0;
   2414 			}
   2415 			p += len;
   2416 			caplen -= len;
   2417 		}
   2418 	}
   2419 
   2420 	/* Print MIC */
   2421 	if (ndo->ndo_vflag > 2 && miclen != 0) {
   2422 		ND_PRINT("\n\tMIC ");
   2423 
   2424 		for (u_int micoffset = 0; micoffset < miclen; micoffset++) {
   2425 			ND_PRINT("%02x", GET_U_1(mic_start + micoffset));
   2426 		}
   2427 		ND_PRINT(" ");
   2428 	}
   2429 
   2430 
   2431 	/* Print FCS */
   2432 	if (ndo->ndo_vflag > 2) {
   2433 		if (crc_check == fcs) {
   2434 			ND_PRINT("FCS %x ", fcs);
   2435 		} else {
   2436 			ND_PRINT("wrong FCS %x vs %x (assume no FCS stored) ",
   2437 				 fcs, crc_check);
   2438 		}
   2439 	}
   2440 
   2441 	if (!ndo->ndo_suppress_default_print)
   2442 		ND_DEFAULTPRINT(p, caplen);
   2443 
   2444 	return 1;
   2445 }
   2446 
   2447 /*
   2448  * Print frag frame.
   2449  *
   2450  * Returns FALSE in case of error.
   2451  */
   2452 static u_int
   2453 ieee802_15_4_frag_frame(netdissect_options *ndo _U_,
   2454 			const u_char *p _U_,
   2455 			u_int caplen _U_,
   2456 			uint16_t fc _U_)
   2457 {
   2458 	/* Not implement yet, might be bit hard to implement, as the
   2459 	 * information to set up the fragment is coming in the previous frame
   2460 	 * in the Fragment Sequence Context Description IE, thus we need to
   2461 	 * store information from there, so we can use it here. */
   2462 	return 0;
   2463 }
   2464 
   2465 /*
   2466  * Internal call to dissector taking packet + len instead of pcap_pkthdr.
   2467  *
   2468  * Returns FALSE in case of error.
   2469  */
   2470 u_int
   2471 ieee802_15_4_print(netdissect_options *ndo,
   2472 		   const u_char *p, u_int caplen)
   2473 {
   2474 	int frame_type;
   2475 	uint16_t fc;
   2476 
   2477 	ndo->ndo_protocol = "802.15.4";
   2478 
   2479 	if (caplen < 2) {
   2480 		nd_print_trunc(ndo);
   2481 		return caplen;
   2482 	}
   2483 
   2484 	fc = GET_LE_U_2(p);
   2485 
   2486 	/* First we need to check the frame type to know how to parse the rest
   2487 	   of the FC. Frame type is the first 3 bit of the frame control field.
   2488 	*/
   2489 
   2490 	frame_type = FC_FRAME_TYPE(fc);
   2491 	ND_PRINT("IEEE 802.15.4 %s packet ", ftypes[frame_type]);
   2492 
   2493 	switch (frame_type) {
   2494 	case 0x00: /* Beacon */
   2495 	case 0x01: /* Data */
   2496 	case 0x02: /* Acknowledgement */
   2497 	case 0x03: /* MAC Command */
   2498 		return ieee802_15_4_std_frames(ndo, p, caplen, fc);
   2499 		break;
   2500 	case 0x04: /* Reserved */
   2501 		return 0;
   2502 		break;
   2503 	case 0x05: /* Multipurpose */
   2504 		return ieee802_15_4_mp_frame(ndo, p, caplen, fc);
   2505 		break;
   2506 	case 0x06: /* Fragment or Frak */
   2507 		return ieee802_15_4_frag_frame(ndo, p, caplen, fc);
   2508 		break;
   2509 	case 0x07: /* Extended */
   2510 		return 0;
   2511 		break;
   2512 	}
   2513 	return 0;
   2514 }
   2515 
   2516 /*
   2517  * Main function to print packets.
   2518  */
   2519 
   2520 void
   2521 ieee802_15_4_if_print(netdissect_options *ndo,
   2522                       const struct pcap_pkthdr *h, const u_char *p)
   2523 {
   2524 	u_int caplen = h->caplen;
   2525 	ndo->ndo_protocol = "802.15.4";
   2526 	ndo->ndo_ll_hdr_len += ieee802_15_4_print(ndo, p, caplen);
   2527 }
   2528 
   2529 /* For DLT_IEEE802_15_4_TAP */
   2530 /* https://github.com/jkcko/ieee802.15.4-tap */
   2531 void
   2532 ieee802_15_4_tap_if_print(netdissect_options *ndo,
   2533                           const struct pcap_pkthdr *h, const u_char *p)
   2534 {
   2535 	uint8_t version;
   2536 	uint16_t length;
   2537 
   2538 	ndo->ndo_protocol = "802.15.4_tap";
   2539 	if (h->caplen < 4) {
   2540 		nd_print_trunc(ndo);
   2541 		ndo->ndo_ll_hdr_len += h->caplen;
   2542 		return;
   2543 	}
   2544 
   2545 	version = GET_U_1(p);
   2546 	length = GET_LE_U_2(p + 2);
   2547 	if (version != 0 || length < 4) {
   2548 		nd_print_invalid(ndo);
   2549 		return;
   2550 	}
   2551 
   2552 	if (h->caplen < length) {
   2553 		nd_print_trunc(ndo);
   2554 		ndo->ndo_ll_hdr_len += h->caplen;
   2555 		return;
   2556 	}
   2557 
   2558 	ndo->ndo_ll_hdr_len += ieee802_15_4_print(ndo, p+length, h->caplen-length) + length;
   2559 }
   2560