]> git.ipfire.org Git - people/ms/libloc.git/blob - src/python/network.c
network: Remove deprecated loc_network_is_subnet_of function
[people/ms/libloc.git] / src / python / network.c
1 /*
2 libloc - A library to determine the location of someone on the Internet
3
4 Copyright (C) 2017 IPFire Development Team <info@ipfire.org>
5
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.
10
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.
15 */
16
17 #include <Python.h>
18
19 #include <errno.h>
20
21 #include <loc/libloc.h>
22 #include <loc/network.h>
23 #include <loc/network-list.h>
24
25 #include "locationmodule.h"
26 #include "network.h"
27
28 static PyObject* PyList_FromNetworkList(struct loc_network_list* networks) {
29 PyObject* list = PyList_New(0);
30 if (!networks)
31 return list;
32
33 while (!loc_network_list_empty(networks)) {
34 struct loc_network* network = loc_network_list_pop(networks);
35
36 PyObject* n = new_network(&NetworkType, network);
37 PyList_Append(list, n);
38
39 loc_network_unref(network);
40 Py_DECREF(n);
41 }
42
43 return list;
44 }
45
46 PyObject* new_network(PyTypeObject* type, struct loc_network* network) {
47 NetworkObject* self = (NetworkObject*)type->tp_alloc(type, 0);
48 if (self) {
49 self->network = loc_network_ref(network);
50 }
51
52 return (PyObject*)self;
53 }
54
55 static PyObject* Network_new(PyTypeObject* type, PyObject* args, PyObject* kwds) {
56 NetworkObject* self = (NetworkObject*)type->tp_alloc(type, 0);
57
58 return (PyObject*)self;
59 }
60
61 static void Network_dealloc(NetworkObject* self) {
62 if (self->network)
63 loc_network_unref(self->network);
64
65 Py_TYPE(self)->tp_free((PyObject* )self);
66 }
67
68 static int Network_init(NetworkObject* self, PyObject* args, PyObject* kwargs) {
69 const char* network = NULL;
70
71 if (!PyArg_ParseTuple(args, "s", &network))
72 return -1;
73
74 // Load the Network
75 int r = loc_network_new_from_string(loc_ctx, &self->network, network);
76 if (r) {
77 PyErr_Format(PyExc_ValueError, "Invalid network: %s", network);
78 return -1;
79 }
80
81 return 0;
82 }
83
84 static PyObject* Network_repr(NetworkObject* self) {
85 char* network = loc_network_str(self->network);
86
87 PyObject* obj = PyUnicode_FromFormat("<location.Network %s>", network);
88 free(network);
89
90 return obj;
91 }
92
93 static PyObject* Network_str(NetworkObject* self) {
94 char* network = loc_network_str(self->network);
95
96 PyObject* obj = PyUnicode_FromString(network);
97 free(network);
98
99 return obj;
100 }
101
102 static PyObject* Network_get_country_code(NetworkObject* self) {
103 const char* country_code = loc_network_get_country_code(self->network);
104
105 return PyUnicode_FromString(country_code);
106 }
107
108 static int Network_set_country_code(NetworkObject* self, PyObject* value) {
109 const char* country_code = PyUnicode_AsUTF8(value);
110
111 int r = loc_network_set_country_code(self->network, country_code);
112 if (r) {
113 if (r == -EINVAL)
114 PyErr_Format(PyExc_ValueError,
115 "Invalid country code: %s", country_code);
116
117 return -1;
118 }
119
120 return 0;
121 }
122
123 static PyObject* Network_get_asn(NetworkObject* self) {
124 uint32_t asn = loc_network_get_asn(self->network);
125
126 if (asn)
127 return PyLong_FromLong(asn);
128
129 Py_RETURN_NONE;
130 }
131
132 static int Network_set_asn(NetworkObject* self, PyObject* value) {
133 long int asn = PyLong_AsLong(value);
134
135 // Check if the ASN is within the valid range
136 if (asn <= 0 || asn > UINT32_MAX) {
137 PyErr_Format(PyExc_ValueError, "Invalid ASN %ld", asn);
138 return -1;
139 }
140
141 int r = loc_network_set_asn(self->network, asn);
142 if (r)
143 return -1;
144
145 return 0;
146 }
147
148 static PyObject* Network_has_flag(NetworkObject* self, PyObject* args) {
149 enum loc_network_flags flag = 0;
150
151 if (!PyArg_ParseTuple(args, "i", &flag))
152 return NULL;
153
154 if (loc_network_has_flag(self->network, flag))
155 Py_RETURN_TRUE;
156
157 Py_RETURN_FALSE;
158 }
159
160 static PyObject* Network_set_flag(NetworkObject* self, PyObject* args) {
161 enum loc_network_flags flag = 0;
162
163 if (!PyArg_ParseTuple(args, "i", &flag))
164 return NULL;
165
166 int r = loc_network_set_flag(self->network, flag);
167
168 if (r) {
169 // What exception to throw here?
170 return NULL;
171 }
172
173 Py_RETURN_NONE;
174 }
175
176 static PyObject* Network_exclude(NetworkObject* self, PyObject* args) {
177 NetworkObject* other = NULL;
178
179 if (!PyArg_ParseTuple(args, "O!", &NetworkType, &other))
180 return NULL;
181
182 struct loc_network_list* list = loc_network_exclude(self->network, other->network);
183
184 // Convert to Python objects
185 PyObject* obj = PyList_FromNetworkList(list);
186 loc_network_list_unref(list);
187
188 return obj;
189 }
190
191 static PyObject* Network_is_subnet_of(NetworkObject* self, PyObject* args) {
192 NetworkObject* other = NULL;
193
194 if (!PyArg_ParseTuple(args, "O!", &NetworkType, &other))
195 return NULL;
196
197 if (loc_network_is_subnet(other->network, self->network))
198 Py_RETURN_TRUE;
199
200 Py_RETURN_FALSE;
201 }
202
203 static PyObject* Network_get_family(NetworkObject* self) {
204 int family = loc_network_address_family(self->network);
205
206 return PyLong_FromLong(family);
207 }
208
209 static PyObject* Network_get_first_address(NetworkObject* self) {
210 char* address = loc_network_format_first_address(self->network);
211
212 PyObject* obj = PyUnicode_FromString(address);
213 free(address);
214
215 return obj;
216 }
217
218 static PyObject* PyBytes_FromAddress(const struct in6_addr* address6) {
219 struct in_addr address4;
220
221 // Convert IPv4 addresses to struct in_addr
222 if (IN6_IS_ADDR_V4MAPPED(address6)) {
223 address4.s_addr = address6->s6_addr32[3];
224
225 return PyBytes_FromStringAndSize((const char*)&address4, sizeof(address4));
226 }
227
228 // Return IPv6 addresses as they are
229 return PyBytes_FromStringAndSize((const char*)address6, sizeof(*address6));
230 }
231
232 static PyObject* Network_get__first_address(NetworkObject* self) {
233 const struct in6_addr* address = loc_network_get_first_address(self->network);
234
235 return PyBytes_FromAddress(address);
236 }
237
238 static PyObject* Network_get_last_address(NetworkObject* self) {
239 char* address = loc_network_format_last_address(self->network);
240
241 PyObject* obj = PyUnicode_FromString(address);
242 free(address);
243
244 return obj;
245 }
246
247 static PyObject* Network_get__last_address(NetworkObject* self) {
248 const struct in6_addr* address = loc_network_get_last_address(self->network);
249
250 return PyBytes_FromAddress(address);
251 }
252
253 static struct PyMethodDef Network_methods[] = {
254 {
255 "exclude",
256 (PyCFunction)Network_exclude,
257 METH_VARARGS,
258 NULL,
259 },
260 {
261 "has_flag",
262 (PyCFunction)Network_has_flag,
263 METH_VARARGS,
264 NULL,
265 },
266 {
267 "is_subnet_of",
268 (PyCFunction)Network_is_subnet_of,
269 METH_VARARGS,
270 NULL,
271 },
272 {
273 "set_flag",
274 (PyCFunction)Network_set_flag,
275 METH_VARARGS,
276 NULL,
277 },
278 { NULL },
279 };
280
281 static struct PyGetSetDef Network_getsetters[] = {
282 {
283 "asn",
284 (getter)Network_get_asn,
285 (setter)Network_set_asn,
286 NULL,
287 NULL,
288 },
289 {
290 "country_code",
291 (getter)Network_get_country_code,
292 (setter)Network_set_country_code,
293 NULL,
294 NULL,
295 },
296 {
297 "family",
298 (getter)Network_get_family,
299 NULL,
300 NULL,
301 NULL,
302 },
303 {
304 "first_address",
305 (getter)Network_get_first_address,
306 NULL,
307 NULL,
308 NULL,
309 },
310 {
311 "_first_address",
312 (getter)Network_get__first_address,
313 NULL,
314 NULL,
315 NULL,
316 },
317 {
318 "last_address",
319 (getter)Network_get_last_address,
320 NULL,
321 NULL,
322 NULL,
323 },
324 {
325 "_last_address",
326 (getter)Network_get__last_address,
327 NULL,
328 NULL,
329 NULL,
330 },
331 { NULL },
332 };
333
334 PyTypeObject NetworkType = {
335 PyVarObject_HEAD_INIT(NULL, 0)
336 .tp_name = "location.Network",
337 .tp_basicsize = sizeof(NetworkObject),
338 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
339 .tp_new = Network_new,
340 .tp_dealloc = (destructor)Network_dealloc,
341 .tp_init = (initproc)Network_init,
342 .tp_doc = "Network object",
343 .tp_methods = Network_methods,
344 .tp_getset = Network_getsetters,
345 .tp_repr = (reprfunc)Network_repr,
346 .tp_str = (reprfunc)Network_str,
347 };