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 dragonfly freebsd netbsd openbsd
7 // Routing sockets and messages
13 // Round the length of a raw sockaddr up to align it properly.
14 func rsaAlignOf(salen
int) int {
16 // NOTE: It seems like 64-bit Darwin kernel still requires
17 // 32-bit aligned access to BSD subsystem. Also NetBSD 6
18 // kernel and beyond require 64-bit aligned access to routing
22 } else if netbsd32Bit
{
28 return (salen
+ salign
- 1) & ^(salign
- 1)
31 // RouteRIB returns routing information base, as known as RIB,
32 // which consists of network facility information, states and
34 func RouteRIB(facility
, param
int) ([]byte, error
) {
35 mib
:= []_C_int
{CTL_NET
, AF_ROUTE
, 0, 0, _C_int(facility
), _C_int(param
)}
38 if err
:= sysctl(mib
, nil, &n
, nil, 0); err
!= nil {
44 tab
:= make([]byte, n
)
45 if err
:= sysctl(mib
, &tab
[0], &n
, nil, 0); err
!= nil {
51 // RoutingMessage represents a routing message.
52 type RoutingMessage
interface {
56 const anyMessageLen
= int(unsafe
.Sizeof(anyMessage
{}))
58 type anyMessage
struct {
64 // RouteMessage represents a routing message containing routing
66 type RouteMessage
struct {
71 const rtaRtMask
= RTA_DST | RTA_GATEWAY | RTA_NETMASK | RTA_GENMASK
73 func (m
*RouteMessage
) sockaddr() []Sockaddr
{
79 for i
:= uint(0); i
< RTAX_MAX
; i
++ {
80 if m
.Header
.Addrs
&rtaRtMask
&(1<<i
) == 0 {
83 rsa
:= (*RawSockaddr
)(unsafe
.Pointer(&b
[0]))
85 case RTAX_DST
, RTAX_GATEWAY
:
86 sa
, err
:= anyToSockaddr((*RawSockaddrAny
)(unsafe
.Pointer(rsa
)))
94 case RTAX_NETMASK
, RTAX_GENMASK
:
97 rsa4
:= (*RawSockaddrInet4
)(unsafe
.Pointer(&b
[0]))
98 sa
:= new(SockaddrInet4
)
99 for j
:= 0; rsa4
.Len
> 0 && j
< int(rsa4
.Len
)-int(unsafe
.Offsetof(rsa4
.Addr
)); j
++ {
100 sa
.Addr
[j
] = rsa4
.Addr
[j
]
104 rsa6
:= (*RawSockaddrInet6
)(unsafe
.Pointer(&b
[0]))
105 sa
:= new(SockaddrInet6
)
106 for j
:= 0; rsa6
.Len
> 0 && j
< int(rsa6
.Len
)-int(unsafe
.Offsetof(rsa6
.Addr
)); j
++ {
107 sa
.Addr
[j
] = rsa6
.Addr
[j
]
112 b
= b
[rsaAlignOf(int(rsa
.Len
)):]
117 // InterfaceMessage represents a routing message containing
118 // network interface entries.
119 type InterfaceMessage
struct {
124 func (m
*InterfaceMessage
) sockaddr() (sas
[]Sockaddr
) {
125 if m
.Header
.Addrs
&RTA_IFP
== 0 {
128 sa
, err
:= anyToSockaddr((*RawSockaddrAny
)(unsafe
.Pointer(&m
.Data
[0])))
132 return append(sas
, sa
)
135 // InterfaceAddrMessage represents a routing message containing
136 // network interface address entries.
137 type InterfaceAddrMessage
struct {
142 const rtaIfaMask
= RTA_IFA | RTA_NETMASK | RTA_BRD
144 func (m
*InterfaceAddrMessage
) sockaddr() (sas
[]Sockaddr
) {
145 if m
.Header
.Addrs
&rtaIfaMask
== 0 {
149 // We still see AF_UNSPEC in socket addresses on some
150 // platforms. To identify each address family correctly, we
151 // will use the address family of RTAX_NETMASK as a preferred
152 // one on the 32-bit NetBSD kernel, also use the length of
153 // RTAX_NETMASK socket address on the FreeBSD kernel.
154 preferredFamily
:= uint8(AF_UNSPEC
)
155 for i
:= uint(0); i
< RTAX_MAX
; i
++ {
156 if m
.Header
.Addrs
&rtaIfaMask
&(1<<i
) == 0 {
159 rsa
:= (*RawSockaddr
)(unsafe
.Pointer(&b
[0]))
162 if rsa
.Family
== AF_UNSPEC
{
163 rsa
.Family
= preferredFamily
165 sa
, err
:= anyToSockaddr((*RawSockaddrAny
)(unsafe
.Pointer(rsa
)))
169 sas
= append(sas
, sa
)
174 case SizeofSockaddrInet4
:
176 case SizeofSockaddrInet6
:
177 rsa
.Family
= AF_INET6
179 rsa
.Family
= AF_INET
// an old fashion, AF_UNSPEC means AF_INET
181 case AF_INET
, AF_INET6
:
182 preferredFamily
= rsa
.Family
186 sa
, err
:= anyToSockaddr((*RawSockaddrAny
)(unsafe
.Pointer(rsa
)))
190 sas
= append(sas
, sa
)
194 b
= b
[rsaAlignOf(int(rsa
.Len
)):]
199 // ParseRoutingMessage parses b as routing messages and returns the
200 // slice containing the RoutingMessage interfaces.
201 func ParseRoutingMessage(b
[]byte) (msgs
[]RoutingMessage
, err error
) {
202 for len(b
) >= anyMessageLen
{
203 any
:= (*anyMessage
)(unsafe
.Pointer(&b
[0]))
204 if any
.Version
!= RTM_VERSION
{
207 msgs
= append(msgs
, any
.toRoutingMessage(b
))
213 // ParseRoutingMessage parses msg's payload as raw sockaddrs and
214 // returns the slice containing the Sockaddr interfaces.
215 func ParseRoutingSockaddr(msg RoutingMessage
) (sas
[]Sockaddr
, err error
) {
216 return append(sas
, msg
.sockaddr()...), nil