3 * Siemens AG, All rights reserved.
4 * Dmitry Eremin-Solenikov (dbaryshkov@gmail.com)
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
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.
23 /* \summary: IEEE 802.15.4 printer */
29 #include <netdissect-stdinc.h>
31 #include "netdissect.h"
32 #include "addrtoname.h"
36 #define CHECK_BIT(num,bit) (((num) >> (bit)) & 0x1)
38 #define BROKEN_6TISCH_PAN_ID_COMPRESSION 0
40 /* Frame types from Table 7-1 of 802.15.4-2015 */
41 static const char *ftypes
[] = {
47 "Multipurpose", /* 5 */
52 /* Element IDs for Header IEs from Table 7-7 of 802.15.4-2015 */
53 static const char *h_ie_names
[] = {
54 "Vendor Specific Header IE", /* 0x00 */
55 "Reserved 0x01", /* 0x01 */
56 "Reserved 0x02", /* 0x02 */
57 "Reserved 0x03", /* 0x03 */
58 "Reserved 0x04", /* 0x04 */
59 "Reserved 0x05", /* 0x05 */
60 "Reserved 0x06", /* 0x06 */
61 "Reserved 0x07", /* 0x07 */
62 "Reserved 0x08", /* 0x08 */
63 "Reserved 0x09", /* 0x09 */
64 "Reserved 0x0a", /* 0x0a */
65 "Reserved 0x0b", /* 0x0b */
66 "Reserved 0x0c", /* 0x0c */
67 "Reserved 0x0d", /* 0x0d */
68 "Reserved 0x0e", /* 0x0e */
69 "Reserved 0x0f", /* 0x0f */
70 "Reserved 0x10", /* 0x10 */
71 "Reserved 0x11", /* 0x11 */
72 "Reserved 0x12", /* 0x12 */
73 "Reserved 0x13", /* 0x13 */
74 "Reserved 0x14", /* 0x14 */
75 "Reserved 0x15", /* 0x15 */
76 "Reserved 0x16", /* 0x16 */
77 "Reserved 0x17", /* 0x17 */
78 "Reserved 0x18", /* 0x18 */
79 "Reserved 0x19", /* 0x19 */
80 "LE CSL IE", /* 0x1a */
81 "LE RIT IE", /* 0x1b */
82 "DSME PAN descriptor IE", /* 0x1c */
83 "Rendezvous Time IE", /* 0x1d */
84 "Time Correction IE", /* 0x1e */
85 "Reserved 0x1f", /* 0x1f */
86 "Reserved 0x20", /* 0x20 */
87 "Extended DSME PAN descriptor IE", /* 0x21 */
88 "Fragment Sequence Context Description IE", /* 0x22 */
89 "Simplified Superframe Specification IE", /* 0x23 */
90 "Simplified GTS Specification IE", /* 0x24 */
91 "LECIM Capabilities IE", /* 0x25 */
92 "TRLE Descriptor IE", /* 0x26 */
93 "RCC Capabilities IE", /* 0x27 */
94 "RCCN Descriptor IE", /* 0x28 */
95 "Global Time IE", /* 0x29 */
96 "Omnibus Header IE", /* 0x2a */
98 "Reserved 0x2c", /* 0x2c */
99 "Reserved 0x2d", /* 0x2d */
100 "Reserved 0x2e", /* 0x2e */
101 "Reserved 0x2f", /* 0x2f */
102 "Reserved 0x30", /* 0x30 */
103 "Reserved 0x31", /* 0x31 */
104 "Reserved 0x32", /* 0x32 */
105 "Reserved 0x33", /* 0x33 */
106 "Reserved 0x34", /* 0x34 */
107 "Reserved 0x35", /* 0x35 */
108 "Reserved 0x36", /* 0x36 */
109 "Reserved 0x37", /* 0x37 */
110 "Reserved 0x38", /* 0x38 */
111 "Reserved 0x39", /* 0x39 */
112 "Reserved 0x3a", /* 0x3a */
113 "Reserved 0x3b", /* 0x3b */
114 "Reserved 0x3c", /* 0x3c */
115 "Reserved 0x3d", /* 0x3d */
116 "Reserved 0x3e", /* 0x3e */
117 "Reserved 0x3f", /* 0x3f */
118 "Reserved 0x40", /* 0x40 */
119 "Reserved 0x41", /* 0x41 */
120 "Reserved 0x42", /* 0x42 */
121 "Reserved 0x43", /* 0x43 */
122 "Reserved 0x44", /* 0x44 */
123 "Reserved 0x45", /* 0x45 */
124 "Reserved 0x46", /* 0x46 */
125 "Reserved 0x47", /* 0x47 */
126 "Reserved 0x48", /* 0x48 */
127 "Reserved 0x49", /* 0x49 */
128 "Reserved 0x4a", /* 0x4a */
129 "Reserved 0x4b", /* 0x4b */
130 "Reserved 0x4c", /* 0x4c */
131 "Reserved 0x4d", /* 0x4d */
132 "Reserved 0x4e", /* 0x4e */
133 "Reserved 0x4f", /* 0x4f */
134 "Reserved 0x50", /* 0x50 */
135 "Reserved 0x51", /* 0x51 */
136 "Reserved 0x52", /* 0x52 */
137 "Reserved 0x53", /* 0x53 */
138 "Reserved 0x54", /* 0x54 */
139 "Reserved 0x55", /* 0x55 */
140 "Reserved 0x56", /* 0x56 */
141 "Reserved 0x57", /* 0x57 */
142 "Reserved 0x58", /* 0x58 */
143 "Reserved 0x59", /* 0x59 */
144 "Reserved 0x5a", /* 0x5a */
145 "Reserved 0x5b", /* 0x5b */
146 "Reserved 0x5c", /* 0x5c */
147 "Reserved 0x5d", /* 0x5d */
148 "Reserved 0x5e", /* 0x5e */
149 "Reserved 0x5f", /* 0x5f */
150 "Reserved 0x60", /* 0x60 */
151 "Reserved 0x61", /* 0x61 */
152 "Reserved 0x62", /* 0x62 */
153 "Reserved 0x63", /* 0x63 */
154 "Reserved 0x64", /* 0x64 */
155 "Reserved 0x65", /* 0x65 */
156 "Reserved 0x66", /* 0x66 */
157 "Reserved 0x67", /* 0x67 */
158 "Reserved 0x68", /* 0x68 */
159 "Reserved 0x69", /* 0x69 */
160 "Reserved 0x6a", /* 0x6a */
161 "Reserved 0x6b", /* 0x6b */
162 "Reserved 0x6c", /* 0x6c */
163 "Reserved 0x6d", /* 0x6d */
164 "Reserved 0x6e", /* 0x6e */
165 "Reserved 0x6f", /* 0x6f */
166 "Reserved 0x70", /* 0x70 */
167 "Reserved 0x71", /* 0x71 */
168 "Reserved 0x72", /* 0x72 */
169 "Reserved 0x73", /* 0x73 */
170 "Reserved 0x74", /* 0x74 */
171 "Reserved 0x75", /* 0x75 */
172 "Reserved 0x76", /* 0x76 */
173 "Reserved 0x77", /* 0x77 */
174 "Reserved 0x78", /* 0x78 */
175 "Reserved 0x79", /* 0x79 */
176 "Reserved 0x7a", /* 0x7a */
177 "Reserved 0x7b", /* 0x7b */
178 "Reserved 0x7c", /* 0x7c */
179 "Reserved 0x7d", /* 0x7d */
180 "Header Termination 1 IE", /* 0x7e */
181 "Header Termination 2 IE" /* 0x7f */
184 /* Payload IE Group IDs from Table 7-15 of 802.15.4-2015 */
185 static const char *p_ie_names
[] = {
186 "ESDU IE", /* 0x00 */
187 "MLME IE", /* 0x01 */
188 "Vendor Specific Nested IE", /* 0x02 */
189 "Multiplexed IE (802.15.9)", /* 0x03 */
190 "Omnibus Payload Group IE", /* 0x04 */
191 "IETF IE", /* 0x05 */
192 "Reserved 0x06", /* 0x06 */
193 "Reserved 0x07", /* 0x07 */
194 "Reserved 0x08", /* 0x08 */
195 "Reserved 0x09", /* 0x09 */
196 "Reserved 0x0a", /* 0x0a */
197 "Reserved 0x0b", /* 0x0b */
198 "Reserved 0x0c", /* 0x0c */
199 "Reserved 0x0d", /* 0x0d */
200 "Reserved 0x0e", /* 0x0e */
201 "List termination" /* 0x0f */
204 /* Sub-ID for short format from Table 7-16 of 802.15.4-2015 */
205 static const char *p_mlme_short_names
[] = {
206 "Reserved for long format 0x0", /* 0x00 */
207 "Reserved for long format 0x1", /* 0x01 */
208 "Reserved for long format 0x2", /* 0x02 */
209 "Reserved for long format 0x3", /* 0x03 */
210 "Reserved for long format 0x4", /* 0x04 */
211 "Reserved for long format 0x5", /* 0x05 */
212 "Reserved for long format 0x6", /* 0x06 */
213 "Reserved for long format 0x7", /* 0x07 */
214 "Reserved for long format 0x8", /* 0x08 */
215 "Reserved for long format 0x9", /* 0x09 */
216 "Reserved for long format 0xa", /* 0x0a */
217 "Reserved for long format 0xb", /* 0x0b */
218 "Reserved for long format 0xc", /* 0x0c */
219 "Reserved for long format 0xd", /* 0x0d */
220 "Reserved for long format 0xe", /* 0x0e */
221 "Reserved for long format 0xf", /* 0x0f */
222 "Reserved 0x10", /* 0x10 */
223 "Reserved 0x11", /* 0x11 */
224 "Reserved 0x12", /* 0x12 */
225 "Reserved 0x13", /* 0x13 */
226 "Reserved 0x14", /* 0x14 */
227 "Reserved 0x15", /* 0x15 */
228 "Reserved 0x16", /* 0x16 */
229 "Reserved 0x17", /* 0x17 */
230 "Reserved 0x18", /* 0x18 */
231 "Reserved 0x19", /* 0x19 */
232 "TSCH Synchronization IE", /* 0x1a */
233 "TSCH Slotframe and Link IE", /* 0x1b */
234 "TSCH Timeslot IE", /* 0x1c */
235 "Hopping timing IE", /* 0x1d */
236 "Enhanced Beacon Filter IE", /* 0x1e */
237 "MAC Metrics IE", /* 0x1f */
238 "All MAC Metrics IE", /* 0x20 */
239 "Coexistence Specification IE", /* 0x21 */
240 "SUN Device Capabilities IE", /* 0x22 */
241 "SUN FSK Generic PHY IE", /* 0x23 */
242 "Mode Switch Parameter IE", /* 0x24 */
243 "PHY Parameter Change IE", /* 0x25 */
244 "O-QPSK PHY Mode IE", /* 0x26 */
245 "PCA Allocation IE", /* 0x27 */
246 "LECIM DSSS Operating Mode IE", /* 0x28 */
247 "LECIM FSK Operating Mode IE", /* 0x29 */
248 "Reserved 0x2a", /* 0x2a */
249 "TVWS PHY Operating Mode Description IE", /* 0x2b */
250 "TVWS Device Capabilities IE", /* 0x2c */
251 "TVWS Device Category IE", /* 0x2d */
252 "TVWS Device Identiication IE", /* 0x2e */
253 "TVWS Device Location IE", /* 0x2f */
254 "TVWS Channel Information Query IE", /* 0x30 */
255 "TVWS Channel Information Source IE", /* 0x31 */
257 "Timestamp IE", /* 0x33 */
258 "Timestamp Difference IE", /* 0x34 */
259 "TMCTP Sepcification IE", /* 0x35 */
260 "RCC PHY Operating Mode IE", /* 0x36 */
261 "Reserved 0x37", /* 0x37 */
262 "Reserved 0x38", /* 0x38 */
263 "Reserved 0x39", /* 0x39 */
264 "Reserved 0x3a", /* 0x3a */
265 "Reserved 0x3b", /* 0x3b */
266 "Reserved 0x3c", /* 0x3c */
267 "Reserved 0x3d", /* 0x3d */
268 "Reserved 0x3e", /* 0x3e */
269 "Reserved 0x3f", /* 0x3f */
270 "Reserved 0x40", /* 0x40 */
271 "Reserved 0x41", /* 0x41 */
272 "Reserved 0x42", /* 0x42 */
273 "Reserved 0x43", /* 0x43 */
274 "Reserved 0x44", /* 0x44 */
275 "Reserved 0x45", /* 0x45 */
276 "Reserved 0x46", /* 0x46 */
277 "Reserved 0x47", /* 0x47 */
278 "Reserved 0x48", /* 0x48 */
279 "Reserved 0x49", /* 0x49 */
280 "Reserved 0x4a", /* 0x4a */
281 "Reserved 0x4b", /* 0x4b */
282 "Reserved 0x4c", /* 0x4c */
283 "Reserved 0x4d", /* 0x4d */
284 "Reserved 0x4e", /* 0x4e */
285 "Reserved 0x4f", /* 0x4f */
286 "Reserved 0x50", /* 0x50 */
287 "Reserved 0x51", /* 0x51 */
288 "Reserved 0x52", /* 0x52 */
289 "Reserved 0x53", /* 0x53 */
290 "Reserved 0x54", /* 0x54 */
291 "Reserved 0x55", /* 0x55 */
292 "Reserved 0x56", /* 0x56 */
293 "Reserved 0x57", /* 0x57 */
294 "Reserved 0x58", /* 0x58 */
295 "Reserved 0x59", /* 0x59 */
296 "Reserved 0x5a", /* 0x5a */
297 "Reserved 0x5b", /* 0x5b */
298 "Reserved 0x5c", /* 0x5c */
299 "Reserved 0x5d", /* 0x5d */
300 "Reserved 0x5e", /* 0x5e */
301 "Reserved 0x5f", /* 0x5f */
302 "Reserved 0x60", /* 0x60 */
303 "Reserved 0x61", /* 0x61 */
304 "Reserved 0x62", /* 0x62 */
305 "Reserved 0x63", /* 0x63 */
306 "Reserved 0x64", /* 0x64 */
307 "Reserved 0x65", /* 0x65 */
308 "Reserved 0x66", /* 0x66 */
309 "Reserved 0x67", /* 0x67 */
310 "Reserved 0x68", /* 0x68 */
311 "Reserved 0x69", /* 0x69 */
312 "Reserved 0x6a", /* 0x6a */
313 "Reserved 0x6b", /* 0x6b */
314 "Reserved 0x6c", /* 0x6c */
315 "Reserved 0x6d", /* 0x6d */
316 "Reserved 0x6e", /* 0x6e */
317 "Reserved 0x6f", /* 0x6f */
318 "Reserved 0x70", /* 0x70 */
319 "Reserved 0x71", /* 0x71 */
320 "Reserved 0x72", /* 0x72 */
321 "Reserved 0x73", /* 0x73 */
322 "Reserved 0x74", /* 0x74 */
323 "Reserved 0x75", /* 0x75 */
324 "Reserved 0x76", /* 0x76 */
325 "Reserved 0x77", /* 0x77 */
326 "Reserved 0x78", /* 0x78 */
327 "Reserved 0x79", /* 0x79 */
328 "Reserved 0x7a", /* 0x7a */
329 "Reserved 0x7b", /* 0x7b */
330 "Reserved 0x7c", /* 0x7c */
331 "Reserved 0x7d", /* 0x7d */
332 "Reserved 0x7e", /* 0x7e */
333 "Reserved 0x7f" /* 0x7f */
336 /* Sub-ID for long format from Table 7-17 of 802.15.4-2015 */
337 static const char *p_mlme_long_names
[] = {
338 "Reserved 0x00", /* 0x00 */
339 "Reserved 0x01", /* 0x01 */
340 "Reserved 0x02", /* 0x02 */
341 "Reserved 0x03", /* 0x03 */
342 "Reserved 0x04", /* 0x04 */
343 "Reserved 0x05", /* 0x05 */
344 "Reserved 0x06", /* 0x06 */
345 "Reserved 0x07", /* 0x07 */
346 "Vendor Specific MLME Nested IE", /* 0x08 */
347 "Channel Hopping IE", /* 0x09 */
348 "Reserved 0x0a", /* 0x0a */
349 "Reserved 0x0b", /* 0x0b */
350 "Reserved 0x0c", /* 0x0c */
351 "Reserved 0x0d", /* 0x0d */
352 "Reserved 0x0e", /* 0x0e */
353 "Reserved 0x0f" /* 0x0f */
356 /* MAC commands from Table 7-49 of 802.15.4-2015 */
357 static const char *mac_c_names
[] = {
358 "Reserved 0x00", /* 0x00 */
359 "Association Request command", /* 0x01 */
360 "Association Response command", /* 0x02 */
361 "Disassociation Notification command", /* 0x03 */
362 "Data Request command", /* 0x04 */
363 "PAN ID Conflict Notification command", /* 0x05 */
364 "Orphan Notification command", /* 0x06 */
365 "Beacon Request command", /* 0x07 */
366 "Coordinator realignment command", /* 0x08 */
367 "GTS request command", /* 0x09 */
368 "TRLE Management Request command", /* 0x0a */
369 "TRLE Management Response command", /* 0x0b */
370 "Reserved 0x0c", /* 0x0c */
371 "Reserved 0x0d", /* 0x0d */
372 "Reserved 0x0e", /* 0x0e */
373 "Reserved 0x0f", /* 0x0f */
374 "Reserved 0x10", /* 0x10 */
375 "Reserved 0x11", /* 0x11 */
376 "Reserved 0x12", /* 0x12 */
377 "DSME Association Request command", /* 0x13 */
378 "DSME Association Response command", /* 0x14 */
379 "DSME GTS Request command", /* 0x15 */
380 "DSME GTS Response command", /* 0x16 */
381 "DSME GTS Notify command", /* 0x17 */
382 "DSME Information Request command", /* 0x18 */
383 "DSME Information Response command", /* 0x19 */
384 "DSME Beacon Allocation Notification command", /* 0x1a */
385 "DSME Beacon Collision Notification command", /* 0x1b */
386 "DSME Link Report command", /* 0x1c */
387 "Reserved 0x1d", /* 0x1d */
388 "Reserved 0x1e", /* 0x1e */
389 "Reserved 0x1f", /* 0x1f */
390 "RIT Data Request command", /* 0x20 */
391 "DBS Request command", /* 0x21 */
392 "DBS Response command", /* 0x22 */
393 "RIT Data Response command", /* 0x23 */
394 "Vendor Specific command", /* 0x24 */
395 "Reserved 0x25", /* 0x25 */
396 "Reserved 0x26", /* 0x26 */
397 "Reserved 0x27", /* 0x27 */
398 "Reserved 0x28", /* 0x28 */
399 "Reserved 0x29", /* 0x29 */
400 "Reserved 0x2a", /* 0x2a */
401 "Reserved 0x2b", /* 0x2b */
402 "Reserved 0x2c", /* 0x2c */
403 "Reserved 0x2d", /* 0x2d */
404 "Reserved 0x2e", /* 0x2e */
405 "Reserved 0x2f" /* 0x2f */
409 * Frame Control subfields.
411 #define FC_FRAME_TYPE(fc) ((fc) & 0x7)
412 #define FC_FRAME_VERSION(fc) (((fc) >> 12) & 0x3)
414 #define FC_ADDRESSING_MODE_NONE 0x00
415 #define FC_ADDRESSING_MODE_RESERVED 0x01
416 #define FC_ADDRESSING_MODE_SHORT 0x02
417 #define FC_ADDRESSING_MODE_LONG 0x03
420 * IEEE 802.15.4 CRC 16 function. This is using CCITT polynomical of 0x1021,
421 * but the initial value is 0, and the bits are reversed for both in and out.
422 * See secton 7.2.10 of 802.15.4-2015 for more information.
425 ieee802_15_4_crc16(const u_char
*p
,
431 crc
= 0x0000; /* Note, initial value is 0x0000 not 0xffff. */
433 while (data_len
!= 0){
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));
443 ((unsigned short)(x
<< 12)) ^
444 ((unsigned short)(x
<<5)) ^
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));
457 * Reverses the bits of the 32-bit word.
460 ieee802_15_4_reverse32(uint32_t x
)
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);
471 * IEEE 802.15.4 CRC 32 function. This is using ANSI X3.66-1979 polynomical of
472 * 0x04C11DB7, but the initial value is 0, and the bits are reversed for both
473 * in and out. See secton 7.2.10 of 802.15.4-2015 for more information.
476 ieee802_15_4_crc32(const u_char
*p
,
482 crc
= 0x00000000; /* Note, initial value is 0x00000000 not 0xffffffff */
484 while (data_len
!= 0){
486 /* Reverse bits on input */
487 byte
= ieee802_15_4_reverse32(byte
);
489 for(b
= 0; b
<= 7; b
++) {
490 if ((int) (crc
^ byte
) < 0)
491 crc
= (crc
<< 1) ^ 0x04C11DB7;
498 /* Reverse bits on output */
499 crc
= ieee802_15_4_reverse32(crc
);
504 * Find out the address length based on the address type. See table 7-3 of
505 * 802.15.4-2015. Returns the address length.
508 ieee802_15_4_addr_len(uint16_t addr_type
)
511 case FC_ADDRESSING_MODE_NONE
: /* None. */
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. */
521 case FC_ADDRESSING_MODE_SHORT
: /* Short. */
524 case FC_ADDRESSING_MODE_LONG
: /* Extended. */
532 * Print out the ieee 802.15.4 address.
535 ieee802_15_4_print_addr(netdissect_options
*ndo
, const u_char
*p
,
538 switch (dst_addr_len
) {
543 ND_PRINT("%04x", EXTRACT_LE_U_2(p
));
546 ND_PRINT("%s", le64addr_string(ndo
, p
));
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
558 ieee802_15_4_print_superframe_specification(netdissect_options
*ndo
,
561 if (ndo
->ndo_vflag
< 1) {
564 ND_PRINT("\n\tBeacon order = %d, Superframe order = %d, ",
565 (ss
& 0xf), ((ss
>> 4) & 0xf));
566 ND_PRINT("Final CAP Slot = %d",
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(", Assocation Permit"); }
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.
577 * Returns number of byts consumed from the packet or -1 in case of error.
580 ieee802_15_4_print_gts_info(netdissect_options
*ndo
,
584 uint8_t gts_spec
, gts_cnt
;
588 gts_spec
= EXTRACT_U_1(p
);
589 gts_cnt
= gts_spec
& 0x7;
592 if (ndo
->ndo_vflag
> 0) {
593 ND_PRINT("\n\tGTS Descriptor Count = %d, ", gts_cnt
);
597 len
= 1 + 1 + gts_cnt
* 3;
599 if (data_len
< len
) {
600 ND_PRINT(" [ERROR: Truncated GTS Info List]");
603 if (ndo
->ndo_vflag
< 2) {
606 ND_PRINT("GTS Descriptor Count = %d, ", gts_cnt
);
607 ND_PRINT("GTS Directions Mask = %02x, [ ",
608 EXTRACT_U_1(p
+ 1) & 0x7f);
610 for(i
= 0; i
< gts_cnt
; i
++) {
612 ieee802_15_4_print_addr(ndo
, p
+ 2 + i
* 3, 2);
613 ND_PRINT(", Start slot = %d, Length = %d ] ",
614 EXTRACT_U_1(p
+ 2 + i
* 3 + 1) & 0x0f,
615 (EXTRACT_U_1(p
+ 2 + i
* 3 + 1) >> 4) & 0x0f);
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.
625 * Returns number of byts consumed from the packet or -1 in case of error.
628 ieee802_15_4_print_pending_addresses(netdissect_options
*ndo
,
632 uint8_t pas
, s_cnt
, e_cnt
, len
, i
;
634 pas
= EXTRACT_U_1(p
);
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",
643 if (data_len
< len
) {
644 ND_PRINT(" [ERROR: Pending address list truncated]");
647 if (ndo
->ndo_vflag
< 2) {
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);
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 +
671 * Print header ie content.
674 ieee802_15_4_print_header_ie(netdissect_options
*ndo
,
681 switch (element_id
) {
682 case 0x00: /* Vendor Specific Header IE */
684 ND_PRINT("[ERROR: Vendor OUI missing]");
686 ND_PRINT("OUI = 0x%02x%02x%02x, ", EXTRACT_U_1(p
),
687 EXTRACT_U_1(p
+ 1), EXTRACT_U_1(p
+ 2));
689 for(i
= 3; i
< ie_len
; i
++) {
690 ND_PRINT("%02x ", EXTRACT_U_1(p
+ i
));
694 case 0x1a: /* LE CSL IE */
696 ND_PRINT("[ERROR: Truncated CSL IE]");
698 ND_PRINT("CSL Phase = %d, CSL Period = %d",
699 EXTRACT_LE_U_2(p
), EXTRACT_LE_U_2(p
+ 2));
701 ND_PRINT(", Rendezvous time = %d",
702 EXTRACT_LE_U_2(p
+ 4));
704 if (ie_len
!= 4 && ie_len
!= 6) {
705 ND_PRINT(" [ERROR: CSL IE length wrong]");
709 case 0x1b: /* LE RIT IE */
711 ND_PRINT("[ERROR: Truncated RIT IE]");
713 ND_PRINT("Time to First Listen = %d, # of Repeat Listen = %d, Repeat Listen Interval = %d",
716 EXTRACT_LE_U_2(p
+ 2));
719 case 0x1c: /* DSME PAN Descriptor IE */
721 case 0x21: /* Extended DSME PAN descriptior IE */
723 ND_PRINT("[ERROR: Truncated DSME PAN IE]");
725 uint16_t ss
, ptr
, ulen
;
731 ss
= EXTRACT_LE_U_2(p
);
732 ieee802_15_4_print_superframe_specification(ndo
, ss
);
734 ND_PRINT("[ERROR: Truncated before pending addresses field]");
738 len
= ieee802_15_4_print_pending_addresses(ndo
,
747 if (element_id
== 0x21) {
748 /* Extended version. */
749 if (ie_len
< ptr
+ 2) {
750 ND_PRINT("[ERROR: Truncated before DSME Superframe Specification]");
753 ss
= EXTRACT_LE_U_2(p
+ ptr
);
755 ND_PRINT("Multi-superframe Order = %d", ss
& 0xff);
756 ND_PRINT(", %s", ((ss
& 0x100) ?
757 "Channel hopping mode" :
758 "Channel adaptation mode"));
760 ND_PRINT(", CAP reduction enabled");
763 ND_PRINT(", Deferred beacon enabled");
766 ND_PRINT(", Hopping Sequence Present");
770 if (ie_len
< ptr
+ 1) {
771 ND_PRINT("[ERROR: Truncated before DSME Superframe Specification]");
774 ss
= EXTRACT_U_1(p
+ ptr
);
776 ND_PRINT("Multi-superframe Order = %d",
778 ND_PRINT(", %s", ((ss
& 0x10) ?
779 "Channel hopping mode" :
780 "Channel adaptation mode"));
782 ND_PRINT(", CAP reduction enabled");
785 ND_PRINT(", Deferred beacon enabled");
788 if (ie_len
< ptr
+ 8) {
789 ND_PRINT(" [ERROR: Truncated before Time syncronization specification]");
792 ND_PRINT("Beacon timestamp = %" PRIu64
", offset = %d",
793 EXTRACT_LE_U_6(p
+ ptr
),
794 EXTRACT_LE_U_2(p
+ ptr
+ 6));
796 if (ie_len
< ptr
+ 4) {
797 ND_PRINT(" [ERROR: Truncated before Beacon Bitmap]");
801 ulen
= EXTRACT_LE_U_2(p
+ ptr
+ 2);
802 ND_PRINT("SD Index = %d, Bitmap len = %d, ",
803 EXTRACT_LE_U_2(p
+ ptr
), ulen
);
805 if (ie_len
< ptr
+ ulen
) {
806 ND_PRINT(" [ERROR: Truncated in SD bitmap]");
809 ND_PRINT(" SD Bitmap = ");
810 for(i
= 0; i
< ulen
; i
++) {
811 ND_PRINT("%02x ", EXTRACT_U_1(p
+ ptr
+ i
));
815 if (ie_len
< ptr
+ 5) {
816 ND_PRINT(" [ERROR: Truncated before Channel hopping specification]");
820 ulen
= EXTRACT_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 EXTRACT_U_1(p
+ ptr
),
824 EXTRACT_U_1(p
+ ptr
+ 1),
825 EXTRACT_LE_U_2(p
+ ptr
+ 2),
828 if (ie_len
< ptr
+ ulen
) {
829 ND_PRINT(" [ERROR: Truncated in Channel offset bitmap]");
832 ND_PRINT(" Channel offset bitmap = ");
833 for(i
= 0; i
< ulen
; i
++) {
834 ND_PRINT("%02x ", EXTRACT_U_1(p
+ ptr
+ i
));
837 if (hopping_present
) {
838 if (ie_len
< ptr
+ 1) {
839 ND_PRINT(" [ERROR: Truncated in Hopping Sequence length]");
842 ulen
= EXTRACT_U_1(p
+ ptr
);
844 ND_PRINT("Hopping Seq length = %d [ ", ulen
);
846 /* The specification is not clear how the
847 hopping sequence is encoded, I assume two
848 octet unsigned integers for each channel. */
850 if (ie_len
< ptr
+ ulen
* 2) {
851 ND_PRINT(" [ERROR: Truncated in Channel offset bitmap]");
854 for(i
= 0; i
< ulen
; i
++) {
855 ND_PRINT("%02x ", EXTRACT_LE_U_2(p
+ ptr
+ i
* 2));
862 case 0x1d: /* Rendezvous Tome IE */
864 ND_PRINT("[ERROR: Length != 2]");
866 uint16_t r_time
, w_u_interval
;
867 r_time
= EXTRACT_LE_U_2(p
);
868 w_u_interval
= EXTRACT_LE_U_2(p
+ 2);
870 ND_PRINT("Rendezvous time = %d, Wake-up Interval = %d",
871 r_time
, w_u_interval
);
874 case 0x1e: /* Time correction IE */
876 ND_PRINT("[ERROR: Length != 2]");
881 val
= EXTRACT_LE_U_2(p
);
882 if (val
& 0x8000) { ND_PRINT("Negative "); }
888 ND_PRINT("Ack time correction = %d, ", timecorr
);
891 case 0x22: /* Frament Sequence Content Description IE */
892 /* XXX Not implemented */
893 case 0x23: /* Simplified Superframe Specification IE */
894 /* XXX Not implemented */
895 case 0x24: /* Simplified GTS Specification IE */
896 /* XXX Not implemented */
897 case 0x25: /* LECIM Capabilities IE */
898 /* XXX Not implemented */
899 case 0x26: /* TRLE Descriptor IE */
900 /* XXX Not implemented */
901 case 0x27: /* RCC Capabilities IE */
902 /* XXX Not implemented */
903 case 0x28: /* RCCN Descriptor IE */
904 /* XXX Not implemented */
905 case 0x29: /* Global Time IE */
906 /* XXX Not implemented */
907 case 0x2b: /* DA IE */
908 /* XXX Not implemented */
910 ND_PRINT("IE Data = ");
911 for(i
= 0; i
< ie_len
; i
++) {
912 ND_PRINT("%02x ", EXTRACT_U_1(p
+ i
));
919 * Parse and print Header IE list. See 7.4.2 of 802.15.4-2015 for
922 * Returns number of byts consumed from the packet or -1 in case of error.
925 ieee802_15_4_print_header_ie_list(netdissect_options
*ndo
,
928 int *payload_ie_present
)
930 int len
, ie
, element_id
, i
;
933 *payload_ie_present
= 0;
937 ND_PRINT("[ERROR: Truncated header IE]");
940 /* Extract IE Header */
941 ie
= EXTRACT_LE_U_2(p
);
942 if (CHECK_BIT(ie
, 15)) {
943 ND_PRINT("[ERROR: Header IE with type 1] ");
945 /* Get length and Element ID */
947 element_id
= (ie
>> 7) & 0xff;
948 if (element_id
> 127) {
949 ND_PRINT("Reserved Element ID %02x, length = %d ",
953 ND_PRINT("\n\t%s [", h_ie_names
[element_id
]);
955 ND_PRINT("\n\t%s [ length = %d, ",
956 h_ie_names
[element_id
], ie_len
);
959 if (caplen
< ie_len
) {
960 ND_PRINT("[ERROR: Truncated IE data]");
966 /* Parse and print content. */
967 if (ndo
->ndo_vflag
> 3 && ie_len
!= 0) {
968 ieee802_15_4_print_header_ie(ndo
, p
,
972 ND_PRINT("IE Data = ");
973 for(i
= 0; i
< ie_len
; i
++) {
974 ND_PRINT("%02x ", EXTRACT_U_1(p
+ i
));
981 caplen
-= 2 + ie_len
;
982 if (element_id
== 0x7e) {
983 *payload_ie_present
= 1;
986 if (element_id
== 0x7f) {
989 } while (caplen
> 0);
994 * Print MLME ie content.
997 ieee802_15_4_print_mlme_ie(netdissect_options
*ndo
,
1005 /* Note, as there is no overlap with the long and short
1006 MLME sub IDs, we can just use one switch here. */
1008 case 0x08: /* Vendor Specific Nested IE */
1009 if (sub_ie_len
< 3) {
1010 ND_PRINT("[ERROR: Vendor OUI missing]");
1012 ND_PRINT("OUI = 0x%02x%02x%02x, ",
1015 EXTRACT_U_1(p
+ 2));
1016 ND_PRINT("Data = ");
1017 for(i
= 3; i
< sub_ie_len
; i
++) {
1018 ND_PRINT("%02x ", EXTRACT_U_1(p
+ i
));
1022 case 0x09: /* Channel Hopping IE */
1023 if (sub_ie_len
< 1) {
1024 ND_PRINT("[ERROR: Hopping sequence ID missing]");
1025 } else if (sub_ie_len
== 1) {
1026 ND_PRINT("Hopping Sequence ID = %d", EXTRACT_U_1(p
));
1030 uint16_t channel_page
, number_of_channels
;
1032 ND_PRINT("Hopping Sequence ID = %d", EXTRACT_U_1(p
));
1035 if (sub_ie_len
< 7) {
1036 ND_PRINT("[ERROR: IE truncated]");
1039 channel_page
= EXTRACT_U_1(p
);
1040 number_of_channels
= EXTRACT_LE_U_2(p
+ 1);
1041 ND_PRINT("Channel Page = %d, Number of Channels = %d, ",
1042 channel_page
, number_of_channels
);
1043 ND_PRINT("Phy Configuration = 0x%08x, ",
1044 EXTRACT_LE_U_4(p
+ 3));
1047 if (channel_page
== 9 || channel_page
== 10) {
1048 len
= (number_of_channels
+ 7) / 8;
1049 if (sub_ie_len
< len
) {
1050 ND_PRINT("[ERROR: IE truncated]");
1053 ND_PRINT("Extended bitmap = 0x");
1054 for(i
= 0; i
< len
; i
++) {
1055 ND_PRINT("%02x", EXTRACT_U_1(p
+ i
));
1061 if (sub_ie_len
< 2) {
1062 ND_PRINT("[ERROR: IE truncated]");
1065 len
= EXTRACT_LE_U_2(p
);
1068 ND_PRINT("Hopping Seq length = %d [ ", len
);
1070 if (sub_ie_len
< len
* 2) {
1071 ND_PRINT(" [ERROR: IE truncated]");
1074 for(i
= 0; i
< len
; i
++) {
1075 ND_PRINT("%02x ", EXTRACT_LE_U_2(p
+ i
* 2));
1079 sub_ie_len
-= len
* 2;
1080 if (sub_ie_len
< 2) {
1081 ND_PRINT("[ERROR: IE truncated]");
1084 ND_PRINT("Current hop = %d", EXTRACT_LE_U_2(p
));
1088 case 0x1a: /* TSCH Syncronization IE. */
1089 if (sub_ie_len
< 6) {
1090 ND_PRINT("[ERROR: Length != 6]");
1092 ND_PRINT("ASN = %010" PRIx64
", Join Metric = %d ",
1093 EXTRACT_LE_U_5(p
), EXTRACT_U_1(p
+ 5));
1095 case 0x1b: /* TSCH Slotframe and Link IE. */
1097 int sf_num
, off
, links
, opts
;
1099 if (sub_ie_len
< 1) {
1100 ND_PRINT("[ERROR: Truncated IE]");
1103 sf_num
= EXTRACT_U_1(p
);
1104 ND_PRINT("Slotframes = %d ", sf_num
);
1106 for(i
= 0; i
< sf_num
; i
++) {
1107 if (sub_ie_len
< off
+ 4) {
1108 ND_PRINT("[ERROR: Truncated IE before slotframes]");
1111 links
= EXTRACT_U_1(p
+ off
+ 3);
1112 ND_PRINT("\n\t\t\t[ Handle %d, size = %d, links = %d ",
1113 EXTRACT_U_1(p
+ off
),
1114 EXTRACT_LE_U_2(p
+ off
+ 1),
1117 for(j
= 0; j
< links
; j
++) {
1118 if (sub_ie_len
< off
+ 5) {
1119 ND_PRINT("[ERROR: Truncated IE links]");
1122 opts
= EXTRACT_U_1(p
+ off
+ 4);
1123 ND_PRINT("\n\t\t\t\t[ Timeslot = %d, Offset = %d, Options = ",
1124 EXTRACT_LE_U_2(p
+ off
),
1125 EXTRACT_LE_U_2(p
+ off
+ 2));
1126 if (opts
& 0x1) { ND_PRINT("TX "); }
1127 if (opts
& 0x2) { ND_PRINT("RX "); }
1128 if (opts
& 0x4) { ND_PRINT("Shared "); }
1130 ND_PRINT("Timekeeping ");
1133 ND_PRINT("Priority ");
1142 case 0x1c: /* TSCH Timeslot IE. */
1143 if (sub_ie_len
== 1) {
1144 ND_PRINT("Time slot ID = %d ", EXTRACT_U_1(p
));
1145 } else if (sub_ie_len
== 25) {
1146 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 EXTRACT_LE_U_2(p
+ 1),
1149 EXTRACT_LE_U_2(p
+ 3),
1150 EXTRACT_LE_U_2(p
+ 5),
1151 EXTRACT_LE_U_2(p
+ 7),
1152 EXTRACT_LE_U_2(p
+ 9),
1153 EXTRACT_LE_U_2(p
+ 11),
1154 EXTRACT_LE_U_2(p
+ 13),
1155 EXTRACT_LE_U_2(p
+ 15),
1156 EXTRACT_LE_U_2(p
+ 17),
1157 EXTRACT_LE_U_2(p
+ 19),
1158 EXTRACT_LE_U_2(p
+ 21),
1159 EXTRACT_LE_U_2(p
+ 23));
1160 } else if (sub_ie_len
== 27) {
1161 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 EXTRACT_LE_U_2(p
+ 1),
1164 EXTRACT_LE_U_2(p
+ 3),
1165 EXTRACT_LE_U_2(p
+ 5),
1166 EXTRACT_LE_U_2(p
+ 7),
1167 EXTRACT_LE_U_2(p
+ 9),
1168 EXTRACT_LE_U_2(p
+ 11),
1169 EXTRACT_LE_U_2(p
+ 13),
1170 EXTRACT_LE_U_2(p
+ 15),
1171 EXTRACT_LE_U_2(p
+ 17),
1172 EXTRACT_LE_U_2(p
+ 19),
1173 EXTRACT_LE_U_3(p
+ 21),
1174 EXTRACT_LE_U_3(p
+ 24));
1176 ND_PRINT("[ERROR: Length not 1, 25, or 27]");
1177 ND_PRINT("\n\t\t\tIE Data = ");
1178 for(i
= 0; i
< sub_ie_len
; i
++) {
1179 ND_PRINT("%02x ", EXTRACT_U_1(p
+ i
));
1183 case 0x1d: /* Hopping timing IE */
1184 /* XXX Not implemented */
1185 case 0x1e: /* Enhanced Beacon Filter IE */
1186 /* XXX Not implemented */
1187 case 0x1f: /* MAC Metrics IE */
1188 /* XXX Not implemented */
1189 case 0x20: /* All MAC Metrics IE */
1190 /* XXX Not implemented */
1191 case 0x21: /* Coexistence Specification IE */
1192 /* XXX Not implemented */
1193 case 0x22: /* SUN Device Capabilities IE */
1194 /* XXX Not implemented */
1195 case 0x23: /* SUN FSK Generic PHY IE */
1196 /* XXX Not implemented */
1197 case 0x24: /* Mode Switch Parameter IE */
1198 /* XXX Not implemented */
1199 case 0x25: /* PHY Parameter Change IE */
1200 /* XXX Not implemented */
1201 case 0x26: /* O-QPSK PHY Mode IE */
1202 /* XXX Not implemented */
1203 case 0x27: /* PCA Allocation IE */
1204 /* XXX Not implemented */
1205 case 0x28: /* LECIM DSSS Operating Mode IE */
1206 /* XXX Not implemented */
1207 case 0x29: /* LECIM FSK Operating Mode IE */
1208 /* XXX Not implemented */
1209 case 0x2b: /* TVWS PHY Operating Mode Description IE */
1210 /* XXX Not implemented */
1211 case 0x2c: /* TVWS Device Capabilities IE */
1212 /* XXX Not implemented */
1213 case 0x2d: /* TVWS Device Catagory IE */
1214 /* XXX Not implemented */
1215 case 0x2e: /* TVWS Device Identification IE */
1216 /* XXX Not implemented */
1217 case 0x2f: /* TVWS Device Location IE */
1218 /* XXX Not implemented */
1219 case 0x30: /* TVWS Channel Information Query IE */
1220 /* XXX Not implemented */
1221 case 0x31: /* TVWS Channel Information Source IE */
1222 /* XXX Not implemented */
1223 case 0x32: /* CTM IE */
1224 /* XXX Not implemented */
1225 case 0x33: /* Timestamp IE */
1226 /* XXX Not implemented */
1227 case 0x34: /* Timestamp Difference IE */
1228 /* XXX Not implemented */
1229 case 0x35: /* TMCTP Specification IE */
1230 /* XXX Not implemented */
1231 case 0x36: /* TCC PHY Operating Mode IE */
1232 /* XXX Not implemented */
1234 ND_PRINT("IE Data = ");
1235 for(i
= 0; i
< sub_ie_len
; i
++) {
1236 ND_PRINT("%02x ", EXTRACT_U_1(p
+ i
));
1243 * MLME IE list parsing and printing. See 7.4.3.2 of 802.15.4-2015
1244 * for more information.
1247 ieee802_15_4_print_mlme_ie_list(netdissect_options
*ndo
,
1251 int ie
, sub_id
, i
, type
;
1252 uint16_t sub_ie_len
;
1256 ND_PRINT("[ERROR: Truncated MLME IE]");
1259 /* Extract IE header */
1260 ie
= EXTRACT_LE_U_2(p
);
1261 type
= CHECK_BIT(ie
, 15);
1264 sub_ie_len
= ie
& 0x3ff;
1265 sub_id
= (ie
>> 11) & 0x0f;
1267 sub_ie_len
= ie
& 0xff;
1268 sub_id
= (ie
>> 8) & 0x7f;
1271 /* Skip the IE header */
1275 ND_PRINT("\n\t\t%s [ length = %d, ",
1276 p_mlme_short_names
[sub_id
], sub_ie_len
);
1278 ND_PRINT("\n\t\t%s [ length = %d, ",
1279 p_mlme_long_names
[sub_id
], sub_ie_len
);
1282 if (ie_len
< sub_ie_len
) {
1283 ND_PRINT("[ERROR: Truncated IE data]");
1286 if (sub_ie_len
!= 0) {
1287 if (ndo
->ndo_vflag
> 3) {
1288 ieee802_15_4_print_mlme_ie(ndo
, p
, sub_ie_len
, sub_id
);
1289 } else if (ndo
->ndo_vflag
> 2) {
1290 ND_PRINT("IE Data = ");
1291 for(i
= 0; i
< sub_ie_len
; i
++) {
1292 ND_PRINT("%02x ", EXTRACT_U_1(p
+ i
));
1298 ie_len
-= 2 + sub_ie_len
;
1299 } while (ie_len
> 0);
1304 * Multiplexd IE (802.15.9) parsing and printing.
1306 * Returns number of bytes consumed from packet or -1 in case of error.
1309 ieee802_15_4_print_mpx_ie(netdissect_options
*ndo
,
1313 int transfer_type
, tid
;
1314 int fragment_number
, data_start
;
1319 ND_PRINT("[ERROR: Transaction control byte missing]");
1323 transfer_type
= EXTRACT_U_1(p
) & 0x7;
1324 tid
= EXTRACT_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) {
1333 ND_PRINT("[ERROR: Multiplex ID missing]");
1337 ND_PRINT("tid = 0x%02x, Multiplex ID = 0x%04x, ",
1338 tid
, EXTRACT_LE_U_2(p
+ 1));
1341 ND_PRINT("Multiplex ID = 0x%04x, ", tid
);
1344 case 0x02: /* First, or middle, Fragments */
1345 case 0x04: /* Last fragment */
1347 ND_PRINT("[ERROR: fragment number missing]");
1351 fragment_number
= EXTRACT_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
,
1359 if (fragment_number
== 0) {
1360 int total_size
, multiplex_id
;
1363 ND_PRINT("[ERROR: Total upper layer size or multiplex ID missing]");
1366 total_size
= EXTRACT_LE_U_2(p
+ 2);
1367 multiplex_id
= EXTRACT_LE_U_2(p
+ 4);
1368 ND_PRINT("Total upper layer size = 0x%04x, Multiplex ID = 0x%04x, ",
1369 total_size
, multiplex_id
);
1373 case 0x06: /* Abort code */
1375 ND_PRINT("Type = Abort, tid = 0x%02x, no max size given",
1377 } else if (ie_len
== 3) {
1378 ND_PRINT("Type = Abort, tid = 0x%02x, max size = 0x%04x",
1379 tid
, EXTRACT_LE_U_2(p
+ 1));
1381 ND_PRINT("Type = Abort, tid = 0x%02x, invalid length = %d (not 1 or 3)",
1383 ND_PRINT("Abort data = ");
1384 for(i
= 1; i
< ie_len
; i
++) {
1385 ND_PRINT("%02x ", EXTRACT_U_1(p
+ i
));
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
);
1400 ND_PRINT("Upper layer data = ");
1401 for(i
= data_start
; i
< ie_len
; i
++) {
1402 ND_PRINT("%02x ", EXTRACT_U_1(p
+ i
));
1407 * Payload IE list parsing and printing. See 7.4.3 of 802.15.4-2015
1408 * for more information.
1410 * Returns number of byts consumed from the packet or -1 in case of error.
1413 ieee802_15_4_print_payload_ie_list(netdissect_options
*ndo
,
1417 int len
, ie
, group_id
, i
;
1423 ND_PRINT("[ERROR: Truncated header IE]");
1426 /* Extract IE header */
1427 ie
= EXTRACT_LE_U_2(p
);
1428 if ((CHECK_BIT(ie
, 15)) == 0) {
1429 ND_PRINT("[ERROR: Payload IE with type 0] ");
1431 ie_len
= ie
& 0x3ff;
1432 group_id
= (ie
>> 11) & 0x0f;
1434 /* Skip the IE header */
1437 ND_PRINT("\n\t%s [", p_ie_names
[group_id
]);
1439 ND_PRINT("\n\t%s [ length = %d, ",
1440 p_ie_names
[group_id
], ie_len
);
1442 if (caplen
< ie_len
) {
1443 ND_PRINT("[ERROR: Truncated IE data]");
1446 if (ndo
->ndo_vflag
> 3 && ie_len
!= 0) {
1448 case 0x1: /* MLME IE */
1449 ieee802_15_4_print_mlme_ie_list(ndo
, p
, ie_len
);
1451 case 0x2: /* Vendor Specific Nested IE */
1453 ND_PRINT("[ERROR: Vendor OUI missing]");
1455 ND_PRINT("OUI = 0x%02x%02x%02x, ",
1458 EXTRACT_U_1(p
+ 2));
1459 ND_PRINT("Data = ");
1460 for(i
= 3; i
< ie_len
; i
++) {
1462 EXTRACT_U_1(p
+ i
));
1466 case 0x3: /* Multiplexed IE (802.15.9) */
1467 ieee802_15_4_print_mpx_ie(ndo
, p
, ie_len
);
1469 case 0x5: /* IETF IE */
1471 ND_PRINT("[ERROR: Subtype ID missing]");
1473 ND_PRINT("Subtype ID = 0x%02x, Subtype content = ",
1475 for(i
= 1; i
< ie_len
; i
++) {
1476 ND_PRINT("%02x ", EXTRACT_U_1(p
+ i
));
1481 ND_PRINT("IE Data = ");
1482 for(i
= 0; i
< ie_len
; i
++) {
1483 ND_PRINT("%02x ", EXTRACT_U_1(p
+ i
));
1489 ND_PRINT("IE Data = ");
1490 for(i
= 0; i
< ie_len
; i
++) {
1491 ND_PRINT("%02x ", EXTRACT_U_1(p
+ i
));
1498 caplen
-= 2 + ie_len
;
1499 if (group_id
== 0xf) {
1502 } while (caplen
> 0);
1507 * Parse and print auxiliary security header.
1509 * Returns number of byts consumed from the packet or -1 in case of error.
1512 ieee802_15_4_print_aux_sec_header(netdissect_options
*ndo
,
1515 int *security_level
)
1517 int sc
, key_id_mode
, len
;
1520 ND_PRINT("[ERROR: Truncated before Aux Security Header]");
1523 sc
= EXTRACT_U_1(p
);
1525 *security_level
= sc
& 0x7;
1526 key_id_mode
= (sc
>> 3) & 0x3;
1531 if (ndo
->ndo_vflag
> 0) {
1532 ND_PRINT("\n\tSecurity Level %d, Key Id Mode %d, ",
1533 *security_level
, key_id_mode
);
1535 if ((CHECK_BIT(sc
, 5)) == 0) {
1537 ND_PRINT("[ERROR: Truncated before Frame Counter]");
1543 if (ndo
->ndo_vflag
> 1) {
1544 ND_PRINT("Frame Counter 0x%08x ",
1545 EXTRACT_LE_U_4(p
+ 1));
1548 switch (key_id_mode
) {
1549 case 0x00: /* Implicit. */
1550 if (ndo
->ndo_vflag
> 1) {
1551 ND_PRINT("Implicit");
1555 case 0x01: /* Key Index, nothing to print here. */
1557 case 0x02: /* PAN and Short address Key Source, and Key Index. */
1559 ND_PRINT("[ERROR: Truncated before Key Source]");
1562 if (ndo
->ndo_vflag
> 1) {
1563 ND_PRINT("KeySource 0x%04x:%0x4x, ",
1564 EXTRACT_LE_U_2(p
), EXTRACT_LE_U_2(p
+ 2));
1570 case 0x03: /* Extended address and Key Index. */
1572 ND_PRINT("[ERROR: Truncated before Key Source]");
1575 if (ndo
->ndo_vflag
> 1) {
1576 ND_PRINT("KeySource %s, ", le64addr_string(ndo
, p
));
1584 ND_PRINT("[ERROR: Truncated before Key Index]");
1587 if (ndo
->ndo_vflag
> 1) {
1588 ND_PRINT("KeyIndex 0x%02x, ", EXTRACT_U_1(p
));
1597 * Print command data.
1599 * Returns number of byts consumed from the packet or -1 in case of error.
1602 ieee802_15_4_print_command_data(netdissect_options
*ndo
,
1609 switch (command_id
) {
1610 case 0x01: /* Assocation Request */
1612 ND_PRINT("Invalid Assocation request command length");
1616 cap_info
= EXTRACT_U_1(p
);
1617 ND_PRINT("%s%s%s%s%s%s",
1618 ((cap_info
& 0x02) ?
1620 ((cap_info
& 0x04) ?
1621 "AC powered, " : ""),
1622 ((cap_info
& 0x08) ?
1623 "Receiver on when idle, " : ""),
1624 ((cap_info
& 0x10) ?
1625 "Fast association, " : ""),
1626 ((cap_info
& 0x40) ?
1627 "Security supported, " : ""),
1628 ((cap_info
& 0x80) ?
1629 "Allocate address, " : ""));
1633 case 0x02: /* Assocation Response */
1635 ND_PRINT("Invalid Assocation response command length");
1638 ND_PRINT("Short address = ");
1639 ieee802_15_4_print_addr(ndo
, p
, 2);
1640 switch (EXTRACT_U_1(p
+ 2)) {
1642 ND_PRINT(", Association successful");
1645 ND_PRINT(", PAN at capacity");
1648 ND_PRINT(", PAN access denied");
1651 ND_PRINT(", Hooping sequence offset duplication");
1654 ND_PRINT(", Fast association successful");
1657 ND_PRINT(", Status = 0x%02x",
1658 EXTRACT_U_1(p
+ 2));
1664 case 0x03: /* Diassociation Notification command */
1666 ND_PRINT("Invalid Disassociation Notification command length");
1669 switch (EXTRACT_U_1(p
)) {
1671 ND_PRINT("Reserved");
1674 ND_PRINT("Reason = The coordinator wishes the device to leave PAN");
1677 ND_PRINT("Reason = The device wishes to leave the PAN");
1680 ND_PRINT("Reason = 0x%02x", EXTRACT_U_1(p
+ 2));
1686 /* Following ones do not have any data. */
1687 case 0x04: /* Data Request command */
1688 case 0x05: /* PAN ID Conflict Notification command */
1689 case 0x06: /* Orphan Notification command */
1690 case 0x07: /* Beacon Request command */
1691 /* Should not have any data. */
1693 case 0x08: /* Coordinator Realignment command */
1694 if (caplen
< 7 || caplen
> 8) {
1695 ND_PRINT("Invalid Coordinator Realignment command length");
1698 uint16_t channel
, page
;
1700 ND_PRINT("Pan ID = 0x%04x, Coordinator short address = ",
1702 ieee802_15_4_print_addr(ndo
, p
+ 2, 2);
1703 channel
= EXTRACT_U_1(p
+ 4);
1706 page
= EXTRACT_U_1(p
+ 7);
1710 if (CHECK_BIT(page
, 7)) {
1711 /* No page present, instead we have msb of
1712 channel in the page. */
1713 channel
|= (page
& 0x7f) << 8;
1714 ND_PRINT(", Channel Number = %d", channel
);
1716 ND_PRINT(", Channel Number = %d, page = %d",
1719 ND_PRINT(", Short address = ");
1720 ieee802_15_4_print_addr(ndo
, p
+ 5, 2);
1724 case 0x09: /* GTS Request command */
1726 ND_PRINT("Invalid GTS Request command length");
1731 gts
= EXTRACT_U_1(p
);
1732 ND_PRINT("GTS Length = %d, %s, %s",
1734 (CHECK_BIT(gts
, 4) ?
1735 "Receive-only GTS" : "Transmit-only GTS"),
1736 (CHECK_BIT(gts
, 5) ?
1737 "GTS allocation" : "GTS deallocations"));
1741 case 0x13: /* DSME Association Request command */
1742 /* XXX Not implemented */
1743 case 0x14: /* DSME Association Response command */
1744 /* XXX Not implemented */
1745 case 0x15: /* DSME GTS Request command */
1746 /* XXX Not implemented */
1747 case 0x16: /* DSME GTS Response command */
1748 /* XXX Not implemented */
1749 case 0x17: /* DSME GTS GTS Notify command */
1750 /* XXX Not implemented */
1751 case 0x18: /* DSME Information Request command */
1752 /* XXX Not implemented */
1753 case 0x19: /* DSME Information Response command */
1754 /* XXX Not implemented */
1755 case 0x1a: /* DSME Beacon Allocation Notification command */
1756 /* XXX Not implemented */
1757 case 0x1b: /* DSME Beacon Collision Notification command */
1758 /* XXX Not implemented */
1759 case 0x1c: /* DSME Link Report command */
1760 /* XXX Not implemented */
1761 case 0x20: /* RIT Data Request command */
1762 /* XXX Not implemented */
1763 case 0x21: /* DBS Request command */
1764 /* XXX Not implemented */
1765 case 0x22: /* DBS Response command */
1766 /* XXX Not implemented */
1767 case 0x23: /* RIT Data Response command */
1768 /* XXX Not implemented */
1769 case 0x24: /* Vendor Specific command */
1770 /* XXX Not implemented */
1771 case 0x0a: /* TRLE Management Request command */
1772 /* XXX Not implemented */
1773 case 0x0b: /* TRLE Management Response command */
1774 /* XXX Not implemented */
1776 ND_PRINT("Command Data = ");
1777 for(i
= 0; i
< caplen
; i
++) {
1778 ND_PRINT("%02x ", EXTRACT_U_1(p
+ i
));
1786 * Parse and print frames folloing standard format.
1788 * Returns FALSE in case of error.
1791 ieee802_15_4_std_frames(netdissect_options
*ndo
,
1792 const u_char
*p
, u_int caplen
,
1795 int len
, frame_version
, pan_id_comp
;
1797 int src_pan
, dst_pan
, src_addr_len
, dst_addr_len
;
1798 int security_level
, miclen
= 0;
1799 int payload_ie_present
;
1801 uint32_t fcs
, crc_check
;
1802 const u_char
*mic_start
= NULL
;
1804 payload_ie_present
= 0;
1807 /* Assume 2 octet FCS, the FCS length depends on the PHY, and we do not
1810 /* Cannot have FCS, assume no FCS. */
1813 /* Test for 4 octet FCS. */
1814 fcs
= EXTRACT_LE_U_4(p
+ caplen
- 4);
1815 crc_check
= ieee802_15_4_crc32(p
, caplen
- 4);
1816 if (crc_check
== fcs
) {
1820 /* Test for 2 octet FCS. */
1821 fcs
= EXTRACT_LE_U_2(p
+ caplen
- 2);
1822 crc_check
= ieee802_15_4_crc16(p
, caplen
- 2);
1823 if (crc_check
== fcs
) {
1827 /* Wrong FCS, FCS might not be included in the
1828 captured frame, do not remove it. */
1833 /* Frame version. */
1834 frame_version
= FC_FRAME_VERSION(fc
);
1835 frame_type
= FC_FRAME_TYPE(fc
);
1836 ND_PRINT("v%d ", frame_version
);
1838 if (ndo
->ndo_vflag
> 2) {
1839 if (CHECK_BIT(fc
, 3)) { ND_PRINT("Security Enabled, "); }
1840 if (CHECK_BIT(fc
, 4)) { ND_PRINT("Frame Pending, "); }
1841 if (CHECK_BIT(fc
, 5)) { ND_PRINT("AR, "); }
1842 if (CHECK_BIT(fc
, 6)) { ND_PRINT("PAN ID Compression, "); }
1843 if (CHECK_BIT(fc
, 8)) { ND_PRINT("Sequence Number Suppression, "); }
1844 if (CHECK_BIT(fc
, 9)) { ND_PRINT("IE present, "); }
1847 /* Check for the sequence number supression. */
1848 if (CHECK_BIT(fc
, 8)) {
1849 /* Sequence number is suppressed. */
1850 if (frame_version
< 2) {
1851 /* Sequence number can only be supressed for frame
1852 version 2 or higher, this is invalid frame. */
1853 ND_PRINT("[ERROR: Sequence number suppressed on frames where version < 2]");
1856 ND_PRINT("seq suppressed ");
1860 seq
= EXTRACT_U_1(p
+ 2);
1864 ND_PRINT("seq %02x ", seq
);
1867 /* See which parts of addresses we have. */
1868 dst_addr_len
= ieee802_15_4_addr_len((fc
>> 10) & 0x3);
1869 src_addr_len
= ieee802_15_4_addr_len((fc
>> 14) & 0x3);
1870 if (src_addr_len
< 0) {
1871 ND_PRINT("[ERROR: Invalid src address mode]");
1874 if (dst_addr_len
< 0) {
1875 ND_PRINT("[ERROR: Invalid dst address mode]");
1880 pan_id_comp
= CHECK_BIT(fc
, 6);
1882 /* The PAN ID Compression rules are complicated. */
1884 /* First check old versions, where the rules are simple. */
1885 if (frame_version
< 2) {
1889 if (dst_addr_len
<= 0 || src_addr_len
<= 0) {
1890 /* Invalid frame, PAN ID Compression must be 0
1891 if only one address in the frame. */
1892 ND_PRINT("[ERROR: PAN ID Compression != 0, and only one address with frame version < 2]");
1898 if (dst_addr_len
<= 0) {
1901 if (src_addr_len
<= 0) {
1905 /* Frame version 2 rules are more complicated, and they depend
1906 on the address modes of the frame, generic rules are same,
1907 but then there are some special cases. */
1915 if (dst_addr_len
<= 0) {
1918 if (src_addr_len
<= 0) {
1922 if (src_addr_len
== 0 &&
1923 dst_addr_len
== 0) {
1924 /* Both addresses are missing, but PAN ID
1925 compression set, special case we have
1926 destination PAN but no addresses. */
1928 } else if ((src_addr_len
== 0 &&
1929 dst_addr_len
> 0) ||
1930 (src_addr_len
> 0 &&
1931 dst_addr_len
== 0)) {
1932 /* Only one address present, and PAN ID
1933 compression is set, we do not have PAN id at
1937 } else if (src_addr_len
== 8 &&
1938 dst_addr_len
== 8) {
1939 /* Both addresses are Extended, and PAN ID
1940 compression set, we do not have PAN ID at
1946 /* Special cases where PAN ID Compression is not set. */
1947 if (src_addr_len
== 8 &&
1948 dst_addr_len
== 8) {
1949 /* Both addresses are Extended, and PAN ID
1950 compression not set, we do have only one PAN
1951 ID (destination). */
1955 #ifdef BROKEN_6TISCH_PAN_ID_COMPRESSION
1956 if (src_addr_len
== 8 &&
1957 dst_addr_len
== 2) {
1958 /* Special case for the broken 6tisch
1962 #endif /* BROKEN_6TISCH_PAN_ID_COMPRESSION */
1966 /* Print dst PAN and address. */
1969 ND_PRINT("[ERROR: Truncated before dst_pan]");
1972 ND_PRINT("%04x:", EXTRACT_LE_U_2(p
));
1978 if (caplen
< (u_int
) dst_addr_len
) {
1979 ND_PRINT("[ERROR: Truncated before dst_addr]");
1982 ieee802_15_4_print_addr(ndo
, p
, dst_addr_len
);
1984 caplen
-= dst_addr_len
;
1988 /* Print src PAN and address. */
1991 ND_PRINT("[ERROR: Truncated before dst_pan]");
1994 ND_PRINT("%04x:", EXTRACT_LE_U_2(p
));
2000 if (caplen
< (u_int
) src_addr_len
) {
2001 ND_PRINT("[ERROR: Truncated before dst_addr]");
2004 ieee802_15_4_print_addr(ndo
, p
, src_addr_len
);
2007 caplen
-= src_addr_len
;
2008 if (CHECK_BIT(fc
, 3)) {
2009 len
= ieee802_15_4_print_aux_sec_header(ndo
, p
, caplen
,
2020 switch (security_level
) {
2021 case 0: /*FALLTHOUGH */
2025 case 1: /*FALLTHOUGH */
2029 case 2: /*FALLTHOUGH */
2033 case 3: /*FALLTHOUGH */
2041 if (caplen
< (u_int
) miclen
) {
2042 ND_PRINT("[ERROR: Truncated before MIC]");
2046 mic_start
= p
+ caplen
;
2049 /* Parse Information elements if present */
2050 if (CHECK_BIT(fc
, 9)) {
2051 /* Yes we have those. */
2052 len
= ieee802_15_4_print_header_ie_list(ndo
, p
, caplen
,
2053 &payload_ie_present
);
2061 if (payload_ie_present
) {
2062 if (security_level
>= 4) {
2063 ND_PRINT("Payload IEs present, but encrypted, cannot print ");
2065 len
= ieee802_15_4_print_payload_ie_list(ndo
, p
, caplen
);
2075 if (ndo
->ndo_vflag
> 2 && miclen
!= 0) {
2076 ND_PRINT("\n\tMIC ");
2078 for(len
= 0; len
< miclen
; len
++) {
2079 ND_PRINT("%02x", EXTRACT_U_1(mic_start
+ len
));
2085 if (ndo
->ndo_vflag
> 2) {
2086 if (crc_check
== fcs
) {
2087 ND_PRINT("FCS %x ", fcs
);
2089 ND_PRINT("wrong FCS %x vs %x (assume no FCS stored) ",
2095 switch (frame_type
) {
2096 case 0x00: /* Beacon */
2097 if (frame_version
< 2) {
2099 ND_PRINT("[ERROR: Truncated before beacon information]");
2104 ss
= EXTRACT_LE_U_2(p
);
2105 ieee802_15_4_print_superframe_specification(ndo
, ss
);
2111 ND_PRINT("[ERROR: Truncated before GTS info]");
2115 len
= ieee802_15_4_print_gts_info(ndo
, p
, caplen
);
2123 /* Pending Addresses */
2125 ND_PRINT("[ERROR: Truncated before pending addresses]");
2128 len
= ieee802_15_4_print_pending_addresses(ndo
, p
, caplen
);
2136 if (!ndo
->ndo_suppress_default_print
)
2137 ND_DEFAULTPRINT(p
, caplen
);
2140 case 0x01: /* Data */
2141 case 0x02: /* Acknowledgement */
2142 if (!ndo
->ndo_suppress_default_print
)
2143 ND_DEFAULTPRINT(p
, caplen
);
2145 case 0x03: /* MAC Command */
2147 ND_PRINT("[ERROR: Truncated before Command ID]");
2151 command_id
= EXTRACT_U_1(p
);
2152 if (command_id
>= 0x30) {
2153 ND_PRINT("Command ID = Reserved 0x%02x ",
2156 ND_PRINT("Command ID = %s ",
2157 mac_c_names
[command_id
]);
2162 len
= ieee802_15_4_print_command_data(ndo
, command_id
, p
, caplen
);
2169 if (!ndo
->ndo_suppress_default_print
)
2170 ND_DEFAULTPRINT(p
, caplen
);
2177 * Print and parse Multipurpose frames.
2179 * Returns FALSE in case of error.
2182 ieee802_15_4_mp_frame(netdissect_options
*ndo
,
2183 const u_char
*p
, u_int caplen
,
2186 int len
, frame_version
, pan_id_present
;
2187 int src_addr_len
, dst_addr_len
;
2188 int security_level
, miclen
= 0;
2189 int ie_present
, payload_ie_present
, security_enabled
;
2191 uint32_t fcs
, crc_check
;
2192 const u_char
*mic_start
= NULL
;
2196 payload_ie_present
= 0;
2197 security_enabled
= 0;
2200 /* Assume 2 octet FCS, the FCS length depends on the PHY, and we do not
2203 /* Cannot have FCS, assume no FCS. */
2207 /* Test for 4 octet FCS. */
2208 fcs
= EXTRACT_LE_U_4(p
+ caplen
- 4);
2209 crc_check
= ieee802_15_4_crc32(p
, caplen
- 4);
2210 if (crc_check
== fcs
) {
2214 fcs
= EXTRACT_LE_U_2(p
+ caplen
- 2);
2215 crc_check
= ieee802_15_4_crc16(p
, caplen
- 2);
2216 if (crc_check
== fcs
) {
2222 fcs
= EXTRACT_LE_U_2(p
+ caplen
- 2);
2223 crc_check
= ieee802_15_4_crc16(p
, caplen
- 2);
2224 if (crc_check
== fcs
) {
2231 if (CHECK_BIT(fc
, 3)) {
2232 /* Long Frame Control */
2234 /* Frame version. */
2235 frame_version
= FC_FRAME_VERSION(fc
);
2236 ND_PRINT("v%d ", frame_version
);
2238 pan_id_present
= CHECK_BIT(fc
, 8);
2239 ie_present
= CHECK_BIT(fc
, 15);
2240 security_enabled
= CHECK_BIT(fc
, 9);
2242 if (ndo
->ndo_vflag
> 2) {
2243 if (security_enabled
) { ND_PRINT("Security Enabled, "); }
2244 if (CHECK_BIT(fc
, 11)) { ND_PRINT("Frame Pending, "); }
2245 if (CHECK_BIT(fc
, 14)) { ND_PRINT("AR, "); }
2246 if (pan_id_present
) { ND_PRINT("PAN ID Present, "); }
2247 if (CHECK_BIT(fc
, 10)) {
2248 ND_PRINT("Sequence Number Suppression, ");
2250 if (ie_present
) { ND_PRINT("IE present, "); }
2253 /* Check for the sequence number supression. */
2254 if (CHECK_BIT(fc
, 10)) {
2255 /* Sequence number is suppressed, but long version. */
2259 seq
= EXTRACT_U_1(p
+ 2);
2263 ND_PRINT("seq %02x ", seq
);
2266 /* Short format of header, but with seq no */
2267 seq
= EXTRACT_U_1(p
+ 1);
2271 ND_PRINT("seq %02x ", seq
);
2274 /* See which parts of addresses we have. */
2275 dst_addr_len
= ieee802_15_4_addr_len((fc
>> 4) & 0x3);
2276 src_addr_len
= ieee802_15_4_addr_len((fc
>> 6) & 0x3);
2277 if (src_addr_len
< 0) {
2278 ND_PRINT("[ERROR: Invalid src address mode]");
2281 if (dst_addr_len
< 0) {
2282 ND_PRINT("[ERROR: Invalid dst address mode]");
2286 /* Print dst PAN and address. */
2287 if (pan_id_present
) {
2289 ND_PRINT("[ERROR: Truncated before dst_pan]");
2292 ND_PRINT("%04x:", EXTRACT_LE_U_2(p
));
2298 if (caplen
< (u_int
) dst_addr_len
) {
2299 ND_PRINT("[ERROR: Truncated before dst_addr]");
2302 ieee802_15_4_print_addr(ndo
, p
, dst_addr_len
);
2304 caplen
-= dst_addr_len
;
2308 /* Print src PAN and address. */
2310 if (caplen
< (u_int
) src_addr_len
) {
2311 ND_PRINT("[ERROR: Truncated before dst_addr]");
2314 ieee802_15_4_print_addr(ndo
, p
, src_addr_len
);
2317 caplen
-= src_addr_len
;
2319 if (security_enabled
) {
2320 len
= ieee802_15_4_print_aux_sec_header(ndo
, p
, caplen
,
2331 switch (security_level
) {
2332 case 0: /*FALLTHOUGH */
2336 case 1: /*FALLTHOUGH */
2340 case 2: /*FALLTHOUGH */
2344 case 3: /*FALLTHOUGH */
2352 if (caplen
< (u_int
) miclen
) {
2353 ND_PRINT("[ERROR: Truncated before MIC]");
2357 mic_start
= p
+ caplen
;
2360 /* Parse Information elements if present */
2362 /* Yes we have those. */
2363 len
= ieee802_15_4_print_header_ie_list(ndo
, p
, caplen
,
2364 &payload_ie_present
);
2372 if (payload_ie_present
) {
2373 if (security_level
>= 4) {
2374 ND_PRINT("Payload IEs present, but encrypted, cannot print ");
2376 len
= ieee802_15_4_print_payload_ie_list(ndo
, p
,
2387 if (ndo
->ndo_vflag
> 2 && miclen
!= 0) {
2388 ND_PRINT("\n\tMIC ");
2390 for(len
= 0; len
< miclen
; len
++) {
2391 ND_PRINT("%02x", EXTRACT_U_1(mic_start
+ len
));
2398 if (ndo
->ndo_vflag
> 2) {
2399 if (crc_check
== fcs
) {
2400 ND_PRINT("FCS %x ", fcs
);
2402 ND_PRINT("wrong FCS %x vs %x (assume no FCS stored) ",
2407 if (!ndo
->ndo_suppress_default_print
)
2408 ND_DEFAULTPRINT(p
, caplen
);
2416 * Returns FALSE in case of error.
2419 ieee802_15_4_frag_frame(netdissect_options
*ndo _U_
,
2420 const u_char
*p _U_
,
2424 /* Not implement yet, might be bit hard to implement, as the
2425 * information to set up the fragment is coming in the previous frame
2426 * in the Fragment Sequence Context Description IE, thus we need to
2427 * store information from there, so we can use it here. */
2432 * Interal call to dissector taking packet + len instead of pcap_pkthdr.
2434 * Returns FALSE in case of error.
2437 ieee802_15_4_print(netdissect_options
*ndo
,
2438 const u_char
*p
, u_int caplen
)
2443 ndo
->ndo_protocol
="802.15.4";
2446 nd_print_trunc(ndo
);
2450 fc
= EXTRACT_LE_U_2(p
);
2452 /* First we need to check the frame type to know how to parse the rest
2453 of the FC. Frame type is the first 3 bit of the frame control field.
2456 frame_type
= FC_FRAME_TYPE(fc
);
2457 ND_PRINT("IEEE 802.15.4 %s packet ", ftypes
[frame_type
]);
2459 switch (frame_type
) {
2460 case 0x00: /* Beacon */
2461 case 0x01: /* Data */
2462 case 0x02: /* Acknowledgement */
2463 case 0x03: /* MAC Command */
2464 return ieee802_15_4_std_frames(ndo
, p
, caplen
, fc
);
2466 case 0x04: /* Reserved */
2469 case 0x05: /* Multipurpose */
2470 return ieee802_15_4_mp_frame(ndo
, p
, caplen
, fc
);
2472 case 0x06: /* Fragment or Frak */
2473 return ieee802_15_4_frag_frame(ndo
, p
, caplen
, fc
);
2475 case 0x07: /* Extended */
2483 * Main function to print packets.
2487 ieee802_15_4_if_print(netdissect_options
*ndo
,
2488 const struct pcap_pkthdr
*h
, const u_char
*p
)
2490 u_int caplen
= h
->caplen
;
2491 ndo
->ndo_protocol
="802.15.4_if";
2492 return ieee802_15_4_print(ndo
, p
, caplen
);
2495 /* For DLT_IEEE802_15_4_TAP */
2496 /* https://github.com/jkcko/ieee802.15.4-tap */
2498 ieee802_15_4_tap_if_print(netdissect_options
*ndo
,
2499 const struct pcap_pkthdr
*h
, const u_char
*p
)
2504 ndo
->ndo_protocol
= "802.15.4_tap";
2505 if (h
->caplen
< 4) {
2506 nd_print_trunc(ndo
);
2510 version
= EXTRACT_U_1(p
);
2511 length
= EXTRACT_LE_U_2(p
+2);
2512 if (version
!= 0 || length
< 4) {
2513 nd_print_invalid(ndo
);
2517 if (h
->caplen
< length
) {
2518 nd_print_trunc(ndo
);
2522 return ieee802_15_4_print(ndo
, p
+length
, h
->caplen
-length
) + length
;
2527 * c-style: whitesmith