1 // Copyright 2016 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 //go:build darwin || dragonfly || freebsd || netbsd || openbsd
6 7 package routebsd
8 9 import (
10 "net/netip"
11 "runtime"
12 "syscall"
13 )
14 15 // An Addr represents an address associated with packet routing.
16 type Addr interface {
17 // Family returns an address family.
18 Family() int
19 }
20 21 // A LinkAddr represents a link-layer address.
22 type LinkAddr struct {
23 Index int // interface index when attached
24 Name []byte // interface name when attached
25 Addr []byte // link-layer address when attached
26 }
27 28 // Family implements the Family method of Addr interface.
29 func (a *LinkAddr) Family() int { return syscall.AF_LINK }
30 31 func parseLinkAddr(b []byte) (Addr, error) {
32 if len(b) < 8 {
33 return nil, errInvalidAddr
34 }
35 _, a, err := parseKernelLinkAddr(syscall.AF_LINK, b[4:])
36 if err != nil {
37 return nil, err
38 }
39 a.(*LinkAddr).Index = int(nativeEndian.Uint16(b[2:4]))
40 return a, nil
41 }
42 43 // parseKernelLinkAddr parses b as a link-layer address in
44 // conventional BSD kernel form.
45 func parseKernelLinkAddr(_ int, b []byte) (int, Addr, error) {
46 // The encoding looks like the following:
47 // +----------------------------+
48 // | Type (1 octet) |
49 // +----------------------------+
50 // | Name length (1 octet) |
51 // +----------------------------+
52 // | Address length (1 octet) |
53 // +----------------------------+
54 // | Selector length (1 octet) |
55 // +----------------------------+
56 // | Data (variable) |
57 // +----------------------------+
58 //
59 // On some platforms, all-bit-one of length field means "don't
60 // care".
61 nlen, alen, slen := int(b[1]), int(b[2]), int(b[3])
62 if nlen == 0xff {
63 nlen = 0
64 }
65 if alen == 0xff {
66 alen = 0
67 }
68 if slen == 0xff {
69 slen = 0
70 }
71 l := 4 + nlen + alen + slen
72 if len(b) < l {
73 return 0, nil, errInvalidAddr
74 }
75 data := b[4:]
76 var name []byte
77 var addr []byte
78 if nlen > 0 {
79 name = []byte(data[:nlen])
80 data = data[nlen:]
81 }
82 if alen > 0 {
83 addr = data[:alen]
84 data = data[alen:]
85 }
86 return l, &LinkAddr{Name: name, Addr: addr}, nil
87 }
88 89 // An InetAddr represent an internet address using IPv4 or IPv6.
90 type InetAddr struct {
91 IP netip.Addr
92 }
93 94 func (a *InetAddr) Family() int {
95 if a.IP.Is4() {
96 return syscall.AF_INET
97 } else {
98 return syscall.AF_INET6
99 }
100 }
101 102 // parseInetAddr parses b as an internet address for IPv4 or IPv6.
103 func parseInetAddr(af int, b []byte) (Addr, error) {
104 const (
105 off4 = 4 // offset of in_addr
106 off6 = 8 // offset of in6_addr
107 ipv4Len = 4 // length of IPv4 address in bytes
108 ipv6Len = 16 // length of IPv6 address in bytes
109 )
110 switch af {
111 case syscall.AF_INET:
112 if len(b) < (off4+1) || len(b) < int(b[0]) {
113 return nil, errInvalidAddr
114 }
115 sockAddrLen := int(b[0])
116 var ip [ipv4Len]byte
117 if sockAddrLen != 0 {
118 // Calculate how many bytes of the address to copy:
119 // either full IPv4 length or the available length.
120 n := off4 + ipv4Len
121 if sockAddrLen < n {
122 n = sockAddrLen
123 }
124 copy(ip[:], b[off4:n])
125 }
126 a := &InetAddr{
127 IP: netip.AddrFrom4(ip),
128 }
129 return a, nil
130 case syscall.AF_INET6:
131 if len(b) < (off6+1) || len(b) < int(b[0]) {
132 return nil, errInvalidAddr
133 }
134 var ip [ipv6Len]byte
135 sockAddrLen := int(b[0])
136 if sockAddrLen != 0 {
137 n := off6 + ipv6Len
138 if sockAddrLen < n {
139 n = sockAddrLen
140 }
141 copy(ip[:], b[off6:n])
142 if ip[0] == 0xfe && ip[1]&0xc0 == 0x80 || ip[0] == 0xff && (ip[1]&0x0f == 0x01 || ip[1]&0x0f == 0x02) {
143 // KAME based IPv6 protocol stack usually
144 // embeds the interface index in the
145 // interface-local or link-local address as
146 // the kernel-internal form.
147 id := int(bigEndian.Uint16(ip[2:4]))
148 if id != 0 {
149 ip[2], ip[3] = 0, 0
150 }
151 }
152 }
153 // The kernel can provide an integer zone ID.
154 // We ignore it.
155 a := &InetAddr{
156 IP: netip.AddrFrom16(ip),
157 }
158 return a, nil
159 default:
160 return nil, errInvalidAddr
161 }
162 }
163 164 // parseKernelInetAddr parses b as an internet address in conventional
165 // BSD kernel form.
166 func parseKernelInetAddr(af int, b []byte) (int, Addr, error) {
167 // The encoding looks similar to the NLRI encoding.
168 // +----------------------------+
169 // | Length (1 octet) |
170 // +----------------------------+
171 // | Address prefix (variable) |
172 // +----------------------------+
173 //
174 // The differences between the kernel form and the NLRI
175 // encoding are:
176 //
177 // - The length field of the kernel form indicates the prefix
178 // length in bytes, not in bits
179 //
180 // - In the kernel form, zero value of the length field
181 // doesn't mean 0.0.0.0/0 or ::/0
182 //
183 // - The kernel form appends leading bytes to the prefix field
184 // to make the <length, prefix> tuple to be conformed with
185 // the routing message boundary
186 l := int(b[0])
187 if runtime.GOOS == "darwin" || runtime.GOOS == "ios" {
188 // On Darwin, an address in the kernel form is also
189 // used as a message filler.
190 if l == 0 || len(b) > roundup(l) {
191 l = roundup(l)
192 }
193 } else {
194 l = roundup(l)
195 }
196 if len(b) < l {
197 return 0, nil, errInvalidAddr
198 }
199 // Don't reorder case expressions.
200 // The case expressions for IPv6 must come first.
201 const (
202 off4 = 4 // offset of in_addr
203 off6 = 8 // offset of in6_addr
204 )
205 switch {
206 case b[0] == syscall.SizeofSockaddrInet6:
207 a := &InetAddr{
208 IP: netip.AddrFrom16([16]byte(b[off6 : off6+16])),
209 }
210 return int(b[0]), a, nil
211 case af == syscall.AF_INET6:
212 var ab [16]byte
213 if l-1 < off6 {
214 copy(ab[:], b[1:l])
215 } else {
216 copy(ab[:], b[l-off6:l])
217 }
218 a := &InetAddr{
219 IP: netip.AddrFrom16(ab),
220 }
221 return int(b[0]), a, nil
222 case b[0] == syscall.SizeofSockaddrInet4:
223 a := &InetAddr{
224 IP: netip.AddrFrom4([4]byte(b[off4 : off4+4])),
225 }
226 return int(b[0]), a, nil
227 default: // an old fashion, AF_UNSPEC or unknown means AF_INET
228 var ab [4]byte
229 if l-1 < off4 {
230 copy(ab[:], b[1:l])
231 } else {
232 copy(ab[:], b[l-off4:l])
233 }
234 a := &InetAddr{
235 IP: netip.AddrFrom4(ab),
236 }
237 return int(b[0]), a, nil
238 }
239 }
240 241 func parseAddrs(attrs uint, b []byte) ([]Addr, error) {
242 var as [syscall.RTAX_MAX]Addr
243 af := int(syscall.AF_UNSPEC)
244 for i := uint(0); i < syscall.RTAX_MAX && len(b) >= roundup(0); i++ {
245 if attrs&(1<<i) == 0 {
246 continue
247 }
248 if i <= syscall.RTAX_BRD {
249 switch b[1] {
250 case syscall.AF_LINK:
251 a, err := parseLinkAddr(b)
252 if err != nil {
253 return nil, err
254 }
255 as[i] = a
256 l := roundup(int(b[0]))
257 if len(b) < l {
258 return nil, errMessageTooShort
259 }
260 b = b[l:]
261 case syscall.AF_INET, syscall.AF_INET6:
262 af = int(b[1])
263 a, err := parseInetAddr(af, b)
264 if err != nil {
265 return nil, err
266 }
267 as[i] = a
268 l := roundup(int(b[0]))
269 if len(b) < l {
270 return nil, errMessageTooShort
271 }
272 b = b[l:]
273 default:
274 l, a, err := parseKernelInetAddr(af, b)
275 if err != nil {
276 return nil, err
277 }
278 as[i] = a
279 ll := roundup(l)
280 if len(b) < ll {
281 b = b[l:]
282 } else {
283 b = b[ll:]
284 }
285 }
286 } else {
287 // Skip unknown addresses.
288 l := roundup(int(b[0]))
289 if len(b) < l {
290 return nil, errMessageTooShort
291 }
292 b = b[l:]
293 }
294 }
295 // The only remaining bytes in b should be alignment.
296 // However, under some circumstances DragonFly BSD appears to put
297 // more addresses in the message than are indicated in the address
298 // bitmask, so don't check for this.
299 return as[:], nil
300 }
301