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 }