From 7ada6b0f1fb0471d0fe898b583f06d64b93302e1 Mon Sep 17 00:00:00 2001 From: Dave Flowerday Date: Tue, 26 Jul 2022 18:22:02 -0600 Subject: [PATCH 1/2] Fix client multicast sending on Windows --- client.go | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/client.go b/client.go index 33e4c0fa..a0f80baf 100644 --- a/client.go +++ b/client.go @@ -436,17 +436,21 @@ func (c *client) sendQuery(msg *dns.Msg) error { return err } if c.ipv4conn != nil { - var wcm ipv4.ControlMessage for ifi := range c.ifaces { - wcm.IfIndex = c.ifaces[ifi].Index - c.ipv4conn.WriteTo(buf, &wcm, ipv4Addr) + if err := c.ipv4conn.SetMulticastInterface(&c.ifaces[ifi]); err != nil { + // log.Printf("[WARN] mdns: Failed to set multicast interface: %v", err) + continue + } + c.ipv4conn.WriteTo(buf, nil, ipv4Addr) } } if c.ipv6conn != nil { - var wcm ipv6.ControlMessage for ifi := range c.ifaces { - wcm.IfIndex = c.ifaces[ifi].Index - c.ipv6conn.WriteTo(buf, &wcm, ipv6Addr) + if err := c.ipv6conn.SetMulticastInterface(&c.ifaces[ifi]); err != nil { + // log.Printf("[WARN] mdns: Failed to set multicast interface: %v", err) + continue + } + c.ipv6conn.WriteTo(buf, nil, ipv6Addr) } } return nil From 3208875044a803d7b003e88902c23418b66e6a8a Mon Sep 17 00:00:00 2001 From: Michael Stufflebeam Date: Wed, 27 Jul 2022 11:47:26 -0600 Subject: [PATCH 2/2] Put in a platform dependent fix for windows to WriteTo on client.go and server.go to allow Multicast transmit --- client.go | 34 ++++++++++++++++++++++++++-------- server.go | 45 +++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 67 insertions(+), 12 deletions(-) diff --git a/client.go b/client.go index a0f80baf..c0b2cae1 100644 --- a/client.go +++ b/client.go @@ -3,8 +3,10 @@ package zeroconf import ( "context" "fmt" + "log" "math/rand" "net" + "runtime" "strings" "time" @@ -436,21 +438,37 @@ func (c *client) sendQuery(msg *dns.Msg) error { return err } if c.ipv4conn != nil { + // See https://pkg.go.dev/golang.org/x/net/ipv4#pkg-note-BUG + // As of Golang 1.18.4 + // On Windows, the ControlMessage for ReadFrom and WriteTo methods of PacketConn is not implemented. + var wcm ipv4.ControlMessage for ifi := range c.ifaces { - if err := c.ipv4conn.SetMulticastInterface(&c.ifaces[ifi]); err != nil { - // log.Printf("[WARN] mdns: Failed to set multicast interface: %v", err) - continue + switch runtime.GOOS { + case "darwin", "ios", "linux": + wcm.IfIndex = c.ifaces[ifi].Index + default: + if err := c.ipv4conn.SetMulticastInterface(&c.ifaces[ifi]); err != nil { + log.Printf("[WARN] mdns: Failed to set multicast interface: %v", err) + } } - c.ipv4conn.WriteTo(buf, nil, ipv4Addr) + c.ipv4conn.WriteTo(buf, &wcm, ipv4Addr) } } if c.ipv6conn != nil { + // See https://pkg.go.dev/golang.org/x/net/ipv6#pkg-note-BUG + // As of Golang 1.18.4 + // On Windows, the ControlMessage for ReadFrom and WriteTo methods of PacketConn is not implemented. + var wcm ipv6.ControlMessage for ifi := range c.ifaces { - if err := c.ipv6conn.SetMulticastInterface(&c.ifaces[ifi]); err != nil { - // log.Printf("[WARN] mdns: Failed to set multicast interface: %v", err) - continue + switch runtime.GOOS { + case "darwin", "ios", "linux": + wcm.IfIndex = c.ifaces[ifi].Index + default: + if err := c.ipv6conn.SetMulticastInterface(&c.ifaces[ifi]); err != nil { + log.Printf("[WARN] mdns: Failed to set multicast interface: %v", err) + } } - c.ipv6conn.WriteTo(buf, nil, ipv6Addr) + c.ipv6conn.WriteTo(buf, &wcm, ipv6Addr) } } return nil diff --git a/server.go b/server.go index fb4b4976..2dbf536e 100644 --- a/server.go +++ b/server.go @@ -6,6 +6,7 @@ import ( "math/rand" "net" "os" + "runtime" "strings" "sync" "time" @@ -764,26 +765,62 @@ func (s *Server) multicastResponse(msg *dns.Msg, ifIndex int) error { return fmt.Errorf("failed to pack msg %v: %w", msg, err) } if s.ipv4conn != nil { + // See https://pkg.go.dev/golang.org/x/net/ipv4#pkg-note-BUG + // As of Golang 1.18.4 + // On Windows, the ControlMessage for ReadFrom and WriteTo methods of PacketConn is not implemented. var wcm ipv4.ControlMessage if ifIndex != 0 { - wcm.IfIndex = ifIndex + switch runtime.GOOS { + case "darwin", "ios", "linux": + wcm.IfIndex = ifIndex + default: + iface, _ := net.InterfaceByIndex(ifIndex) + if err := s.ipv4conn.SetMulticastInterface(iface); err != nil { + log.Printf("[WARN] mdns: Failed to set multicast interface: %v", err) + } + } s.ipv4conn.WriteTo(buf, &wcm, ipv4Addr) } else { for _, intf := range s.ifaces { - wcm.IfIndex = intf.Index + switch runtime.GOOS { + case "darwin", "ios", "linux": + wcm.IfIndex = intf.Index + default: + if err := s.ipv4conn.SetMulticastInterface(&intf); err != nil { + log.Printf("[WARN] mdns: Failed to set multicast interface: %v", err) + } + } s.ipv4conn.WriteTo(buf, &wcm, ipv4Addr) } } } if s.ipv6conn != nil { + // See https://pkg.go.dev/golang.org/x/net/ipv6#pkg-note-BUG + // As of Golang 1.18.4 + // On Windows, the ControlMessage for ReadFrom and WriteTo methods of PacketConn is not implemented. var wcm ipv6.ControlMessage if ifIndex != 0 { - wcm.IfIndex = ifIndex + switch runtime.GOOS { + case "darwin", "ios", "linux": + wcm.IfIndex = ifIndex + default: + iface, _ := net.InterfaceByIndex(ifIndex) + if err := s.ipv6conn.SetMulticastInterface(iface); err != nil { + log.Printf("[WARN] mdns: Failed to set multicast interface: %v", err) + } + } s.ipv6conn.WriteTo(buf, &wcm, ipv6Addr) } else { for _, intf := range s.ifaces { - wcm.IfIndex = intf.Index + switch runtime.GOOS { + case "darwin", "ios", "linux": + wcm.IfIndex = intf.Index + default: + if err := s.ipv6conn.SetMulticastInterface(&intf); err != nil { + log.Printf("[WARN] mdns: Failed to set multicast interface: %v", err) + } + } s.ipv6conn.WriteTo(buf, &wcm, ipv6Addr) } }