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_DISSECTOR_DISSECTOR_HXX_
00023 # define WIFI_FRAME_DISSECTOR_DISSECTOR_HXX_
00024
00025 # include <trace-tools/tool/endianness.hh>
00026 # include <trace-tools/wifi/frame/frame.hh>
00027 # include <trace-tools/wifi/frame/data.hh>
00028
00029 # include "dissector.hh"
00030
00031 namespace wifi
00032 {
00033
00034 namespace frame
00035 {
00036
00037 template <class Hooks>
00038 dissector<Hooks>::dissector(const Hooks& hooks): Hooks (hooks)
00039 {
00040 }
00041
00042 template <class Hooks>
00043 dissector<Hooks>::dissector(const void* frame,
00044 size_t caplen,
00045 const Hooks& hooks): Hooks(hooks)
00046 {
00047 (*this)(frame, caplen);
00048 }
00049
00050 template <class Hooks>
00051 dissector_status::status
00052 dissector<Hooks>::status() const
00053 {
00054 return status_;
00055 }
00056
00057 template <class Hooks>
00058 void
00059 dissector<Hooks>::operator () (const void* frame, size_t caplen)
00060 {
00061 this->frame_hook(frame, caplen);
00062
00063 if (caplen < control)
00064 {
00065 status_ = dissector_status::invalid;
00066 this->truncated_unknown_frame_hook(frame, caplen);
00067 this->truncated_frame_hook(frame, caplen, status_);
00068 }
00069 else
00070 {
00071 status_ = dissector_status::valid_control;
00072 switch (type_of(frame))
00073 {
00074 case type::management: management_frame(frame, caplen); break;
00075 case type::control: control_frame(frame, caplen); break;
00076 case type::data: data_frame(frame, caplen); break;
00077
00078 default:
00079 this->invalid_type_hook(frame, caplen);
00080 this->invalid_type_or_subtype_hook(frame, caplen, status_);
00081 break;
00082 }
00083 }
00084 this->end_of_frame_hook(frame, caplen, status_);
00085 }
00086
00087 template <class Hooks>
00088 Hooks&
00089 dissector<Hooks>::hooks()
00090 {
00091 return *static_cast<Hooks*> (this);
00092 }
00093
00094 template <class Hooks>
00095 const Hooks&
00096 dissector<Hooks>::hooks() const
00097 {
00098 return *static_cast<const Hooks*> (this);
00099 }
00100
00101 # define dissector_get_header(Type, VarName, Frame) \
00102 const Type::header* VarName = static_cast<const Type::header*> (Frame)
00103
00104 # define dissector_check_addr(N, Type, Header, Caplen) \
00105 if (Caplen < addr ## N) \
00106 { \
00107 this->truncated_ ## Type ## _frame_hook(Header, Caplen, status_); \
00108 this->truncated_frame_hook(Header, Caplen, status_); \
00109 return; \
00110 } \
00111 status_ = dissector_status::valid_addr ## N; \
00112 this->Type ## _addr ## N ## _hook(Header, Caplen)
00113
00114 # define dissector_check_addr2(N, Type, Header, Caplen) \
00115 dissector_check_addr(N, Type, Header, Caplen); \
00116 this->addr_hook(Header, Caplen, N, Header->addrs[N - 1])
00117
00118 # define dissector_check_seq_ctl(Type, Header, Caplen) \
00119 if (caplen < seqctl) \
00120 { \
00121 this->truncated_ ## Type ## _frame_hook(Header, Caplen, status_); \
00122 this->truncated_frame_hook(Header, Caplen, status_); \
00123 } \
00124 do \
00125 { \
00126 using tool::extract_swapped_short; \
00127 \
00128 const unsigned seq_ctl = \
00129 ntohs(extract_swapped_short(Header->seq_ctl)); \
00130 const unsigned fragnum = seq_ctl & 0xF; \
00131 const unsigned seqnum = seq_ctl >> 4; \
00132 \
00133 status_ = dissector_status::valid_seq_ctl; \
00134 this->Type ## _seq_ctl_hook(Header, Caplen, fragnum, seqnum); \
00135 this->seq_ctl_hook(Header, Caplen, fragnum, seqnum); \
00136 } \
00137 while (false)
00138
00139 template <class Hooks>
00140 void
00141 dissector<Hooks>::management_frame(const void* frame, size_t caplen)
00142 {
00143 dissector_get_header(mgt::header, h, frame);
00144
00145 this->management_hook(h, caplen);
00146
00147 dissector_check_addr2(1, management, h, caplen);
00148 dissector_check_addr2(2, management, h, caplen);
00149 dissector_check_addr2(3, management, h, caplen);
00150 dissector_check_seq_ctl(management, h, caplen);
00151
00152 return management_frame_dispatch(h, caplen);
00153 }
00154
00155 template <class Hooks>
00156 void
00157 dissector<Hooks>::management_frame_dispatch(const mgt::header* h,
00158 size_t caplen)
00159 {
00160 switch (subtype_of(h))
00161 {
00162 case mgt::subtype::beacon:
00163 return this->beacon_hook(h, caplen);
00164
00165 case mgt::subtype::assoc_req:
00166 return this->assoc_req_hook(h, caplen);
00167
00168 case mgt::subtype::assoc_resp:
00169 return this->assoc_resp_hook(h, caplen);
00170
00171 case mgt::subtype::reassoc_req:
00172 return this->reassoc_req_hook(h, caplen);
00173
00174 case mgt::subtype::reassoc_resp:
00175 return this->reassoc_resp_hook(h, caplen);
00176
00177 case mgt::subtype::probe_req:
00178 return this->probe_req_hook(h, caplen);
00179
00180 case mgt::subtype::probe_resp:
00181 return this->probe_resp_hook(h, caplen);
00182
00183 case mgt::subtype::atim:
00184 return this->atim_hook(h, caplen);
00185
00186 case mgt::subtype::disassoc:
00187 return this->disassoc_hook(h, caplen);
00188
00189 case mgt::subtype::auth:
00190 return this->auth_hook(h, caplen);
00191
00192 case mgt::subtype::deauth:
00193 return this->deauth_hook(h, caplen);
00194
00195 default:
00196 this->invalid_management_subtype_hook(h, caplen);
00197 this->invalid_subtype_hook(h, caplen, status_);
00198 this->invalid_type_or_subtype_hook(h, caplen, status_);
00199 return;
00200 }
00201 }
00202
00203 template <class Hooks>
00204 void
00205 dissector<Hooks>::control_frame(const void* frame, size_t caplen)
00206 {
00207 this->control_hook(frame, caplen);
00208
00209 switch (subtype_of(frame))
00210 {
00211
00212 # define dissector_control_dispatch_1addr(Name, Frame, Caplen) \
00213 case ctl::subtype::Name: \
00214 { \
00215 dissector_get_header(ctl::Name::header, h, Frame); \
00216 if (Caplen < addr1) \
00217 { \
00218 this->truncated_ ## Name ## _frame_hook(h, Caplen); \
00219 this->truncated_frame_hook(h, Caplen, status_); \
00220 return; \
00221 } \
00222 status_ = dissector_status::valid_addr1; \
00223 this->Name ## _addr1 ## _hook(h, Caplen); \
00224 this->addr_hook(h, Caplen, 1, h->ra); \
00225 this->Name ## _hook(h, Caplen); \
00226 } \
00227 return
00228
00229 # define dissector_control_dispatch_2addr(Name, Frame, Caplen) \
00230 case ctl::subtype::Name: \
00231 { \
00232 dissector_get_header(ctl::Name::header, h, Frame); \
00233 dissector_check_addr2(1, Name, h, Caplen); \
00234 dissector_check_addr2(2, Name, h, Caplen); \
00235 this->Name ## _hook(h, Caplen); \
00236 } \
00237 return
00238
00239 dissector_control_dispatch_2addr(ps_poll, frame, caplen);
00240 dissector_control_dispatch_2addr(rts, frame, caplen);
00241 dissector_control_dispatch_2addr(cf_end, frame, caplen);
00242 dissector_control_dispatch_2addr(cf_end_cf_ack, frame, caplen);
00243
00244 dissector_control_dispatch_1addr(cts, frame, caplen);
00245 dissector_control_dispatch_1addr(ack, frame, caplen);
00246
00247 # undef dissector_control_dispatch_2addr
00248 # undef dissector_control_dispatch_1addr
00249
00250 default:
00251 this->invalid_control_subtype_hook(frame, caplen);
00252 this->invalid_subtype_hook(frame, caplen, status_);
00253 this->invalid_type_or_subtype_hook(frame, caplen, status_);
00254 return;
00255 }
00256 }
00257
00258 template <class Hooks>
00259 void
00260 dissector<Hooks>::data_frame(const void* frame, size_t caplen)
00261 {
00262 this->data_hook(frame, caplen);
00263
00264 const data::header_3addr* h3 =
00265 static_cast<const data::header_3addr*> (frame);
00266
00267 dissector_check_addr2(1, data, h3, caplen);
00268 dissector_check_addr2(2, data, h3, caplen);
00269 dissector_check_addr2(3, data, h3, caplen);
00270 dissector_check_seq_ctl(data, h3, caplen);
00271
00272 const int dir = (to_ds(frame) ? 2 : 0) | (from_ds(frame) ? 1 : 0);
00273 switch (dir)
00274 {
00275 case 3:
00276 {
00277 using data::ap_to_ap::header;
00278
00279 const header* const h = static_cast<const header*> (frame);
00280 dissector_check_addr(4, data, h, caplen);
00281 this->addr_hook(h, caplen, 4, h->addrs_sa);
00282 this->ap_to_ap_hook(static_cast<const header*> (frame), caplen);
00283 break;
00284 }
00285
00286 case 2:
00287 {
00288 using data::to_ds::header;
00289
00290 this->to_ds_hook(static_cast<const header*> (frame), caplen);
00291 break;
00292 }
00293
00294 case 1:
00295 {
00296 using data::from_ds::header;
00297
00298 this->from_ds_hook(static_cast<const header*> (frame), caplen);
00299 break;
00300 }
00301
00302 case 0:
00303 {
00304 using data::within_ibss::header;
00305
00306 this->within_ibss_hook(static_cast<const header*> (frame), caplen);
00307 break;
00308 }
00309 }
00310 data_frame_dispatch(frame, caplen);
00311 }
00312
00313 template <class Hooks>
00314 void
00315 dissector<Hooks>::data_frame_dispatch(const void* frame, size_t caplen)
00316 {
00317 switch (subtype_of(frame))
00318 {
00319 case data::subtype::data:
00320 return this->data_only_hook(frame, caplen, status_);
00321 case data::subtype::data_cf_ack:
00322 return this->data_cf_ack_hook(frame, caplen, status_);
00323 case data::subtype::data_cf_poll:
00324 return this->data_cf_poll_hook(frame, caplen, status_);
00325 case data::subtype::data_cf_ack_cf_poll:
00326 return this->data_cf_ack_cf_poll_hook(frame, caplen, status_);
00327 case data::subtype::null:
00328 return this->null_hook(frame, caplen, status_);
00329 case data::subtype::cf_ack:
00330 return this->cf_ack_hook(frame, caplen, status_);
00331 case data::subtype::cf_poll:
00332 return this->cf_poll_hook(frame, caplen, status_);
00333 case data::subtype::cf_ack_cf_poll:
00334 return this->cf_ack_cf_poll_hook(frame, caplen, status_);
00335 default:
00336 this->invalid_data_subtype_hook(frame, caplen, status_);
00337 this->invalid_subtype_hook(frame, caplen, status_);
00338 this->invalid_type_or_subtype_hook(frame, caplen, status_);
00339 return;
00340 }
00341 }
00342
00343 # undef dissector_check_seq_ctl
00344 # undef dissector_check_addr2
00345 # undef dissector_check_addr
00346 # undef dissector_get_header
00347
00348 }
00349
00350 }
00351
00352 #endif // ! WIFI_FRAME_DISSECTOR_DISSECTOR_HXX_