Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

net: ListenMulticastUDP setsockopt: not supported by windows #63529

Open
bt90 opened this issue Oct 13, 2023 · 8 comments
Open

net: ListenMulticastUDP setsockopt: not supported by windows #63529

bt90 opened this issue Oct 13, 2023 · 8 comments
Labels
NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. OS-Windows
Milestone

Comments

@bt90
Copy link

bt90 commented Oct 13, 2023

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 bcmills added this to the Backlog milestone Oct 13, 2023
@bcmills
Copy link
Contributor

bcmills commented Oct 13, 2023

(CC @golang/windows)

@dmitshur dmitshur added the NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. label Oct 13, 2023
@mauri870
Copy link
Member

mauri870 commented Oct 14, 2023

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):

func SetsockoptIPv6Mreq(fd Handle, level, opt int, mreq *IPv6Mreq) (err error) { return EWINDOWS }

@mauri870
Copy link
Member

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
Copy link
Member

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
Copy link
Member

Related #7174

@bcmills
Copy link
Contributor

bcmills commented Oct 17, 2023

Also wondering why the test here didn't catch this

Because os.Getuid always returns -1 on Windows:

go/src/net/listen_test.go

Lines 613 to 615 in 883f062

if os.Getuid() != 0 {
t.Skip("must be root")
}

@bt90
Copy link
Author

bt90 commented Nov 1, 2023

@mauri870 is your patch working?

@mauri870
Copy link
Member

mauri870 commented Nov 1, 2023

@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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. OS-Windows
Projects
None yet
Development

No branches or pull requests

4 participants