Skip to content

Commit

Permalink
route: fix address parsing of messages on Darwin
Browse files Browse the repository at this point in the history
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 <[email protected]>
Reviewed-by: Ian Lance Taylor <[email protected]>
Reviewed-by: Dmitri Shuralyov <[email protected]>
Auto-Submit: Ian Lance Taylor <[email protected]>
  • Loading branch information
hurricanehrndz authored and gopherbot committed Sep 6, 2024
1 parent 35b4aba commit 3c333c0
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 5 deletions.
27 changes: 22 additions & 5 deletions route/address.go
Original file line number Diff line number Diff line change
Expand Up @@ -170,20 +170,37 @@ func (a *Inet6Addr) marshal(b []byte) (int, error) {

// parseInetAddr parses b as an internet address for IPv4 or IPv6.
func parseInetAddr(af int, b []byte) (Addr, error) {
const (
off4 = 4 // offset of in_addr
off6 = 8 // offset of in6_addr
)
switch af {
case syscall.AF_INET:
if len(b) < sizeofSockaddrInet {
if len(b) < (off4+1) || len(b) < int(b[0]) {
return nil, errInvalidAddr
}
sockAddrLen := int(b[0])
a := &Inet4Addr{}
copy(a.IP[:], b[4:8])
n := off4 + 4
if sockAddrLen < n {
n = sockAddrLen
}
copy(a.IP[:], b[off4:n])
return a, nil
case syscall.AF_INET6:
if len(b) < sizeofSockaddrInet6 {
if len(b) < (off6+1) || len(b) < int(b[0]) {
return nil, errInvalidAddr
}
a := &Inet6Addr{ZoneID: int(nativeEndian.Uint32(b[24:28]))}
copy(a.IP[:], b[8:24])
sockAddrLen := int(b[0])
n := off6 + 16
if sockAddrLen < n {
n = sockAddrLen
}
a := &Inet6Addr{}
if sockAddrLen == sizeofSockaddrInet6 {
a.ZoneID = int(nativeEndian.Uint32(b[24:28]))
}
copy(a.IP[:], b[off6:n])
if a.IP[0] == 0xfe && a.IP[1]&0xc0 == 0x80 || a.IP[0] == 0xff && (a.IP[1]&0x0f == 0x01 || a.IP[1]&0x0f == 0x02) {
// KAME based IPv6 protocol stack usually
// embeds the interface index in the
Expand Down
54 changes: 54 additions & 0 deletions route/address_darwin_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,60 @@ var parseAddrsOnDarwinLittleEndianTests = []parseAddrsOnDarwinTest{
nil,
},
},
{
syscall.RTA_DST | syscall.RTA_GATEWAY | syscall.RTA_NETMASK,
parseKernelInetAddr,
[]byte{
0x10, 0x02, 0x00, 0x00, 0x64, 0x71, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

0x14, 0x12, 0x21, 0x00, 0x01, 0x08, 0x00, 0x00,
0x75, 0x74, 0x75, 0x6e, 0x34, 0x33, 0x31, 0x39,
0x00, 0x00, 0x00, 0x00,

0x06, 0x02, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
},
[]Addr{
&Inet4Addr{IP: [4]byte{100, 113, 0, 0}},
&LinkAddr{Index: 33, Name: "utun4319"},
&Inet4Addr{IP: [4]byte{255, 255, 0, 0}},
nil,
nil,
nil,
nil,
nil,
},
},
// route -n add -inet6 fd84:1b4e:6281:: -prefixlen 48 fe80::f22f:4bff:fe09:3bff%utun4319
// gw fe80:0000:0000:0000:f22f:4bff:fe09:3bff
{
syscall.RTA_DST | syscall.RTA_GATEWAY | syscall.RTA_NETMASK,
parseKernelInetAddr,
[]byte{
0x1c, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xfd, 0x84, 0x1b, 0x4e, 0x62, 0x81, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,

0x1c, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xfe, 0x80, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00,
0xf2, 0x2f, 0x4b, 0xff, 0xfe, 0x09, 0x3b, 0xff,
0x00, 0x00, 0x00, 0x00,

0x0e, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00,
},
[]Addr{
&Inet6Addr{IP: [16]byte{ 0xfd, 0x84, 0x1b, 0x4e, 0x62, 0x81 }},
&Inet6Addr{IP: [16]byte{ 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf2, 0x2f, 0x4b, 0xff, 0xfe, 0x09, 0x3b, 0xff }, ZoneID: 33},
&Inet6Addr{IP: [16]byte{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,}},
nil,
nil,
nil,
nil,
nil,
},
},
}

func TestParseAddrsOnDarwin(t *testing.T) {
Expand Down

0 comments on commit 3c333c0

Please sign in to comment.