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
ieee802_15_4_if_print(netdissect_options * ndo,const struct pcap_pkthdr * h,const u_char * p)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 }
224