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