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 \
src_libloc_la_SOURCES = \
src/libloc.c \
src/as.c \
+ src/as-list.c \
src/country.c \
src/country-list.c \
src/database.c \
--- /dev/null
+/*
+ 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;
+}
#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>
// Search string
char* string;
struct loc_country_list* countries;
- uint32_t asn;
+ struct loc_as_list* asns;
enum loc_network_flags flags;
int family;
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;
}
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
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
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;
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;
--- /dev/null
+/*
+ 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
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(
#include <Python.h>
#include <loc/libloc.h>
+#include <loc/as.h>
+#include <loc/as-list.h>
#include <loc/database.h>
#include "locationmodule.h"
}
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;
}
// 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
# 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: