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-lua-ffi.hh"
28 #include "dnsdist-protobuf.hh"
29 #include "dnsdist-kvs.hh"
33 #include "ednsoptions.hh"
34 #include "fstrm_logger.hh"
35 #include "remote_logger.hh"
37 #include <boost/optional/optional_io.hpp>
40 #include "ipcipher.hh"
41 #endif /* HAVE_LIBCRYPTO */
43 class DropAction
: public DNSAction
46 DNSAction::Action
operator()(DNSQuestion
* dq
, std::string
* ruleresult
) const override
50 std::string
toString() const override
56 class AllowAction
: public DNSAction
59 DNSAction::Action
operator()(DNSQuestion
* dq
, std::string
* ruleresult
) const override
63 std::string
toString() const override
69 class NoneAction
: public DNSAction
72 // this action does not stop the processing
73 DNSAction::Action
operator()(DNSQuestion
* dq
, std::string
* ruleresult
) const override
77 std::string
toString() const override
83 class QPSAction
: public DNSAction
86 QPSAction(int limit
) : d_qps(limit
, limit
)
89 DNSAction::Action
operator()(DNSQuestion
* dq
, std::string
* ruleresult
) const override
91 std::lock_guard
<decltype(d_lock
)> guard(d_lock
);
99 std::string
toString() const override
101 return "qps limit to "+std::to_string(d_qps
.getRate());
104 mutable std::mutex d_lock
;
108 class DelayAction
: public DNSAction
111 DelayAction(int msec
) : d_msec(msec
)
114 DNSAction::Action
operator()(DNSQuestion
* dq
, std::string
* ruleresult
) const override
116 *ruleresult
= std::to_string(d_msec
);
117 return Action::Delay
;
119 std::string
toString() const override
121 return "delay by "+std::to_string(d_msec
)+ " msec";
127 class TeeAction
: public DNSAction
130 // this action does not stop the processing
131 TeeAction(const ComboAddress
& ca
, bool addECS
=false);
132 ~TeeAction() override
;
133 DNSAction::Action
operator()(DNSQuestion
* dq
, std::string
* ruleresult
) const override
;
134 std::string
toString() const override
;
135 std::map
<std::string
, double> getStats() const override
;
138 ComboAddress d_remote
;
139 std::thread d_worker
;
143 mutable std::atomic
<unsigned long> d_senderrors
{0};
144 unsigned long d_recverrors
{0};
145 mutable std::atomic
<unsigned long> d_queries
{0};
146 stat_t d_responses
{0};
147 stat_t d_nxdomains
{0};
148 stat_t d_servfails
{0};
149 stat_t d_refuseds
{0};
150 stat_t d_formerrs
{0};
152 stat_t d_noerrors
{0};
153 mutable stat_t d_tcpdrops
{0};
154 stat_t d_otherrcode
{0};
155 std::atomic
<bool> d_pleaseQuit
{false};
156 bool d_addECS
{false};
159 TeeAction::TeeAction(const ComboAddress
& ca
, bool addECS
) : d_remote(ca
), d_addECS(addECS
)
161 d_fd
=SSocket(d_remote
.sin4
.sin_family
, SOCK_DGRAM
, 0);
163 SConnect(d_fd
, d_remote
);
164 setNonBlocking(d_fd
);
165 d_worker
=std::thread([this](){worker();});
175 TeeAction::~TeeAction()
182 DNSAction::Action
TeeAction::operator()(DNSQuestion
* dq
, std::string
* ruleresult
) const
192 PacketBuffer
query(dq
->getData());
193 bool ednsAdded
= false;
194 bool ecsAdded
= false;
196 std::string newECSOption
;
197 generateECSOption(dq
->ecsSet
? dq
->ecs
.getNetwork() : *dq
->remote
, newECSOption
, dq
->ecsSet
? dq
->ecs
.getBits() : dq
->ecsPrefixLength
);
199 if (!handleEDNSClientSubnet(query
, dq
->getMaximumSize(), dq
->qname
->wirelength(), ednsAdded
, ecsAdded
, dq
->ecsOverride
, newECSOption
)) {
200 return DNSAction::Action::None
;
203 res
= send(d_fd
, query
.data(), query
.size(), 0);
206 res
= send(d_fd
, dq
->getData().data(), dq
->getData().size(), 0);
214 return DNSAction::Action::None
;
217 std::string
TeeAction::toString() const
219 return "tee to "+d_remote
.toStringWithPort();
222 std::map
<std::string
,double> TeeAction::getStats() const
224 return {{"queries", d_queries
},
225 {"responses", d_responses
},
226 {"recv-errors", d_recverrors
},
227 {"send-errors", d_senderrors
},
228 {"noerrors", d_noerrors
},
229 {"nxdomains", d_nxdomains
},
230 {"refuseds", d_refuseds
},
231 {"servfails", d_servfails
},
232 {"other-rcode", d_otherrcode
},
233 {"tcp-drops", d_tcpdrops
}
237 void TeeAction::worker()
239 setThreadName("dnsdist/TeeWork");
242 struct dnsheader
* dh
=(struct dnsheader
*)packet
;
244 res
=waitForData(d_fd
, 0, 250000);
253 res
=recv(d_fd
, packet
, sizeof(packet
), 0);
254 if(res
<= (int)sizeof(struct dnsheader
))
259 if(dh
->rcode
== RCode::NoError
)
261 else if(dh
->rcode
== RCode::ServFail
)
263 else if(dh
->rcode
== RCode::NXDomain
)
265 else if(dh
->rcode
== RCode::Refused
)
267 else if(dh
->rcode
== RCode::FormErr
)
269 else if(dh
->rcode
== RCode::NotImp
)
274 class PoolAction
: public DNSAction
277 PoolAction(const std::string
& pool
) : d_pool(pool
) {}
278 DNSAction::Action
operator()(DNSQuestion
* dq
, std::string
* ruleresult
) const override
283 std::string
toString() const override
285 return "to pool "+d_pool
;
293 class QPSPoolAction
: public DNSAction
296 QPSPoolAction(unsigned int limit
, const std::string
& pool
) : d_qps(limit
, limit
), d_pool(pool
) {}
297 DNSAction::Action
operator()(DNSQuestion
* dq
, std::string
* ruleresult
) const override
299 std::lock_guard
<decltype(d_lock
)> guard(d_lock
);
301 *ruleresult
= d_pool
;
308 std::string
toString() const override
310 return "max " +std::to_string(d_qps
.getRate())+" to pool "+d_pool
;
314 mutable std::mutex d_lock
;
319 class RCodeAction
: public DNSAction
322 RCodeAction(uint8_t rcode
) : d_rcode(rcode
) {}
323 DNSAction::Action
operator()(DNSQuestion
* dq
, std::string
* ruleresult
) const override
325 dq
->getHeader()->rcode
= d_rcode
;
326 dq
->getHeader()->qr
= true; // for good measure
327 setResponseHeadersFromConfig(*dq
->getHeader(), d_responseConfig
);
328 return Action::HeaderModify
;
330 std::string
toString() const override
332 return "set rcode "+std::to_string(d_rcode
);
335 ResponseConfig d_responseConfig
;
340 class ERCodeAction
: public DNSAction
343 ERCodeAction(uint8_t rcode
) : d_rcode(rcode
) {}
344 DNSAction::Action
operator()(DNSQuestion
* dq
, std::string
* ruleresult
) const override
346 dq
->getHeader()->rcode
= (d_rcode
& 0xF);
347 dq
->ednsRCode
= ((d_rcode
& 0xFFF0) >> 4);
348 dq
->getHeader()->qr
= true; // for good measure
349 setResponseHeadersFromConfig(*dq
->getHeader(), d_responseConfig
);
350 return Action::HeaderModify
;
352 std::string
toString() const override
354 return "set ercode "+ERCode::to_s(d_rcode
);
357 ResponseConfig d_responseConfig
;
362 class TCAction
: public DNSAction
365 DNSAction::Action
operator()(DNSQuestion
* dq
, std::string
* ruleresult
) const override
367 return Action::Truncate
;
369 std::string
toString() const override
371 return "tc=1 answer";
375 class LuaAction
: public DNSAction
378 typedef std::function
<std::tuple
<int, boost::optional
<string
> >(DNSQuestion
* dq
)> func_t
;
379 LuaAction(const LuaAction::func_t
& func
) : d_func(func
)
382 DNSAction::Action
operator()(DNSQuestion
* dq
, std::string
* ruleresult
) const override
384 std::lock_guard
<std::mutex
> lock(g_luamutex
);
386 auto ret
= d_func(dq
);
388 if (boost::optional
<std::string
> rule
= std::get
<1>(ret
)) {
392 // default to empty string
396 return static_cast<Action
>(std::get
<0>(ret
));
397 } catch (const std::exception
&e
) {
398 warnlog("LuaAction failed inside Lua, returning ServFail: %s", e
.what());
400 warnlog("LuaAction failed inside Lua, returning ServFail: [unknown exception]");
402 return DNSAction::Action::ServFail
;
405 string
toString() const override
413 class LuaResponseAction
: public DNSResponseAction
416 typedef std::function
<std::tuple
<int, boost::optional
<string
> >(DNSResponse
* dr
)> func_t
;
417 LuaResponseAction(const LuaResponseAction::func_t
& func
) : d_func(func
)
419 DNSResponseAction::Action
operator()(DNSResponse
* dr
, std::string
* ruleresult
) const override
421 std::lock_guard
<std::mutex
> lock(g_luamutex
);
423 auto ret
= d_func(dr
);
425 if (boost::optional
<std::string
> rule
= std::get
<1>(ret
)) {
429 // default to empty string
433 return static_cast<Action
>(std::get
<0>(ret
));
434 } catch (const std::exception
&e
) {
435 warnlog("LuaResponseAction failed inside Lua, returning ServFail: %s", e
.what());
437 warnlog("LuaResponseAction failed inside Lua, returning ServFail: [unknown exception]");
439 return DNSResponseAction::Action::ServFail
;
442 string
toString() const override
444 return "Lua response script";
450 class LuaFFIAction
: public DNSAction
453 typedef std::function
<int(dnsdist_ffi_dnsquestion_t
* dq
)> func_t
;
455 LuaFFIAction(const LuaFFIAction::func_t
& func
): d_func(func
)
459 DNSAction::Action
operator()(DNSQuestion
* dq
, std::string
* ruleresult
) const override
461 dnsdist_ffi_dnsquestion_t
dqffi(dq
);
463 std::lock_guard
<std::mutex
> lock(g_luamutex
);
465 auto ret
= d_func(&dqffi
);
468 *ruleresult
= *dqffi
.result
;
471 // default to empty string
475 return static_cast<DNSAction::Action
>(ret
);
476 } catch (const std::exception
&e
) {
477 warnlog("LuaFFIAction failed inside Lua, returning ServFail: %s", e
.what());
479 warnlog("LuaFFIAction failed inside Lua, returning ServFail: [unknown exception]");
481 return DNSAction::Action::ServFail
;
484 string
toString() const override
486 return "Lua FFI script";
492 class LuaFFIPerThreadAction
: public DNSAction
495 typedef std::function
<int(dnsdist_ffi_dnsquestion_t
* dq
)> func_t
;
497 LuaFFIPerThreadAction(const std::string
& code
): d_functionCode(code
), d_functionID(s_functionsCounter
++)
501 DNSAction::Action
operator()(DNSQuestion
* dq
, std::string
* ruleresult
) const override
504 auto& state
= t_perThreadStates
[d_functionID
];
505 if (!state
.d_initialized
) {
506 setupLuaFFIPerThreadContext(state
.d_luaContext
);
507 /* mark the state as initialized first so if there is a syntax error
508 we only try to execute the code once */
509 state
.d_initialized
= true;
510 state
.d_func
= state
.d_luaContext
.executeCode
<func_t
>(d_functionCode
);
514 /* the function was not properly initialized */
515 return DNSAction::Action::None
;
518 dnsdist_ffi_dnsquestion_t
dqffi(dq
);
519 auto ret
= state
.d_func(&dqffi
);
522 *ruleresult
= *dqffi
.result
;
525 // default to empty string
529 return static_cast<DNSAction::Action
>(ret
);
531 catch (const std::exception
&e
) {
532 warnlog("LuaFFIPerThreadAction failed inside Lua, returning ServFail: %s", e
.what());
535 warnlog("LuaFFIPerthreadAction failed inside Lua, returning ServFail: [unknown exception]");
537 return DNSAction::Action::ServFail
;
540 string
toString() const override
542 return "Lua FFI per-thread script";
546 struct PerThreadState
548 LuaContext d_luaContext
;
550 bool d_initialized
{false};
552 static std::atomic
<uint64_t> s_functionsCounter
;
553 static thread_local
std::map
<uint64_t, PerThreadState
> t_perThreadStates
;
554 const std::string d_functionCode
;
555 const uint64_t d_functionID
;
558 std::atomic
<uint64_t> LuaFFIPerThreadAction::s_functionsCounter
= 0;
559 thread_local
std::map
<uint64_t, LuaFFIPerThreadAction::PerThreadState
> LuaFFIPerThreadAction::t_perThreadStates
;
561 class LuaFFIResponseAction
: public DNSResponseAction
564 typedef std::function
<int(dnsdist_ffi_dnsquestion_t
* dq
)> func_t
;
566 LuaFFIResponseAction(const LuaFFIResponseAction::func_t
& func
): d_func(func
)
570 DNSResponseAction::Action
operator()(DNSResponse
* dr
, std::string
* ruleresult
) const override
572 DNSQuestion
* dq
= dynamic_cast<DNSQuestion
*>(dr
);
574 return DNSResponseAction::Action::ServFail
;
577 dnsdist_ffi_dnsquestion_t
dqffi(dq
);
579 std::lock_guard
<std::mutex
> lock(g_luamutex
);
581 auto ret
= d_func(&dqffi
);
584 *ruleresult
= *dqffi
.result
;
587 // default to empty string
591 return static_cast<DNSResponseAction::Action
>(ret
);
592 } catch (const std::exception
&e
) {
593 warnlog("LuaFFIResponseAction failed inside Lua, returning ServFail: %s", e
.what());
595 warnlog("LuaFFIResponseAction failed inside Lua, returning ServFail: [unknown exception]");
597 return DNSResponseAction::Action::ServFail
;
600 string
toString() const override
602 return "Lua FFI script";
608 class LuaFFIPerThreadResponseAction
: public DNSResponseAction
611 typedef std::function
<int(dnsdist_ffi_dnsquestion_t
* dq
)> func_t
;
613 LuaFFIPerThreadResponseAction(const std::string
& code
): d_functionCode(code
), d_functionID(s_functionsCounter
++)
617 DNSResponseAction::Action
operator()(DNSResponse
* dr
, std::string
* ruleresult
) const override
619 DNSQuestion
* dq
= dynamic_cast<DNSQuestion
*>(dr
);
621 return DNSResponseAction::Action::ServFail
;
625 auto& state
= t_perThreadStates
[d_functionID
];
626 if (!state
.d_initialized
) {
627 setupLuaFFIPerThreadContext(state
.d_luaContext
);
628 /* mark the state as initialized first so if there is a syntax error
629 we only try to execute the code once */
630 state
.d_initialized
= true;
631 state
.d_func
= state
.d_luaContext
.executeCode
<func_t
>(d_functionCode
);
635 /* the function was not properly initialized */
636 return DNSResponseAction::Action::None
;
639 dnsdist_ffi_dnsquestion_t
dqffi(dq
);
640 auto ret
= state
.d_func(&dqffi
);
643 *ruleresult
= *dqffi
.result
;
646 // default to empty string
650 return static_cast<DNSResponseAction::Action
>(ret
);
652 catch (const std::exception
&e
) {
653 warnlog("LuaFFIPerThreadResponseAction failed inside Lua, returning ServFail: %s", e
.what());
656 warnlog("LuaFFIPerthreadResponseAction failed inside Lua, returning ServFail: [unknown exception]");
658 return DNSResponseAction::Action::ServFail
;
661 string
toString() const override
663 return "Lua FFI per-thread script";
667 struct PerThreadState
669 LuaContext d_luaContext
;
671 bool d_initialized
{false};
674 static std::atomic
<uint64_t> s_functionsCounter
;
675 static thread_local
std::map
<uint64_t, PerThreadState
> t_perThreadStates
;
676 const std::string d_functionCode
;
677 const uint64_t d_functionID
;
680 std::atomic
<uint64_t> LuaFFIPerThreadResponseAction::s_functionsCounter
= 0;
681 thread_local
std::map
<uint64_t, LuaFFIPerThreadResponseAction::PerThreadState
> LuaFFIPerThreadResponseAction::t_perThreadStates
;
683 thread_local
std::default_random_engine
SpoofAction::t_randomEngine
;
685 DNSAction::Action
SpoofAction::operator()(DNSQuestion
* dq
, std::string
* ruleresult
) const
687 uint16_t qtype
= dq
->qtype
;
688 // do we even have a response?
689 if (d_cname
.empty() &&
690 d_rawResponses
.empty() &&
691 d_types
.count(qtype
) == 0) {
695 vector
<ComboAddress
> addrs
;
696 vector
<std::string
> rawResponses
;
697 unsigned int totrdatalen
= 0;
698 uint16_t numberOfRecords
= 0;
699 if (!d_cname
.empty()) {
700 qtype
= QType::CNAME
;
701 totrdatalen
+= d_cname
.getStorage().size();
703 } else if (!d_rawResponses
.empty()) {
704 rawResponses
.reserve(d_rawResponses
.size());
705 for(const auto& rawResponse
: d_rawResponses
){
706 totrdatalen
+= rawResponse
.size();
707 rawResponses
.push_back(rawResponse
);
710 if (rawResponses
.size() > 1) {
711 shuffle(rawResponses
.begin(), rawResponses
.end(), t_randomEngine
);
715 for(const auto& addr
: d_addrs
) {
716 if(qtype
!= QType::ANY
&& ((addr
.sin4
.sin_family
== AF_INET
&& qtype
!= QType::A
) ||
717 (addr
.sin4
.sin_family
== AF_INET6
&& qtype
!= QType::AAAA
))) {
720 totrdatalen
+= addr
.sin4
.sin_family
== AF_INET
? sizeof(addr
.sin4
.sin_addr
.s_addr
) : sizeof(addr
.sin6
.sin6_addr
.s6_addr
);
721 addrs
.push_back(addr
);
726 if (addrs
.size() > 1) {
727 shuffle(addrs
.begin(), addrs
.end(), t_randomEngine
);
730 unsigned int qnameWireLength
=0;
731 DNSName
ignore((char*)dq
->getData().data(), dq
->getData().size(), sizeof(dnsheader
), false, 0, 0, &qnameWireLength
);
733 if (dq
->getMaximumSize() < (sizeof(dnsheader
) + qnameWireLength
+ 4 + numberOfRecords
*12 /* recordstart */ + totrdatalen
)) {
737 bool dnssecOK
= false;
738 bool hadEDNS
= false;
739 if (g_addEDNSToSelfGeneratedResponses
&& queryHasEDNS(*dq
)) {
741 dnssecOK
= getEDNSZ(*dq
) & EDNS_HEADER_FLAG_DO
;
744 auto& data
= dq
->getMutableData();
745 data
.resize(sizeof(dnsheader
) + qnameWireLength
+ 4 + numberOfRecords
*12 /* recordstart */ + totrdatalen
); // there goes your EDNS
746 uint8_t* dest
= &(data
.at(sizeof(dnsheader
) + qnameWireLength
+ 4));
748 dq
->getHeader()->qr
= true; // for good measure
749 setResponseHeadersFromConfig(*dq
->getHeader(), d_responseConfig
);
750 dq
->getHeader()->ancount
= 0;
751 dq
->getHeader()->arcount
= 0; // for now, forget about your EDNS, we're marching over it
753 uint32_t ttl
= htonl(d_responseConfig
.ttl
);
754 unsigned char recordstart
[] = {0xc0, 0x0c, // compressed name
758 0, 0 }; // rdata length
759 static_assert(sizeof(recordstart
) == 12, "sizeof(recordstart) must be equal to 12, otherwise the above check is invalid");
760 memcpy(&recordstart
[6], &ttl
, sizeof(ttl
));
763 if (qtype
== QType::CNAME
) {
764 const auto& wireData
= d_cname
.getStorage(); // Note! This doesn't do compression!
765 uint16_t rdataLen
= htons(wireData
.length());
766 qtype
= htons(qtype
);
767 memcpy(&recordstart
[2], &qtype
, sizeof(qtype
));
768 memcpy(&recordstart
[10], &rdataLen
, sizeof(rdataLen
));
770 memcpy(dest
, recordstart
, sizeof(recordstart
));
771 dest
+= sizeof(recordstart
);
772 memcpy(dest
, wireData
.c_str(), wireData
.length());
773 dq
->getHeader()->ancount
++;
775 else if (!rawResponses
.empty()) {
776 qtype
= htons(qtype
);
777 for(const auto& rawResponse
: rawResponses
){
778 uint16_t rdataLen
= htons(rawResponse
.size());
779 memcpy(&recordstart
[2], &qtype
, sizeof(qtype
));
780 memcpy(&recordstart
[10], &rdataLen
, sizeof(rdataLen
));
782 memcpy(dest
, recordstart
, sizeof(recordstart
));
783 dest
+= sizeof(recordstart
);
785 memcpy(dest
, rawResponse
.c_str(), rawResponse
.size());
786 dest
+= rawResponse
.size();
788 dq
->getHeader()->ancount
++;
793 for(const auto& addr
: addrs
) {
794 uint16_t rdataLen
= htons(addr
.sin4
.sin_family
== AF_INET
? sizeof(addr
.sin4
.sin_addr
.s_addr
) : sizeof(addr
.sin6
.sin6_addr
.s6_addr
));
795 qtype
= htons(addr
.sin4
.sin_family
== AF_INET
? QType::A
: QType::AAAA
);
796 memcpy(&recordstart
[2], &qtype
, sizeof(qtype
));
797 memcpy(&recordstart
[10], &rdataLen
, sizeof(rdataLen
));
799 memcpy(dest
, recordstart
, sizeof(recordstart
));
800 dest
+= sizeof(recordstart
);
803 addr
.sin4
.sin_family
== AF_INET
? (void*)&addr
.sin4
.sin_addr
.s_addr
: (void*)&addr
.sin6
.sin6_addr
.s6_addr
,
804 addr
.sin4
.sin_family
== AF_INET
? sizeof(addr
.sin4
.sin_addr
.s_addr
) : sizeof(addr
.sin6
.sin6_addr
.s6_addr
));
805 dest
+= (addr
.sin4
.sin_family
== AF_INET
? sizeof(addr
.sin4
.sin_addr
.s_addr
) : sizeof(addr
.sin6
.sin6_addr
.s6_addr
));
806 dq
->getHeader()->ancount
++;
810 dq
->getHeader()->ancount
= htons(dq
->getHeader()->ancount
);
812 if (hadEDNS
&& raw
== false) {
813 addEDNS(dq
->getMutableData(), dq
->getMaximumSize(), dnssecOK
, g_PayloadSizeSelfGenAnswers
, 0);
816 return Action::HeaderModify
;
819 class SetMacAddrAction
: public DNSAction
822 // this action does not stop the processing
823 SetMacAddrAction(uint16_t code
) : d_code(code
)
825 DNSAction::Action
operator()(DNSQuestion
* dq
, std::string
* ruleresult
) const override
827 if (dq
->getHeader()->arcount
) {
831 std::string mac
= getMACAddress(*dq
->remote
);
836 std::string optRData
;
837 generateEDNSOption(d_code
, mac
, optRData
);
839 auto& data
= dq
->getMutableData();
840 if (generateOptRR(optRData
, data
, dq
->getMaximumSize(), g_EdnsUDPPayloadSize
, 0, false)) {
841 dq
->getHeader()->arcount
= htons(1);
846 std::string
toString() const override
848 return "add EDNS MAC (code="+std::to_string(d_code
)+")";
854 class SetNoRecurseAction
: public DNSAction
857 // this action does not stop the processing
858 DNSAction::Action
operator()(DNSQuestion
* dq
, std::string
* ruleresult
) const override
860 dq
->getHeader()->rd
= false;
863 std::string
toString() const override
869 class LogAction
: public DNSAction
, public boost::noncopyable
872 // this action does not stop the processing
877 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
), d_append(append
), d_buffered(buffered
)
883 if (!reopenLogFile()) {
884 throw std::runtime_error("Unable to open file '" + str
+ "' for logging: " + stringerror());
888 DNSAction::Action
operator()(DNSQuestion
* dq
, std::string
* ruleresult
) const override
890 auto fp
= std::atomic_load_explicit(&d_fp
, std::memory_order_acquire
);
892 if (!d_verboseOnly
|| g_verbose
) {
893 if (d_includeTimestamp
) {
894 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
).toString(), dq
->getHeader()->id
);
897 infolog("Packet from %s for %s %s with id %d", dq
->remote
->toStringWithPort(), dq
->qname
->toString(), QType(dq
->qtype
).toString(), dq
->getHeader()->id
);
903 const auto& out
= dq
->qname
->getStorage();
904 if (d_includeTimestamp
) {
905 uint64_t tv_sec
= static_cast<uint64_t>(dq
->queryTime
->tv_sec
);
906 uint32_t tv_nsec
= static_cast<uint32_t>(dq
->queryTime
->tv_nsec
);
907 fwrite(&tv_sec
, sizeof(tv_sec
), 1, fp
.get());
908 fwrite(&tv_nsec
, sizeof(tv_nsec
), 1, fp
.get());
910 uint16_t id
= dq
->getHeader()->id
;
911 fwrite(&id
, sizeof(id
), 1, fp
.get());
912 fwrite(out
.c_str(), 1, out
.size(), fp
.get());
913 fwrite(&dq
->qtype
, sizeof(dq
->qtype
), 1, fp
.get());
914 fwrite(&dq
->remote
->sin4
.sin_family
, sizeof(dq
->remote
->sin4
.sin_family
), 1, fp
.get());
915 if (dq
->remote
->sin4
.sin_family
== AF_INET
) {
916 fwrite(&dq
->remote
->sin4
.sin_addr
.s_addr
, sizeof(dq
->remote
->sin4
.sin_addr
.s_addr
), 1, fp
.get());
918 else if (dq
->remote
->sin4
.sin_family
== AF_INET6
) {
919 fwrite(&dq
->remote
->sin6
.sin6_addr
.s6_addr
, sizeof(dq
->remote
->sin6
.sin6_addr
.s6_addr
), 1, fp
.get());
921 fwrite(&dq
->remote
->sin4
.sin_port
, sizeof(dq
->remote
->sin4
.sin_port
), 1, fp
.get());
924 if (d_includeTimestamp
) {
925 fprintf(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
).toString().c_str(), dq
->getHeader()->id
);
928 fprintf(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
).toString().c_str(), dq
->getHeader()->id
);
935 std::string
toString() const override
937 if (!d_fname
.empty()) {
938 return "log to " + d_fname
;
943 void reload() override
945 if (!reopenLogFile()) {
946 warnlog("Unable to open file '%s' for logging: %s", d_fname
, stringerror());
953 // we are using a naked pointer here because we don't want fclose to be called
954 // with a nullptr, which would happen if we constructor a shared_ptr with fclose
955 // as a custom deleter and nullptr as a FILE*
956 auto nfp
= fopen(d_fname
.c_str(), d_append
? "a+" : "w");
958 /* don't fall on our sword when reopening */
962 auto fp
= std::shared_ptr
<FILE>(nfp
, fclose
);
969 std::atomic_store_explicit(&d_fp
, fp
, std::memory_order_release
);
974 std::shared_ptr
<FILE> d_fp
{nullptr};
976 bool d_verboseOnly
{true};
977 bool d_includeTimestamp
{false};
978 bool d_append
{false};
979 bool d_buffered
{true};
982 class LogResponseAction
: public DNSResponseAction
, public boost::noncopyable
989 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
), d_append(append
), d_buffered(buffered
)
995 if (!reopenLogFile()) {
996 throw std::runtime_error("Unable to open file '" + str
+ "' for logging: " + stringerror());
1000 DNSResponseAction::Action
operator()(DNSResponse
* dr
, std::string
* ruleresult
) const override
1002 auto fp
= std::atomic_load_explicit(&d_fp
, std::memory_order_acquire
);
1004 if (!d_verboseOnly
|| g_verbose
) {
1005 if (d_includeTimestamp
) {
1006 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
).toString(), RCode::to_s(dr
->getHeader()->rcode
), dr
->getHeader()->id
);
1009 infolog("Answer to %s for %s %s (%s) with id %d", dr
->remote
->toStringWithPort(), dr
->qname
->toString(), QType(dr
->qtype
).toString(), RCode::to_s(dr
->getHeader()->rcode
), dr
->getHeader()->id
);
1014 if (d_includeTimestamp
) {
1015 fprintf(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
).toString().c_str(), RCode::to_s(dr
->getHeader()->rcode
).c_str(), dr
->getHeader()->id
);
1018 fprintf(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
).toString().c_str(), RCode::to_s(dr
->getHeader()->rcode
).c_str(), dr
->getHeader()->id
);
1021 return Action::None
;
1024 std::string
toString() const override
1026 if (!d_fname
.empty()) {
1027 return "log to " + d_fname
;
1032 void reload() override
1034 if (!reopenLogFile()) {
1035 warnlog("Unable to open file '%s' for logging: %s", d_fname
, stringerror());
1040 bool reopenLogFile()
1042 // we are using a naked pointer here because we don't want fclose to be called
1043 // with a nullptr, which would happen if we constructor a shared_ptr with fclose
1044 // as a custom deleter and nullptr as a FILE*
1045 auto nfp
= fopen(d_fname
.c_str(), d_append
? "a+" : "w");
1047 /* don't fall on our sword when reopening */
1051 auto fp
= std::shared_ptr
<FILE>(nfp
, fclose
);
1055 setbuf(fp
.get(), 0);
1058 std::atomic_store_explicit(&d_fp
, fp
, std::memory_order_release
);
1062 std::string d_fname
;
1063 std::shared_ptr
<FILE> d_fp
{nullptr};
1064 bool d_verboseOnly
{true};
1065 bool d_includeTimestamp
{false};
1066 bool d_append
{false};
1067 bool d_buffered
{true};
1071 class SetDisableValidationAction
: public DNSAction
1074 // this action does not stop the processing
1075 DNSAction::Action
operator()(DNSQuestion
* dq
, std::string
* ruleresult
) const override
1077 dq
->getHeader()->cd
= true;
1078 return Action::None
;
1080 std::string
toString() const override
1086 class SetSkipCacheAction
: public DNSAction
1089 // this action does not stop the processing
1090 DNSAction::Action
operator()(DNSQuestion
* dq
, std::string
* ruleresult
) const override
1092 dq
->skipCache
= true;
1093 return Action::None
;
1095 std::string
toString() const override
1097 return "skip cache";
1101 class SetSkipCacheResponseAction
: public DNSResponseAction
1104 DNSResponseAction::Action
operator()(DNSResponse
* dr
, std::string
* ruleresult
) const override
1106 dr
->skipCache
= true;
1107 return Action::None
;
1109 std::string
toString() const override
1111 return "skip cache";
1115 class SetTempFailureCacheTTLAction
: public DNSAction
1118 // this action does not stop the processing
1119 SetTempFailureCacheTTLAction(uint32_t ttl
) : d_ttl(ttl
)
1122 DNSAction::Action
operator()(DNSQuestion
* dq
, std::string
* ruleresult
) const override
1124 dq
->tempFailureTTL
= d_ttl
;
1125 return Action::None
;
1127 std::string
toString() const override
1129 return "set tempfailure cache ttl to "+std::to_string(d_ttl
);
1135 class SetECSPrefixLengthAction
: public DNSAction
1138 // this action does not stop the processing
1139 SetECSPrefixLengthAction(uint16_t v4Length
, uint16_t v6Length
) : d_v4PrefixLength(v4Length
), d_v6PrefixLength(v6Length
)
1142 DNSAction::Action
operator()(DNSQuestion
* dq
, std::string
* ruleresult
) const override
1144 dq
->ecsPrefixLength
= dq
->remote
->sin4
.sin_family
== AF_INET
? d_v4PrefixLength
: d_v6PrefixLength
;
1145 return Action::None
;
1147 std::string
toString() const override
1149 return "set ECS prefix length to " + std::to_string(d_v4PrefixLength
) + "/" + std::to_string(d_v6PrefixLength
);
1152 uint16_t d_v4PrefixLength
;
1153 uint16_t d_v6PrefixLength
;
1156 class SetECSOverrideAction
: public DNSAction
1159 // this action does not stop the processing
1160 SetECSOverrideAction(bool ecsOverride
) : d_ecsOverride(ecsOverride
)
1163 DNSAction::Action
operator()(DNSQuestion
* dq
, std::string
* ruleresult
) const override
1165 dq
->ecsOverride
= d_ecsOverride
;
1166 return Action::None
;
1168 std::string
toString() const override
1170 return "set ECS override to " + std::to_string(d_ecsOverride
);
1177 class SetDisableECSAction
: public DNSAction
1180 // this action does not stop the processing
1181 DNSAction::Action
operator()(DNSQuestion
* dq
, std::string
* ruleresult
) const override
1184 return Action::None
;
1186 std::string
toString() const override
1188 return "disable ECS";
1192 class SetECSAction
: public DNSAction
1195 // this action does not stop the processing
1196 SetECSAction(const Netmask
& v4
): d_v4(v4
), d_hasV6(false)
1200 SetECSAction(const Netmask
& v4
, const Netmask
& v6
): d_v4(v4
), d_v6(v6
), d_hasV6(true)
1204 DNSAction::Action
operator()(DNSQuestion
* dq
, std::string
* ruleresult
) const override
1209 dq
->ecs
= dq
->remote
->isIPv4() ? d_v4
: d_v6
;
1215 return Action::None
;
1218 std::string
toString() const override
1220 std::string result
= "set ECS to " + d_v4
.toString();
1222 result
+= " / " + d_v6
.toString();
1233 static DnstapMessage::ProtocolType
ProtocolToDNSTap(DNSQuestion::Protocol protocol
)
1235 DnstapMessage::ProtocolType result
;
1238 case DNSQuestion::Protocol::DoUDP
:
1239 case DNSQuestion::Protocol::DNSCryptUDP
:
1240 result
= DnstapMessage::ProtocolType::DoUDP
;
1242 case DNSQuestion::Protocol::DoTCP
:
1243 case DNSQuestion::Protocol::DNSCryptTCP
:
1244 result
= DnstapMessage::ProtocolType::DoTCP
;
1246 case DNSQuestion::Protocol::DoT
:
1247 result
= DnstapMessage::ProtocolType::DoT
;
1249 case DNSQuestion::Protocol::DoH
:
1250 result
= DnstapMessage::ProtocolType::DoH
;
1256 class DnstapLogAction
: public DNSAction
, public boost::noncopyable
1259 // this action does not stop the processing
1260 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
)
1263 DNSAction::Action
operator()(DNSQuestion
* dq
, std::string
* ruleresult
) const override
1265 static thread_local
std::string data
;
1268 DnstapMessage::ProtocolType protocol
= ProtocolToDNSTap(dq
->getProtocol());
1269 DnstapMessage
message(data
, !dq
->getHeader()->qr
? DnstapMessage::MessageType::client_query
: DnstapMessage::MessageType::client_response
, d_identity
, dq
->remote
, dq
->local
, protocol
, reinterpret_cast<const char*>(dq
->getData().data()), dq
->getData().size(), dq
->queryTime
, nullptr);
1272 std::lock_guard
<std::mutex
> lock(g_luamutex
);
1273 (*d_alterFunc
)(dq
, &message
);
1277 d_logger
->queueData(data
);
1279 return Action::None
;
1281 std::string
toString() const override
1283 return "remote log as dnstap to " + (d_logger
? d_logger
->toString() : "");
1286 std::string d_identity
;
1287 std::shared_ptr
<RemoteLoggerInterface
> d_logger
;
1288 boost::optional
<std::function
<void(DNSQuestion
*, DnstapMessage
*)> > d_alterFunc
;
1291 class RemoteLogAction
: public DNSAction
, public boost::noncopyable
1294 // this action does not stop the processing
1295 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
)
1298 DNSAction::Action
operator()(DNSQuestion
* dq
, std::string
* ruleresult
) const override
1300 if (!dq
->uniqueId
) {
1301 dq
->uniqueId
= getUniqueID();
1304 DNSDistProtoBufMessage
message(*dq
);
1305 if (!d_serverID
.empty()) {
1306 message
.setServerIdentity(d_serverID
);
1310 if (!d_ipEncryptKey
.empty())
1312 message
.setRequestor(encryptCA(*dq
->remote
, d_ipEncryptKey
));
1314 #endif /* HAVE_LIBCRYPTO */
1317 std::lock_guard
<std::mutex
> lock(g_luamutex
);
1318 (*d_alterFunc
)(dq
, &message
);
1321 static thread_local
std::string data
;
1323 message
.serialize(data
);
1324 d_logger
->queueData(data
);
1326 return Action::None
;
1328 std::string
toString() const override
1330 return "remote log to " + (d_logger
? d_logger
->toString() : "");
1333 std::shared_ptr
<RemoteLoggerInterface
> d_logger
;
1334 boost::optional
<std::function
<void(DNSQuestion
*, DNSDistProtoBufMessage
*)> > d_alterFunc
;
1335 std::string d_serverID
;
1336 std::string d_ipEncryptKey
;
1339 class SNMPTrapAction
: public DNSAction
1342 // this action does not stop the processing
1343 SNMPTrapAction(const std::string
& reason
): d_reason(reason
)
1346 DNSAction::Action
operator()(DNSQuestion
* dq
, std::string
* ruleresult
) const override
1348 if (g_snmpAgent
&& g_snmpTrapsEnabled
) {
1349 g_snmpAgent
->sendDNSTrap(*dq
, d_reason
);
1352 return Action::None
;
1354 std::string
toString() const override
1356 return "send SNMP trap";
1359 std::string d_reason
;
1362 class SetTagAction
: public DNSAction
1365 // this action does not stop the processing
1366 SetTagAction(const std::string
& tag
, const std::string
& value
): d_tag(tag
), d_value(value
)
1369 DNSAction::Action
operator()(DNSQuestion
* dq
, std::string
* ruleresult
) const override
1372 dq
->qTag
= std::make_shared
<QTag
>();
1375 dq
->qTag
->insert({d_tag
, d_value
});
1377 return Action::None
;
1379 std::string
toString() const override
1381 return "set tag '" + d_tag
+ "' to value '" + d_value
+ "'";
1385 std::string d_value
;
1388 class DnstapLogResponseAction
: public DNSResponseAction
, public boost::noncopyable
1391 // this action does not stop the processing
1392 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
)
1395 DNSResponseAction::Action
operator()(DNSResponse
* dr
, std::string
* ruleresult
) const override
1397 static thread_local
std::string data
;
1398 struct timespec now
;
1399 gettime(&now
, true);
1402 DnstapMessage::ProtocolType protocol
= ProtocolToDNSTap(dr
->getProtocol());
1403 DnstapMessage
message(data
, DnstapMessage::MessageType::client_response
, d_identity
, dr
->remote
, dr
->local
, protocol
, reinterpret_cast<const char*>(dr
->getData().data()), dr
->getData().size(), dr
->queryTime
, &now
);
1406 std::lock_guard
<std::mutex
> lock(g_luamutex
);
1407 (*d_alterFunc
)(dr
, &message
);
1411 d_logger
->queueData(data
);
1413 return Action::None
;
1415 std::string
toString() const override
1417 return "log response as dnstap to " + (d_logger
? d_logger
->toString() : "");
1420 std::string d_identity
;
1421 std::shared_ptr
<RemoteLoggerInterface
> d_logger
;
1422 boost::optional
<std::function
<void(DNSResponse
*, DnstapMessage
*)> > d_alterFunc
;
1425 class RemoteLogResponseAction
: public DNSResponseAction
, public boost::noncopyable
1428 // this action does not stop the processing
1429 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
)
1432 DNSResponseAction::Action
operator()(DNSResponse
* dr
, std::string
* ruleresult
) const override
1434 if (!dr
->uniqueId
) {
1435 dr
->uniqueId
= getUniqueID();
1438 DNSDistProtoBufMessage
message(*dr
, d_includeCNAME
);
1439 if (!d_serverID
.empty()) {
1440 message
.setServerIdentity(d_serverID
);
1444 if (!d_ipEncryptKey
.empty())
1446 message
.setRequestor(encryptCA(*dr
->remote
, d_ipEncryptKey
));
1448 #endif /* HAVE_LIBCRYPTO */
1451 std::lock_guard
<std::mutex
> lock(g_luamutex
);
1452 (*d_alterFunc
)(dr
, &message
);
1455 static thread_local
std::string data
;
1457 message
.serialize(data
);
1458 d_logger
->queueData(data
);
1460 return Action::None
;
1462 std::string
toString() const override
1464 return "remote log response to " + (d_logger
? d_logger
->toString() : "");
1467 std::shared_ptr
<RemoteLoggerInterface
> d_logger
;
1468 boost::optional
<std::function
<void(DNSResponse
*, DNSDistProtoBufMessage
*)> > d_alterFunc
;
1469 std::string d_serverID
;
1470 std::string d_ipEncryptKey
;
1471 bool d_includeCNAME
;
1474 class DropResponseAction
: public DNSResponseAction
1477 DNSResponseAction::Action
operator()(DNSResponse
* dr
, std::string
* ruleresult
) const override
1479 return Action::Drop
;
1481 std::string
toString() const override
1487 class AllowResponseAction
: public DNSResponseAction
1490 DNSResponseAction::Action
operator()(DNSResponse
* dr
, std::string
* ruleresult
) const override
1492 return Action::Allow
;
1494 std::string
toString() const override
1500 class DelayResponseAction
: public DNSResponseAction
1503 DelayResponseAction(int msec
) : d_msec(msec
)
1506 DNSResponseAction::Action
operator()(DNSResponse
* dr
, std::string
* ruleresult
) const override
1508 *ruleresult
= std::to_string(d_msec
);
1509 return Action::Delay
;
1511 std::string
toString() const override
1513 return "delay by "+std::to_string(d_msec
)+ " msec";
1519 class SNMPTrapResponseAction
: public DNSResponseAction
1522 // this action does not stop the processing
1523 SNMPTrapResponseAction(const std::string
& reason
): d_reason(reason
)
1526 DNSResponseAction::Action
operator()(DNSResponse
* dr
, std::string
* ruleresult
) const override
1528 if (g_snmpAgent
&& g_snmpTrapsEnabled
) {
1529 g_snmpAgent
->sendDNSTrap(*dr
, d_reason
);
1532 return Action::None
;
1534 std::string
toString() const override
1536 return "send SNMP trap";
1539 std::string d_reason
;
1542 class SetTagResponseAction
: public DNSResponseAction
1545 // this action does not stop the processing
1546 SetTagResponseAction(const std::string
& tag
, const std::string
& value
): d_tag(tag
), d_value(value
)
1549 DNSResponseAction::Action
operator()(DNSResponse
* dr
, std::string
* ruleresult
) const override
1552 dr
->qTag
= std::make_shared
<QTag
>();
1555 dr
->qTag
->insert({d_tag
, d_value
});
1557 return Action::None
;
1559 std::string
toString() const override
1561 return "set tag '" + d_tag
+ "' to value '" + d_value
+ "'";
1565 std::string d_value
;
1568 class ContinueAction
: public DNSAction
1571 // this action does not stop the processing
1572 ContinueAction(std::shared_ptr
<DNSAction
>& action
): d_action(action
)
1576 DNSAction::Action
operator()(DNSQuestion
* dq
, std::string
* ruleresult
) const override
1579 /* call the action */
1580 auto action
= (*d_action
)(dq
, ruleresult
);
1582 /* apply the changes if needed (pool selection, flags, etc */
1583 processRulesResult(action
, *dq
, *ruleresult
, drop
);
1586 /* but ignore the resulting action no matter what */
1587 return Action::None
;
1590 std::string
toString() const override
1593 return "continue after: " + (d_action
? d_action
->toString() : "");
1601 std::shared_ptr
<DNSAction
> d_action
;
1604 #ifdef HAVE_DNS_OVER_HTTPS
1605 class HTTPStatusAction
: public DNSAction
1608 HTTPStatusAction(int code
, const PacketBuffer
& body
, const std::string
& contentType
): d_body(body
), d_contentType(contentType
), d_code(code
)
1612 DNSAction::Action
operator()(DNSQuestion
* dq
, std::string
* ruleresult
) const override
1615 return Action::None
;
1618 dq
->du
->setHTTPResponse(d_code
, PacketBuffer(d_body
), d_contentType
);
1619 dq
->getHeader()->qr
= true; // for good measure
1620 setResponseHeadersFromConfig(*dq
->getHeader(), d_responseConfig
);
1621 return Action::HeaderModify
;
1624 std::string
toString() const override
1626 return "return an HTTP status of " + std::to_string(d_code
);
1629 ResponseConfig d_responseConfig
;
1631 PacketBuffer d_body
;
1632 std::string d_contentType
;
1635 #endif /* HAVE_DNS_OVER_HTTPS */
1637 class KeyValueStoreLookupAction
: public DNSAction
1640 // this action does not stop the processing
1641 KeyValueStoreLookupAction(std::shared_ptr
<KeyValueStore
>& kvs
, std::shared_ptr
<KeyValueLookupKey
>& lookupKey
, const std::string
& destinationTag
): d_kvs(kvs
), d_key(lookupKey
), d_tag(destinationTag
)
1645 DNSAction::Action
operator()(DNSQuestion
* dq
, std::string
* ruleresult
) const override
1647 std::vector
<std::string
> keys
= d_key
->getKeys(*dq
);
1649 for (const auto& key
: keys
) {
1650 if (d_kvs
->getValue(key
, result
) == true) {
1656 dq
->qTag
= std::make_shared
<QTag
>();
1659 dq
->qTag
->insert({d_tag
, std::move(result
)});
1661 return Action::None
;
1664 std::string
toString() const override
1666 return "lookup key-value store based on '" + d_key
->toString() + "' and set the result in tag '" + d_tag
+ "'";
1670 std::shared_ptr
<KeyValueStore
> d_kvs
;
1671 std::shared_ptr
<KeyValueLookupKey
> d_key
;
1675 class NegativeAndSOAAction
: public DNSAction
1678 NegativeAndSOAAction(bool nxd
, const DNSName
& zone
, uint32_t ttl
, const DNSName
& mname
, const DNSName
& rname
, uint32_t serial
, uint32_t refresh
, uint32_t retry
, uint32_t expire
, uint32_t minimum
): d_zone(zone
), d_mname(mname
), d_rname(rname
), d_ttl(ttl
), d_serial(serial
), d_refresh(refresh
), d_retry(retry
), d_expire(expire
), d_minimum(minimum
), d_nxd(nxd
)
1682 DNSAction::Action
operator()(DNSQuestion
* dq
, std::string
* ruleresult
) const override
1684 if (!setNegativeAndAdditionalSOA(*dq
, d_nxd
, d_zone
, d_ttl
, d_mname
, d_rname
, d_serial
, d_refresh
, d_retry
, d_expire
, d_minimum
)) {
1685 return Action::None
;
1688 setResponseHeadersFromConfig(*dq
->getHeader(), d_responseConfig
);
1690 return Action::Allow
;
1693 std::string
toString() const override
1695 return std::string(d_nxd
? "NXD " : "NODATA") + " with SOA";
1698 ResponseConfig d_responseConfig
;
1713 class SetProxyProtocolValuesAction
: public DNSAction
1716 // this action does not stop the processing
1717 SetProxyProtocolValuesAction(const std::vector
<std::pair
<uint8_t, std::string
>>& values
)
1719 d_values
.reserve(values
.size());
1720 for (const auto& value
: values
) {
1721 d_values
.push_back({value
.second
, value
.first
});
1725 DNSAction::Action
operator()(DNSQuestion
* dq
, std::string
* ruleresult
) const override
1727 if (!dq
->proxyProtocolValues
) {
1728 dq
->proxyProtocolValues
= make_unique
<std::vector
<ProxyProtocolValue
>>();
1731 *(dq
->proxyProtocolValues
) = d_values
;
1733 return Action::None
;
1736 std::string
toString() const override
1738 return "set Proxy-Protocol values";
1742 std::vector
<ProxyProtocolValue
> d_values
;
1745 class SetAdditionalProxyProtocolValueAction
: public DNSAction
1748 // this action does not stop the processing
1749 SetAdditionalProxyProtocolValueAction(uint8_t type
, const std::string
& value
): d_value(value
), d_type(type
)
1753 DNSAction::Action
operator()(DNSQuestion
* dq
, std::string
* ruleresult
) const override
1755 if (!dq
->proxyProtocolValues
) {
1756 dq
->proxyProtocolValues
= make_unique
<std::vector
<ProxyProtocolValue
>>();
1759 dq
->proxyProtocolValues
->push_back({ d_value
, d_type
});
1761 return Action::None
;
1764 std::string
toString() const override
1766 return "add a Proxy-Protocol value of type " + std::to_string(d_type
);
1770 std::string d_value
;
1774 template<typename T
, typename ActionT
>
1775 static void addAction(GlobalStateHolder
<vector
<T
> > *someRuleActions
, const luadnsrule_t
& var
, const std::shared_ptr
<ActionT
>& action
, boost::optional
<luaruleparams_t
>& params
) {
1779 boost::uuids::uuid uuid
;
1780 uint64_t creationOrder
;
1781 parseRuleParams(params
, uuid
, name
, creationOrder
);
1783 auto rule
= makeRule(var
);
1784 someRuleActions
->modify([&rule
, &action
, &uuid
, creationOrder
, &name
](vector
<T
>& ruleactions
){
1785 ruleactions
.push_back({std::move(rule
), std::move(action
), std::move(name
), std::move(uuid
), creationOrder
});
1789 typedef std::unordered_map
<std::string
, boost::variant
<bool, uint32_t> > responseParams_t
;
1791 static void parseResponseConfig(boost::optional
<responseParams_t
> vars
, ResponseConfig
& config
)
1794 if (vars
->count("ttl")) {
1795 config
.ttl
= boost::get
<uint32_t>((*vars
)["ttl"]);
1797 if (vars
->count("aa")) {
1798 config
.setAA
= boost::get
<bool>((*vars
)["aa"]);
1800 if (vars
->count("ad")) {
1801 config
.setAD
= boost::get
<bool>((*vars
)["ad"]);
1803 if (vars
->count("ra")) {
1804 config
.setRA
= boost::get
<bool>((*vars
)["ra"]);
1809 void setResponseHeadersFromConfig(dnsheader
& dh
, const ResponseConfig
& config
)
1812 dh
.aa
= *config
.setAA
;
1815 dh
.ad
= *config
.setAD
;
1821 dh
.ra
= *config
.setRA
;
1824 dh
.ra
= dh
.rd
; // for good measure
1828 void setupLuaActions(LuaContext
& luaCtx
)
1830 luaCtx
.writeFunction("newRuleAction", [](luadnsrule_t dnsrule
, std::shared_ptr
<DNSAction
> action
, boost::optional
<luaruleparams_t
> params
) {
1831 boost::uuids::uuid uuid
;
1832 uint64_t creationOrder
;
1834 parseRuleParams(params
, uuid
, name
, creationOrder
);
1836 auto rule
= makeRule(dnsrule
);
1837 DNSDistRuleAction
ra({std::move(rule
), action
, std::move(name
), uuid
, creationOrder
});
1838 return std::make_shared
<DNSDistRuleAction
>(ra
);
1841 luaCtx
.writeFunction("addAction", [](luadnsrule_t var
, boost::variant
<std::shared_ptr
<DNSAction
>, std::shared_ptr
<DNSResponseAction
> > era
, boost::optional
<luaruleparams_t
> params
) {
1842 if (era
.type() != typeid(std::shared_ptr
<DNSAction
>)) {
1843 throw std::runtime_error("addAction() can only be called with query-related actions, not response-related ones. Are you looking for addResponseAction()?");
1846 addAction(&g_ruleactions
, var
, boost::get
<std::shared_ptr
<DNSAction
> >(era
), params
);
1849 luaCtx
.writeFunction("addResponseAction", [](luadnsrule_t var
, boost::variant
<std::shared_ptr
<DNSAction
>, std::shared_ptr
<DNSResponseAction
> > era
, boost::optional
<luaruleparams_t
> params
) {
1850 if (era
.type() != typeid(std::shared_ptr
<DNSResponseAction
>)) {
1851 throw std::runtime_error("addResponseAction() can only be called with response-related actions, not query-related ones. Are you looking for addAction()?");
1854 addAction(&g_respruleactions
, var
, boost::get
<std::shared_ptr
<DNSResponseAction
> >(era
), params
);
1857 luaCtx
.writeFunction("addCacheHitResponseAction", [](luadnsrule_t var
, boost::variant
<std::shared_ptr
<DNSAction
>, std::shared_ptr
<DNSResponseAction
>> era
, boost::optional
<luaruleparams_t
> params
) {
1858 if (era
.type() != typeid(std::shared_ptr
<DNSResponseAction
>)) {
1859 throw std::runtime_error("addCacheHitResponseAction() can only be called with response-related actions, not query-related ones. Are you looking for addAction()?");
1862 addAction(&g_cachehitrespruleactions
, var
, boost::get
<std::shared_ptr
<DNSResponseAction
> >(era
), params
);
1865 luaCtx
.writeFunction("addSelfAnsweredResponseAction", [](luadnsrule_t var
, boost::variant
<std::shared_ptr
<DNSAction
>, std::shared_ptr
<DNSResponseAction
>> era
, boost::optional
<luaruleparams_t
> params
) {
1866 if (era
.type() != typeid(std::shared_ptr
<DNSResponseAction
>)) {
1867 throw std::runtime_error("addSelfAnsweredResponseAction() can only be called with response-related actions, not query-related ones. Are you looking for addAction()?");
1870 addAction(&g_selfansweredrespruleactions
, var
, boost::get
<std::shared_ptr
<DNSResponseAction
> >(era
), params
);
1873 luaCtx
.registerFunction
<void(DNSAction::*)()const>("printStats", [](const DNSAction
& ta
) {
1874 setLuaNoSideEffect();
1875 auto stats
= ta
.getStats();
1876 for(const auto& s
: stats
) {
1877 g_outputBuffer
+=s
.first
+"\t";
1878 if((uint64_t)s
.second
== s
.second
)
1879 g_outputBuffer
+= std::to_string((uint64_t)s
.second
)+"\n";
1881 g_outputBuffer
+= std::to_string(s
.second
)+"\n";
1885 luaCtx
.writeFunction("getAction", [](unsigned int num
) {
1886 setLuaNoSideEffect();
1887 boost::optional
<std::shared_ptr
<DNSAction
>> ret
;
1888 auto ruleactions
= g_ruleactions
.getCopy();
1889 if(num
< ruleactions
.size())
1890 ret
=ruleactions
[num
].d_action
;
1894 luaCtx
.registerFunction("getStats", &DNSAction::getStats
);
1895 luaCtx
.registerFunction("reload", &DNSAction::reload
);
1896 luaCtx
.registerFunction("reload", &DNSResponseAction::reload
);
1898 luaCtx
.writeFunction("LuaAction", [](LuaAction::func_t func
) {
1900 return std::shared_ptr
<DNSAction
>(new LuaAction(func
));
1903 luaCtx
.writeFunction("LuaFFIAction", [](LuaFFIAction::func_t func
) {
1905 return std::shared_ptr
<DNSAction
>(new LuaFFIAction(func
));
1908 luaCtx
.writeFunction("LuaFFIPerThreadAction", [](std::string code
) {
1910 return std::shared_ptr
<DNSAction
>(new LuaFFIPerThreadAction(code
));
1913 luaCtx
.writeFunction("SetNoRecurseAction", []() {
1914 return std::shared_ptr
<DNSAction
>(new SetNoRecurseAction
);
1917 luaCtx
.writeFunction("NoRecurseAction", []() {
1918 warnlog("access to NoRecurseAction is deprecated and will be removed in a future version, please use SetNoRecurseAction instead");
1919 return std::shared_ptr
<DNSAction
>(new SetNoRecurseAction
);
1922 luaCtx
.writeFunction("SetMacAddrAction", [](int code
) {
1923 return std::shared_ptr
<DNSAction
>(new SetMacAddrAction(code
));
1926 luaCtx
.writeFunction("MacAddrAction", [](int code
) {
1927 warnlog("access to MacAddrAction is deprecated and will be removed in a future version, please use SetMacAddrAction instead");
1928 return std::shared_ptr
<DNSAction
>(new SetMacAddrAction(code
));
1931 luaCtx
.writeFunction("PoolAction", [](const std::string
& a
) {
1932 return std::shared_ptr
<DNSAction
>(new PoolAction(a
));
1935 luaCtx
.writeFunction("QPSAction", [](int limit
) {
1936 return std::shared_ptr
<DNSAction
>(new QPSAction(limit
));
1939 luaCtx
.writeFunction("QPSPoolAction", [](int limit
, const std::string
& a
) {
1940 return std::shared_ptr
<DNSAction
>(new QPSPoolAction(limit
, a
));
1943 luaCtx
.writeFunction("SpoofAction", [](boost::variant
<std::string
,vector
<pair
<int, std::string
>>> inp
, boost::optional
<responseParams_t
> vars
) {
1944 vector
<ComboAddress
> addrs
;
1945 if(auto s
= boost::get
<std::string
>(&inp
)) {
1946 addrs
.push_back(ComboAddress(*s
));
1948 const auto& v
= boost::get
<vector
<pair
<int,std::string
>>>(inp
);
1949 for(const auto& a
: v
) {
1950 addrs
.push_back(ComboAddress(a
.second
));
1954 auto ret
= std::shared_ptr
<DNSAction
>(new SpoofAction(addrs
));
1955 auto sa
= std::dynamic_pointer_cast
<SpoofAction
>(ret
);
1956 parseResponseConfig(vars
, sa
->d_responseConfig
);
1960 luaCtx
.writeFunction("SpoofCNAMEAction", [](const std::string
& a
, boost::optional
<responseParams_t
> vars
) {
1961 auto ret
= std::shared_ptr
<DNSAction
>(new SpoofAction(DNSName(a
)));
1962 auto sa
= std::dynamic_pointer_cast
<SpoofAction
>(ret
);
1963 parseResponseConfig(vars
, sa
->d_responseConfig
);
1967 luaCtx
.writeFunction("SpoofRawAction", [](boost::variant
<std::string
,vector
<pair
<int, std::string
>>> inp
, boost::optional
<responseParams_t
> vars
) {
1968 vector
<string
> raws
;
1969 if(auto s
= boost::get
<std::string
>(&inp
)) {
1972 const auto& v
= boost::get
<vector
<pair
<int,std::string
>>>(inp
);
1973 for(const auto& raw
: v
) {
1974 raws
.push_back(raw
.second
);
1978 auto ret
= std::shared_ptr
<DNSAction
>(new SpoofAction(raws
));
1979 auto sa
= std::dynamic_pointer_cast
<SpoofAction
>(ret
);
1980 parseResponseConfig(vars
, sa
->d_responseConfig
);
1984 luaCtx
.writeFunction("DropAction", []() {
1985 return std::shared_ptr
<DNSAction
>(new DropAction
);
1988 luaCtx
.writeFunction("AllowAction", []() {
1989 return std::shared_ptr
<DNSAction
>(new AllowAction
);
1992 luaCtx
.writeFunction("NoneAction", []() {
1993 return std::shared_ptr
<DNSAction
>(new NoneAction
);
1996 luaCtx
.writeFunction("DelayAction", [](int msec
) {
1997 return std::shared_ptr
<DNSAction
>(new DelayAction(msec
));
2000 luaCtx
.writeFunction("TCAction", []() {
2001 return std::shared_ptr
<DNSAction
>(new TCAction
);
2004 luaCtx
.writeFunction("SetDisableValidationAction", []() {
2005 return std::shared_ptr
<DNSAction
>(new SetDisableValidationAction
);
2008 luaCtx
.writeFunction("DisableValidationAction", []() {
2009 warnlog("access to DisableValidationAction is deprecated and will be removed in a future version, please use SetDisableValidationAction instead");
2010 return std::shared_ptr
<DNSAction
>(new SetDisableValidationAction
);
2013 luaCtx
.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
) {
2014 return std::shared_ptr
<DNSAction
>(new LogAction(fname
? *fname
: "", binary
? *binary
: true, append
? *append
: false, buffered
? *buffered
: false, verboseOnly
? *verboseOnly
: true, includeTimestamp
? *includeTimestamp
: false));
2017 luaCtx
.writeFunction("LogResponseAction", [](boost::optional
<std::string
> fname
, boost::optional
<bool> append
, boost::optional
<bool> buffered
, boost::optional
<bool> verboseOnly
, boost::optional
<bool> includeTimestamp
) {
2018 return std::shared_ptr
<DNSResponseAction
>(new LogResponseAction(fname
? *fname
: "", append
? *append
: false, buffered
? *buffered
: false, verboseOnly
? *verboseOnly
: true, includeTimestamp
? *includeTimestamp
: false));
2021 luaCtx
.writeFunction("RCodeAction", [](uint8_t rcode
, boost::optional
<responseParams_t
> vars
) {
2022 auto ret
= std::shared_ptr
<DNSAction
>(new RCodeAction(rcode
));
2023 auto rca
= std::dynamic_pointer_cast
<RCodeAction
>(ret
);
2024 parseResponseConfig(vars
, rca
->d_responseConfig
);
2028 luaCtx
.writeFunction("ERCodeAction", [](uint8_t rcode
, boost::optional
<responseParams_t
> vars
) {
2029 auto ret
= std::shared_ptr
<DNSAction
>(new ERCodeAction(rcode
));
2030 auto erca
= std::dynamic_pointer_cast
<ERCodeAction
>(ret
);
2031 parseResponseConfig(vars
, erca
->d_responseConfig
);
2035 luaCtx
.writeFunction("SetSkipCacheAction", []() {
2036 return std::shared_ptr
<DNSAction
>(new SetSkipCacheAction
);
2039 luaCtx
.writeFunction("SkipCacheAction", []() {
2040 warnlog("access to SkipCacheAction is deprecated and will be removed in a future version, please use SetSkipCacheAction instead");
2041 return std::shared_ptr
<DNSAction
>(new SetSkipCacheAction
);
2044 luaCtx
.writeFunction("SetSkipCacheResponseAction", []() {
2045 return std::shared_ptr
<DNSResponseAction
>(new SetSkipCacheResponseAction
);
2048 luaCtx
.writeFunction("SetTempFailureCacheTTLAction", [](int maxTTL
) {
2049 return std::shared_ptr
<DNSAction
>(new SetTempFailureCacheTTLAction(maxTTL
));
2052 luaCtx
.writeFunction("TempFailureCacheTTLAction", [](int maxTTL
) {
2053 warnlog("access to TempFailureCacheTTLAction is deprecated and will be removed in a future version, please use SetTempFailureCacheTTLAction instead");
2054 return std::shared_ptr
<DNSAction
>(new SetTempFailureCacheTTLAction(maxTTL
));
2057 luaCtx
.writeFunction("DropResponseAction", []() {
2058 return std::shared_ptr
<DNSResponseAction
>(new DropResponseAction
);
2061 luaCtx
.writeFunction("AllowResponseAction", []() {
2062 return std::shared_ptr
<DNSResponseAction
>(new AllowResponseAction
);
2065 luaCtx
.writeFunction("DelayResponseAction", [](int msec
) {
2066 return std::shared_ptr
<DNSResponseAction
>(new DelayResponseAction(msec
));
2069 luaCtx
.writeFunction("LuaResponseAction", [](LuaResponseAction::func_t func
) {
2071 return std::shared_ptr
<DNSResponseAction
>(new LuaResponseAction(func
));
2074 luaCtx
.writeFunction("LuaFFIResponseAction", [](LuaFFIResponseAction::func_t func
) {
2076 return std::shared_ptr
<DNSResponseAction
>(new LuaFFIResponseAction(func
));
2079 luaCtx
.writeFunction("LuaFFIPerThreadResponseAction", [](std::string code
) {
2081 return std::shared_ptr
<DNSResponseAction
>(new LuaFFIPerThreadResponseAction(code
));
2084 luaCtx
.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
) {
2086 // avoids potentially-evaluated-expression warning with clang.
2087 RemoteLoggerInterface
& rl
= *logger
.get();
2088 if (typeid(rl
) != typeid(RemoteLogger
)) {
2089 // We could let the user do what he wants, but wrapping PowerDNS Protobuf inside a FrameStream tagged as dnstap is logically wrong.
2090 throw std::runtime_error(std::string("RemoteLogAction only takes RemoteLogger. For other types, please look at DnstapLogAction."));
2094 std::string serverID
;
2095 std::string ipEncryptKey
;
2097 if (vars
->count("serverID")) {
2098 serverID
= boost::get
<std::string
>((*vars
)["serverID"]);
2100 if (vars
->count("ipEncryptKey")) {
2101 ipEncryptKey
= boost::get
<std::string
>((*vars
)["ipEncryptKey"]);
2105 return std::shared_ptr
<DNSAction
>(new RemoteLogAction(logger
, alterFunc
, serverID
, ipEncryptKey
));
2108 luaCtx
.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
) {
2110 // avoids potentially-evaluated-expression warning with clang.
2111 RemoteLoggerInterface
& rl
= *logger
.get();
2112 if (typeid(rl
) != typeid(RemoteLogger
)) {
2113 // We could let the user do what he wants, but wrapping PowerDNS Protobuf inside a FrameStream tagged as dnstap is logically wrong.
2114 throw std::runtime_error("RemoteLogResponseAction only takes RemoteLogger. For other types, please look at DnstapLogResponseAction.");
2118 std::string serverID
;
2119 std::string ipEncryptKey
;
2121 if (vars
->count("serverID")) {
2122 serverID
= boost::get
<std::string
>((*vars
)["serverID"]);
2124 if (vars
->count("ipEncryptKey")) {
2125 ipEncryptKey
= boost::get
<std::string
>((*vars
)["ipEncryptKey"]);
2129 return std::shared_ptr
<DNSResponseAction
>(new RemoteLogResponseAction(logger
, alterFunc
, serverID
, ipEncryptKey
, includeCNAME
? *includeCNAME
: false));
2132 luaCtx
.writeFunction("DnstapLogAction", [](const std::string
& identity
, std::shared_ptr
<RemoteLoggerInterface
> logger
, boost::optional
<std::function
<void(DNSQuestion
*, DnstapMessage
*)> > alterFunc
) {
2133 return std::shared_ptr
<DNSAction
>(new DnstapLogAction(identity
, logger
, alterFunc
));
2136 luaCtx
.writeFunction("DnstapLogResponseAction", [](const std::string
& identity
, std::shared_ptr
<RemoteLoggerInterface
> logger
, boost::optional
<std::function
<void(DNSResponse
*, DnstapMessage
*)> > alterFunc
) {
2137 return std::shared_ptr
<DNSResponseAction
>(new DnstapLogResponseAction(identity
, logger
, alterFunc
));
2140 luaCtx
.writeFunction("TeeAction", [](const std::string
& remote
, boost::optional
<bool> addECS
) {
2141 return std::shared_ptr
<DNSAction
>(new TeeAction(ComboAddress(remote
, 53), addECS
? *addECS
: false));
2144 luaCtx
.writeFunction("SetECSPrefixLengthAction", [](uint16_t v4PrefixLength
, uint16_t v6PrefixLength
) {
2145 return std::shared_ptr
<DNSAction
>(new SetECSPrefixLengthAction(v4PrefixLength
, v6PrefixLength
));
2148 luaCtx
.writeFunction("ECSPrefixLengthAction", [](uint16_t v4PrefixLength
, uint16_t v6PrefixLength
) {
2149 warnlog("access to ECSPrefixLengthAction is deprecated and will be removed in a future version, please use SetECSPrefixLengthAction instead");
2150 return std::shared_ptr
<DNSAction
>(new SetECSPrefixLengthAction(v4PrefixLength
, v6PrefixLength
));
2153 luaCtx
.writeFunction("SetECSOverrideAction", [](bool ecsOverride
) {
2154 return std::shared_ptr
<DNSAction
>(new SetECSOverrideAction(ecsOverride
));
2157 luaCtx
.writeFunction("ECSOverrideAction", [](bool ecsOverride
) {
2158 warnlog("access to ECSOverrideAction is deprecated and will be removed in a future version, please use SetECSOverrideAction instead");
2159 return std::shared_ptr
<DNSAction
>(new SetECSOverrideAction(ecsOverride
));
2162 luaCtx
.writeFunction("SetDisableECSAction", []() {
2163 return std::shared_ptr
<DNSAction
>(new SetDisableECSAction());
2166 luaCtx
.writeFunction("DisableECSAction", []() {
2167 warnlog("access to DisableECSAction is deprecated and will be removed in a future version, please use SetDisableECSAction instead");
2168 return std::shared_ptr
<DNSAction
>(new SetDisableECSAction());
2171 luaCtx
.writeFunction("SetECSAction", [](const std::string v4
, boost::optional
<std::string
> v6
) {
2173 return std::shared_ptr
<DNSAction
>(new SetECSAction(Netmask(v4
), Netmask(*v6
)));
2175 return std::shared_ptr
<DNSAction
>(new SetECSAction(Netmask(v4
)));
2178 luaCtx
.writeFunction("SNMPTrapAction", [](boost::optional
<std::string
> reason
) {
2179 #ifdef HAVE_NET_SNMP
2180 return std::shared_ptr
<DNSAction
>(new SNMPTrapAction(reason
? *reason
: ""));
2182 throw std::runtime_error("NET SNMP support is required to use SNMPTrapAction()");
2183 #endif /* HAVE_NET_SNMP */
2186 luaCtx
.writeFunction("SNMPTrapResponseAction", [](boost::optional
<std::string
> reason
) {
2187 #ifdef HAVE_NET_SNMP
2188 return std::shared_ptr
<DNSResponseAction
>(new SNMPTrapResponseAction(reason
? *reason
: ""));
2190 throw std::runtime_error("NET SNMP support is required to use SNMPTrapResponseAction()");
2191 #endif /* HAVE_NET_SNMP */
2194 luaCtx
.writeFunction("SetTagAction", [](std::string tag
, std::string value
) {
2195 return std::shared_ptr
<DNSAction
>(new SetTagAction(tag
, value
));
2198 luaCtx
.writeFunction("TagAction", [](std::string tag
, std::string value
) {
2199 warnlog("access to TagAction is deprecated and will be removed in a future version, please use SetTagAction instead");
2200 return std::shared_ptr
<DNSAction
>(new SetTagAction(tag
, value
));
2203 luaCtx
.writeFunction("SetTagResponseAction", [](std::string tag
, std::string value
) {
2204 return std::shared_ptr
<DNSResponseAction
>(new SetTagResponseAction(tag
, value
));
2207 luaCtx
.writeFunction("TagResponseAction", [](std::string tag
, std::string value
) {
2208 warnlog("access to TagResponseAction is deprecated and will be removed in a future version, please use SetTagResponseAction instead");
2209 return std::shared_ptr
<DNSResponseAction
>(new SetTagResponseAction(tag
, value
));
2212 luaCtx
.writeFunction("ContinueAction", [](std::shared_ptr
<DNSAction
> action
) {
2213 return std::shared_ptr
<DNSAction
>(new ContinueAction(action
));
2216 #ifdef HAVE_DNS_OVER_HTTPS
2217 luaCtx
.writeFunction("HTTPStatusAction", [](uint16_t status
, std::string body
, boost::optional
<std::string
> contentType
, boost::optional
<responseParams_t
> vars
) {
2218 auto ret
= std::shared_ptr
<DNSAction
>(new HTTPStatusAction(status
, PacketBuffer(body
.begin(), body
.end()), contentType
? *contentType
: ""));
2219 auto hsa
= std::dynamic_pointer_cast
<HTTPStatusAction
>(ret
);
2220 parseResponseConfig(vars
, hsa
->d_responseConfig
);
2223 #endif /* HAVE_DNS_OVER_HTTPS */
2225 luaCtx
.writeFunction("KeyValueStoreLookupAction", [](std::shared_ptr
<KeyValueStore
>& kvs
, std::shared_ptr
<KeyValueLookupKey
>& lookupKey
, const std::string
& destinationTag
) {
2226 return std::shared_ptr
<DNSAction
>(new KeyValueStoreLookupAction(kvs
, lookupKey
, destinationTag
));
2229 luaCtx
.writeFunction("NegativeAndSOAAction", [](bool nxd
, const std::string
& zone
, uint32_t ttl
, const std::string
& mname
, const std::string
& rname
, uint32_t serial
, uint32_t refresh
, uint32_t retry
, uint32_t expire
, uint32_t minimum
, boost::optional
<responseParams_t
> vars
) {
2230 auto ret
= std::shared_ptr
<DNSAction
>(new NegativeAndSOAAction(nxd
, DNSName(zone
), ttl
, DNSName(mname
), DNSName(rname
), serial
, refresh
, retry
, expire
, minimum
));
2231 auto action
= std::dynamic_pointer_cast
<NegativeAndSOAAction
>(ret
);
2232 parseResponseConfig(vars
, action
->d_responseConfig
);
2236 luaCtx
.writeFunction("SetNegativeAndSOAAction", [](bool nxd
, const std::string
& zone
, uint32_t ttl
, const std::string
& mname
, const std::string
& rname
, uint32_t serial
, uint32_t refresh
, uint32_t retry
, uint32_t expire
, uint32_t minimum
, boost::optional
<responseParams_t
> vars
) {
2237 warnlog("access to SetNegativeAndSOAAction is deprecated and will be removed in a future version, please use NegativeAndSOAAction instead");
2238 auto ret
= std::shared_ptr
<DNSAction
>(new NegativeAndSOAAction(nxd
, DNSName(zone
), ttl
, DNSName(mname
), DNSName(rname
), serial
, refresh
, retry
, expire
, minimum
));
2239 auto action
= std::dynamic_pointer_cast
<NegativeAndSOAAction
>(ret
);
2240 parseResponseConfig(vars
, action
->d_responseConfig
);
2244 luaCtx
.writeFunction("SetProxyProtocolValuesAction", [](const std::vector
<std::pair
<uint8_t, std::string
>>& values
) {
2245 return std::shared_ptr
<DNSAction
>(new SetProxyProtocolValuesAction(values
));
2248 luaCtx
.writeFunction("SetAdditionalProxyProtocolValueAction", [](uint8_t type
, const std::string
& value
) {
2249 return std::shared_ptr
<DNSAction
>(new SetAdditionalProxyProtocolValueAction(type
, value
));