GNUnet  0.10.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 (GNUNET_TIME_UNIT_MINUTES, 2)
34 
35 
42 const char *
44 {
45  switch (net)
46  {
48  return "UNSPECIFIED";
49  case GNUNET_NT_LOOPBACK:
50  return "LOOPBACK";
51  case GNUNET_NT_LAN:
52  return "LAN";
53  case GNUNET_NT_WAN:
54  return "WAN";
55  case GNUNET_NT_WLAN:
56  return "WLAN";
57  case GNUNET_NT_BT:
58  return "BLUETOOTH";
59  default:
60  return NULL;
61  }
62 }
63 
64 
71 struct NT_Network
72 {
76  struct NT_Network *next;
77 
81  struct NT_Network *prev;
82 
86  struct sockaddr *network;
87 
91  struct sockaddr *netmask;
92 
96  socklen_t length;
97 };
98 
99 
104 {
105 
110 
115 
120 
121 };
122 
123 
129 static void
131 {
132  struct NT_Network *cur;
133 
134  while (NULL != (cur = is->net_head))
135  {
137  is->net_tail,
138  cur);
139  GNUNET_free (cur);
140  }
141 }
142 
143 
158 static int
159 interface_proc (void *cls,
160  const char *name,
161  int isDefault,
162  const struct sockaddr *addr,
163  const struct sockaddr *broadcast_addr,
164  const struct sockaddr *netmask,
165  socklen_t addrlen)
166 {
167  struct GNUNET_NT_InterfaceScanner *is = cls;
168  /* Calculate network */
169  struct NT_Network *net = NULL;
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 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 & netmask4->sin_addr.s_addr);
211 
212  GNUNET_memcpy (net->netmask,
213  netmask4,
214  sizeof (struct sockaddr_in));
215  GNUNET_memcpy (net->network,
216  &network4,
217  sizeof (struct sockaddr_in));
218  }
219 
220  if (addr->sa_family == AF_INET6)
221  {
222  const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6 *) addr;
223  const struct sockaddr_in6 *netmask6 = (const struct sockaddr_in6 *) netmask;
224  struct sockaddr_in6 * tmp;
225  struct sockaddr_in6 network6;
226 
227  net = GNUNET_malloc (sizeof (struct NT_Network) + 2 * sizeof (struct sockaddr_in6));
228  tmp = (struct sockaddr_in6 *) &net[1];
229  net->network = (struct sockaddr *) &tmp[0];
230  net->netmask = (struct sockaddr *) &tmp[1];
231  net->length = addrlen;
232 
233  memset (&network6, 0, sizeof (network6));
234  network6.sin6_family = AF_INET6;
235 #if HAVE_SOCKADDR_IN_SIN_LEN
236  network6.sin6_len = sizeof (network6);
237 #endif
238  unsigned int c = 0;
239  uint32_t *addr_elem = (uint32_t *) &addr6->sin6_addr;
240  uint32_t *mask_elem = (uint32_t *) &netmask6->sin6_addr;
241  uint32_t *net_elem = (uint32_t *) &network6.sin6_addr;
242  for (c = 0; c < 4; c++)
243  net_elem[c] = addr_elem[c] & mask_elem[c];
244 
245  GNUNET_memcpy (net->netmask,
246  netmask6,
247  sizeof (struct sockaddr_in6));
248  GNUNET_memcpy (net->network,
249  &network6,
250  sizeof (struct sockaddr_in6));
251  }
252  if (NULL == net)
253  return GNUNET_OK; /* odd / unsupported address family */
254 
255  /* Store in list */
256 #if VERBOSE_NT
257  char * netmask = GNUNET_strdup (GNUNET_a2s((struct sockaddr *) net->netmask, addrlen));
259  "nt",
260  "Adding network `%s', netmask `%s'\n",
261  GNUNET_a2s ((struct sockaddr *) net->network,
262  addrlen),
263  netmask);
264  GNUNET_free (netmask);
265 #endif
267  is->net_tail,
268  net);
269 
270  return GNUNET_OK;
271 }
272 
273 
279 static void
280 get_addresses (void *cls)
281 {
282  struct GNUNET_NT_InterfaceScanner *is = cls;
283 
284  is->interface_task = NULL;
285  delete_networks (is);
287  is);
289  &get_addresses,
290  is);
291 }
292 
293 
304  const struct sockaddr *addr,
305  socklen_t addrlen)
306 {
307  struct NT_Network *cur = is->net_head;
309 
310  switch (addr->sa_family)
311  {
312  case AF_UNIX:
313  type = GNUNET_NT_LOOPBACK;
314  break;
315  case AF_INET:
316  {
317  const struct sockaddr_in *a4 = (const struct sockaddr_in *) addr;
318 
319  if ((a4->sin_addr.s_addr & htonl(0xff000000)) == htonl (0x7f000000))
320  type = GNUNET_NT_LOOPBACK;
321  break;
322  }
323  case AF_INET6:
324  {
325  const struct sockaddr_in6 *a6 = (const struct sockaddr_in6 *) addr;
326 
327  if (IN6_IS_ADDR_LOOPBACK (&a6->sin6_addr))
328  type = GNUNET_NT_LOOPBACK;
329  break;
330  }
331  default:
332  GNUNET_break (0);
333  break;
334  }
335 
336  /* Check local networks */
337  while ((NULL != cur) && (GNUNET_NT_UNSPECIFIED == type))
338  {
339  if (addrlen != cur->length)
340  {
341  cur = cur->next;
342  continue;
343  }
344  if (addr->sa_family == AF_INET)
345  {
346  const struct sockaddr_in *a4 = (const struct sockaddr_in *) addr;
347  const struct sockaddr_in *net4 = (const struct sockaddr_in *) cur->network;
348  const struct sockaddr_in *mask4 = (const struct sockaddr_in *) cur->netmask;
349 
350  if (((a4->sin_addr.s_addr & mask4->sin_addr.s_addr)) == net4->sin_addr.s_addr)
351  type = GNUNET_NT_LAN;
352  }
353  if (addr->sa_family == AF_INET6)
354  {
355  const struct sockaddr_in6 *a6 = (const struct sockaddr_in6 *) addr;
356  const struct sockaddr_in6 *net6 = (const struct sockaddr_in6 *) cur->network;
357  const struct sockaddr_in6 *mask6 = (const struct sockaddr_in6 *) cur->netmask;
358 
359  int res = GNUNET_YES;
360  int c = 0;
361  uint32_t *addr_elem = (uint32_t *) &a6->sin6_addr;
362  uint32_t *mask_elem = (uint32_t *) &mask6->sin6_addr;
363  uint32_t *net_elem = (uint32_t *) &net6->sin6_addr;
364  for (c = 0; c < 4; c++)
365  if ((addr_elem[c] & mask_elem[c]) != net_elem[c])
366  res = GNUNET_NO;
367 
368  if (res == GNUNET_YES)
369  type = GNUNET_NT_LAN;
370  }
371  cur = cur->next;
372  }
373 
374  /* no local network found for this address, default: WAN */
375  if (type == GNUNET_NT_UNSPECIFIED)
376  type = GNUNET_NT_WAN;
378  "nt-scanner-api",
379  "`%s' is in network `%s'\n",
380  GNUNET_a2s (addr,
381  addrlen),
382  GNUNET_NT_to_string (type));
383  return type;
384 }
385 
386 
394 {
396 
399  is);
401  &get_addresses,
402  is);
403  return is;
404 }
405 
406 
412 void
414 {
415  if (NULL != is->interface_task)
416  {
418  is->interface_task = NULL;
419  }
420  delete_networks (is);
421  GNUNET_free (is);
422 }
423 
424 
425 /* 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:103
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:303
We keep a list of our local networks so we can answer LAN vs.
Definition: nt.c:71
const char * GNUNET_NT_to_string(enum GNUNET_NetworkType net)
Convert a enum GNUNET_NetworkType to a string.
Definition: nt.c:43
#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:130
struct sockaddr * network
Network address.
Definition: nt.c:86
Wide area network (i.e.
Definition: gnunet_nt_lib.h:55
#define GNUNET_NO
Definition: gnunet_common.h:81
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:78
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:388
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
struct NT_Network * prev
Kept in a DLL.
Definition: nt.c:81
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:109
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:159
struct NT_Network * net_tail
Tail of LAN networks list.
Definition: nt.c:114
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:1246
#define GNUNET_memcpy(dst, src, n)
socklen_t length
How long are network and netmask?
Definition: nt.c:96
#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:76
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:413
const char * name
struct GNUNET_NT_InterfaceScanner * GNUNET_NT_scanner_init()
Initialize the interface scanner.
Definition: nt.c:393
Loopback (same host).
Definition: gnunet_nt_lib.h:45
struct sockaddr * netmask
Netmask to determine what is in the LAN.
Definition: nt.c:91
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:119
enum GNUNET_TESTBED_UnderlayLinkModelType type
the type of this model
#define GNUNET_YES
Definition: gnunet_common.h:80
#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:280
#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:965