]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
Allow IP (netmask) based RPZ trigger to have multiple records.
authorOtto Moerbeek <otto.moerbeek@open-xchange.com>
Tue, 18 Aug 2020 09:34:01 +0000 (11:34 +0200)
committerOtto Moerbeek <otto.moerbeek@open-xchange.com>
Tue, 18 Aug 2020 09:34:01 +0000 (11:34 +0200)
While there, refactor the name based code as well, so name based NS triggers
can have multiple records.

pdns/filterpo.cc
pdns/filterpo.hh
pdns/rpzloader.cc

index 2de0102ac21b383648b6a80eeb3170cc24df0229..3c8220721c6c881596a65626997b75f77d671349 100644 (file)
@@ -311,33 +311,47 @@ void DNSFilterEngine::assureZones(size_t zone)
     d_zones.resize(zone+1);
 }
 
-void DNSFilterEngine::Zone::addClientTrigger(const Netmask& nm, Policy&& pol)
+void DNSFilterEngine::Zone::addToNameMap(std::unordered_map<DNSName,Policy>& map, const DNSName& n, Policy&& pol, bool ignoreDuplicate, PolicyType ptype)
 {
-  pol.d_zoneData = d_zoneData;
-  pol.d_type = PolicyType::ClientIP;
-  d_qpolAddr.insert(nm).second=std::move(pol);
-}
+  auto it = map.find(n);
 
-void DNSFilterEngine::Zone::addResponseTrigger(const Netmask& nm, Policy&& pol)
-{
-  pol.d_zoneData = d_zoneData;
-  pol.d_type = PolicyType::ResponseIP;
-  d_postpolAddr.insert(nm).second=std::move(pol);
+  if (it != map.end()) {
+    auto& existingPol = it->second;
+
+    if (pol.d_kind != PolicyKind::Custom && !ignoreDuplicate) {
+      throw std::runtime_error("Adding a " + getTypeToString(ptype) + "-based filter policy of kind " + getKindToString(pol.d_kind) + " but a policy of kind " + getKindToString(existingPol.d_kind) + " already exists for the following name: " + n.toLogString());
+    }
+
+    if (existingPol.d_kind != PolicyKind::Custom && ignoreDuplicate) {
+      throw std::runtime_error("Adding a " + getTypeToString(ptype) + "-based filter policy of kind " + getKindToString(existingPol.d_kind) + " but there was already an existing policy for the following name: " + n.toLogString());
+    }
+
+    existingPol.d_custom.reserve(existingPol.d_custom.size() + pol.d_custom.size());
+
+    std::move(pol.d_custom.begin(), pol.d_custom.end(), std::back_inserter(existingPol.d_custom));
+  }
+  else {
+    auto& qpol = map.insert({n, std::move(pol)}).first->second;
+    qpol.d_zoneData = d_zoneData;
+    qpol.d_type = ptype;
+  }
 }
 
-void DNSFilterEngine::Zone::addQNameTrigger(const DNSName& n, Policy&& pol, bool ignoreDuplicate)
+void DNSFilterEngine::Zone::addToNetmaskTree(NetmaskTree<Policy>& nmt, const Netmask& nm, Policy&& pol, bool ignoreDuplicate, PolicyType ptype)
 {
-  auto it = d_qpolName.find(n);
+  bool exists = nmt.has_key(nm);
 
-  if (it != d_qpolName.end()) {
-    auto& existingPol = it->second;
+  if (exists) {
+    // XXX NetMaskTree's node_type has a non-const second, but lookup() returns a const node_type *, so we cannot modify second
+    // Should look into making lookup) return a non-const node_type *...
+    auto& existingPol = const_cast<Policy&>(nmt.lookup(nm)->second);
 
     if (pol.d_kind != PolicyKind::Custom && !ignoreDuplicate) {
-      throw std::runtime_error("Adding a QName-based filter policy of kind " + getKindToString(pol.d_kind) + " but a policy of kind " + getKindToString(existingPol.d_kind) + " already exists for the following QName: " + n.toLogString());
+      throw std::runtime_error("Adding a " + getTypeToString(ptype) + "-based filter policy of kind " + getKindToString(pol.d_kind) + " but a policy of kind " + getKindToString(existingPol.d_kind) + " already exists for the following netmask: " + nm.toString());
     }
 
     if (existingPol.d_kind != PolicyKind::Custom && ignoreDuplicate) {
-      throw std::runtime_error("Adding a QName-based filter policy of kind " + getKindToString(existingPol.d_kind) + " but there was already an existing policy for the following QName: " + n.toLogString());
+      throw std::runtime_error("Adding a " + getTypeToString(ptype) + "-based filter policy of kind " + getKindToString(existingPol.d_kind) + " but there was already an existing policy for the following netmask: " + nm.toString());
     }
 
     existingPol.d_custom.reserve(existingPol.d_custom.size() + pol.d_custom.size());
@@ -345,24 +359,35 @@ void DNSFilterEngine::Zone::addQNameTrigger(const DNSName& n, Policy&& pol, bool
     std::move(pol.d_custom.begin(), pol.d_custom.end(), std::back_inserter(existingPol.d_custom));
   }
   else {
-    auto& qpol = d_qpolName.insert({n, std::move(pol)}).first->second;
-    qpol.d_zoneData = d_zoneData;
-    qpol.d_type = PolicyType::QName;
+    pol.d_zoneData = d_zoneData;
+    pol.d_type = ptype;
+    nmt.insert(nm).second = std::move(pol);
   }
 }
 
-void DNSFilterEngine::Zone::addNSTrigger(const DNSName& n, Policy&& pol)
+void DNSFilterEngine::Zone::addClientTrigger(const Netmask& nm, Policy&& pol, bool ignoreDuplicate)
+{
+  addToNetmaskTree(d_qpolAddr, nm, std::move(pol), ignoreDuplicate, PolicyType::ClientIP);
+}
+
+void DNSFilterEngine::Zone::addResponseTrigger(const Netmask& nm, Policy&& pol, bool ignoreDuplicate)
+{
+  addToNetmaskTree(d_postpolAddr, nm, std::move(pol), ignoreDuplicate, PolicyType::ResponseIP);
+}
+
+void DNSFilterEngine::Zone::addQNameTrigger(const DNSName& n, Policy&& pol, bool ignoreDuplicate)
+{
+  addToNameMap(d_qpolName, n, std::move(pol), ignoreDuplicate, PolicyType::QName);
+}
+
+void DNSFilterEngine::Zone::addNSTrigger(const DNSName& n, Policy&& pol, bool ignoreDuplicate)
 {
-  pol.d_zoneData = d_zoneData;
-  pol.d_type = PolicyType::NSDName;
-  d_propolName.insert({n, std::move(pol)});
+  addToNameMap(d_propolName, n, std::move(pol), ignoreDuplicate, PolicyType::NSDName);
 }
 
-void DNSFilterEngine::Zone::addNSIPTrigger(const Netmask& nm, Policy&& pol)
+void DNSFilterEngine::Zone::addNSIPTrigger(const Netmask& nm, Policy&& pol, bool ignoreDuplicate)
 {
-  pol.d_zoneData = d_zoneData;
-  pol.d_type = PolicyType::NSIP;
-  d_propolNSAddr.insert(nm).second = std::move(pol);
+  addToNetmaskTree(d_propolNSAddr, nm, std::move(pol), ignoreDuplicate, PolicyType::NSIP);
 }
 
 bool DNSFilterEngine::Zone::rmClientTrigger(const Netmask& nm, const Policy& pol)
index fc3287b474fa3259d413de27dc1f83c38d00b7d7..e726968e4e3b0bfbd89e3ac56244650d637f844b 100644 (file)
@@ -230,11 +230,11 @@ public:
 
     void dump(FILE * fp) const;
 
-    void addClientTrigger(const Netmask& nm, Policy&& pol);
-    void addQNameTrigger(const DNSName& nm, Policy&& pol, bool ignoreDuplicate=false);
-    void addNSTrigger(const DNSName& dn, Policy&& pol);
-    void addNSIPTrigger(const Netmask& nm, Policy&& pol);
-    void addResponseTrigger(const Netmask& nm, Policy&& pol);
+    void addClientTrigger(const Netmask& nm, Policy&& pol, bool ignoreDuplicate = false);
+    void addQNameTrigger(const DNSName& nm, Policy&& pol, bool ignoreDuplicate = false);
+    void addNSTrigger(const DNSName& dn, Policy&& pol, bool ignoreDuplicate = false);
+    void addNSIPTrigger(const Netmask& nm, Policy&& pol, bool ignoreDuplicate = false);
+    void addResponseTrigger(const Netmask& nm, Policy&& pol, bool ignoreDuplicate = false);
 
     bool rmClientTrigger(const Netmask& nm, const Policy& pol);
     bool rmQNameTrigger(const DNSName& nm, const Policy& pol);
@@ -276,6 +276,8 @@ public:
     }
     
   private:
+    void addToNetmaskTree(NetmaskTree<Policy>& nmt, const Netmask& nm, Policy&& pol, bool ignoreDuplicate, PolicyType ptype);
+    void addToNameMap(std::unordered_map<DNSName,Policy>& map, const DNSName& n, Policy&& pol, bool ignoreDuplicate, PolicyType ptype);
     static DNSName maskToRPZ(const Netmask& nm);
     static bool findExactNamedPolicy(const std::unordered_map<DNSName, DNSFilterEngine::Policy>& polmap, const DNSName& qname, DNSFilterEngine::Policy& pol);
     static bool findNamedPolicy(const std::unordered_map<DNSName, DNSFilterEngine::Policy>& polmap, const DNSName& qname, DNSFilterEngine::Policy& pol);
index 5814f26296deba9a5c65a8534838a643edbbbc24..212c926052229a6786372cb8b8629bfd3b4161bf 100644 (file)
@@ -147,14 +147,14 @@ static void RPZRecordToPolicy(const DNSRecord& dr, std::shared_ptr<DNSFilterEngi
   if(dr.d_name.isPartOf(rpzNSDname)) {
     DNSName filt=dr.d_name.makeRelative(rpzNSDname);
     if(addOrRemove)
-      zone->addNSTrigger(filt, std::move(pol));
+      zone->addNSTrigger(filt, std::move(pol), defpolApplied);
     else
       zone->rmNSTrigger(filt, std::move(pol));
   } else if(dr.d_name.isPartOf(rpzClientIP)) {
     DNSName filt=dr.d_name.makeRelative(rpzClientIP);
     auto nm=makeNetmaskFromRPZ(filt);
     if(addOrRemove)
-      zone->addClientTrigger(nm, std::move(pol));
+      zone->addClientTrigger(nm, std::move(pol), defpolApplied);
     else
       zone->rmClientTrigger(nm, std::move(pol));
     
@@ -163,14 +163,14 @@ static void RPZRecordToPolicy(const DNSRecord& dr, std::shared_ptr<DNSFilterEngi
     DNSName filt=dr.d_name.makeRelative(rpzIP);
     auto nm=makeNetmaskFromRPZ(filt);
     if(addOrRemove)
-      zone->addResponseTrigger(nm, std::move(pol));
+      zone->addResponseTrigger(nm, std::move(pol), defpolApplied);
     else
       zone->rmResponseTrigger(nm, std::move(pol));
   } else if(dr.d_name.isPartOf(rpzNSIP)) {
     DNSName filt=dr.d_name.makeRelative(rpzNSIP);
     auto nm=makeNetmaskFromRPZ(filt);
     if(addOrRemove)
-      zone->addNSIPTrigger(nm, std::move(pol));
+      zone->addNSIPTrigger(nm, std::move(pol), defpolApplied);
     else
       zone->rmNSIPTrigger(nm, std::move(pol));
   } else {