*.com.
*.
*/
-
+
bool first=true;
map<DNSName, DNSFilterEngine::Policy>::const_iterator iter;
do {
return false;
}
-DNSFilterEngine::Policy DNSFilterEngine::getProcessingPolicy(const DNSName& qname) const
+DNSFilterEngine::Policy DNSFilterEngine::getProcessingPolicy(const DNSName& qname, const std::unordered_map<std::string,bool>& discardedPolicies) const
{
// cout<<"Got question for nameserver name "<<qname<<endl;
- Policy pol{PolicyKind::NoAction, nullptr, "", 0};
+ Policy pol{PolicyKind::NoAction, nullptr, nullptr, 0};
for(const auto& z : d_zones) {
+ if(z.name && discardedPolicies.find(*z.name) != discardedPolicies.end()) {
+ continue;
+ }
+
if(findNamedPolicy(z.propolName, qname, pol)) {
// cerr<<"Had a hit on the nameserver ("<<qname<<") used to process the query"<<endl;
return pol;
return pol;
}
-DNSFilterEngine::Policy DNSFilterEngine::getProcessingPolicy(const ComboAddress& address) const
+DNSFilterEngine::Policy DNSFilterEngine::getProcessingPolicy(const ComboAddress& address, const std::unordered_map<std::string,bool>& discardedPolicies) const
{
// cout<<"Got question for nameserver IP "<<address.toString()<<endl;
for(const auto& z : d_zones) {
+ if(z.name && discardedPolicies.find(*z.name) != discardedPolicies.end()) {
+ continue;
+ }
+
if(auto fnd=z.propolNSAddr.lookup(address)) {
// cerr<<"Had a hit on the nameserver ("<<address.toString()<<") used to process the query"<<endl;
return fnd->second;;
}
}
- return Policy{PolicyKind::NoAction, nullptr, "", 0};
+ return Policy{PolicyKind::NoAction, nullptr, nullptr, 0};
}
-DNSFilterEngine::Policy DNSFilterEngine::getQueryPolicy(const DNSName& qname, const ComboAddress& ca) const
+DNSFilterEngine::Policy DNSFilterEngine::getQueryPolicy(const DNSName& qname, const ComboAddress& ca, const std::unordered_map<std::string,bool>& discardedPolicies) const
{
// cout<<"Got question for "<<qname<<" from "<<ca.toString()<<endl;
-
- Policy pol{PolicyKind::NoAction, nullptr, "", 0};
+ Policy pol{PolicyKind::NoAction, nullptr, nullptr, 0};
for(const auto& z : d_zones) {
+ if(z.name && discardedPolicies.find(*z.name) != discardedPolicies.end()) {
+ continue;
+ }
+
if(findNamedPolicy(z.qpolName, qname, pol)) {
// cerr<<"Had a hit on the name of the query"<<endl;
return pol;
return pol;
}
-DNSFilterEngine::Policy DNSFilterEngine::getPostPolicy(const vector<DNSRecord>& records) const
+DNSFilterEngine::Policy DNSFilterEngine::getPostPolicy(const vector<DNSRecord>& records, const std::unordered_map<std::string,bool>& discardedPolicies) const
{
ComboAddress ca;
-
for(const auto& r : records) {
if(r.d_place != DNSResourceRecord::ANSWER)
continue;
continue;
for(const auto& z : d_zones) {
+ if(z.name && discardedPolicies.find(*z.name) != discardedPolicies.end()) {
+ continue;
+ }
+
if(auto fnd=z.postpolAddr.lookup(ca))
return fnd->second;
}
}
- return Policy{PolicyKind::NoAction, nullptr, "", 0};
+ return Policy{PolicyKind::NoAction, nullptr, nullptr, 0};
}
-void DNSFilterEngine::assureZones(int zone)
+void DNSFilterEngine::assureZones(size_t zone)
{
- if((int)d_zones.size() <= zone)
+ if(d_zones.size() <= zone)
d_zones.resize(zone+1);
}
-void DNSFilterEngine::clear(int zone)
+void DNSFilterEngine::clear(size_t zone)
{
assureZones(zone);
auto& z = d_zones[zone];
z.qpolName.clear();
}
-void DNSFilterEngine::addClientTrigger(const Netmask& nm, Policy pol, int zone)
+void DNSFilterEngine::addClientTrigger(const Netmask& nm, Policy pol, size_t zone)
{
assureZones(zone);
+ pol.d_name = d_zones[zone].name;
d_zones[zone].qpolAddr.insert(nm).second=pol;
}
-void DNSFilterEngine::addResponseTrigger(const Netmask& nm, Policy pol, int zone)
+void DNSFilterEngine::addResponseTrigger(const Netmask& nm, Policy pol, size_t zone)
{
assureZones(zone);
+ pol.d_name = d_zones[zone].name;
d_zones[zone].postpolAddr.insert(nm).second=pol;
}
-void DNSFilterEngine::addQNameTrigger(const DNSName& n, Policy pol, int zone)
+void DNSFilterEngine::addQNameTrigger(const DNSName& n, Policy pol, size_t zone)
{
assureZones(zone);
+ pol.d_name = d_zones[zone].name;
d_zones[zone].qpolName[n]=pol;
}
-void DNSFilterEngine::addNSTrigger(const DNSName& n, Policy pol, int zone)
+void DNSFilterEngine::addNSTrigger(const DNSName& n, Policy pol, size_t zone)
{
assureZones(zone);
+ pol.d_name = d_zones[zone].name;
d_zones[zone].propolName[n]=pol;
}
-void DNSFilterEngine::addNSIPTrigger(const Netmask& nm, Policy pol, int zone)
+void DNSFilterEngine::addNSIPTrigger(const Netmask& nm, Policy pol, size_t zone)
{
assureZones(zone);
+ pol.d_name = d_zones[zone].name;
d_zones[zone].propolNSAddr.insert(nm).second = pol;
}
-bool DNSFilterEngine::rmClientTrigger(const Netmask& nm, Policy pol, int zone)
+bool DNSFilterEngine::rmClientTrigger(const Netmask& nm, Policy pol, size_t zone)
{
assureZones(zone);
return true;
}
-bool DNSFilterEngine::rmResponseTrigger(const Netmask& nm, Policy pol, int zone)
+bool DNSFilterEngine::rmResponseTrigger(const Netmask& nm, Policy pol, size_t zone)
{
assureZones(zone);
auto& postpols = d_zones[zone].postpolAddr;
return true;
}
-bool DNSFilterEngine::rmQNameTrigger(const DNSName& n, Policy pol, int zone)
+bool DNSFilterEngine::rmQNameTrigger(const DNSName& n, Policy pol, size_t zone)
{
assureZones(zone);
d_zones[zone].qpolName.erase(n); // XXX verify we had identical policy?
return true;
}
-bool DNSFilterEngine::rmNSTrigger(const DNSName& n, Policy pol, int zone)
+bool DNSFilterEngine::rmNSTrigger(const DNSName& n, Policy pol, size_t zone)
{
assureZones(zone);
d_zones[zone].propolName.erase(n); // XXX verify policy matched? =pol;
return true;
}
-bool DNSFilterEngine::rmNSIPTrigger(const Netmask& nm, Policy pol, int zone)
+bool DNSFilterEngine::rmNSIPTrigger(const Netmask& nm, Policy pol, size_t zone)
{
assureZones(zone);
auto& pols = d_zones[zone].propolNSAddr;
#include "dns.hh"
#include "dnsparser.hh"
#include <map>
+#include <unordered_map>
/* 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.
}
PolicyKind d_kind;
std::shared_ptr<DNSRecordContent> d_custom;
- std::string d_name;
+ std::shared_ptr<std::string> d_name;
int d_ttl;
};
DNSFilterEngine();
void clear();
- void clear(int zone);
- void addClientTrigger(const Netmask& nm, Policy pol, int zone=0);
- void addQNameTrigger(const DNSName& nm, Policy pol, int zone=0);
- void addNSTrigger(const DNSName& dn, Policy pol, int zone=0);
- void addNSIPTrigger(const Netmask& nm, Policy pol, int zone=0);
- void addResponseTrigger(const Netmask& nm, Policy pol, int zone=0);
+ void clear(size_t zone);
+ void addClientTrigger(const Netmask& nm, Policy pol, size_t zone);
+ void addQNameTrigger(const DNSName& nm, Policy pol, size_t zone);
+ void addNSTrigger(const DNSName& dn, Policy pol, size_t zone);
+ void addNSIPTrigger(const Netmask& nm, Policy pol, size_t zone);
+ void addResponseTrigger(const Netmask& nm, Policy pol, size_t zone);
- bool rmClientTrigger(const Netmask& nm, Policy pol, int zone=0);
- bool rmQNameTrigger(const DNSName& nm, Policy pol, int zone=0);
- bool rmNSTrigger(const DNSName& dn, Policy pol, int zone=0);
- bool rmNSIPTrigger(const Netmask& nm, Policy pol, int zone=0);
- bool rmResponseTrigger(const Netmask& nm, Policy pol, int zone=0);
+ bool rmClientTrigger(const Netmask& nm, Policy pol, size_t zone);
+ bool rmQNameTrigger(const DNSName& nm, Policy pol, size_t zone);
+ bool rmNSTrigger(const DNSName& dn, Policy pol, size_t zone);
+ bool rmNSIPTrigger(const Netmask& nm, Policy pol, size_t zone);
+ bool rmResponseTrigger(const Netmask& nm, Policy pol, size_t zone);
- Policy getQueryPolicy(const DNSName& qname, const ComboAddress& nm) const;
- Policy getProcessingPolicy(const DNSName& qname) const;
- Policy getProcessingPolicy(const ComboAddress& address) const;
- Policy getPostPolicy(const vector<DNSRecord>& records) const;
+ Policy getQueryPolicy(const DNSName& qname, const ComboAddress& nm, const std::unordered_map<std::string,bool>& discardedPolicies) const;
+ Policy getProcessingPolicy(const DNSName& qname, const std::unordered_map<std::string,bool>& discardedPolicies) const;
+ Policy getProcessingPolicy(const ComboAddress& address, const std::unordered_map<std::string,bool>& discardedPolicies) const;
+ Policy getPostPolicy(const vector<DNSRecord>& records, const std::unordered_map<std::string,bool>& discardedPolicies) const;
size_t size() {
return d_zones.size();
}
+ void setPolicyName(size_t zoneIdx, std::string name)
+ {
+ assureZones(zoneIdx);
+ d_zones[zoneIdx].name = std::make_shared<std::string>(name);
+ }
private:
- void assureZones(int zone);
+ void assureZones(size_t zone);
struct Zone {
std::map<DNSName, Policy> qpolName; // QNAME trigger (RPZ)
NetmaskTree<Policy> qpolAddr; // Source address
std::map<DNSName, Policy> propolName; // NSDNAME (RPZ)
NetmaskTree<Policy> propolNSAddr; // NSIP (RPZ)
NetmaskTree<Policy> postpolAddr; // IP trigger (RPZ)
+ std::shared_ptr<std::string> name;
};
vector<Zone> d_zones;
return false;
}
+bool RecursorLua4::prerpz(const ComboAddress& remote,const ComboAddress& local, const DNSName& query, const QType& qtype, bool isTcp, vector<DNSRecord>& res, const vector<pair<uint16_t,string> >* ednsOpts, unsigned int tag, int& ret, bool* wantsRPZ, std::unordered_map<std::string,bool>* discardedPolicies)
+{
+}
+
bool RecursorLua4::preresolve(const ComboAddress& remote, const ComboAddress& local, const DNSName& query, const QType& qtype, bool isTcp, vector<DNSRecord>& ret, const vector<pair<uint16_t,string> >* ednsOpts, unsigned int tag, DNSFilterEngine::Policy* appliedPolicy, std::vector<std::string>* policyTags, int& res, bool* variable, bool* wantsRPZ)
{
return false;
return ret;
});
+ d_lw->registerFunction<void(DNSQuestion::*)(const std::string&)>("discardPolicy", [](DNSQuestion& dq, const std::string& policy) {
+ if (dq.discardedPolicies) {
+ (*dq.discardedPolicies)[policy] = true;
+ }
+ });
+
d_lw->writeFunction("newDS", []() { return SuffixMatchNode(); });
d_lw->registerFunction<void(SuffixMatchNode::*)(boost::variant<string,DNSName, vector<pair<unsigned int,string> > >)>(
"add",
}
d_lw->executeCode(ifs);
+ d_prerpz = d_lw->readVariable<boost::optional<luacall_t>>("prerpz").get_value_or(0);
d_preresolve = d_lw->readVariable<boost::optional<luacall_t>>("preresolve").get_value_or(0);
d_nodata = d_lw->readVariable<boost::optional<luacall_t>>("nodata").get_value_or(0);
d_nxdomain = d_lw->readVariable<boost::optional<luacall_t>>("nxdomain").get_value_or(0);
d_gettag = d_lw->readVariable<boost::optional<gettag_t>>("gettag").get_value_or(0);
}
+bool RecursorLua4::prerpz(const ComboAddress& remote,const ComboAddress& local, const DNSName& query, const QType& qtype, bool isTcp, vector<DNSRecord>& res, const vector<pair<uint16_t,string> >* ednsOpts, unsigned int tag, int& ret, bool* wantsRPZ, std::unordered_map<std::string,bool>* discardedPolicies)
+{
+ return genhook(d_prerpz, remote, local, query, qtype, isTcp, res, ednsOpts, tag, nullptr, nullptr, ret, nullptr, wantsRPZ, discardedPolicies);
+}
+
bool RecursorLua4::preresolve(const ComboAddress& remote,const ComboAddress& local, const DNSName& query, const QType& qtype, bool isTcp, vector<DNSRecord>& res, const vector<pair<uint16_t,string> >* ednsOpts, unsigned int tag, DNSFilterEngine::Policy* appliedPolicy, std::vector<std::string>* policyTags, int& ret, bool* variable, bool* wantsRPZ)
{
- return genhook(d_preresolve, remote, local, query, qtype, isTcp, res, ednsOpts, tag, appliedPolicy, policyTags, ret, variable, wantsRPZ);
+ return genhook(d_preresolve, remote, local, query, qtype, isTcp, res, ednsOpts, tag, appliedPolicy, policyTags, ret, variable, wantsRPZ, nullptr);
}
bool RecursorLua4::nxdomain(const ComboAddress& remote,const ComboAddress& local, const DNSName& query, const QType& qtype, bool isTcp, vector<DNSRecord>& res, int& ret, bool* variable)
{
- return genhook(d_nxdomain, remote, local, query, qtype, isTcp, res, 0, 0, nullptr, nullptr, ret, variable, 0);
+ return genhook(d_nxdomain, remote, local, query, qtype, isTcp, res, 0, 0, nullptr, nullptr, ret, variable, 0, nullptr);
}
bool RecursorLua4::nodata(const ComboAddress& remote,const ComboAddress& local, const DNSName& query, const QType& qtype, bool isTcp, vector<DNSRecord>& res, int& ret, bool* variable)
{
- return genhook(d_nodata, remote, local, query, qtype, isTcp, res, 0, 0, nullptr, nullptr, ret, variable, 0);
+ return genhook(d_nodata, remote, local, query, qtype, isTcp, res, 0, 0, nullptr, nullptr, ret, variable, 0, nullptr);
}
bool RecursorLua4::postresolve(const ComboAddress& remote,const ComboAddress& local, const DNSName& query, const QType& qtype, bool isTcp, vector<DNSRecord>& res, DNSFilterEngine::Policy* appliedPolicy, std::vector<std::string>* policyTags, int& ret, bool* variable)
{
- return genhook(d_postresolve, remote, local, query, qtype, isTcp, res, 0, 0, appliedPolicy, policyTags, ret, variable, 0);
+ return genhook(d_postresolve, remote, local, query, qtype, isTcp, res, 0, 0, appliedPolicy, policyTags, ret, variable, 0, nullptr);
}
bool RecursorLua4::preoutquery(const ComboAddress& ns, const ComboAddress& requestor, const DNSName& query, const QType& qtype, bool isTcp, vector<DNSRecord>& res, int& ret)
{
- return genhook(d_preoutquery, ns, requestor, query, qtype, isTcp, res, 0, 0, nullptr, nullptr, ret, 0, 0);
+ return genhook(d_preoutquery, ns, requestor, query, qtype, isTcp, res, 0, 0, nullptr, nullptr, ret, 0, 0, nullptr);
}
bool RecursorLua4::ipfilter(const ComboAddress& remote, const ComboAddress& local, const struct dnsheader& dh)
return 0;
}
-bool RecursorLua4::genhook(luacall_t& func, const ComboAddress& remote,const ComboAddress& local, const DNSName& query, const QType& qtype, bool isTcp, vector<DNSRecord>& res, const vector<pair<uint16_t,string> >* ednsOpts, unsigned int tag, DNSFilterEngine::Policy* appliedPolicy, std::vector<std::string>* policyTags, int& ret, bool* variable, bool* wantsRPZ)
+bool RecursorLua4::genhook(luacall_t& func, const ComboAddress& remote,const ComboAddress& local, const DNSName& query, const QType& qtype, bool isTcp, vector<DNSRecord>& res, const vector<pair<uint16_t,string> >* ednsOpts, unsigned int tag, DNSFilterEngine::Policy* appliedPolicy, std::vector<std::string>* policyTags, int& ret, bool* variable, bool* wantsRPZ, std::unordered_map<std::string,bool>* discardedPolicies)
{
if(!func)
return false;
dq->rcode = ret;
dq->policyTags = policyTags;
dq->appliedPolicy = appliedPolicy;
- dq->wantsRPZ = wantsRPZ;
+ if(wantsRPZ) dq->wantsRPZ = *wantsRPZ;
+ if(discardedPolicies) dq->discardedPolicies = discardedPolicies;
bool handled=func(dq);
if(variable) *variable |= dq->variable; // could still be set to indicate this *name* is variable, even if not 'handled'
- *wantsRPZ = dq->wantsRPZ; // Even if we did not handle the query, RPZ could be disabled
+ if(wantsRPZ) *wantsRPZ = dq->wantsRPZ; // Even if we did not handle the query, RPZ could be disabled
if(handled) {
loop:;
public:
explicit RecursorLua4(const std::string& fname);
~RecursorLua4(); // this is so unique_ptr works with an incomplete type
+ bool prerpz(const ComboAddress& remote,const ComboAddress& local, const DNSName& query, const QType& qtype, bool isTcp, vector<DNSRecord>& res, const vector<pair<uint16_t,string> >* ednsOpts, unsigned int tag, int& ret, bool* wantsRPZ, std::unordered_map<std::string,bool>* discardedPolicies);
bool preresolve(const ComboAddress& remote,const ComboAddress& local, const DNSName& query, const QType& qtype, bool isTcp, vector<DNSRecord>& res, const vector<pair<uint16_t,string> >* ednsOpts, unsigned int tag, DNSFilterEngine::Policy* appliedPolicy, std::vector<std::string>* policyTags, int& ret, bool* variable, bool* wantsRPZ);
bool nxdomain(const ComboAddress& remote, const ComboAddress& local, const DNSName& query, const QType& qtype, bool isTcp, vector<DNSRecord>& res, int& ret, bool* variable);
bool nodata(const ComboAddress& remote, const ComboAddress& local, const DNSName& query, const QType& qtype, bool isTcp, vector<DNSRecord>& res, int& ret, bool* variable);
DNSFilterEngine::Policy* appliedPolicy;
std::vector<std::string>* policyTags;
+ std::unordered_map<std::string,bool>* discardedPolicies;
bool isTcp;
- bool wantsRPZ;
+ bool wantsRPZ{true};
};
typedef std::function<bool(std::shared_ptr<DNSQuestion>)> luacall_t;
- luacall_t d_preresolve, d_nxdomain, d_nodata, d_postresolve, d_preoutquery, d_postoutquery;
- bool genhook(luacall_t& func, const ComboAddress& remote,const ComboAddress& local, const DNSName& query, const QType& qtype, bool isTcp, vector<DNSRecord>& res, const vector<pair<uint16_t,string> >* ednsOpts, unsigned int tag, DNSFilterEngine::Policy* appliedPolicy, std::vector<std::string>* policyTags, int& ret, bool* variable, bool* wantsRPZ);
+ luacall_t d_prerpz, d_preresolve, d_nxdomain, d_nodata, d_postresolve, d_preoutquery, d_postoutquery;
+ bool genhook(luacall_t& func, const ComboAddress& remote,const ComboAddress& local, const DNSName& query, const QType& qtype, bool isTcp, vector<DNSRecord>& res, const vector<pair<uint16_t,string> >* ednsOpts, unsigned int tag, DNSFilterEngine::Policy* appliedPolicy, std::vector<std::string>* policyTags, int& ret, bool* variable, bool* wantsRPZ, std::unordered_map<std::string,bool>* discardedPolicies);
typedef std::function<bool(ComboAddress,ComboAddress, struct dnsheader)> ipfilter_t;
ipfilter_t d_ipfilter;
};
RecProtoBufMessage message(DNSProtoBufMessage::Query, uniqueId, &requestor, &local, qname, qtype, qclass, id, tcp, len);
message.setEDNSSubnet(ednssubnet, ednssubnet.isIpv4() ? maskV4 : maskV6);
- if (!appliedPolicy.d_name.empty()) {
- message.setAppliedPolicy(appliedPolicy.d_name);
+ if (appliedPolicy.d_name && !appliedPolicy.d_name->empty()) {
+ message.setAppliedPolicy(*appliedPolicy.d_name);
}
if (!policyTags.empty()) {
message.setPolicyTags(policyTags);
if(!dc->d_mdp.d_header.rd)
sr.setCacheOnly();
+ if (t_pdl->get()) {
+ (*t_pdl)->prerpz(dc->d_remote, dc->d_local, dc->d_mdp.d_qname, QType(dc->d_mdp.d_qtype), dc->d_tcp, ret, dc->d_ednsOpts.empty() ? 0 : &dc->d_ednsOpts, dc->d_tag, res, &wantsRPZ, &sr.d_discardedPolicies);
+ }
+
// Check if the query has a policy attached to it
- dfepol = luaconfsLocal->dfe.getQueryPolicy(dc->d_mdp.d_qname, dc->d_remote);
+ if (wantsRPZ) {
+ dfepol = luaconfsLocal->dfe.getQueryPolicy(dc->d_mdp.d_qname, dc->d_remote, sr.d_discardedPolicies);
+ }
appliedPolicy = dfepol;
// if there is a RecursorLua active, and it 'took' the query in preResolve, we don't launch beginResolve
}
if (wantsRPZ) {
- dfepol = luaconfsLocal->dfe.getPostPolicy(ret);
+ dfepol = luaconfsLocal->dfe.getPostPolicy(ret, sr.d_discardedPolicies);
appliedPolicy = dfepol;
}
if (luaconfsLocal->protobufServer) {
pbMessage.setBytes(packet.size());
pbMessage.setResponseCode(pw.getHeader()->rcode);
- pbMessage.setAppliedPolicy(appliedPolicy.d_name);
+ if (appliedPolicy.d_name) {
+ pbMessage.setAppliedPolicy(*appliedPolicy.d_name);
+ }
pbMessage.setPolicyTags(dc->d_policyTags);
pbMessage.setQueryTime(dc->d_now.tv_sec, dc->d_now.tv_usec);
protobufLogResponse(luaconfsLocal->protobufServer, pbMessage);
if(have.count("defpol")) {
defpol=DNSFilterEngine::Policy();
defpol->d_kind = (DNSFilterEngine::PolicyKind)boost::get<int>(constGet(have, "defpol"));
- defpol->d_name = polName;
+ defpol->d_name = std::make_shared<std::string>(polName);
if(defpol->d_kind == DNSFilterEngine::PolicyKind::Custom) {
defpol->d_custom=
shared_ptr<DNSRecordContent>(
}
}
}
+ const size_t zoneIdx = lci.dfe.size();
theL()<<Logger::Warning<<"Loading RPZ from file '"<<fname<<"'"<<endl;
- loadRPZFromFile(fname, lci.dfe, polName, defpol, 0);
+ lci.dfe.setPolicyName(zoneIdx, polName);
+ loadRPZFromFile(fname, lci.dfe, defpol, zoneIdx);
theL()<<Logger::Warning<<"Done loading RPZ from file '"<<fname<<"'"<<endl;
}
catch(std::exception& e) {
// cout<<"Set a default policy"<<endl;
defpol=DNSFilterEngine::Policy();
defpol->d_kind = (DNSFilterEngine::PolicyKind)boost::get<int>(constGet(have, "defpol"));
- defpol->d_name = polName;
+ defpol->d_name = std::make_shared<std::string>(polName);
if(defpol->d_kind == DNSFilterEngine::PolicyKind::Custom) {
// cout<<"Setting a custom field even!"<<endl;
defpol->d_custom=
// We were passed a localAddress, check if its AF matches the master's
throw PDNSException("Master address("+master.toString()+") is not of the same Address Family as the local address ("+localAddress.toString()+").");
DNSName zone(zone_);
+ const size_t zoneIdx = lci.dfe.size();
+ lci.dfe.setPolicyName(zoneIdx, polName);
- auto sr=loadRPZFromServer(master, zone, lci.dfe, polName, defpol, 0, tt, maxReceivedXFRMBytes * 1024 * 1024, localAddress);
+ auto sr=loadRPZFromServer(master, zone, lci.dfe, defpol, zoneIdx, tt, maxReceivedXFRMBytes * 1024 * 1024, localAddress);
if(refresh)
sr->d_st.refresh=refresh;
- std::thread t(RPZIXFRTracker, master, zone, polName, tt, sr, maxReceivedXFRMBytes * 1024 * 1024, localAddress);
+ std::thread t(RPZIXFRTracker, master, zone, zoneIdx, tt, sr, maxReceivedXFRMBytes * 1024 * 1024, localAddress);
t.detach();
}
catch(std::exception& e) {
}
-void RPZIXFRTracker(const ComboAddress& master, const DNSName& zone, const std::string& polName, const TSIGTriplet& tt, shared_ptr<SOARecordContent> oursr, size_t maxReceivedBytes, const ComboAddress& localAddress)
+void RPZIXFRTracker(const ComboAddress& master, const DNSName& zone, size_t polZone, const TSIGTriplet& tt, shared_ptr<SOARecordContent> oursr, size_t maxReceivedBytes, const ComboAddress& localAddress)
{
int refresh = oursr->d_st.refresh;
for(;;) {
}
else {
L<<Logger::Info<<"Had removal of "<<rr.d_name<<endl;
- RPZRecordToPolicy(rr, luaconfsCopy.dfe, polName, false, boost::optional<DNSFilterEngine::Policy>(), 0);
+ RPZRecordToPolicy(rr, luaconfsCopy.dfe, false, boost::optional<DNSFilterEngine::Policy>(), polZone);
}
}
}
else {
L<<Logger::Info<<"Had addition of "<<rr.d_name<<endl;
- RPZRecordToPolicy(rr, luaconfsCopy.dfe, polName, true, boost::optional<DNSFilterEngine::Policy>(), 0);
+ RPZRecordToPolicy(rr, luaconfsCopy.dfe, true, boost::optional<DNSFilterEngine::Policy>(), polZone);
}
}
}
return Netmask(v6);
}
-void RPZRecordToPolicy(const DNSRecord& dr, DNSFilterEngine& target, const std::string& polName, bool addOrRemove, boost::optional<DNSFilterEngine::Policy> defpol, int place)
+void RPZRecordToPolicy(const DNSRecord& dr, DNSFilterEngine& target, bool addOrRemove, boost::optional<DNSFilterEngine::Policy> defpol, size_t place)
{
static const DNSName drop("rpz-drop."), truncate("rpz-tcp-only."), noaction("rpz-passthru.");
static const DNSName rpzClientIP("rpz-client-ip"), rpzIP("rpz-ip"),
rpzNSDname("rpz-nsdname"), rpzNSIP("rpz-nsip.");
- DNSFilterEngine::Policy pol{DNSFilterEngine::PolicyKind::NoAction, nullptr, polName, 0};
+ DNSFilterEngine::Policy pol{DNSFilterEngine::PolicyKind::NoAction, nullptr, nullptr, 0};
if(dr.d_class != QClass::IN) {
return;
if(dr.d_name.isPartOf(rpzNSDname)) {
DNSName filt=dr.d_name.makeRelative(rpzNSDname);
if(addOrRemove)
- target.addNSTrigger(filt, pol);
+ target.addNSTrigger(filt, pol, place);
else
- target.rmNSTrigger(filt, pol);
+ target.rmNSTrigger(filt, pol, place);
} else if(dr.d_name.isPartOf(rpzClientIP)) {
DNSName filt=dr.d_name.makeRelative(rpzClientIP);
auto nm=makeNetmaskFromRPZ(filt);
if(addOrRemove)
- target.addClientTrigger(nm, pol);
+ target.addClientTrigger(nm, pol, place);
else
- target.rmClientTrigger(nm, pol);
+ target.rmClientTrigger(nm, pol, place);
} else if(dr.d_name.isPartOf(rpzIP)) {
// cerr<<"Should apply answer content IP policy: "<<dr.d_name<<endl;
DNSName filt=dr.d_name.makeRelative(rpzIP);
auto nm=makeNetmaskFromRPZ(filt);
if(addOrRemove)
- target.addResponseTrigger(nm, pol);
+ target.addResponseTrigger(nm, pol, place);
else
- target.rmResponseTrigger(nm, pol);
+ target.rmResponseTrigger(nm, pol, place);
} else if(dr.d_name.isPartOf(rpzNSIP)) {
DNSName filt=dr.d_name.makeRelative(rpzNSIP);
auto nm=makeNetmaskFromRPZ(filt);
if(addOrRemove)
- target.addNSIPTrigger(nm, pol);
+ target.addNSIPTrigger(nm, pol, place);
else
- target.rmNSIPTrigger(nm, pol);
+ target.rmNSIPTrigger(nm, pol, place);
} else {
if(addOrRemove)
- target.addQNameTrigger(dr.d_name, pol);
+ target.addQNameTrigger(dr.d_name, pol, place);
else
- target.rmQNameTrigger(dr.d_name, pol);
+ target.rmQNameTrigger(dr.d_name, pol, place);
}
}
-shared_ptr<SOARecordContent> loadRPZFromServer(const ComboAddress& master, const DNSName& zone, DNSFilterEngine& target, const std::string& polName, boost::optional<DNSFilterEngine::Policy> defpol, int place, const TSIGTriplet& tt, size_t maxReceivedBytes, const ComboAddress& localAddress)
+shared_ptr<SOARecordContent> loadRPZFromServer(const ComboAddress& master, const DNSName& zone, DNSFilterEngine& target, boost::optional<DNSFilterEngine::Policy> defpol, size_t place, const TSIGTriplet& tt, size_t maxReceivedBytes, const ComboAddress& localAddress)
{
L<<Logger::Warning<<"Loading RPZ zone '"<<zone<<"' from "<<master.toStringWithPort()<<endl;
if(!tt.name.empty())
continue;
}
- RPZRecordToPolicy(dr, target, polName, true, defpol, place);
+ RPZRecordToPolicy(dr, target, true, defpol, place);
nrecords++;
}
if(last != time(0)) {
}
// this function is silent - you do the logging
-int loadRPZFromFile(const std::string& fname, DNSFilterEngine& target, const std::string& polName, boost::optional<DNSFilterEngine::Policy> defpol, int place)
+int loadRPZFromFile(const std::string& fname, DNSFilterEngine& target, boost::optional<DNSFilterEngine::Policy> defpol, size_t place)
{
ZoneParserTNG zpt(fname);
DNSResourceRecord drr;
}
else {
dr.d_name=dr.d_name.makeRelative(domain);
- RPZRecordToPolicy(dr, target, polName, true, defpol, place);
+ RPZRecordToPolicy(dr, target, true, defpol, place);
}
}
catch(PDNSException& pe) {
#include <string>
#include "dnsrecords.hh"
-int loadRPZFromFile(const std::string& fname, DNSFilterEngine& target, const std::string& policyName, boost::optional<DNSFilterEngine::Policy> defpol, int place);
-std::shared_ptr<SOARecordContent> loadRPZFromServer(const ComboAddress& master, const DNSName& zone, DNSFilterEngine& target, const std::string& policyName, boost::optional<DNSFilterEngine::Policy> defpol, int place, const TSIGTriplet& tt, size_t maxReceivedBytes, const ComboAddress& localAddress);
-void RPZRecordToPolicy(const DNSRecord& dr, DNSFilterEngine& target, const std::string& policyName, bool addOrRemove, boost::optional<DNSFilterEngine::Policy> defpol, int place);
-void RPZIXFRTracker(const ComboAddress& master, const DNSName& zone, const std::string& policyName, const TSIGTriplet &tt, shared_ptr<SOARecordContent> oursr, size_t maxReceivedBytes, const ComboAddress& localAddress);
+int loadRPZFromFile(const std::string& fname, DNSFilterEngine& target, boost::optional<DNSFilterEngine::Policy> defpol, size_t place);
+std::shared_ptr<SOARecordContent> loadRPZFromServer(const ComboAddress& master, const DNSName& zone, DNSFilterEngine& target, boost::optional<DNSFilterEngine::Policy> defpol, size_t place, const TSIGTriplet& tt, size_t maxReceivedBytes, const ComboAddress& localAddress);
+void RPZRecordToPolicy(const DNSRecord& dr, DNSFilterEngine& target, bool addOrRemove, boost::optional<DNSFilterEngine::Policy> defpol, size_t place);
+void RPZIXFRTracker(const ComboAddress& master, const DNSName& zone, size_t polZone, const TSIGTriplet &tt, shared_ptr<SOARecordContent> oursr, size_t maxReceivedBytes, const ComboAddress& localAddress);
if(d_wantsRPZ) {
for (auto const &ns : nameservers) {
- d_appliedPolicy = g_luaconfs.getLocal()->dfe.getProcessingPolicy(ns.first);
+ d_appliedPolicy = g_luaconfs.getLocal()->dfe.getProcessingPolicy(ns.first, d_discardedPolicies);
if (d_appliedPolicy.d_kind != DNSFilterEngine::PolicyKind::NoAction) { // client query needs an RPZ response
- LOG(", however nameserver "<<ns.first<<" was blocked by RPZ policy '"<<d_appliedPolicy.d_name<<"'"<<endl);
+ LOG(", however nameserver "<<ns.first<<" was blocked by RPZ policy '"<<(d_appliedPolicy.d_name ? *d_appliedPolicy.d_name : "")<<"'"<<endl);
return -2;
}
// Traverse all IP addresses for this NS to see if they have an RPN NSIP policy
for (auto const &address : ns.second.first) {
- d_appliedPolicy = g_luaconfs.getLocal()->dfe.getProcessingPolicy(address);
+ d_appliedPolicy = g_luaconfs.getLocal()->dfe.getProcessingPolicy(address, d_discardedPolicies);
if (d_appliedPolicy.d_kind != DNSFilterEngine::PolicyKind::NoAction) { // client query needs an RPZ response
- LOG(", however nameserver "<<ns.first<<" IP address "<<address.toString()<<" was blocked by RPZ policy '"<<d_appliedPolicy.d_name<<"'"<<endl);
+ LOG(", however nameserver "<<ns.first<<" IP address "<<address.toString()<<" was blocked by RPZ policy '"<<(d_appliedPolicy.d_name ? *d_appliedPolicy.d_name : "")<<"'"<<endl);
return -2;
}
}
}
LOG(remoteIP->toString());
if (d_wantsRPZ) {
- d_appliedPolicy = g_luaconfs.getLocal()->dfe.getProcessingPolicy(*remoteIP);
+ d_appliedPolicy = g_luaconfs.getLocal()->dfe.getProcessingPolicy(*remoteIP, d_discardedPolicies);
if (d_appliedPolicy.d_kind != DNSFilterEngine::PolicyKind::NoAction) {
hitPolicy = true;
- LOG(" (blocked by RPZ policy '"+d_appliedPolicy.d_name+"')");
+ LOG(" (blocked by RPZ policy '"+(d_appliedPolicy.d_name ? *d_appliedPolicy.d_name : "")+"')");
}
}
}
nameservers.clear();
for (auto const &nameserver : nsset) {
if (d_wantsRPZ) {
- d_appliedPolicy = g_luaconfs.getLocal()->dfe.getProcessingPolicy(nameserver);
+ d_appliedPolicy = g_luaconfs.getLocal()->dfe.getProcessingPolicy(nameserver, d_discardedPolicies);
if (d_appliedPolicy.d_kind != DNSFilterEngine::PolicyKind::NoAction) { // client query needs an RPZ response
- LOG("however "<<nameserver<<" was blocked by RPZ policy '"<<d_appliedPolicy.d_name<<"'"<<endl);
+ LOG("however "<<nameserver<<" was blocked by RPZ policy '"<<(d_appliedPolicy.d_name ? *d_appliedPolicy.d_name : "")<<"'"<<endl);
return -2;
}
}
static bool s_doIPv6;
static unsigned int s_maxqperq;
static unsigned int s_maxtotusec;
+ std::unordered_map<std::string,bool> d_discardedPolicies;
+ DNSFilterEngine::Policy d_appliedPolicy{DNSFilterEngine::PolicyKind::NoAction, nullptr, nullptr, 0};
unsigned int d_outqueries;
unsigned int d_tcpoutqueries;
unsigned int d_throttledqueries;
bool d_wasVariable{false};
bool d_wasOutOfBand{false};
bool d_wantsRPZ{true};
- DNSFilterEngine::Policy d_appliedPolicy{DNSFilterEngine::PolicyKind::NoAction, nullptr, "", 0};
typedef multi_index_container <
NegCacheEntry,