Files
sing-box-extended-mirror/route/network_environment_darwin.go
T

83 lines
2.2 KiB
Go

package route
import (
"net"
"net/netip"
"slices"
"golang.org/x/net/route"
"golang.org/x/sys/unix"
)
func systemGateways(interfaceIndex int) []netip.Addr {
rib, err := route.FetchRIB(unix.AF_UNSPEC, route.RIBTypeRoute, 0)
if err != nil {
return nil
}
messages, err := route.ParseRIB(route.RIBTypeRoute, rib)
if err != nil {
return nil
}
var gateways []netip.Addr
for _, message := range messages {
routeMessage, isRouteMessage := message.(*route.RouteMessage)
if !isRouteMessage || routeMessage.Index != interfaceIndex || routeMessage.Flags&unix.RTF_GATEWAY == 0 {
continue
}
destination := routeAddressAt(routeMessage.Addrs, unix.RTAX_DST)
if !destination.IsValid() || !destination.IsUnspecified() {
continue
}
gateway := routeAddressAt(routeMessage.Addrs, unix.RTAX_GATEWAY)
if gateway.IsValid() {
gateways = append(gateways, gateway)
}
}
return gateways
}
func systemNeighborHardwareAddresses(interfaceIndex int, addresses []netip.Addr) map[netip.Addr]net.HardwareAddr {
rib, err := route.FetchRIB(unix.AF_UNSPEC, route.RIBType(unix.NET_RT_FLAGS), unix.RTF_LLINFO)
if err != nil {
return nil
}
messages, err := route.ParseRIB(route.RIBTypeRoute, rib)
if err != nil {
return nil
}
hardwareAddresses := make(map[netip.Addr]net.HardwareAddr)
for _, message := range messages {
routeMessage, isRouteMessage := message.(*route.RouteMessage)
if !isRouteMessage || routeMessage.Index != interfaceIndex {
continue
}
destination := routeAddressAt(routeMessage.Addrs, unix.RTAX_DST)
if !slices.Contains(addresses, destination) {
continue
}
if len(routeMessage.Addrs) <= unix.RTAX_GATEWAY {
continue
}
linkAddress, isLinkAddress := routeMessage.Addrs[unix.RTAX_GATEWAY].(*route.LinkAddr)
if !isLinkAddress || len(linkAddress.Addr) == 0 {
continue
}
hardwareAddresses[destination] = net.HardwareAddr(linkAddress.Addr)
}
return hardwareAddresses
}
func routeAddressAt(addresses []route.Addr, index int) netip.Addr {
if len(addresses) <= index {
return netip.Addr{}
}
switch address := addresses[index].(type) {
case *route.Inet4Addr:
return netip.AddrFrom4(address.IP)
case *route.Inet6Addr:
return netip.AddrFrom16(address.IP)
default:
return netip.Addr{}
}
}