]>
Commit | Line | Data |
---|---|---|
25f5783a 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 | */ | |
22 | #pragma once | |
23 | ||
e2f1fd57 | 24 | #include <atomic> |
25f5783a RG |
25 | #include <boost/utility.hpp> |
26 | #include <boost/multi_index_container.hpp> | |
27 | #include <boost/multi_index/ordered_index.hpp> | |
28 | #include <boost/multi_index/hashed_index.hpp> | |
29 | #include <boost/multi_index/key_extractors.hpp> | |
30 | #include <boost/multi_index/sequenced_index.hpp> | |
31 | ||
905dae56 RG |
32 | using namespace ::boost::multi_index; |
33 | ||
bf720981 | 34 | #include "base32.hh" |
25f5783a RG |
35 | #include "dnsname.hh" |
36 | #include "dnsrecords.hh" | |
37 | #include "lock.hh" | |
bd468718 | 38 | #include "stat_t.hh" |
10971f78 | 39 | #include "logger.hh" |
15e973d6 | 40 | #include "validate.hh" |
25f5783a RG |
41 | |
42 | class AggressiveNSECCache | |
43 | { | |
44 | public: | |
15e973d6 OM |
45 | static constexpr uint8_t s_default_maxNSEC3CommonPrefix = 10; |
46 | static uint64_t s_nsec3DenialProofMaxCost; | |
dcf64a6e OM |
47 | static uint8_t s_maxNSEC3CommonPrefix; |
48 | ||
45c1026d O |
49 | AggressiveNSECCache(uint64_t entries) : |
50 | d_maxEntries(entries) | |
edcf680e RG |
51 | { |
52 | } | |
53 | ||
2ac00bd0 OM |
54 | void setMaxEntries(uint64_t number) |
55 | { | |
56 | d_maxEntries = number; | |
57 | } | |
58 | ||
e4f20c78 OM |
59 | static bool nsec3Disabled() |
60 | { | |
61 | return s_maxNSEC3CommonPrefix == 0; | |
62 | } | |
63 | ||
d06dcda4 | 64 | void insertNSEC(const DNSName& zone, const DNSName& owner, const DNSRecord& record, const std::vector<std::shared_ptr<const RRSIGRecordContent>>& signatures, bool nsec3); |
15e973d6 | 65 | bool getDenial(time_t, const DNSName& name, const QType& type, std::vector<DNSRecord>& ret, int& res, const ComboAddress& who, const boost::optional<std::string>& routingTag, bool doDNSSEC, pdns::validation::ValidationContext& validationContext, const OptLog& log = std::nullopt); |
25f5783a | 66 | |
da6be6e3 | 67 | void removeZoneInfo(const DNSName& zone, bool subzones); |
25f5783a | 68 | |
6c1fcbfe RG |
69 | uint64_t getEntriesCount() const |
70 | { | |
71 | return d_entriesCount; | |
72 | } | |
73 | ||
74 | uint64_t getNSECHits() const | |
75 | { | |
76 | return d_nsecHits; | |
77 | } | |
78 | ||
79 | uint64_t getNSEC3Hits() const | |
80 | { | |
81 | return d_nsec3Hits; | |
82 | } | |
83 | ||
84 | uint64_t getNSECWildcardHits() const | |
85 | { | |
86 | return d_nsecWildcardHits; | |
87 | } | |
88 | ||
89 | uint64_t getNSEC3WildcardHits() const | |
90 | { | |
91 | return d_nsec3WildcardHits; | |
92 | } | |
93 | ||
171376f1 OM |
94 | // exported for unit test purposes |
95 | static bool isSmallCoveringNSEC3(const DNSName& owner, const std::string& nextHash); | |
96 | ||
5586c462 | 97 | void prune(time_t now); |
45c1026d | 98 | size_t dumpToFile(std::unique_ptr<FILE, int (*)(FILE*)>& fp, const struct timeval& now); |
edcf680e | 99 | |
25f5783a | 100 | private: |
25f5783a RG |
101 | struct ZoneEntry |
102 | { | |
779f35b4 RG |
103 | ZoneEntry(const DNSName& zone) : |
104 | d_zone(zone) | |
25f5783a RG |
105 | { |
106 | } | |
107 | ||
45c1026d O |
108 | ZoneEntry(const DNSName& zone, const std::string& salt, uint16_t iterations, bool nsec3) : |
109 | d_zone(zone), d_salt(salt), d_iterations(iterations), d_nsec3(nsec3) | |
25f5783a RG |
110 | { |
111 | } | |
112 | ||
45c1026d O |
113 | struct HashedTag |
114 | { | |
115 | }; | |
116 | struct SequencedTag | |
117 | { | |
118 | }; | |
119 | struct OrderedTag | |
120 | { | |
121 | }; | |
25f5783a RG |
122 | |
123 | struct CacheEntry | |
124 | { | |
d06dcda4 RG |
125 | std::shared_ptr<const DNSRecordContent> d_record; |
126 | std::vector<std::shared_ptr<const RRSIGRecordContent>> d_signatures; | |
25f5783a RG |
127 | |
128 | DNSName d_owner; | |
129 | DNSName d_next; | |
130 | time_t d_ttd; | |
131 | }; | |
132 | ||
133 | typedef multi_index_container< | |
134 | CacheEntry, | |
45c1026d | 135 | indexed_by< |
25f5783a | 136 | ordered_unique<tag<OrderedTag>, |
1f9eeeba | 137 | member<CacheEntry, const DNSName, &CacheEntry::d_owner>, |
7ca490f0 | 138 | CanonDNSNameCompare>, |
45c1026d | 139 | sequenced<tag<SequencedTag>>, |
25f5783a | 140 | hashed_non_unique<tag<HashedTag>, |
1f9eeeba | 141 | member<CacheEntry, const DNSName, &CacheEntry::d_owner>>>> |
45c1026d | 142 | cache_t; |
25f5783a RG |
143 | |
144 | cache_t d_entries; | |
779f35b4 | 145 | const DNSName d_zone; |
25f5783a | 146 | std::string d_salt; |
25f5783a RG |
147 | uint16_t d_iterations{0}; |
148 | bool d_nsec3{false}; | |
149 | }; | |
150 | ||
1f9eeeba RG |
151 | std::shared_ptr<LockGuarded<ZoneEntry>> getZone(const DNSName& zone); |
152 | std::shared_ptr<LockGuarded<ZoneEntry>> getBestZone(const DNSName& zone); | |
153 | bool getNSECBefore(time_t now, std::shared_ptr<LockGuarded<ZoneEntry>>& zoneEntry, const DNSName& name, ZoneEntry::CacheEntry& entry); | |
154 | bool getNSEC3(time_t now, std::shared_ptr<LockGuarded<ZoneEntry>>& zoneEntry, const DNSName& name, ZoneEntry::CacheEntry& entry); | |
15e973d6 | 155 | bool getNSEC3Denial(time_t now, std::shared_ptr<LockGuarded<ZoneEntry>>& zoneEntry, std::vector<DNSRecord>& soaSet, std::vector<std::shared_ptr<const RRSIGRecordContent>>& soaSignatures, const DNSName& name, const QType& type, std::vector<DNSRecord>& ret, int& res, bool doDNSSEC, const OptLog&, pdns::validation::ValidationContext& validationContext); |
a8cd5db5 OM |
156 | bool synthesizeFromNSEC3Wildcard(time_t now, const DNSName& name, const QType& type, std::vector<DNSRecord>& ret, int& res, bool doDNSSEC, ZoneEntry::CacheEntry& nextCloser, const DNSName& wildcardName, const OptLog&); |
157 | bool synthesizeFromNSECWildcard(time_t now, const DNSName& name, const QType& type, std::vector<DNSRecord>& ret, int& res, bool doDNSSEC, ZoneEntry::CacheEntry& nsec, const DNSName& wildcardName, const OptLog&); | |
25f5783a | 158 | |
da6be6e3 | 159 | /* slowly updates d_entriesCount */ |
1f9eeeba | 160 | void updateEntriesCount(SuffixMatchTree<std::shared_ptr<LockGuarded<ZoneEntry>>>& zones); |
da6be6e3 | 161 | |
1f9eeeba | 162 | SharedLockGuarded<SuffixMatchTree<std::shared_ptr<LockGuarded<ZoneEntry>>>> d_zones; |
bd468718 RG |
163 | pdns::stat_t d_nsecHits{0}; |
164 | pdns::stat_t d_nsec3Hits{0}; | |
165 | pdns::stat_t d_nsecWildcardHits{0}; | |
166 | pdns::stat_t d_nsec3WildcardHits{0}; | |
167 | pdns::stat_t d_entriesCount{0}; | |
e2f1fd57 | 168 | std::atomic<uint64_t> d_maxEntries{0}; |
25f5783a RG |
169 | }; |
170 | ||
25f5783a | 171 | extern std::unique_ptr<AggressiveNSECCache> g_aggressiveNSECCache; |