2022-07-13 11:01:20 +00:00
|
|
|
package dialer
|
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/binary"
|
|
|
|
"net"
|
|
|
|
"net/netip"
|
|
|
|
"syscall"
|
|
|
|
"unsafe"
|
|
|
|
|
|
|
|
"github.com/sagernet/sing-box/adapter"
|
|
|
|
"github.com/sagernet/sing/common/control"
|
|
|
|
E "github.com/sagernet/sing/common/exceptions"
|
|
|
|
|
|
|
|
"golang.org/x/sys/windows"
|
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
|
|
|
IP_UNICAST_IF = 31
|
|
|
|
IPV6_UNICAST_IF = 31
|
|
|
|
)
|
|
|
|
|
|
|
|
func bind4(handle windows.Handle, ifaceIdx int) error {
|
|
|
|
var bytes [4]byte
|
|
|
|
binary.BigEndian.PutUint32(bytes[:], uint32(ifaceIdx))
|
|
|
|
idx := *(*uint32)(unsafe.Pointer(&bytes[0]))
|
|
|
|
return windows.SetsockoptInt(handle, windows.IPPROTO_IP, IP_UNICAST_IF, int(idx))
|
|
|
|
}
|
|
|
|
|
|
|
|
func bind6(handle windows.Handle, ifaceIdx int) error {
|
|
|
|
return windows.SetsockoptInt(handle, windows.IPPROTO_IPV6, IPV6_UNICAST_IF, int(ifaceIdx))
|
|
|
|
}
|
|
|
|
|
|
|
|
func BindToInterface(router adapter.Router) control.Func {
|
|
|
|
return func(network, address string, conn syscall.RawConn) error {
|
2022-07-15 03:51:51 +00:00
|
|
|
interfaceName := router.AutoDetectInterfaceName()
|
2022-07-13 11:01:20 +00:00
|
|
|
if interfaceName == "" {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
ipStr, _, err := net.SplitHostPort(address)
|
|
|
|
if err == nil {
|
|
|
|
if ip, err := netip.ParseAddr(ipStr); err == nil && !ip.IsGlobalUnicast() {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
var innerErr error
|
|
|
|
err = conn.Control(func(fd uintptr) {
|
|
|
|
handle := windows.Handle(fd)
|
|
|
|
// handle ip empty, e.g. net.Listen("udp", ":0")
|
|
|
|
if ipStr == "" {
|
2022-07-15 03:51:51 +00:00
|
|
|
innerErr = bind4(handle, router.AutoDetectInterfaceIndex())
|
2022-07-13 11:01:20 +00:00
|
|
|
if innerErr != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
// try bind ipv6, if failed, ignore. it's a workaround for windows disable interface ipv6
|
2022-07-15 03:51:51 +00:00
|
|
|
bind6(handle, router.AutoDetectInterfaceIndex())
|
2022-07-13 11:01:20 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
switch network {
|
|
|
|
case "tcp4", "udp4", "ip4":
|
2022-07-15 03:51:51 +00:00
|
|
|
innerErr = bind4(handle, router.AutoDetectInterfaceIndex())
|
2022-07-13 11:01:20 +00:00
|
|
|
case "tcp6", "udp6":
|
2022-07-15 03:51:51 +00:00
|
|
|
innerErr = bind6(handle, router.AutoDetectInterfaceIndex())
|
2022-07-13 11:01:20 +00:00
|
|
|
}
|
|
|
|
})
|
|
|
|
return E.Errors(innerErr, err)
|
|
|
|
}
|
|
|
|
}
|