]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blame - src/patches/libloc-0.9.4-upstream.patch
libloc: Import changes from upstream
[people/pmueller/ipfire-2.x.git] / src / patches / libloc-0.9.4-upstream.patch
CommitLineData
05db64d0
MT
1From ee6ea3986dc80183157f67275dc9f28231b5d5b2 Mon Sep 17 00:00:00 2001
2From: Michael Tremer <michael.tremer@ipfire.org>
3Date: Thu, 24 Sep 2020 10:17:58 +0000
0be475ca 4Subject: [PATCH 001/111] Revert "importer: Purge any redundant entries"
05db64d0
MT
5
6This reverts commit c2cc55d5a6875c3838f060032eaed89dcfb92ef6.
7
8The query stalls the database and therefore the automatic
9scripts are no longer able to generate a new version of the
10database.
11
12Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
13---
14 src/python/location-importer.in | 22 +---------------------
15 1 file changed, 1 insertion(+), 21 deletions(-)
16
17diff --git a/src/python/location-importer.in b/src/python/location-importer.in
18index 1467923..e3a07a0 100644
19--- a/src/python/location-importer.in
20+++ b/src/python/location-importer.in
21@@ -374,27 +374,7 @@ class CLI(object):
22 INSERT INTO autnums(number, name)
23 SELECT _autnums.number, _organizations.name FROM _autnums
24 JOIN _organizations ON _autnums.organization = _organizations.handle
25- ON CONFLICT (number) DO UPDATE SET name = excluded.name
26- """)
27-
28- self.db.execute("""
29- --- Purge any redundant entries
30- CREATE TEMPORARY TABLE _garbage ON COMMIT DROP
31- AS
32- SELECT network FROM networks candidates
33- WHERE EXISTS (
34- SELECT FROM networks
35- WHERE
36- networks.network << candidates.network
37- AND
38- networks.country = candidates.country
39- );
40-
41- CREATE UNIQUE INDEX _garbage_search ON _garbage USING BTREE(network);
42-
43- DELETE FROM networks WHERE EXISTS (
44- SELECT FROM _garbage WHERE networks.network = _garbage.network
45- );
46+ ON CONFLICT (number) DO UPDATE SET name = excluded.name;
47 """)
48
49 # Download all extended sources
50--
512.20.1
52
53From 92f6abf4e272672bb0a71cfe991261b95ebe2fef Mon Sep 17 00:00:00 2001
54From: Michael Tremer <michael.tremer@ipfire.org>
55Date: Thu, 24 Sep 2020 10:18:58 +0000
0be475ca 56Subject: [PATCH 002/111] Revert "importer: Import raw sources for inetnum's
05db64d0
MT
57 again"
58
59This reverts commit 64e95fa903edec8b4e4e59830b395e2e4a411853.
60
61Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
62---
63 src/python/importer.py | 14 ++++----
64 src/python/location-importer.in | 63 ---------------------------------
65 2 files changed, 7 insertions(+), 70 deletions(-)
66
67diff --git a/src/python/importer.py b/src/python/importer.py
68index f19db4b..de20f37 100644
69--- a/src/python/importer.py
70+++ b/src/python/importer.py
71@@ -30,8 +30,8 @@ WHOIS_SOURCES = (
72 "https://ftp.afrinic.net/pub/pub/dbase/afrinic.db.gz",
73
74 # Asia Pacific Network Information Centre
75- "https://ftp.apnic.net/apnic/whois/apnic.db.inet6num.gz",
76- "https://ftp.apnic.net/apnic/whois/apnic.db.inetnum.gz",
77+ #"https://ftp.apnic.net/apnic/whois/apnic.db.inet6num.gz",
78+ #"https://ftp.apnic.net/apnic/whois/apnic.db.inetnum.gz",
79 #"https://ftp.apnic.net/apnic/whois/apnic.db.route6.gz",
80 #"https://ftp.apnic.net/apnic/whois/apnic.db.route.gz",
81 "https://ftp.apnic.net/apnic/whois/apnic.db.aut-num.gz",
82@@ -45,8 +45,8 @@ WHOIS_SOURCES = (
83 # XXX ???
84
85 # Réseaux IP Européens
86- "https://ftp.ripe.net/ripe/dbase/split/ripe.db.inet6num.gz",
87- "https://ftp.ripe.net/ripe/dbase/split/ripe.db.inetnum.gz",
88+ #"https://ftp.ripe.net/ripe/dbase/split/ripe.db.inet6num.gz",
89+ #"https://ftp.ripe.net/ripe/dbase/split/ripe.db.inetnum.gz",
90 #"https://ftp.ripe.net/ripe/dbase/split/ripe.db.route6.gz",
91 #"https://ftp.ripe.net/ripe/dbase/split/ripe.db.route.gz",
92 "https://ftp.ripe.net/ripe/dbase/split/ripe.db.aut-num.gz",
93@@ -55,10 +55,10 @@ WHOIS_SOURCES = (
94
95 EXTENDED_SOURCES = (
96 # African Network Information Centre
97- #"https://ftp.afrinic.net/pub/stats/afrinic/delegated-afrinic-extended-latest",
98+ "https://ftp.afrinic.net/pub/stats/afrinic/delegated-afrinic-extended-latest",
99
100 # Asia Pacific Network Information Centre
101- #"https://ftp.apnic.net/apnic/stats/apnic/delegated-apnic-extended-latest",
102+ "https://ftp.apnic.net/apnic/stats/apnic/delegated-apnic-extended-latest",
103
104 # American Registry for Internet Numbers
105 "https://ftp.arin.net/pub/stats/arin/delegated-arin-extended-latest",
106@@ -67,7 +67,7 @@ EXTENDED_SOURCES = (
107 "http://ftp.lacnic.net/pub/stats/lacnic/delegated-lacnic-extended-latest",
108
109 # Réseaux IP Européens
110- #"https://ftp.ripe.net/pub/stats/ripencc/delegated-ripencc-extended-latest",
111+ "https://ftp.ripe.net/pub/stats/ripencc/delegated-ripencc-extended-latest",
112 )
113
114 class Downloader(object):
115diff --git a/src/python/location-importer.in b/src/python/location-importer.in
116index e3a07a0..77952f2 100644
117--- a/src/python/location-importer.in
118+++ b/src/python/location-importer.in
119@@ -393,10 +393,6 @@ class CLI(object):
120 if line.startswith("aut-num:"):
121 return self._parse_autnum_block(block)
122
123- # inetnum
124- if line.startswith("inet6num:") or line.startswith("inetnum:"):
125- return self._parse_inetnum_block(block)
126-
127 # organisation
128 elif line.startswith("organisation:"):
129 return self._parse_org_block(block)
130@@ -426,65 +422,6 @@ class CLI(object):
131 autnum.get("asn"), autnum.get("org"),
132 )
133
134- def _parse_inetnum_block(self, block):
135- logging.debug("Parsing inetnum block:")
136-
137- inetnum = {}
138- for line in block:
139- logging.debug(line)
140-
141- # Split line
142- key, val = split_line(line)
143-
144- if key == "inetnum":
145- start_address, delim, end_address = val.partition("-")
146-
147- # Strip any excess space
148- start_address, end_address = start_address.rstrip(), end_address.strip()
149-
150- # Convert to IP address
151- try:
152- start_address = ipaddress.ip_address(start_address)
153- end_address = ipaddress.ip_address(end_address)
154- except ValueError:
155- logging.warning("Could not parse line: %s" % line)
156- return
157-
158- # Set prefix to default
159- prefix = 32
160-
161- # Count number of addresses in this subnet
162- num_addresses = int(end_address) - int(start_address)
163- if num_addresses:
164- prefix -= math.log(num_addresses, 2)
165-
166- inetnum["inetnum"] = "%s/%.0f" % (start_address, prefix)
167-
168- elif key == "inet6num":
169- inetnum[key] = val
170-
171- elif key == "country":
172- if val == "UNITED STATES":
173- val = "US"
174-
175- inetnum[key] = val.upper()
176-
177- # Skip empty objects
178- if not inetnum:
179- return
180-
181- network = ipaddress.ip_network(inetnum.get("inet6num") or inetnum.get("inetnum"), strict=False)
182-
183- # Bail out in case we have processed a non-public IP network
184- if network.is_private:
185- logging.warning("Skipping non-globally routable network: %s" % network)
186- return
187-
188- self.db.execute("INSERT INTO networks(network, country) \
189- VALUES(%s, %s) ON CONFLICT (network) DO UPDATE SET country = excluded.country",
190- "%s" % network, inetnum.get("country"),
191- )
192-
193 def _parse_org_block(self, block):
194 org = {}
195 for line in block:
196--
1972.20.1
198
199From f532841e9197ce2f40aad8c086d786b2cb783a54 Mon Sep 17 00:00:00 2001
200From: =?UTF-8?q?Peter=20M=C3=BCller?= <peter.mueller@ipfire.org>
201Date: Mon, 12 Oct 2020 20:53:31 +0000
0be475ca 202Subject: [PATCH 003/111] Revert "Revert "importer: Import raw sources for
05db64d0
MT
203 inetnum's again""
204
205This reverts commit 92f6abf4e272672bb0a71cfe991261b95ebe2fef.
206
207Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
208---
209 src/python/importer.py | 14 ++++----
210 src/python/location-importer.in | 63 +++++++++++++++++++++++++++++++++
211 2 files changed, 70 insertions(+), 7 deletions(-)
212
213diff --git a/src/python/importer.py b/src/python/importer.py
214index de20f37..f19db4b 100644
215--- a/src/python/importer.py
216+++ b/src/python/importer.py
217@@ -30,8 +30,8 @@ WHOIS_SOURCES = (
218 "https://ftp.afrinic.net/pub/pub/dbase/afrinic.db.gz",
219
220 # Asia Pacific Network Information Centre
221- #"https://ftp.apnic.net/apnic/whois/apnic.db.inet6num.gz",
222- #"https://ftp.apnic.net/apnic/whois/apnic.db.inetnum.gz",
223+ "https://ftp.apnic.net/apnic/whois/apnic.db.inet6num.gz",
224+ "https://ftp.apnic.net/apnic/whois/apnic.db.inetnum.gz",
225 #"https://ftp.apnic.net/apnic/whois/apnic.db.route6.gz",
226 #"https://ftp.apnic.net/apnic/whois/apnic.db.route.gz",
227 "https://ftp.apnic.net/apnic/whois/apnic.db.aut-num.gz",
228@@ -45,8 +45,8 @@ WHOIS_SOURCES = (
229 # XXX ???
230
231 # Réseaux IP Européens
232- #"https://ftp.ripe.net/ripe/dbase/split/ripe.db.inet6num.gz",
233- #"https://ftp.ripe.net/ripe/dbase/split/ripe.db.inetnum.gz",
234+ "https://ftp.ripe.net/ripe/dbase/split/ripe.db.inet6num.gz",
235+ "https://ftp.ripe.net/ripe/dbase/split/ripe.db.inetnum.gz",
236 #"https://ftp.ripe.net/ripe/dbase/split/ripe.db.route6.gz",
237 #"https://ftp.ripe.net/ripe/dbase/split/ripe.db.route.gz",
238 "https://ftp.ripe.net/ripe/dbase/split/ripe.db.aut-num.gz",
239@@ -55,10 +55,10 @@ WHOIS_SOURCES = (
240
241 EXTENDED_SOURCES = (
242 # African Network Information Centre
243- "https://ftp.afrinic.net/pub/stats/afrinic/delegated-afrinic-extended-latest",
244+ #"https://ftp.afrinic.net/pub/stats/afrinic/delegated-afrinic-extended-latest",
245
246 # Asia Pacific Network Information Centre
247- "https://ftp.apnic.net/apnic/stats/apnic/delegated-apnic-extended-latest",
248+ #"https://ftp.apnic.net/apnic/stats/apnic/delegated-apnic-extended-latest",
249
250 # American Registry for Internet Numbers
251 "https://ftp.arin.net/pub/stats/arin/delegated-arin-extended-latest",
252@@ -67,7 +67,7 @@ EXTENDED_SOURCES = (
253 "http://ftp.lacnic.net/pub/stats/lacnic/delegated-lacnic-extended-latest",
254
255 # Réseaux IP Européens
256- "https://ftp.ripe.net/pub/stats/ripencc/delegated-ripencc-extended-latest",
257+ #"https://ftp.ripe.net/pub/stats/ripencc/delegated-ripencc-extended-latest",
258 )
259
260 class Downloader(object):
261diff --git a/src/python/location-importer.in b/src/python/location-importer.in
262index 77952f2..e3a07a0 100644
263--- a/src/python/location-importer.in
264+++ b/src/python/location-importer.in
265@@ -393,6 +393,10 @@ class CLI(object):
266 if line.startswith("aut-num:"):
267 return self._parse_autnum_block(block)
268
269+ # inetnum
270+ if line.startswith("inet6num:") or line.startswith("inetnum:"):
271+ return self._parse_inetnum_block(block)
272+
273 # organisation
274 elif line.startswith("organisation:"):
275 return self._parse_org_block(block)
276@@ -422,6 +426,65 @@ class CLI(object):
277 autnum.get("asn"), autnum.get("org"),
278 )
279
280+ def _parse_inetnum_block(self, block):
281+ logging.debug("Parsing inetnum block:")
282+
283+ inetnum = {}
284+ for line in block:
285+ logging.debug(line)
286+
287+ # Split line
288+ key, val = split_line(line)
289+
290+ if key == "inetnum":
291+ start_address, delim, end_address = val.partition("-")
292+
293+ # Strip any excess space
294+ start_address, end_address = start_address.rstrip(), end_address.strip()
295+
296+ # Convert to IP address
297+ try:
298+ start_address = ipaddress.ip_address(start_address)
299+ end_address = ipaddress.ip_address(end_address)
300+ except ValueError:
301+ logging.warning("Could not parse line: %s" % line)
302+ return
303+
304+ # Set prefix to default
305+ prefix = 32
306+
307+ # Count number of addresses in this subnet
308+ num_addresses = int(end_address) - int(start_address)
309+ if num_addresses:
310+ prefix -= math.log(num_addresses, 2)
311+
312+ inetnum["inetnum"] = "%s/%.0f" % (start_address, prefix)
313+
314+ elif key == "inet6num":
315+ inetnum[key] = val
316+
317+ elif key == "country":
318+ if val == "UNITED STATES":
319+ val = "US"
320+
321+ inetnum[key] = val.upper()
322+
323+ # Skip empty objects
324+ if not inetnum:
325+ return
326+
327+ network = ipaddress.ip_network(inetnum.get("inet6num") or inetnum.get("inetnum"), strict=False)
328+
329+ # Bail out in case we have processed a non-public IP network
330+ if network.is_private:
331+ logging.warning("Skipping non-globally routable network: %s" % network)
332+ return
333+
334+ self.db.execute("INSERT INTO networks(network, country) \
335+ VALUES(%s, %s) ON CONFLICT (network) DO UPDATE SET country = excluded.country",
336+ "%s" % network, inetnum.get("country"),
337+ )
338+
339 def _parse_org_block(self, block):
340 org = {}
341 for line in block:
342--
3432.20.1
344
345From a36bc686865fc87ea386fd90b389338bdcb80cbc Mon Sep 17 00:00:00 2001
346From: =?UTF-8?q?Peter=20M=C3=BCller?= <peter.mueller@ipfire.org>
347Date: Mon, 12 Oct 2020 20:53:32 +0000
0be475ca 348Subject: [PATCH 004/111] location-importer.in: only import relevant data from
05db64d0
MT
349 AFRINIC, APNIC and RIPE
350MIME-Version: 1.0
351Content-Type: text/plain; charset=UTF-8
352Content-Transfer-Encoding: 8bit
353
354In contrast to ARIN and LACNIC, we are able to process more detailled
355feeds from those RIRs, avoiding storage of obviously unnecessary data.
356
357Thanks to various SQL optimisations, doing so now takes less time than
358the first version of this did.
359
360Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
361Signed-off-by: Peter Müller <peter.mueller@ipfire.org>
362Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
363---
364 src/python/location-importer.in | 89 ++++++++++++++++++++++++++++++++-
365 1 file changed, 87 insertions(+), 2 deletions(-)
366
367diff --git a/src/python/location-importer.in b/src/python/location-importer.in
368index e3a07a0..093f325 100644
369--- a/src/python/location-importer.in
370+++ b/src/python/location-importer.in
371@@ -165,6 +165,7 @@ class CLI(object):
372 -- networks
373 CREATE TABLE IF NOT EXISTS networks(network inet, country text);
374 CREATE UNIQUE INDEX IF NOT EXISTS networks_network ON networks(network);
375+ CREATE INDEX IF NOT EXISTS networks_family ON networks USING BTREE(family(network));
376 CREATE INDEX IF NOT EXISTS networks_search ON networks USING GIST(network inet_ops);
377
378 -- overrides
379@@ -363,6 +364,16 @@ class CLI(object):
380 CREATE TEMPORARY TABLE _organizations(handle text, name text NOT NULL)
381 ON COMMIT DROP;
382 CREATE UNIQUE INDEX _organizations_handle ON _organizations(handle);
383+
384+ CREATE TEMPORARY TABLE _rirdata(network inet NOT NULL, country text NOT NULL)
385+ ON COMMIT DROP;
386+ CREATE INDEX _rirdata_search ON _rirdata USING BTREE(family(network), masklen(network));
387+ CREATE UNIQUE INDEX _rirdata_network ON _rirdata(network);
388+ """)
389+
390+ # Remove all previously imported content
391+ self.db.execute("""
392+ TRUNCATE TABLE networks;
393 """)
394
395 for source in location.importer.WHOIS_SOURCES:
396@@ -370,6 +381,67 @@ class CLI(object):
397 for block in f:
398 self._parse_block(block)
399
400+ # Process all parsed networks from every RIR we happen to have access to,
401+ # insert the largest network chunks into the networks table immediately...
402+ families = self.db.query("SELECT DISTINCT family(network) AS family FROM _rirdata ORDER BY family(network)")
403+
404+ for family in (row.family for row in families):
405+ smallest = self.db.get("SELECT MIN(masklen(network)) AS prefix FROM _rirdata WHERE family(network) = %s", family)
406+
407+ self.db.execute("INSERT INTO networks(network, country) \
408+ SELECT network, country FROM _rirdata WHERE masklen(network) = %s AND family(network) = %s", smallest.prefix, family)
409+
410+ # ... determine any other prefixes for this network family, ...
411+ prefixes = self.db.query("SELECT DISTINCT masklen(network) AS prefix FROM _rirdata \
412+ WHERE family(network) = %s ORDER BY masklen(network) ASC OFFSET 1", family)
413+
414+ # ... and insert networks with this prefix in case they provide additional
415+ # information (i. e. subnet of a larger chunk with a different country)
416+ for prefix in (row.prefix for row in prefixes):
417+ self.db.execute("""
418+ WITH candidates AS (
419+ SELECT
420+ _rirdata.network,
421+ _rirdata.country
422+ FROM
423+ _rirdata
424+ WHERE
425+ family(_rirdata.network) = %s
426+ AND
427+ masklen(_rirdata.network) = %s
428+ ),
429+ filtered AS (
430+ SELECT
431+ DISTINCT ON (c.network)
432+ c.network,
433+ c.country,
434+ masklen(networks.network),
435+ networks.country AS parent_country
436+ FROM
437+ candidates c
438+ LEFT JOIN
439+ networks
440+ ON
441+ c.network << networks.network
442+ ORDER BY
443+ c.network,
444+ masklen(networks.network) DESC NULLS LAST
445+ )
446+ INSERT INTO
447+ networks(network, country)
448+ SELECT
449+ network,
450+ country
451+ FROM
452+ filtered
453+ WHERE
454+ parent_country IS NULL
455+ OR
456+ country <> parent_country
457+ ON CONFLICT DO NOTHING""",
458+ family, prefix,
459+ )
460+
461 self.db.execute("""
462 INSERT INTO autnums(number, name)
463 SELECT _autnums.number, _organizations.name FROM _autnums
464@@ -470,17 +542,30 @@ class CLI(object):
465 inetnum[key] = val.upper()
466
467 # Skip empty objects
468- if not inetnum:
469+ if not inetnum or not "country" in inetnum:
470 return
471
472 network = ipaddress.ip_network(inetnum.get("inet6num") or inetnum.get("inetnum"), strict=False)
473
474+ # Bail out in case we have processed a network covering the entire IP range, which
475+ # is necessary to work around faulty (?) IPv6 network processing
476+ if network.prefixlen == 0:
477+ logging.warning("Skipping network covering the entire IP adress range: %s" % network)
478+ return
479+
480+ # Bail out in case we have processed a network whose prefix length indicates it is
481+ # not globally routable (we have decided not to process them at the moment, as they
482+ # significantly enlarge our database without providing very helpful additional information)
483+ if (network.prefixlen > 24 and network.version == 4) or (network.prefixlen > 48 and network.version == 6):
484+ logging.info("Skipping network too small to be publicly announced: %s" % network)
485+ return
486+
487 # Bail out in case we have processed a non-public IP network
488 if network.is_private:
489 logging.warning("Skipping non-globally routable network: %s" % network)
490 return
491
492- self.db.execute("INSERT INTO networks(network, country) \
493+ self.db.execute("INSERT INTO _rirdata(network, country) \
494 VALUES(%s, %s) ON CONFLICT (network) DO UPDATE SET country = excluded.country",
495 "%s" % network, inetnum.get("country"),
496 )
497--
4982.20.1
499
500From 2373de384f10f5573bbd7570f5522545df70c0e3 Mon Sep 17 00:00:00 2001
501From: Michael Tremer <michael.tremer@ipfire.org>
502Date: Fri, 16 Oct 2020 12:24:58 +0000
0be475ca 503Subject: [PATCH 005/111] location-importer: Include all overridden networks
05db64d0
MT
504
505Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
506---
507 src/python/location-importer.in | 2 ++
508 1 file changed, 2 insertions(+)
509
510diff --git a/src/python/location-importer.in b/src/python/location-importer.in
511index 093f325..d249a35 100644
512--- a/src/python/location-importer.in
513+++ b/src/python/location-importer.in
514@@ -240,6 +240,8 @@ class CLI(object):
515 SELECT network FROM announcements
516 UNION
517 SELECT network FROM networks
518+ UNION
519+ SELECT network FROM network_overrides
520 ORDER BY network
521 )
522
523--
5242.20.1
525
526From 13f67f285856e8eabfeff2daf1be3aeaa36a82cc Mon Sep 17 00:00:00 2001
527From: Michael Tremer <michael.tremer@ipfire.org>
528Date: Fri, 16 Oct 2020 12:26:38 +0000
0be475ca
MT
529Subject: [PATCH 006/111] Revert "location-importer.in: only import relevant
530 data from AFRINIC, APNIC and RIPE"
05db64d0
MT
531
532This reverts commit a36bc686865fc87ea386fd90b389338bdcb80cbc.
533
534Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
535---
536 src/python/location-importer.in | 89 +--------------------------------
537 1 file changed, 2 insertions(+), 87 deletions(-)
538
539diff --git a/src/python/location-importer.in b/src/python/location-importer.in
540index d249a35..b220eaf 100644
541--- a/src/python/location-importer.in
542+++ b/src/python/location-importer.in
543@@ -165,7 +165,6 @@ class CLI(object):
544 -- networks
545 CREATE TABLE IF NOT EXISTS networks(network inet, country text);
546 CREATE UNIQUE INDEX IF NOT EXISTS networks_network ON networks(network);
547- CREATE INDEX IF NOT EXISTS networks_family ON networks USING BTREE(family(network));
548 CREATE INDEX IF NOT EXISTS networks_search ON networks USING GIST(network inet_ops);
549
550 -- overrides
551@@ -366,16 +365,6 @@ class CLI(object):
552 CREATE TEMPORARY TABLE _organizations(handle text, name text NOT NULL)
553 ON COMMIT DROP;
554 CREATE UNIQUE INDEX _organizations_handle ON _organizations(handle);
555-
556- CREATE TEMPORARY TABLE _rirdata(network inet NOT NULL, country text NOT NULL)
557- ON COMMIT DROP;
558- CREATE INDEX _rirdata_search ON _rirdata USING BTREE(family(network), masklen(network));
559- CREATE UNIQUE INDEX _rirdata_network ON _rirdata(network);
560- """)
561-
562- # Remove all previously imported content
563- self.db.execute("""
564- TRUNCATE TABLE networks;
565 """)
566
567 for source in location.importer.WHOIS_SOURCES:
568@@ -383,67 +372,6 @@ class CLI(object):
569 for block in f:
570 self._parse_block(block)
571
572- # Process all parsed networks from every RIR we happen to have access to,
573- # insert the largest network chunks into the networks table immediately...
574- families = self.db.query("SELECT DISTINCT family(network) AS family FROM _rirdata ORDER BY family(network)")
575-
576- for family in (row.family for row in families):
577- smallest = self.db.get("SELECT MIN(masklen(network)) AS prefix FROM _rirdata WHERE family(network) = %s", family)
578-
579- self.db.execute("INSERT INTO networks(network, country) \
580- SELECT network, country FROM _rirdata WHERE masklen(network) = %s AND family(network) = %s", smallest.prefix, family)
581-
582- # ... determine any other prefixes for this network family, ...
583- prefixes = self.db.query("SELECT DISTINCT masklen(network) AS prefix FROM _rirdata \
584- WHERE family(network) = %s ORDER BY masklen(network) ASC OFFSET 1", family)
585-
586- # ... and insert networks with this prefix in case they provide additional
587- # information (i. e. subnet of a larger chunk with a different country)
588- for prefix in (row.prefix for row in prefixes):
589- self.db.execute("""
590- WITH candidates AS (
591- SELECT
592- _rirdata.network,
593- _rirdata.country
594- FROM
595- _rirdata
596- WHERE
597- family(_rirdata.network) = %s
598- AND
599- masklen(_rirdata.network) = %s
600- ),
601- filtered AS (
602- SELECT
603- DISTINCT ON (c.network)
604- c.network,
605- c.country,
606- masklen(networks.network),
607- networks.country AS parent_country
608- FROM
609- candidates c
610- LEFT JOIN
611- networks
612- ON
613- c.network << networks.network
614- ORDER BY
615- c.network,
616- masklen(networks.network) DESC NULLS LAST
617- )
618- INSERT INTO
619- networks(network, country)
620- SELECT
621- network,
622- country
623- FROM
624- filtered
625- WHERE
626- parent_country IS NULL
627- OR
628- country <> parent_country
629- ON CONFLICT DO NOTHING""",
630- family, prefix,
631- )
632-
633 self.db.execute("""
634 INSERT INTO autnums(number, name)
635 SELECT _autnums.number, _organizations.name FROM _autnums
636@@ -544,30 +472,17 @@ class CLI(object):
637 inetnum[key] = val.upper()
638
639 # Skip empty objects
640- if not inetnum or not "country" in inetnum:
641+ if not inetnum:
642 return
643
644 network = ipaddress.ip_network(inetnum.get("inet6num") or inetnum.get("inetnum"), strict=False)
645
646- # Bail out in case we have processed a network covering the entire IP range, which
647- # is necessary to work around faulty (?) IPv6 network processing
648- if network.prefixlen == 0:
649- logging.warning("Skipping network covering the entire IP adress range: %s" % network)
650- return
651-
652- # Bail out in case we have processed a network whose prefix length indicates it is
653- # not globally routable (we have decided not to process them at the moment, as they
654- # significantly enlarge our database without providing very helpful additional information)
655- if (network.prefixlen > 24 and network.version == 4) or (network.prefixlen > 48 and network.version == 6):
656- logging.info("Skipping network too small to be publicly announced: %s" % network)
657- return
658-
659 # Bail out in case we have processed a non-public IP network
660 if network.is_private:
661 logging.warning("Skipping non-globally routable network: %s" % network)
662 return
663
664- self.db.execute("INSERT INTO _rirdata(network, country) \
665+ self.db.execute("INSERT INTO networks(network, country) \
666 VALUES(%s, %s) ON CONFLICT (network) DO UPDATE SET country = excluded.country",
667 "%s" % network, inetnum.get("country"),
668 )
669--
6702.20.1
671
672From 44341478233115b26bb27fdb24da5b0a1eedb173 Mon Sep 17 00:00:00 2001
673From: Michael Tremer <michael.tremer@ipfire.org>
674Date: Fri, 16 Oct 2020 12:26:43 +0000
0be475ca 675Subject: [PATCH 007/111] Revert "Revert "Revert "importer: Import raw sources
05db64d0
MT
676 for inetnum's again"""
677
678This reverts commit f532841e9197ce2f40aad8c086d786b2cb783a54.
679
680Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
681---
682 src/python/importer.py | 14 ++++----
683 src/python/location-importer.in | 63 ---------------------------------
684 2 files changed, 7 insertions(+), 70 deletions(-)
685
686diff --git a/src/python/importer.py b/src/python/importer.py
687index f19db4b..de20f37 100644
688--- a/src/python/importer.py
689+++ b/src/python/importer.py
690@@ -30,8 +30,8 @@ WHOIS_SOURCES = (
691 "https://ftp.afrinic.net/pub/pub/dbase/afrinic.db.gz",
692
693 # Asia Pacific Network Information Centre
694- "https://ftp.apnic.net/apnic/whois/apnic.db.inet6num.gz",
695- "https://ftp.apnic.net/apnic/whois/apnic.db.inetnum.gz",
696+ #"https://ftp.apnic.net/apnic/whois/apnic.db.inet6num.gz",
697+ #"https://ftp.apnic.net/apnic/whois/apnic.db.inetnum.gz",
698 #"https://ftp.apnic.net/apnic/whois/apnic.db.route6.gz",
699 #"https://ftp.apnic.net/apnic/whois/apnic.db.route.gz",
700 "https://ftp.apnic.net/apnic/whois/apnic.db.aut-num.gz",
701@@ -45,8 +45,8 @@ WHOIS_SOURCES = (
702 # XXX ???
703
704 # Réseaux IP Européens
705- "https://ftp.ripe.net/ripe/dbase/split/ripe.db.inet6num.gz",
706- "https://ftp.ripe.net/ripe/dbase/split/ripe.db.inetnum.gz",
707+ #"https://ftp.ripe.net/ripe/dbase/split/ripe.db.inet6num.gz",
708+ #"https://ftp.ripe.net/ripe/dbase/split/ripe.db.inetnum.gz",
709 #"https://ftp.ripe.net/ripe/dbase/split/ripe.db.route6.gz",
710 #"https://ftp.ripe.net/ripe/dbase/split/ripe.db.route.gz",
711 "https://ftp.ripe.net/ripe/dbase/split/ripe.db.aut-num.gz",
712@@ -55,10 +55,10 @@ WHOIS_SOURCES = (
713
714 EXTENDED_SOURCES = (
715 # African Network Information Centre
716- #"https://ftp.afrinic.net/pub/stats/afrinic/delegated-afrinic-extended-latest",
717+ "https://ftp.afrinic.net/pub/stats/afrinic/delegated-afrinic-extended-latest",
718
719 # Asia Pacific Network Information Centre
720- #"https://ftp.apnic.net/apnic/stats/apnic/delegated-apnic-extended-latest",
721+ "https://ftp.apnic.net/apnic/stats/apnic/delegated-apnic-extended-latest",
722
723 # American Registry for Internet Numbers
724 "https://ftp.arin.net/pub/stats/arin/delegated-arin-extended-latest",
725@@ -67,7 +67,7 @@ EXTENDED_SOURCES = (
726 "http://ftp.lacnic.net/pub/stats/lacnic/delegated-lacnic-extended-latest",
727
728 # Réseaux IP Européens
729- #"https://ftp.ripe.net/pub/stats/ripencc/delegated-ripencc-extended-latest",
730+ "https://ftp.ripe.net/pub/stats/ripencc/delegated-ripencc-extended-latest",
731 )
732
733 class Downloader(object):
734diff --git a/src/python/location-importer.in b/src/python/location-importer.in
735index b220eaf..e87d378 100644
736--- a/src/python/location-importer.in
737+++ b/src/python/location-importer.in
738@@ -395,10 +395,6 @@ class CLI(object):
739 if line.startswith("aut-num:"):
740 return self._parse_autnum_block(block)
741
742- # inetnum
743- if line.startswith("inet6num:") or line.startswith("inetnum:"):
744- return self._parse_inetnum_block(block)
745-
746 # organisation
747 elif line.startswith("organisation:"):
748 return self._parse_org_block(block)
749@@ -428,65 +424,6 @@ class CLI(object):
750 autnum.get("asn"), autnum.get("org"),
751 )
752
753- def _parse_inetnum_block(self, block):
754- logging.debug("Parsing inetnum block:")
755-
756- inetnum = {}
757- for line in block:
758- logging.debug(line)
759-
760- # Split line
761- key, val = split_line(line)
762-
763- if key == "inetnum":
764- start_address, delim, end_address = val.partition("-")
765-
766- # Strip any excess space
767- start_address, end_address = start_address.rstrip(), end_address.strip()
768-
769- # Convert to IP address
770- try:
771- start_address = ipaddress.ip_address(start_address)
772- end_address = ipaddress.ip_address(end_address)
773- except ValueError:
774- logging.warning("Could not parse line: %s" % line)
775- return
776-
777- # Set prefix to default
778- prefix = 32
779-
780- # Count number of addresses in this subnet
781- num_addresses = int(end_address) - int(start_address)
782- if num_addresses:
783- prefix -= math.log(num_addresses, 2)
784-
785- inetnum["inetnum"] = "%s/%.0f" % (start_address, prefix)
786-
787- elif key == "inet6num":
788- inetnum[key] = val
789-
790- elif key == "country":
791- if val == "UNITED STATES":
792- val = "US"
793-
794- inetnum[key] = val.upper()
795-
796- # Skip empty objects
797- if not inetnum:
798- return
799-
800- network = ipaddress.ip_network(inetnum.get("inet6num") or inetnum.get("inetnum"), strict=False)
801-
802- # Bail out in case we have processed a non-public IP network
803- if network.is_private:
804- logging.warning("Skipping non-globally routable network: %s" % network)
805- return
806-
807- self.db.execute("INSERT INTO networks(network, country) \
808- VALUES(%s, %s) ON CONFLICT (network) DO UPDATE SET country = excluded.country",
809- "%s" % network, inetnum.get("country"),
810- )
811-
812 def _parse_org_block(self, block):
813 org = {}
814 for line in block:
815--
8162.20.1
817
818From a7d3a7a0565a0e09d3442e5829a0f30f016993b9 Mon Sep 17 00:00:00 2001
819From: Michael Tremer <michael.tremer@ipfire.org>
820Date: Tue, 20 Oct 2020 20:44:43 +0000
0be475ca
MT
821Subject: [PATCH 008/111] as: Fix dereferencing NULL pointer when setting AS
822 name
05db64d0
MT
823
824Reported-by: Gisle Vanem <gisle.vanem@gmail.com>
825Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
826---
827 src/as.c | 8 +++++++-
828 1 file changed, 7 insertions(+), 1 deletion(-)
829
830diff --git a/src/as.c b/src/as.c
831index e1fbb01..8421ac8 100644
832--- a/src/as.c
833+++ b/src/as.c
834@@ -90,7 +90,13 @@ LOC_EXPORT const char* loc_as_get_name(struct loc_as* as) {
835 }
836
837 LOC_EXPORT int loc_as_set_name(struct loc_as* as, const char* name) {
838- as->name = strdup(name);
839+ if (as->name)
840+ free(as->name);
841+
842+ if (name)
843+ as->name = strdup(name);
844+ else
845+ as->name = NULL;
846
847 return 0;
848 }
849--
8502.20.1
851
852From ddb326ad38a7c7202315dd2c6f938313db04ee22 Mon Sep 17 00:00:00 2001
853From: Michael Tremer <michael.tremer@ipfire.org>
854Date: Wed, 21 Oct 2020 09:18:08 +0000
0be475ca 855Subject: [PATCH 009/111] as: Do not attempt to match name when it wasn't set
05db64d0
MT
856
857Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
858---
859 src/as.c | 4 ++++
860 1 file changed, 4 insertions(+)
861
862diff --git a/src/as.c b/src/as.c
863index 8421ac8..757bf3d 100644
864--- a/src/as.c
865+++ b/src/as.c
866@@ -145,6 +145,10 @@ int loc_as_match_string(struct loc_as* as, const char* string) {
867 if (!string)
868 return 1;
869
870+ // Cannot match anything when name is not set
871+ if (!as->name)
872+ return 1;
873+
874 // Search if string is in name
875 if (strcasestr(as->name, string) != NULL)
876 return 1;
877--
8782.20.1
879
880From d226ad2d97cbcd42ce807d9308569b1b9c5d4e2f Mon Sep 17 00:00:00 2001
881From: Michael Tremer <michael.tremer@ipfire.org>
882Date: Wed, 21 Oct 2020 09:28:39 +0000
0be475ca 883Subject: [PATCH 010/111] writer: Free array with pointer to ASes, too
05db64d0
MT
884
885Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
886---
887 src/writer.c | 7 +++++--
888 1 file changed, 5 insertions(+), 2 deletions(-)
889
890diff --git a/src/writer.c b/src/writer.c
891index 5939cff..160650f 100644
892--- a/src/writer.c
893+++ b/src/writer.c
894@@ -147,8 +147,11 @@ static void loc_writer_free(struct loc_writer* writer) {
895 EVP_PKEY_free(writer->private_key2);
896
897 // Unref all AS
898- for (unsigned int i = 0; i < writer->as_count; i++) {
899- loc_as_unref(writer->as[i]);
900+ if (writer->as) {
901+ for (unsigned int i = 0; i < writer->as_count; i++) {
902+ loc_as_unref(writer->as[i]);
903+ }
904+ free(writer->as);
905 }
906
907 // Release network tree
908--
9092.20.1
910
911From d89a7d62772048ae1bd18d03f69df46b7e1a3d3c Mon Sep 17 00:00:00 2001
912From: Michael Tremer <michael.tremer@ipfire.org>
913Date: Wed, 21 Oct 2020 09:31:29 +0000
0be475ca 914Subject: [PATCH 011/111] writer: Free countries when the writer is being
05db64d0
MT
915 destroyed
916
917Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
918---
919 src/writer.c | 8 ++++++++
920 1 file changed, 8 insertions(+)
921
922diff --git a/src/writer.c b/src/writer.c
923index 160650f..2f09b56 100644
924--- a/src/writer.c
925+++ b/src/writer.c
926@@ -154,6 +154,14 @@ static void loc_writer_free(struct loc_writer* writer) {
927 free(writer->as);
928 }
929
930+ // Unref all countries
931+ if (writer->countries) {
932+ for (unsigned int i = 0; i < writer->countries_count; i++) {
933+ loc_country_unref(writer->countries[i]);
934+ }
935+ free(writer->countries);
936+ }
937+
938 // Release network tree
939 if (writer->networks)
940 loc_network_tree_unref(writer->networks);
941--
9422.20.1
943
944From 0f1aedbc68e3945770c93e0ebd83eed0f555d6f0 Mon Sep 17 00:00:00 2001
945From: Michael Tremer <michael.tremer@ipfire.org>
946Date: Wed, 21 Oct 2020 13:19:44 +0000
0be475ca 947Subject: [PATCH 012/111] tests: Try adding an invalid network
05db64d0
MT
948
949Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
950---
951 src/test-network.c | 8 ++++++++
952 1 file changed, 8 insertions(+)
953
954diff --git a/src/test-network.c b/src/test-network.c
955index d38f13d..e908b57 100644
956--- a/src/test-network.c
957+++ b/src/test-network.c
958@@ -160,6 +160,14 @@ int main(int argc, char** argv) {
959 // Set ASN
960 loc_network_set_asn(network4, 1024);
961
962+ // Try adding an invalid network
963+ struct loc_network* network;
964+ err = loc_writer_add_network(writer, &network, "xxxx:xxxx::/32");
965+ if (err != -EINVAL) {
966+ fprintf(stderr, "It was possible to add an invalid network (err = %d)\n", err);
967+ exit(EXIT_FAILURE);
968+ }
969+
970 FILE* f = tmpfile();
971 if (!f) {
972 fprintf(stderr, "Could not open file for writing: %s\n", strerror(errno));
973--
9742.20.1
975
976From 13ad6e695f9ffc7847b3afe3e9cbcea8fb3a443f Mon Sep 17 00:00:00 2001
977From: Michael Tremer <michael.tremer@ipfire.org>
978Date: Wed, 21 Oct 2020 13:36:35 +0000
0be475ca 979Subject: [PATCH 013/111] networks: Improve parsing IP addresses
05db64d0
MT
980
981loc_network_new_from_string() seem to have had some unexpected
982behaviour for invalid inputs.
983
984The function has been tidied up slightly and returns as soon as
985some invalid input was detected.
986
987Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
988---
989 src/network.c | 52 +++++++++++++++++++++++++++++++---------------
990 src/test-network.c | 7 +++++++
991 2 files changed, 42 insertions(+), 17 deletions(-)
992
993diff --git a/src/network.c b/src/network.c
994index 366caa2..c112a41 100644
995--- a/src/network.c
996+++ b/src/network.c
997@@ -160,9 +160,10 @@ LOC_EXPORT int loc_network_new(struct loc_ctx* ctx, struct loc_network** network
998 LOC_EXPORT int loc_network_new_from_string(struct loc_ctx* ctx, struct loc_network** network,
999 const char* address_string) {
1000 struct in6_addr first_address;
1001- unsigned int prefix = 0;
1002 char* prefix_string;
1003- int r = 1;
1004+ int r = -EINVAL;
1005+
1006+ DEBUG(ctx, "Attempting to parse network %s\n", address_string);
1007
1008 // Make a copy of the string to work on it
1009 char* buffer = strdup(address_string);
1010@@ -171,29 +172,46 @@ LOC_EXPORT int loc_network_new_from_string(struct loc_ctx* ctx, struct loc_netwo
1011 // Split address and prefix
1012 address_string = strsep(&prefix_string, "/");
1013
1014- // Did we find a prefix?
1015- if (prefix_string) {
1016- // Convert prefix to integer
1017- prefix = strtol(prefix_string, NULL, 10);
1018+ DEBUG(ctx, " Split into address = %s, prefix = %s\n", address_string, prefix_string);
1019
1020- if (prefix) {
1021- // Parse the address
1022- r = loc_parse_address(ctx, address_string, &first_address);
1023+ // We need to have a prefix
1024+ if (!prefix_string) {
1025+ DEBUG(ctx, "No prefix set\n");
1026+ goto FAIL;
1027+ }
1028
1029- // Map the prefix to IPv6 if needed
1030- if (IN6_IS_ADDR_V4MAPPED(&first_address))
1031- prefix += 96;
1032- }
1033+ // Convert prefix to integer
1034+ unsigned int prefix = strtol(prefix_string, NULL, 10);
1035+
1036+ // End if the prefix was invalid
1037+ if (!prefix) {
1038+ DEBUG(ctx, "The prefix is zero or not a number\n");
1039+ goto FAIL;
1040+ }
1041+
1042+ // Parse the address
1043+ r = loc_parse_address(ctx, address_string, &first_address);
1044+ if (r) {
1045+ DEBUG(ctx, "The address could not be parsed\n");
1046+ goto FAIL;
1047 }
1048
1049+ // Map the prefix to IPv6 if needed
1050+ if (IN6_IS_ADDR_V4MAPPED(&first_address))
1051+ prefix += 96;
1052+
1053+FAIL:
1054 // Free temporary buffer
1055 free(buffer);
1056
1057- if (r == 0) {
1058- r = loc_network_new(ctx, network, &first_address, prefix);
1059- }
1060+ // Exit if the parsing was unsuccessful
1061+ if (r)
1062+ return r;
1063+
1064+ DEBUG(ctx, "GOT HERE\n");
1065
1066- return r;
1067+ // Create a new network
1068+ return loc_network_new(ctx, network, &first_address, prefix);
1069 }
1070
1071 LOC_EXPORT struct loc_network* loc_network_ref(struct loc_network* network) {
1072diff --git a/src/test-network.c b/src/test-network.c
1073index e908b57..85eca00 100644
1074--- a/src/test-network.c
1075+++ b/src/test-network.c
1076@@ -168,6 +168,13 @@ int main(int argc, char** argv) {
1077 exit(EXIT_FAILURE);
1078 }
1079
1080+ // Try adding a single address
1081+ err = loc_writer_add_network(writer, &network, "2001:db8::");
1082+ if (err != -EINVAL) {
1083+ fprintf(stderr, "It was possible to add an invalid network (err = %d)\n", err);
1084+ exit(EXIT_FAILURE);
1085+ }
1086+
1087 FILE* f = tmpfile();
1088 if (!f) {
1089 fprintf(stderr, "Could not open file for writing: %s\n", strerror(errno));
1090--
10912.20.1
1092
1093From 6a467e9345bb5a3d37911c9aaac30019eaa4492b Mon Sep 17 00:00:00 2001
1094From: Michael Tremer <michael.tremer@ipfire.org>
1095Date: Wed, 21 Oct 2020 13:43:21 +0000
0be475ca 1096Subject: [PATCH 014/111] networks: Test if we can add localhost (IPv6)
05db64d0
MT
1097
1098Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
1099---
1100 src/test-network.c | 7 +++++++
1101 1 file changed, 7 insertions(+)
1102
1103diff --git a/src/test-network.c b/src/test-network.c
1104index 85eca00..8c7e898 100644
1105--- a/src/test-network.c
1106+++ b/src/test-network.c
1107@@ -175,6 +175,13 @@ int main(int argc, char** argv) {
1108 exit(EXIT_FAILURE);
1109 }
1110
1111+ // Try adding localhost
1112+ err = loc_writer_add_network(writer, &network, "::1/128");
1113+ if (err != -EINVAL) {
1114+ fprintf(stderr, "It was possible to add localhost (::1/128): %d\n", err);
1115+ exit(EXIT_FAILURE);
1116+ }
1117+
1118 FILE* f = tmpfile();
1119 if (!f) {
1120 fprintf(stderr, "Could not open file for writing: %s\n", strerror(errno));
1121--
11222.20.1
1123
1124From fc1190aa11e3ff3d2dbf5f4d408c298e7916f46f Mon Sep 17 00:00:00 2001
1125From: Michael Tremer <michael.tremer@ipfire.org>
1126Date: Wed, 21 Oct 2020 13:44:50 +0000
0be475ca 1127Subject: [PATCH 015/111] networks: Remove accidentially committed debug line
05db64d0
MT
1128
1129Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
1130---
1131 src/network.c | 2 --
1132 1 file changed, 2 deletions(-)
1133
1134diff --git a/src/network.c b/src/network.c
1135index c112a41..be88d75 100644
1136--- a/src/network.c
1137+++ b/src/network.c
1138@@ -208,8 +208,6 @@ FAIL:
1139 if (r)
1140 return r;
1141
1142- DEBUG(ctx, "GOT HERE\n");
1143-
1144 // Create a new network
1145 return loc_network_new(ctx, network, &first_address, prefix);
1146 }
1147--
11482.20.1
1149
1150From a1707d8983898b6878cdd5c68744bcc444e278ed Mon Sep 17 00:00:00 2001
1151From: Michael Tremer <michael.tremer@ipfire.org>
1152Date: Wed, 21 Oct 2020 13:53:36 +0000
0be475ca 1153Subject: [PATCH 016/111] importer: Add search index to announcements table
05db64d0
MT
1154
1155Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
1156---
1157 src/python/location-importer.in | 1 +
1158 1 file changed, 1 insertion(+)
1159
1160diff --git a/src/python/location-importer.in b/src/python/location-importer.in
1161index e87d378..d0fe5a6 100644
1162--- a/src/python/location-importer.in
1163+++ b/src/python/location-importer.in
1164@@ -152,6 +152,7 @@ class CLI(object):
1165 last_seen_at timestamp without time zone DEFAULT CURRENT_TIMESTAMP);
1166 CREATE UNIQUE INDEX IF NOT EXISTS announcements_networks ON announcements(network);
1167 CREATE INDEX IF NOT EXISTS announcements_family ON announcements(family(network));
1168+ CREATE INDEX IF NOT EXISTS announcements_search ON announcements USING GIST(network inet_ops);
1169
1170 -- autnums
1171 CREATE TABLE IF NOT EXISTS autnums(number bigint, name text NOT NULL);
1172--
11732.20.1
1174
1175From 991baf530d47adb2ed7a15b65dc4565d07fa6d07 Mon Sep 17 00:00:00 2001
1176From: Michael Tremer <michael.tremer@ipfire.org>
1177Date: Wed, 21 Oct 2020 13:54:45 +0000
0be475ca 1178Subject: [PATCH 017/111] importer: Add search index to network_overrides table
05db64d0
MT
1179
1180Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
1181---
1182 src/python/location-importer.in | 2 ++
1183 1 file changed, 2 insertions(+)
1184
1185diff --git a/src/python/location-importer.in b/src/python/location-importer.in
1186index d0fe5a6..fe21d73 100644
1187--- a/src/python/location-importer.in
1188+++ b/src/python/location-importer.in
1189@@ -189,6 +189,8 @@ class CLI(object):
1190 );
1191 CREATE UNIQUE INDEX IF NOT EXISTS network_overrides_network
1192 ON network_overrides(network);
1193+ CREATE INDEX IF NOT EXISTS network_overrides_search
1194+ ON network_overrides USING GIST(network inet_ops);
1195 """)
1196
1197 return db
1198--
11992.20.1
1200
1201From bbea93a74651df10e2ffdbd09eb434dc6a0471bc Mon Sep 17 00:00:00 2001
1202From: Michael Tremer <michael.tremer@ipfire.org>
1203Date: Wed, 21 Oct 2020 16:01:57 +0000
0be475ca 1204Subject: [PATCH 018/111] importer: Restructure SQL query to be executed in
05db64d0
MT
1205 parallel
1206
1207There are no functional changes, this just runs quicker now.
1208
1209Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
1210---
1211 src/python/location-importer.in | 67 ++++++++++++++++++---------------
1212 1 file changed, 37 insertions(+), 30 deletions(-)
1213
1214diff --git a/src/python/location-importer.in b/src/python/location-importer.in
1215index fe21d73..3c1e5e2 100644
1216--- a/src/python/location-importer.in
1217+++ b/src/python/location-importer.in
1218@@ -237,34 +237,24 @@ class CLI(object):
1219
1220 # Select all known networks
1221 rows = self.db.query("""
1222- -- Get a (sorted) list of all known networks
1223- WITH known_networks AS (
1224- SELECT network FROM announcements
1225- UNION
1226- SELECT network FROM networks
1227- UNION
1228- SELECT network FROM network_overrides
1229- ORDER BY network
1230- )
1231-
1232 -- Return a list of those networks enriched with all
1233 -- other information that we store in the database
1234 SELECT
1235- DISTINCT ON (known_networks.network)
1236- known_networks.network AS network,
1237- announcements.autnum AS autnum,
1238+ DISTINCT ON (network)
1239+ network,
1240+ autnum,
1241
1242 -- Country
1243 COALESCE(
1244 (
1245 SELECT country FROM network_overrides overrides
1246- WHERE announcements.network <<= overrides.network
1247+ WHERE networks.network <<= overrides.network
1248 ORDER BY masklen(overrides.network) DESC
1249 LIMIT 1
1250 ),
1251 (
1252 SELECT country FROM autnum_overrides overrides
1253- WHERE announcements.autnum = overrides.number
1254+ WHERE networks.autnum = overrides.number
1255 ),
1256 networks.country
1257 ) AS country,
1258@@ -273,50 +263,67 @@ class CLI(object):
1259 COALESCE(
1260 (
1261 SELECT is_anonymous_proxy FROM network_overrides overrides
1262- WHERE announcements.network <<= overrides.network
1263+ WHERE networks.network <<= overrides.network
1264 ORDER BY masklen(overrides.network) DESC
1265 LIMIT 1
1266 ),
1267 (
1268 SELECT is_anonymous_proxy FROM autnum_overrides overrides
1269- WHERE announcements.autnum = overrides.number
1270+ WHERE networks.autnum = overrides.number
1271 ),
1272 FALSE
1273 ) AS is_anonymous_proxy,
1274 COALESCE(
1275 (
1276 SELECT is_satellite_provider FROM network_overrides overrides
1277- WHERE announcements.network <<= overrides.network
1278+ WHERE networks.network <<= overrides.network
1279 ORDER BY masklen(overrides.network) DESC
1280 LIMIT 1
1281 ),
1282 (
1283 SELECT is_satellite_provider FROM autnum_overrides overrides
1284- WHERE announcements.autnum = overrides.number
1285+ WHERE networks.autnum = overrides.number
1286 ),
1287 FALSE
1288 ) AS is_satellite_provider,
1289 COALESCE(
1290 (
1291 SELECT is_anycast FROM network_overrides overrides
1292- WHERE announcements.network <<= overrides.network
1293+ WHERE networks.network <<= overrides.network
1294 ORDER BY masklen(overrides.network) DESC
1295 LIMIT 1
1296 ),
1297 (
1298 SELECT is_anycast FROM autnum_overrides overrides
1299- WHERE announcements.autnum = overrides.number
1300+ WHERE networks.autnum = overrides.number
1301 ),
1302 FALSE
1303- ) AS is_anycast,
1304-
1305- -- Must be part of returned values for ORDER BY clause
1306- masklen(announcements.network) AS sort_a,
1307- masklen(networks.network) AS sort_b
1308- FROM known_networks
1309- LEFT JOIN announcements ON known_networks.network <<= announcements.network
1310- LEFT JOIN networks ON known_networks.network <<= networks.network
1311- ORDER BY known_networks.network, sort_a DESC, sort_b DESC
1312+ ) AS is_anycast
1313+ FROM (
1314+ SELECT
1315+ known_networks.network AS network,
1316+ announcements.autnum AS autnum,
1317+ networks.country AS country,
1318+
1319+ -- Must be part of returned values for ORDER BY clause
1320+ masklen(announcements.network) AS sort_a,
1321+ masklen(networks.network) AS sort_b
1322+ FROM (
1323+ SELECT network FROM announcements
1324+ UNION ALL
1325+ SELECT network FROM networks
1326+ UNION ALL
1327+ SELECT network FROM network_overrides
1328+ ) known_networks
1329+ LEFT JOIN
1330+ announcements ON known_networks.network <<= announcements.network
1331+ LEFT JOIN
1332+ networks ON known_networks.network <<= networks.network
1333+ ORDER BY
1334+ known_networks.network,
1335+ sort_a DESC,
1336+ sort_b DESC
1337+ ) networks
1338 """)
1339
1340 for row in rows:
1341--
13422.20.1
1343
1344From 26ab419b68d166f932db1f97c38cb9d793d04187 Mon Sep 17 00:00:00 2001
1345From: Michael Tremer <michael.tremer@ipfire.org>
1346Date: Thu, 22 Oct 2020 12:24:34 +0000
0be475ca 1347Subject: [PATCH 019/111] network: Allow adding single IP addresses and
05db64d0
MT
1348 automatically add the prefix
1349
1350Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
1351---
1352 src/network.c | 33 +++++++++++++++------------------
1353 src/test-network.c | 4 ++--
1354 2 files changed, 17 insertions(+), 20 deletions(-)
1355
1356diff --git a/src/network.c b/src/network.c
1357index be88d75..d7b1645 100644
1358--- a/src/network.c
1359+++ b/src/network.c
1360@@ -161,6 +161,7 @@ LOC_EXPORT int loc_network_new_from_string(struct loc_ctx* ctx, struct loc_netwo
1361 const char* address_string) {
1362 struct in6_addr first_address;
1363 char* prefix_string;
1364+ unsigned int prefix = 128;
1365 int r = -EINVAL;
1366
1367 DEBUG(ctx, "Attempting to parse network %s\n", address_string);
1368@@ -174,21 +175,6 @@ LOC_EXPORT int loc_network_new_from_string(struct loc_ctx* ctx, struct loc_netwo
1369
1370 DEBUG(ctx, " Split into address = %s, prefix = %s\n", address_string, prefix_string);
1371
1372- // We need to have a prefix
1373- if (!prefix_string) {
1374- DEBUG(ctx, "No prefix set\n");
1375- goto FAIL;
1376- }
1377-
1378- // Convert prefix to integer
1379- unsigned int prefix = strtol(prefix_string, NULL, 10);
1380-
1381- // End if the prefix was invalid
1382- if (!prefix) {
1383- DEBUG(ctx, "The prefix is zero or not a number\n");
1384- goto FAIL;
1385- }
1386-
1387 // Parse the address
1388 r = loc_parse_address(ctx, address_string, &first_address);
1389 if (r) {
1390@@ -196,9 +182,20 @@ LOC_EXPORT int loc_network_new_from_string(struct loc_ctx* ctx, struct loc_netwo
1391 goto FAIL;
1392 }
1393
1394- // Map the prefix to IPv6 if needed
1395- if (IN6_IS_ADDR_V4MAPPED(&first_address))
1396- prefix += 96;
1397+ // If a prefix was given, we will try to parse it
1398+ if (prefix_string) {
1399+ // Convert prefix to integer
1400+ prefix = strtol(prefix_string, NULL, 10);
1401+
1402+ if (!prefix) {
1403+ DEBUG(ctx, "The prefix was not parsable: %s\n", prefix_string);
1404+ goto FAIL;
1405+ }
1406+
1407+ // Map the prefix to IPv6 if needed
1408+ if (IN6_IS_ADDR_V4MAPPED(&first_address))
1409+ prefix += 96;
1410+ }
1411
1412 FAIL:
1413 // Free temporary buffer
1414diff --git a/src/test-network.c b/src/test-network.c
1415index 8c7e898..b6776b4 100644
1416--- a/src/test-network.c
1417+++ b/src/test-network.c
1418@@ -170,8 +170,8 @@ int main(int argc, char** argv) {
1419
1420 // Try adding a single address
1421 err = loc_writer_add_network(writer, &network, "2001:db8::");
1422- if (err != -EINVAL) {
1423- fprintf(stderr, "It was possible to add an invalid network (err = %d)\n", err);
1424+ if (err) {
1425+ fprintf(stderr, "It was impossible to add an single IP address (err = %d)\n", err);
1426 exit(EXIT_FAILURE);
1427 }
1428
1429--
14302.20.1
1431
1432From aadac4c569e921be1d28dd3b2377ac7f3732213e Mon Sep 17 00:00:00 2001
1433From: =?UTF-8?q?Peter=20M=C3=BCller?= <peter.mueller@ipfire.org>
1434Date: Wed, 21 Oct 2020 14:47:36 +0000
0be475ca 1435Subject: [PATCH 020/111] Revert "Revert "Revert "Revert "importer: Import raw
05db64d0
MT
1436 sources for inetnum's again""""
1437MIME-Version: 1.0
1438Content-Type: text/plain; charset=UTF-8
1439Content-Transfer-Encoding: 8bit
1440
1441This reverts commit 44341478233115b26bb27fdb24da5b0a1eedb173.
1442
1443Signed-off-by: Peter Müller <peter.mueller@ipfire.org>
1444Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
1445---
1446 src/python/importer.py | 14 ++++----
1447 src/python/location-importer.in | 63 +++++++++++++++++++++++++++++++++
1448 2 files changed, 70 insertions(+), 7 deletions(-)
1449
1450diff --git a/src/python/importer.py b/src/python/importer.py
1451index de20f37..f19db4b 100644
1452--- a/src/python/importer.py
1453+++ b/src/python/importer.py
1454@@ -30,8 +30,8 @@ WHOIS_SOURCES = (
1455 "https://ftp.afrinic.net/pub/pub/dbase/afrinic.db.gz",
1456
1457 # Asia Pacific Network Information Centre
1458- #"https://ftp.apnic.net/apnic/whois/apnic.db.inet6num.gz",
1459- #"https://ftp.apnic.net/apnic/whois/apnic.db.inetnum.gz",
1460+ "https://ftp.apnic.net/apnic/whois/apnic.db.inet6num.gz",
1461+ "https://ftp.apnic.net/apnic/whois/apnic.db.inetnum.gz",
1462 #"https://ftp.apnic.net/apnic/whois/apnic.db.route6.gz",
1463 #"https://ftp.apnic.net/apnic/whois/apnic.db.route.gz",
1464 "https://ftp.apnic.net/apnic/whois/apnic.db.aut-num.gz",
1465@@ -45,8 +45,8 @@ WHOIS_SOURCES = (
1466 # XXX ???
1467
1468 # Réseaux IP Européens
1469- #"https://ftp.ripe.net/ripe/dbase/split/ripe.db.inet6num.gz",
1470- #"https://ftp.ripe.net/ripe/dbase/split/ripe.db.inetnum.gz",
1471+ "https://ftp.ripe.net/ripe/dbase/split/ripe.db.inet6num.gz",
1472+ "https://ftp.ripe.net/ripe/dbase/split/ripe.db.inetnum.gz",
1473 #"https://ftp.ripe.net/ripe/dbase/split/ripe.db.route6.gz",
1474 #"https://ftp.ripe.net/ripe/dbase/split/ripe.db.route.gz",
1475 "https://ftp.ripe.net/ripe/dbase/split/ripe.db.aut-num.gz",
1476@@ -55,10 +55,10 @@ WHOIS_SOURCES = (
1477
1478 EXTENDED_SOURCES = (
1479 # African Network Information Centre
1480- "https://ftp.afrinic.net/pub/stats/afrinic/delegated-afrinic-extended-latest",
1481+ #"https://ftp.afrinic.net/pub/stats/afrinic/delegated-afrinic-extended-latest",
1482
1483 # Asia Pacific Network Information Centre
1484- "https://ftp.apnic.net/apnic/stats/apnic/delegated-apnic-extended-latest",
1485+ #"https://ftp.apnic.net/apnic/stats/apnic/delegated-apnic-extended-latest",
1486
1487 # American Registry for Internet Numbers
1488 "https://ftp.arin.net/pub/stats/arin/delegated-arin-extended-latest",
1489@@ -67,7 +67,7 @@ EXTENDED_SOURCES = (
1490 "http://ftp.lacnic.net/pub/stats/lacnic/delegated-lacnic-extended-latest",
1491
1492 # Réseaux IP Européens
1493- "https://ftp.ripe.net/pub/stats/ripencc/delegated-ripencc-extended-latest",
1494+ #"https://ftp.ripe.net/pub/stats/ripencc/delegated-ripencc-extended-latest",
1495 )
1496
1497 class Downloader(object):
1498diff --git a/src/python/location-importer.in b/src/python/location-importer.in
1499index 3c1e5e2..e8a4fc5 100644
1500--- a/src/python/location-importer.in
1501+++ b/src/python/location-importer.in
1502@@ -405,6 +405,10 @@ class CLI(object):
1503 if line.startswith("aut-num:"):
1504 return self._parse_autnum_block(block)
1505
1506+ # inetnum
1507+ if line.startswith("inet6num:") or line.startswith("inetnum:"):
1508+ return self._parse_inetnum_block(block)
1509+
1510 # organisation
1511 elif line.startswith("organisation:"):
1512 return self._parse_org_block(block)
1513@@ -434,6 +438,65 @@ class CLI(object):
1514 autnum.get("asn"), autnum.get("org"),
1515 )
1516
1517+ def _parse_inetnum_block(self, block):
1518+ logging.debug("Parsing inetnum block:")
1519+
1520+ inetnum = {}
1521+ for line in block:
1522+ logging.debug(line)
1523+
1524+ # Split line
1525+ key, val = split_line(line)
1526+
1527+ if key == "inetnum":
1528+ start_address, delim, end_address = val.partition("-")
1529+
1530+ # Strip any excess space
1531+ start_address, end_address = start_address.rstrip(), end_address.strip()
1532+
1533+ # Convert to IP address
1534+ try:
1535+ start_address = ipaddress.ip_address(start_address)
1536+ end_address = ipaddress.ip_address(end_address)
1537+ except ValueError:
1538+ logging.warning("Could not parse line: %s" % line)
1539+ return
1540+
1541+ # Set prefix to default
1542+ prefix = 32
1543+
1544+ # Count number of addresses in this subnet
1545+ num_addresses = int(end_address) - int(start_address)
1546+ if num_addresses:
1547+ prefix -= math.log(num_addresses, 2)
1548+
1549+ inetnum["inetnum"] = "%s/%.0f" % (start_address, prefix)
1550+
1551+ elif key == "inet6num":
1552+ inetnum[key] = val
1553+
1554+ elif key == "country":
1555+ if val == "UNITED STATES":
1556+ val = "US"
1557+
1558+ inetnum[key] = val.upper()
1559+
1560+ # Skip empty objects
1561+ if not inetnum:
1562+ return
1563+
1564+ network = ipaddress.ip_network(inetnum.get("inet6num") or inetnum.get("inetnum"), strict=False)
1565+
1566+ # Bail out in case we have processed a non-public IP network
1567+ if network.is_private:
1568+ logging.warning("Skipping non-globally routable network: %s" % network)
1569+ return
1570+
1571+ self.db.execute("INSERT INTO networks(network, country) \
1572+ VALUES(%s, %s) ON CONFLICT (network) DO UPDATE SET country = excluded.country",
1573+ "%s" % network, inetnum.get("country"),
1574+ )
1575+
1576 def _parse_org_block(self, block):
1577 org = {}
1578 for line in block:
1579--
15802.20.1
1581
1582From 002deb6b42ac0b3624c07e3352cebd72dc0685a2 Mon Sep 17 00:00:00 2001
1583From: =?UTF-8?q?Peter=20M=C3=BCller?= <peter.mueller@ipfire.org>
1584Date: Wed, 21 Oct 2020 14:47:37 +0000
0be475ca 1585Subject: [PATCH 021/111] Revert "Revert "location-importer.in: only import
05db64d0
MT
1586 relevant data from AFRINIC, APNIC and RIPE""
1587MIME-Version: 1.0
1588Content-Type: text/plain; charset=UTF-8
1589Content-Transfer-Encoding: 8bit
1590
1591This reverts commit 13f67f285856e8eabfeff2daf1be3aeaa36a82cc.
1592
1593Signed-off-by: Peter Müller <peter.mueller@ipfire.org>
1594Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
1595---
1596 src/python/location-importer.in | 89 ++++++++++++++++++++++++++++++++-
1597 1 file changed, 87 insertions(+), 2 deletions(-)
1598
1599diff --git a/src/python/location-importer.in b/src/python/location-importer.in
1600index e8a4fc5..5656c41 100644
1601--- a/src/python/location-importer.in
1602+++ b/src/python/location-importer.in
1603@@ -166,6 +166,7 @@ class CLI(object):
1604 -- networks
1605 CREATE TABLE IF NOT EXISTS networks(network inet, country text);
1606 CREATE UNIQUE INDEX IF NOT EXISTS networks_network ON networks(network);
1607+ CREATE INDEX IF NOT EXISTS networks_family ON networks USING BTREE(family(network));
1608 CREATE INDEX IF NOT EXISTS networks_search ON networks USING GIST(network inet_ops);
1609
1610 -- overrides
1611@@ -375,6 +376,16 @@ class CLI(object):
1612 CREATE TEMPORARY TABLE _organizations(handle text, name text NOT NULL)
1613 ON COMMIT DROP;
1614 CREATE UNIQUE INDEX _organizations_handle ON _organizations(handle);
1615+
1616+ CREATE TEMPORARY TABLE _rirdata(network inet NOT NULL, country text NOT NULL)
1617+ ON COMMIT DROP;
1618+ CREATE INDEX _rirdata_search ON _rirdata USING BTREE(family(network), masklen(network));
1619+ CREATE UNIQUE INDEX _rirdata_network ON _rirdata(network);
1620+ """)
1621+
1622+ # Remove all previously imported content
1623+ self.db.execute("""
1624+ TRUNCATE TABLE networks;
1625 """)
1626
1627 for source in location.importer.WHOIS_SOURCES:
1628@@ -382,6 +393,67 @@ class CLI(object):
1629 for block in f:
1630 self._parse_block(block)
1631
1632+ # Process all parsed networks from every RIR we happen to have access to,
1633+ # insert the largest network chunks into the networks table immediately...
1634+ families = self.db.query("SELECT DISTINCT family(network) AS family FROM _rirdata ORDER BY family(network)")
1635+
1636+ for family in (row.family for row in families):
1637+ smallest = self.db.get("SELECT MIN(masklen(network)) AS prefix FROM _rirdata WHERE family(network) = %s", family)
1638+
1639+ self.db.execute("INSERT INTO networks(network, country) \
1640+ SELECT network, country FROM _rirdata WHERE masklen(network) = %s AND family(network) = %s", smallest.prefix, family)
1641+
1642+ # ... determine any other prefixes for this network family, ...
1643+ prefixes = self.db.query("SELECT DISTINCT masklen(network) AS prefix FROM _rirdata \
1644+ WHERE family(network) = %s ORDER BY masklen(network) ASC OFFSET 1", family)
1645+
1646+ # ... and insert networks with this prefix in case they provide additional
1647+ # information (i. e. subnet of a larger chunk with a different country)
1648+ for prefix in (row.prefix for row in prefixes):
1649+ self.db.execute("""
1650+ WITH candidates AS (
1651+ SELECT
1652+ _rirdata.network,
1653+ _rirdata.country
1654+ FROM
1655+ _rirdata
1656+ WHERE
1657+ family(_rirdata.network) = %s
1658+ AND
1659+ masklen(_rirdata.network) = %s
1660+ ),
1661+ filtered AS (
1662+ SELECT
1663+ DISTINCT ON (c.network)
1664+ c.network,
1665+ c.country,
1666+ masklen(networks.network),
1667+ networks.country AS parent_country
1668+ FROM
1669+ candidates c
1670+ LEFT JOIN
1671+ networks
1672+ ON
1673+ c.network << networks.network
1674+ ORDER BY
1675+ c.network,
1676+ masklen(networks.network) DESC NULLS LAST
1677+ )
1678+ INSERT INTO
1679+ networks(network, country)
1680+ SELECT
1681+ network,
1682+ country
1683+ FROM
1684+ filtered
1685+ WHERE
1686+ parent_country IS NULL
1687+ OR
1688+ country <> parent_country
1689+ ON CONFLICT DO NOTHING""",
1690+ family, prefix,
1691+ )
1692+
1693 self.db.execute("""
1694 INSERT INTO autnums(number, name)
1695 SELECT _autnums.number, _organizations.name FROM _autnums
1696@@ -482,17 +554,30 @@ class CLI(object):
1697 inetnum[key] = val.upper()
1698
1699 # Skip empty objects
1700- if not inetnum:
1701+ if not inetnum or not "country" in inetnum:
1702 return
1703
1704 network = ipaddress.ip_network(inetnum.get("inet6num") or inetnum.get("inetnum"), strict=False)
1705
1706+ # Bail out in case we have processed a network covering the entire IP range, which
1707+ # is necessary to work around faulty (?) IPv6 network processing
1708+ if network.prefixlen == 0:
1709+ logging.warning("Skipping network covering the entire IP adress range: %s" % network)
1710+ return
1711+
1712+ # Bail out in case we have processed a network whose prefix length indicates it is
1713+ # not globally routable (we have decided not to process them at the moment, as they
1714+ # significantly enlarge our database without providing very helpful additional information)
1715+ if (network.prefixlen > 24 and network.version == 4) or (network.prefixlen > 48 and network.version == 6):
1716+ logging.info("Skipping network too small to be publicly announced: %s" % network)
1717+ return
1718+
1719 # Bail out in case we have processed a non-public IP network
1720 if network.is_private:
1721 logging.warning("Skipping non-globally routable network: %s" % network)
1722 return
1723
1724- self.db.execute("INSERT INTO networks(network, country) \
1725+ self.db.execute("INSERT INTO _rirdata(network, country) \
1726 VALUES(%s, %s) ON CONFLICT (network) DO UPDATE SET country = excluded.country",
1727 "%s" % network, inetnum.get("country"),
1728 )
1729--
17302.20.1
1731
1732From 28c73fa3f4257e0a41e52af8a9643da414a6cb6f Mon Sep 17 00:00:00 2001
1733From: =?UTF-8?q?Peter=20M=C3=BCller?= <peter.mueller@ipfire.org>
1734Date: Wed, 21 Oct 2020 14:47:38 +0000
0be475ca 1735Subject: [PATCH 022/111] export.py: fix exporting IP networks for crappy
05db64d0
MT
1736 xt_geoip module
1737MIME-Version: 1.0
1738Content-Type: text/plain; charset=UTF-8
1739Content-Transfer-Encoding: 8bit
1740
1741In contrast to the location database itself, the xt_geoip module
1742consumes a list of IP networks for each country, and returns after the
1743first match.
1744
1745We therefore need to...
1746
1747(a) sort IP networks by their size, allow as precise matches as possible
1748(b) export _any_ IP networks - including inverted subnets - to prevent
1749 undefined overlaps
1750(c) do the entire thing as fast as possible, consuming as less disk
1751 space as possible, which is why we can't just iterate over all /24
1752 chunks
1753
1754Partially fixes: #12499
1755
1756Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
1757Signed-off-by: Peter Müller <peter.mueller@ipfire.org>
1758Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
1759---
1760 src/python/export.py | 69 ++++++++++++++++++++++++++++++++++----------
1761 1 file changed, 54 insertions(+), 15 deletions(-)
1762
1763diff --git a/src/python/export.py b/src/python/export.py
1764index d15c6f0..5eaf43f 100644
1765--- a/src/python/export.py
1766+++ b/src/python/export.py
1767@@ -39,8 +39,8 @@ class OutputWriter(object):
1768 suffix = "networks"
1769 mode = "w"
1770
1771- def __init__(self, f, prefix=None, flatten=True):
1772- self.f, self.prefix, self.flatten = f, prefix, flatten
1773+ def __init__(self, db, f, prefix=None, flatten=True):
1774+ self.db, self.f, self.prefix, self.flatten = db, f, prefix, flatten
1775
1776 # The previously written network
1777 self._last_network = None
1778@@ -49,13 +49,13 @@ class OutputWriter(object):
1779 self._write_header()
1780
1781 @classmethod
1782- def open(cls, filename, **kwargs):
1783+ def open(cls, db, filename, **kwargs):
1784 """
1785 Convenience function to open a file
1786 """
1787 f = open(filename, cls.mode)
1788
1789- return cls(f, **kwargs)
1790+ return cls(db, f, **kwargs)
1791
1792 def __repr__(self):
1793 return "<%s f=%s>" % (self.__class__.__name__, self.f)
1794@@ -87,13 +87,31 @@ class OutputWriter(object):
1795 def _write_network(self, network):
1796 self.f.write("%s\n" % network)
1797
1798- def write(self, network):
1799+ def write(self, network, subnets):
1800 if self.flatten and self._flatten(network):
1801 log.debug("Skipping writing network %s" % network)
1802 return
1803
1804- # Write the network to file
1805- self._write_network(network)
1806+ # Write the network when it has no subnets
1807+ if not subnets:
1808+ network = ipaddress.ip_network("%s" % network)
1809+ return self._write_network(network)
1810+
1811+ # Collect all matching subnets
1812+ matching_subnets = []
1813+
1814+ for subnet in sorted(subnets):
1815+ # Try to find the subnet in the database
1816+ n = self.db.lookup("%s" % subnet.network_address)
1817+
1818+ # No entry or matching country means those IP addresses belong here
1819+ if not n or n.country_code == network.country_code:
1820+ matching_subnets.append(subnet)
1821+
1822+ # Write all networks as compact as possible
1823+ for network in ipaddress.collapse_addresses(matching_subnets):
1824+ log.debug("Writing %s to database" % network)
1825+ self._write_network(network)
1826
1827 def finish(self):
1828 """
1829@@ -143,10 +161,10 @@ class XTGeoIPOutputWriter(OutputWriter):
1830 mode = "wb"
1831
1832 def _write_network(self, network):
1833- for address in (network.first_address, network.last_address):
1834+ for address in (network.network_address, network.broadcast_address):
1835 # Convert this into a string of bits
1836 bytes = socket.inet_pton(
1837- network.family, address,
1838+ socket.AF_INET6 if network.version == 6 else socket.AF_INET, "%s" % address,
1839 )
1840
1841 self.f.write(bytes)
1842@@ -175,7 +193,7 @@ class Exporter(object):
1843 directory, prefix=country_code, suffix=self.writer.suffix, family=family,
1844 )
1845
1846- writers[country_code] = self.writer.open(filename, prefix="CC_%s" % country_code)
1847+ writers[country_code] = self.writer.open(self.db, filename, prefix="CC_%s" % country_code)
1848
1849 # Create writers for ASNs
1850 for asn in asns:
1851@@ -183,22 +201,43 @@ class Exporter(object):
1852 directory, "AS%s" % asn, suffix=self.writer.suffix, family=family,
1853 )
1854
1855- writers[asn] = self.writer.open(filename, prefix="AS%s" % asn)
1856+ writers[asn] = self.writer.open(self.db, filename, prefix="AS%s" % asn)
1857
1858 # Get all networks that match the family
1859 networks = self.db.search_networks(family=family)
1860
1861+ # Materialise the generator into a list (uses quite some memory)
1862+ networks = list(networks)
1863+
1864 # Walk through all networks
1865- for network in networks:
1866+ for i, network in enumerate(networks):
1867+ _network = ipaddress.ip_network("%s" % network)
1868+
1869+ # Search for all subnets
1870+ subnets = set()
1871+
1872+ while i < len(networks):
1873+ subnet = networks[i+1]
1874+
1875+ if subnet.is_subnet_of(network):
1876+ _subnet = ipaddress.ip_network("%s" % subnet)
1877+
1878+ subnets.add(_subnet)
1879+ subnets.update(_network.address_exclude(_subnet))
1880+
1881+ i += 1
1882+ else:
1883+ break
1884+
1885 # Write matching countries
1886 try:
1887- writers[network.country_code].write(network)
1888+ writers[network.country_code].write(network, subnets)
1889 except KeyError:
1890 pass
1891
1892 # Write matching ASNs
1893 try:
1894- writers[network.asn].write(network)
1895+ writers[network.asn].write(network, subnets)
1896 except KeyError:
1897 pass
1898
1899@@ -209,7 +248,7 @@ class Exporter(object):
1900 country = flags[flag]
1901
1902 try:
1903- writers[country].write(network)
1904+ writers[country].write(network, subnets)
1905 except KeyError:
1906 pass
1907
1908--
19092.20.1
1910
1911From bd341642fc6bbcc050e9b4ec5124585c83cab84d Mon Sep 17 00:00:00 2001
1912From: =?UTF-8?q?Peter=20M=C3=BCller?= <peter.mueller@ipfire.org>
1913Date: Wed, 21 Oct 2020 14:47:39 +0000
0be475ca
MT
1914Subject: [PATCH 023/111] location-importer.in: filter bogus IP networks for
1915 both Whois and extended sources
05db64d0
MT
1916MIME-Version: 1.0
1917Content-Type: text/plain; charset=UTF-8
1918Content-Transfer-Encoding: 8bit
1919
1920Sanity checks for parsed networks have been put into a separate function
1921to avoid boilerplate code for extended sources. This makes the location
1922database less vulnerable to garbage written into RIR databases on
1923purpose or by chance.
1924
1925Fixes: #12500
1926
1927Signed-off-by: Peter Müller <peter.mueller@ipfire.org>
1928Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
1929---
1930 src/python/location-importer.in | 83 ++++++++++++++++++++++++++-------
1931 1 file changed, 67 insertions(+), 16 deletions(-)
1932
1933diff --git a/src/python/location-importer.in b/src/python/location-importer.in
1934index 5656c41..f24d357 100644
1935--- a/src/python/location-importer.in
1936+++ b/src/python/location-importer.in
1937@@ -469,6 +469,69 @@ class CLI(object):
1938 for line in f:
1939 self._parse_line(line)
1940
1941+ def _check_parsed_network(self, network):
1942+ """
1943+ Assistive function to detect and subsequently sort out parsed
1944+ networks from RIR data (both Whois and so-called "extended sources"),
1945+ which are or have...
1946+
1947+ (a) not globally routable (RFC 1918 space, et al.)
1948+ (b) covering a too large chunk of the IP address space (prefix length
1949+ is < 7 for IPv4 networks, and < 10 for IPv6)
1950+ (c) "0.0.0.0" or "::" as a network address
1951+ (d) are too small for being publicly announced (we have decided not to
1952+ process them at the moment, as they significantly enlarge our
1953+ database without providing very helpful additional information)
1954+
1955+ This unfortunately is necessary due to brain-dead clutter across
1956+ various RIR databases, causing mismatches and eventually disruptions.
1957+
1958+ We will return False in case a network is not suitable for adding
1959+ it to our database, and True otherwise.
1960+ """
1961+
1962+ if not network or not (isinstance(network, ipaddress.IPv4Network) or isinstance(network, ipaddress.IPv6Network)):
1963+ return False
1964+
1965+ if not network.is_global:
1966+ logging.warning("Skipping non-globally routable network: %s" % network)
1967+ return False
1968+
1969+ if network.version == 4:
1970+ if network.prefixlen < 7:
1971+ logging.warning("Skipping too big IP chunk: %s" % network)
1972+ return False
1973+
1974+ if network.prefixlen > 24:
1975+ logging.info("Skipping network too small to be publicly announced: %s" % network)
1976+ return False
1977+
1978+ if str(network.network_address) == "0.0.0.0":
1979+ logging.warning("Skipping network based on 0.0.0.0: %s" % network)
1980+ return False
1981+
1982+ elif network.version == 6:
1983+ if network.prefixlen < 10:
1984+ logging.warning("Skipping too big IP chunk: %s" % network)
1985+ return False
1986+
1987+ if network.prefixlen > 48:
1988+ logging.info("Skipping network too small to be publicly announced: %s" % network)
1989+ return False
1990+
1991+ if str(network.network_address) == "::":
1992+ logging.warning("Skipping network based on '::': %s" % network)
1993+ return False
1994+
1995+ else:
1996+ # This should not happen...
1997+ logging.warning("Skipping network of unknown family, this should not happen: %s" % network)
1998+ return False
1999+
2000+ # In case we have made it here, the network is considered to
2001+ # be suitable for libloc consumption...
2002+ return True
2003+
2004 def _parse_block(self, block):
2005 # Get first line to find out what type of block this is
2006 line = block[0]
2007@@ -559,22 +622,7 @@ class CLI(object):
2008
2009 network = ipaddress.ip_network(inetnum.get("inet6num") or inetnum.get("inetnum"), strict=False)
2010
2011- # Bail out in case we have processed a network covering the entire IP range, which
2012- # is necessary to work around faulty (?) IPv6 network processing
2013- if network.prefixlen == 0:
2014- logging.warning("Skipping network covering the entire IP adress range: %s" % network)
2015- return
2016-
2017- # Bail out in case we have processed a network whose prefix length indicates it is
2018- # not globally routable (we have decided not to process them at the moment, as they
2019- # significantly enlarge our database without providing very helpful additional information)
2020- if (network.prefixlen > 24 and network.version == 4) or (network.prefixlen > 48 and network.version == 6):
2021- logging.info("Skipping network too small to be publicly announced: %s" % network)
2022- return
2023-
2024- # Bail out in case we have processed a non-public IP network
2025- if network.is_private:
2026- logging.warning("Skipping non-globally routable network: %s" % network)
2027+ if not self._check_parsed_network(network):
2028 return
2029
2030 self.db.execute("INSERT INTO _rirdata(network, country) \
2031@@ -658,6 +706,9 @@ class CLI(object):
2032 log.warning("Invalid IP address: %s" % address)
2033 return
2034
2035+ if not self._check_parsed_network(network):
2036+ return
2037+
2038 self.db.execute("INSERT INTO networks(network, country) \
2039 VALUES(%s, %s) ON CONFLICT (network) DO \
2040 UPDATE SET country = excluded.country",
2041--
20422.20.1
2043
2044From eee65490a10e0fe89b3834b8be176fc900084fa0 Mon Sep 17 00:00:00 2001
2045From: =?UTF-8?q?Peter=20M=C3=BCller?= <peter.mueller@ipfire.org>
2046Date: Wed, 21 Oct 2020 14:47:40 +0000
0be475ca 2047Subject: [PATCH 024/111] importer.py: fetch LACNIC data via HTTPS
05db64d0
MT
2048MIME-Version: 1.0
2049Content-Type: text/plain; charset=UTF-8
2050Content-Transfer-Encoding: 8bit
2051
2052Signed-off-by: Peter Müller <peter.mueller@ipfire.org>
2053Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
2054---
2055 src/python/importer.py | 2 +-
2056 1 file changed, 1 insertion(+), 1 deletion(-)
2057
2058diff --git a/src/python/importer.py b/src/python/importer.py
2059index f19db4b..5f46bc3 100644
2060--- a/src/python/importer.py
2061+++ b/src/python/importer.py
2062@@ -64,7 +64,7 @@ EXTENDED_SOURCES = (
2063 "https://ftp.arin.net/pub/stats/arin/delegated-arin-extended-latest",
2064
2065 # Latin America and Caribbean Network Information Centre
2066- "http://ftp.lacnic.net/pub/stats/lacnic/delegated-lacnic-extended-latest",
2067+ "https://ftp.lacnic.net/pub/stats/lacnic/delegated-lacnic-extended-latest",
2068
2069 # Réseaux IP Européens
2070 #"https://ftp.ripe.net/pub/stats/ripencc/delegated-ripencc-extended-latest",
2071--
20722.20.1
2073
2074From 84187ab5436eb158529d6f5e2a38890b4af3ddb4 Mon Sep 17 00:00:00 2001
2075From: =?UTF-8?q?Peter=20M=C3=BCller?= <peter.mueller@ipfire.org>
2076Date: Wed, 21 Oct 2020 14:47:41 +0000
0be475ca 2077Subject: [PATCH 025/111] location-importer.in: omit historic/orphaned RIR data
05db64d0
MT
2078MIME-Version: 1.0
2079Content-Type: text/plain; charset=UTF-8
2080Content-Transfer-Encoding: 8bit
2081
2082Some RIRs include detailled information regarding networks not managed
2083by or allocated to themselves, particually APNIC. We need to filter
2084those networks (they usually have a characteristic network name) in
2085order to prevent operational quirks or returning wrong country codes.
2086
2087Fixes: #12501
2088Partially fixes: #12499
2089
2090Cc: Michael Tremer <michael.tremer@ipfire.org>
2091Signed-off-by: Peter Müller <peter.mueller@ipfire.org>
2092Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
2093---
2094 src/python/location-importer.in | 38 +++++++++++++++++++++------------
2095 1 file changed, 24 insertions(+), 14 deletions(-)
2096
2097diff --git a/src/python/location-importer.in b/src/python/location-importer.in
2098index f24d357..a869256 100644
2099--- a/src/python/location-importer.in
2100+++ b/src/python/location-importer.in
2101@@ -494,38 +494,38 @@ class CLI(object):
2102 return False
2103
2104 if not network.is_global:
2105- logging.warning("Skipping non-globally routable network: %s" % network)
2106+ log.warning("Skipping non-globally routable network: %s" % network)
2107 return False
2108
2109 if network.version == 4:
2110 if network.prefixlen < 7:
2111- logging.warning("Skipping too big IP chunk: %s" % network)
2112+ log.warning("Skipping too big IP chunk: %s" % network)
2113 return False
2114
2115 if network.prefixlen > 24:
2116- logging.info("Skipping network too small to be publicly announced: %s" % network)
2117+ log.info("Skipping network too small to be publicly announced: %s" % network)
2118 return False
2119
2120 if str(network.network_address) == "0.0.0.0":
2121- logging.warning("Skipping network based on 0.0.0.0: %s" % network)
2122+ log.warning("Skipping network based on 0.0.0.0: %s" % network)
2123 return False
2124
2125 elif network.version == 6:
2126 if network.prefixlen < 10:
2127- logging.warning("Skipping too big IP chunk: %s" % network)
2128+ log.warning("Skipping too big IP chunk: %s" % network)
2129 return False
2130
2131 if network.prefixlen > 48:
2132- logging.info("Skipping network too small to be publicly announced: %s" % network)
2133+ log.info("Skipping network too small to be publicly announced: %s" % network)
2134 return False
2135
2136 if str(network.network_address) == "::":
2137- logging.warning("Skipping network based on '::': %s" % network)
2138+ log.warning("Skipping network based on '::': %s" % network)
2139 return False
2140
2141 else:
2142 # This should not happen...
2143- logging.warning("Skipping network of unknown family, this should not happen: %s" % network)
2144+ log.warning("Skipping network of unknown family, this should not happen: %s" % network)
2145 return False
2146
2147 # In case we have made it here, the network is considered to
2148@@ -574,15 +574,22 @@ class CLI(object):
2149 )
2150
2151 def _parse_inetnum_block(self, block):
2152- logging.debug("Parsing inetnum block:")
2153+ log.debug("Parsing inetnum block:")
2154
2155 inetnum = {}
2156 for line in block:
2157- logging.debug(line)
2158+ log.debug(line)
2159
2160 # Split line
2161 key, val = split_line(line)
2162
2163+ # Filter any inetnum records which are only referring to IP space
2164+ # not managed by that specific RIR...
2165+ if key == "netname":
2166+ if re.match(r"(ERX-NETBLOCK|(AFRINIC|ARIN|LACNIC|RIPE)-CIDR-BLOCK|IANA-NETBLOCK-\d{1,3}|NON-RIPE-NCC-MANAGED-ADDRESS-BLOCK)", val.strip()):
2167+ log.warning("Skipping record indicating historic/orphaned data: %s" % val.strip())
2168+ return
2169+
2170 if key == "inetnum":
2171 start_address, delim, end_address = val.partition("-")
2172
2173@@ -594,7 +601,7 @@ class CLI(object):
2174 start_address = ipaddress.ip_address(start_address)
2175 end_address = ipaddress.ip_address(end_address)
2176 except ValueError:
2177- logging.warning("Could not parse line: %s" % line)
2178+ log.warning("Could not parse line: %s" % line)
2179 return
2180
2181 # Set prefix to default
2182@@ -611,15 +618,18 @@ class CLI(object):
2183 inetnum[key] = val
2184
2185 elif key == "country":
2186- if val == "UNITED STATES":
2187- val = "US"
2188-
2189 inetnum[key] = val.upper()
2190
2191 # Skip empty objects
2192 if not inetnum or not "country" in inetnum:
2193 return
2194
2195+ # Skip objects with bogus country code 'ZZ'
2196+ if inetnum.get("country") == "ZZ":
2197+ log.warning("Skipping network with bogus country 'ZZ': %s" % \
2198+ (inetnum.get("inet6num") or inetnum.get("inetnum")))
2199+ return
2200+
2201 network = ipaddress.ip_network(inetnum.get("inet6num") or inetnum.get("inetnum"), strict=False)
2202
2203 if not self._check_parsed_network(network):
2204--
22052.20.1
2206
2207From ebb087cfa30ec5ca0c96dcce66a91245c1ffc271 Mon Sep 17 00:00:00 2001
2208From: =?UTF-8?q?Peter=20M=C3=BCller?= <peter.mueller@ipfire.org>
2209Date: Wed, 21 Oct 2020 14:47:43 +0000
0be475ca 2210Subject: [PATCH 026/111] location-importer.in: avoid log spam for too small
05db64d0
MT
2211 networks
2212MIME-Version: 1.0
2213Content-Type: text/plain; charset=UTF-8
2214Content-Transfer-Encoding: 8bit
2215
2216Signed-off-by: Peter Müller <peter.mueller@ipfire.org>
2217Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
2218---
2219 src/python/location-importer.in | 4 ++--
2220 1 file changed, 2 insertions(+), 2 deletions(-)
2221
2222diff --git a/src/python/location-importer.in b/src/python/location-importer.in
2223index a869256..864eab1 100644
2224--- a/src/python/location-importer.in
2225+++ b/src/python/location-importer.in
2226@@ -503,7 +503,7 @@ class CLI(object):
2227 return False
2228
2229 if network.prefixlen > 24:
2230- log.info("Skipping network too small to be publicly announced: %s" % network)
2231+ log.debug("Skipping network too small to be publicly announced: %s" % network)
2232 return False
2233
2234 if str(network.network_address) == "0.0.0.0":
2235@@ -516,7 +516,7 @@ class CLI(object):
2236 return False
2237
2238 if network.prefixlen > 48:
2239- log.info("Skipping network too small to be publicly announced: %s" % network)
2240+ log.debug("Skipping network too small to be publicly announced: %s" % network)
2241 return False
2242
2243 if str(network.network_address) == "::":
2244--
22452.20.1
2246
2247From bbed1fd2330e8efa6b413dc152a1a6ef2d771aac Mon Sep 17 00:00:00 2001
2248From: Michael Tremer <michael.tremer@ipfire.org>
2249Date: Tue, 27 Oct 2020 17:14:30 +0000
0be475ca 2250Subject: [PATCH 027/111] export: Flatten the tree before exporting it
05db64d0
MT
2251
2252This patch removes the possibility that any IP address ranges
2253might show up in multiple exported files.
2254
2255If this was content from the database:
2256
2257 * 10.0.0.0/16 - DE
2258 * 10.0.1.0/24 - FR
2259
2260Then the IP address 10.0.1.1 would match for both countries.
2261
2262The algorithm will now break the larger /16 subnet apart into
2263smaller subnets so that 10.0.1.0/24 is no longer overlapped.
2264
2265There was some time spent on this to make this as efficient
2266as possible.
2267
2268Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
2269---
2270 src/python/export.py | 154 ++++++++++++++++++++++++++++++-------------
2271 1 file changed, 110 insertions(+), 44 deletions(-)
2272
2273diff --git a/src/python/export.py b/src/python/export.py
2274index 5eaf43f..dd44332 100644
2275--- a/src/python/export.py
2276+++ b/src/python/export.py
2277@@ -89,28 +89,55 @@ class OutputWriter(object):
2278
2279 def write(self, network, subnets):
2280 if self.flatten and self._flatten(network):
2281- log.debug("Skipping writing network %s" % network)
2282+ log.debug("Skipping writing network %s (last one was %s)" % (network, self._last_network))
2283 return
2284
2285+ # Convert network into a Python object
2286+ _network = ipaddress.ip_network("%s" % network)
2287+
2288 # Write the network when it has no subnets
2289 if not subnets:
2290- network = ipaddress.ip_network("%s" % network)
2291- return self._write_network(network)
2292+ log.debug("Writing %s to %s" % (_network, self.f))
2293+ return self._write_network(_network)
2294+
2295+ # Convert subnets into Python objects
2296+ _subnets = [ipaddress.ip_network("%s" % subnet) for subnet in subnets]
2297+
2298+ # Split the network into smaller bits so that
2299+ # we can accomodate for any gaps in it later
2300+ to_check = set()
2301+ for _subnet in _subnets:
2302+ to_check.update(
2303+ _network.address_exclude(_subnet)
2304+ )
2305+
2306+ # Clear the list of all subnets
2307+ subnets = []
2308+
2309+ # Check if all subnets to not overlap with anything else
2310+ while to_check:
2311+ subnet_to_check = to_check.pop()
2312
2313- # Collect all matching subnets
2314- matching_subnets = []
2315+ for _subnet in _subnets:
2316+ # Drop this subnet if it equals one of the subnets
2317+ # or if it is subnet of one of them
2318+ if subnet_to_check == _subnet or subnet_to_check.subnet_of(_subnet):
2319+ break
2320
2321- for subnet in sorted(subnets):
2322- # Try to find the subnet in the database
2323- n = self.db.lookup("%s" % subnet.network_address)
2324+ # Break it down if it overlaps
2325+ if subnet_to_check.overlaps(_subnet):
2326+ to_check.update(
2327+ subnet_to_check.address_exclude(_subnet)
2328+ )
2329+ break
2330
2331- # No entry or matching country means those IP addresses belong here
2332- if not n or n.country_code == network.country_code:
2333- matching_subnets.append(subnet)
2334+ # Add the subnet again as it passed the check
2335+ else:
2336+ subnets.append(subnet_to_check)
2337
2338 # Write all networks as compact as possible
2339- for network in ipaddress.collapse_addresses(matching_subnets):
2340- log.debug("Writing %s to database" % network)
2341+ for network in ipaddress.collapse_addresses(subnets):
2342+ log.debug("Writing %s to %s" % (network, self.f))
2343 self._write_network(network)
2344
2345 def finish(self):
2346@@ -206,40 +233,40 @@ class Exporter(object):
2347 # Get all networks that match the family
2348 networks = self.db.search_networks(family=family)
2349
2350- # Materialise the generator into a list (uses quite some memory)
2351- networks = list(networks)
2352+ # Create a stack with all networks in order where we can put items back
2353+ # again and retrieve them in the next iteration.
2354+ networks = BufferedStack(networks)
2355
2356 # Walk through all networks
2357- for i, network in enumerate(networks):
2358- _network = ipaddress.ip_network("%s" % network)
2359-
2360- # Search for all subnets
2361- subnets = set()
2362-
2363- while i < len(networks):
2364- subnet = networks[i+1]
2365-
2366- if subnet.is_subnet_of(network):
2367- _subnet = ipaddress.ip_network("%s" % subnet)
2368-
2369- subnets.add(_subnet)
2370- subnets.update(_network.address_exclude(_subnet))
2371-
2372- i += 1
2373- else:
2374+ for network in networks:
2375+ # Collect all networks which are a subnet of network
2376+ subnets = []
2377+ for subnet in networks:
2378+ # If the next subnet was not a subnet, we have to push
2379+ # it back on the stack and break this loop
2380+ if not subnet.is_subnet_of(network):
2381+ networks.push(subnet)
2382 break
2383
2384+ subnets.append(subnet)
2385+
2386 # Write matching countries
2387- try:
2388- writers[network.country_code].write(network, subnets)
2389- except KeyError:
2390- pass
2391+ if network.country_code and network.country_code in writers:
2392+ # Mismatching subnets
2393+ gaps = [
2394+ subnet for subnet in subnets if not network.country_code == subnet.country_code
2395+ ]
2396+
2397+ writers[network.country_code].write(network, gaps)
2398
2399 # Write matching ASNs
2400- try:
2401- writers[network.asn].write(network, subnets)
2402- except KeyError:
2403- pass
2404+ if network.asn and network.asn in writers:
2405+ # Mismatching subnets
2406+ gaps = [
2407+ subnet for subnet in subnets if not network.asn == subnet.asn
2408+ ]
2409+
2410+ writers[network.asn].write(network, gaps)
2411
2412 # Handle flags
2413 for flag in flags:
2414@@ -247,10 +274,19 @@ class Exporter(object):
2415 # Fetch the "fake" country code
2416 country = flags[flag]
2417
2418- try:
2419- writers[country].write(network, subnets)
2420- except KeyError:
2421- pass
2422+ if not country in writers:
2423+ continue
2424+
2425+ gaps = [
2426+ subnet for subnet in subnets
2427+ if not subnet.has_flag(flag)
2428+ ]
2429+
2430+ writers[country].write(network, gaps)
2431+
2432+ # Push all subnets back onto the stack
2433+ for subnet in reversed(subnets):
2434+ networks.push(subnet)
2435
2436 # Write everything to the filesystem
2437 for writer in writers.values():
2438@@ -262,3 +298,33 @@ class Exporter(object):
2439 )
2440
2441 return os.path.join(directory, filename)
2442+
2443+
2444+class BufferedStack(object):
2445+ """
2446+ This class takes an iterator and when being iterated
2447+ over it returns objects from that iterator for as long
2448+ as there are any.
2449+
2450+ It additionally has a function to put an item back on
2451+ the back so that it will be returned again at the next
2452+ iteration.
2453+ """
2454+ def __init__(self, iterator):
2455+ self.iterator = iterator
2456+ self.stack = []
2457+
2458+ def __iter__(self):
2459+ return self
2460+
2461+ def __next__(self):
2462+ if self.stack:
2463+ return self.stack.pop(0)
2464+
2465+ return next(self.iterator)
2466+
2467+ def push(self, elem):
2468+ """
2469+ Takes an element and puts it on the stack
2470+ """
2471+ self.stack.insert(0, elem)
2472--
24732.20.1
2474
2475From e99a72265c1ba2194b61663eda7e9f14e0083016 Mon Sep 17 00:00:00 2001
2476From: Michael Tremer <michael.tremer@ipfire.org>
2477Date: Wed, 28 Oct 2020 09:52:36 +0000
0be475ca 2478Subject: [PATCH 028/111] location: Fix Python syntax error in verify()
05db64d0
MT
2479
2480The database is now being opened before the requested
2481method is called and handle_verify() wasn't updated.
2482
2483Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
2484---
2485 src/python/location.in | 8 +-------
2486 1 file changed, 1 insertion(+), 7 deletions(-)
2487
2488diff --git a/src/python/location.in b/src/python/location.in
2489index 44ad726..b5e5758 100644
2490--- a/src/python/location.in
2491+++ b/src/python/location.in
2492@@ -453,13 +453,7 @@ class CLI(object):
2493
2494 return 0
2495
2496- def handle_verify(self, ns):
2497- try:
2498- db = location.Database(ns.database)
2499- except FileNotFoundError as e:
2500- log.error("%s: %s" % (ns.database, e))
2501- return 127
2502-
2503+ def handle_verify(self, db, ns):
2504 # Verify the database
2505 with open(ns.public_key, "r") as f:
2506 if not db.verify(f):
2507--
25082.20.1
2509
2510From 0c74f6b1a3bdce5ebdc2ee452b9baf3e421dd3d1 Mon Sep 17 00:00:00 2001
2511From: =?UTF-8?q?Peter=20M=C3=BCller?= <peter.mueller@ipfire.org>
2512Date: Thu, 29 Oct 2020 07:25:53 -0700
0be475ca
MT
2513Subject: [PATCH 029/111] location update: Remove double conversion of
2514 timestamps
05db64d0
MT
2515MIME-Version: 1.0
2516Content-Type: text/plain; charset=UTF-8
2517Content-Transfer-Encoding: 8bit
2518
2519This caused that the timestamp in DNS was misinterpreted
2520as local time and often, databases could not be downloaded.
2521
2522Signed-off-by: Peter Müller <peter.mueller@ipfire.org>
2523---
2524 src/python/location.in | 5 +----
2525 1 file changed, 1 insertion(+), 4 deletions(-)
2526
2527diff --git a/src/python/location.in b/src/python/location.in
2528index b5e5758..070640c 100644
2529--- a/src/python/location.in
2530+++ b/src/python/location.in
2531@@ -421,11 +421,8 @@ class CLI(object):
2532 # Fetch the timestamp we need from DNS
2533 t = location.discover_latest_version()
2534
2535- # Parse timestamp into datetime format
2536- timestamp = datetime.datetime.utcfromtimestamp(t) if t else None
2537-
2538 # Check the version of the local database
2539- if db and timestamp and db.created_at >= timestamp.timestamp():
2540+ if db and t and db.created_at >= t:
2541 log.info("Already on the latest version")
2542 return
2543
2544--
25452.20.1
2546
2547From 60c1ac0307312614bd6980d30b44bb59b5a6ab6e Mon Sep 17 00:00:00 2001
2548From: =?UTF-8?q?Peter=20M=C3=BCller?= <peter.mueller@ipfire.org>
2549Date: Thu, 29 Oct 2020 07:36:46 -0700
0be475ca 2550Subject: [PATCH 030/111] location.in: do not confuse UTC with local time zones
05db64d0
MT
2551MIME-Version: 1.0
2552Content-Type: text/plain; charset=UTF-8
2553Content-Transfer-Encoding: 8bit
2554
2555Signed-off-by: Peter Müller <peter.mueller@ipfire.org>
2556---
2557 src/python/location.in | 12 +++++-------
2558 1 file changed, 5 insertions(+), 7 deletions(-)
2559
2560diff --git a/src/python/location.in b/src/python/location.in
2561index 070640c..0d09210 100644
2562--- a/src/python/location.in
2563+++ b/src/python/location.in
2564@@ -398,10 +398,7 @@ class CLI(object):
2565
2566 def handle_update(self, db, ns):
2567 if ns.cron and db:
2568- now = datetime.datetime.utcnow()
2569-
2570- # Parse the database timestamp
2571- t = datetime.datetime.utcfromtimestamp(db.created_at)
2572+ now = time.time()
2573
2574 if ns.cron == "daily":
2575 delta = datetime.timedelta(days=1)
2576@@ -410,11 +407,12 @@ class CLI(object):
2577 elif ns.cron == "monthly":
2578 delta = datetime.timedelta(days=30)
2579
2580+ delta = delta.total_seconds()
2581+
2582 # Check if the database has recently been updated
2583- if t >= (now - delta):
2584+ if db.created_at >= (now - delta):
2585 log.info(
2586- _("The database has been updated recently (%s)") % \
2587- format_timedelta(now - t),
2588+ _("The database has been updated recently"),
2589 )
2590 return 3
2591
2592--
25932.20.1
2594
2595From e7d612e5219ef9ba612ed404e4e2c174110d3dd7 Mon Sep 17 00:00:00 2001
2596From: =?UTF-8?q?Peter=20M=C3=BCller?= <peter.mueller@ipfire.org>
2597Date: Tue, 3 Nov 2020 15:31:08 +0000
0be475ca 2598Subject: [PATCH 031/111] location-importer.in: always convert organisation
05db64d0
MT
2599 handles into upper cases
2600MIME-Version: 1.0
2601Content-Type: text/plain; charset=UTF-8
2602Content-Transfer-Encoding: 8bit
2603
2604Fixes: #12523
2605
2606Signed-off-by: Peter Müller <peter.mueller@ipfire.org>
2607Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
2608---
2609 src/python/location-importer.in | 6 ++++--
2610 1 file changed, 4 insertions(+), 2 deletions(-)
2611
2612diff --git a/src/python/location-importer.in b/src/python/location-importer.in
2613index 864eab1..2dec89e 100644
2614--- a/src/python/location-importer.in
2615+++ b/src/python/location-importer.in
2616@@ -560,7 +560,7 @@ class CLI(object):
2617 autnum["asn"] = m.group(2)
2618
2619 elif key == "org":
2620- autnum[key] = val
2621+ autnum[key] = val.upper()
2622
2623 # Skip empty objects
2624 if not autnum:
2625@@ -646,7 +646,9 @@ class CLI(object):
2626 # Split line
2627 key, val = split_line(line)
2628
2629- if key in ("organisation", "org-name"):
2630+ if key == "organisation":
2631+ org[key] = val.upper()
2632+ elif key == "org-name":
2633 org[key] = val
2634
2635 # Skip empty objects
2636--
26372.20.1
2638
2639From e96704f43acca1a8f56d9a680cce281f5e587ec5 Mon Sep 17 00:00:00 2001
2640From: Michael Tremer <michael.tremer@ipfire.org>
2641Date: Wed, 11 Nov 2020 21:16:45 +0000
0be475ca 2642Subject: [PATCH 032/111] test: Add tests for database enumerator
05db64d0
MT
2643
2644Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
2645---
2646 src/test-database.c | 53 +++++++++++++++++++++++++++++++++++++++++++++
2647 1 file changed, 53 insertions(+)
2648
2649diff --git a/src/test-database.c b/src/test-database.c
2650index b4a75c4..4aef94e 100644
2651--- a/src/test-database.c
2652+++ b/src/test-database.c
2653@@ -38,6 +38,14 @@ const char* DESCRIPTION =
2654 "Maecenas ut venenatis nunc.";
2655 const char* LICENSE = "CC";
2656
2657+const char* networks[] = {
2658+ "2001:db8::/32",
2659+ "2001:db8:1000::/48",
2660+ "2001:db8:2000::/48",
2661+ "2001:db8:2020::/48",
2662+ NULL,
2663+};
2664+
2665 static int attempt_to_open(struct loc_ctx* ctx, char* path) {
2666 FILE* f = fopen(path, "r");
2667 if (!f)
2668@@ -139,6 +147,24 @@ int main(int argc, char** argv) {
2669 exit(EXIT_FAILURE);
2670 }
2671
2672+ struct loc_network* network = NULL;
2673+
2674+ // Add some networks
2675+ const char** n = networks;
2676+ while (*n) {
2677+ err = loc_writer_add_network(writer, &network, *n);
2678+ if (err) {
2679+ fprintf(stderr, "Could not add network %s\n", *n);
2680+ exit(EXIT_FAILURE);
2681+ }
2682+
2683+ // Set a country
2684+ loc_network_set_country_code(network, "XX");
2685+
2686+ // Next one
2687+ n++;
2688+ }
2689+
2690 FILE* f = tmpfile();
2691 if (!f) {
2692 fprintf(stderr, "Could not open file for writing: %s\n", strerror(errno));
2693@@ -170,6 +196,33 @@ int main(int argc, char** argv) {
2694 exit(EXIT_FAILURE);
2695 }
2696
2697+ // Enumerator
2698+ struct loc_database_enumerator* enumerator;
2699+ err = loc_database_enumerator_new(&enumerator, db, LOC_DB_ENUMERATE_NETWORKS);
2700+ if (err) {
2701+ fprintf(stderr, "Could not initialise the enumerator: %d\n", err);
2702+ exit(EXIT_FAILURE);
2703+ }
2704+
2705+ // Walk through all networks
2706+ while (1) {
2707+ err = loc_database_enumerator_next_network(enumerator, &network);
2708+ if (err) {
2709+ fprintf(stderr, "Error fetching the next network: %d\n", err);
2710+ exit(EXIT_FAILURE);
2711+ }
2712+
2713+ if (!network)
2714+ break;
2715+
2716+ char* s = loc_network_str(network);
2717+ printf("Got network: %s\n", s);
2718+ free(s);
2719+ }
2720+
2721+ // Free the enumerator
2722+ loc_database_enumerator_unref(enumerator);
2723+
2724 // Close the database
2725 loc_database_unref(db);
2726 loc_unref(ctx);
2727--
27282.20.1
2729
2730From ecce288da39a2c0eb60076050ca21e9619f61844 Mon Sep 17 00:00:00 2001
2731From: Michael Tremer <michael.tremer@ipfire.org>
2732Date: Wed, 11 Nov 2020 23:01:19 +0000
0be475ca 2733Subject: [PATCH 033/111] networks: Add list to manage groups of networks
05db64d0
MT
2734
2735Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
2736---
2737 src/libloc.sym | 11 ++++++
2738 src/loc/network.h | 12 ++++++
2739 src/network.c | 96 +++++++++++++++++++++++++++++++++++++++++++++++
2740 3 files changed, 119 insertions(+)
2741
2742diff --git a/src/libloc.sym b/src/libloc.sym
2743index b8296eb..6ef2d27 100644
2744--- a/src/libloc.sym
2745+++ b/src/libloc.sym
2746@@ -98,6 +98,17 @@ global:
2747 loc_network_str;
2748 loc_network_unref;
2749
2750+ # Network List
2751+ loc_network_list_clear;
2752+ loc_network_list_empty;
2753+ loc_network_list_get;
2754+ loc_network_list_new;
2755+ loc_network_list_pop;
2756+ loc_network_list_push;
2757+ loc_network_list_ref;
2758+ loc_network_list_size;
2759+ loc_network_list_unref;
2760+
2761 # Writer
2762 loc_writer_add_as;
2763 loc_writer_add_country;
2764diff --git a/src/loc/network.h b/src/loc/network.h
2765index 70c3803..fd20812 100644
2766--- a/src/loc/network.h
2767+++ b/src/loc/network.h
2768@@ -56,6 +56,18 @@ int loc_network_match_flag(struct loc_network* network, uint32_t flag);
2769
2770 int loc_network_is_subnet_of(struct loc_network* self, struct loc_network* other);
2771
2772+// List
2773+struct loc_network_list;
2774+int loc_network_list_new(struct loc_ctx* ctx, struct loc_network_list** list);
2775+struct loc_network_list* loc_network_list_ref(struct loc_network_list* list);
2776+struct loc_network_list* loc_network_list_unref(struct loc_network_list* list);
2777+size_t loc_network_list_size(struct loc_network_list* list);
2778+int loc_network_list_empty(struct loc_network_list* list);
2779+void loc_network_list_clear(struct loc_network_list* list);
2780+struct loc_network* loc_network_list_get(struct loc_network_list* list, size_t index);
2781+int loc_network_list_push(struct loc_network_list* list, struct loc_network* network);
2782+struct loc_network* loc_network_list_pop(struct loc_network_list* list);
2783+
2784 #ifdef LIBLOC_PRIVATE
2785
2786 int loc_network_to_database_v1(struct loc_network* network, struct loc_database_network_v1* dbobj);
2787diff --git a/src/network.c b/src/network.c
2788index d7b1645..c9e7979 100644
2789--- a/src/network.c
2790+++ b/src/network.c
2791@@ -746,3 +746,99 @@ LOC_EXPORT int loc_network_tree_node_is_leaf(struct loc_network_tree_node* node)
2792 LOC_EXPORT struct loc_network* loc_network_tree_node_get_network(struct loc_network_tree_node* node) {
2793 return loc_network_ref(node->network);
2794 }
2795+
2796+// List
2797+
2798+struct loc_network_list {
2799+ struct loc_ctx* ctx;
2800+ int refcount;
2801+
2802+ struct loc_network* list[1024];
2803+ size_t size;
2804+ size_t max_size;
2805+};
2806+
2807+LOC_EXPORT int loc_network_list_new(struct loc_ctx* ctx,
2808+ struct loc_network_list** list) {
2809+ struct loc_network_list* l = calloc(1, sizeof(*l));
2810+ if (!l)
2811+ return -ENOMEM;
2812+
2813+ l->ctx = loc_ref(ctx);
2814+ l->refcount = 1;
2815+
2816+ // Do not allow this list to grow larger than this
2817+ l->max_size = 1024;
2818+
2819+ DEBUG(l->ctx, "Network list allocated at %p\n", l);
2820+ *list = l;
2821+ return 0;
2822+}
2823+
2824+LOC_EXPORT struct loc_network_list* loc_network_list_ref(struct loc_network_list* list) {
2825+ list->refcount++;
2826+
2827+ return list;
2828+}
2829+
2830+static void loc_network_list_free(struct loc_network_list* list) {
2831+ DEBUG(list->ctx, "Releasing network list at %p\n", list);
2832+
2833+ for (unsigned int i = 0; i < list->size; i++)
2834+ loc_network_unref(list->list[i]);
2835+
2836+ loc_unref(list->ctx);
2837+ free(list);
2838+}
2839+
2840+LOC_EXPORT struct loc_network_list* loc_network_list_unref(struct loc_network_list* list) {
2841+ if (!list)
2842+ return NULL;
2843+
2844+ if (--list->refcount > 0)
2845+ return list;
2846+
2847+ loc_network_list_free(list);
2848+ return NULL;
2849+}
2850+
2851+LOC_EXPORT size_t loc_network_list_size(struct loc_network_list* list) {
2852+ return list->size;
2853+}
2854+
2855+LOC_EXPORT int loc_network_list_empty(struct loc_network_list* list) {
2856+ return list->size == 0;
2857+}
2858+
2859+LOC_EXPORT void loc_network_list_clear(struct loc_network_list* list) {
2860+ for (unsigned int i = 0; i < list->size; i++)
2861+ loc_network_unref(list->list[i]);
2862+
2863+ list->size = 0;
2864+}
2865+
2866+LOC_EXPORT struct loc_network* loc_network_list_get(struct loc_network_list* list, size_t index) {
2867+ // Check index
2868+ if (index >= list->size)
2869+ return NULL;
2870+
2871+ return loc_network_ref(list->list[index]);
2872+}
2873+
2874+LOC_EXPORT int loc_network_list_push(struct loc_network_list* list, struct loc_network* network) {
2875+ // Check if we have space left
2876+ if (list->size == list->max_size)
2877+ return -ENOMEM;
2878+
2879+ list->list[list->size++] = loc_network_ref(network);
2880+
2881+ return 0;
2882+}
2883+
2884+LOC_EXPORT struct loc_network* loc_network_list_pop(struct loc_network_list* list) {
2885+ // Return nothing when empty
2886+ if (loc_network_list_empty(list))
2887+ return NULL;
2888+
2889+ return list->list[list->size--];
2890+}
2891--
28922.20.1
2893
2894From 8b2205272b7872a1458ad87811abf58609f38ad4 Mon Sep 17 00:00:00 2001
2895From: Michael Tremer <michael.tremer@ipfire.org>
2896Date: Thu, 12 Nov 2020 13:57:35 +0000
0be475ca 2897Subject: [PATCH 034/111] networks: Add function to dump lists
05db64d0
MT
2898
2899Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
2900---
2901 src/libloc.sym | 1 +
2902 src/loc/network.h | 1 +
2903 src/network.c | 14 ++++++++++++++
2904 3 files changed, 16 insertions(+)
2905
2906diff --git a/src/libloc.sym b/src/libloc.sym
2907index 6ef2d27..a5641c6 100644
2908--- a/src/libloc.sym
2909+++ b/src/libloc.sym
2910@@ -100,6 +100,7 @@ global:
2911
2912 # Network List
2913 loc_network_list_clear;
2914+ loc_network_list_dump;
2915 loc_network_list_empty;
2916 loc_network_list_get;
2917 loc_network_list_new;
2918diff --git a/src/loc/network.h b/src/loc/network.h
2919index fd20812..44c50a4 100644
2920--- a/src/loc/network.h
2921+++ b/src/loc/network.h
2922@@ -64,6 +64,7 @@ struct loc_network_list* loc_network_list_unref(struct loc_network_list* list);
2923 size_t loc_network_list_size(struct loc_network_list* list);
2924 int loc_network_list_empty(struct loc_network_list* list);
2925 void loc_network_list_clear(struct loc_network_list* list);
2926+void loc_network_list_dump(struct loc_network_list* list);
2927 struct loc_network* loc_network_list_get(struct loc_network_list* list, size_t index);
2928 int loc_network_list_push(struct loc_network_list* list, struct loc_network* network);
2929 struct loc_network* loc_network_list_pop(struct loc_network_list* list);
2930diff --git a/src/network.c b/src/network.c
2931index c9e7979..0977406 100644
2932--- a/src/network.c
2933+++ b/src/network.c
2934@@ -817,6 +817,20 @@ LOC_EXPORT void loc_network_list_clear(struct loc_network_list* list) {
2935 list->size = 0;
2936 }
2937
2938+LOC_EXPORT void loc_network_list_dump(struct loc_network_list* list) {
2939+ struct loc_network* network;
2940+ char* s;
2941+
2942+ for (unsigned int i = 0; i < list->size; i++) {
2943+ network = list->list[i];
2944+
2945+ s = loc_network_str(network);
2946+
2947+ INFO(list->ctx, "%s\n", s);
2948+ free(s);
2949+ }
2950+}
2951+
2952 LOC_EXPORT struct loc_network* loc_network_list_get(struct loc_network_list* list, size_t index) {
2953 // Check index
2954 if (index >= list->size)
2955--
29562.20.1
2957
2958From 850e75167e8e03fe8b951992c9f7bc2ccb9fb711 Mon Sep 17 00:00:00 2001
2959From: Michael Tremer <michael.tremer@ipfire.org>
2960Date: Thu, 12 Nov 2020 14:18:40 +0000
0be475ca 2961Subject: [PATCH 035/111] network: Add functions to break network into subnets
05db64d0
MT
2962
2963Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
2964---
2965 src/libloc.sym | 5 +
2966 src/loc/network.h | 6 +
2967 src/network.c | 290 ++++++++++++++++++++++++++++++++++++++++++++-
2968 src/test-network.c | 61 ++++++++++
2969 4 files changed, 361 insertions(+), 1 deletion(-)
2970
2971diff --git a/src/libloc.sym b/src/libloc.sym
2972index a5641c6..fcb9ea5 100644
2973--- a/src/libloc.sym
2974+++ b/src/libloc.sym
2975@@ -80,6 +80,8 @@ global:
2976
2977 # Network
2978 loc_network_address_family;
2979+ loc_network_eq;
2980+ loc_network_exclude;
2981 loc_network_format_first_address;
2982 loc_network_format_last_address;
2983 loc_network_get_asn;
2984@@ -96,6 +98,7 @@ global:
2985 loc_network_set_country_code;
2986 loc_network_set_flag;
2987 loc_network_str;
2988+ loc_network_subnets;
2989 loc_network_unref;
2990
2991 # Network List
2992@@ -107,7 +110,9 @@ global:
2993 loc_network_list_pop;
2994 loc_network_list_push;
2995 loc_network_list_ref;
2996+ loc_network_list_reverse;
2997 loc_network_list_size;
2998+ loc_network_list_sort;
2999 loc_network_list_unref;
3000
3001 # Writer
3002diff --git a/src/loc/network.h b/src/loc/network.h
3003index 44c50a4..4e51a62 100644
3004--- a/src/loc/network.h
3005+++ b/src/loc/network.h
3006@@ -54,7 +54,11 @@ int loc_network_has_flag(struct loc_network* network, uint32_t flag);
3007 int loc_network_set_flag(struct loc_network* network, uint32_t flag);
3008 int loc_network_match_flag(struct loc_network* network, uint32_t flag);
3009
3010+int loc_network_eq(struct loc_network* self, struct loc_network* other);
3011 int loc_network_is_subnet_of(struct loc_network* self, struct loc_network* other);
3012+struct loc_network_list* loc_network_subnets(struct loc_network* network);
3013+struct loc_network_list* loc_network_exclude(
3014+ struct loc_network* self, struct loc_network* other);
3015
3016 // List
3017 struct loc_network_list;
3018@@ -68,6 +72,8 @@ void loc_network_list_dump(struct loc_network_list* list);
3019 struct loc_network* loc_network_list_get(struct loc_network_list* list, size_t index);
3020 int loc_network_list_push(struct loc_network_list* list, struct loc_network* network);
3021 struct loc_network* loc_network_list_pop(struct loc_network_list* list);
3022+void loc_network_list_sort(struct loc_network_list* list);
3023+void loc_network_list_reverse(struct loc_network_list* list);
3024
3025 #ifdef LIBLOC_PRIVATE
3026
3027diff --git a/src/network.c b/src/network.c
3028index 0977406..6c08070 100644
3029--- a/src/network.c
3030+++ b/src/network.c
3031@@ -97,6 +97,21 @@ static struct in6_addr make_last_address(const struct in6_addr* address, const s
3032 return a;
3033 }
3034
3035+static struct in6_addr address_increment(const struct in6_addr* address) {
3036+ struct in6_addr a = *address;
3037+
3038+ for (int octet = 15; octet >= 0; octet--) {
3039+ if (a.s6_addr[octet] < 255) {
3040+ a.s6_addr[octet]++;
3041+ break;
3042+ } else {
3043+ a.s6_addr[octet] = 0;
3044+ }
3045+ }
3046+
3047+ return a;
3048+}
3049+
3050 LOC_EXPORT int loc_network_new(struct loc_ctx* ctx, struct loc_network** network,
3051 struct in6_addr* address, unsigned int prefix) {
3052 // Address cannot be unspecified
3053@@ -405,6 +420,69 @@ LOC_EXPORT int loc_network_match_flag(struct loc_network* network, uint32_t flag
3054 return loc_network_has_flag(network, flag);
3055 }
3056
3057+LOC_EXPORT int loc_network_eq(struct loc_network* self, struct loc_network* other) {
3058+#ifdef ENABLE_DEBUG
3059+ char* n1 = loc_network_str(self);
3060+ char* n2 = loc_network_str(other);
3061+
3062+ DEBUG(self->ctx, "Is %s equal to %s?\n", n1, n2);
3063+
3064+ free(n1);
3065+ free(n2);
3066+#endif
3067+
3068+ // Family must be the same
3069+ if (self->family != other->family) {
3070+ DEBUG(self->ctx, " Family mismatch\n");
3071+
3072+ return 0;
3073+ }
3074+
3075+ // The start address must be the same
3076+ if (in6_addr_cmp(&self->first_address, &other->first_address) != 0) {
3077+ DEBUG(self->ctx, " Address mismatch\n");
3078+
3079+ return 0;
3080+ }
3081+
3082+ // The prefix length must be the same
3083+ if (self->prefix != other->prefix) {
3084+ DEBUG(self->ctx, " Prefix mismatch\n");
3085+ return 0;
3086+ }
3087+
3088+ DEBUG(self->ctx, " Yes!\n");
3089+
3090+ return 1;
3091+}
3092+
3093+static int loc_network_gt(struct loc_network* self, struct loc_network* other) {
3094+ // Families must match
3095+ if (self->family != other->family)
3096+ return -1;
3097+
3098+ int r = in6_addr_cmp(&self->first_address, &other->first_address);
3099+
3100+ switch (r) {
3101+ // Smaller
3102+ case -1:
3103+ return 0;
3104+
3105+ // Larger
3106+ case 1:
3107+ return 1;
3108+
3109+ default:
3110+ break;
3111+ }
3112+
3113+ if (self->prefix > other->prefix)
3114+ return 1;
3115+
3116+ // Dunno
3117+ return 0;
3118+}
3119+
3120 LOC_EXPORT int loc_network_is_subnet_of(struct loc_network* self, struct loc_network* other) {
3121 // If the start address of the other network is smaller than this network,
3122 // it cannot be a subnet.
3123@@ -419,6 +497,175 @@ LOC_EXPORT int loc_network_is_subnet_of(struct loc_network* self, struct loc_net
3124 return 1;
3125 }
3126
3127+LOC_EXPORT struct loc_network_list* loc_network_subnets(struct loc_network* network) {
3128+ struct loc_network_list* list;
3129+
3130+ // New prefix length
3131+ unsigned int prefix = network->prefix + 1;
3132+
3133+ // Check if the new prefix is valid
3134+ if (valid_prefix(&network->first_address, prefix))
3135+ return NULL;
3136+
3137+ // Create a new list with the result
3138+ int r = loc_network_list_new(network->ctx, &list);
3139+ if (r) {
3140+ ERROR(network->ctx, "Could not create network list: %d\n", r);
3141+ return NULL;
3142+ }
3143+
3144+ struct loc_network* subnet1 = NULL;
3145+ struct loc_network* subnet2 = NULL;
3146+
3147+ // Create the first half of the network
3148+ r = loc_network_new(network->ctx, &subnet1, &network->first_address, prefix);
3149+ if (r)
3150+ goto ERROR;
3151+
3152+ // The next subnet starts after the first one
3153+ struct in6_addr first_address = address_increment(&subnet1->last_address);
3154+
3155+ // Create the second half of the network
3156+ r = loc_network_new(network->ctx, &subnet2, &first_address, prefix);
3157+ if (r)
3158+ goto ERROR;
3159+
3160+ // Push the both onto the stack (in reverse order)
3161+ r = loc_network_list_push(list, subnet2);
3162+ if (r)
3163+ goto ERROR;
3164+
3165+ r = loc_network_list_push(list, subnet1);
3166+ if (r)
3167+ goto ERROR;
3168+
3169+ loc_network_unref(subnet1);
3170+ loc_network_unref(subnet2);
3171+
3172+ return list;
3173+
3174+ERROR:
3175+ if (subnet1)
3176+ loc_network_unref(subnet1);
3177+
3178+ if (subnet2)
3179+ loc_network_unref(subnet2);
3180+
3181+ if (list)
3182+ loc_network_list_unref(list);
3183+
3184+ return NULL;
3185+}
3186+
3187+LOC_EXPORT struct loc_network_list* loc_network_exclude(
3188+ struct loc_network* self, struct loc_network* other) {
3189+ struct loc_network_list* list;
3190+
3191+#ifdef ENABLE_DEBUG
3192+ char* n1 = loc_network_str(self);
3193+ char* n2 = loc_network_str(other);
3194+
3195+ DEBUG(self->ctx, "Returning %s excluding %s...\n", n1, n2);
3196+
3197+ free(n1);
3198+ free(n2);
3199+#endif
3200+
3201+ // Family must match
3202+ if (self->family != other->family) {
3203+ DEBUG(self->ctx, "Family mismatch\n");
3204+
3205+ return NULL;
3206+ }
3207+
3208+ // Other must be a subnet of self
3209+ if (!loc_network_is_subnet_of(other, self)) {
3210+ DEBUG(self->ctx, "Network %p is not contained in network %p\n", other, self);
3211+
3212+ return NULL;
3213+ }
3214+
3215+ // We cannot perform this operation if both networks equal
3216+ if (loc_network_eq(self, other)) {
3217+ DEBUG(self->ctx, "Networks %p and %p are equal\n", self, other);
3218+
3219+ return NULL;
3220+ }
3221+
3222+ // Create a new list with the result
3223+ int r = loc_network_list_new(self->ctx, &list);
3224+ if (r) {
3225+ ERROR(self->ctx, "Could not create network list: %d\n", r);
3226+ return NULL;
3227+ }
3228+
3229+ struct loc_network_list* subnets = loc_network_subnets(self);
3230+
3231+ struct loc_network* subnet1 = NULL;
3232+ struct loc_network* subnet2 = NULL;
3233+
3234+ while (subnets) {
3235+ // Fetch both subnets
3236+ subnet1 = loc_network_list_get(subnets, 0);
3237+ subnet2 = loc_network_list_get(subnets, 1);
3238+
3239+ // Free list
3240+ loc_network_list_unref(subnets);
3241+ subnets = NULL;
3242+
3243+ if (loc_network_eq(other, subnet1)) {
3244+ r = loc_network_list_push(list, subnet2);
3245+ if (r)
3246+ goto ERROR;
3247+
3248+ } else if (loc_network_eq(other, subnet2)) {
3249+ r = loc_network_list_push(list, subnet1);
3250+ if (r)
3251+ goto ERROR;
3252+
3253+ } else if (loc_network_is_subnet_of(other, subnet1)) {
3254+ r = loc_network_list_push(list, subnet2);
3255+ if (r)
3256+ goto ERROR;
3257+
3258+ subnets = loc_network_subnets(subnet1);
3259+
3260+ } else if (loc_network_is_subnet_of(other, subnet2)) {
3261+ r = loc_network_list_push(list, subnet1);
3262+ if (r)
3263+ goto ERROR;
3264+
3265+ subnets = loc_network_subnets(subnet2);
3266+
3267+ } else {
3268+ ERROR(self->ctx, "We should never get here\n");
3269+ goto ERROR;
3270+ }
3271+
3272+ loc_network_unref(subnet1);
3273+ loc_network_unref(subnet2);
3274+ }
3275+
3276+#ifdef ENABLE_DEBUG
3277+ loc_network_list_dump(list);
3278+#endif
3279+
3280+ // Return the result
3281+ return list;
3282+
3283+ERROR:
3284+ if (subnet1)
3285+ loc_network_unref(subnet1);
3286+
3287+ if (subnet2)
3288+ loc_network_unref(subnet2);
3289+
3290+ if (list)
3291+ loc_network_list_unref(list);
3292+
3293+ return NULL;
3294+}
3295+
3296 LOC_EXPORT int loc_network_to_database_v1(struct loc_network* network, struct loc_database_network_v1* dbobj) {
3297 // Add country code
3298 loc_country_code_copy(dbobj->country_code, network->country_code);
3299@@ -854,5 +1101,46 @@ LOC_EXPORT struct loc_network* loc_network_list_pop(struct loc_network_list* lis
3300 if (loc_network_list_empty(list))
3301 return NULL;
3302
3303- return list->list[list->size--];
3304+ return list->list[--list->size];
3305+}
3306+
3307+static void loc_network_list_swap(struct loc_network_list* list, unsigned int i1, unsigned int i2) {
3308+ // Do nothing for invalid indices
3309+ if (i1 >= list->size || i2 >= list->size)
3310+ return;
3311+
3312+ DEBUG(list->ctx, "Swapping %u with %u\n", i1, i2);
3313+
3314+ struct loc_network* network1 = list->list[i1];
3315+ struct loc_network* network2 = list->list[i2];
3316+
3317+ list->list[i1] = network2;
3318+ list->list[i2] = network1;
3319+}
3320+
3321+LOC_EXPORT void loc_network_list_reverse(struct loc_network_list* list) {
3322+ unsigned int i = 0;
3323+ unsigned int j = list->size - 1;
3324+
3325+ while (i < j) {
3326+ loc_network_list_swap(list, i++, j--);
3327+ }
3328+}
3329+
3330+LOC_EXPORT void loc_network_list_sort(struct loc_network_list* list) {
3331+ unsigned int n = list->size;
3332+ int swapped;
3333+
3334+ do {
3335+ swapped = 0;
3336+
3337+ for (unsigned int i = 1; i < n; i++) {
3338+ if (loc_network_gt(list->list[i-1], list->list[i]) > 0) {
3339+ loc_network_list_swap(list, i-1, i);
3340+ swapped = 1;
3341+ }
3342+ }
3343+
3344+ n--;
3345+ } while (swapped);
3346 }
3347diff --git a/src/test-network.c b/src/test-network.c
3348index b6776b4..af1b2e6 100644
3349--- a/src/test-network.c
3350+++ b/src/test-network.c
3351@@ -118,6 +118,19 @@ int main(int argc, char** argv) {
3352 size_t nodes = loc_network_tree_count_nodes(tree);
3353 printf("The tree has %zu nodes\n", nodes);
3354
3355+ // Check equals function
3356+ err = loc_network_eq(network1, network1);
3357+ if (!err) {
3358+ fprintf(stderr, "Network is not equal with itself\n");
3359+ exit(EXIT_FAILURE);
3360+ }
3361+
3362+ err = loc_network_eq(network1, network2);
3363+ if (err) {
3364+ fprintf(stderr, "Networks equal unexpectedly\n");
3365+ exit(EXIT_FAILURE);
3366+ }
3367+
3368 // Check subnet function
3369 err = loc_network_is_subnet_of(network1, network2);
3370 if (err != 0) {
3371@@ -131,6 +144,54 @@ int main(int argc, char** argv) {
3372 exit(EXIT_FAILURE);
3373 }
3374
3375+ // Make list of subnets
3376+ struct loc_network_list* subnets = loc_network_subnets(network1);
3377+ if (!subnets) {
3378+ fprintf(stderr, "Could not find subnets of network\n");
3379+ exit(EXIT_FAILURE);
3380+ }
3381+
3382+ loc_network_list_dump(subnets);
3383+
3384+ while (!loc_network_list_empty(subnets)) {
3385+ struct loc_network* subnet = loc_network_list_pop(subnets);
3386+ if (!subnet) {
3387+ fprintf(stderr, "Received an empty subnet\n");
3388+ exit(EXIT_FAILURE);
3389+ }
3390+
3391+ char* s = loc_network_str(subnet);
3392+ printf("Received subnet %s\n", s);
3393+ free(s);
3394+
3395+ if (!loc_network_is_subnet_of(subnet, network1)) {
3396+ fprintf(stderr, "Not a subnet\n");
3397+ exit(EXIT_FAILURE);
3398+ }
3399+
3400+ loc_network_unref(subnet);
3401+ }
3402+
3403+ loc_network_list_unref(subnets);
3404+
3405+ struct loc_network_list* excluded = loc_network_exclude(network1, network2);
3406+ if (!excluded) {
3407+ fprintf(stderr, "Could not create excluded list\n");
3408+ exit(EXIT_FAILURE);
3409+ }
3410+
3411+ loc_network_list_dump(excluded);
3412+
3413+ // Reverse it
3414+ loc_network_list_reverse(excluded);
3415+ loc_network_list_dump(excluded);
3416+
3417+ // Sort them and dump them again
3418+ loc_network_list_sort(excluded);
3419+ loc_network_list_dump(excluded);
3420+
3421+ loc_network_list_unref(excluded);
3422+
3423 // Create a database
3424 struct loc_writer* writer;
3425 err = loc_writer_new(ctx, &writer, NULL, NULL);
3426--
34272.20.1
3428
3429From 6159d384c4a98fe45ec52522e2950719e4982d80 Mon Sep 17 00:00:00 2001
3430From: Michael Tremer <michael.tremer@ipfire.org>
3431Date: Thu, 12 Nov 2020 14:24:58 +0000
0be475ca
MT
3432Subject: [PATCH 036/111] networks: Add function to check if two networks
3433 overlap
05db64d0
MT
3434
3435Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
3436---
3437 src/libloc.sym | 1 +
3438 src/loc/network.h | 1 +
3439 src/network.c | 16 ++++++++++++++++
3440 3 files changed, 18 insertions(+)
3441
3442diff --git a/src/libloc.sym b/src/libloc.sym
3443index fcb9ea5..0c2835b 100644
3444--- a/src/libloc.sym
3445+++ b/src/libloc.sym
3446@@ -93,6 +93,7 @@ global:
3447 loc_network_match_flag;
3448 loc_network_new;
3449 loc_network_new_from_string;
3450+ loc_network_overlaps;
3451 loc_network_ref;
3452 loc_network_set_asn;
3453 loc_network_set_country_code;
3454diff --git a/src/loc/network.h b/src/loc/network.h
3455index 4e51a62..ef13756 100644
3456--- a/src/loc/network.h
3457+++ b/src/loc/network.h
3458@@ -55,6 +55,7 @@ int loc_network_set_flag(struct loc_network* network, uint32_t flag);
3459 int loc_network_match_flag(struct loc_network* network, uint32_t flag);
3460
3461 int loc_network_eq(struct loc_network* self, struct loc_network* other);
3462+int loc_network_overlaps(struct loc_network* self, struct loc_network* other);
3463 int loc_network_is_subnet_of(struct loc_network* self, struct loc_network* other);
3464 struct loc_network_list* loc_network_subnets(struct loc_network* network);
3465 struct loc_network_list* loc_network_exclude(
3466diff --git a/src/network.c b/src/network.c
3467index 6c08070..d826511 100644
3468--- a/src/network.c
3469+++ b/src/network.c
3470@@ -483,6 +483,22 @@ static int loc_network_gt(struct loc_network* self, struct loc_network* other) {
3471 return 0;
3472 }
3473
3474+LOC_EXPORT int loc_network_overlaps(struct loc_network* self, struct loc_network* other) {
3475+ if (loc_network_match_address(self, &other->first_address) == 0)
3476+ return 1;
3477+
3478+ if (loc_network_match_address(self, &other->last_address) == 0)
3479+ return 1;
3480+
3481+ if (loc_network_match_address(other, &self->first_address) == 0)
3482+ return 1;
3483+
3484+ if (loc_network_match_address(other, &self->last_address) == 0)
3485+ return 1;
3486+
3487+ return 0;
3488+}
3489+
3490 LOC_EXPORT int loc_network_is_subnet_of(struct loc_network* self, struct loc_network* other) {
3491 // If the start address of the other network is smaller than this network,
3492 // it cannot be a subnet.
3493--
34942.20.1
3495
3496From e52ba21761f27e592040a2793b2a26bbeeeecc05 Mon Sep 17 00:00:00 2001
3497From: Michael Tremer <michael.tremer@ipfire.org>
3498Date: Thu, 12 Nov 2020 14:28:15 +0000
0be475ca
MT
3499Subject: [PATCH 037/111] networks: Add function to check if network is part of
3500 a list
05db64d0
MT
3501
3502Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
3503---
3504 src/libloc.sym | 1 +
3505 src/loc/network.h | 1 +
3506 src/network.c | 9 +++++++++
3507 3 files changed, 11 insertions(+)
3508
3509diff --git a/src/libloc.sym b/src/libloc.sym
3510index 0c2835b..f1b63a2 100644
3511--- a/src/libloc.sym
3512+++ b/src/libloc.sym
3513@@ -104,6 +104,7 @@ global:
3514
3515 # Network List
3516 loc_network_list_clear;
3517+ loc_network_list_contains;
3518 loc_network_list_dump;
3519 loc_network_list_empty;
3520 loc_network_list_get;
3521diff --git a/src/loc/network.h b/src/loc/network.h
3522index ef13756..7804512 100644
3523--- a/src/loc/network.h
3524+++ b/src/loc/network.h
3525@@ -73,6 +73,7 @@ void loc_network_list_dump(struct loc_network_list* list);
3526 struct loc_network* loc_network_list_get(struct loc_network_list* list, size_t index);
3527 int loc_network_list_push(struct loc_network_list* list, struct loc_network* network);
3528 struct loc_network* loc_network_list_pop(struct loc_network_list* list);
3529+int loc_network_list_contains(struct loc_network_list* list, struct loc_network* network);
3530 void loc_network_list_sort(struct loc_network_list* list);
3531 void loc_network_list_reverse(struct loc_network_list* list);
3532
3533diff --git a/src/network.c b/src/network.c
3534index d826511..fcbdc59 100644
3535--- a/src/network.c
3536+++ b/src/network.c
3537@@ -1120,6 +1120,15 @@ LOC_EXPORT struct loc_network* loc_network_list_pop(struct loc_network_list* lis
3538 return list->list[--list->size];
3539 }
3540
3541+LOC_EXPORT int loc_network_list_contains(struct loc_network_list* list, struct loc_network* network) {
3542+ for (unsigned int i = 0; i < list->size; i++) {
3543+ if (loc_network_eq(list->list[i], network))
3544+ return 1;
3545+ }
3546+
3547+ return 0;
3548+}
3549+
3550 static void loc_network_list_swap(struct loc_network_list* list, unsigned int i1, unsigned int i2) {
3551 // Do nothing for invalid indices
3552 if (i1 >= list->size || i2 >= list->size)
3553--
35542.20.1
3555
3556From f802f3a4decf4827ecc8bcabe269ae9f94f7f32d Mon Sep 17 00:00:00 2001
3557From: Michael Tremer <michael.tremer@ipfire.org>
3558Date: Thu, 12 Nov 2020 14:33:22 +0000
0be475ca 3559Subject: [PATCH 038/111] networks: Add function to merge two lists
05db64d0
MT
3560
3561Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
3562---
3563 src/libloc.sym | 1 +
3564 src/loc/network.h | 1 +
3565 src/network.c | 13 +++++++++++++
3566 3 files changed, 15 insertions(+)
3567
3568diff --git a/src/libloc.sym b/src/libloc.sym
3569index f1b63a2..c0b6b1f 100644
3570--- a/src/libloc.sym
3571+++ b/src/libloc.sym
3572@@ -108,6 +108,7 @@ global:
3573 loc_network_list_dump;
3574 loc_network_list_empty;
3575 loc_network_list_get;
3576+ loc_network_list_merge;
3577 loc_network_list_new;
3578 loc_network_list_pop;
3579 loc_network_list_push;
3580diff --git a/src/loc/network.h b/src/loc/network.h
3581index 7804512..e30d91c 100644
3582--- a/src/loc/network.h
3583+++ b/src/loc/network.h
3584@@ -76,6 +76,7 @@ struct loc_network* loc_network_list_pop(struct loc_network_list* list);
3585 int loc_network_list_contains(struct loc_network_list* list, struct loc_network* network);
3586 void loc_network_list_sort(struct loc_network_list* list);
3587 void loc_network_list_reverse(struct loc_network_list* list);
3588+int loc_network_list_merge(struct loc_network_list* self, struct loc_network_list* other);
3589
3590 #ifdef LIBLOC_PRIVATE
3591
3592diff --git a/src/network.c b/src/network.c
3593index fcbdc59..541286d 100644
3594--- a/src/network.c
3595+++ b/src/network.c
3596@@ -1169,3 +1169,16 @@ LOC_EXPORT void loc_network_list_sort(struct loc_network_list* list) {
3597 n--;
3598 } while (swapped);
3599 }
3600+
3601+LOC_EXPORT int loc_network_list_merge(
3602+ struct loc_network_list* self, struct loc_network_list* other) {
3603+ int r;
3604+
3605+ for (unsigned int i = 0; i < other->size; i++) {
3606+ r = loc_network_list_push(self, other->list[i]);
3607+ if (r)
3608+ return r;
3609+ }
3610+
3611+ return 0;
3612+}
3613--
36142.20.1
3615
3616From 6d22a179dffd08fcf2a44aafb361725ab22486d4 Mon Sep 17 00:00:00 2001
3617From: Michael Tremer <michael.tremer@ipfire.org>
3618Date: Thu, 12 Nov 2020 14:35:43 +0000
0be475ca 3619Subject: [PATCH 039/111] network: Make lists unique
05db64d0
MT
3620
3621Networks that are in the list won't be added again
3622
3623Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
3624---
3625 src/network.c | 4 ++++
3626 1 file changed, 4 insertions(+)
3627
3628diff --git a/src/network.c b/src/network.c
3629index 541286d..44571b3 100644
3630--- a/src/network.c
3631+++ b/src/network.c
3632@@ -1103,6 +1103,10 @@ LOC_EXPORT struct loc_network* loc_network_list_get(struct loc_network_list* lis
3633 }
3634
3635 LOC_EXPORT int loc_network_list_push(struct loc_network_list* list, struct loc_network* network) {
3636+ // Do not add networks that are already on the list
3637+ if (loc_network_list_contains(list, network))
3638+ return 0;
3639+
3640 // Check if we have space left
3641 if (list->size == list->max_size)
3642 return -ENOMEM;
3643--
36442.20.1
3645
3646From 681ff05cb7cdf230d38abf09a330a31498e265a4 Mon Sep 17 00:00:00 2001
3647From: Michael Tremer <michael.tremer@ipfire.org>
3648Date: Thu, 12 Nov 2020 19:21:13 +0000
0be475ca 3649Subject: [PATCH 040/111] database: Pass flag to enumerator to flatten output
05db64d0
MT
3650
3651Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
3652---
3653 src/database.c | 8 +++++++-
3654 src/loc/database.h | 6 +++++-
3655 src/perl/Location.xs | 2 +-
3656 src/python/database.c | 25 ++++++++++++++++++-------
3657 4 files changed, 31 insertions(+), 10 deletions(-)
3658
3659diff --git a/src/database.c b/src/database.c
3660index fa1dad0..9baab33 100644
3661--- a/src/database.c
3662+++ b/src/database.c
3663@@ -104,6 +104,9 @@ struct loc_database_enumerator {
3664 enum loc_network_flags flags;
3665 int family;
3666
3667+ // Flatten output?
3668+ int flatten;
3669+
3670 // Index of the AS we are looking at
3671 unsigned int as_index;
3672
3673@@ -933,7 +936,7 @@ LOC_EXPORT int loc_database_get_country(struct loc_database* db,
3674 // Enumerator
3675
3676 LOC_EXPORT int loc_database_enumerator_new(struct loc_database_enumerator** enumerator,
3677- struct loc_database* db, enum loc_database_enumerator_mode mode) {
3678+ struct loc_database* db, enum loc_database_enumerator_mode mode, int flags) {
3679 struct loc_database_enumerator* e = calloc(1, sizeof(*e));
3680 if (!e)
3681 return -ENOMEM;
3682@@ -944,6 +947,9 @@ LOC_EXPORT int loc_database_enumerator_new(struct loc_database_enumerator** enum
3683 e->mode = mode;
3684 e->refcount = 1;
3685
3686+ // Flatten output?
3687+ e->flatten = (flags & LOC_DB_ENUMERATOR_FLAGS_FLATTEN);
3688+
3689 // Initialise graph search
3690 //e->network_stack[++e->network_stack_depth] = 0;
3691 e->network_stack_depth = 1;
3692diff --git a/src/loc/database.h b/src/loc/database.h
3693index 43173dd..14eb5ea 100644
3694--- a/src/loc/database.h
3695+++ b/src/loc/database.h
3696@@ -55,9 +55,13 @@ enum loc_database_enumerator_mode {
3697 LOC_DB_ENUMERATE_COUNTRIES = 3,
3698 };
3699
3700+enum loc_database_enumerator_flags {
3701+ LOC_DB_ENUMERATOR_FLAGS_FLATTEN = (1 << 0),
3702+};
3703+
3704 struct loc_database_enumerator;
3705 int loc_database_enumerator_new(struct loc_database_enumerator** enumerator,
3706- struct loc_database* db, enum loc_database_enumerator_mode mode);
3707+ struct loc_database* db, enum loc_database_enumerator_mode mode, int flags);
3708 struct loc_database_enumerator* loc_database_enumerator_ref(struct loc_database_enumerator* enumerator);
3709 struct loc_database_enumerator* loc_database_enumerator_unref(struct loc_database_enumerator* enumerator);
3710
3711diff --git a/src/perl/Location.xs b/src/perl/Location.xs
3712index dcf3f0d..b7676d2 100644
3713--- a/src/perl/Location.xs
3714+++ b/src/perl/Location.xs
3715@@ -125,7 +125,7 @@ database_countries(db)
3716 PPCODE:
3717 // Create Database enumerator
3718 struct loc_database_enumerator* enumerator;
3719- int err = loc_database_enumerator_new(&enumerator, db, LOC_DB_ENUMERATE_COUNTRIES);
3720+ int err = loc_database_enumerator_new(&enumerator, db, LOC_DB_ENUMERATE_COUNTRIES, 0);
3721
3722 if (err) {
3723 croak("Could not create a database enumerator\n");
3724diff --git a/src/python/database.c b/src/python/database.c
3725index 1013a58..7f8c2c2 100644
3726--- a/src/python/database.c
3727+++ b/src/python/database.c
3728@@ -207,10 +207,10 @@ static PyObject* new_database_enumerator(PyTypeObject* type, struct loc_database
3729 return (PyObject*)self;
3730 }
3731
3732-static PyObject* Database_iterate_all(DatabaseObject* self, enum loc_database_enumerator_mode what) {
3733+static PyObject* Database_iterate_all(DatabaseObject* self, enum loc_database_enumerator_mode what, int flags) {
3734 struct loc_database_enumerator* enumerator;
3735
3736- int r = loc_database_enumerator_new(&enumerator, self->db, what);
3737+ int r = loc_database_enumerator_new(&enumerator, self->db, what, flags);
3738 if (r) {
3739 PyErr_SetFromErrno(PyExc_SystemError);
3740 return NULL;
3741@@ -223,7 +223,7 @@ static PyObject* Database_iterate_all(DatabaseObject* self, enum loc_database_en
3742 }
3743
3744 static PyObject* Database_ases(DatabaseObject* self) {
3745- return Database_iterate_all(self, LOC_DB_ENUMERATE_ASES);
3746+ return Database_iterate_all(self, LOC_DB_ENUMERATE_ASES, 0);
3747 }
3748
3749 static PyObject* Database_search_as(DatabaseObject* self, PyObject* args) {
3750@@ -234,7 +234,7 @@ static PyObject* Database_search_as(DatabaseObject* self, PyObject* args) {
3751
3752 struct loc_database_enumerator* enumerator;
3753
3754- int r = loc_database_enumerator_new(&enumerator, self->db, LOC_DB_ENUMERATE_ASES);
3755+ int r = loc_database_enumerator_new(&enumerator, self->db, LOC_DB_ENUMERATE_ASES, 0);
3756 if (r) {
3757 PyErr_SetFromErrno(PyExc_SystemError);
3758 return NULL;
3759@@ -250,7 +250,11 @@ static PyObject* Database_search_as(DatabaseObject* self, PyObject* args) {
3760 }
3761
3762 static PyObject* Database_networks(DatabaseObject* self) {
3763- return Database_iterate_all(self, LOC_DB_ENUMERATE_NETWORKS);
3764+ return Database_iterate_all(self, LOC_DB_ENUMERATE_NETWORKS, 0);
3765+}
3766+
3767+static PyObject* Database_networks_flattened(DatabaseObject *self) {
3768+ return Database_iterate_all(self, LOC_DB_ENUMERATE_NETWORKS, LOC_DB_ENUMERATOR_FLAGS_FLATTEN);
3769 }
3770
3771 static PyObject* Database_search_networks(DatabaseObject* self, PyObject* args, PyObject* kwargs) {
3772@@ -264,7 +268,7 @@ static PyObject* Database_search_networks(DatabaseObject* self, PyObject* args,
3773 return NULL;
3774
3775 struct loc_database_enumerator* enumerator;
3776- int r = loc_database_enumerator_new(&enumerator, self->db, LOC_DB_ENUMERATE_NETWORKS);
3777+ int r = loc_database_enumerator_new(&enumerator, self->db, LOC_DB_ENUMERATE_NETWORKS, 0);
3778 if (r) {
3779 PyErr_SetFromErrno(PyExc_SystemError);
3780 return NULL;
3781@@ -317,7 +321,7 @@ static PyObject* Database_search_networks(DatabaseObject* self, PyObject* args,
3782 }
3783
3784 static PyObject* Database_countries(DatabaseObject* self) {
3785- return Database_iterate_all(self, LOC_DB_ENUMERATE_COUNTRIES);
3786+ return Database_iterate_all(self, LOC_DB_ENUMERATE_COUNTRIES, 0);
3787 }
3788
3789 static struct PyMethodDef Database_methods[] = {
3790@@ -403,6 +407,13 @@ static struct PyGetSetDef Database_getsetters[] = {
3791 NULL,
3792 NULL,
3793 },
3794+ {
3795+ "networks_flattened",
3796+ (getter)Database_networks_flattened,
3797+ NULL,
3798+ NULL,
3799+ NULL,
3800+ },
3801 {
3802 "vendor",
3803 (getter)Database_get_vendor,
3804--
38052.20.1
3806
3807From f5e50a47e37e9b29d0d2ee9e5a41e5a5fe5aea7f Mon Sep 17 00:00:00 2001
3808From: Michael Tremer <michael.tremer@ipfire.org>
3809Date: Thu, 12 Nov 2020 19:21:58 +0000
0be475ca 3810Subject: [PATCH 041/111] network: Reduce debugging output
05db64d0
MT
3811
3812Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
3813---
3814 src/network.c | 28 +++-------------------------
3815 1 file changed, 3 insertions(+), 25 deletions(-)
3816
3817diff --git a/src/network.c b/src/network.c
3818index 44571b3..f7071a6 100644
3819--- a/src/network.c
3820+++ b/src/network.c
3821@@ -421,37 +421,17 @@ LOC_EXPORT int loc_network_match_flag(struct loc_network* network, uint32_t flag
3822 }
3823
3824 LOC_EXPORT int loc_network_eq(struct loc_network* self, struct loc_network* other) {
3825-#ifdef ENABLE_DEBUG
3826- char* n1 = loc_network_str(self);
3827- char* n2 = loc_network_str(other);
3828-
3829- DEBUG(self->ctx, "Is %s equal to %s?\n", n1, n2);
3830-
3831- free(n1);
3832- free(n2);
3833-#endif
3834-
3835 // Family must be the same
3836- if (self->family != other->family) {
3837- DEBUG(self->ctx, " Family mismatch\n");
3838-
3839+ if (self->family != other->family)
3840 return 0;
3841- }
3842
3843 // The start address must be the same
3844- if (in6_addr_cmp(&self->first_address, &other->first_address) != 0) {
3845- DEBUG(self->ctx, " Address mismatch\n");
3846-
3847+ if (in6_addr_cmp(&self->first_address, &other->first_address) != 0)
3848 return 0;
3849- }
3850
3851 // The prefix length must be the same
3852- if (self->prefix != other->prefix) {
3853- DEBUG(self->ctx, " Prefix mismatch\n");
3854+ if (self->prefix != other->prefix)
3855 return 0;
3856- }
3857-
3858- DEBUG(self->ctx, " Yes!\n");
3859
3860 return 1;
3861 }
3862@@ -1138,8 +1118,6 @@ static void loc_network_list_swap(struct loc_network_list* list, unsigned int i1
3863 if (i1 >= list->size || i2 >= list->size)
3864 return;
3865
3866- DEBUG(list->ctx, "Swapping %u with %u\n", i1, i2);
3867-
3868 struct loc_network* network1 = list->list[i1];
3869 struct loc_network* network2 = list->list[i2];
3870
3871--
38722.20.1
3873
3874From 037c65d3a07ec6d37ff063f0645adda6b483b407 Mon Sep 17 00:00:00 2001
3875From: Michael Tremer <michael.tremer@ipfire.org>
3876Date: Thu, 12 Nov 2020 19:36:38 +0000
0be475ca 3877Subject: [PATCH 042/111] python: Export networks exclude function
05db64d0
MT
3878
3879Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
3880---
3881 src/python/network.c | 39 +++++++++++++++++++++++++++++++++++++++
3882 1 file changed, 39 insertions(+)
3883
3884diff --git a/src/python/network.c b/src/python/network.c
3885index 5496d1e..11f672b 100644
3886--- a/src/python/network.c
3887+++ b/src/python/network.c
3888@@ -24,6 +24,24 @@
3889 #include "locationmodule.h"
3890 #include "network.h"
3891
3892+static PyObject* PyList_FromNetworkList(struct loc_network_list* networks) {
3893+ PyObject* list = PyList_New(0);
3894+ if (!networks)
3895+ return list;
3896+
3897+ while (!loc_network_list_empty(networks)) {
3898+ struct loc_network* network = loc_network_list_pop(networks);
3899+
3900+ PyObject* n = new_network(&NetworkType, network);
3901+ PyList_Append(list, n);
3902+
3903+ loc_network_unref(network);
3904+ Py_DECREF(n);
3905+ }
3906+
3907+ return list;
3908+}
3909+
3910 PyObject* new_network(PyTypeObject* type, struct loc_network* network) {
3911 NetworkObject* self = (NetworkObject*)type->tp_alloc(type, 0);
3912 if (self) {
3913@@ -154,6 +172,21 @@ static PyObject* Network_set_flag(NetworkObject* self, PyObject* args) {
3914 Py_RETURN_NONE;
3915 }
3916
3917+static PyObject* Network_exclude(NetworkObject* self, PyObject* args) {
3918+ NetworkObject* other = NULL;
3919+
3920+ if (!PyArg_ParseTuple(args, "O!", &NetworkType, &other))
3921+ return NULL;
3922+
3923+ struct loc_network_list* list = loc_network_exclude(self->network, other->network);
3924+
3925+ // Convert to Python objects
3926+ PyObject* obj = PyList_FromNetworkList(list);
3927+ loc_network_list_unref(list);
3928+
3929+ return obj;
3930+}
3931+
3932 static PyObject* Network_is_subnet_of(NetworkObject* self, PyObject* args) {
3933 NetworkObject* other = NULL;
3934
3935@@ -191,6 +224,12 @@ static PyObject* Network_get_last_address(NetworkObject* self) {
3936 }
3937
3938 static struct PyMethodDef Network_methods[] = {
3939+ {
3940+ "exclude",
3941+ (PyCFunction)Network_exclude,
3942+ METH_VARARGS,
3943+ NULL,
3944+ },
3945 {
3946 "has_flag",
3947 (PyCFunction)Network_has_flag,
3948--
39492.20.1
3950
3951From 9a7732c8679e805d4d2d55ea4750c5d70ca4bd2c Mon Sep 17 00:00:00 2001
3952From: Michael Tremer <michael.tremer@ipfire.org>
3953Date: Thu, 12 Nov 2020 19:59:22 +0000
0be475ca 3954Subject: [PATCH 043/111] network: Add more debugging output to stacks
05db64d0
MT
3955
3956Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
3957---
3958 src/network.c | 16 +++++++++++++---
3959 1 file changed, 13 insertions(+), 3 deletions(-)
3960
3961diff --git a/src/network.c b/src/network.c
3962index f7071a6..d41e873 100644
3963--- a/src/network.c
3964+++ b/src/network.c
3965@@ -1088,8 +1088,12 @@ LOC_EXPORT int loc_network_list_push(struct loc_network_list* list, struct loc_n
3966 return 0;
3967
3968 // Check if we have space left
3969- if (list->size == list->max_size)
3970+ if (list->size == list->max_size) {
3971+ ERROR(list->ctx, "%p: Could not push network onto the stack: Stack full\n", list);
3972 return -ENOMEM;
3973+ }
3974+
3975+ DEBUG(list->ctx, "%p: Pushing network %p onto stack\n", list, network);
3976
3977 list->list[list->size++] = loc_network_ref(network);
3978
3979@@ -1098,10 +1102,16 @@ LOC_EXPORT int loc_network_list_push(struct loc_network_list* list, struct loc_n
3980
3981 LOC_EXPORT struct loc_network* loc_network_list_pop(struct loc_network_list* list) {
3982 // Return nothing when empty
3983- if (loc_network_list_empty(list))
3984+ if (loc_network_list_empty(list)) {
3985+ DEBUG(list->ctx, "%p: Popped empty stack\n", list);
3986 return NULL;
3987+ }
3988
3989- return list->list[--list->size];
3990+ struct loc_network* network = list->list[--list->size];
3991+
3992+ DEBUG(list->ctx, "%p: Popping network %p from stack\n", list, network);
3993+
3994+ return network;
3995 }
3996
3997 LOC_EXPORT int loc_network_list_contains(struct loc_network_list* list, struct loc_network* network) {
3998--
39992.20.1
4000
4001From 33a051e0435f6e78cc936f26f3b9ee16b7851025 Mon Sep 17 00:00:00 2001
4002From: Michael Tremer <michael.tremer@ipfire.org>
4003Date: Thu, 12 Nov 2020 20:00:09 +0000
0be475ca 4004Subject: [PATCH 044/111] network: Add new subnet function
05db64d0
MT
4005
4006The old one is too difficult to use in terms of order
4007of input parameters and return value.
4008
4009Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
4010---
4011 src/libloc.sym | 1 +
4012 src/loc/network.h | 1 +
4013 src/network.c | 15 +++++++++++++++
4014 3 files changed, 17 insertions(+)
4015
4016diff --git a/src/libloc.sym b/src/libloc.sym
4017index c0b6b1f..5392437 100644
4018--- a/src/libloc.sym
4019+++ b/src/libloc.sym
4020@@ -87,6 +87,7 @@ global:
4021 loc_network_get_asn;
4022 loc_network_get_country_code;
4023 loc_network_has_flag;
4024+ loc_network_is_subnet;
4025 loc_network_is_subnet_of;
4026 loc_network_match_asn;
4027 loc_network_match_country_code;
4028diff --git a/src/loc/network.h b/src/loc/network.h
4029index e30d91c..2154cdc 100644
4030--- a/src/loc/network.h
4031+++ b/src/loc/network.h
4032@@ -56,6 +56,7 @@ int loc_network_match_flag(struct loc_network* network, uint32_t flag);
4033
4034 int loc_network_eq(struct loc_network* self, struct loc_network* other);
4035 int loc_network_overlaps(struct loc_network* self, struct loc_network* other);
4036+int loc_network_is_subnet(struct loc_network* self, struct loc_network* other);
4037 int loc_network_is_subnet_of(struct loc_network* self, struct loc_network* other);
4038 struct loc_network_list* loc_network_subnets(struct loc_network* network);
4039 struct loc_network_list* loc_network_exclude(
4040diff --git a/src/network.c b/src/network.c
4041index d41e873..5719111 100644
4042--- a/src/network.c
4043+++ b/src/network.c
4044@@ -479,6 +479,21 @@ LOC_EXPORT int loc_network_overlaps(struct loc_network* self, struct loc_network
4045 return 0;
4046 }
4047
4048+LOC_EXPORT int loc_network_is_subnet(struct loc_network* self, struct loc_network* other) {
4049+ // If the start address of the other network is smaller than this network,
4050+ // it cannot be a subnet.
4051+ if (in6_addr_cmp(&self->first_address, &other->first_address) < 0)
4052+ return 0;
4053+
4054+ // If the end address of the other network is greater than this network,
4055+ // it cannot be a subnet.
4056+ if (in6_addr_cmp(&self->last_address, &other->last_address) > 0)
4057+ return 0;
4058+
4059+ return 1;
4060+}
4061+
4062+// XXX DEPRECATED - I find this too difficult to use
4063 LOC_EXPORT int loc_network_is_subnet_of(struct loc_network* self, struct loc_network* other) {
4064 // If the start address of the other network is smaller than this network,
4065 // it cannot be a subnet.
4066--
40672.20.1
4068
4069From add5bb652ba1dad1127f79cb6a0db2d363a6d5e5 Mon Sep 17 00:00:00 2001
4070From: Michael Tremer <michael.tremer@ipfire.org>
4071Date: Thu, 12 Nov 2020 20:01:17 +0000
0be475ca 4072Subject: [PATCH 045/111] network: Add function to exclude multiple networks at
05db64d0
MT
4073 once
4074
4075Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
4076---
4077 src/libloc.sym | 1 +
4078 src/loc/network.h | 2 ++
4079 src/network.c | 85 +++++++++++++++++++++++++++++++++++++++++++++++
4080 3 files changed, 88 insertions(+)
4081
4082diff --git a/src/libloc.sym b/src/libloc.sym
4083index 5392437..bcd11be 100644
4084--- a/src/libloc.sym
4085+++ b/src/libloc.sym
4086@@ -82,6 +82,7 @@ global:
4087 loc_network_address_family;
4088 loc_network_eq;
4089 loc_network_exclude;
4090+ loc_network_exclude_list;
4091 loc_network_format_first_address;
4092 loc_network_format_last_address;
4093 loc_network_get_asn;
4094diff --git a/src/loc/network.h b/src/loc/network.h
4095index 2154cdc..40712b9 100644
4096--- a/src/loc/network.h
4097+++ b/src/loc/network.h
4098@@ -61,6 +61,8 @@ int loc_network_is_subnet_of(struct loc_network* self, struct loc_network* other
4099 struct loc_network_list* loc_network_subnets(struct loc_network* network);
4100 struct loc_network_list* loc_network_exclude(
4101 struct loc_network* self, struct loc_network* other);
4102+struct loc_network_list* loc_network_exclude_list(
4103+ struct loc_network* network, struct loc_network_list* list);
4104
4105 // List
4106 struct loc_network_list;
4107diff --git a/src/network.c b/src/network.c
4108index 5719111..751e8e5 100644
4109--- a/src/network.c
4110+++ b/src/network.c
4111@@ -677,6 +677,91 @@ ERROR:
4112 return NULL;
4113 }
4114
4115+LOC_EXPORT struct loc_network_list* loc_network_exclude_list(
4116+ struct loc_network* network, struct loc_network_list* list) {
4117+ struct loc_network_list* to_check;
4118+
4119+ // Create a new list with all networks to look at
4120+ int r = loc_network_list_new(network->ctx, &to_check);
4121+ if (r)
4122+ return NULL;
4123+
4124+ struct loc_network* subnet = NULL;
4125+ struct loc_network_list* subnets = NULL;
4126+
4127+ for (unsigned int i = 0; i < loc_network_list_size(list); i++) {
4128+ subnet = loc_network_list_get(list, i);
4129+
4130+ // Find all excluded networks
4131+ struct loc_network_list* excluded = loc_network_exclude(network, subnet);
4132+ if (excluded) {
4133+ // Add them all to the "to check" list
4134+ loc_network_list_merge(to_check, excluded);
4135+ loc_network_list_unref(excluded);
4136+ }
4137+
4138+ // Cleanup
4139+ loc_network_unref(subnet);
4140+ }
4141+
4142+ r = loc_network_list_new(network->ctx, &subnets);
4143+ if (r) {
4144+ loc_network_list_unref(to_check);
4145+ return NULL;
4146+ }
4147+
4148+ while (!loc_network_list_empty(to_check)) {
4149+ struct loc_network* subnet_to_check = loc_network_list_pop(to_check);
4150+
4151+ // Marks whether this subnet passed all checks
4152+ int passed = 1;
4153+
4154+ for (unsigned int i = 0; i < loc_network_list_size(list); i++) {
4155+ subnet = loc_network_list_get(list, i);
4156+
4157+ // Drop this subnet if is is already in list
4158+ if (loc_network_eq(subnet_to_check, subnet)) {
4159+ passed = 0;
4160+ loc_network_unref(subnet);
4161+ break;
4162+ }
4163+
4164+ // Drop this subnet if is a subnet of another subnet
4165+ if (loc_network_is_subnet_of(subnet, subnet_to_check)) {
4166+ passed = 0;
4167+ loc_network_unref(subnet);
4168+ break;
4169+ }
4170+
4171+ // Break it down if it overlaps
4172+ if (loc_network_overlaps(subnet_to_check, subnet)) {
4173+ passed = 0;
4174+
4175+ struct loc_network_list* excluded = loc_network_exclude(subnet_to_check, subnet);
4176+ if (excluded) {
4177+ loc_network_list_merge(to_check, excluded);
4178+ loc_network_list_unref(excluded);
4179+ }
4180+
4181+ loc_network_unref(subnet);
4182+ break;
4183+ }
4184+
4185+ loc_network_unref(subnet);
4186+ }
4187+
4188+ if (passed) {
4189+ r = loc_network_list_push(subnets, subnet_to_check);
4190+ }
4191+
4192+ loc_network_unref(subnet_to_check);
4193+ }
4194+
4195+ loc_network_list_unref(to_check);
4196+
4197+ return subnets;
4198+}
4199+
4200 LOC_EXPORT int loc_network_to_database_v1(struct loc_network* network, struct loc_database_network_v1* dbobj) {
4201 // Add country code
4202 loc_country_code_copy(dbobj->country_code, network->country_code);
4203--
42042.20.1
4205
4206From d87fd7a3d277b4b03222c7d1680e51b3e45e525b Mon Sep 17 00:00:00 2001
4207From: Michael Tremer <michael.tremer@ipfire.org>
4208Date: Thu, 12 Nov 2020 20:02:03 +0000
0be475ca 4209Subject: [PATCH 046/111] database: Add option to return networks flattened
05db64d0
MT
4210
4211Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
4212---
4213 src/database.c | 174 ++++++++++++++++++++++++++++++++++++++++---------
4214 1 file changed, 143 insertions(+), 31 deletions(-)
4215
4216diff --git a/src/database.c b/src/database.c
4217index 9baab33..7a3d1a7 100644
4218--- a/src/database.c
4219+++ b/src/database.c
4220@@ -118,6 +118,9 @@ struct loc_database_enumerator {
4221 struct loc_node_stack network_stack[MAX_STACK_DEPTH];
4222 int network_stack_depth;
4223 unsigned int* networks_visited;
4224+
4225+ // For subnet search
4226+ struct loc_network_list* stack;
4227 };
4228
4229 static int loc_database_read_magic(struct loc_database* db) {
4230@@ -935,6 +938,26 @@ LOC_EXPORT int loc_database_get_country(struct loc_database* db,
4231
4232 // Enumerator
4233
4234+static void loc_database_enumerator_free(struct loc_database_enumerator* enumerator) {
4235+ DEBUG(enumerator->ctx, "Releasing database enumerator %p\n", enumerator);
4236+
4237+ // Release all references
4238+ loc_database_unref(enumerator->db);
4239+ loc_unref(enumerator->ctx);
4240+
4241+ if (enumerator->string)
4242+ free(enumerator->string);
4243+
4244+ // Free network search
4245+ free(enumerator->networks_visited);
4246+
4247+ // Free subnet stack
4248+ if (enumerator->stack)
4249+ loc_network_list_unref(enumerator->stack);
4250+
4251+ free(enumerator);
4252+}
4253+
4254 LOC_EXPORT int loc_database_enumerator_new(struct loc_database_enumerator** enumerator,
4255 struct loc_database* db, enum loc_database_enumerator_mode mode, int flags) {
4256 struct loc_database_enumerator* e = calloc(1, sizeof(*e));
4257@@ -951,10 +974,16 @@ LOC_EXPORT int loc_database_enumerator_new(struct loc_database_enumerator** enum
4258 e->flatten = (flags & LOC_DB_ENUMERATOR_FLAGS_FLATTEN);
4259
4260 // Initialise graph search
4261- //e->network_stack[++e->network_stack_depth] = 0;
4262 e->network_stack_depth = 1;
4263 e->networks_visited = calloc(db->network_nodes_count, sizeof(*e->networks_visited));
4264
4265+ // Allocate stack
4266+ int r = loc_network_list_new(e->ctx, &e->stack);
4267+ if (r) {
4268+ loc_database_enumerator_free(e);
4269+ return r;
4270+ }
4271+
4272 DEBUG(e->ctx, "Database enumerator object allocated at %p\n", e);
4273
4274 *enumerator = e;
4275@@ -967,22 +996,6 @@ LOC_EXPORT struct loc_database_enumerator* loc_database_enumerator_ref(struct lo
4276 return enumerator;
4277 }
4278
4279-static void loc_database_enumerator_free(struct loc_database_enumerator* enumerator) {
4280- DEBUG(enumerator->ctx, "Releasing database enumerator %p\n", enumerator);
4281-
4282- // Release all references
4283- loc_database_unref(enumerator->db);
4284- loc_unref(enumerator->ctx);
4285-
4286- if (enumerator->string)
4287- free(enumerator->string);
4288-
4289- // Free network search
4290- free(enumerator->networks_visited);
4291-
4292- free(enumerator);
4293-}
4294-
4295 LOC_EXPORT struct loc_database_enumerator* loc_database_enumerator_unref(struct loc_database_enumerator* enumerator) {
4296 if (!enumerator)
4297 return NULL;
4298@@ -1116,17 +1129,13 @@ static int loc_database_enumerator_stack_push_node(
4299 return 0;
4300 }
4301
4302-LOC_EXPORT int loc_database_enumerator_next_network(
4303- struct loc_database_enumerator* enumerator, struct loc_network** network) {
4304- // Reset network
4305- *network = NULL;
4306-
4307- // Do not do anything if not in network mode
4308- if (enumerator->mode != LOC_DB_ENUMERATE_NETWORKS)
4309+static int __loc_database_enumerator_next_network(
4310+ struct loc_database_enumerator* enumerator, struct loc_network** network, int filter) {
4311+ // Return top element from the stack
4312+ *network = loc_network_list_pop(enumerator->stack);
4313+ if (*network)
4314 return 0;
4315
4316- int r;
4317-
4318 DEBUG(enumerator->ctx, "Called with a stack of %u nodes\n",
4319 enumerator->network_stack_depth);
4320
4321@@ -1155,7 +1164,7 @@ LOC_EXPORT int loc_database_enumerator_next_network(
4322 enumerator->db->network_nodes_v1 + node->offset;
4323
4324 // Add edges to stack
4325- r = loc_database_enumerator_stack_push_node(enumerator,
4326+ int r = loc_database_enumerator_stack_push_node(enumerator,
4327 be32toh(n->one), 1, node->depth + 1);
4328
4329 if (r)
4330@@ -1181,6 +1190,10 @@ LOC_EXPORT int loc_database_enumerator_next_network(
4331 if (r)
4332 return r;
4333
4334+ // Return all networks when the filter is disabled
4335+ if (!filter)
4336+ return 0;
4337+
4338 // Check if we are interested in this network
4339
4340 // Skip if the family does not match
4341@@ -1223,12 +1236,111 @@ LOC_EXPORT int loc_database_enumerator_next_network(
4342 }
4343
4344 // Reached the end of the search
4345+ return 0;
4346+}
4347
4348- // Mark all nodes as non-visited
4349- for (unsigned int i = 0; i < enumerator->db->network_nodes_count; i++)
4350- enumerator->networks_visited[i] = 0;
4351+static int __loc_database_enumerator_next_network_flattened(
4352+ struct loc_database_enumerator* enumerator, struct loc_network** network) {
4353+ // Fetch the next network
4354+ int r = __loc_database_enumerator_next_network(enumerator, network, 1);
4355+ if (r)
4356+ return r;
4357
4358- return 0;
4359+ // End if we could not read another network
4360+ if (!*network)
4361+ return 0;
4362+
4363+ struct loc_network* subnet = NULL;
4364+ struct loc_network_list* subnets;
4365+
4366+ // Create a list with all subnets
4367+ r = loc_network_list_new(enumerator->ctx, &subnets);
4368+ if (r)
4369+ return r;
4370+
4371+ // Search all subnets from the database
4372+ while (1) {
4373+ // Fetch the next network in line
4374+ r = __loc_database_enumerator_next_network(enumerator, &subnet, 0);
4375+ if (r)
4376+ goto END;
4377+
4378+ // End if we did not receive another subnet
4379+ if (!subnet)
4380+ break;
4381+
4382+ // Collect all subnets in a list
4383+ if (loc_network_is_subnet(*network, subnet)) {
4384+ r = loc_network_list_push(subnets, subnet);
4385+ if (r)
4386+ goto END;
4387+
4388+ loc_network_unref(subnet);
4389+ continue;
4390+ }
4391+
4392+ // If this is not a subnet, we push it back onto the stack and break
4393+ r = loc_network_list_push(enumerator->stack, subnet);
4394+ if (r)
4395+ goto END;
4396+
4397+ loc_network_unref(subnet);
4398+ break;
4399+ }
4400+
4401+ DEBUG(enumerator->ctx, "Found %zu subnet(s)\n", loc_network_list_size(subnets));
4402+
4403+ // We can abort here if the network has no subnets
4404+ if (loc_network_list_empty(subnets)) {
4405+ loc_network_list_unref(subnets);
4406+
4407+ return 0;
4408+ }
4409+
4410+ // If the network has any subnets, we will break it into smaller parts
4411+ // without the subnets.
4412+ struct loc_network_list* excluded = loc_network_exclude_list(*network, subnets);
4413+ if (!excluded || loc_network_list_empty(excluded)) {
4414+ r = 1;
4415+ goto END;
4416+ }
4417+
4418+ // Sort the result
4419+ loc_network_list_sort(excluded);
4420+
4421+ // Reverse the list
4422+ loc_network_list_reverse(excluded);
4423+
4424+ // Replace network with the first one
4425+ loc_network_unref(*network);
4426+
4427+ *network = loc_network_list_pop(excluded);
4428+
4429+ // Push the rest onto the stack
4430+ loc_network_list_merge(enumerator->stack, excluded);
4431+
4432+ loc_network_list_unref(excluded);
4433+
4434+END:
4435+ if (subnet)
4436+ loc_network_unref(subnet);
4437+
4438+ loc_network_list_unref(subnets);
4439+
4440+ return r;
4441+}
4442+
4443+LOC_EXPORT int loc_database_enumerator_next_network(
4444+ struct loc_database_enumerator* enumerator, struct loc_network** network) {
4445+ // Do not do anything if not in network mode
4446+ if (enumerator->mode != LOC_DB_ENUMERATE_NETWORKS)
4447+ return 0;
4448+
4449+ // Flatten output?
4450+ if (enumerator->flatten)
4451+ return __loc_database_enumerator_next_network_flattened(enumerator, network);
4452+
4453+ return __loc_database_enumerator_next_network(enumerator, network, 1);
4454 }
4455
4456 LOC_EXPORT int loc_database_enumerator_next_country(
4457--
44582.20.1
4459
4460From d3ae93c27dcd7f6984fdc29cc141621e277f2e2a Mon Sep 17 00:00:00 2001
4461From: Michael Tremer <michael.tremer@ipfire.org>
4462Date: Thu, 12 Nov 2020 20:09:20 +0000
0be475ca 4463Subject: [PATCH 047/111] test: Update API
05db64d0
MT
4464
4465Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
4466---
4467 src/test-as.c | 2 +-
4468 src/test-database.c | 2 +-
4469 2 files changed, 2 insertions(+), 2 deletions(-)
4470
4471diff --git a/src/test-as.c b/src/test-as.c
4472index 839a04c..2d61675 100644
4473--- a/src/test-as.c
4474+++ b/src/test-as.c
4475@@ -95,7 +95,7 @@ int main(int argc, char** argv) {
4476 // Enumerator
4477
4478 struct loc_database_enumerator* enumerator;
4479- err = loc_database_enumerator_new(&enumerator, db, LOC_DB_ENUMERATE_ASES);
4480+ err = loc_database_enumerator_new(&enumerator, db, LOC_DB_ENUMERATE_ASES, 0);
4481 if (err) {
4482 fprintf(stderr, "Could not create a database enumerator\n");
4483 exit(EXIT_FAILURE);
4484diff --git a/src/test-database.c b/src/test-database.c
4485index 4aef94e..da4b11c 100644
4486--- a/src/test-database.c
4487+++ b/src/test-database.c
4488@@ -198,7 +198,7 @@ int main(int argc, char** argv) {
4489
4490 // Enumerator
4491 struct loc_database_enumerator* enumerator;
4492- err = loc_database_enumerator_new(&enumerator, db, LOC_DB_ENUMERATE_NETWORKS);
4493+ err = loc_database_enumerator_new(&enumerator, db, LOC_DB_ENUMERATE_NETWORKS, 0);
4494 if (err) {
4495 fprintf(stderr, "Could not initialise the enumerator: %d\n", err);
4496 exit(EXIT_FAILURE);
4497--
44982.20.1
4499
4500From 594ca328c6e124d0f1eb543e9c8d9bbfe8a7b628 Mon Sep 17 00:00:00 2001
4501From: Michael Tremer <michael.tremer@ipfire.org>
4502Date: Thu, 12 Nov 2020 20:09:37 +0000
0be475ca 4503Subject: [PATCH 048/111] networks: Copy all attributes when splitting networks
05db64d0
MT
4504
4505Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
4506---
4507 src/network.c | 14 ++++++++++++++
4508 1 file changed, 14 insertions(+)
4509
4510diff --git a/src/network.c b/src/network.c
4511index 751e8e5..d67f116 100644
4512--- a/src/network.c
4513+++ b/src/network.c
4514@@ -550,6 +550,20 @@ LOC_EXPORT struct loc_network_list* loc_network_subnets(struct loc_network* netw
4515 if (r)
4516 goto ERROR;
4517
4518+ // Copy country code
4519+ const char* country_code = loc_network_get_country_code(network);
4520+ if (country_code) {
4521+ loc_network_set_country_code(subnet1, country_code);
4522+ loc_network_set_country_code(subnet2, country_code);
4523+ }
4524+
4525+ // Copy ASN
4526+ uint32_t asn = loc_network_get_asn(network);
4527+ if (asn) {
4528+ loc_network_set_asn(subnet1, asn);
4529+ loc_network_set_asn(subnet2, asn);
4530+ }
4531+
4532 loc_network_unref(subnet1);
4533 loc_network_unref(subnet2);
4534
4535--
45362.20.1
4537
4538From 69248038292e9ea1a4ee8912cdfc8700456753ad Mon Sep 17 00:00:00 2001
4539From: Michael Tremer <michael.tremer@ipfire.org>
4540Date: Fri, 13 Nov 2020 11:23:33 +0000
0be475ca 4541Subject: [PATCH 049/111] database: Move network filtering into a separate
05db64d0
MT
4542 function
4543
4544Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
4545---
4546 src/database.c | 56 +++++++++++++++++++++++---------------------------
4547 1 file changed, 26 insertions(+), 30 deletions(-)
4548
4549diff --git a/src/database.c b/src/database.c
4550index 7a3d1a7..72bc8eb 100644
4551--- a/src/database.c
4552+++ b/src/database.c
4553@@ -1129,6 +1129,31 @@ static int loc_database_enumerator_stack_push_node(
4554 return 0;
4555 }
4556
4557+static int loc_database_enumerator_filter_network(
4558+ struct loc_database_enumerator* enumerator, struct loc_network* network) {
4559+ // Skip if the family does not match
4560+ if (enumerator->family && loc_network_address_family(network) != enumerator->family)
4561+ return 1;
4562+
4563+ // Skip if the country code does not match
4564+ if (*enumerator->country_code &&
4565+ !loc_network_match_country_code(network, enumerator->country_code))
4566+ return 1;
4567+
4568+ // Skip if the ASN does not match
4569+ if (enumerator->asn &&
4570+ !loc_network_match_asn(network, enumerator->asn))
4571+ return 1;
4572+
4573+ // Skip if flags do not match
4574+ if (enumerator->flags &&
4575+ !loc_network_match_flag(network, enumerator->flags))
4576+ return 1;
4577+
4578+ // Do not filter
4579+ return 0;
4580+}
4581+
4582 static int __loc_database_enumerator_next_network(
4583 struct loc_database_enumerator* enumerator, struct loc_network** network, int filter) {
4584 // Return top element from the stack
4585@@ -1195,36 +1220,7 @@ static int __loc_database_enumerator_next_network(
4586 return 0;
4587
4588 // Check if we are interested in this network
4589-
4590- // Skip if the family does not match
4591- if (enumerator->family && loc_network_address_family(*network) != enumerator->family) {
4592- loc_network_unref(*network);
4593- *network = NULL;
4594-
4595- continue;
4596- }
4597-
4598- // Skip if the country code does not match
4599- if (*enumerator->country_code &&
4600- !loc_network_match_country_code(*network, enumerator->country_code)) {
4601- loc_network_unref(*network);
4602- *network = NULL;
4603-
4604- continue;
4605- }
4606-
4607- // Skip if the ASN does not match
4608- if (enumerator->asn &&
4609- !loc_network_match_asn(*network, enumerator->asn)) {
4610- loc_network_unref(*network);
4611- *network = NULL;
4612-
4613- continue;
4614- }
4615-
4616- // Skip if flags do not match
4617- if (enumerator->flags &&
4618- !loc_network_match_flag(*network, enumerator->flags)) {
4619+ if (loc_database_enumerator_filter_network(enumerator, *network)) {
4620 loc_network_unref(*network);
4621 *network = NULL;
4622
4623--
46242.20.1
4625
4626From 2113e71bf7b997c82670c5c22cf91aa6442fe6f3 Mon Sep 17 00:00:00 2001
4627From: Michael Tremer <michael.tremer@ipfire.org>
4628Date: Fri, 13 Nov 2020 11:29:02 +0000
0be475ca 4629Subject: [PATCH 050/111] database: Filter results coming from stack
05db64d0
MT
4630
4631Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
4632---
4633 src/database.c | 18 ++++++++++++++++--
4634 1 file changed, 16 insertions(+), 2 deletions(-)
4635
4636diff --git a/src/database.c b/src/database.c
4637index 72bc8eb..0f3cdc2 100644
4638--- a/src/database.c
4639+++ b/src/database.c
4640@@ -1157,9 +1157,23 @@ static int loc_database_enumerator_filter_network(
4641 static int __loc_database_enumerator_next_network(
4642 struct loc_database_enumerator* enumerator, struct loc_network** network, int filter) {
4643 // Return top element from the stack
4644- *network = loc_network_list_pop(enumerator->stack);
4645- if (*network)
4646+ while (1) {
4647+ *network = loc_network_list_pop(enumerator->stack);
4648+
4649+ // Stack is empty
4650+ if (!*network)
4651+ break;
4652+
4653+ // Throw away any networks by filter
4654+ if (filter && loc_database_enumerator_filter_network(enumerator, *network)) {
4655+ loc_network_unref(*network);
4656+ *network = NULL;
4657+ continue;
4658+ }
4659+
4660+ // Return result
4661 return 0;
4662+ }
4663
4664 DEBUG(enumerator->ctx, "Called with a stack of %u nodes\n",
4665 enumerator->network_stack_depth);
4666--
46672.20.1
4668
4669From d33753688138c9938743dafbbdddf220dd2afd14 Mon Sep 17 00:00:00 2001
4670From: Michael Tremer <michael.tremer@ipfire.org>
4671Date: Fri, 13 Nov 2020 11:29:15 +0000
0be475ca 4672Subject: [PATCH 051/111] network: Sort result of excluded lists
05db64d0
MT
4673
4674Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
4675---
4676 src/database.c | 3 ---
4677 src/network.c | 3 +++
4678 2 files changed, 3 insertions(+), 3 deletions(-)
4679
4680diff --git a/src/database.c b/src/database.c
4681index 0f3cdc2..6849d97 100644
4682--- a/src/database.c
4683+++ b/src/database.c
4684@@ -1315,9 +1315,6 @@ static int __loc_database_enumerator_next_network_flattened(
4685 goto END;
4686 }
4687
4688- // Sort the result
4689- loc_network_list_sort(excluded);
4690-
4691 // Reverse the list
4692 loc_network_list_reverse(excluded);
4693
4694diff --git a/src/network.c b/src/network.c
4695index d67f116..9d02bf8 100644
4696--- a/src/network.c
4697+++ b/src/network.c
4698@@ -773,6 +773,9 @@ LOC_EXPORT struct loc_network_list* loc_network_exclude_list(
4699
4700 loc_network_list_unref(to_check);
4701
4702+ // Sort the result
4703+ loc_network_list_sort(subnets);
4704+
4705 return subnets;
4706 }
4707
4708--
47092.20.1
4710
4711From 8d777f12f7ffa4df1b28d197563888296803b727 Mon Sep 17 00:00:00 2001
4712From: Michael Tremer <michael.tremer@ipfire.org>
4713Date: Fri, 13 Nov 2020 11:38:15 +0000
0be475ca 4714Subject: [PATCH 052/111] network: Add function to pop first element from stack
05db64d0
MT
4715
4716Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
4717---
4718 src/database.c | 6 ++----
4719 src/libloc.sym | 1 +
4720 src/loc/network.h | 1 +
4721 src/network.c | 19 +++++++++++++++++++
4722 4 files changed, 23 insertions(+), 4 deletions(-)
4723
4724diff --git a/src/database.c b/src/database.c
4725index 6849d97..b9d870f 100644
4726--- a/src/database.c
4727+++ b/src/database.c
4728@@ -1315,15 +1315,13 @@ static int __loc_database_enumerator_next_network_flattened(
4729 goto END;
4730 }
4731
4732- // Reverse the list
4733- loc_network_list_reverse(excluded);
4734-
4735 // Replace network with the first one
4736 loc_network_unref(*network);
4737
4738- *network = loc_network_list_pop(excluded);
4739+ *network = loc_network_list_pop_first(excluded);
4740
4741 // Push the rest onto the stack
4742+ loc_network_list_reverse(excluded);
4743 loc_network_list_merge(enumerator->stack, excluded);
4744
4745 loc_network_list_unref(excluded);
4746diff --git a/src/libloc.sym b/src/libloc.sym
4747index bcd11be..6139db6 100644
4748--- a/src/libloc.sym
4749+++ b/src/libloc.sym
4750@@ -113,6 +113,7 @@ global:
4751 loc_network_list_merge;
4752 loc_network_list_new;
4753 loc_network_list_pop;
4754+ loc_network_list_pop_first;
4755 loc_network_list_push;
4756 loc_network_list_ref;
4757 loc_network_list_reverse;
4758diff --git a/src/loc/network.h b/src/loc/network.h
4759index 40712b9..203e61c 100644
4760--- a/src/loc/network.h
4761+++ b/src/loc/network.h
4762@@ -76,6 +76,7 @@ void loc_network_list_dump(struct loc_network_list* list);
4763 struct loc_network* loc_network_list_get(struct loc_network_list* list, size_t index);
4764 int loc_network_list_push(struct loc_network_list* list, struct loc_network* network);
4765 struct loc_network* loc_network_list_pop(struct loc_network_list* list);
4766+struct loc_network* loc_network_list_pop_first(struct loc_network_list* list);
4767 int loc_network_list_contains(struct loc_network_list* list, struct loc_network* network);
4768 void loc_network_list_sort(struct loc_network_list* list);
4769 void loc_network_list_reverse(struct loc_network_list* list);
4770diff --git a/src/network.c b/src/network.c
4771index 9d02bf8..e7dc97e 100644
4772--- a/src/network.c
4773+++ b/src/network.c
4774@@ -1231,6 +1231,25 @@ LOC_EXPORT struct loc_network* loc_network_list_pop(struct loc_network_list* lis
4775 return network;
4776 }
4777
4778+LOC_EXPORT struct loc_network* loc_network_list_pop_first(struct loc_network_list* list) {
4779+ // Return nothing when empty
4780+ if (loc_network_list_empty(list)) {
4781+ DEBUG(list->ctx, "%p: Popped empty stack\n", list);
4782+ return NULL;
4783+ }
4784+
4785+ struct loc_network* network = list->list[0];
4786+
4787+ // Move all elements to the top of the stack
4788+ for (unsigned int i = 0; i < --list->size; i++) {
4789+ list->list[i] = list->list[i+1];
4790+ }
4791+
4792+ DEBUG(list->ctx, "%p: Popping network %p from stack\n", list, network);
4793+
4794+ return network;
4795+}
4796+
4797 LOC_EXPORT int loc_network_list_contains(struct loc_network_list* list, struct loc_network* network) {
4798 for (unsigned int i = 0; i < list->size; i++) {
4799 if (loc_network_eq(list->list[i], network))
4800--
48012.20.1
4802
4803From 7933f5bfb4dd7603cb646e192840762bf6394292 Mon Sep 17 00:00:00 2001
4804From: Michael Tremer <michael.tremer@ipfire.org>
4805Date: Fri, 13 Nov 2020 11:43:53 +0000
0be475ca 4806Subject: [PATCH 053/111] network: Unexport all tree functions
05db64d0
MT
4807
4808These should not be exported
4809
4810Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
4811---
4812 src/network.c | 28 ++++++++++++++--------------
4813 src/test-network.c | 9 +++++++++
4814 2 files changed, 23 insertions(+), 14 deletions(-)
4815
4816diff --git a/src/network.c b/src/network.c
4817index e7dc97e..d015579 100644
4818--- a/src/network.c
4819+++ b/src/network.c
4820@@ -847,7 +847,7 @@ struct loc_network_tree_node {
4821 struct loc_network* network;
4822 };
4823
4824-LOC_EXPORT int loc_network_tree_new(struct loc_ctx* ctx, struct loc_network_tree** tree) {
4825+int loc_network_tree_new(struct loc_ctx* ctx, struct loc_network_tree** tree) {
4826 struct loc_network_tree* t = calloc(1, sizeof(*t));
4827 if (!t)
4828 return -ENOMEM;
4829@@ -867,7 +867,7 @@ LOC_EXPORT int loc_network_tree_new(struct loc_ctx* ctx, struct loc_network_tree
4830 return 0;
4831 }
4832
4833-LOC_EXPORT struct loc_network_tree_node* loc_network_tree_get_root(struct loc_network_tree* tree) {
4834+struct loc_network_tree_node* loc_network_tree_get_root(struct loc_network_tree* tree) {
4835 return loc_network_tree_node_ref(tree->root);
4836 }
4837
4838@@ -939,7 +939,7 @@ static int __loc_network_tree_walk(struct loc_ctx* ctx, struct loc_network_tree_
4839 return 0;
4840 }
4841
4842-LOC_EXPORT int loc_network_tree_walk(struct loc_network_tree* tree,
4843+int loc_network_tree_walk(struct loc_network_tree* tree,
4844 int(*filter_callback)(struct loc_network* network, void* data),
4845 int(*callback)(struct loc_network* network, void* data), void* data) {
4846 return __loc_network_tree_walk(tree->ctx, tree->root, filter_callback, callback, data);
4847@@ -954,7 +954,7 @@ static void loc_network_tree_free(struct loc_network_tree* tree) {
4848 free(tree);
4849 }
4850
4851-LOC_EXPORT struct loc_network_tree* loc_network_tree_unref(struct loc_network_tree* tree) {
4852+struct loc_network_tree* loc_network_tree_unref(struct loc_network_tree* tree) {
4853 if (--tree->refcount > 0)
4854 return tree;
4855
4856@@ -975,13 +975,13 @@ static int __loc_network_tree_dump(struct loc_network* network, void* data) {
4857 return 0;
4858 }
4859
4860-LOC_EXPORT int loc_network_tree_dump(struct loc_network_tree* tree) {
4861+int loc_network_tree_dump(struct loc_network_tree* tree) {
4862 DEBUG(tree->ctx, "Dumping network tree at %p\n", tree);
4863
4864 return loc_network_tree_walk(tree, NULL, __loc_network_tree_dump, NULL);
4865 }
4866
4867-LOC_EXPORT int loc_network_tree_add_network(struct loc_network_tree* tree, struct loc_network* network) {
4868+int loc_network_tree_add_network(struct loc_network_tree* tree, struct loc_network* network) {
4869 DEBUG(tree->ctx, "Adding network %p to tree %p\n", network, tree);
4870
4871 struct loc_network_tree_node* node = loc_network_tree_get_path(tree,
4872@@ -1012,7 +1012,7 @@ static int __loc_network_tree_count(struct loc_network* network, void* data) {
4873 return 0;
4874 }
4875
4876-LOC_EXPORT size_t loc_network_tree_count_networks(struct loc_network_tree* tree) {
4877+size_t loc_network_tree_count_networks(struct loc_network_tree* tree) {
4878 size_t counter = 0;
4879
4880 int r = loc_network_tree_walk(tree, NULL, __loc_network_tree_count, &counter);
4881@@ -1034,11 +1034,11 @@ static size_t __loc_network_tree_count_nodes(struct loc_network_tree_node* node)
4882 return counter;
4883 }
4884
4885-LOC_EXPORT size_t loc_network_tree_count_nodes(struct loc_network_tree* tree) {
4886+size_t loc_network_tree_count_nodes(struct loc_network_tree* tree) {
4887 return __loc_network_tree_count_nodes(tree->root);
4888 }
4889
4890-LOC_EXPORT int loc_network_tree_node_new(struct loc_ctx* ctx, struct loc_network_tree_node** node) {
4891+int loc_network_tree_node_new(struct loc_ctx* ctx, struct loc_network_tree_node** node) {
4892 struct loc_network_tree_node* n = calloc(1, sizeof(*n));
4893 if (!n)
4894 return -ENOMEM;
4895@@ -1053,7 +1053,7 @@ LOC_EXPORT int loc_network_tree_node_new(struct loc_ctx* ctx, struct loc_network
4896 return 0;
4897 }
4898
4899-LOC_EXPORT struct loc_network_tree_node* loc_network_tree_node_ref(struct loc_network_tree_node* node) {
4900+struct loc_network_tree_node* loc_network_tree_node_ref(struct loc_network_tree_node* node) {
4901 if (node)
4902 node->refcount++;
4903
4904@@ -1076,7 +1076,7 @@ static void loc_network_tree_node_free(struct loc_network_tree_node* node) {
4905 free(node);
4906 }
4907
4908-LOC_EXPORT struct loc_network_tree_node* loc_network_tree_node_unref(struct loc_network_tree_node* node) {
4909+struct loc_network_tree_node* loc_network_tree_node_unref(struct loc_network_tree_node* node) {
4910 if (!node)
4911 return NULL;
4912
4913@@ -1087,7 +1087,7 @@ LOC_EXPORT struct loc_network_tree_node* loc_network_tree_node_unref(struct loc_
4914 return NULL;
4915 }
4916
4917-LOC_EXPORT struct loc_network_tree_node* loc_network_tree_node_get(struct loc_network_tree_node* node, unsigned int index) {
4918+struct loc_network_tree_node* loc_network_tree_node_get(struct loc_network_tree_node* node, unsigned int index) {
4919 if (index == 0)
4920 node = node->zero;
4921 else
4922@@ -1099,11 +1099,11 @@ LOC_EXPORT struct loc_network_tree_node* loc_network_tree_node_get(struct loc_ne
4923 return loc_network_tree_node_ref(node);
4924 }
4925
4926-LOC_EXPORT int loc_network_tree_node_is_leaf(struct loc_network_tree_node* node) {
4927+int loc_network_tree_node_is_leaf(struct loc_network_tree_node* node) {
4928 return (!!node->network);
4929 }
4930
4931-LOC_EXPORT struct loc_network* loc_network_tree_node_get_network(struct loc_network_tree_node* node) {
4932+struct loc_network* loc_network_tree_node_get_network(struct loc_network_tree_node* node) {
4933 return loc_network_ref(node->network);
4934 }
4935
4936diff --git a/src/test-network.c b/src/test-network.c
4937index af1b2e6..7c90224 100644
4938--- a/src/test-network.c
4939+++ b/src/test-network.c
4940@@ -37,12 +37,14 @@ int main(int argc, char** argv) {
4941 // Enable debug logging
4942 loc_set_log_priority(ctx, LOG_DEBUG);
4943
4944+#if 0
4945 struct loc_network_tree* tree;
4946 err = loc_network_tree_new(ctx, &tree);
4947 if (err) {
4948 fprintf(stderr, "Could not create the network tree\n");
4949 exit(EXIT_FAILURE);
4950 }
4951+#endif
4952
4953 // Create a network
4954 struct loc_network* network1;
4955@@ -58,12 +60,14 @@ int main(int argc, char** argv) {
4956 exit(EXIT_FAILURE);
4957 }
4958
4959+#if 0
4960 // Adding network to the tree
4961 err = loc_network_tree_add_network(tree, network1);
4962 if (err) {
4963 fprintf(stderr, "Could not add network to the tree\n");
4964 exit(EXIT_FAILURE);
4965 }
4966+#endif
4967
4968 // Check if the first and last addresses are correct
4969 char* string = loc_network_format_first_address(network1);
4970@@ -101,6 +105,7 @@ int main(int argc, char** argv) {
4971 exit(EXIT_FAILURE);
4972 }
4973
4974+#if 0
4975 // Adding network to the tree
4976 err = loc_network_tree_add_network(tree, network2);
4977 if (err) {
4978@@ -117,6 +122,7 @@ int main(int argc, char** argv) {
4979
4980 size_t nodes = loc_network_tree_count_nodes(tree);
4981 printf("The tree has %zu nodes\n", nodes);
4982+#endif
4983
4984 // Check equals function
4985 err = loc_network_eq(network1, network1);
4986@@ -260,7 +266,10 @@ int main(int argc, char** argv) {
4987 loc_network_unref(network2);
4988 loc_network_unref(network3);
4989 loc_network_unref(network4);
4990+
4991+#if 0
4992 loc_network_tree_unref(tree);
4993+#endif
4994
4995 // And open it again from disk
4996 struct loc_database* db;
4997--
49982.20.1
4999
5000From c242f7325bd6fc4ba26047ac24196d1c161c6e01 Mon Sep 17 00:00:00 2001
5001From: Michael Tremer <michael.tremer@ipfire.org>
5002Date: Fri, 13 Nov 2020 12:09:03 +0000
0be475ca 5003Subject: [PATCH 054/111] python: Move tree flattening into C
05db64d0
MT
5004
5005Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
5006---
5007 src/python/database.c | 8 ++-
5008 src/python/export.py | 138 +++++-------------------------------------
5009 2 files changed, 21 insertions(+), 125 deletions(-)
5010
5011diff --git a/src/python/database.c b/src/python/database.c
5012index 7f8c2c2..d169547 100644
5013--- a/src/python/database.c
5014+++ b/src/python/database.c
5015@@ -258,17 +258,19 @@ static PyObject* Database_networks_flattened(DatabaseObject *self) {
5016 }
5017
5018 static PyObject* Database_search_networks(DatabaseObject* self, PyObject* args, PyObject* kwargs) {
5019- char* kwlist[] = { "country_code", "asn", "flags", "family", NULL };
5020+ char* kwlist[] = { "country_code", "asn", "flags", "family", "flatten", NULL };
5021 const char* country_code = NULL;
5022 unsigned int asn = 0;
5023 int flags = 0;
5024 int family = 0;
5025+ int flatten = 0;
5026
5027- if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|siii", kwlist, &country_code, &asn, &flags, &family))
5028+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|siiip", kwlist, &country_code, &asn, &flags, &family, &flatten))
5029 return NULL;
5030
5031 struct loc_database_enumerator* enumerator;
5032- int r = loc_database_enumerator_new(&enumerator, self->db, LOC_DB_ENUMERATE_NETWORKS, 0);
5033+ int r = loc_database_enumerator_new(&enumerator, self->db, LOC_DB_ENUMERATE_NETWORKS,
5034+ (flatten) ? LOC_DB_ENUMERATOR_FLAGS_FLATTEN : 0);
5035 if (r) {
5036 PyErr_SetFromErrno(PyExc_SystemError);
5037 return NULL;
5038diff --git a/src/python/export.py b/src/python/export.py
5039index dd44332..be4a68e 100644
5040--- a/src/python/export.py
5041+++ b/src/python/export.py
5042@@ -87,58 +87,12 @@ class OutputWriter(object):
5043 def _write_network(self, network):
5044 self.f.write("%s\n" % network)
5045
5046- def write(self, network, subnets):
5047+ def write(self, network):
5048 if self.flatten and self._flatten(network):
5049 log.debug("Skipping writing network %s (last one was %s)" % (network, self._last_network))
5050 return
5051
5052- # Convert network into a Python object
5053- _network = ipaddress.ip_network("%s" % network)
5054-
5055- # Write the network when it has no subnets
5056- if not subnets:
5057- log.debug("Writing %s to %s" % (_network, self.f))
5058- return self._write_network(_network)
5059-
5060- # Convert subnets into Python objects
5061- _subnets = [ipaddress.ip_network("%s" % subnet) for subnet in subnets]
5062-
5063- # Split the network into smaller bits so that
5064- # we can accomodate for any gaps in it later
5065- to_check = set()
5066- for _subnet in _subnets:
5067- to_check.update(
5068- _network.address_exclude(_subnet)
5069- )
5070-
5071- # Clear the list of all subnets
5072- subnets = []
5073-
5074- # Check if all subnets to not overlap with anything else
5075- while to_check:
5076- subnet_to_check = to_check.pop()
5077-
5078- for _subnet in _subnets:
5079- # Drop this subnet if it equals one of the subnets
5080- # or if it is subnet of one of them
5081- if subnet_to_check == _subnet or subnet_to_check.subnet_of(_subnet):
5082- break
5083-
5084- # Break it down if it overlaps
5085- if subnet_to_check.overlaps(_subnet):
5086- to_check.update(
5087- subnet_to_check.address_exclude(_subnet)
5088- )
5089- break
5090-
5091- # Add the subnet again as it passed the check
5092- else:
5093- subnets.append(subnet_to_check)
5094-
5095- # Write all networks as compact as possible
5096- for network in ipaddress.collapse_addresses(subnets):
5097- log.debug("Writing %s to %s" % (network, self.f))
5098- self._write_network(network)
5099+ return self._write_network(network)
5100
5101 def finish(self):
5102 """
5103@@ -188,7 +142,7 @@ class XTGeoIPOutputWriter(OutputWriter):
5104 mode = "wb"
5105
5106 def _write_network(self, network):
5107- for address in (network.network_address, network.broadcast_address):
5108+ for address in (network.first_address, network.last_address):
5109 # Convert this into a string of bits
5110 bytes = socket.inet_pton(
5111 socket.AF_INET6 if network.version == 6 else socket.AF_INET, "%s" % address,
5112@@ -231,42 +185,21 @@ class Exporter(object):
5113 writers[asn] = self.writer.open(self.db, filename, prefix="AS%s" % asn)
5114
5115 # Get all networks that match the family
5116- networks = self.db.search_networks(family=family)
5117-
5118- # Create a stack with all networks in order where we can put items back
5119- # again and retrieve them in the next iteration.
5120- networks = BufferedStack(networks)
5121+ networks = self.db.search_networks(family=family, flatten=True)
5122
5123 # Walk through all networks
5124 for network in networks:
5125- # Collect all networks which are a subnet of network
5126- subnets = []
5127- for subnet in networks:
5128- # If the next subnet was not a subnet, we have to push
5129- # it back on the stack and break this loop
5130- if not subnet.is_subnet_of(network):
5131- networks.push(subnet)
5132- break
5133-
5134- subnets.append(subnet)
5135-
5136 # Write matching countries
5137- if network.country_code and network.country_code in writers:
5138- # Mismatching subnets
5139- gaps = [
5140- subnet for subnet in subnets if not network.country_code == subnet.country_code
5141- ]
5142-
5143- writers[network.country_code].write(network, gaps)
5144+ try:
5145+ writers[network.country_code].write(network)
5146+ except KeyError:
5147+ pass
5148
5149 # Write matching ASNs
5150- if network.asn and network.asn in writers:
5151- # Mismatching subnets
5152- gaps = [
5153- subnet for subnet in subnets if not network.asn == subnet.asn
5154- ]
5155-
5156- writers[network.asn].write(network, gaps)
5157+ try:
5158+ writers[network.asn].write(network)
5159+ except KeyError:
5160+ pass
5161
5162 # Handle flags
5163 for flag in flags:
5164@@ -274,19 +207,10 @@ class Exporter(object):
5165 # Fetch the "fake" country code
5166 country = flags[flag]
5167
5168- if not country in writers:
5169- continue
5170-
5171- gaps = [
5172- subnet for subnet in subnets
5173- if not subnet.has_flag(flag)
5174- ]
5175-
5176- writers[country].write(network, gaps)
5177-
5178- # Push all subnets back onto the stack
5179- for subnet in reversed(subnets):
5180- networks.push(subnet)
5181+ try:
5182+ writers[country].write(network)
5183+ except KeyError:
5184+ pass
5185
5186 # Write everything to the filesystem
5187 for writer in writers.values():
5188@@ -298,33 +222,3 @@ class Exporter(object):
5189 )
5190
5191 return os.path.join(directory, filename)
5192-
5193-
5194-class BufferedStack(object):
5195- """
5196- This class takes an iterator and when being iterated
5197- over it returns objects from that iterator for as long
5198- as there are any.
5199-
5200- It additionally has a function to put an item back on
5201- the back so that it will be returned again at the next
5202- iteration.
5203- """
5204- def __init__(self, iterator):
5205- self.iterator = iterator
5206- self.stack = []
5207-
5208- def __iter__(self):
5209- return self
5210-
5211- def __next__(self):
5212- if self.stack:
5213- return self.stack.pop(0)
5214-
5215- return next(self.iterator)
5216-
5217- def push(self, elem):
5218- """
5219- Takes an element and puts it on the stack
5220- """
5221- self.stack.insert(0, elem)
5222--
52232.20.1
5224
5225From e0b9ff5f38beb0d560b16db881647e5a75127df1 Mon Sep 17 00:00:00 2001
5226From: Michael Tremer <michael.tremer@ipfire.org>
5227Date: Sun, 15 Nov 2020 15:02:28 +0000
0be475ca 5228Subject: [PATCH 055/111] Move network lists into an own file
05db64d0
MT
5229
5230Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
5231---
5232 Makefile.am | 2 +
5233 src/libloc.sym | 1 +
5234 src/loc/network-list.h | 37 +++++++
5235 src/loc/network.h | 20 +---
5236 src/network-list.c | 224 +++++++++++++++++++++++++++++++++++++++++
5237 src/network.c | 207 +------------------------------------
5238 src/python/network.c | 1 +
5239 7 files changed, 269 insertions(+), 223 deletions(-)
5240 create mode 100644 src/loc/network-list.h
5241 create mode 100644 src/network-list.c
5242
5243diff --git a/Makefile.am b/Makefile.am
5244index a0431a6..f0d8c4c 100644
5245--- a/Makefile.am
5246+++ b/Makefile.am
5247@@ -96,6 +96,7 @@ pkginclude_HEADERS = \
5248 src/loc/database.h \
5249 src/loc/format.h \
5250 src/loc/network.h \
5251+ src/loc/network-list.h \
5252 src/loc/private.h \
5253 src/loc/stringpool.h \
5254 src/loc/resolv.h \
5255@@ -110,6 +111,7 @@ src_libloc_la_SOURCES = \
5256 src/country.c \
5257 src/database.c \
5258 src/network.c \
5259+ src/network-list.c \
5260 src/resolv.c \
5261 src/stringpool.c \
5262 src/writer.c
5263diff --git a/src/libloc.sym b/src/libloc.sym
5264index 6139db6..453a1be 100644
5265--- a/src/libloc.sym
5266+++ b/src/libloc.sym
5267@@ -87,6 +87,7 @@ global:
5268 loc_network_format_last_address;
5269 loc_network_get_asn;
5270 loc_network_get_country_code;
5271+ loc_network_gt;
5272 loc_network_has_flag;
5273 loc_network_is_subnet;
5274 loc_network_is_subnet_of;
5275diff --git a/src/loc/network-list.h b/src/loc/network-list.h
5276new file mode 100644
5277index 0000000..af3b28d
5278--- /dev/null
5279+++ b/src/loc/network-list.h
5280@@ -0,0 +1,37 @@
5281+/*
5282+ libloc - A library to determine the location of someone on the Internet
5283+
5284+ Copyright (C) 2020 IPFire Development Team <info@ipfire.org>
5285+
5286+ This library is free software; you can redistribute it and/or
5287+ modify it under the terms of the GNU Lesser General Public
5288+ License as published by the Free Software Foundation; either
5289+ version 2.1 of the License, or (at your option) any later version.
5290+
5291+ This library is distributed in the hope that it will be useful,
5292+ but WITHOUT ANY WARRANTY; without even the implied warranty of
5293+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
5294+ Lesser General Public License for more details.
5295+*/
5296+
5297+#ifndef LIBLOC_NETWORK_LIST_H
5298+#define LIBLOC_NETWORK_LIST_H
5299+
5300+struct loc_network_list;
5301+int loc_network_list_new(struct loc_ctx* ctx, struct loc_network_list** list);
5302+struct loc_network_list* loc_network_list_ref(struct loc_network_list* list);
5303+struct loc_network_list* loc_network_list_unref(struct loc_network_list* list);
5304+size_t loc_network_list_size(struct loc_network_list* list);
5305+int loc_network_list_empty(struct loc_network_list* list);
5306+void loc_network_list_clear(struct loc_network_list* list);
5307+void loc_network_list_dump(struct loc_network_list* list);
5308+struct loc_network* loc_network_list_get(struct loc_network_list* list, size_t index);
5309+int loc_network_list_push(struct loc_network_list* list, struct loc_network* network);
5310+struct loc_network* loc_network_list_pop(struct loc_network_list* list);
5311+struct loc_network* loc_network_list_pop_first(struct loc_network_list* list);
5312+int loc_network_list_contains(struct loc_network_list* list, struct loc_network* network);
5313+void loc_network_list_sort(struct loc_network_list* list);
5314+void loc_network_list_reverse(struct loc_network_list* list);
5315+int loc_network_list_merge(struct loc_network_list* self, struct loc_network_list* other);
5316+
5317+#endif
5318diff --git a/src/loc/network.h b/src/loc/network.h
5319index 203e61c..d86b685 100644
5320--- a/src/loc/network.h
5321+++ b/src/loc/network.h
5322@@ -21,6 +21,7 @@
5323
5324 #include <loc/libloc.h>
5325 #include <loc/format.h>
5326+#include <loc/network-list.h>
5327
5328 enum loc_network_flags {
5329 LOC_NETWORK_FLAG_ANONYMOUS_PROXY = (1 << 0), // A1
5330@@ -55,6 +56,7 @@ int loc_network_set_flag(struct loc_network* network, uint32_t flag);
5331 int loc_network_match_flag(struct loc_network* network, uint32_t flag);
5332
5333 int loc_network_eq(struct loc_network* self, struct loc_network* other);
5334+int loc_network_gt(struct loc_network* self, struct loc_network* other);
5335 int loc_network_overlaps(struct loc_network* self, struct loc_network* other);
5336 int loc_network_is_subnet(struct loc_network* self, struct loc_network* other);
5337 int loc_network_is_subnet_of(struct loc_network* self, struct loc_network* other);
5338@@ -64,24 +66,6 @@ struct loc_network_list* loc_network_exclude(
5339 struct loc_network_list* loc_network_exclude_list(
5340 struct loc_network* network, struct loc_network_list* list);
5341
5342-// List
5343-struct loc_network_list;
5344-int loc_network_list_new(struct loc_ctx* ctx, struct loc_network_list** list);
5345-struct loc_network_list* loc_network_list_ref(struct loc_network_list* list);
5346-struct loc_network_list* loc_network_list_unref(struct loc_network_list* list);
5347-size_t loc_network_list_size(struct loc_network_list* list);
5348-int loc_network_list_empty(struct loc_network_list* list);
5349-void loc_network_list_clear(struct loc_network_list* list);
5350-void loc_network_list_dump(struct loc_network_list* list);
5351-struct loc_network* loc_network_list_get(struct loc_network_list* list, size_t index);
5352-int loc_network_list_push(struct loc_network_list* list, struct loc_network* network);
5353-struct loc_network* loc_network_list_pop(struct loc_network_list* list);
5354-struct loc_network* loc_network_list_pop_first(struct loc_network_list* list);
5355-int loc_network_list_contains(struct loc_network_list* list, struct loc_network* network);
5356-void loc_network_list_sort(struct loc_network_list* list);
5357-void loc_network_list_reverse(struct loc_network_list* list);
5358-int loc_network_list_merge(struct loc_network_list* self, struct loc_network_list* other);
5359-
5360 #ifdef LIBLOC_PRIVATE
5361
5362 int loc_network_to_database_v1(struct loc_network* network, struct loc_database_network_v1* dbobj);
5363diff --git a/src/network-list.c b/src/network-list.c
5364new file mode 100644
5365index 0000000..1f6e80e
5366--- /dev/null
5367+++ b/src/network-list.c
5368@@ -0,0 +1,224 @@
5369+/*
5370+ libloc - A library to determine the location of someone on the Internet
5371+
5372+ Copyright (C) 2020 IPFire Development Team <info@ipfire.org>
5373+
5374+ This library is free software; you can redistribute it and/or
5375+ modify it under the terms of the GNU Lesser General Public
5376+ License as published by the Free Software Foundation; either
5377+ version 2.1 of the License, or (at your option) any later version.
5378+
5379+ This library is distributed in the hope that it will be useful,
5380+ but WITHOUT ANY WARRANTY; without even the implied warranty of
5381+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
5382+ Lesser General Public License for more details.
5383+*/
5384+
5385+#include <errno.h>
5386+#include <stdlib.h>
5387+
5388+#include <loc/libloc.h>
5389+#include <loc/network.h>
5390+#include <loc/private.h>
5391+
5392+struct loc_network_list {
5393+ struct loc_ctx* ctx;
5394+ int refcount;
5395+
5396+ struct loc_network* list[1024];
5397+ size_t size;
5398+ size_t max_size;
5399+};
5400+
5401+LOC_EXPORT int loc_network_list_new(struct loc_ctx* ctx,
5402+ struct loc_network_list** list) {
5403+ struct loc_network_list* l = calloc(1, sizeof(*l));
5404+ if (!l)
5405+ return -ENOMEM;
5406+
5407+ l->ctx = loc_ref(ctx);
5408+ l->refcount = 1;
5409+
5410+ // Do not allow this list to grow larger than this
5411+ l->max_size = 1024;
5412+
5413+ DEBUG(l->ctx, "Network list allocated at %p\n", l);
5414+ *list = l;
5415+ return 0;
5416+}
5417+
5418+LOC_EXPORT struct loc_network_list* loc_network_list_ref(struct loc_network_list* list) {
5419+ list->refcount++;
5420+
5421+ return list;
5422+}
5423+
5424+static void loc_network_list_free(struct loc_network_list* list) {
5425+ DEBUG(list->ctx, "Releasing network list at %p\n", list);
5426+
5427+ for (unsigned int i = 0; i < list->size; i++)
5428+ loc_network_unref(list->list[i]);
5429+
5430+ loc_unref(list->ctx);
5431+ free(list);
5432+}
5433+
5434+LOC_EXPORT struct loc_network_list* loc_network_list_unref(struct loc_network_list* list) {
5435+ if (!list)
5436+ return NULL;
5437+
5438+ if (--list->refcount > 0)
5439+ return list;
5440+
5441+ loc_network_list_free(list);
5442+ return NULL;
5443+}
5444+
5445+LOC_EXPORT size_t loc_network_list_size(struct loc_network_list* list) {
5446+ return list->size;
5447+}
5448+
5449+LOC_EXPORT int loc_network_list_empty(struct loc_network_list* list) {
5450+ return list->size == 0;
5451+}
5452+
5453+LOC_EXPORT void loc_network_list_clear(struct loc_network_list* list) {
5454+ for (unsigned int i = 0; i < list->size; i++)
5455+ loc_network_unref(list->list[i]);
5456+
5457+ list->size = 0;
5458+}
5459+
5460+LOC_EXPORT void loc_network_list_dump(struct loc_network_list* list) {
5461+ struct loc_network* network;
5462+ char* s;
5463+
5464+ for (unsigned int i = 0; i < list->size; i++) {
5465+ network = list->list[i];
5466+
5467+ s = loc_network_str(network);
5468+
5469+ INFO(list->ctx, "%s\n", s);
5470+ free(s);
5471+ }
5472+}
5473+
5474+LOC_EXPORT struct loc_network* loc_network_list_get(struct loc_network_list* list, size_t index) {
5475+ // Check index
5476+ if (index >= list->size)
5477+ return NULL;
5478+
5479+ return loc_network_ref(list->list[index]);
5480+}
5481+
5482+LOC_EXPORT int loc_network_list_push(struct loc_network_list* list, struct loc_network* network) {
5483+ // Do not add networks that are already on the list
5484+ if (loc_network_list_contains(list, network))
5485+ return 0;
5486+
5487+ // Check if we have space left
5488+ if (list->size == list->max_size) {
5489+ ERROR(list->ctx, "%p: Could not push network onto the stack: Stack full\n", list);
5490+ return -ENOMEM;
5491+ }
5492+
5493+ DEBUG(list->ctx, "%p: Pushing network %p onto stack\n", list, network);
5494+
5495+ list->list[list->size++] = loc_network_ref(network);
5496+
5497+ return 0;
5498+}
5499+
5500+LOC_EXPORT struct loc_network* loc_network_list_pop(struct loc_network_list* list) {
5501+ // Return nothing when empty
5502+ if (loc_network_list_empty(list)) {
5503+ DEBUG(list->ctx, "%p: Popped empty stack\n", list);
5504+ return NULL;
5505+ }
5506+
5507+ struct loc_network* network = list->list[--list->size];
5508+
5509+ DEBUG(list->ctx, "%p: Popping network %p from stack\n", list, network);
5510+
5511+ return network;
5512+}
5513+
5514+LOC_EXPORT struct loc_network* loc_network_list_pop_first(struct loc_network_list* list) {
5515+ // Return nothing when empty
5516+ if (loc_network_list_empty(list)) {
5517+ DEBUG(list->ctx, "%p: Popped empty stack\n", list);
5518+ return NULL;
5519+ }
5520+
5521+ struct loc_network* network = list->list[0];
5522+
5523+ // Move all elements to the top of the stack
5524+ for (unsigned int i = 0; i < --list->size; i++) {
5525+ list->list[i] = list->list[i+1];
5526+ }
5527+
5528+ DEBUG(list->ctx, "%p: Popping network %p from stack\n", list, network);
5529+
5530+ return network;
5531+}
5532+
5533+LOC_EXPORT int loc_network_list_contains(struct loc_network_list* list, struct loc_network* network) {
5534+ for (unsigned int i = 0; i < list->size; i++) {
5535+ if (loc_network_eq(list->list[i], network))
5536+ return 1;
5537+ }
5538+
5539+ return 0;
5540+}
5541+
5542+static void loc_network_list_swap(struct loc_network_list* list, unsigned int i1, unsigned int i2) {
5543+ // Do nothing for invalid indices
5544+ if (i1 >= list->size || i2 >= list->size)
5545+ return;
5546+
5547+ struct loc_network* network1 = list->list[i1];
5548+ struct loc_network* network2 = list->list[i2];
5549+
5550+ list->list[i1] = network2;
5551+ list->list[i2] = network1;
5552+}
5553+
5554+LOC_EXPORT void loc_network_list_reverse(struct loc_network_list* list) {
5555+ unsigned int i = 0;
5556+ unsigned int j = list->size - 1;
5557+
5558+ while (i < j) {
5559+ loc_network_list_swap(list, i++, j--);
5560+ }
5561+}
5562+
5563+LOC_EXPORT void loc_network_list_sort(struct loc_network_list* list) {
5564+ unsigned int n = list->size;
5565+ int swapped;
5566+
5567+ do {
5568+ swapped = 0;
5569+
5570+ for (unsigned int i = 1; i < n; i++) {
5571+ if (loc_network_gt(list->list[i-1], list->list[i]) > 0) {
5572+ loc_network_list_swap(list, i-1, i);
5573+ swapped = 1;
5574+ }
5575+ }
5576+
5577+ n--;
5578+ } while (swapped);
5579+}
5580+
5581+LOC_EXPORT int loc_network_list_merge(
5582+ struct loc_network_list* self, struct loc_network_list* other) {
5583+ int r;
5584+
5585+ for (unsigned int i = 0; i < other->size; i++) {
5586+ r = loc_network_list_push(self, other->list[i]);
5587+ if (r)
5588+ return r;
5589+ }
5590+
5591+ return 0;
5592+}
5593diff --git a/src/network.c b/src/network.c
5594index d015579..28ca2df 100644
5595--- a/src/network.c
5596+++ b/src/network.c
5597@@ -29,6 +29,7 @@
5598 #include <loc/compat.h>
5599 #include <loc/country.h>
5600 #include <loc/network.h>
5601+#include <loc/network-list.h>
5602 #include <loc/private.h>
5603
5604 struct loc_network {
5605@@ -436,7 +437,7 @@ LOC_EXPORT int loc_network_eq(struct loc_network* self, struct loc_network* othe
5606 return 1;
5607 }
5608
5609-static int loc_network_gt(struct loc_network* self, struct loc_network* other) {
5610+LOC_EXPORT int loc_network_gt(struct loc_network* self, struct loc_network* other) {
5611 // Families must match
5612 if (self->family != other->family)
5613 return -1;
5614@@ -1106,207 +1107,3 @@ int loc_network_tree_node_is_leaf(struct loc_network_tree_node* node) {
5615 struct loc_network* loc_network_tree_node_get_network(struct loc_network_tree_node* node) {
5616 return loc_network_ref(node->network);
5617 }
5618-
5619-// List
5620-
5621-struct loc_network_list {
5622- struct loc_ctx* ctx;
5623- int refcount;
5624-
5625- struct loc_network* list[1024];
5626- size_t size;
5627- size_t max_size;
5628-};
5629-
5630-LOC_EXPORT int loc_network_list_new(struct loc_ctx* ctx,
5631- struct loc_network_list** list) {
5632- struct loc_network_list* l = calloc(1, sizeof(*l));
5633- if (!l)
5634- return -ENOMEM;
5635-
5636- l->ctx = loc_ref(ctx);
5637- l->refcount = 1;
5638-
5639- // Do not allow this list to grow larger than this
5640- l->max_size = 1024;
5641-
5642- DEBUG(l->ctx, "Network list allocated at %p\n", l);
5643- *list = l;
5644- return 0;
5645-}
5646-
5647-LOC_EXPORT struct loc_network_list* loc_network_list_ref(struct loc_network_list* list) {
5648- list->refcount++;
5649-
5650- return list;
5651-}
5652-
5653-static void loc_network_list_free(struct loc_network_list* list) {
5654- DEBUG(list->ctx, "Releasing network list at %p\n", list);
5655-
5656- for (unsigned int i = 0; i < list->size; i++)
5657- loc_network_unref(list->list[i]);
5658-
5659- loc_unref(list->ctx);
5660- free(list);
5661-}
5662-
5663-LOC_EXPORT struct loc_network_list* loc_network_list_unref(struct loc_network_list* list) {
5664- if (!list)
5665- return NULL;
5666-
5667- if (--list->refcount > 0)
5668- return list;
5669-
5670- loc_network_list_free(list);
5671- return NULL;
5672-}
5673-
5674-LOC_EXPORT size_t loc_network_list_size(struct loc_network_list* list) {
5675- return list->size;
5676-}
5677-
5678-LOC_EXPORT int loc_network_list_empty(struct loc_network_list* list) {
5679- return list->size == 0;
5680-}
5681-
5682-LOC_EXPORT void loc_network_list_clear(struct loc_network_list* list) {
5683- for (unsigned int i = 0; i < list->size; i++)
5684- loc_network_unref(list->list[i]);
5685-
5686- list->size = 0;
5687-}
5688-
5689-LOC_EXPORT void loc_network_list_dump(struct loc_network_list* list) {
5690- struct loc_network* network;
5691- char* s;
5692-
5693- for (unsigned int i = 0; i < list->size; i++) {
5694- network = list->list[i];
5695-
5696- s = loc_network_str(network);
5697-
5698- INFO(list->ctx, "%s\n", s);
5699- free(s);
5700- }
5701-}
5702-
5703-LOC_EXPORT struct loc_network* loc_network_list_get(struct loc_network_list* list, size_t index) {
5704- // Check index
5705- if (index >= list->size)
5706- return NULL;
5707-
5708- return loc_network_ref(list->list[index]);
5709-}
5710-
5711-LOC_EXPORT int loc_network_list_push(struct loc_network_list* list, struct loc_network* network) {
5712- // Do not add networks that are already on the list
5713- if (loc_network_list_contains(list, network))
5714- return 0;
5715-
5716- // Check if we have space left
5717- if (list->size == list->max_size) {
5718- ERROR(list->ctx, "%p: Could not push network onto the stack: Stack full\n", list);
5719- return -ENOMEM;
5720- }
5721-
5722- DEBUG(list->ctx, "%p: Pushing network %p onto stack\n", list, network);
5723-
5724- list->list[list->size++] = loc_network_ref(network);
5725-
5726- return 0;
5727-}
5728-
5729-LOC_EXPORT struct loc_network* loc_network_list_pop(struct loc_network_list* list) {
5730- // Return nothing when empty
5731- if (loc_network_list_empty(list)) {
5732- DEBUG(list->ctx, "%p: Popped empty stack\n", list);
5733- return NULL;
5734- }
5735-
5736- struct loc_network* network = list->list[--list->size];
5737-
5738- DEBUG(list->ctx, "%p: Popping network %p from stack\n", list, network);
5739-
5740- return network;
5741-}
5742-
5743-LOC_EXPORT struct loc_network* loc_network_list_pop_first(struct loc_network_list* list) {
5744- // Return nothing when empty
5745- if (loc_network_list_empty(list)) {
5746- DEBUG(list->ctx, "%p: Popped empty stack\n", list);
5747- return NULL;
5748- }
5749-
5750- struct loc_network* network = list->list[0];
5751-
5752- // Move all elements to the top of the stack
5753- for (unsigned int i = 0; i < --list->size; i++) {
5754- list->list[i] = list->list[i+1];
5755- }
5756-
5757- DEBUG(list->ctx, "%p: Popping network %p from stack\n", list, network);
5758-
5759- return network;
5760-}
5761-
5762-LOC_EXPORT int loc_network_list_contains(struct loc_network_list* list, struct loc_network* network) {
5763- for (unsigned int i = 0; i < list->size; i++) {
5764- if (loc_network_eq(list->list[i], network))
5765- return 1;
5766- }
5767-
5768- return 0;
5769-}
5770-
5771-static void loc_network_list_swap(struct loc_network_list* list, unsigned int i1, unsigned int i2) {
5772- // Do nothing for invalid indices
5773- if (i1 >= list->size || i2 >= list->size)
5774- return;
5775-
5776- struct loc_network* network1 = list->list[i1];
5777- struct loc_network* network2 = list->list[i2];
5778-
5779- list->list[i1] = network2;
5780- list->list[i2] = network1;
5781-}
5782-
5783-LOC_EXPORT void loc_network_list_reverse(struct loc_network_list* list) {
5784- unsigned int i = 0;
5785- unsigned int j = list->size - 1;
5786-
5787- while (i < j) {
5788- loc_network_list_swap(list, i++, j--);
5789- }
5790-}
5791-
5792-LOC_EXPORT void loc_network_list_sort(struct loc_network_list* list) {
5793- unsigned int n = list->size;
5794- int swapped;
5795-
5796- do {
5797- swapped = 0;
5798-
5799- for (unsigned int i = 1; i < n; i++) {
5800- if (loc_network_gt(list->list[i-1], list->list[i]) > 0) {
5801- loc_network_list_swap(list, i-1, i);
5802- swapped = 1;
5803- }
5804- }
5805-
5806- n--;
5807- } while (swapped);
5808-}
5809-
5810-LOC_EXPORT int loc_network_list_merge(
5811- struct loc_network_list* self, struct loc_network_list* other) {
5812- int r;
5813-
5814- for (unsigned int i = 0; i < other->size; i++) {
5815- r = loc_network_list_push(self, other->list[i]);
5816- if (r)
5817- return r;
5818- }
5819-
5820- return 0;
5821-}
5822diff --git a/src/python/network.c b/src/python/network.c
5823index 11f672b..ed91d65 100644
5824--- a/src/python/network.c
5825+++ b/src/python/network.c
5826@@ -20,6 +20,7 @@
5827
5828 #include <loc/libloc.h>
5829 #include <loc/network.h>
5830+#include <loc/network-list.h>
5831
5832 #include "locationmodule.h"
5833 #include "network.h"
5834--
58352.20.1
5836
5837From e646a8f35ec7eff009414b3fd107c9af5cf39a86 Mon Sep 17 00:00:00 2001
5838From: Michael Tremer <michael.tremer@ipfire.org>
5839Date: Mon, 16 Nov 2020 15:13:28 +0000
0be475ca 5840Subject: [PATCH 056/111] Implement filtering for multiple countries in the
05db64d0
MT
5841 enumerator
5842
5843This will allow us to speed up the export of the database
5844if only a few countries should be returned.
5845
5846Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
5847---
5848 Makefile.am | 2 +
5849 src/country-list.c | 138 +++++++++++++++++++++++++++++++++++++++++
5850 src/country.c | 3 +
5851 src/database.c | 47 ++++++--------
5852 src/libloc.sym | 15 ++++-
5853 src/loc/country-list.h | 43 +++++++++++++
5854 src/loc/database.h | 5 +-
5855 src/python/database.c | 57 ++++++++++++++---
5856 8 files changed, 274 insertions(+), 36 deletions(-)
5857 create mode 100644 src/country-list.c
5858 create mode 100644 src/loc/country-list.h
5859
5860diff --git a/Makefile.am b/Makefile.am
5861index f0d8c4c..f4ca3c8 100644
5862--- a/Makefile.am
5863+++ b/Makefile.am
5864@@ -93,6 +93,7 @@ pkginclude_HEADERS = \
5865 src/loc/as.h \
5866 src/loc/compat.h \
5867 src/loc/country.h \
5868+ src/loc/country-list.h \
5869 src/loc/database.h \
5870 src/loc/format.h \
5871 src/loc/network.h \
5872@@ -109,6 +110,7 @@ src_libloc_la_SOURCES = \
5873 src/libloc.c \
5874 src/as.c \
5875 src/country.c \
5876+ src/country-list.c \
5877 src/database.c \
5878 src/network.c \
5879 src/network-list.c \
5880diff --git a/src/country-list.c b/src/country-list.c
5881new file mode 100644
5882index 0000000..ae0d71a
5883--- /dev/null
5884+++ b/src/country-list.c
5885@@ -0,0 +1,138 @@
5886+/*
5887+ libloc - A library to determine the location of someone on the Internet
5888+
5889+ Copyright (C) 2020 IPFire Development Team <info@ipfire.org>
5890+
5891+ This library is free software; you can redistribute it and/or
5892+ modify it under the terms of the GNU Lesser General Public
5893+ License as published by the Free Software Foundation; either
5894+ version 2.1 of the License, or (at your option) any later version.
5895+
5896+ This library is distributed in the hope that it will be useful,
5897+ but WITHOUT ANY WARRANTY; without even the implied warranty of
5898+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
5899+ Lesser General Public License for more details.
5900+*/
5901+
5902+#include <errno.h>
5903+#include <stdlib.h>
5904+
5905+#include <loc/country.h>
5906+#include <loc/country-list.h>
5907+#include <loc/private.h>
5908+
5909+struct loc_country_list {
5910+ struct loc_ctx* ctx;
5911+ int refcount;
5912+
5913+ struct loc_country* list[1024];
5914+ size_t size;
5915+ size_t max_size;
5916+};
5917+
5918+LOC_EXPORT int loc_country_list_new(struct loc_ctx* ctx,
5919+ struct loc_country_list** list) {
5920+ struct loc_country_list* l = calloc(1, sizeof(*l));
5921+ if (!l)
5922+ return -ENOMEM;
5923+
5924+ l->ctx = loc_ref(ctx);
5925+ l->refcount = 1;
5926+
5927+ // Do not allow this list to grow larger than this
5928+ l->max_size = 1024;
5929+
5930+ DEBUG(l->ctx, "Country list allocated at %p\n", l);
5931+ *list = l;
5932+
5933+ return 0;
5934+}
5935+
5936+LOC_EXPORT struct loc_country_list* loc_country_list_ref(struct loc_country_list* list) {
5937+ list->refcount++;
5938+
5939+ return list;
5940+}
5941+
5942+static void loc_country_list_free(struct loc_country_list* list) {
5943+ DEBUG(list->ctx, "Releasing country list at %p\n", list);
5944+
5945+ loc_country_list_clear(list);
5946+
5947+ loc_unref(list->ctx);
5948+ free(list);
5949+}
5950+
5951+LOC_EXPORT struct loc_country_list* loc_country_list_unref(struct loc_country_list* list) {
5952+ if (!list)
5953+ return NULL;
5954+
5955+ if (--list->refcount > 0)
5956+ return list;
5957+
5958+ loc_country_list_free(list);
5959+ return NULL;
5960+}
5961+
5962+LOC_EXPORT size_t loc_country_list_size(struct loc_country_list* list) {
5963+ return list->size;
5964+}
5965+
5966+LOC_EXPORT int loc_country_list_empty(struct loc_country_list* list) {
5967+ return list->size == 0;
5968+}
5969+
5970+LOC_EXPORT void loc_country_list_clear(struct loc_country_list* list) {
5971+ for (unsigned int i = 0; i < list->size; i++)
5972+ loc_country_unref(list->list[i]);
5973+}
5974+
5975+LOC_EXPORT struct loc_country* loc_country_list_get(struct loc_country_list* list, size_t index) {
5976+ // Check index
5977+ if (index >= list->size)
5978+ return NULL;
5979+
5980+ return loc_country_ref(list->list[index]);
5981+}
5982+
5983+LOC_EXPORT int loc_country_list_append(
5984+ struct loc_country_list* list, struct loc_country* country) {
5985+ if (loc_country_list_contains(list, country))
5986+ return 0;
5987+
5988+ // Check if we have space left
5989+ if (list->size == list->max_size) {
5990+ ERROR(list->ctx, "%p: Could not append country to the list. List full\n", list);
5991+ return -ENOMEM;
5992+ }
5993+
5994+ DEBUG(list->ctx, "%p: Appending country %p to list\n", list, country);
5995+
5996+ list->list[list->size++] = loc_country_ref(country);
5997+
5998+ return 0;
5999+}
6000+
6001+LOC_EXPORT int loc_country_list_contains(
6002+ struct loc_country_list* list, struct loc_country* country) {
6003+ for (unsigned int i = 0; i < list->size; i++) {
6004+ if (loc_country_cmp(country, list->list[i]) == 0)
6005+ return 1;
6006+ }
6007+
6008+ return 0;
6009+}
6010+
6011+LOC_EXPORT int loc_country_list_contains_code(
6012+ struct loc_country_list* list, const char* code) {
6013+ struct loc_country* country;
6014+
6015+ int r = loc_country_new(list->ctx, &country, code);
6016+ if (r)
6017+ return -1;
6018+
6019+ r = loc_country_list_contains(list, country);
6020+ loc_country_unref(country);
6021+
6022+ return r;
6023+}
6024diff --git a/src/country.c b/src/country.c
6025index 2ba93e6..7aac0db 100644
6026--- a/src/country.c
6027+++ b/src/country.c
6028@@ -34,6 +34,9 @@ struct loc_country {
6029 };
6030
6031 LOC_EXPORT int loc_country_new(struct loc_ctx* ctx, struct loc_country** country, const char* country_code) {
6032+ if (!loc_country_code_is_valid(country_code))
6033+ return -EINVAL;
6034+
6035 struct loc_country* c = calloc(1, sizeof(*c));
6036 if (!c)
6037 return -ENOMEM;
6038diff --git a/src/database.c b/src/database.c
6039index b9d870f..29823b2 100644
6040--- a/src/database.c
6041+++ b/src/database.c
6042@@ -40,6 +40,7 @@
6043 #include <loc/as.h>
6044 #include <loc/compat.h>
6045 #include <loc/country.h>
6046+#include <loc/country-list.h>
6047 #include <loc/database.h>
6048 #include <loc/format.h>
6049 #include <loc/network.h>
6050@@ -99,7 +100,7 @@ struct loc_database_enumerator {
6051
6052 // Search string
6053 char* string;
6054- char country_code[3];
6055+ struct loc_country_list* countries;
6056 uint32_t asn;
6057 enum loc_network_flags flags;
6058 int family;
6059@@ -1017,33 +1018,20 @@ LOC_EXPORT int loc_database_enumerator_set_string(struct loc_database_enumerator
6060 return 0;
6061 }
6062
6063-LOC_EXPORT int loc_database_enumerator_set_country_code(struct loc_database_enumerator* enumerator, const char* country_code) {
6064- // Set empty country code
6065- if (!country_code || !*country_code) {
6066- *enumerator->country_code = '\0';
6067- return 0;
6068- }
6069+LOC_EXPORT struct loc_country_list* loc_database_enumerator_get_countries(
6070+ struct loc_database_enumerator* enumerator) {
6071+ if (!enumerator->countries)
6072+ return NULL;
6073
6074- // Treat A1, A2, A3 as special country codes,
6075- // but perform search for flags instead
6076- if (strcmp(country_code, "A1") == 0) {
6077- return loc_database_enumerator_set_flag(enumerator,
6078- LOC_NETWORK_FLAG_ANONYMOUS_PROXY);
6079- } else if (strcmp(country_code, "A2") == 0) {
6080- return loc_database_enumerator_set_flag(enumerator,
6081- LOC_NETWORK_FLAG_SATELLITE_PROVIDER);
6082- } else if (strcmp(country_code, "A3") == 0) {
6083- return loc_database_enumerator_set_flag(enumerator,
6084- LOC_NETWORK_FLAG_ANYCAST);
6085- }
6086+ return loc_country_list_ref(enumerator->countries);
6087+}
6088
6089- // Country codes must be two characters
6090- if (!loc_country_code_is_valid(country_code))
6091- return -EINVAL;
6092+LOC_EXPORT int loc_database_enumerator_set_countries(
6093+ struct loc_database_enumerator* enumerator, struct loc_country_list* countries) {
6094+ if (enumerator->countries)
6095+ loc_country_list_unref(enumerator->countries);
6096
6097- for (unsigned int i = 0; i < 3; i++) {
6098- enumerator->country_code[i] = country_code[i];
6099- }
6100+ enumerator->countries = loc_country_list_ref(countries);
6101
6102 return 0;
6103 }
6104@@ -1129,6 +1117,12 @@ static int loc_database_enumerator_stack_push_node(
6105 return 0;
6106 }
6107
6108+static int loc_network_match_countries(struct loc_network* network, struct loc_country_list* countries) {
6109+ const char* country_code = loc_network_get_country_code(network);
6110+
6111+ return loc_country_list_contains_code(countries, country_code);
6112+}
6113+
6114 static int loc_database_enumerator_filter_network(
6115 struct loc_database_enumerator* enumerator, struct loc_network* network) {
6116 // Skip if the family does not match
6117@@ -1136,8 +1130,7 @@ static int loc_database_enumerator_filter_network(
6118 return 1;
6119
6120 // Skip if the country code does not match
6121- if (*enumerator->country_code &&
6122- !loc_network_match_country_code(network, enumerator->country_code))
6123+ if (enumerator->countries && !loc_network_match_countries(network, enumerator->countries))
6124 return 1;
6125
6126 // Skip if the ASN does not match
6127diff --git a/src/libloc.sym b/src/libloc.sym
6128index 453a1be..40e9f88 100644
6129--- a/src/libloc.sym
6130+++ b/src/libloc.sym
6131@@ -49,6 +49,18 @@ global:
6132 loc_country_set_name;
6133 loc_country_unref;
6134
6135+ # Country List
6136+ loc_country_list_append;
6137+ loc_country_list_clear;
6138+ loc_country_list_contains;
6139+ loc_country_list_contains_code;
6140+ loc_country_list_empty;
6141+ loc_country_list_get;
6142+ loc_country_list_new;
6143+ loc_country_list_ref;
6144+ loc_country_list_size;
6145+ loc_country_list_unref;
6146+
6147 # Database
6148 loc_database_add_as;
6149 loc_database_count_as;
6150@@ -66,13 +78,14 @@ global:
6151 loc_database_verify;
6152
6153 # Database Enumerator
6154+ loc_database_enumerator_get_countries;
6155 loc_database_enumerator_new;
6156 loc_database_enumerator_next_as;
6157 loc_database_enumerator_next_country;
6158 loc_database_enumerator_next_network;
6159 loc_database_enumerator_ref;
6160 loc_database_enumerator_set_asn;
6161- loc_database_enumerator_set_country_code;
6162+ loc_database_enumerator_set_countries;
6163 loc_database_enumerator_set_family;
6164 loc_database_enumerator_set_flag;
6165 loc_database_enumerator_set_string;
6166diff --git a/src/loc/country-list.h b/src/loc/country-list.h
6167new file mode 100644
6168index 0000000..a7f818a
6169--- /dev/null
6170+++ b/src/loc/country-list.h
6171@@ -0,0 +1,43 @@
6172+/*
6173+ libloc - A library to determine the location of someone on the Internet
6174+
6175+ Copyright (C) 2017 IPFire Development Team <info@ipfire.org>
6176+
6177+ This library is free software; you can redistribute it and/or
6178+ modify it under the terms of the GNU Lesser General Public
6179+ License as published by the Free Software Foundation; either
6180+ version 2.1 of the License, or (at your option) any later version.
6181+
6182+ This library is distributed in the hope that it will be useful,
6183+ but WITHOUT ANY WARRANTY; without even the implied warranty of
6184+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
6185+ Lesser General Public License for more details.
6186+*/
6187+
6188+#ifndef LIBLOC_COUNTRY_LIST_H
6189+#define LIBLOC_COUNTRY_LIST_H
6190+
6191+#include <stdlib.h>
6192+
6193+#include <loc/libloc.h>
6194+#include <loc/country.h>
6195+
6196+struct loc_country_list;
6197+
6198+int loc_country_list_new(struct loc_ctx* ctx, struct loc_country_list** list);
6199+struct loc_country_list* loc_country_list_ref(struct loc_country_list* list);
6200+struct loc_country_list* loc_country_list_unref(struct loc_country_list* list);
6201+
6202+size_t loc_country_list_size(struct loc_country_list* list);
6203+int loc_country_list_empty(struct loc_country_list* list);
6204+void loc_country_list_clear(struct loc_country_list* list);
6205+
6206+struct loc_country* loc_country_list_get(struct loc_country_list* list, size_t index);
6207+int loc_country_list_append(struct loc_country_list* list, struct loc_country* country);
6208+
6209+int loc_country_list_contains(
6210+ struct loc_country_list* list, struct loc_country* country);
6211+int loc_country_list_contains_code(
6212+ struct loc_country_list* list, const char* code);
6213+
6214+#endif
6215diff --git a/src/loc/database.h b/src/loc/database.h
6216index 14eb5ea..246e5c5 100644
6217--- a/src/loc/database.h
6218+++ b/src/loc/database.h
6219@@ -25,6 +25,7 @@
6220 #include <loc/network.h>
6221 #include <loc/as.h>
6222 #include <loc/country.h>
6223+#include <loc/country-list.h>
6224
6225 struct loc_database;
6226 int loc_database_new(struct loc_ctx* ctx, struct loc_database** database, FILE* f);
6227@@ -66,7 +67,9 @@ struct loc_database_enumerator* loc_database_enumerator_ref(struct loc_database_
6228 struct loc_database_enumerator* loc_database_enumerator_unref(struct loc_database_enumerator* enumerator);
6229
6230 int loc_database_enumerator_set_string(struct loc_database_enumerator* enumerator, const char* string);
6231-int loc_database_enumerator_set_country_code(struct loc_database_enumerator* enumerator, const char* country_code);
6232+struct loc_country_list* loc_database_enumerator_get_countries(struct loc_database_enumerator* enumerator);
6233+int loc_database_enumerator_set_countries(
6234+ struct loc_database_enumerator* enumerator, struct loc_country_list* countries);
6235 int loc_database_enumerator_set_asn(struct loc_database_enumerator* enumerator, unsigned int asn);
6236 int loc_database_enumerator_set_flag(struct loc_database_enumerator* enumerator, enum loc_network_flags flag);
6237 int loc_database_enumerator_set_family(struct loc_database_enumerator* enumerator, int family);
6238diff --git a/src/python/database.c b/src/python/database.c
6239index d169547..e6f6f37 100644
6240--- a/src/python/database.c
6241+++ b/src/python/database.c
6242@@ -258,14 +258,15 @@ static PyObject* Database_networks_flattened(DatabaseObject *self) {
6243 }
6244
6245 static PyObject* Database_search_networks(DatabaseObject* self, PyObject* args, PyObject* kwargs) {
6246- char* kwlist[] = { "country_code", "asn", "flags", "family", "flatten", NULL };
6247- const char* country_code = NULL;
6248+ char* kwlist[] = { "country_codes", "asn", "flags", "family", "flatten", NULL };
6249+ PyObject* country_codes = NULL;
6250 unsigned int asn = 0;
6251 int flags = 0;
6252 int family = 0;
6253 int flatten = 0;
6254
6255- if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|siiip", kwlist, &country_code, &asn, &flags, &family, &flatten))
6256+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O!iiip", kwlist,
6257+ &PyList_Type, &country_codes, &asn, &flags, &family, &flatten))
6258 return NULL;
6259
6260 struct loc_database_enumerator* enumerator;
6261@@ -277,13 +278,55 @@ static PyObject* Database_search_networks(DatabaseObject* self, PyObject* args,
6262 }
6263
6264 // Set country code we are searching for
6265- if (country_code) {
6266- r = loc_database_enumerator_set_country_code(enumerator, country_code);
6267-
6268+ if (country_codes) {
6269+ struct loc_country_list* countries;
6270+ r = loc_country_list_new(loc_ctx, &countries);
6271 if (r) {
6272- PyErr_SetFromErrno(PyExc_SystemError);
6273+ PyErr_SetString(PyExc_SystemError, "Could not create country list");
6274 return NULL;
6275 }
6276+
6277+ for (unsigned int i = 0; i < PyList_Size(country_codes); i++) {
6278+ PyObject* item = PyList_GetItem(country_codes, i);
6279+
6280+ if (!PyUnicode_Check(item)) {
6281+ PyErr_SetString(PyExc_TypeError, "Country codes must be strings");
6282+ loc_country_list_unref(countries);
6283+ return NULL;
6284+ }
6285+
6286+ const char* country_code = PyUnicode_AsUTF8(item);
6287+
6288+ struct loc_country* country;
6289+ r = loc_country_new(loc_ctx, &country, country_code);
6290+ if (r) {
6291+ if (r == -EINVAL) {
6292+ PyErr_Format(PyExc_ValueError, "Invalid country code: %s", country_code);
6293+ } else {
6294+ PyErr_SetString(PyExc_SystemError, "Could not create country");
6295+ }
6296+
6297+ loc_country_list_unref(countries);
6298+ return NULL;
6299+ }
6300+
6301+ // Append it to the list
6302+ r = loc_country_list_append(countries, country);
6303+ if (r) {
6304+ PyErr_SetString(PyExc_SystemError, "Could not append country to the list");
6305+
6306+ loc_country_list_unref(countries);
6307+ loc_country_unref(country);
6308+ return NULL;
6309+ }
6310+
6311+ loc_country_unref(country);
6312+ }
6313+
6314+ loc_database_enumerator_set_countries(enumerator, countries);
6315+
6316+ Py_DECREF(country_codes);
6317+ loc_country_list_unref(countries);
6318 }
6319
6320 // Set the ASN we are searching for
6321--
63222.20.1
6323
6324From 7af51f8a579c79714992a3e175036fb511139310 Mon Sep 17 00:00:00 2001
6325From: Michael Tremer <michael.tremer@ipfire.org>
6326Date: Mon, 16 Nov 2020 15:20:50 +0000
0be475ca 6327Subject: [PATCH 057/111] python: Only return country codes we want
05db64d0
MT
6328
6329Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
6330---
6331 src/python/export.py | 8 +++++++-
6332 1 file changed, 7 insertions(+), 1 deletion(-)
6333
6334diff --git a/src/python/export.py b/src/python/export.py
6335index be4a68e..5e7fe53 100644
6336--- a/src/python/export.py
6337+++ b/src/python/export.py
6338@@ -184,8 +184,14 @@ class Exporter(object):
6339
6340 writers[asn] = self.writer.open(self.db, filename, prefix="AS%s" % asn)
6341
6342+ # Filter countries from special country codes
6343+ country_codes = [
6344+ country_code for country_code in countries if not country_code in flags.values()
6345+ ]
6346+
6347 # Get all networks that match the family
6348- networks = self.db.search_networks(family=family, flatten=True)
6349+ networks = self.db.search_networks(family=family,
6350+ country_codes=country_codes, flatten=True)
6351
6352 # Walk through all networks
6353 for network in networks:
6354--
63552.20.1
6356
6357From bd1dc6bf6fe4ce40bf12e7426e283b31afd274e1 Mon Sep 17 00:00:00 2001
6358From: Michael Tremer <michael.tremer@ipfire.org>
6359Date: Mon, 16 Nov 2020 15:25:15 +0000
0be475ca 6360Subject: [PATCH 058/111] database: Filter flags in C
05db64d0
MT
6361
6362Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
6363---
6364 src/python/export.py | 16 +++++++++++-----
6365 1 file changed, 11 insertions(+), 5 deletions(-)
6366
6367diff --git a/src/python/export.py b/src/python/export.py
6368index 5e7fe53..739742f 100644
6369--- a/src/python/export.py
6370+++ b/src/python/export.py
6371@@ -29,7 +29,7 @@ import _location
6372 log = logging.getLogger("location.export")
6373 log.propagate = 1
6374
6375-flags = {
6376+FLAGS = {
6377 _location.NETWORK_FLAG_ANONYMOUS_PROXY : "A1",
6378 _location.NETWORK_FLAG_SATELLITE_PROVIDER : "A2",
6379 _location.NETWORK_FLAG_ANYCAST : "A3",
6380@@ -186,12 +186,18 @@ class Exporter(object):
6381
6382 # Filter countries from special country codes
6383 country_codes = [
6384- country_code for country_code in countries if not country_code in flags.values()
6385+ country_code for country_code in countries if not country_code in FLAGS.values()
6386 ]
6387
6388+ # Collect flags
6389+ flags = 0
6390+ for flag in FLAGS:
6391+ if FLAGS[flag] in countries:
6392+ flags |= flag
6393+
6394 # Get all networks that match the family
6395 networks = self.db.search_networks(family=family,
6396- country_codes=country_codes, flatten=True)
6397+ country_codes=country_codes, flags=flags, flatten=True)
6398
6399 # Walk through all networks
6400 for network in networks:
6401@@ -208,10 +214,10 @@ class Exporter(object):
6402 pass
6403
6404 # Handle flags
6405- for flag in flags:
6406+ for flag in FLAGS:
6407 if network.has_flag(flag):
6408 # Fetch the "fake" country code
6409- country = flags[flag]
6410+ country = FLAGS[flag]
6411
6412 try:
6413 writers[country].write(network)
6414--
64152.20.1
6416
6417From 84a2f0c2d9cbf8ae4225802c29ccba86561c77ed Mon Sep 17 00:00:00 2001
6418From: Michael Tremer <michael.tremer@ipfire.org>
6419Date: Tue, 17 Nov 2020 16:46:48 +0000
0be475ca 6420Subject: [PATCH 059/111] as: Add list for easier processing
05db64d0
MT
6421
6422Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
6423---
6424 Makefile.am | 2 +
6425 src/as-list.c | 138 ++++++++++++++++++++++++++++++++++++++++++
6426 src/database.c | 29 +++++++--
6427 src/libloc.sym | 15 ++++-
6428 src/loc/as-list.h | 41 +++++++++++++
6429 src/loc/database.h | 5 +-
6430 src/python/database.c | 58 ++++++++++++++++--
6431 src/python/export.py | 2 +-
6432 8 files changed, 275 insertions(+), 15 deletions(-)
6433 create mode 100644 src/as-list.c
6434 create mode 100644 src/loc/as-list.h
6435
6436diff --git a/Makefile.am b/Makefile.am
6437index f4ca3c8..d0cc793 100644
6438--- a/Makefile.am
6439+++ b/Makefile.am
6440@@ -91,6 +91,7 @@ EXTRA_DIST += \
6441 pkginclude_HEADERS = \
6442 src/loc/libloc.h \
6443 src/loc/as.h \
6444+ src/loc/as-list.h \
6445 src/loc/compat.h \
6446 src/loc/country.h \
6447 src/loc/country-list.h \
6448@@ -109,6 +110,7 @@ lib_LTLIBRARIES = \
6449 src_libloc_la_SOURCES = \
6450 src/libloc.c \
6451 src/as.c \
6452+ src/as-list.c \
6453 src/country.c \
6454 src/country-list.c \
6455 src/database.c \
6456diff --git a/src/as-list.c b/src/as-list.c
6457new file mode 100644
6458index 0000000..7c69eb0
6459--- /dev/null
6460+++ b/src/as-list.c
6461@@ -0,0 +1,138 @@
6462+/*
6463+ libloc - A library to determine the location of someone on the Internet
6464+
6465+ Copyright (C) 2020 IPFire Development Team <info@ipfire.org>
6466+
6467+ This library is free software; you can redistribute it and/or
6468+ modify it under the terms of the GNU Lesser General Public
6469+ License as published by the Free Software Foundation; either
6470+ version 2.1 of the License, or (at your option) any later version.
6471+
6472+ This library is distributed in the hope that it will be useful,
6473+ but WITHOUT ANY WARRANTY; without even the implied warranty of
6474+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
6475+ Lesser General Public License for more details.
6476+*/
6477+
6478+#include <errno.h>
6479+#include <stdlib.h>
6480+
6481+#include <loc/as.h>
6482+#include <loc/as-list.h>
6483+#include <loc/private.h>
6484+
6485+struct loc_as_list {
6486+ struct loc_ctx* ctx;
6487+ int refcount;
6488+
6489+ struct loc_as* list[1024];
6490+ size_t size;
6491+ size_t max_size;
6492+};
6493+
6494+LOC_EXPORT int loc_as_list_new(struct loc_ctx* ctx,
6495+ struct loc_as_list** list) {
6496+ struct loc_as_list* l = calloc(1, sizeof(*l));
6497+ if (!l)
6498+ return -ENOMEM;
6499+
6500+ l->ctx = loc_ref(ctx);
6501+ l->refcount = 1;
6502+
6503+ // Do not allow this list to grow larger than this
6504+ l->max_size = 1024;
6505+
6506+ DEBUG(l->ctx, "AS list allocated at %p\n", l);
6507+ *list = l;
6508+
6509+ return 0;
6510+}
6511+
6512+LOC_EXPORT struct loc_as_list* loc_as_list_ref(struct loc_as_list* list) {
6513+ list->refcount++;
6514+
6515+ return list;
6516+}
6517+
6518+static void loc_as_list_free(struct loc_as_list* list) {
6519+ DEBUG(list->ctx, "Releasing AS list at %p\n", list);
6520+
6521+ loc_as_list_clear(list);
6522+
6523+ loc_unref(list->ctx);
6524+ free(list);
6525+}
6526+
6527+LOC_EXPORT struct loc_as_list* loc_as_list_unref(struct loc_as_list* list) {
6528+ if (!list)
6529+ return NULL;
6530+
6531+ if (--list->refcount > 0)
6532+ return list;
6533+
6534+ loc_as_list_free(list);
6535+ return NULL;
6536+}
6537+
6538+LOC_EXPORT size_t loc_as_list_size(struct loc_as_list* list) {
6539+ return list->size;
6540+}
6541+
6542+LOC_EXPORT int loc_as_list_empty(struct loc_as_list* list) {
6543+ return list->size == 0;
6544+}
6545+
6546+LOC_EXPORT void loc_as_list_clear(struct loc_as_list* list) {
6547+ for (unsigned int i = 0; i < list->size; i++)
6548+ loc_as_unref(list->list[i]);
6549+}
6550+
6551+LOC_EXPORT struct loc_as* loc_as_list_get(struct loc_as_list* list, size_t index) {
6552+ // Check index
6553+ if (index >= list->size)
6554+ return NULL;
6555+
6556+ return loc_as_ref(list->list[index]);
6557+}
6558+
6559+LOC_EXPORT int loc_as_list_append(
6560+ struct loc_as_list* list, struct loc_as* as) {
6561+ if (loc_as_list_contains(list, as))
6562+ return 0;
6563+
6564+ // Check if we have space left
6565+ if (list->size == list->max_size) {
6566+ ERROR(list->ctx, "%p: Could not append AS to the list. List full\n", list);
6567+ return -ENOMEM;
6568+ }
6569+
6570+ DEBUG(list->ctx, "%p: Appending AS %p to list\n", list, as);
6571+
6572+ list->list[list->size++] = loc_as_ref(as);
6573+
6574+ return 0;
6575+}
6576+
6577+LOC_EXPORT int loc_as_list_contains(
6578+ struct loc_as_list* list, struct loc_as* as) {
6579+ for (unsigned int i = 0; i < list->size; i++) {
6580+ if (loc_as_cmp(as, list->list[i]) == 0)
6581+ return 1;
6582+ }
6583+
6584+ return 0;
6585+}
6586+
6587+LOC_EXPORT int loc_as_list_contains_number(
6588+ struct loc_as_list* list, uint32_t number) {
6589+ struct loc_as* as;
6590+
6591+ int r = loc_as_new(list->ctx, &as, number);
6592+ if (r)
6593+ return -1;
6594+
6595+ r = loc_as_list_contains(list, as);
6596+ loc_as_unref(as);
6597+
6598+ return r;
6599+}
6600diff --git a/src/database.c b/src/database.c
6601index 29823b2..51cb5cd 100644
6602--- a/src/database.c
6603+++ b/src/database.c
6604@@ -38,6 +38,7 @@
6605
6606 #include <loc/libloc.h>
6607 #include <loc/as.h>
6608+#include <loc/as-list.h>
6609 #include <loc/compat.h>
6610 #include <loc/country.h>
6611 #include <loc/country-list.h>
6612@@ -101,7 +102,7 @@ struct loc_database_enumerator {
6613 // Search string
6614 char* string;
6615 struct loc_country_list* countries;
6616- uint32_t asn;
6617+ struct loc_as_list* asns;
6618 enum loc_network_flags flags;
6619 int family;
6620
6621@@ -1036,9 +1037,20 @@ LOC_EXPORT int loc_database_enumerator_set_countries(
6622 return 0;
6623 }
6624
6625-LOC_EXPORT int loc_database_enumerator_set_asn(
6626- struct loc_database_enumerator* enumerator, unsigned int asn) {
6627- enumerator->asn = asn;
6628+LOC_EXPORT struct loc_as_list* loc_database_enumerator_get_asns(
6629+ struct loc_database_enumerator* enumerator) {
6630+ if (!enumerator->asns)
6631+ return NULL;
6632+
6633+ return loc_as_list_ref(enumerator->asns);
6634+}
6635+
6636+LOC_EXPORT int loc_database_enumerator_set_asns(
6637+ struct loc_database_enumerator* enumerator, struct loc_as_list* asns) {
6638+ if (enumerator->asns)
6639+ loc_as_list_unref(enumerator->asns);
6640+
6641+ enumerator->asns = loc_as_list_ref(asns);
6642
6643 return 0;
6644 }
6645@@ -1123,6 +1135,12 @@ static int loc_network_match_countries(struct loc_network* network, struct loc_c
6646 return loc_country_list_contains_code(countries, country_code);
6647 }
6648
6649+static int loc_network_match_asns(struct loc_network* network, struct loc_as_list* asns) {
6650+ uint32_t asn = loc_network_get_asn(network);
6651+
6652+ return loc_as_list_contains_number(asns, asn);
6653+}
6654+
6655 static int loc_database_enumerator_filter_network(
6656 struct loc_database_enumerator* enumerator, struct loc_network* network) {
6657 // Skip if the family does not match
6658@@ -1134,8 +1152,7 @@ static int loc_database_enumerator_filter_network(
6659 return 1;
6660
6661 // Skip if the ASN does not match
6662- if (enumerator->asn &&
6663- !loc_network_match_asn(network, enumerator->asn))
6664+ if (enumerator->asns && !loc_network_match_asns(network, enumerator->asns))
6665 return 1;
6666
6667 // Skip if flags do not match
6668diff --git a/src/libloc.sym b/src/libloc.sym
6669index 40e9f88..53273cd 100644
6670--- a/src/libloc.sym
6671+++ b/src/libloc.sym
6672@@ -37,6 +37,18 @@ global:
6673 loc_as_set_name;
6674 loc_as_unref;
6675
6676+ # AS List
6677+ loc_as_list_append;
6678+ loc_as_list_clear;
6679+ loc_as_list_contains;
6680+ loc_as_list_contains_number;
6681+ loc_as_list_empty;
6682+ loc_as_list_get;
6683+ loc_as_list_new;
6684+ loc_as_list_ref;
6685+ loc_as_list_size;
6686+ loc_as_list_unref;
6687+
6688 # Country
6689 loc_country_cmp;
6690 loc_country_code_is_valid;
6691@@ -78,13 +90,14 @@ global:
6692 loc_database_verify;
6693
6694 # Database Enumerator
6695+ loc_database_enumerator_get_asns;
6696 loc_database_enumerator_get_countries;
6697 loc_database_enumerator_new;
6698 loc_database_enumerator_next_as;
6699 loc_database_enumerator_next_country;
6700 loc_database_enumerator_next_network;
6701 loc_database_enumerator_ref;
6702- loc_database_enumerator_set_asn;
6703+ loc_database_enumerator_set_asns;
6704 loc_database_enumerator_set_countries;
6705 loc_database_enumerator_set_family;
6706 loc_database_enumerator_set_flag;
6707diff --git a/src/loc/as-list.h b/src/loc/as-list.h
6708new file mode 100644
6709index 0000000..7b5c4e8
6710--- /dev/null
6711+++ b/src/loc/as-list.h
6712@@ -0,0 +1,41 @@
6713+/*
6714+ libloc - A library to determine the location of someone on the Internet
6715+
6716+ Copyright (C) 2017 IPFire Development Team <info@ipfire.org>
6717+
6718+ This library is free software; you can redistribute it and/or
6719+ modify it under the terms of the GNU Lesser General Public
6720+ License as published by the Free Software Foundation; either
6721+ version 2.1 of the License, or (at your option) any later version.
6722+
6723+ This library is distributed in the hope that it will be useful,
6724+ but WITHOUT ANY WARRANTY; without even the implied warranty of
6725+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
6726+ Lesser General Public License for more details.
6727+*/
6728+
6729+#ifndef LIBLOC_AS_LIST_H
6730+#define LIBLOC_AS_LIST_H
6731+
6732+#include <loc/as.h>
6733+#include <loc/libloc.h>
6734+
6735+struct loc_as_list;
6736+
6737+int loc_as_list_new(struct loc_ctx* ctx, struct loc_as_list** list);
6738+struct loc_as_list* loc_as_list_ref(struct loc_as_list* list);
6739+struct loc_as_list* loc_as_list_unref(struct loc_as_list* list);
6740+
6741+size_t loc_as_list_size(struct loc_as_list* list);
6742+int loc_as_list_empty(struct loc_as_list* list);
6743+void loc_as_list_clear(struct loc_as_list* list);
6744+
6745+struct loc_as* loc_as_list_get(struct loc_as_list* list, size_t index);
6746+int loc_as_list_append(struct loc_as_list* list, struct loc_as* as);
6747+
6748+int loc_as_list_contains(
6749+ struct loc_as_list* list, struct loc_as* as);
6750+int loc_as_list_contains_number(
6751+ struct loc_as_list* list, uint32_t number);
6752+
6753+#endif
6754diff --git a/src/loc/database.h b/src/loc/database.h
6755index 246e5c5..70801f0 100644
6756--- a/src/loc/database.h
6757+++ b/src/loc/database.h
6758@@ -70,7 +70,10 @@ int loc_database_enumerator_set_string(struct loc_database_enumerator* enumerato
6759 struct loc_country_list* loc_database_enumerator_get_countries(struct loc_database_enumerator* enumerator);
6760 int loc_database_enumerator_set_countries(
6761 struct loc_database_enumerator* enumerator, struct loc_country_list* countries);
6762-int loc_database_enumerator_set_asn(struct loc_database_enumerator* enumerator, unsigned int asn);
6763+struct loc_as_list* loc_database_enumerator_get_asns(
6764+ struct loc_database_enumerator* enumerator);
6765+int loc_database_enumerator_set_asns(
6766+ struct loc_database_enumerator* enumerator, struct loc_as_list* asns);
6767 int loc_database_enumerator_set_flag(struct loc_database_enumerator* enumerator, enum loc_network_flags flag);
6768 int loc_database_enumerator_set_family(struct loc_database_enumerator* enumerator, int family);
6769 int loc_database_enumerator_next_as(
6770diff --git a/src/python/database.c b/src/python/database.c
6771index e6f6f37..38a804c 100644
6772--- a/src/python/database.c
6773+++ b/src/python/database.c
6774@@ -17,6 +17,8 @@
6775 #include <Python.h>
6776
6777 #include <loc/libloc.h>
6778+#include <loc/as.h>
6779+#include <loc/as-list.h>
6780 #include <loc/database.h>
6781
6782 #include "locationmodule.h"
6783@@ -258,15 +260,15 @@ static PyObject* Database_networks_flattened(DatabaseObject *self) {
6784 }
6785
6786 static PyObject* Database_search_networks(DatabaseObject* self, PyObject* args, PyObject* kwargs) {
6787- char* kwlist[] = { "country_codes", "asn", "flags", "family", "flatten", NULL };
6788+ char* kwlist[] = { "country_codes", "asns", "flags", "family", "flatten", NULL };
6789 PyObject* country_codes = NULL;
6790- unsigned int asn = 0;
6791+ PyObject* asn_list = NULL;
6792 int flags = 0;
6793 int family = 0;
6794 int flatten = 0;
6795
6796- if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O!iiip", kwlist,
6797- &PyList_Type, &country_codes, &asn, &flags, &family, &flatten))
6798+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O!O!iip", kwlist,
6799+ &PyList_Type, &country_codes, &PyList_Type, &asn_list, &flags, &family, &flatten))
6800 return NULL;
6801
6802 struct loc_database_enumerator* enumerator;
6803@@ -330,13 +332,57 @@ static PyObject* Database_search_networks(DatabaseObject* self, PyObject* args,
6804 }
6805
6806 // Set the ASN we are searching for
6807- if (asn) {
6808- r = loc_database_enumerator_set_asn(enumerator, asn);
6809+ if (asn_list) {
6810+ struct loc_as_list* asns;
6811+ r = loc_as_list_new(loc_ctx, &asns);
6812+ if (r) {
6813+ PyErr_SetString(PyExc_SystemError, "Could not create AS list");
6814+ return NULL;
6815+ }
6816+
6817+ for (unsigned int i = 0; i < PyList_Size(asn_list); i++) {
6818+ PyObject* item = PyList_GetItem(asn_list, i);
6819+
6820+ if (!PyLong_Check(item)) {
6821+ PyErr_SetString(PyExc_TypeError, "ASNs must be numbers");
6822+
6823+ loc_as_list_unref(asns);
6824+ return NULL;
6825+ }
6826+
6827+ unsigned long number = PyLong_AsLong(item);
6828
6829+ struct loc_as* as;
6830+ r = loc_as_new(loc_ctx, &as, number);
6831+ if (r) {
6832+ PyErr_SetString(PyExc_SystemError, "Could not create AS");
6833+
6834+ loc_as_list_unref(asns);
6835+ loc_as_unref(as);
6836+ return NULL;
6837+ }
6838+
6839+ r = loc_as_list_append(asns, as);
6840+ if (r) {
6841+ PyErr_SetString(PyExc_SystemError, "Could not append AS to the list");
6842+
6843+ loc_as_list_unref(asns);
6844+ loc_as_unref(as);
6845+ return NULL;
6846+ }
6847+
6848+ loc_as_unref(as);
6849+ }
6850+
6851+ r = loc_database_enumerator_set_asns(enumerator, asns);
6852 if (r) {
6853 PyErr_SetFromErrno(PyExc_SystemError);
6854+
6855+ loc_as_list_unref(asns);
6856 return NULL;
6857 }
6858+
6859+ loc_as_list_unref(asns);
6860 }
6861
6862 // Set the flags we are searching for
6863diff --git a/src/python/export.py b/src/python/export.py
6864index 739742f..f675eb3 100644
6865--- a/src/python/export.py
6866+++ b/src/python/export.py
6867@@ -197,7 +197,7 @@ class Exporter(object):
6868
6869 # Get all networks that match the family
6870 networks = self.db.search_networks(family=family,
6871- country_codes=country_codes, flags=flags, flatten=True)
6872+ country_codes=country_codes, asns=asns, flags=flags, flatten=True)
6873
6874 # Walk through all networks
6875 for network in networks:
6876--
68772.20.1
6878
6879From 50120b991fc2fa4b7813096de87b42d700faf3e6 Mon Sep 17 00:00:00 2001
6880From: Michael Tremer <michael.tremer@ipfire.org>
6881Date: Tue, 17 Nov 2020 16:56:43 +0000
0be475ca 6882Subject: [PATCH 060/111] database: Simplify network matching code
05db64d0
MT
6883
6884Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
6885---
6886 src/database.c | 16 ++++++++--------
6887 1 file changed, 8 insertions(+), 8 deletions(-)
6888
6889diff --git a/src/database.c b/src/database.c
6890index 51cb5cd..1a354f6 100644
6891--- a/src/database.c
6892+++ b/src/database.c
6893@@ -1129,12 +1129,6 @@ static int loc_database_enumerator_stack_push_node(
6894 return 0;
6895 }
6896
6897-static int loc_network_match_countries(struct loc_network* network, struct loc_country_list* countries) {
6898- const char* country_code = loc_network_get_country_code(network);
6899-
6900- return loc_country_list_contains_code(countries, country_code);
6901-}
6902-
6903 static int loc_network_match_asns(struct loc_network* network, struct loc_as_list* asns) {
6904 uint32_t asn = loc_network_get_asn(network);
6905
6906@@ -1148,8 +1142,14 @@ static int loc_database_enumerator_filter_network(
6907 return 1;
6908
6909 // Skip if the country code does not match
6910- if (enumerator->countries && !loc_network_match_countries(network, enumerator->countries))
6911- return 1;
6912+ if (enumerator->countries) {
6913+ if (!loc_country_list_empty(enumerator->countries)) {
6914+ const char* country_code = loc_network_get_country_code(network);
6915+
6916+ if (!loc_country_list_contains_code(enumerator->countries, country_code))
6917+ return 1;
6918+ }
6919+ }
6920
6921 // Skip if the ASN does not match
6922 if (enumerator->asns && !loc_network_match_asns(network, enumerator->asns))
6923--
69242.20.1
6925
6926From c1a36c943181da5cd2aef589a972d5027e529eb8 Mon Sep 17 00:00:00 2001
6927From: Michael Tremer <michael.tremer@ipfire.org>
6928Date: Tue, 17 Nov 2020 16:58:55 +0000
0be475ca 6929Subject: [PATCH 061/111] database: Simplify AS matching code
05db64d0
MT
6930
6931Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
6932---
6933 src/database.c | 16 ++++++++--------
6934 1 file changed, 8 insertions(+), 8 deletions(-)
6935
6936diff --git a/src/database.c b/src/database.c
6937index 1a354f6..be93e00 100644
6938--- a/src/database.c
6939+++ b/src/database.c
6940@@ -1129,12 +1129,6 @@ static int loc_database_enumerator_stack_push_node(
6941 return 0;
6942 }
6943
6944-static int loc_network_match_asns(struct loc_network* network, struct loc_as_list* asns) {
6945- uint32_t asn = loc_network_get_asn(network);
6946-
6947- return loc_as_list_contains_number(asns, asn);
6948-}
6949-
6950 static int loc_database_enumerator_filter_network(
6951 struct loc_database_enumerator* enumerator, struct loc_network* network) {
6952 // Skip if the family does not match
6953@@ -1152,8 +1146,14 @@ static int loc_database_enumerator_filter_network(
6954 }
6955
6956 // Skip if the ASN does not match
6957- if (enumerator->asns && !loc_network_match_asns(network, enumerator->asns))
6958- return 1;
6959+ if (enumerator->asns) {
6960+ if (!loc_as_list_empty(enumerator->asns)) {
6961+ uint32_t asn = loc_network_get_asn(network);
6962+
6963+ if (!loc_as_list_contains_number(enumerator->asns, asn))
6964+ return 1;
6965+ }
6966+ }
6967
6968 // Skip if flags do not match
6969 if (enumerator->flags &&
6970--
69712.20.1
6972
6973From d5205091f9cc1ff987e483325d48696459df08d8 Mon Sep 17 00:00:00 2001
6974From: Michael Tremer <michael.tremer@ipfire.org>
6975Date: Tue, 17 Nov 2020 17:50:17 +0000
0be475ca 6976Subject: [PATCH 062/111] countries: Make list grow dynamically
05db64d0
MT
6977
6978Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
6979---
6980 src/country-list.c | 38 ++++++++++++++++++++++++++------------
6981 1 file changed, 26 insertions(+), 12 deletions(-)
6982
6983diff --git a/src/country-list.c b/src/country-list.c
6984index ae0d71a..1ce2d06 100644
6985--- a/src/country-list.c
6986+++ b/src/country-list.c
6987@@ -25,11 +25,27 @@ struct loc_country_list {
6988 struct loc_ctx* ctx;
6989 int refcount;
6990
6991- struct loc_country* list[1024];
6992+ struct loc_country** elements;
6993+ size_t elements_size;
6994+
6995 size_t size;
6996- size_t max_size;
6997 };
6998
6999+static int loc_country_list_grow(struct loc_country_list* list, size_t size) {
7000+ DEBUG(list->ctx, "Growing country list %p by %zu to %zu\n",
7001+ list, size, list->elements_size + size);
7002+
7003+ struct loc_country** elements = reallocarray(list->elements,
7004+ list->elements_size + size, sizeof(*list->elements));
7005+ if (!elements)
7006+ return -errno;
7007+
7008+ list->elements = elements;
7009+ list->elements_size += size;
7010+
7011+ return 0;
7012+}
7013+
7014 LOC_EXPORT int loc_country_list_new(struct loc_ctx* ctx,
7015 struct loc_country_list** list) {
7016 struct loc_country_list* l = calloc(1, sizeof(*l));
7017@@ -39,9 +55,6 @@ LOC_EXPORT int loc_country_list_new(struct loc_ctx* ctx,
7018 l->ctx = loc_ref(ctx);
7019 l->refcount = 1;
7020
7021- // Do not allow this list to grow larger than this
7022- l->max_size = 1024;
7023-
7024 DEBUG(l->ctx, "Country list allocated at %p\n", l);
7025 *list = l;
7026
7027@@ -84,7 +97,7 @@ LOC_EXPORT int loc_country_list_empty(struct loc_country_list* list) {
7028
7029 LOC_EXPORT void loc_country_list_clear(struct loc_country_list* list) {
7030 for (unsigned int i = 0; i < list->size; i++)
7031- loc_country_unref(list->list[i]);
7032+ loc_country_unref(list->elements[i]);
7033 }
7034
7035 LOC_EXPORT struct loc_country* loc_country_list_get(struct loc_country_list* list, size_t index) {
7036@@ -92,7 +105,7 @@ LOC_EXPORT struct loc_country* loc_country_list_get(struct loc_country_list* lis
7037 if (index >= list->size)
7038 return NULL;
7039
7040- return loc_country_ref(list->list[index]);
7041+ return loc_country_ref(list->elements[index]);
7042 }
7043
7044 LOC_EXPORT int loc_country_list_append(
7045@@ -101,14 +114,15 @@ LOC_EXPORT int loc_country_list_append(
7046 return 0;
7047
7048 // Check if we have space left
7049- if (list->size == list->max_size) {
7050- ERROR(list->ctx, "%p: Could not append country to the list. List full\n", list);
7051- return -ENOMEM;
7052+ if (list->size >= list->elements_size) {
7053+ int r = loc_country_list_grow(list, 64);
7054+ if (r)
7055+ return r;
7056 }
7057
7058 DEBUG(list->ctx, "%p: Appending country %p to list\n", list, country);
7059
7060- list->list[list->size++] = loc_country_ref(country);
7061+ list->elements[list->size++] = loc_country_ref(country);
7062
7063 return 0;
7064 }
7065@@ -116,7 +130,7 @@ LOC_EXPORT int loc_country_list_append(
7066 LOC_EXPORT int loc_country_list_contains(
7067 struct loc_country_list* list, struct loc_country* country) {
7068 for (unsigned int i = 0; i < list->size; i++) {
7069- if (loc_country_cmp(country, list->list[i]) == 0)
7070+ if (loc_country_cmp(country, list->elements[i]) == 0)
7071 return 1;
7072 }
7073
7074--
70752.20.1
7076
7077From 3b44e4211371d2103f89ba8f056b15edb7778fac Mon Sep 17 00:00:00 2001
7078From: Michael Tremer <michael.tremer@ipfire.org>
7079Date: Tue, 17 Nov 2020 17:55:51 +0000
0be475ca 7080Subject: [PATCH 063/111] networks: Make list grow dynamically
05db64d0
MT
7081
7082Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
7083---
7084 src/network-list.c | 60 ++++++++++++++++++++++++++++------------------
7085 1 file changed, 37 insertions(+), 23 deletions(-)
7086
7087diff --git a/src/network-list.c b/src/network-list.c
7088index 1f6e80e..4912c02 100644
7089--- a/src/network-list.c
7090+++ b/src/network-list.c
7091@@ -25,11 +25,27 @@ struct loc_network_list {
7092 struct loc_ctx* ctx;
7093 int refcount;
7094
7095- struct loc_network* list[1024];
7096+ struct loc_network** elements;
7097+ size_t elements_size;
7098+
7099 size_t size;
7100- size_t max_size;
7101 };
7102
7103+static int loc_network_list_grow(struct loc_network_list* list, size_t size) {
7104+ DEBUG(list->ctx, "Growing network list %p by %zu to %zu\n",
7105+ list, size, list->elements_size + size);
7106+
7107+ struct loc_network** elements = reallocarray(list->elements,
7108+ list->elements_size + size, sizeof(*list->elements));
7109+ if (!elements)
7110+ return -errno;
7111+
7112+ list->elements = elements;
7113+ list->elements_size += size;
7114+
7115+ return 0;
7116+}
7117+
7118 LOC_EXPORT int loc_network_list_new(struct loc_ctx* ctx,
7119 struct loc_network_list** list) {
7120 struct loc_network_list* l = calloc(1, sizeof(*l));
7121@@ -39,9 +55,6 @@ LOC_EXPORT int loc_network_list_new(struct loc_ctx* ctx,
7122 l->ctx = loc_ref(ctx);
7123 l->refcount = 1;
7124
7125- // Do not allow this list to grow larger than this
7126- l->max_size = 1024;
7127-
7128 DEBUG(l->ctx, "Network list allocated at %p\n", l);
7129 *list = l;
7130 return 0;
7131@@ -57,7 +70,7 @@ static void loc_network_list_free(struct loc_network_list* list) {
7132 DEBUG(list->ctx, "Releasing network list at %p\n", list);
7133
7134 for (unsigned int i = 0; i < list->size; i++)
7135- loc_network_unref(list->list[i]);
7136+ loc_network_unref(list->elements[i]);
7137
7138 loc_unref(list->ctx);
7139 free(list);
7140@@ -84,7 +97,7 @@ LOC_EXPORT int loc_network_list_empty(struct loc_network_list* list) {
7141
7142 LOC_EXPORT void loc_network_list_clear(struct loc_network_list* list) {
7143 for (unsigned int i = 0; i < list->size; i++)
7144- loc_network_unref(list->list[i]);
7145+ loc_network_unref(list->elements[i]);
7146
7147 list->size = 0;
7148 }
7149@@ -94,7 +107,7 @@ LOC_EXPORT void loc_network_list_dump(struct loc_network_list* list) {
7150 char* s;
7151
7152 for (unsigned int i = 0; i < list->size; i++) {
7153- network = list->list[i];
7154+ network = list->elements[i];
7155
7156 s = loc_network_str(network);
7157
7158@@ -108,7 +121,7 @@ LOC_EXPORT struct loc_network* loc_network_list_get(struct loc_network_list* lis
7159 if (index >= list->size)
7160 return NULL;
7161
7162- return loc_network_ref(list->list[index]);
7163+ return loc_network_ref(list->elements[index]);
7164 }
7165
7166 LOC_EXPORT int loc_network_list_push(struct loc_network_list* list, struct loc_network* network) {
7167@@ -117,14 +130,15 @@ LOC_EXPORT int loc_network_list_push(struct loc_network_list* list, struct loc_n
7168 return 0;
7169
7170 // Check if we have space left
7171- if (list->size == list->max_size) {
7172- ERROR(list->ctx, "%p: Could not push network onto the stack: Stack full\n", list);
7173- return -ENOMEM;
7174+ if (list->size >= list->elements_size) {
7175+ int r = loc_network_list_grow(list, 64);
7176+ if (r)
7177+ return r;
7178 }
7179
7180 DEBUG(list->ctx, "%p: Pushing network %p onto stack\n", list, network);
7181
7182- list->list[list->size++] = loc_network_ref(network);
7183+ list->elements[list->size++] = loc_network_ref(network);
7184
7185 return 0;
7186 }
7187@@ -136,7 +150,7 @@ LOC_EXPORT struct loc_network* loc_network_list_pop(struct loc_network_list* lis
7188 return NULL;
7189 }
7190
7191- struct loc_network* network = list->list[--list->size];
7192+ struct loc_network* network = list->elements[--list->size];
7193
7194 DEBUG(list->ctx, "%p: Popping network %p from stack\n", list, network);
7195
7196@@ -150,11 +164,11 @@ LOC_EXPORT struct loc_network* loc_network_list_pop_first(struct loc_network_lis
7197 return NULL;
7198 }
7199
7200- struct loc_network* network = list->list[0];
7201+ struct loc_network* network = list->elements[0];
7202
7203 // Move all elements to the top of the stack
7204 for (unsigned int i = 0; i < --list->size; i++) {
7205- list->list[i] = list->list[i+1];
7206+ list->elements[i] = list->elements[i+1];
7207 }
7208
7209 DEBUG(list->ctx, "%p: Popping network %p from stack\n", list, network);
7210@@ -164,7 +178,7 @@ LOC_EXPORT struct loc_network* loc_network_list_pop_first(struct loc_network_lis
7211
7212 LOC_EXPORT int loc_network_list_contains(struct loc_network_list* list, struct loc_network* network) {
7213 for (unsigned int i = 0; i < list->size; i++) {
7214- if (loc_network_eq(list->list[i], network))
7215+ if (loc_network_eq(list->elements[i], network))
7216 return 1;
7217 }
7218
7219@@ -176,11 +190,11 @@ static void loc_network_list_swap(struct loc_network_list* list, unsigned int i1
7220 if (i1 >= list->size || i2 >= list->size)
7221 return;
7222
7223- struct loc_network* network1 = list->list[i1];
7224- struct loc_network* network2 = list->list[i2];
7225+ struct loc_network* network1 = list->elements[i1];
7226+ struct loc_network* network2 = list->elements[i2];
7227
7228- list->list[i1] = network2;
7229- list->list[i2] = network1;
7230+ list->elements[i1] = network2;
7231+ list->elements[i2] = network1;
7232 }
7233
7234 LOC_EXPORT void loc_network_list_reverse(struct loc_network_list* list) {
7235@@ -200,7 +214,7 @@ LOC_EXPORT void loc_network_list_sort(struct loc_network_list* list) {
7236 swapped = 0;
7237
7238 for (unsigned int i = 1; i < n; i++) {
7239- if (loc_network_gt(list->list[i-1], list->list[i]) > 0) {
7240+ if (loc_network_gt(list->elements[i-1], list->elements[i]) > 0) {
7241 loc_network_list_swap(list, i-1, i);
7242 swapped = 1;
7243 }
7244@@ -215,7 +229,7 @@ LOC_EXPORT int loc_network_list_merge(
7245 int r;
7246
7247 for (unsigned int i = 0; i < other->size; i++) {
7248- r = loc_network_list_push(self, other->list[i]);
7249+ r = loc_network_list_push(self, other->elements[i]);
7250 if (r)
7251 return r;
7252 }
7253--
72542.20.1
7255
7256From 1a415f8c555f4fe9a68eb2a897c4a1fc0d33db25 Mon Sep 17 00:00:00 2001
7257From: Michael Tremer <michael.tremer@ipfire.org>
7258Date: Tue, 17 Nov 2020 17:57:55 +0000
0be475ca 7259Subject: [PATCH 064/111] as: Make lists grow dynamically
05db64d0
MT
7260
7261Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
7262---
7263 src/as-list.c | 38 ++++++++++++++++++++++++++------------
7264 1 file changed, 26 insertions(+), 12 deletions(-)
7265
7266diff --git a/src/as-list.c b/src/as-list.c
7267index 7c69eb0..17de23e 100644
7268--- a/src/as-list.c
7269+++ b/src/as-list.c
7270@@ -25,11 +25,27 @@ struct loc_as_list {
7271 struct loc_ctx* ctx;
7272 int refcount;
7273
7274- struct loc_as* list[1024];
7275+ struct loc_as** elements;
7276+ size_t elements_size;
7277+
7278 size_t size;
7279- size_t max_size;
7280 };
7281
7282+static int loc_as_list_grow(struct loc_as_list* list, size_t size) {
7283+ DEBUG(list->ctx, "Growing AS list %p by %zu to %zu\n",
7284+ list, size, list->elements_size + size);
7285+
7286+ struct loc_as** elements = reallocarray(list->elements,
7287+ list->elements_size + size, sizeof(*list->elements));
7288+ if (!elements)
7289+ return -errno;
7290+
7291+ list->elements = elements;
7292+ list->elements_size += size;
7293+
7294+ return 0;
7295+}
7296+
7297 LOC_EXPORT int loc_as_list_new(struct loc_ctx* ctx,
7298 struct loc_as_list** list) {
7299 struct loc_as_list* l = calloc(1, sizeof(*l));
7300@@ -39,9 +55,6 @@ LOC_EXPORT int loc_as_list_new(struct loc_ctx* ctx,
7301 l->ctx = loc_ref(ctx);
7302 l->refcount = 1;
7303
7304- // Do not allow this list to grow larger than this
7305- l->max_size = 1024;
7306-
7307 DEBUG(l->ctx, "AS list allocated at %p\n", l);
7308 *list = l;
7309
7310@@ -84,7 +97,7 @@ LOC_EXPORT int loc_as_list_empty(struct loc_as_list* list) {
7311
7312 LOC_EXPORT void loc_as_list_clear(struct loc_as_list* list) {
7313 for (unsigned int i = 0; i < list->size; i++)
7314- loc_as_unref(list->list[i]);
7315+ loc_as_unref(list->elements[i]);
7316 }
7317
7318 LOC_EXPORT struct loc_as* loc_as_list_get(struct loc_as_list* list, size_t index) {
7319@@ -92,7 +105,7 @@ LOC_EXPORT struct loc_as* loc_as_list_get(struct loc_as_list* list, size_t index
7320 if (index >= list->size)
7321 return NULL;
7322
7323- return loc_as_ref(list->list[index]);
7324+ return loc_as_ref(list->elements[index]);
7325 }
7326
7327 LOC_EXPORT int loc_as_list_append(
7328@@ -101,14 +114,15 @@ LOC_EXPORT int loc_as_list_append(
7329 return 0;
7330
7331 // Check if we have space left
7332- if (list->size == list->max_size) {
7333- ERROR(list->ctx, "%p: Could not append AS to the list. List full\n", list);
7334- return -ENOMEM;
7335+ if (list->size >= list->elements_size) {
7336+ int r = loc_as_list_grow(list, 64);
7337+ if (r)
7338+ return r;
7339 }
7340
7341 DEBUG(list->ctx, "%p: Appending AS %p to list\n", list, as);
7342
7343- list->list[list->size++] = loc_as_ref(as);
7344+ list->elements[list->size++] = loc_as_ref(as);
7345
7346 return 0;
7347 }
7348@@ -116,7 +130,7 @@ LOC_EXPORT int loc_as_list_append(
7349 LOC_EXPORT int loc_as_list_contains(
7350 struct loc_as_list* list, struct loc_as* as) {
7351 for (unsigned int i = 0; i < list->size; i++) {
7352- if (loc_as_cmp(as, list->list[i]) == 0)
7353+ if (loc_as_cmp(as, list->elements[i]) == 0)
7354 return 1;
7355 }
7356
7357--
73582.20.1
7359
7360From e6592434ee7836507c1f436ec3b0db3bc81a81b9 Mon Sep 17 00:00:00 2001
7361From: Michael Tremer <michael.tremer@ipfire.org>
7362Date: Tue, 17 Nov 2020 18:13:49 +0000
0be475ca 7363Subject: [PATCH 065/111] export: Change back to use Network objects
05db64d0
MT
7364
7365Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
7366---
7367 src/python/export.py | 4 +---
7368 1 file changed, 1 insertion(+), 3 deletions(-)
7369
7370diff --git a/src/python/export.py b/src/python/export.py
7371index f675eb3..67e437f 100644
7372--- a/src/python/export.py
7373+++ b/src/python/export.py
7374@@ -144,9 +144,7 @@ class XTGeoIPOutputWriter(OutputWriter):
7375 def _write_network(self, network):
7376 for address in (network.first_address, network.last_address):
7377 # Convert this into a string of bits
7378- bytes = socket.inet_pton(
7379- socket.AF_INET6 if network.version == 6 else socket.AF_INET, "%s" % address,
7380- )
7381+ bytes = socket.inet_pton(network.family, address)
7382
7383 self.f.write(bytes)
7384
7385--
73862.20.1
7387
7388From 248f5e0419f2349253b8ea96e477c15649fe2173 Mon Sep 17 00:00:00 2001
7389From: Michael Tremer <michael.tremer@ipfire.org>
7390Date: Tue, 17 Nov 2020 18:14:15 +0000
0be475ca 7391Subject: [PATCH 066/111] Actually clear all lists
05db64d0
MT
7392
7393Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
7394---
7395 src/as-list.c | 8 ++++++++
7396 src/country-list.c | 8 ++++++++
7397 src/network-list.c | 6 ++++++
7398 3 files changed, 22 insertions(+)
7399
7400diff --git a/src/as-list.c b/src/as-list.c
7401index 17de23e..76620c7 100644
7402--- a/src/as-list.c
7403+++ b/src/as-list.c
7404@@ -96,8 +96,16 @@ LOC_EXPORT int loc_as_list_empty(struct loc_as_list* list) {
7405 }
7406
7407 LOC_EXPORT void loc_as_list_clear(struct loc_as_list* list) {
7408+ if (!list->elements)
7409+ return;
7410+
7411 for (unsigned int i = 0; i < list->size; i++)
7412 loc_as_unref(list->elements[i]);
7413+
7414+ free(list->elements);
7415+ list->elements_size = 0;
7416+
7417+ list->size = 0;
7418 }
7419
7420 LOC_EXPORT struct loc_as* loc_as_list_get(struct loc_as_list* list, size_t index) {
7421diff --git a/src/country-list.c b/src/country-list.c
7422index 1ce2d06..1c49c47 100644
7423--- a/src/country-list.c
7424+++ b/src/country-list.c
7425@@ -96,8 +96,16 @@ LOC_EXPORT int loc_country_list_empty(struct loc_country_list* list) {
7426 }
7427
7428 LOC_EXPORT void loc_country_list_clear(struct loc_country_list* list) {
7429+ if (!list->elements)
7430+ return;
7431+
7432 for (unsigned int i = 0; i < list->size; i++)
7433 loc_country_unref(list->elements[i]);
7434+
7435+ free(list->elements);
7436+ list->elements_size = 0;
7437+
7438+ list->size = 0;
7439 }
7440
7441 LOC_EXPORT struct loc_country* loc_country_list_get(struct loc_country_list* list, size_t index) {
7442diff --git a/src/network-list.c b/src/network-list.c
7443index 4912c02..9cb4547 100644
7444--- a/src/network-list.c
7445+++ b/src/network-list.c
7446@@ -96,9 +96,15 @@ LOC_EXPORT int loc_network_list_empty(struct loc_network_list* list) {
7447 }
7448
7449 LOC_EXPORT void loc_network_list_clear(struct loc_network_list* list) {
7450+ if (!list->elements)
7451+ return;
7452+
7453 for (unsigned int i = 0; i < list->size; i++)
7454 loc_network_unref(list->elements[i]);
7455
7456+ free(list->elements);
7457+ list->elements_size = 0;
7458+
7459 list->size = 0;
7460 }
7461
7462--
74632.20.1
7464
7465From c98ebf8aae2aa141193db52cd9429b1ded5b09c4 Mon Sep 17 00:00:00 2001
7466From: Michael Tremer <michael.tremer@ipfire.org>
7467Date: Tue, 17 Nov 2020 18:34:51 +0000
0be475ca 7468Subject: [PATCH 067/111] database: Do not clean up python list
05db64d0
MT
7469
7470Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
7471---
7472 src/python/database.c | 9 +++++++--
7473 1 file changed, 7 insertions(+), 2 deletions(-)
7474
7475diff --git a/src/python/database.c b/src/python/database.c
7476index 38a804c..ed22275 100644
7477--- a/src/python/database.c
7478+++ b/src/python/database.c
7479@@ -325,9 +325,14 @@ static PyObject* Database_search_networks(DatabaseObject* self, PyObject* args,
7480 loc_country_unref(country);
7481 }
7482
7483- loc_database_enumerator_set_countries(enumerator, countries);
7484+ r = loc_database_enumerator_set_countries(enumerator, countries);
7485+ if (r) {
7486+ PyErr_SetFromErrno(PyExc_SystemError);
7487+
7488+ loc_as_list_unref(countries);
7489+ return NULL;
7490+ }
7491
7492- Py_DECREF(country_codes);
7493 loc_country_list_unref(countries);
7494 }
7495
7496--
74972.20.1
7498
7499From 5470d06cb59027f4e04b6d576763dbf7f1093fde Mon Sep 17 00:00:00 2001
7500From: Michael Tremer <michael.tremer@ipfire.org>
7501Date: Tue, 17 Nov 2020 19:01:04 +0000
0be475ca 7502Subject: [PATCH 068/111] database: Free filter lists in enumerator
05db64d0
MT
7503
7504Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
7505---
7506 src/database.c | 6 ++++++
7507 1 file changed, 6 insertions(+)
7508
7509diff --git a/src/database.c b/src/database.c
7510index be93e00..ca35fe1 100644
7511--- a/src/database.c
7512+++ b/src/database.c
7513@@ -950,6 +950,12 @@ static void loc_database_enumerator_free(struct loc_database_enumerator* enumera
7514 if (enumerator->string)
7515 free(enumerator->string);
7516
7517+ if (enumerator->countries)
7518+ loc_country_list_unref(enumerator->countries);
7519+
7520+ if (enumerator->asns)
7521+ loc_as_list_unref(enumerator->asns);
7522+
7523 // Free network search
7524 free(enumerator->networks_visited);
7525
7526--
75272.20.1
7528
7529From e0e96878d3df51c4a265d51d088005dedf9335e3 Mon Sep 17 00:00:00 2001
7530From: Michael Tremer <michael.tremer@ipfire.org>
7531Date: Wed, 18 Nov 2020 13:18:52 +0000
0be475ca 7532Subject: [PATCH 069/111] database: Add debug output to filtering
05db64d0
MT
7533
7534Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
7535---
7536 src/database.c | 29 ++++++++++++++++-------------
7537 1 file changed, 16 insertions(+), 13 deletions(-)
7538
7539diff --git a/src/database.c b/src/database.c
7540index ca35fe1..83dd752 100644
7541--- a/src/database.c
7542+++ b/src/database.c
7543@@ -1138,33 +1138,36 @@ static int loc_database_enumerator_stack_push_node(
7544 static int loc_database_enumerator_filter_network(
7545 struct loc_database_enumerator* enumerator, struct loc_network* network) {
7546 // Skip if the family does not match
7547- if (enumerator->family && loc_network_address_family(network) != enumerator->family)
7548+ if (enumerator->family && loc_network_address_family(network) != enumerator->family) {
7549+ DEBUG(enumerator->ctx, "Filtered network %p because of family not matching\n", network);
7550 return 1;
7551+ }
7552
7553 // Skip if the country code does not match
7554- if (enumerator->countries) {
7555- if (!loc_country_list_empty(enumerator->countries)) {
7556- const char* country_code = loc_network_get_country_code(network);
7557+ if (enumerator->countries && !loc_country_list_empty(enumerator->countries)) {
7558+ const char* country_code = loc_network_get_country_code(network);
7559
7560- if (!loc_country_list_contains_code(enumerator->countries, country_code))
7561- return 1;
7562+ if (!loc_country_list_contains_code(enumerator->countries, country_code)) {
7563+ DEBUG(enumerator->ctx, "Filtered network %p because of country code not matching\n", network);
7564+ return 1;
7565 }
7566 }
7567
7568 // Skip if the ASN does not match
7569- if (enumerator->asns) {
7570- if (!loc_as_list_empty(enumerator->asns)) {
7571- uint32_t asn = loc_network_get_asn(network);
7572+ if (enumerator->asns && !loc_as_list_empty(enumerator->asns)) {
7573+ uint32_t asn = loc_network_get_asn(network);
7574
7575- if (!loc_as_list_contains_number(enumerator->asns, asn))
7576- return 1;
7577+ if (!loc_as_list_contains_number(enumerator->asns, asn)) {
7578+ DEBUG(enumerator->ctx, "Filtered network %p because of ASN not matching\n", network);
7579+ return 1;
7580 }
7581 }
7582
7583 // Skip if flags do not match
7584- if (enumerator->flags &&
7585- !loc_network_match_flag(network, enumerator->flags))
7586+ if (enumerator->flags && !loc_network_match_flag(network, enumerator->flags)) {
7587+ DEBUG(enumerator->ctx, "Filtered network %p because of flags not matching\n", network);
7588 return 1;
7589+ }
7590
7591 // Do not filter
7592 return 0;
7593--
75942.20.1
7595
7596From bce0c9295ff8ff9488f24babe01ce851228d0b1e Mon Sep 17 00:00:00 2001
7597From: Michael Tremer <michael.tremer@ipfire.org>
7598Date: Wed, 18 Nov 2020 13:19:04 +0000
0be475ca 7599Subject: [PATCH 070/111] export: Remove filtering for flags
05db64d0
MT
7600
7601The filter is an AND filter and if we set the flags from
7602the special country codes, we won't get back much.
7603
7604Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
7605---
7606 src/python/export.py | 8 +-------
7607 1 file changed, 1 insertion(+), 7 deletions(-)
7608
7609diff --git a/src/python/export.py b/src/python/export.py
7610index 67e437f..4219957 100644
7611--- a/src/python/export.py
7612+++ b/src/python/export.py
7613@@ -187,15 +187,9 @@ class Exporter(object):
7614 country_code for country_code in countries if not country_code in FLAGS.values()
7615 ]
7616
7617- # Collect flags
7618- flags = 0
7619- for flag in FLAGS:
7620- if FLAGS[flag] in countries:
7621- flags |= flag
7622-
7623 # Get all networks that match the family
7624 networks = self.db.search_networks(family=family,
7625- country_codes=country_codes, asns=asns, flags=flags, flatten=True)
7626+ country_codes=country_codes, asns=asns, flatten=True)
7627
7628 # Walk through all networks
7629 for network in networks:
7630--
76312.20.1
7632
78a6918d
MT
7633From 627bf1daaae1510cfd4016297ed16b82df209aae Mon Sep 17 00:00:00 2001
7634From: Michael Tremer <michael.tremer@ipfire.org>
7635Date: Wed, 18 Nov 2020 13:33:45 +0000
0be475ca 7636Subject: [PATCH 071/111] python: Remove unnecessary db object from writers
78a6918d
MT
7637
7638Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
7639---
7640 src/python/export.py | 12 ++++++------
7641 1 file changed, 6 insertions(+), 6 deletions(-)
7642
7643diff --git a/src/python/export.py b/src/python/export.py
7644index 4219957..5bc9f30 100644
7645--- a/src/python/export.py
7646+++ b/src/python/export.py
7647@@ -39,8 +39,8 @@ class OutputWriter(object):
7648 suffix = "networks"
7649 mode = "w"
7650
7651- def __init__(self, db, f, prefix=None, flatten=True):
7652- self.db, self.f, self.prefix, self.flatten = db, f, prefix, flatten
7653+ def __init__(self, f, prefix=None, flatten=True):
7654+ self.f, self.prefix, self.flatten = f, prefix, flatten
7655
7656 # The previously written network
7657 self._last_network = None
7658@@ -49,13 +49,13 @@ class OutputWriter(object):
7659 self._write_header()
7660
7661 @classmethod
7662- def open(cls, db, filename, **kwargs):
7663+ def open(cls, filename, **kwargs):
7664 """
7665 Convenience function to open a file
7666 """
7667 f = open(filename, cls.mode)
7668
7669- return cls(db, f, **kwargs)
7670+ return cls(f, **kwargs)
7671
7672 def __repr__(self):
7673 return "<%s f=%s>" % (self.__class__.__name__, self.f)
7674@@ -172,7 +172,7 @@ class Exporter(object):
7675 directory, prefix=country_code, suffix=self.writer.suffix, family=family,
7676 )
7677
7678- writers[country_code] = self.writer.open(self.db, filename, prefix="CC_%s" % country_code)
7679+ writers[country_code] = self.writer.open(filename, prefix="CC_%s" % country_code)
7680
7681 # Create writers for ASNs
7682 for asn in asns:
7683@@ -180,7 +180,7 @@ class Exporter(object):
7684 directory, "AS%s" % asn, suffix=self.writer.suffix, family=family,
7685 )
7686
7687- writers[asn] = self.writer.open(self.db, filename, prefix="AS%s" % asn)
7688+ writers[asn] = self.writer.open(filename, prefix="AS%s" % asn)
7689
7690 # Filter countries from special country codes
7691 country_codes = [
7692--
76932.20.1
7694
7695From 9cb56ac9adafafa6e452009c2fa2d42e94474e11 Mon Sep 17 00:00:00 2001
7696From: Michael Tremer <michael.tremer@ipfire.org>
7697Date: Wed, 18 Nov 2020 13:34:50 +0000
0be475ca 7698Subject: [PATCH 072/111] location: End lookup after an invalid IP address was
78a6918d
MT
7699 passed
7700
7701Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
7702---
7703 src/python/location.in | 1 +
7704 1 file changed, 1 insertion(+)
7705
7706diff --git a/src/python/location.in b/src/python/location.in
7707index 0d09210..6885ea0 100644
7708--- a/src/python/location.in
7709+++ b/src/python/location.in
7710@@ -253,6 +253,7 @@ class CLI(object):
7711 network = db.lookup(address)
7712 except ValueError:
7713 print(_("Invalid IP address: %s") % address, file=sys.stderr)
7714+ return 2
7715
7716 args = {
7717 "address" : address,
7718--
77192.20.1
7720
7721From 2a550d12208f8bc8002e05ac08613312df26b20e Mon Sep 17 00:00:00 2001
7722From: Michael Tremer <michael.tremer@ipfire.org>
7723Date: Thu, 19 Nov 2020 12:03:33 +0000
0be475ca 7724Subject: [PATCH 073/111] python: Fix download of database
78a6918d
MT
7725
7726This was all messed up in 0c74f6b1a3bdce5ebdc2ee452b9baf3e421dd3d1
7727when the change of type for the timestamp wasn't changed everywhere
7728else.
7729
7730Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
7731---
7732 src/python/downloader.py | 6 +++---
7733 src/python/location.in | 2 +-
7734 2 files changed, 4 insertions(+), 4 deletions(-)
7735
7736diff --git a/src/python/downloader.py b/src/python/downloader.py
7737index 87bbb68..05f7872 100644
7738--- a/src/python/downloader.py
7739+++ b/src/python/downloader.py
7740@@ -119,8 +119,8 @@ class Downloader(object):
7741
7742 headers = {}
7743 if timestamp:
7744- headers["If-Modified-Since"] = timestamp.strftime(
7745- "%a, %d %b %Y %H:%M:%S GMT",
7746+ headers["If-Modified-Since"] = time.strftime(
7747+ "%a, %d %b %Y %H:%M:%S GMT", time.gmtime(timestamp),
7748 )
7749
7750 t = tempfile.NamedTemporaryFile(dir=tmpdir, delete=False)
7751@@ -195,7 +195,7 @@ class Downloader(object):
7752 db = Database(f.name)
7753
7754 # Database is not recent
7755- if timestamp and db.created_at < timestamp.timestamp():
7756+ if timestamp and db.created_at < timestamp:
7757 return False
7758
7759 log.info("Downloaded new database from %s" % (time.strftime(
7760diff --git a/src/python/location.in b/src/python/location.in
7761index 6885ea0..b30beae 100644
7762--- a/src/python/location.in
7763+++ b/src/python/location.in
7764@@ -433,7 +433,7 @@ class CLI(object):
7765
7766 # Try downloading a new database
7767 try:
7768- t = d.download(public_key=ns.public_key, timestamp=timestamp, tmpdir=tmpdir)
7769+ t = d.download(public_key=ns.public_key, timestamp=t, tmpdir=tmpdir)
7770
7771 # If no file could be downloaded, log a message
7772 except FileNotFoundError as e:
7773--
77742.20.1
7775
7776From a1a00053300cff3c0f690d52377c76c83c2a08b2 Mon Sep 17 00:00:00 2001
7777From: Michael Tremer <michael.tremer@ipfire.org>
7778Date: Thu, 19 Nov 2020 12:34:11 +0000
0be475ca 7779Subject: [PATCH 074/111] python: Add property to return IP addresses as bytes
78a6918d
MT
7780
7781This avoids calling inet_pton to parse IP addresses from string
7782
7783Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
7784---
7785 src/libloc.sym | 2 ++
7786 src/loc/network.h | 2 ++
7787 src/network.c | 8 ++++++++
7788 src/python/database.c | 2 +-
7789 src/python/export.py | 7 ++-----
7790 src/python/network.c | 40 ++++++++++++++++++++++++++++++++++++++++
7791 6 files changed, 55 insertions(+), 6 deletions(-)
7792
7793diff --git a/src/libloc.sym b/src/libloc.sym
7794index 53273cd..406dd15 100644
7795--- a/src/libloc.sym
7796+++ b/src/libloc.sym
7797@@ -113,6 +113,8 @@ global:
7798 loc_network_format_last_address;
7799 loc_network_get_asn;
7800 loc_network_get_country_code;
7801+ loc_network_get_first_address;
7802+ loc_network_get_last_address;
7803 loc_network_gt;
7804 loc_network_has_flag;
7805 loc_network_is_subnet;
7806diff --git a/src/loc/network.h b/src/loc/network.h
7807index d86b685..4b7410c 100644
7808--- a/src/loc/network.h
7809+++ b/src/loc/network.h
7810@@ -39,7 +39,9 @@ struct loc_network* loc_network_unref(struct loc_network* network);
7811 char* loc_network_str(struct loc_network* network);
7812 int loc_network_address_family(struct loc_network* network);
7813
7814+const struct in6_addr* loc_network_get_first_address(struct loc_network* network);
7815 char* loc_network_format_first_address(struct loc_network* network);
7816+const struct in6_addr* loc_network_get_last_address(struct loc_network* network);
7817 char* loc_network_format_last_address(struct loc_network* network);
7818 int loc_network_match_address(struct loc_network* network, const struct in6_addr* address);
7819
7820diff --git a/src/network.c b/src/network.c
7821index 28ca2df..4c8787a 100644
7822--- a/src/network.c
7823+++ b/src/network.c
7824@@ -343,10 +343,18 @@ static char* loc_network_format_address(struct loc_network* network, const struc
7825 return string;
7826 }
7827
7828+LOC_EXPORT const struct in6_addr* loc_network_get_first_address(struct loc_network* network) {
7829+ return &network->first_address;
7830+}
7831+
7832 LOC_EXPORT char* loc_network_format_first_address(struct loc_network* network) {
7833 return loc_network_format_address(network, &network->first_address);
7834 }
7835
7836+LOC_EXPORT const struct in6_addr* loc_network_get_last_address(struct loc_network* network) {
7837+ return &network->last_address;
7838+}
7839+
7840 LOC_EXPORT char* loc_network_format_last_address(struct loc_network* network) {
7841 return loc_network_format_address(network, &network->last_address);
7842 }
7843diff --git a/src/python/database.c b/src/python/database.c
7844index ed22275..f385c61 100644
7845--- a/src/python/database.c
7846+++ b/src/python/database.c
7847@@ -329,7 +329,7 @@ static PyObject* Database_search_networks(DatabaseObject* self, PyObject* args,
7848 if (r) {
7849 PyErr_SetFromErrno(PyExc_SystemError);
7850
7851- loc_as_list_unref(countries);
7852+ loc_country_list_unref(countries);
7853 return NULL;
7854 }
7855
7856diff --git a/src/python/export.py b/src/python/export.py
7857index 5bc9f30..6b39878 100644
7858--- a/src/python/export.py
7859+++ b/src/python/export.py
7860@@ -142,11 +142,8 @@ class XTGeoIPOutputWriter(OutputWriter):
7861 mode = "wb"
7862
7863 def _write_network(self, network):
7864- for address in (network.first_address, network.last_address):
7865- # Convert this into a string of bits
7866- bytes = socket.inet_pton(network.family, address)
7867-
7868- self.f.write(bytes)
7869+ for address in (network._first_address, network._last_address):
7870+ self.f.write(address)
7871
7872
7873 formats = {
7874diff --git a/src/python/network.c b/src/python/network.c
7875index ed91d65..742b472 100644
7876--- a/src/python/network.c
7877+++ b/src/python/network.c
7878@@ -215,6 +215,26 @@ static PyObject* Network_get_first_address(NetworkObject* self) {
7879 return obj;
7880 }
7881
7882+static PyObject* PyBytes_FromAddress(const struct in6_addr* address6) {
7883+ struct in_addr address4;
7884+
7885+ // Convert IPv4 addresses to struct in_addr
7886+ if (IN6_IS_ADDR_V4MAPPED(address6)) {
7887+ address4.s_addr = address6->s6_addr32[3];
7888+
7889+ return PyBytes_FromStringAndSize((const char*)&address4, sizeof(address4));
7890+ }
7891+
7892+ // Return IPv6 addresses as they are
7893+ return PyBytes_FromStringAndSize((const char*)address6, sizeof(*address6));
7894+}
7895+
7896+static PyObject* Network_get__first_address(NetworkObject* self) {
7897+ const struct in6_addr* address = loc_network_get_first_address(self->network);
7898+
7899+ return PyBytes_FromAddress(address);
7900+}
7901+
7902 static PyObject* Network_get_last_address(NetworkObject* self) {
7903 char* address = loc_network_format_last_address(self->network);
7904
7905@@ -224,6 +244,12 @@ static PyObject* Network_get_last_address(NetworkObject* self) {
7906 return obj;
7907 }
7908
7909+static PyObject* Network_get__last_address(NetworkObject* self) {
7910+ const struct in6_addr* address = loc_network_get_last_address(self->network);
7911+
7912+ return PyBytes_FromAddress(address);
7913+}
7914+
7915 static struct PyMethodDef Network_methods[] = {
7916 {
7917 "exclude",
7918@@ -281,6 +307,13 @@ static struct PyGetSetDef Network_getsetters[] = {
7919 NULL,
7920 NULL,
7921 },
7922+ {
7923+ "_first_address",
7924+ (getter)Network_get__first_address,
7925+ NULL,
7926+ NULL,
7927+ NULL,
7928+ },
7929 {
7930 "last_address",
7931 (getter)Network_get_last_address,
7932@@ -288,6 +321,13 @@ static struct PyGetSetDef Network_getsetters[] = {
7933 NULL,
7934 NULL,
7935 },
7936+ {
7937+ "_last_address",
7938+ (getter)Network_get__last_address,
7939+ NULL,
7940+ NULL,
7941+ NULL,
7942+ },
7943 { NULL },
7944 };
7945
7946--
79472.20.1
7948
7949From 90d2194a876c223f9124ce9e27bdee6a6b49ff6a Mon Sep 17 00:00:00 2001
7950From: Michael Tremer <michael.tremer@ipfire.org>
7951Date: Thu, 19 Nov 2020 12:40:01 +0000
0be475ca 7952Subject: [PATCH 075/111] export: Remove old flattening feature
78a6918d
MT
7953
7954The database enumerator now only returns networks that will
7955never overlap.
7956
7957Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
7958---
7959 src/python/export.py | 34 ++++++----------------------------
7960 1 file changed, 6 insertions(+), 28 deletions(-)
7961
7962diff --git a/src/python/export.py b/src/python/export.py
7963index 6b39878..4702bcf 100644
7964--- a/src/python/export.py
7965+++ b/src/python/export.py
7966@@ -39,11 +39,8 @@ class OutputWriter(object):
7967 suffix = "networks"
7968 mode = "w"
7969
7970- def __init__(self, f, prefix=None, flatten=True):
7971- self.f, self.prefix, self.flatten = f, prefix, flatten
7972-
7973- # The previously written network
7974- self._last_network = None
7975+ def __init__(self, f, prefix=None):
7976+ self.f, self.prefix = f, prefix
7977
7978 # Immediately write the header
7979 self._write_header()
7980@@ -60,18 +57,6 @@ class OutputWriter(object):
7981 def __repr__(self):
7982 return "<%s f=%s>" % (self.__class__.__name__, self.f)
7983
7984- def _flatten(self, network):
7985- """
7986- Checks if the given network needs to be written to file,
7987- or if it is a subnet of the previously written network.
7988- """
7989- if self._last_network and network.is_subnet_of(self._last_network):
7990- return True
7991-
7992- # Remember this network for the next call
7993- self._last_network = network
7994- return False
7995-
7996 def _write_header(self):
7997 """
7998 The header of the file
7999@@ -84,15 +69,8 @@ class OutputWriter(object):
8000 """
8001 pass
8002
8003- def _write_network(self, network):
8004- self.f.write("%s\n" % network)
8005-
8006 def write(self, network):
8007- if self.flatten and self._flatten(network):
8008- log.debug("Skipping writing network %s (last one was %s)" % (network, self._last_network))
8009- return
8010-
8011- return self._write_network(network)
8012+ self.f.write("%s\n" % network)
8013
8014 def finish(self):
8015 """
8016@@ -113,7 +91,7 @@ class IpsetOutputWriter(OutputWriter):
8017 def _write_header(self):
8018 self.f.write("create %s hash:net family inet hashsize 1024 maxelem 65536\n" % self.prefix)
8019
8020- def _write_network(self, network):
8021+ def write(self, network):
8022 self.f.write("add %s %s\n" % (self.prefix, network))
8023
8024
8025@@ -129,7 +107,7 @@ class NftablesOutputWriter(OutputWriter):
8026 def _write_footer(self):
8027 self.f.write("}\n")
8028
8029- def _write_network(self, network):
8030+ def write(self, network):
8031 self.f.write(" %s,\n" % network)
8032
8033
8034@@ -141,7 +119,7 @@ class XTGeoIPOutputWriter(OutputWriter):
8035 suffix = "iv"
8036 mode = "wb"
8037
8038- def _write_network(self, network):
8039+ def write(self, network):
8040 for address in (network._first_address, network._last_address):
8041 self.f.write(address)
8042
8043--
80442.20.1
8045
8046From 90188dad86223380b0854b523b63ec024117c5f2 Mon Sep 17 00:00:00 2001
8047From: Michael Tremer <michael.tremer@ipfire.org>
8048Date: Thu, 19 Nov 2020 12:41:19 +0000
0be475ca 8049Subject: [PATCH 076/111] export: Speed-up export in xt_geoip format
78a6918d
MT
8050
8051Removing the loop avoids creating a tuple and then iterating over it
8052
8053Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
8054---
8055 src/python/export.py | 4 ++--
8056 1 file changed, 2 insertions(+), 2 deletions(-)
8057
8058diff --git a/src/python/export.py b/src/python/export.py
8059index 4702bcf..f0eae26 100644
8060--- a/src/python/export.py
8061+++ b/src/python/export.py
8062@@ -120,8 +120,8 @@ class XTGeoIPOutputWriter(OutputWriter):
8063 mode = "wb"
8064
8065 def write(self, network):
8066- for address in (network._first_address, network._last_address):
8067- self.f.write(address)
8068+ self.f.write(network._first_address)
8069+ self.f.write(network._last_address)
8070
8071
8072 formats = {
8073--
80742.20.1
8075
8076From 6661692f3bc8f788af8b75ae25561f4cc4a2acb5 Mon Sep 17 00:00:00 2001
8077From: Michael Tremer <michael.tremer@ipfire.org>
8078Date: Thu, 19 Nov 2020 12:48:46 +0000
0be475ca
MT
8079Subject: [PATCH 077/111] database: Disable some useless code when not running
8080 in debug mode
78a6918d
MT
8081
8082Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
8083---
8084 src/database.c | 16 +++++++++++++++-
8085 1 file changed, 15 insertions(+), 1 deletion(-)
8086
8087diff --git a/src/database.c b/src/database.c
8088index 83dd752..ef4f505 100644
8089--- a/src/database.c
8090+++ b/src/database.c
8091@@ -619,7 +619,7 @@ LOC_EXPORT int loc_database_verify(struct loc_database* db, FILE* f) {
8092 }
8093
8094 clock_t end = clock();
8095- DEBUG(db->ctx, "Signature checked in %.4fms\n",
8096+ INFO(db->ctx, "Signature checked in %.4fms\n",
8097 (double)(end - start) / CLOCKS_PER_SEC * 1000);
8098
8099 CLEANUP:
8100@@ -679,8 +679,10 @@ LOC_EXPORT int loc_database_get_as(struct loc_database* db, struct loc_as** as,
8101 off_t lo = 0;
8102 off_t hi = db->as_count - 1;
8103
8104+#ifdef ENABLE_DEBUG
8105 // Save start time
8106 clock_t start = clock();
8107+#endif
8108
8109 while (lo <= hi) {
8110 off_t i = (lo + hi) / 2;
8111@@ -693,11 +695,13 @@ LOC_EXPORT int loc_database_get_as(struct loc_database* db, struct loc_as** as,
8112 // Check if this is a match
8113 uint32_t as_number = loc_as_get_number(*as);
8114 if (as_number == number) {
8115+#ifdef ENABLE_DEBUG
8116 clock_t end = clock();
8117
8118 // Log how fast this has been
8119 DEBUG(db->ctx, "Found AS%u in %.4fms\n", as_number,
8120 (double)(end - start) / CLOCKS_PER_SEC * 1000);
8121+#endif
8122
8123 return 0;
8124 }
8125@@ -741,11 +745,13 @@ static int loc_database_fetch_network(struct loc_database* db, struct loc_networ
8126 return -1;
8127 }
8128
8129+#ifdef ENABLE_DEBUG
8130 if (r == 0) {
8131 char* string = loc_network_str(*network);
8132 DEBUG(db->ctx, "Got network %s\n", string);
8133 free(string);
8134 }
8135+#endif
8136
8137 return r;
8138 }
8139@@ -840,17 +846,21 @@ LOC_EXPORT int loc_database_lookup(struct loc_database* db,
8140
8141 *network = NULL;
8142
8143+#ifdef ENABLE_DEBUG
8144 // Save start time
8145 clock_t start = clock();
8146+#endif
8147
8148 int r = __loc_database_lookup(db, address, network, &network_address,
8149 db->network_nodes_v1, 0);
8150
8151+#ifdef ENABLE_DEBUG
8152 clock_t end = clock();
8153
8154 // Log how fast this has been
8155 DEBUG(db->ctx, "Executed network search in %.4fms\n",
8156 (double)(end - start) / CLOCKS_PER_SEC * 1000);
8157+#endif
8158
8159 return r;
8160 }
8161@@ -897,8 +907,10 @@ LOC_EXPORT int loc_database_get_country(struct loc_database* db,
8162 off_t lo = 0;
8163 off_t hi = db->countries_count - 1;
8164
8165+#ifdef ENABLE_DEBUG
8166 // Save start time
8167 clock_t start = clock();
8168+#endif
8169
8170 while (lo <= hi) {
8171 off_t i = (lo + hi) / 2;
8172@@ -913,11 +925,13 @@ LOC_EXPORT int loc_database_get_country(struct loc_database* db,
8173 int result = strcmp(code, cc);
8174
8175 if (result == 0) {
8176+#ifdef ENABLE_DEBUG
8177 clock_t end = clock();
8178
8179 // Log how fast this has been
8180 DEBUG(db->ctx, "Found country %s in %.4fms\n", cc,
8181 (double)(end - start) / CLOCKS_PER_SEC * 1000);
8182+#endif
8183
8184 return 0;
8185 }
8186--
81872.20.1
8188
0be475ca
MT
8189From a17c353bce55a9f38f67b4b7d2425194cfa208e7 Mon Sep 17 00:00:00 2001
8190From: Michael Tremer <michael.tremer@ipfire.org>
8191Date: Fri, 20 Nov 2020 14:43:31 +0000
8192Subject: [PATCH 078/111] test: Add tests to network-lists
8193
8194Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
8195---
8196 Makefile.am | 10 ++++
8197 src/.gitignore | 1 +
8198 src/test-network-list.c | 126 ++++++++++++++++++++++++++++++++++++++++
8199 3 files changed, 137 insertions(+)
8200 create mode 100644 src/test-network-list.c
8201
8202diff --git a/Makefile.am b/Makefile.am
8203index d0cc793..ebd7e17 100644
8204--- a/Makefile.am
8205+++ b/Makefile.am
8206@@ -318,6 +318,7 @@ check_PROGRAMS = \
8207 src/test-database \
8208 src/test-as \
8209 src/test-network \
8210+ src/test-network-list \
8211 src/test-country \
8212 src/test-signature
8213
8214@@ -357,6 +358,15 @@ src_test_network_CFLAGS = \
8215 src_test_network_LDADD = \
8216 src/libloc.la
8217
8218+src_test_network_list_SOURCES = \
8219+ src/test-network-list.c
8220+
8221+src_test_network_list_CFLAGS = \
8222+ $(TESTS_CFLAGS)
8223+
8224+src_test_network_list_LDADD = \
8225+ src/libloc.la
8226+
8227 src_test_stringpool_SOURCES = \
8228 src/test-stringpool.c
8229
8230diff --git a/src/.gitignore b/src/.gitignore
8231index caf80b5..3ccbdb8 100644
8232--- a/src/.gitignore
8233+++ b/src/.gitignore
8234@@ -10,5 +10,6 @@ test-libloc
8235 test-database
8236 test-country
8237 test-network
8238+test-network-list
8239 test-signature
8240 test-stringpool
8241diff --git a/src/test-network-list.c b/src/test-network-list.c
8242new file mode 100644
8243index 0000000..3061d63
8244--- /dev/null
8245+++ b/src/test-network-list.c
8246@@ -0,0 +1,126 @@
8247+/*
8248+ libloc - A library to determine the location of someone on the Internet
8249+
8250+ Copyright (C) 2017 IPFire Development Team <info@ipfire.org>
8251+
8252+ This program is free software; you can redistribute it and/or modify
8253+ it under the terms of the GNU General Public License as published by
8254+ the Free Software Foundation; either version 2 of the License, or
8255+ (at your option) any later version.
8256+
8257+ This program is distributed in the hope that it will be useful,
8258+ but WITHOUT ANY WARRANTY; without even the implied warranty of
8259+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
8260+ GNU General Public License for more details.
8261+*/
8262+
8263+#include <errno.h>
8264+#include <stdio.h>
8265+#include <stddef.h>
8266+#include <stdlib.h>
8267+#include <string.h>
8268+#include <syslog.h>
8269+
8270+#include <loc/libloc.h>
8271+#include <loc/network.h>
8272+#include <loc/network-list.h>
8273+
8274+int main(int argc, char** argv) {
8275+ int err;
8276+
8277+ struct loc_ctx* ctx;
8278+ err = loc_new(&ctx);
8279+ if (err < 0)
8280+ exit(EXIT_FAILURE);
8281+
8282+ // Enable debug logging
8283+ loc_set_log_priority(ctx, LOG_DEBUG);
8284+
8285+ // Create a network
8286+ struct loc_network* network1;
8287+ err = loc_network_new_from_string(ctx, &network1, "2001:db8::/32");
8288+ if (err) {
8289+ fprintf(stderr, "Could not create the network1\n");
8290+ exit(EXIT_FAILURE);
8291+ }
8292+
8293+ struct loc_network* subnet1;
8294+ err = loc_network_new_from_string(ctx, &subnet1, "2001:db8:a::/48");
8295+ if (err) {
8296+ fprintf(stderr, "Could not create the subnet1\n");
8297+ exit(EXIT_FAILURE);
8298+ }
8299+
8300+ struct loc_network* subnet2;
8301+ err = loc_network_new_from_string(ctx, &subnet2, "2001:db8:b::/48");
8302+ if (err) {
8303+ fprintf(stderr, "Could not create the subnet2\n");
8304+ exit(EXIT_FAILURE);
8305+ }
8306+
8307+ // Make a list with both subnets
8308+ struct loc_network_list* subnets;
8309+ err = loc_network_list_new(ctx, &subnets);
8310+ if (err) {
8311+ fprintf(stderr, "Could not create subnets list\n");
8312+ exit(EXIT_FAILURE);
8313+ }
8314+
8315+ size_t size = loc_network_list_size(subnets);
8316+ if (size > 0) {
8317+ fprintf(stderr, "The list is not empty: %zu\n", size);
8318+ exit(EXIT_FAILURE);
8319+ }
8320+
8321+ err = loc_network_list_push(subnets, subnet1);
8322+ if (err) {
8323+ fprintf(stderr, "Could not add subnet1 to subnets list\n");
8324+ exit(EXIT_FAILURE);
8325+ }
8326+
8327+ if (loc_network_list_empty(subnets)) {
8328+ fprintf(stderr, "The subnets list reports that it is empty\n");
8329+ exit(EXIT_FAILURE);
8330+ }
8331+
8332+ err = loc_network_list_push(subnets, subnet2);
8333+ if (err) {
8334+ fprintf(stderr, "Could not add subnet2 to subnets list\n");
8335+ exit(EXIT_FAILURE);
8336+ }
8337+
8338+ size = loc_network_list_size(subnets);
8339+ if (size != 2) {
8340+ fprintf(stderr, "Network list is reporting an incorrect size: %zu\n", size);
8341+ exit(EXIT_FAILURE);
8342+ }
8343+
8344+ // Exclude subnet1 from network1
8345+ struct loc_network_list* excluded = loc_network_exclude(network1, subnet1);
8346+ if (!excluded) {
8347+ fprintf(stderr, "Received an empty result from loc_network_exclude() for subnet1\n");
8348+ exit(EXIT_FAILURE);
8349+ }
8350+
8351+ loc_network_list_dump(excluded);
8352+
8353+ // Exclude all subnets from network1
8354+ excluded = loc_network_exclude_list(network1, subnets);
8355+ if (!excluded) {
8356+ fprintf(stderr, "Received an empty result from loc_network_exclude() for subnets\n");
8357+ exit(EXIT_FAILURE);
8358+ }
8359+
8360+ loc_network_list_dump(excluded);
8361+
8362+ if (excluded)
8363+ loc_network_list_unref(excluded);
8364+
8365+ loc_network_list_unref(subnets);
8366+ loc_network_unref(network1);
8367+ loc_network_unref(subnet1);
8368+ loc_network_unref(subnet2);
8369+ loc_unref(ctx);
8370+
8371+ return EXIT_SUCCESS;
8372+}
8373--
83742.20.1
8375
8376From 1209ff0cd4be6b2f52a5e82168db8a8ac68e628a Mon Sep 17 00:00:00 2001
8377From: Michael Tremer <michael.tremer@ipfire.org>
8378Date: Fri, 20 Nov 2020 16:24:40 +0000
8379Subject: [PATCH 079/111] network: Fix loc_network_is_subnet()
8380
8381This function always returned false.
8382
8383Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
8384---
8385 src/network.c | 16 +++-------------
8386 1 file changed, 3 insertions(+), 13 deletions(-)
8387
8388diff --git a/src/network.c b/src/network.c
8389index 4c8787a..b440d76 100644
8390--- a/src/network.c
8391+++ b/src/network.c
8392@@ -491,12 +491,12 @@ LOC_EXPORT int loc_network_overlaps(struct loc_network* self, struct loc_network
8393 LOC_EXPORT int loc_network_is_subnet(struct loc_network* self, struct loc_network* other) {
8394 // If the start address of the other network is smaller than this network,
8395 // it cannot be a subnet.
8396- if (in6_addr_cmp(&self->first_address, &other->first_address) < 0)
8397+ if (in6_addr_cmp(&self->first_address, &other->first_address) > 0)
8398 return 0;
8399
8400 // If the end address of the other network is greater than this network,
8401 // it cannot be a subnet.
8402- if (in6_addr_cmp(&self->last_address, &other->last_address) > 0)
8403+ if (in6_addr_cmp(&self->last_address, &other->last_address) < 0)
8404 return 0;
8405
8406 return 1;
8407@@ -504,17 +504,7 @@ LOC_EXPORT int loc_network_is_subnet(struct loc_network* self, struct loc_networ
8408
8409 // XXX DEPRECATED - I find this too difficult to use
8410 LOC_EXPORT int loc_network_is_subnet_of(struct loc_network* self, struct loc_network* other) {
8411- // If the start address of the other network is smaller than this network,
8412- // it cannot be a subnet.
8413- if (in6_addr_cmp(&self->first_address, &other->first_address) < 0)
8414- return 0;
8415-
8416- // If the end address of the other network is greater than this network,
8417- // it cannot be a subnet.
8418- if (in6_addr_cmp(&self->last_address, &other->last_address) > 0)
8419- return 0;
8420-
8421- return 1;
8422+ return loc_network_is_subnet(other, self);
8423 }
8424
8425 LOC_EXPORT struct loc_network_list* loc_network_subnets(struct loc_network* network) {
8426--
84272.20.1
8428
8429From 92349c14876f8e4711739c82d1a389a53bcb27a5 Mon Sep 17 00:00:00 2001
8430From: Michael Tremer <michael.tremer@ipfire.org>
8431Date: Fri, 20 Nov 2020 16:25:27 +0000
8432Subject: [PATCH 080/111] network: Remove debugging output
8433
8434Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
8435---
8436 src/network.c | 4 ----
8437 1 file changed, 4 deletions(-)
8438
8439diff --git a/src/network.c b/src/network.c
8440index b440d76..3271272 100644
8441--- a/src/network.c
8442+++ b/src/network.c
8443@@ -670,10 +670,6 @@ LOC_EXPORT struct loc_network_list* loc_network_exclude(
8444 loc_network_unref(subnet2);
8445 }
8446
8447-#ifdef ENABLE_DEBUG
8448- loc_network_list_dump(list);
8449-#endif
8450-
8451 // Return the result
8452 return list;
8453
8454--
84552.20.1
8456
8457From ed0f53df0f3ebb915faf25138cc09df7555415a3 Mon Sep 17 00:00:00 2001
8458From: Michael Tremer <michael.tremer@ipfire.org>
8459Date: Fri, 20 Nov 2020 16:25:56 +0000
8460Subject: [PATCH 081/111] database: Flatten out code due to compiler errors
8461
8462It looks like GCC could not follow the code as it was
8463written. Therefore I clean up more often now instead
8464of having a GOTO block where I do that in.
8465
8466Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
8467---
8468 src/database.c | 59 ++++++++++++++++++++++++++++++++++----------------
8469 1 file changed, 40 insertions(+), 19 deletions(-)
8470
8471diff --git a/src/database.c b/src/database.c
8472index ef4f505..c21b957 100644
8473--- a/src/database.c
8474+++ b/src/database.c
8475@@ -1305,8 +1305,12 @@ static int __loc_database_enumerator_next_network_flattened(
8476 while (1) {
8477 // Fetch the next network in line
8478 r = __loc_database_enumerator_next_network(enumerator, &subnet, 0);
8479- if (r)
8480- goto END;
8481+ if (r) {
8482+ loc_network_unref(subnet);
8483+ loc_network_list_unref(subnets);
8484+
8485+ return r;
8486+ }
8487
8488 // End if we did not receive another subnet
8489 if (!subnet)
8490@@ -1315,8 +1319,12 @@ static int __loc_database_enumerator_next_network_flattened(
8491 // Collect all subnets in a list
8492 if (loc_network_is_subnet(*network, subnet)) {
8493 r = loc_network_list_push(subnets, subnet);
8494- if (r)
8495- goto END;
8496+ if (r) {
8497+ loc_network_unref(subnet);
8498+ loc_network_list_unref(subnets);
8499+
8500+ return r;
8501+ }
8502
8503 loc_network_unref(subnet);
8504 continue;
8505@@ -1324,8 +1332,12 @@ static int __loc_database_enumerator_next_network_flattened(
8506
8507 // If this is not a subnet, we push it back onto the stack and break
8508 r = loc_network_list_push(enumerator->stack, subnet);
8509- if (r)
8510- goto END;
8511+ if (r) {
8512+ loc_network_unref(subnet);
8513+ loc_network_list_unref(subnets);
8514+
8515+ return r;
8516+ }
8517
8518 loc_network_unref(subnet);
8519 break;
8520@@ -1343,29 +1355,38 @@ static int __loc_database_enumerator_next_network_flattened(
8521 // If the network has any subnets, we will break it into smaller parts
8522 // without the subnets.
8523 struct loc_network_list* excluded = loc_network_exclude_list(*network, subnets);
8524- if (!excluded || loc_network_list_empty(excluded)) {
8525- r = 1;
8526- goto END;
8527+ if (!excluded) {
8528+ loc_network_list_unref(subnets);
8529+ return -1;
8530+ }
8531+
8532+ // Merge excluded list with subnets
8533+ r = loc_network_list_merge(subnets, excluded);
8534+ if (r) {
8535+ loc_network_list_unref(subnets);
8536+ loc_network_list_unref(excluded);
8537+
8538+ return r;
8539 }
8540
8541+ // We no longer need the excluded list
8542+ loc_network_list_unref(excluded);
8543+
8544+ // Sort all subnets
8545+ loc_network_list_sort(subnets);
8546+
8547 // Replace network with the first one
8548 loc_network_unref(*network);
8549
8550- *network = loc_network_list_pop_first(excluded);
8551+ *network = loc_network_list_pop_first(subnets);
8552
8553 // Push the rest onto the stack
8554- loc_network_list_reverse(excluded);
8555- loc_network_list_merge(enumerator->stack, excluded);
8556-
8557- loc_network_list_unref(excluded);
8558-
8559-END:
8560- if (subnet)
8561- loc_network_unref(subnet);
8562+ loc_network_list_reverse(subnets);
8563+ loc_network_list_merge(enumerator->stack, subnets);
8564
8565 loc_network_list_unref(subnets);
8566
8567- return r;
8568+ return 0;
8569 }
8570
8571 LOC_EXPORT int loc_database_enumerator_next_network(
8572--
85732.20.1
8574
8575From a1024390795d60fab9f697fa230c9901ebd7d221 Mon Sep 17 00:00:00 2001
8576From: Michael Tremer <michael.tremer@ipfire.org>
8577Date: Fri, 20 Nov 2020 16:42:55 +0000
8578Subject: [PATCH 082/111] network-list: Implement merging in reverse in one
8579 step
8580
8581This will save us some time because we do not need to
8582change the list in place first and then merge it.
8583
8584Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
8585---
8586 src/database.c | 3 +--
8587 src/libloc.sym | 1 +
8588 src/loc/network-list.h | 1 +
8589 src/network-list.c | 13 +++++++++++++
8590 4 files changed, 16 insertions(+), 2 deletions(-)
8591
8592diff --git a/src/database.c b/src/database.c
8593index c21b957..ba4f98a 100644
8594--- a/src/database.c
8595+++ b/src/database.c
8596@@ -1381,8 +1381,7 @@ static int __loc_database_enumerator_next_network_flattened(
8597 *network = loc_network_list_pop_first(subnets);
8598
8599 // Push the rest onto the stack
8600- loc_network_list_reverse(subnets);
8601- loc_network_list_merge(enumerator->stack, subnets);
8602+ loc_network_list_merge_reverse(enumerator->stack, subnets);
8603
8604 loc_network_list_unref(subnets);
8605
8606diff --git a/src/libloc.sym b/src/libloc.sym
8607index 406dd15..56cada8 100644
8608--- a/src/libloc.sym
8609+++ b/src/libloc.sym
8610@@ -140,6 +140,7 @@ global:
8611 loc_network_list_empty;
8612 loc_network_list_get;
8613 loc_network_list_merge;
8614+ loc_network_list_merge_reverse;
8615 loc_network_list_new;
8616 loc_network_list_pop;
8617 loc_network_list_pop_first;
8618diff --git a/src/loc/network-list.h b/src/loc/network-list.h
8619index af3b28d..89776a6 100644
8620--- a/src/loc/network-list.h
8621+++ b/src/loc/network-list.h
8622@@ -33,5 +33,6 @@ int loc_network_list_contains(struct loc_network_list* list, struct loc_network*
8623 void loc_network_list_sort(struct loc_network_list* list);
8624 void loc_network_list_reverse(struct loc_network_list* list);
8625 int loc_network_list_merge(struct loc_network_list* self, struct loc_network_list* other);
8626+int loc_network_list_merge_reverse(struct loc_network_list* self, struct loc_network_list* other);
8627
8628 #endif
8629diff --git a/src/network-list.c b/src/network-list.c
8630index 9cb4547..b455caf 100644
8631--- a/src/network-list.c
8632+++ b/src/network-list.c
8633@@ -242,3 +242,16 @@ LOC_EXPORT int loc_network_list_merge(
8634
8635 return 0;
8636 }
8637+
8638+LOC_EXPORT int loc_network_list_merge_reverse(
8639+ struct loc_network_list* self, struct loc_network_list* other) {
8640+ int r;
8641+
8642+ for (int i = other->size - 1; i >= 0; i--) {
8643+ r = loc_network_list_push(self, other->elements[i]);
8644+ if (r)
8645+ return r;
8646+ }
8647+
8648+ return 0;
8649+}
8650--
86512.20.1
8652
8653From a5967330d530504db401540d4bcd5474fe00e421 Mon Sep 17 00:00:00 2001
8654From: Michael Tremer <michael.tremer@ipfire.org>
8655Date: Fri, 20 Nov 2020 18:36:48 +0000
8656Subject: [PATCH 083/111] network: Optimise _subnet function
8657
8658This function used to create a network list which always
8659had exactly two elements. Since splitting a network in half
8660always returns two parts, we can simply return them as a
8661pointer.
8662
8663This improves returning the network tree by about 17%.
8664
8665Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
8666---
8667 src/loc/network.h | 2 +-
8668 src/network.c | 158 ++++++++++++++++++---------------------------
8669 src/test-network.c | 51 ++++++++-------
8670 3 files changed, 91 insertions(+), 120 deletions(-)
8671
8672diff --git a/src/loc/network.h b/src/loc/network.h
8673index 4b7410c..d67ec54 100644
8674--- a/src/loc/network.h
8675+++ b/src/loc/network.h
8676@@ -62,7 +62,7 @@ int loc_network_gt(struct loc_network* self, struct loc_network* other);
8677 int loc_network_overlaps(struct loc_network* self, struct loc_network* other);
8678 int loc_network_is_subnet(struct loc_network* self, struct loc_network* other);
8679 int loc_network_is_subnet_of(struct loc_network* self, struct loc_network* other);
8680-struct loc_network_list* loc_network_subnets(struct loc_network* network);
8681+int loc_network_subnets(struct loc_network* network, struct loc_network** subnet1, struct loc_network** subnet2);
8682 struct loc_network_list* loc_network_exclude(
8683 struct loc_network* self, struct loc_network* other);
8684 struct loc_network_list* loc_network_exclude_list(
8685diff --git a/src/network.c b/src/network.c
8686index 3271272..ff9c1eb 100644
8687--- a/src/network.c
8688+++ b/src/network.c
8689@@ -507,66 +507,91 @@ LOC_EXPORT int loc_network_is_subnet_of(struct loc_network* self, struct loc_net
8690 return loc_network_is_subnet(other, self);
8691 }
8692
8693-LOC_EXPORT struct loc_network_list* loc_network_subnets(struct loc_network* network) {
8694- struct loc_network_list* list;
8695+LOC_EXPORT int loc_network_subnets(struct loc_network* network,
8696+ struct loc_network** subnet1, struct loc_network** subnet2) {
8697+ int r;
8698+ *subnet1 = NULL;
8699+ *subnet2 = NULL;
8700
8701 // New prefix length
8702 unsigned int prefix = network->prefix + 1;
8703
8704 // Check if the new prefix is valid
8705 if (valid_prefix(&network->first_address, prefix))
8706- return NULL;
8707-
8708- // Create a new list with the result
8709- int r = loc_network_list_new(network->ctx, &list);
8710- if (r) {
8711- ERROR(network->ctx, "Could not create network list: %d\n", r);
8712- return NULL;
8713- }
8714-
8715- struct loc_network* subnet1 = NULL;
8716- struct loc_network* subnet2 = NULL;
8717+ return -1;
8718
8719 // Create the first half of the network
8720- r = loc_network_new(network->ctx, &subnet1, &network->first_address, prefix);
8721+ r = loc_network_new(network->ctx, subnet1, &network->first_address, prefix);
8722 if (r)
8723- goto ERROR;
8724+ return r;
8725
8726 // The next subnet starts after the first one
8727- struct in6_addr first_address = address_increment(&subnet1->last_address);
8728+ struct in6_addr first_address = address_increment(&(*subnet1)->last_address);
8729
8730 // Create the second half of the network
8731- r = loc_network_new(network->ctx, &subnet2, &first_address, prefix);
8732- if (r)
8733- goto ERROR;
8734-
8735- // Push the both onto the stack (in reverse order)
8736- r = loc_network_list_push(list, subnet2);
8737+ r = loc_network_new(network->ctx, subnet2, &first_address, prefix);
8738 if (r)
8739- goto ERROR;
8740-
8741- r = loc_network_list_push(list, subnet1);
8742- if (r)
8743- goto ERROR;
8744+ return r;
8745
8746 // Copy country code
8747 const char* country_code = loc_network_get_country_code(network);
8748 if (country_code) {
8749- loc_network_set_country_code(subnet1, country_code);
8750- loc_network_set_country_code(subnet2, country_code);
8751+ loc_network_set_country_code(*subnet1, country_code);
8752+ loc_network_set_country_code(*subnet2, country_code);
8753 }
8754
8755 // Copy ASN
8756 uint32_t asn = loc_network_get_asn(network);
8757 if (asn) {
8758- loc_network_set_asn(subnet1, asn);
8759- loc_network_set_asn(subnet2, asn);
8760+ loc_network_set_asn(*subnet1, asn);
8761+ loc_network_set_asn(*subnet2, asn);
8762 }
8763
8764- loc_network_unref(subnet1);
8765- loc_network_unref(subnet2);
8766+ return 0;
8767+}
8768
8769- return list;
8770+static int __loc_network_exclude(struct loc_network* network,
8771+ struct loc_network* other, struct loc_network_list* list) {
8772+ struct loc_network* subnet1 = NULL;
8773+ struct loc_network* subnet2 = NULL;
8774+
8775+ int r = loc_network_subnets(network, &subnet1, &subnet2);
8776+ if (r)
8777+ goto ERROR;
8778+
8779+ if (loc_network_eq(other, subnet1)) {
8780+ r = loc_network_list_push(list, subnet2);
8781+ if (r)
8782+ goto ERROR;
8783+
8784+ } else if (loc_network_eq(other, subnet2)) {
8785+ r = loc_network_list_push(list, subnet1);
8786+ if (r)
8787+ goto ERROR;
8788+
8789+ } else if (loc_network_is_subnet_of(other, subnet1)) {
8790+ r = loc_network_list_push(list, subnet2);
8791+ if (r)
8792+ goto ERROR;
8793+
8794+ r = __loc_network_exclude(subnet1, other, list);
8795+ if (r)
8796+ goto ERROR;
8797+
8798+ } else if (loc_network_is_subnet_of(other, subnet2)) {
8799+ r = loc_network_list_push(list, subnet1);
8800+ if (r)
8801+ goto ERROR;
8802+
8803+ r = __loc_network_exclude(subnet2, other, list);
8804+ if (r)
8805+ goto ERROR;
8806+
8807+ } else {
8808+ ERROR(network->ctx, "We should never get here\n");
8809+ r = 1;
8810+ goto ERROR;
8811+ }
8812
8813 ERROR:
8814 if (subnet1)
8815@@ -575,10 +600,7 @@ ERROR:
8816 if (subnet2)
8817 loc_network_unref(subnet2);
8818
8819- if (list)
8820- loc_network_list_unref(list);
8821-
8822- return NULL;
8823+ return r;
8824 }
8825
8826 LOC_EXPORT struct loc_network_list* loc_network_exclude(
8827@@ -623,67 +645,15 @@ LOC_EXPORT struct loc_network_list* loc_network_exclude(
8828 return NULL;
8829 }
8830
8831- struct loc_network_list* subnets = loc_network_subnets(self);
8832-
8833- struct loc_network* subnet1 = NULL;
8834- struct loc_network* subnet2 = NULL;
8835-
8836- while (subnets) {
8837- // Fetch both subnets
8838- subnet1 = loc_network_list_get(subnets, 0);
8839- subnet2 = loc_network_list_get(subnets, 1);
8840-
8841- // Free list
8842- loc_network_list_unref(subnets);
8843- subnets = NULL;
8844-
8845- if (loc_network_eq(other, subnet1)) {
8846- r = loc_network_list_push(list, subnet2);
8847- if (r)
8848- goto ERROR;
8849-
8850- } else if (loc_network_eq(other, subnet2)) {
8851- r = loc_network_list_push(list, subnet1);
8852- if (r)
8853- goto ERROR;
8854-
8855- } else if (loc_network_is_subnet_of(other, subnet1)) {
8856- r = loc_network_list_push(list, subnet2);
8857- if (r)
8858- goto ERROR;
8859-
8860- subnets = loc_network_subnets(subnet1);
8861-
8862- } else if (loc_network_is_subnet_of(other, subnet2)) {
8863- r = loc_network_list_push(list, subnet1);
8864- if (r)
8865- goto ERROR;
8866-
8867- subnets = loc_network_subnets(subnet2);
8868-
8869- } else {
8870- ERROR(self->ctx, "We should never get here\n");
8871- goto ERROR;
8872- }
8873+ r = __loc_network_exclude(self, other, list);
8874+ if (r) {
8875+ loc_network_list_unref(list);
8876
8877- loc_network_unref(subnet1);
8878- loc_network_unref(subnet2);
8879+ return NULL;
8880 }
8881
8882 // Return the result
8883 return list;
8884-
8885-ERROR:
8886- if (subnet1)
8887- loc_network_unref(subnet1);
8888-
8889- if (subnet2)
8890- loc_network_unref(subnet2);
8891-
8892- if (list)
8893- loc_network_list_unref(list);
8894-
8895- return NULL;
8896 }
8897
8898 LOC_EXPORT struct loc_network_list* loc_network_exclude_list(
8899diff --git a/src/test-network.c b/src/test-network.c
8900index 7c90224..79c2967 100644
8901--- a/src/test-network.c
8902+++ b/src/test-network.c
8903@@ -138,47 +138,48 @@ int main(int argc, char** argv) {
8904 }
8905
8906 // Check subnet function
8907- err = loc_network_is_subnet_of(network1, network2);
8908- if (err != 0) {
8909+ err = loc_network_is_subnet(network1, network2);
8910+ if (!err) {
8911 fprintf(stderr, "Subnet check 1 failed: %d\n", err);
8912 exit(EXIT_FAILURE);
8913 }
8914
8915- err = loc_network_is_subnet_of(network2, network1);
8916- if (err != 1) {
8917+ err = loc_network_is_subnet(network2, network1);
8918+ if (err) {
8919 fprintf(stderr, "Subnet check 2 failed: %d\n", err);
8920 exit(EXIT_FAILURE);
8921 }
8922
8923- // Make list of subnets
8924- struct loc_network_list* subnets = loc_network_subnets(network1);
8925- if (!subnets) {
8926- fprintf(stderr, "Could not find subnets of network\n");
8927+ // Make subnets
8928+ struct loc_network* subnet1 = NULL;
8929+ struct loc_network* subnet2 = NULL;
8930+
8931+ err = loc_network_subnets(network1, &subnet1, &subnet2);
8932+ if (err || !subnet1 || !subnet2) {
8933+ fprintf(stderr, "Could not find subnets of network: %d\n", err);
8934 exit(EXIT_FAILURE);
8935 }
8936
8937- loc_network_list_dump(subnets);
8938-
8939- while (!loc_network_list_empty(subnets)) {
8940- struct loc_network* subnet = loc_network_list_pop(subnets);
8941- if (!subnet) {
8942- fprintf(stderr, "Received an empty subnet\n");
8943- exit(EXIT_FAILURE);
8944- }
8945+ char* s = loc_network_str(subnet1);
8946+ printf("Received subnet1 = %s\n", s);
8947+ free(s);
8948
8949- char* s = loc_network_str(subnet);
8950- printf("Received subnet %s\n", s);
8951- free(s);
8952+ s = loc_network_str(subnet2);
8953+ printf("Received subnet2 = %s\n", s);
8954+ free(s);
8955
8956- if (!loc_network_is_subnet_of(subnet, network1)) {
8957- fprintf(stderr, "Not a subnet\n");
8958- exit(EXIT_FAILURE);
8959- }
8960+ if (!loc_network_is_subnet(network1, subnet1)) {
8961+ fprintf(stderr, "Subnet1 is not a subnet\n");
8962+ exit(EXIT_FAILURE);
8963+ }
8964
8965- loc_network_unref(subnet);
8966+ if (!loc_network_is_subnet(network1, subnet2)) {
8967+ fprintf(stderr, "Subnet2 is not a subnet\n");
8968+ exit(EXIT_FAILURE);
8969 }
8970
8971- loc_network_list_unref(subnets);
8972+ loc_network_unref(subnet1);
8973+ loc_network_unref(subnet2);
8974
8975 struct loc_network_list* excluded = loc_network_exclude(network1, network2);
8976 if (!excluded) {
8977--
89782.20.1
8979
8980From 7fe6a21845edf6692d239f228117bc95620d0419 Mon Sep 17 00:00:00 2001
8981From: Michael Tremer <michael.tremer@ipfire.org>
8982Date: Fri, 20 Nov 2020 18:38:47 +0000
8983Subject: [PATCH 084/111] network: Add function to return the prefix
8984
8985Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
8986---
8987 src/libloc.sym | 1 +
8988 src/loc/network.h | 1 +
8989 src/network.c | 12 ++++++++++++
8990 3 files changed, 14 insertions(+)
8991
8992diff --git a/src/libloc.sym b/src/libloc.sym
8993index 56cada8..9f41c89 100644
8994--- a/src/libloc.sym
8995+++ b/src/libloc.sym
8996@@ -125,6 +125,7 @@ global:
8997 loc_network_new;
8998 loc_network_new_from_string;
8999 loc_network_overlaps;
9000+ loc_network_prefix;
9001 loc_network_ref;
9002 loc_network_set_asn;
9003 loc_network_set_country_code;
9004diff --git a/src/loc/network.h b/src/loc/network.h
9005index d67ec54..7b2ae4c 100644
9006--- a/src/loc/network.h
9007+++ b/src/loc/network.h
9008@@ -38,6 +38,7 @@ struct loc_network* loc_network_ref(struct loc_network* network);
9009 struct loc_network* loc_network_unref(struct loc_network* network);
9010 char* loc_network_str(struct loc_network* network);
9011 int loc_network_address_family(struct loc_network* network);
9012+unsigned int loc_network_prefix(struct loc_network* network);
9013
9014 const struct in6_addr* loc_network_get_first_address(struct loc_network* network);
9015 char* loc_network_format_first_address(struct loc_network* network);
9016diff --git a/src/network.c b/src/network.c
9017index ff9c1eb..4720503 100644
9018--- a/src/network.c
9019+++ b/src/network.c
9020@@ -310,6 +310,18 @@ LOC_EXPORT int loc_network_address_family(struct loc_network* network) {
9021 return network->family;
9022 }
9023
9024+LOC_EXPORT unsigned int loc_network_prefix(struct loc_network* network) {
9025+ switch (network->family) {
9026+ case AF_INET6:
9027+ return network->prefix;
9028+
9029+ case AF_INET:
9030+ return network->prefix - 96;
9031+ }
9032+
9033+ return 0;
9034+}
9035+
9036 static char* loc_network_format_address(struct loc_network* network, const struct in6_addr* address) {
9037 const size_t length = INET6_ADDRSTRLEN;
9038
9039--
90402.20.1
9041
9042From cf8d3c6454843943e3bc81eb85522779d1c11f9b Mon Sep 17 00:00:00 2001
9043From: Michael Tremer <michael.tremer@ipfire.org>
9044Date: Fri, 20 Nov 2020 18:39:13 +0000
9045Subject: [PATCH 085/111] network: Speed up subnet check
9046
9047There is no point in checking different address families
9048with each other and we do not need to compare addresses
9049when the prefix of the subnet does not fit into the
9050network to check.
9051
9052Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
9053---
9054 src/network.c | 8 ++++++++
9055 1 file changed, 8 insertions(+)
9056
9057diff --git a/src/network.c b/src/network.c
9058index 4720503..e52b58c 100644
9059--- a/src/network.c
9060+++ b/src/network.c
9061@@ -501,6 +501,14 @@ LOC_EXPORT int loc_network_overlaps(struct loc_network* self, struct loc_network
9062 }
9063
9064 LOC_EXPORT int loc_network_is_subnet(struct loc_network* self, struct loc_network* other) {
9065+ // Check family
9066+ if (self->family != other->family)
9067+ return 0;
9068+
9069+ // The prefix must be smaller (this avoids the more complex comparisons later)
9070+ if (self->prefix > other->prefix)
9071+ return 0;
9072+
9073 // If the start address of the other network is smaller than this network,
9074 // it cannot be a subnet.
9075 if (in6_addr_cmp(&self->first_address, &other->first_address) > 0)
9076--
90772.20.1
9078
9079From d6a5092f969bb3bd50d130d4ba64b4e4be2e61f6 Mon Sep 17 00:00:00 2001
9080From: Michael Tremer <michael.tremer@ipfire.org>
9081Date: Fri, 20 Nov 2020 18:44:42 +0000
9082Subject: [PATCH 086/111] network: Remove deprecated loc_network_is_subnet_of
9083 function
9084
9085Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
9086---
9087 src/libloc.sym | 1 -
9088 src/loc/network.h | 1 -
9089 src/network.c | 13 ++++---------
9090 src/python/network.c | 2 +-
9091 4 files changed, 5 insertions(+), 12 deletions(-)
9092
9093diff --git a/src/libloc.sym b/src/libloc.sym
9094index 9f41c89..b2d8a31 100644
9095--- a/src/libloc.sym
9096+++ b/src/libloc.sym
9097@@ -118,7 +118,6 @@ global:
9098 loc_network_gt;
9099 loc_network_has_flag;
9100 loc_network_is_subnet;
9101- loc_network_is_subnet_of;
9102 loc_network_match_asn;
9103 loc_network_match_country_code;
9104 loc_network_match_flag;
9105diff --git a/src/loc/network.h b/src/loc/network.h
9106index 7b2ae4c..b31c8a2 100644
9107--- a/src/loc/network.h
9108+++ b/src/loc/network.h
9109@@ -62,7 +62,6 @@ int loc_network_eq(struct loc_network* self, struct loc_network* other);
9110 int loc_network_gt(struct loc_network* self, struct loc_network* other);
9111 int loc_network_overlaps(struct loc_network* self, struct loc_network* other);
9112 int loc_network_is_subnet(struct loc_network* self, struct loc_network* other);
9113-int loc_network_is_subnet_of(struct loc_network* self, struct loc_network* other);
9114 int loc_network_subnets(struct loc_network* network, struct loc_network** subnet1, struct loc_network** subnet2);
9115 struct loc_network_list* loc_network_exclude(
9116 struct loc_network* self, struct loc_network* other);
9117diff --git a/src/network.c b/src/network.c
9118index e52b58c..72b77e6 100644
9119--- a/src/network.c
9120+++ b/src/network.c
9121@@ -522,11 +522,6 @@ LOC_EXPORT int loc_network_is_subnet(struct loc_network* self, struct loc_networ
9122 return 1;
9123 }
9124
9125-// XXX DEPRECATED - I find this too difficult to use
9126-LOC_EXPORT int loc_network_is_subnet_of(struct loc_network* self, struct loc_network* other) {
9127- return loc_network_is_subnet(other, self);
9128-}
9129-
9130 LOC_EXPORT int loc_network_subnets(struct loc_network* network,
9131 struct loc_network** subnet1, struct loc_network** subnet2) {
9132 int r;
9133@@ -589,7 +584,7 @@ static int __loc_network_exclude(struct loc_network* network,
9134 if (r)
9135 goto ERROR;
9136
9137- } else if (loc_network_is_subnet_of(other, subnet1)) {
9138+ } else if (loc_network_is_subnet(subnet1, other)) {
9139 r = loc_network_list_push(list, subnet2);
9140 if (r)
9141 goto ERROR;
9142@@ -598,7 +593,7 @@ static int __loc_network_exclude(struct loc_network* network,
9143 if (r)
9144 goto ERROR;
9145
9146- } else if (loc_network_is_subnet_of(other, subnet2)) {
9147+ } else if (loc_network_is_subnet(subnet2, other)) {
9148 r = loc_network_list_push(list, subnet1);
9149 if (r)
9150 goto ERROR;
9151@@ -645,7 +640,7 @@ LOC_EXPORT struct loc_network_list* loc_network_exclude(
9152 }
9153
9154 // Other must be a subnet of self
9155- if (!loc_network_is_subnet_of(other, self)) {
9156+ if (!loc_network_is_subnet(self, other)) {
9157 DEBUG(self->ctx, "Network %p is not contained in network %p\n", other, self);
9158
9159 return NULL;
9160@@ -726,7 +721,7 @@ LOC_EXPORT struct loc_network_list* loc_network_exclude_list(
9161 }
9162
9163 // Drop this subnet if is a subnet of another subnet
9164- if (loc_network_is_subnet_of(subnet, subnet_to_check)) {
9165+ if (loc_network_is_subnet(subnet_to_check, subnet)) {
9166 passed = 0;
9167 loc_network_unref(subnet);
9168 break;
9169diff --git a/src/python/network.c b/src/python/network.c
9170index 742b472..b6e92fb 100644
9171--- a/src/python/network.c
9172+++ b/src/python/network.c
9173@@ -194,7 +194,7 @@ static PyObject* Network_is_subnet_of(NetworkObject* self, PyObject* args) {
9174 if (!PyArg_ParseTuple(args, "O!", &NetworkType, &other))
9175 return NULL;
9176
9177- if (loc_network_is_subnet_of(self->network, other->network))
9178+ if (loc_network_is_subnet(other->network, self->network))
9179 Py_RETURN_TRUE;
9180
9181 Py_RETURN_FALSE;
9182--
91832.20.1
9184
9185From af4689bf5c56ad79e9e90396b41be460e49ef384 Mon Sep 17 00:00:00 2001
9186From: Michael Tremer <michael.tremer@ipfire.org>
9187Date: Tue, 24 Nov 2020 14:55:08 +0000
9188Subject: [PATCH 087/111] network-list: Make this a sorted list
9189
9190The list is now organised so that it is always ordered.
9191
9192This allows us to find if a network is on the list a lot
9193quicker using binary search as well as inserting a new
9194network at the right place.
9195
9196This will benefit loc_network_exclude with very large networks.
9197
9198Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
9199---
9200 src/libloc.sym | 1 +
9201 src/loc/network.h | 1 +
9202 src/network-list.c | 84 +++++++++++++++++++++++++++++++++++++++++-----
9203 src/network.c | 22 ++++++++++++
9204 4 files changed, 99 insertions(+), 9 deletions(-)
9205
9206diff --git a/src/libloc.sym b/src/libloc.sym
9207index b2d8a31..28cc8e8 100644
9208--- a/src/libloc.sym
9209+++ b/src/libloc.sym
9210@@ -106,6 +106,7 @@ global:
9211
9212 # Network
9213 loc_network_address_family;
9214+ loc_network_cmp;
9215 loc_network_eq;
9216 loc_network_exclude;
9217 loc_network_exclude_list;
9218diff --git a/src/loc/network.h b/src/loc/network.h
9219index b31c8a2..8ab1562 100644
9220--- a/src/loc/network.h
9221+++ b/src/loc/network.h
9222@@ -58,6 +58,7 @@ int loc_network_has_flag(struct loc_network* network, uint32_t flag);
9223 int loc_network_set_flag(struct loc_network* network, uint32_t flag);
9224 int loc_network_match_flag(struct loc_network* network, uint32_t flag);
9225
9226+int loc_network_cmp(struct loc_network* self, struct loc_network* other);
9227 int loc_network_eq(struct loc_network* self, struct loc_network* other);
9228 int loc_network_gt(struct loc_network* self, struct loc_network* other);
9229 int loc_network_overlaps(struct loc_network* self, struct loc_network* other);
9230diff --git a/src/network-list.c b/src/network-list.c
9231index b455caf..6e9cd37 100644
9232--- a/src/network-list.c
9233+++ b/src/network-list.c
9234@@ -16,6 +16,7 @@
9235
9236 #include <errno.h>
9237 #include <stdlib.h>
9238+#include <time.h>
9239
9240 #include <loc/libloc.h>
9241 #include <loc/network.h>
9242@@ -130,11 +131,71 @@ LOC_EXPORT struct loc_network* loc_network_list_get(struct loc_network_list* lis
9243 return loc_network_ref(list->elements[index]);
9244 }
9245
9246+//MOVE FUNCTION GOES HERE
9247+
9248+static off_t loc_network_list_find(struct loc_network_list* list,
9249+ struct loc_network* network, int* found) {
9250+ off_t lo = 0;
9251+ off_t hi = list->size - 1;
9252+
9253+ *found = 0;
9254+
9255+#ifdef ENABLE_DEBUG
9256+ // Save start time
9257+ clock_t start = clock();
9258+#endif
9259+
9260+ off_t i = 0;
9261+
9262+ while (lo <= hi) {
9263+ i = (lo + hi) / 2;
9264+
9265+ // Check if this is a match
9266+ int result = loc_network_cmp(network, list->elements[i]);
9267+
9268+ if (result == 0) {
9269+ *found = 1;
9270+
9271+#ifdef ENABLE_DEBUG
9272+ clock_t end = clock();
9273+
9274+ // Log how fast this has been
9275+ DEBUG(list->ctx, "Found network in %.4fms at %jd\n",
9276+ (double)(end - start) / CLOCKS_PER_SEC * 1000, (intmax_t)i);
9277+#endif
9278+
9279+ return i;
9280+ }
9281+
9282+ if (result > 0)
9283+ lo = i + 1;
9284+ else
9285+ hi = i - 1;
9286+ }
9287+
9288+#ifdef ENABLE_DEBUG
9289+ clock_t end = clock();
9290+
9291+ // Log how fast this has been
9292+ DEBUG(list->ctx, "Did not find network in %.4fms (last i = %jd)\n",
9293+ (double)(end - start) / CLOCKS_PER_SEC * 1000, (intmax_t)i);
9294+#endif
9295+
9296+ return i;
9297+}
9298+
9299 LOC_EXPORT int loc_network_list_push(struct loc_network_list* list, struct loc_network* network) {
9300- // Do not add networks that are already on the list
9301- if (loc_network_list_contains(list, network))
9302+ int found = 0;
9303+
9304+ off_t index = loc_network_list_find(list, network, &found);
9305+
9306+ // The network has been found on the list. Nothing to do.
9307+ if (found)
9308 return 0;
9309
9310+ DEBUG(list->ctx, "%p: Inserting network %p at index %jd\n",
9311+ list, network, (intmax_t)index);
9312+
9313 // Check if we have space left
9314 if (list->size >= list->elements_size) {
9315 int r = loc_network_list_grow(list, 64);
9316@@ -142,9 +203,15 @@ LOC_EXPORT int loc_network_list_push(struct loc_network_list* list, struct loc_n
9317 return r;
9318 }
9319
9320- DEBUG(list->ctx, "%p: Pushing network %p onto stack\n", list, network);
9321+ // The list is now larger
9322+ list->size++;
9323+
9324+ // Move all elements out of the way
9325+ for (unsigned int i = list->size - 1; i > index; i--)
9326+ list->elements[i] = list->elements[i - 1];
9327
9328- list->elements[list->size++] = loc_network_ref(network);
9329+ // Add the new element at the right place
9330+ list->elements[index] = loc_network_ref(network);
9331
9332 return 0;
9333 }
9334@@ -183,12 +250,11 @@ LOC_EXPORT struct loc_network* loc_network_list_pop_first(struct loc_network_lis
9335 }
9336
9337 LOC_EXPORT int loc_network_list_contains(struct loc_network_list* list, struct loc_network* network) {
9338- for (unsigned int i = 0; i < list->size; i++) {
9339- if (loc_network_eq(list->elements[i], network))
9340- return 1;
9341- }
9342+ int found = 0;
9343
9344- return 0;
9345+ loc_network_list_find(list, network, &found);
9346+
9347+ return found;
9348 }
9349
9350 static void loc_network_list_swap(struct loc_network_list* list, unsigned int i1, unsigned int i2) {
9351diff --git a/src/network.c b/src/network.c
9352index 72b77e6..38d557a 100644
9353--- a/src/network.c
9354+++ b/src/network.c
9355@@ -441,6 +441,28 @@ LOC_EXPORT int loc_network_match_flag(struct loc_network* network, uint32_t flag
9356 return loc_network_has_flag(network, flag);
9357 }
9358
9359+LOC_EXPORT int loc_network_cmp(struct loc_network* self, struct loc_network* other) {
9360+ // Compare family
9361+ if (self->family > other->family)
9362+ return 1;
9363+ else if (self->family < other->family)
9364+ return -1;
9365+
9366+ // Compare address
9367+ int r = in6_addr_cmp(&self->first_address, &other->first_address);
9368+ if (r)
9369+ return r;
9370+
9371+ // Compare prefix
9372+ if (self->prefix > other->prefix)
9373+ return 1;
9374+ else if (self->prefix < other->prefix)
9375+ return -1;
9376+
9377+ // Both networks are equal
9378+ return 0;
9379+}
9380+
9381 LOC_EXPORT int loc_network_eq(struct loc_network* self, struct loc_network* other) {
9382 // Family must be the same
9383 if (self->family != other->family)
9384--
93852.20.1
9386
9387From 39cbbc63aee362d82f69a9b4722b59153ce799a0 Mon Sep 17 00:00:00 2001
9388From: Michael Tremer <michael.tremer@ipfire.org>
9389Date: Tue, 24 Nov 2020 15:04:03 +0000
9390Subject: [PATCH 088/111] network-list: Drop sorting functions
9391
9392Since the list is always sorted, there is no point in
9393sorting it again...
9394
9395Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
9396---
9397 src/database.c | 6 +----
9398 src/libloc.sym | 3 ---
9399 src/loc/network-list.h | 3 ---
9400 src/network-list.c | 52 ------------------------------------------
9401 src/test-network.c | 9 --------
9402 5 files changed, 1 insertion(+), 72 deletions(-)
9403
9404diff --git a/src/database.c b/src/database.c
9405index ba4f98a..5546091 100644
9406--- a/src/database.c
9407+++ b/src/database.c
9408@@ -1372,17 +1372,13 @@ static int __loc_database_enumerator_next_network_flattened(
9409 // We no longer need the excluded list
9410 loc_network_list_unref(excluded);
9411
9412- // Sort all subnets
9413- loc_network_list_sort(subnets);
9414-
9415 // Replace network with the first one
9416 loc_network_unref(*network);
9417
9418 *network = loc_network_list_pop_first(subnets);
9419
9420 // Push the rest onto the stack
9421- loc_network_list_merge_reverse(enumerator->stack, subnets);
9422-
9423+ loc_network_list_merge(enumerator->stack, subnets);
9424 loc_network_list_unref(subnets);
9425
9426 return 0;
9427diff --git a/src/libloc.sym b/src/libloc.sym
9428index 28cc8e8..4b0ce45 100644
9429--- a/src/libloc.sym
9430+++ b/src/libloc.sym
9431@@ -141,15 +141,12 @@ global:
9432 loc_network_list_empty;
9433 loc_network_list_get;
9434 loc_network_list_merge;
9435- loc_network_list_merge_reverse;
9436 loc_network_list_new;
9437 loc_network_list_pop;
9438 loc_network_list_pop_first;
9439 loc_network_list_push;
9440 loc_network_list_ref;
9441- loc_network_list_reverse;
9442 loc_network_list_size;
9443- loc_network_list_sort;
9444 loc_network_list_unref;
9445
9446 # Writer
9447diff --git a/src/loc/network-list.h b/src/loc/network-list.h
9448index 89776a6..21c7402 100644
9449--- a/src/loc/network-list.h
9450+++ b/src/loc/network-list.h
9451@@ -30,9 +30,6 @@ int loc_network_list_push(struct loc_network_list* list, struct loc_network* net
9452 struct loc_network* loc_network_list_pop(struct loc_network_list* list);
9453 struct loc_network* loc_network_list_pop_first(struct loc_network_list* list);
9454 int loc_network_list_contains(struct loc_network_list* list, struct loc_network* network);
9455-void loc_network_list_sort(struct loc_network_list* list);
9456-void loc_network_list_reverse(struct loc_network_list* list);
9457 int loc_network_list_merge(struct loc_network_list* self, struct loc_network_list* other);
9458-int loc_network_list_merge_reverse(struct loc_network_list* self, struct loc_network_list* other);
9459
9460 #endif
9461diff --git a/src/network-list.c b/src/network-list.c
9462index 6e9cd37..7e8b5f3 100644
9463--- a/src/network-list.c
9464+++ b/src/network-list.c
9465@@ -257,45 +257,6 @@ LOC_EXPORT int loc_network_list_contains(struct loc_network_list* list, struct l
9466 return found;
9467 }
9468
9469-static void loc_network_list_swap(struct loc_network_list* list, unsigned int i1, unsigned int i2) {
9470- // Do nothing for invalid indices
9471- if (i1 >= list->size || i2 >= list->size)
9472- return;
9473-
9474- struct loc_network* network1 = list->elements[i1];
9475- struct loc_network* network2 = list->elements[i2];
9476-
9477- list->elements[i1] = network2;
9478- list->elements[i2] = network1;
9479-}
9480-
9481-LOC_EXPORT void loc_network_list_reverse(struct loc_network_list* list) {
9482- unsigned int i = 0;
9483- unsigned int j = list->size - 1;
9484-
9485- while (i < j) {
9486- loc_network_list_swap(list, i++, j--);
9487- }
9488-}
9489-
9490-LOC_EXPORT void loc_network_list_sort(struct loc_network_list* list) {
9491- unsigned int n = list->size;
9492- int swapped;
9493-
9494- do {
9495- swapped = 0;
9496-
9497- for (unsigned int i = 1; i < n; i++) {
9498- if (loc_network_gt(list->elements[i-1], list->elements[i]) > 0) {
9499- loc_network_list_swap(list, i-1, i);
9500- swapped = 1;
9501- }
9502- }
9503-
9504- n--;
9505- } while (swapped);
9506-}
9507-
9508 LOC_EXPORT int loc_network_list_merge(
9509 struct loc_network_list* self, struct loc_network_list* other) {
9510 int r;
9511@@ -308,16 +269,3 @@ LOC_EXPORT int loc_network_list_merge(
9512
9513 return 0;
9514 }
9515-
9516-LOC_EXPORT int loc_network_list_merge_reverse(
9517- struct loc_network_list* self, struct loc_network_list* other) {
9518- int r;
9519-
9520- for (int i = other->size - 1; i >= 0; i--) {
9521- r = loc_network_list_push(self, other->elements[i]);
9522- if (r)
9523- return r;
9524- }
9525-
9526- return 0;
9527-}
9528diff --git a/src/test-network.c b/src/test-network.c
9529index 79c2967..8a6763c 100644
9530--- a/src/test-network.c
9531+++ b/src/test-network.c
9532@@ -188,15 +188,6 @@ int main(int argc, char** argv) {
9533 }
9534
9535 loc_network_list_dump(excluded);
9536-
9537- // Reverse it
9538- loc_network_list_reverse(excluded);
9539- loc_network_list_dump(excluded);
9540-
9541- // Sort them and dump them again
9542- loc_network_list_sort(excluded);
9543- loc_network_list_dump(excluded);
9544-
9545 loc_network_list_unref(excluded);
9546
9547 // Create a database
9548--
95492.20.1
9550
9551From 5dacb45afceac2d05ea597755c1ca5a1b62cc0fd Mon Sep 17 00:00:00 2001
9552From: Michael Tremer <michael.tremer@ipfire.org>
9553Date: Tue, 24 Nov 2020 15:15:59 +0000
9554Subject: [PATCH 089/111] database: Avoid merging the same data twice
9555
9556When finish splitting networks into many parts, we have
9557a list of subnets with the excluded subnets and merge them
9558together first and put them on the stack again.
9559
9560This is slower than pushing it all onto the stack first
9561and then popping the first element.
9562
9563Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
9564---
9565 src/database.c | 24 ++++++++++++++----------
9566 1 file changed, 14 insertions(+), 10 deletions(-)
9567
9568diff --git a/src/database.c b/src/database.c
9569index 5546091..f1f6ae0 100644
9570--- a/src/database.c
9571+++ b/src/database.c
9572@@ -1360,8 +1360,8 @@ static int __loc_database_enumerator_next_network_flattened(
9573 return -1;
9574 }
9575
9576- // Merge excluded list with subnets
9577- r = loc_network_list_merge(subnets, excluded);
9578+ // Merge subnets onto the stack
9579+ r = loc_network_list_merge(enumerator->stack, subnets);
9580 if (r) {
9581 loc_network_list_unref(subnets);
9582 loc_network_list_unref(excluded);
9583@@ -1369,17 +1369,21 @@ static int __loc_database_enumerator_next_network_flattened(
9584 return r;
9585 }
9586
9587- // We no longer need the excluded list
9588- loc_network_list_unref(excluded);
9589-
9590- // Replace network with the first one
9591- loc_network_unref(*network);
9592+ // Push excluded list onto the stack
9593+ r = loc_network_list_merge(enumerator->stack, excluded);
9594+ if (r) {
9595+ loc_network_list_unref(subnets);
9596+ loc_network_list_unref(excluded);
9597
9598- *network = loc_network_list_pop_first(subnets);
9599+ return r;
9600+ }
9601
9602- // Push the rest onto the stack
9603- loc_network_list_merge(enumerator->stack, subnets);
9604 loc_network_list_unref(subnets);
9605+ loc_network_list_unref(excluded);
9606+
9607+ // Replace network with the first one from the stack
9608+ loc_network_unref(*network);
9609+ *network = loc_network_list_pop_first(enumerator->stack);
9610
9611 return 0;
9612 }
9613--
96142.20.1
9615
9616From 04cbd2bfa892fc7374ad506ec7ba81727c5a4b96 Mon Sep 17 00:00:00 2001
9617From: Michael Tremer <michael.tremer@ipfire.org>
9618Date: Tue, 24 Nov 2020 15:22:02 +0000
9619Subject: [PATCH 090/111] database: Read the first element from the list
9620
9621Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
9622---
9623 src/database.c | 2 +-
9624 1 file changed, 1 insertion(+), 1 deletion(-)
9625
9626diff --git a/src/database.c b/src/database.c
9627index f1f6ae0..914ed3e 100644
9628--- a/src/database.c
9629+++ b/src/database.c
9630@@ -1191,7 +1191,7 @@ static int __loc_database_enumerator_next_network(
9631 struct loc_database_enumerator* enumerator, struct loc_network** network, int filter) {
9632 // Return top element from the stack
9633 while (1) {
9634- *network = loc_network_list_pop(enumerator->stack);
9635+ *network = loc_network_list_pop_first(enumerator->stack);
9636
9637 // Stack is empty
9638 if (!*network)
9639--
96402.20.1
9641
9642From c650008e2dd9af5fd1eadba6354aa0b615047f84 Mon Sep 17 00:00:00 2001
9643From: Michael Tremer <michael.tremer@ipfire.org>
9644Date: Tue, 24 Nov 2020 15:41:53 +0000
9645Subject: [PATCH 091/111] network: Add excluded networks to to_check list
9646
9647This is now being done immediately instead of creating a new
9648list which is being merged later.
9649
9650Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
9651---
9652 src/network.c | 55 ++++++++++++++++++++++++++++++---------------------
9653 1 file changed, 32 insertions(+), 23 deletions(-)
9654
9655diff --git a/src/network.c b/src/network.c
9656index 38d557a..7ab22f8 100644
9657--- a/src/network.c
9658+++ b/src/network.c
9659@@ -640,49 +640,55 @@ ERROR:
9660 return r;
9661 }
9662
9663-LOC_EXPORT struct loc_network_list* loc_network_exclude(
9664- struct loc_network* self, struct loc_network* other) {
9665- struct loc_network_list* list;
9666-
9667-#ifdef ENABLE_DEBUG
9668- char* n1 = loc_network_str(self);
9669- char* n2 = loc_network_str(other);
9670-
9671- DEBUG(self->ctx, "Returning %s excluding %s...\n", n1, n2);
9672-
9673- free(n1);
9674- free(n2);
9675-#endif
9676-
9677+static int __loc_network_exclude_to_list(struct loc_network* self,
9678+ struct loc_network* other, struct loc_network_list* list) {
9679 // Family must match
9680 if (self->family != other->family) {
9681 DEBUG(self->ctx, "Family mismatch\n");
9682
9683- return NULL;
9684+ return 1;
9685 }
9686
9687 // Other must be a subnet of self
9688 if (!loc_network_is_subnet(self, other)) {
9689 DEBUG(self->ctx, "Network %p is not contained in network %p\n", other, self);
9690
9691- return NULL;
9692+ return 1;
9693 }
9694
9695 // We cannot perform this operation if both networks equal
9696 if (loc_network_eq(self, other)) {
9697 DEBUG(self->ctx, "Networks %p and %p are equal\n", self, other);
9698
9699- return NULL;
9700+ return 1;
9701 }
9702
9703+ return __loc_network_exclude(self, other, list);
9704+}
9705+
9706+LOC_EXPORT struct loc_network_list* loc_network_exclude(
9707+ struct loc_network* self, struct loc_network* other) {
9708+ struct loc_network_list* list;
9709+
9710+#ifdef ENABLE_DEBUG
9711+ char* n1 = loc_network_str(self);
9712+ char* n2 = loc_network_str(other);
9713+
9714+ DEBUG(self->ctx, "Returning %s excluding %s...\n", n1, n2);
9715+
9716+ free(n1);
9717+ free(n2);
9718+#endif
9719+
9720 // Create a new list with the result
9721 int r = loc_network_list_new(self->ctx, &list);
9722 if (r) {
9723 ERROR(self->ctx, "Could not create network list: %d\n", r);
9724+
9725 return NULL;
9726 }
9727
9728- r = __loc_network_exclude(self, other, list);
9729+ r = __loc_network_exclude_to_list(self, other, list);
9730 if (r) {
9731 loc_network_list_unref(list);
9732
9733@@ -709,11 +715,14 @@ LOC_EXPORT struct loc_network_list* loc_network_exclude_list(
9734 subnet = loc_network_list_get(list, i);
9735
9736 // Find all excluded networks
9737- struct loc_network_list* excluded = loc_network_exclude(network, subnet);
9738- if (excluded) {
9739- // Add them all to the "to check" list
9740- loc_network_list_merge(to_check, excluded);
9741- loc_network_list_unref(excluded);
9742+ if (!loc_network_list_contains(to_check, subnet)) {
9743+ r = __loc_network_exclude_to_list(network, subnet, to_check);
9744+ if (r) {
9745+ loc_network_list_unref(to_check);
9746+ loc_network_unref(subnet);
9747+
9748+ return NULL;
9749+ }
9750 }
9751
9752 // Cleanup
9753--
97542.20.1
9755
9756From 7c6983ad52724d395446bdbd24d36b2ce22aecfd Mon Sep 17 00:00:00 2001
9757From: Michael Tremer <michael.tremer@ipfire.org>
9758Date: Tue, 24 Nov 2020 15:42:54 +0000
9759Subject: [PATCH 092/111] test: Add more networks to list to see the algorithm
9760 work
9761
9762Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
9763---
9764 src/test-network-list.c | 32 +++++++++++++++++++++++++++++++-
9765 1 file changed, 31 insertions(+), 1 deletion(-)
9766
9767diff --git a/src/test-network-list.c b/src/test-network-list.c
9768index 3061d63..8253fc7 100644
9769--- a/src/test-network-list.c
9770+++ b/src/test-network-list.c
9771@@ -58,6 +58,20 @@ int main(int argc, char** argv) {
9772 exit(EXIT_FAILURE);
9773 }
9774
9775+ struct loc_network* subnet3;
9776+ err = loc_network_new_from_string(ctx, &subnet3, "2001:db8:c::/48");
9777+ if (err) {
9778+ fprintf(stderr, "Could not create the subnet3\n");
9779+ exit(EXIT_FAILURE);
9780+ }
9781+
9782+ struct loc_network* subnet4;
9783+ err = loc_network_new_from_string(ctx, &subnet4, "2001:db8:d::/48");
9784+ if (err) {
9785+ fprintf(stderr, "Could not create the subnet4\n");
9786+ exit(EXIT_FAILURE);
9787+ }
9788+
9789 // Make a list with both subnets
9790 struct loc_network_list* subnets;
9791 err = loc_network_list_new(ctx, &subnets);
9792@@ -89,8 +103,24 @@ int main(int argc, char** argv) {
9793 exit(EXIT_FAILURE);
9794 }
9795
9796+ // Add the fourth one next
9797+ err = loc_network_list_push(subnets, subnet4);
9798+ if (err) {
9799+ fprintf(stderr, "Could not add subnet4 to subnets list\n");
9800+ exit(EXIT_FAILURE);
9801+ }
9802+
9803+ // Add the third one
9804+ err = loc_network_list_push(subnets, subnet3);
9805+ if (err) {
9806+ fprintf(stderr, "Could not add subnet3 to subnets list\n");
9807+ exit(EXIT_FAILURE);
9808+ }
9809+
9810+ loc_network_list_dump(subnets);
9811+
9812 size = loc_network_list_size(subnets);
9813- if (size != 2) {
9814+ if (size != 4) {
9815 fprintf(stderr, "Network list is reporting an incorrect size: %zu\n", size);
9816 exit(EXIT_FAILURE);
9817 }
9818--
98192.20.1
9820
9821From da101d55e66ebaeeed8b0b16829a2022a1af0678 Mon Sep 17 00:00:00 2001
9822From: Michael Tremer <michael.tremer@ipfire.org>
9823Date: Tue, 24 Nov 2020 15:48:55 +0000
9824Subject: [PATCH 093/111] Drop loc_network_eq in favour of loc_network_cmp
9825
9826Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
9827---
9828 src/libloc.sym | 1 -
9829 src/loc/network.h | 1 -
9830 src/network.c | 24 ++++--------------------
9831 src/test-network.c | 8 ++++----
9832 4 files changed, 8 insertions(+), 26 deletions(-)
9833
9834diff --git a/src/libloc.sym b/src/libloc.sym
9835index 4b0ce45..d8e8f14 100644
9836--- a/src/libloc.sym
9837+++ b/src/libloc.sym
9838@@ -107,7 +107,6 @@ global:
9839 # Network
9840 loc_network_address_family;
9841 loc_network_cmp;
9842- loc_network_eq;
9843 loc_network_exclude;
9844 loc_network_exclude_list;
9845 loc_network_format_first_address;
9846diff --git a/src/loc/network.h b/src/loc/network.h
9847index 8ab1562..d5d0ccd 100644
9848--- a/src/loc/network.h
9849+++ b/src/loc/network.h
9850@@ -59,7 +59,6 @@ int loc_network_set_flag(struct loc_network* network, uint32_t flag);
9851 int loc_network_match_flag(struct loc_network* network, uint32_t flag);
9852
9853 int loc_network_cmp(struct loc_network* self, struct loc_network* other);
9854-int loc_network_eq(struct loc_network* self, struct loc_network* other);
9855 int loc_network_gt(struct loc_network* self, struct loc_network* other);
9856 int loc_network_overlaps(struct loc_network* self, struct loc_network* other);
9857 int loc_network_is_subnet(struct loc_network* self, struct loc_network* other);
9858diff --git a/src/network.c b/src/network.c
9859index 7ab22f8..503bf3d 100644
9860--- a/src/network.c
9861+++ b/src/network.c
9862@@ -463,22 +463,6 @@ LOC_EXPORT int loc_network_cmp(struct loc_network* self, struct loc_network* oth
9863 return 0;
9864 }
9865
9866-LOC_EXPORT int loc_network_eq(struct loc_network* self, struct loc_network* other) {
9867- // Family must be the same
9868- if (self->family != other->family)
9869- return 0;
9870-
9871- // The start address must be the same
9872- if (in6_addr_cmp(&self->first_address, &other->first_address) != 0)
9873- return 0;
9874-
9875- // The prefix length must be the same
9876- if (self->prefix != other->prefix)
9877- return 0;
9878-
9879- return 1;
9880-}
9881-
9882 LOC_EXPORT int loc_network_gt(struct loc_network* self, struct loc_network* other) {
9883 // Families must match
9884 if (self->family != other->family)
9885@@ -596,12 +580,12 @@ static int __loc_network_exclude(struct loc_network* network,
9886 if (r)
9887 goto ERROR;
9888
9889- if (loc_network_eq(other, subnet1)) {
9890+ if (loc_network_cmp(other, subnet1) == 0) {
9891 r = loc_network_list_push(list, subnet2);
9892 if (r)
9893 goto ERROR;
9894
9895- } else if (loc_network_eq(other, subnet2)) {
9896+ } else if (loc_network_cmp(other, subnet2) == 0) {
9897 r = loc_network_list_push(list, subnet1);
9898 if (r)
9899 goto ERROR;
9900@@ -657,7 +641,7 @@ static int __loc_network_exclude_to_list(struct loc_network* self,
9901 }
9902
9903 // We cannot perform this operation if both networks equal
9904- if (loc_network_eq(self, other)) {
9905+ if (loc_network_cmp(self, other) == 0) {
9906 DEBUG(self->ctx, "Networks %p and %p are equal\n", self, other);
9907
9908 return 1;
9909@@ -745,7 +729,7 @@ LOC_EXPORT struct loc_network_list* loc_network_exclude_list(
9910 subnet = loc_network_list_get(list, i);
9911
9912 // Drop this subnet if is is already in list
9913- if (loc_network_eq(subnet_to_check, subnet)) {
9914+ if (loc_network_cmp(subnet_to_check, subnet) == 0) {
9915 passed = 0;
9916 loc_network_unref(subnet);
9917 break;
9918diff --git a/src/test-network.c b/src/test-network.c
9919index 8a6763c..f4cf97b 100644
9920--- a/src/test-network.c
9921+++ b/src/test-network.c
9922@@ -125,14 +125,14 @@ int main(int argc, char** argv) {
9923 #endif
9924
9925 // Check equals function
9926- err = loc_network_eq(network1, network1);
9927- if (!err) {
9928+ err = loc_network_cmp(network1, network1);
9929+ if (err) {
9930 fprintf(stderr, "Network is not equal with itself\n");
9931 exit(EXIT_FAILURE);
9932 }
9933
9934- err = loc_network_eq(network1, network2);
9935- if (err) {
9936+ err = loc_network_cmp(network1, network2);
9937+ if (!err) {
9938 fprintf(stderr, "Networks equal unexpectedly\n");
9939 exit(EXIT_FAILURE);
9940 }
9941--
99422.20.1
9943
9944From 61a6f6e4bf4493236d796e94f3d721bcf5ba68aa Mon Sep 17 00:00:00 2001
9945From: Michael Tremer <michael.tremer@ipfire.org>
9946Date: Tue, 24 Nov 2020 15:50:39 +0000
9947Subject: [PATCH 094/111] Drop loc_network_gt which is now unused
9948
9949Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
9950---
9951 src/libloc.sym | 1 -
9952 src/loc/network.h | 1 -
9953 src/network.c | 27 ---------------------------
9954 3 files changed, 29 deletions(-)
9955
9956diff --git a/src/libloc.sym b/src/libloc.sym
9957index d8e8f14..cb5e8ef 100644
9958--- a/src/libloc.sym
9959+++ b/src/libloc.sym
9960@@ -115,7 +115,6 @@ global:
9961 loc_network_get_country_code;
9962 loc_network_get_first_address;
9963 loc_network_get_last_address;
9964- loc_network_gt;
9965 loc_network_has_flag;
9966 loc_network_is_subnet;
9967 loc_network_match_asn;
9968diff --git a/src/loc/network.h b/src/loc/network.h
9969index d5d0ccd..af3dafd 100644
9970--- a/src/loc/network.h
9971+++ b/src/loc/network.h
9972@@ -59,7 +59,6 @@ int loc_network_set_flag(struct loc_network* network, uint32_t flag);
9973 int loc_network_match_flag(struct loc_network* network, uint32_t flag);
9974
9975 int loc_network_cmp(struct loc_network* self, struct loc_network* other);
9976-int loc_network_gt(struct loc_network* self, struct loc_network* other);
9977 int loc_network_overlaps(struct loc_network* self, struct loc_network* other);
9978 int loc_network_is_subnet(struct loc_network* self, struct loc_network* other);
9979 int loc_network_subnets(struct loc_network* network, struct loc_network** subnet1, struct loc_network** subnet2);
9980diff --git a/src/network.c b/src/network.c
9981index 503bf3d..ac478d5 100644
9982--- a/src/network.c
9983+++ b/src/network.c
9984@@ -463,33 +463,6 @@ LOC_EXPORT int loc_network_cmp(struct loc_network* self, struct loc_network* oth
9985 return 0;
9986 }
9987
9988-LOC_EXPORT int loc_network_gt(struct loc_network* self, struct loc_network* other) {
9989- // Families must match
9990- if (self->family != other->family)
9991- return -1;
9992-
9993- int r = in6_addr_cmp(&self->first_address, &other->first_address);
9994-
9995- switch (r) {
9996- // Smaller
9997- case -1:
9998- return 0;
9999-
10000- // Larger
10001- case 1:
10002- return 1;
10003-
10004- default:
10005- break;
10006- }
10007-
10008- if (self->prefix > other->prefix)
10009- return 1;
10010-
10011- // Dunno
10012- return 0;
10013-}
10014-
10015 LOC_EXPORT int loc_network_overlaps(struct loc_network* self, struct loc_network* other) {
10016 if (loc_network_match_address(self, &other->first_address) == 0)
10017 return 1;
10018--
100192.20.1
10020
10021From fc692a58d9f4ca958f88cfa202250c572a0af6ea Mon Sep 17 00:00:00 2001
10022From: Michael Tremer <michael.tremer@ipfire.org>
10023Date: Tue, 24 Nov 2020 16:50:17 +0000
10024Subject: [PATCH 095/111] network: Adjust return codes of
10025 loc_network_match_address and add test
10026
10027Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
10028---
10029 src/database.c | 3 +--
10030 src/libloc.sym | 1 +
10031 src/network.c | 16 +++++++++-------
10032 src/test-network.c | 14 ++++++++++++++
10033 4 files changed, 25 insertions(+), 9 deletions(-)
10034
10035diff --git a/src/database.c b/src/database.c
10036index 914ed3e..1871b74 100644
10037--- a/src/database.c
10038+++ b/src/database.c
10039@@ -776,8 +776,7 @@ static int __loc_database_lookup_handle_leaf(struct loc_database* db, const stru
10040 }
10041
10042 // Check if the given IP address is inside the network
10043- r = loc_network_match_address(*network, address);
10044- if (r) {
10045+ if (!loc_network_match_address(*network, address)) {
10046 DEBUG(db->ctx, "Searched address is not part of the network\n");
10047
10048 loc_network_unref(*network);
10049diff --git a/src/libloc.sym b/src/libloc.sym
10050index cb5e8ef..ee333f1 100644
10051--- a/src/libloc.sym
10052+++ b/src/libloc.sym
10053@@ -117,6 +117,7 @@ global:
10054 loc_network_get_last_address;
10055 loc_network_has_flag;
10056 loc_network_is_subnet;
10057+ loc_network_match_address;
10058 loc_network_match_asn;
10059 loc_network_match_country_code;
10060 loc_network_match_flag;
10061diff --git a/src/network.c b/src/network.c
10062index ac478d5..febab95 100644
10063--- a/src/network.c
10064+++ b/src/network.c
10065@@ -374,14 +374,14 @@ LOC_EXPORT char* loc_network_format_last_address(struct loc_network* network) {
10066 LOC_EXPORT int loc_network_match_address(struct loc_network* network, const struct in6_addr* address) {
10067 // Address must be larger than the start address
10068 if (in6_addr_cmp(&network->first_address, address) > 0)
10069- return 1;
10070+ return 0;
10071
10072 // Address must be smaller than the last address
10073 if (in6_addr_cmp(&network->last_address, address) < 0)
10074- return 1;
10075+ return 0;
10076
10077 // The address is inside this network
10078- return 0;
10079+ return 1;
10080 }
10081
10082 LOC_EXPORT const char* loc_network_get_country_code(struct loc_network* network) {
10083@@ -464,16 +464,18 @@ LOC_EXPORT int loc_network_cmp(struct loc_network* self, struct loc_network* oth
10084 }
10085
10086 LOC_EXPORT int loc_network_overlaps(struct loc_network* self, struct loc_network* other) {
10087- if (loc_network_match_address(self, &other->first_address) == 0)
10088+ // Either of the start addresses must be in the other subnet
10089+ if (loc_network_match_address(self, &other->first_address))
10090 return 1;
10091
10092- if (loc_network_match_address(self, &other->last_address) == 0)
10093+ if (loc_network_match_address(other, &self->first_address))
10094 return 1;
10095
10096- if (loc_network_match_address(other, &self->first_address) == 0)
10097+ // Or either of the end addresses is in the other subnet
10098+ if (loc_network_match_address(self, &other->last_address))
10099 return 1;
10100
10101- if (loc_network_match_address(other, &self->last_address) == 0)
10102+ if (loc_network_match_address(other, &self->last_address))
10103 return 1;
10104
10105 return 0;
10106diff --git a/src/test-network.c b/src/test-network.c
10107index f4cf97b..339743d 100644
10108--- a/src/test-network.c
10109+++ b/src/test-network.c
10110@@ -14,6 +14,7 @@
10111 GNU General Public License for more details.
10112 */
10113
10114+#include <arpa/inet.h>
10115 #include <errno.h>
10116 #include <stdio.h>
10117 #include <stddef.h>
10118@@ -46,6 +47,13 @@ int main(int argc, char** argv) {
10119 }
10120 #endif
10121
10122+ struct in6_addr address;
10123+ err = inet_pton(AF_INET6, "2001:db8::1", &address);
10124+ if (err != 1) {
10125+ fprintf(stderr, "Could not parse IP address\n");
10126+ exit(EXIT_FAILURE);
10127+ }
10128+
10129 // Create a network
10130 struct loc_network* network1;
10131 err = loc_network_new_from_string(ctx, &network1, "2001:db8::1/32");
10132@@ -92,6 +100,12 @@ int main(int argc, char** argv) {
10133 exit(EXIT_FAILURE);
10134 }
10135
10136+ err = loc_network_match_address(network1, &address);
10137+ if (!err) {
10138+ fprintf(stderr, "Network1 does not match address\n");
10139+ exit(EXIT_FAILURE);
10140+ }
10141+
10142 struct loc_network* network2;
10143 err = loc_network_new_from_string(ctx, &network2, "2001:db8:ffff::/48");
10144 if (err) {
10145--
101462.20.1
10147
10148From 06177d8c6004bf8b54322d92926152a7656f9c2a Mon Sep 17 00:00:00 2001
10149From: Michael Tremer <michael.tremer@ipfire.org>
10150Date: Tue, 24 Nov 2020 16:57:28 +0000
10151Subject: [PATCH 096/111] network-list: Use binary search to find if a network
10152 is a subnet
10153
10154Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
10155---
10156 src/network.c | 13 ++++++-------
10157 1 file changed, 6 insertions(+), 7 deletions(-)
10158
10159diff --git a/src/network.c b/src/network.c
10160index febab95..394bafc 100644
10161--- a/src/network.c
10162+++ b/src/network.c
10163@@ -697,19 +697,18 @@ LOC_EXPORT struct loc_network_list* loc_network_exclude_list(
10164 while (!loc_network_list_empty(to_check)) {
10165 struct loc_network* subnet_to_check = loc_network_list_pop(to_check);
10166
10167+ // Check whether the subnet to check is part of the input list
10168+ if (loc_network_list_contains(list, subnet_to_check)) {
10169+ loc_network_unref(subnet_to_check);
10170+ continue;
10171+ }
10172+
10173 // Marks whether this subnet passed all checks
10174 int passed = 1;
10175
10176 for (unsigned int i = 0; i < loc_network_list_size(list); i++) {
10177 subnet = loc_network_list_get(list, i);
10178
10179- // Drop this subnet if is is already in list
10180- if (loc_network_cmp(subnet_to_check, subnet) == 0) {
10181- passed = 0;
10182- loc_network_unref(subnet);
10183- break;
10184- }
10185-
10186 // Drop this subnet if is a subnet of another subnet
10187 if (loc_network_is_subnet(subnet_to_check, subnet)) {
10188 passed = 0;
10189--
101902.20.1
10191
10192From 77e6d5379ea0de3264be5b8918d620d16e6bcbd3 Mon Sep 17 00:00:00 2001
10193From: Michael Tremer <michael.tremer@ipfire.org>
10194Date: Tue, 24 Nov 2020 19:39:35 +0000
10195Subject: [PATCH 097/111] network-list: Check last element before doing binary
10196 search
10197
10198This is helpful because very often we walk through a list in
10199order and are most interested in the last element.
10200
10201Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
10202---
10203 src/network-list.c | 24 ++++++++++++++++++++++--
10204 1 file changed, 22 insertions(+), 2 deletions(-)
10205
10206diff --git a/src/network-list.c b/src/network-list.c
10207index 7e8b5f3..c86ad07 100644
10208--- a/src/network-list.c
10209+++ b/src/network-list.c
10210@@ -137,8 +137,26 @@ static off_t loc_network_list_find(struct loc_network_list* list,
10211 struct loc_network* network, int* found) {
10212 off_t lo = 0;
10213 off_t hi = list->size - 1;
10214+ int result;
10215
10216- *found = 0;
10217+ // Since we are working on an ordered list, there is often a good chance that
10218+ // the network we are looking for is at the end or has to go to the end.
10219+ if (hi >= 0) {
10220+ result = loc_network_cmp(network, list->elements[hi]);
10221+
10222+ // Match, so we are done
10223+ if (result == 0) {
10224+ *found = 1;
10225+
10226+ return hi;
10227+
10228+ // This needs to be added after the last one
10229+ } else if (result > 0) {
10230+ *found = 0;
10231+
10232+ return hi + 1;
10233+ }
10234+ }
10235
10236 #ifdef ENABLE_DEBUG
10237 // Save start time
10238@@ -151,7 +169,7 @@ static off_t loc_network_list_find(struct loc_network_list* list,
10239 i = (lo + hi) / 2;
10240
10241 // Check if this is a match
10242- int result = loc_network_cmp(network, list->elements[i]);
10243+ result = loc_network_cmp(network, list->elements[i]);
10244
10245 if (result == 0) {
10246 *found = 1;
10247@@ -173,6 +191,8 @@ static off_t loc_network_list_find(struct loc_network_list* list,
10248 hi = i - 1;
10249 }
10250
10251+ *found = 0;
10252+
10253 #ifdef ENABLE_DEBUG
10254 clock_t end = clock();
10255
10256--
102572.20.1
10258
10259From d42f34ce9b0aa2382ae9b852882c62b34d367cfe Mon Sep 17 00:00:00 2001
10260From: Michael Tremer <michael.tremer@ipfire.org>
10261Date: Wed, 25 Nov 2020 14:41:39 +0000
10262Subject: [PATCH 098/111] network-list: Set elements pointer to NULL so that we
10263 know it is empty
10264
10265Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
10266---
10267 src/network-list.c | 1 +
10268 1 file changed, 1 insertion(+)
10269
10270diff --git a/src/network-list.c b/src/network-list.c
10271index c86ad07..2c4edb3 100644
10272--- a/src/network-list.c
10273+++ b/src/network-list.c
10274@@ -104,6 +104,7 @@ LOC_EXPORT void loc_network_list_clear(struct loc_network_list* list) {
10275 loc_network_unref(list->elements[i]);
10276
10277 free(list->elements);
10278+ list->elements = NULL;
10279 list->elements_size = 0;
10280
10281 list->size = 0;
10282--
102832.20.1
10284
10285From 673e03f7bfc807248a769cb00ec80f0fa2af7a25 Mon Sep 17 00:00:00 2001
10286From: Michael Tremer <michael.tremer@ipfire.org>
10287Date: Wed, 25 Nov 2020 14:42:26 +0000
10288Subject: [PATCH 099/111] network-list: Do not half list when popping the first
10289 element
10290
10291The list was unfortunately halved in size every time an element
10292was taken from it, which was great for performance, but shortened
10293the result substantially.
10294
10295Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
10296---
10297 src/network-list.c | 5 ++++-
10298 1 file changed, 4 insertions(+), 1 deletion(-)
10299
10300diff --git a/src/network-list.c b/src/network-list.c
10301index 2c4edb3..f4a9d05 100644
10302--- a/src/network-list.c
10303+++ b/src/network-list.c
10304@@ -261,10 +261,13 @@ LOC_EXPORT struct loc_network* loc_network_list_pop_first(struct loc_network_lis
10305 struct loc_network* network = list->elements[0];
10306
10307 // Move all elements to the top of the stack
10308- for (unsigned int i = 0; i < --list->size; i++) {
10309+ for (unsigned int i = 0; i < list->size - 1; i++) {
10310 list->elements[i] = list->elements[i+1];
10311 }
10312
10313+ // The list is shorter now
10314+ --list->size;
10315+
10316 DEBUG(list->ctx, "%p: Popping network %p from stack\n", list, network);
10317
10318 return network;
10319--
103202.20.1
10321
10322From 9446c7538ab8b27486d74f6dc0dac8bb5c1bbe92 Mon Sep 17 00:00:00 2001
10323From: Michael Tremer <michael.tremer@ipfire.org>
10324Date: Wed, 25 Nov 2020 14:43:58 +0000
10325Subject: [PATCH 100/111] network-list: Show index when listing networks
10326
10327Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
10328---
10329 src/network-list.c | 2 +-
10330 1 file changed, 1 insertion(+), 1 deletion(-)
10331
10332diff --git a/src/network-list.c b/src/network-list.c
10333index f4a9d05..cf9459d 100644
10334--- a/src/network-list.c
10335+++ b/src/network-list.c
10336@@ -119,7 +119,7 @@ LOC_EXPORT void loc_network_list_dump(struct loc_network_list* list) {
10337
10338 s = loc_network_str(network);
10339
10340- INFO(list->ctx, "%s\n", s);
10341+ INFO(list->ctx, "%4d: %s\n", i, s);
10342 free(s);
10343 }
10344 }
10345--
103462.20.1
10347
10348From dc31666be416dbb3bd2bc04127104a3f75b42d5c Mon Sep 17 00:00:00 2001
10349From: Michael Tremer <michael.tremer@ipfire.org>
10350Date: Wed, 25 Nov 2020 14:44:23 +0000
10351Subject: [PATCH 101/111] network-list: Remove useless comment
10352
10353Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
10354---
10355 src/network-list.c | 2 --
10356 1 file changed, 2 deletions(-)
10357
10358diff --git a/src/network-list.c b/src/network-list.c
10359index cf9459d..bd3d64e 100644
10360--- a/src/network-list.c
10361+++ b/src/network-list.c
10362@@ -132,8 +132,6 @@ LOC_EXPORT struct loc_network* loc_network_list_get(struct loc_network_list* lis
10363 return loc_network_ref(list->elements[index]);
10364 }
10365
10366-//MOVE FUNCTION GOES HERE
10367-
10368 static off_t loc_network_list_find(struct loc_network_list* list,
10369 struct loc_network* network, int* found) {
10370 off_t lo = 0;
10371--
103722.20.1
10373
10374From 82fa4c92c88cc172953198637bccc375c4d25d20 Mon Sep 17 00:00:00 2001
10375From: Michael Tremer <michael.tremer@ipfire.org>
10376Date: Wed, 25 Nov 2020 14:44:56 +0000
10377Subject: [PATCH 102/111] networks: Add tests for overlaps function
10378
10379Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
10380---
10381 src/test-network.c | 10 ++++++++++
10382 1 file changed, 10 insertions(+)
10383
10384diff --git a/src/test-network.c b/src/test-network.c
10385index 339743d..dde13f1 100644
10386--- a/src/test-network.c
10387+++ b/src/test-network.c
10388@@ -192,6 +192,16 @@ int main(int argc, char** argv) {
10389 exit(EXIT_FAILURE);
10390 }
10391
10392+ if (!loc_network_overlaps(network1, subnet1)) {
10393+ fprintf(stderr, "Network1 does not seem to contain subnet1\n");
10394+ exit(EXIT_FAILURE);
10395+ }
10396+
10397+ if (!loc_network_overlaps(network1, subnet2)) {
10398+ fprintf(stderr, "Network1 does not seem to contain subnet2\n");
10399+ exit(EXIT_FAILURE);
10400+ }
10401+
10402 loc_network_unref(subnet1);
10403 loc_network_unref(subnet2);
10404
10405--
104062.20.1
10407
10408From 0a39d5499ae0c343a6600ea30de7d95e384ef911 Mon Sep 17 00:00:00 2001
10409From: Michael Tremer <michael.tremer@ipfire.org>
10410Date: Wed, 25 Nov 2020 15:11:21 +0000
10411Subject: [PATCH 103/111] networks: Remove comparing family
10412
10413Everything is encoded in IPv6 anyways...
10414
10415Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
10416---
10417 src/network.c | 17 -----------------
10418 1 file changed, 17 deletions(-)
10419
10420diff --git a/src/network.c b/src/network.c
10421index 394bafc..66b460f 100644
10422--- a/src/network.c
10423+++ b/src/network.c
10424@@ -442,12 +442,6 @@ LOC_EXPORT int loc_network_match_flag(struct loc_network* network, uint32_t flag
10425 }
10426
10427 LOC_EXPORT int loc_network_cmp(struct loc_network* self, struct loc_network* other) {
10428- // Compare family
10429- if (self->family > other->family)
10430- return 1;
10431- else if (self->family < other->family)
10432- return -1;
10433-
10434 // Compare address
10435 int r = in6_addr_cmp(&self->first_address, &other->first_address);
10436 if (r)
10437@@ -482,10 +476,6 @@ LOC_EXPORT int loc_network_overlaps(struct loc_network* self, struct loc_network
10438 }
10439
10440 LOC_EXPORT int loc_network_is_subnet(struct loc_network* self, struct loc_network* other) {
10441- // Check family
10442- if (self->family != other->family)
10443- return 0;
10444-
10445 // The prefix must be smaller (this avoids the more complex comparisons later)
10446 if (self->prefix > other->prefix)
10447 return 0;
10448@@ -601,13 +591,6 @@ ERROR:
10449
10450 static int __loc_network_exclude_to_list(struct loc_network* self,
10451 struct loc_network* other, struct loc_network_list* list) {
10452- // Family must match
10453- if (self->family != other->family) {
10454- DEBUG(self->ctx, "Family mismatch\n");
10455-
10456- return 1;
10457- }
10458-
10459 // Other must be a subnet of self
10460 if (!loc_network_is_subnet(self, other)) {
10461 DEBUG(self->ctx, "Network %p is not contained in network %p\n", other, self);
10462--
104632.20.1
10464
10465From abf559267696061a0c9723d8f8e09c9d1aa8fb75 Mon Sep 17 00:00:00 2001
10466From: Michael Tremer <michael.tremer@ipfire.org>
10467Date: Wed, 25 Nov 2020 15:13:08 +0000
10468Subject: [PATCH 104/111] network: Do not execute with an error when the
10469 excluded result will be empty
10470
10471Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
10472---
10473 src/network.c | 6 ++++--
10474 1 file changed, 4 insertions(+), 2 deletions(-)
10475
10476diff --git a/src/network.c b/src/network.c
10477index 66b460f..9aa802f 100644
10478--- a/src/network.c
10479+++ b/src/network.c
10480@@ -595,14 +595,16 @@ static int __loc_network_exclude_to_list(struct loc_network* self,
10481 if (!loc_network_is_subnet(self, other)) {
10482 DEBUG(self->ctx, "Network %p is not contained in network %p\n", other, self);
10483
10484- return 1;
10485+ // Exit silently
10486+ return 0;
10487 }
10488
10489 // We cannot perform this operation if both networks equal
10490 if (loc_network_cmp(self, other) == 0) {
10491 DEBUG(self->ctx, "Networks %p and %p are equal\n", self, other);
10492
10493- return 1;
10494+ // Exit silently
10495+ return 0;
10496 }
10497
10498 return __loc_network_exclude(self, other, list);
10499--
105002.20.1
10501
10502From 4fc034e20fdc36267f6ba18e27776fed747fe983 Mon Sep 17 00:00:00 2001
10503From: Michael Tremer <michael.tremer@ipfire.org>
10504Date: Wed, 25 Nov 2020 15:14:31 +0000
10505Subject: [PATCH 105/111] network: Add more excluded networks straight to the
10506 to_check list
10507
10508Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
10509---
10510 src/network.c | 6 +-----
10511 1 file changed, 1 insertion(+), 5 deletions(-)
10512
10513diff --git a/src/network.c b/src/network.c
10514index 9aa802f..19c387d 100644
10515--- a/src/network.c
10516+++ b/src/network.c
10517@@ -705,11 +705,7 @@ LOC_EXPORT struct loc_network_list* loc_network_exclude_list(
10518 if (loc_network_overlaps(subnet_to_check, subnet)) {
10519 passed = 0;
10520
10521- struct loc_network_list* excluded = loc_network_exclude(subnet_to_check, subnet);
10522- if (excluded) {
10523- loc_network_list_merge(to_check, excluded);
10524- loc_network_list_unref(excluded);
10525- }
10526+ __loc_network_exclude_to_list(subnet_to_check, subnet, to_check);
10527
10528 loc_network_unref(subnet);
10529 break;
10530--
105312.20.1
10532
10533From 4de8ff8e5435225d3375a168054490d2a66b1baf Mon Sep 17 00:00:00 2001
10534From: Michael Tremer <michael.tremer@ipfire.org>
10535Date: Wed, 25 Nov 2020 15:15:33 +0000
10536Subject: [PATCH 106/111] network: Call subnet function with the correct order
10537 of arguments
10538
10539Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
10540---
10541 src/network.c | 4 ++--
10542 1 file changed, 2 insertions(+), 2 deletions(-)
10543
10544diff --git a/src/network.c b/src/network.c
10545index 19c387d..a96ce6d 100644
10546--- a/src/network.c
10547+++ b/src/network.c
10548@@ -695,14 +695,14 @@ LOC_EXPORT struct loc_network_list* loc_network_exclude_list(
10549 subnet = loc_network_list_get(list, i);
10550
10551 // Drop this subnet if is a subnet of another subnet
10552- if (loc_network_is_subnet(subnet_to_check, subnet)) {
10553+ if (loc_network_is_subnet(subnet, subnet_to_check)) {
10554 passed = 0;
10555 loc_network_unref(subnet);
10556 break;
10557 }
10558
10559 // Break it down if it overlaps
10560- if (loc_network_overlaps(subnet_to_check, subnet)) {
10561+ if (loc_network_overlaps(subnet, subnet_to_check)) {
10562 passed = 0;
10563
10564 __loc_network_exclude_to_list(subnet_to_check, subnet, to_check);
10565--
105662.20.1
10567
10568From 058e7800e56150bcf0fb8dceaae6fbab1ed239e4 Mon Sep 17 00:00:00 2001
10569From: Michael Tremer <michael.tremer@ipfire.org>
10570Date: Wed, 25 Nov 2020 15:16:06 +0000
10571Subject: [PATCH 107/111] network: Massively improve performance on exclude
10572
10573When we check the result for any overlaps, we can cut this short
10574by walking through both lists from start to end and remember the
10575last network that we checked.
10576
10577The next one will by definition be strictly greater and therefore
10578we do not need to check anything before this any more.
10579
10580Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
10581---
10582 src/network.c | 19 +++++++++++++++++--
10583 1 file changed, 17 insertions(+), 2 deletions(-)
10584
10585diff --git a/src/network.c b/src/network.c
10586index a96ce6d..10fa997 100644
10587--- a/src/network.c
10588+++ b/src/network.c
10589@@ -679,8 +679,10 @@ LOC_EXPORT struct loc_network_list* loc_network_exclude_list(
10590 return NULL;
10591 }
10592
10593+ off_t smallest_subnet = 0;
10594+
10595 while (!loc_network_list_empty(to_check)) {
10596- struct loc_network* subnet_to_check = loc_network_list_pop(to_check);
10597+ struct loc_network* subnet_to_check = loc_network_list_pop_first(to_check);
10598
10599 // Check whether the subnet to check is part of the input list
10600 if (loc_network_list_contains(list, subnet_to_check)) {
10601@@ -691,7 +693,7 @@ LOC_EXPORT struct loc_network_list* loc_network_exclude_list(
10602 // Marks whether this subnet passed all checks
10603 int passed = 1;
10604
10605- for (unsigned int i = 0; i < loc_network_list_size(list); i++) {
10606+ for (unsigned int i = smallest_subnet; i < loc_network_list_size(list); i++) {
10607 subnet = loc_network_list_get(list, i);
10608
10609 // Drop this subnet if is a subnet of another subnet
10610@@ -711,6 +713,19 @@ LOC_EXPORT struct loc_network_list* loc_network_exclude_list(
10611 break;
10612 }
10613
10614+ // If the subnet is strictly greater, we do not need to continue the search
10615+ r = loc_network_cmp(subnet, subnet_to_check);
10616+ if (r > 0) {
10617+ loc_network_unref(subnet);
10618+ break;
10619+
10620+ // If it is strictly smaller, we can continue the search from here next
10621+ // time because all networks that are to be checked can only be larger
10622+ // than this one.
10623+ } else if (r < 0) {
10624+ smallest_subnet = i;
10625+ }
10626+
10627 loc_network_unref(subnet);
10628 }
10629
10630--
106312.20.1
10632
10633From 9caf6cf5f0fd5eb56ad1678910dbc8017f48863c Mon Sep 17 00:00:00 2001
10634From: Michael Tremer <michael.tremer@ipfire.org>
10635Date: Wed, 25 Nov 2020 15:17:21 +0000
10636Subject: [PATCH 108/111] network: Remove deprecated sort call
10637
10638Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
10639---
10640 src/network.c | 3 ---
10641 1 file changed, 3 deletions(-)
10642
10643diff --git a/src/network.c b/src/network.c
10644index 10fa997..4d7ac79 100644
10645--- a/src/network.c
10646+++ b/src/network.c
10647@@ -738,9 +738,6 @@ LOC_EXPORT struct loc_network_list* loc_network_exclude_list(
10648
10649 loc_network_list_unref(to_check);
10650
10651- // Sort the result
10652- loc_network_list_sort(subnets);
10653-
10654 return subnets;
10655 }
10656
10657--
106582.20.1
10659
10660From 8ebf1d3912020d5c0ed98bb32a0640952bd6447c Mon Sep 17 00:00:00 2001
10661From: Michael Tremer <michael.tremer@ipfire.org>
10662Date: Wed, 25 Nov 2020 15:17:42 +0000
10663Subject: [PATCH 109/111] network-list: Include network header
10664
10665Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
10666---
10667 src/loc/network-list.h | 2 ++
10668 1 file changed, 2 insertions(+)
10669
10670diff --git a/src/loc/network-list.h b/src/loc/network-list.h
10671index 21c7402..bee21c4 100644
10672--- a/src/loc/network-list.h
10673+++ b/src/loc/network-list.h
10674@@ -17,6 +17,8 @@
10675 #ifndef LIBLOC_NETWORK_LIST_H
10676 #define LIBLOC_NETWORK_LIST_H
10677
10678+#include <loc/network.h>
10679+
10680 struct loc_network_list;
10681 int loc_network_list_new(struct loc_ctx* ctx, struct loc_network_list** list);
10682 struct loc_network_list* loc_network_list_ref(struct loc_network_list* list);
10683--
106842.20.1
10685
10686From fff093b6827a31ff84a6d5150bfede140b696d25 Mon Sep 17 00:00:00 2001
10687From: Michael Tremer <michael.tremer@ipfire.org>
10688Date: Wed, 25 Nov 2020 15:24:43 +0000
10689Subject: [PATCH 110/111] network-list: Use clear function to tidy up
10690
10691Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
10692---
10693 src/network-list.c | 4 ++--
10694 1 file changed, 2 insertions(+), 2 deletions(-)
10695
10696diff --git a/src/network-list.c b/src/network-list.c
10697index bd3d64e..f3458b4 100644
10698--- a/src/network-list.c
10699+++ b/src/network-list.c
10700@@ -70,8 +70,8 @@ LOC_EXPORT struct loc_network_list* loc_network_list_ref(struct loc_network_list
10701 static void loc_network_list_free(struct loc_network_list* list) {
10702 DEBUG(list->ctx, "Releasing network list at %p\n", list);
10703
10704- for (unsigned int i = 0; i < list->size; i++)
10705- loc_network_unref(list->elements[i]);
10706+ // Remove all content
10707+ loc_network_list_clear(list);
10708
10709 loc_unref(list->ctx);
10710 free(list);
10711--
107122.20.1
10713
10714From adbec5c0317a1c007a897fe3f63f0f86ff448124 Mon Sep 17 00:00:00 2001
10715From: Michael Tremer <michael.tremer@ipfire.org>
10716Date: Wed, 25 Nov 2020 20:00:46 +0000
10717Subject: [PATCH 111/111] configure: Bump version to 0.9.5
10718
10719Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
10720---
10721 configure.ac | 2 +-
10722 1 file changed, 1 insertion(+), 1 deletion(-)
10723
10724diff --git a/configure.ac b/configure.ac
10725index 2364dfd..012d8ca 100644
10726--- a/configure.ac
10727+++ b/configure.ac
10728@@ -1,6 +1,6 @@
10729 AC_PREREQ(2.60)
10730 AC_INIT([libloc],
10731- [0.9.4],
10732+ [0.9.5],
10733 [location@lists.ipfire.org],
10734 [libloc],
10735 [https://location.ipfire.org/])
10736--
107372.20.1
10738