Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 16 additions & 6 deletions client.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,11 @@ func QueryContext(ctx context.Context, params *QueryParam) error {
params.Logger = log.Default()
}
// Create a new client
client, err := newClient(!params.DisableIPv4, !params.DisableIPv6, params.Logger)
// Pass params.Interface so the multicast receive socket joins the correct
// interface. On Windows with multiple NICs, using nil here causes
// IP_ADD_MEMBERSHIP with INADDR_ANY, which joins the wrong interface and
// results in zero packets received (see issue #80).
client, err := newClient(!params.DisableIPv4, !params.DisableIPv6, params.Logger, params.Interface)
if err != nil {
return err
}
Expand Down Expand Up @@ -143,8 +147,11 @@ type client struct {
}

// NewClient creates a new mdns Client that can be used to query
// for records
func newClient(v4 bool, v6 bool, logger *log.Logger) (*client, error) {
// for records.
// iface specifies the network interface to join the multicast group on.
// A nil iface lets the OS choose (system default), which is correct for
// single-NIC machines but unreliable on Windows with multiple NICs.
func newClient(v4 bool, v6 bool, logger *log.Logger, iface *net.Interface) (*client, error) {
if !v4 && !v6 {
return nil, fmt.Errorf("Must enable at least one of IPv4 and IPv6 querying")
}
Expand Down Expand Up @@ -174,15 +181,18 @@ func newClient(v4 bool, v6 bool, logger *log.Logger) (*client, error) {
return nil, fmt.Errorf("failed to bind to any unicast udp port")
}

// Establish multicast connections
// Establish multicast connections.
// iface is passed explicitly so that IP_ADD_MEMBERSHIP is issued for the
// correct interface on multi-NIC Windows hosts. When iface is nil the
// behaviour is identical to before (OS picks based on routing table).
if v4 {
mconn4, err = net.ListenMulticastUDP("udp4", nil, ipv4Addr)
mconn4, err = net.ListenMulticastUDP("udp4", iface, ipv4Addr)
if err != nil {
logger.Printf("[ERR] mdns: Failed to bind to udp4 port: %v", err)
}
}
if v6 {
mconn6, err = net.ListenMulticastUDP("udp6", nil, ipv6Addr)
mconn6, err = net.ListenMulticastUDP("udp6", iface, ipv6Addr)
if err != nil {
logger.Printf("[ERR] mdns: Failed to bind to udp6 port: %v", err)
}
Expand Down