Compare commits
12 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 7af9a49eef | |||
| 4f325fead2 | |||
| 5ac2995b2d | |||
| 8016d570b8 | |||
| 526b27deaf | |||
| 7c19123da9 | |||
| c9e1b0a149 | |||
| 0d96c21199 | |||
| 679d752177 | |||
| 9f88390b1a | |||
| a4c84379ff | |||
| 827cc07175 |
@@ -2,3 +2,4 @@
|
|||||||
.xmake
|
.xmake
|
||||||
build
|
build
|
||||||
compile_commands.json
|
compile_commands.json
|
||||||
|
ignore
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
#include "packet_sniffer_cli.hpp"
|
||||||
|
#include <boost/program_options/value_semantic.hpp>
|
||||||
|
|
||||||
|
PacketSnifferCli::PacketSnifferCli()
|
||||||
|
: CliBase("Packet Sniffer Options")
|
||||||
|
, ip_("")
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void PacketSnifferCli::setupOptions()
|
||||||
|
{
|
||||||
|
// clang-format off
|
||||||
|
desc_.add_options()
|
||||||
|
("help,h", "Show help")
|
||||||
|
("ip,H", withDefault(ip_, "<IP>"), "Local IPv4 to sniff (e.g. 192.168.1.42)")
|
||||||
|
("mask,m", boost::program_options::value<bool>()->default_value(false)->implicit_value(true),
|
||||||
|
"Mask IP addresses in output (demo)");
|
||||||
|
// clang-format on
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string PacketSnifferCli::getIp() const
|
||||||
|
{
|
||||||
|
return vm_.at("ip").as<std::string>();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PacketSnifferCli::isMaskEnabled() const
|
||||||
|
{
|
||||||
|
const auto it = vm_.find("mask");
|
||||||
|
return (it != vm_.end()) ? it->second.as<bool>() : false;
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "cli_base.hpp"
|
||||||
|
#include "option_utils.hpp"
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
class PacketSnifferCli : public CliBase, protected OptionUtils
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PacketSnifferCli();
|
||||||
|
|
||||||
|
std::string getIp() const;
|
||||||
|
bool isMaskEnabled() const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void setupOptions() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string ip_;
|
||||||
|
};
|
||||||
@@ -1,27 +1,29 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <boost/asio.hpp>
|
#include <boost/asio.hpp>
|
||||||
|
#include <boost/asio/ip/address.hpp>
|
||||||
#include <boost/program_options.hpp>
|
#include <boost/program_options.hpp>
|
||||||
#include <boost/system/error_code.hpp>
|
#include <boost/system/error_code.hpp>
|
||||||
|
|
||||||
// --- Error handling ---
|
// --- Error handling ---
|
||||||
using ErrorCode = boost::system::error_code;
|
using ErrorCode = boost::system::error_code;
|
||||||
|
|
||||||
// --- IO Context ---
|
// --- Asio types ---
|
||||||
using IoContext = boost::asio::io_context;
|
using IoContext = boost::asio::io_context;
|
||||||
|
using SteadyTimer = boost::asio::steady_timer;
|
||||||
|
|
||||||
// --- TCP ---
|
// --- Ip types ---
|
||||||
|
using IpAddress = boost::asio::ip::address;
|
||||||
|
|
||||||
|
// --- TCP types ---
|
||||||
using TcpSocket = boost::asio::ip::tcp::socket;
|
using TcpSocket = boost::asio::ip::tcp::socket;
|
||||||
using TcpAcceptor = boost::asio::ip::tcp::acceptor;
|
using TcpAcceptor = boost::asio::ip::tcp::acceptor;
|
||||||
using TcpEndpoint = boost::asio::ip::tcp::endpoint;
|
using TcpEndpoint = boost::asio::ip::tcp::endpoint;
|
||||||
|
|
||||||
// --- UDP (для DNS) ---
|
// --- UDP types ---
|
||||||
using UdpSocket = boost::asio::ip::udp::socket;
|
using UdpSocket = boost::asio::ip::udp::socket;
|
||||||
using UdpEndpoint = boost::asio::ip::udp::endpoint;
|
using UdpEndpoint = boost::asio::ip::udp::endpoint;
|
||||||
|
|
||||||
// --- Таймеры ---
|
|
||||||
using SteadyTimer = boost::asio::steady_timer;
|
|
||||||
|
|
||||||
// --- Program options ---
|
// --- Program options ---
|
||||||
using OptionsDescription = boost::program_options::options_description;
|
using OptionsDescription = boost::program_options::options_description;
|
||||||
using VariablesMap = boost::program_options::variables_map;
|
using VariablesMap = boost::program_options::variables_map;
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
#include "logger.hpp"
|
#include "logger.hpp"
|
||||||
|
|
||||||
#include <boost/date_time/posix_time/posix_time_io.hpp>
|
#include <boost/date_time/posix_time/posix_time_io.hpp>
|
||||||
|
|
||||||
void Logger::init(bool toConsole, const std::string_view filePath)
|
void Logger::init(bool toConsole, const std::string_view filePath)
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <boost/program_options.hpp>
|
||||||
|
|
||||||
|
class OptionUtils
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
template <typename T>
|
||||||
|
using OptionValue = boost::program_options::typed_value<T> *;
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
static OptionValue<T>
|
||||||
|
withDefault(const T &value, const char *name = nullptr);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
OptionUtils() = default;
|
||||||
|
~OptionUtils() = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
#include "option_utils.tpp"
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "option_utils.hpp"
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
OptionUtils::OptionValue<T>
|
||||||
|
OptionUtils::withDefault(const T &value, const char *name)
|
||||||
|
{
|
||||||
|
auto v = boost::program_options::value<T>()->default_value(value);
|
||||||
|
if (name) {
|
||||||
|
v->value_name(name); // Optional
|
||||||
|
}
|
||||||
|
return v;
|
||||||
|
}
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
class Server
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
virtual ~Server() = default;
|
|
||||||
virtual void start() = 0;
|
|
||||||
virtual void stop() = 0;
|
|
||||||
};
|
|
||||||
@@ -1,70 +0,0 @@
|
|||||||
#include "session_base.hpp"
|
|
||||||
#include "logger.hpp"
|
|
||||||
#include <boost/asio/write.hpp>
|
|
||||||
|
|
||||||
SessionBase::SessionBase(TcpSocket socket)
|
|
||||||
: socket_(std::move(socket))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void SessionBase::start()
|
|
||||||
{
|
|
||||||
doRead();
|
|
||||||
}
|
|
||||||
|
|
||||||
void SessionBase::doRead()
|
|
||||||
{
|
|
||||||
using namespace boost::asio;
|
|
||||||
|
|
||||||
auto self = shared_from_this();
|
|
||||||
|
|
||||||
auto handler = [this, self](ErrorCode ec, std::size_t bytesTransferred) {
|
|
||||||
onRead(ec, bytesTransferred);
|
|
||||||
};
|
|
||||||
|
|
||||||
socket_.async_read_some(buffer(buffer_), handler);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SessionBase::onRead(ErrorCode ec, std::size_t bytesTransferred)
|
|
||||||
{
|
|
||||||
if (ec) {
|
|
||||||
Logger::error("Read error: " + ec.message());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string rawRequest(buffer_.data(), bytesTransferred);
|
|
||||||
Logger::info("Received request:\n" + rawRequest);
|
|
||||||
|
|
||||||
try {
|
|
||||||
handleRequest(rawRequest);
|
|
||||||
} catch (const std::exception &ex) {
|
|
||||||
Logger::error(std::string("Request handling failed: ") + ex.what());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SessionBase::doWrite(const std::string &response)
|
|
||||||
{
|
|
||||||
using namespace boost::asio;
|
|
||||||
|
|
||||||
auto self = shared_from_this();
|
|
||||||
auto onWriteHandler =
|
|
||||||
[this, self](ErrorCode ec, std::size_t /*bytesTransferred*/) {
|
|
||||||
if (ec) {
|
|
||||||
Logger::error("Write error: " + ec.message());
|
|
||||||
}
|
|
||||||
|
|
||||||
ErrorCode shutdownEc;
|
|
||||||
if (socket_.shutdown(TcpSocket::shutdown_both, shutdownEc)) {
|
|
||||||
Logger::warn("Shutdown error: " + shutdownEc.message());
|
|
||||||
}
|
|
||||||
|
|
||||||
ErrorCode closeEc;
|
|
||||||
if (socket_.close(closeEc)) {
|
|
||||||
Logger::warn("Close error: " + closeEc.message());
|
|
||||||
} else {
|
|
||||||
Logger::info("Connection closed");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
async_write(socket_, buffer(response), onWriteHandler);
|
|
||||||
}
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "aliases.hpp"
|
|
||||||
#include <array>
|
|
||||||
#include <memory>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
class SessionBase : public std::enable_shared_from_this<SessionBase>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
explicit SessionBase(TcpSocket socket);
|
|
||||||
virtual ~SessionBase() = default;
|
|
||||||
|
|
||||||
void start();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual void handleRequest(const std::string_view rawRequest) = 0;
|
|
||||||
|
|
||||||
void doRead();
|
|
||||||
void onRead(ErrorCode ec, std::size_t bytesTransferred);
|
|
||||||
void doWrite(const std::string &response);
|
|
||||||
|
|
||||||
TcpSocket socket_;
|
|
||||||
std::array<char, 8192> buffer_;
|
|
||||||
};
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
#include "tcp_server_base.hpp"
|
|
||||||
#include "logger.hpp"
|
|
||||||
|
|
||||||
TcpServerBase::TcpServerBase(IoContext &io, unsigned short port)
|
|
||||||
: acceptor_(io, TcpEndpoint(boost::asio::ip::tcp::v4(), port))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void TcpServerBase::start()
|
|
||||||
{
|
|
||||||
auto doAccept = [this]() {
|
|
||||||
acceptor_.async_accept([this](ErrorCode ec, TcpSocket socket) {
|
|
||||||
if (!ec) {
|
|
||||||
Logger::info("New client connected");
|
|
||||||
createSession(std::move(socket));
|
|
||||||
} else {
|
|
||||||
Logger::error("Accept error: " + ec.message());
|
|
||||||
}
|
|
||||||
start(); // continue accepting
|
|
||||||
});
|
|
||||||
};
|
|
||||||
doAccept();
|
|
||||||
}
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "aliases.hpp"
|
|
||||||
|
|
||||||
class TcpServerBase
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
TcpServerBase(IoContext &io, unsigned short port);
|
|
||||||
virtual ~TcpServerBase() = default;
|
|
||||||
|
|
||||||
void start();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual void createSession(TcpSocket socket) = 0;
|
|
||||||
|
|
||||||
TcpAcceptor acceptor_;
|
|
||||||
};
|
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
#include "udp_server_base.hpp"
|
|
||||||
#include "logger.hpp"
|
|
||||||
|
|
||||||
UdpServerBase::UdpServerBase(IoContext &io, unsigned short port)
|
|
||||||
: socket_(io, UdpEndpoint(boost::asio::ip::udp::v4(), port))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void UdpServerBase::start()
|
|
||||||
{
|
|
||||||
doReceive();
|
|
||||||
}
|
|
||||||
|
|
||||||
void UdpServerBase::doReceive()
|
|
||||||
{
|
|
||||||
using namespace boost::asio;
|
|
||||||
|
|
||||||
auto onReceive = [this](ErrorCode ec, std::size_t bytesReceived) {
|
|
||||||
if (!ec && bytesReceived > 0) {
|
|
||||||
std::string_view data(buffer_.data(), bytesReceived);
|
|
||||||
handleRequest(data, remoteEndpoint_);
|
|
||||||
} else if (ec) {
|
|
||||||
Logger::error("UDP receive error: " + ec.message());
|
|
||||||
}
|
|
||||||
doReceive(); // continue listening
|
|
||||||
};
|
|
||||||
|
|
||||||
socket_.async_receive_from(buffer(buffer_), remoteEndpoint_, onReceive);
|
|
||||||
}
|
|
||||||
|
|
||||||
void UdpServerBase::doSend(
|
|
||||||
const std::string &response, const UdpEndpoint &target
|
|
||||||
)
|
|
||||||
{
|
|
||||||
using namespace boost::asio;
|
|
||||||
|
|
||||||
auto bufferToSend = std::make_shared<std::string>(response);
|
|
||||||
|
|
||||||
auto onSend = [bufferToSend](ErrorCode ec, std::size_t /*bytesSent*/) {
|
|
||||||
if (ec) {
|
|
||||||
Logger::error("UDP send error: " + ec.message());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
socket_.async_send_to(buffer(*bufferToSend), target, onSend);
|
|
||||||
}
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "aliases.hpp"
|
|
||||||
|
|
||||||
class UdpServerBase
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
UdpServerBase(IoContext &io, unsigned short port);
|
|
||||||
virtual ~UdpServerBase() = default;
|
|
||||||
|
|
||||||
void start();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual void
|
|
||||||
handleRequest(const std::string_view data, const UdpEndpoint &sender) = 0;
|
|
||||||
|
|
||||||
void doReceive();
|
|
||||||
void doSend(const std::string &response, const UdpEndpoint &target);
|
|
||||||
|
|
||||||
UdpSocket socket_;
|
|
||||||
std::array<char, 4096> buffer_;
|
|
||||||
UdpEndpoint remoteEndpoint_;
|
|
||||||
};
|
|
||||||
@@ -0,0 +1,135 @@
|
|||||||
|
#include "sniffer.hpp"
|
||||||
|
#include "logger.hpp"
|
||||||
|
#include <tins/tins.h>
|
||||||
|
|
||||||
|
Sniffer::Sniffer(std::string localIp, bool maskIp)
|
||||||
|
: ip_(std::move(localIp))
|
||||||
|
, mask_(maskIp)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int Sniffer::run()
|
||||||
|
{
|
||||||
|
const auto ifaceName = resolveIfaceNameByIp(ip_);
|
||||||
|
|
||||||
|
Tins::SnifferConfiguration cfg;
|
||||||
|
cfg.set_promisc_mode(true);
|
||||||
|
cfg.set_immediate_mode(true);
|
||||||
|
|
||||||
|
Tins::Sniffer sniffer(ifaceName, cfg);
|
||||||
|
|
||||||
|
auto running = [this] { return !stop_.load(std::memory_order_relaxed); };
|
||||||
|
|
||||||
|
auto handler = [&](Tins::PDU &pdu) -> bool {
|
||||||
|
if (!running())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
std::string src, dst;
|
||||||
|
const char *type = "OTHER";
|
||||||
|
uint16_t sport = 0, dport = 0;
|
||||||
|
|
||||||
|
if (auto *arp = pdu.find_pdu<Tins::ARP>()) {
|
||||||
|
src = arp->sender_ip_addr().to_string();
|
||||||
|
dst = arp->target_ip_addr().to_string();
|
||||||
|
type = "ARP";
|
||||||
|
} else if (auto *ip4 = pdu.find_pdu<Tins::IP>()) {
|
||||||
|
src = ip4->src_addr().to_string();
|
||||||
|
dst = ip4->dst_addr().to_string();
|
||||||
|
|
||||||
|
if (auto *tcp = pdu.find_pdu<Tins::TCP>()) {
|
||||||
|
type = "TCP";
|
||||||
|
sport = tcp->sport();
|
||||||
|
dport = tcp->dport();
|
||||||
|
} else if (auto *udp = pdu.find_pdu<Tins::UDP>()) {
|
||||||
|
type = "UDP";
|
||||||
|
sport = udp->sport();
|
||||||
|
dport = udp->dport();
|
||||||
|
} else if (pdu.find_pdu<Tins::ICMP>()) {
|
||||||
|
type = "ICMP";
|
||||||
|
} else {
|
||||||
|
type = "IP";
|
||||||
|
}
|
||||||
|
} else if (auto *ip6 = pdu.find_pdu<Tins::IPv6>()) {
|
||||||
|
src = ip6->src_addr().to_string();
|
||||||
|
dst = ip6->dst_addr().to_string();
|
||||||
|
|
||||||
|
if (auto *tcp = pdu.find_pdu<Tins::TCP>()) {
|
||||||
|
type = "TCP";
|
||||||
|
sport = tcp->sport();
|
||||||
|
dport = tcp->dport();
|
||||||
|
} else if (auto *udp = pdu.find_pdu<Tins::UDP>()) {
|
||||||
|
type = "UDP";
|
||||||
|
sport = udp->sport();
|
||||||
|
dport = udp->dport();
|
||||||
|
} else if (pdu.find_pdu<Tins::ICMPv6>()) {
|
||||||
|
type = "ICMPv6";
|
||||||
|
} else {
|
||||||
|
type = "IPv6";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Logger::info("(unknown src) -> (unknown dst) [OTHER]");
|
||||||
|
return running();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mask_) {
|
||||||
|
src = hideHalf(src);
|
||||||
|
dst = hideHalf(dst);
|
||||||
|
}
|
||||||
|
|
||||||
|
printLine(src, dst, type, sport, dport);
|
||||||
|
return running();
|
||||||
|
};
|
||||||
|
|
||||||
|
sniffer.sniff_loop(handler);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Sniffer::stop()
|
||||||
|
{
|
||||||
|
stop_.store(true, std::memory_order_relaxed);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Sniffer::hideHalf(const std::string &s) const
|
||||||
|
{
|
||||||
|
if (s.empty()) {
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
const size_t n = s.size();
|
||||||
|
const size_t hide = n / 2;
|
||||||
|
const size_t keep = n - hide;
|
||||||
|
std::string out = s.substr(0, keep);
|
||||||
|
out.append(hide, '*');
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Sniffer::resolveIfaceNameByIp(const std::string &ip)
|
||||||
|
{
|
||||||
|
const Tins::IPv4Address want(ip);
|
||||||
|
for (const auto &iface : Tins::NetworkInterface::all()) {
|
||||||
|
const auto info = iface.addresses(); // .ip_addr/.netmask/...
|
||||||
|
if (info.ip_addr == want) {
|
||||||
|
return iface.name();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw std::runtime_error("Interface with IP " + ip + " not found");
|
||||||
|
}
|
||||||
|
|
||||||
|
void Sniffer::printLine(
|
||||||
|
const std::string &src,
|
||||||
|
const std::string &dst,
|
||||||
|
const char *type,
|
||||||
|
uint16_t sport,
|
||||||
|
uint16_t dport
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (sport || dport) {
|
||||||
|
Logger::info(
|
||||||
|
std::string(src) + ":" + std::to_string(sport) + " -> " + dst + ":"
|
||||||
|
+ std::to_string(dport) + " [" + type + "]"
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
Logger::info(std::string(src) + " -> " + dst + " [" + type + "]");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <atomic>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
class Sniffer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit Sniffer(std::string localIp, bool maskIp = false);
|
||||||
|
|
||||||
|
Sniffer(const Sniffer &) = delete;
|
||||||
|
Sniffer &operator=(const Sniffer &) = delete;
|
||||||
|
|
||||||
|
std::string hideHalf(const std::string &s) const;
|
||||||
|
|
||||||
|
int run();
|
||||||
|
void stop();
|
||||||
|
|
||||||
|
private:
|
||||||
|
static std::string resolveIfaceNameByIp(const std::string &ip);
|
||||||
|
static void printLine(
|
||||||
|
const std::string &src,
|
||||||
|
const std::string &dst,
|
||||||
|
const char *type,
|
||||||
|
uint16_t sport = 0,
|
||||||
|
uint16_t dport = 0
|
||||||
|
);
|
||||||
|
|
||||||
|
std::string ip_;
|
||||||
|
std::atomic<bool> stop_{false};
|
||||||
|
bool mask_{false};
|
||||||
|
};
|
||||||
+22
-12
@@ -1,16 +1,26 @@
|
|||||||
#include <boost/asio.hpp>
|
#include "logger.hpp"
|
||||||
#include <iostream>
|
#include "packet_sniffer_cli.hpp"
|
||||||
|
#include "sniffer.hpp"
|
||||||
|
#include <exception>
|
||||||
|
|
||||||
int main()
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
std::cout << "Hello, Boost + C++23 + xmake!\n";
|
Logger::init(true);
|
||||||
|
try {
|
||||||
|
PacketSnifferCli cli;
|
||||||
|
cli.parse(argc, argv);
|
||||||
|
if (cli.isHelp()) {
|
||||||
|
cli.printHelp();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
boost::asio::io_context io;
|
Sniffer sniffer(cli.getIp(), cli.isMaskEnabled());
|
||||||
boost::asio::steady_timer timer(io, std::chrono::seconds(1));
|
return sniffer.run();
|
||||||
timer.async_wait([](const boost::system::error_code &) {
|
} catch (const std::exception &ex) {
|
||||||
std::cout << "Timer fired after 1 second!\n";
|
Logger::fatal(ex.what());
|
||||||
});
|
return 1;
|
||||||
|
} catch (...) {
|
||||||
io.run();
|
Logger::fatal("unknown error");
|
||||||
return 0;
|
return 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,16 +2,20 @@ set_languages "c++23"
|
|||||||
|
|
||||||
add_rules("plugin.compile_commands.autoupdate", { outputdir = "." })
|
add_rules("plugin.compile_commands.autoupdate", { outputdir = "." })
|
||||||
|
|
||||||
add_requires("boost", {
|
add_requires("cmake::Boost", {
|
||||||
system = true, -- sudo pacman -S boost
|
alias = "boost",
|
||||||
|
system = true,
|
||||||
configs = {
|
configs = {
|
||||||
all = false,
|
components = { "program_options", "log" },
|
||||||
system = true, -- asio
|
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
target "app"
|
add_requires("cmake::libtins", { alias = "libtins", system = true })
|
||||||
set_kind "binary"
|
|
||||||
add_files "src/*.cpp"
|
target "packet_sniffer"
|
||||||
add_links "boost_system"
|
do
|
||||||
|
set_kind "binary"
|
||||||
|
add_files("src/main.cpp", "src/cli/*.cpp", "src/common/*.cpp", "src/core/*.cpp")
|
||||||
|
add_includedirs("src", "src/cli", "src/common", "src/core", { public = true })
|
||||||
|
add_packages("boost", "libtins")
|
||||||
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user