github.com/metacubex/mihomo@v1.18.5/component/dialer/bind_darwin.go (about)

     1  package dialer
     2  
     3  import (
     4  	"context"
     5  	"net"
     6  	"net/netip"
     7  	"syscall"
     8  
     9  	"github.com/metacubex/mihomo/component/iface"
    10  
    11  	"golang.org/x/sys/unix"
    12  )
    13  
    14  func bindControl(ifaceIdx int) controlFn {
    15  	return func(ctx context.Context, network, address string, c syscall.RawConn) (err error) {
    16  		addrPort, err := netip.ParseAddrPort(address)
    17  		if err == nil && !addrPort.Addr().IsGlobalUnicast() {
    18  			return
    19  		}
    20  
    21  		var innerErr error
    22  		err = c.Control(func(fd uintptr) {
    23  			switch network {
    24  			case "tcp4", "udp4":
    25  				innerErr = unix.SetsockoptInt(int(fd), unix.IPPROTO_IP, unix.IP_BOUND_IF, ifaceIdx)
    26  			case "tcp6", "udp6":
    27  				innerErr = unix.SetsockoptInt(int(fd), unix.IPPROTO_IPV6, unix.IPV6_BOUND_IF, ifaceIdx)
    28  			}
    29  		})
    30  
    31  		if innerErr != nil {
    32  			err = innerErr
    33  		}
    34  
    35  		return
    36  	}
    37  }
    38  
    39  func bindIfaceToDialer(ifaceName string, dialer *net.Dialer, _ string, _ netip.Addr) error {
    40  	ifaceObj, err := iface.ResolveInterface(ifaceName)
    41  	if err != nil {
    42  		return err
    43  	}
    44  
    45  	addControlToDialer(dialer, bindControl(ifaceObj.Index))
    46  	return nil
    47  }
    48  
    49  func bindIfaceToListenConfig(ifaceName string, lc *net.ListenConfig, _, address string, rAddrPort netip.AddrPort) (string, error) {
    50  	ifaceObj, err := iface.ResolveInterface(ifaceName)
    51  	if err != nil {
    52  		return "", err
    53  	}
    54  
    55  	addControlToListenConfig(lc, bindControl(ifaceObj.Index))
    56  	return address, nil
    57  }
    58  
    59  func ParseNetwork(network string, addr netip.Addr) string {
    60  	return network
    61  }