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