#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) {
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,
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 },
};