From 44e5ef712f539bec992c92f248378fbe57b5defe Mon Sep 17 00:00:00 2001 From: Michael Tremer Date: Fri, 29 Nov 2019 19:44:25 +0000 Subject: [PATCH] location-query: Allow filtering networks by family Signed-off-by: Michael Tremer --- man/location-query.txt | 13 ++++++++----- src/database.c | 16 ++++++++++++++++ src/libloc.sym | 2 ++ src/loc/database.h | 1 + src/loc/network.h | 1 + src/network.c | 14 +++++++------- src/python/database.c | 15 +++++++++++++-- src/python/location-query.in | 17 ++++++++++++++--- 8 files changed, 62 insertions(+), 17 deletions(-) diff --git a/man/location-query.txt b/man/location-query.txt index 957dc01..7a98180 100644 --- a/man/location-query.txt +++ b/man/location-query.txt @@ -44,9 +44,12 @@ or countries. + The search will be performed case-insensitively. -'list-networks-by-as [--output-format FORMAT] ASN':: +'list-networks-by-as [--family=[ipv6|ipv4]] [--output-format FORMAT] ASN':: Lists all networks which belong to this Autonomous System. + + The '--family' parameter can be used to filter output to only IPv6 or + IPv4 addresses. + + The '--output-format' parameter can change the output so that it can be directly loaded into other software. The following options are available: + @@ -56,17 +59,17 @@ or countries. * 'xt_geoip': Returns a list of networks to be loaded into the xt_geoip kernel module -'list-networks-by-cc [--output-format FORMAT] COUNTRY_CODE':: +'list-networks-by-cc [--family=[ipv6|ipv4]] [--output-format FORMAT] COUNTRY_CODE':: Lists all networks that belong to a country. + The country has to be encoded in ISO3166 Alpha-2 notation. + - See above for usage of the '--output-format' parameter. + See above for usage of the '--family' and '--output-format' parameters. -'list-networks-by-flags [--output-format FORMAT] [--anonymous-proxy|--satellite-provider|--anycast]':: +'list-networks-by-flags [--family=[ipv6|ipv4]] [--output-format FORMAT] [--anonymous-proxy|--satellite-provider|--anycast]':: Lists all networks that have a certain flag. + - See above for usage of the '--output-format' parameter. + See above for usage of the '--family' and '--output-format' parameters. '--help':: Shows a short help text on using this program. diff --git a/src/database.c b/src/database.c index f126c60..933f1c5 100644 --- a/src/database.c +++ b/src/database.c @@ -99,6 +99,7 @@ struct loc_database_enumerator { char country_code[3]; uint32_t asn; enum loc_network_flags flags; + int family; // Index of the AS we are looking at unsigned int as_index; @@ -943,6 +944,13 @@ LOC_EXPORT int loc_database_enumerator_set_flag( return 0; } +LOC_EXPORT int loc_database_enumerator_set_family( + struct loc_database_enumerator* enumerator, int family) { + enumerator->family = family; + + return 0; +} + LOC_EXPORT int loc_database_enumerator_next_as( struct loc_database_enumerator* enumerator, struct loc_as** as) { *as = NULL; @@ -1070,6 +1078,14 @@ LOC_EXPORT int loc_database_enumerator_next_network( // Check if we are interested in this network + // Skip if the family does not match + if (enumerator->family && loc_network_address_family(*network) != enumerator->family) { + loc_network_unref(*network); + *network = NULL; + + continue; + } + // Skip if the country code does not match if (*enumerator->country_code && !loc_network_match_country_code(*network, enumerator->country_code)) { diff --git a/src/libloc.sym b/src/libloc.sym index 7fe59f1..b3d5b51 100644 --- a/src/libloc.sym +++ b/src/libloc.sym @@ -71,11 +71,13 @@ global: loc_database_enumerator_ref; loc_database_enumerator_set_asn; loc_database_enumerator_set_country_code; + loc_database_enumerator_set_family; loc_database_enumerator_set_flag; loc_database_enumerator_set_string; loc_database_enumerator_unref; # Network + loc_network_address_family; loc_network_get_asn; loc_network_get_country_code; loc_network_has_flag; diff --git a/src/loc/database.h b/src/loc/database.h index f42b432..ab9ef72 100644 --- a/src/loc/database.h +++ b/src/loc/database.h @@ -64,6 +64,7 @@ int loc_database_enumerator_set_string(struct loc_database_enumerator* enumerato int loc_database_enumerator_set_country_code(struct loc_database_enumerator* enumerator, const char* country_code); int loc_database_enumerator_set_asn(struct loc_database_enumerator* enumerator, unsigned int asn); int loc_database_enumerator_set_flag(struct loc_database_enumerator* enumerator, enum loc_network_flags flag); +int loc_database_enumerator_set_family(struct loc_database_enumerator* enumerator, int family); int loc_database_enumerator_next_as( struct loc_database_enumerator* enumerator, struct loc_as** as); int loc_database_enumerator_next_network( diff --git a/src/loc/network.h b/src/loc/network.h index 02c8ad5..ad43c3a 100644 --- a/src/loc/network.h +++ b/src/loc/network.h @@ -36,6 +36,7 @@ int loc_network_new_from_string(struct loc_ctx* ctx, struct loc_network** networ struct loc_network* loc_network_ref(struct loc_network* network); struct loc_network* loc_network_unref(struct loc_network* network); char* loc_network_str(struct loc_network* network); +int loc_network_address_family(struct loc_network* network); int loc_network_match_address(struct loc_network* network, const struct in6_addr* address); const char* loc_network_get_country_code(struct loc_network* network); diff --git a/src/network.c b/src/network.c index ad39892..8dde0ec 100644 --- a/src/network.c +++ b/src/network.c @@ -145,13 +145,6 @@ LOC_EXPORT int loc_network_new(struct loc_ctx* ctx, struct loc_network** network return 0; } -static int loc_network_address_family(struct loc_network* network) { - if (IN6_IS_ADDR_V4MAPPED(&network->start_address)) - return AF_INET; - - return AF_INET6; -} - LOC_EXPORT int loc_network_new_from_string(struct loc_ctx* ctx, struct loc_network** network, const char* address_string) { struct in6_addr start_address; @@ -273,6 +266,13 @@ LOC_EXPORT char* loc_network_str(struct loc_network* network) { return string; } +LOC_EXPORT int loc_network_address_family(struct loc_network* network) { + if (IN6_IS_ADDR_V4MAPPED(&network->start_address)) + return AF_INET; + + return AF_INET6; +} + LOC_EXPORT int loc_network_match_address(struct loc_network* network, const struct in6_addr* address) { // Address must be larger than the start address if (in6_addr_cmp(&network->start_address, address) > 0) diff --git a/src/python/database.c b/src/python/database.c index 9bd938c..2f0a3b0 100644 --- a/src/python/database.c +++ b/src/python/database.c @@ -231,12 +231,13 @@ static PyObject* Database_search_as(DatabaseObject* self, PyObject* args) { } static PyObject* Database_search_networks(DatabaseObject* self, PyObject* args, PyObject* kwargs) { - char* kwlist[] = { "country_code", "asn", "flags", NULL }; + char* kwlist[] = { "country_code", "asn", "flags", "family", NULL }; const char* country_code = NULL; unsigned int asn = 0; int flags = 0; + int family = 0; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|sii", kwlist, &country_code, &asn, &flags)) + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|siii", kwlist, &country_code, &asn, &flags, &family)) return NULL; struct loc_database_enumerator* enumerator; @@ -276,6 +277,16 @@ static PyObject* Database_search_networks(DatabaseObject* self, PyObject* args, } } + // Set the family we are searching for + if (family) { + r = loc_database_enumerator_set_family(enumerator, family); + + if (r) { + PyErr_SetFromErrno(PyExc_SystemError); + return NULL; + } + } + PyObject* obj = new_database_enumerator(&DatabaseEnumeratorType, enumerator); loc_database_enumerator_unref(enumerator); diff --git a/src/python/location-query.in b/src/python/location-query.in index c455d1e..a1ca7fe 100644 --- a/src/python/location-query.in +++ b/src/python/location-query.in @@ -169,6 +169,7 @@ class CLI(object): help=_("Lists all networks in an AS"), ) list_networks_by_as.add_argument("asn", nargs=1, type=int) + list_networks_by_as.add_argument("--family", choices=("ipv6", "ipv4")) list_networks_by_as.add_argument("--output-format", choices=self.output_formats.keys(), default="list") list_networks_by_as.set_defaults(func=self.handle_list_networks_by_as) @@ -178,6 +179,7 @@ class CLI(object): help=_("Lists all networks in a country"), ) list_networks_by_cc.add_argument("country_code", nargs=1) + list_networks_by_cc.add_argument("--family", choices=("ipv6", "ipv4")) list_networks_by_cc.add_argument("--output-format", choices=self.output_formats.keys(), default="list") list_networks_by_cc.set_defaults(func=self.handle_list_networks_by_cc) @@ -195,6 +197,7 @@ class CLI(object): list_networks_by_flags.add_argument("--anycast", action="store_true", help=_("Anycasts"), ) + list_networks_by_flags.add_argument("--family", choices=("ipv6", "ipv4")) list_networks_by_flags.add_argument("--output-format", choices=self.output_formats.keys(), default="list") list_networks_by_flags.set_defaults(func=self.handle_list_networks_by_flags) @@ -232,6 +235,14 @@ class CLI(object): sys.stderr.write("Could not read the public key: %s\n" % e) sys.exit(1) + # Translate family + if args.family == "ipv6": + args.family = socket.AF_INET6 + elif args.family == "ipv4": + args.family = socket.AF_INET + else: + args.family = 0 + # Call function ret = args.func(db, args) @@ -324,14 +335,14 @@ class CLI(object): with self.__get_output_formatter(ns) as f: for asn in ns.asn: # Print all matching networks - for n in db.search_networks(asn=asn): + for n in db.search_networks(asn=asn, family=ns.family): f.network(n) def handle_list_networks_by_cc(self, db, ns): with self.__get_output_formatter(ns) as f: for country_code in ns.country_code: # Print all matching networks - for n in db.search_networks(country_code=country_code): + for n in db.search_networks(country_code=country_code, family=ns.family): f.network(n) def handle_list_networks_by_flags(self, db, ns): @@ -347,7 +358,7 @@ class CLI(object): flags |= location.NETWORK_FLAG_ANYCAST with self.__get_output_formatter(ns) as f: - for n in db.search_networks(flags=flags): + for n in db.search_networks(flags=flags, family=ns.family): f.network(n) -- 2.39.2