package vip import ( "errors" "github.com/vishvananda/netlink" "net" ) 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 { 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{iface, label, 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 { 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 } return ARPSendGratuitous(cidr, n.iface) } func (n *Network) DeleteIP(cidr string) error { addr, err := netlink.ParseAddr(cidr) if err != nil { return err } if !n.HasIP(addr) { return nil } return netlink.AddrDel(n.link, addr) }