From d22074dda16cb63e13ba12b69eb3a0d5b6bc3852 Mon Sep 17 00:00:00 2001 From: williamhedenskog <94441813+pilsnerfrajz@users.noreply.github.com> Date: Mon, 2 Feb 2026 23:24:38 +0100 Subject: [PATCH 01/17] Fix pcap_compile leak --- src/syn_scan.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/syn_scan.c b/src/syn_scan.c index da90919..a5831f3 100644 --- a/src/syn_scan.c +++ b/src/syn_scan.c @@ -731,6 +731,9 @@ static int pcap_filter_setup(char *address, struct src_info src_info) { return PCAP_FILTER; } + + pcap_freecode(&filter); + return 0; } From e4f2582eab61ff89f9cf76730f65ab0fc87f2a39 Mon Sep 17 00:00:00 2001 From: williamhedenskog <94441813+pilsnerfrajz@users.noreply.github.com> Date: Mon, 2 Feb 2026 23:27:19 +0100 Subject: [PATCH 02/17] Add comment --- src/syn_scan.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/syn_scan.c b/src/syn_scan.c index a5831f3..5cc9303 100644 --- a/src/syn_scan.c +++ b/src/syn_scan.c @@ -732,6 +732,7 @@ static int pcap_filter_setup(char *address, struct src_info src_info) return PCAP_FILTER; } + /* Free filter malloc */ pcap_freecode(&filter); return 0; From c0a07eacde9e5971d3bb11c64890edd9ba2639f2 Mon Sep 17 00:00:00 2001 From: williamhedenskog <94441813+pilsnerfrajz@users.noreply.github.com> Date: Mon, 2 Feb 2026 23:31:52 +0100 Subject: [PATCH 03/17] Fix another pcap_compile leak --- src/arp.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/arp.c b/src/arp.c index 437ecf8..d1317fd 100644 --- a/src/arp.c +++ b/src/arp.c @@ -210,6 +210,9 @@ int arp(char *address) return PCAP_FILTER; } + /* Free filter malloc */ + pcap_freecode(&filter); + struct callback_data c_data = {0}; memcpy(&c_data.arp_frame, &arp_frame, sizeof(c_data.arp_frame)); c_data.reply_found = 0; From c8de6cc4c6b73e97868d72b6e2a6a1b1dfb344cd Mon Sep 17 00:00:00 2001 From: williamhedenskog <94441813+pilsnerfrajz@users.noreply.github.com> Date: Mon, 2 Feb 2026 23:40:16 +0100 Subject: [PATCH 04/17] Fix another memory leak --- src/arp.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/arp.c b/src/arp.c index d1317fd..c75d65f 100644 --- a/src/arp.c +++ b/src/arp.c @@ -183,6 +183,9 @@ int arp(char *address) return PCAP_OPEN; } + /* Free memory */ + free(if_name); + if (pcap_inject(handle, &arp_frame, sizeof(arp_frame)) < 0) { pcap_close(handle); From 7270d3ecd3bcbb77b32fb5cd1a5dad4a3dee8bbd Mon Sep 17 00:00:00 2001 From: williamhedenskog <94441813+pilsnerfrajz@users.noreply.github.com> Date: Tue, 3 Feb 2026 20:30:10 +0100 Subject: [PATCH 05/17] Add memory leak compiler flag to tests --- Makefile | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 72eac36..803ea4e 100644 --- a/Makefile +++ b/Makefile @@ -10,6 +10,7 @@ TEST_OBJS := $(notdir $(patsubst %.c,%.o, $(wildcard $(TESTS_DIR)/*.c))) CC := gcc CFLAGS := -Wall -Wextra -pedantic -Werror +CFLAGSTEST := -Wall -Wextra -pedantic -Werror -fsanitize=address LDFLAGS := -lpcap -lpthread $(NAME): dir $(OBJS) @@ -19,13 +20,13 @@ $(OBJS): @$(CC) $(CFLAGS) -o $(BUILD_DIR)/$@ -c $(SRC_DIR)/$*.c test: dir $(TEST_OBJS) $(OBJS) - @$(CC) $(CFLAGS) -o $(TESTS_DIR)/$(BIN_DIR)/run_all_tests \ + @$(CC) $(CFLAGSTEST) -o $(TESTS_DIR)/$(BIN_DIR)/run_all_tests \ $(patsubst %,$(BUILD_DIR)/%, $(filter-out main.o, $(OBJS))) \ $(patsubst %,$(TESTS_DIR)/$(BUILD_DIR)/%, $(TEST_OBJS)) $(LDFLAGS) @sudo $(TESTS_DIR)/$(BIN_DIR)/run_all_tests $(TEST_OBJS): - @$(CC) $(CFLAGS) -o $(TESTS_DIR)/$(BUILD_DIR)/$@ -c $(TESTS_DIR)/$*.c + @$(CC) $(CFLAGSTEST) -o $(TESTS_DIR)/$(BUILD_DIR)/$@ -c $(TESTS_DIR)/$*.c dir: @mkdir -p $(BIN_DIR) $(BUILD_DIR) $(TESTS_DIR)/$(BIN_DIR) \ From c1e98184dce85299a14adb7636048d71d37efec6 Mon Sep 17 00:00:00 2001 From: williamhedenskog <94441813+pilsnerfrajz@users.noreply.github.com> Date: Tue, 3 Feb 2026 20:40:46 +0100 Subject: [PATCH 06/17] Add memset to clear struct --- src/utils.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/utils.c b/src/utils.c index 052d6f3..632e3b6 100644 --- a/src/utils.c +++ b/src/utils.c @@ -74,6 +74,9 @@ struct addrinfo *get_dst_addr_struct(char *dst, int sock_type) return NULL; } + /* Clear struct in case there is garbage */ + memset(res, 0, sizeof(struct addrinfo)); + res->ai_addr = malloc(sizeof(struct addrinfo)); if (res->ai_addr == NULL) { From ca88a237baafdd928d71b9197ace3a7d7b2c8cc6 Mon Sep 17 00:00:00 2001 From: williamhedenskog <94441813+pilsnerfrajz@users.noreply.github.com> Date: Tue, 3 Feb 2026 20:43:21 +0100 Subject: [PATCH 07/17] Fix memory leak Leak caused by copying more bytes than res holds --- src/utils.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/utils.c b/src/utils.c index 632e3b6..595d2bc 100644 --- a/src/utils.c +++ b/src/utils.c @@ -77,13 +77,13 @@ struct addrinfo *get_dst_addr_struct(char *dst, int sock_type) /* Clear struct in case there is garbage */ memset(res, 0, sizeof(struct addrinfo)); - res->ai_addr = malloc(sizeof(struct addrinfo)); + res->ai_addr = malloc(temp->ai_addrlen); if (res->ai_addr == NULL) { freeaddrinfo(dst_info); return NULL; } - memcpy(res->ai_addr, temp->ai_addr, sizeof(struct addrinfo)); + memcpy(res->ai_addr, temp->ai_addr, temp->ai_addrlen); res->ai_family = temp->ai_family; res->ai_addrlen = temp->ai_addrlen; From 5e40767f72c614d9cb2f634adbfaf44cd06438ac Mon Sep 17 00:00:00 2001 From: williamhedenskog <94441813+pilsnerfrajz@users.noreply.github.com> Date: Tue, 3 Feb 2026 21:24:29 +0100 Subject: [PATCH 08/17] Add leaks test to Makefile --- Makefile | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 803ea4e..2503e89 100644 --- a/Makefile +++ b/Makefile @@ -10,7 +10,7 @@ TEST_OBJS := $(notdir $(patsubst %.c,%.o, $(wildcard $(TESTS_DIR)/*.c))) CC := gcc CFLAGS := -Wall -Wextra -pedantic -Werror -CFLAGSTEST := -Wall -Wextra -pedantic -Werror -fsanitize=address +CFLAGSTEST := -Wall -Wextra -pedantic -Werror -fsanitize=address -g LDFLAGS := -lpcap -lpthread $(NAME): dir $(OBJS) @@ -24,10 +24,18 @@ test: dir $(TEST_OBJS) $(OBJS) $(patsubst %,$(BUILD_DIR)/%, $(filter-out main.o, $(OBJS))) \ $(patsubst %,$(TESTS_DIR)/$(BUILD_DIR)/%, $(TEST_OBJS)) $(LDFLAGS) @sudo $(TESTS_DIR)/$(BIN_DIR)/run_all_tests - + @echo "-- SEPARATE LEAK TESTS --" + @$(MAKE) leaks + $(TEST_OBJS): @$(CC) $(CFLAGSTEST) -o $(TESTS_DIR)/$(BUILD_DIR)/$@ -c $(TESTS_DIR)/$*.c +leaks: CFLAGS := $(CFLAGSTEST) +leaks: clean dir $(NAME) + @sudo chmod +x $(TESTS_DIR)/leaks.sh + @sudo $(TESTS_DIR)/leaks.sh + @$(MAKE) clean + dir: @mkdir -p $(BIN_DIR) $(BUILD_DIR) $(TESTS_DIR)/$(BIN_DIR) \ $(TESTS_DIR)/$(BUILD_DIR) @@ -36,4 +44,4 @@ clean: @rm -rf $(BUILD_DIR) $(BIN_DIR) $(TESTS_DIR)/$(BIN_DIR) \ $(TESTS_DIR)/$(BUILD_DIR) -.PHONY: dir test clean +.PHONY: dir test clean leaks From 4145bf85e156dd6c890c33e554e76139b6f19bd9 Mon Sep 17 00:00:00 2001 From: williamhedenskog <94441813+pilsnerfrajz@users.noreply.github.com> Date: Tue, 3 Feb 2026 21:37:45 +0100 Subject: [PATCH 09/17] Fix double-free on dst --- src/ping.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/ping.c b/src/ping.c index afcf402..92784b6 100644 --- a/src/ping.c +++ b/src/ping.c @@ -283,8 +283,7 @@ int ping(char *address, int tries) free(reply_hdr); } } - - if (dst->ai_family == AF_INET6) + else if (dst->ai_family == AF_INET6) { for (int attempt = 0; attempt < tries; attempt++) { From 45927163e6904aec1c0f62e88fdf9880c7c57d26 Mon Sep 17 00:00:00 2001 From: williamhedenskog <94441813+pilsnerfrajz@users.noreply.github.com> Date: Tue, 3 Feb 2026 21:37:51 +0100 Subject: [PATCH 10/17] Create leaks.sh --- tests/leaks.sh | 4 ++++ 1 file changed, 4 insertions(+) create mode 100755 tests/leaks.sh diff --git a/tests/leaks.sh b/tests/leaks.sh new file mode 100755 index 0000000..b9adebe --- /dev/null +++ b/tests/leaks.sh @@ -0,0 +1,4 @@ +#!/bin/bash +set -x + +sudo ./bin/disco localhost -P \ No newline at end of file From 758bf0bd9264b64667ee3d1ea06003ba9b7e53e5 Mon Sep 17 00:00:00 2001 From: williamhedenskog <94441813+pilsnerfrajz@users.noreply.github.com> Date: Tue, 3 Feb 2026 22:02:50 +0100 Subject: [PATCH 11/17] Format prints --- Makefile | 2 +- tests/fingerprint_test.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 2503e89..61b05eb 100644 --- a/Makefile +++ b/Makefile @@ -24,7 +24,7 @@ test: dir $(TEST_OBJS) $(OBJS) $(patsubst %,$(BUILD_DIR)/%, $(filter-out main.o, $(OBJS))) \ $(patsubst %,$(TESTS_DIR)/$(BUILD_DIR)/%, $(TEST_OBJS)) $(LDFLAGS) @sudo $(TESTS_DIR)/$(BIN_DIR)/run_all_tests - @echo "-- SEPARATE LEAK TESTS --" + @echo "\n-- SEPARATE LEAK TESTS --" @$(MAKE) leaks $(TEST_OBJS): diff --git a/tests/fingerprint_test.c b/tests/fingerprint_test.c index afd6378..057dcb8 100644 --- a/tests/fingerprint_test.c +++ b/tests/fingerprint_test.c @@ -9,7 +9,7 @@ void fingerprint_tests(void) { - printf("-- Fingerprint Tests --\n"); + printf("-- FINGERPRINT TESTS --\n"); set_test_print_flag(0); From f08a4d5ee98598c214669b15f86e0401cb7689c3 Mon Sep 17 00:00:00 2001 From: williamhedenskog <94441813+pilsnerfrajz@users.noreply.github.com> Date: Tue, 3 Feb 2026 22:08:23 +0100 Subject: [PATCH 12/17] Add cases with different CLI args for ASan leak tests --- tests/leaks.sh | 74 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 72 insertions(+), 2 deletions(-) diff --git a/tests/leaks.sh b/tests/leaks.sh index b9adebe..ca9f21b 100755 --- a/tests/leaks.sh +++ b/tests/leaks.sh @@ -1,4 +1,74 @@ #!/bin/bash -set -x -sudo ./bin/disco localhost -P \ No newline at end of file +BIN="./bin/disco" + +run_test() { + ERR_LOG=$(mktemp) + + # run binary with argument + $BIN "$@" > /dev/null 2> "$ERR_LOG" + if grep -q "Sanitizer" "$ERR_LOG"; then + echo "❌ Leak test with arguments '$@': failed" + cat "$ERR_LOG" + exit 1 + else + echo "✅ Leak test with arguments '$@': passed" + fi + rm -f "$ERR_LOG" +} + +run_test "-h" +run_test --help +run_test + +run_test localhost -P +run_test localhost --ping-only +run_test localhost -a +run_test localhost --arp-only +run_test localhost -S +run_test localhost --syn-only +run_test localhost -n + +run_test localhost -p 80 +run_test localhost -p 22,80,443 +run_test localhost -p 1-100 +run_test localhost -p 1-5,80,8080-8090 + +run_test localhost -p 0 +run_test localhost -p 70000 +run_test localhost -p 80,,22 +run_test 0.0.0.0 -P +run_test 255.255.255.255 -P + +run_test localhost -P -w out.txt +rm -f out.txt + +run_test localhost -p 80 -o -f +run_test localhost -n -p 22,80 -w out.txt +rm -f out.txt + +run_test 192.168.1.1 -P +run_test 192.168.1.1 --ping-only +run_test 192.168.1.1 -a +run_test 192.168.1.1 --arp-only +run_test 192.168.1.1 -S +run_test 192.168.1.1 --syn-only +run_test 192.168.1.1 -n + +run_test 192.168.1.1 -p 80 +run_test 192.168.1.1 -p 22,80,443 +run_test 192.168.1.1 -p 1-100 +run_test 192.168.1.1 -p 1-5,80,8080-8090 + +run_test 192.168.1.1 -p 0 +run_test 192.168.1.1 -p 70000 +run_test 192.168.1.1 -p 80,,22 +run_test 0.0.0.0 -P +run_test 255.255.255.255 -P + +run_test 192.168.1.1 -P -w out.txt +rm -f out.txt + +run_test 192.168.1.1 -p 80 -o -f +run_test 192.168.1.1 -n -p 22,80 -w out.txt +rm -f out.txt \ No newline at end of file From 40388599b158202d9d814f37198157ddeca6c0ae Mon Sep 17 00:00:00 2001 From: williamhedenskog <94441813+pilsnerfrajz@users.noreply.github.com> Date: Tue, 3 Feb 2026 22:10:06 +0100 Subject: [PATCH 13/17] Remove duplicate tests --- tests/leaks.sh | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/leaks.sh b/tests/leaks.sh index ca9f21b..c175f66 100755 --- a/tests/leaks.sh +++ b/tests/leaks.sh @@ -63,8 +63,6 @@ run_test 192.168.1.1 -p 1-5,80,8080-8090 run_test 192.168.1.1 -p 0 run_test 192.168.1.1 -p 70000 run_test 192.168.1.1 -p 80,,22 -run_test 0.0.0.0 -P -run_test 255.255.255.255 -P run_test 192.168.1.1 -P -w out.txt rm -f out.txt From b830b219d19a0baf5084357e8f3cf69bf84617be Mon Sep 17 00:00:00 2001 From: williamhedenskog <94441813+pilsnerfrajz@users.noreply.github.com> Date: Tue, 3 Feb 2026 22:12:01 +0100 Subject: [PATCH 14/17] Add missing sections --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 4e09109..8f118ca 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,8 @@ Disco is a cross-platform network utility available on Linux and macOS. It suppo - [Address Resolution Protocol (ARP)](#address-resolution-protocol-arp) - [ICMP Echo Request (Ping)](#icmp-echo-request-ping) - [TCP SYN Scanning](#tcp-syn-scanning) + - [OS Fingerprinting](#os-fingerprinting) + - [Network Diagnostics](#network-diagnostics) ## Installation 1. Clone the repository From c71f3d7783dd69100e05cbb43743ff221ec329d3 Mon Sep 17 00:00:00 2001 From: williamhedenskog <94441813+pilsnerfrajz@users.noreply.github.com> Date: Tue, 3 Feb 2026 22:12:56 +0100 Subject: [PATCH 15/17] Remove old tests --- README.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 8f118ca..4689110 100644 --- a/README.md +++ b/README.md @@ -113,13 +113,11 @@ The program includes comprehensive **integration tests** that validate real netw - Port scan of IPv4/IPv6 localhost - Port scan of LAN device - Port scan of IPv4/IPv6 external hosts -- CLI - - Setting all available CLI arguments - - Printing of usage message with `-h` flag + Some tests may fail due to hardcoded IP addresses and port numbers not accessible or open on the targets in your network. Test cases that involve localhost or domains should still pass however. -The future plan is to implement these tests in a CI pipeline using Docker to ensure working features, regardless of device and network configurations. + ## Technical Details Disco is implemented in C using `libpcap` for frame injection and packet filtering. This section describes the implementation of ARP, ping and port scanning in more detail for those interested. From 5510fb8d75bd1929bec1407d3447f5c7221c005d Mon Sep 17 00:00:00 2001 From: williamhedenskog <94441813+pilsnerfrajz@users.noreply.github.com> Date: Tue, 3 Feb 2026 22:21:03 +0100 Subject: [PATCH 16/17] Update README with leak info --- README.md | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 4689110..3d47510 100644 --- a/README.md +++ b/README.md @@ -71,7 +71,7 @@ disco - network utility for host discovery and port enumeration author: pilsnerfrajz usage: disco target [-h] [-p ports] [-o] [-n] [-P] [-a] [-S] - [-w file] [-f] + [-w file] [-f] options: target : host to scan (IP address or domain) -p, --ports : ports to scan, e.g., -p 1-1024 or -p 21,22,80 @@ -100,6 +100,8 @@ sudo ./bin/disco 127.0.0.1 -n -p 1-65535 ``` ## Testing + +### Integration Tests The program includes comprehensive **integration tests** that validate real network functionality. Run with `make test` from the project root to test: - ARP - Requests to LAN devices @@ -113,11 +115,14 @@ The program includes comprehensive **integration tests** that validate real netw - Port scan of IPv4/IPv6 localhost - Port scan of LAN device - Port scan of IPv4/IPv6 external hosts - +- OS Fingerprinting + - Windows, Linux and BSD-like (e.g. macOS) systems +- Memory leaks (see Section [Memory Leak Tests](#memory-leak-tests)) Some tests may fail due to hardcoded IP addresses and port numbers not accessible or open on the targets in your network. Test cases that involve localhost or domains should still pass however. - +### Memory Leak Tests +Memory leak tests are included to ensure proper memory management. These tests utilize the `AddressSanitizer` available in `clang`. Run with `make leaks` from the project root to execute leak tests with various argument combinations. Each test will report if any memory leaks were detected. ## Technical Details Disco is implemented in C using `libpcap` for frame injection and packet filtering. This section describes the implementation of ARP, ping and port scanning in more detail for those interested. From dd1d4c8409399dcc2abd9ad22815c8f445a2e7a6 Mon Sep 17 00:00:00 2001 From: williamhedenskog <94441813+pilsnerfrajz@users.noreply.github.com> Date: Tue, 3 Feb 2026 22:28:04 +0100 Subject: [PATCH 17/17] Update ToC --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 3d47510..ebeab61 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,8 @@ Disco is a cross-platform network utility available on Linux and macOS. It suppo - [Usage](#usage) - [Examples](#examples) - [Testing](#testing) + - [Integration Tests](#integration-tests) + - [Memory Leak Tests](#memory-leak-tests) - [Technical Details](#technical-details) - [Address Resolution Protocol (ARP)](#address-resolution-protocol-arp) - [ICMP Echo Request (Ping)](#icmp-echo-request-ping)