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 openbsd
7 // Routing sockets and messages
15 // Round the length of a raw sockaddr up to align it properly.
16 func rsaAlignOf(salen int) int {
18 // NOTE: It seems like 64-bit Darwin kernel still requires 32-bit
19 // aligned access to BSD subsystem.
26 return (salen + salign - 1) & ^(salign - 1)
29 // RouteRIB returns routing information base, as known as RIB,
30 // which consists of network facility information, states and
32 func RouteRIB(facility, param int) ([]byte, int) {
38 mib := []_C_int{CTL_NET, AF_ROUTE, 0, 0, _C_int(facility), _C_int(param)}
42 if e = sysctl(mib, nil, &n, nil, 0); e != 0 {
50 if e = sysctl(mib, &tab[0], &n, nil, 0); e != 0 {
57 // RoutingMessage represents a routing message.
58 type RoutingMessage interface {
62 const anyMessageLen = int(unsafe.Sizeof(anyMessage{}))
64 type anyMessage struct {
70 // RouteMessage represents a routing message containing routing
72 type RouteMessage struct {
77 const rtaRtMask = RTA_DST | RTA_GATEWAY | RTA_NETMASK | RTA_GENMASK
79 func (m *RouteMessage) sockaddr() []Sockaddr {
86 for i := uint(0); i < RTAX_MAX; i++ {
87 if m.Header.Addrs&rtaRtMask&(1<<i) == 0 {
90 rsa := (*RawSockaddr)(unsafe.Pointer(&buf[0]))
92 case RTAX_DST, RTAX_GATEWAY:
93 sa, e := anyToSockaddr((*RawSockaddrAny)(unsafe.Pointer(rsa)))
101 case RTAX_NETMASK, RTAX_GENMASK:
104 rsa4 := (*RawSockaddrInet4)(unsafe.Pointer(&buf[0]))
105 sa := new(SockaddrInet4)
106 for j := 0; rsa4.Len > 0 && j < int(rsa4.Len)-int(unsafe.Offsetof(rsa4.Addr)); j++ {
107 sa.Addr[j] = rsa4.Addr[j]
111 rsa6 := (*RawSockaddrInet6)(unsafe.Pointer(&buf[0]))
112 sa := new(SockaddrInet6)
113 for j := 0; rsa6.Len > 0 && j < int(rsa6.Len)-int(unsafe.Offsetof(rsa6.Addr)); j++ {
114 sa.Addr[j] = rsa6.Addr[j]
119 buf = buf[rsaAlignOf(int(rsa.Len)):]
125 // InterfaceMessage represents a routing message containing
126 // network interface entries.
127 type InterfaceMessage struct {
132 func (m *InterfaceMessage) sockaddr() (sas []Sockaddr) {
133 if m.Header.Addrs&RTA_IFP == 0 {
136 sa, e := anyToSockaddr((*RawSockaddrAny)(unsafe.Pointer(&m.Data[0])))
140 return append(sas, sa)
143 // InterfaceAddrMessage represents a routing message containing
144 // network interface address entries.
145 type InterfaceAddrMessage struct {
150 const rtaIfaMask = RTA_IFA | RTA_NETMASK | RTA_BRD
152 func (m *InterfaceAddrMessage) sockaddr() (sas []Sockaddr) {
153 if m.Header.Addrs&rtaIfaMask == 0 {
158 for i := uint(0); i < RTAX_MAX; i++ {
159 if m.Header.Addrs&rtaIfaMask&(1<<i) == 0 {
162 rsa := (*RawSockaddr)(unsafe.Pointer(&buf[0]))
165 sa, e := anyToSockaddr((*RawSockaddrAny)(unsafe.Pointer(rsa)))
169 sas = append(sas, sa)
170 case RTAX_NETMASK, RTAX_BRD:
173 buf = buf[rsaAlignOf(int(rsa.Len)):]
179 // ParseRoutingMessage parses buf as routing messages and returns
180 // the slice containing the RoutingMessage interfaces.
181 func ParseRoutingMessage(buf []byte) (msgs []RoutingMessage, errno int) {
182 for len(buf) >= anyMessageLen {
183 any := (*anyMessage)(unsafe.Pointer(&buf[0]))
184 if any.Version != RTM_VERSION {
187 msgs = append(msgs, any.toRoutingMessage(buf))
188 buf = buf[any.Msglen:]
193 // ParseRoutingMessage parses msg's payload as raw sockaddrs and
194 // returns the slice containing the Sockaddr interfaces.
195 func ParseRoutingSockaddr(msg RoutingMessage) (sas []Sockaddr, errno int) {
196 return append(sas, msg.sockaddr()...), 0