RFC 6762

Multicast DNS

๐Ÿ“… published February 2013, from ietf

Multicast DNS ๐ŸŒธ

Okay bestie, this is RFC 6762, and it's giving Multicast DNS ๐Ÿงšโœจ. It's written by S. Cheshire and M. Krochmal from Apple Inc. ๐Ÿ’… It's a Standards Track document, the ISSN is 2070-1721, and it's dated February 2013. Its header doesn't list any RFCs it obsoletes or updates, so it's standing on its own. Main character energy ๐Ÿ‘‘

Abstract

Okay so devices keep getting smaller, more portable, and more everywhere ๐Ÿ“ฑ, which means they really need to work with less setup. Being able to look up DNS resource record data types (host names included, but not limited to them) when there's no normal managed DNS server around is lowkey essential ๐Ÿซถ

Multicast DNS (mDNS) does DNS-like stuff on the local link when there's no conventional Unicast DNS server at all ๐Ÿฆ‹. It also sets aside a chunk of the DNS namespace for local use, so you don't pay any annual fee, and you don't need delegations or any other config on a regular DNS server to answer for those names ๐Ÿ’–

The big wins of Multicast DNS names are that (i) they need little or no admin or setup, (ii) they work when there's no infrastructure at all, and (iii) they still work when infrastructure breaks ๐Ÿ˜ญ๐ŸŽ€

Status of This Memo

This is an Internet Standards Track document ๐Ÿ”ฅ

It's a product of the Internet Engineering Task Force (IETF), so it represents the consensus of the IETF community. It went through public review and was approved for publication by the Internet Engineering Steering Group (IESG). If you want more on Internet Standards, check Section 2 of RFC 5741 ๐ŸŒˆ

Info about this document's current status, any errata, and how to give feedback lives at http://www.rfc-editor.org/info/rfc6762 ๐Ÿ“

Copyright (c) 2013 IETF Trust and the persons identified as the document authors. All rights reserved. ๐Ÿ’œ

This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (http://trustee.ietf.org/license-info) as they stand on the publication date. Please actually read these, because they spell out your rights and restrictions for this document ๐Ÿ™ˆ Any Code Components pulled out of this document must include the Simplified BSD License text described in Section 4.e of the Trust Legal Provisions, and they come with no warranty, as the Simplified BSD License describes.

Heads up: this document may contain material from IETF Documents or IETF Contributions published or made publicly available before November 10, 2008. The people who control the copyright in some of that material may not have given the IETF Trust permission to allow modifications outside the IETF Standards Process. Unless you get an adequate license from those copyright holders, this document may not be modified outside the IETF Standards Process, and derivative works of it may not be created outside the IETF Standards Process. The one exception is formatting it for publication as an RFC or translating it into languages other than English ๐Ÿซถ

Table of Contents

1. Introduction ....................................................4
2. Conventions and Terminology Used in This Document ...............4
3. Multicast DNS Names .............................................5
4. Reverse Address Mapping .........................................7
5. Querying ........................................................8
6. Responding .....................................................13
7. Traffic Reduction ..............................................22
8. Probing and Announcing on Startup ..............................25
9. Conflict Resolution ............................................31
10. Resource Record TTL Values and Cache Coherency ................33
11. Source Address Check ..........................................38
12. Special Characteristics of Multicast DNS Domains ..............40
13. Enabling and Disabling Multicast DNS ..........................41
14. Considerations for Multiple Interfaces ........................42
15. Considerations for Multiple Responders on the Same Machine ....43
16. Multicast DNS Character Set ...................................45
17. Multicast DNS Message Size ....................................46
18. Multicast DNS Message Format ..................................47
19. Summary of Differences between Multicast DNS and Unicast DNS ..51
20. IPv6 Considerations ...........................................52
21. Security Considerations .......................................52
22. IANA Considerations ...........................................53
23. Acknowledgments ...............................................56
24. References ....................................................56
Appendix A. Design Rationale for Choice of UDP Port Number ........60
Appendix B. Design Rationale for Not Using Hashed Multicast
            Addresses .............................................61
Appendix C. Design Rationale for Maximum Multicast DNS Name
            Length ................................................62
Appendix D. Benefits of Multicast Responses .......................64
Appendix E. Design Rationale for Encoding Negative Responses ......65
Appendix F. Use of UTF-8 ..........................................66
Appendix G. Private DNS Namespaces ................................67
Appendix H. Deployment History ....................................67

1. Introduction โœจ

Multicast DNS and its buddy DNS-Based Service Discovery [RFC6763] were made to give IP networking the ease-of-use and autoconfiguration that AppleTalk was famous for [RFC6760]. If you're reading this doc, it helps to already be familiar with Zero Configuration Networking [Zeroconf] and automatic link-local addressing [RFC3927] [RFC4862] ๐Ÿงš

Multicast DNS borrows a lot from the existing DNS protocol [RFC1034] [RFC1035] [RFC6195]. It uses the same DNS message structure, name syntax, and resource record types ๐ŸŽ€ It doesn't specify any new operation codes or response codes, so nothing new to memorize there ๐Ÿ™Œ

What this document actually describes is how clients send DNS-like queries over IP multicast, and how a group of hosts team up to answer those queries in a useful way ๐Ÿซถ

2. Conventions and Terminology Used in This Document ๐Ÿ“š

Okay, the key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document get read the way "Key words for use in RFCs to Indicate Requirement Levels" [RFC2119] says to read them ๐Ÿ’… Pay attention to those, they're the important ones ๐Ÿ‘€

When this document says "Multicast DNS", it should be taken to mean: "Clients performing DNS-like queries for DNS-like resource records by sending DNS-like UDP query and response messages over IP Multicast to UDP port 5353". The reasoning for picking UDP port 5353 is in Appendix A ๐Ÿฆ‹

This document uses "host name" in the strict sense: a fully qualified domain name that has an IPv4 or IPv6 address record. It does not use "host name" in the super common but technically wrong way, meaning just the first DNS label of a host's fully qualified domain name ๐Ÿ™ˆ Not me correcting people, lol, but yes me correcting people ๐Ÿ’€

A DNS (or mDNS) packet has an IP Time to Live (TTL) in the IP header. That's basically a hop-count limit on the packet, so routing loops don't last forever ๐Ÿ” Each resource record also has a TTL, which is how many seconds the record may be cached ๐Ÿ•ฐ๏ธ This document uses "IP TTL" for the IP header TTL (hop limit), and "RR TTL" or just "TTL" for the resource record TTL (cache lifetime). Don't mix them up bestie ๐Ÿ’–

DNS-format messages have a header, then a Question Section, then Answer, Authority, and Additional Record Sections. The Answer, Authority, and Additional Record Sections all hold resource records in the same format. When something applies equally to all three of those, the document calls them collectively the "Resource Record Sections" ๐Ÿง

This document uses the terms "shared" and "unique" for resource record sets [RFC1034]:

A "shared" resource record set is one where several Multicast DNS responders may have records with the same name, rrtype, and rrclass, and several responders may respond to a particular query.
A "unique" resource record set is one where all the records with that name, rrtype, and rrclass are conceptually under the control or ownership of a single responder, and it is expected that at most one responder should respond to a query for that name, rrtype, and rrclass. Before claiming ownership of a unique resource record set, a responder MUST probe to verify that no other responder already claims ownership of that set, as described in Section 8.1, "Probing". (For fault-tolerance and other reasons, sometimes it is permissible to have more than one responder answering for a particular "unique" resource record set, but such cooperating responders MUST give answers containing identical rdata for these records. If they do not give answers containing identical rdata, then the probing step will reject the data as being inconsistent with what is already being advertised on the network for those names.) ๐Ÿ™Œ

Strictly speaking, "shared" and "unique" describe resource record sets, not individual resource records. Still, it's sometimes handy to say "shared resource records" and "unique resource records". When people talk that way, it should be understood as meaning a record that's a member of a "shared" or "unique" resource record set, respectively ๐Ÿ’œ

3. Multicast DNS Names โœจ

okay so if you're an org or a person who controls a piece of the global DNS namespace ๐Ÿ‘‘, you can give your machine a globally unique name in that chunk, like cheshire.example.com. and honestly? iconic. it works great for people who have that luxury ๐Ÿ’… but most home computer users don't have access to any part of the global DNS where they're allowed to make names ๐Ÿ˜ญ. so most home computers are basically anonymous for practical purposes. not it ๐Ÿ’€

so to fix that, this doc lets literally any computer user opt in to link-local Multicast DNS host names that look like single-dns-label.local. ๐ŸŽ€ for example, a laptop can answer to MyComputer.local.. any user gets to name their computer like this, as long as the name isn't already in use on that link. once you've got it, you get to keep using it until a name conflict happens on the link that doesn't go your way. if that happens, the computer (or its human) MUST stop using the name, and SHOULD try to pick a new unique name for that link. conflicts should be pretty rare if you choose reasonably imaginative names, but it's still important to have a way to handle them when they pop up ๐ŸŒธ

the spec says the top-level domain .local. is special ๐Ÿฆ‹ any fully qualified name ending in .local. is link-local, and names in that domain only mean something on the link where they came from. this is like how the IPv4 addresses in 169.254/16 and the IPv6 addresses in FE80::/10 are link-local too, and only meaningful on the link where they originate.

any DNS query for a name ending with .local. MUST be sent to the mDNS IPv4 link-local multicast address 224.0.0.251 (or its IPv6 equivalent FF02::FB) ๐Ÿซถ the reasoning for using one fixed multicast address instead of picking from a range of them with a hash function is in Appendix B. implementers MAY choose to look up these names at the same time through other mechanisms (like Unicast DNS) and combine the results somehow. implementers who do this should be aware of the potential for user confusion when the same name gives different results depending on outside network conditions (like, but not limited to, which lookup mechanism answers faster) ๐Ÿ™ˆ

it doesn't matter whether a name ending with .local. came from someone typing a fully qualified domain name ending in .local., or from someone typing an unqualified name that the host software expanded with the .local. suffix because it was in their search list ๐Ÿ’– the .local. suffix could be in the search list because the user set it up manually, or because it came in over DHCP [RFC2132] or any other mechanism for configuring the DNS search list. in this respect, the .local. suffix is treated no differently from any other search domain in the DNS search list. no special treatment, bestie ๐ŸŒˆ

DNS queries for names that do not end with .local. MAY be sent to the mDNS multicast address, but only if no other conventional DNS server is available โญ this can let hosts on the same link keep talking to each other using their globally unique DNS names during network outages that cut them off from the wider Internet. when you resolve global names through local multicast, it's even more important to use DNS Security Extensions (DNSSEC) [RFC4033] or other security mechanisms so you know the response is trustworthy ๐Ÿ”ฅ resolving global names via local multicast is a contentious issue, so this document doesn't go further into it. it focuses on resolving local names with DNS messages sent to a multicast address instead.

this document recommends a single flat namespace for dot-local host names (so, the names of DNS "A" and "AAAA" records, which map names to IPv4 and IPv6 addresses) ๐Ÿ“ but other DNS record types (like the ones used by DNS-Based Service Discovery [RFC6763]) can have as many labels as they need for what they're doing, up to a max of 255 bytes plus a terminating zero byte at the end. name length stuff gets more detail in Appendix C.

enforcing uniqueness of host names is probably desirable in the common case, but this document doesn't mandate it ๐Ÿงš it's okay for a group of coordinated hosts to agree to keep multiple DNS address records with the same name, maybe for load-balancing or fault-tolerance reasons. this document doesn't take a position on whether that's sensible. what matters is that both modes work. the Multicast DNS protocol lets hosts verify and maintain unique names for resource records when that's the goal, and it also lets hosts keep multiple resource records under one shared name when that's the goal. this applies to all resource records, not just address records (host names). in summary: it is required that the protocol can detect and handle name conflicts, but it is not required that this ability be used for every record ๐Ÿ’œ


4. Reverse Address Mapping ๐Ÿ”ฎ

just like .local., the IPv4 and IPv6 reverse mapping domains are also defined to be link-local โœจ

any DNS query for a name ending with 254.169.in-addr.arpa. MUST be sent to the mDNS IPv4 link-local multicast address 224.0.0.251 or the mDNS IPv6 multicast address FF02::FB ๐Ÿฆ‹ since names under this domain correspond to IPv4 link-local addresses, it makes total sense that the local link is the best place to find info about them.

likewise, any DNS query for a name within the reverse mapping domains for IPv6 link-local addresses (8.e.f.ip6.arpa., 9.e.f.ip6.arpa., a.e.f.ip6.arpa., and b.e.f.ip6.arpa.) MUST be sent to the mDNS IPv6 link-local multicast address FF02::FB or the mDNS IPv4 link-local multicast address 224.0.0.251 ๐ŸŒธ


5. Querying ๐Ÿฆ‹

there are two kinds of Multicast DNS queries ๐Ÿ’… the first is one-shot queries, the kind legacy DNS resolvers make. the second is continuous, ongoing Multicast DNS queries from fully compliant Multicast DNS queriers, which support asynchronous operations including DNS-Based Service Discovery [RFC6763].

unless it's the rare case of a Multicast DNS responder advertising only shared resource records and no unique records, a Multicast DNS responder MUST also implement a Multicast DNS querier ๐Ÿซถ that way it can verify the uniqueness of those records before it starts answering queries for them.

5.1. One-Shot Multicast DNS Queries ๐Ÿ’–

the most basic kind of Multicast DNS client can just blindly send standard DNS queries to 224.0.0.251:5353, without even needing to know what a multicast address is ๐ŸŒˆ this change can usually be done with just a few lines of code in an existing DNS resolver library. if a name being queried falls within one of the reserved Multicast DNS domains (see Sections 3 and 4), then instead of using the configured Unicast DNS server address, the query goes to 224.0.0.251:5353 (or its IPv6 equivalent [FF02::FB]:5353) โญ the timeout is typically shortened to two or three seconds too. it's possible to make a minimal Multicast DNS resolver with only these simple changes. these queries are usually sent from a high-numbered ephemeral UDP source port, but whether they come from a dynamic port or a fixed one, these queries MUST NOT be sent using UDP source port 5353 ๐Ÿ™ˆ that's because using UDP source port 5353 signals the presence of a fully compliant Multicast DNS querier, as described below.

a simple DNS resolver like this will typically just take the first response it receives. it won't listen for extra UDP responses, but in lots of cases that's not a serious problem ๐Ÿ’… if a user types http://MyPrinter.local. into their web browser, the simple resolver takes the first response, and the user gets to see their printer's status and configuration web page, then the protocol has met the user's needs in that case ๐Ÿ–จ๏ธโœจ

a basic DNS resolver like this may be fine for simple host name lookup, but it may not get ideal behavior in other cases ๐Ÿฅบ additional refinements to create a fully compliant Multicast DNS querier are described below. stay tuned, bestie ๐ŸŽ€

5.2. Continuous Multicast DNS Querying โœจ

okay so with one-shot queries the vibe is: you ask, the first answer lands, and we're done ๐ŸŽ€ the transaction starts when the app sends the query and ends when that first response shows up. but there's a second kind of query that's more of a slow burn. getting one response doesn't mean more relevant ones won't come, so the querying keeps going until nothing else is needed ๐Ÿฆ‹ when that's over depends on what the operation is for. if you're looking up the IPv4 and IPv6 addresses of another host, you're finished once you've successfully connected to one of them ๐Ÿ’… if you're browsing to show the user a list of DNS-SD services on the network [RFC6763], you're finished once the user tells the interface software, like by closing the browsing window that's showing the discovered services ๐Ÿซถ

imagine some hypothetical software that lets users find network printers ๐Ÿ–จ๏ธ the user wants every printer on the local network, not just whichever one answers fastest. when they're actively hunting for a printer, they open a browsing window with a list of the printers they've found. it would be so convenient if that list stayed up to date as printers come and go, instead of showing stale info and making the user mash a "refresh" button every time they want accurate results (which, honestly, is already getting stale the moment it appears ๐Ÿ˜ญ). if we want a live, continuously updating list like this, we have to do it efficiently, without naive constant polling, because that would be an unreasonable burden on the network ๐Ÿ’€ not everyone is going to be browsing for new printers all the time, but when someone browses for service instances for a long stretch, we want that to work efficiently too ๐ŸŒˆ

so here's the plan ๐Ÿ“ when you're retransmitting Multicast DNS queries to do this kind of continuous monitoring, the gap between the first two queries MUST be at least one second, the gaps between successive queries MUST increase by at least a factor of two, and the querier MUST implement Known-Answer Suppression, which we'll get to in Section 7.1. Known-Answer Suppression tells responders which answers the querier already has, so responders don't waste network capacity sending the same answers over and over ๐Ÿ™… a querier retransmits its question because it wants answers it might have missed the first time, not because it wants extra duplicate copies of stuff it already got. failing to implement Known-Answer Suppression can lead to unacceptable traffic levels ๐Ÿ’€ when the interval between queries reaches or exceeds 60 minutes, a querier MAY cap it at a maximum of 60 minutes, and then keep querying at a steady rate of one query per hour โฐ also, if a bunch of clients start querying at exactly the same moment (say because of some shared external trigger), they could accidentally sync up, so a Multicast DNS querier SHOULD also delay the first query of the series by a randomly chosen amount in the range 20-120 ms โœจ

when a Multicast DNS querier gets an answer, the answer has a TTL telling how many seconds it's valid for ๐Ÿ•ฐ๏ธ once that time passes, the answer is no longer valid and SHOULD be deleted from the cache. before the record expires, a querier with local clients that actually care about that record's state (like a browsing window showing services) SHOULD reissue its query to check whether the record is still valid ๐Ÿ‘€

to do this cache maintenance, a querier should plan to retransmit its query after at least 50% of the record lifetime has elapsed. this document recommends a specific strategy, and it goes like this ๐Ÿ’…

the querier should plan to issue a query at 80% of the record lifetime, and then, if no answer is received, at 85%, 90%, and 95%. if an answer is received, the remaining TTL is reset to the value given in that answer, and this repeats for as long as the querier has an ongoing interest in the record ๐Ÿ” if no answer comes after four queries, the record gets deleted when it hits 100% of its lifetime. a Multicast DNS querier MUST NOT perform this cache maintenance for records where it has no local clients with an active interest. if the record expiring would have no net effect on any client software running on the querier, and no visible effect to the human user, then there's no reason to waste network capacity checking whether it's still valid ๐Ÿ™ˆ

to stop a bunch of queriers on one network from all querying at the exact same time, a random variation of 2% of the record TTL should be added, so queries are scheduled at 80-82%, 85-87%, 90-92%, and then 95-97% of the TTL ๐ŸŽฒ

an additional efficiency optimization SHOULD be performed when a Multicast DNS response is received containing a unique answer (as indicated by the cache-flush bit being set, described in Section 10.2, "Announcements to Flush Outdated Cache Entries"). in this case there's no need for the querier to keep issuing a stream of queries with exponentially increasing intervals, since getting a unique answer is a good sign that no other answers are coming ๐Ÿ™Œ the Multicast DNS querier SHOULD plan to issue its next query for this record at 80-82% of the record's TTL, as described above.

a compliant Multicast DNS querier, which implements the rules in this document, MUST send its Multicast DNS queries from UDP source port 5353 (the well-known port assigned to mDNS), and MUST listen for Multicast DNS replies sent to UDP destination port 5353 at the mDNS link-local multicast address (224.0.0.251 and/or its IPv6 equivalent FF02::FB) ๐Ÿ“ก


5.3. Multiple Questions per Query ๐Ÿ“ฎ

Multicast DNS lets a querier place multiple questions in the Question Section of a single Multicast DNS query message ๐Ÿงš

a Multicast DNS query message containing multiple questions means exactly the same thing as a series of individual DNS query messages containing one question each. putting them together into one message is purely an efficiency optimization and has no other semantic significance ๐Ÿ’œ


5.4. Questions Requesting Unicast Responses ๐Ÿฆ‹

sending Multicast DNS responses via multicast is great because every other host on the network gets to see those responses, which lets them keep their caches up to date and spot conflicting responses ๐Ÿ‘€

but there are situations where not every host on the network needs to see every response. some examples: a laptop waking from sleep, an Ethernet cable being plugged into a running machine, or a previously inactive interface getting activated through a configuration change ๐Ÿ’ป at the instant of wake-up or link activation, the machine is a brand new participant on a new network. its Multicast DNS cache for that interface is empty, and it has no knowledge of its peers on that link. it may have a significant number of questions it wants answered right away, to learn about its new surroundings and show that info to the user. as a new participant, it has no idea whether those exact same questions were asked and answered just seconds ago. so triggering a large, sudden flood of multicast responses could impose an unreasonable burden on the network ๐Ÿ’€

to avoid large floods of potentially unnecessary responses in these cases, Multicast DNS defines the top bit in the class field of a DNS question as the unicast-response bit ๐ŸŽ€ when this bit is set in a question, it means the querier is willing to accept unicast replies to this specific query, as well as the usual multicast responses. these questions are called "QU" questions, to tell them apart from the more usual questions requesting multicast responses ("QM" questions). a Multicast DNS querier sending its initial batch of questions immediately on wake from sleep or interface activation SHOULD set the unicast-response bit in those questions.

when a question is retransmitted (as described in Section 5.2), the unicast-response bit SHOULD NOT be set in subsequent retransmissions of that question. subsequent retransmissions SHOULD be the usual "QM" questions. after the first question has received its responses, the querier should have a large Known-Answer list (Section 7.1), so subsequent queries should draw few, if any, further responses. going back to multicast responses as soon as possible matters because of the benefits multicast responses provide (see Appendix D) โœจ also, the unicast-response bit SHOULD be set only for questions that are active and ready to be sent at the moment of wake from sleep or interface activation. new questions created by local clients afterwards should be treated as normal "QM" questions, and SHOULD NOT have the unicast-response bit set on the first question of the series ๐Ÿ™…

when a responder receives a question with the unicast-response bit set, it SHOULD usually respond with a unicast packet directed back to the querier ๐Ÿ“ฌ however, if the responder hasn't multicast that record recently (within one quarter of its TTL), then it SHOULD instead multicast the response, so that all the peer caches stay up to date and passive conflict detection is possible ๐Ÿ•ต๏ธ when answering a probe question (Section 8.1) with the unicast-response bit set, the responder should always generate the requested unicast response, but it may also send a multicast announcement if the time since the last multicast announcement of that record is more than a quarter of its TTL ๐ŸŒธ

unicast replies are subject to all the same packet generation rules as multicast replies, including the cache-flush bit (Section 10.2) and (except when defending a unique name against a probe from another host) randomized delays to reduce network collisions (Section 6) ๐Ÿซถ

5.5. Direct Unicast Queries to Port 5353 โœจ

okay so in really specialized apps there may be rare moments where it makes sense for a Multicast DNS querier to send its query via unicast straight to one specific machine ๐ŸŽฏ when a Multicast DNS responder gets a query by direct unicast, it SHOULD respond the same way it would for "QU" questions, as described above in Section 5.4 ๐Ÿ’… and since a unicast query can come from a machine outside the local link, responders SHOULD check that the source address in the query packet matches the local subnet for that link (or, for IPv6, that the source address has an on-link prefix) and silently ignore the packet if it doesn't ๐Ÿ™…โ€โ™€๏ธ

there may be specialized situations outside the scope of this document where a responder that answers queries from outside the local link is intended and desirable ๐ŸŒ a responder like that would need to make sure those non-local queries are always answered via unicast back to the querier, because an answer sent via link-local multicast would never reach a querier outside the local link ๐Ÿ˜ญ

6. Responding ๐Ÿฆ‹

when a Multicast DNS responder builds and sends a Multicast DNS response message, the Resource Record Sections of that message must contain only records the responder is explicitly authoritative for ๐Ÿซถ these answers may be generated because the record answers a question in a Multicast DNS query message, or at certain other times when the responder determines than an unsolicited announcement is warranted. a Multicast DNS responder MUST NOT place records from its cache, which were learned from other responders on the network, in the Resource Record Sections of outgoing response messages ๐Ÿ™…โ€โ™€๏ธ only an authoritative source for a given record is allowed to send responses containing that record โœจ

whether a given record answers a given question is decided with the standard DNS rules ๐Ÿง  the record name must match the question name, the record rrtype must match the question qtype unless the qtype is "ANY" (255) or the rrtype is "CNAME" (5), and the record rrclass must match the question qclass unless the qclass is "ANY" (255). just like Unicast DNS, generally only DNS class 1 ("Internet") is used, but should client software use classes other than 1, the matching rules described above MUST be used ๐Ÿ’œ

a Multicast DNS responder MUST only respond when it has a positive, non-null response to send, or when it authoritatively knows that a particular record does not exist ๐Ÿ’€ for unique records, where the host has already claimed sole ownership of the name, it MUST return negative answers to queries for records that it knows don't exist. for example, a host with no IPv6 address that has claimed sole ownership of the name "host.local." for all rrtypes MUST respond to AAAA queries for "host.local." by sending a negative answer saying that no AAAA records exist for that name. see Section 6.1, "Negative Responses" ๐ŸŒธ for shared records, which aren't owned by any single host, a record's nonexistence is established by the failure of any machine to respond to the Multicast DNS query, not by any explicit negative response. for shared records, NXDOMAIN and other error responses MUST NOT be sent ๐Ÿ™ˆ

Multicast DNS responses MUST NOT contain any questions in the Question Section ๐Ÿšซ any questions in the Question Section of a received Multicast DNS response MUST be silently ignored. Multicast DNS queriers receiving responses don't care what question triggered the response ๐Ÿ’… they only care that the information in the response is true and accurate ๐Ÿ”ฅ

a Multicast DNS responder on Ethernet [IEEE.802.3] and similar shared multiple access networks SHOULD have the capability of delaying its responses by up to 500 ms, as described below โณ

okay the reason for the delay is kind of iconic ๐Ÿ‘‘ if a large number of Multicast DNS responders all responded immediately to a particular query, a collision would be basically guaranteed ๐Ÿ˜ญ a small random delay drastically cuts down on collisions. on a full-sized Ethernet using the maximum cable lengths and the maximum number of repeaters, an Ethernet frame is vulnerable to collisions during the transmission of its first 256 bits. on 10 Mb/s Ethernet, that's a vulnerable window of 25.6 microseconds ๐Ÿงš on higher-speed variants of Ethernet, the vulnerable window is shorter โœจ

in the case where a Multicast DNS responder has good reason to believe it will be the only responder on the link that sends a response (because it can answer every question in the query message, and it has already verified that the name, rrtype, and rrclass are unique on the link for all of those answer records), it SHOULD NOT impose any random delay before responding, and SHOULD normally generate its response within at most 10 ms ๐Ÿƒโ€โ™€๏ธ this applies especially to responding to probe queries with the unicast-response bit set. receiving a probe query is a clear sign that some other responder is planning to start using this name very soon, so answering it to defend a unique record is a high priority and has to happen without delay ๐Ÿšจ a probe query can be told apart from a normal query because it contains a proposed record in the Authority Section that answers the question in the Question Section (for more details, see Section 8.2, "Simultaneous Probe Tiebreaking") ๐ŸŽ€

responding without delay is appropriate for records like the address record for a particular host name, once that host name has been verified unique ๐Ÿ’– responding without delay is not appropriate for things like looking up PTR records used for DNS-Based Service Discovery [RFC6763], where a large number of responses might be expected ๐Ÿ™…โ€โ™€๏ธ

in any case where there may be multiple responses, such as queries where the answer is a member of a shared resource record set, each responder SHOULD delay its response by a random amount of time chosen with uniform random distribution in the range 20-120 ms ๐ŸŒˆ the delay has to be at least 20 ms so that two or more query packets sent back-to-back can be handled by a responder that has answers to more than one of them, letting it combine all of its answers into a single response message ๐Ÿซถ

in the case where the query has the TC (truncated) bit set, meaning subsequent Known-Answer packets will follow, responders SHOULD delay their responses by a random amount of time chosen with uniform random distribution in the range 400-500 ms ๐Ÿงธ that gives all the Known-Answer packets enough time to arrive, as described in Section 7.2, "Multipacket Known-Answer Suppression" ๐Ÿ“

the source UDP port in all Multicast DNS responses MUST be 5353 (the well-known port assigned to mDNS). Multicast DNS implementations MUST silently ignore any Multicast DNS responses they receive where the source UDP port is not 5353 ๐Ÿ”’

the destination UDP port in all Multicast DNS responses MUST be 5353, and the destination address MUST be the mDNS IPv4 link-local multicast address 224.0.0.251 or its IPv6 equivalent FF02::FB ๐Ÿ’œ the only exception is when replying to a query that explicitly asked for a unicast response:

  • via the unicast-response bit,
  • by virtue of being a legacy query (Section 6.7), or
  • by virtue of being a direct unicast query.

except for these three specific cases, responses MUST NOT be sent via unicast ๐Ÿ™…โ€โ™€๏ธ that's because the "Passive Observation of Failures" mechanisms described in Section 10.5 wouldn't work correctly otherwise. other benefits of sending responses via multicast are discussed in Appendix D ๐Ÿ“š a Multicast DNS querier MUST only accept unicast responses if they answer a recently sent query (e.g., sent within the last two seconds) that explicitly requested unicast responses ๐Ÿ•‘ a Multicast DNS querier MUST silently ignore all other unicast responses ๐Ÿ’…

to protect the network from excessive packet flooding caused by software bugs or malicious attacks, a Multicast DNS responder MUST NOT (except in the one special case of answering probe queries) multicast a record on a given interface until at least one second has passed since that record was last multicast on that particular interface ๐Ÿ›ก๏ธ a legitimate querier on the network should have seen the previous transmission and cached it. a querier that didn't receive and cache the previous transmission will retry its request and get a later response ๐Ÿ” for the special case of answering probe queries, the probing host only has a limited amount of time before it decides whether or not to use the name, so a Multicast DNS responder MUST respond quickly ๐Ÿ˜ค in this special case only, when responding via multicast to a probe, a Multicast DNS responder is only required to delay its transmission as necessary to make sure there's an interval of at least 250 ms since the record was last multicast on that interface โญ

6.1. Negative Responses ๐Ÿ™ˆ

okay so, back in the early days of Multicast DNS, everyone assumed explicit negative responses would literally never be needed ๐Ÿ’…. The idea was that a host just asserts the records it claims to have, and the union of all those sets on a link is the full set of mDNS records on that link. Asserting that every other possible record doesn't exist was seen as impractical and kinda unnecessary ๐Ÿ™ƒ. So if a querier wanted to know whether something was missing, it would just ask, and if nobody answered, it'd conclude the record doesn't exist. Simple, right? ๐Ÿฆ‹

But then operational experience showed that explicit negative responses can be seriously valuable ๐Ÿ˜ญ. Like, say a querier wants an AAAA record and the host name has no IPv6 addresses at all. The responder knows it exclusively owns that name and knows it has no IPv6 addresses, so a clear "nope" is way better than the querier re-sending its question over and over, timing out, and only then concluding anything ๐Ÿ’€.

Any time a responder gets a query for a name it has verified exclusive ownership of, for a type that name has no records for, the responder MUST (except as allowed in (a) below) respond asserting that the record doesn't exist, using a DNS NSEC record [RFC4034]. Now, in Multicast DNS the NSEC record is NOT being used for its usual DNSSEC [RFC4033] security stuff ๐Ÿ”. It's just a way of saying which records do or don't exist for a given name, and that's it โœจ.

On receipt of a question for a particular name, rrtype, and rrclass, where the responder does have one or more unique answers, the responder MAY also include an NSEC record in the Additional Record Section, indicating that other rrtypes for that name and rrclass don't exist ๐ŸŒธ.

Implementers working with devices that have plenty of memory and CPU MAY choose to handle the full generality of the DNS NSEC record [RFC4034], including bitmaps up to 65,536 bits long ๐Ÿ’ช. For the little devices with limited memory and CPU, Multicast DNS queriers are only REQUIRED to be able to parse a restricted form of the DNS NSEC record ๐Ÿงš. Every compliant Multicast DNS implementation MUST at least correctly generate and parse the restricted DNS NSEC record format, which looks like this:

  • The 'Next Domain Name' field contains the record's own name. When name compression is used, this means the 'Next Domain Name' field always takes exactly two bytes in the message.
  • The Type Bit Map block number is 0.
  • The Type Bit Map block length byte is a value in the range 1-32.
  • The Type Bit Map data is 1-32 bytes, as indicated by the length byte.

Because this restricted form is limited to Type Bit Map block number zero, it can't express the existence of rrtypes above 255 ๐Ÿ™…โ€โ™€๏ธ. So if a Multicast DNS responder has records with rrtypes above 255, it MUST NOT generate these restricted-form NSEC records for those names, since that would imply the name has no records with rrtypes above 255, which would be false ๐Ÿ˜ฌ. In those cases, a Multicast DNS responder MUST either (a) emit no NSEC record for that name, or (b) emit a full NSEC record containing the appropriate Type Bit Map block(s) with the correct bits set for all the record types that exist. Honestly, not a big deal in practice, since rrtypes above 255 aren't really in widespread use right now ๐Ÿ’….

If a Multicast DNS implementation receives an NSEC record where the 'Next Domain Name' field is NOT the record's own name, the implementation SHOULD ignore the 'Next Domain Name' field and process the rest of the NSEC record as usual ๐ŸŽ€. MDNS doesn't use 'Next Domain Name' yet, but it could in a future version of the protocol, which is exactly why a Multicast DNS implementation MUST NOT reject or ignore an NSEC record just because it finds an unexpected value in that field ๐ŸŒˆ.

If a Multicast DNS implementation receives an NSEC record containing more than one Type Bit Map, or where the Type Bit Map block number isn't zero, or where the block length isn't in the range 1-32, then it MAY silently ignore the entire NSEC record ๐Ÿ™ˆ. A Multicast DNS implementation MUST NOT ignore an entire message just because that message contains one or more NSEC records it can't parse ๐Ÿšซ. This is so future enhancements can be added in a backwards-compatible way that doesn't break older Multicast DNS implementations ๐Ÿซถ.

To tell these synthesized NSEC records (generated on the fly by the program) apart from conventional Unicast DNS NSEC records (which actually exist in a signed DNS zone), the synthesized Multicast DNS NSEC records MUST NOT have the NSEC bit set in the Type Bit Map, whereas conventional Unicast DNS NSEC records DO have the NSEC bit set ๐Ÿ”.

The TTL of the NSEC record indicates the intended lifetime of the negative cache entry โณ. In general, the TTL given for an NSEC record SHOULD be the same as the TTL that the record would have had, had it existed. For example, the TTL for address records in Multicast DNS is typically 120 seconds (see Section 10), so the negative cache lifetime for an address record that doesn't exist should also be 120 seconds ๐Ÿ’œ.

A responder MUST only generate negative responses to queries for which it has legitimate ownership of the name, rrtype, and rrclass in question, and can legitimately assert that no record with that name, rrtype, and rrclass exists ๐Ÿ›ก๏ธ. A responder can assert that a specified rrtype doesn't exist for one of its names if it knows a priori that it has exclusive ownership of that name (e.g., names of reverse address mapping PTR records, which are derived from IP addresses, which should be unique on the local link), or if it previously claimed unique ownership of that name using probe queries for rrtype "ANY" ๐Ÿ‘‘. (If it used probe queries for a specific rrtype instead, then it would only own the name for that rrtype, and it couldn't assert that other rrtypes don't exist. Not me being extra, that's just how it works ๐Ÿค“.)

The design rationale for this mechanism for encoding negative responses is discussed further in Appendix E ๐Ÿ“š.


6.2. Responding to Address Queries ๐Ÿ 

When a Multicast DNS responder sends a response containing its own address records, it MUST include all addresses that are valid on the interface it's sending the message on ๐ŸŒ. It MUST NOT include addresses that aren't valid on that interface, like addresses configured on the host's other interfaces ๐Ÿ™…โ€โ™€๏ธ. For example, if an interface has both an IPv6 link-local address and an IPv6 routable address, both should go in the response so queriers get both and can make their own choice ๐Ÿ’–. That way, a querier that only has an IPv6 link-local address can connect to the link-local address, and a different querier with an IPv6 routable address can connect to the routable one instead ๐Ÿฆ‹.

When a Multicast DNS responder puts an IPv4 or IPv6 address record (rrtype "A" or "AAAA") into a response, it SHOULD also put any records of the other address type with the same name into the additional section, if there's room in the message ๐ŸŽ€. This is called fate sharing, and it means all of a device's addresses get delivered together in one message, which lowers the risk that packet loss leaves a querier with only the IPv4 addresses and not the IPv6 ones, or vice versa ๐Ÿซถ.

If a device has only IPv4 addresses and no IPv6 addresses, or the other way around, then the appropriate NSEC record SHOULD go in the additional section, so queriers can know for sure that the device has no addresses of that kind ๐Ÿ™Œ.

Some Multicast DNS responders treat a physical interface with both IPv4 and IPv6 addresses as one interface with two addresses. Others may treat it as logically two interfaces (one with one or more IPv4 addresses, and one with one or more IPv6 addresses) ๐Ÿงฉ. But responders that work this second way MUST NOT put the corresponding automatic NSEC records in the replies they send (that means no negative IPv4 assertion in their IPv6 responses, and no negative IPv6 assertion in their IPv4 responses), because that would cause incorrect operation in responders on the network that work the first way ๐Ÿšซ๐Ÿ˜ญ.


6.3. Responding to Multiquestion Queries ๐ŸŒท

Multicast DNS responders MUST correctly handle DNS query messages containing more than one question, by answering any or all of the questions they have answers for ๐Ÿ™Œ. Single-question queries can sometimes be answered without any delay when it's appropriate, but for query messages with more than one question, all (non-defensive) answers SHOULD be randomly delayed in the range 20-120 ms, or 400-500 ms if the TC (truncated) bit is set โฐ. Why? Because when a query has more than one question, a responder can't really be sure other responders aren't also answering the other questions in that same query at the same time ๐Ÿ‘€. (Answers defending a name, sent in response to a probe for that name, are NOT subject to this delay rule and still go out immediately ๐Ÿ›ก๏ธ.)


6.4. Response Aggregation ๐Ÿ“ฆ

When possible, a responder SHOULD, for the sake of network efficiency, aggregate as many responses as it can into a single Multicast DNS response message ๐Ÿงบ. For example, if a responder has several responses it plans to send, each delayed by a different interval, then earlier responses SHOULD be delayed by up to an additional 500 ms if that lets them be bundled with other responses scheduled to go out a little later ๐Ÿ“. Efficiency bestie behavior ๐Ÿ’…โœจ.

6.5. Wildcard Queries (qtype "ANY" and qclass "ANY") ๐ŸŒˆ

Okay bestie, when a responder answers a query with qtype "ANY" (255) and/or qclass "ANY" (255), it MUST respond with ALL of its records that match the query. ๐Ÿ’… This is lowkey different from how qtype "ANY" and qclass "ANY" work in Unicast DNS, so pay attention ๐Ÿ‘€

A lot of people think a Unicast DNS query for qtype "ANY" gets back every matching record. That's not it ๐Ÿ™…โ€โ™€๏ธ If any records match, the response only has to include at least one of them, not necessarily all of them.

This somewhat surprising behavior shows up a lot with caching (aka "recursive") name servers. If a caching server gets a qtype "ANY" query and already has at least one valid answer, it's allowed to return just the matching answers it happens to have in its cache. It doesn't have to go back to the authoritative name server to check whether there are more records that match the qtype "ANY" query. ๐Ÿง

Picture this: you ask for qtype "ANY" for the name host.example.com and you'd expect both the IPv4 (A) and the IPv6 (AAAA) address records back. In reality, it depends on what queries the caching servers in between have already gotten. If a caching server has no records for host.example.com, it will consult another server (usually the authoritative name server for that name), and in that case it will typically return all IPv4 and IPv6 address records. โœจ But if some other host recently did a qtype "A" query for host.example.com, so the caching server already has the IPv4 address records cached but no IPv6 address records, then it will return only the IPv4 address records it already has cached, and no IPv6 address records. ๐Ÿ˜ญ

Multicast DNS does not have this property. Its qtype "ANY" and qclass "ANY" queries never return some undefined subset of the matching records. When responding to queries using qtype "ANY" (255) and/or qclass "ANY" (255), a Multicast DNS responder MUST respond with ALL of its records that match the query. ๐ŸŽ€


6.6. Cooperating Multicast DNS Responders ๐Ÿซถ

If a Multicast DNS responder ("A") sees some other Multicast DNS responder ("B") send a Multicast DNS response with a resource record that has the same name, rrtype, and rrclass as one of A's resource records, but different rdata, then:

  • If A's resource record is meant to be a shared resource record, then this is no conflict, and no action is required. ๐ŸŒธ
  • If A's resource record is meant to be a member of a unique resource record set owned solely by that responder, then this is a conflict and MUST be handled as described in Section 9, "Conflict Resolution". ๐Ÿ’ฅ

If a Multicast DNS responder ("A") sees some other Multicast DNS responder ("B") send a Multicast DNS response with a resource record that has the same name, rrtype, and rrclass as one of A's resource records, and identical rdata, then:

  • If the TTL of B's resource record given in the message is at least half the true TTL from A's point of view, then no action is required. ๐Ÿฆ‹
  • If the TTL of B's resource record given in the message is less than half the true TTL from A's point of view, then A MUST mark its record to be announced via multicast. ๐Ÿšจ Queriers that get the record from B would use the TTL B gave, so they might delete the record sooner than A expects. By sending its own multicast response that corrects the TTL, A makes sure the record gets kept for the desired time. ๐Ÿ’–

These rules let multiple Multicast DNS responders offer the same data on the network (maybe for fault-tolerance reasons) without fighting each other. Iconic cooperation ๐Ÿ‘‘


6.7. Legacy Unicast Responses ๐Ÿงš

If the source UDP port in a received Multicast DNS query is not port 5353, that means the querier is a simple resolver like the one described in Section 5.1, "One-Shot Multicast DNS Queries". It doesn't fully implement all of Multicast DNS, so it's not a full participant ๐Ÿ™ˆ In this case, the Multicast DNS responder MUST send a UDP response directly back to the querier, via unicast, to the query packet's source IP address and port. This unicast response MUST be a conventional unicast response, the kind a conventional Unicast DNS server would generate. For example, it MUST repeat the query ID and the question given in the query message. ๐Ÿ“ฌ On top of that, the cache-flush bit described in Section 10.2, "Announcements to Flush Outdated Cache Entries", MUST NOT be set in legacy unicast responses. ๐Ÿ™…โ€โ™€๏ธ

The resource record TTL in a legacy unicast response SHOULD NOT be greater than ten seconds, even if the true TTL of the Multicast DNS resource record is higher. Here's why, and it's kind of a big deal ๐Ÿ˜ณ Multicast DNS responders that fully take part in the protocol use the cache coherency mechanisms described in Section 10, "Resource Record TTL Values and Cache Coherency", to update and invalidate stale data. If unicast responses sent to legacy resolvers used the same high TTLs, those legacy resolvers don't implement these cache coherency mechanisms. They could keep stale cached resource record data long after it stopped being valid. Yikes ๐Ÿ’€


7. Traffic Reduction ๐ŸŒฟ

A bunch of techniques are used to cut down the amount of traffic on the network. ๐Ÿ“

7.1. Known-Answer Suppression ๐Ÿ™Œ

When a Multicast DNS querier sends a query for which it already knows some answers, it fills the Answer Section of the DNS query message with those answers. ๐Ÿ“

Generally, this only applies to Shared records, not Unique records. Think about it: if a Multicast DNS querier already has at least one Unique record in its cache, it shouldn't be expecting any further different answers to this question. The Unique record(s) it already has make up the complete answer, so it has no reason to send the query at all. ๐Ÿคทโ€โ™€๏ธ On the other hand, having some Shared records in its cache doesn't mean the querier won't get more answers to this query. That's exactly when it helps to use the Known-Answer list to stop the repeated sending of redundant answers the querier already knows about. ๐Ÿ’…

A Multicast DNS responder MUST NOT answer a Multicast DNS query if the answer it would give is already in the Answer Section with an RR TTL of at least half the correct value. If the RR TTL of the answer in the Answer Section is less than half of the true RR TTL the responder knows about, the responder MUST send an answer to update the querier's cache before the record is in danger of expiring. โฐ

Because a responder will respond whenever the remaining TTL in the Known-Answer list is less than half the true TTL, it's superfluous for the querier to include those records in the Known-Answer list. So a Multicast DNS querier SHOULD NOT include records in the Known-Answer list whose remaining TTL is less than half of their original TTL. Doing that would just eat up space in the message without achieving the goal of suppressing responses, which would be a pointless waste of network capacity ๐Ÿ™„

A Multicast DNS querier MUST NOT cache resource records it sees in the Known-Answer Section of other Multicast DNS queries. The Answer Section of Multicast DNS queries is not authoritative. When a querier puts information in the Answer Section of a query, it's saying it believes the information is true. It's not claiming the information is true. Some of those records may have come from hosts that aren't on the network anymore, and passing that stale info along to other Multicast DNS queriers wouldn't help anyone ๐Ÿซ 

7.2. Multipacket Known-Answer Suppression ๐Ÿ“ฆ

Sometimes a Multicast DNS querier already has too many answers to fit in the Known-Answer Section of its query packets. In that case, it should issue a Multicast DNS query containing a question and as many Known-Answer records as will fit. It MUST then set the TC (Truncated) bit in the header before sending the query. It MUST immediately follow that packet with another query packet containing no questions and as many more Known-Answer records as will fit. If there are still too many records left to fit in one packet, it sets the TC bit again and keeps going until all the Known-Answer records have been sent. ๐Ÿš€

A Multicast DNS responder that sees a Multicast DNS query with the TC bit set defers its response for a time period randomly picked in the interval 400-500 ms. This gives the querier time to send additional Known-Answer packets before the responder answers. If the responder sees any of its answers listed in the Known-Answer lists of subsequent packets from the querying host, it MUST delete that answer from the list of answers it's planning to give. The one exception is when no other host on the network has also issued a query for that record and is waiting to receive an answer. ๐Ÿง 

If the responder receives additional Known-Answer packets with the TC bit set, it SHOULD extend the delay as necessary to make sure there's a pause of 400-500 ms after the last such packet before it sends its answer. โณ This does open up a potential risk that a continuous stream of Known-Answer packets could, in theory, stop a responder from ever answering. In practice, answers are never actually delayed significantly. And if significant delays did happen, that would mean the network is so overloaded that it's better to err on the side of caution. The downside of delaying an answer is that a user might take longer than usual to discover all the services on the local network. On the flip side, answering before all the Known-Answer packets have arrived would waste capacity sending unnecessary answers on a network that's already overloaded. In this (rare) situation, sacrificing speed to keep the network reliable is the right trade-off ๐Ÿ’–

7.3. Duplicate Question Suppression ๐Ÿ‘ฏ

If a host is planning to transmit (or retransmit) a query, and it sees another host on the network send a query containing the same "QM" question, and the Known-Answer Section of that query doesn't contain any records that this host wouldn't also put in its own Known-Answer Section, then this host SHOULD treat its own query as having been sent. โœจ When multiple queriers on the network are looking for the same resource records, there's no need for all of them to keep asking the same question over and over. Efficiency is the whole vibe ๐ŸŒˆ

7.4. Duplicate Answer Suppression ๐Ÿ’…

okay so if a host is about to send an answer, and it sees ANOTHER host on the network send a response with the same answer record, and that record's TTL is not less than the TTL this host would have given, then this host SHOULD count its own answer as already sent and not send an identical one ๐Ÿซถ when multiple responders have the same data, nobody needs to respond. the group chat already said it ๐Ÿ’–

the window for this happens when a host got a query and is delaying its reply for some pseudo-random time up to 500 ms (more on that elsewhere in this doc ๐Ÿงš). if, before it sends, it sees someone else send a response with that same answer record, that's your moment to stay quiet โœจ

this is super useful with Multicast DNS Proxy Servers ๐Ÿฆ‹ because you could end up with more than one proxy on the network answering for some other host (e.g., because that host is asleep and isn't responding to queries itself ๐Ÿ˜ด). the proxies would all be giving the same answer, and that's just noise.


8. Probing and Announcing on Startup ๐ŸŽ€

bestie, a Multicast DNS responder should have, at the very least, address records for all of its active interfaces ๐ŸŒธ making and advertising an HINFO record on each interface too can be useful for network admins, so it's a nice bonus ๐Ÿ“

whenever a Multicast DNS responder starts up, wakes up from sleep, gets a "Link Change" event from a network interface, or has any other reason to think its network connectivity might have changed in a relevant way, it MUST do the two startup steps: Probing (Section 8.1) and Announcing (Section 8.3). no skipping, no cap ๐Ÿ‘‘

8.1. Probing ๐Ÿ”

step one of startup is that, for every resource record the responder wants to be unique on the local link, it MUST send a Multicast DNS query asking for those records to see if any of them are already taken ๐Ÿ˜ญ the big example is a host's address records, which map its unique host name to its unique IPv4 and/or IPv6 addresses. all probe queries SHOULD use the record name and class you want (usually class 1, "Internet"), with query type "ANY" (255), so you get answers for every type of record with that name ๐Ÿ’… one question does the job of several, which is way more efficient on the network. it also lets a host verify it owns a name for ALL rrtypes, which is what you want most of the time. honestly it'd be so confusing if one host owned the "A" record for "myhost.local." but a different host owned the "AAAA" record for that same name ๐Ÿ’€

you can put more than one question in a Multicast DNS query, and that's super handy here ๐Ÿฆ‹ one message can probe for all of your resource records instead of needing a separate message for each. for example, a host can probe for uniqueness of its "A" record and all its SRV records [RFC6763] in the same query message. iconic efficiency ๐Ÿ‘‘

when a host is ready to send its probe packet(s), it should first wait a short random delay, uniformly distributed in the range 0-250 ms ๐ŸŒˆ this random delay is there so that devices powered on at the same time, or plugged into an Ethernet hub that gets powered on, or hit by some other external event, don't all send synchronized probes at once. chaotic energy avoided โœจ

250 ms after the first query, the host should send a second one; then, 250 ms after that, a third. if, by 250 ms after the third probe, no conflicting Multicast DNS responses have shown up, the host may move on to the next step, announcing ๐ŸŽ‰ (quick note: probing is the one exception to the normal rule that there should be at least one second between repetitions of the same question, and the interval between repetitions should at least double ๐Ÿค“)

when sending probe queries, a host MUST NOT check its cache for potential answers ๐Ÿ™…โ€โ™€๏ธ only conflicting Multicast DNS responses received "live" from the network count when deciding whether probing succeeded or failed. your cache is not invited to this party ๐Ÿซ 

the probing window is intentionally kept quite short, so services can announce themselves without unreasonable delay ๐ŸŒธ which means that from the moment the first probe packet goes out, another device using that name has just 750 ms to defend it. on networks that are slow, or busy, or both, round-trip latency can eat a few hundred milliseconds, and software delays in slow devices can add more on top ๐Ÿ˜ฉ so when a device gets a probe query for a name it's currently using, it SHOULD generate its defensive response immediately and send it as fast as possible. the usual random delays before responding (which prevent sudden bursts of simultaneous answers) do NOT apply here, since normally at most one host should ever respond to a given probe question. even if one DNS query message holds multiple probe questions, it'd be unusual for it to get a defensive response from more than one other host. and because of the mDNS multicast rate-limiting rules, the probes SHOULD be sent as "QU" questions with the unicast-response bit set ๐Ÿ’œ that lets a defending host reply right away via unicast, instead of possibly waiting before replying via multicast.

during probing, from the moment the first probe packet is sent until 250 ms after the third probe, if ANY conflicting Multicast DNS response comes in, the probing host MUST defer to the existing host, and SHOULD pick new names for some or all of its resource records as appropriate ๐Ÿ˜ค apparently-conflicting responses received before the first probe packet is sent MUST be silently ignored (see the discussion of stale probe packets in Section 8.2, "Simultaneous Probe Tiebreaking", below) ๐Ÿ™ˆ and if the host is probing with query type "ANY" like we recommended, then any answer containing a record with that name, of ANY type, MUST be treated as a conflicting response and handled accordingly. no exceptions, periodt ๐Ÿ’…

if fifteen conflicts happen within any ten-second period, the host MUST wait at least five seconds before each successive additional probe attempt ๐Ÿšจ this is so that, if there are software bugs or other unexpected problems, errant hosts don't flood the network with a never-ending stream of multicast traffic. for very simple devices, a valid way to comply is to always wait five seconds after any failed probe attempt before trying again ๐Ÿ’–

if a responder already knows, through other means, that its unique resource record set name, rrtype, and rrclass cannot be in use by any other responder on the network, then it SHOULD skip probing for that record set ๐Ÿง  for example, when creating the reverse address mapping PTR records, the host can reasonably assume nobody else is trying to create those same PTR records, because that would mean two hosts were trying to use the same IP address. if that were the case, they'd already be dealing with communication problems way beyond what Multicast DNS is designed to fix ๐Ÿ˜ญ similarly, if a responder is acting as a proxy and taking over from another Multicast DNS responder that already verified the uniqueness of the record, then the proxy SHOULD NOT repeat the probing step for those records ๐Ÿซถ

8.2. Simultaneous Probe Tiebreaking โœจ

okay so the astute reader (hi bestie, that's you ๐Ÿซถ) will spot a race condition in what we just covered ๐Ÿ˜ญ. if two hosts are probing for the same name at the same time, neither one gets a response to its probe, so both could wrongly conclude they're good to use the name ๐Ÿ’€. to break the tie, each host fills the query message's Authority Section with the record or records (and the rdata) it would propose to use if its probing succeeds ๐ŸŽ€. the Authority Section is doing a job similar to the "Update Section" in a DNS Update message [RFC2136] [RFC3007] ๐Ÿงš

when a host is probing for a group of related records with the same name (like the SRV and TXT records for a DNS-SD service), it only needs one question in the Question Section, because query type "ANY" (255) gets answers for every record with that name ๐ŸŒˆ. BUT, for the tiebreak to work in every case, the Authority Section has to contain all the records and proposed rdata being probed for uniqueness ๐Ÿ‘‘

now the fun part ๐Ÿ’…. when a host that's probing for a record sees another host ask for that same record, it checks the Authority Section of that query. if it finds any resource record(s) there that answer the query, it compares that data with its own tentative data ๐Ÿฆ‹. first the simple case: one host probing for a single record, and a simultaneous probe from another host also probing for a single record. the two records get compared and the lexicographically later data wins ๐Ÿ†. so if your own data is lexicographically later, you just ignore the other host's probe ๐Ÿ˜Œ. if your data is lexicographically earlier, you defer to the winner by waiting one second and then starting to probe for the record again ๐Ÿ“

why wait one second? to guard against stale probe packets hanging around on the network ๐Ÿ‘ป. this includes stale probes the host sent moments ago itself, before some config change, which can get echoed back after a short delay by some Ethernet switches and some 802.11 base stations ๐Ÿ™ˆ. if the winning probe really came from another host, that host will have finished probing after one second and will answer your probes from then on ๐Ÿซถ. if the "winning" probe was just an old stale packet (maybe even your own), then its probes go unanswered when it retries in one second, and you successfully claim the name ๐ŸŽ‰

the determination of "lexicographically later" happens in this order: first compare the record class (not counting the cache-flush bit from Section 10.2), then the record type, then do a raw comparison of the binary rdata content without caring what it means or how it's structured ๐Ÿ”. if the record classes differ, the numerically greater class is "lexicographically later" โœจ. otherwise, if the record types differ, the numerically greater type is "lexicographically later" ๐Ÿ’œ. if rrtype and rrclass both match, then the rdata gets compared ๐ŸŒธ

for resource records whose rdata is subject to name compression [RFC1035], the names MUST be uncompressed before comparison ๐Ÿ™…โ€โ™€๏ธ. (how a particular name got compressed is just an artifact of how and where the record was written into the DNS message. it's not an intrinsic property of the resource record itself ๐Ÿ’…)

the bytes of the raw uncompressed rdata get compared in turn, read as eight-bit UNSIGNED values. this continues until a byte is found whose value is greater than its counterpart (then the rdata with the greater byte is lexicographically later) or one of the records runs out of rdata (then the record that still has data left over is lexicographically later) ๐ŸŒŸ. here's an example of a conflict:

MyPrinter.local. A 169.254.99.200
MyPrinter.local. A 169.254.200.50

so 169.254.200.50 is lexicographically later (the third byte, 200, beats its counterpart, 99), which makes it the winner ๐Ÿ†

bestie, this is so important: the bytes HAVE to be read as UNSIGNED values in the range 0-255, or you'll get the wrong outcome ๐Ÿ˜ฑ. in the example above, if the byte 200 got read as a signed eight-bit value, it would become -56, and the wrong address record would win ๐Ÿ’€

8.2.1. Simultaneous Probe Tiebreaking for Multiple Records

when a host is probing for a set of records with the same name, or a message comes in with multiple tiebreaker records answering a probe question in the Question Section, both the host's records and the tiebreaker records from the message get sorted into order. then they're compared pairwise, using the same comparison technique as above, until a difference shows up ๐Ÿงฉ

the records are sorted with the same lexicographical order we just talked about. so if the classes differ, the record with the lower class number goes first ๐Ÿฅ‡. if the classes are the same but the rrtypes differ, the lower rrtype number goes first ๐ŸŒท. if the class and rrtype both match, the rdata gets compared bytewise until a difference is found ๐Ÿ”. for example, in the super common case of advertising DNS-SD services with a TXT record and an SRV record, the TXT record comes first (the rrtype value for TXT is 16) and the SRV record comes second (the rrtype value for SRV is 33) ๐ŸŽ€

when you compare the records, if the first records match perfectly, then you compare the second records, and so on ๐Ÿซง. if either list runs out of records before any difference is found, the list that still has records left wins the tiebreak ๐Ÿ…. if both lists run out at the same time without finding any difference, that means two devices are advertising identical sets of records (which is sometimes done for fault tolerance), so there's actually no conflict at all ๐Ÿซถโœจ

8.3. Announcing ๐Ÿ“ฃ

the second startup step is that the Multicast DNS responder MUST send an unsolicited Multicast DNS response. this response contains, in the Answer Section, all of its newly registered resource records (both shared records and unique records that have finished the probing step) ๐ŸŽ‰. if there are too many resource records to fit in a single packet, multiple packets should be used ๐Ÿ“ฆ

for shared records (like the PTR records used by DNS-Based Service Discovery [RFC6763]), the records just go as-is into the Answer Section of the DNS response ๐Ÿฆ‹

for records that were verified to be unique in the previous step, they go into the Answer Section of the DNS response with the most significant bit of the rrclass set to one ๐Ÿ‘‘. that most significant bit of the rrclass, in an Answer Section of a response message, is the Multicast DNS cache-flush bit. it's covered in more detail in Section 10.2, "Announcements to Flush Outdated Cache Entries" ๐ŸŒธ

the Multicast DNS responder MUST send at least two unsolicited responses, one second apart ๐Ÿ•. for extra robustness against packet loss, a responder MAY send up to eight unsolicited responses, as long as the interval between unsolicited responses increases by at least a factor of two with every response sent ๐Ÿ“ˆ๐Ÿ’–

a Multicast DNS responder MUST NOT send announcements unless it has information that its network connectivity may have changed in some relevant way ๐Ÿ™…โ€โ™€๏ธ. in particular, a Multicast DNS responder MUST NOT send regular periodic announcements as a matter of course ๐Ÿšซ

whenever a Multicast DNS responder receives any Multicast DNS response (solicited or otherwise) containing a conflicting resource record, the conflict MUST be resolved as described in Section 9, "Conflict Resolution" โš”๏ธ

8.4. Updating ๐Ÿ”„

at any time, if the rdata of any of a host's Multicast DNS records changes, the host MUST repeat the Announcing step described above to update neighboring caches ๐Ÿ“ฃ. for example, if any of a host's IP addresses change, it MUST re-announce those address records ๐Ÿก. the host doesn't need to repeat the Probing step, because it has already established unique ownership of that name ๐Ÿ‘‘

for shared records, a host MUST send a "goodbye" announcement with RR TTL zero (see Section 10.1, "Goodbye Packets") for the old rdata ๐Ÿ‘‹. this makes the old rdata get deleted from peer caches, and it happens before the new rdata gets announced ๐Ÿงน. for unique records, a host SHOULD omit the "goodbye" announcement, since the cache-flush bit on the newly announced records will flush the old rdata from peer caches anyway ๐ŸŒŠโœจ

a host may update the contents of any of its records at any time, but a host SHOULD NOT update records more frequently than ten times per minute ๐Ÿข. frequent rapid updates put a burden on the network ๐Ÿ˜ต. if a host has information to disseminate that changes more often than ten times per minute, it may be more appropriate to design a protocol for that specific purpose ๐Ÿงš๐Ÿ’œ

9. Conflict Resolution โœจ

okay bestie, so a conflict happens when a Multicast DNS responder is in charge of a unique record (it's currently authoritative for it) and it gets a Multicast DNS response with a record that has the same name, rrtype and rrclass but inconsistent rdata. what counts as inconsistent is kinda context sensitive ๐Ÿค” BUT records with identical rdata are never inconsistent, even if they come from different hosts! ๐Ÿ’– that's on purpose, so proxies and other fault-tolerance stuff can give the same answer without starting a fight ๐Ÿซถ

a super common example of a record type that's meant to be unique and NOT shared between hosts is the address record, the one that maps a host's name to its IP address ๐ŸŒธ if a host sees another host announce an address record with the same name but a different IP address, that's inconsistent, and that address record is now in conflict ๐Ÿ˜ญ

okay now the important part ๐Ÿšจ whenever a Multicast DNS responder gets ANY Multicast DNS response (solicited or not ๐Ÿ‘€) with a conflicting record in any of the Resource Record Sections, it MUST immediately reset its conflicted unique record to probing state, and go through the startup steps described above in Section 8, "Probing and Announcing on Startup". the protocol used in the Probing phase picks a winner and a loser, and the loser MUST cease using the name, and reconfigure. ๐Ÿ’…

it is SO important that any host receiving a resource record that conflicts with one of its own MUST take action as described above. no ignoring it, periodt ๐Ÿ™…โ€โ™€๏ธ

like, if two hosts are using the same host name and only one of them was configured to require a unique host name, the one that wasn't configured that way won't perceive any conflict, so it won't do anything ๐Ÿฅฒ the host that does want a unique host name goes back to Probing state, and that's how it runs the steps needed to actually get a unique name ๐Ÿฆ‹

the recommended course of action after probing and failing goes like this:

  1. programmatically change the resource record name to try to find a new name that's unique ๐Ÿ” this could be done by adding some more identifying info (e.g., the model name of the hardware) if it isn't already in the name, or appending the digit "2" to the name, or incrementing a number at the end of the name if one is already there.
  2. probe again, and repeat as necessary until a unique name is found ๐Ÿ”
  3. once an available unique name has been figured out (by probing without getting any conflicting response โœ…), record this newly chosen name in persistent storage so the device uses the same name the next time it's power-cycled ๐Ÿงš
  4. show a message to the user or operator telling them about the name change ๐Ÿ’Œ for example:
The name "Bob's Music" is in use by another music server on
the network.  Your music collection has been renamed to
"Bob's Music (2)".  If you want to change this name, use
[describe appropriate menu item or preference dialog here].

how the user or operator gets told about the new name depends on context ๐Ÿคทโ€โ™€๏ธ a desktop computer with a screen might pop up a dialog box. a headless server in the closet may write a message to a log file, or use whatever mechanism (email, SNMP trap, etc.) it uses to tell the administrator about error conditions. on the other hand, a headless server in the closet may not inform the user at all -- if the user cares, they'll notice the name changed and connect to the server in the usual way (e.g., via web browser) to set a new name ๐Ÿ’ป

  1. after one minute of probing, if the Multicast DNS responder still hasn't found any unused name, it should log an error message to tell the user or operator ๐Ÿšจ this situation should never happen in normal operation ๐Ÿ™ the only things that would cause it are either a deliberate denial-of-service attack, or some kind of very obscure hardware or software bug that acts like a deliberate denial-of-service attack ๐Ÿ’€

these considerations apply to address records (i.e., host names) and to all resource records where uniqueness (or keeping some other defined constraint) is wanted ๐Ÿ’œ


10. Resource Record TTL Values and Cache Coherency ๐Ÿ•ฐ๏ธ

as a general rule, the recommended TTL value for Multicast DNS resource records with a host name as the record's name (e.g., A, AAAA, HINFO) or a host name inside the record's rdata (e.g., SRV, reverse mapping PTR record) SHOULD be 120 seconds ๐Ÿ“

the recommended TTL value for other Multicast DNS resource records is 75 minutes โญ

a querier with an active outstanding query will send a query message when one or more of the resource records in its cache are 80% of the way to expiry ๐Ÿ‘€ if the TTL on those records is 75 minutes, this ongoing cache maintenance process gives a steady-state query rate of one query every 60 minutes ๐ŸŒˆ

any distributed cache needs a cache coherency protocol ๐Ÿง  if Multicast DNS resource records follow the recommendation and have a TTL of 75 minutes, that means stale data could hang around in the system for a little over an hour ๐Ÿ˜ต making the default RR TTL way lower would shorten the lifetime of stale data, but it would make too much extra traffic on the network ๐Ÿš—๐Ÿ’จ so there are various techniques to minimize the impact of stale data, outlined in the five subsections below ๐ŸŽ€

10.1. Goodbye Packets ๐Ÿ‘‹

if a host knows that certain resource record data is about to become invalid (for example, when the host is doing a clean shutdown), the host SHOULD send an unsolicited Multicast DNS response packet with the same resource record name, rrtype, rrclass, and rdata, but an RR TTL of zero ๐Ÿซก this updates the TTL stored in neighboring hosts' cache entries to zero, so that cache entry gets deleted right away ๐Ÿ—‘๏ธ

queriers that receive a Multicast DNS response with a TTL of zero SHOULD NOT delete the record from the cache immediately ๐Ÿ™…โ€โ™€๏ธ instead they record a TTL of 1 and then delete the record one second later โฑ๏ธ in the case of multiple Multicast DNS responders on the network (described in Section 6.6 above), if one of the responders shuts down and sends goodbye packets for its records by mistake, it gives the other cooperating responders one second to send out their own response to "rescue" the records before they expire and get deleted ๐Ÿฆธโ€โ™€๏ธโœจ

10.2. Announcements to Flush Outdated Cache Entries โœจ

okay so whenever a host has a resource record with new data, or with data that might be new (like after a reboot, waking from sleep, plugging into a new network link, or changing IP address), it needs to tell its peers about it ๐Ÿ“ฃ๐Ÿ’–. If the host hasn't been continuously connected and hanging out on the network link, it MUST first probe to re-verify that its unique records are still unique, like we covered in Section 8.1, "Probing" ๐Ÿ•ต๏ธโ€โ™€๏ธ.

Once probing is done (if it was needed), the host MUST then send a series of unsolicited announcements to update the cache entries of its neighbor hosts ๐Ÿš€. In those announcements, if the record has been verified unique, the host sets the most significant bit of the rrclass field. That bit is the cache-flush bit ๐ŸŽ€, and it tells neighbors "hey, this is not a shared record type." So instead of adding the new record into the cache alongside whatever was already there with the same name, rrtype, and rrclass, every old record with that name, rrtype, and rrclass that was received more than one second ago gets declared invalid and marked to expire in one second ๐Ÿ’….

The vibe of the cache-flush bit is super specific ๐Ÿง. Normally, when a resource record shows up in a Resource Record Section of the DNS response, it's basically saying "this info is true" โœ…. But with the cache-flush bit set, it's saying "this is the truth and the whole truth, and anything you heard more than a second ago about records with this name/rrtype/rrclass is no longer true" ๐Ÿ‘‘. Main character energy, honestly ๐Ÿ˜ญ.

Now, a unique RRSet from one host might be too big to fit in a single packet, so only cache records that are more than one second old get flushed ๐ŸŒธ. That gives the announcing host room to fire off a quick burst of packets back-to-back on the wire, all containing the members of the RRSet ๐Ÿ’จ. When a receiver gets records with the cache-flush bit set, every record older than one second is marked to be deleted one second in the future. Then, one second after the end of the little burst, any records not represented in that burst get expired from all peer caches โฐ.

Any time a host sends a response packet containing some members of a unique RRSet, it MUST send the entire RRSet, preferably in a single packet. If the whole RRSet won't fit in one packet, it MUST send it as a quick burst of packets sent as close together as possible ๐Ÿ“ฆ. On top of that, the host MUST set the cache-flush bit on all members of the unique RRSet ๐ŸŽ€.

Waiting one second before deleting stale records also helps with bridged networks ๐ŸŒ‰. Say a host's address record announcement on a wireless interface gets bridged onto a wired Ethernet. That could cause the same host's Ethernet address records to get flushed from peer caches. The one-second delay gives the host time to see its own announcement arrive on the wired Ethernet, so it can immediately re-announce its Ethernet interface's address records and both sets stay valid and live in peer caches ๐Ÿซถ.

These rules, about when to set the cache-flush bit and about sending the entire RRSet, apply regardless of why the response message is being generated ๐Ÿคทโ€โ™€๏ธ. They cover startup announcements as described in Section 8.3, "Announcing", and responses generated because a query message came in.

The cache-flush bit is only set in records in the Resource Record Sections of Multicast DNS responses sent to UDP port 5353 ๐Ÿฆ‹.

The cache-flush bit MUST NOT be set in any resource records in a response message sent in legacy unicast responses to UDP ports other than 5353 ๐Ÿ™…โ€โ™€๏ธ.

The cache-flush bit MUST NOT be set in any resource records in the Known-Answer list of any query message ๐Ÿšซ.

The cache-flush bit MUST NOT ever be set in any shared resource record ๐Ÿ’€. Doing so would cause all the other shared versions of this resource record with different rdata, from different responders, to be immediately deleted from all the caches on the network. Chaos, no thank you.

The cache-flush bit does not apply to questions listed in the Question Section of a Multicast DNS message ๐Ÿ™ˆ. The top bit of the rrclass field in questions is used for a totally different purpose (see Section 5.4, "Questions Requesting Unicast Responses").

Also, the cache-flush bit is not part of the resource record class ๐Ÿง . It's the most significant bit of the second 16-bit word of a resource record in a Resource Record Section of a Multicast DNS message (the field conventionally called the rrclass field), and the actual resource record class is the least significant fifteen bits of that field. There is no Multicast DNS resource record class 0x8001! The value 0x8001 in the rrclass field of a resource record in a Multicast DNS response message means class 1 with the cache-flush bit set ๐ŸŒˆ. So when receiving a resource record with the cache-flush bit set, implementations should take care to mask off that bit before storing the record in memory, or otherwise make sure it gets the correct semantic interpretation ๐Ÿงผ.

The reuse of the top bit of the rrclass field only applies to conventional resource record types that are subject to caching ๐Ÿง. It does not apply to pseudo-RRs like OPT [RFC2671], TSIG [RFC2845], TKEY [RFC2930], SIG0 [RFC2931], and so on, which only pertain to a particular transport-level message and not to any actual DNS data ๐Ÿ™ƒ. Since pseudo-RRs should never go into the Multicast DNS cache, the cache-flush bit concept isn't applicable to them. In particular, the rrclass field of an OPT record encodes the sender's UDP payload size, and it should be read as a sixteen-bit length value in the range 0-65535, not a one-bit flag plus a fifteen-bit length ๐Ÿงฎ.


10.3. Cache Flush on Topology change ๐Ÿ”Œ

If the hardware on a host can indicate physical changes of connectivity, then when the hardware reports one, the host should factor that info into its Multicast DNS cache management strategy โšก. For example, a host might choose to immediately flush all cache records received on a particular interface when that cable gets unplugged. Or it might choose to shrink the remaining TTL on all those records to a few seconds, so that if the cable isn't plugged back in quickly, those records just expire from the cache on their own ๐Ÿฅ€.

Likewise, when a host reboots, wakes from sleep, or goes through some other similar discontinuous state change, the cache management strategy should take that into account too ๐ŸŒ™.


10.4. Cache Flush on Failure Indication ๐Ÿšจ

Sometimes a cache record can be figured out to be stale when a client tries to use the rdata in it and finds that rdata is wrong ๐Ÿ˜ฌ.

For example, the rdata in an address record can be determined to be incorrect if attempts to contact that host fail. That could happen because (for an IPv4 address on a local subnet) ARP requests for that address go unanswered, because (for an IPv6 address with an on-link prefix) ND requests for that address go unanswered, or because (for an address on a remote network) a router returns an ICMP "Host Unreachable" error ๐Ÿ›‘.

The rdata in an SRV record can be determined to be incorrect if attempts to communicate with the indicated service at the given host and port number aren't successful ๐Ÿ“ž.

The rdata in a DNS-SD PTR record can be determined to be incorrect if attempts to look up the SRV record it references aren't successful ๐Ÿ”.

The software implementing the Multicast DNS resource record cache should provide a mechanism so that clients who detect stale rdata can inform the cache ๐Ÿ’Œ.

When the cache gets this hint that it should reconfirm some record, it MUST issue two or more queries for the resource record in dispute ๐Ÿ“จ. If no response comes back within ten seconds, then even though its TTL may say it's not due to expire yet, that record SHOULD be promptly flushed from the cache ๐Ÿ—‘๏ธ.

So the end result is this: if a printer suffers a sudden power failure or some other abrupt disconnection from the network, its name may keep showing up in DNS-SD browser lists on people's screens ๐Ÿ–จ๏ธ. Eventually that entry will expire from the cache naturally. But if a user tries to access the printer before that happens, the failure to contact it will trigger the much hastier demise of its cache entries ๐Ÿ’จ. It's a sensible trade-off between good user experience and good network efficiency ๐Ÿ’–. If we insisted that printers disappear from the printer list within 30 seconds of becoming unavailable, for all failure modes, the only way to pull that off would be for clients to poll the printer at least every 30 seconds, or for the printer to announce its presence at least every 30 seconds. Both of those would be an unreasonable burden on most networks ๐Ÿ˜ตโ€๐Ÿ’ซ.


10.5. Passive Observation Of Failures (POOF) ๐Ÿ‘€

A host observes the multicast queries issued by the other hosts on the network ๐Ÿ•ถ๏ธ. One of the major benefits of also sending responses using multicast is that it lets all hosts see the responses (or lack thereof) to those queries ๐ŸŒ.

If a host sees queries for which a record in its cache would be expected to be given as an answer in a multicast response, but no such answer shows up, then the host may take that as an indication that the record may no longer be valid ๐Ÿง.

After seeing two or more of these queries, and seeing no multicast response containing the expected answer within ten seconds, then even though its TTL may say it's not yet due to expire, that record SHOULD be flushed from the cache ๐Ÿงน. The host SHOULD NOT perform its own queries to reconfirm that the record is truly gone ๐Ÿ™…โ€โ™€๏ธ. If every host on a large network did that, it would cause a lot of unnecessary multicast traffic ๐Ÿ“ˆ. If host A sends multicast queries that stay unanswered, there's no reason to suppose host B or any other host is going to be any more successful ๐Ÿคทโ€โ™€๏ธ.

The previous section, "Cache Flush on Failure Indication", described a situation where a user trying to print discovers the printer is no longer available ๐Ÿ–จ๏ธ๐Ÿ’”. With the passive observation described here, when one user fails to contact the printer, all hosts on the network observe that failure and update their caches accordingly ๐Ÿซถโœจ.

11. Source Address Check โœจ

okay bestie, every Multicast DNS response (even the ones sent as unicast) SHOULD go out with IP TTL set to 255 ๐Ÿ’… this is for backwards-compat with older mDNS queriers (the ones built off a draft from February 2004) that check the TTL on arrival to figure out if a packet came from the local link. they toss anything that isn't 255, so no cap, it matters ๐Ÿซถ

when a host sends an mDNS query to a link-local destination (224.0.0.251 or FF02::FB), it MUST only accept responses that actually came from the local link and silently discard everything else ๐Ÿ™…โ€โ™€๏ธ why? bc without this check, remote rogue hosts could send spoofed answers (maybe unicast right at the victim) and the receiving machine might think they're local. big yikes ๐Ÿ˜ญ

the local-link check works in two ways:

  • any response whose IP header destination is the IPv4 mDNS link-local multicast address 224.0.0.251 or the IPv6 mDNS link-local multicast address FF02::FB is automatically treated as local, no matter the source IP. this is SO important for weird setups, like multiple logical IP subnets overlaid on one link, or when devices are plugged into the same link but misconfigured with totally unrelated IP addresses and subnet masks. it keeps everything working in those messy situations ๐Ÿงš
  • for responses with a unicast destination in the IP header, the source IP gets checked to see if it's on a local subnet. for IPv4, the source counts as local if, for (one of) the address(es) configured on the receiving interface, (I & M) == (P & M) is true. here I and M are the interface address and subnet mask, P is the source IP from the packet, & is bitwise AND, and == is a bitwise equality test. for IPv6, the source counts as on-link if, for any on-link IPv6 prefix on the receiving interface (learned from IPv6 router advertisements or configured some other way on the host), the first n bits of the source address match the first n bits of that prefix, where n is the prefix length being checked ๐ŸŒธ

okay now the responder side, which is lowkey the smart part ๐Ÿง  queriers ignore responses that seem to come from outside the local subnet, so a responder SHOULD avoid generating responses it can reasonably predict will get ignored. this matters especially with overlaid subnets. if a responder gets a query sent to 224.0.0.251 from a source that doesn't look like it's on the same subnet (for IPv6, from a source address where the responder has no address with the same prefix on that interface), then even if the query says a unicast response is preferred (see Section 5.4, "Questions Requesting Unicast Responses"), the responder SHOULD just reply by multicast anyway ๐Ÿ’– because a unicast reply to an apparently non-local source will probably be ignored. no point being extra ๐Ÿ’€


12. Special Characteristics of Multicast DNS Domains ๐Ÿฆ‹

okay so names that end in .local. are NOT like regular DNS names ๐Ÿ™ˆ they only have local significance. same goes for names in the IPv4 link-local reverse mapping domain 254.169.in-addr.arpa. and the IPv6 link-local reverse mapping domains 8.e.f.ip6.arpa., 9.e.f.ip6.arpa., a.e.f.ip6.arpa., and b.e.f.ip6.arpa..

these names are mainly protocol identifiers, not things users are meant to see. even if end users happen to spot them sometimes, that's not what they're for ๐Ÿซถ so they should be treated as opaque identifiers. and the string "local" should not be translated or localized into other languages, same way "localhost" doesn't get translated either. respect the vibe ๐Ÿ’…

now the big difference: conventional Unicast DNS is giving one unified namespace, where the same query gets the same answer no matter where on the planet you ask or which recursive server you send it to โœจ but every IP link has its own private .local., 254.169.in-addr.arpa., and IPv6 link-local reverse mapping namespaces, so the answer to a query for a name in those domains depends on where you ask it ๐ŸŒˆ (fun fact, this isn't unique to mDNS. the original DNS idea was one global namespace, but split views, firewalls, intranets, DNS geolocation, and stuff like that have made answers depend on where the querier is sitting.)

the IPv4 name server address for an mDNS domain is 224.0.0.251, and the IPv6 name server address is FF02::FB. these are multicast addresses, so they point at a whole group of hosts, not one host, all working together to keep up a reasonable copy of a well-managed DNS zone ๐Ÿ“ conceptually, an mDNS domain is one DNS zone. but its server is a distributed process running across a bunch of loosely cooperating CPUs, not one process on one CPU. very cluster energy ๐Ÿงš

mDNS domains aren't delegated from their parent domain with NS (Name Server) records, and there's no concept of delegating subdomains inside an mDNS domain either. so just because one host answers queries for some record type under example.local. doesn't mean it'll answer for child.example.local., or even for other record types under example.local. ๐Ÿ™ƒ no vibes carry over.

there are no NS records anywhere in mDNS domains. instead, IANA reserves the mDNS domains, and there's effectively an implicit delegation of all of them to the 224.0.0.251:5353 and [FF02::FB]:5353 multicast groups, simply because client software is implementing the protocol rules in this document ๐Ÿ”ฅ

mDNS zones also have no SOA (Start of Authority) record ๐Ÿ˜ญ in a normal DNS zone, the SOA has stuff like the zone admin's email address and a monotonically increasing serial number for the last change. but there's no single human admin for any mDNS zone, so there's no email address. and since the hosts managing a zone are only loosely coordinated, there's no easy monotonically increasing serial number to tell whether the zone changed. a host holding part of the shared zone could crash or drop off the network at any moment without telling anyone. there's just no reliable way to have a zone serial number that immediately changes whenever that happens. it's a whole mood ๐Ÿฅบ

and zone transfers aren't possible for any mDNS zone. period ๐Ÿ™…โ€โ™€๏ธ


13. Enabling and Disabling Multicast DNS ๐ŸŽ€

the option to fail over to mDNS for names that don't end in .local. SHOULD be user-configured, and SHOULD be disabled by default ๐Ÿ›ก๏ธ why? bc of the security risk of accidentally resolving apparently global names locally. turning it on might make sense on a secure isolated network, or on some future network where machines only use DNSSEC for all DNS queries and have mDNS responders that can generate the right DNSSEC signatures. that's how you guard against spoofing ๐Ÿ’œ

the option to look up unqualified (relative) names by appending .local. (or not) is controlled by whether .local. is (or isn't) in the client's DNS search list โœจ

no special control is needed for turning mDNS on or off for names explicitly ending with .local. that the user typed in. the user doesn't need a way to disable mDNS for .local. names, bc if they don't want mDNS, they can just not use those names ๐Ÿ™ˆ and if a user does type a name ending in .local., we can safely assume they probably want it to work. user config options that can (on purpose or by accident) stop local names from working are just one more way to frustrate people trying to get stuff done, and that feeds the idea that "IP networking is too complicated to configure and too hard to use" ๐Ÿ˜ญ๐Ÿซถ

14. Considerations for Multiple Interfaces โœจ

okay bestie, so a host SHOULD defend its dot-local host name on every active interface where it's answering Multicast DNS queries ๐Ÿ›ก๏ธ๐Ÿ’–

if there's a name conflict on any interface, a host should pick a new host name if it wants to keep its host name unique ๐Ÿ”„

a host may use the same name (or set of names) for all of its address records on all interfaces ๐ŸŽ€ or it may manage each Multicast DNS interface on its own, answering to a different name (or set of names) on each one ๐Ÿฆ‹

except for proxying and other similar specialized uses, addresses in IPv4 or IPv6 address records in Multicast DNS responses MUST be valid for use on the interface the response is sent on ๐Ÿ’…

just like the same link-local IP address can legally be in use at the same time on different links by different hosts, the same link-local host name can legally be in use at the same time on different links too, and that's not an error ๐ŸŒˆ a multihomed host connected to two different links may be able to talk to two different hosts that are both legally using the same name ๐Ÿ‘ฏโ€โ™€๏ธ this kind of name duplication should be rare, but it means a host that wants to fully support this case needs network programming APIs that let applications choose which interface to run a link-local Multicast DNS query on, and find out which interface a Multicast DNS response came in on ๐Ÿงš

there's one more special precaution multihomed hosts need to take ๐Ÿ‘€ it's super common for laptops nowadays to have an Ethernet connection and an 802.11 [IEEE.802.11] wireless connection active at the same time ๐Ÿ’ป the laptop software can't easily tell whether the wireless connection is actually bridged onto the same network segment as the Ethernet one ๐Ÿคทโ€โ™€๏ธ if the two networks are bridged together, packets the host sends on one interface will show up on the other interface a few milliseconds later, and we have to be careful that this bridging doesn't cause problems ๐Ÿ˜ญ

when the host announces its host name (that is, its address records) on its wireless interface, those announcement records are sent with the cache-flush bit set ๐Ÿšฉ so when they reach the Ethernet segment, they'll make all the peers on the Ethernet flush the host's Ethernet address records from their caches ๐Ÿ’€ Multicast DNS has a safeguard for this: when records arrive with the cache-flush bit set, other records aren't deleted from peer caches right away, they're just marked for deletion in one second โณ when the host sees its own wireless address records show up on its Ethernet interface with the cache-flush bit set, this one-second grace period gives it time to respond and re-announce its Ethernet address records, so they get reinstated in peer caches before they're deleted ๐Ÿ™Œ

but here's the plot twist ๐Ÿ˜ค this fixes one problem and creates another, because when those Ethernet announcement records arrive back on the wireless interface, the host would respond defensively again to reinstate its wireless records, and this would go on forever, flooding the network with traffic ๐ŸŒช๏ธ so Multicast DNS has a second safeguard: the cache-flush bit doesn't apply to records received very recently, within the last second ๐Ÿง  that means when the host sees its own Ethernet address records arrive on its wireless interface with the cache-flush bit set, it knows it doesn't need to re-announce its wireless address records again, because it already sent them less than a second ago, and that makes them immune from deletion from peer caches ๐Ÿ›ก๏ธโœจ (See Section 10.2.)

15. Considerations for Multiple Responders on the Same Machine ๐Ÿ–ฅ๏ธ

it's possible to have more than one Multicast DNS responder and/or querier implementation running on the same machine, but there are some known issues ๐Ÿ™ˆ

15.1. Receiving Unicast Responses

in most operating systems, incoming multicast packets can be delivered to all open sockets bound to the right port number, as long as the clients take the proper steps to allow it ๐Ÿ“ฌ for this reason, all Multicast DNS implementations SHOULD use the SO_REUSEPORT and/or SO_REUSEADDR options (or whatever the equivalent is for the operating system in question) so they can all bind to UDP port 5353 and receive incoming multicast packets addressed to that port ๐ŸŽ‰ but unlike multicast packets, incoming unicast UDP packets are typically delivered only to the first socket to bind to that port ๐Ÿ˜ฉ that means "QU" responses and other packets sent via unicast will only be received by the first Multicast DNS responder and/or querier on a system ๐Ÿ’” this limitation can be partly fixed if Multicast DNS implementations detect when they aren't the first to bind to port 5353, and in that case they don't request "QU" responses ๐Ÿ™ one way to check whether another Multicast DNS implementation is already running is to try binding to port 5353 without using SO_REUSEPORT and/or SO_REUSEADDR, and if that fails, it means some other socket is already bound to this port ๐Ÿ”

15.2. Multipacket Known-Answer lists

when a Multicast DNS querier sends a query with too many Known Answers to fit in a single packet, it splits the Known-Answer list across two or more packets ๐Ÿ“ฆ Multicast DNS responders match the initial truncated query up with its continuation packets by looking at the source IP address in each packet ๐Ÿ”— since two independent Multicast DNS queriers running on the same machine will send packets with the same source IP address, from the outside they look like a single entity ๐Ÿ‘ป and if both queriers happened to send the same multipacket query at the same time, with different Known-Answer lists, they could each end up suppressing answers the other one needs ๐Ÿ˜ฑ

15.3. Efficiency

if different clients on a machine each had their own independent Multicast DNS implementation, they'd lose some efficiency benefits ๐Ÿ“‰ besides the pointless code duplication, memory use, and CPU load, the clients wouldn't get the perks of a shared system-wide cache, and they wouldn't be able to bundle separate queries into single packets to cut down on network traffic ๐Ÿšซ

15.4. Recommendation

because of all this, this document encourages implementers to design systems with a single Multicast DNS implementation that provides Multicast DNS services shared by all clients on that machine ๐Ÿ‘‘ it's kind of like how most operating systems today have a single TCP implementation that every client on the machine shares ๐ŸŒธ sometimes, due to engineering constraints, embedding a "user-level" Multicast DNS implementation in the client application software is the most practical option ๐Ÿ› ๏ธ and while that will usually work fine in practice, implementers should be aware of the issues outlined in this section โš ๏ธ

16. Multicast DNS Character Set ๐Ÿ”ค

historically, Unicast DNS has been used with a very restricted set of characters ๐Ÿ™ƒ honestly, conventional DNS is usually limited to just twenty-six letters, ten digits, and the hyphen character, not even allowing spaces or other punctuation ๐Ÿ˜‚ attempts to fix this for Unicast DNS have been badly held back by the perceived need to accommodate old buggy legacy DNS implementations ๐Ÿฆ– but in reality, the DNS specification itself doesn't impose any limits on what characters can be used in names, and good DNS implementations handle any arbitrary eight-bit data without trouble โœจ "Clarifications to the DNS Specification" [RFC2181] directly discusses the allowable character set in Section 11 ("Name syntax"), and explicitly states that DNS names may contain arbitrary eight-bit data ๐Ÿ’… however, the old rules for ARPANET host names back in the 1980s required host names to be just letters, digits, and hyphens [RFC1034], and since the main use of DNS is storing host address records, lots of people assumed the DNS protocol itself had the same limitation ๐Ÿ™„ it might be accurate to say there could be hypothetical bad implementations that don't handle eight-bit data correctly, but it wouldn't be accurate to say the protocol doesn't allow names containing eight-bit data ๐Ÿ’€

Multicast DNS is a brand-new protocol and doesn't (yet) have old buggy legacy implementations constraining its design choices ๐ŸŒŸ so it goes with the simple, obvious, elegant solution: all names in Multicast DNS MUST be encoded as precomposed UTF-8 [RFC3629] "Net-Unicode" [RFC5198] text ๐ŸŒˆ๐Ÿ‘‘

some people using 16-bit Unicode have started stuffing a "zero-width nonbreaking space" character (U+FEFF) at the start of each UTF-16 file, as a hint for whether the data is big-endian or little-endian, and calling it a "Byte Order Mark" (BOM) ๐Ÿค” since there's only one possible byte order for UTF-8 data, a BOM is neither necessary nor permitted ๐Ÿšซ Multicast DNS names MUST NOT contain a "Byte Order Mark" ๐Ÿ™…โ€โ™€๏ธ any occurrence of the Unicode character U+FEFF at the start or anywhere else in a Multicast DNS name MUST be interpreted as an actual, intended part of the name, representing (just like any other legal Unicode value) a literal instance of that character (in this case, a zero-width nonbreaking space character) ๐Ÿงพ

for names restricted to US-ASCII [RFC0020] letters, digits, and hyphens, the UTF-8 encoding is identical to the US-ASCII encoding, so it's totally compatible with existing host names ๐Ÿ’– for characters outside the US-ASCII range, UTF-8 encoding is used ๐Ÿซถ

Multicast DNS implementations MUST NOT use any other encodings apart from precomposed UTF-8 (US-ASCII being considered a compatible subset of UTF-8) ๐Ÿšท the reasons for picking UTF-8 instead of Punycode [RFC3492] are discussed further in Appendix F ๐Ÿ“–

the simple case-insensitivity rules in Unicast DNS [RFC1034] [RFC1035] also apply in Multicast DNS ๐Ÿ”  that means that when comparing names, the lowercase letters "a" to "z" (0x61 to 0x7A) match their uppercase equivalents "A" to "Z" (0x41 to 0x5A) ๐Ÿ’œ so if a querier sends a query for an address record with the name myprinter.local., then a responder with an address record named MyPrinter.local. should respond ๐Ÿ–จ๏ธ no other automatic equivalences should be assumed ๐Ÿ™… in particular, all UTF-8 multibyte characters (codes 0x80 and higher) are compared by simple binary comparison of the raw byte values ๐Ÿ”ข accented characters are not defined to be automatically equivalent to their unaccented counterparts ๐Ÿšซโœจ where automatic equivalences are wanted, this can be done with programmatically generated CNAME records ๐Ÿช„ for example, say a responder has an address record for an accented name Y, and a querier sends a query for a name X, where X is the same as Y with all the accents removed ๐Ÿฅฐ the responder may send a response containing two resource records: a CNAME record X CNAME Y, asserting that the requested name X (unaccented) is an alias for the true (accented) name Y, followed by the address record for Y ๐ŸŽ€

17. Multicast DNS Message Size โœจ

Okay bestie, so the 1987 DNS spec [RFC1035] limits DNS messages carried by UDP to no more than 512 bytes (not counting the IP or UDP headers) ๐Ÿ“œ. Back then, for UDP packets crossing the wide-area Internet, that made total sense. But for link-local multicast packets on today's networks? There's no reason to keep that restriction ๐Ÿ™…โ€โ™€๏ธ. And since these packets are link-local by definition, there are no Path MTU issues to worry about ๐Ÿงš.

Multicast DNS messages carried by UDP may be up to the IP MTU of the physical interface, less the space required for the IP header (20 bytes for IPv4; 40 bytes for IPv6) and the UDP header (8 bytes) ๐Ÿ’–.

Now, say you've got a single Multicast DNS resource record that's too big to fit in one MTU-sized multicast response packet ๐Ÿ˜ญ. In that case, a Multicast DNS responder SHOULD send the resource record alone, in a single IP datagram, using multiple IP fragments. But big resource records SHOULD be avoided, except in the very rare cases where they really are the appropriate solution to the problem at hand ๐Ÿ™ˆ. Implementers, listen up ๐Ÿ‘‚: lots of simple devices don't reassemble fragmented IP datagrams. So large resource records SHOULD NOT be used, except in specialized cases where the implementer knows that all receivers implement reassembly, or where the large resource record contains optional data that isn't essential for the client to operate correctly ๐Ÿ’….

A Multicast DNS packet that's larger than the interface MTU and gets sent using fragments MUST NOT contain more than one resource record ๐ŸŽ€.

Even when fragmentation is used, a Multicast DNS packet, including IP and UDP headers, MUST NOT exceed 9000 bytes ๐Ÿšซ.

Note that 9000 bytes is also the maximum payload size of an Ethernet "Jumbo" packet [Jumbo]. But in practice, Ethernet "Jumbo" packets aren't widely used, so it's advantageous to keep packets under 1500 bytes whenever possible ๐Ÿ“. Even on hosts that normally handle Ethernet "Jumbo" packets and IP fragment reassembly, it's becoming more common for these hosts to have power-saving modes. In those modes, the main CPU goes to sleep and hands packet reception off to a more limited processor in the network interface hardware, which may not support Ethernet "Jumbo" packets or IP fragment reassembly ๐Ÿ˜ด.


18. Multicast DNS Message Format ๐Ÿฆ‹

This section covers the specific rules for the allowable values of the header fields in a Multicast DNS message, plus other message format considerations ๐Ÿ’œ.

18.1. ID (Query Identifier)

Multicast DNS implementations SHOULD listen for unsolicited responses issued by hosts booting up (or waking up from sleep, or otherwise joining the network) ๐Ÿ‘€. These unsolicited responses might contain a useful answer to a question that the querier is currently waiting on, so Multicast DNS implementations SHOULD examine all received Multicast DNS response messages for useful answers, without regard to the contents of the ID field or the Question Section โœจ. In Multicast DNS, knowing which particular query message (if any) is responsible for eliciting a particular response message is way less interesting than knowing whether the response message actually contains useful information ๐Ÿง .

Multicast DNS implementations MAY cache data from any or all Multicast DNS response messages they receive, for possible future use, as long as normal TTL aging is performed on those cached resource records ๐ŸŒธ.

In multicast query messages, the Query Identifier SHOULD be set to zero on transmission ๐Ÿผ.

In multicast responses, including unsolicited multicast responses, the Query Identifier MUST be set to zero on transmission, and MUST be ignored on reception ๐Ÿ™…โ€โ™€๏ธ.

In legacy unicast response messages generated specifically in response to a particular (unicast or multicast) query, the Query Identifier MUST match the ID from the query message ๐Ÿ”.

18.2. QR (Query/Response) Bit

In query messages, the QR bit MUST be zero. In response messages, the QR bit MUST be one ๐Ÿ’….

18.3. OPCODE

In both multicast query and multicast response messages, the OPCODE MUST be zero on transmission. Only standard queries are currently supported over multicast, so that's the vibe ๐Ÿงš. Multicast DNS messages received with an OPCODE other than zero MUST be silently ignored ๐Ÿคซ.

18.4. AA (Authoritative Answer) Bit

In query messages, the Authoritative Answer bit MUST be zero on transmission, and MUST be ignored on reception ๐Ÿ™ƒ.

In response messages for Multicast domains, the Authoritative Answer bit MUST be set to one. Not setting this bit would imply there's some other place where "better" information may be found, and that's just not the energy we want ๐Ÿ‘‘. The bit MUST be ignored on reception ๐Ÿ’–.

18.5. TC (Truncated) Bit

In query messages, if the TC bit is set, it means that additional Known-Answer records may be following shortly. A responder SHOULD record this fact and wait for those additional Known-Answer records before deciding whether to respond ๐Ÿง. If the TC bit is clear, it means the querying host has no additional Known Answers ๐ŸŒˆ.

In multicast response messages, the TC bit MUST be zero on transmission, and MUST be ignored on reception ๐Ÿซถ.

In legacy unicast response messages, the TC bit has the same meaning as in conventional Unicast DNS. It means the response was too large to fit in a single packet, so the querier SHOULD reissue its query using TCP in order to receive the larger response ๐Ÿ“ฆ.

18.6. RD (Recursion Desired) Bit

In both multicast query and multicast response messages, the Recursion Desired bit SHOULD be zero on transmission, and MUST be ignored on reception ๐ŸŒท.

18.7. RA (Recursion Available) Bit

In both multicast query and multicast response messages, the Recursion Available bit MUST be zero on transmission, and MUST be ignored on reception ๐Ÿฆ„.

18.8. Z (Zero) Bit

In both query and response messages, the Zero bit MUST be zero on transmission, and MUST be ignored on reception ๐Ÿซง.

18.9. AD (Authentic Data) Bit

In both multicast query and multicast response messages, the Authentic Data bit [RFC2535] MUST be zero on transmission, and MUST be ignored on reception ๐Ÿ”.

18.10. CD (Checking Disabled) Bit

In both multicast query and multicast response messages, the Checking Disabled bit [RFC2535] MUST be zero on transmission, and MUST be ignored on reception ๐ŸŽ€.

18.11. RCODE (Response Code)

In both multicast query and multicast response messages, the Response Code MUST be zero on transmission. Multicast DNS messages received with a non-zero Response Code MUST be silently ignored ๐Ÿ™ˆ.

18.12. Repurposing of Top Bit of qclass in Question Section

In the Question Section of a Multicast DNS query, the top bit of the qclass field is used to indicate that unicast responses are preferred for this particular question. (See Section 5.4.) ๐Ÿฆ‹

18.13. Repurposing of Top Bit of rrclass in Resource Record Sections

In the Resource Record Sections of a Multicast DNS response, the top bit of the rrclass field is used to indicate that the record is a member of a unique RRSet, and that the entire RRSet has been sent together (in the same packet, or in consecutive packets if there are too many records to fit in a single packet). (See Section 10.2.) ๐Ÿ’œ

18.14. Name Compression

When generating Multicast DNS messages, implementations SHOULD use name compression wherever possible to compress the names of resource records. They do this by replacing some or all of the resource record name with a compact two-byte reference to an appearance of that data somewhere earlier in the message [RFC1035] ๐Ÿ—œ๏ธ.

This applies not only to Multicast DNS responses, but also to queries. When a query contains more than one question, successive questions in the same message often contain similar names, so name compression SHOULD be used to save bytes โœ‚๏ธ. Queries can also contain Known Answers in the Answer Section, or probe tiebreaking data in the Authority Section, and these names SHOULD similarly be compressed for network efficiency ๐Ÿš€.

In addition to compressing the names of resource records, names that appear within the rdata of the following rrtypes SHOULD also be compressed in all Multicast DNS messages:

NS, CNAME, PTR, DNAME, SOA, MX, AFSDB, RT, KX, RP, PX, SRV, NSEC

Until a future IETF Standards Action [RFC5226] specifies that names in the rdata of other types should be compressed, names that appear within the rdata of any type not listed above MUST NOT be compressed ๐Ÿšซ.

Implementations receiving Multicast DNS messages MUST correctly decode compressed names appearing in the Question Section, and compressed names of resource records appearing in other sections ๐Ÿงฉ.

In addition, implementations MUST correctly decode compressed names appearing within the rdata of the rrtypes listed above. Where possible, implementations SHOULD also correctly decode compressed names appearing within the rdata of other rrtypes known to the implementers at the time of implementation. That's forward-thinking planning ๐Ÿ”ฎ, and it helps facilitate the deployment of future implementations that may have reason to compress those rrtypes. It's possible that no future IETF Standards Action [RFC5226] will ever be created that mandates or permits compression of rdata in new types. Still, having implementations designed to decompress all known types helps keep future options open ๐ŸŒˆ.

One specific difference between Unicast DNS and Multicast DNS is that Unicast DNS does not allow name compression for the target host in an SRV record. That's because Unicast DNS implementations from before the first SRV specification in 1996 [RFC2052] may not decode these compressed records properly ๐Ÿ™ƒ. Since all Multicast DNS implementations were created after 1996, all Multicast DNS implementations are REQUIRED to decode compressed SRV records correctly ๐Ÿ‘‘.

In legacy unicast responses generated to answer legacy queries, name compression MUST NOT be performed on SRV records ๐Ÿซถ.

19. Summary of Differences between Multicast DNS and Unicast DNS โœจ

okay so mDNS is basically giving Unicast DNS vibes ๐Ÿ’… it shares as much as it can with the stuff you already know: the familiar APIs, naming syntax, resource record types, all of it. but obviously it's a different beast, because it uses multicast and it runs in a community of cooperating peers instead of one strict chain of formal delegations from the root ๐ŸŒธ here's the tea on how they differ:

Multicast DNS...

  • uses multicast
  • uses UDP port 5353 instead of port 53
  • operates in well-defined parts of the DNS namespace
  • has no SOA (Start of Authority) records
  • uses UTF-8, and only UTF-8, to encode resource record names
  • allows names up to 255 bytes plus a terminating zero byte
  • allows name compression in rdata for SRV and other record types
  • allows larger UDP packets
  • allows more than one question in a query message
  • defines consistent results for qtype "ANY" and qclass "ANY" queries
  • uses the Answer Section of a query to list Known Answers
  • uses the TC bit in a query to indicate additional Known Answers
  • uses the Authority Section of a query for probe tiebreaking
  • ignores the Query ID field (except for generating legacy responses)
  • doesn't require the question to be repeated in the response message
  • uses unsolicited responses to announce new records
  • uses NSEC records to signal nonexistence of records
  • defines a unicast-response bit in the rrclass of query questions
  • defines a cache-flush bit in the rrclass of response records
  • uses DNS RR TTL 0 to indicate that a record has been deleted
  • recommends AAAA records in the additional section when responding to rrtype "A" queries, and vice versa
  • monitors queries to perform Duplicate Question Suppression
  • monitors responses to perform Duplicate Answer Suppression...
  • ... and Ongoing Conflict Detection
  • ... and Opportunistic Caching

20. IPv6 Considerations ๐Ÿงš

okay so an IPv4-only host and an IPv6-only host basically act like "ships that pass in the night" ๐Ÿšข even if they're chilling on the same Ethernet, neither one has any idea what the other is up to. so each physical link may have two unrelated ".local." zones, one for IPv4 and one for IPv6 ๐ŸŽ€ and honestly, a group of IPv4-only hosts and a group of IPv6-only hosts on the same Ethernet act like they're on two totally separate Ethernet segments, so it makes total sense that they use the ".local." zone exactly the way they would if they really were on two separate segments ๐Ÿซถ

a dual-stack (v4/v6) host is the main character here โœจ it can participate in both ".local." zones, and it should register its name(s) and do its lookups using both IPv4 and IPv6. that's how it can reach, and be reached by, both IPv4-only and IPv6-only hosts ๐Ÿฆ‹ it's giving multihomed host energy: one connection to the logical "IPv4 Ethernet segment", and another to the logical "IPv6 Ethernet segment". and when this host generates NSEC records, if it uses the same host name for its IPv4 addresses and its IPv6 addresses on that network interface, its NSEC records should indicate that the host name has both A and AAAA records ๐Ÿ’œ


21. Security Considerations ๐Ÿ”ฅ

okay this section is serious, bestie, so pay attention ๐Ÿ˜ญ the algorithm for detecting and resolving name conflicts is, by its very nature, one that assumes cooperating participants. its whole purpose is to help a group of hosts end up with a mutually disjoint set of host names and other DNS resource record names, even though there's no central authority to coordinate things or mediate disputes. and if there's no higher authority to settle a fight, the only option left is for the participants to actually work together and reach a resolution ๐Ÿค

in an environment where the participants are mutually antagonistic and unwilling to cooperate, other mechanisms are appropriate, like manually configured DNS ๐Ÿ’€

in an environment where there's a group of cooperating participants, but clients can't be sure there are no antagonistic hosts on the same physical link, the cooperating participants need to use IPsec signatures and/or DNSSEC [RFC4033] signatures. that way they can tell Multicast DNS messages from trusted participants (which they process as usual) apart from Multicast DNS messages from untrusted participants (which they silently discard) ๐Ÿ”

if DNS queries for global DNS names are sent to the mDNS multicast address (during network outages that disrupt communication with the greater Internet), it is especially important to use DNSSEC ๐Ÿšจ why? because the user may think they're talking to some authentic host, when they're actually talking to some local host that's just masquerading as that name. this is less critical for names ending with ".local.", since the user should be aware that those names only have local significance and no global authority is implied ๐Ÿ™ˆ

most computer users skip the trailing dot at the end of a fully qualified domain name, which makes it a relative domain name (e.g., "www.example.com"). during a network outage, attempts to positively resolve the name as entered will fail, which triggers application of the search list, including ".local.", if present. a malicious host could masquerade as "www.example.com." by answering the resulting Multicast DNS query for "www.example.com.local.". this is the sneaky part ๐Ÿ˜ญ

to avoid this, a host MUST NOT append the search suffix ".local.", if present, to any relative (partially qualified) host name containing two or more labels. appending ".local." to single-label relative host names is acceptable, since the user should have no expectation that a single-label host name will resolve as is ๐ŸŒˆ however, users who have both "example.com" and "local" in their search lists should be aware that if they type "www" into their web browser, it may not be immediately clear whether the page that shows up is "www.example.com" or "www.local". so yeah, keep an eye on that ๐Ÿ‘€

Multicast DNS uses UDP port 5353. on operating systems where only privileged processes are allowed to use ports below 1024, no such privilege is required to use port 5353 โœจ


22. IANA Considerations ๐ŸŽ€

IANA has allocated the UDP port 5353 for the Multicast DNS protocol described in this document [SN] ๐ŸŒธ

IANA has allocated the IPv4 link-local multicast address 224.0.0.251 for the use described in this document [MC4] ๐Ÿ’–

IANA has allocated the IPv6 multicast address set FF0X::FB (where "X" indicates any hexadecimal digit from '1' to 'F') for the use described in this document [MC6]. only address FF02::FB (link-local scope) is currently in use by deployed software, but it's possible that in the future implementers may experiment with Multicast DNS using larger-scoped addresses, such as FF05::FB (site-local scope) [RFC4291] ๐Ÿฆ‹

IANA has implemented the following DNS records:

MDNS.MCAST.NET.            IN  A    224.0.0.251
251.0.0.224.IN-ADDR.ARPA.  IN  PTR  MDNS.MCAST.NET.

entries for the AAAA and corresponding PTR records have not been made, because there isn't yet an RFC providing direction for managing the IP6.ARPA domain relating to the IPv6 multicast address space ๐Ÿ™ˆ

the reuse of the top bit of the rrclass field in the Question and Resource Record Sections means that Multicast DNS can only carry DNS records with classes in the range 0-32767. classes in the range 32768 to 65535 are incompatible with Multicast DNS ๐Ÿ˜ญ IANA has noted this fact, and if IANA receives a request to allocate a DNS class value above 32767, IANA will make sure the requester is aware of this implication before proceeding. this doesn't mean allocations of DNS class values above 32767 should be denied, only that they should not be allowed until the requester has indicated that they're aware of how this allocation will interact with Multicast DNS ๐Ÿซถ but honestly? only three DNS classes have been assigned by IANA so far (1, 3, and 4), and only one (1, "Internet") is actually in widespread use, so this issue is likely to stay a purely theoretical one ๐Ÿ’…

IANA has recorded the list of domains below as being Special-Use Domain Names [RFC6761] ๐Ÿ‘‘

.local.
.254.169.in-addr.arpa.
.8.e.f.ip6.arpa.
.9.e.f.ip6.arpa.
.a.e.f.ip6.arpa.
.b.e.f.ip6.arpa.

22.1. Domain Name Reservation Considerations ๐ŸŒธ

okay so the six domains listed above ๐Ÿ’…, plus anything living under them (like MyPrinter.local., 34.12.254.169.in-addr.arpa., and Ink-Jet._pdl-datastream._tcp.local.), are special [RFC6761] in a few ways. bestie, read these carefully ๐Ÿซถ

  1. Users can use these names just like any other DNS name โœจ. They can type them anywhere they'd normally type a conventional DNS name, a dotted decimal IPv4 address, or a literal IPv6 address.

Here's the thing though ๐Ÿ˜ญ. There's no central authority in charge of handing out dot-local names, and every device on the local network is equally allowed to claim any dot-local name. So users SHOULD be aware of this and SHOULD exercise appropriate caution ๐Ÿ™ˆ. On an untrusted or unfamiliar network, users SHOULD be aware that typing something like www.local may not actually take them to the website they meant. It could easily land them on a different page, or even a fake copy of the real site, built to trick them into handing over confidential info ๐Ÿ’€. As always with networking, end-to-end cryptographic security is a useful tool ๐Ÿ”. For example, when you connect with ssh, the ssh host key verification process will tell the user if the identity of the entity they're talking to has changed since the last time they connected to that name. iconic behaviour ๐Ÿ‘‘.

  1. Application software can use these names the same way it uses other similar DNS names, and it is not required to recognize them and treat them specially ๐Ÿฆ‹. Because dot-local names are pretty easy to spoof ๐Ÿ˜ค, end-to-end cryptographic security stays important when you're communicating across a local network, just like it is when you're communicating across the global Internet ๐ŸŒ.
  2. Name resolution APIs and libraries SHOULD recognize these names as special ๐Ÿ’–, and they SHOULD NOT send queries for these names to their configured (unicast) caching DNS server(s). Why? To avoid piling unnecessary load onto the root name servers and other name servers ๐Ÿ™ƒ. Those servers would be getting queries they don't have useful non-negative answers for, and they never ever will have useful non-negative answers for them ๐Ÿ˜ญ. Not it.
  3. Caching DNS servers SHOULD recognize these names as special too โœจ. They SHOULD NOT try to look up NS records for them, and they SHOULD NOT otherwise query authoritative DNS servers in an attempt to resolve these names. Instead, caching DNS servers SHOULD generate immediate NXDOMAIN responses for all such queries they may receive, including the ones from misbehaving name resolver libraries ๐Ÿงš. This is again to dodge unnecessary load on the root name servers and other name servers ๐Ÿซ .
  4. Authoritative DNS servers SHOULD NOT, by default, be configurable to answer queries for these names ๐Ÿ™…โ€โ™€๏ธ. Like caching DNS servers, they SHOULD generate immediate NXDOMAIN responses for all such queries they may receive. DNS server software MAY provide a configuration option to override this default, for testing purposes or other specialized uses ๐Ÿงช. so there's a little escape hatch, but it's not the default vibe.
  5. DNS server operators SHOULD NOT attempt to configure authoritative DNS servers to act as authoritative for any of these names ๐Ÿšซ. Doing that may not, in many cases, give the result you expected ๐Ÿ’€. Since name resolver libraries and caching DNS servers SHOULD NOT send queries for those names (see items 3 and 4 above), those queries SHOULD be suppressed before they even reach the authoritative DNS server in question. So it won't even get a chance to answer them ๐Ÿฅฒ. Main character moment, but the wrong kind.
  6. DNS Registrars MUST NOT allow any of these names to be registered in the normal way to any person or entity ๐Ÿ›‘. These names are reserved protocol identifiers with special meaning, so they fall outside the set of names registrars are allowed to hand out. Trying to allocate one of these names as if it were a normal domain name will probably not work as desired, for the reasons in items 3, 4, and 6 above ๐Ÿ™ˆ.

23. Acknowledgments โœจ

The concepts in this document have been explored, developed, and implemented with help from Ran Atkinson, Richard Brown, Freek Dijkstra, Erik Guttman, Kyle McKay, Pasi Sarolahti, Pekka Savola, Robby Simpson, Mark Townsley, Paul Vixie, Bill Woodcock, and others ๐Ÿซถ. Special thanks go to Bob Bradley, Josh Graessley, Scott Herscher, Rory McGuire, Roger Pantos, and Kiren Sekar for their significant contributions ๐Ÿ‘‘. Special thanks also to Kerry Lynn for converting the document to xml2rfc form in May 2010, and to Area Director Ralph Droms for shepherding the document through its final steps ๐ŸŽ€. the people who made this possible, literally ๐Ÿ˜ญ๐ŸŒˆ.


24. References ๐Ÿ“š

24.1. Normative References

24.2. Informative References

  • [B4W] "Bonjour for Windows", <http://en.wikipedia.org/wiki/Bonjour_(software)>.
  • [BJ] Apple Bonjour Open Source Software, <http://developer.apple.com/bonjour/>.
  • [IEEE.802.3] "Information technology - Telecommunications and information exchange between systems - Local and metropolitan area networks - Specific requirements - Part 3: Carrier Sense Multiple Access with Collision Detection (CMSA/CD) Access Method and Physical Layer Specifications", IEEE Std 802.3-2008, December 2008, <http://standards.ieee.org/getieee802/802.3.html>.
  • [IEEE.802.11] "Information technology - Telecommunications and information exchange between systems - Local and metropolitan area networks - Specific requirements - Part 11: Wireless LAN Medium Access Control (MAC) and Physical Layer (PHY) Specifications", IEEE Std 802.11-2007, June 2007, <http://standards.ieee.org/getieee802/802.11.html>.
  • [Jumbo] "Ethernet Jumbo Frames", November 2009, <http://www.ethernetalliance.org/library/whitepaper/ethernet-jumbo-frames/>.
  • [NIAS] Cheshire, S. "Discovering Named Instances of Abstract Services using DNS", Work in Progress, July 2001.
  • [NSD] "NsdManager | Android Developer", June 2012, <http://developer.android.com/reference/android/net/nsd/NsdManager.html>.
  • [RFC2052] Gulbrandsen, A. and P. Vixie, "A DNS RR for specifying the location of services (DNS SRV)", RFC 2052, October 1996.
  • [RFC2132] Alexander, S. and R. Droms, "DHCP Options and BOOTP Vendor Extensions", RFC 2132, March 1997.
  • [RFC2136] Vixie, P., Ed., Thomson, S., Rekhter, Y., and J. Bound, "Dynamic Updates in the Domain Name System (DNS UPDATE)", RFC 2136, April 1997.
  • [RFC2181] Elz, R. and R. Bush, "Clarifications to the DNS Specification", RFC 2181, July 1997.
  • [RFC2535] Eastlake 3rd, D., "Domain Name System Security Extensions", RFC 2535, March 1999.
  • [RFC2671] Vixie, P., "Extension Mechanisms for DNS (EDNS0)", RFC 2671, August 1999.
  • [RFC2845] Vixie, P., Gudmundsson, O., Eastlake 3rd, D., and B. Wellington, "Secret Key Transaction Authentication for DNS (TSIG)", RFC 2845, May 2000.
  • [RFC2930] Eastlake 3rd, D., "Secret Key Establishment for DNS (TKEY RR)", RFC 2930, September 2000.
  • [RFC2931] Eastlake 3rd, D., "DNS Request and Transaction Signatures ( SIG(0)s )", RFC 2931, September 2000.
  • [RFC3007] Wellington, B., "Secure Domain Name System (DNS) Dynamic Update", RFC 3007, November 2000.
  • [RFC3492] Costello, A., "Punycode: A Bootstring encoding of Unicode for Internationalized Domain Names in Applications (IDNA)", RFC 3492, March 2003.
  • [RFC3927] Cheshire, S., Aboba, B., and E. Guttman, "Dynamic Configuration of IPv4 Link-Local Addresses", RFC 3927, May 2005.
  • [RFC4033] Arends, R., Austein, R., Larson, M., Massey, D., and S. Rose, "DNS Security Introduction and Requirements", RFC 4033, March 2005.
  • [RFC4291] Hinden, R. and S. Deering, "IP Version 6 Addressing Architecture", RFC 4291, February 2006.
  • [RFC4795] Aboba, B., Thaler, D., and L. Esibov, "Link-local Multicast Name Resolution (LLMNR)", RFC 4795, January 2007.
  • [RFC4861] Narten, T., Nordmark, E., Simpson, W., and H. Soliman, "Neighbor Discovery for IP version 6 (IPv6)", RFC 4861, September 2007.
  • [RFC4862] Thomson, S., Narten, T., and T. Jinmei, "IPv6 Stateless Address Autoconfiguration", RFC 4862, September 2007.
  • [RFC5226] Narten, T. and H. Alvestrand, "Guidelines for Writing an IANA Considerations Section in RFCs", BCP 26, RFC 5226, May 2008.
  • [RFC5890] Klensin, J., "Internationalized Domain Names for Applications (IDNA): Definitions and Document Framework", RFC 5890, August 2010.
  • [RFC6281] Cheshire, S., Zhu, Z., Wakikawa, R., and L. Zhang, "Understanding Apple's Back to My Mac (BTMM) Service", RFC 6281, June 2011.
  • [RFC6760] Cheshire, S. and M. Krochmal, "Requirements for a Protocol to Replace the AppleTalk Name Binding Protocol (NBP)", RFC 6760, February 2013.
  • [RFC6763] Cheshire, S. and M. Krochmal, "DNS-Based Service Discovery", RFC 6763, February 2013.
  • [Zeroconf] Cheshire, S. and D. Steinberg, "Zero Configuration Networking: The Definitive Guide", O'Reilly Media, Inc., ISBN 0-596-10100-7, December 2005.

Appendix A. Design Rationale for Choice of UDP Port Number โœจ

okay so the big debate was whether Multicast DNS should just use UDP port 53, the standard Unicast DNS port ๐ŸŽ€ people argued both sides, and it got messy lol. Here are some of the arguments. In the end, the case for a different port had more arguments and way more convincing ones, so that's the one that won ๐Ÿ‘‘. Port 5353 was picked because it looks like 53 ๐Ÿฆ‹

Team port 53 had these points ๐Ÿ’…

  • This is "just DNS", so it should be the same port. ๐Ÿ™„
  • There is less work to be done updating old resolver libraries to do simple Multicast DNS queries. Only the destination address need be changed. In some cases, this can be achieved without any code changes, just by adding the address 224.0.0.251 to a configuration file.

Team port 5353 had these points, and honestly they're stronger ๐Ÿ”ฅ

  • This is not "just DNS". This is a DNS-like protocol, but different.
  • Changing resolver library code to use a different port number is not hard. In some cases, this can be achieved without any code changes, just by adding the address 224.0.0.251:5353 to a configuration file.
  • Using the same port number makes it hard to run a Multicast DNS responder and a conventional Unicast DNS server on the same machine. If a conventional Unicast DNS server wishes to implement Multicast DNS as well, it can still do that, by opening two sockets. Having two different port numbers allows this flexibility. ๐Ÿงš
  • Some VPN software hijacks all outgoing traffic to port 53 and redirects it to a special DNS server set up to serve those VPN clients while they are connected to the corporate network. It is questionable whether this is the right thing to do, but it is common, and redirecting link-local multicast DNS packets to a remote server rarely produces any useful results. It does mean, for example, that a user of such VPN software becomes unable to access their local network printer sitting on their desk right next to their computer. ๐Ÿ˜ญ Using a different UDP port helps avoid this particular problem.
  • On many operating systems, unprivileged software may not send or receive packets on low-numbered ports. This means that any software sending or receiving Multicast DNS packets on port 53 would have to run as "root", which is an undesirable security risk. Using a higher-numbered UDP port avoids this restriction. ๐Ÿ’€

Appendix B. Design Rationale for Not Using Hashed Multicast Addresses ๐ŸŒˆ

some discovery protocols use a whole range of multicast addresses and figure out which one to use by hashing the name being searched for ๐Ÿงš queries go out by multicast to whatever address the hash spits out, and responses come back by unicast. this approach gets advocated a lot, especially in IPv6 where multicast addresses are super plentiful. for example, IPv6 Neighbor Discovery [RFC4861] sends Neighbor Solicitation messages to the "solicited-node multicast address", which is computed as a function of the solicited IPv6 address.

but there are some real downsides to doing this in a service discovery protocol, so let's go ๐Ÿซถ

  • When a host has a large number of records with different names, the host may have to join a large number of multicast groups. Each time a host joins or leaves a multicast group, this results in Internet Group Management Protocol (IGMP) or Multicast Listener Discovery (MLD) traffic on the network announcing this fact. Joining a large number of multicast groups can place undue burden on the Ethernet hardware, which typically supports a limited number of multicast addresses efficiently. When this number is exceeded, the Ethernet hardware may have to resort to receiving all multicasts and passing them up to the host networking code for filtering in software, thereby defeating much of the point of using a multicast address range in the first place. Finally, many IPv6 stacks have a fixed limit IPV6_MAX_MEMBERSHIPS, and the code simply fails with an error if a client attempts to exceed this limit. Common values for IPV6_MAX_MEMBERSHIPS are 20 or 31. ๐Ÿ™ˆ
  • Multiple questions cannot be placed in one packet if they don't all hash to the same multicast address. ๐Ÿ’…
  • Duplicate Question Suppression doesn't work if queriers are not seeing each other's queries. ๐Ÿ’”
  • Duplicate Answer Suppression doesn't work if responders are not seeing each other's responses. ๐Ÿ’”
  • Opportunistic Caching doesn't work. ๐Ÿ’”
  • Ongoing Conflict Detection doesn't work. ๐Ÿ’”

Appendix C. Design Rationale for Maximum Multicast DNS Name Length ๐Ÿ“

Multicast DNS names can be up to 255 bytes long (in the on-the-wire message format), not counting the terminating zero byte at the end. but why 255 and not 256? let's dig in ๐Ÿ”

"Domain Names - Implementation and Specification" [RFC1035] says:

   Various objects and parameters in the DNS have size limits.  They
   are listed below.  Some could be easily changed, others are more
   fundamental.

   labels          63 octets or less

   names           255 octets or less

   ...

   the total length of a domain name (i.e., label octets and label
   length octets) is restricted to 255 octets or less.

this text doesn't say whether the 255-byte limit includes the terminating zero at the end of every name. but several factors lead us to conclude that the 255-byte limit does not include the terminating zero:

  • It is common in software engineering to have size limits that are a power of two, or a multiple of a power of two, for efficiency. For example, an integer on a modern processor is typically 2, 4, or 8 bytes, not 3 or 5 bytes. The number 255 is not a power of two, nor is it to most people a particularly noteworthy number. It is noteworthy to computer scientists for only one reason -- because it is exactly one less than a power of two. When a size limit is exactly one less than a power of two, that suggests strongly that the one extra byte is being reserved for some specific reason -- in this case reserved, perhaps, to leave room for a terminating zero at the end.
  • In the case of DNS label lengths, the stated limit is 63 bytes. As with the total name length, this limit is exactly one less than a power of two. This label length limit also excludes the label length byte at the start of every label. Including that extra byte, a 63-byte label takes 64 bytes of space in memory or in a DNS message.
  • It is common in software engineering for the semantic "length" of an object to be one less than the number of bytes it takes to store that object. For example, in C, strlen("foo") is 3, but sizeof("foo") (which includes the terminating zero byte at the end) is 4.
  • The text describing the total length of a domain name mentions explicitly that label length and data octets are included, but does not mention the terminating zero at the end. The zero byte at the end of a domain name is not a label length. Indeed, the value zero is chosen as the terminating marker precisely because it is not a legal length byte value -- DNS prohibits empty labels. For example, a name like "bad..name." is not a valid domain name because it contains a zero-length label in the middle, which cannot be expressed in a DNS message, because software parsing the message would misinterpret a zero label-length byte as being a zero "end of name" marker instead.

Finally, "Clarifications to the DNS Specification" [RFC2181] offers additional confirmation that, in the context of DNS specifications, the stated "length" of a domain name does not include the terminating zero byte at the end. That document refers to the root name, which is typically written as "." and is represented in a DNS message by a single lone zero byte (i.e., zero bytes of data plus a terminating zero), as the "zero length full name":

   The zero length full name is defined as representing the root of
   the DNS tree, and is typically written and displayed as ".".

this wording supports the interpretation that, in a DNS context, when talking about lengths of names, the terminating zero byte at the end is not counted. If the root name (".") is considered to be zero length, then to be consistent, the length (for example) of "org" has to be 4 and the length of "ietf.org" has to be 9, as shown below:

                                              ------
                                             | 0x00 |   length = 0
                                              ------

                         ------------------   ------
                        | 0x03 | o | r | g | | 0x00 |   length = 4
                         ------------------   ------

  -----------------------------------------   ------
 | 0x04 | i | e | t | f | 0x03 | o | r | g | | 0x00 |   length = 9
  -----------------------------------------   ------

This means that the maximum length of a domain name, as represented in a Multicast DNS message, up to but not including the final terminating zero, must not exceed 255 bytes.

However, many Unicast DNS implementers have read these RFCs differently, and argue that the 255-byte limit does include the terminating zero, and that the "Clarifications to the DNS Specification" [RFC2181] statement that "." is the "zero length full name" was simply a mistake. ๐Ÿค”

Hence, implementers should be aware that other Unicast DNS implementations may limit the maximum domain name to 254 bytes plus a terminating zero, depending on how that implementer interpreted the DNS specifications. so keep that in mind if your code talks to them ๐Ÿซ 

Compliant Multicast DNS implementations MUST support names up to 255 bytes plus a terminating zero, i.e., 256 bytes total. โœจ

Appendix D. Benefits of Multicast Responses โœจ

Some people have argued that sending responses via multicast is inefficient on the network. ๐Ÿ™„ But honestly? Multicast responses can actually lower overall multicast traffic for a bunch of reasons, and they bring some other perks too ๐Ÿ’–

  • Opportunistic Caching. One multicast response can update the caches on all machines on the network. ๐Ÿง  If another machine later wants to issue the same query, and it already has the answer in its cache, it may not even need to transmit that multicast query on the network at all. ๐Ÿฆ‹
  • Duplicate Query Suppression. When more than one machine has the same ongoing long-lived query running, every machine doesn't have to send its own independent query. ๐Ÿ™…โ€โ™€๏ธ When one machine transmits a query, all the other hosts see the answers, so they can suppress their own queries. โœจ
  • Passive Observation Of Failures (POOF). When a host sees a multicast query but doesn't see the matching multicast response, it can use that info to promptly delete stale data from its cache. ๐Ÿ’€ To get the same level of user-interface quality and responsiveness without multicast responses, you'd need lower cache lifetimes and more frequent network polling, which means a higher packet rate. ๐Ÿ“ˆ
  • Passive Conflict Detection. Just because a name was previously verified to be unique doesn't guarantee it'll stay that way forever. ๐Ÿฅบ By letting all Multicast DNS responders constantly monitor their peers' responses, conflicts caused by network topology changes can be spotted and resolved fast. ๐Ÿ”ฅ Without multicast responses, some other conflict detection mechanism would be needed, adding its own extra burden on the network. ๐Ÿ˜ฉ
  • Use on devices with constrained memory resources. When delayed responses are used to reduce network collisions, responders need to keep a list of who each answer should go to. ๐Ÿ“ Multicast responses give responders with limited storage, who can't hold an arbitrarily long list of response addresses, the option to fail over to a single multicast response instead of multiple unicast responses, when that makes sense. ๐ŸŒธ
  • Overlayed Subnets. With overlayed subnets, multicast responses let a receiver know for sure that a response came from the local link, even when its source address might suggest otherwise. ๐Ÿ•ต๏ธโ€โ™€๏ธ
  • Robustness in the face of misconfiguration. Link-local multicast is basically unbreakable ๐Ÿ‘‘ Even if every device has a wrong IP address, subnet mask, default gateway, and DNS server address, packets sent to a link-local multicast destination address still reach all peers on the local link. ๐ŸŽ€ This is super helpful when diagnosing and fixing network problems, because it gives you a direct channel between client and server that works without relying on ARP, IP routing tables, etc. ๐Ÿ› ๏ธ Figuring out what IP address a device has (or thinks it has) is often a very valuable first step in working out why it can't communicate on the local network. ๐Ÿ”

Appendix E. Design Rationale for Encoding Negative Responses ๐Ÿ™ˆ

Other ways of asserting that something doesn't exist were considered, like using an NXDOMAIN response, or emitting a resource record with zero-length rdata. ๐Ÿค”

Using an NXDOMAIN response doesn't work well with Multicast DNS. ๐Ÿšซ A Unicast DNS NXDOMAIN response applies to the entire message, but for efficiency Multicast DNS allows (and encourages) multiple responses in a single message. ๐Ÿ“ฆ If the error code in the header were NXDOMAIN, it wouldn't be clear which name(s) that error code applied to. ๐Ÿ˜ตโ€๐Ÿ’ซ

Asserting nonexistence by emitting a resource record with zero-length rdata would mean there's no way to tell apart a record that doesn't exist from a record that does exist with zero-length rdata. ๐Ÿฅด Think about it like this: most file systems today allow empty files, so a file that exists with zero bytes of data isn't treated the same as a filename that doesn't exist. ๐Ÿ“

The benefit of asserting nonexistence through NSEC records instead of NXDOMAIN responses is that NSEC records can be added to the Additional Section of a DNS response to offer extra information beyond what the querier explicitly asked for. ๐Ÿงš For example, in response to an SRV query, a responder should include A record(s) giving its IPv4 addresses in the Additional Section, plus an NSEC record indicating which other types it does or doesn't have for this name. ๐Ÿ’… If the responder is running on a host that doesn't support IPv6 (or does support IPv6 but currently has no IPv6 address on that interface), this NSEC record in the Additional Section will indicate that there are no AAAA records. ๐Ÿ™…โ€โ™€๏ธ Basically the responder is saying, "Here's my SRV record, and here are my IPv4 addresses, and no, I don't have any IPv6 addresses, so don't waste your time asking" ๐Ÿ’โ€โ™€๏ธ Without this info in the Additional Section, the querier would need an extra round-trip, with another query, to figure out that the target host has no AAAA records. ๐Ÿข (Arguably Unicast DNS could also benefit from this ability to express nonexistence in the Additional Section, but that's outside the scope of this document. ๐Ÿ“š)


Appendix F. Use of UTF-8 ๐Ÿ’œ

After many years of debate, the Unicast DNS community settled on an extremely baroque encoding called "Punycode" [RFC3492]. ๐Ÿ˜ญ This was because of the perceived need to accommodate certain DNS implementations that apparently couldn't handle any character that isn't a letter, digit, or hyphen (and apparently never would be updated to fix this limitation). ๐Ÿ™ƒ Punycode is a remarkably ingenious encoding solution, but it's complicated, hard to understand, and hard to implement, using sophisticated techniques including insertion unsort coding, generalized variable-length integers, and bias adaptation. ๐Ÿงฉ The resulting encoding is remarkably compact given the constraints, but it's still not as good as simple, straightforward UTF-8. ๐Ÿซ 

It's also hard to predict whether a given input string will encode to a Punycode string that fits within DNS's 63-byte limit, except by simply trying the encoding and seeing whether it fits. ๐Ÿ˜ฉ The encoded size depends not only on the input characters, but on the order they appear in. So the same set of characters may or may not encode to a legal Punycode string that fits within DNS's 63-byte limit, depending on the order they show up in. ๐ŸŒ€ This is extremely hard to present in a user interface that has to explain to users why one name is allowed, but another name with the exact same characters isn't. ๐Ÿคฏ

Neither Punycode nor any other of the "ASCII-Compatible Encodings" [RFC5890] proposed for Unicast DNS may be used in Multicast DNS messages. ๐Ÿšท Any text being represented internally in some other representation must be converted to canonical precomposed UTF-8 before being placed in any Multicast DNS message. ๐ŸŒˆ


Appendix G. Private DNS Namespaces ๐Ÿ 

The special treatment of names ending in ".local." has been implemented in Macintosh computers since the days of Mac OS 9, and it continues today in Mac OS X and iOS. ๐ŸŽ There are also implementations for Microsoft Windows [B4W], Linux, and other platforms. ๐Ÿง

Some network operators setting up private internal networks ("intranets") have used unregistered top-level domains, and some may have used the ".local" top-level domain. ๐Ÿ˜ฌ Using ".local" as a private top-level domain conflicts with Multicast DNS and may cause problems for users. โš ๏ธ Clients can be configured to send both Multicast and Unicast DNS queries in parallel for these names. That does let names be looked up both ways, but it means additional network traffic and additional delays in name resolution. ๐ŸŒ It can also create user confusion when it isn't clear whether a given result came via link-local multicast from a peer on the same link, or from the configured unicast name server. ๐Ÿคทโ€โ™€๏ธ

Because of all this, we recommend against using ".local" as a private Unicast DNS top-level domain. ๐Ÿšซ We don't recommend using unregistered top-level domains at all. But if network operators decide to do it anyway, the following top-level domains have been used on private internal networks without the problems caused by trying to reuse ".local." for this purpose: ๐Ÿซถ
   .intranet.
   .internal.
   .private.
   .corp.
   .home.
   .lan.

Appendix H. Deployment History โœจ

okay so this is the storytime part bestie ๐Ÿฆ‹ and it's giving origin story. In July 1997, Stuart Cheshire emailed the net-thinkers@thumper.vmeng.com mailing list and first floated the idea of running the AppleTalk Name Binding Protocol [RFC6760] over IP. ๐Ÿ’ก That led to IETF discussions, and the IETF Zeroconf working group got chartered in September 1999. After a bunch of working group chats and informal IETF convos, several Internet-Drafts got written that were loosely related to DNS and multicast, but none of them actually tackled the service discovery part of NBP. ๐Ÿ™ˆ

Then in April 2000, Stuart registered IPv4 multicast address 224.0.0.251 with IANA [MC4] and started coding to test the idea of doing NBP-like service discovery with Multicast DNS. ๐ŸŽ€ That work got written up as a group of three Internet-Drafts:

  • "Requirements for a Protocol to Replace the AppleTalk Name Binding Protocol (NBP)" [RFC6760] is the overview ๐Ÿ“–. It explains AppleTalk NBP, because lots of people in the IETF had barely used AppleTalk, and the confusion about what NBP actually did was making it hard to figure out what an IP replacement would need. ๐Ÿ˜ญ
  • "Discovering Named Instances of Abstract Services using DNS" [NIAS] proposed a way to do NBP-like service discovery using DNS-compatible names and record types. ๐ŸŒˆ
  • "Multicast DNS" (this document) specifies how to carry those DNS-compatible queries and responses over IP multicast, for zero-configuration environments with no conventional Unicast DNS server. ๐Ÿงš

In 2001, an update to Mac OS 9 added resolver library support for host name lookup using Multicast DNS. ๐Ÿ’… If you typed a name like "MyPrinter.local." into any networking software that used the standard Mac OS 9 name lookup APIs, those APIs would spot the dot-local name and query for it by sending simple one-shot Multicast DNS queries to 224.0.0.251:5353. ๐Ÿซถ So you could type "MyPrinter.local." into your web browser to check a printer's status and configuration page, or into the printer setup utility to make a print queue for that printer. ๐Ÿ–จ๏ธโœจ

Multicast DNS responder software with full service discovery first shipped to end users in volume with Mac OS X 10.2 "Jaguar" in August 2002. Network printer makers, who had supported AppleTalk in their printers and liked IP tech that could offer similar ease-of-use, started adopting Multicast DNS shortly after. ๐Ÿ‘‘

In September 2002, Apple released the source code for the mDNSResponder daemon as Open Source under Apple's standard Apple Public Source License (APSL). ๐Ÿ”ฅ

Multicast DNS responder software came to Microsoft Windows users in June 2004 with the launch of Apple's "Rendezvous for Windows" (now "Bonjour for Windows"). It came both as an executable (a downloadable installer for end users) and as Open Source, as one of the supported platforms in Apple's cross-platform code in the publicly accessible mDNSResponder CVS source code repository [BJ]. ๐Ÿ’–

In August 2006, Apple re-licensed the cross-platform mDNSResponder source code under the Apache License, Version 2.0. ๐ŸŒธ

Multicast DNS isn't just laptops anymore ๐Ÿ’ป๐Ÿ“ฑ. It's in desktop and laptop computers running Mac OS X and Microsoft Windows, and also in a wide range of hardware devices: Apple's "AirPort" wireless base stations, iPhone and iPad, and home gateways from other vendors, network printers, network cameras, TiVo DVRs, etc. ๐Ÿ“

The Open Source community has produced many independent Multicast DNS implementations too ๐ŸŒˆ. Some are in C like Apple's mDNSResponder daemon, and others are in a bunch of different languages, including Java, Python, Perl, and C#/Mono. ๐Ÿ’œ

In January 2007, the IETF published the Informational RFC "Link-Local Multicast Name Resolution (LLMNR)" [RFC4795]. It's substantially similar to Multicast DNS but incompatible in some small but important ways. โญ The big one: the LLMNR design explicitly left out service discovery, which made it an unsuitable candidate for replacing AppleTalk NBP [RFC6760]. ๐Ÿ™…โ€โ™€๏ธ

Multicast DNS and DNS-Based Service Discovery were originally focused on zero-configuration environments without a conventional Unicast DNS server, but DNS-Based Service Discovery also works with Unicast DNS servers. ๐Ÿฆ‹ It uses DNS Update [RFC2136] [RFC3007] to create service discovery records, and standard DNS queries to look them up. Apple's Back to My Mac service, launched with Mac OS X 10.5 "Leopard" in October 2007, uses DNS-Based Service Discovery over Unicast DNS [RFC6281]. ๐ŸŽ€

In June 2012, Google's Android operating system added native support for DNS-SD and Multicast DNS through the android.net.nsd.NsdManager class in Android 4.1 "Jelly Bean" (API Level 16) [NSD]. ๐Ÿค–๐Ÿ’š


Authors' Addresses ๐Ÿซถ

Stuart Cheshire
Apple Inc.
1 Infinite Loop
Cupertino, CA  95014
USA

Phone: +1 408 974 3207
EMail: cheshire@apple.com


Marc Krochmal
Apple Inc.
1 Infinite Loop
Cupertino, CA  95014
USA

Phone: +1 408 974 4368
EMail: marc@apple.com
๐Ÿ“ฆ where this page comes from