]> git.ipfire.org Git - thirdparty/pdns.git/blame - pdns/filterpo.cc
rec: Add regression tests for the ordering of RPZ policies
[thirdparty/pdns.git] / pdns / filterpo.cc
CommitLineData
12471842
PL
1/*
2 * This file is part of PowerDNS or dnsdist.
3 * Copyright -- PowerDNS.COM B.V. and its contributors
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * In addition, for the avoidance of any doubt, permission is granted to
10 * link this program with OpenSSL and to (re)distribute the binaries
11 * produced as the result of such linking.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 */
6791663c
RG
22
23#include <cinttypes>
644dd1da 24#include <iostream>
6791663c
RG
25
26#include "filterpo.hh"
644dd1da 27#include "namespaces.hh"
28#include "dnsrecords.hh"
29
30DNSFilterEngine::DNSFilterEngine()
31{
32}
33
272e9a00
RG
34bool DNSFilterEngine::Zone::findExactQNamePolicy(const DNSName& qname, DNSFilterEngine::Policy& pol) const
35{
36 return findExactNamedPolicy(d_qpolName, qname, pol);
37}
38
272e9a00
RG
39bool DNSFilterEngine::Zone::findExactNSPolicy(const DNSName& qname, DNSFilterEngine::Policy& pol) const
40{
41 return findExactNamedPolicy(d_propolName, qname, pol);
42}
43
6791663c
RG
44bool DNSFilterEngine::Zone::findNSIPPolicy(const ComboAddress& addr, DNSFilterEngine::Policy& pol) const
45{
46 if (const auto fnd = d_propolNSAddr.lookup(addr)) {
47 pol = fnd->second;
48 return true;
49 }
50 return false;
51}
52
53bool DNSFilterEngine::Zone::findResponsePolicy(const ComboAddress& addr, DNSFilterEngine::Policy& pol) const
54{
55 if (const auto fnd = d_postpolAddr.lookup(addr)) {
56 pol = fnd->second;
57 return true;
58 }
59 return false;
60}
61
62bool DNSFilterEngine::Zone::findClientPolicy(const ComboAddress& addr, DNSFilterEngine::Policy& pol) const
63{
64 if (const auto fnd = d_qpolAddr.lookup(addr)) {
65 pol = fnd->second;
66 return true;
67 }
68 return false;
69}
70
272e9a00 71bool DNSFilterEngine::Zone::findNamedPolicy(const std::unordered_map<DNSName, DNSFilterEngine::Policy>& polmap, const DNSName& qname, DNSFilterEngine::Policy& pol)
644dd1da 72{
272e9a00
RG
73 if (polmap.empty()) {
74 return false;
75 }
76
5678437b
PL
77 /* for www.powerdns.com, we need to check:
78 www.powerdns.com.
79 *.powerdns.com.
80 *.com.
81 *.
82 */
0a273054 83
a2d0450e
RG
84 std::unordered_map<DNSName, DNSFilterEngine::Policy>::const_iterator iter;
85 iter = polmap.find(qname);
bef458b2
PL
86
87 if(iter != polmap.end()) {
88 pol=iter->second;
89 return true;
90 }
5678437b 91
a2d0450e 92 DNSName s(qname);
bef458b2 93 while(s.chopOff()){
12c06211 94 iter = polmap.find(g_wildcarddnsname+s);
5678437b
PL
95 if(iter != polmap.end()) {
96 pol=iter->second;
97 return true;
98 }
bef458b2 99 }
644dd1da 100 return false;
101}
102
272e9a00
RG
103bool DNSFilterEngine::Zone::findExactNamedPolicy(const std::unordered_map<DNSName, DNSFilterEngine::Policy>& polmap, const DNSName& qname, DNSFilterEngine::Policy& pol)
104{
105 if (polmap.empty()) {
106 return false;
107 }
108
109 const auto& it = polmap.find(qname);
110 if (it != polmap.end()) {
111 pol = it->second;
112 return true;
113 }
114
115 return false;
116}
117
e37e5795 118DNSFilterEngine::Policy DNSFilterEngine::getProcessingPolicy(const DNSName& qname, const std::unordered_map<std::string,bool>& discardedPolicies, Priority currentPriority) const
644dd1da 119{
272e9a00
RG
120 // cout<<"Got question for nameserver name "<<qname<<endl;
121 std::vector<bool> zoneEnabled(d_zones.size());
122 size_t count = 0;
123 bool allEmpty = true;
124 for (const auto& z : d_zones) {
e37e5795
OM
125 if (z->getPriority() > currentPriority) {
126 break;
127 }
272e9a00 128 bool enabled = true;
6b972d59 129 const auto zoneName = z->getName();
272e9a00
RG
130 if (zoneName && discardedPolicies.find(*zoneName) != discardedPolicies.end()) {
131 enabled = false;
132 }
133 else {
134 if (z->hasNSPolicies()) {
135 allEmpty = false;
136 }
137 else {
138 enabled = false;
139 }
0a273054
RG
140 }
141
272e9a00
RG
142 zoneEnabled[count] = enabled;
143 ++count;
144 }
145
146 Policy pol;
06cfa23f
RG
147 if (allEmpty) {
148 return pol;
149 }
150
151 /* prepare the wildcard-based names */
152 std::vector<DNSName> wcNames;
153 wcNames.reserve(qname.countLabels());
154 DNSName s(qname);
155 while (s.chopOff()){
156 wcNames.emplace_back(g_wildcarddnsname+s);
157 }
158
159 count = 0;
160 for(const auto& z : d_zones) {
e37e5795
OM
161 if (z->getPriority() > currentPriority) {
162 break;
163 }
06cfa23f 164 if (!zoneEnabled[count]) {
272e9a00 165 ++count;
06cfa23f
RG
166 continue;
167 }
06cfa23f
RG
168 if (z->findExactNSPolicy(qname, pol)) {
169 // cerr<<"Had a hit on the nameserver ("<<qname<<") used to process the query"<<endl;
170 return pol;
272e9a00
RG
171 }
172
06cfa23f
RG
173 for (const auto& wc : wcNames) {
174 if (z->findExactNSPolicy(wc, pol)) {
175 // cerr<<"Had a hit on the nameserver ("<<qname<<") used to process the query"<<endl;
176 return pol;
272e9a00 177 }
644dd1da 178 }
06cfa23f 179 ++count;
644dd1da 180 }
272e9a00 181
644dd1da 182 return pol;
b8470add 183}
644dd1da 184
e37e5795 185DNSFilterEngine::Policy DNSFilterEngine::getProcessingPolicy(const ComboAddress& address, const std::unordered_map<std::string,bool>& discardedPolicies, Priority currentPriority) const
b8470add 186{
6791663c 187 Policy pol;
b8470add
PL
188 // cout<<"Got question for nameserver IP "<<address.toString()<<endl;
189 for(const auto& z : d_zones) {
e37e5795
OM
190 if (z->getPriority() > currentPriority) {
191 break;
192 }
6b972d59
RG
193 const auto zoneName = z->getName();
194 if(zoneName && discardedPolicies.find(*zoneName) != discardedPolicies.end()) {
0a273054
RG
195 continue;
196 }
197
6791663c 198 if(z->findNSIPPolicy(address, pol)) {
b8470add 199 // cerr<<"Had a hit on the nameserver ("<<address.toString()<<") used to process the query"<<endl;
6791663c 200 return pol;
b8470add
PL
201 }
202 }
6791663c 203 return pol;
b8470add 204}
644dd1da 205
e37e5795 206DNSFilterEngine::Policy DNSFilterEngine::getQueryPolicy(const DNSName& qname, const ComboAddress& ca, const std::unordered_map<std::string,bool>& discardedPolicies, Priority currentPriority) const
644dd1da 207{
06cfa23f 208 // cout<<"Got question for "<<qname<<" from "<<ca.toString()<<endl;
272e9a00
RG
209 std::vector<bool> zoneEnabled(d_zones.size());
210 size_t count = 0;
211 bool allEmpty = true;
212 for (const auto& z : d_zones) {
e37e5795
OM
213 if (z->getPriority() > currentPriority) {
214 break;
215 }
272e9a00 216 bool enabled = true;
6b972d59 217 const auto zoneName = z->getName();
272e9a00
RG
218 if (zoneName && discardedPolicies.find(*zoneName) != discardedPolicies.end()) {
219 enabled = false;
220 }
221 else {
06cfa23f 222 if (z->hasQNamePolicies() || z->hasClientPolicies()) {
272e9a00
RG
223 allEmpty = false;
224 }
225 else {
226 enabled = false;
227 }
0a273054
RG
228 }
229
272e9a00
RG
230 zoneEnabled[count] = enabled;
231 ++count;
232 }
233
234 Policy pol;
06cfa23f
RG
235 if (allEmpty) {
236 return pol;
237 }
238
239 /* prepare the wildcard-based names */
240 std::vector<DNSName> wcNames;
241 wcNames.reserve(qname.countLabels());
242 DNSName s(qname);
243 while (s.chopOff()){
244 wcNames.emplace_back(g_wildcarddnsname+s);
245 }
246
247 count = 0;
248 for (const auto& z : d_zones) {
e37e5795
OM
249 if (z->getPriority() > currentPriority) {
250 break;
251 }
06cfa23f 252 if (!zoneEnabled[count]) {
272e9a00 253 ++count;
06cfa23f 254 continue;
644dd1da 255 }
06cfa23f
RG
256 if (z->findExactQNamePolicy(qname, pol)) {
257 // cerr<<"Had a hit on the name of the query"<<endl;
258 return pol;
259 }
260
261 for (const auto& wc : wcNames) {
262 if (z->findExactQNamePolicy(wc, pol)) {
263 // cerr<<"Had a hit on the name of the query"<<endl;
264 return pol;
272e9a00
RG
265 }
266 }
272e9a00 267
06cfa23f
RG
268 if (z->findClientPolicy(ca, pol)) {
269 // cerr<<"Had a hit on the IP address ("<<ca.toString()<<") of the client"<<endl;
6791663c 270 return pol;
644dd1da 271 }
06cfa23f 272
ae001b0e 273 ++count;
644dd1da 274 }
275
39ec5d29 276 return pol;
644dd1da 277}
278
e37e5795 279DNSFilterEngine::Policy DNSFilterEngine::getPostPolicy(const vector<DNSRecord>& records, const std::unordered_map<std::string,bool>& discardedPolicies, Priority currentPriority) const
644dd1da 280{
6791663c 281 Policy pol;
644dd1da 282 ComboAddress ca;
06cfa23f
RG
283 for (const auto& r : records) {
284 if (r.d_place != DNSResourceRecord::ANSWER)
644dd1da 285 continue;
06cfa23f 286 if (r.d_type == QType::A) {
ba3c54cb
RG
287 if (auto rec = getRR<ARecordContent>(r)) {
288 ca = rec->getCA();
289 }
290 }
291 else if(r.d_type == QType::AAAA) {
292 if (auto rec = getRR<AAAARecordContent>(r)) {
293 ca = rec->getCA();
294 }
295 }
644dd1da 296 else
297 continue;
298
06cfa23f 299 for (const auto& z : d_zones) {
e37e5795
OM
300 if (z->getPriority() > currentPriority) {
301 break;
302 }
6b972d59 303 const auto zoneName = z->getName();
06cfa23f 304 if (zoneName && discardedPolicies.find(*zoneName) != discardedPolicies.end()) {
0a273054
RG
305 continue;
306 }
307
06cfa23f 308 if (z->findResponsePolicy(ca, pol)) {
6791663c
RG
309 return pol;
310 }
644dd1da 311 }
312 }
6791663c 313 return pol;
644dd1da 314}
315
0a273054 316void DNSFilterEngine::assureZones(size_t zone)
644dd1da 317{
0a273054 318 if(d_zones.size() <= zone)
644dd1da 319 d_zones.resize(zone+1);
644dd1da 320}
321
6da513b2 322void DNSFilterEngine::Zone::addClientTrigger(const Netmask& nm, Policy&& pol)
7eafc52f 323{
6b972d59 324 pol.d_name = d_name;
f3da83fe 325 pol.d_type = PolicyType::ClientIP;
6da513b2 326 d_qpolAddr.insert(nm).second=std::move(pol);
7eafc52f 327}
328
6da513b2 329void DNSFilterEngine::Zone::addResponseTrigger(const Netmask& nm, Policy&& pol)
0a7ef1b8 330{
6b972d59 331 pol.d_name = d_name;
f3da83fe 332 pol.d_type = PolicyType::ResponseIP;
6da513b2 333 d_postpolAddr.insert(nm).second=std::move(pol);
644dd1da 334}
335
d122dac0 336void DNSFilterEngine::Zone::addQNameTrigger(const DNSName& n, Policy&& pol, bool ignoreDuplicate)
644dd1da 337{
6da513b2
RG
338 auto it = d_qpolName.find(n);
339
340 if (it != d_qpolName.end()) {
341 auto& existingPol = it->second;
342
d122dac0 343 if (pol.d_kind != PolicyKind::Custom && !ignoreDuplicate) {
fc38ec55 344 throw std::runtime_error("Adding a QName-based filter policy of kind " + getKindToString(pol.d_kind) + " but a policy of kind " + getKindToString(existingPol.d_kind) + " already exists for the following QName: " + n.toLogString());
6da513b2
RG
345 }
346
d122dac0 347 if (existingPol.d_kind != PolicyKind::Custom && ignoreDuplicate) {
fc38ec55 348 throw std::runtime_error("Adding a QName-based filter policy of kind " + getKindToString(existingPol.d_kind) + " but there was already an existing policy for the following QName: " + n.toLogString());
6da513b2
RG
349 }
350
351 existingPol.d_custom.reserve(existingPol.d_custom.size() + pol.d_custom.size());
352
fc38ec55 353 std::move(pol.d_custom.begin(), pol.d_custom.end(), std::back_inserter(existingPol.d_custom));
6da513b2
RG
354 }
355 else {
356 auto& qpol = d_qpolName.insert({n, std::move(pol)}).first->second;
357 qpol.d_name = d_name;
358 qpol.d_type = PolicyType::QName;
359 }
644dd1da 360}
361
6da513b2 362void DNSFilterEngine::Zone::addNSTrigger(const DNSName& n, Policy&& pol)
644dd1da 363{
6b972d59 364 pol.d_name = d_name;
f3da83fe 365 pol.d_type = PolicyType::NSDName;
6da513b2 366 d_propolName.insert({n, std::move(pol)});
644dd1da 367}
368
6da513b2 369void DNSFilterEngine::Zone::addNSIPTrigger(const Netmask& nm, Policy&& pol)
644dd1da 370{
6b972d59 371 pol.d_name = d_name;
f3da83fe 372 pol.d_type = PolicyType::NSIP;
6da513b2 373 d_propolNSAddr.insert(nm).second = std::move(pol);
644dd1da 374}
39ec5d29 375
6da513b2 376bool DNSFilterEngine::Zone::rmClientTrigger(const Netmask& nm, const Policy& pol)
b8470add 377{
6b972d59 378 d_qpolAddr.erase(nm);
39ec5d29 379 return true;
380}
381
6da513b2 382bool DNSFilterEngine::Zone::rmResponseTrigger(const Netmask& nm, const Policy& pol)
39ec5d29 383{
6b972d59 384 d_postpolAddr.erase(nm);
39ec5d29 385 return true;
386}
387
6da513b2 388bool DNSFilterEngine::Zone::rmQNameTrigger(const DNSName& n, const Policy& pol)
39ec5d29 389{
690b86b7
OM
390 auto found = d_qpolName.find(n);
391 if (found == d_qpolName.end()) {
6da513b2
RG
392 return false;
393 }
394
690b86b7 395 auto& existing = found->second;
6da513b2 396 if (existing.d_kind != DNSFilterEngine::PolicyKind::Custom) {
690b86b7 397 d_qpolName.erase(found);
6da513b2
RG
398 return true;
399 }
400
401 /* for custom types, we might have more than one type,
402 and then we need to remove only the right ones. */
403 if (existing.d_custom.size() <= 1) {
690b86b7 404 d_qpolName.erase(found);
6da513b2
RG
405 return true;
406 }
407
408 bool result = false;
3b027d9e 409 for (auto& toRemove : pol.d_custom) {
6da513b2 410 for (auto it = existing.d_custom.begin(); it != existing.d_custom.end(); ++it) {
3b027d9e 411 if (**it == *toRemove) {
6da513b2
RG
412 existing.d_custom.erase(it);
413 result = true;
414 break;
415 }
416 }
417 }
418
419 return result;
39ec5d29 420}
421
6da513b2 422bool DNSFilterEngine::Zone::rmNSTrigger(const DNSName& n, const Policy& pol)
39ec5d29 423{
6b972d59 424 d_propolName.erase(n); // XXX verify policy matched? =pol;
39ec5d29 425 return true;
426}
b8470add 427
6da513b2 428bool DNSFilterEngine::Zone::rmNSIPTrigger(const Netmask& nm, const Policy& pol)
b8470add 429{
6b972d59 430 d_propolNSAddr.erase(nm);
b8470add
PL
431 return true;
432}
a9e029ee 433
6da513b2
RG
434DNSRecord DNSFilterEngine::Policy::getRecordFromCustom(const DNSName& qname, const std::shared_ptr<DNSRecordContent>& custom) const
435{
436 DNSRecord dr;
437 dr.d_name = qname;
438 dr.d_type = custom->getType();
439 dr.d_ttl = d_ttl;
440 dr.d_class = QClass::IN;
441 dr.d_place = DNSResourceRecord::ANSWER;
442 dr.d_content = custom;
443
444 if (dr.d_type == QType::CNAME) {
445 const auto content = std::dynamic_pointer_cast<CNAMERecordContent>(custom);
446 if (content) {
447 DNSName target = content->getTarget();
448 if (target.isWildcard()) {
449 target.chopOff();
450 dr.d_content = std::make_shared<CNAMERecordContent>(qname + target);
451 }
452 }
453 }
454
455 return dr;
456}
457
458std::vector<DNSRecord> DNSFilterEngine::Policy::getCustomRecords(const DNSName& qname, uint16_t qtype) const
a9e029ee
RG
459{
460 if (d_kind != PolicyKind::Custom) {
461 throw std::runtime_error("Asking for a custom record from a filtering policy of a non-custom type");
462 }
463
6da513b2 464 std::vector<DNSRecord> result;
a9e029ee 465
6da513b2
RG
466 for (const auto& custom : d_custom) {
467 if (qtype != QType::ANY && qtype != custom->getType() && custom->getType() != QType::CNAME) {
468 continue;
469 }
470
471 DNSRecord dr;
472 dr.d_name = qname;
473 dr.d_type = custom->getType();
474 dr.d_ttl = d_ttl;
475 dr.d_class = QClass::IN;
476 dr.d_place = DNSResourceRecord::ANSWER;
477 dr.d_content = custom;
478
479 if (dr.d_type == QType::CNAME) {
480 const auto content = std::dynamic_pointer_cast<CNAMERecordContent>(custom);
481 if (content) {
482 DNSName target = content->getTarget();
483 if (target.isWildcard()) {
484 target.chopOff();
485 dr.d_content = std::make_shared<CNAMERecordContent>(qname + target);
486 }
a9e029ee
RG
487 }
488 }
6da513b2
RG
489
490 result.emplace_back(getRecordFromCustom(qname, custom));
a9e029ee
RG
491 }
492
493 return result;
494}
6791663c 495
6da513b2 496std::string DNSFilterEngine::getKindToString(DNSFilterEngine::PolicyKind kind)
6791663c
RG
497{
498 static const DNSName drop("rpz-drop."), truncate("rpz-tcp-only."), noaction("rpz-passthru.");
499 static const DNSName rpzClientIP("rpz-client-ip"), rpzIP("rpz-ip"),
500 rpzNSDname("rpz-nsdname"), rpzNSIP("rpz-nsip.");
501 static const std::string rpzPrefix("rpz-");
502
6da513b2 503 switch(kind) {
6791663c
RG
504 case DNSFilterEngine::PolicyKind::NoAction:
505 return noaction.toString();
506 case DNSFilterEngine::PolicyKind::Drop:
507 return drop.toString();
508 case DNSFilterEngine::PolicyKind::NXDOMAIN:
509 return g_rootdnsname.toString();
510 case PolicyKind::NODATA:
511 return g_wildcarddnsname.toString();
512 case DNSFilterEngine::PolicyKind::Truncate:
513 return truncate.toString();
514 default:
515 throw std::runtime_error("Unexpected DNSFilterEngine::Policy kind");
516 }
517}
518
6da513b2 519std::string DNSFilterEngine::getTypeToString(DNSFilterEngine::PolicyType type)
6791663c 520{
6da513b2
RG
521 switch(type) {
522 case DNSFilterEngine::PolicyType::None:
523 return "none";
524 case DNSFilterEngine::PolicyType::QName:
525 return "QName";
526 case DNSFilterEngine::PolicyType::ClientIP:
527 return "Client IP";
528 case DNSFilterEngine::PolicyType::ResponseIP:
529 return "Response IP";
530 case DNSFilterEngine::PolicyType::NSDName:
531 return "Name Server Name";
532 case DNSFilterEngine::PolicyType::NSIP:
533 return "Name Server IP";
534 default:
535 throw std::runtime_error("Unexpected DNSFilterEngine::Policy type");
536 }
537}
538
539std::vector<DNSRecord> DNSFilterEngine::Policy::getRecords(const DNSName& qname) const
540{
541 std::vector<DNSRecord> result;
6791663c
RG
542
543 if (d_kind == PolicyKind::Custom) {
6da513b2 544 result = getCustomRecords(qname, QType::ANY);
6791663c
RG
545 }
546 else {
6da513b2 547 DNSRecord dr;
6791663c
RG
548 dr.d_name = qname;
549 dr.d_ttl = static_cast<uint32_t>(d_ttl);
550 dr.d_type = QType::CNAME;
551 dr.d_class = QClass::IN;
6da513b2
RG
552 dr.d_content = DNSRecordContent::mastermake(QType::CNAME, QClass::IN, getKindToString(d_kind));
553 result.push_back(std::move(dr));
6791663c
RG
554 }
555
6da513b2 556 return result;
6791663c
RG
557}
558
272e9a00 559void DNSFilterEngine::Zone::dumpNamedPolicy(FILE* fp, const DNSName& name, const Policy& pol)
6791663c 560{
6da513b2
RG
561 auto records = pol.getRecords(name);
562 for (const auto& dr : records) {
563 fprintf(fp, "%s %" PRIu32 " IN %s %s\n", dr.d_name.toString().c_str(), dr.d_ttl, QType(dr.d_type).getName().c_str(), dr.d_content->getZoneRepresentation().c_str());
564 }
6791663c
RG
565}
566
567DNSName DNSFilterEngine::Zone::maskToRPZ(const Netmask& nm)
568{
569 int bits = nm.getBits();
570 DNSName res(std::to_string(bits));
cffabb3b 571 const auto& addr = nm.getNetwork();
6791663c
RG
572
573 if (addr.isIPv4()) {
574 const uint8_t* bytes = reinterpret_cast<const uint8_t*>(&addr.sin4.sin_addr.s_addr);
575 res += DNSName(std::to_string(bytes[3]) + "." + std::to_string(bytes[2]) + "." + std::to_string(bytes[1]) + "." + std::to_string(bytes[0]));
576 }
577 else {
578 DNSName temp;
579 const auto str = addr.toString();
580 const auto len = str.size();
581 std::string::size_type begin = 0;
582
583 while (begin < len) {
584 std::string::size_type end = str.find(":", begin);
585 std::string sub;
586 if (end != string::npos) {
587 sub = str.substr(begin, end - begin);
588 }
589 else {
590 sub = str.substr(begin);
591 }
592
593 if (sub.empty()) {
594 temp = DNSName("zz") + temp;
595 }
596 else {
597 temp = DNSName(sub) + temp;
598 }
599
600 if (end == string::npos) {
601 break;
602 }
603 begin = end + 1;
604 }
605 res += temp;
606 }
607
608 return res;
609}
610
611
272e9a00 612void DNSFilterEngine::Zone::dumpAddrPolicy(FILE* fp, const Netmask& nm, const DNSName& name, const Policy& pol)
6791663c
RG
613{
614 DNSName full = maskToRPZ(nm);
615 full += name;
616
6da513b2
RG
617 auto records = pol.getRecords(full);
618 for (const auto& dr : records) {
619 fprintf(fp, "%s %" PRIu32 " IN %s %s\n", dr.d_name.toString().c_str(), dr.d_ttl, QType(dr.d_type).getName().c_str(), dr.d_content->getZoneRepresentation().c_str());
620 }
6791663c
RG
621}
622
623void DNSFilterEngine::Zone::dump(FILE* fp) const
624{
625 /* fake the SOA record */
626 auto soa = DNSRecordContent::mastermake(QType::SOA, QClass::IN, "fake.RPZ. hostmaster.fake.RPZ. " + std::to_string(d_serial) + " " + std::to_string(d_refresh) + " 600 3600000 604800");
627 fprintf(fp, "%s IN SOA %s\n", d_domain.toString().c_str(), soa->getZoneRepresentation().c_str());
628
629 for (const auto& pair : d_qpolName) {
630 dumpNamedPolicy(fp, pair.first + d_domain, pair.second);
631 }
632
633 for (const auto& pair : d_propolName) {
634 dumpNamedPolicy(fp, pair.first + DNSName("rpz-nsdname.") + d_domain, pair.second);
635 }
636
637 for (const auto pair : d_qpolAddr) {
7c888097 638 dumpAddrPolicy(fp, pair.first, DNSName("rpz-client-ip.") + d_domain, pair.second);
6791663c
RG
639 }
640
641 for (const auto pair : d_propolNSAddr) {
7c888097 642 dumpAddrPolicy(fp, pair.first, DNSName("rpz-nsip.") + d_domain, pair.second);
6791663c
RG
643 }
644
645 for (const auto pair : d_postpolAddr) {
7c888097 646 dumpAddrPolicy(fp, pair.first, DNSName("rpz-ip.") + d_domain, pair.second);
6791663c
RG
647 }
648}