]> git.ipfire.org Git - people/ms/libloc.git/commitdiff
location-query: Allow filtering networks by family
authorMichael Tremer <michael.tremer@ipfire.org>
Fri, 29 Nov 2019 19:44:25 +0000 (19:44 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Fri, 29 Nov 2019 19:44:25 +0000 (19:44 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
man/location-query.txt
src/database.c
src/libloc.sym
src/loc/database.h
src/loc/network.h
src/network.c
src/python/database.c
src/python/location-query.in

index 957dc01c5ff53c970f303bc30ed3fa676f8ec283..7a9818099b6697c00015827570b9fcb691405bd7 100644 (file)
@@ -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.
index f126c607c48d1aea35de4e0329552b10a2aff561..933f1c5d6c79ad622cdf068a8342f6fd672d39fe 100644 (file)
@@ -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)) {
index 7fe59f1c649dcc69c5111574a07b8f0c00b8e421..b3d5b51d25e136ea804c274d7f6ff2735eb3c301 100644 (file)
@@ -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;
index f42b43256a1eed8129d0f5d7f3987a96a2182bad..ab9ef72c081facaedf9113af0a7894f7e4d3223b 100644 (file)
@@ -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(
index 02c8ad5cfea998658ece00b54bd95b80acc48ebe..ad43c3a7f16c35ce85bc15a164c44612b671b668 100644 (file)
@@ -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);
index ad3989250e421e098068ed52e5f4b8c6d3bd2522..8dde0ec98a18dbd7fac6ef8df9a806768a00b648 100644 (file)
@@ -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)
index 9bd938ca74823e2f488785d47214917d4869a425..2f0a3b0fb1b3c5cba75e68018d405cb96760f4de 100644 (file)
@@ -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);
 
index c455d1e5c660c98a3de1d2e6caaab311991475d0..a1ca7fe6059e7fb17a2035187a2666f6207baffd 100644 (file)
@@ -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)