1
2
3
4
5
6
7 package routebsd
8
9 import (
10 "net/netip"
11 "runtime"
12 "syscall"
13 )
14
15
16 type Addr interface {
17
18 Family() int
19 }
20
21
22 type LinkAddr struct {
23 Index int
24 Name string
25 Addr []byte
26 }
27
28
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
44
45 func parseKernelLinkAddr(_ int, b []byte) (int, Addr, error) {
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
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 string
77 var addr []byte
78 if nlen > 0 {
79 name = string(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
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
103 func parseInetAddr(af int, b []byte) (Addr, error) {
104 const (
105 off4 = 4
106 off6 = 8
107 ipv4Len = 4
108 ipv6Len = 16
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
119
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
144
145
146
147 id := int(bigEndian.Uint16(ip[2:4]))
148 if id != 0 {
149 ip[2], ip[3] = 0, 0
150 }
151 }
152 }
153
154
155 a := &InetAddr{
156 IP: netip.AddrFrom16(ip),
157 }
158 return a, nil
159 default:
160 return nil, errInvalidAddr
161 }
162 }
163
164
165
166 func parseKernelInetAddr(af int, b []byte) (int, Addr, error) {
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186 l := int(b[0])
187 if runtime.GOOS == "darwin" || runtime.GOOS == "ios" {
188
189
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
200
201 const (
202 off4 = 4
203 off6 = 8
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:
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
288 l := roundup(int(b[0]))
289 if len(b) < l {
290 return nil, errMessageTooShort
291 }
292 b = b[l:]
293 }
294 }
295
296
297
298
299 return as[:], nil
300 }
301
View as plain text