clash_darwin_test.go 1.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. package main
  2. import (
  3. "errors"
  4. "fmt"
  5. "net"
  6. "net/netip"
  7. "syscall"
  8. "golang.org/x/net/route"
  9. )
  10. func defaultRouteIP() (netip.Addr, error) {
  11. idx, err := defaultRouteInterfaceIndex()
  12. if err != nil {
  13. return netip.Addr{}, err
  14. }
  15. iface, err := net.InterfaceByIndex(idx)
  16. if err != nil {
  17. return netip.Addr{}, err
  18. }
  19. addrs, err := iface.Addrs()
  20. if err != nil {
  21. return netip.Addr{}, err
  22. }
  23. for _, addr := range addrs {
  24. ip := addr.(*net.IPNet).IP
  25. if ip.To4() != nil {
  26. return netip.AddrFrom4([4]byte(ip)), nil
  27. }
  28. }
  29. return netip.Addr{}, errors.New("no ipv4 addr")
  30. }
  31. func defaultRouteInterfaceIndex() (int, error) {
  32. rib, err := route.FetchRIB(syscall.AF_UNSPEC, syscall.NET_RT_DUMP2, 0)
  33. if err != nil {
  34. return 0, fmt.Errorf("route.FetchRIB: %w", err)
  35. }
  36. msgs, err := route.ParseRIB(syscall.NET_RT_IFLIST2, rib)
  37. if err != nil {
  38. return 0, fmt.Errorf("route.ParseRIB: %w", err)
  39. }
  40. for _, message := range msgs {
  41. routeMessage := message.(*route.RouteMessage)
  42. if routeMessage.Flags&(syscall.RTF_UP|syscall.RTF_GATEWAY|syscall.RTF_STATIC) == 0 {
  43. continue
  44. }
  45. addresses := routeMessage.Addrs
  46. destination, ok := addresses[0].(*route.Inet4Addr)
  47. if !ok {
  48. continue
  49. }
  50. if destination.IP != [4]byte{0, 0, 0, 0} {
  51. continue
  52. }
  53. switch addresses[1].(type) {
  54. case *route.Inet4Addr:
  55. return routeMessage.Index, nil
  56. default:
  57. continue
  58. }
  59. }
  60. return 0, fmt.Errorf("ambiguous gateway interfaces found")
  61. }