Line data Source code
1 : #pragma once 2 : 3 : #include <cstddef> 4 : #include <string> 5 : #include <vector> 6 : 7 : #include "envoy/config/core/v3/address.pb.h" 8 : #include "envoy/network/address.h" 9 : 10 : #include "source/common/protobuf/protobuf.h" 11 : 12 : #include "xds/core/v3/cidr.pb.h" 13 : 14 : namespace Envoy { 15 : namespace Network { 16 : namespace Address { 17 : 18 : /** 19 : * A "Classless Inter-Domain Routing" range of internet addresses, aka a CIDR range, consisting 20 : * of an Ip address and a count of leading bits included in the mask. Other than those leading 21 : * bits, all of the other bits of the Ip address are zero. For more info, see RFC1519 or 22 : * https://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing. 23 : */ 24 : class CidrRange { 25 : public: 26 : /** 27 : * Constructs an uninitialized range: length == -1, and there is no associated address. 28 : */ 29 : CidrRange(); 30 : 31 0 : CidrRange(const CidrRange& other) = default; 32 1269 : CidrRange(CidrRange&& other) = default; 33 : 34 : /** 35 : * Overwrites this with other. 36 : */ 37 : CidrRange& operator=(const CidrRange& other); 38 : 39 : /** 40 : * @return true if the ranges are identical. 41 : */ 42 : bool operator==(const CidrRange& other) const; 43 : 44 : /** 45 : * @return Ip address data IFF length >= 0, otherwise nullptr. 46 : */ 47 : const Ip* ip() const; 48 : 49 : /** 50 : * TODO(jamessynge) Consider making this absl::optional<int> length, or modifying the create() 51 : * methods below to return absl::optional<CidrRange> (the latter is probably better). 52 : * @return the number of bits of the address that are included in the mask. -1 if uninitialized 53 : * or invalid, else in the range 0 to 32 for IPv4, and 0 to 128 for IPv6. 54 : */ 55 : int length() const; 56 : 57 : /** 58 : * @return true if the address argument is in the range of this object, false if not, including 59 : if the range is uninitialized or if the argument is not of the same IpVersion. 60 : */ 61 : bool isInRange(const Instance& address) const; 62 : 63 : /** 64 : * @return a human readable string for the range. This string will be in the following format: 65 : * - For IPv4 ranges: "1.2.3.4/32" or "10.240.0.0/16" 66 : * - For IPv6 ranges: "1234:5678::f/128" or "1234:5678::/64" 67 : */ 68 : std::string asString() const; 69 : 70 : /** 71 : * @return true if this instance is valid; address != nullptr && length is appropriate for the 72 : * IP version (these are checked during construction, and reduced down to a check of 73 : * the length). 74 : */ 75 0 : bool isValid() const { return length_ >= 0; } 76 : 77 : /** 78 : * TODO(ccaraman): Update CidrRange::create to support only constructing valid ranges. 79 : * @return a CidrRange instance with the specified address and length, modified so that the only 80 : * bits that might be non-zero are in the high-order length bits, and so that length is 81 : * in the appropriate range (0 to 32 for IPv4, 0 to 128 for IPv6). If the address or 82 : * length is invalid, then the range will be invalid (i.e. length == -1). 83 : */ 84 : static CidrRange create(InstanceConstSharedPtr address, int length); 85 : static CidrRange create(const std::string& address, int length); 86 : 87 : /** 88 : * Constructs an CidrRange from a string with this format (same as returned 89 : * by CidrRange::asString above): 90 : * <address>/<length> e.g. "10.240.0.0/16" or "1234:5678::/64" 91 : * TODO(ccaraman): Update CidrRange::create to support only constructing valid ranges. 92 : * @return a CidrRange instance with the specified address and length if parsed successfully, 93 : * else with no address and a length of -1. 94 : */ 95 : static CidrRange create(const std::string& range); 96 : 97 : /** 98 : * Constructs a CidrRange from envoy::config::core::v3::CidrRange. 99 : * TODO(ccaraman): Update CidrRange::create to support only constructing valid ranges. 100 : */ 101 : static CidrRange create(const envoy::config::core::v3::CidrRange& cidr); 102 : 103 : /** 104 : * Constructs a CidrRange from xds::core::v3::CidrRange. 105 : * TODO(ccaraman): Update CidrRange::create to support only constructing valid ranges. 106 : */ 107 : static CidrRange create(const xds::core::v3::CidrRange& cidr); 108 : 109 : /** 110 : * Given an IP address and a length of high order bits to keep, returns an address 111 : * where those high order bits are unmodified, and the remaining bits are all zero. 112 : * length_io is reduced to be at most 32 for IPv4 address and at most 128 for IPv6 113 : * addresses. If the address is invalid or the length is less than zero, then *length_io 114 : * is set to -1 and nullptr is returned. 115 : * @return a pointer to an address where the high order *length_io bits are unmodified 116 : * from address, and *length_io is in the range 0 to N, where N is the number of bits 117 : * in an address of the IP version (i.e. address->ip()->version()). 118 : */ 119 : static InstanceConstSharedPtr truncateIpAddressAndLength(InstanceConstSharedPtr address, 120 : int* length_io); 121 : 122 : private: 123 : CidrRange(InstanceConstSharedPtr address, int length); 124 : 125 : InstanceConstSharedPtr address_; 126 : int length_; 127 : }; 128 : 129 : /** 130 : * Class for keeping a list of CidrRanges, and then determining whether an 131 : * IP address is in the CidrRange list. 132 : */ 133 : class IpList { 134 : public: 135 : static absl::StatusOr<std::unique_ptr<IpList>> 136 : create(const Protobuf::RepeatedPtrField<envoy::config::core::v3::CidrRange>& cidrs); 137 : 138 0 : IpList() = default; 139 : 140 : bool contains(const Instance& address) const; 141 0 : size_t getIpListSize() const { return ip_list_.size(); }; 142 0 : const std::string& error() const { return error_; } 143 : 144 : private: 145 : explicit IpList(const Protobuf::RepeatedPtrField<envoy::config::core::v3::CidrRange>& cidrs); 146 : std::vector<CidrRange> ip_list_; 147 : std::string error_; 148 : }; 149 : 150 : } // namespace Address 151 : } // namespace Network 152 : } // namespace Envoy