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 <wipal/tool/endianness.hh>
00026 # include <wipal/wifi/frame/frame.hh>
00027 # include <wipal/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 management_frame_dispatch(h, caplen);
00153 this->end_of_frame_headers_hook(frame, caplen,
00154 static_cast<const char*> (frame) +
00155 seqctl);
00156 }
00157
00158 template <class Hooks>
00159 void
00160 dissector<Hooks>::management_frame_dispatch(const mgt::header* h,
00161 size_t caplen)
00162 {
00163
00164 const void* const body = reinterpret_cast<const uint8_t*> (h) + seqctl;
00165 (void) body;
00166
00167 switch (subtype_of(h))
00168 {
00169 case mgt::subtype::beacon:
00170 return this->beacon_hook(h, caplen);
00171
00172 case mgt::subtype::assoc_req:
00173 return this->assoc_req_hook(h, caplen);
00174
00175 case mgt::subtype::assoc_resp:
00176 return this->assoc_resp_hook(h, caplen);
00177
00178 case mgt::subtype::reassoc_req:
00179 return this->reassoc_req_hook(h, caplen);
00180
00181 case mgt::subtype::reassoc_resp:
00182 return this->reassoc_resp_hook(h, caplen);
00183
00184 case mgt::subtype::probe_req:
00185 return this->probe_req_hook(h, caplen);
00186
00187 case mgt::subtype::probe_resp:
00188 return this->probe_resp_hook(h, caplen);
00189
00190 case mgt::subtype::atim:
00191 return this->atim_hook(h, caplen);
00192
00193 case mgt::subtype::disassoc:
00194 return this->disassoc_hook(h, caplen);
00195
00196 case mgt::subtype::auth:
00197 return this->auth_hook(h, caplen);
00198
00199 case mgt::subtype::deauth:
00200 return this->deauth_hook(h, caplen);
00201
00202 default:
00203 this->invalid_management_subtype_hook(h, caplen);
00204 this->invalid_subtype_hook(h, caplen, status_);
00205 this->invalid_type_or_subtype_hook(h, caplen, status_);
00206 return;
00207 }
00208 }
00209
00210 template <class Hooks>
00211 void
00212 dissector<Hooks>::control_frame(const void* frame, size_t caplen)
00213 {
00214 this->control_hook(frame, caplen);
00215
00216 switch (subtype_of(frame))
00217 {
00218
00219 # define dissector_control_dispatch_1addr(Name, Frame, Caplen) \
00220 case ctl::subtype::Name: \
00221 { \
00222 dissector_get_header(ctl::Name::header, h, Frame); \
00223 if (Caplen < addr1) \
00224 { \
00225 this->truncated_ ## Name ## _frame_hook(h, Caplen); \
00226 this->truncated_frame_hook(h, Caplen, status_); \
00227 return; \
00228 } \
00229 status_ = dissector_status::valid_addr1; \
00230 this->Name ## _addr1 ## _hook(h, Caplen); \
00231 this->addr_hook(h, Caplen, 1, h->ra); \
00232 this->Name ## _hook(h, Caplen); \
00233 this->end_of_frame_headers_hook(h, Caplen, \
00234 reinterpret_cast<const char*> (h) + addr1); \
00235 } \
00236 return
00237
00238 # define dissector_control_dispatch_2addr(Name, Frame, Caplen) \
00239 case ctl::subtype::Name: \
00240 { \
00241 dissector_get_header(ctl::Name::header, h, Frame); \
00242 dissector_check_addr2(1, Name, h, Caplen); \
00243 dissector_check_addr2(2, Name, h, Caplen); \
00244 this->Name ## _hook(h, Caplen); \
00245 this->end_of_frame_headers_hook(h, Caplen, \
00246 reinterpret_cast<const char*> (h) + addr2); \
00247 } \
00248 return
00249
00250 dissector_control_dispatch_2addr(ps_poll, frame, caplen);
00251 dissector_control_dispatch_2addr(rts, frame, caplen);
00252 dissector_control_dispatch_2addr(cf_end, frame, caplen);
00253 dissector_control_dispatch_2addr(cf_end_cf_ack, frame, caplen);
00254
00255 dissector_control_dispatch_1addr(cts, frame, caplen);
00256 dissector_control_dispatch_1addr(ack, frame, caplen);
00257
00258 # undef dissector_control_dispatch_2addr
00259 # undef dissector_control_dispatch_1addr
00260
00261 default:
00262 this->invalid_control_subtype_hook(frame, caplen);
00263 this->invalid_subtype_hook(frame, caplen, status_);
00264 this->invalid_type_or_subtype_hook(frame, caplen, status_);
00265 return;
00266 }
00267 }
00268
00269 template <class Hooks>
00270 void
00271 dissector<Hooks>::data_frame(const void* frame, size_t caplen)
00272 {
00273 this->data_hook(frame, caplen);
00274
00275 const data::header_3addr* h3 =
00276 static_cast<const data::header_3addr*> (frame);
00277
00278 dissector_check_addr2(1, data, h3, caplen);
00279 dissector_check_addr2(2, data, h3, caplen);
00280 dissector_check_addr2(3, data, h3, caplen);
00281 dissector_check_seq_ctl(data, h3, caplen);
00282
00283 const int dir = (to_ds(frame) ? 2 : 0) | (from_ds(frame) ? 1 : 0);
00284 switch (dir)
00285 {
00286 case 3:
00287 {
00288 using data::ap_to_ap::header;
00289
00290 const header* const h = static_cast<const header*> (frame);
00291 dissector_check_addr(4, data, h, caplen);
00292 this->addr_hook(h, caplen, 4, h->addrs_sa);
00293 this->ap_to_ap_hook(static_cast<const header*> (frame), caplen);
00294 break;
00295 }
00296
00297 case 2:
00298 {
00299 using data::to_ds::header;
00300
00301 this->to_ds_hook(static_cast<const header*> (frame), caplen);
00302 break;
00303 }
00304
00305 case 1:
00306 {
00307 using data::from_ds::header;
00308
00309 this->from_ds_hook(static_cast<const header*> (frame), caplen);
00310 break;
00311 }
00312
00313 case 0:
00314 {
00315 using data::within_ibss::header;
00316
00317 this->within_ibss_hook(static_cast<const header*> (frame), caplen);
00318 break;
00319 }
00320 }
00321 data_frame_dispatch(frame, caplen);
00322 this->end_of_frame_headers_hook(frame, caplen,
00323 static_cast<const char*> (frame) +
00324 (dir == 3 ? addr4 : addr3));
00325 }
00326
00327 template <class Hooks>
00328 void
00329 dissector<Hooks>::data_frame_dispatch(const void* frame, size_t caplen)
00330 {
00331 switch (subtype_of(frame))
00332 {
00333 case data::subtype::data:
00334 return this->data_only_hook(frame, caplen, status_);
00335 case data::subtype::data_cf_ack:
00336 return this->data_cf_ack_hook(frame, caplen, status_);
00337 case data::subtype::data_cf_poll:
00338 return this->data_cf_poll_hook(frame, caplen, status_);
00339 case data::subtype::data_cf_ack_cf_poll:
00340 return this->data_cf_ack_cf_poll_hook(frame, caplen, status_);
00341 case data::subtype::null:
00342 return this->null_hook(frame, caplen, status_);
00343 case data::subtype::cf_ack:
00344 return this->cf_ack_hook(frame, caplen, status_);
00345 case data::subtype::cf_poll:
00346 return this->cf_poll_hook(frame, caplen, status_);
00347 case data::subtype::cf_ack_cf_poll:
00348 return this->cf_ack_cf_poll_hook(frame, caplen, status_);
00349 default:
00350 this->invalid_data_subtype_hook(frame, caplen, status_);
00351 this->invalid_subtype_hook(frame, caplen, status_);
00352 this->invalid_type_or_subtype_hook(frame, caplen, status_);
00353 return;
00354 }
00355 }
00356
00357 # undef dissector_check_seq_ctl
00358 # undef dissector_check_addr2
00359 # undef dissector_check_addr
00360 # undef dissector_get_header
00361
00362 }
00363
00364 }
00365
00366 #endif // ! WIFI_FRAME_DISSECTOR_DISSECTOR_HXX_