2013-12-05 Richard Biener <rguenther@suse.de>
[official-gcc.git] / libgo / go / syscall / route_bsd.go
blob638073592d5b910e729ec398c843943bb8eaef95
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
9 package syscall
11 import "unsafe"
13 // Round the length of a raw sockaddr up to align it properly.
14 func rsaAlignOf(salen int) int {
15 salign := sizeofPtr
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
19 // facilities.
20 if darwin64Bit {
21 salign = 4
22 } else if netbsd32Bit {
23 salign = 8
25 if salen == 0 {
26 return salign
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
33 // parameters.
34 func RouteRIB(facility, param int) ([]byte, error) {
35 mib := []_C_int{CTL_NET, AF_ROUTE, 0, 0, _C_int(facility), _C_int(param)}
36 // Find size.
37 n := uintptr(0)
38 if err := sysctl(mib, nil, &n, nil, 0); err != nil {
39 return nil, err
41 if n == 0 {
42 return nil, nil
44 tab := make([]byte, n)
45 if err := sysctl(mib, &tab[0], &n, nil, 0); err != nil {
46 return nil, err
48 return tab[:n], nil
51 // RoutingMessage represents a routing message.
52 type RoutingMessage interface {
53 sockaddr() []Sockaddr
56 const anyMessageLen = int(unsafe.Sizeof(anyMessage{}))
58 type anyMessage struct {
59 Msglen uint16
60 Version uint8
61 Type uint8
64 // RouteMessage represents a routing message containing routing
65 // entries.
66 type RouteMessage struct {
67 Header RtMsghdr
68 Data []byte
71 const rtaRtMask = RTA_DST | RTA_GATEWAY | RTA_NETMASK | RTA_GENMASK
73 func (m *RouteMessage) sockaddr() []Sockaddr {
74 var (
75 af int
76 sas [4]Sockaddr
78 b := m.Data[:]
79 for i := uint(0); i < RTAX_MAX; i++ {
80 if m.Header.Addrs&rtaRtMask&(1<<i) == 0 {
81 continue
83 rsa := (*RawSockaddr)(unsafe.Pointer(&b[0]))
84 switch i {
85 case RTAX_DST, RTAX_GATEWAY:
86 sa, err := anyToSockaddr((*RawSockaddrAny)(unsafe.Pointer(rsa)))
87 if err != nil {
88 return nil
90 if i == RTAX_DST {
91 af = int(rsa.Family)
93 sas[i] = sa
94 case RTAX_NETMASK, RTAX_GENMASK:
95 switch af {
96 case AF_INET:
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]
102 sas[i] = sa
103 case AF_INET6:
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]
109 sas[i] = sa
112 b = b[rsaAlignOf(int(rsa.Len)):]
114 return sas[:]
117 // InterfaceMessage represents a routing message containing
118 // network interface entries.
119 type InterfaceMessage struct {
120 Header IfMsghdr
121 Data []byte
124 func (m *InterfaceMessage) sockaddr() (sas []Sockaddr) {
125 if m.Header.Addrs&RTA_IFP == 0 {
126 return nil
128 sa, err := anyToSockaddr((*RawSockaddrAny)(unsafe.Pointer(&m.Data[0])))
129 if err != nil {
130 return nil
132 return append(sas, sa)
135 // InterfaceAddrMessage represents a routing message containing
136 // network interface address entries.
137 type InterfaceAddrMessage struct {
138 Header IfaMsghdr
139 Data []byte
142 const rtaIfaMask = RTA_IFA | RTA_NETMASK | RTA_BRD
144 func (m *InterfaceAddrMessage) sockaddr() (sas []Sockaddr) {
145 if m.Header.Addrs&rtaIfaMask == 0 {
146 return nil
148 b := m.Data[:]
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 {
157 continue
159 rsa := (*RawSockaddr)(unsafe.Pointer(&b[0]))
160 switch i {
161 case RTAX_IFA:
162 if rsa.Family == AF_UNSPEC {
163 rsa.Family = preferredFamily
165 sa, err := anyToSockaddr((*RawSockaddrAny)(unsafe.Pointer(rsa)))
166 if err != nil {
167 return nil
169 sas = append(sas, sa)
170 case RTAX_NETMASK:
171 switch rsa.Family {
172 case AF_UNSPEC:
173 switch rsa.Len {
174 case SizeofSockaddrInet4:
175 rsa.Family = AF_INET
176 case SizeofSockaddrInet6:
177 rsa.Family = AF_INET6
178 default:
179 rsa.Family = AF_INET // an old fashion, AF_UNSPEC means AF_INET
181 case AF_INET, AF_INET6:
182 preferredFamily = rsa.Family
183 default:
184 return nil
186 sa, err := anyToSockaddr((*RawSockaddrAny)(unsafe.Pointer(rsa)))
187 if err != nil {
188 return nil
190 sas = append(sas, sa)
191 case RTAX_BRD:
192 // nothing to do
194 b = b[rsaAlignOf(int(rsa.Len)):]
196 return sas
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 {
205 return nil, EINVAL
207 msgs = append(msgs, any.toRoutingMessage(b))
208 b = b[any.Msglen:]
210 return msgs, nil
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