A modern C++20 cross-platform networking toolkit for diagnostics, testing, and development.
- π Modern C++20 β Templates,
std::span,std::optional,std::chrono,if constexpr - π¦ Zero Dependencies β No external libraries required
- π₯οΈ Cross-Platform β Linux, macOS, and Windows support
- π§ Easy Integration β Header + source files, just add to your project
- π Comprehensive β Full statistics, callbacks, and configurable options
Every tool builds on Linux, macOS, and Windows. The network-facing tools support both IPv4 and IPv6. NetSim operates on byte payloads and does not inspect or depend on the IP version.
| Tool | IPv4 | IPv6 | Permissions | Documentation |
|---|---|---|---|---|
| NetworkIF | Yes | Yes | None | Guide |
| PmtuDiscoverer | Yes | Yes | None | Guide |
| Ping | Yes | Yes | Linux: root or CAP_NET_RAW; macOS: root; Windows: none |
Guide |
| Traceroute (ICMP) | Yes | Yes | Linux: root or CAP_NET_RAW; macOS: root; Windows: none |
Guide |
| Traceroute (UDP) | Yes | Yes | Linux: root or CAP_NET_RAW; macOS: root; Windows: Administrator may be required |
Guide |
| NetSim | N/A | N/A | None; IP-agnostic payload simulator | Guide |
- CMake 3.20 or later
- C++20 compatible compiler:
- GCC 10+
- Clang 12+
- MSVC 2022+ (Visual Studio 17)
# Clone
git clone https://github.com/andersc/net-tools.git
cd net-tools
# Build
cmake -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build
# Test
ctest --test-dir build --output-on-failure
# Run the network simulator demo (no special privileges required)
./build/netsim_demoBuilding, testing, and most of the toolkit do not require sudo. Ping and
traceroute are the exceptions on Unix because their current backends use raw
ICMP sockets. See Why Ping and Traceroute Need Extra Permission
for the reason and the narrower Linux capability option.
# Clone
git clone https://github.com/andersc/net-tools.git
cd net-tools
# Build
cmake -B build -G "Visual Studio 17 2022" -A x64
cmake --build build --config Release
# Test
ctest --test-dir build --output-on-failure -C Release
# ICMP Ping and Traceroute use Windows IP Helper and need no elevation
.\build\Release\ping_demo.exe ::1 -6
.\build\Release\traceroute_demo.exe 127.0.0.1 --ipv4#include "Ping.h"
#include <iostream>
Ping lPing;
PingConfig lConfig;
lConfig.mCount = 4;
auto lResult = lPing.ping("google.com", lConfig);
std::cout << "Received: " << lResult.mStatistics.mPacketsReceived << "/"
<< lResult.mStatistics.mPacketsSent << "\n";
std::cout << "RTT avg: " << (lResult.mStatistics.mAvgRttMicroseconds / 1000.0) << " ms\n";
std::cout << "Packet loss: " << lResult.mStatistics.mPacketLossPercent << "%\n";#include "Traceroute.h"
#include <iostream>
Traceroute lTraceroute;
TracerouteConfig lConfig;
lConfig.mMaxHops = 30;
auto lResult = lTraceroute.trace("google.com", lConfig);
for (const auto& lHop : lResult.mHops) {
std::cout << lHop.mHopNumber << " ";
if (lHop.mResponded) {
std::cout << lHop.mIpAddress << " "
<< (lHop.mAvgRttMicroseconds / 1000.0) << " ms\n";
} else {
std::cout << "*\n";
}
}#include "NetworkIF.h"
#include <iostream>
UdpServer lServer;
lServer.create(IpVersion::DUAL);
lServer.bind(8080);
lServer.setOnDataReceived([&](const ClientInfo& aClient, std::span<const uint8_t> aData, std::any&) {
std::cout << "Received " << aData.size() << " bytes from " << aClient.mIp << "\n";
int64_t lBytesSent = 0;
lServer.sendTo(aData, aClient.mIp, aClient.mPort, lBytesSent); // Echo back
});
while (true) {
lServer.poll(100);
}#include "PmtuDiscoverer.h"
#include <iostream>
Pmtu::UdpPmtuDiscoverer::Config lConfig;
lConfig.minPayload = 600;
lConfig.maxPayload = 1500;
lConfig.psk = "mysecretkey";
Pmtu::UdpPmtuDiscoverer lDiscoverer;
auto lResult = lDiscoverer.discover("192.168.1.1", 9000, lConfig);
std::cout << "Path MTU: " << lResult.inferredPathMtu << " bytes\n";net-tools/
βββ CMakeLists.txt # Main build configuration
βββ NetworkIF.h/.cpp # Network interface (UDP/TCP)
βββ PmtuDiscoverer.h/.cpp # Path MTU discovery
βββ Traceroute.h/.cpp # Unix traceroute implementation
βββ TracerouteWindows.cpp # Native Windows traceroute backend
βββ Ping.h/.cpp # Unix ping implementation
βββ PingWindows.cpp # Native Windows IP Helper backend
βββ NetSim.h/.cpp # WiFi/4G network simulator
βββ *_main.cpp # CLI demo applications
βββ howto_*.md # Documentation guides
βββ tests/ # Unit tests
βββ CMakeLists.txt
βββ NetworkIFTest.cpp
βββ PmtuDiscovererTest.cpp
βββ TracerouteTest.cpp
βββ PingTest.cpp
βββ NetSimTest.cpp
# Build and run all tests
cmake -B build -DCMAKE_BUILD_TYPE=Debug
cmake --build build
ctest --test-dir build --output-on-failure
# Run specific test
./build/tests/ping_tests config_defaults
./build/tests/traceroute_tests can_trace
The default test run needs no elevation. Raw-socket loopback tests report a skip when the process lacks permission. CI separately elevates and requires the IPv4 and IPv6 raw-socket Ping and Traceroute paths on Linux and macOS; the Windows workflow does the same for its Administrator-only UDP Traceroute path.
NetworkIF, PMTU discovery, NetSim, and normal TCP/UDP applications run as an ordinary user on every supported platform. Extra permission applies only to backends that open raw ICMP sockets.
Ping sends and receives ICMP Echo packets. Traceroute controls the packet hop
limit and listens for ICMP Time Exceeded and Destination Unreachable
responses from routers. On Unix, net-tools implements these operations with
raw ICMP sockets, which the operating system restricts because they allow an
application to create and observe network-control packets.
This is not a requirement for the library as a whole. It applies only when using Ping or Traceroute on Linux/macOS, and when using UDP Traceroute on Windows. Windows Ping and ICMP Traceroute use the native IP Helper API and run without elevation.
# Grant only raw-network access to the two demo executables (recommended)
sudo setcap cap_net_raw+ep ./build/ping_demo
sudo setcap cap_net_raw+ep ./build/traceroute_demo
# The demos now run as your normal user
./build/ping_demo google.com
./build/traceroute_demo 8.8.8.8CAP_NET_RAW is narrower than running the entire process as root. Reapply it
after replacing or rebuilding an executable. Alternatively, prefix an
individual command with sudo when you do not want to set a file capability.
# macOS has no Linux-style CAP_NET_RAW file capability
sudo ./build/ping_demo google.com
sudo ./build/traceroute_demo 8.8.8.8Ping, ICMP traceroute, PMTU discovery, NetworkIF, and NetSim run as a normal
user. UDP traceroute receives raw ICMP errors and may require an Administrator
terminal; if access is denied, use the default --protocol icmp mode. The
Windows GitHub Actions job explicitly requires and tests UDP traceroute over
both IPv4 and IPv6, so this privileged path cannot silently be skipped in CI.
Each tool has comprehensive documentation:
- NetworkIF Guide β UDP/TCP, multicast, callbacks
- PmtuDiscoverer Guide β Path MTU discovery, authentication
- Traceroute Guide β Network path discovery, ICMP/UDP
- Ping Guide β ICMP Echo, statistics, flood mode
- NetSim Guide β WiFi/4G simulation, congestion, queues
Contributions are welcome! Please:
- Fork the repository
- Create a feature branch
- Follow the coding style
- Add tests for new functionality
- Submit a pull request
This project is licensed under the MIT License β see the LICENSE file for details.
