00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
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 )
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 }
00128
00129 # undef tt_diff
00130
00131 #endif // ! RTAP_HEADER_HXX_