1 // Copyright 2011 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
5 // +build darwin freebsd netbsd openbsd
7 // Network interface identification for BSD variants
17 // If the ifindex is zero, interfaceTable returns mappings of all
18 // network interfaces. Otherwise it returns a mapping of a specific
20 func interfaceTable(ifindex int) ([]Interface, error) {
21 tab, err := syscall.RouteRIB(syscall.NET_RT_IFLIST, ifindex)
23 return nil, os.NewSyscallError("route rib", err)
26 msgs, err := syscall.ParseRoutingMessage(tab)
28 return nil, os.NewSyscallError("route message", err)
32 for _, m := range msgs {
33 switch v := m.(type) {
34 case *syscall.InterfaceMessage:
35 if ifindex == 0 || ifindex == int(v.Header.Index) {
36 ifi, err := newLink(v)
40 ift = append(ift, ifi...)
47 func newLink(m *syscall.InterfaceMessage) ([]Interface, error) {
48 sas, err := syscall.ParseRoutingSockaddr(m)
50 return nil, os.NewSyscallError("route sockaddr", err)
54 for _, s := range sas {
55 switch v := s.(type) {
56 case *syscall.SockaddrDatalink:
57 // NOTE: SockaddrDatalink.Data is minimum work area,
59 m.Data = m.Data[unsafe.Offsetof(v.Data):]
60 ifi := Interface{Index: int(m.Header.Index), Flags: linkFlags(m.Header.Flags)}
61 var name [syscall.IFNAMSIZ]byte
62 for i := 0; i < int(v.Nlen); i++ {
63 name[i] = byte(m.Data[i])
65 ifi.Name = string(name[:v.Nlen])
66 ifi.MTU = int(m.Header.Data.Mtu)
67 addr := make([]byte, v.Alen)
68 for i := 0; i < int(v.Alen); i++ {
69 addr[i] = byte(m.Data[int(v.Nlen)+i])
71 ifi.HardwareAddr = addr[:v.Alen]
72 ift = append(ift, ifi)
78 func linkFlags(rawFlags int32) Flags {
80 if rawFlags&syscall.IFF_UP != 0 {
83 if rawFlags&syscall.IFF_BROADCAST != 0 {
86 if rawFlags&syscall.IFF_LOOPBACK != 0 {
89 if rawFlags&syscall.IFF_POINTOPOINT != 0 {
92 if rawFlags&syscall.IFF_MULTICAST != 0 {
98 // If the ifindex is zero, interfaceAddrTable returns addresses
99 // for all network interfaces. Otherwise it returns addresses
100 // for a specific interface.
101 func interfaceAddrTable(ifindex int) ([]Addr, error) {
102 tab, err := syscall.RouteRIB(syscall.NET_RT_IFLIST, ifindex)
104 return nil, os.NewSyscallError("route rib", err)
107 msgs, err := syscall.ParseRoutingMessage(tab)
109 return nil, os.NewSyscallError("route message", err)
113 for _, m := range msgs {
114 switch v := m.(type) {
115 case *syscall.InterfaceAddrMessage:
116 if ifindex == 0 || ifindex == int(v.Header.Index) {
117 ifa, err := newAddr(v)
121 ifat = append(ifat, ifa)
128 func newAddr(m *syscall.InterfaceAddrMessage) (Addr, error) {
129 sas, err := syscall.ParseRoutingSockaddr(m)
131 return nil, os.NewSyscallError("route sockaddr", err)
135 for i, s := range sas {
136 switch v := s.(type) {
137 case *syscall.SockaddrInet4:
140 ifa.Mask = IPv4Mask(v.Addr[0], v.Addr[1], v.Addr[2], v.Addr[3])
142 ifa.IP = IPv4(v.Addr[0], v.Addr[1], v.Addr[2], v.Addr[3])
144 case *syscall.SockaddrInet6:
147 ifa.Mask = make(IPMask, IPv6len)
148 copy(ifa.Mask, v.Addr[:])
150 ifa.IP = make(IP, IPv6len)
151 copy(ifa.IP, v.Addr[:])
152 // NOTE: KAME based IPv6 protcol stack usually embeds
153 // the interface index in the interface-local or link-
154 // local address as the kernel-internal form.
155 if ifa.IP.IsLinkLocalUnicast() {
156 // remove embedded scope zone ID
157 ifa.IP[2], ifa.IP[3] = 0, 0