]> git.ipfire.org Git - location/libloc.git/commitdiff
location-importer.in: process unaligned IP ranges in RIR data files correctly
authorPeter Müller <peter.mueller@ipfire.org>
Mon, 29 Mar 2021 20:24:36 +0000 (22:24 +0200)
committerMichael Tremer <michael.tremer@ipfire.org>
Mon, 29 Mar 2021 20:26:09 +0000 (20:26 +0000)
The IP range given in an inetnum object apparently not necessarily
matches distinct subnet boundaries. As a result, the current attempt to
calculate its CIDR mask resulted in faulty subnets not covering the
entire IP range.

This patch leaves the task of enumerating subnets to the ipaddress
module itself, which handles things much more robust. Since the output
may contain of several subnets, a list for the inetnum key is necessary
as well as a loop over them when conducting the SQL statements.

Fixes: #12595
Cc: Michael Tremer <michael.tremer@ipfire.org>
Signed-off-by: Peter Müller <peter.mueller@ipfire.org>
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/python/location-importer.in

index 25069250135666a2f1c206e60695f4f3c5bfede0..e2f201b1dfbcf631a0be0b778bf369e8e461c576 100644 (file)
@@ -3,7 +3,7 @@
 #                                                                             #
 # libloc - A library to determine the location of someone on the Internet     #
 #                                                                             #
-# Copyright (C) 2020 IPFire Development Team <info@ipfire.org>                #
+# Copyright (C) 2020-2021 IPFire Development Team <info@ipfire.org>           #
 #                                                                             #
 # This library is free software; you can redistribute it and/or               #
 # modify it under the terms of the GNU Lesser General Public                  #
@@ -604,18 +604,10 @@ class CLI(object):
                                        log.warning("Could not parse line: %s" % line)
                                        return
 
-                               # Set prefix to default
-                               prefix = 32
-
-                               # Count number of addresses in this subnet
-                               num_addresses = int(end_address) - int(start_address)
-                               if num_addresses:
-                                       prefix -= math.log(num_addresses, 2)
-
-                               inetnum["inetnum"] = "%s/%.0f" % (start_address, prefix)
+                               inetnum["inetnum"] = list(ipaddress.summarize_address_range(start_address, end_address))
 
                        elif key == "inet6num":
-                               inetnum[key] = val
+                               inetnum[key] = [ipaddress.ip_network(val, strict=False)]
 
                        elif key == "country":
                                inetnum[key] = val.upper()
@@ -630,15 +622,14 @@ class CLI(object):
                                (inetnum.get("inet6num") or inetnum.get("inetnum")))
                        return
 
-               network = ipaddress.ip_network(inetnum.get("inet6num") or inetnum.get("inetnum"), strict=False)
-
-               if not self._check_parsed_network(network):
-                       return
-
-               self.db.execute("INSERT INTO _rirdata(network, country) \
-                       VALUES(%s, %s) ON CONFLICT (network) DO UPDATE SET country = excluded.country",
-                       "%s" % network, inetnum.get("country"),
-               )
+               # Iterate through all networks enumerated from above, check them for plausibility and insert
+               # them into the database, if _check_parsed_network() succeeded
+               for single_network in inetnum.get("inet6num") or inetnum.get("inetnum"):
+                       if self._check_parsed_network(single_network):
+                               self.db.execute("INSERT INTO _rirdata(network, country) \
+                                       VALUES(%s, %s) ON CONFLICT (network) DO UPDATE SET country = excluded.country",
+                                       "%s" % single_network, inetnum.get("country"),
+                               )
 
        def _parse_org_block(self, block):
                org = {}