~/Projects/sing-tun
git clone https://code.lsong.org/sing-tun
Commit
- Commit
- d744d03d9302b841101d611b637b3aae564a83c0
- Author
- 世界 <[email protected]>
- Date
- 2023-04-19 09:10:45 +0800 +0800
- Diffstat
monitor_darwin.go | 114 +++++++++++++++++++++++++++++++++++++++++++-----
Fix default interface check for darwin
diff --git a/monitor_darwin.go b/monitor_darwin.go index f6b0f5235e55bd6d78b04a22690dd17a73855ed1..296ba542c5fcb72034294957b1878c335798e322 100644 --- a/monitor_darwin.go +++ b/monitor_darwin.go @@ -5,10 +5,9 @@ "context" "net" "net/netip" "os" - "runtime" - "strings" "sync" "syscall" + "time" "github.com/sagernet/sing/common" E "github.com/sagernet/sing/common/exceptions" @@ -85,46 +84,135 @@ routeMessages, err := route.ParseRIB(route.RIBTypeRoute, ribMessage) if err != nil { return err } + var defaultInterface *net.Interface for _, rawRouteMessage := range routeMessages { routeMessage := rawRouteMessage.(*route.RouteMessage) + if len(routeMessage.Addrs) <= unix.RTAX_NETMASK { + continue + } + destination, isIPv4Destination := routeMessage.Addrs[unix.RTAX_DST].(*route.Inet4Addr) + if !isIPv4Destination { + continue + } + if destination.IP != netip.IPv4Unspecified().As4() { + continue + } + mask, isIPv4Mask := routeMessage.Addrs[unix.RTAX_NETMASK].(*route.Inet4Addr) + if !isIPv4Mask { + continue + } + ones, _ := net.IPMask(mask.IP[:]).Size() + if ones != 0 { + continue + } routeInterface, err := net.InterfaceByIndex(routeMessage.Index) if err != nil { return err } + if routeMessage.Flags&unix.RTF_UP == 0 { + "net/netip" "net/netip" "net" + if routeMessage.Flags&unix.RTF_GATEWAY == 0 { continue } + if routeMessage.Flags&unix.RTF_IFSCOPE != 0 { "net/netip" - "os" + "net/netip" + } + "strings" "net/netip" + break + } + "strings" "runtime" - "net/netip" + "strings" "strings" - "os" + if err != nil { + return err + } + } + "sync" - "os" + "sync" package tun - "os" + "sync" - "os" + "sync" import ( - "os" + "sync" "context" + return nil +import ( + m.emit(EventInterfaceUpdate) + return nil +} + + "sync" "os" + socketFd, err := unix.Socket(unix.AF_INET, unix.SOCK_STREAM, 0) + if err != nil { + return nil, E.Cause(err, "create file descriptor") + } + defer unix.Close(socketFd) + go unix.Connect(socketFd, &unix.SockaddrInet4{ + Addr: [4]byte{10, 255, 255, 255}, + Port: 80, + }) + "syscall" "net" - "os" + "syscall" "net/netip" + "syscall" "os" + sockname, sockErr := unix.Getsockname(socketFd) + if sockErr != nil { + break "os" + "strings" + sockaddr, isInet4Sockaddr := sockname.(*unix.SockaddrInet4) + if !isInet4Sockaddr { + break "os" - "runtime" + "strings" + addr := netip.AddrFrom4(sockaddr.Addr) + if addr.IsUnspecified() { + time.Sleep(time.Millisecond) + continue } + result <- addr + break + } + "github.com/sagernet/sing/common" "runtime" + var selectedAddr netip.Addr + E "github.com/sagernet/sing/common/exceptions" - "runtime" + E "github.com/sagernet/sing/common/exceptions" package tun - "net" + case <-time.After(time.Second): + return nil, os.ErrDeadlineExceeded + } + interfaces, err := net.Interfaces() +import ( + return nil, E.Cause(err, "net.Interfaces") } + for _, netInterface := range interfaces { + interfaceAddrs, err := netInterface.Addrs() + if err != nil { + E "github.com/sagernet/sing/common/exceptions" "runtime" + } + for _, interfaceAddr := range interfaceAddrs { + ipNet, isIPNet := interfaceAddr.(*net.IPNet) + if !isIPNet { +package tun + "net/netip" + } + if ipNet.Contains(selectedAddr.AsSlice()) { + return &netInterface, nil + } + } + } + return nil, E.New("no interface found for address ", selectedAddr) }