github.com/sagernet/sing-box@v1.9.0-rc.20/experimental/libbox/monitor.go (about)

     1  package libbox
     2  
     3  import (
     4  	"net"
     5  	"net/netip"
     6  	"sync"
     7  
     8  	"github.com/sagernet/sing-tun"
     9  	"github.com/sagernet/sing/common"
    10  	E "github.com/sagernet/sing/common/exceptions"
    11  	"github.com/sagernet/sing/common/logger"
    12  	M "github.com/sagernet/sing/common/metadata"
    13  	"github.com/sagernet/sing/common/x/list"
    14  )
    15  
    16  var (
    17  	_ tun.DefaultInterfaceMonitor = (*platformDefaultInterfaceMonitor)(nil)
    18  	_ InterfaceUpdateListener     = (*platformDefaultInterfaceMonitor)(nil)
    19  )
    20  
    21  type platformDefaultInterfaceMonitor struct {
    22  	*platformInterfaceWrapper
    23  	networkAddresses      []networkAddress
    24  	defaultInterfaceName  string
    25  	defaultInterfaceIndex int
    26  	element               *list.Element[tun.NetworkUpdateCallback]
    27  	access                sync.Mutex
    28  	callbacks             list.List[tun.DefaultInterfaceUpdateCallback]
    29  	logger                logger.Logger
    30  }
    31  
    32  type networkAddress struct {
    33  	interfaceName  string
    34  	interfaceIndex int
    35  	addresses      []netip.Prefix
    36  }
    37  
    38  func (m *platformDefaultInterfaceMonitor) Start() error {
    39  	return m.iif.StartDefaultInterfaceMonitor(m)
    40  }
    41  
    42  func (m *platformDefaultInterfaceMonitor) Close() error {
    43  	return m.iif.CloseDefaultInterfaceMonitor(m)
    44  }
    45  
    46  func (m *platformDefaultInterfaceMonitor) DefaultInterfaceName(destination netip.Addr) string {
    47  	for _, address := range m.networkAddresses {
    48  		for _, prefix := range address.addresses {
    49  			if prefix.Contains(destination) {
    50  				return address.interfaceName
    51  			}
    52  		}
    53  	}
    54  	return m.defaultInterfaceName
    55  }
    56  
    57  func (m *platformDefaultInterfaceMonitor) DefaultInterfaceIndex(destination netip.Addr) int {
    58  	for _, address := range m.networkAddresses {
    59  		for _, prefix := range address.addresses {
    60  			if prefix.Contains(destination) {
    61  				return address.interfaceIndex
    62  			}
    63  		}
    64  	}
    65  	return m.defaultInterfaceIndex
    66  }
    67  
    68  func (m *platformDefaultInterfaceMonitor) DefaultInterface(destination netip.Addr) (string, int) {
    69  	for _, address := range m.networkAddresses {
    70  		for _, prefix := range address.addresses {
    71  			if prefix.Contains(destination) {
    72  				return address.interfaceName, address.interfaceIndex
    73  			}
    74  		}
    75  	}
    76  	return m.defaultInterfaceName, m.defaultInterfaceIndex
    77  }
    78  
    79  func (m *platformDefaultInterfaceMonitor) OverrideAndroidVPN() bool {
    80  	return false
    81  }
    82  
    83  func (m *platformDefaultInterfaceMonitor) AndroidVPNEnabled() bool {
    84  	return false
    85  }
    86  
    87  func (m *platformDefaultInterfaceMonitor) RegisterCallback(callback tun.DefaultInterfaceUpdateCallback) *list.Element[tun.DefaultInterfaceUpdateCallback] {
    88  	m.access.Lock()
    89  	defer m.access.Unlock()
    90  	return m.callbacks.PushBack(callback)
    91  }
    92  
    93  func (m *platformDefaultInterfaceMonitor) UnregisterCallback(element *list.Element[tun.DefaultInterfaceUpdateCallback]) {
    94  	m.access.Lock()
    95  	defer m.access.Unlock()
    96  	m.callbacks.Remove(element)
    97  }
    98  
    99  func (m *platformDefaultInterfaceMonitor) UpdateDefaultInterface(interfaceName string, interfaceIndex32 int32) {
   100  	if interfaceName == "" || interfaceIndex32 == -1 {
   101  		m.defaultInterfaceName = ""
   102  		m.defaultInterfaceIndex = -1
   103  		m.access.Lock()
   104  		callbacks := m.callbacks.Array()
   105  		m.access.Unlock()
   106  		for _, callback := range callbacks {
   107  			callback(tun.EventNoRoute)
   108  		}
   109  		return
   110  	}
   111  	var err error
   112  	if m.iif.UsePlatformInterfaceGetter() {
   113  		err = m.updateInterfacesPlatform()
   114  	} else {
   115  		err = m.updateInterfaces()
   116  	}
   117  	if err == nil {
   118  		err = m.router.UpdateInterfaces()
   119  	}
   120  	if err != nil {
   121  		m.logger.Error(E.Cause(err, "update interfaces"))
   122  	}
   123  	interfaceIndex := int(interfaceIndex32)
   124  	if m.defaultInterfaceName == interfaceName && m.defaultInterfaceIndex == interfaceIndex {
   125  		return
   126  	}
   127  	m.defaultInterfaceName = interfaceName
   128  	m.defaultInterfaceIndex = interfaceIndex
   129  	m.access.Lock()
   130  	callbacks := m.callbacks.Array()
   131  	m.access.Unlock()
   132  	for _, callback := range callbacks {
   133  		callback(tun.EventInterfaceUpdate)
   134  	}
   135  }
   136  
   137  func (m *platformDefaultInterfaceMonitor) updateInterfaces() error {
   138  	interfaces, err := net.Interfaces()
   139  	if err != nil {
   140  		return err
   141  	}
   142  	var addresses []networkAddress
   143  	for _, iif := range interfaces {
   144  		var netAddresses []net.Addr
   145  		netAddresses, err = iif.Addrs()
   146  		if err != nil {
   147  			return err
   148  		}
   149  		var address networkAddress
   150  		address.interfaceName = iif.Name
   151  		address.interfaceIndex = iif.Index
   152  		address.addresses = common.Map(common.FilterIsInstance(netAddresses, func(it net.Addr) (*net.IPNet, bool) {
   153  			value, loaded := it.(*net.IPNet)
   154  			return value, loaded
   155  		}), func(it *net.IPNet) netip.Prefix {
   156  			bits, _ := it.Mask.Size()
   157  			return netip.PrefixFrom(M.AddrFromIP(it.IP), bits)
   158  		})
   159  		addresses = append(addresses, address)
   160  	}
   161  	m.networkAddresses = addresses
   162  	return nil
   163  }
   164  
   165  func (m *platformDefaultInterfaceMonitor) updateInterfacesPlatform() error {
   166  	interfaces, err := m.Interfaces()
   167  	if err != nil {
   168  		return err
   169  	}
   170  	var addresses []networkAddress
   171  	for _, iif := range interfaces {
   172  		var address networkAddress
   173  		address.interfaceName = iif.Name
   174  		address.interfaceIndex = iif.Index
   175  		// address.addresses = common.Map(iif.Addresses, netip.MustParsePrefix)
   176  		addresses = append(addresses, address)
   177  	}
   178  	m.networkAddresses = addresses
   179  	return nil
   180  }