engine: mac: more ipv6 gm
Some checks failed
Quality check / Static analysis (push) Has been cancelled
Quality check / Tests (push) Has been cancelled

This commit is contained in:
2026-02-11 12:19:45 +05:30
parent ef00ca1793
commit 9c2786212b

View File

@@ -4,10 +4,12 @@ import (
"bufio" "bufio"
"net" "net"
"os" "os"
"os/exec"
"strings" "strings"
"sync" "sync"
"time" "time"
"github.com/mdlayher/netlink"
"golang.org/x/sys/unix"
) )
const ( const (
@@ -166,7 +168,7 @@ func (r *sourceMACResolver) refreshNDPCache(now time.Time) {
m, ok := readNeighborCacheFile("/proc/net/ndisc_cache") m, ok := readNeighborCacheFile("/proc/net/ndisc_cache")
if !ok || len(m) == 0 { if !ok || len(m) == 0 {
// Fallback for environments without /proc/net/ndisc_cache. // Fallback for environments without /proc/net/ndisc_cache.
m = readIPv6NeighCommand() m = readIPv6NeighNetlink()
} }
r.mu.Lock() r.mu.Lock()
r.ndpByIP = m r.ndpByIP = m
@@ -196,19 +198,63 @@ func readNeighborCacheFile(path string) (map[string]net.HardwareAddr, bool) {
return m, true return m, true
} }
func readIPv6NeighCommand() map[string]net.HardwareAddr { func readIPv6NeighNetlink() map[string]net.HardwareAddr {
const (
ndMsgLen = 12
ndaDst = 1
ndaLLAddr = 2
)
m := make(map[string]net.HardwareAddr) m := make(map[string]net.HardwareAddr)
out, err := exec.Command("ip", "-6", "neigh", "show").Output() conn, err := netlink.Dial(unix.NETLINK_ROUTE, nil)
if err != nil { if err != nil {
return m return m
} }
for _, line := range strings.Split(string(out), "\n") { defer conn.Close()
ip, mac, ok := parseNeighborLine(line)
if !ok { req := make([]byte, ndMsgLen)
req[0] = unix.AF_INET6
msgs, err := conn.Execute(netlink.Message{
Header: netlink.Header{
Type: unix.RTM_GETNEIGH,
Flags: netlink.Request | netlink.Dump,
},
Data: req,
})
if err != nil {
return m
}
for _, msg := range msgs {
if msg.Header.Type != unix.RTM_NEWNEIGH || len(msg.Data) < ndMsgLen || msg.Data[0] != unix.AF_INET6 {
continue continue
} }
m[ip] = mac attrs, err := netlink.UnmarshalAttributes(msg.Data[ndMsgLen:])
if err != nil {
continue
}
var ipStr string
var mac net.HardwareAddr
for _, a := range attrs {
switch a.Type {
case ndaDst:
if len(a.Data) == net.IPv6len {
ipStr = net.IP(append([]byte(nil), a.Data...)).String()
}
case ndaLLAddr:
if len(a.Data) >= 6 {
candidate := append(net.HardwareAddr(nil), a.Data...)
if candidate.String() != "00:00:00:00:00:00" {
mac = candidate
}
}
}
}
if ipStr != "" && len(mac) != 0 {
m[ipStr] = mac
}
} }
return m return m
} }