2 * This file is part of PowerDNS or dnsdist.
3 * Copyright -- PowerDNS.COM B.V. and its contributors
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
9 * In addition, for the avoidance of any doubt, permission is granted to
10 * link this program with OpenSSL and to (re)distribute the binaries
11 * produced as the result of such linking.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23 #include "dnsdist-ecs.hh"
26 #include "ednsoptions.hh"
28 #include "remote_logger.hh"
29 #include "dnsdist-protobuf.hh"
30 #include "dnsparser.hh"
32 class MaxQPSIPRule : public DNSRule
35 MaxQPSIPRule(unsigned int qps, unsigned int burst, unsigned int ipv4trunc=32, unsigned int ipv6trunc=64) :
36 d_qps(qps), d_burst(burst), d_ipv4trunc(ipv4trunc), d_ipv6trunc(ipv6trunc)
38 pthread_rwlock_init(&d_lock, 0);
41 bool matches(const DNSQuestion* dq) const override
43 ComboAddress zeroport(*dq->remote);
44 zeroport.sin4.sin_port=0;
45 zeroport.truncate(zeroport.sin4.sin_family == AF_INET ? d_ipv4trunc : d_ipv6trunc);
48 const auto iter = d_limits.find(zeroport);
49 if (iter != d_limits.end()) {
50 return !iter->second.check();
55 auto iter = d_limits.find(zeroport);
56 if(iter == d_limits.end()) {
57 iter=d_limits.insert({zeroport,QPSLimiter(d_qps, d_burst)}).first;
59 return !iter->second.check();
63 string toString() const override
65 return "IP (/"+std::to_string(d_ipv4trunc)+", /"+std::to_string(d_ipv6trunc)+") match for QPS over " + std::to_string(d_qps) + " burst "+ std::to_string(d_burst);
70 mutable pthread_rwlock_t d_lock;
71 mutable std::map<ComboAddress, QPSLimiter> d_limits;
72 unsigned int d_qps, d_burst, d_ipv4trunc, d_ipv6trunc;
76 class MaxQPSRule : public DNSRule
79 MaxQPSRule(unsigned int qps)
83 MaxQPSRule(unsigned int qps, unsigned int burst)
88 bool matches(const DNSQuestion* qd) const override
93 string toString() const override
95 return "Max " + std::to_string(d_qps.getRate()) + " qps";
100 mutable QPSLimiter d_qps;
103 class NMGRule : public DNSRule
106 NMGRule(const NetmaskGroup& nmg) : d_nmg(nmg) {}
111 class NetmaskGroupRule : public NMGRule
114 NetmaskGroupRule(const NetmaskGroup& nmg, bool src) : NMGRule(nmg)
118 bool matches(const DNSQuestion* dq) const override
121 return d_nmg.match(*dq->local);
123 return d_nmg.match(*dq->remote);
126 string toString() const override
129 return "Dst: "+d_nmg.toString();
131 return "Src: "+d_nmg.toString();
137 class TimedIPSetRule : public DNSRule, boost::noncopyable
141 IPv6(const ComboAddress& ca)
143 static_assert(sizeof(*this)==16, "IPv6 struct has wrong size");
144 memcpy((char*)this, ca.sin6.sin6_addr.s6_addr, 16);
146 bool operator==(const IPv6& rhs) const
148 return a==rhs.a && b==rhs.b;
156 pthread_rwlock_init(&d_lock4, 0);
157 pthread_rwlock_init(&d_lock6, 0);
159 bool matches(const DNSQuestion* dq) const override
161 if(dq->remote->sin4.sin_family == AF_INET) {
162 ReadLock rl(&d_lock4);
163 auto fnd = d_ip4s.find(dq->remote->sin4.sin_addr.s_addr);
164 if(fnd == d_ip4s.end()) {
167 return time(0) < fnd->second;
169 ReadLock rl(&d_lock6);
170 auto fnd = d_ip6s.find({*dq->remote});
171 if(fnd == d_ip6s.end()) {
174 return time(0) < fnd->second;
178 void add(const ComboAddress& ca, time_t ttd)
180 // think twice before adding templates here
181 if(ca.sin4.sin_family == AF_INET) {
182 WriteLock rl(&d_lock4);
183 auto res=d_ip4s.insert({ca.sin4.sin_addr.s_addr, ttd});
184 if(!res.second && (time_t)res.first->second < ttd)
185 res.first->second = (uint32_t)ttd;
188 WriteLock rl(&d_lock6);
189 auto res=d_ip6s.insert({{ca}, ttd});
190 if(!res.second && (time_t)res.first->second < ttd)
191 res.first->second = (uint32_t)ttd;
195 void remove(const ComboAddress& ca)
197 if(ca.sin4.sin_family == AF_INET) {
198 WriteLock rl(&d_lock4);
199 d_ip4s.erase(ca.sin4.sin_addr.s_addr);
202 WriteLock rl(&d_lock6);
210 WriteLock rl(&d_lock4);
213 WriteLock rl(&d_lock6);
221 WriteLock rl(&d_lock4);
223 for(auto iter = d_ip4s.begin(); iter != d_ip4s.end(); ) {
224 if(iter->second < now)
225 iter=d_ip4s.erase(iter);
233 WriteLock rl(&d_lock6);
235 for(auto iter = d_ip6s.begin(); iter != d_ip6s.end(); ) {
236 if(iter->second < now)
237 iter=d_ip6s.erase(iter);
246 string toString() const override
251 ReadLock rl(&d_lock4);
252 for(const auto& ip : d_ip4s)
257 ReadLock rl(&d_lock6);
258 for(const auto& ip : d_ip6s)
263 return "Src: "+std::to_string(count)+" ips";
268 std::size_t operator()(const IPv6& ip) const
270 auto ah=std::hash<uint64_t>{}(ip.a);
271 auto bh=std::hash<uint64_t>{}(ip.b);
275 std::unordered_map<IPv6, time_t, IPv6Hash> d_ip6s;
276 std::unordered_map<uint32_t, time_t> d_ip4s;
277 mutable pthread_rwlock_t d_lock4;
278 mutable pthread_rwlock_t d_lock6;
282 class AllRule : public DNSRule
286 bool matches(const DNSQuestion* dq) const override
291 string toString() const override
299 class DNSSECRule : public DNSRule
306 bool matches(const DNSQuestion* dq) const override
308 return dq->dh->cd || (getEDNSZ((const char*)dq->dh, dq->len) & EDNS_HEADER_FLAG_DO); // turns out dig sets ad by default..
311 string toString() const override
317 class AndRule : public DNSRule
320 AndRule(const vector<pair<int, shared_ptr<DNSRule> > >& rules)
322 for(const auto& r : rules)
323 d_rules.push_back(r.second);
326 bool matches(const DNSQuestion* dq) const override
328 auto iter = d_rules.begin();
329 for(; iter != d_rules.end(); ++iter)
330 if(!(*iter)->matches(dq))
332 return iter == d_rules.end();
335 string toString() const override
338 for(const auto& rule : d_rules) {
341 ret += "("+ rule->toString()+")";
347 vector<std::shared_ptr<DNSRule> > d_rules;
352 class OrRule : public DNSRule
355 OrRule(const vector<pair<int, shared_ptr<DNSRule> > >& rules)
357 for(const auto& r : rules)
358 d_rules.push_back(r.second);
361 bool matches(const DNSQuestion* dq) const override
363 auto iter = d_rules.begin();
364 for(; iter != d_rules.end(); ++iter)
365 if((*iter)->matches(dq))
370 string toString() const override
373 for(const auto& rule : d_rules) {
376 ret += "("+ rule->toString()+")";
382 vector<std::shared_ptr<DNSRule> > d_rules;
387 class RegexRule : public DNSRule
390 RegexRule(const std::string& regex) : d_regex(regex), d_visual(regex)
394 bool matches(const DNSQuestion* dq) const override
396 return d_regex.match(dq->qname->toStringNoDot());
399 string toString() const override
401 return "Regex: "+d_visual;
410 class RE2Rule : public DNSRule
413 RE2Rule(const std::string& re2) : d_re2(re2, RE2::Latin1), d_visual(re2)
417 bool matches(const DNSQuestion* dq) const override
419 return RE2::FullMatch(dq->qname->toStringNoDot(), d_re2);
422 string toString() const override
424 return "RE2 match: "+d_visual;
433 class SuffixMatchNodeRule : public DNSRule
436 SuffixMatchNodeRule(const SuffixMatchNode& smn, bool quiet=false) : d_smn(smn), d_quiet(quiet)
439 bool matches(const DNSQuestion* dq) const override
441 return d_smn.check(*dq->qname);
443 string toString() const override
446 return "qname==in-set";
448 return "qname in "+d_smn.toString();
451 SuffixMatchNode d_smn;
455 class QNameRule : public DNSRule
458 QNameRule(const DNSName& qname) : d_qname(qname)
461 bool matches(const DNSQuestion* dq) const override
463 return d_qname==*dq->qname;
465 string toString() const override
467 return "qname=="+d_qname.toString();
474 class QTypeRule : public DNSRule
477 QTypeRule(uint16_t qtype) : d_qtype(qtype)
480 bool matches(const DNSQuestion* dq) const override
482 return d_qtype == dq->qtype;
484 string toString() const override
487 return "qtype=="+qt.getName();
493 class QClassRule : public DNSRule
496 QClassRule(uint16_t qclass) : d_qclass(qclass)
499 bool matches(const DNSQuestion* dq) const override
501 return d_qclass == dq->qclass;
503 string toString() const override
505 return "qclass=="+std::to_string(d_qclass);
511 class OpcodeRule : public DNSRule
514 OpcodeRule(uint8_t opcode) : d_opcode(opcode)
517 bool matches(const DNSQuestion* dq) const override
519 return d_opcode == dq->dh->opcode;
521 string toString() const override
523 return "opcode=="+std::to_string(d_opcode);
529 class TCPRule : public DNSRule
532 TCPRule(bool tcp): d_tcp(tcp)
535 bool matches(const DNSQuestion* dq) const override
537 return dq->tcp == d_tcp;
539 string toString() const override
541 return (d_tcp ? "TCP" : "UDP");
548 class NotRule : public DNSRule
551 NotRule(shared_ptr<DNSRule>& rule): d_rule(rule)
554 bool matches(const DNSQuestion* dq) const override
556 return !d_rule->matches(dq);
558 string toString() const override
560 return "!("+ d_rule->toString()+")";
563 shared_ptr<DNSRule> d_rule;
566 class RecordsCountRule : public DNSRule
569 RecordsCountRule(uint8_t section, uint16_t minCount, uint16_t maxCount): d_minCount(minCount), d_maxCount(maxCount), d_section(section)
572 bool matches(const DNSQuestion* dq) const override
577 count = ntohs(dq->dh->qdcount);
580 count = ntohs(dq->dh->ancount);
583 count = ntohs(dq->dh->nscount);
586 count = ntohs(dq->dh->arcount);
589 return count >= d_minCount && count <= d_maxCount;
591 string toString() const override
608 return std::to_string(d_minCount) + " <= records in " + section + " <= "+ std::to_string(d_maxCount);
616 class RecordsTypeCountRule : public DNSRule
619 RecordsTypeCountRule(uint8_t section, uint16_t type, uint16_t minCount, uint16_t maxCount): d_type(type), d_minCount(minCount), d_maxCount(maxCount), d_section(section)
622 bool matches(const DNSQuestion* dq) const override
627 count = ntohs(dq->dh->qdcount);
630 count = ntohs(dq->dh->ancount);
633 count = ntohs(dq->dh->nscount);
636 count = ntohs(dq->dh->arcount);
639 if (count < d_minCount) {
642 count = getRecordsOfTypeCount(reinterpret_cast<const char*>(dq->dh), dq->len, d_section, d_type);
643 return count >= d_minCount && count <= d_maxCount;
645 string toString() const override
662 return std::to_string(d_minCount) + " <= " + QType(d_type).getName() + " records in " + section + " <= "+ std::to_string(d_maxCount);
671 class TrailingDataRule : public DNSRule
677 bool matches(const DNSQuestion* dq) const override
679 uint16_t length = getDNSPacketLength(reinterpret_cast<const char*>(dq->dh), dq->len);
680 return length < dq->len;
682 string toString() const override
684 return "trailing data";
688 class QNameLabelsCountRule : public DNSRule
691 QNameLabelsCountRule(unsigned int minLabelsCount, unsigned int maxLabelsCount): d_min(minLabelsCount), d_max(maxLabelsCount)
694 bool matches(const DNSQuestion* dq) const override
696 unsigned int count = dq->qname->countLabels();
697 return count < d_min || count > d_max;
699 string toString() const override
701 return "labels count < " + std::to_string(d_min) + " || labels count > " + std::to_string(d_max);
708 class QNameWireLengthRule : public DNSRule
711 QNameWireLengthRule(size_t min, size_t max): d_min(min), d_max(max)
714 bool matches(const DNSQuestion* dq) const override
716 size_t const wirelength = dq->qname->wirelength();
717 return wirelength < d_min || wirelength > d_max;
719 string toString() const override
721 return "wire length < " + std::to_string(d_min) + " || wire length > " + std::to_string(d_max);
728 class RCodeRule : public DNSRule
731 RCodeRule(int rcode) : d_rcode(rcode)
734 bool matches(const DNSQuestion* dq) const override
736 return d_rcode == dq->dh->rcode;
738 string toString() const override
740 return "rcode=="+RCode::to_s(d_rcode);
746 class RDRule : public DNSRule
752 bool matches(const DNSQuestion* dq) const override
754 return dq->dh->rd == 1;
756 string toString() const override
763 class ProbaRule : public DNSRule
766 ProbaRule(double proba) : d_proba(proba)
769 bool matches(const DNSQuestion* dq) const override;
770 string toString() const override;
775 class DropAction : public DNSAction
778 DNSAction::Action operator()(DNSQuestion* dq, string* ruleresult) const override
782 string toString() const override
788 class AllowAction : public DNSAction
791 DNSAction::Action operator()(DNSQuestion* dq, string* ruleresult) const override
793 return Action::Allow;
795 string toString() const override
802 class QPSAction : public DNSAction
805 QPSAction(int limit) : d_qps(limit, limit)
807 DNSAction::Action operator()(DNSQuestion* dq, string* ruleresult) const override
814 string toString() const override
816 return "qps limit to "+std::to_string(d_qps.getRate());
822 class DelayAction : public DNSAction
825 DelayAction(int msec) : d_msec(msec)
827 DNSAction::Action operator()(DNSQuestion* dq, string* ruleresult) const override
829 *ruleresult=std::to_string(d_msec);
830 return Action::Delay;
832 string toString() const override
834 return "delay by "+std::to_string(d_msec)+ " msec";
841 class TeeAction : public DNSAction
844 TeeAction(const ComboAddress& ca, bool addECS=false);
845 ~TeeAction() override;
846 DNSAction::Action operator()(DNSQuestion* dq, string* ruleresult) const override;
847 string toString() const override;
848 std::unordered_map<string, double> getStats() const override;
851 ComboAddress d_remote;
852 std::thread d_worker;
856 mutable std::atomic<unsigned long> d_senderrors{0};
857 unsigned long d_recverrors{0};
858 mutable std::atomic<unsigned long> d_queries{0};
859 unsigned long d_responses{0};
860 unsigned long d_nxdomains{0};
861 unsigned long d_servfails{0};
862 unsigned long d_refuseds{0};
863 unsigned long d_formerrs{0};
864 unsigned long d_notimps{0};
865 unsigned long d_noerrors{0};
866 mutable unsigned long d_tcpdrops{0};
867 unsigned long d_otherrcode{0};
868 std::atomic<bool> d_pleaseQuit{false};
869 bool d_addECS{false};
872 class PoolAction : public DNSAction
875 PoolAction(const std::string& pool) : d_pool(pool) {}
876 DNSAction::Action operator()(DNSQuestion* dq, string* ruleresult) const override
881 string toString() const override
883 return "to pool "+d_pool;
891 class QPSPoolAction : public DNSAction
894 QPSPoolAction(unsigned int limit, const std::string& pool) : d_qps(limit, limit), d_pool(pool) {}
895 DNSAction::Action operator()(DNSQuestion* dq, string* ruleresult) const override
904 string toString() const override
906 return "max " +std::to_string(d_qps.getRate())+" to pool "+d_pool;
914 class RCodeAction : public DNSAction
917 RCodeAction(int rcode) : d_rcode(rcode) {}
918 DNSAction::Action operator()(DNSQuestion* dq, string* ruleresult) const override
920 dq->dh->rcode = d_rcode;
921 dq->dh->qr = true; // for good measure
922 return Action::HeaderModify;
924 string toString() const override
926 return "set rcode "+std::to_string(d_rcode);
933 class TCAction : public DNSAction
936 DNSAction::Action operator()(DNSQuestion* dq, string* ruleresult) const override
938 return Action::Truncate;
940 string toString() const override
942 return "tc=1 answer";
946 class SpoofAction : public DNSAction
949 SpoofAction(const vector<ComboAddress>& addrs) : d_addrs(addrs)
953 SpoofAction(const string& cname): d_cname(cname) { }
955 DNSAction::Action operator()(DNSQuestion* dq, string* ruleresult) const override
957 uint16_t qtype = dq->qtype;
958 // do we even have a response?
959 if(d_cname.empty() && !std::count_if(d_addrs.begin(), d_addrs.end(), [qtype](const ComboAddress& a)
961 return (qtype == QType::ANY || ((a.sin4.sin_family == AF_INET && qtype == QType::A) ||
962 (a.sin4.sin_family == AF_INET6 && qtype == QType::AAAA)));
966 vector<ComboAddress> addrs;
967 unsigned int totrdatalen=0;
968 if (!d_cname.empty()) {
969 qtype = QType::CNAME;
970 totrdatalen += d_cname.toDNSString().size();
972 for(const auto& addr : d_addrs) {
973 if(qtype != QType::ANY && ((addr.sin4.sin_family == AF_INET && qtype != QType::A) ||
974 (addr.sin4.sin_family == AF_INET6 && qtype != QType::AAAA)))
976 totrdatalen += addr.sin4.sin_family == AF_INET ? sizeof(addr.sin4.sin_addr.s_addr) : sizeof(addr.sin6.sin6_addr.s6_addr);
977 addrs.push_back(addr);
982 random_shuffle(addrs.begin(), addrs.end());
984 unsigned int consumed=0;
985 DNSName ignore((char*)dq->dh, dq->len, sizeof(dnsheader), false, 0, 0, &consumed);
987 if (dq->size < (sizeof(dnsheader) + consumed + 4 + ((d_cname.empty() ? 0 : 1) + addrs.size())*12 /* recordstart */ + totrdatalen)) {
991 dq->len = sizeof(dnsheader) + consumed + 4; // there goes your EDNS
992 char* dest = ((char*)dq->dh) + dq->len;
994 dq->dh->qr = true; // for good measure
995 dq->dh->ra = dq->dh->rd; // for good measure
998 dq->dh->arcount = 0; // for now, forget about your EDNS, we're marching over it
1000 if(qtype == QType::CNAME) {
1001 string wireData = d_cname.toDNSString(); // Note! This doesn't do compression!
1002 const unsigned char recordstart[]={0xc0, 0x0c, // compressed name
1003 0, (unsigned char) qtype,
1004 0, QClass::IN, // IN
1006 0, (unsigned char)wireData.length()};
1007 static_assert(sizeof(recordstart) == 12, "sizeof(recordstart) must be equal to 12, otherwise the above check is invalid");
1009 memcpy(dest, recordstart, sizeof(recordstart));
1010 dest += sizeof(recordstart);
1011 memcpy(dest, wireData.c_str(), wireData.length());
1012 dq->len += wireData.length() + sizeof(recordstart);
1016 for(const auto& addr : addrs) {
1017 unsigned char rdatalen = addr.sin4.sin_family == AF_INET ? sizeof(addr.sin4.sin_addr.s_addr) : sizeof(addr.sin6.sin6_addr.s6_addr);
1018 const unsigned char recordstart[]={0xc0, 0x0c, // compressed name
1019 0, (unsigned char) (addr.sin4.sin_family == AF_INET ? QType::A : QType::AAAA),
1020 0, QClass::IN, // IN
1023 static_assert(sizeof(recordstart) == 12, "sizeof(recordstart) must be equal to 12, otherwise the above check is invalid");
1025 memcpy(dest, recordstart, sizeof(recordstart));
1026 dest += sizeof(recordstart);
1029 addr.sin4.sin_family == AF_INET ? (void*)&addr.sin4.sin_addr.s_addr : (void*)&addr.sin6.sin6_addr.s6_addr,
1032 dq->len += rdatalen + sizeof(recordstart);
1037 dq->dh->ancount = htons(dq->dh->ancount);
1039 return Action::HeaderModify;
1042 string toString() const override
1044 string ret = "spoof in ";
1045 if(!d_cname.empty()) {
1046 ret+=d_cname.toString()+ " ";
1048 for(const auto& a : d_addrs)
1049 ret += a.toString()+" ";
1054 std::vector<ComboAddress> d_addrs;
1058 class MacAddrAction : public DNSAction
1061 MacAddrAction(uint16_t code) : d_code(code)
1063 DNSAction::Action operator()(DNSQuestion* dq, string* ruleresult) const override
1066 return Action::None;
1068 string mac = getMACAddress(*dq->remote);
1070 return Action::None;
1073 generateEDNSOption(d_code, mac, optRData);
1076 generateOptRR(optRData, res);
1078 if ((dq->size - dq->len) < res.length())
1079 return Action::None;
1081 dq->dh->arcount = htons(1);
1082 char* dest = ((char*)dq->dh) + dq->len;
1083 memcpy(dest, res.c_str(), res.length());
1084 dq->len += res.length();
1086 return Action::None;
1088 string toString() const override
1090 return "add EDNS MAC (code="+std::to_string(d_code)+")";
1096 class NoRecurseAction : public DNSAction
1099 DNSAction::Action operator()(DNSQuestion* dq, string* ruleresult) const override
1102 return Action::None;
1104 string toString() const override
1110 class LogAction : public DNSAction, public boost::noncopyable
1113 LogAction() : d_fp(0)
1116 LogAction(const std::string& str, bool binary=true, bool append=false, bool buffered=true) : d_fname(str), d_binary(binary)
1121 d_fp = fopen(str.c_str(), "a+");
1123 d_fp = fopen(str.c_str(), "w");
1125 throw std::runtime_error("Unable to open file '"+str+"' for logging: "+string(strerror(errno)));
1129 ~LogAction() override
1134 DNSAction::Action operator()(DNSQuestion* dq, string* ruleresult) const override
1137 vinfolog("Packet from %s for %s %s with id %d", dq->remote->toStringWithPort(), dq->qname->toString(), QType(dq->qtype).getName(), dq->dh->id);
1141 string out = dq->qname->toDNSString();
1142 fwrite(out.c_str(), 1, out.size(), d_fp);
1143 fwrite((void*)&dq->qtype, 1, 2, d_fp);
1146 fprintf(d_fp, "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);
1149 return Action::None;
1151 string toString() const override
1153 if (!d_fname.empty()) {
1154 return "log to " + d_fname;
1161 bool d_binary{true};
1165 class DisableValidationAction : public DNSAction
1168 DNSAction::Action operator()(DNSQuestion* dq, string* ruleresult) const override
1171 return Action::None;
1173 string toString() const override
1179 class SkipCacheAction : public DNSAction
1182 DNSAction::Action operator()(DNSQuestion* dq, string* ruleresult) const override
1184 dq->skipCache = true;
1185 return Action::None;
1187 string toString() const override
1189 return "skip cache";
1193 class ECSPrefixLengthAction : public DNSAction
1196 ECSPrefixLengthAction(uint16_t v4Length, uint16_t v6Length) : d_v4PrefixLength(v4Length), d_v6PrefixLength(v6Length)
1199 DNSAction::Action operator()(DNSQuestion* dq, string* ruleresult) const override
1201 dq->ecsPrefixLength = dq->remote->sin4.sin_family == AF_INET ? d_v4PrefixLength : d_v6PrefixLength;
1202 return Action::None;
1204 string toString() const override
1206 return "set ECS prefix length to " + std::to_string(d_v4PrefixLength) + "/" + std::to_string(d_v6PrefixLength);
1209 uint16_t d_v4PrefixLength;
1210 uint16_t d_v6PrefixLength;
1213 class ECSOverrideAction : public DNSAction
1216 ECSOverrideAction(bool ecsOverride) : d_ecsOverride(ecsOverride)
1219 DNSAction::Action operator()(DNSQuestion* dq, string* ruleresult) const override
1221 dq->ecsOverride = d_ecsOverride;
1222 return Action::None;
1224 string toString() const override
1226 return "set ECS override to " + std::to_string(d_ecsOverride);
1233 class DisableECSAction : public DNSAction
1236 DNSAction::Action operator()(DNSQuestion* dq, string* ruleresult) const override
1239 return Action::None;
1241 string toString() const override
1243 return "disable ECS";
1247 class RemoteLogAction : public DNSAction, public boost::noncopyable
1250 RemoteLogAction(std::shared_ptr<RemoteLogger> logger, boost::optional<std::function<void(const DNSQuestion&, DNSDistProtoBufMessage*)> > alterFunc): d_logger(logger), d_alterFunc(alterFunc)
1253 DNSAction::Action operator()(DNSQuestion* dq, string* ruleresult) const override
1255 #ifdef HAVE_PROTOBUF
1256 if (!dq->uniqueId) {
1257 dq->uniqueId = t_uuidGenerator();
1260 DNSDistProtoBufMessage message(*dq);
1263 std::lock_guard<std::mutex> lock(g_luamutex);
1264 (*d_alterFunc)(*dq, &message);
1268 message.serialize(data);
1269 d_logger->queueData(data);
1270 #endif /* HAVE_PROTOBUF */
1271 return Action::None;
1273 string toString() const override
1275 return "remote log to " + (d_logger ? d_logger->toString() : "");
1278 std::shared_ptr<RemoteLogger> d_logger;
1279 boost::optional<std::function<void(const DNSQuestion&, DNSDistProtoBufMessage*)> > d_alterFunc;
1282 class SNMPTrapAction : public DNSAction
1285 SNMPTrapAction(const std::string& reason): d_reason(reason)
1288 DNSAction::Action operator()(DNSQuestion* dq, string* ruleresult) const override
1290 if (g_snmpAgent && g_snmpTrapsEnabled) {
1291 g_snmpAgent->sendDNSTrap(*dq, d_reason);
1294 return Action::None;
1296 string toString() const override
1298 return "send SNMP trap";
1301 std::string d_reason;
1304 class RemoteLogResponseAction : public DNSResponseAction, public boost::noncopyable
1307 RemoteLogResponseAction(std::shared_ptr<RemoteLogger> logger, boost::optional<std::function<void(const DNSResponse&, DNSDistProtoBufMessage*)> > alterFunc, bool includeCNAME): d_logger(logger), d_alterFunc(alterFunc), d_includeCNAME(includeCNAME)
1310 DNSResponseAction::Action operator()(DNSResponse* dr, string* ruleresult) const override
1312 #ifdef HAVE_PROTOBUF
1313 if (!dr->uniqueId) {
1314 dr->uniqueId = t_uuidGenerator();
1317 DNSDistProtoBufMessage message(*dr, d_includeCNAME);
1320 std::lock_guard<std::mutex> lock(g_luamutex);
1321 (*d_alterFunc)(*dr, &message);
1325 message.serialize(data);
1326 d_logger->queueData(data);
1327 #endif /* HAVE_PROTOBUF */
1328 return Action::None;
1330 string toString() const override
1332 return "remote log response to " + (d_logger ? d_logger->toString() : "");
1335 std::shared_ptr<RemoteLogger> d_logger;
1336 boost::optional<std::function<void(const DNSResponse&, DNSDistProtoBufMessage*)> > d_alterFunc;
1337 bool d_includeCNAME;
1340 class DropResponseAction : public DNSResponseAction
1343 DNSResponseAction::Action operator()(DNSResponse* dr, string* ruleresult) const override
1345 return Action::Drop;
1347 string toString() const override
1353 class AllowResponseAction : public DNSResponseAction
1356 DNSResponseAction::Action operator()(DNSResponse* dr, string* ruleresult) const override
1358 return Action::Allow;
1360 string toString() const override
1366 class DelayResponseAction : public DNSResponseAction
1369 DelayResponseAction(int msec) : d_msec(msec)
1371 DNSResponseAction::Action operator()(DNSResponse* dr, string* ruleresult) const override
1373 *ruleresult=std::to_string(d_msec);
1374 return Action::Delay;
1376 string toString() const override
1378 return "delay by "+std::to_string(d_msec)+ " msec";
1384 class SNMPTrapResponseAction : public DNSResponseAction
1387 SNMPTrapResponseAction(const std::string& reason): d_reason(reason)
1390 DNSResponseAction::Action operator()(DNSResponse* dr, string* ruleresult) const override
1392 if (g_snmpAgent && g_snmpTrapsEnabled) {
1393 g_snmpAgent->sendDNSTrap(*dr, d_reason);
1396 return Action::None;
1398 string toString() const override
1400 return "send SNMP trap";
1403 std::string d_reason;