Traceroute From Scratch
This would be a pretty good interview question.
Suppose you’re on a system which is having trouble downloading the latest packages. You’re on the phone with the network team and they ask for a trace. But much to your dismay the traceroute command isn’t on the system. How do you proceed?
The Short Answer⌗
#! /usr/bin/env bash
host=google.com
for i in `seq 1 256`; do
ping -4 -c 1 -t $i $host | grep -iF 'from'
[[ ${PIPESTATUS[0]} ]] && break
done
The Long Answer⌗
In order to keep packets from erroneously bouncing around a network
indefinitely IP packets, both IPv4 and IPv6, have an 8-bit field denoting the
packets ‘time to live’ or TTL. This value is set initially by the sender and is
decremented each time the packet passes though a router. When the value reaches
zero the packet is dropped and the router sends a Time Exceeded
message back to
the sender.
The traceroute
program uses this fact, along with the assumption that path
though a network will remain relatively constant over a short period of time,
to determine path taken though the network by sending a series of pings with an
increasing TTL.
For example:
PING TTL=1 example.com -> Reply from first router.
PING TTL=2 example.com -> Reply from second router.
PING TTL=3 example.com -> Reply from third router.
...
Since the TTL is an 8 bit field we just need to loop until either we reach our destination or the TTL is 255 which is what the short answer does.
Comments⌗
- PIPESTATUS is a bash-ism that contains the exit status of the nth command in the previous pipe in an array.
- ping returns 1 on a Time Exceeded message and 0 when it reaches the destination. When we see an exit status of 0 we can break out of the loop. There are other corner cases we might consider but this is good enough for a whiteboard question.
- The lines we’re interested in from ping start either with From in the case of a Time Exceeded message or from when we reach our destination.