1 // Copyright 2019 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 // Collection of constants defined for multicast DNS (RFC 6762) and DNS-Based
6 // Service Discovery (RFC 6763), along with a few constants used specifically
7 // for cast receiver's implementation of the mDNS spec (not 100% conformant).
8 //
9 // Some cast-specific implementation details include the maximum multicast
10 // message size (synced with sender SDK) and usage of site-local MDNS group
11 // in addition to the default link-local MDNS multicast group.
12 
13 #ifndef DISCOVERY_MDNS_PUBLIC_MDNS_CONSTANTS_H_
14 #define DISCOVERY_MDNS_PUBLIC_MDNS_CONSTANTS_H_
15 
16 #include <stddef.h>
17 #include <stdint.h>
18 
19 #include <array>
20 #include <chrono>
21 
22 #include "platform/api/time.h"
23 #include "platform/base/ip_address.h"
24 #include "util/osp_logging.h"
25 
26 namespace openscreen {
27 namespace discovery {
28 
29 // ============================================================================
30 // Networking
31 // ============================================================================
32 
33 // RFC 6762: https://www.ietf.org/rfc/rfc6762.txt
34 // RFC 2365: https://www.ietf.org/rfc/rfc2365.txt
35 // RFC 5771: https://www.ietf.org/rfc/rfc5771.txt
36 // RFC 7346: https://www.ietf.org/rfc/rfc7346.txt
37 
38 // Default multicast port used by mDNS protocol. On some systems there may be
39 // multiple processes binding to same port, so prefer to allow address re-use.
40 // See RFC 6762, Section 2
41 constexpr uint16_t kDefaultMulticastPort = 5353;
42 
43 // IPv4 group address for sending mDNS messages, given as byte array in
44 // network-order. This is a link-local multicast address, so messages will not
45 // be forwarded outside local network. See RFC 6762, section 3.
46 constexpr IPAddress kDefaultMulticastGroupIPv4{224, 0, 0, 251};
47 
48 // IPv6 group address for sending mDNS messages. This is a link-local
49 // multicast address, so messages will not be forwarded outside local network.
50 // See RFC 6762, section 3.
51 constexpr IPAddress kDefaultMulticastGroupIPv6{
52     0xFF02, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x00FB,
53 };
54 
55 // The send address for multicast mDNS should be the any address (0.*) on the
56 // default mDNS multicast port.
57 constexpr IPEndpoint kMulticastSendIPv4Endpoint{kDefaultMulticastGroupIPv4,
58                                                 kDefaultMulticastPort};
59 constexpr IPEndpoint kMulticastSendIPv6Endpoint{kDefaultMulticastGroupIPv6,
60                                                 kDefaultMulticastPort};
61 
62 // IPv4 group address for joining cast-specific site-local mDNS multicast group,
63 // given as byte array in network-order. This is a site-local multicast address,
64 // so messages can extend past the local network to the administrative area
65 // boundary. Local sockets will filter out messages that are not on local-
66 // subnet though, so it will behave the same as link-local. The difference is
67 // that router sometimes treat link-local and site-local differently, which
68 // may cause link-local to have worse reliability than site-local.
69 // See https://tools.ietf.org/html/draft-cai-ssdp-v1-03
70 
71 // 239.X.X.X is "administratively scoped IPv4 multicast space". See RFC 2365
72 // and RFC 5771, Section 3. Combined with relative address of 5 for SSDP this
73 // gives 239.255.255.250. See
74 // https://www.iana.org/assignments/multicast-addresses
75 
76 // NOTE: For now the group address is the same group address used for SSDP
77 // discovery, albeit using the MDNS port rather than SSDP port.
78 constexpr IPAddress kDefaultSiteLocalGroupIPv4{239, 255, 255, 250};
79 constexpr IPEndpoint kDefaultSiteLocalGroupIPv4Endpoint{
80     kDefaultSiteLocalGroupIPv4, kDefaultMulticastPort};
81 
82 // IPv6 group address for joining cast-specific site-local mDNS multicast group,
83 // give as byte array in network-order. See comments for IPv4 group address for
84 // more details on site-local vs. link-local.
85 // 0xFF05 is site-local. See RFC 7346.
86 // FF0X:0:0:0:0:0:0:C is variable scope multicast addresses for SSDP. See
87 // https://www.iana.org/assignments/ipv6-multicast-addresses
88 constexpr IPAddress kDefaultSiteLocalGroupIPv6{
89     0xFF05, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x000C,
90 };
91 constexpr IPEndpoint kDefaultSiteLocalGroupIPv6Endpoint{
92     kDefaultSiteLocalGroupIPv6, kDefaultMulticastPort};
93 
94 // Maximum MTU size (1500) minus the UDP header size (8) and IP header size
95 // (20). If any packets are larger than this size, the responder or sender
96 // should break up the message into multiple packets and set the TC
97 // (Truncated) bit to 1. See RFC 6762, section 7.2.
98 // TODO(https://crbug.com/openscreen/47): Figure out the exact size that the
99 // senders are using and sync with them. We want to verify that we are using the
100 // same maximum packet size. The spec also suggests keeping all UDP messsages
101 // below 512 bytes, since that is where some fragmentation may occur. If
102 // possible we should measure the rate of fragmented messages and see if
103 // lowering the max size alleviates it.
104 constexpr size_t kMaxMulticastMessageSize = 1500 - 20 - 8;
105 
106 // Specifies whether the site-local group described above should be enabled
107 // by default. When enabled, the responder will be able to receive messages from
108 // that group; when disabled, only the default MDNS multicast group will be
109 // enabled.
110 constexpr bool kDefaultSupportSiteLocalGroup = true;
111 
112 // ============================================================================
113 // Message Header
114 // ============================================================================
115 
116 // RFC 1035: https://www.ietf.org/rfc/rfc1035.txt
117 // RFC 2535: https://www.ietf.org/rfc/rfc2535.txt
118 
119 // DNS packet consists of a fixed-size header (12 bytes) followed by
120 // zero or more questions and/or records.
121 // For the meaning of specific fields, please see RFC 1035 and 2535.
122 //
123 // Header format:
124 //                                  1  1  1  1  1  1
125 //    0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
126 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
127 //  |                      ID                       |
128 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
129 //  |QR|   Opcode  |AA|TC|RD|RA| Z|AD|CD|   RCODE   |
130 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
131 //  |                    QDCOUNT                    |
132 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
133 //  |                    ANCOUNT                    |
134 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
135 //  |                    NSCOUNT                    |
136 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
137 //  |                    ARCOUNT                    |
138 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
139 
140 // On-the-wire header. All uint16_t are in network order.
141 struct Header {
142   uint16_t id;
143   uint16_t flags;
144   uint16_t question_count;
145   uint16_t answer_count;
146   uint16_t authority_record_count;
147   uint16_t additional_record_count;
148 };
149 
150 static_assert(sizeof(Header) == 12, "Size of mDNS header must be 12 bytes.");
151 
152 enum class MessageType {
153   Query = 0,
154   Response = 1,
155 };
156 
157 constexpr uint16_t kFlagResponse = 0x8000;
158 constexpr uint16_t kFlagAA = 0x0400;
159 constexpr uint16_t kFlagTC = 0x0200;
160 constexpr uint16_t kOpcodeMask = 0x7800;
161 constexpr uint16_t kRcodeMask = 0x000F;
162 
GetMessageType(uint16_t flags)163 constexpr MessageType GetMessageType(uint16_t flags) {
164   // RFC 6762 Section 18.2
165   return (flags & kFlagResponse) ? MessageType::Response : MessageType::Query;
166 }
167 
IsMessageTruncated(uint16_t flags)168 constexpr bool IsMessageTruncated(uint16_t flags) {
169   return flags & kFlagTC;
170 }
171 
MakeFlags(MessageType type,bool is_truncated)172 constexpr uint16_t MakeFlags(MessageType type, bool is_truncated) {
173   // RFC 6762 Section 18.2 and Section 18.4
174   uint16_t flags =
175       (type == MessageType::Response) ? (kFlagResponse | kFlagAA) : 0;
176   if (is_truncated) {
177     flags |= kFlagTC;
178   }
179   return flags;
180 }
181 
IsValidFlagsSection(uint16_t flags)182 constexpr bool IsValidFlagsSection(uint16_t flags) {
183   // RFC 6762 Section 18.3 and Section 18.11
184   return (flags & (kOpcodeMask | kRcodeMask)) == 0;
185 }
186 
187 // ============================================================================
188 // Domain Name
189 // ============================================================================
190 
191 // RFC 1035: https://www.ietf.org/rfc/rfc1035.txt
192 
193 // Maximum number of octets allowed in a single domain name including the
194 // terminating character octet
195 constexpr size_t kMaxDomainNameLength = 256;
196 // Maximum number of octets allowed in a single domain name label.
197 constexpr size_t kMaxLabelLength = 63;
198 
199 // To allow for message compression, domain names can fall under the following
200 // categories:
201 // - A sequence of labels ending in a zero octet (label of length zero)
202 // - A pointer to prior occurance of name in message
203 // - A sequence of labels ending with a pointer.
204 //
205 // Domain Name Label - DIRECT:
206 //                                  1  1  1  1  1  1
207 //    0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
208 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
209 //  | 0  0|  LABEL LENGTH   |        CHAR 0         |
210 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
211 //  /         CHAR 1        |        CHAR 2         /
212 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
213 //
214 // Domain Name Label - POINTER:
215 //                                  1  1  1  1  1  1
216 //    0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
217 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
218 //  | 1  1|               OFFSET                    |
219 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
220 
221 constexpr uint8_t kLabelTermination = 0x00;
222 constexpr uint8_t kLabelTypeMask = 0xC0;
223 constexpr uint8_t kLabelDirect = 0x00;
224 constexpr uint8_t kLabelPointer = 0xC0;
225 constexpr uint8_t kLabelLengthMask = 0x3F;
226 constexpr uint16_t kLabelOffsetMask = 0x3FFF;
227 
IsTerminationLabel(uint8_t label)228 constexpr bool IsTerminationLabel(uint8_t label) {
229   return label == kLabelTermination;
230 }
231 
IsDirectLabel(uint8_t label)232 constexpr bool IsDirectLabel(uint8_t label) {
233   return (label & kLabelTypeMask) == kLabelDirect;
234 }
235 
IsPointerLabel(uint8_t label)236 constexpr bool IsPointerLabel(uint8_t label) {
237   return (label & kLabelTypeMask) == kLabelPointer;
238 }
239 
GetDirectLabelLength(uint8_t label)240 constexpr uint8_t GetDirectLabelLength(uint8_t label) {
241   return label & kLabelLengthMask;
242 }
243 
GetPointerLabelOffset(uint16_t label)244 constexpr uint16_t GetPointerLabelOffset(uint16_t label) {
245   return label & kLabelOffsetMask;
246 }
247 
IsValidPointerLabelOffset(size_t offset)248 constexpr bool IsValidPointerLabelOffset(size_t offset) {
249   return offset <= kLabelOffsetMask;
250 }
251 
MakePointerLabel(uint16_t offset)252 constexpr uint16_t MakePointerLabel(uint16_t offset) {
253   return (uint16_t(kLabelPointer) << 8) | (offset & kLabelOffsetMask);
254 }
255 
MakeDirectLabel(uint8_t length)256 constexpr uint8_t MakeDirectLabel(uint8_t length) {
257   return kLabelDirect | (length & kLabelLengthMask);
258 }
259 
260 // ============================================================================
261 // Record Fields
262 // ============================================================================
263 
264 // RFC 1035: https://www.ietf.org/rfc/rfc1035.txt
265 // RFC 2535: https://www.ietf.org/rfc/rfc2535.txt
266 
267 // Question format:
268 //                                  1  1  1  1  1  1
269 //    0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
270 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
271 //  |                                               |
272 //  /                     QNAME                     /
273 //  /                                               /
274 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
275 //  |                     QTYPE                     |
276 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
277 //  |                     QCLASS                    |
278 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
279 
280 // Answer format:
281 //                                  1  1  1  1  1  1
282 //    0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
283 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
284 //  |                                               |
285 //  /                                               /
286 //  /                      NAME                     /
287 //  |                                               |
288 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
289 //  |                      TYPE                     |
290 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
291 //  |                     CLASS                     |
292 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
293 //  |                      TTL                      |
294 //  |                                               |
295 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
296 //  |                   RDLENGTH                    |
297 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--|
298 //  /                     RDATA                     /
299 //  /                                               /
300 //  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
301 
302 // DNS TYPE values. See http://www.iana.org/assignments/dns-parameters for full
303 // list. Only a sub-set is used and listed here.
304 enum class DnsType : uint16_t {
305   kA = 1,
306   kPTR = 12,
307   kTXT = 16,
308   kAAAA = 28,
309   kSRV = 33,
310   kOPT = 41,
311   kNSEC = 47,
312   kANY = 255,  // Only allowed for QTYPE
313 };
314 
315 inline std::ostream& operator<<(std::ostream& output, DnsType type) {
316   switch (type) {
317     case DnsType::kA:
318       return output << "A";
319     case DnsType::kPTR:
320       return output << "PTR";
321     case DnsType::kTXT:
322       return output << "TXT";
323     case DnsType::kAAAA:
324       return output << "AAAA";
325     case DnsType::kSRV:
326       return output << "SRV";
327     case DnsType::kOPT:
328       return output << "OPT";
329     case DnsType::kNSEC:
330       return output << "NSEC";
331     case DnsType::kANY:
332       return output << "ANY";
333   }
334 
335   OSP_NOTREACHED();
336 }
337 
338 constexpr std::array<DnsType, 7> kSupportedDnsTypes = {
339     DnsType::kA,   DnsType::kPTR,  DnsType::kTXT, DnsType::kAAAA,
340     DnsType::kSRV, DnsType::kNSEC, DnsType::kANY};
341 
342 enum class DnsClass : uint16_t {
343   kIN = 1,
344   kANY = 255,  // Only allowed for QCLASS
345 };
346 
347 // Unique and shared records are described in
348 // https://tools.ietf.org/html/rfc6762#section-2 and
349 // https://tools.ietf.org/html/rfc6762#section-10.2
350 enum class RecordType {
351   kShared = 0,
352   kUnique = 1,
353 };
354 
355 // Unicast and multicast preferred response types are described in
356 // https://tools.ietf.org/html/rfc6762#section-5.4
357 enum class ResponseType {
358   kMulticast = 0,
359   kUnicast = 1,
360 };
361 
362 // These are the default TTL values for supported DNS Record types  as specified
363 // by RFC 6762 section 10.
364 constexpr std::chrono::seconds kPtrRecordTtl(120);
365 constexpr std::chrono::seconds kSrvRecordTtl(120);
366 constexpr std::chrono::seconds kARecordTtl(120);
367 constexpr std::chrono::seconds kAAAARecordTtl(120);
368 constexpr std::chrono::seconds kTXTRecordTtl(120);
369 
370 // DNS CLASS masks and values.
371 // In mDNS the most significant bit of the RRCLASS for response records is
372 // designated as the "cache-flush bit", as described in
373 // https://tools.ietf.org/html/rfc6762#section-10.2
374 // In mDNS the most significant bit of the RRCLASS for query records is
375 // designated as the "unicast-response bit", as described in
376 // https://tools.ietf.org/html/rfc6762#section-5.4
377 constexpr uint16_t kClassMask = 0x7FFF;
378 constexpr uint16_t kClassMsbMask = 0x8000;
379 constexpr uint16_t kClassMsbShift = 0xF;
380 
GetDnsClass(uint16_t rrclass)381 constexpr DnsClass GetDnsClass(uint16_t rrclass) {
382   return static_cast<DnsClass>(rrclass & kClassMask);
383 }
384 
GetRecordType(uint16_t rrclass)385 constexpr RecordType GetRecordType(uint16_t rrclass) {
386   return static_cast<RecordType>((rrclass & kClassMsbMask) >> kClassMsbShift);
387 }
388 
GetResponseType(uint16_t rrclass)389 constexpr ResponseType GetResponseType(uint16_t rrclass) {
390   return static_cast<ResponseType>((rrclass & kClassMsbMask) >> kClassMsbShift);
391 }
392 
MakeRecordClass(DnsClass dns_class,RecordType record_type)393 constexpr uint16_t MakeRecordClass(DnsClass dns_class, RecordType record_type) {
394   return static_cast<uint16_t>(dns_class) |
395          (static_cast<uint16_t>(record_type) << kClassMsbShift);
396 }
397 
MakeQuestionClass(DnsClass dns_class,ResponseType response_type)398 constexpr uint16_t MakeQuestionClass(DnsClass dns_class,
399                                      ResponseType response_type) {
400   return static_cast<uint16_t>(dns_class) |
401          (static_cast<uint16_t>(response_type) << kClassMsbShift);
402 }
403 
404 // See RFC 6762, section 11: https://tools.ietf.org/html/rfc6762#section-11
405 //
406 // The IP TTL value for the UDP packets sent to the multicast group is advised
407 // to be 255 in order to be compatible with older DNS queriers. This also keeps
408 // consistent with other mDNS solutions (jMDNS, Avahi, etc.), which use 255
409 // as the IP TTL as well.
410 //
411 // The default mDNS group address is in a range of link-local addresses, so
412 // messages should not be forwarded by routers even when TTL is greater than 1.
413 constexpr uint32_t kDefaultRecordTTLSeconds = 255;
414 
415 // ============================================================================
416 // RDATA Constants
417 // ============================================================================
418 
419 // The maximum allowed size for a single entry in a TXT resource record. The
420 // mDNS spec specifies that entries in TXT record should be key/value pair
421 // separated by '=', so the size of the key + value + '=' should not exceed
422 // the maximum allowed size.
423 // See: https://tools.ietf.org/html/rfc6763#section-6.1
424 constexpr size_t kTXTMaxEntrySize = 255;
425 // Placeholder RDATA for "empty" TXT records that contains only a single
426 // zero length byte. This is required since TXT records CANNOT have empty
427 // RDATA sections.
428 // See RFC: https://tools.ietf.org/html/rfc6763#section-6.1
429 constexpr uint8_t kTXTEmptyRdata = 0;
430 
431 // ============================================================================
432 // Probing Constants
433 // ============================================================================
434 
435 // RFC 6762 section 8.1 specifies that a probe should wait 250 ms between
436 // subsequent probe queries.
437 constexpr Clock::duration kDelayBetweenProbeQueries =
438     Clock::to_duration(std::chrono::milliseconds(250));
439 
440 // RFC 6762 section 8.1 specifies that the probing phase should send out probe
441 // requests 3 times before treating the probe as completed.
442 constexpr int kProbeIterationCountBeforeSuccess = 3;
443 
444 // ============================================================================
445 // OPT Pseudo-Record Constants
446 // ============================================================================
447 
448 // For OPT records, the TTL field has been re-purposed as follows:
449 //
450 //                   +0 (MSB)                            +1 (LSB)
451 //        +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
452 //     0: |         EXTENDED-RCODE        |            VERSION            |
453 //        +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
454 //     2: | DO|                           Z                               |
455 //        +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
456 
457 constexpr uint32_t kExtendedRcodeMask = 0xFF000000;
458 constexpr int kExtendedRcodeShift = 24;
459 constexpr uint32_t kVersionMask = 0x00FF0000;
460 constexpr int kVersionShift = 16;
461 constexpr uint32_t kDnssecOkBitMask = 0x00008000;
462 constexpr uint8_t kVersionBadvers = 0x10;
463 
464 }  // namespace discovery
465 }  // namespace openscreen
466 
467 #endif  // DISCOVERY_MDNS_PUBLIC_MDNS_CONSTANTS_H_
468