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/ctl.hh>
00029 # include <wipal/wifi/mgt.hh>
00030 # include <wipal/wifi/data.hh>
00031 # include <wipal/wifi/dissector/dissector.hh>
00032 # include <wipal/wifi/dissector/default_hooks.hh>
00033
00034 namespace wpl
00035 {
00036
00037 namespace wifi
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 namespace
00102 {
00103
00104 struct seqnum_fragnum_hooks: public dissector_default_hooks
00105 {
00106 seqnum_fragnum_hooks(): valid_ (false)
00107 {
00108 }
00109
00110 void seq_ctl_hook(const void*, size_t,
00111 unsigned frag,
00112 unsigned seqno)
00113 {
00114 valid_ = true;
00115 frag_ = frag;
00116 seqno_ = seqno;
00117 }
00118
00119 operator bool () const
00120 {
00121 return valid_;
00122 }
00123
00124 bool operator not () const
00125 {
00126 return not operator bool ();
00127 }
00128
00129 unsigned frag() const
00130 {
00131 assert(*this);
00132
00133 return frag_;
00134 }
00135
00136 unsigned seqno() const
00137 {
00138 assert(*this);
00139
00140 return seqno_;
00141 }
00142
00143 private:
00144 bool valid_;
00145 unsigned frag_;
00146 unsigned seqno_;
00147 };
00148
00149 }
00150
00151 inline
00152 boost::optional<unsigned>
00153 fragment_number_of(const void* frame, size_t caplen)
00154 {
00155 dissector<seqnum_fragnum_hooks> d (frame, caplen);
00156
00157 if (not d)
00158 return boost::none_t ();
00159 return d.frag();
00160 }
00161
00162 inline
00163 boost::optional<unsigned>
00164 sequence_number_of(const void* frame, size_t caplen)
00165 {
00166 dissector<seqnum_fragnum_hooks> d (frame, caplen);
00167
00168 if (not d)
00169 return boost::none_t ();
00170 return d.seqno();
00171 }
00172
00173 inline
00174 const addr*
00175 transmitter_address(const void* frame)
00176 {
00177 switch (type_of(frame))
00178 {
00179 case type::management:
00180 return & static_cast<const mgt::header*> (frame)
00181 ->addrs[mgt::header::sa];
00182
00183 case type::control:
00184 {
00185 switch (subtype_of(frame))
00186 {
00187 case ctl::subtype::ps_poll:
00188 return & static_cast<const ctl::ps_poll::header*> (frame)
00189 ->addrs[ctl::ps_poll::header::ta];
00190
00191 case ctl::subtype::rts:
00192 return & static_cast<const ctl::rts::header*> (frame)
00193 ->addrs[ctl::rts::header::ta];
00194
00195 default:
00196 return 0;
00197 }
00198 }
00199
00200 case type::data:
00201 {
00202 typedef data::header_3addr header;
00203
00204 return & static_cast<const header*> (frame)->addrs[1];
00205 }
00206
00207 default:
00208 return 0;
00209 }
00210 }
00211
00213 struct bssid_address_hooks: public dissector_default_hooks
00214 {
00216 bssid_address_hooks() { res_ = 0; }
00217
00219 const addr* result() const { return res_; }
00220
00221 # ifndef DOXYGEN
00222 # define WP_bssid_address_hooks_define_hook(Type, Name) \
00223 void Name ## _hook(const Type::Name::header* h, size_t) \
00224 { \
00225 res_ = & h->addrs[Type::Name::header::bssid]; \
00226 }
00227
00228 protected:
00229 WP_bssid_address_hooks_define_hook(ctl, ps_poll)
00230 WP_bssid_address_hooks_define_hook(ctl, cf_end)
00231 WP_bssid_address_hooks_define_hook(ctl, cf_end_cf_ack)
00232 WP_bssid_address_hooks_define_hook(data, within_ibss)
00233 WP_bssid_address_hooks_define_hook(data, from_ds)
00234 WP_bssid_address_hooks_define_hook(data, to_ds)
00235
00236 # undef WP_bssid_address_hooks_define_hook
00237
00238 protected:
00239 void ap_to_ap_hook(const data::ap_to_ap::header* h, size_t)
00240 {
00241
00242 res_ = & h->addrs[data::ap_to_ap::header::ta];
00243 }
00244
00245 void management_addr3_hook(const mgt::header* h, size_t)
00246 {
00247 res_ = & h->addrs[mgt::header::bssid];
00248 }
00249
00250 # endif // ! DOXYGEN
00251
00252 private:
00253 const addr* res_;
00254 };
00255
00256 inline
00257 const addr*
00258 bssid_address(const void* frame, size_t caplen)
00259 {
00260 return dissector<bssid_address_hooks> (frame, caplen).result();
00261 }
00262
00263 }
00264
00265 }
00266
00267 #endif // ! WIFI_FRAME_FRAME_HXX