127 lines
2.1 KiB
Go
127 lines
2.1 KiB
Go
package vip
|
|
|
|
import (
|
|
"errors"
|
|
"net"
|
|
"sync"
|
|
|
|
"github.com/vishvananda/netlink"
|
|
)
|
|
|
|
var ErrNoDefaultInterface = errors.New("no default interface found")
|
|
|
|
func DefaultInterface() (iface string, err error) {
|
|
routes, err := netlink.RouteGet(net.IPv4bcast)
|
|
if err != nil {
|
|
return
|
|
}
|
|
if len(routes) >= 1 {
|
|
link, err := netlink.LinkByIndex(routes[0].LinkIndex)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
return link.Attrs().Name, nil
|
|
}
|
|
err = ErrNoDefaultInterface
|
|
return
|
|
}
|
|
|
|
type Network struct {
|
|
mu sync.Mutex
|
|
m map[string]struct{}
|
|
iface string
|
|
label string
|
|
link netlink.Link
|
|
}
|
|
|
|
func NewNetwork(iface string) (n *Network, err error) {
|
|
return NewNetworkWithLabel(iface, "")
|
|
}
|
|
|
|
func NewNetworkWithLabel(iface, label string) (n *Network, err error) {
|
|
if iface == "" {
|
|
iface, err = DefaultInterface()
|
|
if err != nil {
|
|
return
|
|
}
|
|
}
|
|
link, err := netlink.LinkByName(iface)
|
|
if err != nil {
|
|
return
|
|
}
|
|
n = &Network{
|
|
m: make(map[string]struct{}),
|
|
iface: iface,
|
|
label: label,
|
|
link: link,
|
|
}
|
|
return
|
|
}
|
|
|
|
func (n *Network) Interface() string {
|
|
return n.iface
|
|
}
|
|
|
|
func (n *Network) HasIP(a *netlink.Addr) bool {
|
|
addrs, err := netlink.AddrList(n.link, 0)
|
|
if err != nil {
|
|
return false
|
|
}
|
|
for _, addr := range addrs {
|
|
if addr.Equal(*a) {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
func (n *Network) AddIP(cidr string) error {
|
|
n.mu.Lock()
|
|
defer n.mu.Unlock()
|
|
addr, err := netlink.ParseAddr(cidr)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if n.HasIP(addr) {
|
|
return nil
|
|
}
|
|
if n.label != "" {
|
|
addr.Label = n.iface + ":" + n.label
|
|
}
|
|
err = netlink.AddrReplace(n.link, addr)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
n.m[cidr] = struct{}{}
|
|
return ARPSendGratuitous(cidr, n.iface)
|
|
}
|
|
|
|
func (n *Network) DeleteIP(cidr string) error {
|
|
n.mu.Lock()
|
|
defer n.mu.Unlock()
|
|
addr, err := netlink.ParseAddr(cidr)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if !n.HasIP(addr) {
|
|
return nil
|
|
}
|
|
err = netlink.AddrDel(n.link, addr)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
delete(n.m, cidr)
|
|
return nil
|
|
}
|
|
|
|
func (n *Network) GetIPs() (cidrs []string) {
|
|
n.mu.Lock()
|
|
defer n.mu.Unlock()
|
|
cidrs = make([]string, len(n.m))
|
|
c := 0
|
|
for k := range n.m {
|
|
cidrs[c] = k
|
|
c++
|
|
}
|
|
return
|
|
}
|