]> git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/test-dnsname_cc.cc
Merge pull request #14021 from Habbie/auth-lua-join-whitespace
[thirdparty/pdns.git] / pdns / test-dnsname_cc.cc
1 #define BOOST_TEST_DYN_LINK
2 #define BOOST_TEST_NO_MAIN
3 #include <boost/test/unit_test.hpp>
4 #include <boost/assign/std/map.hpp>
5 #include <numeric>
6 #include <math.h>
7 #include "dnsname.hh"
8 #include "misc.hh"
9 #include "dnswriter.hh"
10 #include "dnsrecords.hh"
11 #include <unordered_set>
12 using namespace boost;
13 using std::string;
14
15 BOOST_AUTO_TEST_SUITE(test_dnsname_cc)
16
17 BOOST_AUTO_TEST_CASE(test_basic) {
18 DNSName aroot("a.root-servers.net"), broot("b.root-servers.net");
19 BOOST_CHECK(aroot < broot);
20 BOOST_CHECK(!(broot < aroot));
21 BOOST_CHECK(aroot.canonCompare(broot));
22 BOOST_CHECK(!broot.canonCompare(aroot));
23
24
25 string before("www.ds9a.nl.");
26 DNSName b(before);
27 BOOST_CHECK_EQUAL(b.getRawLabels().size(), 3);
28 string after(b.toString());
29 BOOST_CHECK_EQUAL(before, after);
30
31 DNSName jpmens("ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc.bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.test.xxx.yyy-yyyy.zzzzzzzzz-test.");
32
33 BOOST_CHECK_EQUAL(jpmens.toString(), "ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc.bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.test.xxx.yyy-yyyy.zzzzzzzzz-test.");
34
35 DNSName wwwds9anl("www.ds9a.nl.");
36 DNSName wwwds9anl1("www.ds9a\002nl.");
37 DNSName nl("nl.");
38 BOOST_CHECK(wwwds9anl.isPartOf(nl));
39 BOOST_CHECK(!wwwds9anl1.isPartOf(nl));
40 BOOST_CHECK(wwwds9anl.isPartOf(wwwds9anl));
41
42 BOOST_CHECK(!nl.isPartOf(wwwds9anl));
43
44 BOOST_CHECK(wwwds9anl == wwwds9anl);
45
46 BOOST_CHECK(DNSName("wWw.ds9A.Nl.") == DNSName("www.ds9a.nl."));
47 BOOST_CHECK(DNSName("www.ds9a.nl.") == DNSName("www.ds9a.nl."));
48
49 BOOST_CHECK(DNSName("www.ds9a.nl.").toString() == "www.ds9a.nl.");
50
51
52 { // Check root vs empty
53 DNSName name("."); // root
54 DNSName parent; // empty
55 BOOST_CHECK(name != parent);
56 }
57
58 { // Check name part of root
59 DNSName name("a.");
60 DNSName parent(".");
61 BOOST_CHECK(name.isPartOf(parent));
62 }
63
64 { // Label boundary
65 DNSName name("a\002bb.");
66 DNSName parent("bb.");
67 BOOST_CHECK(!name.isPartOf(parent));
68 }
69
70 { // Multi label parent
71 DNSName name("a.bb.ccc.dddd.");
72 DNSName parent("ccc.dddd.");
73 BOOST_CHECK(name.isPartOf(parent));
74 }
75
76 { // Last char diff
77 DNSName name("a.bb.ccc.dddd.");
78 DNSName parent("ccc.dddx.");
79 BOOST_CHECK(!name.isPartOf(parent));
80 }
81
82 { // Equal length identical
83 DNSName name("aaaa.bbb.cc.d.");
84 DNSName parent("aaaa.bbb.cc.d.");
85 BOOST_CHECK(name.isPartOf(parent));
86 }
87
88 { // Equal length first char diff
89 DNSName name("xaaa.bbb.cc.d.");
90 DNSName parent("aaaa.bbb.cc.d.");
91 BOOST_CHECK(!name.isPartOf(parent));
92 }
93
94 { // Make relative
95 DNSName name("aaaa.bbb.cc.d.");
96 DNSName parent("cc.d.");
97 BOOST_CHECK_EQUAL( name.makeRelative(parent), DNSName("aaaa.bbb."));
98 }
99
100 { // Labelreverse
101 DNSName name("aaaa.bbb.cc.d.");
102 BOOST_CHECK( name.labelReverse() == DNSName("d.cc.bbb.aaaa."));
103 }
104
105 { // empty() empty
106 DNSName name;
107 BOOST_CHECK(name.empty());
108 }
109
110 { // empty() root
111 DNSName name(".");
112 BOOST_CHECK(!name.empty());
113
114 DNSName rootnodot("");
115 BOOST_CHECK_EQUAL(name, rootnodot);
116
117 string empty;
118 DNSName rootnodot2(empty);
119 BOOST_CHECK_EQUAL(rootnodot2, name);
120 }
121
122 DNSName left("ds9a.nl.");
123 left.prependRawLabel("www");
124 BOOST_CHECK( left == DNSName("WwW.Ds9A.Nl."));
125
126 left.appendRawLabel("com");
127
128 BOOST_CHECK( left == DNSName("WwW.Ds9A.Nl.com."));
129
130 DNSName unset;
131
132 unset.appendRawLabel("www");
133 unset.appendRawLabel("powerdns.com");
134 unset.appendRawLabel("com");
135
136 BOOST_CHECK_EQUAL(unset.toString(), "www.powerdns\\.com.com.");
137
138 DNSName rfc4343_2_1("~!.example.");
139 DNSName rfc4343_2_2(R"(Donald\032E\.\032Eastlake\0323rd.example.)");
140 DNSName example("example.");
141 BOOST_CHECK(rfc4343_2_1.isPartOf(example));
142 BOOST_CHECK(rfc4343_2_2.isPartOf(example));
143 BOOST_CHECK_EQUAL(rfc4343_2_1.toString(), "~!.example.");
144
145 auto labels=rfc4343_2_2.getRawLabels();
146 BOOST_CHECK_EQUAL(*labels.begin(), "Donald E. Eastlake 3rd");
147 BOOST_CHECK_EQUAL(*labels.rbegin(), "example");
148 BOOST_CHECK_EQUAL(labels.size(), 2);
149
150 DNSName build;
151 build.appendRawLabel("Donald E. Eastlake 3rd");
152 build.appendRawLabel("example");
153 BOOST_CHECK_EQUAL(build.toString(), R"(Donald\032E\.\032Eastlake\0323rd.example.)");
154 BOOST_CHECK_THROW(DNSName broken("bert..hubert."), std::runtime_error);
155
156 DNSName n;
157 n.appendRawLabel("powerdns.dnsmaster");
158 n.appendRawLabel("powerdns");
159 n.appendRawLabel("com");
160
161 BOOST_CHECK_EQUAL(n.toString(), "powerdns\\.dnsmaster.powerdns.com.");
162
163 // BOOST_CHECK(DNSName().toString() != ".");
164
165 DNSName p;
166 string label("power");
167 label.append(1, (char)0);
168 label.append("dns");
169 p.appendRawLabel(label);
170 p.appendRawLabel("com");
171
172 BOOST_CHECK_EQUAL(p.toString(), "power\\000dns.com.");
173 }
174
175 BOOST_AUTO_TEST_CASE(test_trim) {
176 DNSName w("www.powerdns.com.");
177 BOOST_CHECK_EQUAL(w.countLabels(), 3);
178 w.trimToLabels(2);
179 BOOST_CHECK_EQUAL(w.toString(), "powerdns.com.");
180 DNSName w2("powerdns.com.");
181 BOOST_CHECK(w==w2);
182
183 DNSName root(".");
184 BOOST_CHECK_EQUAL(root.countLabels(), 0);
185 }
186
187 BOOST_AUTO_TEST_CASE(test_toolong) {
188
189 BOOST_CHECK_THROW(DNSName w("1234567890123456789012345678901234567890123456789012345678901234567890.com."), std::range_error);
190
191 BOOST_CHECK_THROW(DNSName w("12345678901234567890.12345678901234567890123456.789012345678901.234567890.12345678901234567890.12345678901234567890123456.789012345678901.234567890.12345678901234567890.12345678901234567890123456.789012345678901.234567890.234567890.789012345678901.234567890.234567890.789012345678901.234567890.234567890.com."), std::range_error);
192 }
193
194 BOOST_AUTO_TEST_CASE(test_dnsstrings) {
195 DNSName w("www.powerdns.com.");
196 BOOST_CHECK_EQUAL(w.toDNSString(), string("\003www\010powerdns\003com\000", 18));
197 }
198
199 BOOST_AUTO_TEST_CASE(test_empty) {
200 DNSName empty;
201 BOOST_CHECK_THROW(empty.toString(), std::out_of_range);
202 BOOST_CHECK_THROW(empty.toStringNoDot(), std::out_of_range);
203 BOOST_CHECK_THROW(empty.toDNSString(), std::out_of_range);
204 BOOST_CHECK(empty.empty());
205 BOOST_CHECK(!empty.isRoot());
206 BOOST_CHECK(!empty.isWildcard());
207 BOOST_CHECK_EQUAL(empty, empty);
208 BOOST_CHECK(!(empty < empty));
209
210 DNSName root(".");
211 BOOST_CHECK(empty < root);
212
213 BOOST_CHECK_THROW(empty.isPartOf(root), std::out_of_range);
214 BOOST_CHECK_THROW(root.isPartOf(empty), std::out_of_range);
215 }
216
217 BOOST_AUTO_TEST_CASE(test_specials) {
218 DNSName root(".");
219
220 BOOST_CHECK(root.isRoot());
221 BOOST_CHECK(root != DNSName());
222
223 DNSName wcard("*.powerdns.com");
224 BOOST_CHECK(wcard.isWildcard());
225
226 DNSName notwcard("www.powerdns.com");
227 BOOST_CHECK(!notwcard.isWildcard());
228 }
229
230
231 BOOST_AUTO_TEST_CASE(test_chopping) {
232 DNSName w("www.powerdns.com.");
233 BOOST_CHECK_EQUAL(w.toString(), "www.powerdns.com.");
234 BOOST_CHECK(w.chopOff());
235 BOOST_CHECK_EQUAL(w.toString(), "powerdns.com.");
236 BOOST_CHECK(w.chopOff());
237 BOOST_CHECK_EQUAL(w.toString(), "com.");
238 BOOST_CHECK(w.chopOff());
239 BOOST_CHECK_EQUAL(w.toString(), ".");
240 BOOST_CHECK(!w.chopOff());
241 BOOST_CHECK(!w.chopOff());
242
243 w.prependRawLabel("net");
244 w.prependRawLabel("root-servers");
245 w.prependRawLabel("a");
246 BOOST_CHECK_EQUAL(w.toString(), "a.root-servers.net.");
247 }
248
249 BOOST_AUTO_TEST_CASE(test_Append) {
250 DNSName dn("www."), powerdns("powerdns.com.");
251 DNSName tot=dn+powerdns;
252
253 BOOST_CHECK_EQUAL(tot.toString(), "www.powerdns.com.");
254 BOOST_CHECK(tot == DNSName("www.powerdns.com."));
255
256 dn+=powerdns;
257
258 BOOST_CHECK(dn == DNSName("www.powerdns.com."));
259 }
260
261 BOOST_AUTO_TEST_CASE(test_packetCompress) {
262 reportBasicTypes();
263 vector<unsigned char> packet;
264 DNSPacketWriter dpw(packet, DNSName("www.ds9a.nl."), QType::AAAA);
265 dpw.startRecord(DNSName("ds9a.nl"), QType::SOA);
266 SOARecordContent src("ns1.powerdns.nl admin.powerdns.nl 1 2 3 4 5");
267 src.toPacket(dpw);
268 AAAARecordContent aaaa("::1");
269 dpw.startRecord(DNSName("www.dS9A.nl"), QType::AAAA);
270 aaaa.toPacket(dpw);
271 dpw.startRecord(DNSName("www.ds9A.nl"), QType::AAAA);
272 aaaa.toPacket(dpw);
273 dpw.startRecord(DNSName("www.dS9a.nl"), QType::AAAA);
274 aaaa.toPacket(dpw);
275 dpw.startRecord(DNSName("www2.DS9a.nl"), QType::AAAA);
276 aaaa.toPacket(dpw);
277 dpw.startRecord(DNSName("www2.dS9a.nl"), QType::AAAA);
278 aaaa.toPacket(dpw);
279 dpw.commit();
280 string str((const char*)&packet[0], (const char*)&packet[0] + packet.size());
281 size_t pos = 0;
282 int count=0;
283 while((pos = str.find("ds9a", pos)) != string::npos) {
284 ++pos;
285 ++count;
286 }
287 BOOST_CHECK_EQUAL(count, 1);
288 pos = 0;
289 count=0;
290 while((pos = str.find("powerdns", pos)) != string::npos) {
291 ++pos;
292 ++count;
293 }
294 BOOST_CHECK_EQUAL(count, 1);
295
296 }
297
298 BOOST_AUTO_TEST_CASE(test_packetCompressLong) {
299 reportBasicTypes();
300 vector<unsigned char> packet;
301 DNSName loopback("1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa");
302 DNSPacketWriter dpw(packet, loopback, QType::PTR);
303
304 dpw.startRecord(loopback, QType::PTR);
305 PTRRecordContent prc(DNSName("localhost"));
306 prc.toPacket(dpw);
307 dpw.commit();
308 DNSName roundtrip((char*)&packet[0], packet.size(), 12, false);
309 BOOST_CHECK_EQUAL(loopback,roundtrip);
310
311 packet.clear();
312 DNSName longer("1.2.3.4.5.6.7.8.1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa");
313 DNSPacketWriter dpw2(packet, longer, QType::PTR);
314
315 dpw2.startRecord(DNSName("a.b.c.d.e")+longer, QType::PTR);
316 PTRRecordContent prc2(DNSName("localhost"));
317 prc2.toPacket(dpw2);
318 dpw2.commit();
319
320 }
321
322
323
324
325 BOOST_AUTO_TEST_CASE(test_PacketParse) {
326 vector<unsigned char> packet;
327 reportBasicTypes();
328 DNSName root(".");
329 DNSPacketWriter dpw1(packet, g_rootdnsname, QType::AAAA);
330 DNSName p((char*)&packet[0], packet.size(), 12, false);
331 BOOST_CHECK_EQUAL(p, root);
332 unsigned char* buffer=&packet[0];
333 /* set invalid label len:
334 - packet.size() == 17 (sizeof(dnsheader) + 1 + 2 + 2)
335 - label len < packet.size() but
336 - offset is 12, label len of 15 should be rejected
337 because offset + 15 >= packet.size()
338 */
339 buffer[sizeof(dnsheader)] = 15;
340 BOOST_CHECK_THROW(DNSName((char*)&packet[0], packet.size(), 12, false), std::range_error);
341 }
342
343
344 BOOST_AUTO_TEST_CASE(test_hash) {
345 DNSName a("wwW.Ds9A.Nl"), b("www.ds9a.nl");
346 BOOST_CHECK_EQUAL(a.hash(), b.hash());
347
348 vector<uint32_t> counts(1500);
349
350 for(unsigned int n=0; n < 100000; ++n) {
351 DNSName dn(std::to_string(n)+"."+std::to_string(n*2)+"ds9a.nl");
352 DNSName dn2(std::to_string(n)+"."+std::to_string(n*2)+"Ds9a.nL");
353 BOOST_CHECK_EQUAL(dn.hash(), dn2.hash());
354 counts[dn.hash() % counts.size()]++;
355 }
356
357 double sum = std::accumulate(std::begin(counts), std::end(counts), 0.0);
358 double m = sum / counts.size();
359
360 double accum = 0.0;
361 std::for_each (std::begin(counts), std::end(counts), [&](const double d) {
362 accum += (d - m) * (d - m);
363 });
364
365 double stdev = sqrt(accum / (counts.size()-1));
366 BOOST_CHECK(stdev < 10);
367 }
368
369 BOOST_AUTO_TEST_CASE(test_hashContainer) {
370 std::unordered_set<DNSName> s;
371 s.insert(DNSName("www.powerdns.com"));
372 BOOST_CHECK(s.count(DNSName("WwW.PoWerDNS.CoM")));
373 BOOST_CHECK_EQUAL(s.size(), 1);
374 s.insert(DNSName("www.POWERDNS.com"));
375 BOOST_CHECK_EQUAL(s.size(), 1);
376 s.insert(DNSName("www2.POWERDNS.com"));
377 BOOST_CHECK_EQUAL(s.size(), 2);
378
379 s.clear();
380 unsigned int n=0;
381 for(; n < 100000; ++n)
382 s.insert(DNSName(std::to_string(n)+".test.nl"));
383 BOOST_CHECK_EQUAL(s.size(), n);
384
385 }
386
387
388 BOOST_AUTO_TEST_CASE(test_QuestionHash) {
389 vector<unsigned char> packet;
390 reportBasicTypes();
391 DNSPacketWriter dpw1(packet, DNSName("www.ds9a.nl."), QType::AAAA);
392
393 auto hash1=hashQuestion((char*)&packet[0], packet.size(), 0);
394 DNSPacketWriter dpw2(packet, DNSName("wWw.Ds9A.nL."), QType::AAAA);
395 auto hash2=hashQuestion((char*)&packet[0], packet.size(), 0);
396 BOOST_CHECK_EQUAL(hash1, hash2);
397
398 vector<uint32_t> counts(1500);
399
400 for(unsigned int n=0; n < 100000; ++n) {
401 packet.clear();
402 DNSPacketWriter dpw3(packet, DNSName(std::to_string(n)+"."+std::to_string(n*2)+"."), QType::AAAA);
403 counts[hashQuestion((char*)&packet[0], packet.size(), 0) % counts.size()]++;
404 }
405
406 double sum = std::accumulate(std::begin(counts), std::end(counts), 0.0);
407 double m = sum / counts.size();
408
409 double accum = 0.0;
410 std::for_each (std::begin(counts), std::end(counts), [&](const double d) {
411 accum += (d - m) * (d - m);
412 });
413
414 double stdev = sqrt(accum / (counts.size()-1));
415 BOOST_CHECK(stdev < 10);
416 }
417
418
419 BOOST_AUTO_TEST_CASE(test_packetParse) {
420 vector<unsigned char> packet;
421 reportBasicTypes();
422 DNSPacketWriter dpw(packet, DNSName("www.ds9a.nl."), QType::AAAA);
423
424 uint16_t qtype, qclass;
425 DNSName dn((char*)&packet[0], packet.size(), 12, false, &qtype, &qclass);
426 BOOST_CHECK_EQUAL(dn.toString(), "www.ds9a.nl.");
427 BOOST_CHECK(qtype == QType::AAAA);
428 BOOST_CHECK_EQUAL(qclass, 1);
429
430 dpw.startRecord(DNSName("ds9a.nl."), DNSRecordContent::TypeToNumber("NS"));
431 NSRecordContent nrc("ns1.powerdns.com");
432 nrc.toPacket(dpw);
433
434 dpw.commit();
435
436 /* packet now looks like this:
437 012345678901 12 bytes of header
438 3www4ds9a2nl0 13 bytes of name
439 0001 0001 4 bytes of qtype and qclass
440 answername 2 bytes
441 0001 0001 4 bytes of qtype and class
442 0000 0000 4 bytes of TTL
443 0000 2 bytes of content length
444 content name */
445
446 DNSName dn2((char*)&packet[0], packet.size(), 12+13+4, true, &qtype, &qclass);
447 BOOST_CHECK_EQUAL(dn2.toString(), "ds9a.nl.");
448 BOOST_CHECK(qtype == QType::NS);
449 BOOST_CHECK_EQUAL(qclass, 1);
450
451 DNSName dn3((char*)&packet[0], packet.size(), 12+13+4+2 + 4 + 4 + 2, true);
452 BOOST_CHECK_EQUAL(dn3.toString(), "ns1.powerdns.com.");
453 try {
454 DNSName dn4((char*)&packet[0], packet.size(), 12+13+4, false); // compressed, should fail
455 BOOST_CHECK(0);
456 }
457 catch(...){}
458 }
459
460 BOOST_AUTO_TEST_CASE(test_escaping) {
461 DNSName n;
462 string label;
463
464 for(int i = 0; i < 250; ++i) {
465 if(!((i+1)%63)) {
466 n.appendRawLabel(label);
467 label.clear();
468 }
469 label.append(1,(char)i);
470 }
471 if(!label.empty())
472 n.appendRawLabel(label);
473
474 DNSName n2(n.toString());
475 BOOST_CHECK(n==n2);
476 }
477
478 BOOST_AUTO_TEST_CASE(test_suffixmatch) {
479 SuffixMatchNode smn;
480 DNSName ezdns("ezdns.it.");
481 smn.add(ezdns.getRawLabels());
482
483 smn.add(DNSName("org.").getRawLabels());
484
485 DNSName wwwpowerdnscom("www.powerdns.com.");
486 DNSName wwwezdnsit("www.ezdns.it.");
487 BOOST_CHECK(smn.check(wwwezdnsit));
488 BOOST_CHECK(!smn.check(wwwpowerdnscom));
489
490 BOOST_CHECK(smn.check(DNSName("www.powerdns.org.")));
491 BOOST_CHECK(smn.check(DNSName("www.powerdns.oRG.")));
492
493 smn.add(DNSName("news.bbc.co.uk."));
494 BOOST_CHECK(smn.check(DNSName("news.bbc.co.uk.")));
495 BOOST_CHECK(smn.check(DNSName("www.news.bbc.co.uk.")));
496 BOOST_CHECK(smn.check(DNSName("www.www.www.www.www.news.bbc.co.uk.")));
497 BOOST_CHECK(!smn.check(DNSName("images.bbc.co.uk.")));
498
499 BOOST_CHECK(!smn.check(DNSName("www.news.gov.uk.")));
500
501 smn.add(g_rootdnsname); // block the root
502 BOOST_CHECK(smn.check(DNSName("a.root-servers.net.")));
503
504 DNSName examplenet("example.net.");
505 DNSName net("net.");
506 smn.add(examplenet);
507 smn.add(net);
508 BOOST_CHECK(smn.check(examplenet));
509 BOOST_CHECK(smn.check(net));
510
511 // Remove .net and the root, and check that example.net still exists
512 smn.remove(g_rootdnsname);
513 smn.remove(net);
514 BOOST_CHECK_EQUAL(smn.check(net), false);
515 BOOST_CHECK(smn.check(examplenet));
516
517 smn.add(DNSName("fr."));
518 smn.add(DNSName("www.sub.domain.fr."));
519 // should not match www.sub.domain.fr. but should still match fr.
520 BOOST_CHECK(smn.check(DNSName("sub.domain.fr.")));
521 }
522
523 BOOST_AUTO_TEST_CASE(test_suffixmatch_tree) {
524 SuffixMatchTree<DNSName> smt;
525 DNSName ezdns("ezdns.it.");
526 smt.add(ezdns, ezdns);
527
528 smt.add(DNSName("org.").getRawLabels(), DNSName("org."));
529
530 DNSName wwwpowerdnscom("www.powerdns.com.");
531 DNSName wwwezdnsit("www.ezdns.it.");
532 BOOST_REQUIRE(smt.lookup(wwwezdnsit));
533 BOOST_CHECK_EQUAL(*smt.lookup(wwwezdnsit), ezdns);
534 BOOST_CHECK(smt.lookup(wwwpowerdnscom) == nullptr);
535
536 BOOST_REQUIRE(smt.lookup(DNSName("www.powerdns.org.")));
537 BOOST_CHECK_EQUAL(*smt.lookup(DNSName("www.powerdns.org.")), DNSName("org."));
538 BOOST_REQUIRE(smt.lookup(DNSName("www.powerdns.oRG.")));
539 BOOST_CHECK_EQUAL(*smt.lookup(DNSName("www.powerdns.oRG.")), DNSName("org."));
540
541 smt.add(DNSName("news.bbc.co.uk."), DNSName("news.bbc.co.uk."));
542 BOOST_REQUIRE(smt.lookup(DNSName("news.bbc.co.uk.")));
543 BOOST_CHECK_EQUAL(*smt.lookup(DNSName("news.bbc.co.uk.")), DNSName("news.bbc.co.uk."));
544 BOOST_REQUIRE(smt.lookup(DNSName("www.news.bbc.co.uk.")));
545 BOOST_CHECK_EQUAL(*smt.lookup(DNSName("www.news.bbc.co.uk.")), DNSName("news.bbc.co.uk."));
546 BOOST_REQUIRE(smt.lookup(DNSName("www.www.www.www.www.news.bbc.co.uk.")));
547 BOOST_CHECK_EQUAL(*smt.lookup(DNSName("www.www.www.www.www.news.bbc.co.uk.")), DNSName("news.bbc.co.uk."));
548 BOOST_CHECK(smt.lookup(DNSName("images.bbc.co.uk.")) == nullptr);
549 BOOST_CHECK(smt.lookup(DNSName("www.news.gov.uk.")) == nullptr);
550
551 smt.add(g_rootdnsname, g_rootdnsname); // block the root
552 BOOST_REQUIRE(smt.lookup(DNSName("a.root-servers.net.")));
553 BOOST_CHECK_EQUAL(*smt.lookup(DNSName("a.root-servers.net.")), g_rootdnsname);
554
555 DNSName apowerdnscom("a.powerdns.com.");
556 DNSName bpowerdnscom("b.powerdns.com.");
557 smt.add(apowerdnscom, apowerdnscom);
558 smt.add(bpowerdnscom, bpowerdnscom);
559 BOOST_REQUIRE(smt.lookup(apowerdnscom));
560 BOOST_CHECK_EQUAL(*smt.lookup(apowerdnscom), apowerdnscom);
561 BOOST_REQUIRE(smt.lookup(bpowerdnscom));
562 BOOST_CHECK_EQUAL(*smt.lookup(bpowerdnscom), bpowerdnscom);
563
564 DNSName examplenet("example.net.");
565 DNSName net("net.");
566 smt.add(examplenet, examplenet);
567 smt.add(net, net);
568 BOOST_REQUIRE(smt.lookup(examplenet));
569 BOOST_CHECK_EQUAL(*smt.lookup(examplenet), examplenet);
570 BOOST_REQUIRE(smt.lookup(net));
571 BOOST_CHECK_EQUAL(*smt.lookup(net), net);
572
573 // Remove .net and the root, and check that example.net remains
574 smt.remove(g_rootdnsname);
575 smt.remove(net);
576 BOOST_CHECK(smt.lookup(net) == nullptr);
577 BOOST_CHECK_EQUAL(*smt.lookup(examplenet), examplenet);
578
579 smt = SuffixMatchTree<DNSName>();
580 smt.add(examplenet, examplenet);
581 smt.add(net, net);
582 smt.add(DNSName("news.bbc.co.uk."), DNSName("news.bbc.co.uk."));
583 smt.add(apowerdnscom, apowerdnscom);
584
585 smt.remove(DNSName("not-such-entry.news.bbc.co.uk."));
586 BOOST_REQUIRE(smt.lookup(DNSName("news.bbc.co.uk.")));
587 smt.remove(DNSName("news.bbc.co.uk."));
588 BOOST_CHECK(smt.lookup(DNSName("news.bbc.co.uk.")) == nullptr);
589
590 smt.remove(net);
591 BOOST_REQUIRE(smt.lookup(examplenet));
592 BOOST_CHECK_EQUAL(*smt.lookup(examplenet), examplenet);
593 BOOST_CHECK(smt.lookup(net) == nullptr);
594
595 smt.remove(examplenet);
596 BOOST_CHECK(smt.lookup(net) == nullptr);
597 BOOST_CHECK(smt.lookup(examplenet) == nullptr);
598
599 smt.add(examplenet, examplenet);
600 smt.add(net, net);
601 BOOST_REQUIRE(smt.lookup(examplenet));
602 BOOST_CHECK_EQUAL(*smt.lookup(examplenet), examplenet);
603 BOOST_REQUIRE(smt.lookup(net));
604 BOOST_CHECK_EQUAL(*smt.lookup(net), net);
605
606 smt.remove(examplenet);
607 BOOST_CHECK_EQUAL(*smt.lookup(examplenet), net);
608 BOOST_CHECK_EQUAL(*smt.lookup(net), net);
609 smt.remove(examplenet);
610 BOOST_CHECK_EQUAL(*smt.lookup(examplenet), net);
611 BOOST_CHECK_EQUAL(*smt.lookup(net), net);
612 smt.remove(net);
613 BOOST_CHECK(smt.lookup(net) == nullptr);
614 BOOST_CHECK(smt.lookup(examplenet) == nullptr);
615 smt.remove(net);
616
617 size_t count = 0;
618 smt.visit([apowerdnscom, &count](const SuffixMatchTree<DNSName>& smt) {
619 count++;
620 BOOST_CHECK_EQUAL(smt.d_value, apowerdnscom);
621 });
622 BOOST_CHECK_EQUAL(count, 1);
623
624 BOOST_CHECK_EQUAL(*smt.lookup(apowerdnscom), apowerdnscom);
625 smt.remove(apowerdnscom);
626 BOOST_CHECK(smt.lookup(apowerdnscom) == nullptr);
627
628 count = 0;
629 smt.visit([&count](const SuffixMatchTree<DNSName>& smt) {
630 count++;
631 });
632 BOOST_CHECK_EQUAL(count, 0);
633 }
634
635
636 BOOST_AUTO_TEST_CASE(test_concat) {
637 DNSName first("www."), second("powerdns.com.");
638 BOOST_CHECK_EQUAL((first+second).toString(), "www.powerdns.com.");
639 }
640
641 BOOST_AUTO_TEST_CASE(test_compare_naive) {
642 BOOST_CHECK(DNSName("abc.com.") < DNSName("zdf.com."));
643 BOOST_CHECK(DNSName("Abc.com.") < DNSName("zdf.com."));
644 BOOST_CHECK(DNSName("Abc.com.") < DNSName("Zdf.com."));
645 BOOST_CHECK(DNSName("abc.com.") < DNSName("Zdf.com."));
646 }
647
648 BOOST_AUTO_TEST_CASE(test_compare_empty) {
649 DNSName a, b;
650 BOOST_CHECK(!(a<b));
651 BOOST_CHECK(!a.canonCompare(b));
652 }
653
654 BOOST_AUTO_TEST_CASE(test_casing) {
655 DNSName a("WwW.PoWeRdNS.Com"), b("www.powerdns.com.");
656 BOOST_CHECK_EQUAL(a,b);
657 BOOST_CHECK_EQUAL(a.toString(), "WwW.PoWeRdNS.Com.");
658 DNSName c=a.makeLowerCase();
659 BOOST_CHECK_EQUAL(a,c);
660 BOOST_CHECK_EQUAL(b,c);
661 BOOST_CHECK_EQUAL(c.toString(), b.toString());
662 BOOST_CHECK_EQUAL(c.toString(), "www.powerdns.com.");
663 }
664
665
666
667 BOOST_AUTO_TEST_CASE(test_compare_canonical) {
668 DNSName lower("bert.com."), higher("alpha.nl.");
669 BOOST_CHECK(lower.canonCompare(higher));
670
671 BOOST_CHECK(DNSName("bert.com").canonCompare(DNSName("www.bert.com")));
672 BOOST_CHECK(DNSName("BeRt.com").canonCompare(DNSName("WWW.berT.com")));
673 BOOST_CHECK(!DNSName("www.BeRt.com").canonCompare(DNSName("WWW.berT.com")));
674
675 CanonDNSNameCompare a;
676 BOOST_CHECK(a(g_rootdnsname, DNSName("www.powerdns.com")));
677 BOOST_CHECK(a(g_rootdnsname, DNSName("www.powerdns.net")));
678 BOOST_CHECK(!a(DNSName("www.powerdns.net"), g_rootdnsname));
679
680 vector<DNSName> vec;
681 for(const std::string& b : {"bert.com.", "alpha.nl.", "articles.xxx.",
682 "Aleph1.powerdns.com.", "ZOMG.powerdns.com.", "aaa.XXX.", "yyy.XXX.",
683 "test.powerdns.com.", "\\128.com"}) {
684 vec.push_back(DNSName(b));
685 }
686 sort(vec.begin(), vec.end(), CanonDNSNameCompare());
687 // for(const auto& v : vec)
688 // cerr<<'"'<<v<<'"'<<endl;
689
690 vector<DNSName> right;
691 for(const auto& b: {"bert.com.", "Aleph1.powerdns.com.",
692 "test.powerdns.com.",
693 "ZOMG.powerdns.com.",
694 "\\128.com.",
695 "alpha.nl.",
696 "aaa.XXX.",
697 "articles.xxx.",
698 "yyy.XXX."})
699 right.push_back(DNSName(b));
700
701
702 BOOST_CHECK(vec==right);
703 }
704
705
706 BOOST_AUTO_TEST_CASE(test_empty_label) { // empty label
707
708 { // append
709 DNSName dn("www.");
710 BOOST_CHECK_THROW(dn.appendRawLabel(""), std::range_error);
711 }
712
713 { // prepend
714 DNSName dn("www.");
715 BOOST_CHECK_THROW(dn.prependRawLabel(""), std::range_error);
716 }
717 }
718
719 BOOST_AUTO_TEST_CASE(test_label_length_max) { // 63 char label
720
721 string label("123456789012345678901234567890123456789012345678901234567890123");
722
723 { // append
724 DNSName dn("www.");
725 dn.appendRawLabel(label);
726 BOOST_CHECK_EQUAL(dn.toString(), "www." + label + ".");
727 }
728
729 { // prepend
730 DNSName dn("www.");
731 dn.prependRawLabel(label);
732 BOOST_CHECK_EQUAL(dn.toString(), label + ".www.");
733 }
734 }
735
736 BOOST_AUTO_TEST_CASE(test_label_length_too_long) { // 64 char label
737
738 string label("1234567890123456789012345678901234567890123456789012345678901234");
739
740 { // append
741 DNSName dn("www.");
742 BOOST_CHECK_THROW(dn.appendRawLabel(label), std::range_error);
743 }
744
745 { // prepend
746 DNSName dn("www.");
747 BOOST_CHECK_THROW(dn.prependRawLabel(label), std::range_error);
748 }
749 }
750
751 BOOST_AUTO_TEST_CASE(test_name_length_max) { // 255 char name
752
753 string name("123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789."
754 "123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789."
755 "123456789.123456789.123456789.123456789.123456789.");
756 string label("123");
757
758 { // append
759 DNSName dn(name);
760 dn.appendRawLabel(label);
761 BOOST_CHECK_EQUAL(dn.toString().size(), 254);
762 }
763
764 { // prepend
765 DNSName dn(name);
766 dn.prependRawLabel(label);
767 BOOST_CHECK_EQUAL(dn.toString().size(), 254);
768 }
769
770 { // concat
771 DNSName dn(name);
772
773 dn += DNSName(label + ".");
774 BOOST_CHECK_EQUAL(dn.toString().size(), 254);
775 }
776 }
777
778 BOOST_AUTO_TEST_CASE(test_name_length_too_long) { // 256 char name
779
780 string name("123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789."
781 "123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789.123456789."
782 "123456789.123456789.123456789.123456789.123456789.");
783 string label("1234");
784
785 { // append
786 DNSName dn(name);
787 BOOST_CHECK_THROW(dn.appendRawLabel(label), std::range_error);
788 }
789
790 { // prepend
791 DNSName dn(name);
792 BOOST_CHECK_THROW(dn.prependRawLabel(label), std::range_error);
793 }
794
795 { // concat
796 DNSName dn(name);
797 BOOST_CHECK_THROW(dn += DNSName(label + "."), std::range_error);
798 }
799 }
800
801
802 BOOST_AUTO_TEST_CASE(test_invalid_label_length) { // Invalid label length in qname
803
804 string name("\x02""ns\x07""example\x04""com\x00", 16);
805
806 BOOST_CHECK_THROW(DNSName dn(name.c_str(), name.size(), 0, true), std::range_error);
807 }
808
809 BOOST_AUTO_TEST_CASE(test_compression) { // Compression test
810
811 string name("\x03""com\x00""\x07""example\xc0""\x00""\x03""www\xc0""\x05", 21);
812
813 DNSName dn(name.c_str(), name.size(), 15, true);
814 BOOST_CHECK_EQUAL(dn.toString(), "www.example.com.");
815 }
816
817 BOOST_AUTO_TEST_CASE(test_compression_qtype_qclass) { // Compression test with QClass and QType extraction
818
819 uint16_t qtype = 0;
820 uint16_t qclass = 0;
821
822 {
823 string name("\x03""com\x00""\x07""example\xc0""\x00""\x03""www\xc0""\x05""\x00""\x01""\x00""\x01", 25);
824 DNSName dn(name.c_str(), name.size(), 15, true, &qtype, &qclass);
825 BOOST_CHECK_EQUAL(dn.toString(), "www.example.com.");
826 BOOST_CHECK_EQUAL(qtype, 1);
827 BOOST_CHECK_EQUAL(qclass, 1);
828 }
829
830 {
831 /* same but this time we are one byte short for the qclass */
832 string name("\x03""com\x00""\x07""example\xc0""\x00""\x03""www\xc0""\x05""\x00""\x01""\x00""", 24);
833 BOOST_CHECK_THROW(DNSName dn(name.c_str(), name.size(), 15, true, &qtype, &qclass), std::range_error);
834 }
835
836 {
837 /* this time with a compression pointer such as (labellen << 8) != 0, see #4718 */
838 string name("\x03""com\x00""\x07""example\xc1""\x00""\x03""www\xc1""\x05""\x00""\x01""\x00""\x01", 25);
839 name.insert(0, 256, '0');
840
841 DNSName dn(name.c_str(), name.size(), 271, true, &qtype, &qclass);
842 BOOST_CHECK_EQUAL(dn.toString(), "www.example.com.");
843 BOOST_CHECK_EQUAL(qtype, 1);
844 BOOST_CHECK_EQUAL(qclass, 1);
845 }
846
847 {
848 /* same but this time we are one byte short for the qclass */
849 string name("\x03""com\x00""\x07""example\xc1""\x00""\x03""www\xc1""\x05""\x00""\x01""\x00", 24);
850 name.insert(0, 256, '0');
851
852 BOOST_CHECK_THROW(DNSName dn(name.c_str(), name.size(), 271, true, &qtype, &qclass), std::range_error);
853 }
854 }
855
856 BOOST_AUTO_TEST_CASE(test_compression_single_bit_set) { // first 2 bits as 10 or 01, not 11
857
858 // first 2 bits: 10
859 {
860 string name("\x03""com\x00""\x07""example\x80""\x00""\x03""www\x80""\x05", 21);
861
862 BOOST_CHECK_THROW(DNSName dn(name.c_str(), name.size(), 15, true), std::range_error);
863 }
864
865 // first 2 bits: 01
866 {
867 string name("\x03""com\x00""\x07""example\x40""\x00""\x03""www\x40""\x05", 21);
868
869 BOOST_CHECK_THROW(DNSName dn(name.c_str(), name.size(), 15, true), std::range_error);
870 }
871
872 }
873
874 BOOST_AUTO_TEST_CASE(test_pointer_pointer_root) { // Pointer to pointer to root
875
876 string name("\x00""\xc0""\x00""\x03""com\xc0""\x01",9);
877
878 DNSName dn(name.c_str(), name.size(), 3, true);
879 BOOST_CHECK_EQUAL(dn.toString(), "com.");
880 }
881
882 BOOST_AUTO_TEST_CASE(test_bad_compression_pointer) { // Pointing beyond packet boundary
883
884 std::string name("\x03""com\x00""\x07""example\xc0""\x11""xc0""\x00", 17);
885
886 BOOST_CHECK_THROW(DNSName dn(name.c_str(), name.length(), 5, true), std::range_error);
887 }
888
889 BOOST_AUTO_TEST_CASE(test_compression_loop) { // Compression loop (add one label)
890
891 std::string name("\x03""www\xc0""\x00", 6);
892
893 BOOST_CHECK_THROW(DNSName dn(name.c_str(), name.length(), 0, true), std::range_error);
894 }
895
896 BOOST_AUTO_TEST_CASE(test_compression_loop1) { // Compression loop (pointer loop)
897
898 string name("\xc0""\x00", 2);
899
900 BOOST_CHECK_THROW(DNSName dn(name.c_str(), name.size(), 0, true), std::range_error);
901 }
902
903 BOOST_AUTO_TEST_CASE(test_compression_loop2) { // Compression loop (deep recursion)
904
905 int i;
906 string name("\x00\xc0\x00", 3);
907 for (i=0; i<98; ++i) {
908 name.append( 1, ((i >> 7) & 0xff) | 0xc0);
909 name.append( 1, ((i << 1) & 0xff) | 0x01);
910 }
911 BOOST_CHECK_NO_THROW(DNSName dn(name.c_str(), name.size(), name.size()-2, true));
912
913 ++i;
914 name.append( 1, ((i >> 7) & 0xff) | 0xc0);
915 name.append( 1, ((i << 1) & 0xff) | 0x01);
916
917 BOOST_CHECK_THROW(DNSName dn(name.c_str(), name.size(), name.size()-2, true), std::range_error);
918 }
919
920 BOOST_AUTO_TEST_CASE(test_wirelength) { // Testing if we get the correct value from the wirelength function
921 DNSName name("www.powerdns.com");
922 BOOST_CHECK_EQUAL(name.wirelength(), 18);
923
924 DNSName sname("powerdns.com");
925 sname.prependRawLabel(string("ww\x00""w", 4));
926 BOOST_CHECK_EQUAL(sname.wirelength(), 19);
927
928 sname = DNSName("powerdns.com");
929 sname.prependRawLabel(string("www\x00", 4));
930 BOOST_CHECK_EQUAL(sname.wirelength(), 19);
931 }
932
933 BOOST_AUTO_TEST_CASE(test_getrawlabel) {
934 DNSName name("a.bb.ccc.dddd.");
935 BOOST_CHECK_EQUAL(name.getRawLabel(0), "a");
936 BOOST_CHECK_EQUAL(name.getRawLabel(1), "bb");
937 BOOST_CHECK_EQUAL(name.getRawLabel(2), "ccc");
938 BOOST_CHECK_EQUAL(name.getRawLabel(3), "dddd");
939 BOOST_CHECK_THROW(name.getRawLabel(name.countLabels()), std::out_of_range);
940 }
941
942 BOOST_AUTO_TEST_CASE(test_getlastlabel) {
943 DNSName name("www.powerdns.com");
944 DNSName ans = name.getLastLabel();
945
946 // Check the const-ness
947 BOOST_CHECK_EQUAL(name, DNSName("www.powerdns.com"));
948
949 // Check if the last label is indeed returned
950 BOOST_CHECK_EQUAL(ans, DNSName("com"));
951 }
952
953 BOOST_AUTO_TEST_CASE(test_getcommonlabels) {
954 const DNSName name1("www.powerdns.com");
955 const DNSName name2("a.long.list.of.labels.powerdns.com");
956
957 BOOST_CHECK_EQUAL(name1.getCommonLabels(name1), name1);
958 BOOST_CHECK_EQUAL(name2.getCommonLabels(name2), name2);
959
960 BOOST_CHECK_EQUAL(name1.getCommonLabels(name2), DNSName("powerdns.com"));
961 BOOST_CHECK_EQUAL(name2.getCommonLabels(name1), DNSName("powerdns.com"));
962
963 const DNSName name3("www.powerdns.org");
964 BOOST_CHECK_EQUAL(name1.getCommonLabels(name3), DNSName());
965 BOOST_CHECK_EQUAL(name2.getCommonLabels(name3), DNSName());
966 BOOST_CHECK_EQUAL(name3.getCommonLabels(name1), DNSName());
967 BOOST_CHECK_EQUAL(name3.getCommonLabels(name2), DNSName());
968
969 const DNSName name4("WWw.PowErDnS.org");
970 BOOST_CHECK_EQUAL(name3.getCommonLabels(name4), name3);
971 BOOST_CHECK_EQUAL(name4.getCommonLabels(name3), name4);
972 }
973
974 BOOST_AUTO_TEST_SUITE_END()