github.com/chwjbn/xclash@v0.2.0/component/dialer/bind_others.go (about)

     1  //go:build !linux && !darwin
     2  // +build !linux,!darwin
     3  
     4  package dialer
     5  
     6  import (
     7  	"net"
     8  	"strconv"
     9  	"strings"
    10  
    11  	"github.com/chwjbn/xclash/component/iface"
    12  )
    13  
    14  func lookupLocalAddr(ifaceName string, network string, destination net.IP, port int) (net.Addr, error) {
    15  	ifaceObj, err := iface.ResolveInterface(ifaceName)
    16  	if err != nil {
    17  		return nil, err
    18  	}
    19  
    20  	var addr *net.IPNet
    21  	switch network {
    22  	case "udp4", "tcp4":
    23  		addr, err = ifaceObj.PickIPv4Addr(destination)
    24  	case "tcp6", "udp6":
    25  		addr, err = ifaceObj.PickIPv6Addr(destination)
    26  	default:
    27  		if destination != nil {
    28  			if destination.To4() != nil {
    29  				addr, err = ifaceObj.PickIPv4Addr(destination)
    30  			} else {
    31  				addr, err = ifaceObj.PickIPv6Addr(destination)
    32  			}
    33  		} else {
    34  			addr, err = ifaceObj.PickIPv4Addr(destination)
    35  		}
    36  	}
    37  	if err != nil {
    38  		return nil, err
    39  	}
    40  
    41  	if strings.HasPrefix(network, "tcp") {
    42  		return &net.TCPAddr{
    43  			IP:   addr.IP,
    44  			Port: port,
    45  		}, nil
    46  	} else if strings.HasPrefix(network, "udp") {
    47  		return &net.UDPAddr{
    48  			IP:   addr.IP,
    49  			Port: port,
    50  		}, nil
    51  	}
    52  
    53  	return nil, iface.ErrAddrNotFound
    54  }
    55  
    56  func bindIfaceToDialer(ifaceName string, dialer *net.Dialer, network string, destination net.IP) error {
    57  	if !destination.IsGlobalUnicast() {
    58  		return nil
    59  	}
    60  
    61  	local := uint64(0)
    62  	if dialer.LocalAddr != nil {
    63  		_, port, err := net.SplitHostPort(dialer.LocalAddr.String())
    64  		if err == nil {
    65  			local, _ = strconv.ParseUint(port, 10, 16)
    66  		}
    67  	}
    68  
    69  	addr, err := lookupLocalAddr(ifaceName, network, destination, int(local))
    70  	if err != nil {
    71  		return err
    72  	}
    73  
    74  	dialer.LocalAddr = addr
    75  
    76  	return nil
    77  }
    78  
    79  func bindIfaceToListenConfig(ifaceName string, _ *net.ListenConfig, network, address string) (string, error) {
    80  	_, port, err := net.SplitHostPort(address)
    81  	if err != nil {
    82  		port = "0"
    83  	}
    84  
    85  	local, _ := strconv.ParseUint(port, 10, 16)
    86  
    87  	addr, err := lookupLocalAddr(ifaceName, network, nil, int(local))
    88  	if err != nil {
    89  		return "", err
    90  	}
    91  
    92  	return addr.String(), nil
    93  }