network.cpp
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2014-2022, 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.
10  *
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  */
25 
26 #include "network.hpp"
27 
28 #include <boost/lexical_cast.hpp>
29 #include <boost/utility/value_init.hpp>
30 
31 #include <algorithm>
32 #include <cctype>
33 #include <istream>
34 #include <ostream>
35 
36 namespace nfd {
37 
38 Network::Network() = default;
39 
40 Network::Network(const boost::asio::ip::address& minAddress,
41  const boost::asio::ip::address& maxAddress)
42  : m_minAddress(minAddress)
43  , m_maxAddress(maxAddress)
44 {
45 }
46 
47 const Network&
49 {
50  using boost::asio::ip::address_v4;
51  static Network range{address_v4{}, address_v4{0xffffffff}};
52  return range;
53 }
54 
55 const Network&
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}};
61  static Network range{address_v6{}, address_v6{maxV6}};
62  return range;
63 }
64 
65 bool
66 Network::isValidCidr(std::string_view cidr)
67 {
68  auto pos = cidr.find('/');
69  if (pos == std::string::npos) {
70  return false;
71  }
72 
73  try {
74  boost::lexical_cast<Network>(cidr);
75  return true;
76  }
77  catch (const boost::bad_lexical_cast&) {
78  return false;
79  }
80 }
81 
82 std::ostream&
83 operator<<(std::ostream& os, const Network& network)
84 {
85  return os << network.m_minAddress << " <-> " << network.m_maxAddress;
86 }
87 
88 std::istream&
89 operator>>(std::istream& is, Network& network)
90 {
91  namespace ip = boost::asio::ip;
92 
93  std::string networkStr;
94  is >> networkStr;
95 
96  size_t position = networkStr.find('/');
97  if (position == std::string::npos) {
98  try {
99  network.m_minAddress = ip::address::from_string(networkStr);
100  network.m_maxAddress = ip::address::from_string(networkStr);
101  }
102  catch (const boost::system::system_error&) {
103  is.setstate(std::ios::failbit);
104  return is;
105  }
106  }
107  else {
108  boost::system::error_code ec;
109  auto address = ip::address::from_string(networkStr.substr(0, position), ec);
110  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  }
129 
130  if (address.is_v4()) {
131  if (mask > 32) {
132  is.setstate(std::ios::failbit);
133  return is;
134  }
135 
136  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);
154  }
155  else {
156  if (mask > 128) {
157  is.setstate(std::ios::failbit);
158  return is;
159  }
160 
161  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  }
167 
168  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;
171 
172  for (size_t i = 0; i < addressBytes.size(); i++) {
173  min[i] = addressBytes[i] & maskBytes[i];
174  max[i] = addressBytes[i] | ~(maskBytes[i]);
175  }
176 
177  network.m_minAddress = ip::address_v6(min);
178  network.m_maxAddress = ip::address_v6(max);
179  }
180  }
181 
182  return is;
183 }
184 
185 } // namespace nfd
static bool isValidCidr(std::string_view cidr)
Definition: network.cpp:66
static const Network & getMaxRangeV6()
Definition: network.cpp:56
static const Network & getMaxRangeV4()
Definition: network.cpp:48
Definition: common.hpp:77
std::ostream & operator<<(std::ostream &os, const Network &network)
Definition: network.cpp:83
std::istream & operator>>(std::istream &is, Network &network)
Definition: network.cpp:89