diff options
| author | srdusr <[email protected]> | 2024-05-21 22:24:00 +0200 |
|---|---|---|
| committer | srdusr <[email protected]> | 2024-05-21 22:24:00 +0200 |
| commit | fbedc55d5aa861c381701c9f913b34ee7ab57ec4 (patch) | |
| tree | d34c3648b61d417f2a5d8690e0eb4a76bd64c943 /src/main.cpp | |
| parent | e0f4c701028aa81026a17cf9ebfb36112184f4bc (diff) | |
| download | packeteer-fbedc55d5aa861c381701c9f913b34ee7ab57ec4.tar.gz packeteer-fbedc55d5aa861c381701c9f913b34ee7ab57ec4.zip | |
Add GUI parity for -c/-a, mDNS/SSH dissectors, and two new fuzz harnesses
GUI parity: checksum_status()/reassembled_http_status() moved out of
main.cpp into a shared wireframe/packet_diagnostics.hpp so the GUI can
show the same -c/-a diagnostics for the selected packet without
duplicating the Ethernet/IPv4/TCP walk. Visually verified under Xvfb
with the same split-segment scenario used to verify -a on the CLI.
Two new L7 dissectors: mDNS (reuses parse_dns outright - RFC 6762
keeps DNS's wire format, just a different port) and SSH's cleartext
identification banner. Live-verified against this machine's real
sshd and a real DNS-wire-format packet sent to port 5353.
Two new fuzz harnesses (fuzz_checksum, fuzz_tcp_reassembly) covering
code added here that the original nine harnesses never
touched. All 12 run clean across ~90M executions with no crashes.
NAMES.md and PLAN.md updated with this round's decisions and naming
candidates.
Diffstat (limited to 'src/main.cpp')
| -rw-r--r-- | src/main.cpp | 105 |
1 files changed, 8 insertions, 97 deletions
diff --git a/src/main.cpp b/src/main.cpp index 31fca73..72dd267 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -48,12 +48,8 @@ #include <ftxui/dom/elements.hpp> #include "wireframe/capture_session.hpp" -#include "wireframe/l7/http.hpp" -#include "wireframe/net/checksum.hpp" -#include "wireframe/net/ethernet.hpp" -#include "wireframe/net/ipv4.hpp" -#include "wireframe/net/tcp.hpp" #include "wireframe/net/tcp_reassembly.hpp" +#include "wireframe/packet_diagnostics.hpp" #include "wireframe/search.hpp" #include "wireframe/summarize.hpp" @@ -72,95 +68,6 @@ void hex_dump(std::span<const unsigned char> bytes) { std::printf("\n"); } -// -c only: checksum validation isn't part of summarize_packet()'s -// shared output (see wireframe/net/checksum.hpp for why - checksum -// offload makes it noise, not signal, on most of the interfaces this -// project has actually been tested against). IPv4 only for now; this -// does its own minimal walk down to the IP/TCP/UDP byte spans the -// checksum functions need, reusing the existing decoders rather than -// duplicating their parsing logic. -std::string checksum_status(std::span<const unsigned char> bytes, int datalink) { - std::span<const unsigned char> ip_bytes; - if (datalink == DLT_RAW) { - ip_bytes = bytes; - } else { - auto eth = wireframe::net::parse_ethernet(bytes); - if (!eth || eth->header.ethertype != wireframe::net::kEthertypeIPv4) return ""; - ip_bytes = eth->payload; - } - if (ip_bytes.empty() || (ip_bytes[0] >> 4) != 4) return ""; // only IPv4 checksums, for now - - auto ip = wireframe::net::parse_ipv4(ip_bytes); - if (!ip) return ""; - - std::size_t header_len = static_cast<std::size_t>(ip->header.ihl) * 4; - std::string out = " checksums: IP="; - out += wireframe::net::verify_ipv4_checksum(ip_bytes.first(header_len)) ? "ok" : "BAD"; - - using wireframe::net::ChecksumResult; - if (ip->header.protocol == wireframe::net::kProtoTcp) { - auto result = - wireframe::net::verify_tcp_checksum_ipv4(ip->header.src, ip->header.dst, ip->payload); - out += result == ChecksumResult::kValid ? " TCP=ok" : " TCP=BAD"; - } else if (ip->header.protocol == wireframe::net::kProtoUdp) { - auto result = - wireframe::net::verify_udp_checksum_ipv4(ip->header.src, ip->header.dst, ip->payload); - out += result == ChecksumResult::kValid ? " UDP=ok" - : result == ChecksumResult::kNotPresent ? " UDP=none" - : " UDP=BAD"; - } - return out; -} - -// -a only: TCP stream reassembly (wireframe/net/tcp_reassembly.hpp), -// re-run through the same HTTP dissector summarize_packet() already -// uses for a single segment - reassembly only helps when a message is -// actually split across packets, and HTTP is the L7 dissector in this -// project that's structured around lines/headers rather than one fixed -// datagram (DNS/TLS ClientHello are each their own single UDP datagram -// or first TCP segment already). Printed as its own line rather than -// folded into the per-packet summary: it reflects accumulated flow -// state, not just this one packet. In-order-only reassembly (see the -// header's own comment) means this can legitimately fire again on a -// later packet of the same request with an unchanged result once the -// headers are already complete - an honest simplification, not -// deduplicated further. -std::optional<std::string> reassembled_http_status(std::span<const unsigned char> bytes, - int datalink, - wireframe::net::TcpReassembler& reassembler) { - std::span<const unsigned char> ip_bytes; - if (datalink == DLT_RAW) { - ip_bytes = bytes; - } else { - auto eth = wireframe::net::parse_ethernet(bytes); - if (!eth || eth->header.ethertype != wireframe::net::kEthertypeIPv4) return std::nullopt; - ip_bytes = eth->payload; - } - if (ip_bytes.empty() || (ip_bytes[0] >> 4) != 4) return std::nullopt; // IPv4 only, for now - - auto ip = wireframe::net::parse_ipv4(ip_bytes); - if (!ip || ip->header.protocol != wireframe::net::kProtoTcp) return std::nullopt; - - auto tcp = wireframe::net::parse_tcp(ip->payload); - if (!tcp) return std::nullopt; - - auto reassembled = reassembler.process_segment(ip->header.src, tcp->header.src_port, - ip->header.dst, tcp->header.dst_port, - tcp->header.seq, tcp->header.flags, - tcp->payload); - if (!reassembled) return std::nullopt; - - auto http = wireframe::net::parse_http(*reassembled); - if (!http) return std::nullopt; - - std::string out = " [reassembled "; - out += http->is_request ? "request] " : "response] "; - out += http->method_or_version + " " + http->target_or_status; - if (http->host) out += " Host: " + *http->host; - out += " (" + std::to_string(reassembled->size()) + " bytes so far)"; - return out; -} - struct RenderOptions { bool verbose_hex; bool verbose_checksums; @@ -185,11 +92,15 @@ void render_packet(const wireframe::CapturedPacket& packet, const RenderOptions& if (!wireframe::matches_search(line, opts.search_term)) return; - if (opts.verbose_checksums) line += checksum_status(bytes, opts.datalink); + if (opts.verbose_checksums) { + std::string status = wireframe::checksum_status(bytes, opts.datalink); + if (!status.empty()) line += " " + status; + } std::printf("%s\n", line.c_str()); if (opts.reassembler) { - if (auto status = reassembled_http_status(bytes, opts.datalink, *opts.reassembler)) { - std::printf("%s\n", status->c_str()); + if (auto status = wireframe::reassembled_http_status(bytes, opts.datalink, + *opts.reassembler)) { + std::printf(" [%s]\n", status->c_str()); } } if (opts.verbose_hex) hex_dump(bytes); |