engine: mac: more ipv6 gm
This commit is contained in:
@@ -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
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user