]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/tcpdump/print-802_15_4.c
ident(1): Normalizing date format
[FreeBSD/FreeBSD.git] / contrib / tcpdump / print-802_15_4.c
1 /*
2  * Copyright (c) 2009
3  *      Siemens AG, All rights reserved.
4  *      Dmitry Eremin-Solenikov (dbaryshkov@gmail.com)
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that: (1) source code distributions
8  * retain the above copyright notice and this paragraph in its entirety, (2)
9  * distributions including binary code include the above copyright notice and
10  * this paragraph in its entirety in the documentation or other materials
11  * provided with the distribution, and (3) all advertising materials mentioning
12  * features or use of this software display the following acknowledgement:
13  * ``This product includes software developed by the University of California,
14  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
15  * the University nor the names of its contributors may be used to endorse
16  * or promote products derived from this software without specific prior
17  * written permission.
18  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
19  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
20  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
21  */
22
23 /* \summary: IEEE 802.15.4 printer */
24
25 #ifdef HAVE_CONFIG_H
26 #include "config.h"
27 #endif
28
29 #include <netdissect-stdinc.h>
30
31 #include "netdissect.h"
32 #include "addrtoname.h"
33
34 #include "extract.h"
35
36 static const char *ftypes[] = {
37         "Beacon",                       /* 0 */
38         "Data",                         /* 1 */
39         "ACK",                          /* 2 */
40         "Command",                      /* 3 */
41         "Reserved (0x4)",               /* 4 */
42         "Reserved (0x5)",               /* 5 */
43         "Reserved (0x6)",               /* 6 */
44         "Reserved (0x7)",               /* 7 */
45 };
46
47 /*
48  * Frame Control subfields.
49  */
50 #define FC_FRAME_TYPE(fc)               ((fc) & 0x7)
51 #define FC_SECURITY_ENABLED             0x0008
52 #define FC_FRAME_PENDING                0x0010
53 #define FC_ACK_REQUEST                  0x0020
54 #define FC_PAN_ID_COMPRESSION           0x0040
55 #define FC_DEST_ADDRESSING_MODE(fc)     (((fc) >> 10) & 0x3)
56 #define FC_FRAME_VERSION(fc)            (((fc) >> 12) & 0x3)
57 #define FC_SRC_ADDRESSING_MODE(fc)      (((fc) >> 14) & 0x3)
58
59 #define FC_ADDRESSING_MODE_NONE         0x00
60 #define FC_ADDRESSING_MODE_RESERVED     0x01
61 #define FC_ADDRESSING_MODE_SHORT        0x02
62 #define FC_ADDRESSING_MODE_LONG         0x03
63
64 u_int
65 ieee802_15_4_if_print(netdissect_options *ndo,
66                       const struct pcap_pkthdr *h, const u_char *p)
67 {
68         u_int caplen = h->caplen;
69         u_int hdrlen;
70         uint16_t fc;
71         uint8_t seq;
72         uint16_t panid = 0;
73
74         if (caplen < 3) {
75                 ND_PRINT((ndo, "[|802.15.4]"));
76                 return caplen;
77         }
78         hdrlen = 3;
79
80         fc = EXTRACT_LE_16BITS(p);
81         seq = EXTRACT_LE_8BITS(p + 2);
82
83         p += 3;
84         caplen -= 3;
85
86         ND_PRINT((ndo,"IEEE 802.15.4 %s packet ", ftypes[FC_FRAME_TYPE(fc)]));
87         if (ndo->ndo_vflag)
88                 ND_PRINT((ndo,"seq %02x ", seq));
89
90         /*
91          * Destination address and PAN ID, if present.
92          */
93         switch (FC_DEST_ADDRESSING_MODE(fc)) {
94         case FC_ADDRESSING_MODE_NONE:
95                 if (fc & FC_PAN_ID_COMPRESSION) {
96                         /*
97                          * PAN ID compression; this requires that both
98                          * the source and destination addresses be present,
99                          * but the destination address is missing.
100                          */
101                         ND_PRINT((ndo, "[|802.15.4]"));
102                         return hdrlen;
103                 }
104                 if (ndo->ndo_vflag)
105                         ND_PRINT((ndo,"none "));
106                 break;
107         case FC_ADDRESSING_MODE_RESERVED:
108                 if (ndo->ndo_vflag)
109                         ND_PRINT((ndo,"reserved destination addressing mode"));
110                 return hdrlen;
111         case FC_ADDRESSING_MODE_SHORT:
112                 if (caplen < 2) {
113                         ND_PRINT((ndo, "[|802.15.4]"));
114                         return hdrlen;
115                 }
116                 panid = EXTRACT_LE_16BITS(p);
117                 p += 2;
118                 caplen -= 2;
119                 hdrlen += 2;
120                 if (caplen < 2) {
121                         ND_PRINT((ndo, "[|802.15.4]"));
122                         return hdrlen;
123                 }
124                 if (ndo->ndo_vflag)
125                         ND_PRINT((ndo,"%04x:%04x ", panid, EXTRACT_LE_16BITS(p)));
126                 p += 2;
127                 caplen -= 2;
128                 hdrlen += 2;
129                 break;
130         case FC_ADDRESSING_MODE_LONG:
131                 if (caplen < 2) {
132                         ND_PRINT((ndo, "[|802.15.4]"));
133                         return hdrlen;
134                 }
135                 panid = EXTRACT_LE_16BITS(p);
136                 p += 2;
137                 caplen -= 2;
138                 hdrlen += 2;
139                 if (caplen < 8) {
140                         ND_PRINT((ndo, "[|802.15.4]"));
141                         return hdrlen;
142                 }
143                 if (ndo->ndo_vflag)
144                         ND_PRINT((ndo,"%04x:%s ", panid, le64addr_string(ndo, p)));
145                 p += 8;
146                 caplen -= 8;
147                 hdrlen += 8;
148                 break;
149         }
150         if (ndo->ndo_vflag)
151                 ND_PRINT((ndo,"< "));
152
153         /*
154          * Source address and PAN ID, if present.
155          */
156         switch (FC_SRC_ADDRESSING_MODE(fc)) {
157         case FC_ADDRESSING_MODE_NONE:
158                 if (ndo->ndo_vflag)
159                         ND_PRINT((ndo,"none "));
160                 break;
161         case FC_ADDRESSING_MODE_RESERVED:
162                 if (ndo->ndo_vflag)
163                         ND_PRINT((ndo,"reserved source addressing mode"));
164                 return 0;
165         case FC_ADDRESSING_MODE_SHORT:
166                 if (!(fc & FC_PAN_ID_COMPRESSION)) {
167                         /*
168                          * The source PAN ID is not compressed out, so
169                          * fetch it.  (Otherwise, we'll use the destination
170                          * PAN ID, fetched above.)
171                          */
172                         if (caplen < 2) {
173                                 ND_PRINT((ndo, "[|802.15.4]"));
174                                 return hdrlen;
175                         }
176                         panid = EXTRACT_LE_16BITS(p);
177                         p += 2;
178                         caplen -= 2;
179                         hdrlen += 2;
180                 }
181                 if (caplen < 2) {
182                         ND_PRINT((ndo, "[|802.15.4]"));
183                         return hdrlen;
184                 }
185                 if (ndo->ndo_vflag)
186                         ND_PRINT((ndo,"%04x:%04x ", panid, EXTRACT_LE_16BITS(p)));
187                 p += 2;
188                 caplen -= 2;
189                 hdrlen += 2;
190                 break;
191         case FC_ADDRESSING_MODE_LONG:
192                 if (!(fc & FC_PAN_ID_COMPRESSION)) {
193                         /*
194                          * The source PAN ID is not compressed out, so
195                          * fetch it.  (Otherwise, we'll use the destination
196                          * PAN ID, fetched above.)
197                          */
198                         if (caplen < 2) {
199                                 ND_PRINT((ndo, "[|802.15.4]"));
200                                 return hdrlen;
201                         }
202                         panid = EXTRACT_LE_16BITS(p);
203                         p += 2;
204                         caplen -= 2;
205                         hdrlen += 2;
206                 }
207                 if (caplen < 8) {
208                         ND_PRINT((ndo, "[|802.15.4]"));
209                         return hdrlen;
210                 }
211                 if (ndo->ndo_vflag)
212                         ND_PRINT((ndo,"%04x:%s ", panid, le64addr_string(ndo, p)));
213                 p += 8;
214                 caplen -= 8;
215                 hdrlen += 8;
216                 break;
217         }
218
219         if (!ndo->ndo_suppress_default_print)
220                 ND_DEFAULTPRINT(p, caplen);
221
222         return hdrlen;
223 }