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