xref: /aosp_15_r20/external/cronet/net/dns/dns_names_util.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker // Copyright 2022 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker 
5*6777b538SAndroid Build Coastguard Worker #ifndef NET_DNS_DNS_NAMES_UTIL_H_
6*6777b538SAndroid Build Coastguard Worker #define NET_DNS_DNS_NAMES_UTIL_H_
7*6777b538SAndroid Build Coastguard Worker 
8*6777b538SAndroid Build Coastguard Worker #include <cstdint>
9*6777b538SAndroid Build Coastguard Worker #include <optional>
10*6777b538SAndroid Build Coastguard Worker #include <string>
11*6777b538SAndroid Build Coastguard Worker #include <string_view>
12*6777b538SAndroid Build Coastguard Worker #include <vector>
13*6777b538SAndroid Build Coastguard Worker 
14*6777b538SAndroid Build Coastguard Worker #include "base/containers/span.h"
15*6777b538SAndroid Build Coastguard Worker #include "base/containers/span_reader.h"
16*6777b538SAndroid Build Coastguard Worker #include "base/strings/string_util.h"
17*6777b538SAndroid Build Coastguard Worker #include "net/base/net_export.h"
18*6777b538SAndroid Build Coastguard Worker 
19*6777b538SAndroid Build Coastguard Worker // Various utilities for converting, validating, and comparing DNS names.
20*6777b538SAndroid Build Coastguard Worker namespace net::dns_names_util {
21*6777b538SAndroid Build Coastguard Worker 
22*6777b538SAndroid Build Coastguard Worker // Returns true iff `dotted` is acceptable to be encoded as a DNS name. That is
23*6777b538SAndroid Build Coastguard Worker // that it is non-empty and fits size limitations. Also must match the expected
24*6777b538SAndroid Build Coastguard Worker // structure of dot-separated labels, each non-empty and fitting within
25*6777b538SAndroid Build Coastguard Worker // additional size limitations, and an optional dot at the end. See RFCs 1035
26*6777b538SAndroid Build Coastguard Worker // and 2181.
27*6777b538SAndroid Build Coastguard Worker //
28*6777b538SAndroid Build Coastguard Worker // No validation is performed for correctness of characters within a label.
29*6777b538SAndroid Build Coastguard Worker // As explained by RFC 2181, commonly cited rules for such characters are not
30*6777b538SAndroid Build Coastguard Worker // DNS restrictions, but actually restrictions for Internet hostnames. For such
31*6777b538SAndroid Build Coastguard Worker // validation, see IsCanonicalizedHostCompliant().
32*6777b538SAndroid Build Coastguard Worker NET_EXPORT_PRIVATE bool IsValidDnsName(std::string_view dotted_form_name);
33*6777b538SAndroid Build Coastguard Worker 
34*6777b538SAndroid Build Coastguard Worker // Like IsValidDnsName() but further validates `dotted_form_name` is not an IP
35*6777b538SAndroid Build Coastguard Worker // address (with or without surrounding []) or localhost, as such names would
36*6777b538SAndroid Build Coastguard Worker // not be suitable for DNS queries or for use as DNS record names or alias
37*6777b538SAndroid Build Coastguard Worker // target names.
38*6777b538SAndroid Build Coastguard Worker NET_EXPORT_PRIVATE bool IsValidDnsRecordName(std::string_view dotted_form_name);
39*6777b538SAndroid Build Coastguard Worker 
40*6777b538SAndroid Build Coastguard Worker // Convert a dotted-form DNS name to network wire format. Returns nullopt if
41*6777b538SAndroid Build Coastguard Worker // input is not valid for conversion (equivalent validity can be checked using
42*6777b538SAndroid Build Coastguard Worker // IsValidDnsName()). If `require_valid_internet_hostname` is true, also returns
43*6777b538SAndroid Build Coastguard Worker // nullopt if input is not a valid internet hostname (equivalent validity can be
44*6777b538SAndroid Build Coastguard Worker // checked using net::IsCanonicalizedHostCompliant()).
45*6777b538SAndroid Build Coastguard Worker NET_EXPORT_PRIVATE std::optional<std::vector<uint8_t>> DottedNameToNetwork(
46*6777b538SAndroid Build Coastguard Worker     std::string_view dotted_form_name,
47*6777b538SAndroid Build Coastguard Worker     bool require_valid_internet_hostname = false);
48*6777b538SAndroid Build Coastguard Worker 
49*6777b538SAndroid Build Coastguard Worker // Converts a domain in DNS format to a dotted string. Excludes the dot at the
50*6777b538SAndroid Build Coastguard Worker // end.  Returns nullopt on malformed input.
51*6777b538SAndroid Build Coastguard Worker //
52*6777b538SAndroid Build Coastguard Worker // If `require_complete` is true, input will be considered malformed if it does
53*6777b538SAndroid Build Coastguard Worker // not contain a terminating zero-length label. If false, assumes the standard
54*6777b538SAndroid Build Coastguard Worker // terminating zero-length label at the end if not included in the input.
55*6777b538SAndroid Build Coastguard Worker //
56*6777b538SAndroid Build Coastguard Worker // DNS name compression (see RFC 1035, section 4.1.4) is disallowed and
57*6777b538SAndroid Build Coastguard Worker // considered malformed. To handle a potentially compressed name, in a
58*6777b538SAndroid Build Coastguard Worker // DnsResponse object, use DnsRecordParser::ReadName().
59*6777b538SAndroid Build Coastguard Worker NET_EXPORT_PRIVATE std::optional<std::string> NetworkToDottedName(
60*6777b538SAndroid Build Coastguard Worker     base::SpanReader<const uint8_t>& reader,
61*6777b538SAndroid Build Coastguard Worker     bool require_complete = false);
62*6777b538SAndroid Build Coastguard Worker NET_EXPORT_PRIVATE std::optional<std::string> NetworkToDottedName(
63*6777b538SAndroid Build Coastguard Worker     base::span<const uint8_t> span,
64*6777b538SAndroid Build Coastguard Worker     bool require_complete = false);
65*6777b538SAndroid Build Coastguard Worker 
66*6777b538SAndroid Build Coastguard Worker // Reads a length-prefixed region:
67*6777b538SAndroid Build Coastguard Worker // 1. reads a big-endian length L from the buffer of a size determined by the
68*6777b538SAndroid Build Coastguard Worker //    function (e.g. ReadU8 reads an 8-bit length);
69*6777b538SAndroid Build Coastguard Worker // 2. sets `*out` to a span over the next L many bytes of the buffer (beyond
70*6777b538SAndroid Build Coastguard Worker //    the end of the bytes encoding the length); and
71*6777b538SAndroid Build Coastguard Worker // 3. skips the main reader past this L-byte substring.
72*6777b538SAndroid Build Coastguard Worker //
73*6777b538SAndroid Build Coastguard Worker // Fails if reading the length L fails, or if the parsed length is greater
74*6777b538SAndroid Build Coastguard Worker // than the number of bytes remaining in the input span.
75*6777b538SAndroid Build Coastguard Worker //
76*6777b538SAndroid Build Coastguard Worker // On failure, leaves the stream at the same position
77*6777b538SAndroid Build Coastguard Worker // as before the call.
78*6777b538SAndroid Build Coastguard Worker NET_EXPORT_PRIVATE bool ReadU8LengthPrefixed(
79*6777b538SAndroid Build Coastguard Worker     base::SpanReader<const uint8_t>& reader,
80*6777b538SAndroid Build Coastguard Worker     base::span<const uint8_t>* out);
81*6777b538SAndroid Build Coastguard Worker NET_EXPORT_PRIVATE bool ReadU16LengthPrefixed(
82*6777b538SAndroid Build Coastguard Worker     base::SpanReader<const uint8_t>& reader,
83*6777b538SAndroid Build Coastguard Worker     base::span<const uint8_t>* out);
84*6777b538SAndroid Build Coastguard Worker 
85*6777b538SAndroid Build Coastguard Worker // Canonicalize `name` as a URL hostname if able. If unable (typically if a name
86*6777b538SAndroid Build Coastguard Worker // is not a valid URL hostname), returns `name` without change because such a
87*6777b538SAndroid Build Coastguard Worker // name could still be a valid DNS name.
88*6777b538SAndroid Build Coastguard Worker NET_EXPORT_PRIVATE std::string UrlCanonicalizeNameIfAble(std::string_view name);
89*6777b538SAndroid Build Coastguard Worker 
90*6777b538SAndroid Build Coastguard Worker // std::map-compliant Compare for two domain names. Works for any valid
91*6777b538SAndroid Build Coastguard Worker // dotted-format or network-wire-format names. Returns true iff `lhs` is before
92*6777b538SAndroid Build Coastguard Worker // `rhs` in strict weak ordering.
93*6777b538SAndroid Build Coastguard Worker class NET_EXPORT_PRIVATE DomainNameComparator {
94*6777b538SAndroid Build Coastguard Worker  public:
operator()95*6777b538SAndroid Build Coastguard Worker   bool operator()(std::string_view lhs, std::string_view rhs) const {
96*6777b538SAndroid Build Coastguard Worker     // This works for dotted format or network-wire format as long as the names
97*6777b538SAndroid Build Coastguard Worker     // are valid because valid network-wire names have labels of max 63 bytes
98*6777b538SAndroid Build Coastguard Worker     // and thus will never have label length prefixes high enough to be
99*6777b538SAndroid Build Coastguard Worker     // misinterpreted as capital letters ('A' is 65).
100*6777b538SAndroid Build Coastguard Worker     return base::CompareCaseInsensitiveASCII(lhs, rhs) < 0;
101*6777b538SAndroid Build Coastguard Worker   }
102*6777b538SAndroid Build Coastguard Worker };
103*6777b538SAndroid Build Coastguard Worker 
104*6777b538SAndroid Build Coastguard Worker }  // namespace net::dns_names_util
105*6777b538SAndroid Build Coastguard Worker 
106*6777b538SAndroid Build Coastguard Worker #endif  // NET_DNS_DNS_NAMES_UTIL_H_
107