1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
|
package rtnl
import (
"net"
"github.com/jsimonetti/rtnetlink/v2"
)
// Neigh represents a neighbour table entry (e.g. an entry in the ARP table)
type Neigh struct {
HwAddr net.HardwareAddr // Link-layer address
IP net.IP // Network-layer address
Interface *net.Interface // Network interface
// Bitfield representing the state of the neighbor entry,
// corresponding to the NUD_ constants.
State uint16
}
// Neighbours lists entries from the neighbor table (e.g. the ARP table).
func (c *Conn) Neighbours(ifc *net.Interface, family int) (r []*Neigh, err error) {
rx, err := c.Conn.Neigh.List()
if err != nil {
return nil, err
}
match := func(v *rtnetlink.NeighMessage, ifc *net.Interface, family int) bool {
if ifc != nil && v.Index != uint32(ifc.Index) {
return false
}
if family != 0 && v.Family != uint16(family) {
return false
}
return true
}
ifcache := map[int]*net.Interface{}
for _, m := range rx {
if !match(&m, ifc, family) {
continue
}
ifindex := int(m.Index)
iface, ok := ifcache[ifindex]
if !ok {
iface, err = c.LinkByIndex(ifindex)
if err != nil {
// Received a neigh entry for a link that no longer exists, so we cannot
// populate the Interface field. Skip the entry.
continue
}
ifcache[ifindex] = iface
}
p := &Neigh{
HwAddr: m.Attributes.LLAddress,
IP: m.Attributes.Address,
Interface: iface,
State: m.State,
}
r = append(r, p)
}
return r, nil
}
|