diff options
author | Martin Schanzenbach <schanzen@gnunet.org> | 2023-10-13 23:03:36 +0200 |
---|---|---|
committer | Martin Schanzenbach <schanzen@gnunet.org> | 2023-10-13 23:03:36 +0200 |
commit | 5b8a20569176983c441c4d48030d213f55d95f99 (patch) | |
tree | dffd25fc128f92956ed20402ef200c34fbd40ba4 /src/nt | |
parent | 52960a71696e798d673b1719fe2a9f6aa8c4a0a9 (diff) | |
download | gnunet-5b8a20569176983c441c4d48030d213f55d95f99.tar.gz gnunet-5b8a20569176983c441c4d48030d213f55d95f99.zip |
UTIL: Incorporate nt component. Fixes #7955
Diffstat (limited to 'src/nt')
-rw-r--r-- | src/nt/Makefile.am | 33 | ||||
-rw-r--r-- | src/nt/meson.build | 21 | ||||
-rw-r--r-- | src/nt/nt.c | 439 |
3 files changed, 0 insertions, 493 deletions
diff --git a/src/nt/Makefile.am b/src/nt/Makefile.am deleted file mode 100644 index 2c55ab88f..000000000 --- a/src/nt/Makefile.am +++ /dev/null | |||
@@ -1,33 +0,0 @@ | |||
1 | # This Makefile.am is in the public domain | ||
2 | AM_CPPFLAGS = -I$(top_srcdir)/src/include | ||
3 | |||
4 | if USE_COVERAGE | ||
5 | AM_CFLAGS = --coverage | ||
6 | endif | ||
7 | |||
8 | lib_LTLIBRARIES = libgnunetnt.la | ||
9 | |||
10 | libgnunetnt_la_SOURCES = \ | ||
11 | nt.c | ||
12 | |||
13 | libgnunetnt_la_LIBADD = \ | ||
14 | $(top_builddir)/src/util/libgnunetutil.la | ||
15 | libgnunetnt_la_LDFLAGS = \ | ||
16 | $(GN_LIB_LDFLAGS) \ | ||
17 | $(GN_LIBINTL) \ | ||
18 | -version-info 0:0:0 | ||
19 | |||
20 | #if ENABLE_TEST_RUN | ||
21 | #TESTS = \ | ||
22 | # test_nt | ||
23 | #endif | ||
24 | |||
25 | #check_PROGRAMS= \ | ||
26 | # test_nt | ||
27 | # | ||
28 | #test_nt_SOURCES = \ | ||
29 | # test_nt.c | ||
30 | #test_nt_LDADD = \ | ||
31 | # libgnunetnt.la \ | ||
32 | # $(top_builddir)/src/util/libgnunetutil.la \ | ||
33 | # $(XLIB) | ||
diff --git a/src/nt/meson.build b/src/nt/meson.build deleted file mode 100644 index 9b2a97568..000000000 --- a/src/nt/meson.build +++ /dev/null | |||
@@ -1,21 +0,0 @@ | |||
1 | libgnunetnt_src = ['nt.c'] | ||
2 | |||
3 | if get_option('monolith') | ||
4 | foreach p : libgnunetnt_src | ||
5 | gnunet_src += 'nt/' + p | ||
6 | endforeach | ||
7 | subdir_done() | ||
8 | endif | ||
9 | |||
10 | libgnunetnt = library('gnunetnt', | ||
11 | libgnunetnt_src, | ||
12 | soversion: '0', | ||
13 | version: '0.0.0', | ||
14 | dependencies: libgnunetutil_dep, | ||
15 | include_directories: [incdir, configuration_inc], | ||
16 | install: true, | ||
17 | install_dir: get_option('libdir')) | ||
18 | libgnunetnt_dep = declare_dependency(link_with : libgnunetnt) | ||
19 | pkg.generate(libgnunetnt, url: 'https://www.gnunet.org', | ||
20 | description : 'Provides API for accessing GNUnet NT') | ||
21 | |||
diff --git a/src/nt/nt.c b/src/nt/nt.c deleted file mode 100644 index 8dfacb02b..000000000 --- a/src/nt/nt.c +++ /dev/null | |||
@@ -1,439 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2010-2015, 2018 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | /** | ||
21 | * @file nt/nt_api_scanner.c | ||
22 | * @brief LAN interface scanning to determine IPs in LAN | ||
23 | * @author Christian Grothoff | ||
24 | * @author Matthias Wachs | ||
25 | */ | ||
26 | #include "platform.h" | ||
27 | #include "gnunet_util_lib.h" | ||
28 | #include "gnunet_nt_lib.h" | ||
29 | |||
30 | /** | ||
31 | * How frequently do we scan the interfaces for changes to the addresses? | ||
32 | */ | ||
33 | #define INTERFACE_PROCESSING_INTERVAL GNUNET_TIME_relative_multiply ( \ | ||
34 | GNUNET_TIME_UNIT_MINUTES, 2) | ||
35 | |||
36 | |||
37 | const char * | ||
38 | GNUNET_NT_to_string (enum GNUNET_NetworkType net) | ||
39 | { | ||
40 | switch (net) | ||
41 | { | ||
42 | case GNUNET_NT_UNSPECIFIED: | ||
43 | return "UNSPECIFIED"; | ||
44 | |||
45 | case GNUNET_NT_LOOPBACK: | ||
46 | return "LOOPBACK"; | ||
47 | |||
48 | case GNUNET_NT_LAN: | ||
49 | return "LAN"; | ||
50 | |||
51 | case GNUNET_NT_WAN: | ||
52 | return "WAN"; | ||
53 | |||
54 | case GNUNET_NT_WLAN: | ||
55 | return "WLAN"; | ||
56 | |||
57 | case GNUNET_NT_BT: | ||
58 | return "BLUETOOTH"; | ||
59 | |||
60 | default: | ||
61 | return NULL; | ||
62 | } | ||
63 | } | ||
64 | |||
65 | |||
66 | /** | ||
67 | * We keep a list of our local networks so we can answer | ||
68 | * LAN vs. WAN questions. Note: WLAN is not detected yet. | ||
69 | * (maybe we can do that heuristically based on interface | ||
70 | * name in the future?). | ||
71 | */ | ||
72 | struct NT_Network | ||
73 | { | ||
74 | /** | ||
75 | * Kept in a DLL. | ||
76 | */ | ||
77 | struct NT_Network *next; | ||
78 | |||
79 | /** | ||
80 | * Kept in a DLL. | ||
81 | */ | ||
82 | struct NT_Network *prev; | ||
83 | |||
84 | /** | ||
85 | * Network address. | ||
86 | */ | ||
87 | struct sockaddr *network; | ||
88 | |||
89 | /** | ||
90 | * Netmask to determine what is in the LAN. | ||
91 | */ | ||
92 | struct sockaddr *netmask; | ||
93 | |||
94 | /** | ||
95 | * How long are @e network and @e netmask? | ||
96 | */ | ||
97 | socklen_t length; | ||
98 | }; | ||
99 | |||
100 | |||
101 | /** | ||
102 | * Handle to the interface scanner. | ||
103 | */ | ||
104 | struct GNUNET_NT_InterfaceScanner | ||
105 | { | ||
106 | /** | ||
107 | * Head of LAN networks list. | ||
108 | */ | ||
109 | struct NT_Network *net_head; | ||
110 | |||
111 | /** | ||
112 | * Tail of LAN networks list. | ||
113 | */ | ||
114 | struct NT_Network *net_tail; | ||
115 | |||
116 | /** | ||
117 | * Task for periodically refreshing our LAN network list. | ||
118 | */ | ||
119 | struct GNUNET_SCHEDULER_Task *interface_task; | ||
120 | }; | ||
121 | |||
122 | |||
123 | /** | ||
124 | * Delete all entries from the current network list. | ||
125 | * | ||
126 | * @param is scanner to clean up | ||
127 | */ | ||
128 | static void | ||
129 | delete_networks (struct GNUNET_NT_InterfaceScanner *is) | ||
130 | { | ||
131 | struct NT_Network *cur; | ||
132 | |||
133 | while (NULL != (cur = is->net_head)) | ||
134 | { | ||
135 | GNUNET_CONTAINER_DLL_remove (is->net_head, | ||
136 | is->net_tail, | ||
137 | cur); | ||
138 | GNUNET_free (cur); | ||
139 | } | ||
140 | } | ||
141 | |||
142 | |||
143 | /** | ||
144 | * Function invoked for each interface found. Adds the interface's | ||
145 | * network addresses to the respective DLL, so we can distinguish | ||
146 | * between LAN and WAN. | ||
147 | * | ||
148 | * @param cls closure with the `struct GNUNET_NT_InterfaceScanner` | ||
149 | * @param name name of the interface (can be NULL for unknown) | ||
150 | * @param isDefault is this presumably the default interface | ||
151 | * @param addr address of this interface (can be NULL for unknown or unassigned) | ||
152 | * @param broadcast_addr the broadcast address (can be NULL for unknown or unassigned) | ||
153 | * @param netmask the network mask (can be NULL for unknown or unassigned) | ||
154 | * @param addrlen length of the address | ||
155 | * @return #GNUNET_OK to continue iteration | ||
156 | */ | ||
157 | static int | ||
158 | interface_proc (void *cls, | ||
159 | const char *name, | ||
160 | int isDefault, | ||
161 | const struct sockaddr *addr, | ||
162 | const struct sockaddr *broadcast_addr, | ||
163 | const struct sockaddr *netmask, | ||
164 | socklen_t addrlen) | ||
165 | { | ||
166 | struct GNUNET_NT_InterfaceScanner *is = cls; | ||
167 | /* Calculate network */ | ||
168 | struct NT_Network *net = NULL; | ||
169 | |||
170 | (void) name; | ||
171 | (void) isDefault; | ||
172 | (void) broadcast_addr; | ||
173 | |||
174 | /* Skipping IPv4 loopback addresses since we have special check */ | ||
175 | if (addr->sa_family == AF_INET) | ||
176 | { | ||
177 | const struct sockaddr_in *a4 = (const struct sockaddr_in *) addr; | ||
178 | |||
179 | if ((a4->sin_addr.s_addr & htonl (0xff000000)) == htonl (0x7f000000)) | ||
180 | return GNUNET_OK; | ||
181 | } | ||
182 | /* Skipping IPv6 loopback addresses since we have special check */ | ||
183 | if (addr->sa_family == AF_INET6) | ||
184 | { | ||
185 | const struct sockaddr_in6 *a6 = (const struct sockaddr_in6 *) addr; | ||
186 | if (IN6_IS_ADDR_LOOPBACK (&a6->sin6_addr)) | ||
187 | return GNUNET_OK; | ||
188 | } | ||
189 | |||
190 | if (addr->sa_family == AF_INET) | ||
191 | { | ||
192 | const struct sockaddr_in *addr4 = (const struct sockaddr_in *) addr; | ||
193 | const struct sockaddr_in *netmask4 = (const struct sockaddr_in *) netmask; | ||
194 | struct sockaddr_in *tmp; | ||
195 | struct sockaddr_in network4; | ||
196 | |||
197 | net = GNUNET_malloc (sizeof(struct NT_Network) + 2 * sizeof(struct | ||
198 | sockaddr_in)); | ||
199 | tmp = (struct sockaddr_in *) &net[1]; | ||
200 | net->network = (struct sockaddr *) &tmp[0]; | ||
201 | net->netmask = (struct sockaddr *) &tmp[1]; | ||
202 | net->length = addrlen; | ||
203 | |||
204 | memset (&network4, | ||
205 | 0, | ||
206 | sizeof(network4)); | ||
207 | network4.sin_family = AF_INET; | ||
208 | #if HAVE_SOCKADDR_IN_SIN_LEN | ||
209 | network4.sin_len = sizeof(network4); | ||
210 | #endif | ||
211 | network4.sin_addr.s_addr = (addr4->sin_addr.s_addr | ||
212 | & netmask4->sin_addr.s_addr); | ||
213 | |||
214 | GNUNET_memcpy (net->netmask, | ||
215 | netmask4, | ||
216 | sizeof(struct sockaddr_in)); | ||
217 | GNUNET_memcpy (net->network, | ||
218 | &network4, | ||
219 | sizeof(struct sockaddr_in)); | ||
220 | } | ||
221 | |||
222 | if (addr->sa_family == AF_INET6) | ||
223 | { | ||
224 | const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6 *) addr; | ||
225 | const struct sockaddr_in6 *netmask6 = (const struct sockaddr_in6 *) netmask; | ||
226 | struct sockaddr_in6 *tmp; | ||
227 | struct sockaddr_in6 network6; | ||
228 | |||
229 | net = GNUNET_malloc (sizeof(struct NT_Network) + 2 * sizeof(struct | ||
230 | sockaddr_in6)); | ||
231 | tmp = (struct sockaddr_in6 *) &net[1]; | ||
232 | net->network = (struct sockaddr *) &tmp[0]; | ||
233 | net->netmask = (struct sockaddr *) &tmp[1]; | ||
234 | net->length = addrlen; | ||
235 | |||
236 | memset (&network6, 0, sizeof(network6)); | ||
237 | network6.sin6_family = AF_INET6; | ||
238 | #if HAVE_SOCKADDR_IN_SIN_LEN | ||
239 | network6.sin6_len = sizeof(network6); | ||
240 | #endif | ||
241 | unsigned int c = 0; | ||
242 | uint32_t *addr_elem = (uint32_t *) &addr6->sin6_addr; | ||
243 | uint32_t *mask_elem = (uint32_t *) &netmask6->sin6_addr; | ||
244 | uint32_t *net_elem = (uint32_t *) &network6.sin6_addr; | ||
245 | for (c = 0; c < 4; c++) | ||
246 | net_elem[c] = addr_elem[c] & mask_elem[c]; | ||
247 | |||
248 | GNUNET_memcpy (net->netmask, | ||
249 | netmask6, | ||
250 | sizeof(struct sockaddr_in6)); | ||
251 | GNUNET_memcpy (net->network, | ||
252 | &network6, | ||
253 | sizeof(struct sockaddr_in6)); | ||
254 | } | ||
255 | if (NULL == net) | ||
256 | return GNUNET_OK; /* odd / unsupported address family */ | ||
257 | |||
258 | /* Store in list */ | ||
259 | #if VERBOSE_NT | ||
260 | char *netmask = GNUNET_strdup (GNUNET_a2s ((struct sockaddr *) net->netmask, | ||
261 | addrlen)); | ||
262 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, | ||
263 | "nt", | ||
264 | "Adding network `%s', netmask `%s'\n", | ||
265 | GNUNET_a2s ((struct sockaddr *) net->network, | ||
266 | addrlen), | ||
267 | netmask); | ||
268 | GNUNET_free (netmask); | ||
269 | #endif | ||
270 | GNUNET_CONTAINER_DLL_insert (is->net_head, | ||
271 | is->net_tail, | ||
272 | net); | ||
273 | |||
274 | return GNUNET_OK; | ||
275 | } | ||
276 | |||
277 | |||
278 | /** | ||
279 | * Periodically get list of network addresses from our interfaces. | ||
280 | * | ||
281 | * @param cls closure | ||
282 | */ | ||
283 | static void | ||
284 | get_addresses (void *cls) | ||
285 | { | ||
286 | struct GNUNET_NT_InterfaceScanner *is = cls; | ||
287 | |||
288 | is->interface_task = NULL; | ||
289 | delete_networks (is); | ||
290 | GNUNET_OS_network_interfaces_list (&interface_proc, | ||
291 | is); | ||
292 | is->interface_task = GNUNET_SCHEDULER_add_delayed ( | ||
293 | INTERFACE_PROCESSING_INTERVAL, | ||
294 | &get_addresses, | ||
295 | is); | ||
296 | } | ||
297 | |||
298 | |||
299 | /** | ||
300 | * Returns where the address is located: LAN or WAN or ... | ||
301 | * | ||
302 | * @param is the interface scanner handle | ||
303 | * @param addr address | ||
304 | * @param addrlen address length | ||
305 | * @return type of the network the address belongs to | ||
306 | */ | ||
307 | enum GNUNET_NetworkType | ||
308 | GNUNET_NT_scanner_get_type (struct GNUNET_NT_InterfaceScanner *is, | ||
309 | const struct sockaddr *addr, | ||
310 | socklen_t addrlen) | ||
311 | { | ||
312 | struct NT_Network *cur = is->net_head; | ||
313 | enum GNUNET_NetworkType type = GNUNET_NT_UNSPECIFIED; | ||
314 | |||
315 | switch (addr->sa_family) | ||
316 | { | ||
317 | case AF_UNIX: | ||
318 | type = GNUNET_NT_LOOPBACK; | ||
319 | break; | ||
320 | |||
321 | case AF_INET: | ||
322 | { | ||
323 | const struct sockaddr_in *a4 = (const struct sockaddr_in *) addr; | ||
324 | |||
325 | if ((a4->sin_addr.s_addr & htonl (0xff000000)) == htonl (0x7f000000)) | ||
326 | type = GNUNET_NT_LOOPBACK; | ||
327 | break; | ||
328 | } | ||
329 | |||
330 | case AF_INET6: | ||
331 | { | ||
332 | const struct sockaddr_in6 *a6 = (const struct sockaddr_in6 *) addr; | ||
333 | |||
334 | if (IN6_IS_ADDR_LOOPBACK (&a6->sin6_addr)) | ||
335 | type = GNUNET_NT_LOOPBACK; | ||
336 | break; | ||
337 | } | ||
338 | |||
339 | default: | ||
340 | GNUNET_break (0); | ||
341 | break; | ||
342 | } | ||
343 | |||
344 | /* Check local networks */ | ||
345 | while ((NULL != cur) && (GNUNET_NT_UNSPECIFIED == type)) | ||
346 | { | ||
347 | if (addrlen != cur->length) | ||
348 | { | ||
349 | cur = cur->next; | ||
350 | continue; | ||
351 | } | ||
352 | if (addr->sa_family == AF_INET) | ||
353 | { | ||
354 | const struct sockaddr_in *a4 = (const struct sockaddr_in *) addr; | ||
355 | const struct sockaddr_in *net4 = (const struct | ||
356 | sockaddr_in *) cur->network; | ||
357 | const struct sockaddr_in *mask4 = (const struct | ||
358 | sockaddr_in *) cur->netmask; | ||
359 | |||
360 | if (((a4->sin_addr.s_addr & mask4->sin_addr.s_addr)) == | ||
361 | net4->sin_addr.s_addr) | ||
362 | type = GNUNET_NT_LAN; | ||
363 | } | ||
364 | if (addr->sa_family == AF_INET6) | ||
365 | { | ||
366 | const struct sockaddr_in6 *a6 = (const struct sockaddr_in6 *) addr; | ||
367 | const struct sockaddr_in6 *net6 = (const struct | ||
368 | sockaddr_in6 *) cur->network; | ||
369 | const struct sockaddr_in6 *mask6 = (const struct | ||
370 | sockaddr_in6 *) cur->netmask; | ||
371 | |||
372 | int res = GNUNET_YES; | ||
373 | int c = 0; | ||
374 | uint32_t *addr_elem = (uint32_t *) &a6->sin6_addr; | ||
375 | uint32_t *mask_elem = (uint32_t *) &mask6->sin6_addr; | ||
376 | uint32_t *net_elem = (uint32_t *) &net6->sin6_addr; | ||
377 | for (c = 0; c < 4; c++) | ||
378 | if ((addr_elem[c] & mask_elem[c]) != net_elem[c]) | ||
379 | res = GNUNET_NO; | ||
380 | |||
381 | if (res == GNUNET_YES) | ||
382 | type = GNUNET_NT_LAN; | ||
383 | } | ||
384 | cur = cur->next; | ||
385 | } | ||
386 | |||
387 | /* no local network found for this address, default: WAN */ | ||
388 | if (type == GNUNET_NT_UNSPECIFIED) | ||
389 | type = GNUNET_NT_WAN; | ||
390 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, | ||
391 | "nt-scanner-api", | ||
392 | "`%s' is in network `%s'\n", | ||
393 | GNUNET_a2s (addr, | ||
394 | addrlen), | ||
395 | GNUNET_NT_to_string (type)); | ||
396 | return type; | ||
397 | } | ||
398 | |||
399 | |||
400 | /** | ||
401 | * Initialize the interface scanner. | ||
402 | * | ||
403 | * @return interface scanner | ||
404 | */ | ||
405 | struct GNUNET_NT_InterfaceScanner * | ||
406 | GNUNET_NT_scanner_init () | ||
407 | { | ||
408 | struct GNUNET_NT_InterfaceScanner *is; | ||
409 | |||
410 | is = GNUNET_new (struct GNUNET_NT_InterfaceScanner); | ||
411 | GNUNET_OS_network_interfaces_list (&interface_proc, | ||
412 | is); | ||
413 | is->interface_task = GNUNET_SCHEDULER_add_delayed ( | ||
414 | INTERFACE_PROCESSING_INTERVAL, | ||
415 | &get_addresses, | ||
416 | is); | ||
417 | return is; | ||
418 | } | ||
419 | |||
420 | |||
421 | /** | ||
422 | * Client is done with the interface scanner, release resources. | ||
423 | * | ||
424 | * @param is handle to release | ||
425 | */ | ||
426 | void | ||
427 | GNUNET_NT_scanner_done (struct GNUNET_NT_InterfaceScanner *is) | ||
428 | { | ||
429 | if (NULL != is->interface_task) | ||
430 | { | ||
431 | GNUNET_SCHEDULER_cancel (is->interface_task); | ||
432 | is->interface_task = NULL; | ||
433 | } | ||
434 | delete_networks (is); | ||
435 | GNUNET_free (is); | ||
436 | } | ||
437 | |||
438 | |||
439 | /* end of nt.c */ | ||