GNUnet  0.11.x
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 #include "gnunet_nt_lib.h"
29 
33 #define INTERFACE_PROCESSING_INTERVAL GNUNET_TIME_relative_multiply ( \
34  GNUNET_TIME_UNIT_MINUTES, 2)
35 
36 
43 const char *
45 {
46  switch (net)
47  {
49  return "UNSPECIFIED";
50 
51  case GNUNET_NT_LOOPBACK:
52  return "LOOPBACK";
53 
54  case GNUNET_NT_LAN:
55  return "LAN";
56 
57  case GNUNET_NT_WAN:
58  return "WAN";
59 
60  case GNUNET_NT_WLAN:
61  return "WLAN";
62 
63  case GNUNET_NT_BT:
64  return "BLUETOOTH";
65 
66  default:
67  return NULL;
68  }
69 }
70 
71 
78 struct NT_Network
79 {
83  struct NT_Network *next;
84 
88  struct NT_Network *prev;
89 
93  struct sockaddr *network;
94 
98  struct sockaddr *netmask;
99 
103  socklen_t length;
104 };
105 
106 
111 {
116 
121 
126 };
127 
128 
134 static void
136 {
137  struct NT_Network *cur;
138 
139  while (NULL != (cur = is->net_head))
140  {
142  is->net_tail,
143  cur);
144  GNUNET_free (cur);
145  }
146 }
147 
148 
163 static int
164 interface_proc (void *cls,
165  const char *name,
166  int isDefault,
167  const struct sockaddr *addr,
168  const struct sockaddr *broadcast_addr,
169  const struct sockaddr *netmask,
170  socklen_t addrlen)
171 {
172  struct GNUNET_NT_InterfaceScanner *is = cls;
173  /* Calculate network */
174  struct NT_Network *net = NULL;
175 
176  (void) name;
177  (void) isDefault;
178  (void) broadcast_addr;
179 
180  /* Skipping IPv4 loopback addresses since we have special check */
181  if (addr->sa_family == AF_INET)
182  {
183  const struct sockaddr_in *a4 = (const struct sockaddr_in *) addr;
184 
185  if ((a4->sin_addr.s_addr & htonl (0xff000000)) == htonl (0x7f000000))
186  return GNUNET_OK;
187  }
188  /* Skipping IPv6 loopback addresses since we have special check */
189  if (addr->sa_family == AF_INET6)
190  {
191  const struct sockaddr_in6 *a6 = (const struct sockaddr_in6 *) addr;
192  if (IN6_IS_ADDR_LOOPBACK (&a6->sin6_addr))
193  return GNUNET_OK;
194  }
195 
196  if (addr->sa_family == AF_INET)
197  {
198  const struct sockaddr_in *addr4 = (const struct sockaddr_in *) addr;
199  const struct sockaddr_in *netmask4 = (const struct sockaddr_in *) netmask;
200  struct sockaddr_in *tmp;
201  struct sockaddr_in network4;
202 
203  net = GNUNET_malloc (sizeof(struct NT_Network) + 2 * sizeof(struct
204  sockaddr_in));
205  tmp = (struct sockaddr_in *) &net[1];
206  net->network = (struct sockaddr *) &tmp[0];
207  net->netmask = (struct sockaddr *) &tmp[1];
208  net->length = addrlen;
209 
210  memset (&network4,
211  0,
212  sizeof(network4));
213  network4.sin_family = AF_INET;
214 #if HAVE_SOCKADDR_IN_SIN_LEN
215  network4.sin_len = sizeof(network4);
216 #endif
217  network4.sin_addr.s_addr = (addr4->sin_addr.s_addr
218  & netmask4->sin_addr.s_addr);
219 
220  GNUNET_memcpy (net->netmask,
221  netmask4,
222  sizeof(struct sockaddr_in));
223  GNUNET_memcpy (net->network,
224  &network4,
225  sizeof(struct sockaddr_in));
226  }
227 
228  if (addr->sa_family == AF_INET6)
229  {
230  const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6 *) addr;
231  const struct sockaddr_in6 *netmask6 = (const struct sockaddr_in6 *) netmask;
232  struct sockaddr_in6 *tmp;
233  struct sockaddr_in6 network6;
234 
235  net = GNUNET_malloc (sizeof(struct NT_Network) + 2 * sizeof(struct
236  sockaddr_in6));
237  tmp = (struct sockaddr_in6 *) &net[1];
238  net->network = (struct sockaddr *) &tmp[0];
239  net->netmask = (struct sockaddr *) &tmp[1];
240  net->length = addrlen;
241 
242  memset (&network6, 0, sizeof(network6));
243  network6.sin6_family = AF_INET6;
244 #if HAVE_SOCKADDR_IN_SIN_LEN
245  network6.sin6_len = sizeof(network6);
246 #endif
247  unsigned int c = 0;
248  uint32_t *addr_elem = (uint32_t *) &addr6->sin6_addr;
249  uint32_t *mask_elem = (uint32_t *) &netmask6->sin6_addr;
250  uint32_t *net_elem = (uint32_t *) &network6.sin6_addr;
251  for (c = 0; c < 4; c++)
252  net_elem[c] = addr_elem[c] & mask_elem[c];
253 
254  GNUNET_memcpy (net->netmask,
255  netmask6,
256  sizeof(struct sockaddr_in6));
257  GNUNET_memcpy (net->network,
258  &network6,
259  sizeof(struct sockaddr_in6));
260  }
261  if (NULL == net)
262  return GNUNET_OK; /* odd / unsupported address family */
263 
264  /* Store in list */
265 #if VERBOSE_NT
266  char *netmask = GNUNET_strdup (GNUNET_a2s ((struct sockaddr *) net->netmask,
267  addrlen));
269  "nt",
270  "Adding network `%s', netmask `%s'\n",
271  GNUNET_a2s ((struct sockaddr *) net->network,
272  addrlen),
273  netmask);
274  GNUNET_free (netmask);
275 #endif
277  is->net_tail,
278  net);
279 
280  return GNUNET_OK;
281 }
282 
283 
289 static void
290 get_addresses (void *cls)
291 {
292  struct GNUNET_NT_InterfaceScanner *is = cls;
293 
294  is->interface_task = NULL;
295  delete_networks (is);
297  is);
300  &get_addresses,
301  is);
302 }
303 
304 
315  const struct sockaddr *addr,
316  socklen_t addrlen)
317 {
318  struct NT_Network *cur = is->net_head;
320 
321  switch (addr->sa_family)
322  {
323  case AF_UNIX:
324  type = GNUNET_NT_LOOPBACK;
325  break;
326 
327  case AF_INET:
328  {
329  const struct sockaddr_in *a4 = (const struct sockaddr_in *) addr;
330 
331  if ((a4->sin_addr.s_addr & htonl (0xff000000)) == htonl (0x7f000000))
332  type = GNUNET_NT_LOOPBACK;
333  break;
334  }
335 
336  case AF_INET6:
337  {
338  const struct sockaddr_in6 *a6 = (const struct sockaddr_in6 *) addr;
339 
340  if (IN6_IS_ADDR_LOOPBACK (&a6->sin6_addr))
341  type = GNUNET_NT_LOOPBACK;
342  break;
343  }
344 
345  default:
346  GNUNET_break (0);
347  break;
348  }
349 
350  /* Check local networks */
351  while ((NULL != cur) && (GNUNET_NT_UNSPECIFIED == type))
352  {
353  if (addrlen != cur->length)
354  {
355  cur = cur->next;
356  continue;
357  }
358  if (addr->sa_family == AF_INET)
359  {
360  const struct sockaddr_in *a4 = (const struct sockaddr_in *) addr;
361  const struct sockaddr_in *net4 = (const struct
362  sockaddr_in *) cur->network;
363  const struct sockaddr_in *mask4 = (const struct
364  sockaddr_in *) cur->netmask;
365 
366  if (((a4->sin_addr.s_addr & mask4->sin_addr.s_addr)) ==
367  net4->sin_addr.s_addr)
368  type = GNUNET_NT_LAN;
369  }
370  if (addr->sa_family == AF_INET6)
371  {
372  const struct sockaddr_in6 *a6 = (const struct sockaddr_in6 *) addr;
373  const struct sockaddr_in6 *net6 = (const struct
374  sockaddr_in6 *) cur->network;
375  const struct sockaddr_in6 *mask6 = (const struct
376  sockaddr_in6 *) cur->netmask;
377 
378  int res = GNUNET_YES;
379  int c = 0;
380  uint32_t *addr_elem = (uint32_t *) &a6->sin6_addr;
381  uint32_t *mask_elem = (uint32_t *) &mask6->sin6_addr;
382  uint32_t *net_elem = (uint32_t *) &net6->sin6_addr;
383  for (c = 0; c < 4; c++)
384  if ((addr_elem[c] & mask_elem[c]) != net_elem[c])
385  res = GNUNET_NO;
386 
387  if (res == GNUNET_YES)
388  type = GNUNET_NT_LAN;
389  }
390  cur = cur->next;
391  }
392 
393  /* no local network found for this address, default: WAN */
394  if (type == GNUNET_NT_UNSPECIFIED)
395  type = GNUNET_NT_WAN;
397  "nt-scanner-api",
398  "`%s' is in network `%s'\n",
399  GNUNET_a2s (addr,
400  addrlen),
401  GNUNET_NT_to_string (type));
402  return type;
403 }
404 
405 
413 {
415 
418  is);
421  &get_addresses,
422  is);
423  return is;
424 }
425 
426 
432 void
434 {
435  if (NULL != is->interface_task)
436  {
438  is->interface_task = NULL;
439  }
440  delete_networks (is);
441  GNUNET_free (is);
442 }
443 
444 
445 /* end of nt.c */
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
Handle to the interface scanner.
Definition: nt.c:110
Local area network.
Definition: gnunet_nt_lib.h:50
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:314
We keep a list of our local networks so we can answer LAN vs.
Definition: nt.c:78
const char * GNUNET_NT_to_string(enum GNUNET_NetworkType net)
Convert a enum GNUNET_NetworkType to a string.
Definition: nt.c:44
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
static void delete_networks(struct GNUNET_NT_InterfaceScanner *is)
Delete all entries from the current network list.
Definition: nt.c:135
struct sockaddr * network
Network address.
Definition: nt.c:93
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
Wide area network (i.e.
Definition: gnunet_nt_lib.h:55
#define GNUNET_NO
Definition: gnunet_common.h:78
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
Wireless LAN (i.e.
Definition: gnunet_nt_lib.h:60
static struct GNUNET_NT_InterfaceScanner * is
Network scanner to determine network types.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
void GNUNET_OS_network_interfaces_list(GNUNET_OS_NetworkInterfaceProcessor proc, void *proc_cls)
Enumerate all network interfaces.
Definition: os_network.c:396
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
struct NT_Network * prev
Kept in a DLL.
Definition: nt.c:88
GNUNET_NetworkType
Types of networks (with separate quotas) we support.
Definition: gnunet_nt_lib.h:35
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
struct NT_Network * net_head
Head of LAN networks list.
Definition: nt.c:115
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:164
struct NT_Network * net_tail
Tail of LAN networks list.
Definition: nt.c:120
Bluetooth LAN.
Definition: gnunet_nt_lib.h:65
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:1253
socklen_t length
How long are network and netmask?
Definition: nt.c:103
#define INTERFACE_PROCESSING_INTERVAL
How frequently do we scan the interfaces for changes to the addresses?
Definition: nt.c:33
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)...
struct NT_Network * next
Kept in a DLL.
Definition: nt.c:83
static int res
void GNUNET_NT_scanner_done(struct GNUNET_NT_InterfaceScanner *is)
Client is done with the interface scanner, release resources.
Definition: nt.c:433
struct GNUNET_NT_InterfaceScanner * GNUNET_NT_scanner_init()
Initialize the interface scanner.
Definition: nt.c:412
Loopback (same host).
Definition: gnunet_nt_lib.h:45
struct sockaddr * netmask
Netmask to determine what is in the LAN.
Definition: nt.c:98
const char * name
Entry in list of pending tasks.
Definition: scheduler.c:134
struct GNUNET_SCHEDULER_Task * interface_task
Task for periodically refreshing our LAN network list.
Definition: nt.c:125
enum GNUNET_TESTBED_UnderlayLinkModelType type
the type of this model
#define GNUNET_YES
Definition: gnunet_common.h:77
#define GNUNET_log_from(kind, comp,...)
#define GNUNET_malloc(size)
Wrapper around malloc.
static void get_addresses(void *cls)
Periodically get list of network addresses from our interfaces.
Definition: nt.c:290
#define GNUNET_free(ptr)
Wrapper around free.
Category of last resort.
Definition: gnunet_nt_lib.h:40
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:966