]> git.ipfire.org Git - thirdparty/pdns.git/blame - pdns/recursor_cache.hh
limit compression pointers to 14 bits
[thirdparty/pdns.git] / pdns / recursor_cache.hh
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 */
6320ad3a
BH
22#ifndef RECURSOR_CACHE_HH
23#define RECURSOR_CACHE_HH
6320ad3a
BH
24#include <string>
25#include <set>
26#include "dns.hh"
27#include "qtype.hh"
7738a23f 28#include "misc.hh"
c5c066bf 29#include "dnsname.hh"
c154c8a4 30#include <iostream>
57769f13 31#include "dnsrecords.hh"
8e843282 32#include <boost/utility.hpp>
ca0b5def
BH
33#include <boost/multi_index_container.hpp>
34#include <boost/multi_index/ordered_index.hpp>
e74f866a 35#include <boost/multi_index/hashed_index.hpp>
748eff9f 36#include <boost/tuple/tuple_comparison.hpp>
ca0b5def 37#include <boost/multi_index/key_extractors.hpp>
bec87d21 38#include <boost/multi_index/sequenced_index.hpp>
1676d61a 39#include <boost/version.hpp>
c4443ccb 40#include "iputils.hh"
4d2be65d 41#include "validate.hh"
705f31ae
BH
42#undef max
43
61b26744 44#include "namespaces.hh"
ca0b5def 45using namespace ::boost::multi_index;
6320ad3a 46
8e843282 47class MemRecursorCache : public boost::noncopyable // : public RecursorCache
6320ad3a
BH
48{
49public:
9348824d 50 MemRecursorCache() : d_cachecachevalid(false)
34264879 51 {
b0c3b7d8 52 cacheHits = cacheMisses = 0;
34264879 53 }
1ffea92c
RG
54 unsigned int size() const;
55 unsigned int bytes() const;
56 size_t ecsIndexSize() const;
57
428f41b7 58 int32_t get(time_t, const DNSName &qname, const QType& qt, bool requireAuth, vector<DNSRecord>* res, const ComboAddress& who, vector<std::shared_ptr<RRSIGRecordContent>>* signatures=nullptr, std::vector<std::shared_ptr<DNSRecord>>* authorityRecs=nullptr, bool* variable=nullptr, vState* state=nullptr, bool* wasAuth=nullptr);
2b984251
RG
59
60 void replace(time_t, const DNSName &qname, const QType& qt, const vector<DNSRecord>& content, const vector<shared_ptr<RRSIGRecordContent>>& signatures, const std::vector<std::shared_ptr<DNSRecord>>& authorityRecs, bool auth, boost::optional<Netmask> ednsmask=boost::none, vState state=Indeterminate);
b23b8614 61
c68ae9fa 62 void doPrune(unsigned int keep);
d7948528 63 uint64_t doDump(int fd);
a82ce718 64
86f3ca51 65 int doWipeCache(const DNSName& name, bool sub, uint16_t qtype=0xffff);
6b68a4e3 66 bool doAgeCache(time_t now, const DNSName& name, uint16_t qtype, uint32_t newTTL);
b9473937 67 bool updateValidationStatus(time_t now, const DNSName &qname, const QType& qt, const ComboAddress& who, bool requireAuth, vState newState, boost::optional<time_t> capTTD);
941db220 68
5e4a2466 69 uint64_t cacheHits, cacheMisses;
ea634573 70
6320ad3a 71private:
43a2b29c 72
ca0b5def
BH
73 struct CacheEntry
74 {
48f19abe
RG
75 CacheEntry(const boost::tuple<DNSName, uint16_t, Netmask>& key, bool auth):
76 d_qname(key.get<0>()), d_netmask(key.get<2>()), d_state(Indeterminate), d_ttd(0), d_qtype(key.get<1>()), d_auth(auth)
77 {
78 }
748eff9f 79
e325f20c 80 typedef vector<std::shared_ptr<DNSRecordContent>> records_t;
6b68a4e3 81 time_t getTTD() const
ca0b5def 82 {
e325f20c 83 return d_ttd;
ca0b5def 84 }
34264879 85
c4443ccb 86 records_t d_records;
8edd5bb4 87 std::vector<std::shared_ptr<RRSIGRecordContent>> d_signatures;
2b984251 88 std::vector<std::shared_ptr<DNSRecord>> d_authorityRecs;
e74f866a 89 DNSName d_qname;
6c674e9a 90 Netmask d_netmask;
787737ae 91 mutable vState d_state;
b9473937 92 mutable time_t d_ttd;
e74f866a
RG
93 uint16_t d_qtype;
94 bool d_auth;
95 };
96
b0274132
RG
97 /* The ECS Index (d_ecsIndex) keeps track of whether there is any ECS-specific
98 entry for a given (qname,qtype) entry in the cache (d_cache), and if so
99 provides a NetmaskTree of those ECS entries.
100 This allows figuring out quickly if we should look for an entry
101 specific to the requestor IP, and if so which entry is the most
102 specific one.
103 Keeping the entries in the regular cache is currently necessary
104 because of the way we manage expired entries (moving them to the
105 front of the expunge queue to be deleted at a regular interval).
106 */
107 class ECSIndexEntry
e74f866a
RG
108 {
109 public:
84a5e382 110 ECSIndexEntry(const DNSName& qname, uint16_t qtype): d_nmt(true), d_qname(qname), d_qtype(qtype)
e74f866a
RG
111 {
112 }
113
114 Netmask lookupBestMatch(const ComboAddress& addr) const
115 {
116 Netmask result = Netmask();
117
118 const auto best = d_nmt.lookup(addr);
119 if (best != nullptr) {
120 result = best->first;
121 }
122
123 return result;
124 }
125
126 void addMask(const Netmask& nm) const
127 {
128 d_nmt.insert(nm).second = true;
129 }
130
131 void removeNetmask(const Netmask& nm) const
132 {
133 d_nmt.erase(nm);
134 }
135
136 bool isEmpty() const
137 {
138 return d_nmt.empty();
139 }
140
141 mutable NetmaskTree<bool> d_nmt;
142 DNSName d_qname;
143 uint16_t d_qtype;
ca0b5def
BH
144 };
145
4c8d2585
RG
146 struct HashedTag {};
147 struct SequencedTag {};
148 struct NameOnlyHashedTag {};
149 struct OrderedTag {};
150
ca0b5def
BH
151 typedef multi_index_container<
152 CacheEntry,
153 indexed_by <
4c8d2585
RG
154 ordered_unique<tag<OrderedTag>,
155 composite_key<
156 CacheEntry,
157 member<CacheEntry,DNSName,&CacheEntry::d_qname>,
158 member<CacheEntry,uint16_t,&CacheEntry::d_qtype>,
159 member<CacheEntry,Netmask,&CacheEntry::d_netmask>
160 >,
161 composite_key_compare<CanonDNSNameCompare, std::less<uint16_t>, std::less<Netmask> >
748eff9f 162 >,
4c8d2585
RG
163 sequenced<tag<SequencedTag> >,
164 hashed_non_unique<tag<NameOnlyHashedTag>,
165 member<CacheEntry,DNSName,&CacheEntry::d_qname>
166 >
ca0b5def
BH
167 >
168 > cache_t;
4c8d2585
RG
169
170 typedef MemRecursorCache::cache_t::index<MemRecursorCache::OrderedTag>::type::iterator OrderedTagIterator_t;
171 typedef MemRecursorCache::cache_t::index<MemRecursorCache::NameOnlyHashedTag>::type::iterator NameOnlyHashedTagIterator_t;
172
e74f866a 173 typedef multi_index_container<
b0274132 174 ECSIndexEntry,
e74f866a 175 indexed_by <
4c8d2585 176 hashed_unique <tag<HashedTag>,
e74f866a 177 composite_key<
b0274132
RG
178 ECSIndexEntry,
179 member<ECSIndexEntry,DNSName,&ECSIndexEntry::d_qname>,
180 member<ECSIndexEntry,uint16_t,&ECSIndexEntry::d_qtype>
e74f866a 181 >
4c8d2585
RG
182 >,
183 ordered_unique<tag<OrderedTag>,
184 composite_key<
185 ECSIndexEntry,
186 member<ECSIndexEntry,DNSName,&ECSIndexEntry::d_qname>,
187 member<ECSIndexEntry,uint16_t,&ECSIndexEntry::d_qtype>
188 >,
189 composite_key_compare<CanonDNSNameCompare, std::less<uint16_t> >
e74f866a
RG
190 >
191 >
b0274132 192 > ecsIndex_t;
ca0b5def 193
6320ad3a 194 cache_t d_cache;
b0274132 195 ecsIndex_t d_ecsIndex;
4c8d2585 196 std::pair<MemRecursorCache::NameOnlyHashedTagIterator_t, MemRecursorCache::NameOnlyHashedTagIterator_t> d_cachecache;
c5c066bf 197 DNSName d_cachedqname;
cf98aa40 198 bool d_cachecachevalid;
787737ae 199
4c8d2585
RG
200 bool entryMatches(OrderedTagIterator_t& entry, uint16_t qt, bool requireAuth, const ComboAddress& who);
201 std::pair<NameOnlyHashedTagIterator_t, NameOnlyHashedTagIterator_t> getEntries(const DNSName &qname, const QType& qt);
b0274132 202 cache_t::const_iterator getEntryUsingECSIndex(time_t now, const DNSName &qname, uint16_t qtype, bool requireAuth, const ComboAddress& who);
4c8d2585 203 int32_t handleHit(OrderedTagIterator_t& entry, const DNSName& qname, const ComboAddress& who, vector<DNSRecord>* res, vector<std::shared_ptr<RRSIGRecordContent>>* signatures, std::vector<std::shared_ptr<DNSRecord>>* authorityRecs, bool* variable, vState* state, bool* wasAuth);
787737ae 204
e74f866a
RG
205public:
206 void preRemoval(const CacheEntry& entry)
207 {
208 if (entry.d_netmask.empty()) {
209 return;
210 }
211
212 auto key = tie(entry.d_qname, entry.d_qtype);
b0274132
RG
213 auto ecsIndexEntry = d_ecsIndex.find(key);
214 if (ecsIndexEntry != d_ecsIndex.end()) {
215 ecsIndexEntry->removeNetmask(entry.d_netmask);
216 if (ecsIndexEntry->isEmpty()) {
217 d_ecsIndex.erase(ecsIndexEntry);
e74f866a
RG
218 }
219 }
220 }
6320ad3a 221};
6320ad3a 222#endif