]> git.ipfire.org Git - people/ms/libloc.git/blobdiff - src/python/network.c
network: Remove deprecated loc_network_is_subnet_of function
[people/ms/libloc.git] / src / python / network.c
index f36b3393ff177747b77c762337cab04dea2f1b9d..b6e92fbc8f8fe7a8dc4603fd48a71ae8c91301ee 100644 (file)
 
 #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) {
@@ -71,6 +90,15 @@ static PyObject* Network_repr(NetworkObject* 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);
 
@@ -83,7 +111,8 @@ static int Network_set_country_code(NetworkObject* self, PyObject* value) {
        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;
        }
@@ -116,6 +145,139 @@ static int Network_set_asn(NetworkObject* self, PyObject* value) {
        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",
@@ -131,18 +293,55 @@ static struct PyGetSetDef Network_getsetters[] = {
                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,
 };