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