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