blob: 08a1197ad6a9173a0c45c3c73100cfc9d1c273ae [file] [log] [blame]
Alexander Afanasyev82afa1a2014-03-20 16:56:56 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Yanbiao Liafb20592017-08-03 16:20:46 -07002/*
Davide Pesavento191a7a22023-05-17 22:40:43 -04003 * Copyright (c) 2014-2023, Regents of the University of California,
susmit91e1d7c2016-10-03 16:16:57 -06004 * Arizona Board of Regents,
5 * Colorado State University,
6 * University Pierre & Marie Curie, Sorbonne University,
7 * Washington University in St. Louis,
8 * Beijing Institute of Technology,
Alexander Afanasyev3bdc1de2018-04-03 17:33:31 -04009 * The University of Memphis.
Alexander Afanasyev9bcbc7c2014-04-06 19:37:37 -070010 *
11 * This file is part of NFD (Named Data Networking Forwarding Daemon).
12 * See AUTHORS.md for complete list of NFD authors and contributors.
13 *
14 * NFD is free software: you can redistribute it and/or modify it under the terms
15 * of the GNU General Public License as published by the Free Software Foundation,
16 * either version 3 of the License, or (at your option) any later version.
17 *
18 * NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
19 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
20 * PURPOSE. See the GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License along with
23 * NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
Yanbiao Liafb20592017-08-03 16:20:46 -070024 */
Alexander Afanasyev82afa1a2014-03-20 16:56:56 -070025
Alexander Afanasyev689f0e92014-11-09 12:09:00 -080026#include "network.hpp"
Alexander Afanasyev82afa1a2014-03-20 16:56:56 -070027
Davide Pesaventoa9b09b62022-06-04 14:07:25 -040028#include <boost/lexical_cast.hpp>
Davide Pesavento89567d32016-11-19 16:39:45 +010029#include <boost/utility/value_init.hpp>
Davide Pesaventoa9b09b62022-06-04 14:07:25 -040030
Davide Pesaventoac767aa2016-11-19 18:17:35 +010031#include <algorithm>
Alexander Afanasyev3bdc1de2018-04-03 17:33:31 -040032#include <cctype>
Davide Pesaventoa9b09b62022-06-04 14:07:25 -040033#include <istream>
34#include <ostream>
Davide Pesavento89567d32016-11-19 16:39:45 +010035
Alexander Afanasyev689f0e92014-11-09 12:09:00 -080036namespace nfd {
Alexander Afanasyev82afa1a2014-03-20 16:56:56 -070037
Davide Pesavento89567d32016-11-19 16:39:45 +010038Network::Network() = default;
39
40Network::Network(const boost::asio::ip::address& minAddress,
41 const boost::asio::ip::address& maxAddress)
42 : m_minAddress(minAddress)
43 , m_maxAddress(maxAddress)
Alexander Afanasyev82afa1a2014-03-20 16:56:56 -070044{
Alexander Afanasyev689f0e92014-11-09 12:09:00 -080045}
Alexander Afanasyev82afa1a2014-03-20 16:56:56 -070046
Alexander Afanasyev689f0e92014-11-09 12:09:00 -080047const Network&
48Network::getMaxRangeV4()
49{
50 using boost::asio::ip::address_v4;
Davide Pesavento89567d32016-11-19 16:39:45 +010051 static Network range{address_v4{}, address_v4{0xffffffff}};
Alexander Afanasyev689f0e92014-11-09 12:09:00 -080052 return range;
53}
Alexander Afanasyev82afa1a2014-03-20 16:56:56 -070054
Alexander Afanasyev689f0e92014-11-09 12:09:00 -080055const Network&
56Network::getMaxRangeV6()
57{
58 using boost::asio::ip::address_v6;
59 static address_v6::bytes_type maxV6 = {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
60 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}};
Davide Pesavento89567d32016-11-19 16:39:45 +010061 static Network range{address_v6{}, address_v6{maxV6}};
Alexander Afanasyev689f0e92014-11-09 12:09:00 -080062 return range;
63}
Alexander Afanasyev82afa1a2014-03-20 16:56:56 -070064
susmit91e1d7c2016-10-03 16:16:57 -060065bool
Davide Pesavento191a7a22023-05-17 22:40:43 -040066Network::isValidCidr(std::string_view cidr) noexcept
susmit91e1d7c2016-10-03 16:16:57 -060067{
Davide Pesaventoac767aa2016-11-19 18:17:35 +010068 auto pos = cidr.find('/');
69 if (pos == std::string::npos) {
Davide Pesavento89567d32016-11-19 16:39:45 +010070 return false;
71 }
susmit91e1d7c2016-10-03 16:16:57 -060072
Davide Pesaventoac767aa2016-11-19 18:17:35 +010073 try {
Alexander Afanasyev3bdc1de2018-04-03 17:33:31 -040074 boost::lexical_cast<Network>(cidr);
75 return true;
Davide Pesaventoac767aa2016-11-19 18:17:35 +010076 }
77 catch (const boost::bad_lexical_cast&) {
78 return false;
79 }
susmit91e1d7c2016-10-03 16:16:57 -060080}
Alexander Afanasyev82afa1a2014-03-20 16:56:56 -070081
Alexander Afanasyev689f0e92014-11-09 12:09:00 -080082std::ostream&
Alexander Afanasyev82afa1a2014-03-20 16:56:56 -070083operator<<(std::ostream& os, const Network& network)
84{
Davide Pesavento89567d32016-11-19 16:39:45 +010085 return os << network.m_minAddress << " <-> " << network.m_maxAddress;
Alexander Afanasyev82afa1a2014-03-20 16:56:56 -070086}
87
Alexander Afanasyev689f0e92014-11-09 12:09:00 -080088std::istream&
Alexander Afanasyev82afa1a2014-03-20 16:56:56 -070089operator>>(std::istream& is, Network& network)
90{
Davide Pesavento89567d32016-11-19 16:39:45 +010091 namespace ip = boost::asio::ip;
Alexander Afanasyev82afa1a2014-03-20 16:56:56 -070092
93 std::string networkStr;
94 is >> networkStr;
95
96 size_t position = networkStr.find('/');
Davide Pesavento89567d32016-11-19 16:39:45 +010097 if (position == std::string::npos) {
Alexander Afanasyev3bdc1de2018-04-03 17:33:31 -040098 try {
Davide Pesavento9c33b902018-05-20 01:30:29 -040099 network.m_minAddress = ip::address::from_string(networkStr);
100 network.m_maxAddress = ip::address::from_string(networkStr);
Alexander Afanasyev3bdc1de2018-04-03 17:33:31 -0400101 }
102 catch (const boost::system::system_error&) {
103 is.setstate(std::ios::failbit);
104 return is;
105 }
Davide Pesavento89567d32016-11-19 16:39:45 +0100106 }
107 else {
Alexander Afanasyev3bdc1de2018-04-03 17:33:31 -0400108 boost::system::error_code ec;
Davide Pesavento9c33b902018-05-20 01:30:29 -0400109 auto address = ip::address::from_string(networkStr.substr(0, position), ec);
Alexander Afanasyev3bdc1de2018-04-03 17:33:31 -0400110 if (ec) {
111 is.setstate(std::ios::failbit);
112 return is;
113 }
114
115 auto prefixLenStr = networkStr.substr(position + 1);
116 if (!std::all_of(prefixLenStr.begin(), prefixLenStr.end(),
117 [] (unsigned char c) { return std::isdigit(c); })) {
118 is.setstate(std::ios::failbit);
119 return is;
120 }
121 size_t mask;
122 try {
123 mask = boost::lexical_cast<size_t>(prefixLenStr);
124 }
125 catch (const boost::bad_lexical_cast&) {
126 is.setstate(std::ios::failbit);
127 return is;
128 }
Davide Pesavento89567d32016-11-19 16:39:45 +0100129
130 if (address.is_v4()) {
Alexander Afanasyev3bdc1de2018-04-03 17:33:31 -0400131 if (mask > 32) {
132 is.setstate(std::ios::failbit);
133 return is;
134 }
135
Davide Pesavento89567d32016-11-19 16:39:45 +0100136 ip::address_v4::bytes_type maskBytes = boost::initialized_value;
137 for (size_t i = 0; i < mask; i++) {
138 size_t byteId = i / 8;
139 size_t bitIndex = 7 - i % 8;
140 maskBytes[byteId] |= (1 << bitIndex);
141 }
142
143 ip::address_v4::bytes_type addressBytes = address.to_v4().to_bytes();
144 ip::address_v4::bytes_type min;
145 ip::address_v4::bytes_type max;
146
147 for (size_t i = 0; i < addressBytes.size(); i++) {
148 min[i] = addressBytes[i] & maskBytes[i];
149 max[i] = addressBytes[i] | ~(maskBytes[i]);
150 }
151
152 network.m_minAddress = ip::address_v4(min);
153 network.m_maxAddress = ip::address_v4(max);
Alexander Afanasyev82afa1a2014-03-20 16:56:56 -0700154 }
Davide Pesavento89567d32016-11-19 16:39:45 +0100155 else {
Alexander Afanasyev3bdc1de2018-04-03 17:33:31 -0400156 if (mask > 128) {
157 is.setstate(std::ios::failbit);
158 return is;
159 }
160
Davide Pesavento89567d32016-11-19 16:39:45 +0100161 ip::address_v6::bytes_type maskBytes = boost::initialized_value;
162 for (size_t i = 0; i < mask; i++) {
163 size_t byteId = i / 8;
164 size_t bitIndex = 7 - i % 8;
165 maskBytes[byteId] |= (1 << bitIndex);
166 }
Alexander Afanasyev82afa1a2014-03-20 16:56:56 -0700167
Davide Pesavento89567d32016-11-19 16:39:45 +0100168 ip::address_v6::bytes_type addressBytes = address.to_v6().to_bytes();
169 ip::address_v6::bytes_type min;
170 ip::address_v6::bytes_type max;
Alexander Afanasyev82afa1a2014-03-20 16:56:56 -0700171
Davide Pesavento89567d32016-11-19 16:39:45 +0100172 for (size_t i = 0; i < addressBytes.size(); i++) {
173 min[i] = addressBytes[i] & maskBytes[i];
174 max[i] = addressBytes[i] | ~(maskBytes[i]);
175 }
Alexander Afanasyev82afa1a2014-03-20 16:56:56 -0700176
Davide Pesavento89567d32016-11-19 16:39:45 +0100177 network.m_minAddress = ip::address_v6(min);
178 network.m_maxAddress = ip::address_v6(max);
Alexander Afanasyev82afa1a2014-03-20 16:56:56 -0700179 }
Davide Pesavento89567d32016-11-19 16:39:45 +0100180 }
181
Alexander Afanasyev82afa1a2014-03-20 16:56:56 -0700182 return is;
183}
184
Alexander Afanasyev689f0e92014-11-09 12:09:00 -0800185} // namespace nfd