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