2015-09-02 19:42:01 -04:00
|
|
|
package osl
|
2015-06-20 20:08:36 -04:00
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"fmt"
|
|
|
|
"net"
|
|
|
|
|
|
|
|
"github.com/vishvananda/netlink"
|
|
|
|
)
|
|
|
|
|
|
|
|
// NeighOption is a function option type to set interface options
|
|
|
|
type NeighOption func(nh *neigh)
|
|
|
|
|
|
|
|
type neigh struct {
|
|
|
|
dstIP net.IP
|
|
|
|
dstMac net.HardwareAddr
|
|
|
|
linkName string
|
|
|
|
linkDst string
|
|
|
|
family int
|
|
|
|
}
|
|
|
|
|
|
|
|
func (n *networkNamespace) findNeighbor(dstIP net.IP, dstMac net.HardwareAddr) *neigh {
|
|
|
|
n.Lock()
|
|
|
|
defer n.Unlock()
|
|
|
|
|
|
|
|
for _, nh := range n.neighbors {
|
|
|
|
if nh.dstIP.Equal(dstIP) && bytes.Equal(nh.dstMac, dstMac) {
|
|
|
|
return nh
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2016-09-20 21:21:19 -04:00
|
|
|
func (n *networkNamespace) DeleteNeighbor(dstIP net.IP, dstMac net.HardwareAddr, osDelete bool) error {
|
2016-06-07 17:28:28 -04:00
|
|
|
var (
|
|
|
|
iface netlink.Link
|
|
|
|
err error
|
|
|
|
)
|
|
|
|
|
2015-06-20 20:08:36 -04:00
|
|
|
nh := n.findNeighbor(dstIP, dstMac)
|
|
|
|
if nh == nil {
|
|
|
|
return fmt.Errorf("could not find the neighbor entry to delete")
|
|
|
|
}
|
|
|
|
|
2016-09-20 21:21:19 -04:00
|
|
|
if osDelete {
|
|
|
|
n.Lock()
|
|
|
|
nlh := n.nlHandle
|
|
|
|
n.Unlock()
|
|
|
|
|
|
|
|
if nh.linkDst != "" {
|
|
|
|
iface, err = nlh.LinkByName(nh.linkDst)
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("could not find interface with destination name %s: %v",
|
|
|
|
nh.linkDst, err)
|
|
|
|
}
|
2015-06-20 20:08:36 -04:00
|
|
|
}
|
|
|
|
|
2016-09-20 21:21:19 -04:00
|
|
|
nlnh := &netlink.Neigh{
|
|
|
|
IP: dstIP,
|
|
|
|
State: netlink.NUD_PERMANENT,
|
|
|
|
Family: nh.family,
|
|
|
|
}
|
2015-06-20 20:08:36 -04:00
|
|
|
|
2016-09-20 21:21:19 -04:00
|
|
|
if nlnh.Family > 0 {
|
|
|
|
nlnh.HardwareAddr = dstMac
|
|
|
|
nlnh.Flags = netlink.NTF_SELF
|
|
|
|
}
|
2015-06-20 20:08:36 -04:00
|
|
|
|
2016-09-20 21:21:19 -04:00
|
|
|
if nh.linkDst != "" {
|
|
|
|
nlnh.LinkIndex = iface.Attrs().Index
|
|
|
|
}
|
2015-06-20 20:08:36 -04:00
|
|
|
|
2016-09-20 21:21:19 -04:00
|
|
|
if err := nlh.NeighDel(nlnh); err != nil {
|
|
|
|
return fmt.Errorf("could not delete neighbor entry: %v", err)
|
|
|
|
}
|
2016-06-07 17:28:28 -04:00
|
|
|
}
|
2015-06-20 20:08:36 -04:00
|
|
|
|
2016-09-20 21:21:19 -04:00
|
|
|
n.Lock()
|
2016-06-07 17:28:28 -04:00
|
|
|
for i, nh := range n.neighbors {
|
|
|
|
if nh.dstIP.Equal(dstIP) && bytes.Equal(nh.dstMac, dstMac) {
|
|
|
|
n.neighbors = append(n.neighbors[:i], n.neighbors[i+1:]...)
|
2016-11-19 19:03:22 -05:00
|
|
|
break
|
2015-06-20 20:08:36 -04:00
|
|
|
}
|
2016-06-07 17:28:28 -04:00
|
|
|
}
|
2016-09-20 21:21:19 -04:00
|
|
|
n.Unlock()
|
2015-06-20 20:08:36 -04:00
|
|
|
|
2016-06-07 17:28:28 -04:00
|
|
|
return nil
|
2015-06-20 20:08:36 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
func (n *networkNamespace) AddNeighbor(dstIP net.IP, dstMac net.HardwareAddr, options ...NeighOption) error {
|
2016-06-07 17:28:28 -04:00
|
|
|
var (
|
|
|
|
iface netlink.Link
|
|
|
|
err error
|
|
|
|
)
|
|
|
|
|
2015-06-20 20:08:36 -04:00
|
|
|
nh := n.findNeighbor(dstIP, dstMac)
|
|
|
|
if nh != nil {
|
|
|
|
// If it exists silently return
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
nh = &neigh{
|
|
|
|
dstIP: dstIP,
|
|
|
|
dstMac: dstMac,
|
|
|
|
}
|
|
|
|
|
|
|
|
nh.processNeighOptions(options...)
|
|
|
|
|
|
|
|
if nh.linkName != "" {
|
|
|
|
nh.linkDst = n.findDst(nh.linkName, false)
|
|
|
|
if nh.linkDst == "" {
|
|
|
|
return fmt.Errorf("could not find the interface with name %s", nh.linkName)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-06-07 17:28:28 -04:00
|
|
|
n.Lock()
|
|
|
|
nlh := n.nlHandle
|
|
|
|
n.Unlock()
|
|
|
|
|
|
|
|
if nh.linkDst != "" {
|
|
|
|
iface, err = nlh.LinkByName(nh.linkDst)
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("could not find interface with destination name %s: %v",
|
|
|
|
nh.linkDst, err)
|
2015-06-20 20:08:36 -04:00
|
|
|
}
|
2016-06-07 17:28:28 -04:00
|
|
|
}
|
2015-06-20 20:08:36 -04:00
|
|
|
|
2016-06-07 17:28:28 -04:00
|
|
|
nlnh := &netlink.Neigh{
|
|
|
|
IP: dstIP,
|
|
|
|
HardwareAddr: dstMac,
|
|
|
|
State: netlink.NUD_PERMANENT,
|
|
|
|
Family: nh.family,
|
|
|
|
}
|
2015-06-20 20:08:36 -04:00
|
|
|
|
2016-06-07 17:28:28 -04:00
|
|
|
if nlnh.Family > 0 {
|
|
|
|
nlnh.Flags = netlink.NTF_SELF
|
|
|
|
}
|
2015-06-20 20:08:36 -04:00
|
|
|
|
2016-06-07 17:28:28 -04:00
|
|
|
if nh.linkDst != "" {
|
|
|
|
nlnh.LinkIndex = iface.Attrs().Index
|
|
|
|
}
|
2015-06-20 20:08:36 -04:00
|
|
|
|
2016-06-07 17:28:28 -04:00
|
|
|
if err := nlh.NeighSet(nlnh); err != nil {
|
|
|
|
return fmt.Errorf("could not add neighbor entry: %v", err)
|
|
|
|
}
|
2015-06-20 20:08:36 -04:00
|
|
|
|
2016-06-07 17:28:28 -04:00
|
|
|
n.neighbors = append(n.neighbors, nh)
|
2015-06-20 20:08:36 -04:00
|
|
|
|
2016-06-07 17:28:28 -04:00
|
|
|
return nil
|
2015-06-20 20:08:36 -04:00
|
|
|
}
|