#include <loc/libloc.h>
#include <loc/network.h>
+#include <loc/network-list.h>
#include "locationmodule.h"
#include "network.h"
+static PyObject* PyList_FromNetworkList(struct loc_network_list* networks) {
+ PyObject* list = PyList_New(0);
+ if (!networks)
+ return list;
+
+ while (!loc_network_list_empty(networks)) {
+ struct loc_network* network = loc_network_list_pop(networks);
+
+ PyObject* n = new_network(&NetworkType, network);
+ PyList_Append(list, n);
+
+ loc_network_unref(network);
+ Py_DECREF(n);
+ }
+
+ return list;
+}
+
PyObject* new_network(PyTypeObject* type, struct loc_network* network) {
NetworkObject* self = (NetworkObject*)type->tp_alloc(type, 0);
if (self) {
return obj;
}
+static PyObject* Network_str(NetworkObject* self) {
+ char* network = loc_network_str(self->network);
+
+ PyObject* obj = PyUnicode_FromString(network);
+ free(network);
+
+ return obj;
+}
+
static PyObject* Network_get_country_code(NetworkObject* self) {
const char* country_code = loc_network_get_country_code(self->network);
int r = loc_network_set_country_code(self->network, country_code);
if (r) {
if (r == -EINVAL)
- PyErr_SetString(PyExc_ValueError, "Invalid country code");
+ PyErr_Format(PyExc_ValueError,
+ "Invalid country code: %s", country_code);
return -1;
}
return 0;
}
+static PyObject* Network_has_flag(NetworkObject* self, PyObject* args) {
+ enum loc_network_flags flag = 0;
+
+ if (!PyArg_ParseTuple(args, "i", &flag))
+ return NULL;
+
+ if (loc_network_has_flag(self->network, flag))
+ Py_RETURN_TRUE;
+
+ Py_RETURN_FALSE;
+}
+
+static PyObject* Network_set_flag(NetworkObject* self, PyObject* args) {
+ enum loc_network_flags flag = 0;
+
+ if (!PyArg_ParseTuple(args, "i", &flag))
+ return NULL;
+
+ int r = loc_network_set_flag(self->network, flag);
+
+ if (r) {
+ // What exception to throw here?
+ return NULL;
+ }
+
+ Py_RETURN_NONE;
+}
+
+static PyObject* Network_exclude(NetworkObject* self, PyObject* args) {
+ NetworkObject* other = NULL;
+
+ if (!PyArg_ParseTuple(args, "O!", &NetworkType, &other))
+ return NULL;
+
+ struct loc_network_list* list = loc_network_exclude(self->network, other->network);
+
+ // Convert to Python objects
+ PyObject* obj = PyList_FromNetworkList(list);
+ loc_network_list_unref(list);
+
+ return obj;
+}
+
+static PyObject* Network_is_subnet_of(NetworkObject* self, PyObject* args) {
+ NetworkObject* other = NULL;
+
+ if (!PyArg_ParseTuple(args, "O!", &NetworkType, &other))
+ return NULL;
+
+ if (loc_network_is_subnet(other->network, self->network))
+ Py_RETURN_TRUE;
+
+ Py_RETURN_FALSE;
+}
+
+static PyObject* Network_get_family(NetworkObject* self) {
+ int family = loc_network_address_family(self->network);
+
+ return PyLong_FromLong(family);
+}
+
+static PyObject* Network_get_first_address(NetworkObject* self) {
+ char* address = loc_network_format_first_address(self->network);
+
+ PyObject* obj = PyUnicode_FromString(address);
+ free(address);
+
+ return obj;
+}
+
+static PyObject* PyBytes_FromAddress(const struct in6_addr* address6) {
+ struct in_addr address4;
+
+ // Convert IPv4 addresses to struct in_addr
+ if (IN6_IS_ADDR_V4MAPPED(address6)) {
+ address4.s_addr = address6->s6_addr32[3];
+
+ return PyBytes_FromStringAndSize((const char*)&address4, sizeof(address4));
+ }
+
+ // Return IPv6 addresses as they are
+ return PyBytes_FromStringAndSize((const char*)address6, sizeof(*address6));
+}
+
+static PyObject* Network_get__first_address(NetworkObject* self) {
+ const struct in6_addr* address = loc_network_get_first_address(self->network);
+
+ return PyBytes_FromAddress(address);
+}
+
+static PyObject* Network_get_last_address(NetworkObject* self) {
+ char* address = loc_network_format_last_address(self->network);
+
+ PyObject* obj = PyUnicode_FromString(address);
+ free(address);
+
+ return obj;
+}
+
+static PyObject* Network_get__last_address(NetworkObject* self) {
+ const struct in6_addr* address = loc_network_get_last_address(self->network);
+
+ return PyBytes_FromAddress(address);
+}
+
+static struct PyMethodDef Network_methods[] = {
+ {
+ "exclude",
+ (PyCFunction)Network_exclude,
+ METH_VARARGS,
+ NULL,
+ },
+ {
+ "has_flag",
+ (PyCFunction)Network_has_flag,
+ METH_VARARGS,
+ NULL,
+ },
+ {
+ "is_subnet_of",
+ (PyCFunction)Network_is_subnet_of,
+ METH_VARARGS,
+ NULL,
+ },
+ {
+ "set_flag",
+ (PyCFunction)Network_set_flag,
+ METH_VARARGS,
+ NULL,
+ },
+ { NULL },
+};
+
static struct PyGetSetDef Network_getsetters[] = {
{
"asn",
NULL,
NULL,
},
+ {
+ "family",
+ (getter)Network_get_family,
+ NULL,
+ NULL,
+ NULL,
+ },
+ {
+ "first_address",
+ (getter)Network_get_first_address,
+ NULL,
+ NULL,
+ NULL,
+ },
+ {
+ "_first_address",
+ (getter)Network_get__first_address,
+ NULL,
+ NULL,
+ NULL,
+ },
+ {
+ "last_address",
+ (getter)Network_get_last_address,
+ NULL,
+ NULL,
+ NULL,
+ },
+ {
+ "_last_address",
+ (getter)Network_get__last_address,
+ NULL,
+ NULL,
+ NULL,
+ },
{ NULL },
};
PyTypeObject NetworkType = {
PyVarObject_HEAD_INIT(NULL, 0)
- tp_name: "location.Network",
- tp_basicsize: sizeof(NetworkObject),
- tp_flags: Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
- tp_new: Network_new,
- tp_dealloc: (destructor)Network_dealloc,
- tp_init: (initproc)Network_init,
- tp_doc: "Network object",
- tp_getset: Network_getsetters,
- tp_repr: (reprfunc)Network_repr,
+ .tp_name = "location.Network",
+ .tp_basicsize = sizeof(NetworkObject),
+ .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
+ .tp_new = Network_new,
+ .tp_dealloc = (destructor)Network_dealloc,
+ .tp_init = (initproc)Network_init,
+ .tp_doc = "Network object",
+ .tp_methods = Network_methods,
+ .tp_getset = Network_getsetters,
+ .tp_repr = (reprfunc)Network_repr,
+ .tp_str = (reprfunc)Network_str,
};