// Copyright 2015 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifdef UNSAFE_BUFFERS_BUILD // TODO(crbug.com/40284755): Remove this and spanify to fix the errors. #pragma allow_unsafe_buffers #endif #ifndef NET_BASE_IP_ADDRESS_H_ #define NET_BASE_IP_ADDRESS_H_ #include <stddef.h> #include <stdint.h> #include <algorithm> #include <array> #include <optional> #include <string> #include <string_view> #include <vector> #include "base/check_op.h" #include "base/containers/span.h" #include "base/values.h" #include "net/base/net_export.h" namespace net { // Helper class to represent the sequence of bytes in an IP address. // A vector<uint8_t> would be simpler but incurs heap allocation, so // IPAddressBytes uses a fixed size array. class NET_EXPORT IPAddressBytes { … }; class NET_EXPORT IPAddress { … }; IPAddressList; // Returns the canonical string representation of an IP address along with its // port. For example: "192.168.0.1:99" or "[::1]:80". NET_EXPORT std::string IPAddressToStringWithPort(const IPAddress& address, uint16_t port); // Returns the address as a sequence of bytes in network-byte-order. NET_EXPORT std::string IPAddressToPackedString(const IPAddress& address); // Converts an IPv4 address to an IPv4-mapped IPv6 address. // For example 192.168.0.1 would be converted to ::ffff:192.168.0.1. NET_EXPORT IPAddress ConvertIPv4ToIPv4MappedIPv6(const IPAddress& address); // Converts an IPv4-mapped IPv6 address to IPv4 address. Should only be called // on IPv4-mapped IPv6 addresses. NET_EXPORT IPAddress ConvertIPv4MappedIPv6ToIPv4(const IPAddress& address); // Compares an IP address to see if it falls within the specified IP block. // Returns true if it does, false otherwise. // // The IP block is given by (|ip_prefix|, |prefix_length_in_bits|) -- any // IP address whose |prefix_length_in_bits| most significant bits match // |ip_prefix| will be matched. // // In cases when an IPv4 address is being compared to an IPv6 address prefix // and vice versa, the IPv4 addresses will be converted to IPv4-mapped // (IPv6) addresses. NET_EXPORT bool IPAddressMatchesPrefix(const IPAddress& ip_address, const IPAddress& ip_prefix, size_t prefix_length_in_bits); // Parses an IP block specifier from CIDR notation to an // (IP address, prefix length) pair. Returns true on success and fills // |*ip_address| with the numeric value of the IP address and sets // |*prefix_length_in_bits| with the length of the prefix. On failure, // |ip_address| will be cleared to an empty value. // // CIDR notation literals can use either IPv4 or IPv6 literals. Some examples: // // 10.10.3.1/20 // a:b:c::/46 // ::1/128 NET_EXPORT bool ParseCIDRBlock(std::string_view cidr_literal, IPAddress* ip_address, size_t* prefix_length_in_bits); // Parses a URL-safe IP literal (see RFC 3986, Sec 3.2.2) to its numeric value. // Returns true on success, and fills |ip_address| with the numeric value. // In other words, |hostname| must be an IPv4 literal, or an IPv6 literal // surrounded by brackets as in [::1]. On failure |ip_address| may have been // overwritten and could contain an invalid IPAddress. [[nodiscard]] NET_EXPORT bool ParseURLHostnameToAddress( std::string_view hostname, IPAddress* ip_address); // Returns number of matching initial bits between the addresses |a1| and |a2|. NET_EXPORT size_t CommonPrefixLength(const IPAddress& a1, const IPAddress& a2); // Computes the number of leading 1-bits in |mask|. NET_EXPORT size_t MaskPrefixLength(const IPAddress& mask); // Checks whether |address| starts with |prefix|. This provides similar // functionality as IPAddressMatchesPrefix() but doesn't perform automatic IPv4 // to IPv4MappedIPv6 conversions and only checks against full bytes. template <size_t N> bool IPAddressStartsWith(const IPAddress& address, const uint8_t (&prefix)[N]) { … } // According to RFC6052 Section 2.2 IPv4-Embedded IPv6 Address Format. // https://www.rfc-editor.org/rfc/rfc6052#section-2.2 // +--+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ // |PL| 0-------------32--40--48--56--64--72--80--88--96--104---------| // +--+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ // |32| prefix |v4(32) | u | suffix | // +--+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ // |40| prefix |v4(24) | u |(8)| suffix | // +--+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ // |48| prefix |v4(16) | u | (16) | suffix | // +--+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ // |56| prefix |(8)| u | v4(24) | suffix | // +--+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ // |64| prefix | u | v4(32) | suffix | // +--+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ // |96| prefix | v4(32) | // +--+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ // // The NAT64/DNS64 translation prefixes has one of the following lengths. enum class Dns64PrefixLength { … }; // Extracts the NAT64 translation prefix from the IPv6 address using the well // known address ipv4only.arpa 192.0.0.170 and 192.0.0.171. // Returns prefix length on success, or Dns64PrefixLength::kInvalid on failure // (when the ipv4only.arpa IPv4 address is not found) NET_EXPORT Dns64PrefixLength ExtractPref64FromIpv4onlyArpaAAAA(const IPAddress& address); // Converts an IPv4 address to an IPv4-embedded IPv6 address using the given // prefix. For example 192.168.0.1 and 64:ff9b::/96 would be converted to // 64:ff9b::192.168.0.1 // Returns converted IPv6 address when prefix_length is not // Dns64PrefixLength::kInvalid, and returns the original IPv4 address when // prefix_length is Dns64PrefixLength::kInvalid. NET_EXPORT IPAddress ConvertIPv4ToIPv4EmbeddedIPv6(const IPAddress& ipv4_address, const IPAddress& ipv6_address, Dns64PrefixLength prefix_length); } // namespace net #endif // NET_BASE_IP_ADDRESS_H_