v0.3.0

A high-performance, dependency-free traceroute implementation in pure C

Blazingly fast network diagnostics with minimal footprint • Non-blocking event loop • Async DNS • Kernel Timestamps

Terminal
$ 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)

Overview

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.

Zero Dependencies

Relies solely on standard C libraries and system calls

Maximum Performance

Event-driven pipeline with non-blocking I/O and monotonic timing for sub-millisecond precision

Low Memory Footprint

Compact data structures with dynamic allocation sized to trace configuration

Dual Socket Implementation

Uses UDP for probes and raw sockets for response capture

Visual Route Mapping

Displays network topology with a structured, tree-like representation

Security-Focused Design

Implements secure socket handling with comprehensive bounds checking

Runtime Tunability

CLI options for hop count, probe volume, concurrency, timeouts, and DNS behavior

Asynchronous DNS

Background thread handles reverse DNS lookups, preventing stalls during packet processing

Kernel Timestamps

Uses SO_TIMESTAMP for microsecond-precision packet arrival times directly from the kernel

Technical Architecture

Dual Socket Architecture

Fastrace uses two socket types for maximum effectiveness:

  • UDP socket (SOCK_DGRAM) for sending probe packets
  • Raw ICMP socket (SOCK_RAW) for receiving router responses
send_sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
recv_sock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);

Probe Structure

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;

Adaptive Route Discovery

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.

Efficient Response Processing

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 ...
    }
}

Asynchronous DNS Resolution

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;
}

Visual Path Representation

Fastrace provides a structured visual representation of network paths:

  • Tree-like format shows branching at load-balanced routes
  • Clear arrows indicate path progression
  • Distinct formatting for primary and alternative routes
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)

Performance Benchmarks

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

Usage

Using Makefile

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

Command-Line Options

# 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
OptionDescription
-nDisable 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)
-VPrint version information
-hDisplay help message

Manual Compilation

gcc -O3 -pthread -o fastrace fastrace.c

For maximum performance:

gcc -O3 -march=native -mtune=native -flto -pthread -o fastrace fastrace.c

Basic Usage

sudo ./fastrace <target>

Example:

sudo ./fastrace google.com

Technical Requirements

System Requirements

  • Operating System: Linux, macOS, or other Unix-like systems with raw socket support
  • Permissions: Root/sudo access required (raw sockets)
  • Compiler: GCC with C99 support or later
  • Architecture: x86, x86_64, ARM, or any platform with standard C library support

Header Dependencies

#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>