GNUnet  0.20.0
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 
37 const char *
39 {
40  switch (net)
41  {
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 
72 struct NT_Network
73 {
77  struct NT_Network *next;
78 
82  struct NT_Network *prev;
83 
87  struct sockaddr *network;
88 
92  struct sockaddr *netmask;
93 
97  socklen_t length;
98 };
99 
100 
105 {
110 
115 
120 };
121 
122 
128 static void
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 
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));
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 
283 static void
284 get_addresses (void *cls)
285 {
286  struct GNUNET_NT_InterfaceScanner *is = cls;
287 
288  is->interface_task = NULL;
291  is);
292  is->interface_task = GNUNET_SCHEDULER_add_delayed (
294  &get_addresses,
295  is);
296 }
297 
298 
309  const struct sockaddr *addr,
310  socklen_t addrlen)
311 {
312  struct NT_Network *cur = is->net_head;
314 
315  switch (addr->sa_family)
316  {
317  case AF_UNIX:
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))
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))
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)
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)
383  }
384  cur = cur->next;
385  }
386 
387  /* no local network found for this address, default: WAN */
391  "nt-scanner-api",
392  "`%s' is in network `%s'\n",
393  GNUNET_a2s (addr,
394  addrlen),
396  return type;
397 }
398 
399 
407 {
409 
412  is);
413  is->interface_task = GNUNET_SCHEDULER_add_delayed (
415  &get_addresses,
416  is);
417  return is;
418 }
419 
420 
426 void
428 {
429  if (NULL != is->interface_task)
430  {
431  GNUNET_SCHEDULER_cancel (is->interface_task);
432  is->interface_task = NULL;
433  }
435  GNUNET_free (is);
436 }
437 
438 
439 /* end of nt.c */
static int res
struct GNUNET_TESTING_Interpreter * is
#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:39
void GNUNET_NT_scanner_done(struct GNUNET_NT_InterfaceScanner *is)
Client is done with the interface scanner, release resources.
Definition: nt.c:427
struct GNUNET_NT_InterfaceScanner * GNUNET_NT_scanner_init()
Initialize the interface scanner.
Definition: nt.c:406
const char * GNUNET_NT_to_string(enum GNUNET_NetworkType net)
Convert a enum GNUNET_NetworkType to a string.
Definition: nt.c:38
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:308
@ GNUNET_NT_WLAN
Wireless LAN (i.e.
Definition: gnunet_nt_lib.h:63
@ GNUNET_NT_WAN
Wide area network (i.e.
Definition: gnunet_nt_lib.h:58
@ GNUNET_NT_UNSPECIFIED
Category of last resort.
Definition: gnunet_nt_lib.h:43
@ GNUNET_NT_LAN
Local area network.
Definition: gnunet_nt_lib.h:53
@ GNUNET_NT_LOOPBACK
Loopback (same host).
Definition: gnunet_nt_lib.h:48
@ GNUNET_NT_BT
Bluetooth LAN.
Definition: gnunet_nt_lib.h:68
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:975
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:1272
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:158
static void delete_networks(struct GNUNET_NT_InterfaceScanner *is)
Delete all entries from the current network list.
Definition: nt.c:129
#define INTERFACE_PROCESSING_INTERVAL
How frequently do we scan the interfaces for changes to the addresses?
Definition: nt.c:33
static void get_addresses(void *cls)
Periodically get list of network addresses from our interfaces.
Definition: nt.c:284
const char * name
Handle to the interface scanner.
Definition: nt.c:105
struct NT_Network * net_head
Head of LAN networks list.
Definition: nt.c:109
struct NT_Network * net_tail
Tail of LAN networks list.
Definition: nt.c:114
struct GNUNET_SCHEDULER_Task * interface_task
Task for periodically refreshing our LAN network list.
Definition: nt.c:119
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:73
struct NT_Network * next
Kept in a DLL.
Definition: nt.c:77
socklen_t length
How long are network and netmask?
Definition: nt.c:97
struct sockaddr * network
Network address.
Definition: nt.c:87
struct NT_Network * prev
Kept in a DLL.
Definition: nt.c:82
struct sockaddr * netmask
Netmask to determine what is in the LAN.
Definition: nt.c:92
enum GNUNET_TESTBED_UnderlayLinkModelType type
the type of this model