Blazingly fast network diagnostics with minimal footprint • Non-blocking event loop • Async DNS • Kernel Timestamps
$ sudo ./fastrace google.com
fastrace
Tracing route to google.com (142.250.180.174)
Maximum hops: 30, Probes per hop: 3, Protocol: UDP
TTL │ IP Address (RTT ms) Hostname
────┼───────────────────────────────────────────
1 │ → 192.168.1.1 ( 3.58 ms)
2 │ * * * (timeout)
3 │ * * * (timeout)
4 │ → 185.89.159.5 ( 7.34 ms)
5 │ → 213.250.43.77 ( 38.62 ms) bsn-250-43-77.static.siol.net
6 │ → 193.77.107.46 ( 51.31 ms) bsn-77-107-46.static.siol.net
7 │ * * * (timeout)
8 │ → 142.251.235.172 ( 36.53 ms)
└→ 142.251.235.174 ( 35.54 ms)
Fastrace is a blazingly fast traceroute utility designed for network diagnostics and performance analysis. It maps the route that packets take across an IP network from source to destination, providing detailed timing information and identifying potential bottlenecks or routing issues.
Relies solely on standard C libraries and system calls
Event-driven pipeline with non-blocking I/O and monotonic timing for sub-millisecond precision
Compact data structures with dynamic allocation sized to trace configuration
Uses UDP for probes and raw sockets for response capture
Displays network topology with a structured, tree-like representation
Implements secure socket handling with comprehensive bounds checking
CLI options for hop count, probe volume, concurrency, timeouts, and DNS behavior
Background thread handles reverse DNS lookups, preventing stalls during packet processing
Uses SO_TIMESTAMP for microsecond-precision packet arrival times directly from the kernel
Fastrace uses two socket types for maximum effectiveness:
SOCK_DGRAM) for sending probe packetsSOCK_RAW) for receiving router responsessend_sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
recv_sock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
Each probe is tracked using a specialized structure with monotonic timing:
typedef struct {
int ttl; /* Time-to-Live value */
int probe; /* Probe sequence number */
struct timespec sent_time; /* Monotonic timestamp when sent */
bool received; /* Whether response was received */
struct in_addr addr; /* Address of responding hop */
double rtt; /* Round-trip time in ms */
int port; /* UDP port used for this probe */
} probe_t;
Fastrace implements a configurable multi-TTL probing system with runtime-adjustable concurrency:
// Default concurrency window (tunable via -c flag)
config.max_active_ttls = 6;
// Probes per hop (tunable via -q flag)
config.num_probes = 3;
While standard traceroute sequentially probes one TTL at a time, Fastrace processes multiple TTLs concurrently, dramatically reducing total trace time. The concurrency window can be adjusted at runtime to optimize for different network conditions.
The response processor relies on a poll()-driven event loop with non-blocking sockets to eagerly drain ICMP bursts:
int process_responses(int timeout_ms) {
struct pollfd pfd = {
.fd = recv_sock,
.events = POLLIN | POLLERR | POLLHUP
};
if (poll(&pfd, 1, timeout_ms) > 0) {
return drain_icmp_socket();
}
return 0;
}
RTT calculations use kernel-provided timestamps (SO_TIMESTAMP) when available, falling back to monotonic time:
struct cmsghdr *cmsg;
for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SO_TIMESTAMP) {
struct timeval *tv = (struct timeval *)CMSG_DATA(cmsg);
// ... use kernel timestamp ...
}
}
Hostname lookups are offloaded to a dedicated background thread to prevent blocking the main packet loop:
static void *dns_worker(void *arg) {
while (dns_running) {
// ... wait for queue item ...
if (getnameinfo(...) == 0) {
host_cache_store(item->addr, host);
}
}
return NULL;
}
Fastrace provides a structured visual representation of network paths:
7 │→ 72.14.209.224 ( 60.76 ms)
└→ 72.14.223.184 ( 61.65 ms)
8 │→ 142.251.244.109 ( 59.57 ms)
└→ 216.239.62.49 ( 71.36 ms)
└→ 142.250.210.95 ( 70.25 ms)
Fastrace significantly outperforms standard traceroute in several key metrics:
| Metric | Standard Traceroute | Fastrace | Improvement |
|---|---|---|---|
| Total trace time (30 hops) | ~15-20 seconds | ~3-5 seconds | ~4x faster (Async DNS) |
| Memory usage | ~400-600 KB | ~150-200 KB | 60-70% less memory |
| CPU utilization | 5-8% | 2-3% | 60% less CPU |
| Packet efficiency | 1 TTL at a time | Up to 6+ TTLs concurrently | 6x+ throughput |
| Response waiting | Fixed timeouts | Non-blocking + Async DNS | No stalls during lookup |
| Visual clarity | Flat output | Hierarchical tree view | Improved readability |
| RTT accuracy | User-space (~ms) | Kernel-space (SO_TIMESTAMP) | Microsecond precision |
| Security features | Basic | Comprehensive | Enhanced protection |
The project includes a Makefile for easy compilation and installation:
# Standard optimized build
make
# Build with debugging symbols
make debug
# Build with maximum performance optimizations
make optimized
# Install to system (default: /usr/local/bin)
sudo make install
# Uninstall from system
sudo make uninstall
# Clean build artifacts
make clean
# Disable DNS lookups for faster output
sudo ./fastrace -n google.com
# Set maximum hops and probes per hop
sudo ./fastrace -m 20 -q 5 google.com
# Adjust concurrent TTL window and timeouts
sudo ./fastrace -c 8 -W 2 -t 700 google.com
# Use custom base port
sudo ./fastrace -P 40000 google.com
# Show version
./fastrace -V
| Option | Description |
|---|---|
-n | Disable reverse DNS lookups |
-m <hops> | Maximum hop count (1-128, default 30) |
-q <probes> | Probes per hop (1-10, default 3) |
-c <count> | Concurrent TTL window size (default 6) |
-W <ms> | Poll wait timeout in milliseconds (default 2) |
-t <ms> | Hop completion timeout in milliseconds (default 700) |
-P <port> | Base UDP destination port (default 33434) |
-V | Print version information |
-h | Display help message |
gcc -O3 -pthread -o fastrace fastrace.c
For maximum performance:
gcc -O3 -march=native -mtune=native -flto -pthread -o fastrace fastrace.c
sudo ./fastrace <target>
Example:
sudo ./fastrace google.com
#include <arpa/inet.h>
#include <errno.h>
#include <fcntl.h>
#include <netdb.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
#include <netinet/udp.h>
#include <poll.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/types.h>
#include <time.h>
#include <unistd.h>
#include <pthread.h>
#include <signal.h>