1 | // |
2 | // network_v4.cpp |
3 | // ~~~~~~~~~~~~~~ |
4 | // |
5 | // Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) |
6 | // Copyright (c) 2014 Oliver Kowalke (oliver dot kowalke at gmail dot com) |
7 | // |
8 | // Distributed under the Boost Software License, Version 1.0. (See accompanying |
9 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |
10 | // |
11 | |
12 | // Disable autolinking for unit tests. |
13 | #if !defined(BOOST_ALL_NO_LIB) |
14 | #define BOOST_ALL_NO_LIB 1 |
15 | #endif // !defined(BOOST_ALL_NO_LIB) |
16 | |
17 | // Test that header file is self-contained. |
18 | #include <boost/asio/ip/network_v4.hpp> |
19 | |
20 | #include "../unit_test.hpp" |
21 | #include <sstream> |
22 | |
23 | //------------------------------------------------------------------------------ |
24 | |
25 | // ip_network_v4_compile test |
26 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~ |
27 | // The following test checks that all public member functions on the class |
28 | // ip::network_v4 compile and link correctly. Runtime failures are ignored. |
29 | |
30 | namespace ip_network_v4_compile { |
31 | |
32 | void test() |
33 | { |
34 | using namespace boost::asio; |
35 | namespace ip = boost::asio::ip; |
36 | |
37 | try |
38 | { |
39 | boost::system::error_code ec; |
40 | |
41 | // network_v4 constructors. |
42 | |
43 | ip::network_v4 net1(ip::make_address_v4(str: "192.168.1.0" ), 32); |
44 | ip::network_v4 net2(ip::make_address_v4(str: "192.168.1.0" ), |
45 | ip::make_address_v4(str: "255.255.255.0" )); |
46 | |
47 | // network_v4 functions. |
48 | |
49 | ip::address_v4 addr1 = net1.address(); |
50 | (void)addr1; |
51 | |
52 | unsigned short prefix_len = net1.prefix_length(); |
53 | (void)prefix_len; |
54 | |
55 | ip::address_v4 addr2 = net1.netmask(); |
56 | (void)addr2; |
57 | |
58 | ip::address_v4 addr3 = net1.network(); |
59 | (void)addr3; |
60 | |
61 | ip::address_v4 addr4 = net1.broadcast(); |
62 | (void)addr4; |
63 | |
64 | ip::address_v4_range hosts = net1.hosts(); |
65 | (void)hosts; |
66 | |
67 | ip::network_v4 net3 = net1.canonical(); |
68 | (void)net3; |
69 | |
70 | bool b1 = net1.is_host(); |
71 | (void)b1; |
72 | |
73 | bool b2 = net1.is_subnet_of(other: net2); |
74 | (void)b2; |
75 | |
76 | std::string s1 = net1.to_string(); |
77 | (void)s1; |
78 | |
79 | std::string s2 = net1.to_string(ec); |
80 | (void)s2; |
81 | |
82 | // network_v4 comparisons. |
83 | |
84 | bool b3 = (net1 == net2); |
85 | (void)b3; |
86 | |
87 | bool b4 = (net1 != net2); |
88 | (void)b4; |
89 | |
90 | // network_v4 creation functions. |
91 | |
92 | net1 = ip::make_network_v4(addr: ip::address_v4(), prefix_len: 24); |
93 | net1 = ip::make_network_v4(addr: ip::address_v4(), mask: ip::address_v4()); |
94 | net1 = ip::make_network_v4(str: "10.0.0.0/8" ); |
95 | net1 = ip::make_network_v4(str: "10.0.0.0/8" , ec); |
96 | net1 = ip::make_network_v4(str: s1); |
97 | net1 = ip::make_network_v4(str: s1, ec); |
98 | #if defined(BOOST_ASIO_HAS_STRING_VIEW) |
99 | # if defined(BOOST_ASIO_HAS_STD_STRING_VIEW) |
100 | std::string_view string_view_value("10.0.0.0/8" ); |
101 | # elif defined(BOOST_ASIO_HAS_STD_EXPERIMENTAL_STRING_VIEW) |
102 | std::experimental::string_view string_view_value("10.0.0.0/8" ); |
103 | # endif // defined(BOOST_ASIO_HAS_STD_EXPERIMENTAL_STRING_VIEW) |
104 | net1 = ip::make_network_v4(str: string_view_value); |
105 | net1 = ip::make_network_v4(str: string_view_value, ec); |
106 | #endif // defined(BOOST_ASIO_HAS_STRING_VIEW) |
107 | |
108 | // network_v4 I/O. |
109 | |
110 | std::ostringstream os; |
111 | os << net1; |
112 | |
113 | #if !defined(BOOST_NO_STD_WSTREAMBUF) |
114 | std::wostringstream wos; |
115 | wos << net1; |
116 | #endif // !defined(BOOST_NO_STD_WSTREAMBUF) |
117 | } |
118 | catch (std::exception&) |
119 | { |
120 | } |
121 | } |
122 | |
123 | } // namespace ip_network_v4_compile |
124 | |
125 | //------------------------------------------------------------------------------ |
126 | |
127 | // ip_network_v4_runtime test |
128 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~ |
129 | // The following test checks that the various public member functions meet the |
130 | // necessary postconditions. |
131 | |
132 | namespace ip_network_v4_runtime { |
133 | |
134 | void test() |
135 | { |
136 | using boost::asio::ip::address_v4; |
137 | using boost::asio::ip::make_address_v4; |
138 | using boost::asio::ip::network_v4; |
139 | using boost::asio::ip::make_network_v4; |
140 | |
141 | address_v4 addr = make_address_v4(str: "1.2.3.4" ); |
142 | |
143 | // calculate prefix length |
144 | |
145 | network_v4 net1(addr, make_address_v4(str: "255.255.255.0" )); |
146 | BOOST_ASIO_CHECK(net1.prefix_length() == 24); |
147 | |
148 | network_v4 net2(addr, make_address_v4(str: "255.255.255.192" )); |
149 | BOOST_ASIO_CHECK(net2.prefix_length() == 26); |
150 | |
151 | network_v4 net3(addr, make_address_v4(str: "128.0.0.0" )); |
152 | BOOST_ASIO_CHECK(net3.prefix_length() == 1); |
153 | |
154 | std::string msg; |
155 | try |
156 | { |
157 | make_network_v4(addr, mask: make_address_v4(str: "255.255.255.1" )); |
158 | } |
159 | catch(std::exception& ex) |
160 | { |
161 | msg = ex.what(); |
162 | } |
163 | BOOST_ASIO_CHECK(msg == std::string("non-contiguous netmask" )); |
164 | |
165 | msg.clear(); |
166 | try |
167 | { |
168 | make_network_v4(addr, mask: make_address_v4(str: "0.255.255.0" )); |
169 | } |
170 | catch(std::exception& ex) |
171 | { |
172 | msg = ex.what(); |
173 | } |
174 | BOOST_ASIO_CHECK(msg == std::string("non-contiguous netmask" )); |
175 | |
176 | // calculate netmask |
177 | |
178 | network_v4 net4(addr, 23); |
179 | BOOST_ASIO_CHECK(net4.netmask() == make_address_v4("255.255.254.0" )); |
180 | |
181 | network_v4 net5(addr, 12); |
182 | BOOST_ASIO_CHECK(net5.netmask() == make_address_v4("255.240.0.0" )); |
183 | |
184 | network_v4 net6(addr, 24); |
185 | BOOST_ASIO_CHECK(net6.netmask() == make_address_v4("255.255.255.0" )); |
186 | |
187 | network_v4 net7(addr, 16); |
188 | BOOST_ASIO_CHECK(net7.netmask() == make_address_v4("255.255.0.0" )); |
189 | |
190 | network_v4 net8(addr, 8); |
191 | BOOST_ASIO_CHECK(net8.netmask() == make_address_v4("255.0.0.0" )); |
192 | |
193 | network_v4 net9(addr, 32); |
194 | BOOST_ASIO_CHECK(net9.netmask() == make_address_v4("255.255.255.255" )); |
195 | |
196 | network_v4 net10(addr, 1); |
197 | BOOST_ASIO_CHECK(net10.netmask() == make_address_v4("128.0.0.0" )); |
198 | |
199 | network_v4 net11(addr, 0); |
200 | BOOST_ASIO_CHECK(net11.netmask() == make_address_v4("0.0.0.0" )); |
201 | |
202 | msg.clear(); |
203 | try |
204 | { |
205 | make_network_v4(addr, prefix_len: 33); |
206 | } |
207 | catch(std::out_of_range& ex) |
208 | { |
209 | msg = ex.what(); |
210 | } |
211 | BOOST_ASIO_CHECK(msg == std::string("prefix length too large" )); |
212 | |
213 | // construct address range from address and prefix length |
214 | BOOST_ASIO_CHECK(network_v4(make_address_v4("192.168.77.100" ), 32).network() == make_address_v4("192.168.77.100" )); |
215 | BOOST_ASIO_CHECK(network_v4(make_address_v4("192.168.77.100" ), 24).network() == make_address_v4("192.168.77.0" )); |
216 | BOOST_ASIO_CHECK(network_v4(make_address_v4("192.168.77.128" ), 25).network() == make_address_v4("192.168.77.128" )); |
217 | |
218 | // construct address range from string in CIDR notation |
219 | BOOST_ASIO_CHECK(make_network_v4("192.168.77.100/32" ).network() == make_address_v4("192.168.77.100" )); |
220 | BOOST_ASIO_CHECK(make_network_v4("192.168.77.100/24" ).network() == make_address_v4("192.168.77.0" )); |
221 | BOOST_ASIO_CHECK(make_network_v4("192.168.77.128/25" ).network() == make_address_v4("192.168.77.128" )); |
222 | |
223 | // construct network from invalid string |
224 | boost::system::error_code ec; |
225 | make_network_v4(str: "10.0.0.256/24" , ec); |
226 | BOOST_ASIO_CHECK(!!ec); |
227 | make_network_v4(str: "10.0.0.0/33" , ec); |
228 | BOOST_ASIO_CHECK(!!ec); |
229 | make_network_v4(str: "10.0.0.0/-1" , ec); |
230 | BOOST_ASIO_CHECK(!!ec); |
231 | make_network_v4(str: "10.0.0.0/" , ec); |
232 | BOOST_ASIO_CHECK(!!ec); |
233 | make_network_v4(str: "10.0.0.0" , ec); |
234 | BOOST_ASIO_CHECK(!!ec); |
235 | |
236 | // prefix length |
237 | BOOST_ASIO_CHECK(make_network_v4("193.99.144.80/24" ).prefix_length() == 24); |
238 | BOOST_ASIO_CHECK(network_v4(make_address_v4("193.99.144.80" ), 24).prefix_length() == 24); |
239 | BOOST_ASIO_CHECK(network_v4(make_address_v4("192.168.77.0" ), make_address_v4("255.255.255.0" )).prefix_length() == 24); |
240 | |
241 | // to string |
242 | std::string a("192.168.77.0/32" ); |
243 | BOOST_ASIO_CHECK(make_network_v4(a.c_str()).to_string() == a); |
244 | BOOST_ASIO_CHECK(network_v4(make_address_v4("192.168.77.10" ), 24).to_string() == std::string("192.168.77.10/24" )); |
245 | |
246 | // return host part |
247 | BOOST_ASIO_CHECK(make_network_v4("192.168.77.11/24" ).address() == make_address_v4("192.168.77.11" )); |
248 | |
249 | // return host in CIDR notation |
250 | BOOST_ASIO_CHECK(make_network_v4("192.168.78.30/20" ).address().to_string() == "192.168.78.30" ); |
251 | |
252 | // return network in CIDR notation |
253 | BOOST_ASIO_CHECK(make_network_v4("192.168.78.30/20" ).canonical().to_string() == "192.168.64.0/20" ); |
254 | |
255 | // is host |
256 | BOOST_ASIO_CHECK(make_network_v4("192.168.77.0/32" ).is_host()); |
257 | BOOST_ASIO_CHECK(!make_network_v4("192.168.77.0/31" ).is_host()); |
258 | |
259 | // is real subnet of |
260 | BOOST_ASIO_CHECK(make_network_v4("192.168.0.192/24" ).is_subnet_of(make_network_v4("192.168.0.0/16" ))); |
261 | BOOST_ASIO_CHECK(make_network_v4("192.168.0.0/24" ).is_subnet_of(make_network_v4("192.168.192.168/16" ))); |
262 | BOOST_ASIO_CHECK(make_network_v4("192.168.0.192/24" ).is_subnet_of(make_network_v4("192.168.192.168/16" ))); |
263 | BOOST_ASIO_CHECK(make_network_v4("192.168.0.0/24" ).is_subnet_of(make_network_v4("192.168.0.0/16" ))); |
264 | BOOST_ASIO_CHECK(make_network_v4("192.168.0.0/24" ).is_subnet_of(make_network_v4("192.168.0.0/23" ))); |
265 | BOOST_ASIO_CHECK(make_network_v4("192.168.0.0/24" ).is_subnet_of(make_network_v4("192.168.0.0/0" ))); |
266 | BOOST_ASIO_CHECK(make_network_v4("192.168.0.0/32" ).is_subnet_of(make_network_v4("192.168.0.0/24" ))); |
267 | |
268 | BOOST_ASIO_CHECK(!make_network_v4("192.168.0.0/32" ).is_subnet_of(make_network_v4("192.168.0.0/32" ))); |
269 | BOOST_ASIO_CHECK(!make_network_v4("192.168.0.0/24" ).is_subnet_of(make_network_v4("192.168.1.0/24" ))); |
270 | BOOST_ASIO_CHECK(!make_network_v4("192.168.0.0/16" ).is_subnet_of(make_network_v4("192.168.1.0/24" ))); |
271 | |
272 | network_v4 r(make_network_v4(str: "192.168.0.0/24" )); |
273 | BOOST_ASIO_CHECK(!r.is_subnet_of(r)); |
274 | |
275 | network_v4 net12(make_network_v4(str: "192.168.0.2/24" )); |
276 | network_v4 net13(make_network_v4(str: "192.168.1.1/28" )); |
277 | network_v4 net14(make_network_v4(str: "192.168.1.21/28" )); |
278 | // network |
279 | BOOST_ASIO_CHECK(net12.network() == make_address_v4("192.168.0.0" )); |
280 | BOOST_ASIO_CHECK(net13.network() == make_address_v4("192.168.1.0" )); |
281 | BOOST_ASIO_CHECK(net14.network() == make_address_v4("192.168.1.16" )); |
282 | // netmask |
283 | BOOST_ASIO_CHECK(net12.netmask() == make_address_v4("255.255.255.0" )); |
284 | BOOST_ASIO_CHECK(net13.netmask() == make_address_v4("255.255.255.240" )); |
285 | BOOST_ASIO_CHECK(net14.netmask() == make_address_v4("255.255.255.240" )); |
286 | // broadcast |
287 | BOOST_ASIO_CHECK(net12.broadcast() == make_address_v4("192.168.0.255" )); |
288 | BOOST_ASIO_CHECK(net13.broadcast() == make_address_v4("192.168.1.15" )); |
289 | BOOST_ASIO_CHECK(net14.broadcast() == make_address_v4("192.168.1.31" )); |
290 | // iterator |
291 | BOOST_ASIO_CHECK(std::distance(net12.hosts().begin(),net12.hosts().end()) == 254); |
292 | BOOST_ASIO_CHECK(*net12.hosts().begin() == make_address_v4("192.168.0.1" )); |
293 | BOOST_ASIO_CHECK(net12.hosts().end() != net12.hosts().find(make_address_v4("192.168.0.10" ))); |
294 | BOOST_ASIO_CHECK(net12.hosts().end() == net12.hosts().find(make_address_v4("192.168.1.10" ))); |
295 | BOOST_ASIO_CHECK(std::distance(net13.hosts().begin(),net13.hosts().end()) == 14); |
296 | BOOST_ASIO_CHECK(*net13.hosts().begin() == make_address_v4("192.168.1.1" )); |
297 | BOOST_ASIO_CHECK(net13.hosts().end() != net13.hosts().find(make_address_v4("192.168.1.14" ))); |
298 | BOOST_ASIO_CHECK(net13.hosts().end() == net13.hosts().find(make_address_v4("192.168.1.15" ))); |
299 | BOOST_ASIO_CHECK(std::distance(net14.hosts().begin(),net14.hosts().end()) == 14); |
300 | BOOST_ASIO_CHECK(*net14.hosts().begin() == make_address_v4("192.168.1.17" )); |
301 | BOOST_ASIO_CHECK(net14.hosts().end() != net14.hosts().find(make_address_v4("192.168.1.30" ))); |
302 | BOOST_ASIO_CHECK(net14.hosts().end() == net14.hosts().find(make_address_v4("192.168.1.31" ))); |
303 | } |
304 | |
305 | } // namespace ip_network_v4_runtime |
306 | |
307 | //------------------------------------------------------------------------------ |
308 | |
309 | BOOST_ASIO_TEST_SUITE |
310 | ( |
311 | "ip/network_v4" , |
312 | BOOST_ASIO_COMPILE_TEST_CASE(ip_network_v4_compile::test) |
313 | BOOST_ASIO_TEST_CASE(ip_network_v4_runtime::test) |
314 | ) |
315 | |