]>
git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/dnsdistdist/dnsdist-kvs.cc
2 * This file is part of PowerDNS or dnsdist.
3 * Copyright -- PowerDNS.COM B.V. and its contributors
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.
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.
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.
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.
23 #include "dnsdist-kvs.hh"
28 std::vector
<std::string
> KeyValueLookupKeySourceIP::getKeys(const ComboAddress
& addr
)
30 std::vector
<std::string
> result
;
32 if (addr
.sin4
.sin_family
== AF_INET
) {
33 result
.emplace_back(reinterpret_cast<const char*>(&addr
.sin4
.sin_addr
.s_addr
), sizeof(addr
.sin4
.sin_addr
.s_addr
));
35 else if (addr
.sin4
.sin_family
== AF_INET6
) {
36 result
.emplace_back(reinterpret_cast<const char*>(&addr
.sin6
.sin6_addr
.s6_addr
), sizeof(addr
.sin6
.sin6_addr
.s6_addr
));
42 std::vector
<std::string
> KeyValueLookupKeySuffix::getKeys(const DNSName
& qname
)
44 if (qname
.empty() || qname
.isRoot()) {
48 auto lowerQName
= qname
.makeLowerCase();
49 size_t labelsCount
= lowerQName
.countLabels();
50 if (d_minLabels
!= 0) {
51 if (labelsCount
< d_minLabels
) {
54 labelsCount
-= (d_minLabels
- 1);
57 std::vector
<std::string
> result
;
58 result
.reserve(labelsCount
);
60 while(!lowerQName
.isRoot()) {
61 result
.emplace_back(d_wireFormat
? lowerQName
.toDNSString() : lowerQName
.toStringRootDot());
63 if (!lowerQName
.chopOff() || labelsCount
== 0) {
73 bool LMDBKVStore::getValue(const std::string
& key
, std::string
& value
)
76 auto transaction
= d_env
.getROTransaction();
77 auto dbi
= transaction
->openDB(d_dbName
, 0);
79 int rc
= transaction
->get(dbi
, MDBInVal(key
), result
);
81 value
= result
.get
<std::string
>();
84 else if (rc
== MDB_NOTFOUND
) {
88 catch(const std::exception
& e
) {
89 warnlog("Error while looking up key '%s' from LMDB file '%s', database '%s': %s", key
, d_fname
, d_dbName
, e
.what());
94 bool LMDBKVStore::keyExists(const std::string
& key
)
97 auto transaction
= d_env
.getROTransaction();
98 auto dbi
= transaction
->openDB(d_dbName
, 0);
100 int rc
= transaction
->get(dbi
, MDBInVal(key
), result
);
104 else if (rc
== MDB_NOTFOUND
) {
108 catch(const std::exception
& e
) {
109 warnlog("Error while looking up key '%s' from LMDB file '%s', database '%s': %s", key
, d_fname
, d_dbName
, e
.what());
114 #endif /* HAVE_LMDB */
118 CDBKVStore::CDBKVStore(const std::string
& fname
, time_t refreshDelay
): d_fname(fname
), d_refreshDelay(refreshDelay
)
120 pthread_rwlock_init(&d_lock
, nullptr);
121 d_refreshing
.clear();
123 time_t now
= time(nullptr);
124 if (d_refreshDelay
> 0) {
125 d_nextCheck
= now
+ d_refreshDelay
;
128 refreshDBIfNeeded(now
);
131 CDBKVStore::~CDBKVStore() {
132 pthread_rwlock_destroy(&d_lock
);
135 bool CDBKVStore::reload(const struct stat
& st
)
137 auto newCDB
= std::unique_ptr
<CDB
>(new CDB(d_fname
));
139 WriteLock
wl(&d_lock
);
140 d_cdb
= std::move(newCDB
);
142 d_mtime
= st
.st_mtime
;
146 bool CDBKVStore::reload()
149 if (stat(d_fname
.c_str(), &st
) == 0) {
153 warnlog("Error while retrieving the last modification time of CDB database '%s': %s", d_fname
, stringerror());
158 void CDBKVStore::refreshDBIfNeeded(time_t now
)
160 if (d_refreshing
.test_and_set()) {
161 /* someone else is already refreshing */
167 if (stat(d_fname
.c_str(), &st
) == 0) {
168 if (st
.st_mtime
> d_mtime
) {
173 warnlog("Error while retrieving the last modification time of CDB database '%s': %s", d_fname
, stringerror());
175 d_nextCheck
= now
+ d_refreshDelay
;
176 d_refreshing
.clear();
179 d_refreshing
.clear();
184 bool CDBKVStore::getValue(const std::string
& key
, std::string
& value
)
186 time_t now
= time(nullptr);
189 if (d_nextCheck
!= 0 && now
>= d_nextCheck
) {
190 refreshDBIfNeeded(now
);
194 ReadLock
rl(&d_lock
);
195 if (d_cdb
&& d_cdb
->findOne(key
, value
)) {
200 catch(const std::exception
& e
) {
201 warnlog("Error while looking up key '%s' from CDB file '%s': %s", key
, d_fname
, e
.what());
206 bool CDBKVStore::keyExists(const std::string
& key
)
208 time_t now
= time(nullptr);
211 if (d_nextCheck
!= 0 && now
>= d_nextCheck
) {
212 refreshDBIfNeeded(now
);
216 ReadLock
rl(&d_lock
);
221 return d_cdb
->keyExists(key
);
224 catch(const std::exception
& e
) {
225 warnlog("Error while looking up key '%s' from CDB file '%s': %s", key
, d_fname
, e
.what());
230 #endif /* HAVE_CDB */