hickory-dns / hickory-dns

A Rust based DNS client, server, and resolver
Other
4.02k stars 452 forks source link

Unable to resolve using MDNS. multithreaded_runtime example hangs. #1065

Open dawid-nowak opened 4 years ago

dawid-nowak commented 4 years ago

Unable to resolve using MDNS. multithreaded_runtime example hangs :

[2020-04-07T15:48:11Z DEBUG trust_dns_proto::xfer::dns_handle] querying: ginger.local A [2020-04-07T15:48:11Z DEBUG trust_dns_resolver::name_server::name_server] reconnecting: NameServerConfig { socket_addr: V4(224.0.0.251:5353), protocol: Mdns, tls_dns_name: None } [2020-04-07T15:48:11Z DEBUG trust_dns_resolver::name_server::connection_provider] connection-provider for mdns NameServerConfig { socket_addr: V4(224.0.0.251:5353), protocol: Mdns, tls_dns_name: None } [2020-04-07T15:48:11Z DEBUG trust_dns_proto::multicast::mdns_stream] binding sending stream 2 to 0.0.0.0:11078 [2020-04-07T15:48:11Z DEBUG trust_dns_proto::multicast::mdns_stream] preparing sender 2 on: 0.0.0.0:11078 [2020-04-07T15:48:11Z DEBUG trust_dns_proto::xfer] enqueueing message: [Query { name: Name { is_fqdn: false, labels: [ginger, local] }, query_type: A, query_class: IN }]

and nothing shows in Wireshark network traces

To Reproduce change: let names = &["www.google.com", "www.reddit.com", "www.wikipedia.org","ginger.local"]; execute: trust-dns/crates/resolver$ export RUST_LOG=debug; cargo run --features mdns --example multithreaded_runtime

Expected behavior I would at least expect that i will see MDNS request in wireshark traces. ping gigner.local and resolvectl ginger.local do show up in wireshark traces

System:

Version: Crate: resolver Version: master

bluejekyll commented 4 years ago

mDNS is highly experimental, and has a bunch of known issues in trust-dns today.

bluejekyll commented 4 years ago

See https://github.com/bluejekyll/trust-dns/labels/feature%3Amdns

dawid-nowak commented 4 years ago

understood; i was digging into it further but i am getting lost in channels :) i think the problem is in udp_stream.rs

impl<S: UdpSocket + Send + 'static> Stream for UdpStream<S> {
    type Item = Result<SerialMessage, io::Error>;

    fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Option<Self::Item>> {
...
**        while let Poll::Ready(Some(message)) = outbound_messages.as_mut().poll_peek(cx) {**

the poll result is always Pending and the code never sends a packet out, then it tries to receive a packet that never arrives.

So i suppose two questions?

  1. where is the other side of outbound_messages channel ?
  2. is it possible to set a timeout on a socket for mdns ? where is that socket created ?
bluejekyll commented 4 years ago

It makes me happy that you want to look into this! I'll give you a brain dump as best as I can, it's been a while since I worked on that code (and make sure to review the other issues in this area).

The main implementation for the socket management happens in this module: https://github.com/bluejekyll/trust-dns/tree/master/crates/proto/src/multicast

For the resolver, the mDNS initial request happens here: https://github.com/bluejekyll/trust-dns/blob/master/crates/resolver/src/name_server/name_server_pool.rs#L305

The streams are constructed here, which is where the initial channel is created: https://github.com/bluejekyll/trust-dns/blob/master/crates/resolver/src/name_server/connection_provider.rs#L179-L195

As to why the query isn't being issued on the network, I'm not really sure why that would happen. There are some issues with this implementation. One such thing is that many systems have a mDNSresponder running locally, the multicast configuration for those don't easily allow for more than one on a system to be running. This is why I've picked the OneShot configuration for the mDNS configuration in the Resolver, since spawning something competing with the system mDNSResponder is tricky.

I hope this helps.