"Fossies" - the Fresh Open Source Software Archive

Member "tcpflow-1.6.1/src/wifipcap/wifipcap.cpp" (19 Feb 2021, 55775 Bytes) of package /linux/misc/tcpflow-1.6.1.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "wifipcap.cpp" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 1.5.0_vs_1.6.1.

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