]> granicus.if.org Git - pdns/commitdiff
geoipbackend: Make sure initial netmask is not too wide
authorAki Tuomi <cmouse@cmouse.fi>
Tue, 8 May 2018 17:07:47 +0000 (20:07 +0300)
committerAki Tuomi <cmouse@cmouse.fi>
Tue, 15 May 2018 11:53:20 +0000 (14:53 +0300)
Otherwise cache will be "poisoned" with too wide value, rendering
the geoip functionality useless.

Fixes #6584, found by @blop

modules/geoipbackend/geoipbackend.cc

index ed5da8fb78107a6f58c9e8a828f38f4edd14ffae..d75d4f9e389eaf74a503aba930a67818825afb71 100644 (file)
@@ -38,6 +38,8 @@ struct GeoIPDNSResourceRecord: DNSResourceRecord {
 
 struct GeoIPService {
   NetmaskTree<vector<string> > masks;
+  unsigned int netmask4;
+  unsigned int netmask6;
 };
 
 struct GeoIPDomain {
@@ -187,6 +189,8 @@ void GeoIPBackend::initialize() {
     }
 
     for(YAML::const_iterator service = domain["services"].begin(); service != domain["services"].end(); service++) {
+      unsigned int netmask4 = 0, netmask6 = 0;
+      DNSName srvName{service->first.as<string>()};
       NetmaskTree<vector<string> > nmt;
 
       // if it's an another map, we need to iterate it again, otherwise we just add two root entries.
@@ -202,7 +206,12 @@ void GeoIPBackend::initialize() {
             nmt.insert(Netmask("0.0.0.0/0")).second.assign(value.begin(),value.end());
             nmt.insert(Netmask("::/0")).second.swap(value);
           } else {
-            nmt.insert(Netmask(net->first.as<string>())).second.swap(value);
+            Netmask nm{net->first.as<string>()};
+            nmt.insert(nm).second.swap(value);
+            if (nm.isIpv6() == true && netmask6 < nm.getBits())
+              netmask6 = nm.getBits();
+            if (nm.isIpv6() == false && netmask4 < nm.getBits())
+              netmask4 = nm.getBits();
           }
         }
       } else {
@@ -215,7 +224,10 @@ void GeoIPBackend::initialize() {
         nmt.insert(Netmask("0.0.0.0/0")).second.assign(value.begin(),value.end());
         nmt.insert(Netmask("::/0")).second.swap(value);
       }
-      dom.services[DNSName(service->first.as<string>())].masks.swap(nmt);
+
+      dom.services[srvName].netmask4 = netmask4;
+      dom.services[srvName].netmask6 = netmask6;
+      dom.services[srvName].masks.swap(nmt);
     }
 
     // rectify the zone, first static records
@@ -380,6 +392,23 @@ void GeoIPBackend::lookup(const QType &qtype, const DNSName& qdomain, DNSPacket
 
   DNSName sformat;
   gl.netmask = node->first.getBits();
+  // figure out smallest sensible netmask
+  if (gl.netmask == 0) {
+    GeoIPLookup tmp_gl;
+    tmp_gl.netmask = 0;
+    // get netmask from geoip backend
+    if (queryGeoIP(ip, v6, GeoIPQueryAttribute::Name, &tmp_gl) == "unknown") {
+      if (v6)
+        gl.netmask = target->second.netmask6;
+      else
+        gl.netmask = target->second.netmask4;
+    }
+  } else {
+    if (v6)
+      gl.netmask = target->second.netmask6;
+    else
+      gl.netmask = target->second.netmask4;
+  }
 
   // note that this means the array format won't work with indirect
   for(auto it = node->second.begin(); it != node->second.end(); it++) {