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 "threadname.hh"
25 #include "dnsdist-ecs.hh"
26 #include "dnsdist-lua.hh"
27 #include "dnsdist-protobuf.hh"
28 #include "dnsdist-kvs.hh"
32 #include "ednsoptions.hh"
33 #include "fstrm_logger.hh"
34 #include "remote_logger.hh"
36 #include <boost/optional/optional_io.hpp>
39 #include "ipcipher.hh"
40 #endif /* HAVE_LIBCRYPTO */
42 class DropAction
: public DNSAction
45 DNSAction::Action
operator()(DNSQuestion
* dq
, std::string
* ruleresult
) const override
49 std::string
toString() const override
55 class AllowAction
: public DNSAction
58 DNSAction::Action
operator()(DNSQuestion
* dq
, std::string
* ruleresult
) const override
62 std::string
toString() const override
68 class NoneAction
: public DNSAction
71 DNSAction::Action
operator()(DNSQuestion
* dq
, std::string
* ruleresult
) const override
75 std::string
toString() const override
81 class QPSAction
: public DNSAction
84 QPSAction(int limit
) : d_qps(limit
, limit
)
86 DNSAction::Action
operator()(DNSQuestion
* dq
, std::string
* ruleresult
) const override
93 std::string
toString() const override
95 return "qps limit to "+std::to_string(d_qps
.getRate());
101 class DelayAction
: public DNSAction
104 DelayAction(int msec
) : d_msec(msec
)
106 DNSAction::Action
operator()(DNSQuestion
* dq
, std::string
* ruleresult
) const override
108 *ruleresult
=std::to_string(d_msec
);
109 return Action::Delay
;
111 std::string
toString() const override
113 return "delay by "+std::to_string(d_msec
)+ " msec";
120 class TeeAction
: public DNSAction
123 TeeAction(const ComboAddress
& ca
, bool addECS
=false);
124 ~TeeAction() override
;
125 DNSAction::Action
operator()(DNSQuestion
* dq
, std::string
* ruleresult
) const override
;
126 std::string
toString() const override
;
127 std::map
<std::string
, double> getStats() const override
;
130 ComboAddress d_remote
;
131 std::thread d_worker
;
135 mutable std::atomic
<unsigned long> d_senderrors
{0};
136 unsigned long d_recverrors
{0};
137 mutable std::atomic
<unsigned long> d_queries
{0};
138 unsigned long d_responses
{0};
139 unsigned long d_nxdomains
{0};
140 unsigned long d_servfails
{0};
141 unsigned long d_refuseds
{0};
142 unsigned long d_formerrs
{0};
143 unsigned long d_notimps
{0};
144 unsigned long d_noerrors
{0};
145 mutable unsigned long d_tcpdrops
{0};
146 unsigned long d_otherrcode
{0};
147 std::atomic
<bool> d_pleaseQuit
{false};
148 bool d_addECS
{false};
151 TeeAction::TeeAction(const ComboAddress
& ca
, bool addECS
) : d_remote(ca
), d_addECS(addECS
)
153 d_fd
=SSocket(d_remote
.sin4
.sin_family
, SOCK_DGRAM
, 0);
154 SConnect(d_fd
, d_remote
);
155 setNonBlocking(d_fd
);
156 d_worker
=std::thread(std::bind(&TeeAction::worker
, this));
159 TeeAction::~TeeAction()
166 DNSAction::Action
TeeAction::operator()(DNSQuestion
* dq
, std::string
* ruleresult
) const
177 uint16_t len
= dq
->len
;
178 bool ednsAdded
= false;
179 bool ecsAdded
= false;
180 query
.reserve(dq
->size
);
181 query
.assign((char*) dq
->dh
, len
);
183 std::string newECSOption
;
184 generateECSOption(dq
->ecsSet
? dq
->ecs
.getNetwork() : *dq
->remote
, newECSOption
, dq
->ecsSet
? dq
->ecs
.getBits() : dq
->ecsPrefixLength
);
186 if (!handleEDNSClientSubnet(const_cast<char*>(query
.c_str()), query
.capacity(), dq
->qname
->wirelength(), &len
, &ednsAdded
, &ecsAdded
, dq
->ecsOverride
, newECSOption
, g_preserveTrailingData
)) {
187 return DNSAction::Action::None
;
190 res
= send(d_fd
, query
.c_str(), len
, 0);
193 res
= send(d_fd
, (char*)dq
->dh
, dq
->len
, 0);
199 return DNSAction::Action::None
;
202 std::string
TeeAction::toString() const
204 return "tee to "+d_remote
.toStringWithPort();
207 std::map
<std::string
,double> TeeAction::getStats() const
209 return {{"queries", d_queries
},
210 {"responses", d_responses
},
211 {"recv-errors", d_recverrors
},
212 {"send-errors", d_senderrors
},
213 {"noerrors", d_noerrors
},
214 {"nxdomains", d_nxdomains
},
215 {"refuseds", d_refuseds
},
216 {"servfails", d_servfails
},
217 {"other-rcode", d_otherrcode
},
218 {"tcp-drops", d_tcpdrops
}
222 void TeeAction::worker()
224 setThreadName("dnsdist/TeeWork");
227 struct dnsheader
* dh
=(struct dnsheader
*)packet
;
229 res
=waitForData(d_fd
, 0, 250000);
238 res
=recv(d_fd
, packet
, sizeof(packet
), 0);
239 if(res
<= (int)sizeof(struct dnsheader
))
244 if(dh
->rcode
== RCode::NoError
)
246 else if(dh
->rcode
== RCode::ServFail
)
248 else if(dh
->rcode
== RCode::NXDomain
)
250 else if(dh
->rcode
== RCode::Refused
)
252 else if(dh
->rcode
== RCode::FormErr
)
254 else if(dh
->rcode
== RCode::NotImp
)
259 class PoolAction
: public DNSAction
262 PoolAction(const std::string
& pool
) : d_pool(pool
) {}
263 DNSAction::Action
operator()(DNSQuestion
* dq
, std::string
* ruleresult
) const override
268 std::string
toString() const override
270 return "to pool "+d_pool
;
278 class QPSPoolAction
: public DNSAction
281 QPSPoolAction(unsigned int limit
, const std::string
& pool
) : d_qps(limit
, limit
), d_pool(pool
) {}
282 DNSAction::Action
operator()(DNSQuestion
* dq
, std::string
* ruleresult
) const override
291 std::string
toString() const override
293 return "max " +std::to_string(d_qps
.getRate())+" to pool "+d_pool
;
301 class RCodeAction
: public DNSAction
304 RCodeAction(uint8_t rcode
) : d_rcode(rcode
) {}
305 DNSAction::Action
operator()(DNSQuestion
* dq
, std::string
* ruleresult
) const override
307 dq
->dh
->rcode
= d_rcode
;
308 dq
->dh
->qr
= true; // for good measure
309 setResponseHeadersFromConfig(*dq
->dh
, d_responseConfig
);
310 return Action::HeaderModify
;
312 std::string
toString() const override
314 return "set rcode "+std::to_string(d_rcode
);
317 ResponseConfig d_responseConfig
;
322 class ERCodeAction
: public DNSAction
325 ERCodeAction(uint8_t rcode
) : d_rcode(rcode
) {}
326 DNSAction::Action
operator()(DNSQuestion
* dq
, std::string
* ruleresult
) const override
328 dq
->dh
->rcode
= (d_rcode
& 0xF);
329 dq
->ednsRCode
= ((d_rcode
& 0xFFF0) >> 4);
330 dq
->dh
->qr
= true; // for good measure
331 setResponseHeadersFromConfig(*dq
->dh
, d_responseConfig
);
332 return Action::HeaderModify
;
334 std::string
toString() const override
336 return "set ercode "+ERCode::to_s(d_rcode
);
339 ResponseConfig d_responseConfig
;
344 class TCAction
: public DNSAction
347 DNSAction::Action
operator()(DNSQuestion
* dq
, std::string
* ruleresult
) const override
349 return Action::Truncate
;
351 std::string
toString() const override
353 return "tc=1 answer";
357 DNSAction::Action
LuaAction::operator()(DNSQuestion
* dq
, std::string
* ruleresult
) const
359 std::lock_guard
<std::mutex
> lock(g_luamutex
);
361 auto ret
= d_func(dq
);
363 if (boost::optional
<std::string
> rule
= std::get
<1>(ret
)) {
367 // default to empty string
371 return (Action
)std::get
<0>(ret
);
372 } catch (std::exception
&e
) {
373 warnlog("LuaAction failed inside lua, returning ServFail: %s", e
.what());
375 warnlog("LuaAction failed inside lua, returning ServFail: [unknown exception]");
377 return DNSAction::Action::ServFail
;
380 DNSResponseAction::Action
LuaResponseAction::operator()(DNSResponse
* dr
, std::string
* ruleresult
) const
382 std::lock_guard
<std::mutex
> lock(g_luamutex
);
384 auto ret
= d_func(dr
);
386 if (boost::optional
<std::string
> rule
= std::get
<1>(ret
)) {
390 // default to empty string
394 return (Action
)std::get
<0>(ret
);
395 } catch (std::exception
&e
) {
396 warnlog("LuaResponseAction failed inside lua, returning ServFail: %s", e
.what());
398 warnlog("LuaResponseAction failed inside lua, returning ServFail: [unknown exception]");
400 return DNSResponseAction::Action::ServFail
;
403 DNSAction::Action
SpoofAction::operator()(DNSQuestion
* dq
, std::string
* ruleresult
) const
405 uint16_t qtype
= dq
->qtype
;
406 // do we even have a response?
407 if (d_cname
.empty() &&
408 d_rawResponse
.empty() &&
409 d_types
.count(qtype
) == 0) {
413 vector
<ComboAddress
> addrs
;
414 unsigned int totrdatalen
= 0;
415 uint16_t numberOfRecords
= 0;
416 if (!d_cname
.empty()) {
417 qtype
= QType::CNAME
;
418 totrdatalen
+= d_cname
.toDNSString().size();
420 } else if (!d_rawResponse
.empty()) {
421 totrdatalen
+= d_rawResponse
.size();
425 for(const auto& addr
: d_addrs
) {
426 if(qtype
!= QType::ANY
&& ((addr
.sin4
.sin_family
== AF_INET
&& qtype
!= QType::A
) ||
427 (addr
.sin4
.sin_family
== AF_INET6
&& qtype
!= QType::AAAA
))) {
430 totrdatalen
+= addr
.sin4
.sin_family
== AF_INET
? sizeof(addr
.sin4
.sin_addr
.s_addr
) : sizeof(addr
.sin6
.sin6_addr
.s6_addr
);
431 addrs
.push_back(addr
);
437 random_shuffle(addrs
.begin(), addrs
.end());
439 unsigned int consumed
=0;
440 DNSName
ignore((char*)dq
->dh
, dq
->len
, sizeof(dnsheader
), false, 0, 0, &consumed
);
442 if (dq
->size
< (sizeof(dnsheader
) + consumed
+ 4 + numberOfRecords
*12 /* recordstart */ + totrdatalen
)) {
446 bool dnssecOK
= false;
447 bool hadEDNS
= false;
448 if (g_addEDNSToSelfGeneratedResponses
&& queryHasEDNS(*dq
)) {
450 dnssecOK
= getEDNSZ(*dq
) & EDNS_HEADER_FLAG_DO
;
453 dq
->len
= sizeof(dnsheader
) + consumed
+ 4; // there goes your EDNS
454 char* dest
= ((char*)dq
->dh
) + dq
->len
;
456 dq
->dh
->qr
= true; // for good measure
457 setResponseHeadersFromConfig(*dq
->dh
, d_responseConfig
);
459 dq
->dh
->arcount
= 0; // for now, forget about your EDNS, we're marching over it
461 uint32_t ttl
= htonl(d_responseConfig
.ttl
);
462 unsigned char recordstart
[] = {0xc0, 0x0c, // compressed name
466 0, 0 }; // rdata length
467 static_assert(sizeof(recordstart
) == 12, "sizeof(recordstart) must be equal to 12, otherwise the above check is invalid");
468 memcpy(&recordstart
[6], &ttl
, sizeof(ttl
));
470 if (qtype
== QType::CNAME
) {
471 const std::string wireData
= d_cname
.toDNSString(); // Note! This doesn't do compression!
472 uint16_t rdataLen
= htons(wireData
.length());
473 qtype
= htons(qtype
);
474 memcpy(&recordstart
[2], &qtype
, sizeof(qtype
));
475 memcpy(&recordstart
[10], &rdataLen
, sizeof(rdataLen
));
477 memcpy(dest
, recordstart
, sizeof(recordstart
));
478 dest
+= sizeof(recordstart
);
479 memcpy(dest
, wireData
.c_str(), wireData
.length());
480 dq
->len
+= wireData
.length() + sizeof(recordstart
);
483 else if (!d_rawResponse
.empty()) {
484 uint16_t rdataLen
= htons(d_rawResponse
.size());
485 qtype
= htons(qtype
);
486 memcpy(&recordstart
[2], &qtype
, sizeof(qtype
));
487 memcpy(&recordstart
[10], &rdataLen
, sizeof(rdataLen
));
489 memcpy(dest
, recordstart
, sizeof(recordstart
));
490 dest
+= sizeof(recordstart
);
491 memcpy(dest
, d_rawResponse
.c_str(), d_rawResponse
.size());
492 dq
->len
+= d_rawResponse
.size() + sizeof(recordstart
);
496 for(const auto& addr
: addrs
) {
497 uint16_t rdataLen
= htons(addr
.sin4
.sin_family
== AF_INET
? sizeof(addr
.sin4
.sin_addr
.s_addr
) : sizeof(addr
.sin6
.sin6_addr
.s6_addr
));
498 qtype
= htons(addr
.sin4
.sin_family
== AF_INET
? QType::A
: QType::AAAA
);
499 memcpy(&recordstart
[2], &qtype
, sizeof(qtype
));
500 memcpy(&recordstart
[10], &rdataLen
, sizeof(rdataLen
));
502 memcpy(dest
, recordstart
, sizeof(recordstart
));
503 dest
+= sizeof(recordstart
);
506 addr
.sin4
.sin_family
== AF_INET
? (void*)&addr
.sin4
.sin_addr
.s_addr
: (void*)&addr
.sin6
.sin6_addr
.s6_addr
,
507 addr
.sin4
.sin_family
== AF_INET
? sizeof(addr
.sin4
.sin_addr
.s_addr
) : sizeof(addr
.sin6
.sin6_addr
.s6_addr
));
508 dest
+= (addr
.sin4
.sin_family
== AF_INET
? sizeof(addr
.sin4
.sin_addr
.s_addr
) : sizeof(addr
.sin6
.sin6_addr
.s6_addr
));
509 dq
->len
+= (addr
.sin4
.sin_family
== AF_INET
? sizeof(addr
.sin4
.sin_addr
.s_addr
) : sizeof(addr
.sin6
.sin6_addr
.s6_addr
)) + sizeof(recordstart
);
514 dq
->dh
->ancount
= htons(dq
->dh
->ancount
);
517 addEDNS(dq
->dh
, dq
->len
, dq
->size
, dnssecOK
, g_PayloadSizeSelfGenAnswers
, 0);
520 return Action::HeaderModify
;
523 class MacAddrAction
: public DNSAction
526 MacAddrAction(uint16_t code
) : d_code(code
)
528 DNSAction::Action
operator()(DNSQuestion
* dq
, std::string
* ruleresult
) const override
533 std::string mac
= getMACAddress(*dq
->remote
);
537 std::string optRData
;
538 generateEDNSOption(d_code
, mac
, optRData
);
541 generateOptRR(optRData
, res
, g_EdnsUDPPayloadSize
, 0, false);
543 if ((dq
->size
- dq
->len
) < res
.length())
546 dq
->dh
->arcount
= htons(1);
547 char* dest
= ((char*)dq
->dh
) + dq
->len
;
548 memcpy(dest
, res
.c_str(), res
.length());
549 dq
->len
+= res
.length();
553 std::string
toString() const override
555 return "add EDNS MAC (code="+std::to_string(d_code
)+")";
561 class NoRecurseAction
: public DNSAction
564 DNSAction::Action
operator()(DNSQuestion
* dq
, std::string
* ruleresult
) const override
569 std::string
toString() const override
575 class LogAction
: public DNSAction
, public boost::noncopyable
578 LogAction(): d_fp(nullptr, fclose
)
582 LogAction(const std::string
& str
, bool binary
=true, bool append
=false, bool buffered
=true, bool verboseOnly
=true, bool includeTimestamp
=false): d_fname(str
), d_binary(binary
), d_verboseOnly(verboseOnly
), d_includeTimestamp(includeTimestamp
)
587 d_fp
= std::unique_ptr
<FILE, int(*)(FILE*)>(fopen(str
.c_str(), "a+"), fclose
);
589 d_fp
= std::unique_ptr
<FILE, int(*)(FILE*)>(fopen(str
.c_str(), "w"), fclose
);
591 throw std::runtime_error("Unable to open file '"+str
+"' for logging: "+stringerror());
593 setbuf(d_fp
.get(), 0);
596 DNSAction::Action
operator()(DNSQuestion
* dq
, std::string
* ruleresult
) const override
599 if (!d_verboseOnly
|| g_verbose
) {
600 if (d_includeTimestamp
) {
601 infolog("[%u.%u] Packet from %s for %s %s with id %d", static_cast<unsigned long long>(dq
->queryTime
->tv_sec
), static_cast<unsigned long>(dq
->queryTime
->tv_nsec
), dq
->remote
->toStringWithPort(), dq
->qname
->toString(), QType(dq
->qtype
).getName(), dq
->dh
->id
);
604 infolog("Packet from %s for %s %s with id %d", dq
->remote
->toStringWithPort(), dq
->qname
->toString(), QType(dq
->qtype
).getName(), dq
->dh
->id
);
610 std::string out
= dq
->qname
->toDNSString();
611 if (d_includeTimestamp
) {
612 uint64_t tv_sec
= static_cast<uint64_t>(dq
->queryTime
->tv_sec
);
613 uint32_t tv_nsec
= static_cast<uint32_t>(dq
->queryTime
->tv_nsec
);
614 fwrite(&tv_sec
, sizeof(tv_sec
), 1, d_fp
.get());
615 fwrite(&tv_nsec
, sizeof(tv_nsec
), 1, d_fp
.get());
617 uint16_t id
= dq
->dh
->id
;
618 fwrite(&id
, sizeof(id
), 1, d_fp
.get());
619 fwrite(out
.c_str(), 1, out
.size(), d_fp
.get());
620 fwrite(&dq
->qtype
, sizeof(dq
->qtype
), 1, d_fp
.get());
621 fwrite(&dq
->remote
->sin4
.sin_family
, sizeof(dq
->remote
->sin4
.sin_family
), 1, d_fp
.get());
622 if (dq
->remote
->sin4
.sin_family
== AF_INET
) {
623 fwrite(&dq
->remote
->sin4
.sin_addr
.s_addr
, sizeof(dq
->remote
->sin4
.sin_addr
.s_addr
), 1, d_fp
.get());
625 else if (dq
->remote
->sin4
.sin_family
== AF_INET6
) {
626 fwrite(&dq
->remote
->sin6
.sin6_addr
.s6_addr
, sizeof(dq
->remote
->sin6
.sin6_addr
.s6_addr
), 1, d_fp
.get());
628 fwrite(&dq
->remote
->sin4
.sin_port
, sizeof(dq
->remote
->sin4
.sin_port
), 1, d_fp
.get());
631 if (d_includeTimestamp
) {
632 fprintf(d_fp
.get(), "[%llu.%lu] Packet from %s for %s %s with id %d\n", static_cast<unsigned long long>(dq
->queryTime
->tv_sec
), static_cast<unsigned long>(dq
->queryTime
->tv_nsec
), dq
->remote
->toStringWithPort().c_str(), dq
->qname
->toString().c_str(), QType(dq
->qtype
).getName().c_str(), dq
->dh
->id
);
635 fprintf(d_fp
.get(), "Packet from %s for %s %s with id %d\n", dq
->remote
->toStringWithPort().c_str(), dq
->qname
->toString().c_str(), QType(dq
->qtype
).getName().c_str(), dq
->dh
->id
);
642 std::string
toString() const override
644 if (!d_fname
.empty()) {
645 return "log to " + d_fname
;
651 std::unique_ptr
<FILE, int(*)(FILE*)> d_fp
{nullptr, fclose
};
653 bool d_verboseOnly
{true};
654 bool d_includeTimestamp
{false};
657 class LogResponseAction
: public DNSResponseAction
, public boost::noncopyable
660 LogResponseAction(): d_fp(nullptr, fclose
)
664 LogResponseAction(const std::string
& str
, bool append
=false, bool buffered
=true, bool verboseOnly
=true, bool includeTimestamp
=false): d_fname(str
), d_verboseOnly(verboseOnly
), d_includeTimestamp(includeTimestamp
)
669 d_fp
= std::unique_ptr
<FILE, int(*)(FILE*)>(fopen(str
.c_str(), "a+"), fclose
);
671 d_fp
= std::unique_ptr
<FILE, int(*)(FILE*)>(fopen(str
.c_str(), "w"), fclose
);
673 throw std::runtime_error("Unable to open file '"+str
+"' for logging: "+stringerror());
675 setbuf(d_fp
.get(), 0);
678 DNSResponseAction::Action
operator()(DNSResponse
* dr
, std::string
* ruleresult
) const override
681 if (!d_verboseOnly
|| g_verbose
) {
682 if (d_includeTimestamp
) {
683 infolog("[%u.%u] Answer to %s for %s %s (%s) with id %d", static_cast<unsigned long long>(dr
->queryTime
->tv_sec
), static_cast<unsigned long>(dr
->queryTime
->tv_nsec
), dr
->remote
->toStringWithPort(), dr
->qname
->toString(), QType(dr
->qtype
).getName(), RCode::to_s(dr
->dh
->rcode
), dr
->dh
->id
);
686 infolog("Answer to %s for %s %s (%s) with id %d", dr
->remote
->toStringWithPort(), dr
->qname
->toString(), QType(dr
->qtype
).getName(), RCode::to_s(dr
->dh
->rcode
), dr
->dh
->id
);
691 if (d_includeTimestamp
) {
692 fprintf(d_fp
.get(), "[%llu.%lu] Answer to %s for %s %s (%s) with id %d\n", static_cast<unsigned long long>(dr
->queryTime
->tv_sec
), static_cast<unsigned long>(dr
->queryTime
->tv_nsec
), dr
->remote
->toStringWithPort().c_str(), dr
->qname
->toString().c_str(), QType(dr
->qtype
).getName().c_str(), RCode::to_s(dr
->dh
->rcode
).c_str(), dr
->dh
->id
);
695 fprintf(d_fp
.get(), "Answer to %s for %s %s (%s) with id %d\n", dr
->remote
->toStringWithPort().c_str(), dr
->qname
->toString().c_str(), QType(dr
->qtype
).getName().c_str(), RCode::to_s(dr
->dh
->rcode
).c_str(), dr
->dh
->id
);
701 std::string
toString() const override
703 if (!d_fname
.empty()) {
704 return "log to " + d_fname
;
710 std::unique_ptr
<FILE, int(*)(FILE*)> d_fp
{nullptr, fclose
};
711 bool d_verboseOnly
{true};
712 bool d_includeTimestamp
{false};
716 class DisableValidationAction
: public DNSAction
719 DNSAction::Action
operator()(DNSQuestion
* dq
, std::string
* ruleresult
) const override
724 std::string
toString() const override
730 class SkipCacheAction
: public DNSAction
733 DNSAction::Action
operator()(DNSQuestion
* dq
, std::string
* ruleresult
) const override
735 dq
->skipCache
= true;
738 std::string
toString() const override
744 class TempFailureCacheTTLAction
: public DNSAction
747 TempFailureCacheTTLAction(uint32_t ttl
) : d_ttl(ttl
)
749 TempFailureCacheTTLAction::Action
operator()(DNSQuestion
* dq
, std::string
* ruleresult
) const override
751 dq
->tempFailureTTL
= d_ttl
;
754 std::string
toString() const override
756 return "set tempfailure cache ttl to "+std::to_string(d_ttl
);
762 class ECSPrefixLengthAction
: public DNSAction
765 ECSPrefixLengthAction(uint16_t v4Length
, uint16_t v6Length
) : d_v4PrefixLength(v4Length
), d_v6PrefixLength(v6Length
)
768 DNSAction::Action
operator()(DNSQuestion
* dq
, std::string
* ruleresult
) const override
770 dq
->ecsPrefixLength
= dq
->remote
->sin4
.sin_family
== AF_INET
? d_v4PrefixLength
: d_v6PrefixLength
;
773 std::string
toString() const override
775 return "set ECS prefix length to " + std::to_string(d_v4PrefixLength
) + "/" + std::to_string(d_v6PrefixLength
);
778 uint16_t d_v4PrefixLength
;
779 uint16_t d_v6PrefixLength
;
782 class ECSOverrideAction
: public DNSAction
785 ECSOverrideAction(bool ecsOverride
) : d_ecsOverride(ecsOverride
)
788 DNSAction::Action
operator()(DNSQuestion
* dq
, std::string
* ruleresult
) const override
790 dq
->ecsOverride
= d_ecsOverride
;
793 std::string
toString() const override
795 return "set ECS override to " + std::to_string(d_ecsOverride
);
802 class DisableECSAction
: public DNSAction
805 DNSAction::Action
operator()(DNSQuestion
* dq
, std::string
* ruleresult
) const override
810 std::string
toString() const override
812 return "disable ECS";
816 class SetECSAction
: public DNSAction
819 SetECSAction(const Netmask
& v4
): d_v4(v4
), d_hasV6(false)
823 SetECSAction(const Netmask
& v4
, const Netmask
& v6
): d_v4(v4
), d_v6(v6
), d_hasV6(true)
827 DNSAction::Action
operator()(DNSQuestion
* dq
, std::string
* ruleresult
) const override
832 dq
->ecs
= dq
->remote
->isIPv4() ? d_v4
: d_v6
;
841 std::string
toString() const override
843 std::string result
= "set ECS to " + d_v4
.toString();
845 result
+= " / " + d_v6
.toString();
857 class DnstapLogAction
: public DNSAction
, public boost::noncopyable
860 DnstapLogAction(const std::string
& identity
, std::shared_ptr
<RemoteLoggerInterface
>& logger
, boost::optional
<std::function
<void(DNSQuestion
*, DnstapMessage
*)> > alterFunc
): d_identity(identity
), d_logger(logger
), d_alterFunc(alterFunc
)
863 DNSAction::Action
operator()(DNSQuestion
* dq
, std::string
* ruleresult
) const override
866 DnstapMessage
message(d_identity
, dq
->remote
, dq
->local
, dq
->tcp
, reinterpret_cast<const char*>(dq
->dh
), dq
->len
, dq
->queryTime
, nullptr);
869 std::lock_guard
<std::mutex
> lock(g_luamutex
);
870 (*d_alterFunc
)(dq
, &message
);
874 message
.serialize(data
);
875 d_logger
->queueData(data
);
876 #endif /* HAVE_PROTOBUF */
879 std::string
toString() const override
881 return "remote log as dnstap to " + (d_logger
? d_logger
->toString() : "");
884 std::string d_identity
;
885 std::shared_ptr
<RemoteLoggerInterface
> d_logger
;
886 boost::optional
<std::function
<void(DNSQuestion
*, DnstapMessage
*)> > d_alterFunc
;
889 class RemoteLogAction
: public DNSAction
, public boost::noncopyable
892 RemoteLogAction(std::shared_ptr
<RemoteLoggerInterface
>& logger
, boost::optional
<std::function
<void(DNSQuestion
*, DNSDistProtoBufMessage
*)> > alterFunc
, const std::string
& serverID
, const std::string
& ipEncryptKey
): d_logger(logger
), d_alterFunc(alterFunc
), d_serverID(serverID
), d_ipEncryptKey(ipEncryptKey
)
895 DNSAction::Action
operator()(DNSQuestion
* dq
, std::string
* ruleresult
) const override
899 dq
->uniqueId
= getUniqueID();
902 DNSDistProtoBufMessage
message(*dq
);
903 if (!d_serverID
.empty()) {
904 message
.setServerIdentity(d_serverID
);
908 if (!d_ipEncryptKey
.empty())
910 message
.setRequestor(encryptCA(*dq
->remote
, d_ipEncryptKey
));
912 #endif /* HAVE_LIBCRYPTO */
915 std::lock_guard
<std::mutex
> lock(g_luamutex
);
916 (*d_alterFunc
)(dq
, &message
);
920 message
.serialize(data
);
921 d_logger
->queueData(data
);
922 #endif /* HAVE_PROTOBUF */
925 std::string
toString() const override
927 return "remote log to " + (d_logger
? d_logger
->toString() : "");
930 std::shared_ptr
<RemoteLoggerInterface
> d_logger
;
931 boost::optional
<std::function
<void(DNSQuestion
*, DNSDistProtoBufMessage
*)> > d_alterFunc
;
932 std::string d_serverID
;
933 std::string d_ipEncryptKey
;
936 class SNMPTrapAction
: public DNSAction
939 SNMPTrapAction(const std::string
& reason
): d_reason(reason
)
942 DNSAction::Action
operator()(DNSQuestion
* dq
, std::string
* ruleresult
) const override
944 if (g_snmpAgent
&& g_snmpTrapsEnabled
) {
945 g_snmpAgent
->sendDNSTrap(*dq
, d_reason
);
950 std::string
toString() const override
952 return "send SNMP trap";
955 std::string d_reason
;
958 class TagAction
: public DNSAction
961 TagAction(const std::string
& tag
, const std::string
& value
): d_tag(tag
), d_value(value
)
964 DNSAction::Action
operator()(DNSQuestion
* dq
, std::string
* ruleresult
) const override
967 dq
->qTag
= std::make_shared
<QTag
>();
970 dq
->qTag
->insert({d_tag
, d_value
});
974 std::string
toString() const override
976 return "set tag '" + d_tag
+ "' to value '" + d_value
+ "'";
983 class DnstapLogResponseAction
: public DNSResponseAction
, public boost::noncopyable
986 DnstapLogResponseAction(const std::string
& identity
, std::shared_ptr
<RemoteLoggerInterface
>& logger
, boost::optional
<std::function
<void(DNSResponse
*, DnstapMessage
*)> > alterFunc
): d_identity(identity
), d_logger(logger
), d_alterFunc(alterFunc
)
989 DNSResponseAction::Action
operator()(DNSResponse
* dr
, std::string
* ruleresult
) const override
994 DnstapMessage
message(d_identity
, dr
->remote
, dr
->local
, dr
->tcp
, reinterpret_cast<const char*>(dr
->dh
), dr
->len
, dr
->queryTime
, &now
);
997 std::lock_guard
<std::mutex
> lock(g_luamutex
);
998 (*d_alterFunc
)(dr
, &message
);
1002 message
.serialize(data
);
1003 d_logger
->queueData(data
);
1004 #endif /* HAVE_PROTOBUF */
1005 return Action::None
;
1007 std::string
toString() const override
1009 return "log response as dnstap to " + (d_logger
? d_logger
->toString() : "");
1012 std::string d_identity
;
1013 std::shared_ptr
<RemoteLoggerInterface
> d_logger
;
1014 boost::optional
<std::function
<void(DNSResponse
*, DnstapMessage
*)> > d_alterFunc
;
1017 class RemoteLogResponseAction
: public DNSResponseAction
, public boost::noncopyable
1020 RemoteLogResponseAction(std::shared_ptr
<RemoteLoggerInterface
>& logger
, boost::optional
<std::function
<void(DNSResponse
*, DNSDistProtoBufMessage
*)> > alterFunc
, const std::string
& serverID
, const std::string
& ipEncryptKey
, bool includeCNAME
): d_logger(logger
), d_alterFunc(alterFunc
), d_serverID(serverID
), d_ipEncryptKey(ipEncryptKey
), d_includeCNAME(includeCNAME
)
1023 DNSResponseAction::Action
operator()(DNSResponse
* dr
, std::string
* ruleresult
) const override
1025 #ifdef HAVE_PROTOBUF
1026 if (!dr
->uniqueId
) {
1027 dr
->uniqueId
= getUniqueID();
1030 DNSDistProtoBufMessage
message(*dr
, d_includeCNAME
);
1031 if (!d_serverID
.empty()) {
1032 message
.setServerIdentity(d_serverID
);
1036 if (!d_ipEncryptKey
.empty())
1038 message
.setRequestor(encryptCA(*dr
->remote
, d_ipEncryptKey
));
1040 #endif /* HAVE_LIBCRYPTO */
1043 std::lock_guard
<std::mutex
> lock(g_luamutex
);
1044 (*d_alterFunc
)(dr
, &message
);
1048 message
.serialize(data
);
1049 d_logger
->queueData(data
);
1050 #endif /* HAVE_PROTOBUF */
1051 return Action::None
;
1053 std::string
toString() const override
1055 return "remote log response to " + (d_logger
? d_logger
->toString() : "");
1058 std::shared_ptr
<RemoteLoggerInterface
> d_logger
;
1059 boost::optional
<std::function
<void(DNSResponse
*, DNSDistProtoBufMessage
*)> > d_alterFunc
;
1060 std::string d_serverID
;
1061 std::string d_ipEncryptKey
;
1062 bool d_includeCNAME
;
1065 class DropResponseAction
: public DNSResponseAction
1068 DNSResponseAction::Action
operator()(DNSResponse
* dr
, std::string
* ruleresult
) const override
1070 return Action::Drop
;
1072 std::string
toString() const override
1078 class AllowResponseAction
: public DNSResponseAction
1081 DNSResponseAction::Action
operator()(DNSResponse
* dr
, std::string
* ruleresult
) const override
1083 return Action::Allow
;
1085 std::string
toString() const override
1091 class DelayResponseAction
: public DNSResponseAction
1094 DelayResponseAction(int msec
) : d_msec(msec
)
1096 DNSResponseAction::Action
operator()(DNSResponse
* dr
, std::string
* ruleresult
) const override
1098 *ruleresult
=std::to_string(d_msec
);
1099 return Action::Delay
;
1101 std::string
toString() const override
1103 return "delay by "+std::to_string(d_msec
)+ " msec";
1109 class SNMPTrapResponseAction
: public DNSResponseAction
1112 SNMPTrapResponseAction(const std::string
& reason
): d_reason(reason
)
1115 DNSResponseAction::Action
operator()(DNSResponse
* dr
, std::string
* ruleresult
) const override
1117 if (g_snmpAgent
&& g_snmpTrapsEnabled
) {
1118 g_snmpAgent
->sendDNSTrap(*dr
, d_reason
);
1121 return Action::None
;
1123 std::string
toString() const override
1125 return "send SNMP trap";
1128 std::string d_reason
;
1131 class TagResponseAction
: public DNSResponseAction
1134 TagResponseAction(const std::string
& tag
, const std::string
& value
): d_tag(tag
), d_value(value
)
1137 DNSResponseAction::Action
operator()(DNSResponse
* dr
, std::string
* ruleresult
) const override
1140 dr
->qTag
= std::make_shared
<QTag
>();
1143 dr
->qTag
->insert({d_tag
, d_value
});
1145 return Action::None
;
1147 std::string
toString() const override
1149 return "set tag '" + d_tag
+ "' to value '" + d_value
+ "'";
1153 std::string d_value
;
1156 class ContinueAction
: public DNSAction
1159 ContinueAction(std::shared_ptr
<DNSAction
>& action
): d_action(action
)
1163 DNSAction::Action
operator()(DNSQuestion
* dq
, std::string
* ruleresult
) const override
1166 /* call the action */
1167 auto action
= (*d_action
)(dq
, ruleresult
);
1169 /* apply the changes if needed (pool selection, flags, etc */
1170 processRulesResult(action
, *dq
, *ruleresult
, drop
);
1173 /* but ignore the resulting action no matter what */
1174 return Action::None
;
1177 std::string
toString() const override
1180 return "continue after: " + (d_action
? d_action
->toString() : "");
1188 std::shared_ptr
<DNSAction
> d_action
;
1191 #ifdef HAVE_DNS_OVER_HTTPS
1192 class HTTPStatusAction
: public DNSAction
1195 HTTPStatusAction(int code
, const std::string
& body
, const std::string
& contentType
): d_body(body
), d_contentType(contentType
), d_code(code
)
1199 DNSAction::Action
operator()(DNSQuestion
* dq
, std::string
* ruleresult
) const override
1202 return Action::None
;
1205 dq
->du
->setHTTPResponse(d_code
, d_body
, d_contentType
);
1206 dq
->dh
->qr
= true; // for good measure
1207 setResponseHeadersFromConfig(*dq
->dh
, d_responseConfig
);
1208 return Action::HeaderModify
;
1211 std::string
toString() const override
1213 return "return an HTTP status of " + std::to_string(d_code
);
1216 ResponseConfig d_responseConfig
;
1219 std::string d_contentType
;
1222 #endif /* HAVE_DNS_OVER_HTTPS */
1224 class KeyValueStoreLookupAction
: public DNSAction
1227 KeyValueStoreLookupAction(std::shared_ptr
<KeyValueStore
>& kvs
, std::shared_ptr
<KeyValueLookupKey
>& lookupKey
, const std::string
& destinationTag
): d_kvs(kvs
), d_key(lookupKey
), d_tag(destinationTag
)
1231 DNSAction::Action
operator()(DNSQuestion
* dq
, std::string
* ruleresult
) const override
1233 std::vector
<std::string
> keys
= d_key
->getKeys(*dq
);
1235 for (const auto& key
: keys
) {
1236 if (d_kvs
->getValue(key
, result
) == true) {
1242 dq
->qTag
= std::make_shared
<QTag
>();
1245 dq
->qTag
->insert({d_tag
, std::move(result
)});
1247 return Action::None
;
1250 std::string
toString() const override
1252 return "lookup key-value store based on '" + d_key
->toString() + "' and set the result in tag '" + d_tag
+ "'";
1256 std::shared_ptr
<KeyValueStore
> d_kvs
;
1257 std::shared_ptr
<KeyValueLookupKey
> d_key
;
1261 template<typename T
, typename ActionT
>
1262 static void addAction(GlobalStateHolder
<vector
<T
> > *someRulActions
, const luadnsrule_t
& var
, const std::shared_ptr
<ActionT
>& action
, boost::optional
<luaruleparams_t
>& params
) {
1265 boost::uuids::uuid uuid
;
1266 uint64_t creationOrder
;
1267 parseRuleParams(params
, uuid
, creationOrder
);
1269 auto rule
=makeRule(var
);
1270 someRulActions
->modify([&rule
, &action
, &uuid
, creationOrder
](vector
<T
>& rulactions
){
1271 rulactions
.push_back({std::move(rule
), std::move(action
), std::move(uuid
), creationOrder
});
1275 typedef std::unordered_map
<std::string
, boost::variant
<bool, uint32_t> > responseParams_t
;
1277 static void parseResponseConfig(boost::optional
<responseParams_t
> vars
, ResponseConfig
& config
)
1280 if (vars
->count("ttl")) {
1281 config
.ttl
= boost::get
<uint32_t>((*vars
)["ttl"]);
1283 if (vars
->count("aa")) {
1284 config
.setAA
= boost::get
<bool>((*vars
)["aa"]);
1286 if (vars
->count("ad")) {
1287 config
.setAD
= boost::get
<bool>((*vars
)["ad"]);
1289 if (vars
->count("ra")) {
1290 config
.setRA
= boost::get
<bool>((*vars
)["ra"]);
1295 void setResponseHeadersFromConfig(dnsheader
& dh
, const ResponseConfig
& config
)
1298 dh
.aa
= *config
.setAA
;
1301 dh
.ad
= *config
.setAD
;
1307 dh
.ra
= *config
.setRA
;
1310 dh
.ra
= dh
.rd
; // for good measure
1314 void setupLuaActions()
1316 g_lua
.writeFunction("newRuleAction", [](luadnsrule_t dnsrule
, std::shared_ptr
<DNSAction
> action
, boost::optional
<luaruleparams_t
> params
) {
1317 boost::uuids::uuid uuid
;
1318 uint64_t creationOrder
;
1319 parseRuleParams(params
, uuid
, creationOrder
);
1321 auto rule
=makeRule(dnsrule
);
1322 DNSDistRuleAction
ra({std::move(rule
), action
, uuid
, creationOrder
});
1323 return std::make_shared
<DNSDistRuleAction
>(ra
);
1326 g_lua
.writeFunction("addAction", [](luadnsrule_t var
, boost::variant
<std::shared_ptr
<DNSAction
>, std::shared_ptr
<DNSResponseAction
> > era
, boost::optional
<luaruleparams_t
> params
) {
1327 if (era
.type() != typeid(std::shared_ptr
<DNSAction
>)) {
1328 throw std::runtime_error("addAction() can only be called with query-related actions, not response-related ones. Are you looking for addResponseAction()?");
1331 addAction(&g_rulactions
, var
, boost::get
<std::shared_ptr
<DNSAction
> >(era
), params
);
1334 g_lua
.writeFunction("addResponseAction", [](luadnsrule_t var
, boost::variant
<std::shared_ptr
<DNSAction
>, std::shared_ptr
<DNSResponseAction
> > era
, boost::optional
<luaruleparams_t
> params
) {
1335 if (era
.type() != typeid(std::shared_ptr
<DNSResponseAction
>)) {
1336 throw std::runtime_error("addResponseAction() can only be called with response-related actions, not query-related ones. Are you looking for addAction()?");
1339 addAction(&g_resprulactions
, var
, boost::get
<std::shared_ptr
<DNSResponseAction
> >(era
), params
);
1342 g_lua
.writeFunction("addCacheHitResponseAction", [](luadnsrule_t var
, boost::variant
<std::shared_ptr
<DNSAction
>, std::shared_ptr
<DNSResponseAction
>> era
, boost::optional
<luaruleparams_t
> params
) {
1343 if (era
.type() != typeid(std::shared_ptr
<DNSResponseAction
>)) {
1344 throw std::runtime_error("addCacheHitResponseAction() can only be called with response-related actions, not query-related ones. Are you looking for addAction()?");
1347 addAction(&g_cachehitresprulactions
, var
, boost::get
<std::shared_ptr
<DNSResponseAction
> >(era
), params
);
1350 g_lua
.writeFunction("addSelfAnsweredResponseAction", [](luadnsrule_t var
, boost::variant
<std::shared_ptr
<DNSAction
>, std::shared_ptr
<DNSResponseAction
>> era
, boost::optional
<luaruleparams_t
> params
) {
1351 if (era
.type() != typeid(std::shared_ptr
<DNSResponseAction
>)) {
1352 throw std::runtime_error("addSelfAnsweredResponseAction() can only be called with response-related actions, not query-related ones. Are you looking for addAction()?");
1355 addAction(&g_selfansweredresprulactions
, var
, boost::get
<std::shared_ptr
<DNSResponseAction
> >(era
), params
);
1358 g_lua
.registerFunction
<void(DNSAction::*)()>("printStats", [](const DNSAction
& ta
) {
1359 setLuaNoSideEffect();
1360 auto stats
= ta
.getStats();
1361 for(const auto& s
: stats
) {
1362 g_outputBuffer
+=s
.first
+"\t";
1363 if((uint64_t)s
.second
== s
.second
)
1364 g_outputBuffer
+= std::to_string((uint64_t)s
.second
)+"\n";
1366 g_outputBuffer
+= std::to_string(s
.second
)+"\n";
1370 g_lua
.writeFunction("getAction", [](unsigned int num
) {
1371 setLuaNoSideEffect();
1372 boost::optional
<std::shared_ptr
<DNSAction
>> ret
;
1373 auto rulactions
= g_rulactions
.getCopy();
1374 if(num
< rulactions
.size())
1375 ret
=rulactions
[num
].d_action
;
1379 g_lua
.registerFunction("getStats", &DNSAction::getStats
);
1381 g_lua
.writeFunction("LuaAction", [](LuaAction::func_t func
) {
1383 return std::shared_ptr
<DNSAction
>(new LuaAction(func
));
1386 g_lua
.writeFunction("NoRecurseAction", []() {
1387 return std::shared_ptr
<DNSAction
>(new NoRecurseAction
);
1390 g_lua
.writeFunction("MacAddrAction", [](int code
) {
1391 return std::shared_ptr
<DNSAction
>(new MacAddrAction(code
));
1394 g_lua
.writeFunction("PoolAction", [](const std::string
& a
) {
1395 return std::shared_ptr
<DNSAction
>(new PoolAction(a
));
1398 g_lua
.writeFunction("QPSAction", [](int limit
) {
1399 return std::shared_ptr
<DNSAction
>(new QPSAction(limit
));
1402 g_lua
.writeFunction("QPSPoolAction", [](int limit
, const std::string
& a
) {
1403 return std::shared_ptr
<DNSAction
>(new QPSPoolAction(limit
, a
));
1406 g_lua
.writeFunction("SpoofAction", [](boost::variant
<std::string
,vector
<pair
<int, std::string
>>> inp
, boost::optional
<std::string
> b
, boost::optional
<responseParams_t
> vars
) {
1407 vector
<ComboAddress
> addrs
;
1408 if(auto s
= boost::get
<std::string
>(&inp
))
1409 addrs
.push_back(ComboAddress(*s
));
1411 const auto& v
= boost::get
<vector
<pair
<int,std::string
>>>(inp
);
1412 for(const auto& a
: v
)
1413 addrs
.push_back(ComboAddress(a
.second
));
1416 addrs
.push_back(ComboAddress(*b
));
1419 auto ret
= std::shared_ptr
<DNSAction
>(new SpoofAction(addrs
));
1420 auto sa
= std::dynamic_pointer_cast
<SpoofAction
>(ret
);
1421 parseResponseConfig(vars
, sa
->d_responseConfig
);
1425 g_lua
.writeFunction("SpoofCNAMEAction", [](const std::string
& a
, boost::optional
<responseParams_t
> vars
) {
1426 auto ret
= std::shared_ptr
<DNSAction
>(new SpoofAction(DNSName(a
)));
1427 auto sa
= std::dynamic_pointer_cast
<SpoofAction
>(ret
);
1428 parseResponseConfig(vars
, sa
->d_responseConfig
);
1432 g_lua
.writeFunction("SpoofRawAction", [](const std::string
& raw
, boost::optional
<responseParams_t
> vars
) {
1433 auto ret
= std::shared_ptr
<DNSAction
>(new SpoofAction(raw
));
1434 auto sa
= std::dynamic_pointer_cast
<SpoofAction
>(ret
);
1435 parseResponseConfig(vars
, sa
->d_responseConfig
);
1439 g_lua
.writeFunction("DropAction", []() {
1440 return std::shared_ptr
<DNSAction
>(new DropAction
);
1443 g_lua
.writeFunction("AllowAction", []() {
1444 return std::shared_ptr
<DNSAction
>(new AllowAction
);
1447 g_lua
.writeFunction("NoneAction", []() {
1448 return std::shared_ptr
<DNSAction
>(new NoneAction
);
1451 g_lua
.writeFunction("DelayAction", [](int msec
) {
1452 return std::shared_ptr
<DNSAction
>(new DelayAction(msec
));
1455 g_lua
.writeFunction("TCAction", []() {
1456 return std::shared_ptr
<DNSAction
>(new TCAction
);
1459 g_lua
.writeFunction("DisableValidationAction", []() {
1460 return std::shared_ptr
<DNSAction
>(new DisableValidationAction
);
1463 g_lua
.writeFunction("LogAction", [](boost::optional
<std::string
> fname
, boost::optional
<bool> binary
, boost::optional
<bool> append
, boost::optional
<bool> buffered
, boost::optional
<bool> verboseOnly
, boost::optional
<bool> includeTimestamp
) {
1464 return std::shared_ptr
<DNSAction
>(new LogAction(fname
? *fname
: "", binary
? *binary
: true, append
? *append
: false, buffered
? *buffered
: false, verboseOnly
? *verboseOnly
: true, includeTimestamp
? *includeTimestamp
: false));
1467 g_lua
.writeFunction("LogResponseAction", [](boost::optional
<std::string
> fname
, boost::optional
<bool> append
, boost::optional
<bool> buffered
, boost::optional
<bool> verboseOnly
, boost::optional
<bool> includeTimestamp
) {
1468 return std::shared_ptr
<DNSResponseAction
>(new LogResponseAction(fname
? *fname
: "", append
? *append
: false, buffered
? *buffered
: false, verboseOnly
? *verboseOnly
: true, includeTimestamp
? *includeTimestamp
: false));
1471 g_lua
.writeFunction("RCodeAction", [](uint8_t rcode
, boost::optional
<responseParams_t
> vars
) {
1472 auto ret
= std::shared_ptr
<DNSAction
>(new RCodeAction(rcode
));
1473 auto rca
= std::dynamic_pointer_cast
<RCodeAction
>(ret
);
1474 parseResponseConfig(vars
, rca
->d_responseConfig
);
1478 g_lua
.writeFunction("ERCodeAction", [](uint8_t rcode
, boost::optional
<responseParams_t
> vars
) {
1479 auto ret
= std::shared_ptr
<DNSAction
>(new ERCodeAction(rcode
));
1480 auto erca
= std::dynamic_pointer_cast
<ERCodeAction
>(ret
);
1481 parseResponseConfig(vars
, erca
->d_responseConfig
);
1485 g_lua
.writeFunction("SkipCacheAction", []() {
1486 return std::shared_ptr
<DNSAction
>(new SkipCacheAction
);
1489 g_lua
.writeFunction("TempFailureCacheTTLAction", [](int maxTTL
) {
1490 return std::shared_ptr
<DNSAction
>(new TempFailureCacheTTLAction(maxTTL
));
1493 g_lua
.writeFunction("DropResponseAction", []() {
1494 return std::shared_ptr
<DNSResponseAction
>(new DropResponseAction
);
1497 g_lua
.writeFunction("AllowResponseAction", []() {
1498 return std::shared_ptr
<DNSResponseAction
>(new AllowResponseAction
);
1501 g_lua
.writeFunction("DelayResponseAction", [](int msec
) {
1502 return std::shared_ptr
<DNSResponseAction
>(new DelayResponseAction(msec
));
1505 g_lua
.writeFunction("LuaResponseAction", [](LuaResponseAction::func_t func
) {
1507 return std::shared_ptr
<DNSResponseAction
>(new LuaResponseAction(func
));
1510 g_lua
.writeFunction("RemoteLogAction", [](std::shared_ptr
<RemoteLoggerInterface
> logger
, boost::optional
<std::function
<void(DNSQuestion
*, DNSDistProtoBufMessage
*)> > alterFunc
, boost::optional
<std::unordered_map
<std::string
, std::string
>> vars
) {
1512 // avoids potentially-evaluated-expression warning with clang.
1513 RemoteLoggerInterface
& rl
= *logger
.get();
1514 if (typeid(rl
) != typeid(RemoteLogger
)) {
1515 // We could let the user do what he wants, but wrapping PowerDNS Protobuf inside a FrameStream tagged as dnstap is logically wrong.
1516 throw std::runtime_error(std::string("RemoteLogAction only takes RemoteLogger. For other types, please look at DnstapLogAction."));
1520 std::string serverID
;
1521 std::string ipEncryptKey
;
1523 if (vars
->count("serverID")) {
1524 serverID
= boost::get
<std::string
>((*vars
)["serverID"]);
1526 if (vars
->count("ipEncryptKey")) {
1527 ipEncryptKey
= boost::get
<std::string
>((*vars
)["ipEncryptKey"]);
1531 #ifdef HAVE_PROTOBUF
1532 return std::shared_ptr
<DNSAction
>(new RemoteLogAction(logger
, alterFunc
, serverID
, ipEncryptKey
));
1534 throw std::runtime_error("Protobuf support is required to use RemoteLogAction");
1538 g_lua
.writeFunction("RemoteLogResponseAction", [](std::shared_ptr
<RemoteLoggerInterface
> logger
, boost::optional
<std::function
<void(DNSResponse
*, DNSDistProtoBufMessage
*)> > alterFunc
, boost::optional
<bool> includeCNAME
, boost::optional
<std::unordered_map
<std::string
, std::string
>> vars
) {
1540 // avoids potentially-evaluated-expression warning with clang.
1541 RemoteLoggerInterface
& rl
= *logger
.get();
1542 if (typeid(rl
) != typeid(RemoteLogger
)) {
1543 // We could let the user do what he wants, but wrapping PowerDNS Protobuf inside a FrameStream tagged as dnstap is logically wrong.
1544 throw std::runtime_error("RemoteLogResponseAction only takes RemoteLogger. For other types, please look at DnstapLogResponseAction.");
1548 std::string serverID
;
1549 std::string ipEncryptKey
;
1551 if (vars
->count("serverID")) {
1552 serverID
= boost::get
<std::string
>((*vars
)["serverID"]);
1554 if (vars
->count("ipEncryptKey")) {
1555 ipEncryptKey
= boost::get
<std::string
>((*vars
)["ipEncryptKey"]);
1559 #ifdef HAVE_PROTOBUF
1560 return std::shared_ptr
<DNSResponseAction
>(new RemoteLogResponseAction(logger
, alterFunc
, serverID
, ipEncryptKey
, includeCNAME
? *includeCNAME
: false));
1562 throw std::runtime_error("Protobuf support is required to use RemoteLogResponseAction");
1566 g_lua
.writeFunction("DnstapLogAction", [](const std::string
& identity
, std::shared_ptr
<RemoteLoggerInterface
> logger
, boost::optional
<std::function
<void(DNSQuestion
*, DnstapMessage
*)> > alterFunc
) {
1567 #ifdef HAVE_PROTOBUF
1568 return std::shared_ptr
<DNSAction
>(new DnstapLogAction(identity
, logger
, alterFunc
));
1570 throw std::runtime_error("Protobuf support is required to use DnstapLogAction");
1574 g_lua
.writeFunction("DnstapLogResponseAction", [](const std::string
& identity
, std::shared_ptr
<RemoteLoggerInterface
> logger
, boost::optional
<std::function
<void(DNSResponse
*, DnstapMessage
*)> > alterFunc
) {
1575 #ifdef HAVE_PROTOBUF
1576 return std::shared_ptr
<DNSResponseAction
>(new DnstapLogResponseAction(identity
, logger
, alterFunc
));
1578 throw std::runtime_error("Protobuf support is required to use DnstapLogResponseAction");
1582 g_lua
.writeFunction("TeeAction", [](const std::string
& remote
, boost::optional
<bool> addECS
) {
1583 return std::shared_ptr
<DNSAction
>(new TeeAction(ComboAddress(remote
, 53), addECS
? *addECS
: false));
1586 g_lua
.writeFunction("ECSPrefixLengthAction", [](uint16_t v4PrefixLength
, uint16_t v6PrefixLength
) {
1587 return std::shared_ptr
<DNSAction
>(new ECSPrefixLengthAction(v4PrefixLength
, v6PrefixLength
));
1590 g_lua
.writeFunction("ECSOverrideAction", [](bool ecsOverride
) {
1591 return std::shared_ptr
<DNSAction
>(new ECSOverrideAction(ecsOverride
));
1594 g_lua
.writeFunction("DisableECSAction", []() {
1595 return std::shared_ptr
<DNSAction
>(new DisableECSAction());
1598 g_lua
.writeFunction("SetECSAction", [](const std::string v4
, boost::optional
<std::string
> v6
) {
1600 return std::shared_ptr
<DNSAction
>(new SetECSAction(Netmask(v4
), Netmask(*v6
)));
1602 return std::shared_ptr
<DNSAction
>(new SetECSAction(Netmask(v4
)));
1605 g_lua
.writeFunction("SNMPTrapAction", [](boost::optional
<std::string
> reason
) {
1606 #ifdef HAVE_NET_SNMP
1607 return std::shared_ptr
<DNSAction
>(new SNMPTrapAction(reason
? *reason
: ""));
1609 throw std::runtime_error("NET SNMP support is required to use SNMPTrapAction()");
1610 #endif /* HAVE_NET_SNMP */
1613 g_lua
.writeFunction("SNMPTrapResponseAction", [](boost::optional
<std::string
> reason
) {
1614 #ifdef HAVE_NET_SNMP
1615 return std::shared_ptr
<DNSResponseAction
>(new SNMPTrapResponseAction(reason
? *reason
: ""));
1617 throw std::runtime_error("NET SNMP support is required to use SNMPTrapResponseAction()");
1618 #endif /* HAVE_NET_SNMP */
1621 g_lua
.writeFunction("TagAction", [](std::string tag
, std::string value
) {
1622 return std::shared_ptr
<DNSAction
>(new TagAction(tag
, value
));
1625 g_lua
.writeFunction("TagResponseAction", [](std::string tag
, std::string value
) {
1626 return std::shared_ptr
<DNSResponseAction
>(new TagResponseAction(tag
, value
));
1629 g_lua
.writeFunction("ContinueAction", [](std::shared_ptr
<DNSAction
> action
) {
1630 return std::shared_ptr
<DNSAction
>(new ContinueAction(action
));
1633 #ifdef HAVE_DNS_OVER_HTTPS
1634 g_lua
.writeFunction("HTTPStatusAction", [](uint16_t status
, std::string body
, boost::optional
<std::string
> contentType
, boost::optional
<responseParams_t
> vars
) {
1635 auto ret
= std::shared_ptr
<DNSAction
>(new HTTPStatusAction(status
, body
, contentType
? *contentType
: ""));
1636 auto hsa
= std::dynamic_pointer_cast
<HTTPStatusAction
>(ret
);
1637 parseResponseConfig(vars
, hsa
->d_responseConfig
);
1640 #endif /* HAVE_DNS_OVER_HTTPS */
1642 g_lua
.writeFunction("KeyValueStoreLookupAction", [](std::shared_ptr
<KeyValueStore
>& kvs
, std::shared_ptr
<KeyValueLookupKey
>& lookupKey
, const std::string
& destinationTag
) {
1643 return std::shared_ptr
<DNSAction
>(new KeyValueStoreLookupAction(kvs
, lookupKey
, destinationTag
));