Skip to content

Commit

Permalink
route: fix address parsing of messages on Darwin
Browse files Browse the repository at this point in the history
partial fix golang/go#44740

sizeofSockaddrInet is 16, but first byte of sockaddr specifies the size
of the address.

16 works for most cases, except Netmasks addresses, on Darwin where only
the significant bits are in the msg.

Take this route message as an example
```
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
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
DST 10 02 00 00 64 71 00 00 00 00 00 00 00 00 00 00 // 100.113.0.0
GW 14 12 21 00 01 08 00 00 75 74 75 6e 34 33 31 39 00 00 00 00 // !utun4319
MASK 06 02 00 00 ff ff // 255.255.0.0
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 lenght.

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
  • Loading branch information
hurricanehrndz committed Sep 5, 2024
1 parent 35b4aba commit 34e7bf9
Showing 1 changed file with 22 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

0 comments on commit 34e7bf9

Please sign in to comment.