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