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