From 9c2786212b009a232527d939d4317d53d4997799 Mon Sep 17 00:00:00 2001 From: hayzam Date: Wed, 11 Feb 2026 12:19:45 +0530 Subject: [PATCH] engine: mac: more ipv6 gm --- engine/mac_resolver.go | 62 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 54 insertions(+), 8 deletions(-) diff --git a/engine/mac_resolver.go b/engine/mac_resolver.go index cedda40..1c8d985 100644 --- a/engine/mac_resolver.go +++ b/engine/mac_resolver.go @@ -4,10 +4,12 @@ import ( "bufio" "net" "os" - "os/exec" "strings" "sync" "time" + + "github.com/mdlayher/netlink" + "golang.org/x/sys/unix" ) const ( @@ -166,7 +168,7 @@ func (r *sourceMACResolver) refreshNDPCache(now time.Time) { m, ok := readNeighborCacheFile("/proc/net/ndisc_cache") if !ok || len(m) == 0 { // Fallback for environments without /proc/net/ndisc_cache. - m = readIPv6NeighCommand() + m = readIPv6NeighNetlink() } r.mu.Lock() r.ndpByIP = m @@ -196,19 +198,63 @@ func readNeighborCacheFile(path string) (map[string]net.HardwareAddr, bool) { 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) - out, err := exec.Command("ip", "-6", "neigh", "show").Output() + conn, err := netlink.Dial(unix.NETLINK_ROUTE, nil) if err != nil { return m } - for _, line := range strings.Split(string(out), "\n") { - ip, mac, ok := parseNeighborLine(line) - if !ok { + defer conn.Close() + + 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 } - 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 }