include/wipal/wifi/frame/frame.hxx

00001 /*
00002  * WiPal - A library and a set of tools to manipulate wireless traces.
00003  * Copyright (C) 2007  Universite Pierre et Marie Curie - Paris 6
00004  *
00005  * This program is free software; you can redistribute it and/or modify
00006  * it under the terms of the GNU General Public License as published by
00007  * the Free Software Foundation; either version 2 of the License, or
00008  * (at your option) any later version.
00009  *
00010  * This program is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  * GNU General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU General Public License
00016  * along with this program; if not, write to the Free Software
00017  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
00018  * MA  02110-1301  USA
00019  *
00020  * Author: Thomas Claveirole <thomas.claveirole@lip6.fr>
00021  */
00022 #ifndef WIFI_FRAME_FRAME_HXX_
00023 # define WIFI_FRAME_FRAME_HXX_
00024 
00025 extern "C"
00026 {
00027 # include <netinet/in.h>
00028 }
00029 
00030 # include "frame.hh"
00031 
00032 # include <wipal/tool/endianness.hh>
00033 # include <wipal/wifi/frame/ctl.hh>
00034 # include <wipal/wifi/frame/mgt.hh>
00035 # include <wipal/wifi/frame/data.hh>
00036 # include <wipal/wifi/frame/dissector/dissector.hh>
00037 # include <wipal/wifi/frame/dissector/default_hooks.hh>
00038 
00039 namespace wifi
00040 {
00041 
00042   namespace frame
00043   {
00044 
00045     inline
00046     unsigned
00047     protocol_version_of(const void* frame)
00048     {
00049       return (ntohs(tool::extract_unswapped_short(frame)) >> 8) & 0x2;
00050     }
00051 
00052     inline
00053     type::frame_type
00054     type_of(const void* frame)
00055     {
00056       using tool::extract_unswapped_short;
00057       using type::frame_type;
00058 
00059       return frame_type ((ntohs(extract_unswapped_short(frame)) >> 10) & 0x3);
00060     }
00061 
00062     inline
00063     unsigned
00064     subtype_of(const void* frame)
00065     {
00066       return ntohs(tool::extract_unswapped_short(frame)) >> 12;
00067     }
00068 
00069     inline
00070     uint8_t
00071     control_flags_of(const void* frame)
00072     {
00073       return ntohs(tool::extract_unswapped_short(frame));
00074     }
00075 
00076     inline
00077     bool
00078     control_flag(const unsigned i, const void* frame)
00079     {
00080       const unsigned v = 1 << i;
00081 
00082       return (control_flags_of(frame) & v) == v;
00083     }
00084 
00085     inline
00086     bool
00087     to_ds(const void* frame)
00088     {
00089       return control_flag(0, frame);
00090     }
00091 
00092     inline
00093     bool
00094     from_ds(const void* frame)
00095     {
00096       return control_flag(1, frame);
00097     }
00098 
00099     inline
00100     unsigned
00101     duration_of(const void* frame)
00102     {
00103       const unsigned d =
00104         tool::extract_swapped_short(static_cast<const uint16_t*> (frame) + 1);
00105       return ntohs(d);
00106     }
00107 
00108     inline
00109     const addr*
00110     transmitter_address(const void* frame)
00111     {
00112       switch (type_of(frame))
00113         {
00114         case type::management:
00115           return & static_cast<const mgt::header*> (frame)->
00116             addrs[mgt::header::sa];
00117 
00118         case type::control:
00119           {
00120             using namespace ctl;
00121 
00122             switch (subtype_of(frame))
00123               {
00124               case subtype::ps_poll:
00125                 return & static_cast<const ps_poll::header*> (frame)->
00126                   addrs[ps_poll::header::ta];
00127 
00128               case subtype::rts:
00129                 return & static_cast<const rts::header*> (frame)->
00130                   addrs[rts::header::ta];
00131 
00132               default:
00133                 return 0;
00134               }
00135           }
00136 
00137         case type::data:
00138           {
00139             typedef data::header_3addr  header;
00140 
00141             return & static_cast<const header*> (frame)->addrs[1];
00142           }
00143 
00144         default:
00145           return 0;
00146         }
00147     }
00148 
00150     struct bssid_address_hooks: public dissector_default_hooks
00151     {
00153                         bssid_address_hooks()   { res_ = 0;     }
00154 
00156       const addr*       result() const          { return res_;  }
00157 
00158 # ifndef DOXYGEN
00159 #  define bssid_address_hooks_setup_hook(Type, Name)                    \
00160       void      Name ## _hook(const Type::Name::header* h, size_t)      \
00161       {                                                                 \
00162         res_ = & h->addrs[Type::Name::header::bssid];                   \
00163       }
00164 
00165     protected:
00166       bssid_address_hooks_setup_hook(ctl, ps_poll)
00167       bssid_address_hooks_setup_hook(ctl, cf_end)
00168       bssid_address_hooks_setup_hook(ctl, cf_end_cf_ack)
00169       bssid_address_hooks_setup_hook(data, within_ibss)
00170       bssid_address_hooks_setup_hook(data, from_ds)
00171       bssid_address_hooks_setup_hook(data, to_ds)
00172 
00173 #  undef bssid_address_hooks_setup_hook
00174 
00175     protected:
00176       void      ap_to_ap_hook(const data::ap_to_ap::header* h, size_t)
00177       {
00178         // FIXME: Actually, this frame holds two bssid addresses.
00179         res_ = & h->addrs[data::ap_to_ap::header::ta];
00180       }
00181 
00182       void      management_addr3_hook(const mgt::header* h, size_t)
00183       {
00184         res_ = & h->addrs[mgt::header::bssid];
00185       }
00186 
00187 # endif // ! DOXYGEN
00188 
00189     private:
00190       const addr*       res_;
00191     };
00192 
00193     inline
00194     const addr*
00195     bssid_address(const void* frame, size_t caplen)
00196     {
00197       return dissector<bssid_address_hooks> (frame, caplen).result();
00198     }
00199 
00200   } // End of namespace wifi::frame.
00201 
00202 } // End of namespace wifi.
00203 
00204 #endif // ! WIFI_FRAME_FRAME_HXX

Generated on Wed Jan 16 16:15:14 2008 for wipal by  doxygen 1.5.4