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 
50  case GNUNET_NT_LOOPBACK:
51  return "LOOPBACK";
52 
53  case GNUNET_NT_LAN:
54  return "LAN";
55 
56  case GNUNET_NT_WAN:
57  return "WAN";
58 
59  case GNUNET_NT_WLAN:
60  return "WLAN";
61 
62  case GNUNET_NT_BT:
63  return "BLUETOOTH";
64 
65  default:
66  return NULL;
67  }
68 }
69 
70 
77 struct NT_Network {
81  struct NT_Network *next;
82 
86  struct NT_Network *prev;
87 
91  struct sockaddr *network;
92 
96  struct sockaddr *netmask;
97 
101  socklen_t length;
102 };
103 
104 
113 
118 
123 };
124 
125 
131 static void
133 {
134  struct NT_Network *cur;
135 
136  while (NULL != (cur = is->net_head))
137  {
139  is->net_tail,
140  cur);
141  GNUNET_free(cur);
142  }
143 }
144 
145 
160 static int
161 interface_proc(void *cls,
162  const char *name,
163  int isDefault,
164  const struct sockaddr *addr,
165  const struct sockaddr *broadcast_addr,
166  const struct sockaddr *netmask,
167  socklen_t addrlen)
168 {
169  struct GNUNET_NT_InterfaceScanner *is = cls;
170  /* Calculate network */
171  struct NT_Network *net = NULL;
172 
173  (void)name;
174  (void)isDefault;
175  (void)broadcast_addr;
176 
177  /* Skipping IPv4 loopback addresses since we have special check */
178  if (addr->sa_family == AF_INET)
179  {
180  const struct sockaddr_in *a4 = (const struct sockaddr_in *)addr;
181 
182  if ((a4->sin_addr.s_addr & htonl(0xff000000)) == htonl(0x7f000000))
183  return GNUNET_OK;
184  }
185  /* Skipping IPv6 loopback addresses since we have special check */
186  if (addr->sa_family == AF_INET6)
187  {
188  const struct sockaddr_in6 *a6 = (const struct sockaddr_in6 *)addr;
189  if (IN6_IS_ADDR_LOOPBACK(&a6->sin6_addr))
190  return GNUNET_OK;
191  }
192 
193  if (addr->sa_family == AF_INET)
194  {
195  const struct sockaddr_in *addr4 = (const struct sockaddr_in *)addr;
196  const struct sockaddr_in *netmask4 = (const struct sockaddr_in *)netmask;
197  struct sockaddr_in *tmp;
198  struct sockaddr_in network4;
199 
200  net = GNUNET_malloc(sizeof(struct NT_Network) + 2 * sizeof(struct sockaddr_in));
201  tmp = (struct sockaddr_in *)&net[1];
202  net->network = (struct sockaddr *)&tmp[0];
203  net->netmask = (struct sockaddr *)&tmp[1];
204  net->length = addrlen;
205 
206  memset(&network4,
207  0,
208  sizeof(network4));
209  network4.sin_family = AF_INET;
210 #if HAVE_SOCKADDR_IN_SIN_LEN
211  network4.sin_len = sizeof(network4);
212 #endif
213  network4.sin_addr.s_addr = (addr4->sin_addr.s_addr & netmask4->sin_addr.s_addr);
214 
215  GNUNET_memcpy(net->netmask,
216  netmask4,
217  sizeof(struct sockaddr_in));
218  GNUNET_memcpy(net->network,
219  &network4,
220  sizeof(struct sockaddr_in));
221  }
222 
223  if (addr->sa_family == AF_INET6)
224  {
225  const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6 *)addr;
226  const struct sockaddr_in6 *netmask6 = (const struct sockaddr_in6 *)netmask;
227  struct sockaddr_in6 * tmp;
228  struct sockaddr_in6 network6;
229 
230  net = GNUNET_malloc(sizeof(struct NT_Network) + 2 * sizeof(struct 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, addrlen));
262  "nt",
263  "Adding network `%s', netmask `%s'\n",
264  GNUNET_a2s((struct sockaddr *)net->network,
265  addrlen),
266  netmask);
267  GNUNET_free(netmask);
268 #endif
270  is->net_tail,
271  net);
272 
273  return GNUNET_OK;
274 }
275 
276 
282 static void
283 get_addresses(void *cls)
284 {
285  struct GNUNET_NT_InterfaceScanner *is = cls;
286 
287  is->interface_task = NULL;
288  delete_networks(is);
290  is);
292  &get_addresses,
293  is);
294 }
295 
296 
307  const struct sockaddr *addr,
308  socklen_t addrlen)
309 {
310  struct NT_Network *cur = is->net_head;
312 
313  switch (addr->sa_family)
314  {
315  case AF_UNIX:
316  type = GNUNET_NT_LOOPBACK;
317  break;
318 
319  case AF_INET:
320  {
321  const struct sockaddr_in *a4 = (const struct sockaddr_in *)addr;
322 
323  if ((a4->sin_addr.s_addr & htonl(0xff000000)) == htonl(0x7f000000))
324  type = GNUNET_NT_LOOPBACK;
325  break;
326  }
327 
328  case AF_INET6:
329  {
330  const struct sockaddr_in6 *a6 = (const struct sockaddr_in6 *)addr;
331 
332  if (IN6_IS_ADDR_LOOPBACK(&a6->sin6_addr))
333  type = GNUNET_NT_LOOPBACK;
334  break;
335  }
336 
337  default:
338  GNUNET_break(0);
339  break;
340  }
341 
342  /* Check local networks */
343  while ((NULL != cur) && (GNUNET_NT_UNSPECIFIED == type))
344  {
345  if (addrlen != cur->length)
346  {
347  cur = cur->next;
348  continue;
349  }
350  if (addr->sa_family == AF_INET)
351  {
352  const struct sockaddr_in *a4 = (const struct sockaddr_in *)addr;
353  const struct sockaddr_in *net4 = (const struct sockaddr_in *)cur->network;
354  const struct sockaddr_in *mask4 = (const struct sockaddr_in *)cur->netmask;
355 
356  if (((a4->sin_addr.s_addr & mask4->sin_addr.s_addr)) == net4->sin_addr.s_addr)
357  type = GNUNET_NT_LAN;
358  }
359  if (addr->sa_family == AF_INET6)
360  {
361  const struct sockaddr_in6 *a6 = (const struct sockaddr_in6 *)addr;
362  const struct sockaddr_in6 *net6 = (const struct sockaddr_in6 *)cur->network;
363  const struct sockaddr_in6 *mask6 = (const struct sockaddr_in6 *)cur->netmask;
364 
365  int res = GNUNET_YES;
366  int c = 0;
367  uint32_t *addr_elem = (uint32_t *)&a6->sin6_addr;
368  uint32_t *mask_elem = (uint32_t *)&mask6->sin6_addr;
369  uint32_t *net_elem = (uint32_t *)&net6->sin6_addr;
370  for (c = 0; c < 4; c++)
371  if ((addr_elem[c] & mask_elem[c]) != net_elem[c])
372  res = GNUNET_NO;
373 
374  if (res == GNUNET_YES)
375  type = GNUNET_NT_LAN;
376  }
377  cur = cur->next;
378  }
379 
380  /* no local network found for this address, default: WAN */
381  if (type == GNUNET_NT_UNSPECIFIED)
382  type = GNUNET_NT_WAN;
384  "nt-scanner-api",
385  "`%s' is in network `%s'\n",
386  GNUNET_a2s(addr,
387  addrlen),
388  GNUNET_NT_to_string(type));
389  return type;
390 }
391 
392 
400 {
402 
405  is);
407  &get_addresses,
408  is);
409  return is;
410 }
411 
412 
418 void
420 {
421  if (NULL != is->interface_task)
422  {
424  is->interface_task = NULL;
425  }
426  delete_networks(is);
427  GNUNET_free(is);
428 }
429 
430 
431 /* 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:108
Local area network.
Definition: gnunet_nt_lib.h:49
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:306
We keep a list of our local networks so we can answer LAN vs.
Definition: nt.c:77
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:132
struct sockaddr * network
Network address.
Definition: nt.c:91
#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:54
#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:59
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:86
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:112
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:161
struct NT_Network * net_tail
Tail of LAN networks list.
Definition: nt.c:117
Bluetooth LAN.
Definition: gnunet_nt_lib.h:64
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:1237
socklen_t length
How long are network and netmask?
Definition: nt.c:101
#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:81
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:419
const char * name
struct GNUNET_NT_InterfaceScanner * GNUNET_NT_scanner_init()
Initialize the interface scanner.
Definition: nt.c:399
Loopback (same host).
Definition: gnunet_nt_lib.h:44
struct sockaddr * netmask
Netmask to determine what is in the LAN.
Definition: nt.c:96
Entry in list of pending tasks.
Definition: scheduler.c:131
struct GNUNET_SCHEDULER_Task * interface_task
Task for periodically refreshing our LAN network list.
Definition: nt.c:122
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:283
#define GNUNET_free(ptr)
Wrapper around free.
Category of last resort.
Definition: gnunet_nt_lib.h:39
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:956