00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifndef TOOL_OPTIONS_HXX_
00023 # define TOOL_OPTIONS_HXX_
00024
00025 # include <boost/algorithm/string/classification.hpp>
00026 # include <boost/algorithm/string/split.hpp>
00027 # include <boost/lexical_cast.hpp>
00028 # include <boost/preprocessor/seq/for_each.hpp>
00029 # include <boost/preprocessor/seq/for_each_i.hpp>
00030 # include <boost/preprocessor/tuple/elem.hpp>
00031 # include <boost/preprocessor/stringize.hpp>
00032
00033 # include <cassert>
00034 # include <stdexcept>
00035 # include <sstream>
00036 # include <unistd.h>
00037
00038 # include "options.hh"
00039
00040 #ifdef HAVE_OPENSSL
00041 # include <wipal/wifi/frame/unique_id/hash.hh>
00042 #endif // HAVE_OPENSSL
00043 #include <wipal/wifi/frame/unique_id/timestamp.hh>
00044 #include <wipal/wifi/frame/unique_id/addr_timestamp.hh>
00045 #include <wipal/wifi/frame/unique_id/source_bssid_timestamp.hh>
00046 #include <wipal/wifi/frame/unique_id/seqctl_timestamp.hh>
00047 #include <wipal/wifi/frame/unique_id/seqctl_bssid_timestamp.hh>
00048 #include <wipal/wifi/frame/unique_id/seqctl_dest_bssid_timestamp.hh>
00049 #include <wipal/wifi/frame/unique_id/seqctl_source_bssid_timestamp.hh>
00050
00051 namespace tool
00052 {
00053
00054 namespace opt
00055 {
00056
00057 namespace internals
00058 {
00059
00060 inline
00061 void
00062 usage(const std::string& progname,
00063 const std::string& available_options,
00064 unsigned ninputs, unsigned noutputs)
00065 {
00066 std::cerr << "Invocation:\n\t" << progname << " [options]";
00067 switch (ninputs)
00068 {
00069 case 0: break;
00070 case 1: std::cerr << " <input>"; break;
00071 case 2: std::cerr << " <input-1> <input-2>"; break;
00072 default: std::cerr << " <inputs...>"; break;
00073 }
00074 switch (noutputs)
00075 {
00076 case 0: break;
00077 case 1: std::cerr << " <output>"; break;
00078 default: std::cerr << " <outputs...>"; break;
00079 }
00080 std::cerr << "\n\nOptions:\n";
00081
00082 # define WP_help_print_opt(R, Unused, Opt) \
00083 if (available_options.find(BOOST_PP_CAT(WP_OPT_, Opt)) < \
00084 available_options.size()) \
00085 std::cerr << BOOST_PP_CAT(WP_HELP_, Opt);
00086
00087 BOOST_PP_SEQ_FOR_EACH(WP_help_print_opt, ~, WP_OPT_LIST)
00088
00089 # undef WP_help_print
00090
00091 # define WP_help_attr_string(R, Unused, A) \
00092 " " BOOST_PP_STRINGIZE(A) ":\t" BOOST_PP_CAT(WP_ATTR_HELP_, A) "\n"
00093 # define WP_help_linktypes_string(R, Unused, LT) \
00094 " " BOOST_PP_STRINGIZE(BOOST_PP_TUPLE_ELEM(2, 0, LT)) "\n"
00095
00096 if (available_options.find(WP_OPT_ATTR) < available_options.size())
00097 std::cerr << "\nAvailable attributes:\n"
00098 BOOST_PP_SEQ_FOR_EACH(WP_help_attr_string, ~, WP_ATTRIBUTES);
00099 std::cerr << "\nSupported PCAP link types:\n"
00100 BOOST_PP_SEQ_FOR_EACH(WP_help_linktypes_string, ~, WP_LINKTYPES);
00101
00102 # undef WP_help_linktypes_string
00103 # undef WP_help_attr_string
00104 }
00105
00106 inline
00107 void
00108 version(const std::string& progname)
00109 {
00110 std::cerr << progname << "\n"
00111 "Trace Tools, version " << PACKAGE_VERSION << '.' << std::endl;
00112 }
00113
00114 inline
00115 std::pair<unsigned, unsigned>
00116 make_reference(const std::string& s)
00117 {
00118 static const std::string err = ("Invalid reference frame format. "
00119 "Format is ``<unsigned>-<unsigned>''");
00120
00121 std::vector<std::string> v;
00122
00123 boost::split(v, s, boost::is_any_of("-"));
00124 if (v.size() != 2)
00125 throw std::invalid_argument (err);
00126 try
00127 {
00128 return std::make_pair(boost::lexical_cast<unsigned> (v[0]),
00129 boost::lexical_cast<unsigned> (v[1]));
00130 }
00131 catch (const boost::bad_lexical_cast&)
00132 {
00133 throw std::invalid_argument (err);
00134 }
00135 }
00136
00137 }
00138
00139 inline
00140 options
00141 parse_args(int argc, char* const* argv,
00142 const std::string& available_options,
00143 int ninputs, int noutputs)
00144 {
00145 const std::string optstring =
00146 available_options + WP_OPT_HELP WP_OPT_VERSION_;
00147
00148 options r;
00149 int o;
00150
00151 r.mapping = WP_MAPPING_DEFAULT;
00152 r.attributes = BOOST_PP_STRINGIZE(WP_DEFAULT_ATTRIBUTE);
00153 r.endianness = endian::guess;
00154
00155 r.cmp = options::cmp_default;
00156 r.prism_noise_means_error = false;
00157 r.print_errors = false;
00158 r.print_frame_indices = true;
00159 r.print_column_headers = isatty(STDOUT_FILENO);
00160 r.print_microseconds = false;
00161 r.print_summary = true;
00162
00163 while ((o = getopt(argc, argv, optstring.c_str())) != -1)
00164 switch (o)
00165 {
00166 case '8':
00167 r.cmp = options::cmp_802;
00168 break;
00169
00170 case 'a':
00171 r.attributes = optarg;
00172 break;
00173
00174 case 'b':
00175 r.cmp = options::cmp_bytes;
00176 break;
00177
00178 case 'c':
00179 r.print_column_headers = false;
00180 break;
00181
00182 case 'C':
00183 r.print_column_headers = true;
00184 break;
00185
00186 case 'd':
00187 r.cmp = options::cmp_default;
00188 break;
00189
00190 case 'e':
00191 r.print_errors = false;
00192 break;
00193
00194 case 'E':
00195 r.print_errors = true;
00196 break;
00197
00198 case 'h':
00199 internals::usage(argv[0], optstring, ninputs, noutputs);
00200 exit(EXIT_SUCCESS);
00201 break;
00202
00203 case 'i':
00204 r.print_frame_indices = false;
00205 break;
00206
00207 case 'I':
00208 r.print_frame_indices = true;
00209 break;
00210
00211 case 'm':
00212 r.mapping = optarg;
00213 break;
00214
00215 case 'n':
00216 r.endianness = endian::little;
00217 break;
00218
00219 case 'N':
00220 r.endianness = endian::big;
00221 break;
00222
00223 case 'p':
00224 r.prism_noise_means_error = false;
00225 break;
00226
00227 case 'P':
00228 r.prism_noise_means_error = true;
00229 break;
00230
00231 case 'q':
00232 r.print_errors = false;
00233 r.print_frame_indices = false;
00234 r.print_column_headers = false;
00235 r.print_microseconds = false;
00236 r.print_summary = false;
00237 break;
00238
00239 case 'r':
00240 try
00241 {
00242 r.ref_blacklist.insert(internals::make_reference(optarg));
00243 }
00244 catch (const std::invalid_argument& i)
00245 {
00246 std::cerr << "ERROR: " << i.what() << '.' << std::endl;
00247 exit(EXIT_FAILURE);
00248 }
00249 break;
00250
00251 case 't':
00252 r.cmp = options::cmp_time;
00253 break;
00254
00255 case 'u':
00256 r.print_microseconds = false;
00257 break;
00258
00259 case 'U':
00260 r.print_microseconds = true;
00261 break;
00262
00263 case 'v':
00264 internals::version(argv[0]);
00265 exit(EXIT_SUCCESS);
00266
00267 default:
00268 internals::usage(argv[0], optstring, ninputs, noutputs);
00269 exit(EXIT_FAILURE);
00270 }
00271
00272 assert(ninputs != options::arbitrary_number_of_inputs or
00273 noutputs != options::arbitrary_number_of_outputs);
00274
00275 if (ninputs == options::arbitrary_number_of_inputs)
00276 ninputs = argc - optind - noutputs;
00277 if (noutputs == options::arbitrary_number_of_outputs)
00278 noutputs = argc - optind - ninputs;
00279 if (ninputs < 0 or noutputs < 0 or optind + ninputs + noutputs != argc)
00280 {
00281 std::cerr << "ERROR: Wrong number of arguments." << std::endl;
00282 internals::usage(argv[0], optstring, ninputs, noutputs);
00283 exit(EXIT_FAILURE);
00284 }
00285 for (int i = 0; i < ninputs; ++i)
00286 r.input.push_back(argv[optind + i]);
00287 for (int i = 0; i < noutputs; ++i)
00288 r.output.push_back(argv[optind + ninputs + i]);
00289
00290 return r;
00291 }
00292
00293 template <class Fun>
00294 int
00295 dispatch_unique_id(const options& o, Fun f)
00296 {
00297 if (false)
00298 ;
00299 # define WP_dispatch_unique_id_else(R, Unused, A) \
00300 else if (o.attributes == BOOST_PP_STRINGIZE(A)) \
00301 return f.template operator () <wifi::frame::BOOST_PP_CAT(A, _id)>(o);
00302
00303 BOOST_PP_SEQ_FOR_EACH(WP_dispatch_unique_id_else, ~, WP_ATTRIBUTES)
00304
00305 # undef WP_dispatch_unique_id_else
00306
00307 throw std::invalid_argument ("Invalid distinctive attributes");
00308 }
00309
00310 inline
00311 void
00312 unsupported_linktype(const pcapxx::descriptor<>::link_type lt)
00313 {
00314 std::ostringstream os;
00315
00316 # define WP_linktype_string(R, Unused, I, LT) \
00317 BOOST_PP_IF(I, ", ", "") \
00318 BOOST_PP_STRINGIZE(BOOST_PP_TUPLE_ELEM(2, 0, LT))
00319
00320 os << "Unsupported PCAP link type: " << lt << " - expected one of ["
00321 BOOST_PP_SEQ_FOR_EACH_I(WP_linktype_string, ~, WP_LINKTYPES) "]";
00322
00323 # undef WP_linktype_string
00324
00325 throw std::invalid_argument (os.str());
00326 }
00327
00328 }
00329
00330 }
00331
00332 #endif // TOOL_OPTIONS_HXX_