00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifndef FILTER_ANONYMIZER_HXX_
00023 # define FILTER_ANONYMIZER_HXX_
00024
00025 # include <cassert>
00026 # include <stdexcept>
00027
00028 # include <boost/foreach.hpp>
00029 # include <boost/lexical_cast.hpp>
00030
00031 # include <wipal/wifi/dissector/dissector.hh>
00032
00033 # include "anonymizer.hh"
00034
00035 namespace wpl
00036 {
00037 namespace wifi
00038 {
00039
00040
00041
00042
00043
00044 namespace anon
00045 {
00046
00047 inline
00048 addr
00049 dummy_mac_policy::operator [] (const addr& mac_addr) const
00050 {
00051 return mac_addr;
00052 }
00053
00054 inline
00055 essid
00056 dummy_essid_policy::operator [] (const essid& essid) const
00057 {
00058 return essid;
00059 }
00060
00061 template <class MACAnonPolicy, class ESSIDAnonPolicy>
00062 generic_policy<MACAnonPolicy, ESSIDAnonPolicy>::
00063 generic_policy(const MACAnonPolicy& macp,
00064 const ESSIDAnonPolicy& essidp):
00065 MACAnonPolicy (macp),
00066 ESSIDAnonPolicy (essidp)
00067 {
00068 }
00069
00070 template <class MACAnonPolicy, class ESSIDAnonPolicy>
00071 addr
00072 generic_policy<MACAnonPolicy, ESSIDAnonPolicy>::
00073 operator [] (const addr& mac_addr)
00074 {
00075 return MACAnonPolicy::operator [] (mac_addr);
00076 }
00077
00078 template <class MACAnonPolicy, class ESSIDAnonPolicy>
00079 essid
00080 generic_policy<MACAnonPolicy, ESSIDAnonPolicy>::
00081 operator [] (const essid& essid)
00082 {
00083 return ESSIDAnonPolicy::operator [] (essid);
00084 }
00085
00086 }
00087
00088
00089 namespace internals
00090 {
00091
00092
00093
00094
00095
00096 template <class AnonPolicy>
00097 void
00098 anonymize_addrs(AnonPolicy& anon_policy,
00099 void* const bytes,
00100 const std::set<const wifi::addr*>& addrs)
00101 {
00102 uint8_t* const bytes_u8 = static_cast<uint8_t*> (bytes);
00103
00104 BOOST_FOREACH(const wifi::addr* a, addrs)
00105 {
00106 const uint8_t* const a_u8 = reinterpret_cast<const uint8_t*> (a);
00107 const ptrdiff_t offset = a_u8 - bytes_u8;
00108 wifi::addr* const a2 = reinterpret_cast<wifi::addr*> (bytes_u8 +
00109 offset);
00110 *a2 = anon_policy[*a];
00111 }
00112 }
00113
00114
00115
00116
00117
00118 template <class AnonPolicy>
00119 size_t
00120 anonymize_ssid(AnonPolicy& anon_policy,
00121 const size_t anon_caplen,
00122 const pkt::metadata& meta,
00123 void* const bytes,
00124 const wifi::ssid_elt* const ssid,
00125 const std::string* const pkt_id)
00126 {
00127 if (not ssid)
00128 return anon_caplen;
00129
00130 const std::string msg_pfx = pkt_id? *pkt_id + ": ": "";
00131
00132 if (ssid->elt_id != 0)
00133 {
00134 std::cerr << msg_pfx << "SSID element ID not found, skipping ("
00135 << unsigned (ssid->elt_id) << " instead of 0)."
00136 << std::endl;
00137 return anon_caplen;
00138 }
00139
00140 uint8_t* const bytes_u8 = static_cast<uint8_t*> (bytes);
00141 const size_t caplen = meta.caplen;
00142 const ptrdiff_t ssid_offset = ssid->ssid - bytes_u8;
00143 size_t ssid_len = ssid->length;
00144
00145 if (ssid_offset > ptrdiff_t (anon_caplen))
00146 return anon_caplen;
00147
00148 if (ssid_len > 32)
00149 {
00150 std::cerr << msg_pfx << "Invalid SSID length of " << ssid_len
00151 << ", truncating frame (should be between 0 and 32)."
00152 << std::endl;
00153 return ssid_offset;
00154 }
00155
00156 if (ssid->ssid + ssid_len > bytes_u8 + caplen)
00157 {
00158 std::cerr << msg_pfx
00159 << "SSID overruns captured bytes, truncating."
00160 << std::endl;
00161 ssid_len = caplen - ssid_offset;
00162 }
00163
00164 const essid ssid_str (*ssid, ssid_len);
00165 essid anon_ssid_str = anon_policy[ssid_str];
00166
00167 if (anon_ssid_str.size() > ssid_len)
00168 throw std::runtime_error ("Anonymized ESSID is too big");
00169 anon_ssid_str.append(ssid_len - anon_ssid_str.size(), '\0');
00170
00171 if (ssid_offset + ssid_len > anon_caplen)
00172 ssid_len = anon_caplen - ssid_offset;
00173 memcpy(bytes_u8 + ssid_offset, anon_ssid_str.data(), ssid_len);
00174
00175 return anon_caplen;
00176 }
00177
00178
00179
00180
00181
00182 inline
00183 anon_hooks::anon_hooks():
00184 ty (type::reserved),
00185 end (0),
00186 ssid (0)
00187 {
00188 }
00189
00190 inline
00191 void
00192 anon_hooks::addr_hook(const void* f, size_t, unsigned n, const addr& a)
00193 {
00194 if (n == 1)
00195 ty = type_of(f);
00196
00197 addrs.insert(&a);
00198 }
00199
00200 inline
00201 void
00202 anon_hooks::end_of_frame_headers_hook(const void* f, size_t caplen,
00203 const void* eofh)
00204 {
00205 const uint8_t* const eofh_u8 = static_cast<const uint8_t*> (eofh);
00206 const uint8_t* const eof = static_cast<const uint8_t*> (f) + caplen;
00207 const uint8_t* tmp_ssid = 0;
00208
00209 switch (ty)
00210 {
00211 case type::data:
00212 end = eofh_u8;
00213 break;
00214
00215 case type::management:
00216 switch (subtype_of(f))
00217 {
00218 case mgt::subtype::assoc_req:
00219
00220 tmp_ssid = eofh_u8 + 4;
00221 break;
00222
00223 case mgt::subtype::reassoc_req:
00224
00225 tmp_ssid = eofh_u8 + 10;
00226 break;
00227
00228 case mgt::subtype::probe_req:
00229 tmp_ssid = eofh_u8;
00230 break;
00231
00232 case mgt::subtype::probe_resp:
00233 case mgt::subtype::beacon:
00234
00235 tmp_ssid = eofh_u8 + 12;
00236 break;
00237 }
00238 break;
00239
00240 default:
00241 break;
00242 }
00243 if (tmp_ssid and tmp_ssid + sizeof (ssid_elt) < eof)
00244 ssid = reinterpret_cast<const ssid_elt*> (tmp_ssid);
00245 }
00246
00247 }
00248
00249 template <class Phy, class AnonPolicy, class S>
00250 void
00251 anonymize(AnonPolicy& anon_policy,
00252 pkt::packet<S>& frm)
00253 {
00254 const std::string pkt_str = boost::lexical_cast<std::string> (frm);
00255
00256 return anonymize<Phy>(anon_policy,
00257 frm.meta(), frm.bytes(), frm.swapped(), &pkt_str);
00258 }
00259
00260 template <class Phy, class AnonPolicy>
00261 void
00262 anonymize(AnonPolicy& anon_policy,
00263 pkt::metadata& meta,
00264 void* bytes,
00265 const bool swapped,
00266 const std::string* const pkt_str)
00267 {
00268 const Phy* const phy = static_cast<const Phy*> (bytes);
00269 const size_t caplen = meta.caplen;
00270 const size_t phy_len = phy->len(caplen, swapped);
00271 const uint8_t* const mac = (static_cast<const uint8_t*>
00272 (phy->decapsulate(caplen, swapped)));
00273
00274 wifi::dissector<internals::anon_hooks> d;
00275 const internals::anon_hooks& h = d.hooks();
00276
00277 if (mac)
00278 {
00279 assert(caplen >= phy_len);
00280 d(mac, caplen - phy_len);
00281 }
00282
00283 const size_t anon_caplen = h.end? phy_len + (h.end - mac): caplen;
00284
00285 internals::anonymize_addrs(anon_policy, bytes, h.addrs);
00286 meta.caplen = internals::anonymize_ssid(anon_policy, anon_caplen,
00287 meta, bytes, h.ssid, pkt_str);
00288 }
00289
00290 }
00291
00292 namespace filter
00293 {
00294
00295 namespace internals
00296 {
00297
00298
00299
00300
00301
00302 template <class I, class P, class A, class B1, class B2>
00303 anonymizer_iterator<I, P, A, B1, B2>::
00304 anonymizer_iterator(const iterable_type& iterable, bool end):
00305 A (iterable),
00306 next_ (end? iterable.last_ : iterable.first_),
00307 last_ (iterable.last_)
00308 {
00309 if (not end)
00310 increment();
00311 }
00312
00313 template <class I, class P, class A, class B1, class B2>
00314 bool
00315 anonymizer_iterator<I, P, A, B1, B2>::
00316 equal(const anonymizer_iterator& rhs) const
00317 {
00318 if (not rhs.value())
00319 return not this->value();
00320
00321 return next_ == rhs.next_;
00322 }
00323
00324 template <class I, class P, class A, class B1, class B2>
00325 void
00326 anonymizer_iterator<I, P, A, B1, B2>::increment()
00327 {
00328 if (next_ == last_)
00329 this->value() = boost::none_t ();
00330 else
00331 {
00332 boost::optional<value_type>& v = this->value();
00333
00334 if (not v or not v->unique())
00335 v = value_type (next_->meta());
00336 else
00337 v->meta() = next_->meta();
00338 memcpy(v->bytes(), next_->bytes(), next_->meta().caplen);
00339 wifi::anonymize<P, A>(*this, *v);
00340 ++next_;
00341 }
00342 }
00343
00344 }
00345
00346
00347 template <class I, class P, class A, class B>
00348 anonymizer<I, P, A, B>::anonymizer(const I& first, const I& last,
00349 const A& anon_policy):
00350 A (anon_policy),
00351 first_ (first),
00352 last_ (last)
00353 {
00354 }
00355
00356 template <class I, class P, class A, class B>
00357 bool
00358 anonymizer<I, P, A, B>::swapped_impl() const
00359 {
00360 if (first_ == last_)
00361 return false;
00362
00363 return first_->swapped();
00364 }
00365
00366
00367 }
00368
00369 }
00370
00371 #endif // ! FILTER_ANONYMIZER_HXX_