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 namespace wpl
00033 {
00034
00035 namespace rtap
00036 {
00037
00038 inline
00039 size_t
00040 header::len_impl(size_t caplen, bool) const
00041 {
00042
00043 if (caplen and it_version)
00044 return caplen + 1;
00045
00046
00047 if (caplen < sizeof (rtap::header))
00048 return caplen + 1;
00049
00050 return tool::extract_little_endian_short_u(it_len);
00051 }
00052
00053 inline
00054 header::time_type
00055 header::time_get_impl(bool) const
00056 {
00057 return tsft_get(tool::extract_little_endian_short_u(it_len));
00058 }
00059
00060 inline
00061 void
00062 header::time_set_impl(const time_type& t, bool)
00063 {
00064 const size_t len = tool::extract_little_endian_short_u(it_len);
00065 void* const f = first_field(len);
00066 const uint64_t v = t.get_impl();
00067
00068 if (not tool::need_swap(tool::end::little, false))
00069 *static_cast<uint64_t*> (f) = v;
00070 else
00071 {
00072 const uint32_t lo = tool::extract_swapped_long_u(v & uint32_t (-1));
00073 const uint32_t hi = tool::extract_swapped_long_u(v >> 32);
00074 uint32_t* const f32 = static_cast<uint32_t*> (f);
00075
00076 f32[0] = lo;
00077 f32[1] = hi;
00078 }
00079 }
00080
00081 template <class S1, class S2>
00082 bool
00083 header::eq_time(const pkt::packet<S1>& lhs,
00084 const pkt::packet<S2>& rhs,
00085 const unsigned prec,
00086 const tool::end::endianness )
00087 {
00088 const size_t lhs_caplen = lhs.meta().caplen;
00089 const size_t rhs_caplen = rhs.meta().caplen;
00090
00091 const header* const lhs_phy = (static_cast<const header*>
00092 (lhs.bytes()));
00093 const header* const rhs_phy = (static_cast<const header*>
00094 (rhs.bytes()));
00095
00096 if (lhs_phy->len(lhs_caplen, false) > lhs_caplen or
00097 rhs_phy->len(rhs_caplen, false) > rhs_caplen)
00098 return false;
00099
00100 return std::abs(int64_t (lhs_phy->tsft_get(lhs_caplen) -
00101 rhs_phy->tsft_get(rhs_caplen))) <= prec;
00102 }
00103
00104 # define WP_diff(P1, P2) (reinterpret_cast<const uint8_t*> (P2) - \
00105 reinterpret_cast<const uint8_t*> (P1))
00106
00107 inline
00108 const void*
00109 header::first_field(size_t caplen) const
00110 {
00111 const uint32_t* p = &it_present;
00112
00113 while (WP_diff(this, p + 1) < ptrdiff_t (caplen) and
00114 tool::extract_little_endian_long_u(*p) & ext)
00115 ++p;
00116 return WP_diff(this, p + 1) >= ptrdiff_t (caplen) ? 0 : p + 1;
00117 }
00118
00119 inline
00120 void*
00121 header::first_field(size_t caplen)
00122 {
00123 uint32_t* p = &it_present;
00124
00125 while (WP_diff(this, p + 1) < ptrdiff_t (caplen) and
00126 tool::extract_little_endian_long_u(*p) & ext)
00127 ++p;
00128 return WP_diff(this, p + 1) >= ptrdiff_t (caplen) ? 0 : p + 1;
00129 }
00130
00131 # undef WP_diff
00132
00133 inline
00134 uint64_t
00135 header::tsft_get(size_t caplen) const
00136 {
00137 if (not it_present & tsft)
00138 throw std::invalid_argument ("Radiotap header has no TSFT field");
00139
00140 if (caplen < sizeof (rtap::header) + 8)
00141 throw std::invalid_argument ("Truncated or inconsistent RTAP header "
00142 "(length too short w.r.t. present fields)");
00143
00144 const void* const f = first_field(caplen);
00145
00146 assert(f);
00147 if (not tool::need_swap(tool::end::little, false))
00148 return *static_cast<const uint64_t*> (f);
00149 else
00150 {
00151 const uint32_t* const f32 = static_cast<const uint32_t*> (f);
00152
00153 const uint32_t lo = tool::extract_little_endian_long_u(f32[0]);
00154 const uint32_t hi = tool::extract_little_endian_long_u(f32[1]);
00155
00156 return (uint64_t (hi) << 32) | lo;
00157 }
00158 }
00159
00160 }
00161
00162 }
00163
00164 #endif // ! RTAP_HEADER_HXX_