diff --git a/dist/livetrace-linux-amd64 b/dist/livetrace-linux-amd64 index 5e57d6c..ca1b4af 100755 Binary files a/dist/livetrace-linux-amd64 and b/dist/livetrace-linux-amd64 differ diff --git a/dist/livetrace-windows-amd64.exe b/dist/livetrace-windows-amd64.exe index 2197d1b..7048e85 100755 Binary files a/dist/livetrace-windows-amd64.exe and b/dist/livetrace-windows-amd64.exe differ diff --git a/src/main.go b/src/main.go index 2efa7b4..1e1b395 100644 --- a/src/main.go +++ b/src/main.go @@ -233,6 +233,7 @@ type Tracer struct { // lifecycle stopCh chan struct{} started time.Time + debug bool } func NewTracer( @@ -244,6 +245,7 @@ func NewTracer( maxRounds int, maxDur time.Duration, noDNS bool, + debug bool, ) (*Tracer, error) { ips, err := net.LookupHost(target) if err != nil { @@ -287,6 +289,7 @@ func NewTracer( maxActive: maxHops, stopCh: make(chan struct{}), started: time.Now(), + debug: debug, }, nil } @@ -523,8 +526,9 @@ func (t *Tracer) receiveLoop() { continue } } - - fmt.Fprintf(os.Stderr, "[debug] icmp recv %d bytes from %s\n", n, peer) + if t.debug { + fmt.Fprintf(os.Stderr, "[debug] icmp recv %d bytes from %s\n", n, peer) + } from := peerString(peer) now := time.Now() @@ -553,7 +557,7 @@ func (t *Tracer) receiveLoop() { continue } if t.proto == "udp" { - dstPort, ok := extractOriginalUDPPort(te.Data) + dstPort, ok := t.extractOriginalUDPPort(te.Data) if !ok { continue } @@ -580,7 +584,7 @@ func (t *Tracer) receiveLoop() { continue } if t.proto == "udp" { - dstPort, ok := extractOriginalUDPPort(du.Data) + dstPort, ok := t.extractOriginalUDPPort(du.Data) if !ok { continue } @@ -626,22 +630,30 @@ func extractOriginalICMP(data []byte) (seq, id int, ok bool) { // extractOriginalUDPPort reads the original UDP destination port from the // embedded original IP+UDP header in a Time Exceeded or Dest Unreachable reply. -func extractOriginalUDPPort(data []byte) (dstPort int, ok bool) { +func (t *Tracer) extractOriginalUDPPort(data []byte) (dstPort int, ok bool) { if len(data) < 28 { - fmt.Fprintf(os.Stderr, "[debug] extractUDP: too short (%d bytes)\n", len(data)) + if t.debug { + fmt.Fprintf(os.Stderr, "[debug] extractUDP: too short (%d bytes)\n", len(data)) + } return 0, false } ihl := int(data[0]&0x0f) * 4 if ihl < 20 || len(data) < ihl+8 { - fmt.Fprintf(os.Stderr, "[debug] extractUDP: bad IHL (%d)\n", ihl) + if t.debug { + fmt.Fprintf(os.Stderr, "[debug] extractUDP: bad IHL (%d)\n", ihl) + } return 0, false } if data[9] != 17 { - fmt.Fprintf(os.Stderr, "[debug] extractUDP: proto=%d (not UDP)\n", data[9]) + if t.debug { + fmt.Fprintf(os.Stderr, "[debug] extractUDP: proto=%d (not UDP)\n", data[9]) + } return 0, false } dstPort = int(binary.BigEndian.Uint16(data[ihl+2 : ihl+4])) - fmt.Fprintf(os.Stderr, "[debug] extractUDP: dstPort=%d\n", dstPort) + if t.debug { + fmt.Fprintf(os.Stderr, "[debug] extractUDP: dstPort=%d\n", dstPort) + } return dstPort, true } @@ -921,6 +933,7 @@ func main() { noDNS := flag.Bool("n", false, "disable reverse DNS (show numeric IPs only)") count := flag.Int("count", 0, "stop after N complete probe rounds (0 = run forever)") dur := flag.Duration("duration", 0, "stop after this duration, e.g. 30s, 5m (0 = run forever)") + debug := flag.Bool("debug", false, "enable debug output") flag.Usage = func() { fmt.Fprintf(os.Stderr, `Usage: livetrace [options] @@ -968,6 +981,7 @@ if p == "winapi" && runtime.GOOS != "windows" { *count, *dur, *noDNS, + *debug, ) if err != nil { fmt.Fprintln(os.Stderr, "Error:", err)