]> git.ipfire.org Git - thirdparty/pdns.git/blame - pdns/filterpo.cc
Merge pull request #5461 from rgacogne/rec-cache-index
[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 */
644dd1da 22#include "filterpo.hh"
23#include <iostream>
24#include "namespaces.hh"
25#include "dnsrecords.hh"
26
27DNSFilterEngine::DNSFilterEngine()
28{
29}
30
a2d0450e 31static bool findNamedPolicy(const std::unordered_map<DNSName, DNSFilterEngine::Policy>& polmap, const DNSName& qname, DNSFilterEngine::Policy& pol)
644dd1da 32{
5678437b
PL
33 /* for www.powerdns.com, we need to check:
34 www.powerdns.com.
35 *.powerdns.com.
36 *.com.
37 *.
38 */
0a273054 39
a2d0450e
RG
40 std::unordered_map<DNSName, DNSFilterEngine::Policy>::const_iterator iter;
41 iter = polmap.find(qname);
bef458b2
PL
42
43 if(iter != polmap.end()) {
44 pol=iter->second;
45 return true;
46 }
5678437b 47
a2d0450e 48 DNSName s(qname);
bef458b2 49 while(s.chopOff()){
12c06211 50 iter = polmap.find(g_wildcarddnsname+s);
5678437b
PL
51 if(iter != polmap.end()) {
52 pol=iter->second;
53 return true;
54 }
bef458b2 55 }
644dd1da 56 return false;
57}
58
0a273054 59DNSFilterEngine::Policy DNSFilterEngine::getProcessingPolicy(const DNSName& qname, const std::unordered_map<std::string,bool>& discardedPolicies) const
644dd1da 60{
39ec5d29 61 // cout<<"Got question for nameserver name "<<qname<<endl;
1f1ca368 62 Policy pol;
644dd1da 63 for(const auto& z : d_zones) {
6b972d59
RG
64 const auto zoneName = z->getName();
65 if(zoneName && discardedPolicies.find(*zoneName) != discardedPolicies.end()) {
0a273054
RG
66 continue;
67 }
68
6b972d59 69 if(findNamedPolicy(z->d_propolName, qname, pol)) {
de0f72ba 70 // cerr<<"Had a hit on the nameserver ("<<qname<<") used to process the query"<<endl;
644dd1da 71 return pol;
72 }
73 }
74 return pol;
b8470add 75}
644dd1da 76
0a273054 77DNSFilterEngine::Policy DNSFilterEngine::getProcessingPolicy(const ComboAddress& address, const std::unordered_map<std::string,bool>& discardedPolicies) const
b8470add
PL
78{
79 // cout<<"Got question for nameserver IP "<<address.toString()<<endl;
80 for(const auto& z : d_zones) {
6b972d59
RG
81 const auto zoneName = z->getName();
82 if(zoneName && discardedPolicies.find(*zoneName) != discardedPolicies.end()) {
0a273054
RG
83 continue;
84 }
85
6b972d59 86 if(auto fnd=z->d_propolNSAddr.lookup(address)) {
b8470add
PL
87 // cerr<<"Had a hit on the nameserver ("<<address.toString()<<") used to process the query"<<endl;
88 return fnd->second;;
89 }
90 }
1f1ca368 91 return Policy();
b8470add 92}
644dd1da 93
0a273054 94DNSFilterEngine::Policy DNSFilterEngine::getQueryPolicy(const DNSName& qname, const ComboAddress& ca, const std::unordered_map<std::string,bool>& discardedPolicies) const
644dd1da 95{
de0f72ba 96 // cout<<"Got question for "<<qname<<" from "<<ca.toString()<<endl;
1f1ca368 97 Policy pol;
644dd1da 98 for(const auto& z : d_zones) {
6b972d59
RG
99 const auto zoneName = z->getName();
100 if(zoneName && discardedPolicies.find(*zoneName) != discardedPolicies.end()) {
0a273054
RG
101 continue;
102 }
103
6b972d59 104 if(findNamedPolicy(z->d_qpolName, qname, pol)) {
de0f72ba 105 // cerr<<"Had a hit on the name of the query"<<endl;
644dd1da 106 return pol;
107 }
108
6b972d59 109 if(auto fnd=z->d_qpolAddr.lookup(ca)) {
0e760497 110 // cerr<<"Had a hit on the IP address ("<<ca.toString()<<") of the client"<<endl;
111 return fnd->second;
644dd1da 112 }
113 }
114
39ec5d29 115 return pol;
644dd1da 116}
117
0a273054 118DNSFilterEngine::Policy DNSFilterEngine::getPostPolicy(const vector<DNSRecord>& records, const std::unordered_map<std::string,bool>& discardedPolicies) const
644dd1da 119{
120 ComboAddress ca;
644dd1da 121 for(const auto& r : records) {
589ad24b 122 if(r.d_place != DNSResourceRecord::ANSWER)
644dd1da 123 continue;
ba3c54cb
RG
124 if(r.d_type == QType::A) {
125 if (auto rec = getRR<ARecordContent>(r)) {
126 ca = rec->getCA();
127 }
128 }
129 else if(r.d_type == QType::AAAA) {
130 if (auto rec = getRR<AAAARecordContent>(r)) {
131 ca = rec->getCA();
132 }
133 }
644dd1da 134 else
135 continue;
136
137 for(const auto& z : d_zones) {
6b972d59
RG
138 const auto zoneName = z->getName();
139 if(zoneName && discardedPolicies.find(*zoneName) != discardedPolicies.end()) {
0a273054
RG
140 continue;
141 }
142
6b972d59 143 if(auto fnd=z->d_postpolAddr.lookup(ca))
0e760497 144 return fnd->second;
644dd1da 145 }
146 }
1f1ca368 147 return Policy();
644dd1da 148}
149
0a273054 150void DNSFilterEngine::assureZones(size_t zone)
644dd1da 151{
0a273054 152 if(d_zones.size() <= zone)
644dd1da 153 d_zones.resize(zone+1);
644dd1da 154}
155
6b972d59 156void DNSFilterEngine::Zone::addClientTrigger(const Netmask& nm, Policy pol)
7eafc52f 157{
6b972d59
RG
158 pol.d_name = d_name;
159 d_qpolAddr.insert(nm).second=pol;
7eafc52f 160}
161
6b972d59 162void DNSFilterEngine::Zone::addResponseTrigger(const Netmask& nm, Policy pol)
0a7ef1b8 163{
6b972d59
RG
164 pol.d_name = d_name;
165 d_postpolAddr.insert(nm).second=pol;
644dd1da 166}
167
6b972d59 168void DNSFilterEngine::Zone::addQNameTrigger(const DNSName& n, Policy pol)
644dd1da 169{
6b972d59
RG
170 pol.d_name = d_name;
171 d_qpolName[n]=pol;
644dd1da 172}
173
6b972d59 174void DNSFilterEngine::Zone::addNSTrigger(const DNSName& n, Policy pol)
644dd1da 175{
6b972d59
RG
176 pol.d_name = d_name;
177 d_propolName[n]=pol;
644dd1da 178}
179
6b972d59 180void DNSFilterEngine::Zone::addNSIPTrigger(const Netmask& nm, Policy pol)
644dd1da 181{
6b972d59
RG
182 pol.d_name = d_name;
183 d_propolNSAddr.insert(nm).second = pol;
644dd1da 184}
39ec5d29 185
6b972d59 186bool DNSFilterEngine::Zone::rmClientTrigger(const Netmask& nm, Policy pol)
b8470add 187{
6b972d59 188 d_qpolAddr.erase(nm);
39ec5d29 189 return true;
190}
191
6b972d59 192bool DNSFilterEngine::Zone::rmResponseTrigger(const Netmask& nm, Policy pol)
39ec5d29 193{
6b972d59 194 d_postpolAddr.erase(nm);
39ec5d29 195 return true;
196}
197
6b972d59 198bool DNSFilterEngine::Zone::rmQNameTrigger(const DNSName& n, Policy pol)
39ec5d29 199{
6b972d59 200 d_qpolName.erase(n); // XXX verify we had identical policy?
39ec5d29 201 return true;
202}
203
6b972d59 204bool DNSFilterEngine::Zone::rmNSTrigger(const DNSName& n, Policy pol)
39ec5d29 205{
6b972d59 206 d_propolName.erase(n); // XXX verify policy matched? =pol;
39ec5d29 207 return true;
208}
b8470add 209
6b972d59 210bool DNSFilterEngine::Zone::rmNSIPTrigger(const Netmask& nm, Policy pol)
b8470add 211{
6b972d59 212 d_propolNSAddr.erase(nm);
b8470add
PL
213 return true;
214}
a9e029ee
RG
215
216DNSRecord DNSFilterEngine::Policy::getCustomRecord(const DNSName& qname) const
217{
218 if (d_kind != PolicyKind::Custom) {
219 throw std::runtime_error("Asking for a custom record from a filtering policy of a non-custom type");
220 }
221
222 DNSRecord result;
223 result.d_name = qname;
224 result.d_type = d_custom->getType();
225 result.d_ttl = d_ttl;
226 result.d_class = QClass::IN;
227 result.d_place = DNSResourceRecord::ANSWER;
228 result.d_content = d_custom;
229
230 if (result.d_type == QType::CNAME) {
231 const auto content = std::dynamic_pointer_cast<CNAMERecordContent>(d_custom);
232 if (content) {
233 DNSName target = content->getTarget();
234 if (target.isWildcard()) {
235 target.chopOff();
236 result.d_content = std::make_shared<CNAMERecordContent>(qname + target);
237 }
238 }
239 }
240
241 return result;
242}