]> Cypherpunks repositories - gostls13.git/commitdiff
net: fix ListenMulitcastUDP to work properly when interface has no IPv4
authorJesse Rittner <rittneje@gmail.com>
Sat, 25 Jan 2025 21:21:53 +0000 (16:21 -0500)
committerGopher Robot <gobot@golang.org>
Thu, 6 Feb 2025 17:36:55 +0000 (09:36 -0800)
The existing implementation would either fail or bind to the wrong interface
when the requested interface had no IPv4 address, such as when the Ethernet cable
was unplugged.

Now on Linux, it will always bind to the requested interface.
On other operating systems, it will consistently fail if the requested interface
has no IPv4 address.

Fixes #70132

Change-Id: I22ec7f9d4adaa4b5afb21fc448050fb4219cacee
Reviewed-on: https://go-review.googlesource.com/c/go/+/644375
Reviewed-by: Damien Neil <dneil@google.com>
Reviewed-by: Ian Lance Taylor <iant@google.com>
Commit-Queue: Ian Lance Taylor <iant@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Auto-Submit: Ian Lance Taylor <iant@google.com>

src/net/sockopt_posix.go
src/net/sockoptip4_bsdvar.go [moved from src/net/sockoptip_bsdvar.go with 100% similarity]
src/net/sockoptip4_linux.go [moved from src/net/sockoptip_linux.go with 68% similarity]
src/net/sockoptip4_posix_nonlinux.go [new file with mode: 0644]
src/net/sockoptip4_windows.go [moved from src/net/sockoptip_windows.go with 100% similarity]
src/net/sockoptip6_posix.go [moved from src/net/sockoptip_posix.go with 74% similarity]

index a380c7719b484c224f161f4aa776972e32fa1851..2452f06b0a6e32cad3ef09e96e3b9d0ecea29f1b 100644 (file)
@@ -7,7 +7,6 @@
 package net
 
 import (
-       "internal/bytealg"
        "runtime"
        "syscall"
 )
@@ -43,35 +42,6 @@ func interfaceToIPv4Addr(ifi *Interface) (IP, error) {
        return nil, errNoSuchInterface
 }
 
-func setIPv4MreqToInterface(mreq *syscall.IPMreq, ifi *Interface) error {
-       if ifi == nil {
-               return nil
-       }
-       ifat, err := ifi.Addrs()
-       if err != nil {
-               return err
-       }
-       for _, ifa := range ifat {
-               switch v := ifa.(type) {
-               case *IPAddr:
-                       if a := v.IP.To4(); a != nil {
-                               copy(mreq.Interface[:], a)
-                               goto done
-                       }
-               case *IPNet:
-                       if a := v.IP.To4(); a != nil {
-                               copy(mreq.Interface[:], a)
-                               goto done
-                       }
-               }
-       }
-done:
-       if bytealg.Equal(mreq.Multiaddr[:], IPv4zero.To4()) {
-               return errNoSuchMulticastInterface
-       }
-       return nil
-}
-
 func setReadBuffer(fd *netFD, bytes int) error {
        err := fd.pfd.SetsockoptInt(syscall.SOL_SOCKET, syscall.SO_RCVBUF, bytes)
        runtime.KeepAlive(fd)
similarity index 68%
rename from src/net/sockoptip_linux.go
rename to src/net/sockoptip4_linux.go
index bd7d8344258e2418fb8ac8c36463deb19fcec96e..8b953ebdc6b438951c185b1def0e6bfbc08201a1 100644 (file)
@@ -9,6 +9,16 @@ import (
        "syscall"
 )
 
+func joinIPv4Group(fd *netFD, ifi *Interface, ip IP) error {
+       mreq := &syscall.IPMreqn{Multiaddr: [4]byte{ip[0], ip[1], ip[2], ip[3]}}
+       if ifi != nil {
+               mreq.Ifindex = int32(ifi.Index)
+       }
+       err := fd.pfd.SetsockoptIPMreqn(syscall.IPPROTO_IP, syscall.IP_ADD_MEMBERSHIP, mreq)
+       runtime.KeepAlive(fd)
+       return wrapSyscallError("setsockopt", err)
+}
+
 func setIPv4MulticastInterface(fd *netFD, ifi *Interface) error {
        var v int32
        if ifi != nil {
diff --git a/src/net/sockoptip4_posix_nonlinux.go b/src/net/sockoptip4_posix_nonlinux.go
new file mode 100644 (file)
index 0000000..85e8c6d
--- /dev/null
@@ -0,0 +1,52 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build (unix && !linux) || windows
+
+package net
+
+import (
+       "internal/bytealg"
+       "runtime"
+       "syscall"
+)
+
+func joinIPv4Group(fd *netFD, ifi *Interface, ip IP) error {
+       mreq := &syscall.IPMreq{Multiaddr: [4]byte{ip[0], ip[1], ip[2], ip[3]}}
+       if err := setIPv4MreqToInterface(mreq, ifi); err != nil {
+               return err
+       }
+       err := fd.pfd.SetsockoptIPMreq(syscall.IPPROTO_IP, syscall.IP_ADD_MEMBERSHIP, mreq)
+       runtime.KeepAlive(fd)
+       return wrapSyscallError("setsockopt", err)
+}
+
+func setIPv4MreqToInterface(mreq *syscall.IPMreq, ifi *Interface) error {
+       if ifi == nil {
+               return nil
+       }
+       ifat, err := ifi.Addrs()
+       if err != nil {
+               return err
+       }
+       for _, ifa := range ifat {
+               switch v := ifa.(type) {
+               case *IPAddr:
+                       if a := v.IP.To4(); a != nil {
+                               copy(mreq.Interface[:], a)
+                               goto done
+                       }
+               case *IPNet:
+                       if a := v.IP.To4(); a != nil {
+                               copy(mreq.Interface[:], a)
+                               goto done
+                       }
+               }
+       }
+done:
+       if bytealg.Equal(mreq.Interface[:], IPv4zero.To4()) {
+               return errNoSuchMulticastInterface
+       }
+       return nil
+}
similarity index 74%
rename from src/net/sockoptip_posix.go
rename to src/net/sockoptip6_posix.go
index 572ea455c09586f02d45d3b23716cf31d59240a9..5bbc609f7b1a4b33c8f5e103995ff506d91ec7ca 100644 (file)
@@ -11,16 +11,6 @@ import (
        "syscall"
 )
 
-func joinIPv4Group(fd *netFD, ifi *Interface, ip IP) error {
-       mreq := &syscall.IPMreq{Multiaddr: [4]byte{ip[0], ip[1], ip[2], ip[3]}}
-       if err := setIPv4MreqToInterface(mreq, ifi); err != nil {
-               return err
-       }
-       err := fd.pfd.SetsockoptIPMreq(syscall.IPPROTO_IP, syscall.IP_ADD_MEMBERSHIP, mreq)
-       runtime.KeepAlive(fd)
-       return wrapSyscallError("setsockopt", err)
-}
-
 func setIPv6MulticastInterface(fd *netFD, ifi *Interface) error {
        var v int
        if ifi != nil {