1 2 /** 3 * Copyright (C) 2018-present MongoDB, Inc. 4 * 5 * This program is free software: you can redistribute it and/or modify 6 * it under the terms of the Server Side Public License, version 1, 7 * as published by MongoDB, Inc. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * Server Side Public License for more details. 13 * 14 * You should have received a copy of the Server Side Public License 15 * along with this program. If not, see 16 * <http://www.mongodb.com/licensing/server-side-public-license>. 17 * 18 * As a special exception, the copyright holders give permission to link the 19 * code of portions of this program with the OpenSSL library under certain 20 * conditions as described in each individual source file and distribute 21 * linked combinations including the program with the OpenSSL library. You 22 * must comply with the Server Side Public License in all respects for 23 * all of the code used other than as permitted herein. If you modify file(s) 24 * with this exception, you may extend this exception to your version of the 25 * file(s), but you are not obligated to do so. If you do not wish to do so, 26 * delete this exception statement from your version. If you delete this 27 * exception statement from all source files in the program, then also delete 28 * it in the license file. 29 */ 30 31 #pragma once 32 33 #include "mongo/base/status_with.h" 34 #include "mongo/base/string_data.h" 35 #include "mongo/bson/bsonelement.h" 36 #include "mongo/bson/bsonmisc.h" 37 38 #include <stdexcept> 39 #include <string> 40 41 #ifndef _WIN32 42 #include <sys/socket.h> 43 #endif 44 45 namespace mongo { 46 47 /** 48 * CIDR (Classless Inter-Domain Routing) 49 */ 50 class CIDR { 51 public: 52 explicit CIDR(StringData); 53 54 /** 55 * If the given BSONElement represents a valid CIDR range, 56 * constructs and returns the CIDR. 57 * Otherwise returns an error. 58 */ 59 static StatusWith<CIDR> parse(BSONElement from) noexcept; 60 61 /** 62 * If the given string represents a valid CIDR range, 63 * constructs and returns the CIDR. 64 * Otherwise returns an error. 65 */ 66 static StatusWith<CIDR> parse(StringData from) noexcept; 67 68 /** 69 * Returns true if the provided address range is contained 70 * entirely within this one, false otherwise. 71 */ contains(const CIDR & cidr)72 bool contains(const CIDR& cidr) const { 73 if ((_family != cidr._family) || (_len > cidr._len)) { 74 return false; 75 } 76 77 auto bytes = _len / 8; 78 auto const range = _ip.begin(); 79 auto const ip = cidr._ip.begin(); 80 if (!std::equal(range, range + bytes, ip, ip + bytes)) { 81 return false; 82 } 83 84 if ((_len % 8) == 0) { 85 return true; 86 } 87 88 auto mask = (0xFF << (8 - (_len % 8))) & 0xFF; 89 return (_ip[bytes] & mask) == (cidr._ip[bytes] & mask); 90 } 91 92 friend bool operator==(const CIDR& lhs, const CIDR& rhs); 93 friend bool operator!=(const CIDR& lhs, const CIDR& rhs) { 94 return !(lhs == rhs); 95 } 96 friend std::ostream& operator<<(std::ostream& s, const CIDR& rhs); 97 friend StringBuilder& operator<<(StringBuilder& s, const CIDR& rhs); 98 99 /** 100 * Return a string representation of this CIDR (i.e. "169.254.0.0/16") 101 */ toString()102 std::string toString() const { 103 StringBuilder s; 104 s << *this; 105 return s.str(); 106 } 107 108 private: 109 #ifdef _WIN32 110 using sa_family_t = int; 111 #endif 112 equalityLens()113 auto equalityLens() const { 114 return std::tie(_ip, _family, _len); 115 } 116 117 std::array<std::uint8_t, 16> _ip; 118 sa_family_t _family; 119 std::uint8_t _len; 120 }; 121 122 inline bool operator==(const CIDR& lhs, const CIDR& rhs) { 123 return lhs.equalityLens() == rhs.equalityLens(); 124 } 125 126 std::ostream& operator<<(std::ostream& s, const CIDR& cidr); 127 StringBuilder& operator<<(StringBuilder& s, const CIDR& cidr); 128 129 /** 130 * Supports use of CIDR with the BSON macro: 131 * BSON("cidr" << cidr) -> { cidr: "..." } 132 */ 133 template <> 134 BSONObjBuilder& BSONObjBuilderValueStream::operator<<<CIDR>(CIDR value); 135 136 } // namespace mongo 137