Source file
src/syscall/route_bsd.go
Documentation: syscall
1
2
3
4
5
6
7
8 package syscall
9
10 import (
11 "runtime"
12 "unsafe"
13 )
14
15 var (
16 freebsdConfArch string
17 minRoutingSockaddrLen = rsaAlignOf(0)
18 )
19
20
21 func rsaAlignOf(salen int) int {
22 salign := sizeofPtr
23 if darwin64Bit {
24
25
26 salign = 4
27 } else if netbsd32Bit {
28
29
30 salign = 8
31 } else if runtime.GOOS == "freebsd" {
32
33
34
35
36 if freebsdConfArch == "amd64" {
37 salign = 8
38 }
39 }
40 if salen == 0 {
41 return salign
42 }
43 return (salen + salign - 1) & ^(salign - 1)
44 }
45
46
47 func parseSockaddrLink(b []byte) (*SockaddrDatalink, error) {
48 if len(b) < 8 {
49 return nil, EINVAL
50 }
51 sa, _, err := parseLinkLayerAddr(b[4:])
52 if err != nil {
53 return nil, err
54 }
55 rsa := (*RawSockaddrDatalink)(unsafe.Pointer(&b[0]))
56 sa.Len = rsa.Len
57 sa.Family = rsa.Family
58 sa.Index = rsa.Index
59 return sa, nil
60 }
61
62
63
64 func parseLinkLayerAddr(b []byte) (*SockaddrDatalink, int, error) {
65
66
67
68
69
70
71
72
73
74
75
76
77 type linkLayerAddr struct {
78 Type byte
79 Nlen byte
80 Alen byte
81 Slen byte
82 }
83 lla := (*linkLayerAddr)(unsafe.Pointer(&b[0]))
84 l := 4 + int(lla.Nlen) + int(lla.Alen) + int(lla.Slen)
85 if len(b) < l {
86 return nil, 0, EINVAL
87 }
88 b = b[4:]
89 sa := &SockaddrDatalink{Type: lla.Type, Nlen: lla.Nlen, Alen: lla.Alen, Slen: lla.Slen}
90 for i := 0; len(sa.Data) > i && i < l-4; i++ {
91 sa.Data[i] = int8(b[i])
92 }
93 return sa, rsaAlignOf(l), nil
94 }
95
96
97 func parseSockaddrInet(b []byte, family byte) (Sockaddr, error) {
98 switch family {
99 case AF_INET:
100 if len(b) < SizeofSockaddrInet4 {
101 return nil, EINVAL
102 }
103 rsa := (*RawSockaddrAny)(unsafe.Pointer(&b[0]))
104 return anyToSockaddr(rsa)
105 case AF_INET6:
106 if len(b) < SizeofSockaddrInet6 {
107 return nil, EINVAL
108 }
109 rsa := (*RawSockaddrAny)(unsafe.Pointer(&b[0]))
110 return anyToSockaddr(rsa)
111 default:
112 return nil, EINVAL
113 }
114 }
115
116 const (
117 offsetofInet4 = int(unsafe.Offsetof(RawSockaddrInet4{}.Addr))
118 offsetofInet6 = int(unsafe.Offsetof(RawSockaddrInet6{}.Addr))
119 )
120
121
122
123 func parseNetworkLayerAddr(b []byte, family byte) (Sockaddr, error) {
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143 l := int(rsaAlignOf(int(b[0])))
144 if len(b) < l {
145 return nil, EINVAL
146 }
147
148
149 switch {
150 case b[0] == SizeofSockaddrInet6:
151 sa := &SockaddrInet6{}
152 copy(sa.Addr[:], b[offsetofInet6:])
153 return sa, nil
154 case family == AF_INET6:
155 sa := &SockaddrInet6{}
156 if l-1 < offsetofInet6 {
157 copy(sa.Addr[:], b[1:l])
158 } else {
159 copy(sa.Addr[:], b[l-offsetofInet6:l])
160 }
161 return sa, nil
162 case b[0] == SizeofSockaddrInet4:
163 sa := &SockaddrInet4{}
164 copy(sa.Addr[:], b[offsetofInet4:])
165 return sa, nil
166 default:
167 sa := &SockaddrInet4{}
168 if l-1 < offsetofInet4 {
169 copy(sa.Addr[:], b[1:l])
170 } else {
171 copy(sa.Addr[:], b[l-offsetofInet4:l])
172 }
173 return sa, nil
174 }
175 }
176
177
178
179
180
181
182 func RouteRIB(facility, param int) ([]byte, error) {
183 mib := []_C_int{CTL_NET, AF_ROUTE, 0, 0, _C_int(facility), _C_int(param)}
184
185 n := uintptr(0)
186 if err := sysctl(mib, nil, &n, nil, 0); err != nil {
187 return nil, err
188 }
189 if n == 0 {
190 return nil, nil
191 }
192 tab := make([]byte, n)
193 if err := sysctl(mib, &tab[0], &n, nil, 0); err != nil {
194 return nil, err
195 }
196 return tab[:n], nil
197 }
198
199
200
201
202 type RoutingMessage interface {
203 sockaddr() ([]Sockaddr, error)
204 }
205
206 const anyMessageLen = int(unsafe.Sizeof(anyMessage{}))
207
208 type anyMessage struct {
209 Msglen uint16
210 Version uint8
211 Type uint8
212 }
213
214
215
216
217
218 type RouteMessage struct {
219 Header RtMsghdr
220 Data []byte
221 }
222
223 func (m *RouteMessage) sockaddr() ([]Sockaddr, error) {
224 var sas [RTAX_MAX]Sockaddr
225 b := m.Data[:]
226 family := uint8(AF_UNSPEC)
227 for i := uint(0); i < RTAX_MAX && len(b) >= minRoutingSockaddrLen; i++ {
228 if m.Header.Addrs&(1<<i) == 0 {
229 continue
230 }
231 rsa := (*RawSockaddr)(unsafe.Pointer(&b[0]))
232 switch rsa.Family {
233 case AF_LINK:
234 sa, err := parseSockaddrLink(b)
235 if err != nil {
236 return nil, err
237 }
238 sas[i] = sa
239 b = b[rsaAlignOf(int(rsa.Len)):]
240 case AF_INET, AF_INET6:
241 sa, err := parseSockaddrInet(b, rsa.Family)
242 if err != nil {
243 return nil, err
244 }
245 sas[i] = sa
246 b = b[rsaAlignOf(int(rsa.Len)):]
247 family = rsa.Family
248 default:
249 sa, err := parseNetworkLayerAddr(b, family)
250 if err != nil {
251 return nil, err
252 }
253 sas[i] = sa
254 b = b[rsaAlignOf(int(b[0])):]
255 }
256 }
257 return sas[:], nil
258 }
259
260
261
262
263
264 type InterfaceMessage struct {
265 Header IfMsghdr
266 Data []byte
267 }
268
269 func (m *InterfaceMessage) sockaddr() ([]Sockaddr, error) {
270 var sas [RTAX_MAX]Sockaddr
271 if m.Header.Addrs&RTA_IFP == 0 {
272 return nil, nil
273 }
274 sa, err := parseSockaddrLink(m.Data[:])
275 if err != nil {
276 return nil, err
277 }
278 sas[RTAX_IFP] = sa
279 return sas[:], nil
280 }
281
282
283
284
285
286 type InterfaceAddrMessage struct {
287 Header IfaMsghdr
288 Data []byte
289 }
290
291 func (m *InterfaceAddrMessage) sockaddr() ([]Sockaddr, error) {
292 var sas [RTAX_MAX]Sockaddr
293 b := m.Data[:]
294 family := uint8(AF_UNSPEC)
295 for i := uint(0); i < RTAX_MAX && len(b) >= minRoutingSockaddrLen; i++ {
296 if m.Header.Addrs&(1<<i) == 0 {
297 continue
298 }
299 rsa := (*RawSockaddr)(unsafe.Pointer(&b[0]))
300 switch rsa.Family {
301 case AF_LINK:
302 sa, err := parseSockaddrLink(b)
303 if err != nil {
304 return nil, err
305 }
306 sas[i] = sa
307 b = b[rsaAlignOf(int(rsa.Len)):]
308 case AF_INET, AF_INET6:
309 sa, err := parseSockaddrInet(b, rsa.Family)
310 if err != nil {
311 return nil, err
312 }
313 sas[i] = sa
314 b = b[rsaAlignOf(int(rsa.Len)):]
315 family = rsa.Family
316 default:
317 sa, err := parseNetworkLayerAddr(b, family)
318 if err != nil {
319 return nil, err
320 }
321 sas[i] = sa
322 b = b[rsaAlignOf(int(b[0])):]
323 }
324 }
325 return sas[:], nil
326 }
327
328
329
330
331
332 func ParseRoutingMessage(b []byte) (msgs []RoutingMessage, err error) {
333 nmsgs, nskips := 0, 0
334 for len(b) >= anyMessageLen {
335 nmsgs++
336 any := (*anyMessage)(unsafe.Pointer(&b[0]))
337 if any.Version != RTM_VERSION {
338 b = b[any.Msglen:]
339 continue
340 }
341 if m := any.toRoutingMessage(b); m == nil {
342 nskips++
343 } else {
344 msgs = append(msgs, m)
345 }
346 b = b[any.Msglen:]
347 }
348
349 if nmsgs != len(msgs)+nskips {
350 return nil, EINVAL
351 }
352 return msgs, nil
353 }
354
355
356
357
358
359 func ParseRoutingSockaddr(msg RoutingMessage) ([]Sockaddr, error) {
360 sas, err := msg.sockaddr()
361 if err != nil {
362 return nil, err
363 }
364 return sas, nil
365 }
366
View as plain text