GNUnet 0.22.2
nt.c
Go to the documentation of this file.
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 */
26#include "platform.h"
27#include "gnunet_util_lib.h"
28
32#define INTERFACE_PROCESSING_INTERVAL GNUNET_TIME_relative_multiply ( \
33 GNUNET_TIME_UNIT_MINUTES, 2)
34
35
36const char *
38{
39 switch (net)
40 {
42 return "UNSPECIFIED";
43
45 return "LOOPBACK";
46
47 case GNUNET_NT_LAN:
48 return "LAN";
49
50 case GNUNET_NT_WAN:
51 return "WAN";
52
53 case GNUNET_NT_WLAN:
54 return "WLAN";
55
56 case GNUNET_NT_BT:
57 return "BLUETOOTH";
58
59 default:
60 return NULL;
61 }
62}
63
64
72{
77
82
86 struct sockaddr *network;
87
91 struct sockaddr *netmask;
92
96 socklen_t length;
97};
98
99
104{
109
114
119};
120
121
127static void
129{
130 struct NT_Network *cur;
131
132 while (NULL != (cur = is->net_head))
133 {
135 is->net_tail,
136 cur);
137 GNUNET_free (cur);
138 }
139}
140
141
156static int
157interface_proc (void *cls,
158 const char *name,
159 int isDefault,
160 const struct sockaddr *addr,
161 const struct sockaddr *broadcast_addr,
162 const struct sockaddr *netmask,
163 socklen_t addrlen)
164{
165 struct GNUNET_NT_InterfaceScanner *is = cls;
166 /* Calculate network */
167 struct NT_Network *net = NULL;
168
169 (void) name;
170 (void) isDefault;
171 (void) broadcast_addr;
172
173 /* Skipping IPv4 loopback addresses since we have special check */
174 if (addr->sa_family == AF_INET)
175 {
176 const struct sockaddr_in *a4 = (const struct sockaddr_in *) addr;
177
178 if ((a4->sin_addr.s_addr & htonl (0xff000000)) == htonl (0x7f000000))
179 return GNUNET_OK;
180 }
181 /* Skipping IPv6 loopback addresses since we have special check */
182 if (addr->sa_family == AF_INET6)
183 {
184 const struct sockaddr_in6 *a6 = (const struct sockaddr_in6 *) addr;
185 if (IN6_IS_ADDR_LOOPBACK (&a6->sin6_addr))
186 return GNUNET_OK;
187 }
188
189 if (addr->sa_family == AF_INET)
190 {
191 const struct sockaddr_in *addr4 = (const struct sockaddr_in *) addr;
192 const struct sockaddr_in *netmask4 = (const struct sockaddr_in *) netmask;
193 struct sockaddr_in *tmp;
194 struct sockaddr_in network4;
195
196 net = GNUNET_malloc (sizeof(struct NT_Network) + 2 * sizeof(struct
197 sockaddr_in));
198 tmp = (struct sockaddr_in *) &net[1];
199 net->network = (struct sockaddr *) &tmp[0];
200 net->netmask = (struct sockaddr *) &tmp[1];
201 net->length = addrlen;
202
203 memset (&network4,
204 0,
205 sizeof(network4));
206 network4.sin_family = AF_INET;
207#if HAVE_SOCKADDR_IN_SIN_LEN
208 network4.sin_len = sizeof(network4);
209#endif
210 network4.sin_addr.s_addr = (addr4->sin_addr.s_addr
211 & netmask4->sin_addr.s_addr);
212
213 GNUNET_memcpy (net->netmask,
214 netmask4,
215 sizeof(struct sockaddr_in));
216 GNUNET_memcpy (net->network,
217 &network4,
218 sizeof(struct sockaddr_in));
219 }
220
221 if (addr->sa_family == AF_INET6)
222 {
223 const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6 *) addr;
224 const struct sockaddr_in6 *netmask6 = (const struct sockaddr_in6 *) netmask;
225 struct sockaddr_in6 *tmp;
226 struct sockaddr_in6 network6;
227
228 net = GNUNET_malloc (sizeof(struct NT_Network) + 2 * sizeof(struct
229 sockaddr_in6));
230 tmp = (struct sockaddr_in6 *) &net[1];
231 net->network = (struct sockaddr *) &tmp[0];
232 net->netmask = (struct sockaddr *) &tmp[1];
233 net->length = addrlen;
234
235 memset (&network6, 0, sizeof(network6));
236 network6.sin6_family = AF_INET6;
237#if HAVE_SOCKADDR_IN_SIN_LEN
238 network6.sin6_len = sizeof(network6);
239#endif
240 {
241 unsigned int c;
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 }
256 if (NULL == net)
257 return GNUNET_OK; /* odd / unsupported address family */
258
259 /* Store in list */
260#if VERBOSE_NT
261 char *netmask = GNUNET_strdup (GNUNET_a2s ((struct sockaddr *) net->netmask,
262 addrlen));
264 "nt",
265 "Adding network `%s', netmask `%s'\n",
266 GNUNET_a2s ((struct sockaddr *) net->network,
267 addrlen),
268 netmask);
269 GNUNET_free (netmask);
270#endif
272 is->net_tail,
273 net);
274
275 return GNUNET_OK;
276}
277
278
284static void
285get_addresses (void *cls)
286{
287 struct GNUNET_NT_InterfaceScanner *is = cls;
288
289 is->interface_task = NULL;
292 is);
293 is->interface_task = GNUNET_SCHEDULER_add_delayed (
296 is);
297}
298
299
310 const struct sockaddr *addr,
311 socklen_t addrlen)
312{
313 struct NT_Network *cur = is->net_head;
315
316 switch (addr->sa_family)
317 {
318 case AF_UNIX:
320 break;
321
322 case AF_INET:
323 {
324 const struct sockaddr_in *a4 = (const struct sockaddr_in *) addr;
325
326 if ((a4->sin_addr.s_addr & htonl (0xff000000)) == htonl (0x7f000000))
328 break;
329 }
330
331 case AF_INET6:
332 {
333 const struct sockaddr_in6 *a6 = (const struct sockaddr_in6 *) addr;
334
335 if (IN6_IS_ADDR_LOOPBACK (&a6->sin6_addr))
337 break;
338 }
339
340 default:
341 GNUNET_break (0);
342 break;
343 }
344
345 /* Check local networks */
346 while ((NULL != cur) && (GNUNET_NT_UNSPECIFIED == type))
347 {
348 if (addrlen != cur->length)
349 {
350 cur = cur->next;
351 continue;
352 }
353 if (addr->sa_family == AF_INET)
354 {
355 const struct sockaddr_in *a4 = (const struct sockaddr_in *) addr;
356 const struct sockaddr_in *net4 = (const struct
357 sockaddr_in *) cur->network;
358 const struct sockaddr_in *mask4 = (const struct
359 sockaddr_in *) cur->netmask;
360
361 if (((a4->sin_addr.s_addr & mask4->sin_addr.s_addr)) ==
362 net4->sin_addr.s_addr)
364 }
365 if (addr->sa_family == AF_INET6)
366 {
367 const struct sockaddr_in6 *a6 = (const struct sockaddr_in6 *) addr;
368 const struct sockaddr_in6 *net6 = (const struct
369 sockaddr_in6 *) cur->network;
370 const struct sockaddr_in6 *mask6 = (const struct
371 sockaddr_in6 *) cur->netmask;
372
373 int res = GNUNET_YES;
374 int c = 0;
375 uint32_t *addr_elem = (uint32_t *) &a6->sin6_addr;
376 uint32_t *mask_elem = (uint32_t *) &mask6->sin6_addr;
377 uint32_t *net_elem = (uint32_t *) &net6->sin6_addr;
378 for (c = 0; c < 4; c++)
379 if ((addr_elem[c] & mask_elem[c]) != net_elem[c])
380 res = GNUNET_NO;
381
382 if (res == GNUNET_YES)
384 }
385 cur = cur->next;
386 }
387
388 /* no local network found for this address, default: WAN */
392 "nt-scanner-api",
393 "`%s' is in network `%s'\n",
394 GNUNET_a2s (addr,
395 addrlen),
397 return type;
398}
399
400
408{
410
413 is);
414 is->interface_task = GNUNET_SCHEDULER_add_delayed (
417 is);
418 return is;
419}
420
421
427void
429{
430 if (NULL != is->interface_task)
431 {
432 GNUNET_SCHEDULER_cancel (is->interface_task);
433 is->interface_task = NULL;
434 }
436 GNUNET_free (is);
437}
438
439
440/* end of nt.c */
static struct GNUNET_TESTING_Interpreter * is
static char * name
Name (label) of the records to list.
static char * res
Currently read line or NULL on EOF.
static uint32_t type
Type string converted to DNS type value.
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
#define GNUNET_log_from(kind, comp,...)
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
@ GNUNET_OK
@ GNUNET_YES
@ GNUNET_NO
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.
const char * GNUNET_a2s(const struct sockaddr *addr, socklen_t addrlen)
Convert a "struct sockaddr*" (IPv4 or IPv6 address) to a string (for printing debug messages).
@ GNUNET_ERROR_TYPE_DEBUG
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_malloc(size)
Wrapper around malloc.
#define GNUNET_free(ptr)
Wrapper around free.
GNUNET_NetworkType
Types of networks (with separate quotas) we support.
Definition: gnunet_nt_lib.h:44
void GNUNET_NT_scanner_done(struct GNUNET_NT_InterfaceScanner *is)
Client is done with the interface scanner, release resources.
Definition: nt.c:428
struct GNUNET_NT_InterfaceScanner * GNUNET_NT_scanner_init()
Initialize the interface scanner.
Definition: nt.c:407
enum GNUNET_NetworkType GNUNET_NT_scanner_get_type(struct GNUNET_NT_InterfaceScanner *is, const struct sockaddr *addr, socklen_t addrlen)
Returns where the address is located: LAN or WAN or ...
Definition: nt.c:309
const char * GNUNET_NT_to_string(enum GNUNET_NetworkType net)
Convert a enum GNUNET_NetworkType to a string.
Definition: nt.c:37
@ GNUNET_NT_WLAN
Wireless LAN (i.e.
Definition: gnunet_nt_lib.h:68
@ GNUNET_NT_WAN
Wide area network (i.e.
Definition: gnunet_nt_lib.h:63
@ GNUNET_NT_UNSPECIFIED
Category of last resort.
Definition: gnunet_nt_lib.h:48
@ GNUNET_NT_LAN
Local area network.
Definition: gnunet_nt_lib.h:58
@ GNUNET_NT_LOOPBACK
Loopback (same host).
Definition: gnunet_nt_lib.h:53
@ GNUNET_NT_BT
Bluetooth LAN.
Definition: gnunet_nt_lib.h:73
void GNUNET_OS_network_interfaces_list(GNUNET_OS_NetworkInterfaceProcessor proc, void *proc_cls)
Enumerate all network interfaces.
Definition: os_network.c:397
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:980
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_delayed(struct GNUNET_TIME_Relative delay, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay.
Definition: scheduler.c:1277
static int interface_proc(void *cls, const char *name, int isDefault, const struct sockaddr *addr, const struct sockaddr *broadcast_addr, const struct sockaddr *netmask, socklen_t addrlen)
Function invoked for each interface found.
Definition: nt.c:157
static void delete_networks(struct GNUNET_NT_InterfaceScanner *is)
Delete all entries from the current network list.
Definition: nt.c:128
#define INTERFACE_PROCESSING_INTERVAL
How frequently do we scan the interfaces for changes to the addresses?
Definition: nt.c:32
static void get_addresses(void *cls)
Periodically get list of network addresses from our interfaces.
Definition: nt.c:285
Handle to the interface scanner.
Definition: nt.c:104
struct NT_Network * net_head
Head of LAN networks list.
Definition: nt.c:108
struct NT_Network * net_tail
Tail of LAN networks list.
Definition: nt.c:113
struct GNUNET_SCHEDULER_Task * interface_task
Task for periodically refreshing our LAN network list.
Definition: nt.c:118
Entry in list of pending tasks.
Definition: scheduler.c:136
We keep a list of our local networks so we can answer LAN vs.
Definition: nt.c:72
struct NT_Network * next
Kept in a DLL.
Definition: nt.c:76
socklen_t length
How long are network and netmask?
Definition: nt.c:96
struct sockaddr * network
Network address.
Definition: nt.c:86
struct NT_Network * prev
Kept in a DLL.
Definition: nt.c:81
struct sockaddr * netmask
Netmask to determine what is in the LAN.
Definition: nt.c:91