github.com/inazumav/sing-box@v0.0.0-20230926072359-ab51429a14f1/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) OverrideAndroidVPN() bool {
    69  	return false
    70  }
    71  
    72  func (m *platformDefaultInterfaceMonitor) AndroidVPNEnabled() bool {
    73  	return false
    74  }
    75  
    76  func (m *platformDefaultInterfaceMonitor) RegisterCallback(callback tun.DefaultInterfaceUpdateCallback) *list.Element[tun.DefaultInterfaceUpdateCallback] {
    77  	m.access.Lock()
    78  	defer m.access.Unlock()
    79  	return m.callbacks.PushBack(callback)
    80  }
    81  
    82  func (m *platformDefaultInterfaceMonitor) UnregisterCallback(element *list.Element[tun.DefaultInterfaceUpdateCallback]) {
    83  	m.access.Lock()
    84  	defer m.access.Unlock()
    85  	m.callbacks.Remove(element)
    86  }
    87  
    88  func (m *platformDefaultInterfaceMonitor) UpdateDefaultInterface(interfaceName string, interfaceIndex32 int32) {
    89  	var err error
    90  	if m.iif.UsePlatformInterfaceGetter() {
    91  		err = m.updateInterfacesPlatform()
    92  	} else {
    93  		err = m.updateInterfaces()
    94  	}
    95  	if err == nil {
    96  		err = m.router.UpdateInterfaces()
    97  	}
    98  	if err != nil {
    99  		m.logger.Error(E.Cause(err, "update interfaces"))
   100  	}
   101  	interfaceIndex := int(interfaceIndex32)
   102  	if interfaceName == "" {
   103  		for _, netIf := range m.networkAddresses {
   104  			if netIf.interfaceIndex == interfaceIndex {
   105  				interfaceName = netIf.interfaceName
   106  				break
   107  			}
   108  		}
   109  	} else if interfaceIndex == -1 {
   110  		for _, netIf := range m.networkAddresses {
   111  			if netIf.interfaceName == interfaceName {
   112  				interfaceIndex = netIf.interfaceIndex
   113  				break
   114  			}
   115  		}
   116  	}
   117  	if interfaceName == "" {
   118  		m.logger.Error(E.New("invalid interface name for ", interfaceIndex))
   119  		return
   120  	} else if interfaceIndex == -1 {
   121  		m.logger.Error(E.New("invalid interface index for ", interfaceName))
   122  		return
   123  	}
   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  }