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
15 freebsdConfArch
string // "machine $arch" line in kern.conftxt on freebsd
16 minRoutingSockaddrLen
= rsaAlignOf(0)
19 // Round the length of a raw sockaddr up to align it properly.
20 func rsaAlignOf(salen
int) int {
23 // Darwin kernels require 32-bit aligned access to
24 // routing facilities.
26 } else if netbsd32Bit
{
27 // NetBSD 6 and beyond kernels require 64-bit aligned
28 // access to routing facilities.
30 } else if runtime
.GOOS
== "freebsd" {
31 // In the case of kern.supported_archs="amd64 i386",
32 // we need to know the underlying kernel's
33 // architecture because the alignment for routing
34 // facilities are set at the build time of the kernel.
35 if freebsdConfArch
== "amd64" {
42 return (salen
+ salign
- 1) & ^(salign
- 1)
45 // parseSockaddrLink parses b as a datalink socket address.
46 func parseSockaddrLink(b
[]byte) (*SockaddrDatalink
, error
) {
50 sa
, _
, err
:= parseLinkLayerAddr(b
[4:])
54 rsa
:= (*RawSockaddrDatalink
)(unsafe
.Pointer(&b
[0]))
56 sa
.Family
= rsa
.Family
61 // parseLinkLayerAddr parses b as a datalink socket address in
62 // conventional BSD kernel form.
63 func parseLinkLayerAddr(b
[]byte) (*SockaddrDatalink
, int, error
) {
64 // The encoding looks like the following:
65 // +----------------------------+
67 // +----------------------------+
68 // | Name length (1 octet) |
69 // +----------------------------+
70 // | Address length (1 octet) |
71 // +----------------------------+
72 // | Selector length (1 octet) |
73 // +----------------------------+
74 // | Data (variable) |
75 // +----------------------------+
76 type linkLayerAddr
struct {
82 lla
:= (*linkLayerAddr
)(unsafe
.Pointer(&b
[0]))
83 l
:= 4 + int(lla
.Nlen
) + int(lla
.Alen
) + int(lla
.Slen
)
88 sa
:= &SockaddrDatalink
{Type
: lla
.Type
, Nlen
: lla
.Nlen
, Alen
: lla
.Alen
, Slen
: lla
.Slen
}
89 for i
:= 0; len(sa
.Data
) > i
&& i
< l
-4; i
++ {
90 sa
.Data
[i
] = int8(b
[i
])
92 return sa
, rsaAlignOf(l
), nil
95 // parseSockaddrInet parses b as an internet socket address.
96 func parseSockaddrInet(b
[]byte, family
byte) (Sockaddr
, error
) {
99 if len(b
) < SizeofSockaddrInet4
{
102 rsa
:= (*RawSockaddrAny
)(unsafe
.Pointer(&b
[0]))
103 return anyToSockaddr(rsa
)
105 if len(b
) < SizeofSockaddrInet6
{
108 rsa
:= (*RawSockaddrAny
)(unsafe
.Pointer(&b
[0]))
109 return anyToSockaddr(rsa
)
116 offsetofInet4
= int(unsafe
.Offsetof(RawSockaddrInet4
{}.Addr
))
117 offsetofInet6
= int(unsafe
.Offsetof(RawSockaddrInet6
{}.Addr
))
120 // parseNetworkLayerAddr parses b as an internet socket address in
121 // conventional BSD kernel form.
122 func parseNetworkLayerAddr(b
[]byte, family
byte) (Sockaddr
, error
) {
123 // The encoding looks similar to the NLRI encoding.
124 // +----------------------------+
125 // | Length (1 octet) |
126 // +----------------------------+
127 // | Address prefix (variable) |
128 // +----------------------------+
130 // The differences between the kernel form and the NLRI
133 // - The length field of the kernel form indicates the prefix
134 // length in bytes, not in bits
136 // - In the kernel form, zero value of the length field
137 // doesn't mean 0.0.0.0/0 or ::/0
139 // - The kernel form appends leading bytes to the prefix field
140 // to make the <length, prefix> tuple to be conformed with
141 // the routing message boundary
142 l
:= int(rsaAlignOf(int(b
[0])))
146 // Don't reorder case expressions.
147 // The case expressions for IPv6 must come first.
149 case b
[0] == SizeofSockaddrInet6
:
150 sa
:= &SockaddrInet6
{}
151 copy(sa
.Addr
[:], b
[offsetofInet6
:])
153 case family
== AF_INET6
:
154 sa
:= &SockaddrInet6
{}
155 if l
-1 < offsetofInet6
{
156 copy(sa
.Addr
[:], b
[1:l
])
158 copy(sa
.Addr
[:], b
[l
-offsetofInet6
:l
])
161 case b
[0] == SizeofSockaddrInet4
:
162 sa
:= &SockaddrInet4
{}
163 copy(sa
.Addr
[:], b
[offsetofInet4
:])
165 default: // an old fashion, AF_UNSPEC or unknown means AF_INET
166 sa
:= &SockaddrInet4
{}
167 if l
-1 < offsetofInet4
{
168 copy(sa
.Addr
[:], b
[1:l
])
170 copy(sa
.Addr
[:], b
[l
-offsetofInet4
:l
])
176 // RouteRIB returns routing information base, as known as RIB,
177 // which consists of network facility information, states and
180 // Deprecated: Use golang.org/x/net/route instead.
181 func RouteRIB(facility
, param
int) ([]byte, error
) {
182 mib
:= []_C_int
{CTL_NET
, AF_ROUTE
, 0, 0, _C_int(facility
), _C_int(param
)}
185 if err
:= sysctl(mib
, nil, &n
, nil, 0); err
!= nil {
191 tab
:= make([]byte, n
)
192 if err
:= sysctl(mib
, &tab
[0], &n
, nil, 0); err
!= nil {
198 // RoutingMessage represents a routing message.
200 // Deprecated: Use golang.org/x/net/route instead.
201 type RoutingMessage
interface {
202 sockaddr() ([]Sockaddr
, error
)
205 const anyMessageLen
= int(unsafe
.Sizeof(anyMessage
{}))
207 type anyMessage
struct {
213 // RouteMessage represents a routing message containing routing
216 // Deprecated: Use golang.org/x/net/route instead.
217 type RouteMessage
struct {
222 func (m
*RouteMessage
) sockaddr() ([]Sockaddr
, error
) {
223 var sas
[RTAX_MAX
]Sockaddr
225 family
:= uint8(AF_UNSPEC
)
226 for i
:= uint(0); i
< RTAX_MAX
&& len(b
) >= minRoutingSockaddrLen
; i
++ {
227 if m
.Header
.Addrs
&(1<<i
) == 0 {
230 rsa
:= (*RawSockaddr
)(unsafe
.Pointer(&b
[0]))
233 sa
, err
:= parseSockaddrLink(b
)
238 b
= b
[rsaAlignOf(int(rsa
.Len
)):]
239 case AF_INET
, AF_INET6
:
240 sa
, err
:= parseSockaddrInet(b
, rsa
.Family
)
245 b
= b
[rsaAlignOf(int(rsa
.Len
)):]
248 sa
, err
:= parseNetworkLayerAddr(b
, family
)
253 b
= b
[rsaAlignOf(int(b
[0])):]
259 // InterfaceMessage represents a routing message containing
260 // network interface entries.
262 // Deprecated: Use golang.org/x/net/route instead.
263 type InterfaceMessage
struct {
268 func (m
*InterfaceMessage
) sockaddr() ([]Sockaddr
, error
) {
269 var sas
[RTAX_MAX
]Sockaddr
270 if m
.Header
.Addrs
&RTA_IFP
== 0 {
273 sa
, err
:= parseSockaddrLink(m
.Data
[:])
281 // InterfaceAddrMessage represents a routing message containing
282 // network interface address entries.
284 // Deprecated: Use golang.org/x/net/route instead.
285 type InterfaceAddrMessage
struct {
290 func (m
*InterfaceAddrMessage
) sockaddr() ([]Sockaddr
, error
) {
291 var sas
[RTAX_MAX
]Sockaddr
293 family
:= uint8(AF_UNSPEC
)
294 for i
:= uint(0); i
< RTAX_MAX
&& len(b
) >= minRoutingSockaddrLen
; i
++ {
295 if m
.Header
.Addrs
&(1<<i
) == 0 {
298 rsa
:= (*RawSockaddr
)(unsafe
.Pointer(&b
[0]))
301 sa
, err
:= parseSockaddrLink(b
)
306 b
= b
[rsaAlignOf(int(rsa
.Len
)):]
307 case AF_INET
, AF_INET6
:
308 sa
, err
:= parseSockaddrInet(b
, rsa
.Family
)
313 b
= b
[rsaAlignOf(int(rsa
.Len
)):]
316 sa
, err
:= parseNetworkLayerAddr(b
, family
)
321 b
= b
[rsaAlignOf(int(b
[0])):]
327 // ParseRoutingMessage parses b as routing messages and returns the
328 // slice containing the RoutingMessage interfaces.
330 // Deprecated: Use golang.org/x/net/route instead.
331 func ParseRoutingMessage(b
[]byte) (msgs
[]RoutingMessage
, err error
) {
332 nmsgs
, nskips
:= 0, 0
333 for len(b
) >= anyMessageLen
{
335 any
:= (*anyMessage
)(unsafe
.Pointer(&b
[0]))
336 if any
.Version
!= RTM_VERSION
{
340 if m
:= any
.toRoutingMessage(b
); m
== nil {
343 msgs
= append(msgs
, m
)
347 // We failed to parse any of the messages - version mismatch?
348 if nmsgs
!= len(msgs
)+nskips
{
354 // ParseRoutingSockaddr parses msg's payload as raw sockaddrs and
355 // returns the slice containing the Sockaddr interfaces.
357 // Deprecated: Use golang.org/x/net/route instead.
358 func ParseRoutingSockaddr(msg RoutingMessage
) ([]Sockaddr
, error
) {
359 sas
, err
:= msg
.sockaddr()