GNUnet 0.22.1
plugin_dhtu_ip.c File Reference

plain IP based DHT network underlay More...

#include "platform.h"
#include "gnunet_dhtu_plugin.h"
#include "plugin_dhtu_ip.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...
 
struct GNUNET_DHTU_PluginFunctionsDHTU_ip_init (struct GNUNET_DHTU_PluginEnvironment *env)
 Entry point for the plugin. More...
 
void * DHTU_ip_done (struct GNUNET_DHTU_PluginFunctions *api)
 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 34 of file plugin_dhtu_ip.c.

◆ MAX_DESTS

#define MAX_DESTS   256

Maximum number of concurrently active destinations to support.

Definition at line 39 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 247 of file plugin_dhtu_ip.c.

251{
252 struct GNUNET_DHTU_Target *dst;
253
254 if (MAX_DESTS <=
256 {
257 struct GNUNET_HashCode key;
258
259 dst = NULL;
260 for (struct GNUNET_DHTU_Target *pos = plugin->dst_head;
261 NULL != pos;
262 pos = pos->next)
263 {
264 /* >= here assures we remove oldest entries first */
265 if ( (NULL == dst) ||
266 (dst->ph_count >= pos->ph_count) )
267 dst = pos;
268 }
269 GNUNET_assert (NULL != dst);
270 plugin->env->disconnect_cb (dst->app_ctx);
271 GNUNET_CRYPTO_hash (&dst->addr,
272 dst->addrlen,
273 &key);
276 &key,
277 dst));
279 plugin->dst_tail,
280 dst);
281 GNUNET_assert (NULL == dst->ph_head);
282 GNUNET_free (dst);
283 }
284 dst = GNUNET_new (struct GNUNET_DHTU_Target);
285 dst->addrlen = addrlen;
286 dst->pid = *pid;
287 memcpy (&dst->addr,
288 addr,
289 addrlen);
291 plugin->dst_tail,
292 dst);
293 plugin->env->connect_cb (plugin->env->cls,
294 dst,
295 &dst->pid,
296 &dst->app_ctx);
297 return dst;
298}
static struct GNUNET_TESTING_PluginFunctions * plugin
Plugin to dynamically load a test case.
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.
void * cls
Closure to pass to start_testcase.

References GNUNET_DHTU_Target::addr, GNUNET_DHTU_Target::addrlen, GNUNET_DHTU_Target::app_ctx, GNUNET_TESTING_PluginFunctions::cls, 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 312 of file plugin_dhtu_ip.c.

316{
317 struct GNUNET_HashCode key;
318 struct GNUNET_DHTU_Target *dst;
319
321 addrlen,
322 &key);
324 &key);
325 if (NULL == dst)
326 {
327 dst = create_target (plugin,
328 pid,
329 (const struct sockaddr *) addr,
330 addrlen);
333 plugin->dsts,
334 &key,
335 dst,
337 }
338 else
339 {
340 /* move to head of DLL */
342 plugin->dst_tail,
343 dst);
345 plugin->dst_tail,
346 dst);
347
348 }
349 return dst;
350}
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.
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.
@ 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 361 of file plugin_dhtu_ip.c.

364{
365 struct Plugin *plugin = cls;
366 char *colon;
367 const char *port;
368 char *addr;
369 struct addrinfo hints = {
370 .ai_flags = AI_NUMERICHOST | AI_NUMERICSERV
371 };
372 struct addrinfo *result = NULL;
373
374 if (0 !=
375 strncmp (address,
376 "ip+",
377 strlen ("ip+")))
378 return;
379 address += strlen ("ip+");
380 if (0 !=
381 strncmp (address,
382 "udp://",
383 strlen ("udp://")))
384 return;
385 address += strlen ("udp://");
386 addr = GNUNET_strdup (address);
387 colon = strchr (addr, ':');
388 if (NULL == colon)
389 {
390 port = plugin->port;
391 }
392 else
393 {
394 *colon = '\0';
395 port = colon + 1;
396 }
397 if (0 !=
398 getaddrinfo (addr,
399 port,
400 &hints,
401 &result))
402 {
403 GNUNET_break (0);
404 GNUNET_free (addr);
405 return;
406 }
407 GNUNET_free (addr);
408 (void) find_target (plugin,
409 pid,
410 result->ai_addr,
411 result->ai_addrlen);
412 freeaddrinfo (result);
413}
static uint16_t port
Port number.
Definition: gnunet-bcd.c:146
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 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 425 of file plugin_dhtu_ip.c.

427{
429
431 ph->target = target;
434 ph);
435 target->ph_count++;
436 return ph;
437}
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, GNUNET_DHTU_Target::ph_count, GNUNET_DHTU_Target::ph_head, GNUNET_DHTU_Target::ph_tail, and GNUNET_DHTU_PreferenceHandle::target.

Referenced by 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 447 of file plugin_dhtu_ip.c.

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

References GNUNET_CONTAINER_DLL_remove, GNUNET_free, GNUNET_DHTU_Target::ph_count, GNUNET_DHTU_Target::ph_head, GNUNET_DHTU_Target::ph_tail, and GNUNET_DHTU_PreferenceHandle::target.

Referenced by 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 475 of file plugin_dhtu_ip.c.

481{
482 struct Plugin *plugin = cls;
483 char buf[sizeof (plugin->my_id) + msg_size];
484
485 memcpy (buf,
486 &plugin->my_id,
487 sizeof (plugin->my_id));
488 memcpy (&buf[sizeof (plugin->my_id)],
489 msg,
490 msg_size);
492 buf,
493 sizeof (buf),
494 (const struct sockaddr *) &target->addr,
495 target->addrlen);
496 finished_cb (finished_cb_cls);
497}
struct GNUNET_MessageHeader * msg
Definition: 005.c:2
static void finished_cb(void *cls, enum GNUNET_GenericReturnValue rv)
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, finished_cb(), GNUNET_NETWORK_socket_sendto(), msg, and plugin.

Referenced by 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 509 of file plugin_dhtu_ip.c.

512{
513 struct GNUNET_DHTU_Source *src;
514
515 src = GNUNET_new (struct GNUNET_DHTU_Source);
516 src->addrlen = addrlen;
517 memcpy (&src->addr,
518 addr,
519 addrlen);
520 src->scan_generation = plugin->scan_generation;
521 switch (addr->sa_family)
522 {
523 case AF_INET:
524 {
525 const struct sockaddr_in *s4 = (const struct sockaddr_in *) addr;
526 char buf[INET_ADDRSTRLEN];
527
528 GNUNET_assert (sizeof (struct sockaddr_in) == addrlen);
530 "ip+udp://%s:%u",
531 inet_ntop (AF_INET,
532 &s4->sin_addr,
533 buf,
534 sizeof (buf)),
535 ntohs (s4->sin_port));
536 }
537 break;
538 case AF_INET6:
539 {
540 const struct sockaddr_in6 *s6 = (const struct sockaddr_in6 *) addr;
541 char buf[INET6_ADDRSTRLEN];
542
543 GNUNET_assert (sizeof (struct sockaddr_in6) == addrlen);
545 "ip+udp://[%s]:%u",
546 inet_ntop (AF_INET6,
547 &s6->sin6_addr,
548 buf,
549 sizeof (buf)),
550 ntohs (s6->sin6_port));
551 }
552 break;
553 default:
554 GNUNET_break (0);
555 GNUNET_free (src);
556 return NULL;
557 }
559 plugin->src_tail,
560 src);
561 plugin->env->address_add_cb (plugin->env->cls,
562 src->address,
563 src,
564 &src->app_ctx);
565 return src;
566}
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, GNUNET_TESTING_PluginFunctions::cls, 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(), and process_ifcs().

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 579 of file plugin_dhtu_ip.c.

582{
583 GNUNET_assert (a1->sa_family == a2->sa_family);
584 switch (a1->sa_family)
585 {
586 case AF_INET:
587 GNUNET_assert (sizeof (struct sockaddr_in) == alen);
588 {
589 const struct sockaddr_in *s1 = (const struct sockaddr_in *) a1;
590 const struct sockaddr_in *s2 = (const struct sockaddr_in *) a2;
591
592 if (s1->sin_addr.s_addr != s2->sin_addr.s_addr)
593 return 1;
594 break;
595 }
596 case AF_INET6:
597 GNUNET_assert (sizeof (struct sockaddr_in6) == alen);
598 {
599 const struct sockaddr_in6 *s1 = (const struct sockaddr_in6 *) a1;
600 const struct sockaddr_in6 *s2 = (const struct sockaddr_in6 *) a2;
601
602 if (0 != GNUNET_memcmp (&s1->sin6_addr,
603 &s2->sin6_addr))
604 return 1;
605 break;
606 }
607 default:
608 GNUNET_assert (0);
609 }
610 return 0;
611}
#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.

Referenced by process_ifcs().

Here is the caller graph for this function:

◆ 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 625 of file plugin_dhtu_ip.c.

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

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 677 of file plugin_dhtu_ip.c.

684{
685 struct Plugin *plugin = cls;
686 struct GNUNET_DHTU_Source *src;
687
688 for (src = plugin->src_head;
689 NULL != src;
690 src = src->next)
691 {
692 if ( (addrlen == src->addrlen) &&
693 (0 == addrcmp_np (addr,
694 (const struct sockaddr *) &src->addr,
695 addrlen)) )
696 {
697 src->scan_generation = plugin->scan_generation;
698 return GNUNET_OK;
699 }
700 }
701 switch (addr->sa_family)
702 {
703 case AF_INET:
704 {
705 struct sockaddr_in v4;
706
707 GNUNET_assert (sizeof(v4) == addrlen);
708 memcpy (&v4,
709 addr,
710 addrlen);
711 v4.sin_port = htons (plugin->port16);
712 (void) create_source (plugin,
713 (const struct sockaddr *) &v4,
714 sizeof (v4));
715 break;
716 }
717 case AF_INET6:
718 {
719 struct sockaddr_in6 v6;
720
721 GNUNET_assert (sizeof(v6) == addrlen);
722 memcpy (&v6,
723 addr,
724 addrlen);
725 v6.sin6_port = htons (plugin->port16);
726 (void) create_source (plugin,
727 (const struct sockaddr *) &v6,
728 sizeof (v6));
729 break;
730 }
731 }
732 return GNUNET_OK;
733}
@ 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.

References GNUNET_DHTU_Source::addr, addrcmp_np(), GNUNET_DHTU_Source::addrlen, create_source(), GNUNET_assert, GNUNET_OK, GNUNET_DHTU_Source::next, plugin, and GNUNET_DHTU_Source::scan_generation.

Referenced by scan().

Here is the call graph for this function:
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 742 of file plugin_dhtu_ip.c.

743{
744 struct Plugin *plugin = cls;
745 struct GNUNET_DHTU_Source *next;
746
747 plugin->scan_generation++;
749 plugin);
750 for (struct GNUNET_DHTU_Source *src = plugin->src_head;
751 NULL != src;
752 src = next)
753 {
754 next = src->next;
755 if (src->scan_generation >= plugin->scan_generation)
756 continue;
758 plugin->src_tail,
759 src);
760 plugin->env->address_del_cb (src->app_ctx);
761 GNUNET_free (src->address);
762 GNUNET_free (src);
763 }
765 &scan,
766 plugin);
767}
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:1276
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_CONTAINER_DLL_remove, GNUNET_free, GNUNET_OS_network_interfaces_list(), GNUNET_SCHEDULER_add_delayed(), GNUNET_DHTU_Source::next, plugin, process_ifcs(), scan(), and SCAN_FREQ.

Referenced by DHTU_ip_init(), and scan().

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 780 of file plugin_dhtu_ip.c.

783{
784 for (struct GNUNET_DHTU_Source *src = plugin->src_head;
785 NULL != src;
786 src = src->next)
787 {
788 if ( (addrlen == src->addrlen) &&
789 (0 == addrcmp (addr,
790 (const struct sockaddr *) &src->addr,
791 addrlen)) )
792 return src;
793 }
794
795 return create_source (plugin,
796 (const struct sockaddr *) addr,
797 addrlen);
798}
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(), 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 807 of file plugin_dhtu_ip.c.

808{
809 struct Plugin *plugin = cls;
810 ssize_t ret;
811 const struct GNUNET_PeerIdentity *pid;
812 char buf[65536] GNUNET_ALIGN;
813 struct sockaddr_storage sa;
814 struct iovec iov = {
815 .iov_base = buf,
816 .iov_len = sizeof (buf)
817 };
818 char ctl[128];
819 struct msghdr mh = {
820 .msg_name = &sa,
821 .msg_namelen = sizeof (sa),
822 .msg_iov = &iov,
823 .msg_iovlen = 1,
824 .msg_control = ctl,
825 .msg_controllen = sizeof (ctl)
826 };
827 struct GNUNET_DHTU_Target *dst = NULL;
828 struct GNUNET_DHTU_Source *src = NULL;
829
830 ret = recvmsg (GNUNET_NETWORK_get_fd (plugin->sock),
831 &mh,
832 MSG_DONTWAIT);
835 plugin->sock,
836 &read_cb,
837 plugin);
838 if (ret < 0)
839 return; /* read failure, hopefully EAGAIN */
840 if (ret < sizeof (*pid))
841 {
842 GNUNET_break_op (0);
843 return;
844 }
845 /* find IP where we received message */
846 for (struct cmsghdr *cmsg = CMSG_FIRSTHDR (&mh);
847 NULL != cmsg;
848 cmsg = CMSG_NXTHDR (&mh,
849 cmsg))
850 {
852 "Got CMSG level %u (%d/%d), type %u (%d/%d)\n",
853 cmsg->cmsg_level,
854 (cmsg->cmsg_level == IPPROTO_IP),
855 (cmsg->cmsg_level == IPPROTO_IPV6),
856 cmsg->cmsg_type,
857 (cmsg->cmsg_type == IP_PKTINFO),
858 (cmsg->cmsg_type == IPV6_PKTINFO));
859 if ( (cmsg->cmsg_level == IPPROTO_IP) &&
860 (cmsg->cmsg_type == IP_PKTINFO) )
861 {
862 if (CMSG_LEN (sizeof (struct in_pktinfo)) ==
863 cmsg->cmsg_len)
864 {
865 struct in_pktinfo pi;
866
867 memcpy (&pi,
868 CMSG_DATA (cmsg),
869 sizeof (pi));
870 {
871 struct sockaddr_in sa_tmp = {
872 .sin_family = AF_INET,
873 .sin_addr = pi.ipi_addr,
874 .sin_port = htons (plugin->port16)
875 };
876
877 src = find_source (plugin,
878 &sa_tmp,
879 sizeof (sa_tmp));
880 /* For sources we discovered by reading,
881 force the generation far into the future */
882 src->scan_generation = plugin->scan_generation + 60;
883 }
884 break;
885 }
886 else
887 GNUNET_break (0);
888 }
889 if ( (cmsg->cmsg_level == IPPROTO_IPV6) &&
890 (cmsg->cmsg_type == IPV6_PKTINFO) )
891 {
892 if (CMSG_LEN (sizeof (struct in6_pktinfo)) ==
893 cmsg->cmsg_len)
894 {
895 struct in6_pktinfo pi;
896
897 memcpy (&pi,
898 CMSG_DATA (cmsg),
899 sizeof (pi));
900 {
901 struct sockaddr_in6 sa_tmp = {
902 .sin6_family = AF_INET6,
903 .sin6_addr = pi.ipi6_addr,
904 .sin6_port = htons (plugin->port16),
905 .sin6_scope_id = pi.ipi6_ifindex
906 };
907
908 src = find_source (plugin,
909 &sa_tmp,
910 sizeof (sa_tmp));
911 /* For sources we discovered by reading,
912 force the generation far into the future */
913 src->scan_generation = plugin->scan_generation + 60;
914 break;
915 }
916 }
917 else
918 GNUNET_break (0);
919 }
920 }
921 if (NULL == src)
922 {
923 GNUNET_break (0);
924 return;
925 }
926 pid = (const struct GNUNET_PeerIdentity *) buf;
927 dst = find_target (plugin,
928 pid,
929 &sa,
930 mh.msg_namelen);
931 if (NULL == dst)
932 {
933 GNUNET_break (0);
934 return;
935 }
936 plugin->env->receive_cb (plugin->env->cls,
937 &dst->app_ctx,
938 &src->app_ctx,
939 &buf[sizeof(*pid)],
940 ret - sizeof (*pid));
941}
static int ret
Final status code.
Definition: gnunet-arm.c:93
static struct GNUNET_CADET_Handle * mh
Cadet handle.
Definition: gnunet-cadet.c:92
#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:1510
#define GNUNET_TIME_UNIT_FOREVER_REL
Constant used to specify "forever".
static struct GNUNET_DHTU_Source * find_source(struct Plugin *plugin, const void *addr, size_t addrlen)
Find our source matching addr.
static void read_cb(void *cls)
UDP socket is ready to receive.
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, GNUNET_TESTING_PluginFunctions::cls, 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, pid, plugin, read_cb(), ret, and GNUNET_DHTU_Source::scan_generation.

Referenced by DHTU_ip_init(), and read_cb().

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

◆ DHTU_ip_init()

struct GNUNET_DHTU_PluginFunctions * DHTU_ip_init ( struct GNUNET_DHTU_PluginEnvironment env)

Entry point for the plugin.

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

Definition at line 951 of file plugin_dhtu_ip.c.

952{
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");
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 {
1009 return NULL;
1010 }
1011 if (GNUNET_NETWORK_test_pf (PF_INET6))
1012 af = AF_INET6;
1013 else
1014 af = AF_INET;
1015 sock = socket (af,
1016 SOCK_DGRAM,
1017 IPPROTO_UDP);
1018 if (-1 == sock)
1019 {
1021 "socket");
1022 GNUNET_free (plugin->port);
1024 return NULL;
1025 }
1026 switch (af)
1027 {
1028 case AF_INET:
1029 {
1030 int on = 1;
1031
1032 if (0 !=
1033 setsockopt (sock,
1034 IPPROTO_IP,
1035 IP_PKTINFO,
1036 &on,
1037 sizeof (on)))
1038 {
1040 "setsockopt");
1041 }
1042 }
1043 {
1044 struct sockaddr_in sa = {
1045 .sin_family = AF_INET,
1046 .sin_port = htons ((uint16_t) nport)
1047 };
1048
1049 if (0 !=
1050 bind (sock,
1051 (const struct sockaddr *) &sa,
1052 sizeof (sa)))
1053 {
1055 "socket");
1056 GNUNET_break (0 ==
1057 close (sock));
1058 GNUNET_free (plugin->port);
1060 return NULL;
1061 }
1062 }
1063 break;
1064 case AF_INET6:
1065 {
1066 int on = 1;
1067
1068 if (0 !=
1069 setsockopt (sock,
1070 IPPROTO_IPV6,
1071 IPV6_RECVPKTINFO,
1072 &on,
1073 sizeof (on)))
1074 {
1076 "setsockopt");
1077 }
1078 }
1079 {
1080 struct sockaddr_in6 sa = {
1081 .sin6_family = AF_INET6,
1082 .sin6_port = htons ((uint16_t) nport)
1083 };
1084
1085 if (0 !=
1086 bind (sock,
1087 (const struct sockaddr *) &sa,
1088 sizeof (sa)))
1089 {
1091 "socket");
1092 GNUNET_break (0 ==
1093 close (sock));
1094 GNUNET_free (plugin->port);
1096 return NULL;
1097 }
1098 }
1099 break;
1100 }
1102 GNUNET_NO);
1106 plugin->sock,
1107 &read_cb,
1108 plugin);
1109 env->network_size_cb (env->cls,
1111 log (nse) / log (2),
1112 -1.0 /* stddev */);
1113 plugin->scan_task = GNUNET_SCHEDULER_add_now (&scan,
1114 plugin);
1116 api->cls = plugin;
1118 api->hold = &ip_hold;
1119 api->drop = &ip_drop;
1120 api->send = &ip_send;
1121 return api;
1122}
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:34
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
enum GNUNET_GenericReturnValue GNUNET_NETWORK_test_pf(int pf)
Test if the given protocol family is supported by this system.
Definition: network.c:79
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:1303
#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 struct GNUNET_DHTU_PreferenceHandle * ip_hold(void *cls, struct GNUNET_DHTU_Target *target)
Request underlay to keep the connection to target alive if possible.
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.
struct returned by the initialization function of the plugin
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.
struct GNUNET_DHTU_PreferenceHandle *(* hold)(void *cls, struct GNUNET_DHTU_Target *target)
Request underlay to keep the connection to target alive if possible.
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_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_NETWORK_test_pf(), 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.

Referenced by load_underlay().

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

◆ DHTU_ip_done()

void * DHTU_ip_done ( struct GNUNET_DHTU_PluginFunctions api)

Exit point from the plugin.

Parameters
clsclosure (our struct Plugin)
Returns
NULL

Definition at line 1132 of file plugin_dhtu_ip.c.

1133{
1134 struct Plugin *plugin = api->cls;
1135 struct GNUNET_DHTU_Source *src;
1136 struct GNUNET_DHTU_Target *dst;
1137
1138 while (NULL != (dst = plugin->dst_head))
1139 {
1140 plugin->env->disconnect_cb (dst->app_ctx);
1141 GNUNET_assert (NULL == dst->ph_head);
1143 plugin->dst_tail,
1144 dst);
1145 GNUNET_free (dst);
1146 }
1147 while (NULL != (src = plugin->src_head))
1148 {
1149 plugin->env->address_del_cb (src->app_ctx);
1151 plugin->src_tail,
1152 src);
1153 GNUNET_free (src->address);
1154 GNUNET_free (src);
1155 }
1156 plugin->env->network_size_cb (plugin->env->cls,
1158 0.0,
1159 0.0);
1161 if (NULL != plugin->read_task)
1162 {
1163 GNUNET_SCHEDULER_cancel (plugin->read_task);
1164 plugin->read_task = NULL;
1165 }
1166 GNUNET_SCHEDULER_cancel (plugin->scan_task);
1169 GNUNET_free (plugin->port);
1171 GNUNET_free (api);
1172 return NULL;
1173}
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:508
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:979
#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_TESTING_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.

Referenced by shutdown_task().

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