blob: 3360e6288c16975580dcca29951a3f3dd90635b6 [file] [log] [blame]
Alexander Afanasyev82afa1a2014-03-20 16:56:56 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
susmit91e1d7c2016-10-03 16:16:57 -06003 * Copyright (c) 2014-2016, Regents of the University of California,
4 * 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,
9 * 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/>.
24 **/
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 Pesavento89567d32016-11-19 16:39:45 +010028#include <boost/utility/value_init.hpp>
Davide Pesaventoac767aa2016-11-19 18:17:35 +010029#include <algorithm>
Davide Pesavento89567d32016-11-19 16:39:45 +010030
Alexander Afanasyev689f0e92014-11-09 12:09:00 -080031namespace nfd {
Alexander Afanasyev82afa1a2014-03-20 16:56:56 -070032
Davide Pesavento89567d32016-11-19 16:39:45 +010033Network::Network() = default;
34
35Network::Network(const boost::asio::ip::address& minAddress,
36 const boost::asio::ip::address& maxAddress)
37 : m_minAddress(minAddress)
38 , m_maxAddress(maxAddress)
Alexander Afanasyev82afa1a2014-03-20 16:56:56 -070039{
Alexander Afanasyev689f0e92014-11-09 12:09:00 -080040}
Alexander Afanasyev82afa1a2014-03-20 16:56:56 -070041
Alexander Afanasyev689f0e92014-11-09 12:09:00 -080042const Network&
43Network::getMaxRangeV4()
44{
45 using boost::asio::ip::address_v4;
Davide Pesavento89567d32016-11-19 16:39:45 +010046 static Network range{address_v4{}, address_v4{0xffffffff}};
Alexander Afanasyev689f0e92014-11-09 12:09:00 -080047 return range;
48}
Alexander Afanasyev82afa1a2014-03-20 16:56:56 -070049
Alexander Afanasyev689f0e92014-11-09 12:09:00 -080050const Network&
51Network::getMaxRangeV6()
52{
53 using boost::asio::ip::address_v6;
54 static address_v6::bytes_type maxV6 = {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
55 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}};
Davide Pesavento89567d32016-11-19 16:39:45 +010056 static Network range{address_v6{}, address_v6{maxV6}};
Alexander Afanasyev689f0e92014-11-09 12:09:00 -080057 return range;
58}
Alexander Afanasyev82afa1a2014-03-20 16:56:56 -070059
susmit91e1d7c2016-10-03 16:16:57 -060060bool
61Network::isValidCidr(const std::string& cidr)
62{
Davide Pesaventoac767aa2016-11-19 18:17:35 +010063 auto pos = cidr.find('/');
64 if (pos == std::string::npos) {
Davide Pesavento89567d32016-11-19 16:39:45 +010065 return false;
66 }
susmit91e1d7c2016-10-03 16:16:57 -060067
Davide Pesavento89567d32016-11-19 16:39:45 +010068 boost::system::error_code invalidIp;
Davide Pesaventoac767aa2016-11-19 18:17:35 +010069 boost::asio::ip::address_v4::from_string(cidr.substr(0, pos), invalidIp);
Davide Pesavento89567d32016-11-19 16:39:45 +010070 if (invalidIp) {
71 return false;
72 }
susmit91e1d7c2016-10-03 16:16:57 -060073
Davide Pesaventoac767aa2016-11-19 18:17:35 +010074 auto prefixLenStr = cidr.substr(pos + 1);
75 if (!std::all_of(prefixLenStr.begin(), prefixLenStr.end(), ::isdigit)) {
Davide Pesavento89567d32016-11-19 16:39:45 +010076 return false;
77 }
Davide Pesaventoac767aa2016-11-19 18:17:35 +010078 int prefixLen = -1;
79 try {
80 prefixLen = boost::lexical_cast<int>(prefixLenStr);
81 }
82 catch (const boost::bad_lexical_cast&) {
83 return false;
84 }
Davide Pesavento89567d32016-11-19 16:39:45 +010085 if (prefixLen < 0 || prefixLen > 32) {
86 return false;
87 }
88
89 return true;
susmit91e1d7c2016-10-03 16:16:57 -060090}
Alexander Afanasyev82afa1a2014-03-20 16:56:56 -070091
Alexander Afanasyev689f0e92014-11-09 12:09:00 -080092std::ostream&
Alexander Afanasyev82afa1a2014-03-20 16:56:56 -070093operator<<(std::ostream& os, const Network& network)
94{
Davide Pesavento89567d32016-11-19 16:39:45 +010095 return os << network.m_minAddress << " <-> " << network.m_maxAddress;
Alexander Afanasyev82afa1a2014-03-20 16:56:56 -070096}
97
Alexander Afanasyev689f0e92014-11-09 12:09:00 -080098std::istream&
Alexander Afanasyev82afa1a2014-03-20 16:56:56 -070099operator>>(std::istream& is, Network& network)
100{
Davide Pesavento89567d32016-11-19 16:39:45 +0100101 namespace ip = boost::asio::ip;
Alexander Afanasyev82afa1a2014-03-20 16:56:56 -0700102
103 std::string networkStr;
104 is >> networkStr;
105
106 size_t position = networkStr.find('/');
Davide Pesavento89567d32016-11-19 16:39:45 +0100107 if (position == std::string::npos) {
108 network.m_minAddress = ip::address::from_string(networkStr);
109 network.m_maxAddress = ip::address::from_string(networkStr);
110 }
111 else {
112 ip::address address = ip::address::from_string(networkStr.substr(0, position));
113 size_t mask = boost::lexical_cast<size_t>(networkStr.substr(position+1));
114
115 if (address.is_v4()) {
116 ip::address_v4::bytes_type maskBytes = boost::initialized_value;
117 for (size_t i = 0; i < mask; i++) {
118 size_t byteId = i / 8;
119 size_t bitIndex = 7 - i % 8;
120 maskBytes[byteId] |= (1 << bitIndex);
121 }
122
123 ip::address_v4::bytes_type addressBytes = address.to_v4().to_bytes();
124 ip::address_v4::bytes_type min;
125 ip::address_v4::bytes_type max;
126
127 for (size_t i = 0; i < addressBytes.size(); i++) {
128 min[i] = addressBytes[i] & maskBytes[i];
129 max[i] = addressBytes[i] | ~(maskBytes[i]);
130 }
131
132 network.m_minAddress = ip::address_v4(min);
133 network.m_maxAddress = ip::address_v4(max);
Alexander Afanasyev82afa1a2014-03-20 16:56:56 -0700134 }
Davide Pesavento89567d32016-11-19 16:39:45 +0100135 else {
136 ip::address_v6::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 }
Alexander Afanasyev82afa1a2014-03-20 16:56:56 -0700142
Davide Pesavento89567d32016-11-19 16:39:45 +0100143 ip::address_v6::bytes_type addressBytes = address.to_v6().to_bytes();
144 ip::address_v6::bytes_type min;
145 ip::address_v6::bytes_type max;
Alexander Afanasyev82afa1a2014-03-20 16:56:56 -0700146
Davide Pesavento89567d32016-11-19 16:39:45 +0100147 for (size_t i = 0; i < addressBytes.size(); i++) {
148 min[i] = addressBytes[i] & maskBytes[i];
149 max[i] = addressBytes[i] | ~(maskBytes[i]);
150 }
Alexander Afanasyev82afa1a2014-03-20 16:56:56 -0700151
Davide Pesavento89567d32016-11-19 16:39:45 +0100152 network.m_minAddress = ip::address_v6(min);
153 network.m_maxAddress = ip::address_v6(max);
Alexander Afanasyev82afa1a2014-03-20 16:56:56 -0700154 }
Davide Pesavento89567d32016-11-19 16:39:45 +0100155 }
156
Alexander Afanasyev82afa1a2014-03-20 16:56:56 -0700157 return is;
158}
159
Alexander Afanasyev689f0e92014-11-09 12:09:00 -0800160} // namespace nfd