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