include/trace-tools/wifi/frame/dissector/dissector.hxx

00001 /*
00002  * trace-tools - 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_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: // To DS: 1, From DS: 1
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: // To DS: 1, From DS: 0
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: // To DS: 0, From DS: 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: // To DS: 0, From DS: 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   } // End of namespace:
00349 
00350 } // End of namespace wifi.
00351 
00352 #endif // ! WIFI_FRAME_DISSECTOR_DISSECTOR_HXX_

Generated on Wed Sep 12 16:02:47 2007 for trace-tools by  doxygen 1.5.3