]> The Tcpdump Group git mirrors - tcpdump/blob - print-802_15_4.c
IEEE 802.15.4: Refactor with two functions
[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 static u_int
65 ieee802_15_4_print(netdissect_options *ndo,
66 const u_char *p, u_int caplen)
67 {
68 u_int hdrlen;
69 uint16_t fc;
70 uint8_t seq;
71 uint16_t panid = 0;
72
73 if (caplen < 3) {
74 ND_PRINT("[|802.15.4]");
75 return caplen;
76 }
77 hdrlen = 3;
78
79 fc = EXTRACT_LE_U_2(p);
80 seq = EXTRACT_U_1(p + 2);
81
82 p += 3;
83 caplen -= 3;
84
85 ND_PRINT("IEEE 802.15.4 %s packet ", ftypes[FC_FRAME_TYPE(fc)]);
86 if (ndo->ndo_vflag)
87 ND_PRINT("seq %02x ", seq);
88
89 /*
90 * Destination address and PAN ID, if present.
91 */
92 switch (FC_DEST_ADDRESSING_MODE(fc)) {
93 case FC_ADDRESSING_MODE_NONE:
94 if (fc & FC_PAN_ID_COMPRESSION) {
95 /*
96 * PAN ID compression; this requires that both
97 * the source and destination addresses be present,
98 * but the destination address is missing.
99 */
100 ND_PRINT("[|802.15.4]");
101 return hdrlen;
102 }
103 if (ndo->ndo_vflag)
104 ND_PRINT("none ");
105 break;
106 case FC_ADDRESSING_MODE_RESERVED:
107 if (ndo->ndo_vflag)
108 ND_PRINT("reserved destination addressing mode");
109 return hdrlen;
110 case FC_ADDRESSING_MODE_SHORT:
111 if (caplen < 2) {
112 ND_PRINT("[|802.15.4]");
113 return hdrlen;
114 }
115 panid = EXTRACT_LE_U_2(p);
116 p += 2;
117 caplen -= 2;
118 hdrlen += 2;
119 if (caplen < 2) {
120 ND_PRINT("[|802.15.4]");
121 return hdrlen;
122 }
123 if (ndo->ndo_vflag)
124 ND_PRINT("%04x:%04x ", panid, EXTRACT_LE_U_2(p));
125 p += 2;
126 caplen -= 2;
127 hdrlen += 2;
128 break;
129 case FC_ADDRESSING_MODE_LONG:
130 if (caplen < 2) {
131 ND_PRINT("[|802.15.4]");
132 return hdrlen;
133 }
134 panid = EXTRACT_LE_U_2(p);
135 p += 2;
136 caplen -= 2;
137 hdrlen += 2;
138 if (caplen < 8) {
139 ND_PRINT("[|802.15.4]");
140 return hdrlen;
141 }
142 if (ndo->ndo_vflag)
143 ND_PRINT("%04x:%s ", panid, le64addr_string(ndo, p));
144 p += 8;
145 caplen -= 8;
146 hdrlen += 8;
147 break;
148 }
149 if (ndo->ndo_vflag)
150 ND_PRINT("< ");
151
152 /*
153 * Source address and PAN ID, if present.
154 */
155 switch (FC_SRC_ADDRESSING_MODE(fc)) {
156 case FC_ADDRESSING_MODE_NONE:
157 if (ndo->ndo_vflag)
158 ND_PRINT("none ");
159 break;
160 case FC_ADDRESSING_MODE_RESERVED:
161 if (ndo->ndo_vflag)
162 ND_PRINT("reserved source addressing mode");
163 return 0;
164 case FC_ADDRESSING_MODE_SHORT:
165 if (!(fc & FC_PAN_ID_COMPRESSION)) {
166 /*
167 * The source PAN ID is not compressed out, so
168 * fetch it. (Otherwise, we'll use the destination
169 * PAN ID, fetched above.)
170 */
171 if (caplen < 2) {
172 ND_PRINT("[|802.15.4]");
173 return hdrlen;
174 }
175 panid = EXTRACT_LE_U_2(p);
176 p += 2;
177 caplen -= 2;
178 hdrlen += 2;
179 }
180 if (caplen < 2) {
181 ND_PRINT("[|802.15.4]");
182 return hdrlen;
183 }
184 if (ndo->ndo_vflag)
185 ND_PRINT("%04x:%04x ", panid, EXTRACT_LE_U_2(p));
186 p += 2;
187 caplen -= 2;
188 hdrlen += 2;
189 break;
190 case FC_ADDRESSING_MODE_LONG:
191 if (!(fc & FC_PAN_ID_COMPRESSION)) {
192 /*
193 * The source PAN ID is not compressed out, so
194 * fetch it. (Otherwise, we'll use the destination
195 * PAN ID, fetched above.)
196 */
197 if (caplen < 2) {
198 ND_PRINT("[|802.15.4]");
199 return hdrlen;
200 }
201 panid = EXTRACT_LE_U_2(p);
202 p += 2;
203 caplen -= 2;
204 hdrlen += 2;
205 }
206 if (caplen < 8) {
207 ND_PRINT("[|802.15.4]");
208 return hdrlen;
209 }
210 if (ndo->ndo_vflag)
211 ND_PRINT("%04x:%s ", panid, le64addr_string(ndo, p));
212 p += 8;
213 caplen -= 8;
214 hdrlen += 8;
215 break;
216 }
217
218 if (!ndo->ndo_suppress_default_print)
219 ND_DEFAULTPRINT(p, caplen);
220
221 return hdrlen;
222 }
223
224 /* For DLT_IEEE802_15_4 and DLT_IEEE802_15_4_NOFCS */
225 u_int
226 ieee802_15_4_if_print(netdissect_options *ndo,
227 const struct pcap_pkthdr *h, const u_char *p)
228 {
229 return ieee802_15_4_print(ndo, p, h->caplen);
230 }