chromium/third_party/openscreen/src/discovery/mdns/public/mdns_constants.h

// Copyright 2019 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Collection of constants defined for multicast DNS (RFC 6762) and DNS-Based
// Service Discovery (RFC 6763), along with a few constants used specifically
// for cast receiver's implementation of the mDNS spec (not 100% conformant).
//
// Some cast-specific implementation details include the maximum multicast
// message size (synced with sender SDK) and usage of site-local MDNS group
// in addition to the default link-local MDNS multicast group.

#ifndef DISCOVERY_MDNS_PUBLIC_MDNS_CONSTANTS_H_
#define DISCOVERY_MDNS_PUBLIC_MDNS_CONSTANTS_H_

#include <stddef.h>
#include <stdint.h>

#include <array>
#include <chrono>

#include "platform/api/time.h"
#include "platform/base/ip_address.h"
#include "util/osp_logging.h"

namespace openscreen::discovery {

// ============================================================================
// Networking
// ============================================================================

// RFC 6762: https://www.ietf.org/rfc/rfc6762.txt
// RFC 2365: https://www.ietf.org/rfc/rfc2365.txt
// RFC 5771: https://www.ietf.org/rfc/rfc5771.txt
// RFC 7346: https://www.ietf.org/rfc/rfc7346.txt

// Default multicast port used by mDNS protocol. On some systems there may be
// multiple processes binding to same port, so prefer to allow address re-use.
// See RFC 6762, Section 2
constexpr uint16_t kDefaultMulticastPort =;

// IPv4 group address for sending mDNS messages, given as byte array in
// network-order. This is a link-local multicast address, so messages will not
// be forwarded outside local network. See RFC 6762, section 3.
constexpr IPAddress kDefaultMulticastGroupIPv4{};

// IPv6 group address for sending mDNS messages. This is a link-local
// multicast address, so messages will not be forwarded outside local network.
// See RFC 6762, section 3.
constexpr IPAddress kDefaultMulticastGroupIPv6{};

// The send address for multicast mDNS should be the any address (0.*) on the
// default mDNS multicast port.
constexpr IPEndpoint kMulticastSendIPv4Endpoint{};
constexpr IPEndpoint kMulticastSendIPv6Endpoint{};

// IPv4 group address for joining cast-specific site-local mDNS multicast group,
// given as byte array in network-order. This is a site-local multicast address,
// so messages can extend past the local network to the administrative area
// boundary. Local sockets will filter out messages that are not on local-
// subnet though, so it will behave the same as link-local. The difference is
// that router sometimes treat link-local and site-local differently, which
// may cause link-local to have worse reliability than site-local.
// See https://tools.ietf.org/html/draft-cai-ssdp-v1-03

// 239.X.X.X is "administratively scoped IPv4 multicast space". See RFC 2365
// and RFC 5771, Section 3. Combined with relative address of 5 for SSDP this
// gives 239.255.255.250. See
// https://www.iana.org/assignments/multicast-addresses

// NOTE: For now the group address is the same group address used for SSDP
// discovery, albeit using the MDNS port rather than SSDP port.
constexpr IPAddress kDefaultSiteLocalGroupIPv4{};
constexpr IPEndpoint kDefaultSiteLocalGroupIPv4Endpoint{};

// IPv6 group address for joining cast-specific site-local mDNS multicast group,
// give as byte array in network-order. See comments for IPv4 group address for
// more details on site-local vs. link-local.
// 0xFF05 is site-local. See RFC 7346.
// FF0X:0:0:0:0:0:0:C is variable scope multicast addresses for SSDP. See
// https://www.iana.org/assignments/ipv6-multicast-addresses
constexpr IPAddress kDefaultSiteLocalGroupIPv6{};
constexpr IPEndpoint kDefaultSiteLocalGroupIPv6Endpoint{};

// Maximum MTU size (1500) minus the UDP header size (8) and IP header size
// (20). If any packets are larger than this size, the responder or sender
// should break up the message into multiple packets and set the TC
// (Truncated) bit to 1. See RFC 6762, section 7.2.
// TODO(https://crbug.com/openscreen/47): Figure out the exact size that the
// senders are using and sync with them. We want to verify that we are using the
// same maximum packet size. The spec also suggests keeping all UDP messsages
// below 512 bytes, since that is where some fragmentation may occur. If
// possible we should measure the rate of fragmented messages and see if
// lowering the max size alleviates it.
constexpr size_t kMaxMulticastMessageSize =;

// Specifies whether the site-local group described above should be enabled
// by default. When enabled, the responder will be able to receive messages from
// that group; when disabled, only the default MDNS multicast group will be
// enabled.
constexpr bool kDefaultSupportSiteLocalGroup =;

// ============================================================================
// Message Header
// ============================================================================

// RFC 1035: https://www.ietf.org/rfc/rfc1035.txt
// RFC 2535: https://www.ietf.org/rfc/rfc2535.txt

// DNS packet consists of a fixed-size header (12 bytes) followed by
// zero or more questions and/or records.
// For the meaning of specific fields, please see RFC 1035 and 2535.
//
// Header format:
//                                  1  1  1  1  1  1
//    0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
//  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
//  |                      ID                       |
//  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
//  |QR|   Opcode  |AA|TC|RD|RA| Z|AD|CD|   RCODE   |
//  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
//  |                    QDCOUNT                    |
//  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
//  |                    ANCOUNT                    |
//  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
//  |                    NSCOUNT                    |
//  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
//  |                    ARCOUNT                    |
//  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

// On-the-wire header. All uint16_t are in network order.
struct Header {};

static_assert;

enum class MessageType {};

constexpr uint16_t kFlagResponse =;
constexpr uint16_t kFlagAA =;
constexpr uint16_t kFlagTC =;
constexpr uint16_t kOpcodeMask =;
constexpr uint16_t kRcodeMask =;

constexpr MessageType GetMessageType(uint16_t flags) {}

constexpr bool IsMessageTruncated(uint16_t flags) {}

constexpr uint16_t MakeFlags(MessageType type, bool is_truncated) {}

constexpr bool IsValidFlagsSection(uint16_t flags) {}

// ============================================================================
// Domain Name
// ============================================================================

// RFC 1035: https://www.ietf.org/rfc/rfc1035.txt

// Maximum number of octets allowed in a single domain name including the
// terminating character octet
constexpr size_t kMaxDomainNameLength =;
// Maximum number of octets allowed in a single domain name label.
constexpr size_t kMaxLabelLength =;

// To allow for message compression, domain names can fall under the following
// categories:
// - A sequence of labels ending in a zero octet (label of length zero)
// - A pointer to prior occurance of name in message
// - A sequence of labels ending with a pointer.
//
// Domain Name Label - DIRECT:
//                                  1  1  1  1  1  1
//    0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
//  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
//  | 0  0|  LABEL LENGTH   |        CHAR 0         |
//  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
//  /         CHAR 1        |        CHAR 2         /
//  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
//
// Domain Name Label - POINTER:
//                                  1  1  1  1  1  1
//    0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
//  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
//  | 1  1|               OFFSET                    |
//  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

constexpr uint8_t kLabelTermination =;
constexpr uint8_t kLabelTypeMask =;
constexpr uint8_t kLabelDirect =;
constexpr uint8_t kLabelPointer =;
constexpr uint8_t kLabelLengthMask =;
constexpr uint16_t kLabelOffsetMask =;

constexpr bool IsTerminationLabel(uint8_t label) {}

constexpr bool IsDirectLabel(uint8_t label) {}

constexpr bool IsPointerLabel(uint8_t label) {}

constexpr uint8_t GetDirectLabelLength(uint8_t label) {}

constexpr uint16_t GetPointerLabelOffset(uint16_t label) {}

constexpr bool IsValidPointerLabelOffset(size_t offset) {}

constexpr uint16_t MakePointerLabel(uint16_t offset) {}

constexpr uint8_t MakeDirectLabel(uint8_t length) {}

// ============================================================================
// Record Fields
// ============================================================================

// RFC 1035: https://www.ietf.org/rfc/rfc1035.txt
// RFC 2535: https://www.ietf.org/rfc/rfc2535.txt

// Question format:
//                                  1  1  1  1  1  1
//    0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
//  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
//  |                                               |
//  /                     QNAME                     /
//  /                                               /
//  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
//  |                     QTYPE                     |
//  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
//  |                     QCLASS                    |
//  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

// Answer format:
//                                  1  1  1  1  1  1
//    0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
//  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
//  |                                               |
//  /                                               /
//  /                      NAME                     /
//  |                                               |
//  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
//  |                      TYPE                     |
//  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
//  |                     CLASS                     |
//  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
//  |                      TTL                      |
//  |                                               |
//  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
//  |                   RDLENGTH                    |
//  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--|
//  /                     RDATA                     /
//  /                                               /
//  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

// DNS TYPE values. See http://www.iana.org/assignments/dns-parameters for full
// list. Only a sub-set is used and listed here.
enum class DnsType : uint16_t {};

// TODO(mfoltz): Move definition so we don't have to inline.
inline std::ostream& operator<<(std::ostream& output, DnsType type) {}

constexpr std::array<DnsType, 7> kSupportedDnsTypes =;

enum class DnsClass : uint16_t {};

// Unique and shared records are described in
// https://tools.ietf.org/html/rfc6762#section-2 and
// https://tools.ietf.org/html/rfc6762#section-10.2
enum class RecordType {};

// Unicast and multicast preferred response types are described in
// https://tools.ietf.org/html/rfc6762#section-5.4
enum class ResponseType {};

// These are the default TTL values for supported DNS Record types  as specified
// by RFC 6762 section 10.
constexpr std::chrono::seconds kPtrRecordTtl(120);
constexpr std::chrono::seconds kSrvRecordTtl(120);
constexpr std::chrono::seconds kARecordTtl(120);
constexpr std::chrono::seconds kAAAARecordTtl(120);
constexpr std::chrono::seconds kTXTRecordTtl(120);

// DNS CLASS masks and values.
// In mDNS the most significant bit of the RRCLASS for response records is
// designated as the "cache-flush bit", as described in
// https://tools.ietf.org/html/rfc6762#section-10.2
// In mDNS the most significant bit of the RRCLASS for query records is
// designated as the "unicast-response bit", as described in
// https://tools.ietf.org/html/rfc6762#section-5.4
constexpr uint16_t kClassMask =;
constexpr uint16_t kClassMsbMask =;
constexpr uint16_t kClassMsbShift =;

constexpr DnsClass GetDnsClass(uint16_t rrclass) {}

constexpr RecordType GetRecordType(uint16_t rrclass) {}

constexpr ResponseType GetResponseType(uint16_t rrclass) {}

constexpr uint16_t MakeRecordClass(DnsClass dns_class, RecordType record_type) {}

constexpr uint16_t MakeQuestionClass(DnsClass dns_class,
                                     ResponseType response_type) {}

// See RFC 6762, section 11: https://tools.ietf.org/html/rfc6762#section-11
//
// The IP TTL value for the UDP packets sent to the multicast group is advised
// to be 255 in order to be compatible with older DNS queriers. This also keeps
// consistent with other mDNS solutions (jMDNS, Avahi, etc.), which use 255
// as the IP TTL as well.
//
// The default mDNS group address is in a range of link-local addresses, so
// messages should not be forwarded by routers even when TTL is greater than 1.
constexpr uint32_t kDefaultRecordTTLSeconds =;

// ============================================================================
// RDATA Constants
// ============================================================================

// The maximum allowed size for a single entry in a TXT resource record. The
// mDNS spec specifies that entries in TXT record should be key/value pair
// separated by '=', so the size of the key + value + '=' should not exceed
// the maximum allowed size.
// See: https://tools.ietf.org/html/rfc6763#section-6.1
constexpr size_t kTXTMaxEntrySize =;
// Placeholder RDATA for "empty" TXT records that contains only a single
// zero length byte. This is required since TXT records CANNOT have empty
// RDATA sections.
// See RFC: https://tools.ietf.org/html/rfc6763#section-6.1
constexpr uint8_t kTXTEmptyRdata =;

// ============================================================================
// Probing Constants
// ============================================================================

// RFC 6762 section 8.1 specifies that a probe should wait 250 ms between
// subsequent probe queries.
constexpr Clock::duration kDelayBetweenProbeQueries =;

// RFC 6762 section 8.1 specifies that the probing phase should send out probe
// requests 3 times before treating the probe as completed.
constexpr int kProbeIterationCountBeforeSuccess =;

// ============================================================================
// OPT Pseudo-Record Constants
// ============================================================================

// For OPT records, the TTL field has been re-purposed as follows:
//
//                   +0 (MSB)                            +1 (LSB)
//        +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
//     0: |         EXTENDED-RCODE        |            VERSION            |
//        +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
//     2: | DO|                           Z                               |
//        +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+

constexpr uint32_t kExtendedRcodeMask =;
constexpr int kExtendedRcodeShift =;
constexpr uint32_t kVersionMask =;
constexpr int kVersionShift =;
constexpr uint32_t kDnssecOkBitMask =;
constexpr uint8_t kVersionBadvers =;

}  // namespace openscreen::discovery

#endif  // DISCOVERY_MDNS_PUBLIC_MDNS_CONSTANTS_H_