GNUnet  0.11.x
Data Structures | Macros | Enumerations | Functions | Variables
gnunet-service-transport_validation.c File Reference

address validation subsystem More...

#include "platform.h"
#include "gnunet-service-transport_ats.h"
#include "gnunet-service-transport_hello.h"
#include "gnunet-service-transport_neighbours.h"
#include "gnunet-service-transport_plugins.h"
#include "gnunet-service-transport_validation.h"
#include "gnunet-service-transport.h"
#include "gnunet_hello_lib.h"
#include "gnunet_ats_service.h"
#include "gnunet_peerinfo_service.h"
#include "gnunet_signatures.h"
Include dependency graph for gnunet-service-transport_validation.c:

Go to the source code of this file.

Data Structures

struct  TransportPingMessage
 Message used to ask a peer to validate receipt (to check an address from a HELLO). More...
 
struct  TransportPongMessage
 Message used to validate a HELLO. More...
 
struct  ValidationEntry
 Information about an address under validation. More...
 
struct  ValidationEntryMatchContext
 Context for the validation entry match function. More...
 
struct  IteratorContext
 Closure for the neighbours_iterate() function. More...
 

Macros

#define PONG_SIGNATURE_LIFETIME
 How long is a PONG signature valid? We'll recycle a signature until 1/4 of this time is remaining. More...
 
#define HELLO_ADDRESS_EXPIRATION
 After how long do we expire an address in a HELLO that we just validated? This value is also used for our own addresses when we create a HELLO. More...
 
#define UNVALIDATED_PING_KEEPALIVE
 How often do we allow PINGing an address that we have not yet validated? This also determines how long we track an address that we cannot validate (because after this time we can destroy the validation record). More...
 
#define VALIDATED_PING_FREQUENCY
 How often do we PING an address that we have successfully validated in the past but are not actively using? Should be (significantly) smaller than HELLO_ADDRESS_EXPIRATION. More...
 
#define CONNECTED_PING_FREQUENCY
 How often do we PING an address that we are currently using? More...
 
#define ACCEPTABLE_PING_DELAY
 How much delay is acceptable for sending the PING or PONG? More...
 
#define VALIDATION_MAP_SIZE   256
 Size of the validation map hashmap. More...
 
#define PING_PRIORITY   2
 Priority to use for PINGs. More...
 
#define PONG_PRIORITY   4
 Priority to use for PONGs. More...
 

Enumerations

enum  GNUNET_TRANSPORT_ValidationState {
  GNUNET_TRANSPORT_VS_NONE , GNUNET_TRANSPORT_VS_NEW , GNUNET_TRANSPORT_VS_UPDATE , GNUNET_TRANSPORT_VS_TIMEOUT ,
  GNUNET_TRANSPORT_VS_REMOVE
}
 Current state of a validation process. More...
 

Functions

static void publish_ve_stat_update ()
 Provide an update on the validation_map map size to statistics. More...
 
static int validation_entry_match (void *cls, const struct GNUNET_PeerIdentity *key, void *value)
 Iterate over validation entries until a matching one is found. More...
 
static void validation_entry_changed (struct ValidationEntry *ve, enum GNUNET_TRANSPORT_ValidationState state)
 A validation entry changed. More...
 
static int cleanup_validation_entry (void *cls, const struct GNUNET_PeerIdentity *key, void *value)
 Iterate over validation entries and free them. More...
 
static void timeout_hello_validation (void *cls)
 Address validation cleanup task. More...
 
static void transmit_ping_if_allowed (void *cls, const struct GNUNET_PeerIdentity *pid, const struct GNUNET_HELLO_Address *address_null, struct GNUNET_ATS_Session *session_null, int result)
 Function called with the result from blacklisting. More...
 
static void revalidate_address (void *cls)
 Do address validation again to keep address valid. More...
 
static struct ValidationEntryfind_validation_entry (const struct GNUNET_HELLO_Address *address)
 Find a ValidationEntry entry for the given neighbour that matches the given address and transport. More...
 
static int add_valid_address (void *cls, const struct GNUNET_HELLO_Address *address, struct GNUNET_TIME_Absolute expiration)
 Iterator which adds the given address to the set of validated addresses. More...
 
static void process_peerinfo_hello (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HELLO_Message *hello, const char *err_msg)
 Function called for any HELLO known to PEERINFO. More...
 
void GST_validation_start (unsigned int max_fds)
 Start the validation subsystem. More...
 
void GST_validation_stop ()
 Stop the validation subsystem. More...
 
static void multicast_pong (void *cls, struct GNUNET_TIME_Absolute valid_until, struct GNUNET_TIME_Absolute validation_block, const struct GNUNET_HELLO_Address *address)
 Send the given PONG to the given address. More...
 
int GST_validation_handle_ping (const struct GNUNET_PeerIdentity *sender, const struct GNUNET_MessageHeader *hdr, const struct GNUNET_HELLO_Address *sender_address, struct GNUNET_ATS_Session *session)
 We've received a PING. More...
 
void GST_validation_handle_address (const struct GNUNET_HELLO_Address *address)
 Validate an individual address. More...
 
static int validate_address_iterator (void *cls, const struct GNUNET_HELLO_Address *address, struct GNUNET_TIME_Absolute expiration)
 Iterator callback to go over all addresses and try to validate them (unless blocked or already validated). More...
 
static ssize_t add_valid_peer_address (void *cls, size_t max, void *buf)
 Add the validated peer address to the HELLO. More...
 
int GST_validation_handle_pong (const struct GNUNET_PeerIdentity *sender, const struct GNUNET_MessageHeader *hdr)
 We've received a PONG. More...
 
int GST_validation_handle_hello (const struct GNUNET_MessageHeader *hello)
 We've received a HELLO, check which addresses are new and trigger validation. More...
 
static int iterate_addresses (void *cls, const struct GNUNET_PeerIdentity *key, void *value)
 Call the callback in the closure for each validation entry. More...
 
void GST_validation_get_addresses (const struct GNUNET_PeerIdentity *target, GST_ValidationAddressCallback cb, void *cb_cls)
 Call the given function for each address for the given target. More...
 
void GST_validation_set_address_use (const struct GNUNET_HELLO_Address *address, int in_use)
 Update if we are using an address for a connection actively right now. More...
 

Variables

static struct GNUNET_CONTAINER_MultiPeerMapvalidation_map
 Map of PeerIdentities to 'struct ValidationEntry*'s (addresses of the given peer that we are currently validating, have validated or are blocked from re-validation for a while). More...
 
static struct GNUNET_PEERINFO_NotifyContextpnc
 Context for peerinfo iteration. More...
 
static struct GNUNET_TIME_Relative validation_delay
 Minimum delay between to validations. More...
 
static unsigned int validations_running
 Number of validations running; any PING that was not yet matched by a PONG and for which we have not yet hit the timeout is considered a running 'validation'. More...
 
static unsigned int validations_fast_start_threshold
 Validition fast start threshold. More...
 
static struct GNUNET_TIME_Absolute validation_next
 When is next validation allowed. More...
 

Detailed Description

address validation subsystem

Author
Christian Grothoff

Definition in file gnunet-service-transport_validation.c.

Macro Definition Documentation

◆ PONG_SIGNATURE_LIFETIME

#define PONG_SIGNATURE_LIFETIME
Value:
#define GNUNET_TIME_UNIT_HOURS
One hour.
struct GNUNET_TIME_Relative GNUNET_TIME_relative_multiply(struct GNUNET_TIME_Relative rel, unsigned long long factor)
Multiply relative time by a given factor.
Definition: time.c:311

How long is a PONG signature valid? We'll recycle a signature until 1/4 of this time is remaining.

PONGs should expire so that if our external addresses change an adversary cannot replay them indefinitely. OTOH, we don't want to spend too much time generating PONG signatures, so they must have some lifetime to reduce our CPU usage.

Definition at line 91 of file gnunet-service-transport_validation.c.

◆ HELLO_ADDRESS_EXPIRATION

#define HELLO_ADDRESS_EXPIRATION
Value:

After how long do we expire an address in a HELLO that we just validated? This value is also used for our own addresses when we create a HELLO.

Definition at line 99 of file gnunet-service-transport_validation.c.

◆ UNVALIDATED_PING_KEEPALIVE

#define UNVALIDATED_PING_KEEPALIVE
Value:
#define GNUNET_TIME_UNIT_MINUTES
One minute.

How often do we allow PINGing an address that we have not yet validated? This also determines how long we track an address that we cannot validate (because after this time we can destroy the validation record).

Definition at line 108 of file gnunet-service-transport_validation.c.

◆ VALIDATED_PING_FREQUENCY

#define VALIDATED_PING_FREQUENCY
Value:

How often do we PING an address that we have successfully validated in the past but are not actively using? Should be (significantly) smaller than HELLO_ADDRESS_EXPIRATION.

Definition at line 116 of file gnunet-service-transport_validation.c.

◆ CONNECTED_PING_FREQUENCY

#define CONNECTED_PING_FREQUENCY
Value:

How often do we PING an address that we are currently using?

Definition at line 122 of file gnunet-service-transport_validation.c.

◆ ACCEPTABLE_PING_DELAY

#define ACCEPTABLE_PING_DELAY
Value:
#define GNUNET_TIME_UNIT_SECONDS
One second.

How much delay is acceptable for sending the PING or PONG?

Definition at line 128 of file gnunet-service-transport_validation.c.

◆ VALIDATION_MAP_SIZE

#define VALIDATION_MAP_SIZE   256

Size of the validation map hashmap.

Definition at line 134 of file gnunet-service-transport_validation.c.

◆ PING_PRIORITY

#define PING_PRIORITY   2

Priority to use for PINGs.

Definition at line 139 of file gnunet-service-transport_validation.c.

◆ PONG_PRIORITY

#define PONG_PRIORITY   4

Priority to use for PONGs.

Definition at line 144 of file gnunet-service-transport_validation.c.

Enumeration Type Documentation

◆ GNUNET_TRANSPORT_ValidationState

Current state of a validation process.

FIXME: what state is used to indicate that a validation was successful? If that is clarified/determined, "UGH" in ~gnunetpeerinfogtk.c:1103 should be resolved.

Enumerator
GNUNET_TRANSPORT_VS_NONE 

Undefined state.

Used for final callback indicating operation done

GNUNET_TRANSPORT_VS_NEW 

Fresh validation entry.

Entry was just created, no validation process was executed

GNUNET_TRANSPORT_VS_UPDATE 

Updated validation entry.

This is an update for an existing validation entry

GNUNET_TRANSPORT_VS_TIMEOUT 

Timeout for validation entry.

A timeout occurred during the validation process

GNUNET_TRANSPORT_VS_REMOVE 

Validation entry is removed.

The validation entry is getting removed due to a failed validation

Definition at line 45 of file gnunet-service-transport_validation.c.

46 {
53 
60 
67 
74 
81 };
@ GNUNET_TRANSPORT_VS_TIMEOUT
Timeout for validation entry.
@ GNUNET_TRANSPORT_VS_REMOVE
Validation entry is removed.
@ GNUNET_TRANSPORT_VS_UPDATE
Updated validation entry.
@ GNUNET_TRANSPORT_VS_NONE
Undefined state.
@ GNUNET_TRANSPORT_VS_NEW
Fresh validation entry.

Function Documentation

◆ publish_ve_stat_update()

static void publish_ve_stat_update ( )
static

Provide an update on the validation_map map size to statistics.

This function should be called whenever the validation_map is changed.

Definition at line 383 of file gnunet-service-transport_validation.c.

384 {
386  gettext_noop ("# Addresses in validation map"),
388  GNUNET_NO);
389 }
#define gettext_noop(String)
Definition: gettext.h:69
static struct GNUNET_STATISTICS_Handle * GST_stats
Statistics handle.
static struct GNUNET_CONTAINER_MultiPeerMap * validation_map
Map of PeerIdentities to 'struct ValidationEntry*'s (addresses of the given peer that we are currentl...
@ GNUNET_NO
Definition: gnunet_common.h:94
unsigned int GNUNET_CONTAINER_multipeermap_size(const struct GNUNET_CONTAINER_MultiPeerMap *map)
Get the number of key-value pairs in the map.
void GNUNET_STATISTICS_set(struct GNUNET_STATISTICS_Handle *handle, const char *name, uint64_t value, int make_persistent)
Set statistic value for the peer.

References gettext_noop, GNUNET_CONTAINER_multipeermap_size(), GNUNET_NO, GNUNET_STATISTICS_set(), GST_stats, and validation_map.

Referenced by cleanup_validation_entry(), and find_validation_entry().

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

◆ validation_entry_match()

static int validation_entry_match ( void *  cls,
const struct GNUNET_PeerIdentity key,
void *  value 
)
static

Iterate over validation entries until a matching one is found.

Parameters
clsthe struct ValidationEntryMatchContext *
keypeer identity (unused)
valuea struct ValidationEntry * to match
Returns
GNUNET_YES if the entry does not match, GNUNET_NO if the entry does match

Definition at line 402 of file gnunet-service-transport_validation.c.

405 {
406  struct ValidationEntryMatchContext *vemc = cls;
407  struct ValidationEntry *ve = value;
408 
409  if (0 == GNUNET_HELLO_address_cmp (ve->address,
410  vemc->address))
411  {
412  vemc->ve = ve;
413  return GNUNET_NO;
414  }
415  return GNUNET_YES;
416 }
static char * value
Value of the record to add/remove.
@ GNUNET_YES
Definition: gnunet_common.h:97
int GNUNET_HELLO_address_cmp(const struct GNUNET_HELLO_Address *a1, const struct GNUNET_HELLO_Address *a2)
Compare two addresses.
Definition: address.c:130
Context for the validation entry match function.
const struct GNUNET_HELLO_Address * address
Address we're interested in.
struct ValidationEntry * ve
Where to store the result?
Information about an address under validation.
struct GNUNET_HELLO_Address * address
The address.

References ValidationEntry::address, ValidationEntryMatchContext::address, GNUNET_HELLO_address_cmp(), GNUNET_NO, GNUNET_YES, value, and ValidationEntryMatchContext::ve.

Referenced by find_validation_entry().

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

◆ validation_entry_changed()

static void validation_entry_changed ( struct ValidationEntry ve,
enum GNUNET_TRANSPORT_ValidationState  state 
)
static

A validation entry changed.

Update the state and notify monitors.

Parameters
vevalidation entry that changed
statenew state

Definition at line 427 of file gnunet-service-transport_validation.c.

429 {
430  ve->state = state;
431 }
enum State state
current state of profiling
enum GNUNET_TRANSPORT_ValidationState state
Current state of this validation entry.

References state, and ValidationEntry::state.

Referenced by add_valid_address(), cleanup_validation_entry(), find_validation_entry(), GST_validation_handle_pong(), and transmit_ping_if_allowed().

Here is the caller graph for this function:

◆ cleanup_validation_entry()

static int cleanup_validation_entry ( void *  cls,
const struct GNUNET_PeerIdentity key,
void *  value 
)
static

Iterate over validation entries and free them.

Parameters
cls(unused)
keypeer identity (unused)
valuea struct ValidationEntry * to clean up
Returns
GNUNET_YES (continue to iterate)

Definition at line 443 of file gnunet-service-transport_validation.c.

446 {
447  struct ValidationEntry *ve = value;
448 
451 
452  /* Notify about deleted entry */
455 
456  if (NULL != ve->bc)
457  {
459  ve->bc = NULL;
460  }
463  &ve->address->peer,
464  ve));
466  if (GNUNET_YES == ve->known_to_ats)
467  {
471  ve->known_to_ats = GNUNET_NO;
472  }
474  if (NULL != ve->timeout_task)
475  {
477  ve->timeout_task = NULL;
478  }
479  if (NULL != ve->revalidation_task)
480  {
482  ve->revalidation_task = NULL;
483  }
484  if ((GNUNET_YES == ve->expecting_pong) &&
485  (validations_running > 0))
486  {
489  gettext_noop ("# validations running"),
491  GNUNET_NO);
492  }
493  GNUNET_free (ve);
494  return GNUNET_OK;
495 }
void GST_blacklist_test_cancel(struct GST_BlacklistCheck *bc)
Cancel a blacklist check.
int GST_ats_is_known_no_session(const struct GNUNET_HELLO_Address *address)
Test if ATS knows about this address.
void GST_ats_expire_address(const struct GNUNET_HELLO_Address *address)
Notify ATS that the address has expired and thus cannot be used any longer.
static void publish_ve_stat_update()
Provide an update on the validation_map map size to statistics.
static void validation_entry_changed(struct ValidationEntry *ve, enum GNUNET_TRANSPORT_ValidationState state)
A validation entry changed.
static unsigned int validations_running
Number of validations running; any PING that was not yet matched by a PONG and for which we have not ...
@ GNUNET_OK
Definition: gnunet_common.h:95
int GNUNET_CONTAINER_multipeermap_remove(struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key, const void *value)
Remove the given key-value pair from the map.
#define GNUNET_HELLO_address_free(addr)
Free an address.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.
#define GNUNET_free(ptr)
Wrapper around free.
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:972
#define GNUNET_TIME_UNIT_ZERO_ABS
Absolute time zero.
struct GNUNET_PeerIdentity peer
For which peer is this an address?
struct GNUNET_SCHEDULER_Task * revalidation_task
ID of task that will trigger address revalidation.
struct GNUNET_TIME_Absolute next_validation
At what time do we send the next validation request (PING)?
struct GNUNET_SCHEDULER_Task * timeout_task
ID of task that will clean up this entry if nothing happens.
struct GNUNET_TIME_Absolute valid_until
Until when is this address valid? ZERO if it is not currently considered valid.
struct GST_BlacklistCheck * bc
Handle to the blacklist check (if we're currently in it).
int known_to_ats
Is this address known to ATS as valid right now?
int expecting_pong
Are we expecting a PONG message for this validation entry?

References ValidationEntry::address, ValidationEntry::bc, ValidationEntry::expecting_pong, gettext_noop, GNUNET_assert, GNUNET_break, GNUNET_CONTAINER_multipeermap_remove(), GNUNET_free, GNUNET_HELLO_address_free, GNUNET_NO, GNUNET_OK, GNUNET_SCHEDULER_cancel(), GNUNET_STATISTICS_set(), GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_TRANSPORT_VS_REMOVE, GNUNET_YES, GST_ats_expire_address(), GST_ats_is_known_no_session(), GST_blacklist_test_cancel(), GST_stats, ValidationEntry::known_to_ats, ValidationEntry::next_validation, GNUNET_HELLO_Address::peer, publish_ve_stat_update(), ValidationEntry::revalidation_task, ValidationEntry::timeout_task, ValidationEntry::valid_until, validation_entry_changed(), validation_map, validations_running, and value.

Referenced by GST_validation_stop(), timeout_hello_validation(), and transmit_ping_if_allowed().

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

◆ timeout_hello_validation()

static void timeout_hello_validation ( void *  cls)
static

Address validation cleanup task.

Assesses if the record is no longer valid and then possibly triggers its removal.

Parameters
clsthe struct ValidationEntry

Definition at line 505 of file gnunet-service-transport_validation.c.

506 {
507  struct ValidationEntry *ve = cls;
508  struct GNUNET_TIME_Absolute max;
509  struct GNUNET_TIME_Relative left;
510 
511  ve->timeout_task = NULL;
512  /* For valid addresses, we want to wait until the expire;
513  for addresses under PING validation, we want to wait
514  until we give up on the PING */
516  ve->revalidation_block);
518  if (left.rel_value_us > 0)
519  {
520  /* We should wait a bit longer. This happens when
521  address lifetimes are extended due to successful
522  validations. */
523  ve->timeout_task =
526  ve);
527  return;
528  }
530  gettext_noop (
531  "# address records discarded (timeout)"),
532  1,
533  GNUNET_NO);
535  &ve->address->peer,
536  ve);
537 }
static int cleanup_validation_entry(void *cls, const struct GNUNET_PeerIdentity *key, void *value)
Iterate over validation entries and free them.
static void timeout_hello_validation(void *cls)
Address validation cleanup task.
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:1269
void GNUNET_STATISTICS_update(struct GNUNET_STATISTICS_Handle *handle, const char *name, int64_t delta, int make_persistent)
Set statistic value for the peer.
struct GNUNET_TIME_Relative GNUNET_TIME_absolute_get_remaining(struct GNUNET_TIME_Absolute future)
Given a timestamp in the future, how much time remains until then?
Definition: time.c:232
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_max(struct GNUNET_TIME_Absolute t1, struct GNUNET_TIME_Absolute t2)
Return the maximum of two absolute time values.
Definition: time.c:224
#define max(x, y)
Time for absolute times used by GNUnet, in microseconds.
Time for relative time used by GNUnet, in microseconds.
struct GNUNET_TIME_Absolute revalidation_block
How long until we can try to validate this address again? FOREVER if the address is for an unsupporte...

References ValidationEntry::address, cleanup_validation_entry(), gettext_noop, GNUNET_NO, GNUNET_SCHEDULER_add_delayed(), GNUNET_STATISTICS_update(), GNUNET_TIME_absolute_get_remaining(), GNUNET_TIME_absolute_max(), GST_stats, max, GNUNET_HELLO_Address::peer, GNUNET_TIME_Relative::rel_value_us, ValidationEntry::revalidation_block, ValidationEntry::timeout_task, and ValidationEntry::valid_until.

Referenced by find_validation_entry().

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

◆ transmit_ping_if_allowed()

static void transmit_ping_if_allowed ( void *  cls,
const struct GNUNET_PeerIdentity pid,
const struct GNUNET_HELLO_Address address_null,
struct GNUNET_ATS_Session session_null,
int  result 
)
static

Function called with the result from blacklisting.

Send a PING to the other peer if a communication is allowed.

Parameters
clsour struct ValidationEntry
pididentity of the other peer
address_nulladdress associated with the request, always NULL
session_nullsession associated with the request, always NULL
resultGNUNET_OK if the connection is allowed, GNUNET_NO if not, GNUNET_SYSERR if operation was aborted

Definition at line 553 of file gnunet-service-transport_validation.c.

558 {
559  struct ValidationEntry *ve = cls;
560  struct TransportPingMessage ping;
562  struct GNUNET_TIME_Absolute next;
563  const struct GNUNET_MessageHeader *hello;
564  ssize_t ret;
565  size_t tsize;
566  size_t slen;
567  uint16_t hsize;
568  struct GNUNET_ATS_Session *session;
569 
570  ve->bc = NULL;
571  if (GNUNET_OK != result)
572  {
574  "Blacklist denies sending PING to `%s' `%s' `%s'\n",
575  GNUNET_i2s (pid),
576  GST_plugins_a2s (ve->address),
577  ve->address->transport_name);
579  gettext_noop (
580  "# address records discarded (blacklist)"),
581  1,
582  GNUNET_NO);
584  pid,
585  ve);
586  return;
587  }
588  hello = GST_hello_get ();
589  GNUNET_assert (NULL != hello);
590  slen = strlen (ve->address->transport_name) + 1;
591  hsize = ntohs (hello->size);
592  tsize = sizeof(struct TransportPingMessage)
593  + ve->address->address_length + slen + hsize;
594 
595  ping.header.size =
596  htons (sizeof(struct TransportPingMessage)
597  + ve->address->address_length + slen);
598  ping.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_PING);
599  ping.challenge = htonl (ve->challenge);
600  ping.target = *pid;
601 
602  if (tsize >= GNUNET_MAX_MESSAGE_SIZE)
603  {
604  GNUNET_break (0);
605  hsize = 0;
606  tsize =
607  sizeof(struct TransportPingMessage) + ve->address->address_length
608  + slen + hsize;
609  }
610  {
611  char message_buf[tsize] GNUNET_ALIGN;
612 
613  GNUNET_memcpy (message_buf,
614  hello,
615  hsize);
616  GNUNET_memcpy (&message_buf[hsize],
617  &ping,
618  sizeof(struct TransportPingMessage));
619  GNUNET_memcpy (&message_buf[sizeof(struct TransportPingMessage) + hsize],
620  ve->address->transport_name,
621  slen);
622  GNUNET_memcpy (&message_buf[sizeof(struct TransportPingMessage) + slen
623  + hsize],
624  ve->address->address,
625  ve->address->address_length);
627  GNUNET_assert (NULL != papi);
628  session = papi->get_session (papi->cls,
629  ve->address);
630  if (NULL == session)
631  {
632  /* Could not get a valid session */
634  "Failed to get session to send PING to `%s' at `%s'\n",
635  GNUNET_i2s (pid),
636  GST_plugins_a2s (ve->address));
637  return;
638  }
639 
640  ret = papi->send (papi->cls, session,
641  message_buf, tsize,
644  NULL, NULL);
645  if (-1 == ret)
646  {
648  "Failed to send PING to `%s' at `%s'\n",
649  GNUNET_i2s (pid),
650  GST_plugins_a2s (ve->address));
651  return;
652  }
654  "Transmitted plain PING to `%s' `%s' `%s'\n",
655  GNUNET_i2s (pid),
656  GST_plugins_a2s (ve->address),
657  ve->address->transport_name);
658  ve->network = papi->get_network (papi->cls,
659  session);
662  session,
663  tsize);
669  gettext_noop (
670  "# PINGs for address validation sent"),
671  1,
672  GNUNET_NO);
676  "Validation started, %u validation processes running\n",
679  gettext_noop ("# validations running"),
681  GNUNET_NO);
682  /* Notify about PING sent */
685  }
686 }
static int ret
Return value of the commandline.
Definition: gnunet-abd.c:81
static void ping(void *cls)
Send a ping to destination.
static char * address
GNS address for this phone.
static int result
Global testing status.
const struct GNUNET_MessageHeader * GST_hello_get()
Obtain this peers HELLO message.
void GST_neighbours_notify_data_sent(const struct GNUNET_HELLO_Address *address, struct GNUNET_ATS_Session *session, size_t size)
Track information about data we transmitted using the given address and session (used to notify ATS a...
struct GNUNET_TRANSPORT_PluginFunctions * GST_plugins_find(const char *name)
Obtain the plugin API based on a plugin name.
const char * GST_plugins_a2s(const struct GNUNET_HELLO_Address *address)
Convert a given address to a human-readable format.
#define PING_PRIORITY
Priority to use for PINGs.
static struct GNUNET_TIME_Relative validation_delay
Minimum delay between to validations.
#define ACCEPTABLE_PING_DELAY
How much delay is acceptable for sending the PING or PONG?
static struct GNUNET_TIME_Absolute validation_next
When is next validation allowed.
static struct GNUNET_PeerIdentity pid
Identity of the peer we transmit to / connect to.
#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_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
#define GNUNET_MAX_MESSAGE_SIZE
Largest supported message (to be precise, one byte more than the largest possible message,...
const char * GNUNET_i2s(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
@ GNUNET_ERROR_TYPE_DEBUG
@ GNUNET_ERROR_TYPE_INFO
@ GNUNET_NT_UNSPECIFIED
Category of last resort.
Definition: gnunet_nt_lib.h:40
#define GNUNET_MESSAGE_TYPE_TRANSPORT_PING
Transport PING message.
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get(void)
Get the current time.
Definition: time.c:86
struct GNUNET_TIME_Absolute GNUNET_TIME_relative_to_absolute(struct GNUNET_TIME_Relative rel)
Convert relative time to an absolute time in the future.
Definition: time.c:181
Session handle for connections.
const char * transport_name
Name of the transport plugin enabling the communication using this address.
size_t address_length
Number of bytes in address.
const void * address
Binary representation of the address (plugin-specific).
Header for all communications.
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format.
Each plugin is required to return a pointer to a struct of this type as the return value from its ent...
void * cls
Closure for all of the callbacks.
GNUNET_TRANSPORT_TransmitFunction send
Function that the transport service will use to transmit data to another peer.
GNUNET_TRANSPORT_GetNetworkType get_network
Function to obtain the network type for a session.
GNUNET_TRANSPORT_CreateSession get_session
Function that will be called tell the plugin to create a session object.
Message used to ask a peer to validate receipt (to check an address from a HELLO).
struct GNUNET_TIME_Absolute send_time
At what time did we send the latest validation request (PING)?
uint32_t challenge
Challenge number we used.
enum GNUNET_NetworkType network
Which network type does our address belong to?

References ACCEPTABLE_PING_DELAY, address, GNUNET_HELLO_Address::address, ValidationEntry::address, GNUNET_HELLO_Address::address_length, ValidationEntry::bc, ValidationEntry::challenge, cleanup_validation_entry(), GNUNET_TRANSPORT_PluginFunctions::cls, ValidationEntry::expecting_pong, GNUNET_TRANSPORT_PluginFunctions::get_network, GNUNET_TRANSPORT_PluginFunctions::get_session, gettext_noop, GNUNET_ALIGN, GNUNET_assert, GNUNET_break, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_INFO, GNUNET_i2s(), GNUNET_log, GNUNET_MAX_MESSAGE_SIZE, GNUNET_memcpy, GNUNET_MESSAGE_TYPE_TRANSPORT_PING, GNUNET_NO, GNUNET_NT_UNSPECIFIED, GNUNET_OK, GNUNET_STATISTICS_set(), GNUNET_STATISTICS_update(), GNUNET_TIME_absolute_get(), GNUNET_TIME_absolute_max(), GNUNET_TIME_relative_to_absolute(), GNUNET_TRANSPORT_VS_UPDATE, GNUNET_YES, GST_hello_get(), GST_neighbours_notify_data_sent(), GST_plugins_a2s(), GST_plugins_find(), GST_stats, ValidationEntry::network, pid, ping(), PING_PRIORITY, result, ret, GNUNET_TRANSPORT_PluginFunctions::send, ValidationEntry::send_time, GNUNET_MessageHeader::size, GNUNET_HELLO_Address::transport_name, validation_delay, validation_entry_changed(), validation_next, and validations_running.

Referenced by revalidate_address().

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

◆ revalidate_address()

static void revalidate_address ( void *  cls)
static

Do address validation again to keep address valid.

Parameters
clsthe struct ValidationEntry

Definition at line 695 of file gnunet-service-transport_validation.c.

696 {
697  struct ValidationEntry *ve = cls;
698  struct GNUNET_TIME_Relative canonical_delay;
700  struct GNUNET_TIME_Relative blocked_for;
701  struct GST_BlacklistCheck *bc;
702  uint32_t rdelay;
703 
704  ve->revalidation_task = NULL;
706  /* Considering current connectivity situation, what is the maximum
707  block period permitted? */
708  if (GNUNET_YES == ve->in_use)
709  canonical_delay = CONNECTED_PING_FREQUENCY;
711  0)
712  canonical_delay = VALIDATED_PING_FREQUENCY;
713  else
714  canonical_delay = UNVALIDATED_PING_KEEPALIVE;
715  /* Use delay that is MIN of original delay and possibly adjusted
716  new maximum delay (which may be lower); the real delay
717  is originally randomized between "canonical_delay" and "2 * canonical_delay",
718  so continue to permit that window for the operation. */
721  canonical_delay,
722  2));
724  if (delay.rel_value_us > 0)
725  {
726  /* should wait a bit longer */
728  "Waiting for %s longer before (re)validating address `%s'\n",
730  GNUNET_YES),
731  GST_plugins_a2s (ve->address));
732  ve->revalidation_task =
734  &revalidate_address, ve);
736  return;
737  }
738  /* check if globally we have too many active validations at a
739  too high rate, if so, delay ours */
742  (blocked_for.rel_value_us > 0))
743  {
744  /* Validations are blocked, have to wait for blocked_for time */
746  "Validations blocked for another %s, delaying validating address `%s'\n",
748  GNUNET_YES),
749  GST_plugins_a2s (ve->address));
751  gettext_noop (
752  "# validations delayed by global throttle"),
753  1,
754  GNUNET_NO);
755  ve->revalidation_task =
756  GNUNET_SCHEDULER_add_delayed (blocked_for,
758  ve);
760  return;
761  }
762 
763  /* We are good to go; remember to not go again for `canonical_delay` time;
764  add up to `canonical_delay` to randomize start time */
766  /* schedule next PINGing with some extra random delay to avoid synchronous re-validations */
767  rdelay =
769  canonical_delay.rel_value_us);
770 
771  delay = GNUNET_TIME_relative_add (canonical_delay,
774  rdelay));
775 
777  "Validating now, next scheduled for %s, now validating address `%s'\n",
779  GNUNET_YES),
780  GST_plugins_a2s (ve->address));
781  ve->revalidation_task =
784  ve);
786 
787  /* start PINGing by checking blacklist */
789  gettext_noop ("# address revalidations started"), 1,
790  GNUNET_NO);
791  if (NULL != ve->bc)
792  {
794  ve->bc = NULL;
795  }
797  ve->address->transport_name,
799  ve,
800  NULL,
801  NULL);
802  if (NULL != bc)
803  {
804  /* If transmit_ping_if_allowed was already called it may have freed ve,
805  * so only set ve->bc if it has not been called.
806  */
807  ve->bc = bc;
808  }
809 }
static struct GNUNET_TIME_Relative delay
When should dkg communication start?
struct GST_BlacklistCheck * GST_blacklist_test_allowed(const struct GNUNET_PeerIdentity *peer, const char *transport_name, GST_BlacklistTestContinuation cont, void *cont_cls, const struct GNUNET_HELLO_Address *address, struct GNUNET_ATS_Session *session)
Test if a peer/transport combination is blacklisted.
#define CONNECTED_PING_FREQUENCY
How often do we PING an address that we are currently using?
static void transmit_ping_if_allowed(void *cls, const struct GNUNET_PeerIdentity *pid, const struct GNUNET_HELLO_Address *address_null, struct GNUNET_ATS_Session *session_null, int result)
Function called with the result from blacklisting.
static void revalidate_address(void *cls)
Do address validation again to keep address valid.
#define UNVALIDATED_PING_KEEPALIVE
How often do we allow PINGing an address that we have not yet validated? This also determines how lon...
#define VALIDATED_PING_FREQUENCY
How often do we PING an address that we have successfully validated in the past but are not actively ...
static unsigned int validations_fast_start_threshold
Validition fast start threshold.
uint32_t GNUNET_CRYPTO_random_u32(enum GNUNET_CRYPTO_Quality mode, uint32_t i)
Produce a random value.
@ GNUNET_CRYPTO_QUALITY_WEAK
No good quality of the operation is needed (i.e., random numbers can be pseudo-random).
struct GNUNET_TIME_Relative GNUNET_TIME_relative_min(struct GNUNET_TIME_Relative t1, struct GNUNET_TIME_Relative t2)
Return the minimum of two relative time values.
Definition: time.c:200
struct GNUNET_TIME_Relative GNUNET_TIME_relative_add(struct GNUNET_TIME_Relative a1, struct GNUNET_TIME_Relative a2)
Add relative times together.
Definition: time.c:411
const char * GNUNET_STRINGS_relative_time_to_string(struct GNUNET_TIME_Relative delta, int do_round)
Give relative time in human-readable fancy format.
Definition: strings.c:557
#define GNUNET_TIME_UNIT_MICROSECONDS
One microsecond, our basic time unit.
uint64_t rel_value_us
The actual value.
Context we use when performing a blacklist check.
int in_use
Are we currently using this address for a connection?

References ValidationEntry::address, ValidationEntry::bc, CONNECTED_PING_FREQUENCY, delay, gettext_noop, GNUNET_CRYPTO_QUALITY_WEAK, GNUNET_CRYPTO_random_u32(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_NO, GNUNET_SCHEDULER_add_delayed(), GNUNET_STATISTICS_update(), GNUNET_STRINGS_relative_time_to_string(), GNUNET_TIME_absolute_get_remaining(), GNUNET_TIME_relative_add(), GNUNET_TIME_relative_min(), GNUNET_TIME_relative_multiply(), GNUNET_TIME_relative_to_absolute(), GNUNET_TIME_UNIT_MICROSECONDS, GNUNET_YES, GST_blacklist_test_allowed(), GST_blacklist_test_cancel(), GST_plugins_a2s(), GST_stats, ValidationEntry::in_use, ValidationEntry::next_validation, GNUNET_HELLO_Address::peer, GNUNET_TIME_Relative::rel_value_us, ValidationEntry::revalidation_block, ValidationEntry::revalidation_task, transmit_ping_if_allowed(), GNUNET_HELLO_Address::transport_name, UNVALIDATED_PING_KEEPALIVE, ValidationEntry::valid_until, VALIDATED_PING_FREQUENCY, validation_next, validations_fast_start_threshold, and validations_running.

Referenced by add_valid_address(), and GST_validation_handle_address().

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

◆ find_validation_entry()

static struct ValidationEntry* find_validation_entry ( const struct GNUNET_HELLO_Address address)
static

Find a ValidationEntry entry for the given neighbour that matches the given address and transport.

If none exists, create one (but without starting any validation).

Parameters
addressaddress to find
Returns
validation entry matching the given specifications, NULL if we don't have an existing entry and no public key was given

Definition at line 822 of file gnunet-service-transport_validation.c.

823 {
824  struct ValidationEntryMatchContext vemc;
825  struct ValidationEntry *ve;
826 
827  vemc.ve = NULL;
828  vemc.address = address;
830  &address->peer,
831  &validation_entry_match, &vemc);
832  if (NULL != (ve = vemc.ve))
833  return ve;
836  ve = GNUNET_new (struct ValidationEntry);
837  ve->in_use = GNUNET_SYSERR; /* not defined */
840  memset (&ve->pong_sig_cache,
841  '\0',
842  sizeof(struct GNUNET_CRYPTO_EddsaSignature));
844  ve->challenge =
846  ve->timeout_task =
849  ve);
851  &address->peer,
852  ve,
857  return ve;
858 }
static int validation_entry_match(void *cls, const struct GNUNET_PeerIdentity *key, void *value)
Iterate over validation entries until a matching one is found.
@ GNUNET_SYSERR
Definition: gnunet_common.h:93
@ GNUNET_CRYPTO_QUALITY_NONCE
Randomness for IVs etc.
int GNUNET_CONTAINER_multipeermap_get_multiple(struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key, GNUNET_CONTAINER_PeerMapIterator it, void *it_cls)
Iterate over all entries in the map that match a particular key.
int GNUNET_CONTAINER_multipeermap_put(struct GNUNET_CONTAINER_MultiPeerMap *map, const struct GNUNET_PeerIdentity *key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
@ GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE
Allow multiple values with the same key.
struct GNUNET_HELLO_Address * GNUNET_HELLO_address_copy(const struct GNUNET_HELLO_Address *address)
Copy an address struct.
Definition: address.c:109
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_TIME_UNIT_FOREVER_REL
Constant used to specify "forever".
an ECC signature using EdDSA.
struct GNUNET_TIME_Absolute pong_sig_valid_until
Until when is the cached PONG signature valid? ZERO if it is not currently considered valid.
struct GNUNET_CRYPTO_EddsaSignature pong_sig_cache
Cached PONG signature.
struct GNUNET_TIME_Relative latency
Last observed latency for this address (round-trip), delay between last PING sent and PONG received; ...

References address, ValidationEntry::address, ValidationEntryMatchContext::address, ValidationEntry::challenge, GNUNET_assert, GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE, GNUNET_CONTAINER_multipeermap_get_multiple(), GNUNET_CONTAINER_multipeermap_put(), GNUNET_CRYPTO_QUALITY_NONCE, GNUNET_CRYPTO_random_u32(), GNUNET_HELLO_address_copy(), GNUNET_new, GNUNET_NO, GNUNET_SCHEDULER_add_delayed(), GNUNET_SYSERR, GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_TIME_UNIT_ZERO_ABS, GNUNET_TRANSPORT_VS_NEW, GST_ats_is_known_no_session(), ValidationEntry::in_use, ValidationEntry::latency, ValidationEntry::pong_sig_cache, ValidationEntry::pong_sig_valid_until, publish_ve_stat_update(), timeout_hello_validation(), ValidationEntry::timeout_task, UNVALIDATED_PING_KEEPALIVE, validation_entry_changed(), validation_entry_match(), validation_map, and ValidationEntryMatchContext::ve.

Referenced by add_valid_address(), GST_validation_handle_address(), and GST_validation_handle_pong().

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

◆ add_valid_address()

static int add_valid_address ( void *  cls,
const struct GNUNET_HELLO_Address address,
struct GNUNET_TIME_Absolute  expiration 
)
static

Iterator which adds the given address to the set of validated addresses.

Parameters
clsoriginal HELLO message
addressthe address
expirationexpiration time
Returns
GNUNET_OK (keep the address), could return GNUNET_NO (delete address, but this is ignored); GNUNET_SYSERR would abort iteration (but we always iterate all)

Definition at line 873 of file gnunet-service-transport_validation.c.

876 {
877  const struct GNUNET_HELLO_Message *hello = cls;
878  struct ValidationEntry *ve;
879  struct GNUNET_PeerIdentity pid;
880  struct GNUNET_ATS_Properties prop;
882 
883  if (0 == GNUNET_TIME_absolute_get_remaining (expiration).rel_value_us)
884  return GNUNET_OK; /* expired */
885  if (GNUNET_OK != GNUNET_HELLO_get_id (hello, &pid))
886  {
887  GNUNET_break (0);
888  return GNUNET_OK; /* invalid HELLO !? */
889  }
890  if (NULL == (papi = GST_plugins_find (address->transport_name)))
891  {
892  /* might have been valid in the past, but we don't have that
893  plugin loaded right now */
894  return GNUNET_OK;
895  }
896  if (NULL ==
897  papi->address_to_string (papi->cls,
898  address->address,
899  address->address_length))
900  {
901  /* Why do we try to add an ill-formed address? */
902  GNUNET_break (0);
904  "Address with %u bytes for plugin %s and peer %s is malformed\n",
905  (unsigned int) address->address_length,
906  address->transport_name,
907  GNUNET_i2s (&pid));
908  return GNUNET_OK;
909  }
910 
912  ve->network = papi->get_network_for_address (papi->cls,
913  address);
916  expiration);
917  if (NULL == ve->revalidation_task)
918  {
920  "Starting revalidations for valid address `%s'\n",
921  GST_plugins_a2s (ve->address));
924  }
927  memset (&prop, 0, sizeof(prop));
928  prop.scope = ve->network;
929  prop.delay = GNUNET_TIME_relative_divide (ve->latency, 2);
930  if (GNUNET_YES != ve->known_to_ats)
931  {
932  ve->known_to_ats = GNUNET_YES;
933  GST_ats_add_address (address, &prop);
936  }
937  return GNUNET_OK;
938 }
static char * expiration
Credential TTL.
Definition: gnunet-abd.c:96
void GST_ats_add_address(const struct GNUNET_HELLO_Address *address, const struct GNUNET_ATS_Properties *prop)
Notify ATS about the new address including the network this address is located in.
static struct ValidationEntry * find_validation_entry(const struct GNUNET_HELLO_Address *address)
Find a ValidationEntry entry for the given neighbour that matches the given address and transport.
int GNUNET_HELLO_get_id(const struct GNUNET_HELLO_Message *hello, struct GNUNET_PeerIdentity *peer)
Get the peer identity from a HELLO message.
Definition: hello.c:671
@ GNUNET_ERROR_TYPE_ERROR
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:1296
struct GNUNET_TIME_Relative GNUNET_TIME_relative_divide(struct GNUNET_TIME_Relative rel, unsigned long long factor)
Divide relative time by a given factor.
Definition: time.c:376
ATS performance characteristics for an address.
A HELLO message is used to exchange information about transports with other peers.
The identity of the host (wraps the signing key of the peer).
GNUNET_TRANSPORT_GetNetworkTypeForAddress get_network_for_address
Function to obtain the network type for an address.
GNUNET_TRANSPORT_AddressToString address_to_string
Function that will be called to convert a binary address to a string (numeric conversion only).

References address, ValidationEntry::address, GNUNET_TRANSPORT_PluginFunctions::address_to_string, GNUNET_TRANSPORT_PluginFunctions::cls, GNUNET_ATS_Properties::delay, expiration, find_validation_entry(), GNUNET_TRANSPORT_PluginFunctions::get_network_for_address, GNUNET_assert, GNUNET_break, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_ERROR, GNUNET_HELLO_get_id(), GNUNET_i2s(), GNUNET_log, GNUNET_NT_UNSPECIFIED, GNUNET_OK, GNUNET_SCHEDULER_add_now(), GNUNET_TIME_absolute_get(), GNUNET_TIME_absolute_get_remaining(), GNUNET_TIME_absolute_max(), GNUNET_TIME_relative_divide(), GNUNET_TRANSPORT_VS_UPDATE, GNUNET_YES, GST_ats_add_address(), GST_ats_is_known_no_session(), GST_plugins_a2s(), GST_plugins_find(), ValidationEntry::known_to_ats, ValidationEntry::latency, ValidationEntry::network, ValidationEntry::next_validation, pid, revalidate_address(), ValidationEntry::revalidation_task, GNUNET_ATS_Properties::scope, ValidationEntry::valid_until, and validation_entry_changed().

Referenced by process_peerinfo_hello().

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

◆ process_peerinfo_hello()

static void process_peerinfo_hello ( void *  cls,
const struct GNUNET_PeerIdentity peer,
const struct GNUNET_HELLO_Message hello,
const char *  err_msg 
)
static

Function called for any HELLO known to PEERINFO.

Parameters
clsunused (NULL)
peerid of the peer, NULL for last call (during iteration, as we are monitoring, this should never happen)
hellohello message for the peer (can be NULL)
err_msgerror message

Definition at line 951 of file gnunet-service-transport_validation.c.

955 {
956  GNUNET_assert (NULL != peer);
957  if (NULL == hello)
958  return;
959  if (0 == memcmp (&GST_my_identity,
960  peer,
961  sizeof(struct GNUNET_PeerIdentity)))
962  {
963  /* Peerinfo returned own identity, skip validation */
964  return;
965  }
967  "Handling HELLO for peer `%s'\n",
968  GNUNET_i2s (peer));
969  GNUNET_assert (NULL ==
972  (void *) hello));
973 }
static struct GNUNET_PeerIdentity GST_my_identity
Our public key.
static int add_valid_address(void *cls, const struct GNUNET_HELLO_Address *address, struct GNUNET_TIME_Absolute expiration)
Iterator which adds the given address to the set of validated addresses.
struct GNUNET_HELLO_Message * GNUNET_HELLO_iterate_addresses(const struct GNUNET_HELLO_Message *msg, int return_modified, GNUNET_HELLO_AddressIterator it, void *it_cls)
Iterate over all of the addresses in the HELLO.
Definition: hello.c:254
struct GNUNET_TESTBED_Peer * peer
The peer associated with this model.

References add_valid_address(), GNUNET_assert, GNUNET_ERROR_TYPE_DEBUG, GNUNET_HELLO_iterate_addresses(), GNUNET_i2s(), GNUNET_log, GNUNET_NO, GST_my_identity, and peer.

Referenced by GST_validation_start().

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

◆ GST_validation_start()

void GST_validation_start ( unsigned int  max_fds)

Start the validation subsystem.

Parameters
max_fdsmaximum number of fds to use

Initialization for validation throttling

We have a maximum number max_fds of connections we can use for validation We monitor the number of validations in parallel and start to throttle it when doing to many validations in parallel: if (running validations < (max_fds / 2))

  • "fast start": run validation immediately
  • have delay of (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT.rel_value_us) / (max_fds / 2) (300 sec / ~150 == ~2 sec.) between two validations

Definition at line 982 of file gnunet-service-transport_validation.c.

996  (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT.rel_value_us) / (max_fds / 2);
997  validations_fast_start_threshold = (max_fds / 2);
1000  gettext_noop ("# validations running"),
1002  GNUNET_NO);
1004  "Validation uses a fast start threshold of %u connections and a delay of %s\n",
1007  GNUNET_YES));
1009  GNUNET_NO);
1011  &process_peerinfo_hello, NULL);
1012 }
static const struct GNUNET_CONFIGURATION_Handle * GST_cfg
Configuration handle.
#define VALIDATION_MAP_SIZE
Size of the validation map hashmap.
static struct GNUNET_PEERINFO_NotifyContext * pnc
Context for peerinfo iteration.
static void process_peerinfo_hello(void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_HELLO_Message *hello, const char *err_msg)
Function called for any HELLO known to PEERINFO.
#define GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT
After how long do we consider a connection to a peer dead if we don't receive messages from the peer?
struct GNUNET_CONTAINER_MultiPeerMap * GNUNET_CONTAINER_multipeermap_create(unsigned int len, int do_not_copy_keys)
Create a multi peer map (hash map for public keys of peers).
struct GNUNET_PEERINFO_NotifyContext * GNUNET_PEERINFO_notify(const struct GNUNET_CONFIGURATION_Handle *cfg, int include_friend_only, GNUNET_PEERINFO_Processor callback, void *callback_cls)
Call a method whenever our known information about peers changes.

References gettext_noop, GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT, GNUNET_CONTAINER_multipeermap_create(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_NO, GNUNET_PEERINFO_notify(), GNUNET_STATISTICS_set(), GNUNET_STRINGS_relative_time_to_string(), GNUNET_TIME_absolute_get(), GNUNET_YES, GST_cfg, GST_stats, pnc, process_peerinfo_hello(), GNUNET_TIME_Relative::rel_value_us, validation_delay, validation_map, VALIDATION_MAP_SIZE, validation_next, validations_fast_start_threshold, and validations_running.

Referenced by run().

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

◆ GST_validation_stop()

void GST_validation_stop ( void  )

Stop the validation subsystem.

Definition at line 1019 of file gnunet-service-transport_validation.c.

1020 {
1023  NULL);
1025  validation_map = NULL;
1027 }
void GNUNET_CONTAINER_multipeermap_destroy(struct GNUNET_CONTAINER_MultiPeerMap *map)
Destroy a hash map.
int GNUNET_CONTAINER_multipeermap_iterate(struct GNUNET_CONTAINER_MultiPeerMap *map, GNUNET_CONTAINER_PeerMapIterator it, void *it_cls)
Iterate over all entries in the map.
void GNUNET_PEERINFO_notify_cancel(struct GNUNET_PEERINFO_NotifyContext *nc)
Stop notifying about changes.

References cleanup_validation_entry(), GNUNET_CONTAINER_multipeermap_destroy(), GNUNET_CONTAINER_multipeermap_iterate(), GNUNET_PEERINFO_notify_cancel(), pnc, and validation_map.

Referenced by shutdown_task().

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

◆ multicast_pong()

static void multicast_pong ( void *  cls,
struct GNUNET_TIME_Absolute  valid_until,
struct GNUNET_TIME_Absolute  validation_block,
const struct GNUNET_HELLO_Address address 
)
static

Send the given PONG to the given address.

Parameters
clsthe PONG message
valid_untilis ZERO if we never validated the address, otherwise a time up to when we consider it (or was) valid
validation_blockis FOREVER if the address is for an unsupported plugin (from PEERINFO) is ZERO if the address is considered valid (no validation needed) otherwise a time in the future if we're currently denying re-validation
addresstarget address

Definition at line 1042 of file gnunet-service-transport_validation.c.

1046 {
1047  struct TransportPongMessage *pong = cls;
1048  struct GNUNET_TRANSPORT_PluginFunctions *papi;
1049  struct GNUNET_ATS_Session *session;
1050 
1051  papi = GST_plugins_find (address->transport_name);
1052  if (NULL == papi)
1053  {
1055  "Plugin %s not supported, cannot send PONG\n",
1056  address->transport_name);
1057  return;
1058  }
1059  GNUNET_assert (NULL != papi->send);
1060  GNUNET_assert (NULL != papi->get_session);
1061  session = papi->get_session (papi->cls, address);
1062  if (NULL == session)
1063  {
1064  GNUNET_break (0);
1065  return;
1066  }
1067  GST_ats_new_session (address, session);
1068  papi->send (papi->cls, session,
1069  (const char *) pong,
1070  ntohs (pong->header.size),
1071  PONG_PRIORITY,
1073  NULL, NULL);
1075  session,
1076  pong->header.size);
1077 }
static void pong(struct GNUNET_CADET_Channel *channel, const struct CadetPingMessage *ping)
Reply with a pong to origin.
void GST_ats_new_session(const struct GNUNET_HELLO_Address *address, struct GNUNET_ATS_Session *session)
Notify ATS about a new session now existing for the given address.
#define PONG_PRIORITY
Priority to use for PONGs.
Message used to validate a HELLO.

References ACCEPTABLE_PING_DELAY, address, GNUNET_TRANSPORT_PluginFunctions::cls, GNUNET_TRANSPORT_PluginFunctions::get_session, GNUNET_assert, GNUNET_break, GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GST_ats_new_session(), GST_neighbours_notify_data_sent(), GST_plugins_find(), pong(), PONG_PRIORITY, and GNUNET_TRANSPORT_PluginFunctions::send.

Referenced by GST_validation_handle_ping().

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

◆ GST_validation_handle_ping()

int GST_validation_handle_ping ( const struct GNUNET_PeerIdentity sender,
const struct GNUNET_MessageHeader hdr,
const struct GNUNET_HELLO_Address sender_address,
struct GNUNET_ATS_Session session 
)

We've received a PING.

If appropriate, generate a PONG.

Parameters
senderpeer sending the PING
hdrthe PING
sender_addressthe sender address as we got it
sessionsession we got the PING from
Returns
GNUNET_OK if the message was fine, GNUNET_SYSERR on serious error

Definition at line 1090 of file gnunet-service-transport_validation.c.

1094 {
1095  const struct TransportPingMessage *ping;
1096  struct TransportPongMessage *pong;
1097  struct GNUNET_TRANSPORT_PluginFunctions *papi;
1098  struct GNUNET_CRYPTO_EddsaSignature *sig_cache;
1099  struct GNUNET_TIME_Absolute *sig_cache_exp;
1100  const char *addr;
1101  const char *addrend;
1102  char *plugin_name;
1103  char *pos;
1104  size_t len_address;
1105  size_t len_plugin;
1106  ssize_t ret;
1108 
1109  if (0 ==
1110  memcmp (&GST_my_identity,
1111  sender,
1112  sizeof(struct GNUNET_PeerIdentity)))
1113  return GNUNET_OK; /* our own, ignore! */
1114  if (ntohs (hdr->size) < sizeof(struct TransportPingMessage))
1115  {
1116  GNUNET_break_op (0);
1117  return GNUNET_SYSERR;
1118  }
1119  ping = (const struct TransportPingMessage *) hdr;
1120  if (0 !=
1121  memcmp (&ping->target,
1122  &GST_my_identity,
1123  sizeof(struct GNUNET_PeerIdentity)))
1124  {
1126  gettext_noop
1127  ("# PING message for different peer received"),
1128  1,
1129  GNUNET_NO);
1130  return GNUNET_SYSERR;
1131  }
1133  gettext_noop ("# PING messages received"), 1,
1134  GNUNET_NO);
1135  addr = (const char *) &ping[1];
1136  len_address = ntohs (hdr->size) - sizeof(struct TransportPingMessage);
1137  /* peer wants to confirm that this is one of our addresses, this is what is
1138  * used for address validation */
1139 
1140  sig_cache = NULL;
1141  sig_cache_exp = NULL;
1142  papi = NULL;
1143  if (len_address > 0)
1144  {
1145  addrend = memchr (addr, '\0', len_address);
1146  if (NULL == addrend)
1147  {
1148  GNUNET_break_op (0);
1149  return GNUNET_SYSERR;
1150  }
1151  addrend++;
1152  len_plugin = strlen (addr) + 1;
1153  len_address -= len_plugin;
1155  address.address = addrend;
1156  address.address_length = len_address;
1157  address.transport_name = addr;
1158  address.peer = GST_my_identity;
1159 
1160  if (NULL == address.transport_name)
1161  {
1162  GNUNET_break (0);
1163  }
1164 
1165  if (0 != strstr (address.transport_name, "_client"))
1166  {
1167  plugin_name = GNUNET_strdup (address.transport_name);
1168  pos = strstr (plugin_name, "_client");
1169  GNUNET_assert (NULL != pos);
1170  GNUNET_snprintf (pos, strlen ("_server") + 1, "%s", "_server");
1171  }
1172  else
1173  plugin_name = GNUNET_strdup (address.transport_name);
1174 
1175  if (NULL == (papi = GST_plugins_find (plugin_name)))
1176  {
1177  /* we don't have the plugin for this address */
1179  _ (
1180  "Plugin `%s' not available, cannot confirm having this address\n"),
1181  plugin_name);
1183  return GNUNET_SYSERR;
1184  }
1186  if (GNUNET_OK !=
1187  papi->check_address (papi->cls,
1188  addrend,
1189  len_address))
1190  {
1192  gettext_noop
1193  ("# failed address checks during validation"),
1194  1,
1195  GNUNET_NO);
1197  _ (
1198  "Address `%s' is not one of my addresses, not confirming PING\n"),
1200  return GNUNET_SYSERR;
1201  }
1202  else
1203  {
1205  gettext_noop
1206  (
1207  "# successful address checks during validation"),
1208  1,
1209  GNUNET_NO);
1211  "Address `%s' is one of my addresses, confirming PING\n",
1213  }
1214 
1215  if (GNUNET_YES !=
1217  &sig_cache,
1218  &sig_cache_exp))
1219  {
1221  _ (
1222  "Not confirming PING from peer `%s' with address `%s' since I cannot confirm having this address.\n"),
1223  GNUNET_i2s (sender),
1225  return GNUNET_SYSERR;
1226  }
1227  }
1228  else
1229  {
1230  addrend = NULL; /* make gcc happy */
1231  len_plugin = 0;
1232  static struct GNUNET_CRYPTO_EddsaSignature no_address_signature;
1233  static struct GNUNET_TIME_Absolute no_address_signature_expiration;
1234 
1235  sig_cache = &no_address_signature;
1236  sig_cache_exp = &no_address_signature_expiration;
1237  }
1238 
1240  "I am `%s', sending PONG to peer `%s'\n",
1242  GNUNET_i2s (sender));
1243 
1244  /* message with structure:
1245  * [TransportPongMessage][Transport name][Address] */
1246 
1247  pong = GNUNET_malloc (sizeof(struct TransportPongMessage) + len_address
1248  + len_plugin);
1249  pong->header.size =
1250  htons (sizeof(struct TransportPongMessage) + len_address + len_plugin);
1251  pong->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_PONG);
1252  pong->purpose.size =
1253  htonl (sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose)
1254  + sizeof(uint32_t) + sizeof(struct GNUNET_TIME_AbsoluteNBO)
1255  + len_address + len_plugin);
1256  pong->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_PONG_OWN);
1257  GNUNET_memcpy (&pong->challenge, &ping->challenge, sizeof(ping->challenge));
1258  pong->addrlen = htonl (len_address + len_plugin);
1259  GNUNET_memcpy (&pong[1], addr, len_plugin); /* Copy transport plugin */
1260  if (len_address > 0)
1261  {
1262  GNUNET_assert (NULL != addrend);
1263  GNUNET_memcpy (&((char *) &pong[1])[len_plugin], addrend, len_address);
1264  }
1265  if (GNUNET_TIME_absolute_get_remaining (*sig_cache_exp).rel_value_us <
1266  PONG_SIGNATURE_LIFETIME.rel_value_us / 4)
1267  {
1268  /* create / update cached sig */
1270  "Creating PONG signature to indicate ownership.\n");
1272  pong->expiration = GNUNET_TIME_absolute_hton (*sig_cache_exp);
1273  if (GNUNET_OK !=
1275  &pong->purpose,
1276  sig_cache))
1277  {
1279  _ ("Failed to create PONG signature for peer `%s'\n"),
1280  GNUNET_i2s (sender));
1281  }
1282  }
1283  else
1284  {
1285  pong->expiration = GNUNET_TIME_absolute_hton (*sig_cache_exp);
1286  }
1287  pong->signature = *sig_cache;
1288 
1289  GNUNET_assert (NULL != sender_address);
1290 
1291  /* first see if the session we got this PING from can be used to transmit
1292  * a response reliably */
1293  if (NULL == papi)
1294  {
1295  ret = -1;
1296  }
1297  else
1298  {
1299  GNUNET_assert (NULL != papi->send);
1300  GNUNET_assert (NULL != papi->get_session);
1301  if (NULL == session)
1302  {
1303  session = papi->get_session (papi->cls, sender_address);
1304  }
1305  if (NULL == session)
1306  {
1307  GNUNET_break (0);
1308  ret = -1;
1309  }
1310  else
1311  {
1312  ret = papi->send (papi->cls, session,
1313  (const char *) pong,
1314  ntohs (pong->header.size),
1316  NULL, NULL);
1317  if (-1 != ret)
1318  GST_neighbours_notify_data_sent (sender_address,
1319  session,
1320  pong->header.size);
1321  }
1322  }
1323  if (-1 != ret)
1324  {
1326  "Transmitted PONG to `%s' via reliable mechanism\n",
1327  GNUNET_i2s (sender));
1328  /* done! */
1330  gettext_noop
1331  ("# PONGs unicast via reliable transport"), 1,
1332  GNUNET_NO);
1333  GNUNET_free (pong);
1334  return GNUNET_OK;
1335  }
1336 
1337  /* no reliable method found, try transmission via all known addresses */
1339  gettext_noop
1340  ("# PONGs multicast to all available addresses"),
1341  1,
1342  GNUNET_NO);
1344  &multicast_pong, pong);
1345  GNUNET_free (pong);
1346  return GNUNET_OK;
1347 }
static char * plugin_name
Name of our plugin.
static struct GNUNET_CRYPTO_EddsaPrivateKey * GST_my_private_key
Our private key.
int GST_hello_test_address(const struct GNUNET_HELLO_Address *address, struct GNUNET_CRYPTO_EddsaSignature **sig, struct GNUNET_TIME_Absolute **sig_expiration)
Test if a particular address is one of ours.
static void multicast_pong(void *cls, struct GNUNET_TIME_Absolute valid_until, struct GNUNET_TIME_Absolute validation_block, const struct GNUNET_HELLO_Address *address)
Send the given PONG to the given address.
#define PONG_SIGNATURE_LIFETIME
How long is a PONG signature valid? We'll recycle a signature until 1/4 of this time is remaining.
void GST_validation_get_addresses(const struct GNUNET_PeerIdentity *target, GST_ValidationAddressCallback cb, void *cb_cls)
Call the given function for each address for the given target.
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_eddsa_sign_(const struct GNUNET_CRYPTO_EddsaPrivateKey *priv, const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose, struct GNUNET_CRYPTO_EddsaSignature *sig)
EdDSA sign a given block.
Definition: crypto_ecc.c:599
@ GNUNET_HELLO_ADDRESS_INFO_NONE
No additional information.
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
const char * GNUNET_i2s_full(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
int GNUNET_snprintf(char *buf, size_t size, const char *format,...) __attribute__((format(printf
Like snprintf, just aborts if the buffer is of insufficient size.
#define GNUNET_malloc(size)
Wrapper around malloc.
#define GNUNET_MESSAGE_TYPE_TRANSPORT_PONG
Transport PONG message.
#define GNUNET_SIGNATURE_PURPOSE_TRANSPORT_PONG_OWN
Signature for confirming that this peer uses a particular address.
struct GNUNET_TIME_AbsoluteNBO GNUNET_TIME_absolute_hton(struct GNUNET_TIME_Absolute a)
Convert absolute time to network byte order.
Definition: time.c:464
#define _(String)
GNU gettext support macro.
Definition: platform.h:177
header of what an ECC signature signs this must be followed by "size - 8" bytes of the actual signed ...
An address for communicating with a peer.
Time for absolute time used by GNUnet, in microseconds and in network byte order.
GNUNET_TRANSPORT_CheckAddress check_address
Function that will be called to check if a binary address for this plugin is well-formed and correspo...

References _, ACCEPTABLE_PING_DELAY, address, GNUNET_TRANSPORT_PluginFunctions::check_address, GNUNET_TRANSPORT_PluginFunctions::cls, GNUNET_TRANSPORT_PluginFunctions::get_session, gettext_noop, GNUNET_assert, GNUNET_break, GNUNET_break_op, GNUNET_CRYPTO_eddsa_sign_(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_ERROR, GNUNET_ERROR_TYPE_INFO, GNUNET_free, GNUNET_HELLO_ADDRESS_INFO_NONE, GNUNET_i2s(), GNUNET_i2s_full(), GNUNET_log, GNUNET_malloc, GNUNET_memcpy, GNUNET_MESSAGE_TYPE_TRANSPORT_PONG, GNUNET_NO, GNUNET_OK, GNUNET_SIGNATURE_PURPOSE_TRANSPORT_PONG_OWN, GNUNET_snprintf(), GNUNET_STATISTICS_update(), GNUNET_strdup, GNUNET_SYSERR, GNUNET_TIME_absolute_get_remaining(), GNUNET_TIME_absolute_hton(), GNUNET_TIME_relative_to_absolute(), GNUNET_YES, GST_hello_test_address(), GST_my_identity, GST_my_private_key, GST_neighbours_notify_data_sent(), GST_plugins_a2s(), GST_plugins_find(), GST_stats, GST_validation_get_addresses(), multicast_pong(), ping(), plugin_name, pong(), PONG_PRIORITY, PONG_SIGNATURE_LIFETIME, GNUNET_TIME_Relative::rel_value_us, ret, GNUNET_TRANSPORT_PluginFunctions::send, and GNUNET_MessageHeader::size.

Here is the call graph for this function:

◆ GST_validation_handle_address()

void GST_validation_handle_address ( const struct GNUNET_HELLO_Address address)

Validate an individual address.

Parameters
addressaddress we should try to validate

Definition at line 1356 of file gnunet-service-transport_validation.c.

1357 {
1358  struct GNUNET_TRANSPORT_PluginFunctions *papi;
1359  struct ValidationEntry *ve;
1360 
1361  papi = GST_plugins_find (address->transport_name);
1362  if (NULL == papi)
1363  {
1364  /* This plugin is currently unavailable ... ignore */
1366  "No plugin available for %s\n",
1367  address->transport_name);
1368  return;
1369  }
1371  if (NULL == ve->revalidation_task)
1372  {
1374  "Validation process started for fresh address `%s' of %s\n",
1375  GST_plugins_a2s (ve->address),
1376  GNUNET_i2s (&ve->address->peer));
1378  }
1379  else
1380  {
1382  "Validation already running for address `%s' of %s\n",
1383  GST_plugins_a2s (ve->address),
1384  GNUNET_i2s (&ve->address->peer));
1385  }
1386 }

References address, ValidationEntry::address, find_validation_entry(), GNUNET_ERROR_TYPE_INFO, GNUNET_i2s(), GNUNET_log, GNUNET_SCHEDULER_add_now(), GST_plugins_a2s(), GST_plugins_find(), GNUNET_HELLO_Address::peer, revalidate_address(), and ValidationEntry::revalidation_task.

Referenced by plugin_env_session_start_bl_check_cont(), and validate_address_iterator().

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

◆ validate_address_iterator()

static int validate_address_iterator ( void *  cls,
const struct GNUNET_HELLO_Address address,
struct GNUNET_TIME_Absolute  expiration 
)
static

Iterator callback to go over all addresses and try to validate them (unless blocked or already validated).

Parameters
clsNULL
addressthe address
expirationexpiration time
Returns
GNUNET_OK (keep the address)

Definition at line 1399 of file gnunet-service-transport_validation.c.

1402 {
1403  if (0 == GNUNET_TIME_absolute_get_remaining (expiration).rel_value_us)
1404  {
1406  "Skipping expired address from HELLO\n");
1407  return GNUNET_OK; /* expired */
1408  }
1410  return GNUNET_OK;
1411 }
void GST_validation_handle_address(const struct GNUNET_HELLO_Address *address)
Validate an individual address.

References address, expiration, GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_OK, GNUNET_TIME_absolute_get_remaining(), and GST_validation_handle_address().

Referenced by GST_validation_handle_hello().

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

◆ add_valid_peer_address()

static ssize_t add_valid_peer_address ( void *  cls,
size_t  max,
void *  buf 
)
static

Add the validated peer address to the HELLO.

Parameters
clsthe struct ValidationEntry * with the validated address
maxspace in buf
bufwhere to add the address
Returns
number of bytes written, GNUNET_SYSERR to signal the end of the iteration.

Definition at line 1424 of file gnunet-service-transport_validation.c.

1427 {
1428  struct ValidationEntry *ve = cls;
1429 
1430  if (GNUNET_YES == ve->copied)
1431  return GNUNET_SYSERR; /* Done */
1432  ve->copied = GNUNET_YES;
1433  return GNUNET_HELLO_add_address (ve->address,
1434  ve->valid_until,
1435  buf,
1436  max);
1437 }
static char buf[2048]
size_t GNUNET_HELLO_add_address(const struct GNUNET_HELLO_Address *address, struct GNUNET_TIME_Absolute expiration, char *target, size_t max)
Copy the given address information into the given buffer using the format of HELLOs.
Definition: hello.c:109
int copied
When passing the address in add_valid_peer_address(), did we copy the address to the HELLO yet?

References ValidationEntry::address, buf, ValidationEntry::copied, GNUNET_HELLO_add_address(), GNUNET_SYSERR, GNUNET_YES, max, and ValidationEntry::valid_until.

Referenced by GST_validation_handle_pong().

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

◆ GST_validation_handle_pong()

int GST_validation_handle_pong ( const struct GNUNET_PeerIdentity sender,
const struct GNUNET_MessageHeader hdr 
)

We've received a PONG.

Check if it matches a pending PING and mark the respective address as confirmed.

Parameters
senderpeer sending the PONG
hdrthe PONG
Returns
GNUNET_OK if the message was fine, GNUNET_SYSERR on serious error

Definition at line 1449 of file gnunet-service-transport_validation.c.

1451 {
1452  const struct TransportPongMessage *pong;
1453  struct ValidationEntry *ve;
1454  const char *tname;
1455  const char *addr;
1456  size_t addrlen;
1457  size_t slen;
1458  size_t size;
1459  struct GNUNET_HELLO_Message *hello;
1461  int sig_res;
1462  int do_verify;
1463 
1464  if (0 ==
1465  memcmp (&GST_my_identity,
1466  sender,
1467  sizeof(struct GNUNET_PeerIdentity)))
1468  return GNUNET_OK; /* our own, ignore! */
1469 
1470  if (ntohs (hdr->size) < sizeof(struct TransportPongMessage))
1471  {
1472  GNUNET_break_op (0);
1473  return GNUNET_SYSERR;
1474  }
1476  gettext_noop ("# PONG messages received"), 1,
1477  GNUNET_NO);
1478 
1479  /* message with structure:
1480  * [TransportPongMessage][Transport name][Address] */
1481 
1482  pong = (const struct TransportPongMessage *) hdr;
1483  tname = (const char *) &pong[1];
1484  size = ntohs (hdr->size) - sizeof(struct TransportPongMessage);
1485  addr = memchr (tname, '\0', size);
1486  if (NULL == addr)
1487  {
1488  GNUNET_break_op (0);
1489  return GNUNET_SYSERR;
1490  }
1491  addr++;
1492  slen = strlen (tname) + 1;
1493  addrlen = size - slen;
1494 
1495  if (NULL == GST_plugins_find (tname))
1496  {
1497  /* we got the PONG, but the transport plugin specified in it
1498  is not supported by this peer, so this cannot be a good
1499  PONG for us. */
1500  GNUNET_break_op (0);
1501  return GNUNET_OK;
1502  }
1503 
1504  address.peer = *sender;
1505  address.address = addr;
1506  address.address_length = addrlen;
1507  address.transport_name = tname;
1510  if ((NULL == ve) || (GNUNET_NO == ve->expecting_pong))
1511  {
1513  gettext_noop
1514  (
1515  "# PONGs dropped, no matching pending validation"),
1516  1, GNUNET_NO);
1517  return GNUNET_OK;
1518  }
1519  /* now check that PONG is well-formed */
1520  if (0 != memcmp (&ve->address->peer,
1521  sender,
1522  sizeof(struct GNUNET_PeerIdentity)))
1523  {
1524  GNUNET_break_op (0);
1525  return GNUNET_SYSERR;
1526  }
1527  if (0 ==
1530  {
1532  gettext_noop
1533  ("# PONGs dropped, signature expired"), 1,
1534  GNUNET_NO);
1535  return GNUNET_SYSERR;
1536  }
1537 
1538  sig_res = GNUNET_SYSERR;
1539  do_verify = GNUNET_YES;
1542  {
1543  /* We have a cached and valid signature for this peer,
1544  * try to compare instead of verify */
1545  if (0 == memcmp (&ve->pong_sig_cache,
1546  &pong->signature,
1547  sizeof(struct GNUNET_CRYPTO_EddsaSignature)))
1548  {
1549  /* signatures are identical, we can skip verification */
1550  sig_res = GNUNET_OK;
1551  do_verify = GNUNET_NO;
1552  }
1553  else
1554  {
1555  sig_res = GNUNET_SYSERR;
1556  /* signatures do not match, we have to verify */
1557  }
1558  }
1559 
1560  if (GNUNET_YES == do_verify)
1561  {
1562  /* Do expensive verification */
1563  sig_res = GNUNET_CRYPTO_eddsa_verify_ (
1565  &pong->purpose,
1566  &pong->signature,
1567  &ve->address->peer.public_key);
1568  if (sig_res == GNUNET_SYSERR)
1569  {
1570  GNUNET_break_op (0);
1572  "Failed to verify: invalid signature on address `%s':%s from peer `%s'\n",
1573  tname,
1574  GST_plugins_a2s (ve->address),
1575  GNUNET_i2s (sender));
1576  }
1577  }
1578  if (sig_res == GNUNET_SYSERR)
1579  {
1580  GNUNET_break_op (0);
1581  return GNUNET_SYSERR;
1582  }
1583 
1585  "Validation process successful for peer `%s' with plugin `%s' address `%s'\n",
1586  GNUNET_i2s (sender),
1587  tname,
1588  GST_plugins_a2s (ve->address));
1590  gettext_noop ("# validations succeeded"),
1591  1,
1592  GNUNET_NO);
1593  /* validity achieved, remember it! */
1594  ve->expecting_pong = GNUNET_NO;
1596  ve->pong_sig_cache = pong->signature;
1599  {
1600  if (GNUNET_YES == ve->known_to_ats)
1601  {
1606  }
1607  else
1608  {
1609  struct GNUNET_ATS_Properties prop;
1610 
1611  memset (&prop, 0, sizeof(prop));
1613  prop.scope = ve->network;
1614  prop.delay = GNUNET_TIME_relative_divide (ve->latency, 2);
1617  ve->known_to_ats = GNUNET_YES;
1618  GST_ats_add_address (ve->address, &prop);
1621  }
1622  }
1623  if (validations_running > 0)
1624  {
1627  gettext_noop ("# validations running"),
1629  GNUNET_NO);
1631  "Validation finished, %u validation processes running\n",
1633  }
1634  else
1635  {
1636  GNUNET_break (0);
1637  }
1638 
1639  /* Notify about new validity */
1642 
1643  /* build HELLO to store in PEERINFO */
1645  gettext_noop ("# HELLOs given to peerinfo"),
1646  1,
1647  GNUNET_NO);
1648  ve->copied = GNUNET_NO;
1649  hello = GNUNET_HELLO_create (&ve->address->peer.public_key,
1651  ve,
1652  GNUNET_NO);
1653  GNUNET_break (NULL !=
1655  hello,
1656  NULL,
1657  NULL));
1658  GNUNET_free (hello);
1659  return GNUNET_OK;
1660 }
struct GNUNET_PEERINFO_Handle * GST_peerinfo
Handle to peerinfo service.
void GST_ats_update_delay(const struct GNUNET_HELLO_Address *address, struct GNUNET_TIME_Relative delay)
Notify ATS about delay changes to properties of an address.
static ssize_t add_valid_peer_address(void *cls, size_t max, void *buf)
Add the validated peer address to the HELLO.
#define HELLO_ADDRESS_EXPIRATION
After how long do we expire an address in a HELLO that we just validated? This value is also used for...
int GNUNET_CRYPTO_eddsa_verify_(uint32_t purpose, const struct GNUNET_CRYPTO_EccSignaturePurpose *validate, const struct GNUNET_CRYPTO_EddsaSignature *sig, const struct GNUNET_CRYPTO_EddsaPublicKey *pub)
Verify EdDSA signature.
Definition: crypto_ecc.c:682
struct GNUNET_HELLO_Message * GNUNET_HELLO_create(const struct GNUNET_CRYPTO_EddsaPublicKey *public_key, GNUNET_HELLO_GenerateAddressListCallback addrgen, void *addrgen_cls, int friend_only)
Construct a HELLO message given the public key, expiration time and an iterator that spews the transp...
Definition: hello.c:204
@ GNUNET_ERROR_TYPE_WARNING
struct GNUNET_MQ_Envelope * GNUNET_PEERINFO_add_peer(struct GNUNET_PEERINFO_Handle *h, const struct GNUNET_HELLO_Message *hello, GNUNET_SCHEDULER_TaskCallback cont, void *cont_cls)
Add a host to the persistent list.
Definition: peerinfo_api.c:553
struct GNUNET_TIME_Relative GNUNET_TIME_absolute_get_duration(struct GNUNET_TIME_Absolute whence)
Get the duration of an operation as the difference of the current time and the given start time "henc...
Definition: time.c:263
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_ntoh(struct GNUNET_TIME_AbsoluteNBO a)
Convert absolute time from network byte order.
Definition: time.c:542
static unsigned int size
Size of the "table".
Definition: peer.c:67
struct GNUNET_CRYPTO_EddsaPublicKey public_key
uint32_t addrlen
Size of address appended to this message (part of what is being signed, hence not redundant).

References add_valid_peer_address(), address, ValidationEntry::address, TransportPongMessage::addrlen, ValidationEntry::copied, GNUNET_ATS_Properties::delay, ValidationEntry::expecting_pong, find_validation_entry(), gettext_noop, GNUNET_assert, GNUNET_break, GNUNET_break_op, GNUNET_CRYPTO_eddsa_verify_(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_INFO, GNUNET_ERROR_TYPE_WARNING, GNUNET_free, GNUNET_HELLO_ADDRESS_INFO_NONE, GNUNET_HELLO_create(), GNUNET_i2s(), GNUNET_log, GNUNET_NO, GNUNET_NT_UNSPECIFIED, GNUNET_OK, GNUNET_PEERINFO_add_peer(), GNUNET_SIGNATURE_PURPOSE_TRANSPORT_PONG_OWN, GNUNET_STATISTICS_set(), GNUNET_STATISTICS_update(), GNUNET_SYSERR, GNUNET_TIME_absolute_get_duration(), GNUNET_TIME_absolute_get_remaining(), GNUNET_TIME_absolute_ntoh(), GNUNET_TIME_relative_divide(), GNUNET_TIME_relative_to_absolute(), GNUNET_TRANSPORT_VS_UPDATE, GNUNET_YES, GST_ats_add_address(), GST_ats_is_known_no_session(), GST_ats_update_delay(), GST_my_identity, GST_peerinfo, GST_plugins_a2s(), GST_plugins_find(), GST_stats, HELLO_ADDRESS_EXPIRATION, ValidationEntry::known_to_ats, ValidationEntry::latency, ValidationEntry::network, GNUNET_HELLO_Address::peer, pong(), ValidationEntry::pong_sig_cache, ValidationEntry::pong_sig_valid_until, GNUNET_PeerIdentity::public_key, GNUNET_TIME_Relative::rel_value_us, GNUNET_ATS_Properties::scope, ValidationEntry::send_time, GNUNET_MessageHeader::size, size, ValidationEntry::valid_until, validation_entry_changed(), and validations_running.

Here is the call graph for this function:

◆ GST_validation_handle_hello()

int GST_validation_handle_hello ( const struct GNUNET_MessageHeader hello)

We've received a HELLO, check which addresses are new and trigger validation.

Parameters
hellothe HELLO we received
Returns
GNUNET_OK if the message was fine, GNUNET_SYSERR on serious error

Definition at line 1671 of file gnunet-service-transport_validation.c.

1672 {
1673  const struct GNUNET_HELLO_Message *hm =
1674  (const struct GNUNET_HELLO_Message *) hello;
1675  struct GNUNET_PeerIdentity pid;
1676  int friend;
1677 
1678  friend = GNUNET_HELLO_is_friend_only (hm);
1679  if (((GNUNET_YES != friend) &&
1680  (GNUNET_NO != friend)) ||
1681  (GNUNET_OK != GNUNET_HELLO_get_id (hm, &pid)))
1682  {
1683  /* malformed HELLO */
1684  GNUNET_break_op (0);
1685  return GNUNET_SYSERR;
1686  }
1687  if (0 ==
1688  memcmp (&GST_my_identity,
1689  &pid,
1690  sizeof(struct GNUNET_PeerIdentity)))
1691  {
1692  /* got our own HELLO, how boring */
1694  "Validation received our own HELLO (%s), ignoring\n",
1695  GNUNET_i2s (&pid));
1696  return GNUNET_OK;
1697  }
1699  "Validation received HELLO message for peer `%s' with size %u, checking for new addresses\n",
1700  GNUNET_i2s (&pid),
1701  ntohs (hello->size));
1702  GNUNET_assert (NULL ==
1704  GNUNET_NO,
1706  NULL));
1707  return GNUNET_OK;
1708 }
static int validate_address_iterator(void *cls, const struct GNUNET_HELLO_Address *address, struct GNUNET_TIME_Absolute expiration)
Iterator callback to go over all addresses and try to validate them (unless blocked or already valida...
int GNUNET_HELLO_is_friend_only(const struct GNUNET_HELLO_Message *h)
Return HELLO type.
Definition: hello.c:89

References GNUNET_assert, GNUNET_break_op, GNUNET_ERROR_TYPE_DEBUG, GNUNET_HELLO_get_id(), GNUNET_HELLO_is_friend_only(), GNUNET_HELLO_iterate_addresses(), GNUNET_i2s(), GNUNET_log, GNUNET_NO, GNUNET_OK, GNUNET_SYSERR, GNUNET_YES, GST_my_identity, pid, GNUNET_MessageHeader::size, and validate_address_iterator().

Referenced by handle_client_hello().

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

◆ iterate_addresses()

static int iterate_addresses ( void *  cls,
const struct GNUNET_PeerIdentity key,
void *  value 
)
static

Call the callback in the closure for each validation entry.

Parameters
clsthe struct IteratorContext
keythe peer's identity
valuethe struct ValidationEntry
Returns
GNUNET_OK (continue to iterate)

Definition at line 1737 of file gnunet-service-transport_validation.c.

1740 {
1741  struct IteratorContext *ic = cls;
1742  struct ValidationEntry *ve = value;
1743 
1744  ic->cb (ic->cb_cls,
1745  ve->valid_until,
1746  ve->revalidation_block,
1747  ve->address);
1748  return GNUNET_OK;
1749 }
Closure for the neighbours_iterate() function.
GST_NeighbourIterator cb
Function to call on each connected neighbour.

References ValidationEntry::address, IteratorContext::cb, IteratorContext::cb_cls, GNUNET_OK, ValidationEntry::revalidation_block, ValidationEntry::valid_until, and value.

Referenced by GST_validation_get_addresses().

Here is the caller graph for this function:

◆ GST_validation_get_addresses()

void GST_validation_get_addresses ( const struct GNUNET_PeerIdentity target,
GST_ValidationAddressCallback  cb,
void *  cb_cls 
)

Call the given function for each address for the given target.

Can either give a snapshot (synchronous API) or be continuous.

Parameters
targetpeer information is requested for
cbfunction to call; will not be called after this function returns
cb_clsclosure for cb

Definition at line 1761 of file gnunet-service-transport_validation.c.

1764 {
1765  struct IteratorContext ic;
1766 
1767  ic.cb = cb;
1768  ic.cb_cls = cb_cls;
1770  target,
1771  &iterate_addresses, &ic);
1772 }
static int iterate_addresses(void *cls, const struct GNUNET_PeerIdentity *key, void *value)
Call the callback in the closure for each validation entry.

References IteratorContext::cb, IteratorContext::cb_cls, GNUNET_CONTAINER_multipeermap_get_multiple(), iterate_addresses(), and validation_map.

Referenced by GST_validation_handle_ping().

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

◆ GST_validation_set_address_use()

void GST_validation_set_address_use ( const struct GNUNET_HELLO_Address address,
int  in_use 
)

Update if we are using an address for a connection actively right now.

Based on this, the validation module will measure latency for the address more or less often.

Parameters
addressthe address that we are now using (or not)
in_useGNUNET_YES if we are now using the address for a connection, GNUNET_NO if we are no longer using the address for a connection

Definition at line 1785 of file gnunet-service-transport_validation.c.

1787 {
1788  struct ValidationEntry *ve;
1789 
1792  return; /* ignore inbound for validation */
1793  if (NULL == GST_plugins_find (address->transport_name))
1794  {
1795  /* How can we use an address for which we don't have the plugin? */
1796  GNUNET_break (0);
1797  return;
1798  }
1800  if (NULL == ve)
1801  {
1802  GNUNET_break (0);
1803  return;
1804  }
1805  if (in_use == ve->in_use)
1806  return;
1807  ve->in_use = in_use;
1808  if (GNUNET_YES == in_use)
1809  {
1810  /* from now on, higher frequency, so reschedule now */
1811  if (NULL != ve->revalidation_task)
1814  ve);
1815  }
1816 }
int GNUNET_HELLO_address_check_option(const struct GNUNET_HELLO_Address *address, enum GNUNET_HELLO_AddressInfo option)
Check if an address has a local option set.
Definition: address.c:39
@ GNUNET_HELLO_ADDRESS_INFO_INBOUND
This is an inbound address and cannot be used to initiate an outbound connection to another peer.

Referenced by free_address(), and set_primary_address().

Here is the caller graph for this function:

Variable Documentation

◆ validation_map

struct GNUNET_CONTAINER_MultiPeerMap* validation_map
static

Map of PeerIdentities to 'struct ValidationEntry*'s (addresses of the given peer that we are currently validating, have validated or are blocked from re-validation for a while).

Definition at line 330 of file gnunet-service-transport_validation.c.

Referenced by cleanup_validation_entry(), find_validation_entry(), GST_validation_get_addresses(), GST_validation_start(), GST_validation_stop(), and publish_ve_stat_update().

◆ pnc

struct GNUNET_PEERINFO_NotifyContext* pnc
static

Context for peerinfo iteration.

Definition at line 335 of file gnunet-service-transport_validation.c.

Referenced by GST_validation_start(), and GST_validation_stop().

◆ validation_delay

struct GNUNET_TIME_Relative validation_delay
static

Minimum delay between to validations.

Definition at line 335 of file gnunet-service-transport_validation.c.

Referenced by GST_validation_start(), and transmit_ping_if_allowed().

◆ validations_running

unsigned int validations_running
static

Number of validations running; any PING that was not yet matched by a PONG and for which we have not yet hit the timeout is considered a running 'validation'.

Definition at line 347 of file gnunet-service-transport_validation.c.

Referenced by cleanup_validation_entry(), GST_validation_handle_pong(), GST_validation_start(), revalidate_address(), and transmit_ping_if_allowed().

◆ validations_fast_start_threshold

unsigned int validations_fast_start_threshold
static

Validition fast start threshold.

Definition at line 352 of file gnunet-service-transport_validation.c.

Referenced by GST_validation_start(), and revalidate_address().

◆ validation_next

struct GNUNET_TIME_Absolute validation_next
static

When is next validation allowed.

Definition at line 352 of file gnunet-service-transport_validation.c.

Referenced by GST_validation_start(), revalidate_address(), and transmit_ping_if_allowed().