Skip to content

Commit a116280

Browse files
route: fix RTM_GET netmask parsing on Darwin
On Darwin, the AF_FAMILY byte of a sockaddr for a netmask or genmask can be ignored if unreasonable. In such cases, it is the family of the DST address that should instead be used. Depends on golang#231. Fixes golang/go#71578.
1 parent 396d8a2 commit a116280

File tree

2 files changed

+72
-4
lines changed

2 files changed

+72
-4
lines changed

route/address.go

+6-4
Original file line numberDiff line numberDiff line change
@@ -401,8 +401,8 @@ func parseAddrs(attrs uint, fn func(int, []byte) (int, Addr, error), b []byte) (
401401
continue
402402
}
403403
if i <= syscall.RTAX_BRD {
404-
switch b[1] {
405-
case syscall.AF_LINK:
404+
switch {
405+
case b[1] == syscall.AF_LINK:
406406
a, err := parseLinkAddr(b)
407407
if err != nil {
408408
return nil, err
@@ -413,8 +413,10 @@ func parseAddrs(attrs uint, fn func(int, []byte) (int, Addr, error), b []byte) (
413413
return nil, errMessageTooShort
414414
}
415415
b = b[l:]
416-
case syscall.AF_INET, syscall.AF_INET6:
417-
af = int(b[1])
416+
case ((b[1] == syscall.AF_INET || b[1] == syscall.AF_INET6) || ((i == syscall.RTAX_NETMASK || i == syscall.RTAX_GENMASK) && (af == syscall.AF_INET || af == syscall.AF_INET6))):
417+
if (i != syscall.RTAX_NETMASK && i != syscall.RTAX_GENMASK) {
418+
af = int(b[1])
419+
}
418420
a, err := parseInetAddr(af, b)
419421
if err != nil {
420422
return nil, err

route/example_darwin_test.go

+66
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
package route_test
2+
3+
import (
4+
"fmt"
5+
"net/netip"
6+
"os"
7+
"syscall"
8+
9+
"golang.org/x/net/route"
10+
"golang.org/x/sys/unix"
11+
)
12+
13+
func ExampleParseRIB_RTMGet() {
14+
// This example demonstrates how to parse a response to RTM_GET request.
15+
fd, err := unix.Socket(unix.AF_ROUTE, unix.SOCK_RAW, unix.AF_UNSPEC)
16+
if err != nil {
17+
return
18+
}
19+
defer unix.Close(fd)
20+
21+
// Create a RouteMessage with RTM_GET type
22+
rtm := &route.RouteMessage{
23+
Version: syscall.RTM_VERSION,
24+
Type: unix.RTM_GET,
25+
ID: uintptr(os.Getpid()),
26+
Seq: 0,
27+
Addrs: []route.Addr{
28+
&route.Inet4Addr{IP: [4]byte{127, 0, 0, 0}},
29+
},
30+
}
31+
32+
// Marshal the message into bytes
33+
msgBytes, err := rtm.Marshal()
34+
if err != nil {
35+
return
36+
}
37+
38+
// Send the message over the routing socket
39+
_, err = unix.Write(fd, msgBytes)
40+
if err != nil {
41+
return
42+
}
43+
44+
// Read the response from the routing socket
45+
var buf [2 << 10]byte
46+
n, err := unix.Read(fd, buf[:])
47+
if err != nil {
48+
return
49+
}
50+
51+
// Parse the response messages
52+
msgs, err := route.ParseRIB(route.RIBTypeRoute, buf[:n])
53+
if err != nil {
54+
return
55+
}
56+
routeMsg, ok := msgs[0].(*route.RouteMessage)
57+
if !ok {
58+
return
59+
}
60+
netmask, ok := routeMsg.Addrs[2].(*route.Inet4Addr)
61+
if !ok {
62+
return
63+
}
64+
fmt.Println(netip.AddrFrom4(netmask.IP))
65+
// Output: 255.0.0.0
66+
}

0 commit comments

Comments
 (0)