]> git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/test-iputils_hh.cc
Merge remote-tracking branch 'origin/master' into api-tsig-keys
[thirdparty/pdns.git] / pdns / test-iputils_hh.cc
1 #define BOOST_TEST_DYN_LINK
2 #define BOOST_TEST_NO_MAIN
3 #ifdef HAVE_CONFIG_H
4 #include "config.h"
5 #endif
6 #include <boost/test/unit_test.hpp>
7 #include <bitset>
8 #include "iputils.hh"
9
10 using namespace boost;
11
12 BOOST_AUTO_TEST_SUITE(test_iputils_hh)
13
14 BOOST_AUTO_TEST_CASE(test_ComboAddress) {
15 ComboAddress local("127.0.0.1", 53);
16 BOOST_CHECK(local==local);
17 BOOST_CHECK_EQUAL(local.sin4.sin_family, AF_INET);
18 BOOST_CHECK_EQUAL(local.sin4.sin_port, htons(53));
19 BOOST_CHECK_EQUAL(local.sin4.sin_addr.s_addr, htonl(0x7f000001UL));
20
21 ComboAddress remote("130.161.33.15", 53);
22 BOOST_CHECK(!(local == remote));
23 BOOST_CHECK_EQUAL(remote.sin4.sin_port, htons(53));
24
25 ComboAddress withport("213.244.168.210:53");
26 BOOST_CHECK_EQUAL(withport.sin4.sin_port, htons(53));
27
28 ComboAddress withportO("213.244.168.210:53", 5300);
29 BOOST_CHECK_EQUAL(withportO.sin4.sin_port, htons(53));
30
31 withport = ComboAddress("[::]:53");
32 BOOST_CHECK_EQUAL(withport.sin4.sin_port, htons(53));
33
34 withport = ComboAddress("[::]:5300", 53);
35 BOOST_CHECK_EQUAL(withport.sin4.sin_port, htons(5300));
36
37 ComboAddress defaultport("213.244.168.210");
38 BOOST_CHECK_EQUAL(defaultport.sin4.sin_port, htons(0));
39
40 defaultport = ComboAddress("[::1]");
41 BOOST_CHECK_EQUAL(defaultport.sin4.sin_port, htons(0));
42
43 defaultport = ComboAddress("::1");
44 BOOST_CHECK_EQUAL(defaultport.sin4.sin_port, htons(0));
45
46 // Verify that 2 'empty' ComboAddresses are equal, used in syncres.hh to
47 // signal auth-zones
48 ComboAddress a = ComboAddress();
49 ComboAddress b = ComboAddress();
50 BOOST_CHECK(a == b);
51
52 // Verify that 2 ComboAddresses are not the same
53 ComboAddress c = ComboAddress("127.0.0.1:53");
54 ComboAddress d = ComboAddress("127.0.0.1:52");
55 ComboAddress e = ComboAddress("127.0.0.2:53");
56
57 BOOST_CHECK(a != c);
58 BOOST_CHECK(c != d);
59 BOOST_CHECK(c != e);
60 BOOST_CHECK(d != e);
61 BOOST_CHECK(!(a != b));
62
63 // Verify that we don't allow invalid port numbers
64 BOOST_CHECK_THROW(ComboAddress("127.0.0.1:70000"), PDNSException); // Port no. too high
65 BOOST_CHECK_THROW(ComboAddress("127.0.0.1:-6"), PDNSException); // Port no. too low
66 BOOST_CHECK_THROW(ComboAddress("[::1]:70000"), PDNSException); // Port no. too high
67 BOOST_CHECK_THROW(ComboAddress("[::1]:-6"), PDNSException); // Port no. too low
68 }
69
70 BOOST_AUTO_TEST_CASE(test_ComboAddressCompare) {
71 ComboAddress a, b;
72 a.reset();
73 b.reset();
74 BOOST_CHECK(!(a<b));
75 BOOST_CHECK(!(a>b));
76 }
77
78 BOOST_AUTO_TEST_CASE(test_ComboAddressTruncate) {
79 ComboAddress ca4("130.161.252.29");
80 ca4.truncate(24);
81 BOOST_CHECK_EQUAL(ca4.toString(), "130.161.252.0");
82 ca4.truncate(16);
83 BOOST_CHECK_EQUAL(ca4.toString(), "130.161.0.0");
84
85
86
87 ca4 = ComboAddress("130.161.252.29");
88 ComboAddress orig(ca4);
89 for(int n=32; n; --n) {
90 ca4.truncate(n);
91
92 uint32_t p;
93 memcpy(&p, (char*)&ca4.sin4.sin_addr.s_addr, 4);
94 std::bitset<32> result(htonl(p));
95
96 memcpy(&p, (char*)&orig.sin4.sin_addr.s_addr, 4);
97 std::bitset<32> manual(htonl(p));
98
99 auto tokill=32-n;
100 for(int i =0; i< tokill; ++i)
101 manual.set(i, 0);
102
103 BOOST_CHECK_EQUAL(result, manual);
104 }
105
106 ca4 = ComboAddress("130.161.252.29");
107 ca4.truncate(31);
108 BOOST_CHECK_EQUAL(ca4.toString(), "130.161.252.28");
109
110 ca4.truncate(30);
111 BOOST_CHECK_EQUAL(ca4.toString(), "130.161.252.28");
112
113 ca4.truncate(29);
114 BOOST_CHECK_EQUAL(ca4.toString(), "130.161.252.24");
115
116 ca4.truncate(23);
117 BOOST_CHECK_EQUAL(ca4.toString(), "130.161.252.0");
118
119 ca4.truncate(22);
120 BOOST_CHECK_EQUAL(ca4.toString(), "130.161.252.0");
121
122 ca4.truncate(21);
123 BOOST_CHECK_EQUAL(ca4.toString(), "130.161.248.0");
124
125 ComboAddress ca6("2001:888:2000:1d::2");
126 ca6.truncate(120);
127 BOOST_CHECK_EQUAL(ca6.toString(), "2001:888:2000:1d::");
128 ca6.truncate(64);
129 BOOST_CHECK_EQUAL(ca6.toString(), "2001:888:2000:1d::");
130 ca6.truncate(72); // 0102 304 0506 78
131 BOOST_CHECK_EQUAL(ca6.toString(), "2001:888:2000:1d::");
132 ca6.truncate(56);
133 BOOST_CHECK_EQUAL(ca6.toString(), "2001:888:2000::");
134 ca6.truncate(48);
135 BOOST_CHECK_EQUAL(ca6.toString(), "2001:888:2000::");
136 ca6.truncate(32);
137 BOOST_CHECK_EQUAL(ca6.toString(), "2001:888::");
138 ca6.truncate(16);
139 BOOST_CHECK_EQUAL(ca6.toString(), "2001::");
140 ca6.truncate(8);
141 BOOST_CHECK_EQUAL(ca6.toString(), "2000::");
142
143
144 orig=ca6=ComboAddress("2001:888:2000:1d::2");
145 for(int n=128; n; --n) {
146 ca6.truncate(n);
147
148 std::bitset<128> result, manual;
149 for(int i=0; i < 16; ++i) {
150 result<<=8;
151 result|= std::bitset<128>(*((unsigned char*)&ca6.sin6.sin6_addr.s6_addr + i));
152
153 manual<<=8;
154 manual|= std::bitset<128>(*((unsigned char*)&orig.sin6.sin6_addr.s6_addr + i));
155 }
156
157 auto tokill=128-n;
158 for(int i =0; i< tokill; ++i)
159 manual.set(i, 0);
160
161 BOOST_CHECK_EQUAL(result, manual);
162 }
163 }
164
165
166 BOOST_AUTO_TEST_CASE(test_Mapping)
167 {
168 ComboAddress lh("::1");
169 BOOST_CHECK_EQUAL(lh.toString(), "::1");
170 }
171
172 BOOST_AUTO_TEST_CASE(test_Netmask) {
173 ComboAddress local("127.0.0.1", 53);
174 ComboAddress remote("130.161.252.29", 53);
175
176 Netmask nm("127.0.0.1/24");
177 BOOST_CHECK(nm.getBits() == 24);
178 BOOST_CHECK(nm.match(local));
179 BOOST_CHECK(!nm.match(remote));
180 BOOST_CHECK(nm.isIpv4());
181 BOOST_CHECK(!nm.isIpv6());
182
183 Netmask nm6("fe80::92fb:a6ff:fe4a:51da/64");
184 BOOST_CHECK(nm6.getBits() == 64);
185 BOOST_CHECK(nm6.match("fe80::92fb:a6ff:fe4a:51db"));
186 BOOST_CHECK(!nm6.match("fe81::92fb:a6ff:fe4a:51db"));
187 BOOST_CHECK(!nm6.isIpv4());
188 BOOST_CHECK(nm6.isIpv6());
189
190 Netmask nmp("130.161.252.29/32");
191 BOOST_CHECK(nmp.match(remote));
192
193 Netmask nmp6("fe80::92fb:a6ff:fe4a:51da/128");
194 BOOST_CHECK(nmp6.match("fe80::92fb:a6ff:fe4a:51da"));
195 BOOST_CHECK(!nmp6.match("fe81::92fb:a6ff:fe4a:51db"));
196
197 Netmask all("0.0.0.0/0");
198 BOOST_CHECK(all.match(local) && all.match(remote));
199
200 Netmask all6("::/0");
201 BOOST_CHECK(all6.match("::1") && all6.match("fe80::92fb:a6ff:fe4a:51da"));
202
203
204 Netmask fromCombo1(ComboAddress("192.0.2.1:53"), 32);
205 Netmask fromCombo2(ComboAddress("192.0.2.1:54"), 32);
206 BOOST_CHECK(fromCombo1 == fromCombo2);
207 BOOST_CHECK(fromCombo1.match("192.0.2.1"));
208 BOOST_CHECK(fromCombo1.match(ComboAddress("192.0.2.1:80")));
209 BOOST_CHECK(fromCombo1.getNetwork() == ComboAddress("192.0.2.1"));
210 BOOST_CHECK(fromCombo1.getMaskedNetwork() == ComboAddress("192.0.2.1"));
211
212 Netmask nm25("192.0.2.255/25");
213 BOOST_CHECK(nm25.getBits() == 25);
214 BOOST_CHECK(nm25.getNetwork() == ComboAddress("192.0.2.255"));
215 BOOST_CHECK(nm25.getMaskedNetwork() == ComboAddress("192.0.2.128"));
216
217 /* Make sure that more specific Netmasks are lesser than less specific ones,
218 as this is very useful when matching. */
219 Netmask specific32("192.0.0.0/32");
220 Netmask specific24("192.0.0.0/24");
221 Netmask specific16("192.0.0.0/16");
222 BOOST_CHECK(specific32 < specific24);
223 BOOST_CHECK(specific24 > specific32);
224 BOOST_CHECK(specific24 < specific16);
225 BOOST_CHECK(specific16 > specific24);
226
227 Netmask sameMask1("192.0.0.0/16");
228 Netmask sameMask2("192.0.0.1/16");
229 BOOST_CHECK(sameMask1 < sameMask2);
230 BOOST_CHECK(sameMask2 > sameMask1);
231
232 /* An empty Netmask should be larger than
233 every others. */
234 Netmask empty = Netmask();
235 Netmask full("255.255.255.255/32");
236 BOOST_CHECK(empty > all);
237 BOOST_CHECK(all < empty);
238 BOOST_CHECK(empty > full);
239 BOOST_CHECK(full < empty);
240 }
241
242 static std::string NMGOutputToSorted(const std::string& str)
243 {
244 std::vector<std::string> vect;
245 stringtok(vect, str, ", ");
246 std::sort(vect.begin(), vect.end());
247 std::string result;
248 for (const auto& entry : vect) {
249 if (!result.empty()) {
250 result += " ";
251 }
252 result += entry;
253 }
254
255 return result;
256 }
257
258 BOOST_AUTO_TEST_CASE(test_NetmaskGroup) {
259
260 {
261 NetmaskGroup ng;
262 ng.addMask("10.0.1.0");
263 BOOST_CHECK(ng.match(ComboAddress("10.0.1.0")));
264 ng.toMasks("127.0.0.0/8, 10.0.0.0/24");
265 BOOST_CHECK(ng.match(ComboAddress("127.0.0.1")));
266 BOOST_CHECK(ng.match(ComboAddress("10.0.0.3")));
267 BOOST_CHECK(ng.match(ComboAddress("10.0.1.0")));
268 BOOST_CHECK(!ng.match(ComboAddress("128.1.2.3")));
269 BOOST_CHECK(!ng.match(ComboAddress("10.0.1.1")));
270 BOOST_CHECK(!ng.match(ComboAddress("::1")));
271 ng.addMask("::1");
272 BOOST_CHECK(ng.match(ComboAddress("::1")));
273 BOOST_CHECK(!ng.match(ComboAddress("::2")));
274 ng.addMask("fe80::/16");
275 BOOST_CHECK(ng.match(ComboAddress("fe80::1")));
276 BOOST_CHECK(!ng.match(ComboAddress("fe81::1")));
277 BOOST_CHECK_EQUAL(NMGOutputToSorted(ng.toString()), NMGOutputToSorted("10.0.1.0/32, 127.0.0.0/8, 10.0.0.0/24, ::1/128, fe80::/16"));
278
279 /* negative entries using the explicit flag */
280 ng.addMask("172.16.0.0/16", true);
281 BOOST_CHECK(ng.match(ComboAddress("172.16.1.1")));
282 BOOST_CHECK(ng.match(ComboAddress("172.16.4.50")));
283 ng.addMask("172.16.4.0/24", false);
284 BOOST_CHECK(ng.match(ComboAddress("172.16.1.1")));
285 BOOST_CHECK(!ng.match(ComboAddress("172.16.4.50")));
286 ng.addMask("fe80::/24", false);
287 BOOST_CHECK(!ng.match(ComboAddress("fe80::1")));
288 BOOST_CHECK(!ng.match(ComboAddress("fe81::1")));
289 /* not in fe80::/24 but in fe80::/16, should match */
290 BOOST_CHECK(ng.match(ComboAddress("fe80:0100::1")));
291
292 /* negative entries using '!' */
293 BOOST_CHECK(ng.match(ComboAddress("172.16.10.80")));
294 ng.addMask("!172.16.10.0/24");
295 BOOST_CHECK(!ng.match(ComboAddress("172.16.10.80")));
296 ng.addMask("2001:db8::/32");
297 ng.addMask("!2001:db8::/64");
298 BOOST_CHECK(!ng.match(ComboAddress("2001:db8::1")));
299 /* not in 2001:db8::/64 but in 2001:db8::/32, should match */
300 BOOST_CHECK(ng.match(ComboAddress("2001:db8:1::1")));
301
302 BOOST_CHECK_EQUAL(NMGOutputToSorted(ng.toString()), NMGOutputToSorted("10.0.1.0/32, 127.0.0.0/8, 10.0.0.0/24, ::1/128, fe80::/16, 172.16.0.0/16, !172.16.4.0/24, !fe80::/24, !172.16.10.0/24, 2001:db8::/32, !2001:db8::/64"));
303 }
304
305 {
306 /* this time using Netmask objects instead of strings */
307 NetmaskGroup ng;
308 ng.addMask(Netmask("10.0.1.0"));
309 BOOST_CHECK(ng.match(ComboAddress("10.0.1.0")));
310 ng.addMask(Netmask("127.0.0.0/8"));
311 ng.addMask(Netmask("10.0.0.0/24"));
312 BOOST_CHECK(ng.match(ComboAddress("127.0.0.1")));
313 BOOST_CHECK(ng.match(ComboAddress("10.0.0.3")));
314 BOOST_CHECK(ng.match(ComboAddress("10.0.1.0")));
315 BOOST_CHECK(!ng.match(ComboAddress("128.1.2.3")));
316 BOOST_CHECK(!ng.match(ComboAddress("10.0.1.1")));
317 BOOST_CHECK(!ng.match(ComboAddress("::1")));
318 ng.addMask(Netmask("::1"));
319 BOOST_CHECK(ng.match(ComboAddress("::1")));
320 BOOST_CHECK(!ng.match(ComboAddress("::2")));
321 ng.addMask(Netmask("fe80::/16"));
322 BOOST_CHECK(ng.match(ComboAddress("fe80::1")));
323 BOOST_CHECK(!ng.match(ComboAddress("fe81::1")));
324 BOOST_CHECK_EQUAL(NMGOutputToSorted(ng.toString()), NMGOutputToSorted("10.0.1.0/32, 127.0.0.0/8, 10.0.0.0/24, ::1/128, fe80::/16"));
325
326 /* negative entries using the explicit flag */
327 ng.addMask(Netmask("172.16.0.0/16"), true);
328 BOOST_CHECK(ng.match(ComboAddress("172.16.1.1")));
329 BOOST_CHECK(ng.match(ComboAddress("172.16.4.50")));
330 ng.addMask(Netmask("172.16.4.0/24"), false);
331 BOOST_CHECK(ng.match(ComboAddress("172.16.1.1")));
332 BOOST_CHECK(!ng.match(ComboAddress("172.16.4.50")));
333 ng.addMask("fe80::/24", false);
334 BOOST_CHECK(!ng.match(ComboAddress("fe80::1")));
335 BOOST_CHECK(!ng.match(ComboAddress("fe81::1")));
336 /* not in fe80::/24 but in fe80::/16, should match */
337 BOOST_CHECK(ng.match(ComboAddress("fe80:0100::1")));
338
339 BOOST_CHECK_EQUAL(NMGOutputToSorted(ng.toString()), NMGOutputToSorted("10.0.1.0/32, 127.0.0.0/8, 10.0.0.0/24, ::1/128, fe80::/16, 172.16.0.0/16, !172.16.4.0/24, !fe80::/24"));
340 }
341 }
342
343
344 BOOST_AUTO_TEST_CASE(test_NetmaskTree) {
345 NetmaskTree<int> nmt;
346 nmt.insert(Netmask("130.161.252.0/24")).second=0;
347 nmt.insert(Netmask("130.161.0.0/16")).second=1;
348 nmt.insert(Netmask("130.0.0.0/8")).second=2;
349
350 BOOST_CHECK_EQUAL(nmt.lookup(ComboAddress("213.244.168.210")), (void*)0);
351 auto found=nmt.lookup(ComboAddress("130.161.252.29"));
352 BOOST_CHECK(found);
353 BOOST_CHECK_EQUAL(found->second, 0);
354 found=nmt.lookup(ComboAddress("130.161.180.1"));
355 BOOST_CHECK(found);
356 BOOST_CHECK_EQUAL(found->second, 1);
357
358 BOOST_CHECK_EQUAL(nmt.lookup(ComboAddress("130.255.255.255"))->second, 2);
359 BOOST_CHECK_EQUAL(nmt.lookup(ComboAddress("130.161.252.255"))->second, 0);
360 BOOST_CHECK_EQUAL(nmt.lookup(ComboAddress("130.161.253.255"))->second, 1);
361
362 found=nmt.lookup(ComboAddress("130.145.180.1"));
363 BOOST_CHECK(found);
364 BOOST_CHECK_EQUAL(found->second, 2);
365
366 nmt.clear();
367 BOOST_CHECK(!nmt.lookup(ComboAddress("130.161.180.1")));
368
369 nmt.insert(Netmask("::1")).second=1;
370 nmt.insert(Netmask("::/0")).second=0;
371 nmt.insert(Netmask("fe80::/16")).second=2;
372 BOOST_CHECK_EQUAL(nmt.lookup(ComboAddress("130.161.253.255")), (void*)0);
373 BOOST_CHECK_EQUAL(nmt.lookup(ComboAddress("::2"))->second, 0);
374 BOOST_CHECK_EQUAL(nmt.lookup(ComboAddress("::ffff"))->second, 0);
375 BOOST_CHECK_EQUAL(nmt.lookup(ComboAddress("::1"))->second, 1);
376 BOOST_CHECK_EQUAL(nmt.lookup(ComboAddress("fe80::1"))->second, 2);
377 }
378
379 BOOST_AUTO_TEST_CASE(test_single) {
380 NetmaskTree<bool> nmt;
381 nmt.insert(Netmask("127.0.0.0/8")).second=1;
382 BOOST_CHECK_EQUAL(nmt.lookup(ComboAddress("127.0.0.1"))->second, 1);
383 }
384
385 BOOST_AUTO_TEST_CASE(test_scale) {
386 string start="192.168.";
387 NetmaskTree<int> works;
388 for(int i=0; i < 256; ++i) {
389 for(int j=0; j < 256; ++j) {
390 works.insert(Netmask(start+std::to_string(i)+"."+std::to_string(j))).second=i*j;
391 }
392 }
393
394 for(int i=0; i < 256; ++i) {
395 for(int j=0; j < 256; ++j) {
396 BOOST_CHECK_EQUAL(works.lookup(ComboAddress(start+std::to_string(i)+"."+std::to_string(j)))->second, i*j);
397 }
398 }
399
400 start="130.161.";
401 for(int i=0; i < 256; ++i) {
402 for(int j=0; j < 256; ++j) {
403 BOOST_CHECK_EQUAL(works.lookup(ComboAddress(start+std::to_string(i)+"."+std::to_string(j))), (void*)0);
404 }
405 }
406
407 start="2000:123:";
408 for(int i=0; i < 256; ++i) {
409 for(int j=0; j < 256; ++j) {
410 works.insert(Netmask(start+std::to_string(i)+":"+std::to_string(j)+"::/64")).second=i*j;
411 }
412 }
413
414 for(int i=0; i < 256; ++i) {
415 for(int j=0; j < 256; ++j) {
416 BOOST_CHECK_EQUAL(works.lookup(ComboAddress(start+std::to_string(i)+":"+std::to_string(j)+"::"+std::to_string(i)+":"+std::to_string(j)))->second, i*j);
417 }
418 }
419
420 start="2001:123:";
421 for(int i=0; i < 256; ++i) {
422 for(int j=0; j < 256; ++j) {
423 BOOST_CHECK_EQUAL(works.lookup(ComboAddress(start+std::to_string(i)+":"+std::to_string(j)+"::"+std::to_string(i)+":"+std::to_string(j))), (void*)0);
424 }
425 }
426 }
427
428 BOOST_AUTO_TEST_CASE(test_removal) {
429 std::string prefix = "192.";
430 NetmaskTree<int> nmt(true);
431
432 size_t count = 0;
433 for(unsigned int i = 0; i < 256; ++i) {
434 for(unsigned int j = 16; j <= 32; ++j) {
435 nmt.insert(Netmask(prefix + std::to_string(i) +".127.255/"+std::to_string(j))).second = j;
436 count++;
437 }
438 }
439
440 BOOST_CHECK_EQUAL(nmt.size(), count);
441
442 for(unsigned int i = 0; i < 256; ++i) {
443 ComboAddress key(prefix + std::to_string(i) + ".127.255");
444 const auto result = nmt.lookup(key);
445 BOOST_CHECK_EQUAL(result->first.getBits(), 32);
446 BOOST_CHECK_EQUAL(result->first.getMaskedNetwork().toString(), key.toString());
447 BOOST_CHECK_EQUAL(result->second, 32);
448 }
449
450 for(unsigned int i = 0; i < 256; ++i) {
451 for(unsigned int j = 32; j >= 16; --j) {
452 ComboAddress key(prefix + std::to_string(i) + ".127.255");
453 nmt.erase(Netmask(key, j));
454 const auto result = nmt.lookup(key);
455
456 if (j > 16) {
457 BOOST_REQUIRE(result != nullptr);
458 BOOST_CHECK_EQUAL(result->first.getBits(), j-1);
459 BOOST_CHECK_EQUAL(result->first.getMaskedNetwork().toString(), Netmask(key, j-1).getMaskedNetwork().toString());
460 BOOST_CHECK_EQUAL(result->second, j - 1);
461 }
462 else {
463 BOOST_CHECK(result == nullptr);
464 }
465 }
466 }
467
468 BOOST_CHECK_EQUAL(nmt.size(), 0);
469 BOOST_CHECK(nmt.empty());
470 }
471
472 BOOST_AUTO_TEST_SUITE_END()