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