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 <trace-tools/prism_header.hh>
00034 # include <trace-tools/wifi/timestamp.hh>
00035 # include <trace-tools/wifi/frame/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(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 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 wifi::frame::mgt::header* h,
00128 size_t caplen)
00129 {
00130 if (caplen < sizeof (*h) + sizeof (wifi::timestamp))
00131 {
00132 truncated_frame_hook(h, caplen,
00133 wifi::frame::dissector_status::valid_addr3);
00134 return;
00135 }
00136
00137 std::ostringstream output;
00138 output << *reinterpret_cast<const 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 wifi::frame::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 pcapxx::pkthdr* 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 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 prism::header*
00242 importer::handle_prism_header(const std::string& time_string,
00243 const void* p,
00244 size_t caplen)
00245 {
00246 typedef prism::header header;
00247
00248 bool truncated_frame = false;
00249 const header* const prism = static_cast<const header*> (p);
00250
00251 if (caplen < sizeof (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.data;
00266 assert(last_channel_ > 0);
00267 assert(last_channel_ <= channels_max);
00268
00269 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 f << prism->channel.data << '\t'
00282 << prism->hosttime.data << '\t'
00283 << prism->mactime.data << '\t'
00284 << (prism->rate.data / 2.) << '\t'
00285 << int16_t (prism->signal.data) << '\t'
00286 << prism->frmlen.data << '\t';
00287
00288 return prism;
00289 }
00290
00291 inline
00292 void
00293 importer::got_frame(const pcapxx::pkthdr* h, const void* p)
00294 {
00295 const std::string tstr = handle_time_data(h);
00296 const prism::header* const prism = handle_prism_header(tstr, p,
00297 h->caplen);
00298
00299 if (not prism)
00300 return;
00301
00302 tool::datafile& f = frames_data_[last_channel_ - 1];
00303
00304
00305
00306
00307
00308 if (const unsigned noise = prism->noise.data)
00309 {
00310 for (unsigned i = 0; i < 19; ++i)
00311 f << db_null << '\t';
00312 f << driver_reported << '\t'
00313 << noise << '\t';
00314
00315
00316
00317
00318
00319 if (noise & 8)
00320 f << prism->rssi.data << '\n';
00321 else
00322 f << db_null << '\n';
00323 }
00324
00325
00326
00327
00328
00329 else
00330 {
00331 using namespace wifi::frame;
00332
00333 const void* const frame = static_cast<const void*> (prism + 1);
00334 const size_t caplen = h->caplen - sizeof (*prism);
00335 wifi::addr_mapping& map = mappings_[last_channel_ - 1];
00336 const dissector<hooks> dctor (frame, caplen, map);
00337 const unsigned type = type_of(frame);
00338 const unsigned subtype = subtype_of(frame);
00339
00340 f << dctor.addrs() << '\t'
00341
00342
00343
00344 << from_ds(frame) << '\t'
00345 << to_ds(frame) << '\t'
00346 << duration_of(frame) << '\t'
00347 << dctor.fragnum() << '\t'
00348 << control_flag(5, frame) << '\t'
00349 << control_flag(2, frame) << '\t'
00350 << control_flag(7, frame) << '\t'
00351 << protocol_version_of(frame) << '\t'
00352 << control_flag(4, frame) << '\t'
00353 << control_flag(3, frame) << '\t'
00354 << dctor.seqnum() << '\t'
00355 << ((type << 4) | subtype) << '\t'
00356 << type << '\t'
00357 << control_flag(6, frame) << '\t'
00358 << dctor.beacon_timestamp() << '\t'
00359 << dctor.error() << '\t'
00360 << db_null << '\t'
00361 << db_null << '\n';
00362 }
00363 }
00364
00365 }
00366
00367 #endif // ! WIT_IMPORTER_HXX_