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