github.com/sagernet/sing@v0.2.6/common/control/bind_windows.go (about) 1 package control 2 3 import ( 4 "encoding/binary" 5 "syscall" 6 "unsafe" 7 8 M "github.com/sagernet/sing/common/metadata" 9 ) 10 11 func bindToInterface(conn syscall.RawConn, network string, address string, interfaceName string, interfaceIndex int) error { 12 return Raw(conn, func(fd uintptr) error { 13 handle := syscall.Handle(fd) 14 if M.ParseSocksaddr(address).AddrString() == "" { 15 err := bind4(handle, interfaceIndex) 16 if err != nil { 17 return err 18 } 19 // try bind ipv6, if failed, ignore. it's a workaround for windows disable interface ipv6 20 bind6(handle, interfaceIndex) 21 return nil 22 } 23 switch network { 24 case "tcp4", "udp4", "ip4": 25 return bind4(handle, interfaceIndex) 26 default: 27 return bind6(handle, interfaceIndex) 28 } 29 }) 30 } 31 32 const ( 33 IP_UNICAST_IF = 31 34 IPV6_UNICAST_IF = 31 35 ) 36 37 func bind4(handle syscall.Handle, ifaceIdx int) error { 38 var bytes [4]byte 39 binary.BigEndian.PutUint32(bytes[:], uint32(ifaceIdx)) 40 idx := *(*uint32)(unsafe.Pointer(&bytes[0])) 41 return syscall.SetsockoptInt(handle, syscall.IPPROTO_IP, IP_UNICAST_IF, int(idx)) 42 } 43 44 func bind6(handle syscall.Handle, ifaceIdx int) error { 45 return syscall.SetsockoptInt(handle, syscall.IPPROTO_IPV6, IPV6_UNICAST_IF, ifaceIdx) 46 }