]> git.ipfire.org Git - thirdparty/pdns.git/blame - pdns/auth-packetcache.hh
Merge pull request #11431 from jroessler-ox/docs-kskzskroll-update
[thirdparty/pdns.git] / pdns / auth-packetcache.hh
CommitLineData
bf269e28
RG
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 */
e8c59f2d 22#pragma once
bf269e28
RG
23#include <string>
24#include <map>
25#include "dns.hh"
26#include <boost/version.hpp>
27#include "namespaces.hh"
bf269e28 28
905dae56
RG
29#include <boost/multi_index_container.hpp>
30#include <boost/multi_index/ordered_index.hpp>
bf269e28 31#include <boost/multi_index/hashed_index.hpp>
905dae56
RG
32#include <boost/multi_index/sequenced_index.hpp>
33#include <boost/multi_index/key_extractors.hpp>
34using namespace ::boost::multi_index;
bf269e28
RG
35
36#include "dnspacket.hh"
37#include "lock.hh"
38#include "packetcache.hh"
39
40/** This class performs 'whole packet caching'. Feed it a question packet and it will
41 try to find an answer. If you have an answer, insert it to have it cached for later use.
42 Take care not to replace existing cache entries. While this works, it is wasteful. Only
43 insert packets that where not found by get()
44
45 Locking!
46
47 The cache itself is protected by a read/write lock. Because deleting is a two step process, which
48 first marks and then sweeps, a second lock is present to prevent simultaneous inserts and deletes.
49*/
50
51class AuthPacketCache : public PacketCache
52{
53public:
54 AuthPacketCache(size_t mapsCount=1024);
bf269e28 55
c2826d2e 56 void insert(DNSPacket& q, DNSPacket& r, uint32_t maxTTL); //!< We copy the contents of *p into our cache. Do not needlessly call this to insert questions already in the cache as it wastes resources
bf269e28 57
c2826d2e 58 bool get(DNSPacket& p, DNSPacket& q); //!< You need to spoof in the right ID with the DNSPacket.spoofID() method.
bf269e28
RG
59
60 void cleanup(); //!< force the cache to preen itself from expired packets
61 uint64_t purge();
62 uint64_t purge(const std::string& match); // could be $ terminated. Is not a dnsname!
63 uint64_t purgeExact(const DNSName& qname); // no wildcard matching here
64
65 uint64_t size() const { return *d_statnumentries; };
66
67 void setMaxEntries(uint64_t maxEntries)
68 {
69 d_maxEntries = maxEntries;
307994e7
RG
70 for (auto& shard : d_maps) {
71 shard.reserve(maxEntries / d_maps.size());
72 }
bf269e28
RG
73 }
74 void setTTL(uint32_t ttl)
75 {
76 d_ttl = ttl;
9a037bfa
KM
77 }
78 bool enabled()
79 {
80 return (d_ttl > 0);
81 }
bf269e28
RG
82private:
83
84 struct CacheEntry
85 {
08b02366 86 mutable string query;
bf269e28
RG
87 mutable string value;
88 DNSName qname;
89
90 mutable time_t created{0};
91 mutable time_t ttd{0};
92 uint32_t hash{0};
93 uint16_t qtype{0};
94 bool tcp{false};
95 };
96
97 struct HashTag{};
98 struct NameTag{};
94306029 99 struct SequencedTag{};
bf269e28
RG
100 typedef multi_index_container<
101 CacheEntry,
102 indexed_by <
103 hashed_non_unique<tag<HashTag>, member<CacheEntry,uint32_t,&CacheEntry::hash> >,
104 ordered_non_unique<tag<NameTag>, member<CacheEntry,DNSName,&CacheEntry::qname>, CanonDNSNameCompare >,
d2814f81
RG
105 /* Note that this sequence holds 'least recently inserted or replaced', not least recently used.
106 Making it a LRU would require taking a write-lock when fetching from the cache, making the RW-lock inefficient compared to a mutex */
94306029 107 sequenced<tag<SequencedTag>>
bf269e28
RG
108 >
109 > cmap_t;
110
111 struct MapCombo
112 {
abb11ca4
RP
113 MapCombo() = default;
114 ~MapCombo() = default;
9c0ad051
OM
115 MapCombo(const MapCombo&) = delete;
116 MapCombo& operator=(const MapCombo&) = delete;
117
307994e7
RG
118 void reserve(size_t numberOfEntries);
119
1620901c 120 SharedLockGuarded<cmap_t> d_map;
bf269e28
RG
121 };
122
123 vector<MapCombo> d_maps;
124 MapCombo& getMap(const DNSName& name)
125 {
126 return d_maps[name.hash() % d_maps.size()];
127 }
128
08b02366 129 static bool entryMatches(cmap_t::index<HashTag>::type::iterator& iter, const std::string& query, const DNSName& qname, uint16_t qtype, bool tcp);
1620901c 130 bool getEntryLocked(const cmap_t& map, const std::string& query, uint32_t hash, const DNSName &qname, uint16_t qtype, bool tcp, time_t now, string& entry);
bf269e28
RG
131 void cleanupIfNeeded();
132
133 AtomicCounter d_ops{0};
134 AtomicCounter *d_statnumhit;
135 AtomicCounter *d_statnummiss;
136 AtomicCounter *d_statnumentries;
137
138 uint64_t d_maxEntries{0};
139 time_t d_lastclean; // doesn't need to be atomic
140 unsigned long d_nextclean{4096};
141 unsigned int d_cleaninterval{4096};
142 uint32_t d_ttl{0};
143 bool d_cleanskipped{false};
144
145 static const unsigned int s_mincleaninterval=1000, s_maxcleaninterval=300000;
146};