github.com/sagernet/sing@v0.2.6/common/control/bind.go (about)

     1  package control
     2  
     3  import (
     4  	"os"
     5  	"runtime"
     6  	"syscall"
     7  
     8  	M "github.com/sagernet/sing/common/metadata"
     9  	N "github.com/sagernet/sing/common/network"
    10  )
    11  
    12  func BindToInterface(finder InterfaceFinder, interfaceName string, interfaceIndex int) Func {
    13  	return func(network, address string, conn syscall.RawConn) error {
    14  		return BindToInterface0(finder, conn, network, address, interfaceName, interfaceIndex)
    15  	}
    16  }
    17  
    18  func BindToInterfaceFunc(finder InterfaceFinder, block func(network string, address string) (interfaceName string, interfaceIndex int)) Func {
    19  	return func(network, address string, conn syscall.RawConn) error {
    20  		interfaceName, interfaceIndex := block(network, address)
    21  		return BindToInterface0(finder, conn, network, address, interfaceName, interfaceIndex)
    22  	}
    23  }
    24  
    25  const useInterfaceName = runtime.GOOS == "linux" || runtime.GOOS == "android"
    26  
    27  func BindToInterface0(finder InterfaceFinder, conn syscall.RawConn, network string, address string, interfaceName string, interfaceIndex int) error {
    28  	if addr := M.ParseSocksaddr(address).Addr; addr.IsValid() && N.IsVirtual(addr) {
    29  		return nil
    30  	}
    31  	if interfaceName == "" && interfaceIndex == -1 {
    32  		return nil
    33  	}
    34  	if interfaceName != "" && useInterfaceName || interfaceIndex != -1 && !useInterfaceName {
    35  		return bindToInterface(conn, network, address, interfaceName, interfaceIndex)
    36  	}
    37  	if finder == nil {
    38  		return os.ErrInvalid
    39  	}
    40  	var err error
    41  	if useInterfaceName {
    42  		interfaceName, err = finder.InterfaceNameByIndex(interfaceIndex)
    43  	} else {
    44  		interfaceIndex, err = finder.InterfaceIndexByName(interfaceName)
    45  	}
    46  	if err != nil {
    47  		return err
    48  	}
    49  	if useInterfaceName {
    50  		if interfaceName == "" {
    51  			return nil
    52  		}
    53  	} else {
    54  		if interfaceIndex == -1 {
    55  			return nil
    56  		}
    57  	}
    58  	return bindToInterface(conn, network, address, interfaceName, interfaceIndex)
    59  }