Skip to content

Commit

Permalink
fix: don't ignore bind6 error when udp's target is ipv6 address
Browse files Browse the repository at this point in the history
  • Loading branch information
wwqgtxx committed Apr 17, 2024
1 parent f0ad37a commit 2eab14f
Show file tree
Hide file tree
Showing 7 changed files with 16 additions and 15 deletions.
3 changes: 2 additions & 1 deletion component/dhcp/conn.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package dhcp
import (
"context"
"net"
"net/netip"
"runtime"

"github.com/metacubex/mihomo/component/dialer"
Expand All @@ -24,5 +25,5 @@ func ListenDHCPClient(ctx context.Context, ifaceName string) (net.PacketConn, er
options = append(options, dialer.WithFallbackBind(true))
}

return dialer.ListenPacket(ctx, "udp4", listenAddr, options...)
return dialer.ListenPacket(ctx, "udp4", listenAddr, netip.AddrPortFrom(netip.AddrFrom4([4]byte{255, 255, 255, 255}), 67), options...)
}
2 changes: 1 addition & 1 deletion component/dialer/bind.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ func fallbackBindIfaceToDialer(ifaceName string, dialer *net.Dialer, network str
return nil
}

func fallbackBindIfaceToListenConfig(ifaceName string, _ *net.ListenConfig, network, address string) (string, error) {
func fallbackBindIfaceToListenConfig(ifaceName string, _ *net.ListenConfig, network, address string, rAddrPort netip.AddrPort) (string, error) {
_, port, err := net.SplitHostPort(address)
if err != nil {
port = "0"
Expand Down
2 changes: 1 addition & 1 deletion component/dialer/bind_darwin.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ func bindIfaceToDialer(ifaceName string, dialer *net.Dialer, _ string, _ netip.A
return nil
}

func bindIfaceToListenConfig(ifaceName string, lc *net.ListenConfig, _, address string) (string, error) {
func bindIfaceToListenConfig(ifaceName string, lc *net.ListenConfig, _, address string, rAddrPort netip.AddrPort) (string, error) {
ifaceObj, err := iface.ResolveInterface(ifaceName)
if err != nil {
return "", err
Expand Down
2 changes: 1 addition & 1 deletion component/dialer/bind_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ func bindIfaceToDialer(ifaceName string, dialer *net.Dialer, _ string, _ netip.A
return nil
}

func bindIfaceToListenConfig(ifaceName string, lc *net.ListenConfig, _, address string) (string, error) {
func bindIfaceToListenConfig(ifaceName string, lc *net.ListenConfig, _, address string, rAddrPort netip.AddrPort) (string, error) {
addControlToListenConfig(lc, bindControl(ifaceName))

return address, nil
Expand Down
4 changes: 2 additions & 2 deletions component/dialer/bind_others.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ func bindIfaceToDialer(ifaceName string, dialer *net.Dialer, network string, des
return fallbackBindIfaceToDialer(ifaceName, dialer, network, destination)
}

func bindIfaceToListenConfig(ifaceName string, lc *net.ListenConfig, network, address string) (string, error) {
return fallbackBindIfaceToListenConfig(ifaceName, lc, network, address)
func bindIfaceToListenConfig(ifaceName string, lc *net.ListenConfig, network, address string, rAddrPort netip.AddrPort) (string, error) {
return fallbackBindIfaceToListenConfig(ifaceName, lc, network, address, rAddrPort)
}

func ParseNetwork(network string, addr netip.Addr) string {
Expand Down
12 changes: 6 additions & 6 deletions component/dialer/bind_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ func bind6(handle syscall.Handle, ifaceIdx int) error {
return syscall.SetsockoptInt(handle, syscall.IPPROTO_IPV6, IPV6_UNICAST_IF, ifaceIdx)
}

func bindControl(ifaceIdx int) controlFn {
func bindControl(ifaceIdx int, rAddrPort netip.AddrPort) controlFn {
return func(ctx context.Context, network, address string, c syscall.RawConn) (err error) {
addrPort, err := netip.ParseAddrPort(address)
if err == nil && !addrPort.Addr().IsGlobalUnicast() {
Expand All @@ -46,7 +46,7 @@ func bindControl(ifaceIdx int) controlFn {
innerErr = bind4err
case "udp6":
// golang will set network to udp6 when listenUDP on wildcard ip (eg: ":0", "")
if (!addrPort.Addr().IsValid() || addrPort.Addr().IsUnspecified()) && bind6err != nil {
if (!addrPort.Addr().IsValid() || addrPort.Addr().IsUnspecified()) && bind6err != nil && rAddrPort.Addr().Unmap().Is4() {
// try bind ipv6, if failed, ignore. it's a workaround for windows disable interface ipv6
if bind4err != nil {
innerErr = bind6err
Expand All @@ -67,23 +67,23 @@ func bindControl(ifaceIdx int) controlFn {
}
}

func bindIfaceToDialer(ifaceName string, dialer *net.Dialer, _ string, _ netip.Addr) error {
func bindIfaceToDialer(ifaceName string, dialer *net.Dialer, _ string, destination netip.Addr) error {
ifaceObj, err := iface.ResolveInterface(ifaceName)
if err != nil {
return err
}

addControlToDialer(dialer, bindControl(ifaceObj.Index))
addControlToDialer(dialer, bindControl(ifaceObj.Index, netip.AddrPortFrom(destination, 0)))
return nil
}

func bindIfaceToListenConfig(ifaceName string, lc *net.ListenConfig, _, address string) (string, error) {
func bindIfaceToListenConfig(ifaceName string, lc *net.ListenConfig, _, address string, rAddrPort netip.AddrPort) (string, error) {
ifaceObj, err := iface.ResolveInterface(ifaceName)
if err != nil {
return "", err
}

addControlToListenConfig(lc, bindControl(ifaceObj.Index))
addControlToListenConfig(lc, bindControl(ifaceObj.Index, rAddrPort))
return address, nil
}

Expand Down
6 changes: 3 additions & 3 deletions component/dialer/dialer.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ func DialContext(ctx context.Context, network, address string, options ...Option
}
}

func ListenPacket(ctx context.Context, network, address string, options ...Option) (net.PacketConn, error) {
func ListenPacket(ctx context.Context, network, address string, rAddrPort netip.AddrPort, options ...Option) (net.PacketConn, error) {
cfg := applyOptions(options...)

lc := &net.ListenConfig{}
Expand All @@ -46,7 +46,7 @@ func ListenPacket(ctx context.Context, network, address string, options ...Optio
if cfg.fallbackBind {
bind = fallbackBindIfaceToListenConfig
}
addr, err := bind(cfg.interfaceName, lc, network, address)
addr, err := bind(cfg.interfaceName, lc, network, address, rAddrPort)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -416,7 +416,7 @@ func (d Dialer) ListenPacket(ctx context.Context, network, address string, rAddr
// avoid "The requested address is not valid in its context."
opt = WithInterface("")
}
return ListenPacket(ctx, ParseNetwork(network, rAddrPort.Addr()), address, opt)
return ListenPacket(ctx, ParseNetwork(network, rAddrPort.Addr()), address, rAddrPort, opt)
}

func NewDialer(options ...Option) Dialer {
Expand Down

0 comments on commit 2eab14f

Please sign in to comment.