232 lines
6.3 KiB
C++
232 lines
6.3 KiB
C++
#include <algorithm>
|
|
#include <csignal>
|
|
#include <cstdint>
|
|
#include <cstdlib>
|
|
#include <exception>
|
|
#include <filesystem>
|
|
#include <iostream>
|
|
#include <memory>
|
|
#include <stdexcept>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
#include <boost/program_options.hpp>
|
|
#include <boost/program_options/options_description.hpp>
|
|
#include <boost/program_options/parsers.hpp>
|
|
#include <boost/program_options/value_semantic.hpp>
|
|
#include <boost/program_options/variables_map.hpp>
|
|
|
|
#include "netvuconfig.h"
|
|
|
|
#ifdef USE_SCANNER
|
|
# include "Scanner.h"
|
|
#endif
|
|
|
|
#ifdef USE_ANALYZER
|
|
# include "Analyzer.h"
|
|
#endif
|
|
|
|
#ifdef USE_SERVER
|
|
# include "Server.h"
|
|
#endif
|
|
|
|
std::string launchMode;
|
|
void signalHandler(int signal);
|
|
|
|
int main(int argc, char **argv) {
|
|
|
|
namespace po = boost::program_options;
|
|
namespace fs = std::filesystem;
|
|
|
|
po::options_description desc("Allowed options");
|
|
desc.add_options()
|
|
(
|
|
"help,h",
|
|
"print usage information and exit"
|
|
)
|
|
(
|
|
"config,c",
|
|
po::value<std::string>()->default_value("netvu.conf")->required(),
|
|
"alternative config file"
|
|
);
|
|
|
|
po::options_description config("Configuration");
|
|
config.add_options()
|
|
(
|
|
"mode,m",
|
|
po::value<std::string>(),
|
|
"runtime mode - scanner/analyzer/server"
|
|
);
|
|
|
|
|
|
po::options_description scannerConfig("Scanner");
|
|
scannerConfig.add_options()
|
|
(
|
|
"scanner.interface,i",
|
|
po::value<std::string>(),
|
|
"wireless interface"
|
|
)
|
|
(
|
|
"scanner.channels,C",
|
|
po::value< std::vector<std::string> >()->composing()->multitoken(),
|
|
"space separated 802.11 channels numbers"
|
|
)
|
|
(
|
|
"scanner.max_packets,M",
|
|
po::value< std::string >()->default_value("0"),
|
|
"packet capture limit"
|
|
)
|
|
(
|
|
"scanner.log_dir,l",
|
|
po::value<std::string>()->default_value("log")->required(),
|
|
"where to save captured packets"
|
|
)
|
|
(
|
|
"scanner.channel_hop_interval,I",
|
|
po::value<std::string>()->default_value("300")->required(),
|
|
"channel hop interval in milliseconds"
|
|
);
|
|
config.add(scannerConfig);
|
|
|
|
po::options_description analyzerConfig("Analyzer");
|
|
analyzerConfig.add_options()
|
|
(
|
|
"analyzer.log_dir,L",
|
|
po::value<std::string>()->default_value("log"),
|
|
"where captured packets are stored"
|
|
)
|
|
(
|
|
"analyzer.database_dir,D",
|
|
po::value<std::string>()->default_value("db"),
|
|
"where to save analisys result"
|
|
);
|
|
config.add(analyzerConfig);
|
|
|
|
po::options_description serverConfig("Server");
|
|
serverConfig.add_options()
|
|
(
|
|
"server.address,a",
|
|
po::value<std::string>()->default_value("0.0.0.0"),
|
|
"listening address"
|
|
)
|
|
(
|
|
"server.port,p",
|
|
po::value<std::string>()->default_value("9000"),
|
|
"listening port"
|
|
)
|
|
(
|
|
"server.database_dir,d",
|
|
po::value<std::string>()->default_value("db"),
|
|
"where analisys result is stored"
|
|
)
|
|
(
|
|
"server.cors,o",
|
|
po::value<std::string>()->default_value("*"),
|
|
"access control allow origin"
|
|
);
|
|
config.add(serverConfig);
|
|
|
|
desc.add(config);
|
|
|
|
try {
|
|
po::variables_map vm;
|
|
po::store(po::parse_command_line(argc, argv, desc), vm);
|
|
|
|
if (fs::exists(vm["config"].as<std::string>())) {
|
|
po::store(
|
|
po::parse_config_file(vm["config"].as<std::string>().data(), config),
|
|
vm
|
|
);
|
|
}
|
|
|
|
po::notify(vm);
|
|
|
|
if (vm.count("help")) {
|
|
std::cout << desc << "\n";
|
|
return EXIT_SUCCESS;
|
|
}
|
|
|
|
std::signal(SIGINT, signalHandler);
|
|
|
|
if (!vm.count("mode")) {
|
|
std::cout << desc << "\n";
|
|
return EXIT_SUCCESS;
|
|
}
|
|
|
|
auto mode = vm["mode"].as<std::string>();
|
|
|
|
if (mode == "scanner") {
|
|
#ifdef USE_SCANNER
|
|
std::cout << "Starting scanner\n";
|
|
launchMode = "scanner";
|
|
|
|
std::string interface;
|
|
if (vm.count("scanner.interface")) {
|
|
interface = vm["scanner.interface"].as<std::string>();
|
|
}
|
|
|
|
std::vector<std::string> channels;
|
|
if (vm.count("scanner.channels")) {
|
|
channels = vm["scanner.channels"].as<std::vector<std::string>>();
|
|
}
|
|
|
|
auto maxPackets = vm["scanner.max_packets"].as<std::string>();
|
|
auto logDir = vm["scanner.log_dir"].as<std::string>();
|
|
auto channelHopInterval = vm["scanner.channel_hop_interval"].as<std::string>();
|
|
|
|
auto wifiScanner = Scanner::WifiScanner(
|
|
interface,
|
|
channels,
|
|
maxPackets,
|
|
logDir,
|
|
channelHopInterval
|
|
);
|
|
wifiScanner.start();
|
|
#else
|
|
throw std::runtime_error("Netvu was compiled without Scanner support");
|
|
#endif
|
|
} else if (mode == "analyzer") {
|
|
#ifdef USE_ANALYZER
|
|
std::cout << "Starting analyzer\n";
|
|
launchMode = "analyzer";
|
|
|
|
auto logDir = vm["analyzer.log_dir"].as<std::string>();
|
|
auto databaseDir = vm["analyzer.database_dir"].as<std::string>();
|
|
|
|
auto pcapAnalyzer = Analyzer::PCAPAnalyzer(logDir, databaseDir);
|
|
pcapAnalyzer.start();
|
|
#else
|
|
throw std::runtime_error("Netvu was compiled without Analyzer support");
|
|
#endif
|
|
} else if (mode == "server") {
|
|
#ifdef USE_SERVER
|
|
std::cout << "Starting server\n";
|
|
launchMode = "server";
|
|
|
|
auto address = vm["server.address"].as<std::string>();
|
|
auto port = vm["server.port"].as<std::string>();
|
|
auto databaseDir = vm["server.database_dir"].as<std::string>();
|
|
auto cors = vm["server.cors"].as<std::string>();
|
|
|
|
auto httpServer = Server::HttpServer(databaseDir, address, port, cors);
|
|
httpServer.start();
|
|
#else
|
|
throw std::runtime_error("Netvu was compiled without Server support");
|
|
#endif
|
|
} else {
|
|
std::cerr << "Invalid runtime mode specified\n";
|
|
return EXIT_FAILURE;
|
|
}
|
|
|
|
} catch (const std::exception& ex) {
|
|
std::cerr << ex.what() << std::endl;
|
|
return EXIT_FAILURE;
|
|
}
|
|
}
|
|
|
|
void signalHandler(int signal) {
|
|
std::cout << "Stopping " + launchMode << '\n';
|
|
std::exit(2);
|
|
}
|
|
|