mirror of
https://github.com/shtorm-7/sing-box-extended.git
synced 2026-09-15 21:00:27 +00:00
83 lines
2.2 KiB
Go
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{}
|
|
}
|
|
}
|