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