Skip to content

Commit 1b38f00

Browse files
committed
feat: improve CLI, CI, and packaging
- Updated README and documentation, moving and cleaning - Added bash and CLI completion scripts - Implemented JSON output for the CLI - Enabled default sandbox usage, refined landlock message handling - Integrated `vcpkg` for dependency downloads - Added utilities for port scanning and tool scanning - Updated build scripts: added CPack packaging, Fedora RPM build, and CI configurations - Made numerous bug fixes and clean‑ups across the codebase. GitOrigin-RevId: c75502466c03a5af29d55ddc88311642d0e59b0d
1 parent 9e19123 commit 1b38f00

24 files changed

Lines changed: 1141 additions & 77 deletions

.github/workflows/ci.yml

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,12 @@ jobs:
2121
sudo apt-get update
2222
sudo apt-get install -y cmake ninja-build build-essential pkg-config clang
2323
24+
- name: Ensure vcpkg downloads directory
25+
run: |
26+
VCPKG_DOWNLOADS="${VCPKG_DOWNLOADS:-/tmp/vcpkg-downloads}"
27+
mkdir -p "${VCPKG_DOWNLOADS}"
28+
echo "VCPKG_DOWNLOADS=${VCPKG_DOWNLOADS}" >> "${GITHUB_ENV}"
29+
2430
- name: Setup vcpkg
2531
uses: lukka/run-vcpkg@v11
2632
with:
@@ -40,3 +46,37 @@ jobs:
4046

4147
# - name: Test
4248
# run: ctest --test-dir build --output-on-failure
49+
50+
build-rpm:
51+
runs-on: ubuntu-latest
52+
container:
53+
image: fedora:43
54+
steps:
55+
- name: Install build dependencies
56+
run: |
57+
dnf install -y \
58+
gcc-c++ cmake ninja-build pkgconf-pkg-config \
59+
boost-devel cli11-devel catch2-devel \
60+
rpm-build git
61+
62+
- name: Checkout
63+
uses: actions/checkout@v4
64+
65+
- name: Configure
66+
run: >
67+
cmake -S . -B build
68+
-DCMAKE_BUILD_TYPE=Release
69+
-DPULSECAN_USE_VCPKG=OFF
70+
-DBUILD_TESTING=OFF
71+
72+
- name: Build
73+
run: cmake --build build --config Release
74+
75+
- name: Package (RPM)
76+
run: cpack --config build/CPackConfig.cmake -G RPM
77+
78+
- name: Upload RPM
79+
uses: actions/upload-artifact@v4
80+
with:
81+
name: pulsescan-cpp-rpm
82+
path: build/*.rpm

CMakeLists.txt

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,21 @@
11
cmake_minimum_required(VERSION 3.20)
22

3-
message("VCPKG_ROOT: $ENV{VCPKG_ROOT}")
4-
message("CMAKE_TOOLCHAIN_FILE: $ENV{CMAKE_TOOLCHAIN_FILE}")
3+
option(PULSECAN_USE_VCPKG "Use vcpkg toolchain when available" ON)
54

6-
list(APPEND CMAKE_PROJECT_TOP_LEVEL_INCLUDES "$ENV{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake")
7-
list(APPEND CMAKE_TRY_COMPILE_PLATFORM_VARIABLES CMAKE_PROJECT_TOP_LEVEL_INCLUDES)
5+
if(PULSECAN_USE_VCPKG)
6+
message("VCPKG_ROOT: $ENV{VCPKG_ROOT}")
7+
message("CMAKE_TOOLCHAIN_FILE: $ENV{CMAKE_TOOLCHAIN_FILE}")
8+
if(DEFINED ENV{VCPKG_ROOT} AND EXISTS "$ENV{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake")
9+
list(APPEND CMAKE_PROJECT_TOP_LEVEL_INCLUDES "$ENV{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake")
10+
list(APPEND CMAKE_TRY_COMPILE_PLATFORM_VARIABLES CMAKE_PROJECT_TOP_LEVEL_INCLUDES)
11+
endif()
12+
endif()
813

914
if(POLICY CMP0167)
1015
cmake_policy(SET CMP0167 NEW)
1116
endif()
1217

13-
project(pulsescan_cpp LANGUAGES CXX)
18+
project(pulsescan_cpp VERSION 1.0.0 LANGUAGES CXX)
1419

1520
option(ENABLE_STACKTRACE "Enable Boost stacktrace logging" OFF)
1621
option(ENABLE_ASIO_SSL "Enable Boost.Asio SSL support" OFF)
@@ -21,7 +26,7 @@ set(CMAKE_CXX_EXTENSIONS OFF)
2126
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
2227

2328
find_package(CLI11 CONFIG REQUIRED)
24-
find_package(Boost REQUIRED COMPONENTS asio)
29+
find_package(Boost REQUIRED COMPONENTS asio system)
2530
if(ENABLE_STACKTRACE)
2631
find_package(Boost REQUIRED COMPONENTS stacktrace_basic)
2732
endif()
@@ -34,6 +39,7 @@ add_executable(pulsescan_cpp
3439
src/core/logging.cpp
3540
src/core/output.cpp
3641
src/core/ping_loop.cpp
42+
src/core/ports.cpp
3743
src/core/status.cpp
3844
src/net/icmp_packet.cpp
3945
src/core/resolve.cpp
@@ -57,7 +63,7 @@ else()
5763
endif()
5864
target_include_directories(pulsescan_cpp PRIVATE src)
5965

60-
target_link_libraries(pulsescan_cpp PRIVATE Boost::asio CLI11::CLI11)
66+
target_link_libraries(pulsescan_cpp PRIVATE Boost::asio Boost::system CLI11::CLI11)
6167
if(ENABLE_STACKTRACE)
6268
target_link_libraries(pulsescan_cpp PRIVATE Boost::stacktrace_basic)
6369
target_compile_definitions(pulsescan_cpp PRIVATE ENABLE_STACKTRACE)
@@ -78,13 +84,14 @@ if(BUILD_TESTING)
7884
src/core/cli.cpp
7985
src/core/logging.cpp
8086
src/core/output.cpp
87+
src/core/ports.cpp
8188
src/core/resolve.cpp
8289
src/core/status.cpp
8390
src/net/icmp_packet.cpp
8491
src/net/udp_probes.cpp
8592
)
8693
target_include_directories(pulsescan_cpp_tests PRIVATE src)
87-
target_link_libraries(pulsescan_cpp_tests PRIVATE Boost::asio CLI11::CLI11 Catch2::Catch2WithMain)
94+
target_link_libraries(pulsescan_cpp_tests PRIVATE Boost::asio Boost::system CLI11::CLI11 Catch2::Catch2WithMain)
8895
if(ENABLE_STACKTRACE)
8996
target_link_libraries(pulsescan_cpp_tests PRIVATE Boost::stacktrace_basic)
9097
target_compile_definitions(pulsescan_cpp_tests PRIVATE ENABLE_STACKTRACE)
@@ -94,3 +101,22 @@ if(BUILD_TESTING)
94101
endif()
95102
catch_discover_tests(pulsescan_cpp_tests)
96103
endif()
104+
105+
include(GNUInstallDirs)
106+
install(TARGETS pulsescan_cpp RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
107+
install(FILES README.md LICENSE
108+
DESTINATION ${CMAKE_INSTALL_DOCDIR})
109+
install(DIRECTORY docs/
110+
DESTINATION ${CMAKE_INSTALL_DOCDIR})
111+
install(FILES scripts/completions/pulsescan-cpp.bash
112+
DESTINATION ${CMAKE_INSTALL_DATADIR}/bash-completion/completions
113+
RENAME pulsescan-cpp)
114+
115+
set(CPACK_PACKAGE_NAME "pulsescan-cpp")
116+
set(CPACK_PACKAGE_VENDOR "ryoung")
117+
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "PulseScan C++ async port and host scanner")
118+
set(CPACK_PACKAGE_VERSION ${PROJECT_VERSION})
119+
set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON)
120+
set(CPACK_RPM_PACKAGE_AUTOREQPROV ON)
121+
set(CPACK_GENERATOR "DEB;RPM")
122+
include(CPack)

README.md

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,39 +25,40 @@ cmake --build build
2525

2626
Basic scan (replace with hosts you are authorized to test):
2727
```bash
28-
./build/pulsescan-cpp localhost -p 80,443,8000-8005 -t 1.5 --max-inflight 500
28+
./pulsescan-cpp localhost -p 80,443,8000-8005 -t 1.5 --max-inflight 500
2929
```
3030

3131
Multi-host scan:
3232
```bash
33-
./build/pulsescan-cpp localhost 127.0.0.1 ::1 -p 22,80
33+
./pulsescan-cpp localhost 127.0.0.1 ::1 -p 22,80
3434
```
3535

3636
Ping mode (repeat and report changes):
3737
```bash
38-
./build/pulsescan-cpp localhost -p 80 --ping --interval 2
38+
./pulsescan-cpp localhost -p 80 --ping --interval 2
3939
```
4040

4141
ICMP ping (requires root or CAP_NET_RAW):
4242
```bash
43-
sudo ./build/pulsescan-cpp 127.0.0.1 --icmp-ping -c 3
43+
sudo ./pulsescan-cpp 127.0.0.1 --icmp-ping -c 3
4444
```
4545

4646
Modes:
4747
- `-m connect` (default): TCP connect scan.
4848
- `-m banner`: TCP connect plus a short banner read (`--banner-timeout`, `--banner-bytes`).
49-
- `-m udp`: UDP probe that sends a protocol-specific payload when known (DNS, NTP, QUIC VN, SIP, IAX2), otherwise a minimal payload. No reply is reported as `open|filtered`.
49+
- `-m udp`: UDP probe that sends a protocol-specific payload when known (DNS, NTP, SIP), otherwise a minimal payload. No reply is reported as `open|filtered`.
5050

5151
Features:
5252
- Multi-host scanning.
5353
- `--ping` change detection.
5454
- ICMP ping mode with CIDR/range expansion.
5555
- IPv4/IPv6 filtering (`-4`/`-6`).
5656
- Optional reverse DNS (`--reverse-dns`).
57-
- Optional sandboxing (`--sandbox`) using Landlock (Linux) or Capsicum (FreeBSD).
57+
- Report-style text output by default, JSON line output (`--output json`) when needed.
58+
- Sandboxing enabled by default using Landlock (Linux) or Capsicum (FreeBSD).
5859
- Press Enter (or SIGINFO on FreeBSD) to print progress while running.
5960

6061
## Notes / Next steps
6162
- UDP scans are best-effort; no response is reported as `open|filtered`.
6263
- ICMP ping requires root or `CAP_NET_RAW`.
63-
- Consider JSON output and per-host/port rate caps for larger sweeps.
64+
- Consider per-host/port rate caps for larger sweeps.

build.md

Lines changed: 0 additions & 24 deletions
This file was deleted.

cmake/toolchains/freebsd14.cmake

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@ set(CMAKE_SYSTEM_PROCESSOR x86_64)
44

55
set(FREEBSD_TARGET "x86_64-unknown-freebsd14.3")
66

7-
if(NOT DEFINED FREEBSD_SYSROOT)
7+
if(NOT DEFINED FREEBSD_SYSROOT OR FREEBSD_SYSROOT STREQUAL "")
8+
set(FREEBSD_SYSROOT "$ENV{FREEBSD_SYSROOT}")
9+
endif()
10+
if(NOT DEFINED FREEBSD_SYSROOT OR FREEBSD_SYSROOT STREQUAL "")
811
message(FATAL_ERROR "FREEBSD_SYSROOT is not set (path to FreeBSD base sysroot).")
912
endif()
1013

docs/benchmark.md

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
# Benchmarking PulseScan vs Nmap
2+
3+
This document outlines a simple, repeatable way to compare PulseScan's range
4+
scanning performance against nmap. The goal is a fair wall-clock comparison
5+
with minimal DNS or network noise.
6+
7+
## General guidance
8+
9+
- Use a stable test range you own (lab VLAN, VM subnet, loopback).
10+
- Disable DNS lookups (PulseScan: no `--reverse-dns`, nmap: `-n`).
11+
- Keep scan scope identical (same hosts, same ports, same protocol).
12+
- Use multiple runs and a warm-up to reduce variance.
13+
- Do not scan public networks or hosts without permission.
14+
15+
## Tooling
16+
17+
`hyperfine` is a good fit for measuring total runtime.
18+
19+
Install (example for Debian/Ubuntu):
20+
21+
```bash
22+
sudo apt-get install -y hyperfine
23+
```
24+
25+
## Suggested baselines
26+
27+
Pick a range and port set:
28+
29+
- Range: `192.168.1.0/24` (example)
30+
- Ports: 10 common ports
31+
- Timeouts: 1.0s
32+
- No DNS, no banner, no UDP (TCP connect only)
33+
34+
## Example: TCP connect scan
35+
36+
PulseScan:
37+
38+
```bash
39+
./build/pulsescan-cpp 192.168.1.0/24 \
40+
--top-ports 10 \
41+
-t 1.0 \
42+
--max-inflight 200 \
43+
--output json > /dev/null
44+
```
45+
46+
nmap:
47+
48+
```bash
49+
nmap -n -Pn \
50+
--max-retries 1 \
51+
--host-timeout 1s \
52+
-p 20,21,22,23,25,53,80,81,88,110 \
53+
192.168.1.0/24 > /dev/null
54+
```
55+
56+
Hyperfine:
57+
58+
```bash
59+
hyperfine --warmup 1 --runs 5 \
60+
'./build/pulsescan-cpp 192.168.1.0/24 --top-ports 10 -t 1.0 --max-inflight 200 --output json > /dev/null' \
61+
'nmap -n -Pn --max-retries 1 --host-timeout 1s -p 20,21,22,23,25,53,80,81,88,110 192.168.1.0/24 > /dev/null'
62+
```
63+
64+
## Notes on fairness
65+
66+
- `--max-inflight` is PulseScan's concurrency knob; nmap has its own timing engine.
67+
You can also try `-T3` or `-T4` in nmap to explore different profiles.
68+
- `--host-timeout` in nmap is a hard cap per host; adjust to match PulseScan timeouts.
69+
- If you use `--ping` or `--icmp-ping`, benchmark them separately.
70+
71+
## Interpreting results
72+
73+
Hyperfine reports mean/median runtime and standard deviation. Compare relative
74+
performance on the same hardware and network conditions. If results are noisy,
75+
increase run count or narrow the test range.

docs/build.md

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
# Build
2+
3+
## Configure and Build
4+
5+
```bash
6+
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
7+
cmake --build build --config Release
8+
```
9+
10+
## Dependency Source (system vs vcpkg)
11+
12+
By default, the build uses vcpkg if `VCPKG_ROOT` is set. To prefer system
13+
packages, disable vcpkg:
14+
15+
```bash
16+
cmake -S . -B build -DPULSECAN_USE_VCPKG=OFF
17+
```
18+
19+
To force vcpkg (static libs) when it is available:
20+
21+
```bash
22+
cmake -S . -B build -DPULSECAN_USE_VCPKG=ON
23+
```
24+
25+
## Packaging (DEB/RPM)
26+
27+
Packages are generated via CPack. After a successful build, run:
28+
29+
```bash
30+
cpack --config build/CPackConfig.cmake -G DEB
31+
cpack --config build/CPackConfig.cmake -G RPM
32+
```
33+
34+
Or use the package target:
35+
36+
```bash
37+
cmake --build build --target package
38+
```
39+
40+
## Enable Stacktrace (Optional)
41+
42+
The stacktrace support is optional and off by default.
43+
44+
Enable the vcpkg feature:
45+
46+
```bash
47+
vcpkg install --feature-flags=manifest pulsescan-cpp[stacktrace]
48+
```
49+
50+
Enable the CMake toggle:
51+
52+
```bash
53+
cmake -S . -B build -DENABLE_STACKTRACE=ON
54+
```

0 commit comments

Comments
 (0)