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.
4
5// +build darwin dragonfly freebsd netbsd openbsd
6
7package syscall
8
9import (
10	"runtime"
11	"unsafe"
12)
13
14var (
15	freebsdConfArch       string // "machine $arch" line in kern.conftxt on freebsd
16	minRoutingSockaddrLen = rsaAlignOf(0)
17)
18
19// Round the length of a raw sockaddr up to align it properly.
20func rsaAlignOf(salen int) int {
21	salign := sizeofPtr
22	if darwin64Bit {
23		// Darwin kernels require 32-bit aligned access to
24		// routing facilities.
25		salign = 4
26	} else if netbsd32Bit {
27		// NetBSD 6 and beyond kernels require 64-bit aligned
28		// access to routing facilities.
29		salign = 8
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" {
36			salign = 8
37		}
38	}
39	if salen == 0 {
40		return salign
41	}
42	return (salen + salign - 1) & ^(salign - 1)
43}
44
45// parseSockaddrLink parses b as a datalink socket address.
46func parseSockaddrLink(b []byte) (*SockaddrDatalink, error) {
47	if len(b) < 8 {
48		return nil, EINVAL
49	}
50	sa, _, err := parseLinkLayerAddr(b[4:])
51	if err != nil {
52		return nil, err
53	}
54	rsa := (*RawSockaddrDatalink)(unsafe.Pointer(&b[0]))
55	sa.Len = rsa.Len
56	sa.Family = rsa.Family
57	sa.Index = rsa.Index
58	return sa, nil
59}
60
61// parseLinkLayerAddr parses b as a datalink socket address in
62// conventional BSD kernel form.
63func parseLinkLayerAddr(b []byte) (*SockaddrDatalink, int, error) {
64	// The encoding looks like the following:
65	// +----------------------------+
66	// | Type             (1 octet) |
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 {
77		Type byte
78		Nlen byte
79		Alen byte
80		Slen byte
81	}
82	lla := (*linkLayerAddr)(unsafe.Pointer(&b[0]))
83	l := 4 + int(lla.Nlen) + int(lla.Alen) + int(lla.Slen)
84	if len(b) < l {
85		return nil, 0, EINVAL
86	}
87	b = b[4:]
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])
91	}
92	return sa, rsaAlignOf(l), nil
93}
94
95// parseSockaddrInet parses b as an internet socket address.
96func parseSockaddrInet(b []byte, family byte) (Sockaddr, error) {
97	switch family {
98	case AF_INET:
99		if len(b) < SizeofSockaddrInet4 {
100			return nil, EINVAL
101		}
102		rsa := (*RawSockaddrAny)(unsafe.Pointer(&b[0]))
103		return anyToSockaddr(rsa)
104	case AF_INET6:
105		if len(b) < SizeofSockaddrInet6 {
106			return nil, EINVAL
107		}
108		rsa := (*RawSockaddrAny)(unsafe.Pointer(&b[0]))
109		return anyToSockaddr(rsa)
110	default:
111		return nil, EINVAL
112	}
113}
114
115const (
116	offsetofInet4 = int(unsafe.Offsetof(RawSockaddrInet4{}.Addr))
117	offsetofInet6 = int(unsafe.Offsetof(RawSockaddrInet6{}.Addr))
118)
119
120// parseNetworkLayerAddr parses b as an internet socket address in
121// conventional BSD kernel form.
122func 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	// +----------------------------+
129	//
130	// The differences between the kernel form and the NLRI
131	// encoding are:
132	//
133	// - The length field of the kernel form indicates the prefix
134	//   length in bytes, not in bits
135	//
136	// - In the kernel form, zero value of the length field
137	//   doesn't mean 0.0.0.0/0 or ::/0
138	//
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])))
143	if len(b) < l {
144		return nil, EINVAL
145	}
146	// Don't reorder case expressions.
147	// The case expressions for IPv6 must come first.
148	switch {
149	case b[0] == SizeofSockaddrInet6:
150		sa := &SockaddrInet6{}
151		copy(sa.Addr[:], b[offsetofInet6:])
152		return sa, nil
153	case family == AF_INET6:
154		sa := &SockaddrInet6{}
155		if l-1 < offsetofInet6 {
156			copy(sa.Addr[:], b[1:l])
157		} else {
158			copy(sa.Addr[:], b[l-offsetofInet6:l])
159		}
160		return sa, nil
161	case b[0] == SizeofSockaddrInet4:
162		sa := &SockaddrInet4{}
163		copy(sa.Addr[:], b[offsetofInet4:])
164		return sa, nil
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])
169		} else {
170			copy(sa.Addr[:], b[l-offsetofInet4:l])
171		}
172		return sa, nil
173	}
174}
175
176// RouteRIB returns routing information base, as known as RIB,
177// which consists of network facility information, states and
178// parameters.
179//
180// Deprecated: Use golang.org/x/net/route instead.
181func RouteRIB(facility, param int) ([]byte, error) {
182	mib := []_C_int{CTL_NET, AF_ROUTE, 0, 0, _C_int(facility), _C_int(param)}
183	// Find size.
184	n := uintptr(0)
185	if err := sysctl(mib, nil, &n, nil, 0); err != nil {
186		return nil, err
187	}
188	if n == 0 {
189		return nil, nil
190	}
191	tab := make([]byte, n)
192	if err := sysctl(mib, &tab[0], &n, nil, 0); err != nil {
193		return nil, err
194	}
195	return tab[:n], nil
196}
197
198// RoutingMessage represents a routing message.
199//
200// Deprecated: Use golang.org/x/net/route instead.
201type RoutingMessage interface {
202	sockaddr() ([]Sockaddr, error)
203}
204
205const anyMessageLen = int(unsafe.Sizeof(anyMessage{}))
206
207type anyMessage struct {
208	Msglen  uint16
209	Version uint8
210	Type    uint8
211}
212
213// RouteMessage represents a routing message containing routing
214// entries.
215//
216// Deprecated: Use golang.org/x/net/route instead.
217type RouteMessage struct {
218	Header RtMsghdr
219	Data   []byte
220}
221
222func (m *RouteMessage) sockaddr() ([]Sockaddr, error) {
223	var sas [RTAX_MAX]Sockaddr
224	b := m.Data[:]
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 {
228			continue
229		}
230		rsa := (*RawSockaddr)(unsafe.Pointer(&b[0]))
231		switch rsa.Family {
232		case AF_LINK:
233			sa, err := parseSockaddrLink(b)
234			if err != nil {
235				return nil, err
236			}
237			sas[i] = sa
238			b = b[rsaAlignOf(int(rsa.Len)):]
239		case AF_INET, AF_INET6:
240			sa, err := parseSockaddrInet(b, rsa.Family)
241			if err != nil {
242				return nil, err
243			}
244			sas[i] = sa
245			b = b[rsaAlignOf(int(rsa.Len)):]
246			family = rsa.Family
247		default:
248			sa, err := parseNetworkLayerAddr(b, family)
249			if err != nil {
250				return nil, err
251			}
252			sas[i] = sa
253			b = b[rsaAlignOf(int(b[0])):]
254		}
255	}
256	return sas[:], nil
257}
258
259// InterfaceMessage represents a routing message containing
260// network interface entries.
261//
262// Deprecated: Use golang.org/x/net/route instead.
263type InterfaceMessage struct {
264	Header IfMsghdr
265	Data   []byte
266}
267
268func (m *InterfaceMessage) sockaddr() ([]Sockaddr, error) {
269	var sas [RTAX_MAX]Sockaddr
270	if m.Header.Addrs&RTA_IFP == 0 {
271		return nil, nil
272	}
273	sa, err := parseSockaddrLink(m.Data[:])
274	if err != nil {
275		return nil, err
276	}
277	sas[RTAX_IFP] = sa
278	return sas[:], nil
279}
280
281// InterfaceAddrMessage represents a routing message containing
282// network interface address entries.
283//
284// Deprecated: Use golang.org/x/net/route instead.
285type InterfaceAddrMessage struct {
286	Header IfaMsghdr
287	Data   []byte
288}
289
290func (m *InterfaceAddrMessage) sockaddr() ([]Sockaddr, error) {
291	var sas [RTAX_MAX]Sockaddr
292	b := m.Data[:]
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 {
296			continue
297		}
298		rsa := (*RawSockaddr)(unsafe.Pointer(&b[0]))
299		switch rsa.Family {
300		case AF_LINK:
301			sa, err := parseSockaddrLink(b)
302			if err != nil {
303				return nil, err
304			}
305			sas[i] = sa
306			b = b[rsaAlignOf(int(rsa.Len)):]
307		case AF_INET, AF_INET6:
308			sa, err := parseSockaddrInet(b, rsa.Family)
309			if err != nil {
310				return nil, err
311			}
312			sas[i] = sa
313			b = b[rsaAlignOf(int(rsa.Len)):]
314			family = rsa.Family
315		default:
316			sa, err := parseNetworkLayerAddr(b, family)
317			if err != nil {
318				return nil, err
319			}
320			sas[i] = sa
321			b = b[rsaAlignOf(int(b[0])):]
322		}
323	}
324	return sas[:], nil
325}
326
327// ParseRoutingMessage parses b as routing messages and returns the
328// slice containing the RoutingMessage interfaces.
329//
330// Deprecated: Use golang.org/x/net/route instead.
331func ParseRoutingMessage(b []byte) (msgs []RoutingMessage, err error) {
332	nmsgs, nskips := 0, 0
333	for len(b) >= anyMessageLen {
334		nmsgs++
335		any := (*anyMessage)(unsafe.Pointer(&b[0]))
336		if any.Version != RTM_VERSION {
337			b = b[any.Msglen:]
338			continue
339		}
340		if m := any.toRoutingMessage(b); m == nil {
341			nskips++
342		} else {
343			msgs = append(msgs, m)
344		}
345		b = b[any.Msglen:]
346	}
347	// We failed to parse any of the messages - version mismatch?
348	if nmsgs != len(msgs)+nskips {
349		return nil, EINVAL
350	}
351	return msgs, nil
352}
353
354// ParseRoutingSockaddr parses msg's payload as raw sockaddrs and
355// returns the slice containing the Sockaddr interfaces.
356//
357// Deprecated: Use golang.org/x/net/route instead.
358func ParseRoutingSockaddr(msg RoutingMessage) ([]Sockaddr, error) {
359	sas, err := msg.sockaddr()
360	if err != nil {
361		return nil, err
362	}
363	return sas, nil
364}
365