From 39dbcd8d8dc3326be3969e874f44b35774fee907 Mon Sep 17 00:00:00 2001 From: Trekkie Coder Date: Tue, 17 Dec 2024 12:33:40 +0900 Subject: [PATCH] Fixed probes for ep6 --- go.mod | 2 +- go.sum | 2 ++ lib_test.go | 48 +++++++++++++----------------------- serviceprobe.go | 65 +++++++++++++++++++++++++++++++++++++++++++------ 4 files changed, 78 insertions(+), 39 deletions(-) diff --git a/go.mod b/go.mod index c985231..660ebc4 100644 --- a/go.mod +++ b/go.mod @@ -7,4 +7,4 @@ require ( golang.org/x/sys v0.8.0 // indirect ) -require github.com/loxilb-io/sctp v0.0.0-20240912025756-01894eac308b +require github.com/loxilb-io/sctp v0.0.0-20241217032220-301b591b9ced diff --git a/go.sum b/go.sum index 4961f15..dde33ee 100644 --- a/go.sum +++ b/go.sum @@ -10,6 +10,8 @@ github.com/loxilb-io/sctp v0.0.0-20240912024735-b9c5910e672f h1:sm8UnXJa4dAV/wTE github.com/loxilb-io/sctp v0.0.0-20240912024735-b9c5910e672f/go.mod h1:g3xKRvSWoeijv487mRGw3sLDacD9bC+wRQ4QebiafiQ= github.com/loxilb-io/sctp v0.0.0-20240912025756-01894eac308b h1:QZHlUZTWMpghNQW/OzdKFY2PhhPFMPAjsfRSLZkAONU= github.com/loxilb-io/sctp v0.0.0-20240912025756-01894eac308b/go.mod h1:g3xKRvSWoeijv487mRGw3sLDacD9bC+wRQ4QebiafiQ= +github.com/loxilb-io/sctp v0.0.0-20241217032220-301b591b9ced h1:XRB++1zTq2epcR8c8K+OK0+8RnEg/Rf6a73qs+rJ0fE= +github.com/loxilb-io/sctp v0.0.0-20241217032220-301b591b9ced/go.mod h1:g3xKRvSWoeijv487mRGw3sLDacD9bC+wRQ4QebiafiQ= golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= diff --git a/lib_test.go b/lib_test.go index 7f98607..2e05998 100644 --- a/lib_test.go +++ b/lib_test.go @@ -5,9 +5,7 @@ package loxilib import ( "fmt" - "net" "testing" - "github.com/loxilb-io/sctp" ) type Tk struct { @@ -999,38 +997,19 @@ func TestIPAlloc(t *testing.T) { } func TestProber(t *testing.T) { - epIp, err := net.ResolveIPAddr("ip", "127.0.0.1") - if err != nil { - t.Fatal("Failed to resolve IP") - } - - ips := []net.IPAddr{*epIp} + sOk := L4ServiceProber("sctp", "192.168.20.58:8080", "", "", "") + t.Logf("sctp prober test1 %v", sOk) - addr := &sctp.SCTPAddr{ - IPAddrs: ips, - Port: 8080, - } - - cn, err := sctp.DialSCTP("sctp", nil, addr, false) - if err == nil { - t.Logf("sctp prober connected") - cn.Close() - } else { - t.Logf("sctp prober not connected %s", err) - } + sOk = L4ServiceProber("sctp", "[3ffe:cafe::1]:1346", "", "", "") + t.Logf("sctp prober test2 %v", sOk) - cn, err = sctp.DialSCTP("sctp", nil, addr, true) - if err == nil { - t.Logf("sctp (block) prober connected") - cn.Close() - } else { - t.Logf("sctp (block) prober not connected %s", err) - } + sOk = L4ServiceProber("tcp", "192.168.20.58:8081", "", "", "") + t.Logf("tcp prober test1 %v", sOk) - // We are checking if this blocks forever - t.Logf("sctp prober test OK") + sOk = L4ServiceProber("sctp", "[3ffe:cafe::1]:1446", "", "", "") + t.Logf("tcp prober test2 %v", sOk) - sOk := L4ServiceProber("udp", "192.168.20.55:12234", "", "", "") + sOk = L4ServiceProber("udp", "192.168.20.55:12234", "", "", "") t.Logf("udp prober test1 %v\n", sOk) sOk = L4ServiceProber("udp", "127.0.0.1:12234", "", "", "") @@ -1039,6 +1018,13 @@ func TestProber(t *testing.T) { sOk = L4ServiceProber("udp", "127.0.0.1:8080", "", "", "") t.Logf("udp prober test3 %v\n", sOk) + sOk = L4ServiceProber("udp", "[::1]:8080", "", "", "") + t.Logf("udp prober test4 %v\n", sOk) + + sOk = L4ServiceProber("udp", "[3ffe:cafe::1]:2020", "", "", "") + t.Logf("udp prober test5 %v\n", sOk) + sOk = L4ServiceProber("udp", "192.168.20.55:2234", "", "", "") - t.Logf("udp prober test4 %v\n\n\n", sOk) + t.Logf("udp prober test6 %v\n", sOk) + } diff --git a/serviceprobe.go b/serviceprobe.go index 5fc9ac3..bd513b3 100644 --- a/serviceprobe.go +++ b/serviceprobe.go @@ -10,6 +10,7 @@ import ( "github.com/loxilb-io/sctp" "golang.org/x/net/icmp" "golang.org/x/net/ipv4" + "golang.org/x/net/ipv6" "net" "net/http" "os" @@ -45,6 +46,50 @@ func waitForBoolChannelOrTimeout(ch <-chan bool, timeout time.Duration) (bool, b } } +func listenForICMP6UNreachable() { + conn, err := icmp.ListenPacket("ip6:ipv6-icmp", "::") + if err != nil { + os.Exit(1) + } + defer conn.Close() + + buffer := make([]byte, 1500) + //conn.SetReadDeadline(time.Now().Add(100 * time.Millisecond)) + icmpRunner <- true + for { + n, _, err := conn.ReadFrom(buffer) + if err != nil { + if netErr, ok := err.(net.Error); ok && netErr.Timeout() { + continue // Ignore timeout errors + } + continue + } + + // Parse the ICMPv6 message + message, err := icmp.ParseMessage(ipv6.ICMPTypeDestinationUnreachable.Protocol(), buffer[:n]) + if err != nil { + continue + } + + // Check for Destination Unreachable messages + if message.Type == ipv6.ICMPTypeDestinationUnreachable { + if body, ok := message.Body.(*icmp.DstUnreach); ok { + pktData := body.Data + if len(pktData) >= 48 { + destIP := net.IP(pktData[24:40]).String() + dport := int(pktData[42])<<8 | int(pktData[43]) + svcLock.Lock() + key := SvcKey{Dst: destIP, Port: dport} + if svcWait := svcs[key]; svcWait != nil { + svcWait.wait <- true + } + svcLock.Unlock() + } + } + } + } +} + func listenForICMPUNreachable() { // Open a raw socket to listen for ICMP messages @@ -109,6 +154,8 @@ func L4ServiceProber(sType string, sName string, sHint, req, resp string) bool { icmpRunner = make(chan bool) svcs = map[SvcKey]*SvcWait{} go listenForICMPUNreachable() + go listenForICMP6UNreachable() + <-icmpRunner <-icmpRunner } svcLock.Unlock() @@ -133,15 +180,14 @@ func L4ServiceProber(sType string, sName string, sHint, req, resp string) bool { } netAddr := sName[:len(sName)-len(portString)-1] + if netAddr[0:1] == "[" { + netAddr = strings.Trim(netAddr, "[") + netAddr = strings.Trim(netAddr, "]") + } if sType == "sctp" { - if netAddr[0:1] == "[" { - netAddr = strings.Trim(netAddr, "[") - netAddr = strings.Trim(netAddr, "]") - } network := "ip4" - if IsNetIPv6(netAddr) { network = "ip6" } @@ -225,7 +271,7 @@ func L4ServiceProber(sType string, sName string, sHint, req, resp string) bool { } else if sType == "udp" { svcLock.Lock() - key := SvcKey{Dst: svcPair[0], Port: svcPort} + key := SvcKey{Dst: netAddr, Port: svcPort} svcWait := svcs[key] if svcWait == nil { svcWait = &SvcWait{wait: make(chan bool)} @@ -245,7 +291,12 @@ func L4ServiceProber(sType string, sName string, sHint, req, resp string) bool { return sOk } - _, unRch := waitForBoolChannelOrTimeout(svcWait.wait, 1*time.Second) + period := 1 * time.Second + if IsNetIPv6(netAddr) { + period = 3 * time.Second + } + + _, unRch := waitForBoolChannelOrTimeout(svcWait.wait, period) if unRch { sOk = false }