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