Open matthew-a-thomas opened 6 years ago
Upon further research, for mDNS+DNS-SD to work it looks like more needs to change than just label name restrictions. Unfortunately the LookupClient
immediately returns after it receives the first response. This isn't good for mDNS where multiple hosts can reply with different DNS responses.
So in summary, changing label name restrictions would only help DNS-SD on a network with a standard unicasted DNS server. On an mDNS network it's still no good.
So feel free to toss out this issue if you don't feel like taking on full mDNS+DNS-SD support.
Hi @matthew-a-thomas I'm actually using this library primarily for service discovery, but in a completely different scenario. I'm using Consul's DNS endpoint for service discovery in a micro service project @ work.
Your use case sounds totally reasonable. I never played with mDNS though and don't have much experience with what the RFC actually says/requires.
There seem to be some changes needed to support that. I'm not 100% sure how the multi-casting is supposed to work from a consumer (DNS Client) point of view. I'd have to spend some time to figure all that out and also setup some testing environment.
Lifting the current restricting in DnsString
to support non domain name characters and such, shouldn't be that difficult.
Not sure if that should always be the default behavior though.
I'll try to get some time and dig a bit more into nDNS
Thank you for being willing to research this stuff.
Hey, @matthew-a-thomas
Didn't reply to this issue in a long time but just wanted to note that the "workaround" by using DnsQuery
is possible for quite some time, the example you posted does not throw any validation error and should work:
var lookup = new LookupClient(
new LookupClientOptions(new IPEndPoint(
address: IPAddress.Parse("224.0.0.251"),
port: 5353
))
{
UseTcpFallback = false
});
var result = await lookup.QueryAsync(new DnsQuestion(
query: DnsString.FromResponseQueryString("HP LaserJet MXYZ (ABCDEFG)._printer._tcp.local."),
questionType: QueryType.ANY,
questionClass: QueryClass.IN
));
Issue
It doesn't appear that DNS-SD is entirely supported due to the fact that DNS label names in DnsClient.NET strictly follow the recommendation in RFC 1035.
Background
DNS Service Discovery (DNS-SD) is defined in RFC 6763. It uses normal DNS queries to find and resolve services. Bonjour and Avahi are Apple and Linux's implementations, respectively.
According to Stuart Cheshire (the main guy on the RFC):
This is because a DNS-SD query is just a regular DNS query: service descriptions are stored in
SRV
andTXT
records.mDNS is just DNS implemented in a distributed manner on the
224.0.0.251
multicast address over UDP port 5353.So, DNS-SD queries can be asked of either a normal DNS server or of an mDNS network. My examples focus on mDNS+DNS-SD. So just keep in mind that most things I say would still apply if I were communicating with a "real" DNS server.
Details
I am able to fabricate a query to discover all printers via mDNS, DNS-SD style. It's really neat that this works with DnsClient.NET, by the way. Kudos!
Because I happen to have an HP printer on my network which implements mDNS+DNS-SD, then in response I get all the
PTR
,SRV
, andTXT
records I need to find its friendly name, regular cryptic DNS name, IP addresses, port numbers, and printer config stuff.But I think I would quickly face truncation as the number of printers on the network grows.
Instead of querying for everything, section 4 of RFC 6763 says to issue a
PTR
query. The responses will include friendly names that can be individually resolved.And the
PTR
query works. For example, I get back aPtrRecord
containingPtrDomainName
=HP LaserJet MXYZ (ABCDEF)._printer._tcp.local.
when I execute this code:The
PtrDomainName
is of the format<Instance>.<Service>.<Domain>.
and in this case the<Instance>
isHP LaserJet MXYZ (ABCDEF)
. According to section 4.1.1:This is where the trouble starts: instance names include spaces (and other bad stuff) which isn't a strictly traditional DNS label. Therefore I'm unable to issue further
SRV
andTXT
queries for this specific instance.For example, this code:
...results in this error:
Proposal
I propose that you relax the label name requirements to be "anything at most 63 octets in length, except ASCII control characters".
After all, as you know names end up encoded as just a bunch of length-prefixed byte arrays. So strictly speaking, any 63-octet label is able to be transmitted.
Unfortunately, this would be a breaking change. So if you're concerned about yanking out the rug from under the feet of existing users relying on
DnsString
to sanitize DNS names, then perhaps theDnsString
class could gain a staticIsTraditional
method for folks to use instead?Alternative
I know what you're going to say:
And although I disagree (the RFC merely recommends that format), I can understand where you'd be coming from.
So if you feel that way, then I propose that you create a query method having this signature:
(In fact, perhaps this could replace the existing
QueryAsync
method, since the existing method signature could be an extension method deriving from the above signature. And there would be no breaking changes.)Then I would be free to ~shoot myself in the foot with strange queries if I want to~ issue DNS-SD queries like:
(And if
DnsString.FromResponseQueryString
is too strange in this context, then perhaps you could give us aDnsString.FromUnchecked
method or open up theDnsString
constructor?)Conclusion
I believe that either of these options would enable full DNS-SD support.
Bonus 👍
Full DNS-SD support would bring you up to par with onovotny/Zeroconf. I would be able to use your package to do everything that
Zeroconf
does, and more.