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
15 // If the ifindex is zero, interfaceTable returns mappings of all
16 // network interfaces. Otherwise it returns a mapping of a specific
18 func interfaceTable(ifindex
int) ([]Interface
, error
) {
19 tab
, err
:= syscall
.RouteRIB(syscall
.NET_RT_IFLIST
, ifindex
)
21 return nil, os
.NewSyscallError("route rib", err
)
23 msgs
, err
:= syscall
.ParseRoutingMessage(tab
)
25 return nil, os
.NewSyscallError("route message", err
)
27 return parseInterfaceTable(ifindex
, msgs
)
30 func parseInterfaceTable(ifindex
int, msgs
[]syscall
.RoutingMessage
) ([]Interface
, error
) {
33 for _
, m
:= range msgs
{
34 switch m
:= m
.(type) {
35 case *syscall
.InterfaceMessage
:
36 if ifindex
== 0 || ifindex
== int(m
.Header
.Index
) {
37 ifi
, err
:= newLink(m
)
41 ift
= append(ift
, *ifi
)
42 if ifindex
== int(m
.Header
.Index
) {
51 func newLink(m
*syscall
.InterfaceMessage
) (*Interface
, error
) {
52 sas
, err
:= syscall
.ParseRoutingSockaddr(m
)
54 return nil, os
.NewSyscallError("route sockaddr", err
)
56 ifi
:= &Interface
{Index
: int(m
.Header
.Index
), Flags
: linkFlags(m
.Header
.Flags
)}
57 for _
, sa
:= range sas
{
58 switch sa
:= sa
.(type) {
59 case *syscall
.SockaddrDatalink
:
60 // NOTE: SockaddrDatalink.Data is minimum work area,
62 m
.Data
= m
.Data
[unsafe
.Offsetof(sa
.Data
):]
63 var name
[syscall
.IFNAMSIZ
]byte
64 for i
:= 0; i
< int(sa
.Nlen
); i
++ {
65 name
[i
] = byte(m
.Data
[i
])
67 ifi
.Name
= string(name
[:sa
.Nlen
])
68 ifi
.MTU
= int(m
.Header
.Data
.Mtu
)
69 addr
:= make([]byte, sa
.Alen
)
70 for i
:= 0; i
< int(sa
.Alen
); i
++ {
71 addr
[i
] = byte(m
.Data
[int(sa
.Nlen
)+i
])
73 ifi
.HardwareAddr
= addr
[:sa
.Alen
]
79 func linkFlags(rawFlags
int32) Flags
{
81 if rawFlags
&syscall
.IFF_UP
!= 0 {
84 if rawFlags
&syscall
.IFF_BROADCAST
!= 0 {
87 if rawFlags
&syscall
.IFF_LOOPBACK
!= 0 {
90 if rawFlags
&syscall
.IFF_POINTOPOINT
!= 0 {
93 if rawFlags
&syscall
.IFF_MULTICAST
!= 0 {
99 // If the ifi is nil, interfaceAddrTable returns addresses for all
100 // network interfaces. Otherwise it returns addresses for a specific
102 func interfaceAddrTable(ifi
*Interface
) ([]Addr
, error
) {
107 tab
, err
:= syscall
.RouteRIB(syscall
.NET_RT_IFLIST
, index
)
109 return nil, os
.NewSyscallError("route rib", err
)
111 msgs
, err
:= syscall
.ParseRoutingMessage(tab
)
113 return nil, os
.NewSyscallError("route message", err
)
117 ift
, err
= parseInterfaceTable(index
, msgs
)
123 for _
, m
:= range msgs
{
124 switch m
:= m
.(type) {
125 case *syscall
.InterfaceAddrMessage
:
126 if index
== 0 || index
== int(m
.Header
.Index
) {
129 ifi
, err
= interfaceByIndex(ift
, int(m
.Header
.Index
))
134 ifa
, err
:= newAddr(ifi
, m
)
139 ifat
= append(ifat
, ifa
)
147 func newAddr(ifi
*Interface
, m
*syscall
.InterfaceAddrMessage
) (Addr
, error
) {
148 sas
, err
:= syscall
.ParseRoutingSockaddr(m
)
150 return nil, os
.NewSyscallError("route sockaddr", err
)
153 for i
, sa
:= range sas
{
154 switch sa
:= sa
.(type) {
155 case *syscall
.SockaddrInet4
:
158 ifa
.Mask
= IPv4Mask(sa
.Addr
[0], sa
.Addr
[1], sa
.Addr
[2], sa
.Addr
[3])
160 ifa
.IP
= IPv4(sa
.Addr
[0], sa
.Addr
[1], sa
.Addr
[2], sa
.Addr
[3])
162 case *syscall
.SockaddrInet6
:
165 ifa
.Mask
= make(IPMask
, IPv6len
)
166 copy(ifa
.Mask
, sa
.Addr
[:])
168 ifa
.IP
= make(IP
, IPv6len
)
169 copy(ifa
.IP
, sa
.Addr
[:])
170 // NOTE: KAME based IPv6 protcol stack usually embeds
171 // the interface index in the interface-local or link-
172 // local address as the kernel-internal form.
173 if ifa
.IP
.IsLinkLocalUnicast() {
174 ifa
.IP
[2], ifa
.IP
[3] = 0, 0
177 default: // Sockaddrs contain syscall.SockaddrDatalink on NetBSD