Skip to content

Commit 4c84fbe

Browse files
committed
mtr: Add ptr lookups
1 parent 57a3d9f commit 4c84fbe

File tree

3 files changed

+44
-19
lines changed

3 files changed

+44
-19
lines changed

cli/cli.go

+6-10
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@ package cli
22

33
import (
44
"fmt"
5-
"log"
6-
"net"
75
"sync"
86
"time"
97

@@ -24,6 +22,7 @@ var (
2422
MAX_HOPS = 64
2523
MAX_UNKNOWN_HOPS = 10
2624
RING_BUFFER_SIZE = 50
25+
PTR_LOOKUP = false
2726
jsonFmt = false
2827
srcAddr = "0.0.0.0"
2928
versionFlag bool
@@ -38,15 +37,11 @@ var RootCmd = &cobra.Command{
3837
fmt.Printf("MTR Version: %s, build date: %s\n", version, date)
3938
return nil
4039
}
41-
ip := args[0]
42-
if net.ParseIP(args[0]) == nil {
43-
addrs, err := net.LookupHost(args[0])
44-
if err != nil || len(addrs) == 0 {
45-
log.Fatalf("invalid host or ip provided: %s", err)
46-
}
47-
ip = addrs[0]
40+
m, ch, err := mtr.NewMTR(args[0], srcAddr, TIMEOUT, INTERVAL, HOP_SLEEP,
41+
MAX_HOPS, MAX_UNKNOWN_HOPS, RING_BUFFER_SIZE, PTR_LOOKUP)
42+
if err != nil {
43+
return err
4844
}
49-
m, ch := mtr.NewMTR(ip, srcAddr, TIMEOUT, INTERVAL, HOP_SLEEP, MAX_HOPS, MAX_UNKNOWN_HOPS, RING_BUFFER_SIZE)
5045
if jsonFmt {
5146
go func(ch chan struct{}) {
5247
for {
@@ -93,6 +88,7 @@ func init() {
9388
RootCmd.Flags().IntVar(&MAX_UNKNOWN_HOPS, "max-unknown-hops", MAX_UNKNOWN_HOPS, "Maximal hops that do not reply before stopping to look")
9489
RootCmd.Flags().IntVar(&RING_BUFFER_SIZE, "buffer-size", RING_BUFFER_SIZE, "Cached packet buffer size")
9590
RootCmd.Flags().BoolVar(&jsonFmt, "json", jsonFmt, "Print json results")
91+
RootCmd.Flags().BoolVarP(&PTR_LOOKUP, "ptr", "n", PTR_LOOKUP, "Reverse lookup on host")
9692
RootCmd.Flags().BoolVar(&versionFlag, "version", false, "Print version")
9793
RootCmd.Flags().StringVar(&srcAddr, "address", srcAddr, "The address to be bound the outgoing socket")
9894
}

pkg/hop/hop.go

+25-6
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ type HopStatistic struct {
2626
Packets *ring.Ring
2727
RingBufferSize int
2828
pingSeq int
29+
dnsCache map[string]string
2930
}
3031

3132
type packet struct {
@@ -124,7 +125,10 @@ func (h *HopStatistic) packets() []*packet {
124125
return v
125126
}
126127

127-
func (h *HopStatistic) Render() {
128+
func (h *HopStatistic) Render(ptrLookup bool) {
129+
if h.dnsCache == nil {
130+
h.dnsCache = map[string]string{}
131+
}
128132
packets := make([]byte, h.RingBufferSize)
129133
i := h.RingBufferSize - 1
130134
h.Packets.Do(func(f interface{}) {
@@ -137,14 +141,10 @@ func (h *HopStatistic) Render() {
137141
}
138142
i--
139143
})
140-
addr := "???"
141-
if h.Target != "" {
142-
addr = h.Target
143-
}
144144
l := fmt.Sprintf("%d", h.RingBufferSize)
145145
gm.Printf("%3d:|-- %-20s %5.1f%% %4d %6.1f %6.1f %6.1f %6.1f %"+l+"s\n",
146146
h.TTL,
147-
addr,
147+
fmt.Sprintf("%.20s", h.lookupAddr(ptrLookup)),
148148
h.Loss(),
149149
h.Sent,
150150
h.Last.Elapsed.Seconds()*1000,
@@ -154,3 +154,22 @@ func (h *HopStatistic) Render() {
154154
packets,
155155
)
156156
}
157+
158+
func (h *HopStatistic) lookupAddr(ptrLookup bool) string {
159+
addr := "???"
160+
if h.Target != "" {
161+
addr = h.Target
162+
if ptrLookup {
163+
if key, ok := h.dnsCache[h.Target]; ok {
164+
addr = key
165+
} else {
166+
names, err := net.LookupAddr(h.Target)
167+
if err == nil && len(names) > 0 {
168+
addr = names[0]
169+
}
170+
}
171+
}
172+
h.dnsCache[h.Target] = addr
173+
}
174+
return addr
175+
}

pkg/mtr/mtr.go

+13-3
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,18 @@ type MTR struct {
2424
ringBufferSize int
2525
maxHops int
2626
maxUnknownHops int
27+
ptrLookup bool
2728
}
2829

29-
func NewMTR(addr, srcAddr string, timeout time.Duration, interval time.Duration, hopsleep time.Duration, maxHops, maxUnknownHops, ringBufferSize int) (*MTR, chan struct{}) {
30+
func NewMTR(addr, srcAddr string, timeout time.Duration, interval time.Duration,
31+
hopsleep time.Duration, maxHops, maxUnknownHops, ringBufferSize int, ptr bool) (*MTR, chan struct{}, error) {
32+
if net.ParseIP(addr) == nil {
33+
addrs, err := net.LookupHost(addr)
34+
if err != nil || len(addrs) == 0 {
35+
return nil, nil, fmt.Errorf("invalid host or ip provided: %s", err)
36+
}
37+
addr = addrs[0]
38+
}
3039
return &MTR{
3140
SrcAddress: srcAddr,
3241
interval: interval,
@@ -38,7 +47,8 @@ func NewMTR(addr, srcAddr string, timeout time.Duration, interval time.Duration,
3847
maxHops: maxHops,
3948
ringBufferSize: ringBufferSize,
4049
maxUnknownHops: maxUnknownHops,
41-
}, make(chan struct{})
50+
ptrLookup: ptr,
51+
}, make(chan struct{}), nil
4252
}
4353

4454
func (m *MTR) registerStatistic(ttl int, r icmp.ICMPReturn) *hop.HopStatistic {
@@ -69,7 +79,7 @@ func (m *MTR) Render(offset int) {
6979
for i := 1; i <= len(m.Statistic); i++ {
7080
gm.MoveCursor(1, offset+i)
7181
m.mutex.RLock()
72-
m.Statistic[i].Render()
82+
m.Statistic[i].Render(m.ptrLookup)
7383
m.mutex.RUnlock()
7484
}
7585
}

0 commit comments

Comments
 (0)