github.com/kelleygo/clashcore@v1.0.2/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/kelleygo/clashcore/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 }