00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifndef WIT_IMPORTER_HXX_
00023 # define WIT_IMPORTER_HXX_
00024
00025 # include <cassert>
00026 # include <utility>
00027 # include <fstream>
00028 # include <sstream>
00029 # include <iomanip>
00030
00031 # include <boost/lexical_cast.hpp>
00032
00033 # include <wipal/phy/prism_header.hh>
00034 # include <wipal/wifi/timestamp.hh>
00035 # include <wipal/wifi/dissector/dissector.hh>
00036
00037 # include "wit_importer.hh"
00038
00039 namespace wit
00040 {
00041
00042
00043
00044
00045
00046 inline
00047 importer::hooks::hooks(wpl::wifi::addr_mapping& m)
00048 : mapping_ (m),
00049 addrs_ (),
00050 beacon_timestamp_ (db_null),
00051 fragnum_ (db_null),
00052 seqnum_ (db_null),
00053 error_ (db_null)
00054 {
00055 }
00056
00057 inline
00058 std::string
00059 importer::hooks::addrs() const
00060 {
00061 return addrs_;
00062 }
00063
00064 inline
00065 std::string
00066 importer::hooks::beacon_timestamp() const
00067 {
00068 return beacon_timestamp_;
00069 }
00070
00071 inline
00072 std::string
00073 importer::hooks::fragnum() const
00074 {
00075 return fragnum_;
00076 }
00077
00078 inline
00079 std::string
00080 importer::hooks::seqnum() const
00081 {
00082 return seqnum_;
00083 }
00084
00085 inline
00086 std::string
00087 importer::hooks::error() const
00088 {
00089 return error_;
00090 }
00091
00092 inline
00093 void
00094 importer::hooks::invalid_type_or_subtype_hook(const void*, size_t, status)
00095 {
00096 error_ = boost::lexical_cast<std::string> (bad_type_subtype);
00097 }
00098
00099 inline
00100 void
00101 importer::hooks::truncated_frame_hook(const void*, size_t, status)
00102 {
00103 error_ = boost::lexical_cast<std::string> (malformed_802);
00104 }
00105
00106 inline
00107 void
00108 importer::hooks::addr_hook(const void*, size_t,
00109 unsigned n, const wpl::wifi::addr& a)
00110 {
00111 addrs_ += boost::lexical_cast<std::string> (mapping_[a]);
00112 if (n < 4)
00113 addrs_ += '\t';
00114 }
00115
00116 inline
00117 void
00118 importer::hooks::seq_ctl_hook(const void*, size_t,
00119 unsigned fragnum, unsigned seqnum)
00120 {
00121 fragnum_ = boost::lexical_cast<std::string> (fragnum);
00122 seqnum_ = boost::lexical_cast<std::string> (seqnum);
00123 }
00124
00125 inline
00126 void
00127 importer::hooks::beacon_hook(const wpl::wifi::mgt::header* h,
00128 size_t caplen)
00129 {
00130 if (caplen < sizeof (*h) + sizeof (wpl::wifi::timestamp))
00131 {
00132 truncated_frame_hook(h, caplen,
00133 wpl::wifi::dissector_status::valid_addr3);
00134 return;
00135 }
00136
00137 std::ostringstream output;
00138 output << *reinterpret_cast<const wpl::wifi::timestamp*> (h->body);
00139 beacon_timestamp_ = output.str();
00140 }
00141
00142 inline
00143 void
00144 importer::hooks::end_of_frame_hook(const void*, size_t, status s)
00145 {
00146 using namespace wpl::wifi::dissector_status;
00147
00148 std::ostringstream nulls;
00149 switch (s)
00150 {
00151 case valid_addr4:
00152 break;
00153
00154 case valid_seq_ctl:
00155 case valid_addr3:
00156 addrs_ += db_null;
00157 break;
00158
00159 case valid_addr2:
00160 nulls << db_null << '\t' << db_null;
00161 break;
00162
00163 case valid_addr1:
00164 nulls << db_null << '\t' << db_null << '\t' << db_null;
00165 break;
00166
00167 case valid_control:
00168 case invalid:
00169 nulls << db_null << '\t' << db_null << '\t'
00170 << db_null << '\t' << db_null;
00171 break;
00172 }
00173 addrs_ += nulls.str();
00174 }
00175
00176
00177
00178
00179
00180 inline
00181 std::string
00182 importer::frames_data_filename(const std::string& prefix, unsigned channel)
00183 {
00184 assert(0 < channel);
00185 assert(channel <= channels_max);
00186
00187 return prefix + "_c" + boost::lexical_cast<std::string> (channel);
00188 }
00189
00190 inline
00191 std::string
00192 importer::mapping_filename(const std::string& prefix, unsigned channel)
00193 {
00194 assert(0 < channel);
00195 assert(channel <= channels_max);
00196
00197 return frames_data_filename(prefix, channel) + "_MACIndex";
00198 }
00199
00200 inline
00201 std::string
00202 importer::handle_time_data(const wpl::pkt::metadata& h)
00203 {
00204 using namespace boost::gregorian;
00205 using namespace boost::posix_time;
00206
00207 std::ostringstream time_string;
00208 const ptime toa (date(1970, Jan, 01),
00209 seconds (h.ts.tv_sec) +
00210 microseconds (h.ts.tv_usec));
00211
00212 time_string << h.ts.tv_sec
00213 << '.'
00214 << std::setw (6) << std::setfill('0') << h.ts.tv_usec
00215 << '\t';
00216
00217 if (last_frame_.is_not_a_date_time())
00218 time_string << db_null;
00219 else
00220 time_string << (toa - last_frame_).total_microseconds();
00221
00222 last_frame_ = toa;
00223
00224 return time_string.str();
00225 }
00226
00227 inline
00228 void
00229 importer::handle_malformed_prism()
00230 {
00231 wpl::tool::datafile& f = frames_data_[last_channel_ - 1];
00232
00233 for (unsigned i = 0; i < 25; ++i)
00234 f << db_null << '\t';
00235 f << boost::lexical_cast<std::string> (malformed_prism)
00236 << '\t' << db_null << '\t' << db_null << '\n';
00237
00238 }
00239
00240 inline
00241 const wpl::prism::header*
00242 importer::handle_prism_header(const std::string& time_string,
00243 const void* p,
00244 size_t caplen)
00245 {
00246 typedef wpl::prism::header header;
00247
00248 bool truncated_frame = false;
00249 const header* const prism = static_cast<const header*> (p);
00250
00251 if (caplen < sizeof (wpl::prism::header))
00252 {
00253 truncated_frame = true;
00254 std::cerr << "WARNING: Truncated Prism header. Unknown channel, ";
00255 if (not last_channel_)
00256 {
00257 last_channel_ = 1;
00258 std::cerr << "using default value of 1.";
00259 }
00260 else
00261 std::cerr << "using last value of " << last_channel_ << '.';
00262 std::cerr << std::endl;
00263 }
00264 else
00265 last_channel_ = prism->channel.get(false);
00266 assert(last_channel_ > 0);
00267 assert(last_channel_ <= channels_max);
00268
00269 wpl::tool::datafile& f = frames_data_[last_channel_ - 1];
00270
00271 f << ++last_id_[last_channel_ - 1] << '\t'
00272 << time_string << '\t';
00273
00274
00275 if (truncated_frame)
00276 {
00277 handle_malformed_prism();
00278 return 0;
00279 }
00280
00281
00282 f << prism->channel.get(false) << '\t'
00283 << prism->hosttime.get(false) << '\t'
00284 << prism->mactime.get(false) << '\t'
00285 << (prism->rate.get(false) / 2.) << '\t'
00286 << int16_t (prism->signal.get(false)) << '\t'
00287 << prism->frmlen.get(false) << '\t';
00288
00289 return prism;
00290 }
00291
00292 template <class T>
00293 void
00294 importer::operator () (const wpl::pkt::packet<T>& d)
00295 {
00296 const wpl::pkt::metadata& h = d.meta();
00297 const void* const p = d.bytes();
00298 const std::string tstr = handle_time_data(h);
00299 const wpl::prism::header* const prism = handle_prism_header(tstr, p,
00300 h.caplen);
00301
00302 if (not prism)
00303 return;
00304
00305 wpl::tool::datafile& f = frames_data_[last_channel_ - 1];
00306
00307
00308
00309
00310
00311
00312
00313 if (const unsigned noise = prism->noise.get(false))
00314 {
00315 for (unsigned i = 0; i < 19; ++i)
00316 f << db_null << '\t';
00317 f << driver_reported << '\t'
00318 << noise << '\t';
00319
00320
00321
00322
00323
00324 if (noise & 8)
00325 f << prism->rssi.get(false) << '\n';
00326 else
00327 f << db_null << '\n';
00328 }
00329
00330
00331
00332
00333
00334 else
00335 {
00336 using namespace wpl::wifi;
00337
00338 const void* const frame = static_cast<const void*> (prism + 1);
00339 const size_t caplen = h.caplen - sizeof (*prism);
00340 wpl::wifi::addr_mapping& map = mappings_[last_channel_ - 1];
00341 const dissector<hooks> dctor (frame, caplen, map);
00342 const unsigned type = type_of(frame);
00343 const unsigned subtype = subtype_of(frame);
00344
00345 f << dctor.addrs() << '\t'
00346
00347
00348
00349 << from_ds(frame) << '\t'
00350 << to_ds(frame) << '\t'
00351 << duration_of(frame) << '\t'
00352 << dctor.fragnum() << '\t'
00353 << control_flag(5, frame) << '\t'
00354 << control_flag(2, frame) << '\t'
00355 << control_flag(7, frame) << '\t'
00356 << protocol_version_of(frame) << '\t'
00357 << control_flag(4, frame) << '\t'
00358 << control_flag(3, frame) << '\t'
00359 << dctor.seqnum() << '\t'
00360 << ((type << 4) | subtype) << '\t'
00361 << type << '\t'
00362 << control_flag(6, frame) << '\t'
00363 << dctor.beacon_timestamp() << '\t'
00364 << dctor.error() << '\t'
00365 << db_null << '\t'
00366 << db_null << '\n';
00367 }
00368 }
00369
00370 }
00371
00372 #endif // ! WIT_IMPORTER_HXX_