This commit is contained in:
Eliezer Croitoru 2026-09-09 16:45:56 +03:00
parent c89cea01a6
commit 2fe99008cb
5 changed files with 43 additions and 14 deletions

Binary file not shown.

Binary file not shown.

View File

@ -444,7 +444,8 @@ func (t *Tracer) sendProbeUDP(ttl int) {
t.hops[ttl-1].recordSent()
t.sendMu.Lock()
_ = t.udpPC.SetTTL(ttl)
_ = setUDPSocketTTL(t.udpPC, t.udpSend, ttl)
_, err := t.udpSend.WriteTo(payload, &net.UDPAddr{IP: t.targetIP, Port: dstPort})
t.sendMu.Unlock()
@ -523,6 +524,8 @@ func (t *Tracer) receiveLoop() {
}
}
fmt.Fprintf(os.Stderr, "[debug] icmp recv %d bytes from %s\n", n, peer)
from := peerString(peer)
now := time.Now()
@ -624,19 +627,22 @@ 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) {
if len(data) < 28 {
return 0, false
}
ihl := int(data[0]&0x0f) * 4
if ihl < 20 || len(data) < ihl+8 {
return 0, false
}
if data[9] != 17 { // protocol must be UDP (17)
return 0, false
}
// UDP: srcPort(2) dstPort(2) length(2) checksum(2)
dstPort = int(binary.BigEndian.Uint16(data[ihl+2 : ihl+4]))
return dstPort, true
if len(data) < 28 {
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)
return 0, false
}
if data[9] != 17 {
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)
return dstPort, true
}
// ─── Reply handler ────────────────────────────────────────────────────────────

View File

@ -6,6 +6,7 @@ import (
"fmt"
"net"
"time"
"golang.org/x/net/ipv4"
)
func winAPIProbe(_ net.IP, _ int, _ time.Duration, _ []byte) (float64, string, uint32, error) {
@ -15,3 +16,7 @@ func winAPIProbe(_ net.IP, _ int, _ time.Duration, _ []byte) (float64, string, u
func (t *Tracer) sendProbeWinAPI(_ int) {}
func udpModeWarning() {}
func setUDPSocketTTL(pc *ipv4.PacketConn, conn net.PacketConn, ttl int) error {
return pc.SetTTL(ttl)
}

View File

@ -9,6 +9,7 @@ import (
"time"
"unsafe"
"os"
"golang.org/x/net/ipv4"
)
var (
@ -142,3 +143,20 @@ func (t *Tracer) sendProbeWinAPI(ttl int) {
}
}()
}
func setUDPSocketTTL(pc *ipv4.PacketConn, conn net.PacketConn, ttl int) error {
udpConn, ok := conn.(*net.UDPConn)
if !ok {
return pc.SetTTL(ttl)
}
raw, err := udpConn.SyscallConn()
if err != nil {
return pc.SetTTL(ttl)
}
var sockErr error
raw.Control(func(fd uintptr) {
sockErr = syscall.SetsockoptInt(syscall.Handle(fd),
syscall.IPPROTO_IP, syscall.IP_TTL, ttl)
})
return sockErr
}