include/wipal/phy/rtap_header.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 RTAP_HEADER_HXX_
00023 # define RTAP_HEADER_HXX_
00024 
00025 # include "rtap_header.hh"
00026 
00027 # include <stdexcept>
00028 # include <cstring>
00029 
00030 # include <wipal/tool/endianness.hh>
00031 
00032 # define tt_diff(B, E) \
00033   (reinterpret_cast<const uint8_t*> (E) - reinterpret_cast<const uint8_t*> (B))
00034 
00035 namespace rtap
00036 {
00037 
00038   void
00039   check(const header* h, size_t caplen)
00040   {
00041     if (caplen < sizeof (*h))
00042       throw std::invalid_argument ("Truncated radiotap header");
00043 
00044     if (h->it_version)
00045       throw std::invalid_argument ("Invalid radiotap version");
00046   }
00047 
00048   const void*
00049   first_field(const header* h, size_t caplen)
00050   {
00051     const uint32_t* p = &h->it_present;
00052 
00053     while (tt_diff(h, p + 1) < ptrdiff_t (caplen) and
00054            tool::extract_little_endian_long_u(*p) & header::ext)
00055       ++p;
00056     return tt_diff(h, p + 1) >= ptrdiff_t (caplen) ? 0 : p + 1;
00057   }
00058 
00059   const void*
00060   get80211(const header* h, size_t caplen)
00061   {
00062     const size_t it_len = tool::extract_little_endian_long_u(h->it_len);
00063 
00064     if (caplen < it_len)
00065       return 0;
00066 
00067     return reinterpret_cast<const uint8_t*> (h) + it_len;
00068   }
00069 
00070 
00071   bool
00072   eq_80211(const header* lhs, size_t lhs_caplen,
00073            const header* rhs, size_t rhs_caplen)
00074   {
00075     check(lhs, lhs_caplen);
00076     check(rhs, rhs_caplen);
00077 
00078     const void*         lhs_80211 = get80211(lhs, lhs_caplen);
00079     const void*         rhs_80211 = get80211(rhs, rhs_caplen);
00080 
00081     if (not lhs_80211 or not rhs_80211)
00082       return false;
00083 
00084     const size_t  lhs_80211_caplen = lhs_caplen - tt_diff(lhs, lhs_80211);
00085     const size_t  rhs_80211_caplen = rhs_caplen - tt_diff(rhs, rhs_80211);
00086 
00087     if (not lhs_80211_caplen or not rhs_80211_caplen)
00088       return false;
00089 
00090     return 0 == memcmp(lhs_80211, rhs_80211,
00091                        std::min(lhs_80211_caplen, rhs_80211_caplen));
00092   }
00093 
00094   tool::microseconds
00095   get_tsft(const header* h, size_t caplen, const void* first_field)
00096   {
00097     if (not h->it_present & header::tsft)
00098       throw std::invalid_argument ("Radiotap header has no TSFT field");
00099 
00100     if (caplen < sizeof (*h) + 8 /* TSFT length */)
00101       throw std::invalid_argument ("Truncated TSFT in radiotap header");
00102 
00103     const uint32_t* const  tsft = static_cast<const uint32_t*> (first_field);
00104     const uint32_t         lo = tool::extract_little_endian_long_u(tsft[0]);
00105     const uint32_t         hi = tool::extract_little_endian_long_u(tsft[1]);
00106 
00107     return tool::microseconds (hi, lo);
00108   }
00109 
00110   bool
00111   eq_time_and_80211(const header* lhs, size_t lhs_caplen,
00112                     const header* rhs, size_t rhs_caplen,
00113                     unsigned    precision)
00114   {
00115     check(lhs, lhs_caplen);
00116     check(rhs, rhs_caplen);
00117 
00118     const tool::microseconds l = get_tsft(lhs, lhs_caplen,
00119                                           first_field(lhs, lhs_caplen));
00120     const tool::microseconds r = get_tsft(rhs, rhs_caplen,
00121                                           first_field(rhs, rhs_caplen));
00122 
00123     return abs(l - r) < precision and eq_80211(lhs, lhs_caplen,
00124                                                    rhs, rhs_caplen);
00125   }
00126 
00127 } // End of namespace rtap.
00128 
00129 # undef tt_diff
00130 
00131 #endif // ! RTAP_HEADER_HXX_

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