include/wipal/wifi/frame/dissector/dissector.hxx

00001 /*
00002  * WiPal - 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 <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       // FIXME: TODO: Use this to parse IEEE 802.11 elements in frame bodies.
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: // To DS: 1, From DS: 1
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: // To DS: 1, From DS: 0
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: // To DS: 0, From DS: 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: // To DS: 0, From DS: 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   } // End of namespace:
00363 
00364 } // End of namespace wifi.
00365 
00366 #endif // ! WIFI_FRAME_DISSECTOR_DISSECTOR_HXX_

Generated on Tue Jan 15 19:32:31 2008 for wipal by  doxygen 1.5.4