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