Skip to content

Commit 3c333c0

Browse files
hurricanehrndzgopherbot
authored andcommitted
route: fix address parsing of messages on Darwin
sizeofSockaddrInet is 16, but first byte of sockaddr specifies actual size of sockaddr. Although, 16 works for most cases, it fails for Netmasks addresses. On Darwin only the significant bits of the netmask are in the msg. Take this route message as an example ``` // rt_msg_hdr 88 00 05 01 00 00 00 00 41 08 00 00 07 00 00 00 92 7b 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 // metrics 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 // SOCKADDRS - DST (100.113.0.0) 10 02 00 00 64 71 00 00 00 00 00 00 00 00 00 00 // GW utun4319 14 12 21 00 01 08 00 00 75 74 75 6e 34 33 31 39 00 00 00 00 // NETMASK 255.255.0.0 06 02 00 00 ff ff // NULL 00 00 ``` i.e. ipv4 ``` 06 02 00 00 ff ff ``` The above byte sequence is for a sockaddr that is 6 bytes long representing an ipv4 for address that is 255.255.0.0. i.e. ipv6 netmask ``` 0e 1e 00 00 00 00 00 00 ff ff ff ff ff ff 00 00 ``` The above is `/48` netmask that should also be parsed using `b[0]` of the sockaddr that contains the length. Confirmed by using `route monitor`. sources: https://github.com/apple/darwin-xnu/blob/main/bsd/net/route.h https://github.com/apple/darwin-xnu/blob/main/bsd/sys/socket.h#L603 Fixes golang/go#44740 Change-Id: I8153130d02d0a5e547fbf60a85762d3889e1d08c GitHub-Last-Rev: f7b9253 GitHub-Pull-Request: #220 Reviewed-on: https://go-review.googlesource.com/c/net/+/609577 LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Ian Lance Taylor <iant@google.com> Reviewed-by: Dmitri Shuralyov <dmitshur@google.com> Auto-Submit: Ian Lance Taylor <iant@google.com>
1 parent 35b4aba commit 3c333c0

File tree

2 files changed

+76
-5
lines changed

2 files changed

+76
-5
lines changed

route/address.go

+22-5
Original file line numberDiff line numberDiff line change
@@ -170,20 +170,37 @@ func (a *Inet6Addr) marshal(b []byte) (int, error) {
170170

171171
// parseInetAddr parses b as an internet address for IPv4 or IPv6.
172172
func parseInetAddr(af int, b []byte) (Addr, error) {
173+
const (
174+
off4 = 4 // offset of in_addr
175+
off6 = 8 // offset of in6_addr
176+
)
173177
switch af {
174178
case syscall.AF_INET:
175-
if len(b) < sizeofSockaddrInet {
179+
if len(b) < (off4+1) || len(b) < int(b[0]) {
176180
return nil, errInvalidAddr
177181
}
182+
sockAddrLen := int(b[0])
178183
a := &Inet4Addr{}
179-
copy(a.IP[:], b[4:8])
184+
n := off4 + 4
185+
if sockAddrLen < n {
186+
n = sockAddrLen
187+
}
188+
copy(a.IP[:], b[off4:n])
180189
return a, nil
181190
case syscall.AF_INET6:
182-
if len(b) < sizeofSockaddrInet6 {
191+
if len(b) < (off6+1) || len(b) < int(b[0]) {
183192
return nil, errInvalidAddr
184193
}
185-
a := &Inet6Addr{ZoneID: int(nativeEndian.Uint32(b[24:28]))}
186-
copy(a.IP[:], b[8:24])
194+
sockAddrLen := int(b[0])
195+
n := off6 + 16
196+
if sockAddrLen < n {
197+
n = sockAddrLen
198+
}
199+
a := &Inet6Addr{}
200+
if sockAddrLen == sizeofSockaddrInet6 {
201+
a.ZoneID = int(nativeEndian.Uint32(b[24:28]))
202+
}
203+
copy(a.IP[:], b[off6:n])
187204
if a.IP[0] == 0xfe && a.IP[1]&0xc0 == 0x80 || a.IP[0] == 0xff && (a.IP[1]&0x0f == 0x01 || a.IP[1]&0x0f == 0x02) {
188205
// KAME based IPv6 protocol stack usually
189206
// embeds the interface index in the

route/address_darwin_test.go

+54
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,60 @@ var parseAddrsOnDarwinLittleEndianTests = []parseAddrsOnDarwinTest{
4242
nil,
4343
},
4444
},
45+
{
46+
syscall.RTA_DST | syscall.RTA_GATEWAY | syscall.RTA_NETMASK,
47+
parseKernelInetAddr,
48+
[]byte{
49+
0x10, 0x02, 0x00, 0x00, 0x64, 0x71, 0x00, 0x00,
50+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
51+
52+
0x14, 0x12, 0x21, 0x00, 0x01, 0x08, 0x00, 0x00,
53+
0x75, 0x74, 0x75, 0x6e, 0x34, 0x33, 0x31, 0x39,
54+
0x00, 0x00, 0x00, 0x00,
55+
56+
0x06, 0x02, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
57+
},
58+
[]Addr{
59+
&Inet4Addr{IP: [4]byte{100, 113, 0, 0}},
60+
&LinkAddr{Index: 33, Name: "utun4319"},
61+
&Inet4Addr{IP: [4]byte{255, 255, 0, 0}},
62+
nil,
63+
nil,
64+
nil,
65+
nil,
66+
nil,
67+
},
68+
},
69+
// route -n add -inet6 fd84:1b4e:6281:: -prefixlen 48 fe80::f22f:4bff:fe09:3bff%utun4319
70+
// gw fe80:0000:0000:0000:f22f:4bff:fe09:3bff
71+
{
72+
syscall.RTA_DST | syscall.RTA_GATEWAY | syscall.RTA_NETMASK,
73+
parseKernelInetAddr,
74+
[]byte{
75+
0x1c, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76+
0xfd, 0x84, 0x1b, 0x4e, 0x62, 0x81, 0x00, 0x00,
77+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
78+
0x00, 0x00, 0x00, 0x00,
79+
80+
0x1c, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
81+
0xfe, 0x80, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00,
82+
0xf2, 0x2f, 0x4b, 0xff, 0xfe, 0x09, 0x3b, 0xff,
83+
0x00, 0x00, 0x00, 0x00,
84+
85+
0x0e, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
86+
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00,
87+
},
88+
[]Addr{
89+
&Inet6Addr{IP: [16]byte{ 0xfd, 0x84, 0x1b, 0x4e, 0x62, 0x81 }},
90+
&Inet6Addr{IP: [16]byte{ 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf2, 0x2f, 0x4b, 0xff, 0xfe, 0x09, 0x3b, 0xff }, ZoneID: 33},
91+
&Inet6Addr{IP: [16]byte{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,}},
92+
nil,
93+
nil,
94+
nil,
95+
nil,
96+
nil,
97+
},
98+
},
4599
}
46100

47101
func TestParseAddrsOnDarwin(t *testing.T) {

0 commit comments

Comments
 (0)