00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifndef WIFI_FRAME_FRAME_HXX_
00023 # define WIFI_FRAME_FRAME_HXX_
00024
00025 # include "frame.hh"
00026
00027 # include <wipal/tool/endianness.hh>
00028 # include <wipal/wifi/frame/ctl.hh>
00029 # include <wipal/wifi/frame/mgt.hh>
00030 # include <wipal/wifi/frame/data.hh>
00031 # include <wipal/wifi/frame/dissector/dissector.hh>
00032 # include <wipal/wifi/frame/dissector/default_hooks.hh>
00033
00034 namespace wifi
00035 {
00036
00037 namespace frame
00038 {
00039
00040 inline
00041 unsigned
00042 protocol_version_of(const void* frame)
00043 {
00044 return tool::extract_little_endian_short_u(frame) & 0x3;
00045 }
00046
00047 inline
00048 type::frame_type
00049 type_of(const void* frame)
00050 {
00051 const unsigned t =
00052 (tool::extract_little_endian_short_u(frame) >> 2) & 0x3;
00053 return type::frame_type (t);
00054 }
00055
00056 inline
00057 unsigned
00058 subtype_of(const void* frame)
00059 {
00060 return (tool::extract_little_endian_short_u(frame) >> 4) & 0xF;
00061 }
00062
00063 inline
00064 uint8_t
00065 control_flags_of(const void* frame)
00066 {
00067 return tool::extract_little_endian_short_u(frame) >> 8;
00068 }
00069
00070 inline
00071 bool
00072 control_flag(const unsigned i, const void* frame)
00073 {
00074 const unsigned v = 1 << i;
00075
00076 return (control_flags_of(frame) & v) == v;
00077 }
00078
00079 inline
00080 bool
00081 to_ds(const void* frame)
00082 {
00083 return control_flag(0, frame);
00084 }
00085
00086 inline
00087 bool
00088 from_ds(const void* frame)
00089 {
00090 return control_flag(1, frame);
00091 }
00092
00093 inline
00094 unsigned
00095 duration_of(const void* frame)
00096 {
00097 return tool::
00098 extract_little_endian_short_u(static_cast<const uint16_t*> (frame) + 1);
00099 }
00100
00101 inline
00102 const addr*
00103 transmitter_address(const void* frame)
00104 {
00105 switch (type_of(frame))
00106 {
00107 case type::management:
00108 return & static_cast<const mgt::header*> (frame)
00109 ->addrs[mgt::header::sa];
00110
00111 case type::control:
00112 {
00113 switch (subtype_of(frame))
00114 {
00115 case ctl::subtype::ps_poll:
00116 return & static_cast<const ctl::ps_poll::header*> (frame)
00117 ->addrs[ctl::ps_poll::header::ta];
00118
00119 case ctl::subtype::rts:
00120 return & static_cast<const ctl::rts::header*> (frame)
00121 ->addrs[ctl::rts::header::ta];
00122
00123 default:
00124 return 0;
00125 }
00126 }
00127
00128 case type::data:
00129 {
00130 typedef data::header_3addr header;
00131
00132 return & static_cast<const header*> (frame)->addrs[1];
00133 }
00134
00135 default:
00136 return 0;
00137 }
00138 }
00139
00141 struct bssid_address_hooks: public dissector_default_hooks
00142 {
00144 bssid_address_hooks() { res_ = 0; }
00145
00147 const addr* result() const { return res_; }
00148
00149 # ifndef DOXYGEN
00150 # define WP_bssid_address_hooks_define_hook(Type, Name) \
00151 void Name ## _hook(const Type::Name::header* h, size_t) \
00152 { \
00153 res_ = & h->addrs[Type::Name::header::bssid]; \
00154 }
00155
00156 protected:
00157 WP_bssid_address_hooks_define_hook(ctl, ps_poll)
00158 WP_bssid_address_hooks_define_hook(ctl, cf_end)
00159 WP_bssid_address_hooks_define_hook(ctl, cf_end_cf_ack)
00160 WP_bssid_address_hooks_define_hook(data, within_ibss)
00161 WP_bssid_address_hooks_define_hook(data, from_ds)
00162 WP_bssid_address_hooks_define_hook(data, to_ds)
00163
00164 # undef WP_bssid_address_hooks_define_hook
00165
00166 protected:
00167 void ap_to_ap_hook(const data::ap_to_ap::header* h, size_t)
00168 {
00169
00170 res_ = & h->addrs[data::ap_to_ap::header::ta];
00171 }
00172
00173 void management_addr3_hook(const mgt::header* h, size_t)
00174 {
00175 res_ = & h->addrs[mgt::header::bssid];
00176 }
00177
00178 # endif // ! DOXYGEN
00179
00180 private:
00181 const addr* res_;
00182 };
00183
00184 inline
00185 const addr*
00186 bssid_address(const void* frame, size_t caplen)
00187 {
00188 return dissector<bssid_address_hooks> (frame, caplen).result();
00189 }
00190
00191 }
00192
00193 }
00194
00195 #endif // ! WIFI_FRAME_FRAME_HXX