]> git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/filterpo.cc
Standardize license text in all PDNS files
[thirdparty/pdns.git] / pdns / filterpo.cc
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 */
22 #include "filterpo.hh"
23 #include <iostream>
24 #include "namespaces.hh"
25 #include "dnsrecords.hh"
26
27 DNSFilterEngine::DNSFilterEngine()
28 {
29 }
30
31 bool findNamedPolicy(const map<DNSName, DNSFilterEngine::Policy>& polmap, const DNSName& qname, DNSFilterEngine::Policy& pol)
32 {
33 DNSName s(qname);
34
35 /* for www.powerdns.com, we need to check:
36 www.powerdns.com.
37 *.powerdns.com.
38 powerdns.com.
39 *.com.
40 com.
41 *.
42 . */
43
44 bool first=true;
45 do {
46 auto iter = polmap.find(s);
47 if(iter != polmap.end()) {
48 pol=iter->second;
49 return true;
50 }
51 if(!first) {
52 iter = polmap.find(DNSName("*")+s);
53 if(iter != polmap.end()) {
54 pol=iter->second;
55 return true;
56 }
57 }
58 first=false;
59 } while(s.chopOff());
60 return false;
61 }
62
63 DNSFilterEngine::Policy DNSFilterEngine::getProcessingPolicy(const DNSName& qname) const
64 {
65 // cout<<"Got question for nameserver name "<<qname<<endl;
66 Policy pol{PolicyKind::NoAction, nullptr, "", 0};
67 for(const auto& z : d_zones) {
68 if(findNamedPolicy(z.propolName, qname, pol)) {
69 // cerr<<"Had a hit on the nameserver ("<<qname<<") used to process the query"<<endl;
70 return pol;
71 }
72 }
73 return pol;
74 }
75
76
77 DNSFilterEngine::Policy DNSFilterEngine::getQueryPolicy(const DNSName& qname, const ComboAddress& ca) const
78 {
79 // cout<<"Got question for "<<qname<<" from "<<ca.toString()<<endl;
80
81 Policy pol{PolicyKind::NoAction, nullptr, "", 0};
82 for(const auto& z : d_zones) {
83 if(findNamedPolicy(z.qpolName, qname, pol)) {
84 // cerr<<"Had a hit on the name of the query"<<endl;
85 return pol;
86 }
87
88 if(auto fnd=z.qpolAddr.lookup(ca)) {
89 // cerr<<"Had a hit on the IP address ("<<ca.toString()<<") of the client"<<endl;
90 return fnd->second;
91 }
92 }
93
94 return pol;
95 }
96
97 DNSFilterEngine::Policy DNSFilterEngine::getPostPolicy(const vector<DNSRecord>& records) const
98 {
99 ComboAddress ca;
100
101 for(const auto& r : records) {
102 if(r.d_place != DNSResourceRecord::ANSWER)
103 continue;
104 if(r.d_type == QType::A) {
105 if (auto rec = getRR<ARecordContent>(r)) {
106 ca = rec->getCA();
107 }
108 }
109 else if(r.d_type == QType::AAAA) {
110 if (auto rec = getRR<AAAARecordContent>(r)) {
111 ca = rec->getCA();
112 }
113 }
114 else
115 continue;
116
117 for(const auto& z : d_zones) {
118 if(auto fnd=z.postpolAddr.lookup(ca))
119 return fnd->second;
120 }
121 }
122 return Policy{PolicyKind::NoAction, nullptr, "", 0};
123 }
124
125 void DNSFilterEngine::assureZones(int zone)
126 {
127 if((int)d_zones.size() <= zone)
128 d_zones.resize(zone+1);
129 }
130
131 void DNSFilterEngine::clear(int zone)
132 {
133 assureZones(zone);
134 auto& z = d_zones[zone];
135 z.qpolAddr.clear();
136 z.postpolAddr.clear();
137 z.propolName.clear();
138 z.qpolName.clear();
139 }
140
141 void DNSFilterEngine::addClientTrigger(const Netmask& nm, Policy pol, int zone)
142 {
143 assureZones(zone);
144 d_zones[zone].qpolAddr.insert(nm).second=pol;
145 }
146
147 void DNSFilterEngine::addResponseTrigger(const Netmask& nm, Policy pol, int zone)
148 {
149 assureZones(zone);
150 d_zones[zone].postpolAddr.insert(nm).second=pol;
151 }
152
153 void DNSFilterEngine::addQNameTrigger(const DNSName& n, Policy pol, int zone)
154 {
155 assureZones(zone);
156 d_zones[zone].qpolName[n]=pol;
157 }
158
159 void DNSFilterEngine::addNSTrigger(const DNSName& n, Policy pol, int zone)
160 {
161 assureZones(zone);
162 d_zones[zone].propolName[n]=pol;
163 }
164
165 bool DNSFilterEngine::rmClientTrigger(const Netmask& nm, Policy pol, int zone)
166 {
167 assureZones(zone);
168
169 auto& qpols = d_zones[zone].qpolAddr;
170 qpols.erase(nm);
171 return true;
172 }
173
174 bool DNSFilterEngine::rmResponseTrigger(const Netmask& nm, Policy pol, int zone)
175 {
176 assureZones(zone);
177 auto& postpols = d_zones[zone].postpolAddr;
178 postpols.erase(nm);
179 return true;
180 }
181
182 bool DNSFilterEngine::rmQNameTrigger(const DNSName& n, Policy pol, int zone)
183 {
184 assureZones(zone);
185 d_zones[zone].qpolName.erase(n); // XXX verify we had identical policy?
186 return true;
187 }
188
189 bool DNSFilterEngine::rmNSTrigger(const DNSName& n, Policy pol, int zone)
190 {
191 assureZones(zone);
192 d_zones[zone].propolName.erase(n); // XXX verify policy matched? =pol;
193 return true;
194 }