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/gui_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/gui_main.cpp')
| -rw-r--r-- | src/gui_main.cpp | 45 |
1 files changed, 41 insertions, 4 deletions
diff --git a/src/gui_main.cpp b/src/gui_main.cpp index 16ee769..8a7771a 100644 --- a/src/gui_main.cpp +++ b/src/gui_main.cpp @@ -23,6 +23,8 @@ #include <thread> #include "wireframe/capture_session.hpp" +#include "wireframe/net/tcp_reassembly.hpp" +#include "wireframe/packet_diagnostics.hpp" #include "wireframe/search.hpp" #include "wireframe/summarize.hpp" @@ -31,6 +33,11 @@ namespace { struct PacketRow { std::string summary; std::vector<unsigned char> data; + // -a only: computed once at consume time (reassembly needs + // in-order state across packets, unlike checksum status below, + // which is stateless and cheap enough to compute lazily when a row + // is selected instead of storing it on every row). + std::optional<std::string> reassembled_http; }; constexpr std::size_t kMaxRows = 5000; // cap memory; oldest rows scroll off @@ -52,7 +59,7 @@ struct SharedState { }; void consumer_loop(wireframe::CaptureSession& session, wireframe::CaptureQueue& queue, - SharedState& state) { + SharedState& state, wireframe::net::TcpReassembler* reassembler) { while (auto packet = queue.pop()) { std::span<const unsigned char> bytes{packet->data}; std::string summary = wireframe::summarize_packet(bytes, session.datalink()); @@ -62,8 +69,15 @@ void consumer_loop(wireframe::CaptureSession& session, wireframe::CaptureQueue& packet->original_len); } + std::optional<std::string> reassembled_http; + if (reassembler) { + reassembled_http = wireframe::reassembled_http_status(bytes, session.datalink(), + *reassembler); + } + std::lock_guard<std::mutex> lock(state.mutex); - state.rows.push_back({std::move(summary), std::move(packet->data)}); + state.rows.push_back({std::move(summary), std::move(packet->data), + std::move(reassembled_http)}); if (state.rows.size() > kMaxRows) state.rows.pop_front(); ++state.packet_count; } @@ -89,6 +103,11 @@ void print_usage(const char* argv0) { " -r <file> Replay a saved pcapng file instead of a live device\n" " -f <expr> Kernel-level capture filter (tcpdump/BPF syntax); also\n" " applies to what -w writes. Can't be combined with -r.\n" + " -c Show IPv4/TCP/UDP checksum validity for the selected packet.\n" + " Off by default - see the CLI's -h for why (checksum offload).\n" + " -a Reassemble TCP streams and show HTTP requests/responses\n" + " joined across segments for the selected packet, when its\n" + " segment contributed to one. In-order segments only.\n" " -h, --help Show this help and exit\n" "\n" "Examples:\n" @@ -109,6 +128,8 @@ int main(int argc, char** argv) { } wireframe::CaptureSessionOptions options; + bool enable_checksums = false; + bool enable_reassembly = false; for (int i = 1; i < argc; ++i) { if (std::strcmp(argv[i], "-w") == 0 && i + 1 < argc) { options.pcapng_output_path = argv[++i]; @@ -116,6 +137,10 @@ int main(int argc, char** argv) { options.filter_expr = argv[++i]; } else if (std::strcmp(argv[i], "-r") == 0 && i + 1 < argc) { options.replay_input_path = argv[++i]; + } else if (std::strcmp(argv[i], "-c") == 0) { + enable_checksums = true; + } else if (std::strcmp(argv[i], "-a") == 0) { + enable_reassembly = true; } else if (options.device.empty()) { options.device = argv[i]; } @@ -158,9 +183,10 @@ int main(int argc, char** argv) { wireframe::CaptureQueue queue(4096); SharedState state; + wireframe::net::TcpReassembler reassembler; std::thread capture_thread = session.start_capture_thread(queue); std::thread consumer_thread(consumer_loop, std::ref(session), std::ref(queue), - std::ref(state)); + std::ref(state), enable_reassembly ? &reassembler : nullptr); int selected_row = -1; bool quit = false; @@ -248,7 +274,18 @@ int main(int argc, char** argv) { { std::lock_guard<std::mutex> lock(state.mutex); if (selected_row >= 0 && selected_row < static_cast<int>(state.rows.size())) { - for (const auto& line : wireframe::hex_dump_lines(state.rows[selected_row].data)) { + const auto& row = state.rows[selected_row]; + if (enable_checksums) { + std::string status = wireframe::checksum_status(row.data, session.datalink()); + if (!status.empty()) { + ImGui::TextColored(ImVec4(0.6f, 0.8f, 1.0f, 1.0f), "%s", status.c_str()); + } + } + if (row.reassembled_http) { + ImGui::TextColored(ImVec4(0.6f, 1.0f, 0.6f, 1.0f), "%s", + row.reassembled_http->c_str()); + } + for (const auto& line : wireframe::hex_dump_lines(row.data)) { ImGui::TextUnformatted(line.c_str()); } } else { |