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
)
122 ifat
= append(ifat
, ifa
)
130 func newAddr(m
*syscall
.InterfaceAddrMessage
) (Addr
, error
) {
131 sas
, err
:= syscall
.ParseRoutingSockaddr(m
)
133 return nil, os
.NewSyscallError("route sockaddr", err
)
137 for i
, s
:= range sas
{
138 switch v
:= s
.(type) {
139 case *syscall
.SockaddrInet4
:
142 ifa
.Mask
= IPv4Mask(v
.Addr
[0], v
.Addr
[1], v
.Addr
[2], v
.Addr
[3])
144 ifa
.IP
= IPv4(v
.Addr
[0], v
.Addr
[1], v
.Addr
[2], v
.Addr
[3])
146 case *syscall
.SockaddrInet6
:
149 ifa
.Mask
= make(IPMask
, IPv6len
)
150 copy(ifa
.Mask
, v
.Addr
[:])
152 ifa
.IP
= make(IP
, IPv6len
)
153 copy(ifa
.IP
, v
.Addr
[:])
154 // NOTE: KAME based IPv6 protcol stack usually embeds
155 // the interface index in the interface-local or link-
156 // local address as the kernel-internal form.
157 if ifa
.IP
.IsLinkLocalUnicast() {
158 // remove embedded scope zone ID
159 ifa
.IP
[2], ifa
.IP
[3] = 0, 0
162 default: // Sockaddrs contain syscall.SockaddrDatalink on NetBSD