• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

PowerDNS / pdns / 13317890644

13 Feb 2025 11:32AM UTC coverage: 59.24% (-5.5%) from 64.714%
13317890644

push

github

web-flow
Merge pull request #15149 from rgacogne/ddist-meson-min-version

dnsdist: Bump the required version of `meson` to 1.3

50429 of 138204 branches covered (36.49%)

Branch coverage included in aggregate %.

140112 of 183436 relevant lines covered (76.38%)

6753565.52 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

17.14
/modules/bindbackend/bindbackend2.hh
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 <map>
25
#include <set>
26
#include <pthread.h>
27
#include <time.h>
28
#include <fstream>
29
#include <mutex>
30
#include <boost/utility.hpp>
31

32
#include <boost/multi_index_container.hpp>
33
#include <boost/multi_index/hashed_index.hpp>
34
#include <boost/multi_index/ordered_index.hpp>
35
#include <boost/multi_index/identity.hpp>
36
#include <boost/multi_index/member.hpp>
37
#include <sys/types.h>
38
#include <sys/stat.h>
39
#include <unistd.h>
40
#include "pdns/lock.hh"
41
#include "pdns/misc.hh"
42
#include "pdns/dnsbackend.hh"
43
#include "pdns/namespaces.hh"
44
#include "pdns/backends/gsql/ssql.hh"
45

46
using namespace ::boost::multi_index;
47

48
/**
49
  This struct is used within the Bind2Backend to store DNS information. It is
50
  almost identical to a DNSResourceRecord, but then a bit smaller and with
51
  different sorting rules, which make sure that the SOA record comes up front.
52
*/
53

54
struct Bind2DNSRecord
55
{
56
  DNSName qname;
57
  string content;
58
  string nsec3hash;
59
  uint32_t ttl;
60
  uint16_t qtype;
61
  mutable bool auth;
62
  bool operator<(const Bind2DNSRecord& rhs) const
63
  {
×
64
    if (qname.canonCompare(rhs.qname))
×
65
      return true;
×
66
    if (rhs.qname.canonCompare(qname))
×
67
      return false;
×
68
    if (qtype == QType::SOA && rhs.qtype != QType::SOA)
×
69
      return true;
×
70
    return std::tie(qtype, content, ttl) < std::tie(rhs.qtype, rhs.content, rhs.ttl);
×
71
  }
×
72
};
73

74
struct Bind2DNSCompare : std::less<Bind2DNSRecord>
75
{
76
  using std::less<Bind2DNSRecord>::operator();
77
  // use operator<
78
  bool operator()(const DNSName& a, const Bind2DNSRecord& b) const
79
  {
×
80
    return a.canonCompare(b.qname);
×
81
  }
×
82
  bool operator()(const Bind2DNSRecord& a, const DNSName& b) const
83
  {
×
84
    return a.qname.canonCompare(b);
×
85
  }
×
86
  bool operator()(const Bind2DNSRecord& a, const Bind2DNSRecord& b) const
87
  {
16✔
88
    return a.qname.canonCompare(b.qname);
16✔
89
  }
16✔
90
};
91

92
struct NSEC3Tag
93
{
94
};
95
struct UnorderedNameTag
96
{
97
};
98

99
typedef multi_index_container<
100
  Bind2DNSRecord,
101
  indexed_by<
102
    ordered_non_unique<identity<Bind2DNSRecord>, Bind2DNSCompare>,
103
    hashed_non_unique<tag<UnorderedNameTag>, member<Bind2DNSRecord, DNSName, &Bind2DNSRecord::qname>>,
104
    ordered_non_unique<tag<NSEC3Tag>, member<Bind2DNSRecord, std::string, &Bind2DNSRecord::nsec3hash>>>>
105
  recordstorage_t;
106

107
template <typename T>
108
class LookButDontTouch
109
{
110
public:
111
  LookButDontTouch() = default;
1,154✔
112
  LookButDontTouch(shared_ptr<T>&& records) :
113
    d_records(std::move(records))
114
  {
2✔
115
  }
2✔
116

117
  shared_ptr<const T> get()
118
  {
×
119
    return d_records;
×
120
  }
×
121

122
  size_t getEntriesCount() const
123
  {
×
124
    if (!d_records) {
×
125
      return 0;
×
126
    }
×
127
    return d_records->size();
×
128
  }
×
129

130
private:
131
  /* we can increase the number of references to that object,
132
     but never update the object itself */
133
  shared_ptr<const T> d_records;
134
};
135

136
/** Class which describes all metadata of a domain for storage by the Bind2Backend, and also contains a pointer to a vector of Bind2DNSRecord's */
137
class BB2DomainInfo
138
{
139
public:
140
  BB2DomainInfo();
141
  void setCtime();
142
  bool current();
143
  //! configure how often this domain should be checked for changes (on disk)
144
  void setCheckInterval(time_t seconds);
145
  time_t getCheckInterval() const
146
  {
×
147
    return d_checkinterval;
×
148
  }
×
149

150
  DNSName d_name; //!< actual name of the domain
151
  DomainInfo::DomainKind d_kind{DomainInfo::Native}; //!< the kind of domain
152
  string d_filename; //!< full absolute filename of the zone on disk
153
  string d_status; //!< message describing status of a domain, for human consumption
154
  vector<ComboAddress> d_primaries; //!< IP address of the primary of this domain
155
  set<string> d_also_notify; //!< IP list of hosts to also notify
156
  LookButDontTouch<recordstorage_t> d_records; //!< the actual records belonging to this domain
157
  time_t d_ctime{0}; //!< last known ctime of the file on disk
158
  time_t d_lastcheck{0}; //!< last time domain was checked for freshness
159
  uint32_t d_lastnotified{0}; //!< Last serial number we notified our secondaries of
160
  unsigned int d_id{0}; //!< internal id of the domain
161
  mutable bool d_checknow; //!< if this domain has been flagged for a check
162
  bool d_loaded{false}; //!< if a domain is loaded
163
  bool d_wasRejectedLastReload{false}; //!< if the domain was rejected during Bind2Backend::queueReloadAndStore
164
  bool d_nsec3zone{false};
165
  NSEC3PARAMRecordContent d_nsec3param;
166

167
private:
168
  time_t getCtime();
169
  time_t d_checkinterval{0};
170
};
171

172
class SSQLite3;
173
class NSEC3PARAMRecordContent;
174

175
struct NameTag
176
{
177
};
178

179
class Bind2Backend : public DNSBackend
180
{
181
public:
182
  Bind2Backend(const string& suffix = "", bool loadZones = true);
183
  ~Bind2Backend() override;
184
  void getUnfreshSecondaryInfos(vector<DomainInfo>* unfreshDomains) override;
185
  void getUpdatedPrimaries(vector<DomainInfo>& changedDomains, std::unordered_set<DNSName>& catalogs, CatalogHashMap& catalogHashes) override;
186
  bool getDomainInfo(const DNSName& domain, DomainInfo& di, bool getSerial = true) override;
187
  time_t getCtime(const string& fname);
188
  // DNSSEC
189
  bool getBeforeAndAfterNamesAbsolute(uint32_t id, const DNSName& qname, DNSName& unhashed, DNSName& before, DNSName& after) override;
190
  void lookup(const QType&, const DNSName& qdomain, int zoneId, DNSPacket* p = nullptr) override;
191
  bool list(const DNSName& target, int id, bool include_disabled = false) override;
192
  bool get(DNSResourceRecord&) override;
193
  void getAllDomains(vector<DomainInfo>* domains, bool getSerial, bool include_disabled = false) override;
194

195
  static DNSBackend* maker();
196
  static std::mutex s_startup_lock;
197

198
  void setStale(uint32_t domain_id) override;
199
  void setFresh(uint32_t domain_id) override;
200
  void setNotified(uint32_t id, uint32_t serial) override;
201
  bool startTransaction(const DNSName& qname, int id) override;
202
  bool feedRecord(const DNSResourceRecord& rr, const DNSName& ordername, bool ordernameIsNSEC3 = false) override;
203
  bool commitTransaction() override;
204
  bool abortTransaction() override;
205
  void alsoNotifies(const DNSName& domain, set<string>* ips) override;
206
  bool searchRecords(const string& pattern, size_t maxResults, vector<DNSResourceRecord>& result) override;
207

208
  // the DNSSEC related (getDomainMetadata has broader uses too)
209
  bool getAllDomainMetadata(const DNSName& name, std::map<std::string, std::vector<std::string>>& meta) override;
210
  bool getDomainMetadata(const DNSName& name, const std::string& kind, std::vector<std::string>& meta) override;
211
  bool setDomainMetadata(const DNSName& name, const std::string& kind, const std::vector<std::string>& meta) override;
212
  bool getDomainKeys(const DNSName& name, std::vector<KeyData>& keys) override;
213
  bool removeDomainKey(const DNSName& name, unsigned int id) override;
214
  bool addDomainKey(const DNSName& name, const KeyData& key, int64_t& id) override;
215
  bool activateDomainKey(const DNSName& name, unsigned int id) override;
216
  bool deactivateDomainKey(const DNSName& name, unsigned int id) override;
217
  bool publishDomainKey(const DNSName& name, unsigned int id) override;
218
  bool unpublishDomainKey(const DNSName& name, unsigned int id) override;
219
  bool getTSIGKey(const DNSName& name, DNSName& algorithm, string& content) override;
220
  bool setTSIGKey(const DNSName& name, const DNSName& algorithm, const string& content) override;
221
  bool deleteTSIGKey(const DNSName& name) override;
222
  bool getTSIGKeys(std::vector<struct TSIGKey>& keys) override;
223
  bool doesDNSSEC() override;
224
  // end of DNSSEC
225

226
  typedef multi_index_container<BB2DomainInfo,
227
                                indexed_by<ordered_unique<member<BB2DomainInfo, unsigned int, &BB2DomainInfo::d_id>>,
228
                                           ordered_unique<tag<NameTag>, member<BB2DomainInfo, DNSName, &BB2DomainInfo::d_name>>>>
229
    state_t;
230
  static SharedLockGuarded<state_t> s_state;
231

232
  void parseZoneFile(BB2DomainInfo* bbd);
233
  void rediscover(string* status = nullptr) override;
234

235
  // for autoprimary support
236
  bool autoPrimariesList(std::vector<AutoPrimary>& primaries) override;
237
  bool autoPrimaryBackend(const string& ip, const DNSName& domain, const vector<DNSResourceRecord>& nsset, string* nameserver, string* account, DNSBackend** db) override;
238
  static std::mutex s_autosecondary_config_lock;
239
  bool createSecondaryDomain(const string& ip, const DNSName& domain, const string& nameserver, const string& account) override;
240

241
private:
242
  void setupDNSSEC();
243
  void setupStatements();
244
  void freeStatements();
245
  static bool safeGetBBDomainInfo(int id, BB2DomainInfo* bbd);
246
  static void safePutBBDomainInfo(const BB2DomainInfo& bbd);
247
  static bool safeGetBBDomainInfo(const DNSName& name, BB2DomainInfo* bbd);
248
  static bool safeRemoveBBDomainInfo(const DNSName& name);
249
  shared_ptr<SSQLite3> d_dnssecdb;
250
  bool getNSEC3PARAM(const DNSName& name, NSEC3PARAMRecordContent* ns3p);
251
  void setLastCheck(uint32_t domain_id, time_t lastcheck);
252
  bool getNSEC3PARAMuncached(const DNSName& name, NSEC3PARAMRecordContent* ns3p);
253
  class handle
254
  {
255
  public:
256
    bool get(DNSResourceRecord&);
257
    void reset();
258

259
    handle();
260

261
    handle(const handle&) = delete;
262
    handle& operator=(const handle&) = delete; // don't go copying this
263

264
    shared_ptr<const recordstorage_t> d_records;
265
    recordstorage_t::index<UnorderedNameTag>::type::const_iterator d_iter, d_end_iter;
266

267
    recordstorage_t::const_iterator d_qname_iter, d_qname_end;
268

269
    DNSName qname;
270
    DNSName domain;
271

272
    int id{-1};
273
    QType qtype;
274
    bool d_list{false};
275
    bool mustlog{false};
276

277
  private:
278
    bool get_normal(DNSResourceRecord&);
279
    bool get_list(DNSResourceRecord&);
280
  };
281

282
  unique_ptr<SSqlStatement> d_getAllDomainMetadataQuery_stmt;
283
  unique_ptr<SSqlStatement> d_getDomainMetadataQuery_stmt;
284
  unique_ptr<SSqlStatement> d_deleteDomainMetadataQuery_stmt;
285
  unique_ptr<SSqlStatement> d_insertDomainMetadataQuery_stmt;
286
  unique_ptr<SSqlStatement> d_getDomainKeysQuery_stmt;
287
  unique_ptr<SSqlStatement> d_deleteDomainKeyQuery_stmt;
288
  unique_ptr<SSqlStatement> d_insertDomainKeyQuery_stmt;
289
  unique_ptr<SSqlStatement> d_GetLastInsertedKeyIdQuery_stmt;
290
  unique_ptr<SSqlStatement> d_activateDomainKeyQuery_stmt;
291
  unique_ptr<SSqlStatement> d_deactivateDomainKeyQuery_stmt;
292
  unique_ptr<SSqlStatement> d_publishDomainKeyQuery_stmt;
293
  unique_ptr<SSqlStatement> d_unpublishDomainKeyQuery_stmt;
294
  unique_ptr<SSqlStatement> d_getTSIGKeyQuery_stmt;
295
  unique_ptr<SSqlStatement> d_setTSIGKeyQuery_stmt;
296
  unique_ptr<SSqlStatement> d_deleteTSIGKeyQuery_stmt;
297
  unique_ptr<SSqlStatement> d_getTSIGKeysQuery_stmt;
298

299
  DNSName d_transaction_qname;
300
  string d_transaction_tmpname;
301
  string d_logprefix;
302
  set<string> alsoNotify; //!< this is used to store the also-notify list of interested peers.
303
  std::unique_ptr<ofstream> d_of;
304
  handle d_handle;
305
  static string s_binddirectory; //!< this is used to store the 'directory' setting of the bind configuration
306
  static int s_first; //!< this is raised on construction to prevent multiple instances of us being generated
307
  int d_transaction_id;
308
  static bool s_ignore_broken_records;
309
  bool d_hybrid;
310
  bool d_upgradeContent;
311

312
  BB2DomainInfo createDomainEntry(const DNSName& domain, const string& filename); //!< does not insert in s_state
313

314
  void queueReloadAndStore(unsigned int id);
315
  static bool findBeforeAndAfterUnhashed(std::shared_ptr<const recordstorage_t>& records, const DNSName& qname, DNSName& unhashed, DNSName& before, DNSName& after);
316
  static void insertRecord(std::shared_ptr<recordstorage_t>& records, const DNSName& zoneName, const DNSName& qname, const QType& qtype, const string& content, int ttl, const std::string& hashed = string(), bool* auth = nullptr);
317
  void reload() override;
318
  static string DLDomStatusHandler(const vector<string>& parts, Utility::pid_t ppid);
319
  static string DLDomExtendedStatusHandler(const vector<string>& parts, Utility::pid_t ppid);
320
  static string DLListRejectsHandler(const vector<string>& parts, Utility::pid_t ppid);
321
  static string DLReloadNowHandler(const vector<string>& parts, Utility::pid_t ppid);
322
  static string DLAddDomainHandler(const vector<string>& parts, Utility::pid_t ppid);
323
  static void fixupOrderAndAuth(std::shared_ptr<recordstorage_t>& records, const DNSName& zoneName, bool nsec3zone, const NSEC3PARAMRecordContent& ns3pr);
324
  static void doEmptyNonTerminals(std::shared_ptr<recordstorage_t>& records, const DNSName& zoneName, bool nsec3zone, const NSEC3PARAMRecordContent& ns3pr);
325
  void loadConfig(string* status = nullptr);
326
};
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc