]> git.ipfire.org Git - location/libloc.git/commitdiff
as: Add list for easier processing
authorMichael Tremer <michael.tremer@ipfire.org>
Tue, 17 Nov 2020 16:46:48 +0000 (16:46 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Tue, 17 Nov 2020 16:46:48 +0000 (16:46 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
Makefile.am
src/as-list.c [new file with mode: 0644]
src/database.c
src/libloc.sym
src/loc/as-list.h [new file with mode: 0644]
src/loc/database.h
src/python/database.c
src/python/export.py

index f4ca3c802881298fcbe86f845f6c607b473b7e9a..d0cc793948d78b93cbbe6eb9f19420866cc2eab0 100644 (file)
@@ -91,6 +91,7 @@ EXTRA_DIST += \
 pkginclude_HEADERS = \
        src/loc/libloc.h \
        src/loc/as.h \
+       src/loc/as-list.h \
        src/loc/compat.h \
        src/loc/country.h \
        src/loc/country-list.h \
@@ -109,6 +110,7 @@ lib_LTLIBRARIES = \
 src_libloc_la_SOURCES = \
        src/libloc.c \
        src/as.c \
+       src/as-list.c \
        src/country.c \
        src/country-list.c \
        src/database.c \
diff --git a/src/as-list.c b/src/as-list.c
new file mode 100644 (file)
index 0000000..7c69eb0
--- /dev/null
@@ -0,0 +1,138 @@
+/*
+       libloc - A library to determine the location of someone on the Internet
+
+       Copyright (C) 2020 IPFire Development Team <info@ipfire.org>
+
+       This library is free software; you can redistribute it and/or
+       modify it under the terms of the GNU Lesser General Public
+       License as published by the Free Software Foundation; either
+       version 2.1 of the License, or (at your option) any later version.
+
+       This library is distributed in the hope that it will be useful,
+       but WITHOUT ANY WARRANTY; without even the implied warranty of
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+       Lesser General Public License for more details.
+*/
+
+#include <errno.h>
+#include <stdlib.h>
+
+#include <loc/as.h>
+#include <loc/as-list.h>
+#include <loc/private.h>
+
+struct loc_as_list {
+       struct loc_ctx* ctx;
+       int refcount;
+
+       struct loc_as* list[1024];
+       size_t size;
+       size_t max_size;
+};
+
+LOC_EXPORT int loc_as_list_new(struct loc_ctx* ctx,
+               struct loc_as_list** list) {
+       struct loc_as_list* l = calloc(1, sizeof(*l));
+       if (!l)
+               return -ENOMEM;
+
+       l->ctx = loc_ref(ctx);
+       l->refcount = 1;
+
+       // Do not allow this list to grow larger than this
+       l->max_size = 1024;
+
+       DEBUG(l->ctx, "AS list allocated at %p\n", l);
+       *list = l;
+
+       return 0;
+}
+
+LOC_EXPORT struct loc_as_list* loc_as_list_ref(struct loc_as_list* list) {
+       list->refcount++;
+
+       return list;
+}
+
+static void loc_as_list_free(struct loc_as_list* list) {
+       DEBUG(list->ctx, "Releasing AS list at %p\n", list);
+
+       loc_as_list_clear(list);
+
+       loc_unref(list->ctx);
+       free(list);
+}
+
+LOC_EXPORT struct loc_as_list* loc_as_list_unref(struct loc_as_list* list) {
+       if (!list)
+               return NULL;
+
+       if (--list->refcount > 0)
+               return list;
+
+       loc_as_list_free(list);
+       return NULL;
+}
+
+LOC_EXPORT size_t loc_as_list_size(struct loc_as_list* list) {
+       return list->size;
+}
+
+LOC_EXPORT int loc_as_list_empty(struct loc_as_list* list) {
+       return list->size == 0;
+}
+
+LOC_EXPORT void loc_as_list_clear(struct loc_as_list* list) {
+       for (unsigned int i = 0; i < list->size; i++)
+               loc_as_unref(list->list[i]);
+}
+
+LOC_EXPORT struct loc_as* loc_as_list_get(struct loc_as_list* list, size_t index) {
+       // Check index
+       if (index >= list->size)
+               return NULL;
+
+       return loc_as_ref(list->list[index]);
+}
+
+LOC_EXPORT int loc_as_list_append(
+               struct loc_as_list* list, struct loc_as* as) {
+       if (loc_as_list_contains(list, as))
+               return 0;
+
+       // Check if we have space left
+       if (list->size == list->max_size) {
+               ERROR(list->ctx, "%p: Could not append AS to the list. List full\n", list);
+               return -ENOMEM;
+       }
+
+       DEBUG(list->ctx, "%p: Appending AS %p to list\n", list, as);
+
+       list->list[list->size++] = loc_as_ref(as);
+
+       return 0;
+}
+
+LOC_EXPORT int loc_as_list_contains(
+               struct loc_as_list* list, struct loc_as* as) {
+       for (unsigned int i = 0; i < list->size; i++) {
+               if (loc_as_cmp(as, list->list[i]) == 0)
+                       return 1;
+       }
+
+       return 0;
+}
+
+LOC_EXPORT int loc_as_list_contains_number(
+               struct loc_as_list* list, uint32_t number) {
+       struct loc_as* as;
+
+       int r = loc_as_new(list->ctx, &as, number);
+       if (r)
+               return -1;
+
+       r = loc_as_list_contains(list, as);
+       loc_as_unref(as);
+
+       return r;
+}
index 29823b2b512c8249a82f0c816bdde631beb2d829..51cb5cda2fca21e4863e577da342c177a7cc899a 100644 (file)
@@ -38,6 +38,7 @@
 
 #include <loc/libloc.h>
 #include <loc/as.h>
+#include <loc/as-list.h>
 #include <loc/compat.h>
 #include <loc/country.h>
 #include <loc/country-list.h>
@@ -101,7 +102,7 @@ struct loc_database_enumerator {
        // Search string
        char* string;
        struct loc_country_list* countries;
-       uint32_t asn;
+       struct loc_as_list* asns;
        enum loc_network_flags flags;
        int family;
 
@@ -1036,9 +1037,20 @@ LOC_EXPORT int loc_database_enumerator_set_countries(
        return 0;
 }
 
-LOC_EXPORT int loc_database_enumerator_set_asn(
-               struct loc_database_enumerator* enumerator, unsigned int asn) {
-       enumerator->asn = asn;
+LOC_EXPORT struct loc_as_list* loc_database_enumerator_get_asns(
+               struct loc_database_enumerator* enumerator) {
+       if (!enumerator->asns)
+               return NULL;
+
+       return loc_as_list_ref(enumerator->asns);
+}
+
+LOC_EXPORT int loc_database_enumerator_set_asns(
+               struct loc_database_enumerator* enumerator, struct loc_as_list* asns) {
+       if (enumerator->asns)
+               loc_as_list_unref(enumerator->asns);
+
+       enumerator->asns = loc_as_list_ref(asns);
 
        return 0;
 }
@@ -1123,6 +1135,12 @@ static int loc_network_match_countries(struct loc_network* network, struct loc_c
        return loc_country_list_contains_code(countries, country_code);
 }
 
+static int loc_network_match_asns(struct loc_network* network, struct loc_as_list* asns) {
+       uint32_t asn = loc_network_get_asn(network);
+
+       return loc_as_list_contains_number(asns, asn);
+}
+
 static int loc_database_enumerator_filter_network(
                struct loc_database_enumerator* enumerator, struct loc_network* network) {
        // Skip if the family does not match
@@ -1134,8 +1152,7 @@ static int loc_database_enumerator_filter_network(
                return 1;
 
        // Skip if the ASN does not match
-       if (enumerator->asn &&
-                       !loc_network_match_asn(network, enumerator->asn))
+       if (enumerator->asns && !loc_network_match_asns(network, enumerator->asns))
                return 1;
 
        // Skip if flags do not match
index 40e9f88105a90f92022d4e82545792bb42ed9cf8..53273cdaee6dc6532bfd4be8ee85cca69424192d 100644 (file)
@@ -37,6 +37,18 @@ global:
        loc_as_set_name;
        loc_as_unref;
 
+       # AS List
+       loc_as_list_append;
+       loc_as_list_clear;
+       loc_as_list_contains;
+       loc_as_list_contains_number;
+       loc_as_list_empty;
+       loc_as_list_get;
+       loc_as_list_new;
+       loc_as_list_ref;
+       loc_as_list_size;
+       loc_as_list_unref;
+
        # Country
        loc_country_cmp;
        loc_country_code_is_valid;
@@ -78,13 +90,14 @@ global:
        loc_database_verify;
 
        # Database Enumerator
+       loc_database_enumerator_get_asns;
        loc_database_enumerator_get_countries;
        loc_database_enumerator_new;
        loc_database_enumerator_next_as;
        loc_database_enumerator_next_country;
        loc_database_enumerator_next_network;
        loc_database_enumerator_ref;
-       loc_database_enumerator_set_asn;
+       loc_database_enumerator_set_asns;
        loc_database_enumerator_set_countries;
        loc_database_enumerator_set_family;
        loc_database_enumerator_set_flag;
diff --git a/src/loc/as-list.h b/src/loc/as-list.h
new file mode 100644 (file)
index 0000000..7b5c4e8
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+       libloc - A library to determine the location of someone on the Internet
+
+       Copyright (C) 2017 IPFire Development Team <info@ipfire.org>
+
+       This library is free software; you can redistribute it and/or
+       modify it under the terms of the GNU Lesser General Public
+       License as published by the Free Software Foundation; either
+       version 2.1 of the License, or (at your option) any later version.
+
+       This library is distributed in the hope that it will be useful,
+       but WITHOUT ANY WARRANTY; without even the implied warranty of
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+       Lesser General Public License for more details.
+*/
+
+#ifndef LIBLOC_AS_LIST_H
+#define LIBLOC_AS_LIST_H
+
+#include <loc/as.h>
+#include <loc/libloc.h>
+
+struct loc_as_list;
+
+int loc_as_list_new(struct loc_ctx* ctx, struct loc_as_list** list);
+struct loc_as_list* loc_as_list_ref(struct loc_as_list* list);
+struct loc_as_list* loc_as_list_unref(struct loc_as_list* list);
+
+size_t loc_as_list_size(struct loc_as_list* list);
+int loc_as_list_empty(struct loc_as_list* list);
+void loc_as_list_clear(struct loc_as_list* list);
+
+struct loc_as* loc_as_list_get(struct loc_as_list* list, size_t index);
+int loc_as_list_append(struct loc_as_list* list, struct loc_as* as);
+
+int loc_as_list_contains(
+       struct loc_as_list* list, struct loc_as* as);
+int loc_as_list_contains_number(
+       struct loc_as_list* list, uint32_t number);
+
+#endif
index 246e5c550cfb7a418e53d44eb47bb4ed406f665c..70801f0d66db5a34515e1fa8b5f42c1951b8013b 100644 (file)
@@ -70,7 +70,10 @@ int loc_database_enumerator_set_string(struct loc_database_enumerator* enumerato
 struct loc_country_list* loc_database_enumerator_get_countries(struct loc_database_enumerator* enumerator);
 int loc_database_enumerator_set_countries(
        struct loc_database_enumerator* enumerator, struct loc_country_list* countries);
-int loc_database_enumerator_set_asn(struct loc_database_enumerator* enumerator, unsigned int asn);
+struct loc_as_list* loc_database_enumerator_get_asns(
+       struct loc_database_enumerator* enumerator);
+int loc_database_enumerator_set_asns(
+       struct loc_database_enumerator* enumerator, struct loc_as_list* asns);
 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(
index e6f6f37e2bc437a55c5b3c84ef5672a0faa7353f..38a804cd8a8936e925601498f0c52c3fc1e3f6b5 100644 (file)
@@ -17,6 +17,8 @@
 #include <Python.h>
 
 #include <loc/libloc.h>
+#include <loc/as.h>
+#include <loc/as-list.h>
 #include <loc/database.h>
 
 #include "locationmodule.h"
@@ -258,15 +260,15 @@ static PyObject* Database_networks_flattened(DatabaseObject *self) {
 }
 
 static PyObject* Database_search_networks(DatabaseObject* self, PyObject* args, PyObject* kwargs) {
-       char* kwlist[] = { "country_codes", "asn", "flags", "family", "flatten", NULL };
+       char* kwlist[] = { "country_codes", "asns", "flags", "family", "flatten", NULL };
        PyObject* country_codes = NULL;
-       unsigned int asn = 0;
+       PyObject* asn_list = NULL;
        int flags = 0;
        int family = 0;
        int flatten = 0;
 
-       if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O!iiip", kwlist,
-                       &PyList_Type, &country_codes, &asn, &flags, &family, &flatten))
+       if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O!O!iip", kwlist,
+                       &PyList_Type, &country_codes, &PyList_Type, &asn_list, &flags, &family, &flatten))
                return NULL;
 
        struct loc_database_enumerator* enumerator;
@@ -330,13 +332,57 @@ static PyObject* Database_search_networks(DatabaseObject* self, PyObject* args,
        }
 
        // Set the ASN we are searching for
-       if (asn) {
-               r = loc_database_enumerator_set_asn(enumerator, asn);
+       if (asn_list) {
+               struct loc_as_list* asns;
+               r = loc_as_list_new(loc_ctx, &asns);
+               if (r) {
+                       PyErr_SetString(PyExc_SystemError, "Could not create AS list");
+                       return NULL;
+               }
+
+               for (unsigned int i = 0; i < PyList_Size(asn_list); i++) {
+                       PyObject* item = PyList_GetItem(asn_list, i);
+
+                       if (!PyLong_Check(item)) {
+                               PyErr_SetString(PyExc_TypeError, "ASNs must be numbers");
+
+                               loc_as_list_unref(asns);
+                               return NULL;
+                       }
+
+                       unsigned long number = PyLong_AsLong(item);
 
+                       struct loc_as* as;
+                       r = loc_as_new(loc_ctx, &as, number);
+                       if (r) {
+                               PyErr_SetString(PyExc_SystemError, "Could not create AS");
+
+                               loc_as_list_unref(asns);
+                               loc_as_unref(as);
+                               return NULL;
+                       }
+
+                       r = loc_as_list_append(asns, as);
+                       if (r) {
+                               PyErr_SetString(PyExc_SystemError, "Could not append AS to the list");
+
+                               loc_as_list_unref(asns);
+                               loc_as_unref(as);
+                               return NULL;
+                       }
+
+                       loc_as_unref(as);
+               }
+
+               r = loc_database_enumerator_set_asns(enumerator, asns);
                if (r) {
                        PyErr_SetFromErrno(PyExc_SystemError);
+
+                       loc_as_list_unref(asns);
                        return NULL;
                }
+
+               loc_as_list_unref(asns);
        }
 
        // Set the flags we are searching for
index 739742f0a407d3db92114299a5bd8d50977b3c14..f675eb312db6eff401df619c1e4e5c57597cb3d8 100644 (file)
@@ -197,7 +197,7 @@ class Exporter(object):
 
                        # Get all networks that match the family
                        networks = self.db.search_networks(family=family,
-                               country_codes=country_codes, flags=flags, flatten=True)
+                               country_codes=country_codes, asns=asns, flags=flags, flatten=True)
 
                        # Walk through all networks
                        for network in networks: