1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154
|
/*
* This file is part of PowerDNS or dnsdist.
* Copyright -- PowerDNS.COM B.V. and its contributors
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* In addition, for the avoidance of any doubt, permission is granted to
* link this program with OpenSSL and to (re)distribute the binaries
* produced as the result of such linking.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#pragma once
#include <boost/utility.hpp>
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/hashed_index.hpp>
#include <boost/multi_index/key_extractors.hpp>
#include <boost/multi_index/sequenced_index.hpp>
using namespace ::boost::multi_index;
#include "base32.hh"
#include "dnsname.hh"
#include "dnsrecords.hh"
#include "lock.hh"
#include "stat_t.hh"
#include "validate.hh"
class AggressiveNSECCache
{
public:
static uint64_t s_nsec3DenialProofMaxCost;
AggressiveNSECCache(uint64_t entries) :
d_maxEntries(entries)
{
}
void insertNSEC(const DNSName& zone, const DNSName& owner, const DNSRecord& record, const std::vector<std::shared_ptr<RRSIGRecordContent>>& signatures, bool nsec3);
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);
void removeZoneInfo(const DNSName& zone, bool subzones);
uint64_t getEntriesCount() const
{
return d_entriesCount;
}
uint64_t getNSECHits() const
{
return d_nsecHits;
}
uint64_t getNSEC3Hits() const
{
return d_nsec3Hits;
}
uint64_t getNSECWildcardHits() const
{
return d_nsecWildcardHits;
}
uint64_t getNSEC3WildcardHits() const
{
return d_nsec3WildcardHits;
}
void prune(time_t now);
size_t dumpToFile(std::unique_ptr<FILE, int (*)(FILE*)>& fp, const struct timeval& now);
private:
struct ZoneEntry
{
ZoneEntry(const DNSName& zone) :
d_zone(zone)
{
}
ZoneEntry(const DNSName& zone, const std::string& salt, uint16_t iterations, bool nsec3) :
d_zone(zone), d_salt(salt), d_iterations(iterations), d_nsec3(nsec3)
{
}
struct HashedTag
{
};
struct SequencedTag
{
};
struct OrderedTag
{
};
struct CacheEntry
{
std::shared_ptr<DNSRecordContent> d_record;
std::vector<std::shared_ptr<RRSIGRecordContent>> d_signatures;
DNSName d_owner;
DNSName d_next;
time_t d_ttd;
};
typedef multi_index_container<
CacheEntry,
indexed_by<
ordered_unique<tag<OrderedTag>,
member<CacheEntry, const DNSName, &CacheEntry::d_owner>,
CanonDNSNameCompare>,
sequenced<tag<SequencedTag>>,
hashed_non_unique<tag<HashedTag>,
member<CacheEntry, const DNSName, &CacheEntry::d_owner>>>>
cache_t;
cache_t d_entries;
const DNSName d_zone;
std::string d_salt;
uint16_t d_iterations{0};
bool d_nsec3{false};
};
std::shared_ptr<LockGuarded<ZoneEntry>> getZone(const DNSName& zone);
std::shared_ptr<LockGuarded<ZoneEntry>> getBestZone(const DNSName& zone);
bool getNSECBefore(time_t now, std::shared_ptr<LockGuarded<ZoneEntry>>& zoneEntry, const DNSName& name, ZoneEntry::CacheEntry& entry);
bool getNSEC3(time_t now, std::shared_ptr<LockGuarded<ZoneEntry>>& zoneEntry, const DNSName& name, ZoneEntry::CacheEntry& entry);
bool getNSEC3Denial(time_t now, std::shared_ptr<LockGuarded<ZoneEntry>>& zoneEntry, std::vector<DNSRecord>& soaSet, std::vector<std::shared_ptr<RRSIGRecordContent>>& soaSignatures, const DNSName& name, const QType& type, std::vector<DNSRecord>& ret, int& res, bool doDNSSEC, pdns::validation::ValidationContext& validationContext);
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);
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);
/* slowly updates d_entriesCount */
void updateEntriesCount(SuffixMatchTree<std::shared_ptr<LockGuarded<ZoneEntry>>>& zones);
SharedLockGuarded<SuffixMatchTree<std::shared_ptr<LockGuarded<ZoneEntry>>>> d_zones;
pdns::stat_t d_nsecHits{0};
pdns::stat_t d_nsec3Hits{0};
pdns::stat_t d_nsecWildcardHits{0};
pdns::stat_t d_nsec3WildcardHits{0};
pdns::stat_t d_entriesCount{0};
uint64_t d_maxEntries{0};
};
extern std::unique_ptr<AggressiveNSECCache> g_aggressiveNSECCache;
|