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 #include <string>
24 #include <unordered_map>
25 #include <vector>
26 #include "dnsname.hh"
27 #include "lock.hh"
28 #include "misc.hh"
29 
30 class AuthZoneCache : public boost::noncopyable
31 {
32 public:
33   AuthZoneCache(size_t mapsCount = 1024);
34   ~AuthZoneCache();
35 
36   void replace(const vector<tuple<DNSName, int>>& zone);
37   void add(const DNSName& zone, const int zoneId);
38   void setReplacePending(); //!< call this when data collection for the subsequent replace() call starts.
39 
40   bool getEntry(const DNSName& zone, int& zoneId);
41 
size()42   size_t size() { return *d_statnumentries; } //!< number of entries in the cache
43 
getRefreshInterval() const44   uint32_t getRefreshInterval() const
45   {
46     return d_refreshinterval;
47   }
48 
setRefreshInterval(uint32_t interval)49   void setRefreshInterval(uint32_t interval)
50   {
51     d_refreshinterval = interval;
52   }
53 
54   bool isEnabled() const;
55 
56   void clear();
57 
58 private:
59   struct CacheValue
60   {
61     int zoneId{-1};
62   };
63 
64   typedef std::unordered_map<DNSName, CacheValue, std::hash<DNSName>> cmap_t;
65 
66   struct MapCombo
67   {
MapComboAuthZoneCache::MapCombo68     MapCombo() {}
~MapComboAuthZoneCache::MapCombo69     ~MapCombo() {}
70     MapCombo(const MapCombo&) = delete;
71     MapCombo& operator=(const MapCombo&) = delete;
72 
73     ReadWriteLock d_mut;
74     cmap_t d_map;
75   };
76 
77   vector<MapCombo> d_maps;
getMapIndex(const DNSName & zone)78   size_t getMapIndex(const DNSName& zone)
79   {
80     return zone.hash() % d_maps.size();
81   }
getMap(const DNSName & qname)82   MapCombo& getMap(const DNSName& qname)
83   {
84     return d_maps[getMapIndex(qname)];
85   }
86 
87   AtomicCounter* d_statnumhit;
88   AtomicCounter* d_statnummiss;
89   AtomicCounter* d_statnumentries;
90 
91   time_t d_refreshinterval{0};
92 
93   ReadWriteLock d_mut;
94   std::vector<tuple<DNSName, int>> d_pendingAdds;
95   bool d_replacePending{false};
96 };
97 
98 extern AuthZoneCache g_zoneCache;
99