2 libloc - A library to determine the location of someone on the Internet
4 Copyright (C) 2017 IPFire Development Team <info@ipfire.org>
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
19 #include <loc/libloc.h>
20 #include <loc/database.h>
22 #include "locationmodule.h"
28 static PyObject
* Database_new(PyTypeObject
* type
, PyObject
* args
, PyObject
* kwds
) {
29 DatabaseObject
* self
= (DatabaseObject
*)type
->tp_alloc(type
, 0);
31 return (PyObject
*)self
;
34 static void Database_dealloc(DatabaseObject
* self
) {
36 loc_database_unref(self
->db
);
41 Py_TYPE(self
)->tp_free((PyObject
* )self
);
44 static int Database_init(DatabaseObject
* self
, PyObject
* args
, PyObject
* kwargs
) {
45 const char* path
= NULL
;
47 if (!PyArg_ParseTuple(args
, "s", &path
))
50 self
->path
= strdup(path
);
52 // Open the file for reading
53 FILE* f
= fopen(self
->path
, "r");
55 PyErr_SetFromErrno(PyExc_IOError
);
60 int r
= loc_database_new(loc_ctx
, &self
->db
, f
);
63 // Return on any errors
70 static PyObject
* Database_repr(DatabaseObject
* self
) {
71 return PyUnicode_FromFormat("<Database %s>", self
->path
);
74 static PyObject
* Database_get_description(DatabaseObject
* self
) {
75 const char* description
= loc_database_get_description(self
->db
);
77 return PyUnicode_FromString(description
);
80 static PyObject
* Database_get_vendor(DatabaseObject
* self
) {
81 const char* vendor
= loc_database_get_vendor(self
->db
);
83 return PyUnicode_FromString(vendor
);
86 static PyObject
* Database_get_license(DatabaseObject
* self
) {
87 const char* license
= loc_database_get_license(self
->db
);
89 return PyUnicode_FromString(license
);
92 static PyObject
* Database_get_created_at(DatabaseObject
* self
) {
93 time_t created_at
= loc_database_created_at(self
->db
);
95 return PyLong_FromLong(created_at
);
98 static PyObject
* Database_get_as(DatabaseObject
* self
, PyObject
* args
) {
99 struct loc_as
* as
= NULL
;
102 if (!PyArg_ParseTuple(args
, "i", &number
))
105 // Try to retrieve the AS
106 int r
= loc_database_get_as(self
->db
, &as
, number
);
110 PyObject
* obj
= new_as(&ASType
, as
);
124 static PyObject
* Database_get_country(DatabaseObject
* self
, PyObject
* args
) {
125 const char* country_code
= NULL
;
127 if (!PyArg_ParseTuple(args
, "s", &country_code
))
130 struct loc_country
* country
;
131 int r
= loc_database_get_country(self
->db
, &country
, country_code
);
136 PyObject
* obj
= new_country(&CountryType
, country
);
137 loc_country_unref(country
);
142 static PyObject
* Database_lookup(DatabaseObject
* self
, PyObject
* args
) {
143 struct loc_network
* network
= NULL
;
144 const char* address
= NULL
;
146 if (!PyArg_ParseTuple(args
, "s", &address
))
149 // Try to retrieve a matching network
150 int r
= loc_database_lookup_from_string(self
->db
, address
, &network
);
154 PyObject
* obj
= new_network(&NetworkType
, network
);
155 loc_network_unref(network
);
164 } else if (r
== -EINVAL
) {
165 PyErr_Format(PyExc_ValueError
, "Invalid IP address: %s", address
);
173 static PyObject
* new_database_enumerator(PyTypeObject
* type
, struct loc_database_enumerator
* enumerator
) {
174 DatabaseEnumeratorObject
* self
= (DatabaseEnumeratorObject
*)type
->tp_alloc(type
, 0);
176 self
->enumerator
= loc_database_enumerator_ref(enumerator
);
179 return (PyObject
*)self
;
182 static PyObject
* Database_search_as(DatabaseObject
* self
, PyObject
* args
) {
183 const char* string
= NULL
;
185 if (!PyArg_ParseTuple(args
, "s", &string
))
188 struct loc_database_enumerator
* enumerator
;
190 int r
= loc_database_enumerator_new(&enumerator
, self
->db
, LOC_DB_ENUMERATE_ASES
);
192 PyErr_SetFromErrno(PyExc_SystemError
);
196 // Search string we are searching for
197 loc_database_enumerator_set_string(enumerator
, string
);
199 PyObject
* obj
= new_database_enumerator(&DatabaseEnumeratorType
, enumerator
);
200 loc_database_enumerator_unref(enumerator
);
205 static PyObject
* Database_search_networks(DatabaseObject
* self
, PyObject
* args
, PyObject
* kwargs
) {
206 char* kwlist
[] = { "country_code", "asn", "flags", NULL
};
207 const char* country_code
= NULL
;
208 unsigned int asn
= 0;
211 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "|sii", kwlist
, &country_code
, &asn
, &flags
))
214 struct loc_database_enumerator
* enumerator
;
215 int r
= loc_database_enumerator_new(&enumerator
, self
->db
, LOC_DB_ENUMERATE_NETWORKS
);
217 PyErr_SetFromErrno(PyExc_SystemError
);
221 // Set country code we are searching for
223 r
= loc_database_enumerator_set_country_code(enumerator
, country_code
);
226 PyErr_SetFromErrno(PyExc_SystemError
);
231 // Set the ASN we are searching for
233 r
= loc_database_enumerator_set_asn(enumerator
, asn
);
236 PyErr_SetFromErrno(PyExc_SystemError
);
241 // Set the flags we are searching for
243 r
= loc_database_enumerator_set_flag(enumerator
, flags
);
246 PyErr_SetFromErrno(PyExc_SystemError
);
251 PyObject
* obj
= new_database_enumerator(&DatabaseEnumeratorType
, enumerator
);
252 loc_database_enumerator_unref(enumerator
);
257 static struct PyMethodDef Database_methods
[] = {
260 (PyCFunction
)Database_get_as
,
266 (PyCFunction
)Database_get_country
,
272 (PyCFunction
)Database_lookup
,
278 (PyCFunction
)Database_search_as
,
284 (PyCFunction
)Database_search_networks
,
285 METH_VARARGS
|METH_KEYWORDS
,
291 static struct PyGetSetDef Database_getsetters
[] = {
294 (getter
)Database_get_created_at
,
301 (getter
)Database_get_description
,
308 (getter
)Database_get_license
,
315 (getter
)Database_get_vendor
,
323 PyTypeObject DatabaseType
= {
324 PyVarObject_HEAD_INIT(NULL
, 0)
325 .tp_name
= "location.Database",
326 .tp_basicsize
= sizeof(DatabaseObject
),
327 .tp_flags
= Py_TPFLAGS_DEFAULT
|Py_TPFLAGS_BASETYPE
,
328 .tp_new
= Database_new
,
329 .tp_dealloc
= (destructor
)Database_dealloc
,
330 .tp_init
= (initproc
)Database_init
,
331 .tp_doc
= "Database object",
332 .tp_methods
= Database_methods
,
333 .tp_getset
= Database_getsetters
,
334 .tp_repr
= (reprfunc
)Database_repr
,
337 static PyObject
* DatabaseEnumerator_new(PyTypeObject
* type
, PyObject
* args
, PyObject
* kwds
) {
338 DatabaseEnumeratorObject
* self
= (DatabaseEnumeratorObject
*)type
->tp_alloc(type
, 0);
340 return (PyObject
*)self
;
343 static void DatabaseEnumerator_dealloc(DatabaseEnumeratorObject
* self
) {
344 loc_database_enumerator_unref(self
->enumerator
);
346 Py_TYPE(self
)->tp_free((PyObject
* )self
);
349 static PyObject
* DatabaseEnumerator_next(DatabaseEnumeratorObject
* self
) {
350 struct loc_network
* network
= NULL
;
352 // Enumerate all networks
353 int r
= loc_database_enumerator_next_network(self
->enumerator
, &network
);
355 PyErr_SetFromErrno(PyExc_ValueError
);
359 // A network was found
361 PyObject
* obj
= new_network(&NetworkType
, network
);
362 loc_network_unref(network
);
367 // Enumerate all ASes
368 struct loc_as
* as
= NULL
;
370 r
= loc_database_enumerator_next_as(self
->enumerator
, &as
);
372 PyErr_SetFromErrno(PyExc_ValueError
);
377 PyObject
* obj
= new_as(&ASType
, as
);
383 // Nothing found, that means the end
384 PyErr_SetNone(PyExc_StopIteration
);
388 PyTypeObject DatabaseEnumeratorType
= {
389 PyVarObject_HEAD_INIT(NULL
, 0)
390 .tp_name
= "location.DatabaseEnumerator",
391 .tp_basicsize
= sizeof(DatabaseEnumeratorObject
),
392 .tp_flags
= Py_TPFLAGS_DEFAULT
,
393 .tp_alloc
= PyType_GenericAlloc
,
394 .tp_new
= DatabaseEnumerator_new
,
395 .tp_dealloc
= (destructor
)DatabaseEnumerator_dealloc
,
396 .tp_iter
= PyObject_SelfIter
,
397 .tp_iternext
= (iternextfunc
)DatabaseEnumerator_next
,