// network interfaces. Otheriwse it returns a mapping of a specific
// interface.
func interfaceTable(ifindex int) ([]Interface, error) {
- var (
- tab []byte
- e error
- msgs []syscall.RoutingMessage
- ift []Interface
- )
-
- tab, e = syscall.RouteRIB(syscall.NET_RT_IFLIST, ifindex)
- if e != nil {
- return nil, os.NewSyscallError("route rib", e)
+ var ift []Interface
+
+ tab, err := syscall.RouteRIB(syscall.NET_RT_IFLIST, ifindex)
+ if err != nil {
+ return nil, os.NewSyscallError("route rib", err)
}
- msgs, e = syscall.ParseRoutingMessage(tab)
- if e != nil {
- return nil, os.NewSyscallError("route message", e)
+ msgs, err := syscall.ParseRoutingMessage(tab)
+ if err != nil {
+ return nil, os.NewSyscallError("route message", err)
}
for _, m := range msgs {
func newLink(m *syscall.InterfaceMessage) ([]Interface, error) {
var ift []Interface
- sas, e := syscall.ParseRoutingSockaddr(m)
- if e != nil {
- return nil, os.NewSyscallError("route sockaddr", e)
+ sas, err := syscall.ParseRoutingSockaddr(m)
+ if err != nil {
+ return nil, os.NewSyscallError("route sockaddr", err)
}
for _, s := range sas {
// for all network interfaces. Otherwise it returns addresses
// for a specific interface.
func interfaceAddrTable(ifindex int) ([]Addr, error) {
- var (
- tab []byte
- e error
- msgs []syscall.RoutingMessage
- ifat []Addr
- )
-
- tab, e = syscall.RouteRIB(syscall.NET_RT_IFLIST, ifindex)
- if e != nil {
- return nil, os.NewSyscallError("route rib", e)
+ var ifat []Addr
+
+ tab, err := syscall.RouteRIB(syscall.NET_RT_IFLIST, ifindex)
+ if err != nil {
+ return nil, os.NewSyscallError("route rib", err)
}
- msgs, e = syscall.ParseRoutingMessage(tab)
- if e != nil {
- return nil, os.NewSyscallError("route message", e)
+ msgs, err := syscall.ParseRoutingMessage(tab)
+ if err != nil {
+ return nil, os.NewSyscallError("route message", err)
}
for _, m := range msgs {
if err != nil {
return nil, err
}
- ifat = append(ifat, ifa...)
+ ifat = append(ifat, ifa)
}
}
}
return ifat, nil
}
-func newAddr(m *syscall.InterfaceAddrMessage) ([]Addr, error) {
- var ifat []Addr
+func newAddr(m *syscall.InterfaceAddrMessage) (Addr, error) {
+ ifa := &IPNet{}
- sas, e := syscall.ParseRoutingSockaddr(m)
- if e != nil {
- return nil, os.NewSyscallError("route sockaddr", e)
+ sas, err := syscall.ParseRoutingSockaddr(m)
+ if err != nil {
+ return nil, os.NewSyscallError("route sockaddr", err)
}
- for _, s := range sas {
+ for i, s := range sas {
switch v := s.(type) {
case *syscall.SockaddrInet4:
- ifa := &IPAddr{IP: IPv4(v.Addr[0], v.Addr[1], v.Addr[2], v.Addr[3])}
- ifat = append(ifat, ifa.toAddr())
+ switch i {
+ case 0:
+ ifa.Mask = IPv4Mask(v.Addr[0], v.Addr[1], v.Addr[2], v.Addr[3])
+ case 1:
+ ifa.IP = IPv4(v.Addr[0], v.Addr[1], v.Addr[2], v.Addr[3])
+ }
case *syscall.SockaddrInet6:
- ifa := &IPAddr{IP: make(IP, IPv6len)}
- copy(ifa.IP, v.Addr[:])
- // NOTE: KAME based IPv6 protcol stack usually embeds
- // the interface index in the interface-local or link-
- // local address as the kernel-internal form.
- if ifa.IP.IsLinkLocalUnicast() {
- // remove embedded scope zone ID
- ifa.IP[2], ifa.IP[3] = 0, 0
+ switch i {
+ case 0:
+ ifa.Mask = make(IPMask, IPv6len)
+ copy(ifa.Mask, v.Addr[:])
+ case 1:
+ ifa.IP = make(IP, IPv6len)
+ copy(ifa.IP, v.Addr[:])
+ // NOTE: KAME based IPv6 protcol stack usually embeds
+ // the interface index in the interface-local or link-
+ // local address as the kernel-internal form.
+ if ifa.IP.IsLinkLocalUnicast() {
+ // remove embedded scope zone ID
+ ifa.IP[2], ifa.IP[3] = 0, 0
+ }
}
- ifat = append(ifat, ifa.toAddr())
}
}
- return ifat, nil
+ return ifa, nil
}
// network interfaces. Otheriwse it returns a mapping of a specific
// interface.
func interfaceTable(ifindex int) ([]Interface, error) {
- var (
- ift []Interface
- tab []byte
- msgs []syscall.NetlinkMessage
- e error
- )
+ var ift []Interface
- tab, e = syscall.NetlinkRIB(syscall.RTM_GETLINK, syscall.AF_UNSPEC)
- if e != nil {
- return nil, os.NewSyscallError("netlink rib", e)
+ tab, err := syscall.NetlinkRIB(syscall.RTM_GETLINK, syscall.AF_UNSPEC)
+ if err != nil {
+ return nil, os.NewSyscallError("netlink rib", err)
}
- msgs, e = syscall.ParseNetlinkMessage(tab)
- if e != nil {
- return nil, os.NewSyscallError("netlink message", e)
+ msgs, err := syscall.ParseNetlinkMessage(tab)
+ if err != nil {
+ return nil, os.NewSyscallError("netlink message", err)
}
for _, m := range msgs {
case syscall.RTM_NEWLINK:
ifim := (*syscall.IfInfomsg)(unsafe.Pointer(&m.Data[0]))
if ifindex == 0 || ifindex == int(ifim.Index) {
- attrs, e := syscall.ParseNetlinkRouteAttr(&m)
- if e != nil {
- return nil, os.NewSyscallError("netlink routeattr", e)
+ attrs, err := syscall.ParseNetlinkRouteAttr(&m)
+ if err != nil {
+ return nil, os.NewSyscallError("netlink routeattr", err)
}
- ifi := newLink(attrs, ifim)
+ ifi := newLink(ifim, attrs)
ift = append(ift, ifi)
}
}
return ift, nil
}
-func newLink(attrs []syscall.NetlinkRouteAttr, ifim *syscall.IfInfomsg) Interface {
+func newLink(ifim *syscall.IfInfomsg, attrs []syscall.NetlinkRouteAttr) Interface {
ifi := Interface{Index: int(ifim.Index), Flags: linkFlags(ifim.Flags)}
for _, a := range attrs {
switch a.Attr.Type {
// for all network interfaces. Otherwise it returns addresses
// for a specific interface.
func interfaceAddrTable(ifindex int) ([]Addr, error) {
- tab, e := syscall.NetlinkRIB(syscall.RTM_GETADDR, syscall.AF_UNSPEC)
- if e != nil {
- return nil, os.NewSyscallError("netlink rib", e)
+ tab, err := syscall.NetlinkRIB(syscall.RTM_GETADDR, syscall.AF_UNSPEC)
+ if err != nil {
+ return nil, os.NewSyscallError("netlink rib", err)
}
- msgs, e := syscall.ParseNetlinkMessage(tab)
- if e != nil {
- return nil, os.NewSyscallError("netlink message", e)
+ msgs, err := syscall.ParseNetlinkMessage(tab)
+ if err != nil {
+ return nil, os.NewSyscallError("netlink message", err)
}
- ifat, e := addrTable(msgs, ifindex)
- if e != nil {
- return nil, e
+ ifat, err := addrTable(msgs, ifindex)
+ if err != nil {
+ return nil, err
}
return ifat, nil
case syscall.RTM_NEWADDR:
ifam := (*syscall.IfAddrmsg)(unsafe.Pointer(&m.Data[0]))
if ifindex == 0 || ifindex == int(ifam.Index) {
- attrs, e := syscall.ParseNetlinkRouteAttr(&m)
- if e != nil {
- return nil, os.NewSyscallError("netlink routeattr", e)
+ attrs, err := syscall.ParseNetlinkRouteAttr(&m)
+ if err != nil {
+ return nil, os.NewSyscallError("netlink routeattr", err)
}
- ifat = append(ifat, newAddr(attrs, int(ifam.Family))...)
+ ifat = append(ifat, newAddr(attrs, int(ifam.Family), int(ifam.Prefixlen)))
}
}
}
return ifat, nil
}
-func newAddr(attrs []syscall.NetlinkRouteAttr, family int) []Addr {
- var ifat []Addr
-
+func newAddr(attrs []syscall.NetlinkRouteAttr, family, pfxlen int) Addr {
+ ifa := &IPNet{}
for _, a := range attrs {
switch a.Attr.Type {
case syscall.IFA_ADDRESS:
switch family {
case syscall.AF_INET:
- ifa := &IPAddr{IP: IPv4(a.Value[0], a.Value[1], a.Value[2], a.Value[3])}
- ifat = append(ifat, ifa.toAddr())
+ ifa.IP = IPv4(a.Value[0], a.Value[1], a.Value[2], a.Value[3])
+ ifa.Mask = CIDRMask(pfxlen, 8*IPv4len)
case syscall.AF_INET6:
- ifa := &IPAddr{IP: make(IP, IPv6len)}
+ ifa.IP = make(IP, IPv6len)
copy(ifa.IP, a.Value[:])
- ifat = append(ifat, ifa.toAddr())
+ ifa.Mask = CIDRMask(pfxlen, 8*IPv6len)
}
}
}
-
- return ifat
+ return ifa
}
// If the ifindex is zero, interfaceMulticastAddrTable returns
// addresses for a specific interface.
func interfaceMulticastAddrTable(ifindex int) ([]Addr, error) {
var (
- ifi *Interface
err error
+ ifi *Interface
)
if ifindex > 0 {
func TestInterfaces(t *testing.T) {
ift, err := Interfaces()
if err != nil {
- t.Fatalf("Interfaces() failed: %v", err)
+ t.Fatalf("Interfaces failed: %v", err)
}
t.Logf("table: len/cap = %v/%v\n", len(ift), cap(ift))
if !sameInterface(ifxn, &ifi) {
t.Fatalf("InterfaceByName(%#q) = %v, want %v", ifi.Name, *ifxn, ifi)
}
- ifat, err := ifi.Addrs()
- if err != nil {
- t.Fatalf("Interface.Addrs() failed: %v", err)
- }
- ifmat, err := ifi.MulticastAddrs()
- if err != nil {
- t.Fatalf("Interface.MulticastAddrs() failed: %v", err)
- }
t.Logf("%q: flags %q, ifindex %v, mtu %v\n", ifi.Name, ifi.Flags.String(), ifi.Index, ifi.MTU)
- for _, ifa := range ifat {
- t.Logf("\tinterface address %q\n", ifa.String())
- }
- for _, ifma := range ifmat {
- t.Logf("\tjoined group address %q\n", ifma.String())
- }
t.Logf("\thardware address %q", ifi.HardwareAddr.String())
+ testInterfaceAddrs(t, &ifi)
+ testInterfaceMulticastAddrs(t, &ifi)
}
}
func TestInterfaceAddrs(t *testing.T) {
ifat, err := InterfaceAddrs()
if err != nil {
- t.Fatalf("InterfaceAddrs() failed: %v", err)
+ t.Fatalf("InterfaceAddrs failed: %v", err)
}
t.Logf("table: len/cap = %v/%v\n", len(ifat), cap(ifat))
+ testAddrs(t, ifat)
+}
+
+func testInterfaceAddrs(t *testing.T, ifi *Interface) {
+ ifat, err := ifi.Addrs()
+ if err != nil {
+ t.Fatalf("Interface.Addrs failed: %v", err)
+ }
+ testAddrs(t, ifat)
+}
+
+func testInterfaceMulticastAddrs(t *testing.T, ifi *Interface) {
+ ifmat, err := ifi.MulticastAddrs()
+ if err != nil {
+ t.Fatalf("Interface.MulticastAddrs failed: %v", err)
+ }
+ testMulticastAddrs(t, ifmat)
+}
+func testAddrs(t *testing.T, ifat []Addr) {
for _, ifa := range ifat {
- t.Logf("interface address %q\n", ifa.String())
+ switch ifa.(type) {
+ case *IPAddr, *IPNet:
+ t.Logf("\tinterface address %q\n", ifa.String())
+ default:
+ t.Errorf("\tunexpected type: %T", ifa)
+ }
+ }
+}
+
+func testMulticastAddrs(t *testing.T, ifmat []Addr) {
+ for _, ifma := range ifmat {
+ switch ifma.(type) {
+ case *IPAddr:
+ t.Logf("\tjoined group address %q\n", ifma.String())
+ default:
+ t.Errorf("\tunexpected type: %T", ifma)
+ }
}
}
return nn.String() + "/" + itod(uint(l))
}
+// Network returns the address's network name, "ip+net".
+func (n *IPNet) Network() string { return "ip+net" }
+
// Parse IPv4 address (d.d.d.d).
func parseIPv4(s string) IP {
var p [IPv4len]byte
rsa := (*RawSockaddr)(unsafe.Pointer(&buf[0]))
switch i {
case RTAX_DST, RTAX_GATEWAY:
- sa, e := anyToSockaddr((*RawSockaddrAny)(unsafe.Pointer(rsa)))
- if e != nil {
+ sa, err := anyToSockaddr((*RawSockaddrAny)(unsafe.Pointer(rsa)))
+ if err != nil {
return nil
}
if i == RTAX_DST {
if m.Header.Addrs&RTA_IFP == 0 {
return nil
}
- sa, e := anyToSockaddr((*RawSockaddrAny)(unsafe.Pointer(&m.Data[0])))
- if e != nil {
+ sa, err := anyToSockaddr((*RawSockaddrAny)(unsafe.Pointer(&m.Data[0])))
+ if err != nil {
return nil
}
return append(sas, sa)
rsa := (*RawSockaddr)(unsafe.Pointer(&buf[0]))
switch i {
case RTAX_IFA:
- sa, e := anyToSockaddr((*RawSockaddrAny)(unsafe.Pointer(rsa)))
- if e != nil {
+ sa, err := anyToSockaddr((*RawSockaddrAny)(unsafe.Pointer(rsa)))
+ if err != nil {
return nil
}
sas = append(sas, sa)
- case RTAX_NETMASK, RTAX_BRD:
+ case RTAX_NETMASK:
+ if rsa.Family == AF_UNSPEC {
+ rsa.Family = AF_INET // an old fasion, AF_UNSPEC means AF_INET
+ }
+ sa, err := anyToSockaddr((*RawSockaddrAny)(unsafe.Pointer(rsa)))
+ if err != nil {
+ return nil
+ }
+ sas = append(sas, sa)
+ case RTAX_BRD:
// nothing to do
}
buf = buf[rsaAlignOf(int(rsa.Len)):]