golang / go

The Go programming language
https://go.dev
BSD 3-Clause "New" or "Revised" License
123.91k stars 17.65k forks source link

net: ListenMulticastUDP setsockopt: not supported by windows #63529

Open bt90 opened 1 year ago

bt90 commented 1 year ago

What version of Go are you using (go version)?

$ go version
go version go1.21.3 windows/amd64

Does this issue reproduce with the latest release?

Yes

What operating system and processor architecture are you using (go env)?

go env Output
$ go env
set GOHOSTARCH=amd64
set GOHOSTOS=windows

What did you do?

package main

import (
    "fmt"
    "net"
)

func main() {
    multicastIP := net.ParseIP("ff02::c")
    multicastAddr := net.UDPAddr{IP: multicastIP}

    interfaces, err := net.Interfaces()
    if err != nil {
        fmt.Println("Failed to list interfaces", err)
        return
    }

    for _, iface := range interfaces {
        if iface.Flags&net.FlagUp == 0 || iface.Flags&net.FlagLoopback != 0 || iface.Flags&net.FlagMulticast == 0 {
            fmt.Println("Skipping interface", iface.Name)
            continue
        }

        conn, err := net.ListenMulticastUDP("udp6", &iface, &multicastAddr)
        if err != nil {
            fmt.Println("Failed to listen on", iface.Name, err)
            continue
        }

        fmt.Println("Listening on", iface.Name)

        defer conn.Close()
    }
}

What did you expect to see?

Example output on a Linux host:

Skipping interface lo
Listening on enp0s31f6
Listening on enxc4cbe10cec3d
Listening on wlp0s20f3
Listening on virbr0
Skipping interface wg0
Skipping interface wg1
Listening on docker0
Listening on br-651beae84a39
Listening on vethfed639d
Listening on vnet0

What did you see instead?

This fails for regular interfaces on Windows 10 and Windows 11 hosts:

Failed to listen on Ethernet-Instanz 0 listen udp6 [ff02::c]:0: setsockopt: not supported by windows
Skipping interface Loopback Pseudo-Interface 1
bcmills commented 1 year ago

(CC @golang/windows)

mauri870 commented 1 year ago

Looks like ListenMulticastUDP calls listenIPv6MulticastUDP to handle ipv6 addresses, which calls joinIPv6Group:

https://github.com/golang/go/blob/883f062fc0a097bf561030ad453fd3e300896975/src/net/sockoptip_posix.go#L40-L50

joinIPv6Group then calls fd.pfd.SetsockoptIPv6Mreq which in turn calls syscall.SetsockoptIPv6Mreq:

https://github.com/golang/go/blob/883f062fc0a097bf561030ad453fd3e300896975/src/internal/poll/sockoptip.go#L20-L28

SetsockoptIPv6Mreq for windows just returns EWINDOWS (aka not supported by windows):

https://github.com/golang/go/blob/883f062fc0a097bf561030ad453fd3e300896975/src/syscall/syscall_windows.go#L1174-L1175

mauri870 commented 1 year ago

Well I decided to just copy what SetsockoptIPMreq does

func SetsockoptIPMreq(fd Handle, level, opt int, mreq *IPMreq) (err error) {
    return Setsockopt(fd, int32(level), int32(opt), (*byte)(unsafe.Pointer(mreq)), int32(unsafe.Sizeof(*mreq)))
}
func SetsockoptIPv6Mreq(fd Handle, level, opt int, mreq *IPv6Mreq) (err error) {
    return Setsockopt(fd, int32(level), int32(opt), (*byte)(unsafe.Pointer(mreq)), int32(unsafe.Sizeof(*mreq)))
}

It appears to have worked

.\udp.exe
Listening on VirtualBox Host-Only Network
Listening on Ethernet
Skipping interface Wi-Fi
Listening on vEthernet (Default Switch)
Listening on vEthernet (WSL)   

tbh I don't known why it is marked as not supported.

mauri870 commented 1 year ago

Also wondering why the test here didn't catch this

https://github.com/golang/go/blob/go1.21.3/src/net/listen_test.go#L603

mauri870 commented 1 year ago

Related https://github.com/golang/go/issues/7174

bcmills commented 1 year ago

Also wondering why the test here didn't catch this

Because os.Getuid always returns -1 on Windows: https://github.com/golang/go/blob/883f062fc0a097bf561030ad453fd3e300896975/src/net/listen_test.go#L613-L615

bt90 commented 1 year ago

@mauri870 is your patch working?

mauri870 commented 1 year ago

@bt90 I just tried to run the example OP provided, it seemed to enumerate the interfaces correctly, I'm not sure about the actual state of IPv6 on windows