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 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
|
//go:build integration
// +build integration
package rtnl
import (
"errors"
"net"
"syscall"
"testing"
"github.com/mdlayher/netlink"
)
var errNoLoopback = errors.New("no loopback interface")
func loopbackInterface(c *Conn) (*net.Interface, error) {
links, err := c.Links()
if err != nil {
return nil, err
}
for _, ifc := range links {
if ifc.Flags&net.FlagLoopback != 0 {
return ifc, nil
}
}
return nil, errNoLoopback
}
func interfaceHasAddr(c *Conn, ifc *net.Interface, addr *net.IPNet) (bool, error) {
addrs, err := c.Addrs(ifc, 0)
if err != nil {
return false, err
}
for _, a := range addrs {
if ipnetEqual(a, addr) {
return true, nil
}
}
return false, nil
}
func ipnetEqual(a, b *net.IPNet) bool {
na, _ := a.Mask.Size()
nb, _ := b.Mask.Size()
return na == nb && a.IP.Equal(b.IP)
}
func TestLiveAddrs(t *testing.T) {
c, err := Dial(nil)
if err != nil {
t.Fatal(err)
}
defer c.Close()
addrs, err := c.Addrs(nil, 0)
if err != nil {
t.Fatal(err)
}
if len(addrs) == 0 {
t.Skip("no network addresses")
}
for i, a := range addrs {
t.Logf("* entry %d: %#v", i, a)
if a == nil {
t.Error("nil address result")
continue
}
if a.IP.IsUnspecified() {
t.Error("address unspecified")
}
if a.Mask == nil {
t.Error("mask unspecified")
} else {
ones, bits := a.Mask.Size()
if bits != 8*net.IPv4len && bits != 8*net.IPv6len {
t.Error("bad mask length")
}
if ones == 0 || ones > bits {
t.Error("bad prefix length")
}
}
}
}
func TestLiveAddrAddDel(t *testing.T) {
c, err := Dial(nil)
if err != nil {
t.Fatal(err)
}
defer c.Close()
lo, err := loopbackInterface(c)
if err != nil {
t.Skip(err)
}
if lo == nil {
t.Fatal("no error but nil result")
}
testip := MustParseAddr("127.0.0.99/32")
c.AddrDel(lo, testip) // ok if fails
if err := c.AddrAdd(lo, testip); err != nil {
// requires specific privilege - skip the test if can't do
if v, ok := err.(*netlink.OpError); ok && v.Err == syscall.EPERM {
t.Skip("AddrAdd: ", err)
}
t.Fatal("AddrAdd:", err)
}
// if the above suceeded, everything below should do, too
ok, err := interfaceHasAddr(c, lo, testip)
if err != nil {
t.Error(err)
} else if !ok {
t.Error("address reported as added but can't confirm")
}
if err := c.AddrDel(lo, testip); err != nil {
t.Error("AddrDel: ", err)
}
}
|