#include <map>
#include <unordered_map>
#include <limits>
+#include <utility>
/* This class implements a filtering policy that is able to fully implement RPZ, but is not bound to it.
In other words, it is generic enough to support RPZ, but could get its data from other places.
std::unordered_set<std::string> d_tags;
std::string d_name;
std::string d_extendedErrorExtra;
+ DNSRecord d_soa{};
boost::optional<uint16_t> d_extendedErrorCode{boost::none};
Priority d_priority{maximumPriority};
bool d_policyOverridesGettag{true};
+ bool d_includeSOA{false};
};
struct Policy
return true;
}
+ [[nodiscard]] bool getSOA(DNSRecord& rec) const
+ {
+ if (d_zoneData) {
+ rec = d_zoneData->d_soa;
+ return true;
+ }
+ return false;
+ }
+
+ [[nodiscard]] bool includeSOA() const
+ {
+ if (d_zoneData) {
+ return d_zoneData->d_includeSOA;
+ }
+ return false;
+ }
+
bool wasHit() const
{
return (d_type != DNSFilterEngine::PolicyType::None && d_kind != DNSFilterEngine::PolicyKind::NoAction);
PolicyKind d_kind;
PolicyType d_type;
+ void addSOAtoRPZResult(vector<DNSRecord>& ret) const
+ {
+ DNSRecord soa{};
+ if (includeSOA() && getSOA(soa)) {
+ soa.d_place = DNSResourceRecord::ADDITIONAL;
+ ret.emplace_back(soa);
+ }
+ }
+
private:
DNSRecord getRecordFromCustom(const DNSName& qname, const std::shared_ptr<const DNSRecordContent>& custom) const;
};
{
d_zoneData->d_extendedErrorExtra = extra;
}
-
+ void setSOA(DNSRecord soa)
+ {
+ d_zoneData->d_soa = std::move(soa);
+ }
const std::string& getName() const
{
return d_zoneData->d_name;
return d_qpolAddr.size() + d_postpolAddr.size() + d_propolName.size() + d_propolNSAddr.size() + d_qpolName.size();
}
+ void setIncludeSOA(bool flag)
+ {
+ d_zoneData->d_includeSOA = flag;
+ }
+
void dump(FILE* fp) const;
void addClientTrigger(const Netmask& nm, Policy&& pol, bool ignoreDuplicate = false);
case DNSFilterEngine::PolicyKind::NXDOMAIN:
ret.clear();
+ appliedPolicy.addSOAtoRPZResult(ret);
res = RCode::NXDomain;
return PolicyResult::HaveAnswer;
case DNSFilterEngine::PolicyKind::NODATA:
ret.clear();
+ appliedPolicy.addSOAtoRPZResult(ret);
res = RCode::NoError;
return PolicyResult::HaveAnswer;
case DNSFilterEngine::PolicyKind::Truncate:
if (!dc->d_tcp) {
ret.clear();
+ appliedPolicy.addSOAtoRPZResult(ret);
res = RCode::NoError;
pw.getHeader()->tc = 1;
return PolicyResult::HaveAnswer;
}
}
+ appliedPolicy.addSOAtoRPZResult(ret);
return PolicyResult::HaveAnswer;
}
}
zone->setExtendedErrorExtra(boost::get<std::string>(have["extendedErrorExtra"]));
}
}
+ if (have.count("includeSOA")) {
+ zone->setIncludeSOA(boost::get<bool>(have["includeSOA"]));
+ }
}
typedef std::unordered_map<std::string, boost::variant<bool, uint64_t, std::string, std::vector<std::pair<int, std::string>>>> protobufOptions_t;
dr.d_name.makeUsRelative(zoneName);
if (dr.d_type == QType::SOA) {
sr = getRR<SOARecordContent>(dr);
+ zone->setSOA(dr);
continue;
}
zpt.setMaxGenerateSteps(::arg().asNum("max-generate-steps"));
zpt.setMaxIncludes(::arg().asNum("max-include-depth"));
DNSResourceRecord drr;
+ DNSRecord soaRecord;
DNSName domain;
auto log = g_slog->withName("rpz")->withValues("file", Logging::Loggable(fname), "zone", Logging::Loggable(zone->getName()));
while (zpt.get(drr)) {
sr = getRR<SOARecordContent>(dr);
domain = dr.d_name;
zone->setDomain(domain);
+ soaRecord = dr;
}
else if (dr.d_type == QType::NS) {
continue;
if (sr != nullptr) {
zone->setRefresh(sr->d_st.refresh);
+ zone->setSOA(soaRecord);
setRPZZoneNewState(zone->getName(), sr->d_st.serial, zone->size(), true, false);
}
return sr;
case DNSFilterEngine::PolicyKind::NXDOMAIN:
ret.clear();
+ d_appliedPolicy.addSOAtoRPZResult(ret);
rcode = RCode::NXDomain;
done = true;
return;
case DNSFilterEngine::PolicyKind::NODATA:
ret.clear();
+ d_appliedPolicy.addSOAtoRPZResult(ret);
rcode = RCode::NoError;
done = true;
return;
case DNSFilterEngine::PolicyKind::Truncate:
if (!d_queryReceivedOverTCP) {
ret.clear();
+ d_appliedPolicy.addSOAtoRPZResult(ret);
rcode = RCode::NoError;
throw SendTruncatedAnswerException();
}
}
}
}
+ d_appliedPolicy.addSOAtoRPZResult(ret);
}
}
}