blob: 7c96ed33cc6f214c132b9f8837a27e5ba220ba6f [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/*
Alexander Afanasyev3bdc1de2018-04-03 17:33:31 -04003 * Copyright (c) 2014-2018, 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
Yanbiao Liafb20592017-08-03 16:20:46 -070028#include <ndn-cxx/net/address-converter.hpp>
Davide Pesavento89567d32016-11-19 16:39:45 +010029#include <boost/utility/value_init.hpp>
Davide Pesaventoac767aa2016-11-19 18:17:35 +010030#include <algorithm>
Alexander Afanasyev3bdc1de2018-04-03 17:33:31 -040031#include <cctype>
Davide Pesavento89567d32016-11-19 16:39:45 +010032
Alexander Afanasyev689f0e92014-11-09 12:09:00 -080033namespace nfd {
Alexander Afanasyev82afa1a2014-03-20 16:56:56 -070034
Davide Pesavento89567d32016-11-19 16:39:45 +010035Network::Network() = default;
36
37Network::Network(const boost::asio::ip::address& minAddress,
38 const boost::asio::ip::address& maxAddress)
39 : m_minAddress(minAddress)
40 , m_maxAddress(maxAddress)
Alexander Afanasyev82afa1a2014-03-20 16:56:56 -070041{
Alexander Afanasyev689f0e92014-11-09 12:09:00 -080042}
Alexander Afanasyev82afa1a2014-03-20 16:56:56 -070043
Alexander Afanasyev689f0e92014-11-09 12:09:00 -080044const Network&
45Network::getMaxRangeV4()
46{
47 using boost::asio::ip::address_v4;
Davide Pesavento89567d32016-11-19 16:39:45 +010048 static Network range{address_v4{}, address_v4{0xffffffff}};
Alexander Afanasyev689f0e92014-11-09 12:09:00 -080049 return range;
50}
Alexander Afanasyev82afa1a2014-03-20 16:56:56 -070051
Alexander Afanasyev689f0e92014-11-09 12:09:00 -080052const Network&
53Network::getMaxRangeV6()
54{
55 using boost::asio::ip::address_v6;
56 static address_v6::bytes_type maxV6 = {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
57 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}};
Davide Pesavento89567d32016-11-19 16:39:45 +010058 static Network range{address_v6{}, address_v6{maxV6}};
Alexander Afanasyev689f0e92014-11-09 12:09:00 -080059 return range;
60}
Alexander Afanasyev82afa1a2014-03-20 16:56:56 -070061
susmit91e1d7c2016-10-03 16:16:57 -060062bool
63Network::isValidCidr(const std::string& cidr)
64{
Davide Pesaventoac767aa2016-11-19 18:17:35 +010065 auto pos = cidr.find('/');
66 if (pos == std::string::npos) {
Davide Pesavento89567d32016-11-19 16:39:45 +010067 return false;
68 }
susmit91e1d7c2016-10-03 16:16:57 -060069
Davide Pesaventoac767aa2016-11-19 18:17:35 +010070 try {
Alexander Afanasyev3bdc1de2018-04-03 17:33:31 -040071 boost::lexical_cast<Network>(cidr);
72 return true;
Davide Pesaventoac767aa2016-11-19 18:17:35 +010073 }
74 catch (const boost::bad_lexical_cast&) {
75 return false;
76 }
susmit91e1d7c2016-10-03 16:16:57 -060077}
Alexander Afanasyev82afa1a2014-03-20 16:56:56 -070078
Alexander Afanasyev689f0e92014-11-09 12:09:00 -080079std::ostream&
Alexander Afanasyev82afa1a2014-03-20 16:56:56 -070080operator<<(std::ostream& os, const Network& network)
81{
Davide Pesavento89567d32016-11-19 16:39:45 +010082 return os << network.m_minAddress << " <-> " << network.m_maxAddress;
Alexander Afanasyev82afa1a2014-03-20 16:56:56 -070083}
84
Alexander Afanasyev689f0e92014-11-09 12:09:00 -080085std::istream&
Alexander Afanasyev82afa1a2014-03-20 16:56:56 -070086operator>>(std::istream& is, Network& network)
87{
Davide Pesavento89567d32016-11-19 16:39:45 +010088 namespace ip = boost::asio::ip;
Alexander Afanasyev82afa1a2014-03-20 16:56:56 -070089
90 std::string networkStr;
91 is >> networkStr;
92
93 size_t position = networkStr.find('/');
Davide Pesavento89567d32016-11-19 16:39:45 +010094 if (position == std::string::npos) {
Alexander Afanasyev3bdc1de2018-04-03 17:33:31 -040095 try {
96 network.m_minAddress = ndn::ip::addressFromString(networkStr);
97 network.m_maxAddress = ndn::ip::addressFromString(networkStr);
98 }
99 catch (const boost::system::system_error&) {
100 is.setstate(std::ios::failbit);
101 return is;
102 }
Davide Pesavento89567d32016-11-19 16:39:45 +0100103 }
104 else {
Alexander Afanasyev3bdc1de2018-04-03 17:33:31 -0400105 boost::system::error_code ec;
106 ip::address address = ndn::ip::addressFromString(networkStr.substr(0, position), ec);
107 if (ec) {
108 is.setstate(std::ios::failbit);
109 return is;
110 }
111
112 auto prefixLenStr = networkStr.substr(position + 1);
113 if (!std::all_of(prefixLenStr.begin(), prefixLenStr.end(),
114 [] (unsigned char c) { return std::isdigit(c); })) {
115 is.setstate(std::ios::failbit);
116 return is;
117 }
118 size_t mask;
119 try {
120 mask = boost::lexical_cast<size_t>(prefixLenStr);
121 }
122 catch (const boost::bad_lexical_cast&) {
123 is.setstate(std::ios::failbit);
124 return is;
125 }
Davide Pesavento89567d32016-11-19 16:39:45 +0100126
127 if (address.is_v4()) {
Alexander Afanasyev3bdc1de2018-04-03 17:33:31 -0400128 if (mask > 32) {
129 is.setstate(std::ios::failbit);
130 return is;
131 }
132
Davide Pesavento89567d32016-11-19 16:39:45 +0100133 ip::address_v4::bytes_type maskBytes = boost::initialized_value;
134 for (size_t i = 0; i < mask; i++) {
135 size_t byteId = i / 8;
136 size_t bitIndex = 7 - i % 8;
137 maskBytes[byteId] |= (1 << bitIndex);
138 }
139
140 ip::address_v4::bytes_type addressBytes = address.to_v4().to_bytes();
141 ip::address_v4::bytes_type min;
142 ip::address_v4::bytes_type max;
143
144 for (size_t i = 0; i < addressBytes.size(); i++) {
145 min[i] = addressBytes[i] & maskBytes[i];
146 max[i] = addressBytes[i] | ~(maskBytes[i]);
147 }
148
149 network.m_minAddress = ip::address_v4(min);
150 network.m_maxAddress = ip::address_v4(max);
Alexander Afanasyev82afa1a2014-03-20 16:56:56 -0700151 }
Davide Pesavento89567d32016-11-19 16:39:45 +0100152 else {
Alexander Afanasyev3bdc1de2018-04-03 17:33:31 -0400153 if (mask > 128) {
154 is.setstate(std::ios::failbit);
155 return is;
156 }
157
Davide Pesavento89567d32016-11-19 16:39:45 +0100158 ip::address_v6::bytes_type maskBytes = boost::initialized_value;
159 for (size_t i = 0; i < mask; i++) {
160 size_t byteId = i / 8;
161 size_t bitIndex = 7 - i % 8;
162 maskBytes[byteId] |= (1 << bitIndex);
163 }
Alexander Afanasyev82afa1a2014-03-20 16:56:56 -0700164
Davide Pesavento89567d32016-11-19 16:39:45 +0100165 ip::address_v6::bytes_type addressBytes = address.to_v6().to_bytes();
166 ip::address_v6::bytes_type min;
167 ip::address_v6::bytes_type max;
Alexander Afanasyev82afa1a2014-03-20 16:56:56 -0700168
Davide Pesavento89567d32016-11-19 16:39:45 +0100169 for (size_t i = 0; i < addressBytes.size(); i++) {
170 min[i] = addressBytes[i] & maskBytes[i];
171 max[i] = addressBytes[i] | ~(maskBytes[i]);
172 }
Alexander Afanasyev82afa1a2014-03-20 16:56:56 -0700173
Davide Pesavento89567d32016-11-19 16:39:45 +0100174 network.m_minAddress = ip::address_v6(min);
175 network.m_maxAddress = ip::address_v6(max);
Alexander Afanasyev82afa1a2014-03-20 16:56:56 -0700176 }
Davide Pesavento89567d32016-11-19 16:39:45 +0100177 }
178
Alexander Afanasyev82afa1a2014-03-20 16:56:56 -0700179 return is;
180}
181
Alexander Afanasyev689f0e92014-11-09 12:09:00 -0800182} // namespace nfd