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 <string> 10 #include <vector> 11 12 #include "base/containers/span.h" 13 #include "base/strings/string_piece.h" 14 #include "base/strings/string_util.h" 15 #include "net/base/net_export.h" 16 #include "third_party/abseil-cpp/absl/types/optional.h" 17 18 namespace base { 19 class BigEndianReader; 20 } // namespace base 21 22 // Various utilities for converting, validating, and comparing DNS names. 23 namespace net::dns_names_util { 24 25 // Returns true iff `dotted` is acceptable to be encoded as a DNS name. That is 26 // that it is non-empty and fits size limitations. Also must match the expected 27 // structure of dot-separated labels, each non-empty and fitting within 28 // additional size limitations, and an optional dot at the end. See RFCs 1035 29 // and 2181. 30 // 31 // No validation is performed for correctness of characters within a label. 32 // As explained by RFC 2181, commonly cited rules for such characters are not 33 // DNS restrictions, but actually restrictions for Internet hostnames. For such 34 // validation, see IsCanonicalizedHostCompliant(). 35 NET_EXPORT_PRIVATE bool IsValidDnsName(base::StringPiece dotted_form_name); 36 37 // Like IsValidDnsName() but further validates `dotted_form_name` is not an IP 38 // address (with or without surrounding []) or localhost, as such names would 39 // not be suitable for DNS queries or for use as DNS record names or alias 40 // target names. 41 NET_EXPORT_PRIVATE bool IsValidDnsRecordName( 42 base::StringPiece dotted_form_name); 43 44 // Convert a dotted-form DNS name to network wire format. Returns nullopt if 45 // input is not valid for conversion (equivalent validity can be checked using 46 // IsValidDnsName()). If `require_valid_internet_hostname` is true, also returns 47 // nullopt if input is not a valid internet hostname (equivalent validity can be 48 // checked using net::IsCanonicalizedHostCompliant()). 49 NET_EXPORT_PRIVATE absl::optional<std::vector<uint8_t>> DottedNameToNetwork( 50 base::StringPiece dotted_form_name, 51 bool require_valid_internet_hostname = false); 52 53 // Converts a domain in DNS format to a dotted string. Excludes the dot at the 54 // end. Returns nullopt on malformed input. 55 // 56 // If `require_complete` is true, input will be considered malformed if it does 57 // not contain a terminating zero-length label. If false, assumes the standard 58 // terminating zero-length label at the end if not included in the input. 59 // 60 // DNS name compression (see RFC 1035, section 4.1.4) is disallowed and 61 // considered malformed. To handle a potentially compressed name, in a 62 // DnsResponse object, use DnsRecordParser::ReadName(). 63 NET_EXPORT_PRIVATE absl::optional<std::string> NetworkToDottedName( 64 base::span<const uint8_t> dns_network_wire_name, 65 bool require_complete = false); 66 NET_EXPORT_PRIVATE absl::optional<std::string> NetworkToDottedName( 67 base::StringPiece dns_network_wire_name, 68 bool require_complete = false); 69 NET_EXPORT_PRIVATE absl::optional<std::string> NetworkToDottedName( 70 base::BigEndianReader& reader, 71 bool require_complete = false); 72 73 // Canonicalize `name` as a URL hostname if able. If unable (typically if a name 74 // is not a valid URL hostname), returns `name` without change because such a 75 // name could still be a valid DNS name. 76 NET_EXPORT_PRIVATE std::string UrlCanonicalizeNameIfAble( 77 base::StringPiece name); 78 79 // std::map-compliant Compare for two domain names. Works for any valid 80 // dotted-format or network-wire-format names. Returns true iff `lhs` is before 81 // `rhs` in strict weak ordering. 82 class NET_EXPORT_PRIVATE DomainNameComparator { 83 public: operator()84 bool operator()(base::StringPiece lhs, base::StringPiece rhs) const { 85 // This works for dotted format or network-wire format as long as the names 86 // are valid because valid network-wire names have labels of max 63 bytes 87 // and thus will never have label length prefixes high enough to be 88 // misinterpreted as capital letters ('A' is 65). 89 return base::CompareCaseInsensitiveASCII(lhs, rhs) < 0; 90 } 91 }; 92 93 } // namespace net::dns_names_util 94 95 #endif // NET_DNS_DNS_NAMES_UTIL_H_ 96