]> git.ipfire.org Git - thirdparty/pdns.git/blame - pdns/filterpo.cc
Merge pull request #9070 from rgacogne/boost-173
[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
2996400c 118bool DNSFilterEngine::getProcessingPolicy(const DNSName& qname, const std::unordered_map<std::string,bool>& discardedPolicies, Policy& pol) 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) {
125 bool enabled = true;
b502d522
RG
126 const auto& zoneName = z->getName();
127 if (z->getPriority() >= pol.getPriority()) {
79f64c2b
OM
128 enabled = false;
129 }
b502d522 130 else if (discardedPolicies.find(zoneName) != discardedPolicies.end()) {
272e9a00
RG
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
06cfa23f 146 if (allEmpty) {
2996400c 147 return false;
06cfa23f
RG
148 }
149
150 /* prepare the wildcard-based names */
151 std::vector<DNSName> wcNames;
152 wcNames.reserve(qname.countLabels());
153 DNSName s(qname);
154 while (s.chopOff()){
155 wcNames.emplace_back(g_wildcarddnsname+s);
156 }
157
158 count = 0;
159 for(const auto& z : d_zones) {
160 if (!zoneEnabled[count]) {
272e9a00 161 ++count;
06cfa23f
RG
162 continue;
163 }
06cfa23f
RG
164 if (z->findExactNSPolicy(qname, pol)) {
165 // cerr<<"Had a hit on the nameserver ("<<qname<<") used to process the query"<<endl;
2996400c 166 return true;
272e9a00
RG
167 }
168
06cfa23f
RG
169 for (const auto& wc : wcNames) {
170 if (z->findExactNSPolicy(wc, pol)) {
171 // cerr<<"Had a hit on the nameserver ("<<qname<<") used to process the query"<<endl;
2996400c 172 return true;
272e9a00 173 }
644dd1da 174 }
06cfa23f 175 ++count;
644dd1da 176 }
272e9a00 177
2996400c 178 return false;
b8470add 179}
644dd1da 180
2996400c 181bool DNSFilterEngine::getProcessingPolicy(const ComboAddress& address, const std::unordered_map<std::string,bool>& discardedPolicies, Policy& pol) const
b8470add
PL
182{
183 // cout<<"Got question for nameserver IP "<<address.toString()<<endl;
184 for(const auto& z : d_zones) {
b502d522 185 if (z->getPriority() >= pol.getPriority()) {
e37e5795
OM
186 break;
187 }
b502d522
RG
188 const auto& zoneName = z->getName();
189 if (discardedPolicies.find(zoneName) != discardedPolicies.end()) {
0a273054
RG
190 continue;
191 }
192
6791663c 193 if(z->findNSIPPolicy(address, pol)) {
b8470add 194 // cerr<<"Had a hit on the nameserver ("<<address.toString()<<") used to process the query"<<endl;
2996400c 195 return true;
b8470add
PL
196 }
197 }
2996400c 198 return false;
b8470add 199}
644dd1da 200
2996400c 201bool DNSFilterEngine::getQueryPolicy(const DNSName& qname, const ComboAddress& ca, const std::unordered_map<std::string,bool>& discardedPolicies, Policy& pol) const
644dd1da 202{
06cfa23f 203 // cout<<"Got question for "<<qname<<" from "<<ca.toString()<<endl;
272e9a00
RG
204 std::vector<bool> zoneEnabled(d_zones.size());
205 size_t count = 0;
206 bool allEmpty = true;
207 for (const auto& z : d_zones) {
208 bool enabled = true;
b502d522 209 if (z->getPriority() >= pol.getPriority()) {
272e9a00 210 enabled = false;
79f64c2b 211 } else {
b502d522
RG
212 const auto& zoneName = z->getName();
213 if (discardedPolicies.find(zoneName) != discardedPolicies.end()) {
79f64c2b 214 enabled = false;
272e9a00
RG
215 }
216 else {
79f64c2b
OM
217 if (z->hasQNamePolicies() || z->hasClientPolicies()) {
218 allEmpty = false;
219 }
220 else {
221 enabled = false;
222 }
272e9a00 223 }
0a273054
RG
224 }
225
272e9a00
RG
226 zoneEnabled[count] = enabled;
227 ++count;
228 }
229
06cfa23f 230 if (allEmpty) {
2996400c 231 return false;
06cfa23f
RG
232 }
233
234 /* prepare the wildcard-based names */
235 std::vector<DNSName> wcNames;
236 wcNames.reserve(qname.countLabels());
237 DNSName s(qname);
238 while (s.chopOff()){
239 wcNames.emplace_back(g_wildcarddnsname+s);
240 }
241
242 count = 0;
243 for (const auto& z : d_zones) {
244 if (!zoneEnabled[count]) {
272e9a00 245 ++count;
06cfa23f 246 continue;
644dd1da 247 }
a7e329b8 248
a4fc3b37
OM
249 if (z->findClientPolicy(ca, pol)) {
250 // cerr<<"Had a hit on the IP address ("<<ca.toString()<<") of the client"<<endl;
2996400c 251 return true;
a4fc3b37
OM
252 }
253
06cfa23f
RG
254 if (z->findExactQNamePolicy(qname, pol)) {
255 // cerr<<"Had a hit on the name of the query"<<endl;
2996400c 256 return true;
06cfa23f
RG
257 }
258
259 for (const auto& wc : wcNames) {
260 if (z->findExactQNamePolicy(wc, pol)) {
261 // cerr<<"Had a hit on the name of the query"<<endl;
2996400c 262 return true;
272e9a00
RG
263 }
264 }
272e9a00 265
ae001b0e 266 ++count;
644dd1da 267 }
268
2996400c 269 return false;
644dd1da 270}
271
2996400c 272bool DNSFilterEngine::getPostPolicy(const vector<DNSRecord>& records, const std::unordered_map<std::string,bool>& discardedPolicies, Policy& pol) const
644dd1da 273{
274 ComboAddress ca;
06cfa23f
RG
275 for (const auto& r : records) {
276 if (r.d_place != DNSResourceRecord::ANSWER)
644dd1da 277 continue;
06cfa23f 278 if (r.d_type == QType::A) {
ba3c54cb
RG
279 if (auto rec = getRR<ARecordContent>(r)) {
280 ca = rec->getCA();
281 }
282 }
283 else if(r.d_type == QType::AAAA) {
284 if (auto rec = getRR<AAAARecordContent>(r)) {
285 ca = rec->getCA();
286 }
287 }
644dd1da 288 else
289 continue;
290
06cfa23f 291 for (const auto& z : d_zones) {
b502d522 292 if (z->getPriority() >= pol.getPriority()) {
e37e5795
OM
293 break;
294 }
b502d522
RG
295 const auto& zoneName = z->getName();
296 if (discardedPolicies.find(zoneName) != discardedPolicies.end()) {
0a273054
RG
297 continue;
298 }
299
06cfa23f 300 if (z->findResponsePolicy(ca, pol)) {
2996400c 301 return true;
6791663c 302 }
644dd1da 303 }
304 }
2996400c 305 return false;
644dd1da 306}
307
0a273054 308void DNSFilterEngine::assureZones(size_t zone)
644dd1da 309{
0a273054 310 if(d_zones.size() <= zone)
644dd1da 311 d_zones.resize(zone+1);
644dd1da 312}
313
6da513b2 314void DNSFilterEngine::Zone::addClientTrigger(const Netmask& nm, Policy&& pol)
7eafc52f 315{
b502d522 316 pol.d_zoneData = d_zoneData;
f3da83fe 317 pol.d_type = PolicyType::ClientIP;
6da513b2 318 d_qpolAddr.insert(nm).second=std::move(pol);
7eafc52f 319}
320
6da513b2 321void DNSFilterEngine::Zone::addResponseTrigger(const Netmask& nm, Policy&& pol)
0a7ef1b8 322{
b502d522 323 pol.d_zoneData = d_zoneData;
f3da83fe 324 pol.d_type = PolicyType::ResponseIP;
6da513b2 325 d_postpolAddr.insert(nm).second=std::move(pol);
644dd1da 326}
327
d122dac0 328void DNSFilterEngine::Zone::addQNameTrigger(const DNSName& n, Policy&& pol, bool ignoreDuplicate)
644dd1da 329{
6da513b2
RG
330 auto it = d_qpolName.find(n);
331
332 if (it != d_qpolName.end()) {
333 auto& existingPol = it->second;
334
d122dac0 335 if (pol.d_kind != PolicyKind::Custom && !ignoreDuplicate) {
fc38ec55 336 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
337 }
338
d122dac0 339 if (existingPol.d_kind != PolicyKind::Custom && ignoreDuplicate) {
fc38ec55 340 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
341 }
342
343 existingPol.d_custom.reserve(existingPol.d_custom.size() + pol.d_custom.size());
344
fc38ec55 345 std::move(pol.d_custom.begin(), pol.d_custom.end(), std::back_inserter(existingPol.d_custom));
6da513b2
RG
346 }
347 else {
348 auto& qpol = d_qpolName.insert({n, std::move(pol)}).first->second;
b502d522 349 qpol.d_zoneData = d_zoneData;
6da513b2
RG
350 qpol.d_type = PolicyType::QName;
351 }
644dd1da 352}
353
6da513b2 354void DNSFilterEngine::Zone::addNSTrigger(const DNSName& n, Policy&& pol)
644dd1da 355{
b502d522 356 pol.d_zoneData = d_zoneData;
f3da83fe 357 pol.d_type = PolicyType::NSDName;
6da513b2 358 d_propolName.insert({n, std::move(pol)});
644dd1da 359}
360
6da513b2 361void DNSFilterEngine::Zone::addNSIPTrigger(const Netmask& nm, Policy&& pol)
644dd1da 362{
b502d522 363 pol.d_zoneData = d_zoneData;
f3da83fe 364 pol.d_type = PolicyType::NSIP;
6da513b2 365 d_propolNSAddr.insert(nm).second = std::move(pol);
644dd1da 366}
39ec5d29 367
6da513b2 368bool DNSFilterEngine::Zone::rmClientTrigger(const Netmask& nm, const Policy& pol)
b8470add 369{
6b972d59 370 d_qpolAddr.erase(nm);
39ec5d29 371 return true;
372}
373
6da513b2 374bool DNSFilterEngine::Zone::rmResponseTrigger(const Netmask& nm, const Policy& pol)
39ec5d29 375{
6b972d59 376 d_postpolAddr.erase(nm);
39ec5d29 377 return true;
378}
379
6da513b2 380bool DNSFilterEngine::Zone::rmQNameTrigger(const DNSName& n, const Policy& pol)
39ec5d29 381{
690b86b7
OM
382 auto found = d_qpolName.find(n);
383 if (found == d_qpolName.end()) {
6da513b2
RG
384 return false;
385 }
386
690b86b7 387 auto& existing = found->second;
6da513b2 388 if (existing.d_kind != DNSFilterEngine::PolicyKind::Custom) {
690b86b7 389 d_qpolName.erase(found);
6da513b2
RG
390 return true;
391 }
392
393 /* for custom types, we might have more than one type,
394 and then we need to remove only the right ones. */
395 if (existing.d_custom.size() <= 1) {
690b86b7 396 d_qpolName.erase(found);
6da513b2
RG
397 return true;
398 }
399
400 bool result = false;
3b027d9e 401 for (auto& toRemove : pol.d_custom) {
6da513b2 402 for (auto it = existing.d_custom.begin(); it != existing.d_custom.end(); ++it) {
3b027d9e 403 if (**it == *toRemove) {
6da513b2
RG
404 existing.d_custom.erase(it);
405 result = true;
406 break;
407 }
408 }
409 }
410
411 return result;
39ec5d29 412}
413
6da513b2 414bool DNSFilterEngine::Zone::rmNSTrigger(const DNSName& n, const Policy& pol)
39ec5d29 415{
6b972d59 416 d_propolName.erase(n); // XXX verify policy matched? =pol;
39ec5d29 417 return true;
418}
b8470add 419
6da513b2 420bool DNSFilterEngine::Zone::rmNSIPTrigger(const Netmask& nm, const Policy& pol)
b8470add 421{
6b972d59 422 d_propolNSAddr.erase(nm);
b8470add
PL
423 return true;
424}
a9e029ee 425
6da513b2
RG
426DNSRecord DNSFilterEngine::Policy::getRecordFromCustom(const DNSName& qname, const std::shared_ptr<DNSRecordContent>& custom) const
427{
428 DNSRecord dr;
429 dr.d_name = qname;
430 dr.d_type = custom->getType();
431 dr.d_ttl = d_ttl;
432 dr.d_class = QClass::IN;
433 dr.d_place = DNSResourceRecord::ANSWER;
434 dr.d_content = custom;
435
436 if (dr.d_type == QType::CNAME) {
437 const auto content = std::dynamic_pointer_cast<CNAMERecordContent>(custom);
438 if (content) {
439 DNSName target = content->getTarget();
440 if (target.isWildcard()) {
441 target.chopOff();
442 dr.d_content = std::make_shared<CNAMERecordContent>(qname + target);
443 }
444 }
445 }
446
447 return dr;
448}
449
450std::vector<DNSRecord> DNSFilterEngine::Policy::getCustomRecords(const DNSName& qname, uint16_t qtype) const
a9e029ee
RG
451{
452 if (d_kind != PolicyKind::Custom) {
453 throw std::runtime_error("Asking for a custom record from a filtering policy of a non-custom type");
454 }
455
6da513b2 456 std::vector<DNSRecord> result;
a9e029ee 457
6da513b2
RG
458 for (const auto& custom : d_custom) {
459 if (qtype != QType::ANY && qtype != custom->getType() && custom->getType() != QType::CNAME) {
460 continue;
461 }
462
463 DNSRecord dr;
464 dr.d_name = qname;
465 dr.d_type = custom->getType();
466 dr.d_ttl = d_ttl;
467 dr.d_class = QClass::IN;
468 dr.d_place = DNSResourceRecord::ANSWER;
469 dr.d_content = custom;
470
471 if (dr.d_type == QType::CNAME) {
472 const auto content = std::dynamic_pointer_cast<CNAMERecordContent>(custom);
473 if (content) {
474 DNSName target = content->getTarget();
475 if (target.isWildcard()) {
476 target.chopOff();
477 dr.d_content = std::make_shared<CNAMERecordContent>(qname + target);
478 }
a9e029ee
RG
479 }
480 }
6da513b2
RG
481
482 result.emplace_back(getRecordFromCustom(qname, custom));
a9e029ee
RG
483 }
484
485 return result;
486}
6791663c 487
6da513b2 488std::string DNSFilterEngine::getKindToString(DNSFilterEngine::PolicyKind kind)
6791663c
RG
489{
490 static const DNSName drop("rpz-drop."), truncate("rpz-tcp-only."), noaction("rpz-passthru.");
491 static const DNSName rpzClientIP("rpz-client-ip"), rpzIP("rpz-ip"),
492 rpzNSDname("rpz-nsdname"), rpzNSIP("rpz-nsip.");
493 static const std::string rpzPrefix("rpz-");
494
6da513b2 495 switch(kind) {
6791663c
RG
496 case DNSFilterEngine::PolicyKind::NoAction:
497 return noaction.toString();
498 case DNSFilterEngine::PolicyKind::Drop:
499 return drop.toString();
500 case DNSFilterEngine::PolicyKind::NXDOMAIN:
501 return g_rootdnsname.toString();
502 case PolicyKind::NODATA:
503 return g_wildcarddnsname.toString();
504 case DNSFilterEngine::PolicyKind::Truncate:
505 return truncate.toString();
506 default:
507 throw std::runtime_error("Unexpected DNSFilterEngine::Policy kind");
508 }
509}
510
6da513b2 511std::string DNSFilterEngine::getTypeToString(DNSFilterEngine::PolicyType type)
6791663c 512{
6da513b2
RG
513 switch(type) {
514 case DNSFilterEngine::PolicyType::None:
515 return "none";
516 case DNSFilterEngine::PolicyType::QName:
517 return "QName";
518 case DNSFilterEngine::PolicyType::ClientIP:
519 return "Client IP";
520 case DNSFilterEngine::PolicyType::ResponseIP:
521 return "Response IP";
522 case DNSFilterEngine::PolicyType::NSDName:
523 return "Name Server Name";
524 case DNSFilterEngine::PolicyType::NSIP:
525 return "Name Server IP";
526 default:
527 throw std::runtime_error("Unexpected DNSFilterEngine::Policy type");
528 }
529}
530
531std::vector<DNSRecord> DNSFilterEngine::Policy::getRecords(const DNSName& qname) const
532{
533 std::vector<DNSRecord> result;
6791663c
RG
534
535 if (d_kind == PolicyKind::Custom) {
6da513b2 536 result = getCustomRecords(qname, QType::ANY);
6791663c
RG
537 }
538 else {
6da513b2 539 DNSRecord dr;
6791663c
RG
540 dr.d_name = qname;
541 dr.d_ttl = static_cast<uint32_t>(d_ttl);
542 dr.d_type = QType::CNAME;
543 dr.d_class = QClass::IN;
6da513b2
RG
544 dr.d_content = DNSRecordContent::mastermake(QType::CNAME, QClass::IN, getKindToString(d_kind));
545 result.push_back(std::move(dr));
6791663c
RG
546 }
547
6da513b2 548 return result;
6791663c
RG
549}
550
272e9a00 551void DNSFilterEngine::Zone::dumpNamedPolicy(FILE* fp, const DNSName& name, const Policy& pol)
6791663c 552{
6da513b2
RG
553 auto records = pol.getRecords(name);
554 for (const auto& dr : records) {
555 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());
556 }
6791663c
RG
557}
558
559DNSName DNSFilterEngine::Zone::maskToRPZ(const Netmask& nm)
560{
561 int bits = nm.getBits();
562 DNSName res(std::to_string(bits));
cffabb3b 563 const auto& addr = nm.getNetwork();
6791663c
RG
564
565 if (addr.isIPv4()) {
566 const uint8_t* bytes = reinterpret_cast<const uint8_t*>(&addr.sin4.sin_addr.s_addr);
567 res += DNSName(std::to_string(bytes[3]) + "." + std::to_string(bytes[2]) + "." + std::to_string(bytes[1]) + "." + std::to_string(bytes[0]));
568 }
569 else {
570 DNSName temp;
571 const auto str = addr.toString();
572 const auto len = str.size();
573 std::string::size_type begin = 0;
574
575 while (begin < len) {
576 std::string::size_type end = str.find(":", begin);
577 std::string sub;
578 if (end != string::npos) {
579 sub = str.substr(begin, end - begin);
580 }
581 else {
582 sub = str.substr(begin);
583 }
584
585 if (sub.empty()) {
586 temp = DNSName("zz") + temp;
587 }
588 else {
589 temp = DNSName(sub) + temp;
590 }
591
592 if (end == string::npos) {
593 break;
594 }
595 begin = end + 1;
596 }
597 res += temp;
598 }
599
600 return res;
601}
602
603
272e9a00 604void DNSFilterEngine::Zone::dumpAddrPolicy(FILE* fp, const Netmask& nm, const DNSName& name, const Policy& pol)
6791663c
RG
605{
606 DNSName full = maskToRPZ(nm);
607 full += name;
608
6da513b2
RG
609 auto records = pol.getRecords(full);
610 for (const auto& dr : records) {
611 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());
612 }
6791663c
RG
613}
614
615void DNSFilterEngine::Zone::dump(FILE* fp) const
616{
617 /* fake the SOA record */
618 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");
619 fprintf(fp, "%s IN SOA %s\n", d_domain.toString().c_str(), soa->getZoneRepresentation().c_str());
620
621 for (const auto& pair : d_qpolName) {
622 dumpNamedPolicy(fp, pair.first + d_domain, pair.second);
623 }
624
625 for (const auto& pair : d_propolName) {
626 dumpNamedPolicy(fp, pair.first + DNSName("rpz-nsdname.") + d_domain, pair.second);
627 }
628
f0c604d5 629 for (const auto& pair : d_qpolAddr) {
7c888097 630 dumpAddrPolicy(fp, pair.first, DNSName("rpz-client-ip.") + d_domain, pair.second);
6791663c
RG
631 }
632
f0c604d5 633 for (const auto& pair : d_propolNSAddr) {
7c888097 634 dumpAddrPolicy(fp, pair.first, DNSName("rpz-nsip.") + d_domain, pair.second);
6791663c
RG
635 }
636
f0c604d5 637 for (const auto& pair : d_postpolAddr) {
7c888097 638 dumpAddrPolicy(fp, pair.first, DNSName("rpz-ip.") + d_domain, pair.second);
6791663c
RG
639 }
640}
b502d522
RG
641
642void mergePolicyTags(std::unordered_set<std::string>& tags, const std::unordered_set<std::string>& newTags)
643{
644 for (const auto& tag : newTags) {
645 tags.insert(tag);
646 }
647}