"Fossies" - the Fresh Open Source Software Archive 
Member "tcpflow-1.6.1/src/wifipcap/wifipcap.cpp" (19 Feb 2021, 55775 Bytes) of package /linux/misc/tcpflow-1.6.1.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "wifipcap.cpp" see the
Fossies "Dox" file reference documentation and the latest
Fossies "Diffs" side-by-side code changes report:
1.5.0_vs_1.6.1.
1 /**********************************************************************
2 * Log:
3 * 2006-03-12: Parts originally authored by Doug Madory as wifi_parser.c
4 * 2013-03-15: Substantially modified by Simson Garfinkel for inclusion into tcpflow
5 * 2013-11-18: reworked static calls to be entirely calls to a class. Changed TimeVal pointer to an instance variable that includes the full packet header.
6 **********************************************************************/
7
8 //*do 11-18
9
10 #include "config.h" // pull in HAVE_ defines
11
12 #define __STDC_FORMAT_MACROS
13
14 #include <stdint.h>
15 #include <inttypes.h>
16
17 #include <iostream>
18 #include <cstdlib>
19 #include <cstdio>
20 #include <cstring>
21 #include <stdarg.h>
22 #include <errno.h>
23
24 #ifdef HAVE_NET_ETHERNET_H
25 #ifdef HAVE_SYS_PARAM_H
26 #include <sys/param.h>
27 #endif
28 #include <net/ethernet.h>
29 #endif
30
31 #ifdef HAVE_ARPA_INET_H
32 #include <arpa/inet.h>
33 #endif
34
35 #ifdef HAVE_UNISTD_H
36 #include <unistd.h>
37 #endif
38
39 #pragma GCC diagnostic ignored "-Wcast-align"
40
41 #include "wifipcap.h"
42
43 #include "cpack.h"
44 #include "extract.h"
45 #include "oui.h"
46 #include "ethertype.h"
47 #include "icmp.h"
48 #include "ipproto.h"
49
50 /* wifipcap uses a MAC class which is somewhat lame, but works */
51
52 MAC MAC::broadcast(0xffffffffffffULL);
53 MAC MAC::null((uint64_t)0);
54 int WifiPacket::debug=0;
55 int MAC::print_fmt(MAC::PRINT_FMT_COLON);
56
57 std::ostream& operator<<(std::ostream& out, const MAC& mac) {
58 const char *fmt = MAC::print_fmt == MAC::PRINT_FMT_COLON ?
59 "%02x:%02x:%02x:%02x:%02x:%02x" :
60 "%02x%02x%02x%02x%02x%02x";
61 char buf[24];
62 sprintf(buf, fmt,
63 (int)((mac.val>>40)&0xff),
64 (int)((mac.val>>32)&0xff),
65 (int)((mac.val>>24)&0xff),
66 (int)((mac.val>>16)&0xff),
67 (int)((mac.val>>8)&0xff),
68 (int)((mac.val)&0xff)
69 );
70 out << buf;
71 return out;
72 }
73
74 std::ostream& operator<<(std::ostream& out, const struct in_addr& ip) {
75 out << inet_ntoa(ip);
76 return out;
77 }
78
79 struct tok {
80 int v; /* value */
81 const char *s; /* string */
82 };
83
84 #if 0
85 static const struct tok ethertype_values[] = {
86 { ETHERTYPE_IP, "IPv4" },
87 { ETHERTYPE_MPLS, "MPLS unicast" },
88 { ETHERTYPE_MPLS_MULTI, "MPLS multicast" },
89 { ETHERTYPE_IPV6, "IPv6" },
90 { ETHERTYPE_8021Q, "802.1Q" },
91 { ETHERTYPE_VMAN, "VMAN" },
92 { ETHERTYPE_PUP, "PUP" },
93 { ETHERTYPE_ARP, "ARP"},
94 { ETHERTYPE_REVARP, "Reverse ARP"},
95 { ETHERTYPE_NS, "NS" },
96 { ETHERTYPE_SPRITE, "Sprite" },
97 { ETHERTYPE_TRAIL, "Trail" },
98 { ETHERTYPE_MOPDL, "MOP DL" },
99 { ETHERTYPE_MOPRC, "MOP RC" },
100 { ETHERTYPE_DN, "DN" },
101 { ETHERTYPE_LAT, "LAT" },
102 { ETHERTYPE_SCA, "SCA" },
103 { ETHERTYPE_LANBRIDGE, "Lanbridge" },
104 { ETHERTYPE_DECDNS, "DEC DNS" },
105 { ETHERTYPE_DECDTS, "DEC DTS" },
106 { ETHERTYPE_VEXP, "VEXP" },
107 { ETHERTYPE_VPROD, "VPROD" },
108 { ETHERTYPE_ATALK, "Appletalk" },
109 { ETHERTYPE_AARP, "Appletalk ARP" },
110 { ETHERTYPE_IPX, "IPX" },
111 { ETHERTYPE_PPP, "PPP" },
112 { ETHERTYPE_SLOW, "Slow Protocols" },
113 { ETHERTYPE_PPPOED, "PPPoE D" },
114 { ETHERTYPE_PPPOES, "PPPoE S" },
115 { ETHERTYPE_EAPOL, "EAPOL" },
116 { ETHERTYPE_JUMBO, "Jumbo" },
117 { ETHERTYPE_LOOPBACK, "Loopback" },
118 { ETHERTYPE_ISO, "OSI" },
119 { ETHERTYPE_GRE_ISO, "GRE-OSI" },
120 { 0, NULL}
121 };
122 #endif
123
124 /*max length of an IEEE 802.11 packet*/
125 #ifndef MAX_LEN_80211
126 #define MAX_LEN_80211 3000
127 #endif
128
129 /* from ethereal packet-prism.c */
130 #define pletohs(p) ((u_int16_t) \
131 ((u_int16_t)*((const u_int8_t *)(p)+1)<<8| \
132 (u_int16_t)*((const u_int8_t *)(p)+0)<<0))
133 #define pntohl(p) ((u_int32_t)*((const u_int8_t *)(p)+0)<<24| \
134 (u_int32_t)*((const u_int8_t *)(p)+1)<<16| \
135 (u_int32_t)*((const u_int8_t *)(p)+2)<<8| \
136 (u_int32_t)*((const u_int8_t *)(p)+3)<<0)
137 #define COOK_FRAGMENT_NUMBER(x) ((x) & 0x000F)
138 #define COOK_SEQUENCE_NUMBER(x) (((x) & 0xFFF0) >> 4)
139 /* end ethereal code */
140
141 /* Sequence number gap */
142 #define SEQ_GAP(current, last)(0xfff & (current - last))
143
144 /* In the following three arrays, even though the QoS subtypes are listed, in the rest of the program
145 * the QoS subtypes are treated as "OTHER_TYPES". The file "ieee802_11.h" currently doesn't account for
146 * the existence of QoS subtypes. The QoS subtypes might need to be accomodated there in the future.
147 */
148 #if 0
149 static const char * mgmt_subtype_text[] = {
150 "AssocReq",
151 "AssocResp",
152 "ReAssocReq",
153 "ReAssocResp",
154 "ProbeReq",
155 "ProbeResp",
156 "",
157 "",
158 "Beacon",
159 "ATIM",
160 "Disassoc",
161 "Auth",
162 "DeAuth",
163 "Action", /*QoS mgmt_subtype*/
164 "",
165 ""
166 };
167
168 static const char * ctrl_subtype_text[] = {
169 "", "", "", "", "", "", "", "",
170 "BlockAckReq", /*QoS ctrl_subtype*/
171 "BlockAck", /*QoS ctrl_subtype*/
172 "PS-Poll",
173 "RTS",
174 "CTS",
175 "ACK",
176 "CF-End",
177 "CF-End+CF-Ack"
178 };
179
180 static const char * data_subtype_text[] = {
181 "Data",
182 "Data+CF-Ack",
183 "Data+CF-Poll",
184 "Data+CF-Ack+CF-Poll",
185 "Null(no_data)",
186 "CF-Ack(no_data)",
187 "CF-Poll(no_data)",
188 "CF-Ack+CF-Poll(no_data)",
189 "QoS_Data", /*QoS data_subtypes from here on*/
190 "QoS_Data+CF-Ack",
191 "QoS_Data+CF-Poll",
192 "QoS_Data+CF-Ack+CF-Poll",
193 "QoS_Null(no_data)",
194 "",
195 "QoS_CF-Poll(no_data)",
196 "QoS_CF-Ack+CF-Poll(no_data)"
197 };
198 #endif
199
200 ///////////////////////////////////////////////////////////////////////////////
201 // crc32 implementation needed for wifi checksum
202
203 /* crc32.c
204 * CRC-32 routine
205 *
206 * $Id: crc32.cpp,v 1.1 2007/02/14 00:05:50 jpang Exp $
207 *
208 * Ethereal - Network traffic analyzer
209 * By Gerald Combs <gerald@ethereal.com>
210 * Copyright 1998 Gerald Combs
211 *
212 * Copied from README.developer
213 *
214 * This program is free software; you can redistribute it and/or
215 * modify it under the terms of the GNU General Public License
216 * as published by the Free Software Foundation; either version 2
217 * of the License, or (at your option) any later version.
218 *
219 * This program is distributed in the hope that it will be useful,
220 * but WITHOUT ANY WARRANTY; without even the implied warranty of
221 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
222 * GNU General Public License for more details.
223 *
224 * You should have received a copy of the GNU General Public License
225 * along with this program; if not, write to the Free Software
226 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
227 *
228 * Credits:
229 *
230 * Table from Solomon Peachy
231 * Routine from Chris Waters
232 */
233
234 /*
235 * Table for the AUTODIN/HDLC/802.x CRC.
236 *
237 * Polynomial is
238 *
239 * x^32 + x^26 + x^23 + x^22 + x^16 + x^12 + x^11 + x^8 + x^7 +
240 * x^5 + x^4 + x^2 + x + 1
241 */
242 static const uint32_t crc32_ccitt_table[256] = {
243 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419,
244 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4,
245 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07,
246 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
247 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856,
248 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
249 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4,
250 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
251 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3,
252 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a,
253 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599,
254 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
255 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190,
256 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f,
257 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e,
258 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
259 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed,
260 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
261 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3,
262 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
263 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a,
264 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5,
265 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010,
266 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
267 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17,
268 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6,
269 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615,
270 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
271 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344,
272 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
273 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a,
274 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
275 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1,
276 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c,
277 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef,
278 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
279 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe,
280 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31,
281 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c,
282 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
283 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b,
284 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
285 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1,
286 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
287 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278,
288 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7,
289 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66,
290 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
291 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605,
292 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8,
293 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b,
294 0x2d02ef8d
295 };
296
297 #define CRC32_CCITT_SEED 0xFFFFFFFF
298
299 static uint32_t crc32_ccitt_seed(const uint8_t *buf, size_t len, uint32_t seed);
300
301 static uint32_t crc32_ccitt(const uint8_t *buf, size_t len)
302 {
303 return ( crc32_ccitt_seed(buf, len, CRC32_CCITT_SEED) );
304 }
305
306 static uint32_t crc32_ccitt_seed(const uint8_t *buf, size_t len, uint32_t seed)
307 {
308 uint32_t crc32 = seed;
309
310 for (unsigned int i = 0; i < len; i++){
311 crc32 = crc32_ccitt_table[(crc32 ^ buf[i]) & 0xff] ^ (crc32 >> 8);
312 }
313
314 return ( ~crc32 );
315 }
316
317 /*
318 * IEEE 802.x version (Ethernet and 802.11, at least) - byte-swap
319 * the result of "crc32()".
320 *
321 * XXX - does this mean we should fetch the Ethernet and 802.11
322 * Frame Checksum (FCS) with "tvb_get_letohl()" rather than "tvb_get_ntohl()",
323 * or is fetching it big-endian and byte-swapping the CRC done
324 * to cope with 802.x sending stuff out in reverse bit order?
325 */
326 static uint32_t crc32_802(const unsigned char *buf, size_t len)
327 {
328 uint32_t c_crc;
329
330 c_crc = crc32_ccitt(buf, len);
331
332 /* Byte reverse. */
333 c_crc = ((unsigned char)(c_crc>>0)<<24) |
334 ((unsigned char)(c_crc>>8)<<16) |
335 ((unsigned char)(c_crc>>16)<<8) |
336 ((unsigned char)(c_crc>>24)<<0);
337
338 return ( c_crc );
339 }
340 ///////////////////////////////////////////////////////////////////////////////
341
342 ///////////////////////////////////////////////////////////////////////////////
343
344 /* Translate Ethernet address, as seen in struct ether_header, to type MAC. */
345 /* Extract header length. */
346 static size_t extract_header_length(u_int16_t fc)
347 {
348 switch (FC_TYPE(fc)) {
349 case T_MGMT:
350 return MGMT_HDRLEN;
351 case T_CTRL:
352 switch (FC_SUBTYPE(fc)) {
353 case CTRL_PS_POLL:
354 return CTRL_PS_POLL_HDRLEN;
355 case CTRL_RTS:
356 return CTRL_RTS_HDRLEN;
357 case CTRL_CTS:
358 return CTRL_CTS_HDRLEN;
359 case CTRL_ACK:
360 return CTRL_ACK_HDRLEN;
361 case CTRL_CF_END:
362 return CTRL_END_HDRLEN;
363 case CTRL_END_ACK:
364 return CTRL_END_ACK_HDRLEN;
365 default:
366 return 0;
367 }
368 case T_DATA:
369 return (FC_TO_DS(fc) && FC_FROM_DS(fc)) ? 30 : 24;
370 default:
371 return 0;
372 }
373 }
374
375 ///////////////////////////////////////////////////////////////////////////////
376
377 ///////////////////////////////////////////////////////////////////////////////
378
379 #pragma GCC diagnostic ignored "-Wcast-align"
380 void WifiPacket::handle_llc(const mac_hdr_t &mac,const u_char *ptr, size_t len,u_int16_t fc)
381 {
382 if (len < 7) {
383 // truncated header!
384 cbs->HandleLLC(*this,NULL, ptr, len);
385 return;
386 }
387
388 // http://www.wildpackets.com/resources/compendium/wireless_lan/wlan_packets
389
390 llc_hdr_t hdr;
391 hdr.dsap = EXTRACT_LE_8BITS(ptr); // Destination Service Access point
392 hdr.ssap = EXTRACT_LE_8BITS(ptr + 1); // Source Service Access Point
393 hdr.control= EXTRACT_LE_8BITS(ptr + 2); // ignored by most protocols
394 hdr.oui = EXTRACT_24BITS(ptr + 3);
395 hdr.type = EXTRACT_16BITS(ptr + 6);
396
397
398 /* "When both the DSAP and SSAP are set to 0xAA, the type is
399 * interpreted as a protocol not defined by IEEE and the LSAP is
400 * referred to as SubNetwork Access Protocol (SNAP). In SNAP, the
401 * 5 bytes that follow the DSAP, SSAP, and control byte are called
402 * the Protocol Discriminator."
403 */
404
405 if(hdr.dsap==0xAA && hdr.ssap==0xAA){
406 cbs->HandleLLC(*this,&hdr,ptr+8,len-8);
407 return;
408 }
409
410 if (hdr.oui == OUI_ENCAP_ETHER || hdr.oui == OUI_CISCO_90) {
411 cbs->HandleLLC(*this,&hdr, ptr+8, len-8);
412 return;
413 }
414
415 cbs->HandleLLCUnknown(*this,ptr, len);
416 }
417
418 void WifiPacket::handle_wep(const u_char *ptr, size_t len)
419 {
420 // Jeff: XXX handle TKIP/CCMP ? how can we demultiplex different
421 // protection protocols?
422
423 struct wep_hdr_t hdr;
424 u_int32_t iv;
425
426 if (len < IEEE802_11_IV_LEN + IEEE802_11_KID_LEN) {
427 // truncated!
428 cbs->HandleWEP(*this,NULL, ptr, len);
429 return;
430 }
431 iv = EXTRACT_LE_32BITS(ptr);
432 hdr.iv = IV_IV(iv);
433 hdr.pad = IV_PAD(iv);
434 hdr.keyid = IV_KEYID(iv);
435 cbs->HandleWEP(*this,&hdr, ptr, len);
436 }
437
438 ///////////////////////////////////////////////////////////////////////////////
439
440 static const char *auth_alg_text[]={"Open System","Shared Key","EAP"};
441 #define NUM_AUTH_ALGS (sizeof auth_alg_text / sizeof auth_alg_text[0])
442
443 static const char *status_text[] = {
444 "Succesful", /* 0 */
445 "Unspecified failure", /* 1 */
446 "Reserved", /* 2 */
447 "Reserved", /* 3 */
448 "Reserved", /* 4 */
449 "Reserved", /* 5 */
450 "Reserved", /* 6 */
451 "Reserved", /* 7 */
452 "Reserved", /* 8 */
453 "Reserved", /* 9 */
454 "Cannot Support all requested capabilities in the Capability Information field", /* 10 */
455 "Reassociation denied due to inability to confirm that association exists", /* 11 */
456 "Association denied due to reason outside the scope of the standard", /* 12 */
457 "Responding station does not support the specified authentication algorithm ", /* 13 */
458 "Received an Authentication frame with authentication transaction " \
459 "sequence number out of expected sequence", /* 14 */
460 "Authentication rejected because of challenge failure", /* 15 */
461 "Authentication rejected due to timeout waiting for next frame in sequence", /* 16 */
462 "Association denied because AP is unable to handle additional associated stations", /* 17 */
463 "Association denied due to requesting station not supporting all of the " \
464 "data rates in BSSBasicRateSet parameter", /* 18 */
465 };
466 #define NUM_STATUSES (sizeof status_text / sizeof status_text[0])
467
468 static const char *reason_text[] = {
469 "Reserved", /* 0 */
470 "Unspecified reason", /* 1 */
471 "Previous authentication no longer valid", /* 2 */
472 "Deauthenticated because sending station is leaving (or has left) IBSS or ESS", /* 3 */
473 "Disassociated due to inactivity", /* 4 */
474 "Disassociated because AP is unable to handle all currently associated stations", /* 5 */
475 "Class 2 frame received from nonauthenticated station", /* 6 */
476 "Class 3 frame received from nonassociated station", /* 7 */
477 "Disassociated because sending station is leaving (or has left) BSS", /* 8 */
478 "Station requesting (re)association is not authenticated with responding station", /* 9 */
479 };
480 #define NUM_REASONS (sizeof reason_text / sizeof reason_text[0])
481
482 const char *Wifipcap::WifiUtil::MgmtAuthAlg2Txt(uint v) {
483 return v < NUM_AUTH_ALGS ? auth_alg_text[v] : "Unknown";
484 }
485 const char *Wifipcap::WifiUtil::MgmtStatusCode2Txt(uint v) {
486 return v < NUM_STATUSES ? status_text[v] : "Reserved";
487 }
488 const char *Wifipcap::WifiUtil::MgmtReasonCode2Txt(uint v) {
489 return v < NUM_REASONS ? reason_text[v] : "Reserved";
490 }
491
492 ///////////////////////////////////////////////////////////////////////////////
493
494 // Jeff: HACK -- tcpdump uses a global variable to check truncation
495 #define TTEST2(_p, _l) ((const u_char *)&(_p) - p + (_l) <= (ssize_t)len)
496
497 void WifiPacket::parse_elements(struct mgmt_body_t *pbody, const u_char *p, int offset, size_t len)
498 {
499 /*
500 * We haven't seen any elements yet.
501 */
502 pbody->challenge_status = NOT_PRESENT;
503 pbody->ssid_status = NOT_PRESENT;
504 pbody->rates_status = NOT_PRESENT;
505 pbody->ds_status = NOT_PRESENT;
506 pbody->cf_status = NOT_PRESENT;
507 pbody->tim_status = NOT_PRESENT;
508
509 for (;;) {
510 if (!TTEST2(*(p + offset), 1))
511 return;
512 switch (*(p + offset)) {
513 case E_SSID:
514 /* Present, possibly truncated */
515 pbody->ssid_status = TRUNCATED;
516 if (!TTEST2(*(p + offset), 2))
517 return;
518 memcpy(&pbody->ssid, p + offset, 2);
519 offset += 2;
520 if (pbody->ssid.length != 0) {
521 if (pbody->ssid.length >
522 sizeof(pbody->ssid.ssid) - 1)
523 return;
524 if (!TTEST2(*(p + offset), pbody->ssid.length))
525 return;
526 memcpy(&pbody->ssid.ssid, p + offset,
527 pbody->ssid.length);
528 offset += pbody->ssid.length;
529 }
530 pbody->ssid.ssid[pbody->ssid.length] = '\0';
531 /* Present and not truncated */
532 pbody->ssid_status = PRESENT;
533 break;
534 case E_CHALLENGE:
535 /* Present, possibly truncated */
536 pbody->challenge_status = TRUNCATED;
537 if (!TTEST2(*(p + offset), 2))
538 return;
539 memcpy(&pbody->challenge, p + offset, 2);
540 offset += 2;
541 if (pbody->challenge.length != 0) {
542 if (pbody->challenge.length >
543 sizeof(pbody->challenge.text) - 1)
544 return;
545 if (!TTEST2(*(p + offset), pbody->challenge.length))
546 return;
547 memcpy(&pbody->challenge.text, p + offset,
548 pbody->challenge.length);
549 offset += pbody->challenge.length;
550 }
551 pbody->challenge.text[pbody->challenge.length] = '\0';
552 /* Present and not truncated */
553 pbody->challenge_status = PRESENT;
554 break;
555 case E_RATES:
556 /* Present, possibly truncated */
557 pbody->rates_status = TRUNCATED;
558 if (!TTEST2(*(p + offset), 2))
559 return;
560 memcpy(&(pbody->rates), p + offset, 2);
561 offset += 2;
562 if (pbody->rates.length != 0) {
563 if (pbody->rates.length > sizeof pbody->rates.rate)
564 return;
565 if (!TTEST2(*(p + offset), pbody->rates.length))
566 return;
567 memcpy(&pbody->rates.rate, p + offset,
568 pbody->rates.length);
569 offset += pbody->rates.length;
570 }
571 /* Present and not truncated */
572 pbody->rates_status = PRESENT;
573 break;
574 case E_DS:
575 /* Present, possibly truncated */
576 pbody->ds_status = TRUNCATED;
577 if (!TTEST2(*(p + offset), 3))
578 return;
579 memcpy(&pbody->ds, p + offset, 3);
580 offset += 3;
581 /* Present and not truncated */
582 pbody->ds_status = PRESENT;
583 break;
584 case E_CF:
585 /* Present, possibly truncated */
586 pbody->cf_status = TRUNCATED;
587 if (!TTEST2(*(p + offset), 8))
588 return;
589 memcpy(&pbody->cf, p + offset, 8);
590 offset += 8;
591 /* Present and not truncated */
592 pbody->cf_status = PRESENT;
593 break;
594 case E_TIM:
595 /* Present, possibly truncated */
596 pbody->tim_status = TRUNCATED;
597 if (!TTEST2(*(p + offset), 2))
598 return;
599 memcpy(&pbody->tim, p + offset, 2);
600 offset += 2;
601 if (!TTEST2(*(p + offset), 3))
602 return;
603 memcpy(&pbody->tim.count, p + offset, 3);
604 offset += 3;
605
606 if (pbody->tim.length <= 3)
607 break;
608 if (pbody->rates.length > sizeof pbody->tim.bitmap)
609 return;
610 if (!TTEST2(*(p + offset), pbody->tim.length - 3))
611 return;
612 memcpy(pbody->tim.bitmap, p + (pbody->tim.length - 3),
613 (pbody->tim.length - 3));
614 offset += pbody->tim.length - 3;
615 /* Present and not truncated */
616 pbody->tim_status = PRESENT;
617 break;
618 default:
619 #ifdef DEBUG_WIFI
620 printf("(1) unhandled element_id (%d) ", *(p + offset) );
621 #endif
622 if (!TTEST2(*(p + offset), 2))
623 return;
624 if (!TTEST2(*(p + offset + 2), *(p + offset + 1)))
625 return;
626 offset += *(p + offset + 1) + 2;
627 break;
628 }
629 }
630 }
631
632 /*********************************************************************************
633 * Print Handle functions for the management frame types
634 *********************************************************************************/
635
636 int
637 WifiPacket::handle_beacon( const struct mgmt_header_t *pmh, const u_char *p, size_t len)
638 {
639 struct mgmt_body_t pbody;
640 int offset = 0;
641
642 memset(&pbody, 0, sizeof(pbody));
643
644 if (!TTEST2(*p, IEEE802_11_TSTAMP_LEN + IEEE802_11_BCNINT_LEN +
645 IEEE802_11_CAPINFO_LEN))
646 return 0;
647 memcpy(&pbody.timestamp, p, IEEE802_11_TSTAMP_LEN);
648 offset += IEEE802_11_TSTAMP_LEN;
649 pbody.beacon_interval = EXTRACT_LE_16BITS(p+offset);
650 offset += IEEE802_11_BCNINT_LEN;
651 pbody.capability_info = EXTRACT_LE_16BITS(p+offset);
652 offset += IEEE802_11_CAPINFO_LEN;
653
654 parse_elements(&pbody, p, offset, len);
655
656 /*
657 PRINT_SSID(pbody);
658 PRINT_RATES(pbody);
659 printf(" %s",
660 CAPABILITY_ESS(pbody.capability_info) ? "ESS" : "IBSS");
661 PRINT_DS_CHANNEL(pbody);
662 */
663 cbs->Handle80211MgmtBeacon(*this, pmh, &pbody);
664 return 1;
665 }
666
667 int WifiPacket::handle_assoc_request( const struct mgmt_header_t *pmh, const u_char *p, size_t len)
668 {
669 struct mgmt_body_t pbody;
670 int offset = 0;
671
672 memset(&pbody, 0, sizeof(pbody));
673
674 if (!TTEST2(*p, IEEE802_11_CAPINFO_LEN + IEEE802_11_LISTENINT_LEN))
675 return 0;
676 pbody.capability_info = EXTRACT_LE_16BITS(p);
677 offset += IEEE802_11_CAPINFO_LEN;
678 pbody.listen_interval = EXTRACT_LE_16BITS(p+offset);
679 offset += IEEE802_11_LISTENINT_LEN;
680
681 parse_elements(&pbody, p, offset, len);
682
683 /*
684 PRINT_SSID(pbody);
685 PRINT_RATES(pbody);
686 */
687 cbs->Handle80211MgmtAssocRequest(*this, pmh, &pbody);
688
689 return 1;
690 }
691
692 int WifiPacket::handle_assoc_response( const struct mgmt_header_t *pmh, const u_char *p, size_t len, bool reassoc)
693 {
694 struct mgmt_body_t pbody;
695 int offset = 0;
696
697 memset(&pbody, 0, sizeof(pbody));
698
699 if (!TTEST2(*p, IEEE802_11_CAPINFO_LEN + IEEE802_11_STATUS_LEN +
700 IEEE802_11_AID_LEN))
701 return 0;
702 pbody.capability_info = EXTRACT_LE_16BITS(p);
703 offset += IEEE802_11_CAPINFO_LEN;
704 pbody.status_code = EXTRACT_LE_16BITS(p+offset);
705 offset += IEEE802_11_STATUS_LEN;
706 pbody.aid = EXTRACT_LE_16BITS(p+offset);
707 offset += IEEE802_11_AID_LEN;
708
709 parse_elements(&pbody, p, offset, len);
710
711 /*
712 printf(" AID(%x) :%s: %s", ((u_int16_t)(pbody.aid << 2 )) >> 2 ,
713 CAPABILITY_PRIVACY(pbody.capability_info) ? " PRIVACY " : "",
714 (pbody.status_code < NUM_STATUSES
715 ? status_text[pbody.status_code]
716 : "n/a"));
717 */
718 if (!reassoc)
719 cbs->Handle80211MgmtAssocResponse(*this, pmh, &pbody);
720 else
721 cbs->Handle80211MgmtReassocResponse(*this, pmh, &pbody);
722
723 return 1;
724 }
725
726 int
727 WifiPacket::handle_reassoc_request( const struct mgmt_header_t *pmh, const u_char *p, size_t len)
728 {
729 struct mgmt_body_t pbody;
730 int offset = 0;
731
732 memset(&pbody, 0, sizeof(pbody));
733
734 if (!TTEST2(*p, IEEE802_11_CAPINFO_LEN + IEEE802_11_LISTENINT_LEN +
735 IEEE802_11_AP_LEN))
736 return 0;
737 pbody.capability_info = EXTRACT_LE_16BITS(p);
738 offset += IEEE802_11_CAPINFO_LEN;
739 pbody.listen_interval = EXTRACT_LE_16BITS(p+offset);
740 offset += IEEE802_11_LISTENINT_LEN;
741 memcpy(&pbody.ap, p+offset, IEEE802_11_AP_LEN);
742 offset += IEEE802_11_AP_LEN;
743
744 parse_elements(&pbody, p, offset, len);
745
746 /*
747 PRINT_SSID(pbody);
748 printf(" AP : %s", etheraddr_string( pbody.ap ));
749 */
750 cbs->Handle80211MgmtReassocRequest(*this, pmh, &pbody);
751
752 return 1;
753 }
754
755 int
756 WifiPacket::handle_reassoc_response( const struct mgmt_header_t *pmh, const u_char *p, size_t len)
757 {
758 /* Same as a Association Reponse */
759 return handle_assoc_response(pmh, p, len, true);
760 }
761
762 int
763 WifiPacket::handle_probe_request( const struct mgmt_header_t *pmh, const u_char *p, size_t len)
764 {
765 struct mgmt_body_t pbody;
766 int offset = 0;
767
768 memset(&pbody, 0, sizeof(pbody));
769
770 parse_elements(&pbody, p, offset, len);
771
772 /*
773 PRINT_SSID(pbody);
774 PRINT_RATES(pbody);
775 */
776 cbs->Handle80211MgmtProbeRequest(*this, pmh, &pbody);
777
778 return 1;
779 }
780
781 int
782 WifiPacket::handle_probe_response( const struct mgmt_header_t *pmh, const u_char *p, size_t len)
783 {
784 struct mgmt_body_t pbody;
785 int offset = 0;
786
787 memset(&pbody, 0, sizeof(pbody));
788
789 if (!TTEST2(*p, IEEE802_11_TSTAMP_LEN + IEEE802_11_BCNINT_LEN +
790 IEEE802_11_CAPINFO_LEN))
791 return 0;
792
793 memcpy(&pbody.timestamp, p, IEEE802_11_TSTAMP_LEN);
794 offset += IEEE802_11_TSTAMP_LEN;
795 pbody.beacon_interval = EXTRACT_LE_16BITS(p+offset);
796 offset += IEEE802_11_BCNINT_LEN;
797 pbody.capability_info = EXTRACT_LE_16BITS(p+offset);
798 offset += IEEE802_11_CAPINFO_LEN;
799
800 parse_elements(&pbody, p, offset, len);
801
802 /*
803 PRINT_SSID(pbody);
804 PRINT_RATES(pbody);
805 PRINT_DS_CHANNEL(pbody);
806 */
807 cbs->Handle80211MgmtProbeResponse(*this, pmh, &pbody);
808
809 return 1;
810 }
811
812 int
813 WifiPacket::handle_atim( const struct mgmt_header_t *pmh, const u_char *p, size_t len)
814 {
815 /* the frame body for ATIM is null. */
816
817 cbs->Handle80211MgmtATIM(*this, pmh);
818
819 return 1;
820 }
821
822 int
823 WifiPacket::handle_disassoc( const struct mgmt_header_t *pmh, const u_char *p, size_t len)
824 {
825 struct mgmt_body_t pbody;
826
827 memset(&pbody, 0, sizeof(pbody));
828
829 if (!TTEST2(*p, IEEE802_11_REASON_LEN))
830 return 0;
831 pbody.reason_code = EXTRACT_LE_16BITS(p);
832
833 /*
834 printf(": %s",
835 (pbody.reason_code < NUM_REASONS)
836 ? reason_text[pbody.reason_code]
837 : "Reserved" );
838 */
839 cbs->Handle80211MgmtDisassoc(*this, pmh, &pbody);
840
841 return 1;
842 }
843
844 int
845 WifiPacket::handle_auth( const struct mgmt_header_t *pmh, const u_char *p, size_t len)
846 {
847 struct mgmt_body_t pbody;
848 int offset = 0;
849
850 memset(&pbody, 0, sizeof(pbody));
851
852 if (!TTEST2(*p, 6))
853 return 0;
854 pbody.auth_alg = EXTRACT_LE_16BITS(p);
855 offset += 2;
856 pbody.auth_trans_seq_num = EXTRACT_LE_16BITS(p + offset);
857 offset += 2;
858 pbody.status_code = EXTRACT_LE_16BITS(p + offset);
859 offset += 2;
860
861 parse_elements(&pbody, p, offset, len);
862
863 /*
864 if ((pbody.auth_alg == 1) &&
865 ((pbody.auth_trans_seq_num == 2) ||
866 (pbody.auth_trans_seq_num == 3))) {
867 printf(" (%s)-%x [Challenge Text] %s",
868 (pbody.auth_alg < NUM_AUTH_ALGS)
869 ? auth_alg_text[pbody.auth_alg]
870 : "Reserved",
871 pbody.auth_trans_seq_num,
872 ((pbody.auth_trans_seq_num % 2)
873 ? ((pbody.status_code < NUM_STATUSES)
874 ? status_text[pbody.status_code]
875 : "n/a") : ""));
876 return 1;
877 }
878 printf(" (%s)-%x: %s",
879 (pbody.auth_alg < NUM_AUTH_ALGS)
880 ? auth_alg_text[pbody.auth_alg]
881 : "Reserved",
882 pbody.auth_trans_seq_num,
883 (pbody.auth_trans_seq_num % 2)
884 ? ((pbody.status_code < NUM_STATUSES)
885 ? status_text[pbody.status_code]
886 : "n/a")
887 : "");
888 */
889 cbs->Handle80211MgmtAuth(*this, pmh, &pbody);
890
891 return 1;
892 }
893
894 int
895 WifiPacket::handle_deauth( const struct mgmt_header_t *pmh, const u_char *p, size_t len)
896 {
897 struct mgmt_body_t pbody;
898 int offset = 0;
899 //const char *reason = NULL;
900
901 memset(&pbody, 0, sizeof(pbody));
902
903 if (!TTEST2(*p, IEEE802_11_REASON_LEN))
904 return 0;
905 pbody.reason_code = EXTRACT_LE_16BITS(p);
906 offset += IEEE802_11_REASON_LEN;
907
908 /*
909 reason = (pbody.reason_code < NUM_REASONS)
910 ? reason_text[pbody.reason_code]
911 : "Reserved";
912
913 if (eflag) {
914 printf(": %s", reason);
915 } else {
916 printf(" (%s): %s", etheraddr_string(pmh->sa), reason);
917 }
918 */
919 cbs->Handle80211MgmtDeauth(*this, pmh, &pbody);
920
921 return 1;
922 }
923
924
925 /*********************************************************************************
926 * Print Body funcs
927 *********************************************************************************/
928
929
930 /** Decode a management request.
931 * @return 0 - failure, non-zero success
932 *
933 * NOTE — this function and all that it calls should be handled as methods in WifipcapCallbacks
934 */
935
936 int
937 WifiPacket::decode_mgmt_body(u_int16_t fc, struct mgmt_header_t *pmh, const u_char *p, size_t len)
938 {
939 if(debug) std::cerr << "decode_mgmt_body FC_SUBTYPE(fc)="<<(int)FC_SUBTYPE(fc)<<" ";
940 switch (FC_SUBTYPE(fc)) {
941 case ST_ASSOC_REQUEST:
942 return handle_assoc_request(pmh, p, len);
943 case ST_ASSOC_RESPONSE:
944 return handle_assoc_response(pmh, p, len);
945 case ST_REASSOC_REQUEST:
946 return handle_reassoc_request(pmh, p, len);
947 case ST_REASSOC_RESPONSE:
948 return handle_reassoc_response(pmh, p, len);
949 case ST_PROBE_REQUEST:
950 return handle_probe_request(pmh, p, len);
951 case ST_PROBE_RESPONSE:
952 return handle_probe_response(pmh, p, len);
953 case ST_BEACON:
954 return handle_beacon(pmh, p, len);
955 case ST_ATIM:
956 return handle_atim(pmh, p, len);
957 case ST_DISASSOC:
958 return handle_disassoc(pmh, p, len);
959 case ST_AUTH:
960 if (len < 3) {
961 return 0;
962 }
963 if ((p[0] == 0 ) && (p[1] == 0) && (p[2] == 0)) {
964 //printf("Authentication (Shared-Key)-3 ");
965 cbs->Handle80211MgmtAuthSharedKey(*this, pmh, p, len);
966 return 0;
967 }
968 return handle_auth(pmh, p, len);
969 case ST_DEAUTH:
970 return handle_deauth(pmh, p, len);
971 break;
972 default:
973 return 0;
974 }
975 }
976
977 int WifiPacket::decode_mgmt_frame(const u_char * ptr, size_t len, u_int16_t fc, u_int8_t hdrlen)
978 {
979 mgmt_header_t hdr;
980 u_int16_t seq_ctl;
981
982 hdr.da = MAC::ether2MAC(ptr + 4);
983 hdr.sa = MAC::ether2MAC(ptr + 10);
984 hdr.bssid = MAC::ether2MAC(ptr + 16);
985
986 hdr.duration = EXTRACT_LE_16BITS(ptr+2);
987
988 seq_ctl = pletohs(ptr + 22);
989
990 hdr.seq = COOK_SEQUENCE_NUMBER(seq_ctl);
991 hdr.frag = COOK_FRAGMENT_NUMBER(seq_ctl);
992
993 cbs->Handle80211(*this, fc, hdr.sa, hdr.da, MAC::null, MAC::null, ptr, len);
994
995 int ret = decode_mgmt_body(fc, &hdr, ptr+MGMT_HDRLEN, len-MGMT_HDRLEN);
996
997 if (ret==0) {
998 cbs->Handle80211Unknown(*this, fc, ptr, len);
999 return 0;
1000 }
1001
1002 return 0;
1003 }
1004
1005 int WifiPacket::decode_data_frame(const u_char * ptr, size_t len, u_int16_t fc)
1006 {
1007 mac_hdr_t hdr;
1008 hdr.fc = fc;
1009 hdr.duration = EXTRACT_LE_16BITS(ptr+2);
1010 hdr.seq_ctl = pletohs(ptr + 22);
1011 hdr.seq = COOK_SEQUENCE_NUMBER(hdr.seq_ctl);
1012 hdr.frag = COOK_FRAGMENT_NUMBER(hdr.seq_ctl);
1013
1014 if(FC_TYPE(fc)==2 && FC_SUBTYPE(fc)==8){ // quality of service?
1015 hdr.qos = 1;
1016 }
1017
1018 size_t hdrlen=0;
1019
1020 const MAC address1 = MAC::ether2MAC(ptr+4);
1021 const MAC address2 = MAC::ether2MAC(ptr+10);
1022 const MAC address3 = MAC::ether2MAC(ptr+16);
1023
1024 /* call the 80211 callback data callback */
1025
1026 if (FC_TO_DS(fc)==0 && FC_FROM_DS(fc)==0) { /* ad hoc IBSS */
1027 hdr.da = address1;
1028 hdr.sa = address2;
1029 hdr.bssid = address3;
1030 hdrlen = DATA_HDRLEN;
1031 if(hdr.qos) hdrlen+=2;
1032 cbs->Handle80211( *this, fc, hdr.sa, hdr.da, hdr.ra, hdr.ta, ptr, len);
1033 cbs->Handle80211DataIBSS( *this, hdr, ptr+hdrlen, len-hdrlen);
1034 } else if (FC_TO_DS(fc)==0 && FC_FROM_DS(fc)) { /* from AP to STA */
1035 hdr.da = address1;
1036 hdr.bssid = address2;
1037 hdr.sa = address3;
1038 hdrlen = DATA_HDRLEN;
1039 if(hdr.qos) hdrlen+=2;
1040 cbs->Handle80211( *this, fc, hdr.sa, hdr.da, hdr.ra, hdr.ta, ptr, len);
1041 cbs->Handle80211DataFromAP( *this, hdr, ptr+hdrlen, len-hdrlen);
1042 } else if (FC_TO_DS(fc) && FC_FROM_DS(fc)==0) { /* frame from STA to AP */
1043 hdr.bssid = address1;
1044 hdr.sa = address2;
1045 hdr.da = address3;
1046 hdrlen = DATA_HDRLEN;
1047 if(hdr.qos) hdrlen+=2;
1048 cbs->Handle80211( *this, fc, hdr.sa, hdr.da, hdr.ra, hdr.ta, ptr, len);
1049 cbs->Handle80211DataToAP( *this, hdr, ptr+hdrlen, len-hdrlen);
1050 } else if (FC_TO_DS(fc) && FC_FROM_DS(fc)) { /* WDS */
1051 const MAC address4 = MAC::ether2MAC(ptr+18);
1052 hdr.ra = address1;
1053 hdr.ta = address2;
1054 hdr.da = address3;
1055 hdr.sa = address4;
1056 hdrlen = DATA_WDS_HDRLEN;
1057 if(hdr.qos) hdrlen+=2;
1058 cbs->Handle80211( *this, fc, hdr.sa, hdr.da, hdr.ra, hdr.ta, ptr, len);
1059 cbs->Handle80211DataWDS( *this, hdr, ptr+hdrlen, len-hdrlen);
1060 }
1061
1062 /* Handle either the WEP or the link layer. This handles the data itself */
1063 if (FC_WEP(fc)) {
1064 handle_wep(ptr+hdrlen, len-hdrlen-4 );
1065 } else {
1066 handle_llc(hdr, ptr+hdrlen, len-hdrlen-4, fc);
1067 }
1068 return 0;
1069 }
1070
1071 int WifiPacket::decode_ctrl_frame(const u_char * ptr, size_t len, u_int16_t fc)
1072 {
1073 u_int16_t du = EXTRACT_LE_16BITS(ptr+2); //duration
1074
1075 switch (FC_SUBTYPE(fc)) {
1076 case CTRL_PS_POLL: {
1077 ctrl_ps_poll_t hdr;
1078 hdr.fc = fc;
1079 hdr.aid = du;
1080 hdr.bssid = MAC::ether2MAC(ptr+4);
1081 hdr.ta = MAC::ether2MAC(ptr+10);
1082 cbs->Handle80211( *this, fc, MAC::null, MAC::null, MAC::null, hdr.ta, ptr, len);
1083 cbs->Handle80211CtrlPSPoll( *this, &hdr);
1084 break;
1085 }
1086 case CTRL_RTS: {
1087 ctrl_rts_t hdr;
1088 hdr.fc = fc;
1089 hdr.duration = du;
1090 hdr.ra = MAC::ether2MAC(ptr+4);
1091 hdr.ta = MAC::ether2MAC(ptr+10);
1092 cbs->Handle80211( *this, fc, MAC::null, MAC::null, hdr.ra, hdr.ta, ptr, len);
1093 cbs->Handle80211CtrlRTS( *this, &hdr);
1094 break;
1095 }
1096 case CTRL_CTS: {
1097 ctrl_cts_t hdr;
1098 hdr.fc = fc;
1099 hdr.duration = du;
1100 hdr.ra = MAC::ether2MAC(ptr+4);
1101 cbs->Handle80211( *this, fc, MAC::null, MAC::null, hdr.ra, MAC::null, ptr, len);
1102 cbs->Handle80211CtrlCTS( *this, &hdr);
1103 break;
1104 }
1105 case CTRL_ACK: {
1106 ctrl_ack_t hdr;
1107 hdr.fc = fc;
1108 hdr.duration = du;
1109 hdr.ra = MAC::ether2MAC(ptr+4);
1110 cbs->Handle80211( *this, fc, MAC::null, MAC::null, hdr.ra, MAC::null, ptr, len);
1111 cbs->Handle80211CtrlAck( *this, &hdr);
1112 break;
1113 }
1114 case CTRL_CF_END: {
1115 ctrl_end_t hdr;
1116 hdr.fc = fc;
1117 hdr.duration = du;
1118 hdr.ra = MAC::ether2MAC(ptr+4);
1119 hdr.bssid = MAC::ether2MAC(ptr+10);
1120 cbs->Handle80211( *this, fc, MAC::null, MAC::null, hdr.ra, MAC::null, ptr, len);
1121 cbs->Handle80211CtrlCFEnd( *this, &hdr);
1122 break;
1123 }
1124 case CTRL_END_ACK: {
1125 ctrl_end_ack_t hdr;
1126 hdr.fc = fc;
1127 hdr.duration = du;
1128 hdr.ra = MAC::ether2MAC(ptr+4);
1129 hdr.bssid = MAC::ether2MAC(ptr+10);
1130 cbs->Handle80211( *this, fc, MAC::null, MAC::null, hdr.ra, MAC::null, ptr, len);
1131 cbs->Handle80211CtrlEndAck( *this, &hdr);
1132 break;
1133 }
1134 default: {
1135 cbs->Handle80211( *this, fc, MAC::null, MAC::null, MAC::null, MAC::null, ptr, len);
1136 cbs->Handle80211Unknown( *this, fc, ptr, len);
1137 return -1;
1138 //add the case statements for QoS control frames once ieee802_11.h is updated
1139 }
1140 }
1141 return 0;
1142 }
1143
1144 #ifndef roundup2
1145 #define roundup2(x, y) (((x)+((y)-1))&(~((y)-1))) /* if y is powers of two */
1146 #endif
1147
1148 void WifiPacket::handle_80211(const u_char * pkt, size_t len /* , int pad */)
1149 {
1150 if (debug) std::cerr << "handle_80211(len= " << len << " ";
1151 if (len < 2) {
1152 cbs->Handle80211( *this, 0, MAC::null, MAC::null, MAC::null, MAC::null, pkt, len);
1153 cbs->Handle80211Unknown( *this, -1, pkt, len);
1154 return;
1155 }
1156
1157 u_int16_t fc = EXTRACT_LE_16BITS(pkt); //frame control
1158 size_t hdrlen = extract_header_length(fc);
1159 /*
1160 if (pad) {
1161 hdrlen = roundup2(hdrlen, 4);
1162 }
1163 */
1164
1165 if (debug) std::cerr << "FC_TYPE(fc)= " << FC_TYPE(fc) << " ";
1166
1167 if (len < IEEE802_11_FC_LEN || len < hdrlen) {
1168 cbs->Handle80211Unknown( *this, fc, pkt, len);
1169 return;
1170 }
1171
1172 /* Always calculate the frame checksum, but only process the packets if the FCS or if we are ignoring it */
1173 if (len >= hdrlen + 4) {
1174 // assume fcs is last 4 bytes (?)
1175 u_int32_t fcs_sent = EXTRACT_32BITS(pkt+len-4);
1176 u_int32_t fcs = crc32_802(pkt, len-4);
1177
1178 /*
1179 if (fcs != fcs_sent) {
1180 cerr << "bad fcs: ";
1181 fprintf (stderr, "%08x != %08x\n", fcs_sent, fcs);
1182 }
1183 */
1184
1185 fcs_ok = (fcs == fcs_sent);
1186 }
1187 if (cbs->Check80211FCS(*this) && fcs_ok==false){
1188 cbs->Handle80211Unknown(*this,fc,pkt,len);
1189 return;
1190 }
1191
1192
1193 // fill in current_frame: type, sn
1194 switch (FC_TYPE(fc)) {
1195 case T_MGMT:
1196 if(decode_mgmt_frame(pkt, len, fc, hdrlen)<0)
1197 return;
1198 break;
1199 case T_DATA:
1200 if(decode_data_frame(pkt, len, fc)<0)
1201 return;
1202 break;
1203 case T_CTRL:
1204 if(decode_ctrl_frame(pkt, len, fc)<0)
1205 return;
1206 break;
1207 default:
1208 cbs->Handle80211( *this, fc, MAC::null, MAC::null, MAC::null, MAC::null, pkt, len);
1209 cbs->Handle80211Unknown( *this, fc, pkt, len);
1210 return;
1211 }
1212 }
1213
1214 int WifiPacket::print_radiotap_field(struct cpack_state *s, u_int32_t bit, int *pad, radiotap_hdr *hdr)
1215 {
1216 union {
1217 int8_t i8;
1218 u_int8_t u8;
1219 int16_t i16;
1220 u_int16_t u16;
1221 u_int32_t u32;
1222 u_int64_t u64;
1223 } u, u2, u3;
1224 int rc;
1225
1226 switch (bit) {
1227 case IEEE80211_RADIOTAP_FLAGS:
1228 rc = cpack_uint8(s, &u.u8);
1229 if (u.u8 & IEEE80211_RADIOTAP_F_DATAPAD)
1230 *pad = 1;
1231 break;
1232 case IEEE80211_RADIOTAP_RATE:
1233 case IEEE80211_RADIOTAP_DB_ANTSIGNAL:
1234 case IEEE80211_RADIOTAP_DB_ANTNOISE:
1235 case IEEE80211_RADIOTAP_ANTENNA:
1236 rc = cpack_uint8(s, &u.u8);
1237 break;
1238 case IEEE80211_RADIOTAP_DBM_ANTSIGNAL:
1239 case IEEE80211_RADIOTAP_DBM_ANTNOISE:
1240 rc = cpack_int8(s, &u.i8);
1241 break;
1242 case IEEE80211_RADIOTAP_CHANNEL:
1243 rc = cpack_uint16(s, &u.u16);
1244 if (rc != 0)
1245 break;
1246 rc = cpack_uint16(s, &u2.u16);
1247 break;
1248 case IEEE80211_RADIOTAP_FHSS:
1249 case IEEE80211_RADIOTAP_LOCK_QUALITY:
1250 case IEEE80211_RADIOTAP_TX_ATTENUATION:
1251 rc = cpack_uint16(s, &u.u16);
1252 break;
1253 case IEEE80211_RADIOTAP_DB_TX_ATTENUATION:
1254 rc = cpack_uint8(s, &u.u8);
1255 break;
1256 case IEEE80211_RADIOTAP_DBM_TX_POWER:
1257 rc = cpack_int8(s, &u.i8);
1258 break;
1259 case IEEE80211_RADIOTAP_TSFT:
1260 rc = cpack_uint64(s, &u.u64);
1261 break;
1262 case IEEE80211_RADIOTAP_RX_FLAGS:
1263 rc = cpack_uint16(s, &u.u16);
1264 break;
1265 case IEEE80211_RADIOTAP_TX_FLAGS:
1266 rc = cpack_uint16(s, &u.u16);
1267 break;
1268 case IEEE80211_RADIOTAP_RTS_RETRIES:
1269 rc = cpack_uint8(s, &u.u8);
1270 break;
1271 case IEEE80211_RADIOTAP_DATA_RETRIES:
1272 rc = cpack_uint8(s, &u.u8);
1273 break;
1274 // simson add follows:
1275 case IEEE80211_RADIOTAP_XCHANNEL:
1276 rc = cpack_uint8(s, &u.u8); // simson guess
1277 break;
1278 case IEEE80211_RADIOTAP_MCS:
1279 rc = cpack_uint8(s, &u.u8) || cpack_uint8(s, &u2.u8) || cpack_uint8(s, &u3.u8); // simson guess
1280 break;
1281 // simson end
1282 default:
1283 /* this bit indicates a field whose
1284 * size we do not know, so we cannot
1285 * proceed.
1286 */
1287 //printf("[0x%08x] ", bit);
1288 fprintf(stderr, "wifipcap: unknown radiotap bit: %d (%d)\n", bit,IEEE80211_RADIOTAP_XCHANNEL);
1289 return -1 ;
1290 }
1291
1292 if (rc != 0) {
1293 //printf("[|802.11]");
1294 fprintf(stderr, "wifipcap: truncated radiotap header for bit: %d\n", bit);
1295 return rc ;
1296 }
1297
1298 switch (bit) {
1299 case IEEE80211_RADIOTAP_CHANNEL:
1300 //printf("%u MHz ", u.u16);
1301 if (u2.u16 != 0)
1302 //printf("(0x%04x) ", u2.u16);
1303 hdr->has_channel = true;
1304 hdr->channel = u2.u16;
1305 break;
1306 case IEEE80211_RADIOTAP_FHSS:
1307 //printf("fhset %d fhpat %d ", u.u16 & 0xff, (u.u16 >> 8) & 0xff);
1308 hdr->has_fhss = true;
1309 hdr->fhss_fhset = u.u16 & 0xff;
1310 hdr->fhss_fhpat = (u.u16 >> 8) & 0xff;
1311 break;
1312 case IEEE80211_RADIOTAP_RATE:
1313 //PRINT_RATE("", u.u8, " Mb/s ");
1314 hdr->has_rate = true;
1315 hdr->rate = u.u8;
1316 break;
1317 case IEEE80211_RADIOTAP_DBM_ANTSIGNAL:
1318 //printf("%ddB signal ", u.i8);
1319 hdr->has_signal_dbm = true;
1320 hdr->signal_dbm = u.i8;
1321 break;
1322 case IEEE80211_RADIOTAP_DBM_ANTNOISE:
1323 //printf("%ddB noise ", u.i8);
1324 hdr->has_noise_dbm = true;
1325 hdr->noise_dbm = u.i8;
1326 break;
1327 case IEEE80211_RADIOTAP_DB_ANTSIGNAL:
1328 //printf("%ddB signal ", u.u8);
1329 hdr->has_signal_db = true;
1330 hdr->signal_db = u.u8;
1331 break;
1332 case IEEE80211_RADIOTAP_DB_ANTNOISE:
1333 //printf("%ddB noise ", u.u8);
1334 hdr->has_noise_db = true;
1335 hdr->noise_db = u.u8;
1336 break;
1337 case IEEE80211_RADIOTAP_LOCK_QUALITY:
1338 //printf("%u sq ", u.u16);
1339 hdr->has_quality = true;
1340 hdr->quality = u.u16;
1341 break;
1342 case IEEE80211_RADIOTAP_TX_ATTENUATION:
1343 //printf("%d tx power ", -(int)u.u16);
1344 hdr->has_txattenuation = true;
1345 hdr->txattenuation = -(int)u.u16;
1346 break;
1347 case IEEE80211_RADIOTAP_DB_TX_ATTENUATION:
1348 //printf("%ddB tx power ", -(int)u.u8);
1349 hdr->has_txattenuation_db = true;
1350 hdr->txattenuation_db = -(int)u.u8;
1351 break;
1352 case IEEE80211_RADIOTAP_DBM_TX_POWER:
1353 //printf("%ddBm tx power ", u.i8);
1354 hdr->has_txpower_dbm = true;
1355 hdr->txpower_dbm = u.i8;
1356 break;
1357 case IEEE80211_RADIOTAP_FLAGS:
1358 hdr->has_flags = true;
1359 if (u.u8 & IEEE80211_RADIOTAP_F_CFP)
1360 //printf("cfp ");
1361 hdr->flags_cfp = true;
1362 if (u.u8 & IEEE80211_RADIOTAP_F_SHORTPRE)
1363 //printf("short preamble ");
1364 hdr->flags_short_preamble = true;
1365 if (u.u8 & IEEE80211_RADIOTAP_F_WEP)
1366 //printf("wep ");
1367 hdr->flags_wep = true;
1368 if (u.u8 & IEEE80211_RADIOTAP_F_FRAG)
1369 //printf("fragmented ");
1370 hdr->flags_fragmented = true;
1371 if (u.u8 & IEEE80211_RADIOTAP_F_BADFCS)
1372 //printf("bad-fcs ");
1373 hdr->flags_badfcs = true;
1374 break;
1375 case IEEE80211_RADIOTAP_ANTENNA:
1376 //printf("antenna %d ", u.u8);
1377 hdr->has_antenna = true;
1378 hdr->antenna = u.u8;
1379 break;
1380 case IEEE80211_RADIOTAP_TSFT:
1381 //printf("%" PRIu64 "us tsft ", u.u64);
1382 hdr->has_tsft = true;
1383 hdr->tsft = u.u64;
1384 break;
1385 case IEEE80211_RADIOTAP_RX_FLAGS:
1386 hdr->has_rxflags = true;
1387 hdr->rxflags = u.u16;
1388 break;
1389 case IEEE80211_RADIOTAP_TX_FLAGS:
1390 hdr->has_txflags = true;
1391 hdr->txflags = u.u16;
1392 break;
1393 case IEEE80211_RADIOTAP_RTS_RETRIES:
1394 hdr->has_rts_retries = true;
1395 hdr->rts_retries = u.u8;
1396 break;
1397 case IEEE80211_RADIOTAP_DATA_RETRIES:
1398 hdr->has_data_retries = true;
1399 hdr->data_retries = u.u8;
1400 break;
1401 }
1402 return 0 ;
1403 }
1404
1405
1406
1407 void WifiPacket::handle_radiotap(const u_char *p,size_t caplen)
1408 {
1409 #define BITNO_32(x) (((x) >> 16) ? 16 + BITNO_16((x) >> 16) : BITNO_16((x)))
1410 #define BITNO_16(x) (((x) >> 8) ? 8 + BITNO_8((x) >> 8) : BITNO_8((x)))
1411 #define BITNO_8(x) (((x) >> 4) ? 4 + BITNO_4((x) >> 4) : BITNO_4((x)))
1412 #define BITNO_4(x) (((x) >> 2) ? 2 + BITNO_2((x) >> 2) : BITNO_2((x)))
1413 #define BITNO_2(x) (((x) & 2) ? 1 : 0)
1414 #define BIT(n) (1 << n)
1415 #define IS_EXTENDED(__p) (EXTRACT_LE_32BITS(__p) & BIT(IEEE80211_RADIOTAP_EXT)) != 0
1416
1417 // If caplen is too small, just give it a try and carry on.
1418 if (caplen < sizeof(struct ieee80211_radiotap_header)) {
1419 cbs->HandleRadiotap( *this, NULL, p, caplen);
1420 return;
1421 }
1422
1423 struct ieee80211_radiotap_header *hdr = (struct ieee80211_radiotap_header *)p;
1424
1425 size_t len = EXTRACT_LE_16BITS(&hdr->it_len); // length of radiotap header
1426
1427 if (caplen < len) {
1428 //printf("[|802.11]");
1429 cbs->HandleRadiotap( *this, NULL, p, caplen);
1430 return;// caplen;
1431 }
1432 uint32_t *last_presentp=0;
1433 for (last_presentp = &hdr->it_present;
1434 IS_EXTENDED(last_presentp) && (u_char*)(last_presentp + 1) <= p + len;
1435 last_presentp++){
1436 }
1437
1438 /* are there more bitmap extensions than bytes in header? */
1439 if (IS_EXTENDED(last_presentp)) {
1440 //printf("[|802.11]");
1441 cbs->HandleRadiotap( *this, NULL, p, caplen);
1442 return;// caplen;
1443 }
1444
1445 const u_char *iter = (u_char*)(last_presentp + 1);
1446 struct cpack_state cpacker;
1447
1448
1449 /* Handle malformed data */
1450 if ((ssize_t)(len - (iter - p)) <= 0) {
1451 cbs->HandleRadiotap( *this, NULL, p, caplen);
1452 return;// caplen;
1453 }
1454
1455 if (cpack_init(&cpacker, (u_int8_t*)iter, len - (iter - p)) != 0) {
1456 /* XXX */
1457 //printf("[|802.11]");
1458 cbs->HandleRadiotap( *this, NULL, p, caplen);
1459 return;// caplen;
1460 }
1461
1462 radiotap_hdr ohdr;
1463 memset(&ohdr, 0, sizeof(ohdr));
1464
1465 /* Assume no Atheros padding between 802.11 header and body */
1466 int pad = 0;
1467 uint32_t *presentp;
1468 int bit0=0;
1469 for (bit0 = 0, presentp = &hdr->it_present; presentp <= last_presentp;
1470 presentp++, bit0 += 32) {
1471
1472 u_int32_t present, next_present;
1473 for (present = EXTRACT_LE_32BITS(presentp); present;
1474 present = next_present) {
1475 /* clear the least significant bit that is set */
1476 next_present = present & (present - 1);
1477
1478 /* extract the least significant bit that is set */
1479 enum ieee80211_radiotap_type bit = (enum ieee80211_radiotap_type)
1480 (bit0 + BITNO_32(present ^ next_present));
1481
1482 /* print the next radiotap field */
1483 int r = print_radiotap_field(&cpacker, bit, &pad, &ohdr);
1484
1485 /* If we got an error, break both loops */
1486 if(r!=0) goto done;
1487 }
1488 }
1489 done:;
1490 cbs->HandleRadiotap( *this, &ohdr, p, caplen);
1491 //return len + ieee802_11_print(p + len, length - len, caplen - len, pad);
1492 #undef BITNO_32
1493 #undef BITNO_16
1494 #undef BITNO_8
1495 #undef BITNO_4
1496 #undef BITNO_2
1497 #undef BIT
1498 handle_80211(p+len, caplen-len);
1499 }
1500
1501 void WifiPacket::handle_prism(const u_char *pc, size_t len)
1502 {
1503 prism2_pkthdr hdr;
1504
1505 /* get the fields */
1506 if (len>=144){
1507 hdr.host_time = EXTRACT_LE_32BITS(pc+32);
1508 hdr.mac_time = EXTRACT_LE_32BITS(pc+44);
1509 hdr.channel = EXTRACT_LE_32BITS(pc+56);
1510 hdr.rssi = EXTRACT_LE_32BITS(pc+68);
1511 hdr.sq = EXTRACT_LE_32BITS(pc+80);
1512 hdr.signal = EXTRACT_LE_32BITS(pc+92);
1513 hdr.noise = EXTRACT_LE_32BITS(pc+104);
1514 hdr.rate = EXTRACT_LE_32BITS(pc+116)/2;
1515 hdr.istx = EXTRACT_LE_32BITS(pc+128);
1516 cbs->HandlePrism( *this, &hdr, pc + 144, len - 144);
1517 handle_80211(pc+144,len-144);
1518 }
1519 }
1520
1521 ///////////////////////////////////////////////////////////////////////////////
1522 ///
1523 /// handle_*:
1524 /// handle each of the packet types
1525 ///
1526
1527 /// 2018-08-02: slg - I'm not sure why this is commented out.
1528 void WifiPacket::handle_ether(const u_char *ptr, size_t len)
1529 {
1530 #if 0
1531 ether_hdr_t hdr;
1532
1533 hdr.da = MAC::ether2MAC(ptr);
1534 hdr.sa = MAC::ether2MAC(ptr+6);
1535 hdr.type = EXTRACT_16BITS(ptr + 12);
1536
1537 ptr += 14;
1538 len -= 14;
1539
1540 cbs->HandleEthernet(*this, &hdr, ptr, len);
1541
1542 switch (hdr.type) {
1543 case ETHERTYPE_IP:
1544 handle_ip(ptr, len);
1545 return;
1546 case ETHERTYPE_IPV6:
1547 handle_ip6(ptr, len);
1548 return;
1549 case ETHERTYPE_ARP:
1550 handle_arp( ptr, len);
1551 return;
1552 default:
1553 cbs->HandleL2Unknown(*this, hdr.type, ptr, len);
1554 return;
1555 }
1556 #endif
1557 }
1558
1559 ///////////////////////////////////////////////////////////////////////////////
1560 /* These are all static functions */
1561 #if 0
1562 void Wifipcap::dl_prism(const PcapUserData &data, const struct pcap_pkthdr *header, const u_char * packet)
1563 {
1564 WifipcapCallbacks *cbs = data.cbs;
1565
1566 if(header->caplen < 144) return; // prism header
1567
1568 cbs->PacketBegin( packet, header->caplen, header->len);
1569 handle_prism(cbs,packet+144,header->caplen-144);
1570 cbs->PacketEnd();
1571 }
1572
1573 void Wifipcap::dl_prism(u_char *user, const struct pcap_pkthdr *header, const u_char * packet)
1574 {
1575 PcapUserData *data = reinterpret_cast<PcapUserData *>(user);
1576 Wifipcap::dl_prism(*data,header,packet);
1577 }
1578 #endif
1579
1580 #if 0
1581 void Wifipcap::dl_ieee802_11_radio(const PcapUserData &data, const struct pcap_pkthdr *header,
1582 const u_char * packet)
1583 {
1584
1585 data.cbs->PacketBegin( packet, header->caplen, header->len);
1586 handle_radiotap(packet, header->caplen);
1587 data.cbs->PacketEnd();
1588 }
1589 #endif
1590
1591 void Wifipcap::dl_ieee802_11_radio(const u_char *user, const struct pcap_pkthdr *header, const u_char * packet)
1592 {
1593 const PcapUserData *data = reinterpret_cast<const PcapUserData *>(user);
1594 WifiPacket pkt(data->cbs,data->header_type,header,packet);
1595
1596 data->cbs->PacketBegin(pkt,packet,header->caplen,header->len);
1597 pkt.handle_radiotap(packet,header->caplen);
1598 data->cbs->PacketEnd(pkt);
1599
1600 //Wifipcap::dl_ieee802_11_radio(*data,header,packet);
1601 }
1602
1603 ///////////////////////////////////////////////////////////////////////////////
1604
1605 /* None of these are used in tcpflow */
1606
1607 bool Wifipcap::InitNext()
1608 {
1609 if (morefiles.size() < 1){
1610 return false;
1611 }
1612 if (descr) {
1613 pcap_close(descr);
1614 }
1615 Init(morefiles.front(), false);
1616 morefiles.pop_front();
1617 return true;
1618 }
1619
1620 void Wifipcap::Init(const char *name, bool live) {
1621 if (verbose){
1622 std::cerr << "wifipcap: initializing '" << name << "'" << std::endl;
1623 }
1624
1625 if (!live) {
1626 #ifdef _WIN32
1627 std::cerr << "Trace replay is unsupported in windows." << std::endl;
1628 exit(1);
1629 #else
1630 // mini hack: handle gziped files since all our traces are in
1631 // this format
1632 int slen = strlen(name);
1633
1634 bool gzip = !strcmp(name+slen-3, ".gz");
1635 bool bzip = !strcmp(name+slen-4, ".bz2");
1636
1637 char cmd[256];
1638 char errbuf[256];
1639 if (gzip)
1640 sprintf(cmd, "zcat %s", name);
1641 else if (bzip)
1642 sprintf(cmd, "bzcat %s", name);
1643 else
1644 // using cat here instead of pcap_open or fopen is intentional
1645 // neither of these may be able to handle large files (>2GB files)
1646 // but cat uses the linux routines to allow it to
1647 sprintf(cmd, "cat %s", name);
1648
1649 FILE *pipe = popen(cmd, "r");
1650 if (pipe == NULL) {
1651 printf("popen(): %s\n", strerror(errno));
1652 exit(1);
1653 }
1654 descr = pcap_fopen_offline(pipe, errbuf);
1655
1656 if(descr == NULL) {
1657 printf("pcap_open_offline(): %s\n", errbuf);
1658 exit(1);
1659 }
1660 #endif
1661 } else {
1662 char errbuf[256];
1663 descr = pcap_open_live(name,BUFSIZ,1,-1,errbuf);
1664 if(descr == NULL) {
1665 printf("pcap_open_live(): %s\n", errbuf);
1666 exit(1);
1667 }
1668 }
1669
1670 datalink = pcap_datalink(descr);
1671 if (datalink != DLT_PRISM_HEADER && datalink != DLT_IEEE802_11_RADIO && datalink != DLT_IEEE802_11) {
1672 if (datalink == DLT_EN10MB) {
1673 printf("warning: ethernet datalink type: %s\n",
1674 pcap_datalink_val_to_name(datalink));
1675 } else {
1676 printf("warning: unrecognized datalink type: %s\n",
1677 pcap_datalink_val_to_name(datalink));
1678 }
1679 }
1680 }
1681
1682
1683
1684
1685 /* object-oriented version of pcap callback. Called with the callbacks object,
1686 * the DLT type, the header and the packet.
1687 * This is the main packet processor.
1688 * It records some stats and then dispatches to the appropriate callback.
1689 */
1690 void Wifipcap::handle_packet(WifipcapCallbacks *cbs,int header_type,
1691 const struct pcap_pkthdr *header, const u_char * packet)
1692 {
1693 /* Record start time if we don't have it */
1694 if (startTime == TIME_NONE) {
1695 startTime = header->ts;
1696 lastPrintTime = header->ts;
1697 }
1698 /* Print stats if necessary */
1699 if (header->ts.tv_sec > lastPrintTime.tv_sec + Wifipcap::PRINT_TIME_INTERVAL) {
1700 if (verbose) {
1701 int hours = (header->ts.tv_sec - startTime.tv_sec)/3600;
1702 int days = hours/24;
1703 int left = hours%24;
1704 fprintf(stderr, "wifipcap: %2d days %2d hours, %10" PRId64 " pkts\n",
1705 days, left, packetsProcessed);
1706 }
1707 lastPrintTime = header->ts;
1708 }
1709 packetsProcessed++;
1710
1711 /* Create the packet object and call the appropriate callbacks */
1712 WifiPacket pkt(cbs,header_type,header,packet);
1713
1714 /* Notify callback */
1715 cbs->PacketBegin(pkt, packet, header->caplen, header->len);
1716 //int frameLen = header->caplen;
1717 switch(header_type) {
1718 case DLT_PRISM_HEADER:
1719 pkt.handle_prism(packet,header->caplen);
1720 break;
1721 case DLT_IEEE802_11_RADIO:
1722 pkt.handle_radiotap(packet,header->caplen);
1723 break;
1724 case DLT_IEEE802_11:
1725 pkt.handle_80211(packet,header->caplen);
1726 break;
1727 case DLT_EN10MB:
1728 pkt.handle_ether(packet,header->caplen);
1729 break;
1730 default:
1731 #if 0
1732 /// 2018-08-02: slg - I'm also not sure why this is commented out.
1733 // try handling it as default IP assuming framing is ethernet
1734 // (this is for testing)
1735 pkt.handle_ip(packet,header->caplen);
1736 #endif
1737 break;
1738 }
1739 cbs->PacketEnd(pkt);
1740 }
1741
1742
1743 /* The raw callback from pcap; jump back into the object-oriented domain */
1744 /* note: u_char *user may not be const according to spec */
1745 void Wifipcap::handle_packet_callback(u_char *user, const struct pcap_pkthdr *header, const u_char * packet)
1746 {
1747 Wifipcap::PcapUserData *data = reinterpret_cast<Wifipcap::PcapUserData *>(user);
1748 data->wcap->handle_packet(data->cbs,data->header_type,header,packet);
1749 }
1750
1751
1752 const char *Wifipcap::SetFilter(const char *filter)
1753 {
1754 struct bpf_program fp;
1755 #ifdef PCAP_NETMASK_UNKNOWN
1756 bpf_u_int32 netp=PCAP_NETMASK_UNKNOWN;
1757 #else
1758 bpf_u_int32 netp=0;
1759 #endif
1760
1761
1762 if(pcap_compile(descr,&fp,(char *)filter,0,netp) == -1) {
1763 return "Error calling pcap_compile";
1764 }
1765
1766 if(pcap_setfilter(descr,&fp) == -1) {
1767 return "Error setting filter";
1768 }
1769
1770 return NULL;
1771 }
1772
1773
1774 void Wifipcap::Run(WifipcapCallbacks *cbs, int maxpkts)
1775 {
1776 /* NOTE: This needs to be fixed so that the correct handle_packet is called */
1777
1778 packetsProcessed = 0;
1779
1780 do {
1781 PcapUserData data(this,cbs,DLT_IEEE802_11_RADIO);
1782 pcap_loop(descr, maxpkts > 0 ? maxpkts - packetsProcessed : 0,
1783 Wifipcap::handle_packet_callback, reinterpret_cast<u_char *>(&data));
1784 } while ( InitNext() );
1785 }
1786
1787
1788 ///////////////////////////////////////////////////////////////////////////////
1789