GNUnet  0.20.0
plugin_dhtu_ip.c File Reference

plain IP based DHT network underlay More...

#include "platform.h"
#include "gnunet_dhtu_plugin.h"
Include dependency graph for plugin_dhtu_ip.c:

Go to the source code of this file.

Data Structures

struct  GNUNET_DHTU_Source
 Opaque handle that the underlay offers for our address to be used when sending messages to another peer. More...
 
struct  GNUNET_DHTU_Target
 Opaque handle that the underlay offers for the target peer when sending messages to another peer. More...
 
struct  GNUNET_DHTU_PreferenceHandle
 Opaque handle expressing a preference of the DHT to keep a particular target connected. More...
 
struct  Plugin
 Handle for a plugin. More...
 

Macros

#define SCAN_FREQ   GNUNET_TIME_UNIT_MINUTES
 How frequently should we re-scan our local interfaces for IPs? More...
 
#define MAX_DESTS   256
 Maximum number of concurrently active destinations to support. More...
 

Functions

static struct GNUNET_DHTU_Targetcreate_target (struct Plugin *plugin, const struct GNUNET_PeerIdentity *pid, const struct sockaddr *addr, socklen_t addrlen)
 Create a target to which we may send traffic. More...
 
static struct GNUNET_DHTU_Targetfind_target (struct Plugin *plugin, const struct GNUNET_PeerIdentity *pid, const void *addr, size_t addrlen)
 Find target matching addr. More...
 
static void ip_try_connect (void *cls, const struct GNUNET_PeerIdentity *pid, const char *address)
 Request creation of a session with a peer at the given address. More...
 
static struct GNUNET_DHTU_PreferenceHandleip_hold (void *cls, struct GNUNET_DHTU_Target *target)
 Request underlay to keep the connection to target alive if possible. More...
 
static void ip_drop (struct GNUNET_DHTU_PreferenceHandle *ph)
 Do no long request underlay to keep the connection alive. More...
 
static void ip_send (void *cls, struct GNUNET_DHTU_Target *target, const void *msg, size_t msg_size, GNUNET_SCHEDULER_TaskCallback finished_cb, void *finished_cb_cls)
 Send message to some other participant over the network. More...
 
static struct GNUNET_DHTU_Sourcecreate_source (struct Plugin *plugin, const struct sockaddr *addr, socklen_t addrlen)
 Create a new source on which we may be receiving traffic. More...
 
static int addrcmp_np (const struct sockaddr *a1, const struct sockaddr *a2, size_t alen)
 Compare two addresses excluding the ports for equality. More...
 
static int addrcmp (const struct sockaddr *a1, const struct sockaddr *a2, size_t alen)
 Compare two addresses for equality. More...
 
static enum GNUNET_GenericReturnValue process_ifcs (void *cls, const char *name, int isDefault, const struct sockaddr *addr, const struct sockaddr *broadcast_addr, const struct sockaddr *netmask, socklen_t addrlen)
 Callback function invoked for each interface found. More...
 
static void scan (void *cls)
 Scan network interfaces for IP address changes. More...
 
static struct GNUNET_DHTU_Sourcefind_source (struct Plugin *plugin, const void *addr, size_t addrlen)
 Find our source matching addr. More...
 
static void read_cb (void *cls)
 UDP socket is ready to receive. More...
 
void * libgnunet_plugin_dhtu_ip_init (void *cls)
 Entry point for the plugin. More...
 
void * libgnunet_plugin_dhtu_ip_done (void *cls)
 Exit point from the plugin. More...
 

Detailed Description

plain IP based DHT network underlay

Author
Christian Grothoff

Definition in file plugin_dhtu_ip.c.

Macro Definition Documentation

◆ SCAN_FREQ

#define SCAN_FREQ   GNUNET_TIME_UNIT_MINUTES

How frequently should we re-scan our local interfaces for IPs?

Definition at line 33 of file plugin_dhtu_ip.c.

◆ MAX_DESTS

#define MAX_DESTS   256

Maximum number of concurrently active destinations to support.

Definition at line 38 of file plugin_dhtu_ip.c.

Function Documentation

◆ create_target()

static struct GNUNET_DHTU_Target* create_target ( struct Plugin plugin,
const struct GNUNET_PeerIdentity pid,
const struct sockaddr *  addr,
socklen_t  addrlen 
)
static

Create a target to which we may send traffic.

Parameters
pluginour plugin
pidpresumed identity of the target
addrtarget address
addrlennumber of bytes in addr
Returns
new target object

Definition at line 246 of file plugin_dhtu_ip.c.

250 {
251  struct GNUNET_DHTU_Target *dst;
252 
253  if (MAX_DESTS <=
255  {
256  struct GNUNET_HashCode key;
257 
258  dst = NULL;
259  for (struct GNUNET_DHTU_Target *pos = plugin->dst_head;
260  NULL != pos;
261  pos = pos->next)
262  {
263  /* >= here assures we remove oldest entries first */
264  if ( (NULL == dst) ||
265  (dst->ph_count >= pos->ph_count) )
266  dst = pos;
267  }
268  GNUNET_assert (NULL != dst);
269  plugin->env->disconnect_cb (dst->app_ctx);
270  GNUNET_CRYPTO_hash (&dst->addr,
271  dst->addrlen,
272  &key);
275  &key,
276  dst));
278  plugin->dst_tail,
279  dst);
280  GNUNET_assert (NULL == dst->ph_head);
281  GNUNET_free (dst);
282  }
283  dst = GNUNET_new (struct GNUNET_DHTU_Target);
284  dst->addrlen = addrlen;
285  dst->pid = *pid;
286  memcpy (&dst->addr,
287  addr,
288  addrlen);
290  plugin->dst_tail,
291  dst);
292  plugin->env->connect_cb (plugin->env->cls,
293  dst,
294  &dst->pid,
295  &dst->app_ctx);
296  return dst;
297 }
struct TestcasePlugin * plugin
The process handle to the testbed service.
struct GNUNET_HashCode key
The key used in the DHT.
static struct GNUNET_PeerIdentity pid
Identity of the peer we transmit to / connect to.
#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.
void GNUNET_CRYPTO_hash(const void *block, size_t size, struct GNUNET_HashCode *ret)
Compute hash of a given block.
Definition: crypto_hash.c:41
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multihashmap_remove(struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key, const void *value)
Remove the given key-value pair from the map.
unsigned int GNUNET_CONTAINER_multihashmap_size(const struct GNUNET_CONTAINER_MultiHashMap *map)
Get the number of key-value pairs in the map.
@ GNUNET_YES
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_free(ptr)
Wrapper around free.
#define MAX_DESTS
Maximum number of concurrently active destinations to support.
Opaque handle that the underlay offers for the target peer when sending messages to another peer.
A 512-bit hashcode.

References GNUNET_DHTU_Target::addr, GNUNET_DHTU_Target::addrlen, GNUNET_DHTU_Target::app_ctx, GNUNET_assert, GNUNET_CONTAINER_DLL_insert, GNUNET_CONTAINER_DLL_remove, GNUNET_CONTAINER_multihashmap_remove(), GNUNET_CONTAINER_multihashmap_size(), GNUNET_CRYPTO_hash(), GNUNET_free, GNUNET_new, GNUNET_YES, key, MAX_DESTS, GNUNET_DHTU_Target::pid, pid, and plugin.

Referenced by find_target().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ find_target()

static struct GNUNET_DHTU_Target* find_target ( struct Plugin plugin,
const struct GNUNET_PeerIdentity pid,
const void *  addr,
size_t  addrlen 
)
static

Find target matching addr.

If none exists, create one!

Parameters
pluginthe plugin handle
pidpresumed identity of the target
addrsocket address to find
addrlennumber of bytes in addr
Returns
matching target object

Definition at line 311 of file plugin_dhtu_ip.c.

315 {
316  struct GNUNET_HashCode key;
317  struct GNUNET_DHTU_Target *dst;
318 
320  addrlen,
321  &key);
323  &key);
324  if (NULL == dst)
325  {
326  dst = create_target (plugin,
327  pid,
328  (const struct sockaddr *) addr,
329  addrlen);
332  plugin->dsts,
333  &key,
334  dst,
336  }
337  else
338  {
339  /* move to head of DLL */
341  plugin->dst_tail,
342  dst);
344  plugin->dst_tail,
345  dst);
346 
347  }
348  return dst;
349 }
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multihashmap_put(struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
void * GNUNET_CONTAINER_multihashmap_get(const struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key)
Given a key find a value in the map matching the key.
@ GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY
There must only be one value per key; storing a value should fail if a value under the same key alrea...
static struct GNUNET_DHTU_Target * create_target(struct Plugin *plugin, const struct GNUNET_PeerIdentity *pid, const struct sockaddr *addr, socklen_t addrlen)
Create a target to which we may send traffic.
socklen_t addrlen
Number of bytes in addr.
struct sockaddr_storage addr
Target IP address.

References GNUNET_DHTU_Target::addr, GNUNET_DHTU_Target::addrlen, create_target(), GNUNET_assert, GNUNET_CONTAINER_DLL_insert, GNUNET_CONTAINER_DLL_remove, GNUNET_CONTAINER_multihashmap_get(), GNUNET_CONTAINER_multihashmap_put(), GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY, GNUNET_CRYPTO_hash(), GNUNET_YES, key, pid, and plugin.

Referenced by ip_try_connect(), and read_cb().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ ip_try_connect()

static void ip_try_connect ( void *  cls,
const struct GNUNET_PeerIdentity pid,
const char *  address 
)
static

Request creation of a session with a peer at the given address.

Parameters
clsclosure (internal context for the plugin)
pididentity of the target peer
addresstarget address to connect to

Definition at line 360 of file plugin_dhtu_ip.c.

363 {
364  struct Plugin *plugin = cls;
365  char *colon;
366  const char *port;
367  char *addr;
368  struct addrinfo hints = {
369  .ai_flags = AI_NUMERICHOST | AI_NUMERICSERV
370  };
371  struct addrinfo *result = NULL;
372 
373  if (0 !=
374  strncmp (address,
375  "ip+",
376  strlen ("ip+")))
377  return;
378  address += strlen ("ip+");
379  if (0 !=
380  strncmp (address,
381  "udp://",
382  strlen ("udp://")))
383  return;
384  address += strlen ("udp://");
385  addr = GNUNET_strdup (address);
386  colon = strchr (addr, ':');
387  if (NULL == colon)
388  {
389  port = plugin->port;
390  }
391  else
392  {
393  *colon = '\0';
394  port = colon + 1;
395  }
396  if (0 !=
397  getaddrinfo (addr,
398  port,
399  &hints,
400  &result))
401  {
402  GNUNET_break (0);
403  GNUNET_free (addr);
404  return;
405  }
406  GNUNET_free (addr);
407  (void) find_target (plugin,
408  pid,
409  result->ai_addr,
410  result->ai_addrlen);
411  freeaddrinfo (result);
412 }
static uint16_t port
Port number.
Definition: gnunet-bcd.c:147
static char * address
GNS address for this phone.
static int result
Global testing status.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
#define AI_NUMERICSERV
AI_NUMERICSERV not defined in windows.
Definition: platform.h:219
static struct GNUNET_DHTU_Target * find_target(struct Plugin *plugin, const struct GNUNET_PeerIdentity *pid, const void *addr, size_t addrlen)
Find target matching addr.
Handle for a plugin.
Definition: block.c:38

References address, AI_NUMERICSERV, find_target(), GNUNET_break, GNUNET_free, GNUNET_strdup, pid, plugin, port, and result.

Referenced by libgnunet_plugin_dhtu_ip_init().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ ip_hold()

static struct GNUNET_DHTU_PreferenceHandle* ip_hold ( void *  cls,
struct GNUNET_DHTU_Target target 
)
static

Request underlay to keep the connection to target alive if possible.

Hold may be called multiple times to express a strong preference to keep a connection, say because a target is in multiple tables.

Parameters
clsclosure
targetconnection to keep alive

Definition at line 424 of file plugin_dhtu_ip.c.

426 {
428 
430  ph->target = target;
432  target->ph_tail,
433  ph);
434  target->ph_count++;
435  return ph;
436 }
static struct GNUNET_ATS_PerformanceHandle * ph
ATS performance handle used.
Definition: gnunet-ats.c:116
Opaque handle expressing a preference of the DHT to keep a particular target connected.
struct GNUNET_DHTU_Target * target
Target a preference was expressed for.
struct GNUNET_DHTU_PreferenceHandle * ph_head
Head of preferences expressed for this target.
unsigned int ph_count
Preference counter, length of the ph_head DLL.
struct GNUNET_DHTU_PreferenceHandle * ph_tail
Tail of preferences expressed for this target.

References GNUNET_CONTAINER_DLL_insert, GNUNET_new, ph, GNUNET_DHTU_Target::ph_count, GNUNET_DHTU_Target::ph_head, GNUNET_DHTU_Target::ph_tail, and GNUNET_DHTU_PreferenceHandle::target.

Referenced by libgnunet_plugin_dhtu_ip_init().

Here is the caller graph for this function:

◆ ip_drop()

static void ip_drop ( struct GNUNET_DHTU_PreferenceHandle ph)
static

Do no long request underlay to keep the connection alive.

Parameters
clsclosure
targetconnection to keep alive

Definition at line 446 of file plugin_dhtu_ip.c.

447 {
448  struct GNUNET_DHTU_Target *target = ph->target;
449 
451  target->ph_tail,
452  ph);
453  target->ph_count--;
454  GNUNET_free (ph);
455 }

References GNUNET_CONTAINER_DLL_remove, GNUNET_free, ph, GNUNET_DHTU_Target::ph_count, GNUNET_DHTU_Target::ph_head, and GNUNET_DHTU_Target::ph_tail.

Referenced by libgnunet_plugin_dhtu_ip_init().

Here is the caller graph for this function:

◆ ip_send()

static void ip_send ( void *  cls,
struct GNUNET_DHTU_Target target,
const void *  msg,
size_t  msg_size,
GNUNET_SCHEDULER_TaskCallback  finished_cb,
void *  finished_cb_cls 
)
static

Send message to some other participant over the network.

Note that sending is not guaranteeing that the other peer actually received the message. For any given target, the DHT must wait for the finished_cb to be called before calling send() again.

Parameters
clsclosure (internal context for the plugin)
targetreceiver identification
msgmessage
msg_sizenumber of bytes in msg
finished_cbfunction called once transmission is done (not called if target disconnects, then only the disconnect_cb is called).
finished_cb_clsclosure for finished_cb

Definition at line 474 of file plugin_dhtu_ip.c.

480 {
481  struct Plugin *plugin = cls;
482  char buf[sizeof (plugin->my_id) + msg_size];
483 
484  memcpy (buf,
485  &plugin->my_id,
486  sizeof (plugin->my_id));
487  memcpy (&buf[sizeof (plugin->my_id)],
488  msg,
489  msg_size);
491  buf,
492  sizeof (buf),
493  (const struct sockaddr *) &target->addr,
494  target->addrlen);
495  finished_cb (finished_cb_cls);
496 }
struct GNUNET_MessageHeader * msg
Definition: 005.c:2
static void finished_cb(enum GNUNET_GenericReturnValue rv)
static char buf[2048]
ssize_t GNUNET_NETWORK_socket_sendto(const struct GNUNET_NETWORK_Handle *desc, const void *message, size_t length, const struct sockaddr *dest_addr, socklen_t dest_len)
Send data to a particular destination (always non-blocking).
Definition: network.c:772

References GNUNET_DHTU_Target::addr, GNUNET_DHTU_Target::addrlen, buf, finished_cb(), GNUNET_NETWORK_socket_sendto(), msg, and plugin.

Referenced by libgnunet_plugin_dhtu_ip_init().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ create_source()

static struct GNUNET_DHTU_Source* create_source ( struct Plugin plugin,
const struct sockaddr *  addr,
socklen_t  addrlen 
)
static

Create a new source on which we may be receiving traffic.

Parameters
pluginour plugin
addrour address
addrlennumber of bytes in addr
Returns
new source object

Definition at line 508 of file plugin_dhtu_ip.c.

511 {
512  struct GNUNET_DHTU_Source *src;
513 
514  src = GNUNET_new (struct GNUNET_DHTU_Source);
515  src->addrlen = addrlen;
516  memcpy (&src->addr,
517  addr,
518  addrlen);
519  src->scan_generation = plugin->scan_generation;
520  switch (addr->sa_family)
521  {
522  case AF_INET:
523  {
524  const struct sockaddr_in *s4 = (const struct sockaddr_in *) addr;
525  char buf[INET_ADDRSTRLEN];
526 
527  GNUNET_assert (sizeof (struct sockaddr_in) == addrlen);
528  GNUNET_asprintf (&src->address,
529  "ip+udp://%s:%u",
530  inet_ntop (AF_INET,
531  &s4->sin_addr,
532  buf,
533  sizeof (buf)),
534  ntohs (s4->sin_port));
535  }
536  break;
537  case AF_INET6:
538  {
539  const struct sockaddr_in6 *s6 = (const struct sockaddr_in6 *) addr;
540  char buf[INET6_ADDRSTRLEN];
541 
542  GNUNET_assert (sizeof (struct sockaddr_in6) == addrlen);
543  GNUNET_asprintf (&src->address,
544  "ip+udp://[%s]:%u",
545  inet_ntop (AF_INET6,
546  &s6->sin6_addr,
547  buf,
548  sizeof (buf)),
549  ntohs (s6->sin6_port));
550  }
551  break;
552  default:
553  GNUNET_break (0);
554  GNUNET_free (src);
555  return NULL;
556  }
558  plugin->src_tail,
559  src);
560  plugin->env->address_add_cb (plugin->env->cls,
561  src->address,
562  src,
563  &src->app_ctx);
564  return src;
565 }
int int GNUNET_asprintf(char **buf, const char *format,...) __attribute__((format(printf
Like asprintf, just portable.
Opaque handle that the underlay offers for our address to be used when sending messages to another pe...
void * app_ctx
Application context for this source.
socklen_t addrlen
Number of bytes in addr.
char * address
Address in URL form ("ip+udp://$PID/$IP:$PORT")
struct sockaddr_storage addr
My actual address.
unsigned int scan_generation
Last generation this address was observed.

References GNUNET_DHTU_Source::addr, GNUNET_DHTU_Source::address, GNUNET_DHTU_Source::addrlen, GNUNET_DHTU_Source::app_ctx, buf, GNUNET_asprintf(), GNUNET_assert, GNUNET_break, GNUNET_CONTAINER_DLL_insert, GNUNET_free, GNUNET_new, plugin, and GNUNET_DHTU_Source::scan_generation.

Referenced by find_source().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ addrcmp_np()

static int addrcmp_np ( const struct sockaddr *  a1,
const struct sockaddr *  a2,
size_t  alen 
)
static

Compare two addresses excluding the ports for equality.

Only compares IP address. Must only be called on AF_INET or AF_INET6 addresses.

Parameters
a1address to compare
a2address to compare
alennumber of bytes in a1 and a2
Returns
0 if a1 == a2.

Definition at line 578 of file plugin_dhtu_ip.c.

581 {
582  GNUNET_assert (a1->sa_family == a2->sa_family);
583  switch (a1->sa_family)
584  {
585  case AF_INET:
586  GNUNET_assert (sizeof (struct sockaddr_in) == alen);
587  {
588  const struct sockaddr_in *s1 = (const struct sockaddr_in *) a1;
589  const struct sockaddr_in *s2 = (const struct sockaddr_in *) a2;
590 
591  if (s1->sin_addr.s_addr != s2->sin_addr.s_addr)
592  return 1;
593  break;
594  }
595  case AF_INET6:
596  GNUNET_assert (sizeof (struct sockaddr_in6) == alen);
597  {
598  const struct sockaddr_in6 *s1 = (const struct sockaddr_in6 *) a1;
599  const struct sockaddr_in6 *s2 = (const struct sockaddr_in6 *) a2;
600 
601  if (0 != GNUNET_memcmp (&s1->sin6_addr,
602  &s2->sin6_addr))
603  return 1;
604  break;
605  }
606  default:
607  GNUNET_assert (0);
608  }
609  return 0;
610 }
#define GNUNET_memcmp(a, b)
Compare memory in a and b, where both must be of the same pointer type.

References GNUNET_assert, and GNUNET_memcmp.

◆ addrcmp()

static int addrcmp ( const struct sockaddr *  a1,
const struct sockaddr *  a2,
size_t  alen 
)
static

Compare two addresses for equality.

Only compares IP address and port. Must only be called on AF_INET or AF_INET6 addresses.

Parameters
a1address to compare
a2address to compare
alennumber of bytes in a1 and a2
Returns
0 if a1 == a2.

Definition at line 624 of file plugin_dhtu_ip.c.

627 {
628  GNUNET_assert (a1->sa_family == a2->sa_family);
629  switch (a1->sa_family)
630  {
631  case AF_INET:
632  GNUNET_assert (sizeof (struct sockaddr_in) == alen);
633  {
634  const struct sockaddr_in *s1 = (const struct sockaddr_in *) a1;
635  const struct sockaddr_in *s2 = (const struct sockaddr_in *) a2;
636 
637  if (s1->sin_port != s2->sin_port)
638  return 1;
639  if (s1->sin_addr.s_addr != s2->sin_addr.s_addr)
640  return 1;
641  break;
642  }
643  case AF_INET6:
644  GNUNET_assert (sizeof (struct sockaddr_in6) == alen);
645  {
646  const struct sockaddr_in6 *s1 = (const struct sockaddr_in6 *) a1;
647  const struct sockaddr_in6 *s2 = (const struct sockaddr_in6 *) a2;
648 
649  if (s1->sin6_port != s2->sin6_port)
650  return 1;
651  if (0 != GNUNET_memcmp (&s1->sin6_addr,
652  &s2->sin6_addr))
653  return 1;
654  break;
655  }
656  default:
657  GNUNET_assert (0);
658  }
659  return 0;
660 }

References GNUNET_assert, and GNUNET_memcmp.

Referenced by find_source().

Here is the caller graph for this function:

◆ process_ifcs()

static enum GNUNET_GenericReturnValue process_ifcs ( void *  cls,
const char *  name,
int  isDefault,
const struct sockaddr *  addr,
const struct sockaddr *  broadcast_addr,
const struct sockaddr *  netmask,
socklen_t  addrlen 
)
static

Callback function invoked for each interface found.

Parameters
clsclosure
namename of the interface (can be NULL for unknown)
isDefaultis this presumably the default interface
addraddress of this interface (can be NULL for unknown or unassigned)
broadcast_addrthe broadcast address (can be NULL for unknown or unassigned)
netmaskthe network mask (can be NULL for unknown or unassigned)
addrlenlength of the address
Returns
GNUNET_OK to continue iteration, GNUNET_SYSERR to abort

Definition at line 624 of file plugin_dhtu_ip.c.

683 {
684  struct Plugin *plugin = cls;
685  struct GNUNET_DHTU_Source *src;
686 
687  for (src = plugin->src_head;
688  NULL != src;
689  src = src->next)
690  {
691  if ( (addrlen == src->addrlen) &&
692  (0 == addrcmp_np (addr,
693  (const struct sockaddr *) &src->addr,
694  addrlen)) )
695  {
696  src->scan_generation = plugin->scan_generation;
697  return GNUNET_OK;
698  }
699  }
700  switch (addr->sa_family)
701  {
702  case AF_INET:
703  {
704  struct sockaddr_in v4;
705 
706  GNUNET_assert (sizeof(v4) == addrlen);
707  memcpy (&v4,
708  addr,
709  addrlen);
710  v4.sin_port = htons (plugin->port16);
711  (void) create_source (plugin,
712  (const struct sockaddr *) &v4,
713  sizeof (v4));
714  break;
715  }
716  case AF_INET6:
717  {
718  struct sockaddr_in6 v6;
719 
720  GNUNET_assert (sizeof(v6) == addrlen);
721  memcpy (&v6,
722  addr,
723  addrlen);
724  v6.sin6_port = htons (plugin->port16);
725  (void) create_source (plugin,
726  (const struct sockaddr *) &v6,
727  sizeof (v6));
728  break;
729  }
730  }
731  return GNUNET_OK;
732 }
@ GNUNET_OK
static int addrcmp_np(const struct sockaddr *a1, const struct sockaddr *a2, size_t alen)
Compare two addresses excluding the ports for equality.
static struct GNUNET_DHTU_Source * create_source(struct Plugin *plugin, const struct sockaddr *addr, socklen_t addrlen)
Create a new source on which we may be receiving traffic.
struct GNUNET_DHTU_Source * next
Kept in a DLL.

Referenced by scan().

Here is the caller graph for this function:

◆ scan()

static void scan ( void *  cls)
static

Scan network interfaces for IP address changes.

Parameters
clsa struct Plugin

Definition at line 741 of file plugin_dhtu_ip.c.

742 {
743  struct Plugin *plugin = cls;
744  struct GNUNET_DHTU_Source *next;
745 
746  plugin->scan_generation++;
748  plugin);
749  for (struct GNUNET_DHTU_Source *src = plugin->src_head;
750  NULL != src;
751  src = next)
752  {
753  next = src->next;
754  if (src->scan_generation >= plugin->scan_generation)
755  continue;
757  plugin->src_tail,
758  src);
759  plugin->env->address_del_cb (src->app_ctx);
760  GNUNET_free (src->address);
761  GNUNET_free (src);
762  }
764  &scan,
765  plugin);
766 }
void GNUNET_OS_network_interfaces_list(GNUNET_OS_NetworkInterfaceProcessor proc, void *proc_cls)
Enumerate all network interfaces.
Definition: os_network.c:397
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 enum GNUNET_GenericReturnValue process_ifcs(void *cls, const char *name, int isDefault, const struct sockaddr *addr, const struct sockaddr *broadcast_addr, const struct sockaddr *netmask, socklen_t addrlen)
Callback function invoked for each interface found.
static void scan(void *cls)
Scan network interfaces for IP address changes.
#define SCAN_FREQ
How frequently should we re-scan our local interfaces for IPs?

References GNUNET_DHTU_Source::address, GNUNET_DHTU_Source::app_ctx, GNUNET_CONTAINER_DLL_remove, GNUNET_free, GNUNET_OS_network_interfaces_list(), GNUNET_SCHEDULER_add_delayed(), GNUNET_DHTU_Source::next, plugin, process_ifcs(), SCAN_FREQ, and GNUNET_DHTU_Source::scan_generation.

Referenced by libgnunet_plugin_dhtu_ip_init().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ find_source()

static struct GNUNET_DHTU_Source* find_source ( struct Plugin plugin,
const void *  addr,
size_t  addrlen 
)
static

Find our source matching addr.

If none exists, create one!

Parameters
pluginthe plugin handle
addrsocket address to find
addrlennumber of bytes in addr
Returns
matching source object

Definition at line 779 of file plugin_dhtu_ip.c.

782 {
783  for (struct GNUNET_DHTU_Source *src = plugin->src_head;
784  NULL != src;
785  src = src->next)
786  {
787  if ( (addrlen == src->addrlen) &&
788  (0 == addrcmp (addr,
789  (const struct sockaddr *) &src->addr,
790  addrlen)) )
791  return src;
792  }
793 
794  return create_source (plugin,
795  (const struct sockaddr *) addr,
796  addrlen);
797 }
static int addrcmp(const struct sockaddr *a1, const struct sockaddr *a2, size_t alen)
Compare two addresses for equality.

References GNUNET_DHTU_Source::addr, addrcmp(), GNUNET_DHTU_Source::addrlen, create_source(), GNUNET_DHTU_Source::next, and plugin.

Referenced by read_cb().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ read_cb()

static void read_cb ( void *  cls)
static

UDP socket is ready to receive.

Read.

Parameters
clsour struct Plugin *

Definition at line 806 of file plugin_dhtu_ip.c.

807 {
808  struct Plugin *plugin = cls;
809  ssize_t ret;
810  const struct GNUNET_PeerIdentity *pid;
811  char buf[65536] GNUNET_ALIGN;
812  struct sockaddr_storage sa;
813  struct iovec iov = {
814  .iov_base = buf,
815  .iov_len = sizeof (buf)
816  };
817  char ctl[128];
818  struct msghdr mh = {
819  .msg_name = &sa,
820  .msg_namelen = sizeof (sa),
821  .msg_iov = &iov,
822  .msg_iovlen = 1,
823  .msg_control = ctl,
824  .msg_controllen = sizeof (ctl)
825  };
826  struct GNUNET_DHTU_Target *dst = NULL;
827  struct GNUNET_DHTU_Source *src = NULL;
828 
829  ret = recvmsg (GNUNET_NETWORK_get_fd (plugin->sock),
830  &mh,
831  MSG_DONTWAIT);
834  plugin->sock,
835  &read_cb,
836  plugin);
837  if (ret < 0)
838  return; /* read failure, hopefully EAGAIN */
839  if (ret < sizeof (*pid))
840  {
841  GNUNET_break_op (0);
842  return;
843  }
844  /* find IP where we received message */
845  for (struct cmsghdr *cmsg = CMSG_FIRSTHDR (&mh);
846  NULL != cmsg;
847  cmsg = CMSG_NXTHDR (&mh,
848  cmsg))
849  {
851  "Got CMSG level %u (%d/%d), type %u (%d/%d)\n",
852  cmsg->cmsg_level,
853  (cmsg->cmsg_level == IPPROTO_IP),
854  (cmsg->cmsg_level == IPPROTO_IPV6),
855  cmsg->cmsg_type,
856  (cmsg->cmsg_type == IP_PKTINFO),
857  (cmsg->cmsg_type == IPV6_PKTINFO));
858  if ( (cmsg->cmsg_level == IPPROTO_IP) &&
859  (cmsg->cmsg_type == IP_PKTINFO) )
860  {
861  if (CMSG_LEN (sizeof (struct in_pktinfo)) ==
862  cmsg->cmsg_len)
863  {
864  struct in_pktinfo pi;
865 
866  memcpy (&pi,
867  CMSG_DATA (cmsg),
868  sizeof (pi));
869  {
870  struct sockaddr_in sa = {
871  .sin_family = AF_INET,
872  .sin_addr = pi.ipi_addr,
873  .sin_port = htons (plugin->port16)
874  };
875 
876  src = find_source (plugin,
877  &sa,
878  sizeof (sa));
879  /* For sources we discovered by reading,
880  force the generation far into the future */
881  src->scan_generation = plugin->scan_generation + 60;
882  }
883  break;
884  }
885  else
886  GNUNET_break (0);
887  }
888  if ( (cmsg->cmsg_level == IPPROTO_IPV6) &&
889  (cmsg->cmsg_type == IPV6_PKTINFO) )
890  {
891  if (CMSG_LEN (sizeof (struct in6_pktinfo)) ==
892  cmsg->cmsg_len)
893  {
894  struct in6_pktinfo pi;
895 
896  memcpy (&pi,
897  CMSG_DATA (cmsg),
898  sizeof (pi));
899  {
900  struct sockaddr_in6 sa = {
901  .sin6_family = AF_INET6,
902  .sin6_addr = pi.ipi6_addr,
903  .sin6_port = htons (plugin->port16),
904  .sin6_scope_id = pi.ipi6_ifindex
905  };
906 
907  src = find_source (plugin,
908  &sa,
909  sizeof (sa));
910  /* For sources we discovered by reading,
911  force the generation far into the future */
912  src->scan_generation = plugin->scan_generation + 60;
913  break;
914  }
915  }
916  else
917  GNUNET_break (0);
918  }
919  }
920  if (NULL == src)
921  {
922  GNUNET_break (0);
923  return;
924  }
925  pid = (const struct GNUNET_PeerIdentity *) buf;
926  dst = find_target (plugin,
927  pid,
928  &sa,
929  mh.msg_namelen);
930  if (NULL == dst)
931  {
932  GNUNET_break (0);
933  return;
934  }
935  plugin->env->receive_cb (plugin->env->cls,
936  &dst->app_ctx,
937  &src->app_ctx,
938  &buf[sizeof(*pid)],
939  ret - sizeof (*pid));
940 }
static int ret
Return value of the commandline.
Definition: gnunet-abd.c:81
static struct GNUNET_CADET_Handle * mh
Cadet handle.
Definition: gnunet-cadet.c:92
static struct GNUNET_PEERINFO_Handle * pi
Handle to peerinfo service.
#define GNUNET_log(kind,...)
#define GNUNET_ALIGN
gcc-ism to force alignment; we use this to align char-arrays that may then be cast to 'struct's.
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
@ GNUNET_ERROR_TYPE_INFO
int GNUNET_NETWORK_get_fd(const struct GNUNET_NETWORK_Handle *desc)
Return file descriptor for this network handle.
Definition: network.c:1001
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_read_net(struct GNUNET_TIME_Relative delay, struct GNUNET_NETWORK_Handle *rfd, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay or when the specified file descriptor is ready f...
Definition: scheduler.c:1506
#define GNUNET_TIME_UNIT_FOREVER_REL
Constant used to specify "forever".
static void read_cb(void *cls)
UDP socket is ready to receive.
static struct GNUNET_DHTU_Source * find_source(struct Plugin *plugin, const void *addr, size_t addrlen)
Find our source matching addr.
void * app_ctx
Application context for this target.
The identity of the host (wraps the signing key of the peer).

References GNUNET_DHTU_Source::app_ctx, GNUNET_DHTU_Target::app_ctx, buf, find_source(), find_target(), GNUNET_ALIGN, GNUNET_break, GNUNET_break_op, GNUNET_ERROR_TYPE_INFO, GNUNET_log, GNUNET_NETWORK_get_fd(), GNUNET_SCHEDULER_add_read_net(), GNUNET_TIME_UNIT_FOREVER_REL, mh, pi, pid, plugin, ret, and GNUNET_DHTU_Source::scan_generation.

Referenced by libgnunet_plugin_dhtu_ip_init().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ libgnunet_plugin_dhtu_ip_init()

void* libgnunet_plugin_dhtu_ip_init ( void *  cls)

Entry point for the plugin.

Parameters
clsclosure (the struct GNUNET_DHTU_PluginEnvironment)
Returns
the plugin's API

Definition at line 950 of file plugin_dhtu_ip.c.

951 {
953  struct GNUNET_DHTU_PluginFunctions *api;
954  struct Plugin *plugin;
955  char *port;
956  unsigned int nport;
957  int sock;
958  int af;
959  unsigned long long nse;
960 
961  if (GNUNET_OK !=
963  "DHTU-IP",
964  "NSE",
965  &nse))
966  {
968  "DHTU-IP",
969  "NSE");
970  return NULL;
971  }
972  if (GNUNET_OK !=
974  "DHTU-IP",
975  "UDP_PORT",
976  &port))
977  {
979  "DHTU-IP",
980  "UDP_PORT");
981  return NULL;
982  }
983  {
984  char dummy;
985 
986  if ( (1 != sscanf (port,
987  "%u%c",
988  &nport,
989  &dummy)) ||
990  (nport > UINT16_MAX) )
991  {
993  "DHTU-IP",
994  "UDP_PORT",
995  "must be number below 65536");
996  GNUNET_free (port);
997  return NULL;
998  }
999  }
1000  plugin = GNUNET_new (struct Plugin);
1001  plugin->env = env;
1002  plugin->port = port;
1003  plugin->port16 = (uint16_t) nport;
1004  if (GNUNET_OK !=
1006  &plugin->my_id))
1007  {
1008  GNUNET_free (plugin);
1009  return NULL;
1010  }
1011  af = AF_INET6;
1012  sock = socket (af,
1013  SOCK_DGRAM,
1014  IPPROTO_UDP);
1015  if (-1 == sock)
1016  {
1018  "socket");
1019  GNUNET_free (plugin->port);
1020  GNUNET_free (plugin);
1021  return NULL;
1022  }
1023  switch (af)
1024  {
1025  case AF_INET:
1026  {
1027  int on = 1;
1028 
1029  if (0 !=
1030  setsockopt (sock,
1031  IPPROTO_IP,
1032  IP_PKTINFO,
1033  &on,
1034  sizeof (on)))
1035  {
1037  "setsockopt");
1038  }
1039  }
1040  {
1041  struct sockaddr_in sa = {
1042  .sin_family = AF_INET,
1043  .sin_port = htons ((uint16_t) nport)
1044  };
1045 
1046  if (0 !=
1047  bind (sock,
1048  (const struct sockaddr *) &sa,
1049  sizeof (sa)))
1050  {
1052  "socket");
1053  GNUNET_break (0 ==
1054  close (sock));
1055  GNUNET_free (plugin->port);
1056  GNUNET_free (plugin);
1057  return NULL;
1058  }
1059  }
1060  break;
1061  case AF_INET6:
1062  {
1063  int on = 1;
1064 
1065  if (0 !=
1066  setsockopt (sock,
1067  IPPROTO_IPV6,
1068  IPV6_RECVPKTINFO,
1069  &on,
1070  sizeof (on)))
1071  {
1073  "setsockopt");
1074  }
1075  }
1076  {
1077  struct sockaddr_in6 sa = {
1078  .sin6_family = AF_INET6,
1079  .sin6_port = htons ((uint16_t) nport)
1080  };
1081 
1082  if (0 !=
1083  bind (sock,
1084  (const struct sockaddr *) &sa,
1085  sizeof (sa)))
1086  {
1088  "socket");
1089  GNUNET_break (0 ==
1090  close (sock));
1091  GNUNET_free (plugin->port);
1092  GNUNET_free (plugin);
1093  return NULL;
1094  }
1095  }
1096  break;
1097  }
1099  GNUNET_NO);
1101  plugin->read_task = GNUNET_SCHEDULER_add_read_net (
1103  plugin->sock,
1104  &read_cb,
1105  plugin);
1106  env->network_size_cb (env->cls,
1108  log (nse) / log (2),
1109  -1.0 /* stddev */);
1110  plugin->scan_task = GNUNET_SCHEDULER_add_now (&scan,
1111  plugin);
1112  api = GNUNET_new (struct GNUNET_DHTU_PluginFunctions);
1113  api->cls = plugin;
1114  api->try_connect = &ip_try_connect;
1115  api->hold = &ip_hold;
1116  api->drop = &ip_drop;
1117  api->send = &ip_send;
1118  return api;
1119 }
struct GNUNET_MQ_Envelope * env
Definition: 005.c:1
static struct in_addr dummy
Target "dummy" address of the packet we pretend to respond to.
static struct GNUNET_NSE_Handle * nse
The handle to the NSE service.
Definition: gnunet-nse.c:33
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_number(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, unsigned long long *number)
Get a configuration value that should be a number.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_string(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, char **value)
Get a configuration value that should be a string.
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_get_peer_identity(const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_PeerIdentity *dst)
Retrieve the identity of the host's peer.
struct GNUNET_CONTAINER_MultiHashMap * GNUNET_CONTAINER_multihashmap_create(unsigned int len, int do_not_copy_keys)
Create a multi hash map.
@ GNUNET_NO
void GNUNET_log_config_invalid(enum GNUNET_ErrorType kind, const char *section, const char *option, const char *required)
Log error message about invalid configuration option value.
void GNUNET_log_config_missing(enum GNUNET_ErrorType kind, const char *section, const char *option)
Log error message about missing configuration option.
#define GNUNET_log_strerror(level, cmd)
Log an error message at log-level 'level' that indicates a failure of the command 'cmd' with the mess...
@ GNUNET_ERROR_TYPE_ERROR
struct GNUNET_NETWORK_Handle * GNUNET_NETWORK_socket_box_native(int fd)
Box a native socket (and check that it is a socket).
Definition: network.c:580
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_now(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run as soon as possible.
Definition: scheduler.c:1299
#define GNUNET_TIME_UNIT_ZERO_ABS
Absolute time zero.
static void ip_send(void *cls, struct GNUNET_DHTU_Target *target, const void *msg, size_t msg_size, GNUNET_SCHEDULER_TaskCallback finished_cb, void *finished_cb_cls)
Send message to some other participant over the network.
static void ip_try_connect(void *cls, const struct GNUNET_PeerIdentity *pid, const char *address)
Request creation of a session with a peer at the given address.
static void ip_drop(struct GNUNET_DHTU_PreferenceHandle *ph)
Do no long request underlay to keep the connection alive.
static struct GNUNET_DHTU_PreferenceHandle * ip_hold(void *cls, struct GNUNET_DHTU_Target *target)
Request underlay to keep the connection to target alive if possible.
The datastore service will pass a pointer to a struct of this type as the first and only argument to ...
void * cls
Closure to use for callbacks.
struct returned by the initialization function of the plugin
struct GNUNET_DHTU_PreferenceHandle *(* hold)(void *cls, struct GNUNET_DHTU_Target *target)
Request underlay to keep the connection to target alive if possible.
void(* try_connect)(void *cls, const struct GNUNET_PeerIdentity *pid, const char *address)
Request creation of a session with a peer at the given address.
void * cls
Closure to pass to all plugin functions.
void(* drop)(struct GNUNET_DHTU_PreferenceHandle *ph)
Do no longer request underlay to keep the connection alive.
void(* send)(void *cls, struct GNUNET_DHTU_Target *target, const void *msg, size_t msg_size, GNUNET_SCHEDULER_TaskCallback finished_cb, void *finished_cb_cls)
Send message to some other participant over the network.
struct GNUNET_NETWORK_Handle * sock
My UDP socket.

References GNUNET_DHTU_PluginEnvironment::cls, GNUNET_DHTU_PluginFunctions::cls, GNUNET_DHTU_PluginFunctions::drop, dummy, env, GNUNET_break, GNUNET_CONFIGURATION_get_value_number(), GNUNET_CONFIGURATION_get_value_string(), GNUNET_CONTAINER_multihashmap_create(), GNUNET_CRYPTO_get_peer_identity(), GNUNET_ERROR_TYPE_ERROR, GNUNET_free, GNUNET_log_config_invalid(), GNUNET_log_config_missing(), GNUNET_log_strerror, GNUNET_NETWORK_socket_box_native(), GNUNET_new, GNUNET_NO, GNUNET_OK, GNUNET_SCHEDULER_add_now(), GNUNET_SCHEDULER_add_read_net(), GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_DHTU_PluginFunctions::hold, ip_drop(), ip_hold(), ip_send(), ip_try_connect(), nse, plugin, port, read_cb(), scan(), GNUNET_DHTU_PluginFunctions::send, Plugin::sock, and GNUNET_DHTU_PluginFunctions::try_connect.

Here is the call graph for this function:

◆ libgnunet_plugin_dhtu_ip_done()

void* libgnunet_plugin_dhtu_ip_done ( void *  cls)

Exit point from the plugin.

Parameters
clsclosure (our struct Plugin)
Returns
NULL

Definition at line 1129 of file plugin_dhtu_ip.c.

1130 {
1131  struct GNUNET_DHTU_PluginFunctions *api = cls;
1132  struct Plugin *plugin = api->cls;
1133  struct GNUNET_DHTU_Source *src;
1134  struct GNUNET_DHTU_Target *dst;
1135 
1136  while (NULL != (dst = plugin->dst_head))
1137  {
1138  plugin->env->disconnect_cb (dst->app_ctx);
1139  GNUNET_assert (NULL == dst->ph_head);
1141  plugin->dst_tail,
1142  dst);
1143  GNUNET_free (dst);
1144  }
1145  while (NULL != (src = plugin->src_head))
1146  {
1147  plugin->env->address_del_cb (src->app_ctx);
1149  plugin->src_tail,
1150  src);
1151  GNUNET_free (src->address);
1152  GNUNET_free (src);
1153  }
1154  plugin->env->network_size_cb (plugin->env->cls,
1156  0.0,
1157  0.0);
1159  if (NULL != plugin->read_task)
1160  {
1161  GNUNET_SCHEDULER_cancel (plugin->read_task);
1162  plugin->read_task = NULL;
1163  }
1164  GNUNET_SCHEDULER_cancel (plugin->scan_task);
1167  GNUNET_free (plugin->port);
1168  GNUNET_free (plugin);
1169  GNUNET_free (api);
1170  return NULL;
1171 }
void GNUNET_CONTAINER_multihashmap_destroy(struct GNUNET_CONTAINER_MultiHashMap *map)
Destroy a hash map.
enum GNUNET_GenericReturnValue GNUNET_NETWORK_socket_close(struct GNUNET_NETWORK_Handle *desc)
Close a socket.
Definition: network.c:509
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:975
#define GNUNET_TIME_UNIT_FOREVER_ABS
Constant used to specify "forever".
void * cls
Closure for all of the callbacks.
struct GNUNET_BLOCK_PluginFunctions * api
Plugin API.
Definition: block.c:47

References GNUNET_DHTU_Source::address, Plugin::api, GNUNET_DHTU_Source::app_ctx, GNUNET_DHTU_Target::app_ctx, GNUNET_BLOCK_PluginFunctions::cls, GNUNET_DHTU_PluginFunctions::cls, GNUNET_assert, GNUNET_break, GNUNET_CONTAINER_DLL_remove, GNUNET_CONTAINER_multihashmap_destroy(), GNUNET_free, GNUNET_NETWORK_socket_close(), GNUNET_OK, GNUNET_SCHEDULER_cancel(), GNUNET_TIME_UNIT_FOREVER_ABS, GNUNET_DHTU_Target::ph_head, and plugin.

Here is the call graph for this function: