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

network address translation traversal service More...

#include "platform.h"
#include <math.h>
#include "gnunet_util_lib.h"
#include "gnunet_protocols.h"
#include "gnunet_signatures.h"
#include "gnunet_statistics_service.h"
#include "gnunet_resolver_service.h"
#include "gnunet_nat_service.h"
#include "gnunet-service-nat.h"
#include "gnunet-service-nat_externalip.h"
#include "gnunet-service-nat_stun.h"
#include "gnunet-service-nat_mini.h"
#include "gnunet-service-nat_helper.h"
#include "nat.h"
#include <gcrypt.h>
Include dependency graph for gnunet-service-nat.c:

Go to the source code of this file.

Data Structures

struct  ClientAddress
 Information we track per client address. More...
 
struct  LocalAddressList
 List of local addresses this system has. More...
 
struct  ClientHandle
 Struct containing information about a client, handle to connect to it, and any pending messages that need to be sent to it. More...
 
struct  StunExternalIP
 External IP address as given to us via some STUN server. More...
 
struct  IfcProcContext
 Closure for ifc_proc. More...
 

Macros

#define SCAN_FREQ   GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 15)
 How often should we ask the OS about a list of active network interfaces? More...
 
#define AUTOCONFIG_TIMEOUT
 How long do we wait until we forcefully terminate autoconfiguration? More...
 
#define DYNDNS_FREQUENCY
 How often do we scan for changes in how our external (dyndns) hostname resolves? More...
 

Functions

static void free_lal (struct LocalAddressList *lal)
 Remove and free an entry from the lal_head DLL. More...
 
static void destroy_lal ()
 Free the DLL starting at lal_head. More...
 
static int check_register (void *cls, const struct GNUNET_NAT_RegisterMessage *message)
 Check validity of GNUNET_MESSAGE_TYPE_NAT_REGISTER message from client. More...
 
static int match_ipv4 (const char *network, const struct in_addr *ip, uint8_t bits)
 Check if ip is in network with bits netmask. More...
 
static int match_ipv6 (const char *network, const struct in6_addr *ip, uint8_t bits)
 Check if ip is in network with bits netmask. More...
 
static int is_nat_v4 (const struct in_addr *ip)
 Test if the given IPv4 address is in a known range for private networks. More...
 
static int is_nat_v6 (const struct in6_addr *ip)
 Test if the given IPv6 address is in a known range for private networks. More...
 
static int ifc_proc (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 notify_client (enum GNUNET_NAT_AddressClass ac, struct ClientHandle *ch, int add, const void *addr, size_t addr_len)
 Notify client about a change in the list of addresses this peer has. More...
 
static void check_notify_client (struct LocalAddressList *delta, struct ClientHandle *ch, int add)
 Check if we should bother to notify this client about this address change, and if so, do it. More...
 
static void notify_clients (struct LocalAddressList *delta, int add)
 Notify all clients about a change in the list of addresses this peer has. More...
 
static void notify_client_external_ipv4_change (void *cls, const struct in_addr *v4, int add)
 Tell relevant client about a change in our external IPv4 address. More...
 
static void reversal_callback (void *cls, const struct sockaddr_in *ra)
 We got a connection reversal request from another peer. More...
 
static void run_scan (void *cls)
 Task we run periodically to scan for network interfaces. More...
 
static void upnp_addr_change_cb (void *cls, int add_remove, const struct sockaddr *addr, socklen_t addrlen, enum GNUNET_NAT_StatusCode result)
 Function called whenever our set of external addresses as created by upnpc changes. More...
 
static void dyndns_lookup (void *cls)
 Resolve the hole_external name to figure out our external address from a manually punched hole. More...
 
static void process_external_ip (void *cls, const struct sockaddr *addr, socklen_t addrlen)
 Our (external) hostname was resolved. More...
 
static void lookup_hole_external (struct ClientHandle *ch)
 Resolve the hole_external name to figure out our external address from a manually punched hole. More...
 
static void handle_register (void *cls, const struct GNUNET_NAT_RegisterMessage *message)
 Handler for GNUNET_MESSAGE_TYPE_NAT_REGISTER message from client. More...
 
static int check_stun (void *cls, const struct GNUNET_NAT_HandleStunMessage *message)
 Check validity of GNUNET_MESSAGE_TYPE_NAT_HANDLE_STUN message from client. More...
 
static void notify_clients_stun_change (const struct sockaddr_in *ip, int add)
 Notify all clients about our external IP address as reported by the STUN server. More...
 
static void stun_ip_timeout (void *cls)
 Function to be called when we decide that an external IP address as told to us by a STUN server has gone stale. More...
 
static void handle_stun (void *cls, const struct GNUNET_NAT_HandleStunMessage *message)
 Handler for GNUNET_MESSAGE_TYPE_NAT_HANDLE_STUN message from client. More...
 
static int check_request_connection_reversal (void *cls, const struct GNUNET_NAT_RequestConnectionReversalMessage *message)
 Check validity of GNUNET_MESSAGE_TYPE_NAT_REQUEST_CONNECTION_REVERSAL message from client. More...
 
static void handle_request_connection_reversal (void *cls, const struct GNUNET_NAT_RequestConnectionReversalMessage *message)
 Handler for GNUNET_MESSAGE_TYPE_NAT_REQUEST_CONNECTION_REVERSAL message from client. More...
 
static void shutdown_task (void *cls)
 Task run during shutdown. More...
 
static void run (void *cls, const struct GNUNET_CONFIGURATION_Handle *c, struct GNUNET_SERVICE_Handle *service)
 Setup NAT service. More...
 
static void * client_connect_cb (void *cls, struct GNUNET_SERVICE_Client *c, struct GNUNET_MQ_Handle *mq)
 Callback called when a client connects to the service. More...
 
static void client_disconnect_cb (void *cls, struct GNUNET_SERVICE_Client *c, void *internal_cls)
 Callback called when a client disconnected from the service. More...
 
 GNUNET_SERVICE_MAIN ("nat", GNUNET_SERVICE_OPTION_NONE, &run, &client_connect_cb, &client_disconnect_cb, NULL, GNUNET_MQ_hd_var_size(register, GNUNET_MESSAGE_TYPE_NAT_REGISTER, struct GNUNET_NAT_RegisterMessage, NULL), GNUNET_MQ_hd_var_size(stun, GNUNET_MESSAGE_TYPE_NAT_HANDLE_STUN, struct GNUNET_NAT_HandleStunMessage, NULL), GNUNET_MQ_hd_var_size(request_connection_reversal, GNUNET_MESSAGE_TYPE_NAT_REQUEST_CONNECTION_REVERSAL, struct GNUNET_NAT_RequestConnectionReversalMessage, NULL), GNUNET_MQ_handler_end())
 Define "main" method using service macro. More...
 

Variables

static struct GNUNET_TIME_Relative stun_stale_timeout
 Timeout to use when STUN data is considered stale. More...
 
static struct GNUNET_TIME_Relative dyndns_frequency
 How often do we scan for changes in how our external (dyndns) hostname resolves? More...
 
static const struct GNUNET_CONFIGURATION_Handlecfg
 Handle to our current configuration. More...
 
static struct GNUNET_STATISTICS_Handlestats
 Handle to the statistics service. More...
 
static struct GNUNET_SCHEDULER_Taskscan_task
 Task scheduled to periodically scan our network interfaces. More...
 
static struct ClientHandlech_head
 Head of client DLL. More...
 
static struct ClientHandlech_tail
 Tail of client DLL. More...
 
static struct LocalAddressListlal_head
 Head of DLL of local addresses. More...
 
static struct LocalAddressListlal_tail
 Tail of DLL of local addresses. More...
 
static struct StunExternalIPse_head
 Kept in a DLL. More...
 
static struct StunExternalIPse_tail
 Kept in a DLL. More...
 
int enable_upnp
 Is UPnP enabled? GNUNET_YES if enabled, GNUNET_NO if disabled, GNUNET_SYSERR if configuration enabled but binary is unavailable. More...
 
int enable_ipscan
 Is IP Scanning enabled? GNUNET_YES if enabled, GNUNET_NO if disabled, without, only explicitly specified IPs will be handled (HOLE_EXTERNAL) More...
 

Detailed Description

network address translation traversal service

Author
Christian Grothoff

The purpose of this service is to enable transports to traverse NAT routers, by providing traversal options and knowledge about the local network topology.

TODO:

Definition in file gnunet-service-nat.c.

Macro Definition Documentation

◆ SCAN_FREQ

How often should we ask the OS about a list of active network interfaces?

Definition at line 58 of file gnunet-service-nat.c.

Referenced by run_scan().

◆ AUTOCONFIG_TIMEOUT

#define AUTOCONFIG_TIMEOUT
Value:
#define GNUNET_TIME_UNIT_SECONDS
One second.
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:442

How long do we wait until we forcefully terminate autoconfiguration?

Definition at line 63 of file gnunet-service-nat.c.

◆ DYNDNS_FREQUENCY

#define DYNDNS_FREQUENCY
Value:
#define GNUNET_TIME_UNIT_MINUTES
One minute.
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:442

How often do we scan for changes in how our external (dyndns) hostname resolves?

Definition at line 69 of file gnunet-service-nat.c.

Referenced by run().

Function Documentation

◆ free_lal()

static void free_lal ( struct LocalAddressList lal)
static

Remove and free an entry from the lal_head DLL.

Parameters
lalentry to free

Definition at line 350 of file gnunet-service-nat.c.

References LocalAddressList::addr, GN_stop_gnunet_nat_server_(), GNUNET_a2s(), GNUNET_CONTAINER_DLL_remove, GNUNET_ERROR_TYPE_MESSAGE, GNUNET_free, GNUNET_log, and LocalAddressList::hc.

Referenced by destroy_lal(), and run_scan().

351 {
353  lal_tail,
354  lal);
355  if (NULL != lal->hc)
356  {
358  "Lost NATed local address %s, stopping NAT server\n",
359  GNUNET_a2s ((const struct sockaddr *) &lal->addr,
360  sizeof(struct sockaddr_in)));
361 
363  lal->hc = NULL;
364  }
365  GNUNET_free (lal);
366 }
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
static struct LocalAddressList * lal_tail
Tail of DLL of local addresses.
void GN_stop_gnunet_nat_server_(struct HelperContext *h)
Start the gnunet-helper-nat-server and process incoming requests.
struct sockaddr_storage addr
The address itself (i.e.
const char * GNUNET_a2s(const struct sockaddr *addr, socklen_t addrlen)
Convert a "struct sockaddr*" (IPv4 or IPv6 address) to a string (for printing debug messages)...
#define GNUNET_log(kind,...)
struct HelperContext * hc
Context for a gnunet-helper-nat-server used to listen for ICMP messages to this client for connection...
static struct LocalAddressList * lal_head
Head of DLL of local addresses.
#define GNUNET_free(ptr)
Wrapper around free.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ destroy_lal()

static void destroy_lal ( )
static

Free the DLL starting at lal_head.

Definition at line 373 of file gnunet-service-nat.c.

References free_lal().

Referenced by shutdown_task().

374 {
375  struct LocalAddressList *lal;
376 
377  while (NULL != (lal = lal_head))
378  free_lal (lal);
379 }
static void free_lal(struct LocalAddressList *lal)
Remove and free an entry from the lal_head DLL.
List of local addresses this system has.
static struct LocalAddressList * lal_head
Head of DLL of local addresses.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ check_register()

static int check_register ( void *  cls,
const struct GNUNET_NAT_RegisterMessage message 
)
static

Check validity of GNUNET_MESSAGE_TYPE_NAT_REGISTER message from client.

Parameters
clsclient who sent the message
messagethe message received
Returns
GNUNET_OK if message is well-formed

Definition at line 391 of file gnunet-service-nat.c.

References GNUNET_break, GNUNET_OK, GNUNET_SYSERR, GNUNET_NAT_RegisterMessage::header, GNUNET_NAT_RegisterMessage::num_addrs, GNUNET_MessageHeader::size, and GNUNET_NAT_RegisterMessage::str_len.

393 {
394  uint16_t num_addrs = ntohs (message->num_addrs);
395  const char *off = (const char *) &message[1];
396  size_t left = ntohs (message->header.size) - sizeof(*message);
397 
398  for (unsigned int i = 0; i < num_addrs; i++)
399  {
400  size_t alen;
401  const struct sockaddr *sa = (const struct sockaddr *) off;
402 
403  if (sizeof(sa_family_t) > left)
404  {
405  GNUNET_break (0);
406  return GNUNET_SYSERR;
407  }
408  switch (sa->sa_family)
409  {
410  case AF_INET:
411  alen = sizeof(struct sockaddr_in);
412  break;
413 
414  case AF_INET6:
415  alen = sizeof(struct sockaddr_in6);
416  break;
417 
418 #if AF_UNIX
419  case AF_UNIX:
420  alen = sizeof(struct sockaddr_un);
421  break;
422 #endif
423  default:
424  GNUNET_break (0);
425  return GNUNET_SYSERR;
426  }
427  if (alen > left)
428  {
429  GNUNET_break (0);
430  return GNUNET_SYSERR;
431  }
432  off += alen;
433  left -= alen;
434  }
435  if (left != ntohs (message->str_len))
436  {
437  GNUNET_break (0);
438  return GNUNET_SYSERR;
439  }
440  return GNUNET_OK;
441 }
uint16_t str_len
Number of bytes in the string that follow which specifies a section name in the configuration.
Definition: nat.h:115
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format...
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
uint16_t num_addrs
Number of addresses that this service is bound to that follow.
Definition: nat.h:122
#define GNUNET_SYSERR
Definition: gnunet_common.h:76
struct GNUNET_MessageHeader header
Header with type GNUNET_MESSAGE_TYPE_NAT_REGISTER.
Definition: nat.h:99

◆ match_ipv4()

static int match_ipv4 ( const char *  network,
const struct in_addr *  ip,
uint8_t  bits 
)
static

Check if ip is in network with bits netmask.

Parameters
networkto test
ipIP address to test
bitsbitmask for the network
Returns
GNUNET_YES if ip is in network

Definition at line 453 of file gnunet-service-nat.c.

References GNUNET_assert, and GNUNET_YES.

Referenced by check_notify_client(), ifc_proc(), and is_nat_v4().

456 {
457  struct in_addr net;
458 
459  if (0 == ip->s_addr)
460  return GNUNET_YES;
461  if (0 == bits)
462  return GNUNET_YES;
463  GNUNET_assert (1 == inet_pton (AF_INET,
464  network,
465  &net));
466  return ! ((ip->s_addr ^ net.s_addr) & htonl (0xFFFFFFFFu << (32 - bits)));
467 }
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_YES
Definition: gnunet_common.h:77
Here is the caller graph for this function:

◆ match_ipv6()

static int match_ipv6 ( const char *  network,
const struct in6_addr *  ip,
uint8_t  bits 
)
static

Check if ip is in network with bits netmask.

Parameters
networkto test
ipIP address to test
bitsbitmask for the network
Returns
GNUNET_YES if ip is in network

Definition at line 479 of file gnunet-service-nat.c.

References GNUNET_assert, GNUNET_memcmp, GNUNET_NO, and GNUNET_YES.

Referenced by check_notify_client(), ifc_proc(), and is_nat_v6().

482 {
483  struct in6_addr net;
484  struct in6_addr mask;
485  unsigned int off;
486 
487  if (0 == bits)
488  return GNUNET_YES;
489  GNUNET_assert (1 == inet_pton (AF_INET6,
490  network,
491  &net));
492  memset (&mask, 0, sizeof(mask));
493  if (0 == GNUNET_memcmp (&mask,
494  ip))
495  return GNUNET_YES;
496  off = 0;
497  while (bits > 8)
498  {
499  mask.s6_addr[off++] = 0xFF;
500  bits -= 8;
501  }
502  while (bits > 0)
503  {
504  mask.s6_addr[off] = (mask.s6_addr[off] >> 1) + 0x80;
505  bits--;
506  }
507  for (unsigned j = 0; j < sizeof(struct in6_addr) / sizeof(uint32_t); j++)
508  if (((((uint32_t *) ip)[j] & ((uint32_t *) &mask)[j])) !=
509  (((uint32_t *) &net)[j] & ((int *) &mask)[j]))
510  return GNUNET_NO;
511  return GNUNET_YES;
512 }
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_NO
Definition: gnunet_common.h:78
#define GNUNET_memcmp(a, b)
Compare memory in a and b, where both must be of the same pointer type.
#define GNUNET_YES
Definition: gnunet_common.h:77
Here is the caller graph for this function:

◆ is_nat_v4()

static int is_nat_v4 ( const struct in_addr *  ip)
static

Test if the given IPv4 address is in a known range for private networks.

Parameters
ipaddress to test
Returns
GNUNET_YES if ip is in a NAT range

Definition at line 523 of file gnunet-service-nat.c.

References match_ipv4().

Referenced by check_notify_client(), handle_register(), ifc_proc(), notify_client_external_ipv4_change(), and upnp_addr_change_cb().

524 {
525  return
526  match_ipv4 ("10.0.0.0", ip, 8) || /* RFC 1918 */
527  match_ipv4 ("100.64.0.0", ip, 10) || /* CG-NAT, RFC 6598 */
528  match_ipv4 ("192.168.0.0", ip, 12) || /* RFC 1918 */
529  match_ipv4 ("169.254.0.0", ip, 16) || /* AUTO, RFC 3927 */
530  match_ipv4 ("172.16.0.0", ip, 16); /* RFC 1918 */
531 }
static int match_ipv4(const char *network, const struct in_addr *ip, uint8_t bits)
Check if ip is in network with bits netmask.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ is_nat_v6()

static int is_nat_v6 ( const struct in6_addr *  ip)
static

Test if the given IPv6 address is in a known range for private networks.

Parameters
ipaddress to test
Returns
GNUNET_YES if ip is in a NAT range

Definition at line 542 of file gnunet-service-nat.c.

References match_ipv6().

Referenced by check_notify_client(), handle_register(), ifc_proc(), and upnp_addr_change_cb().

543 {
544  return
545  match_ipv6 ("fc00::", ip, 7) || /* RFC 4193 */
546  match_ipv6 ("fec0::", ip, 10) || /* RFC 3879 */
547  match_ipv6 ("fe80::", ip, 10); /* RFC 4291, link-local */
548 }
static int match_ipv6(const char *network, const struct in6_addr *ip, uint8_t bits)
Check if ip is in network with bits netmask.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ ifc_proc()

static int ifc_proc ( 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.

Adds them to our new address list.

Parameters
clsa struct IfcProcContext *
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 582 of file gnunet-service-nat.c.

References LocalAddressList::ac, ac, LocalAddressList::addr, LocalAddressList::af, GNUNET_break, GNUNET_CONTAINER_DLL_insert, GNUNET_malloc, GNUNET_memcpy, GNUNET_NAT_AC_GLOBAL, GNUNET_NAT_AC_LAN, GNUNET_NAT_AC_LOOPBACK, GNUNET_NAT_AC_PRIVATE, GNUNET_OK, is_nat_v4(), is_nat_v6(), IfcProcContext::lal_head, IfcProcContext::lal_tail, match_ipv4(), and match_ipv6().

Referenced by run_scan().

589 {
590  struct IfcProcContext *ifc_ctx = cls;
591  struct LocalAddressList *lal;
592  size_t alen;
593  const struct in_addr *ip4;
594  const struct in6_addr *ip6;
596 
597  switch (addr->sa_family)
598  {
599  case AF_INET:
600  alen = sizeof(struct sockaddr_in);
601  ip4 = &((const struct sockaddr_in *) addr)->sin_addr;
602  if (match_ipv4 ("127.0.0.0", ip4, 8))
604  else if (is_nat_v4 (ip4))
605  ac = GNUNET_NAT_AC_LAN;
606  else
608  break;
609 
610  case AF_INET6:
611  alen = sizeof(struct sockaddr_in6);
612  ip6 = &((const struct sockaddr_in6 *) addr)->sin6_addr;
613  if (match_ipv6 ("::1", ip6, 128))
615  else if (is_nat_v6 (ip6))
616  ac = GNUNET_NAT_AC_LAN;
617  else
619  if ((ip6->s6_addr[11] == 0xFF) &&
620  (ip6->s6_addr[12] == 0xFE))
621  {
622  /* contains a MAC, be extra careful! */
623  ac |= GNUNET_NAT_AC_PRIVATE;
624  }
625  break;
626 
627 #if AF_UNIX
628  case AF_UNIX:
629  GNUNET_break (0);
630  return GNUNET_OK;
631 #endif
632  default:
633  GNUNET_break (0);
634  return GNUNET_OK;
635  }
636  lal = GNUNET_malloc (sizeof(*lal));
637  lal->af = addr->sa_family;
638  lal->ac = ac;
639  GNUNET_memcpy (&lal->addr,
640  addr,
641  alen);
643  ifc_ctx->lal_tail,
644  lal);
645  return GNUNET_OK;
646 }
static int match_ipv6(const char *network, const struct in6_addr *ip, uint8_t bits)
Check if ip is in network with bits netmask.
GNUNET_NAT_AddressClass
Some addresses contain sensitive information or are not suitable for global distribution.
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
Closure for ifc_proc.
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
List of local addresses this system has.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
struct sockaddr_storage addr
The address itself (i.e.
static int is_nat_v4(const struct in_addr *ip)
Test if the given IPv4 address is in a known range for private networks.
static int match_ipv4(const char *network, const struct in_addr *ip, uint8_t bits)
Check if ip is in network with bits netmask.
Loopback addresses, only useful under special cirumstances.
Addresses that are global (i.e.
static struct GNUNET_MQ_Envelope * ac
Handle to current GNUNET_PEERINFO_add_peer() operation.
Addresses useful in the local wired network, i.e.
Flag for addresses that are highly sensitive (i.e.
struct LocalAddressList * lal_tail
Tail of DLL of local addresses.
int af
Address family.
enum GNUNET_NAT_AddressClass ac
What type of address is this?
struct LocalAddressList * lal_head
Head of DLL of local addresses.
#define GNUNET_malloc(size)
Wrapper around malloc.
static int is_nat_v6(const struct in6_addr *ip)
Test if the given IPv6 address is in a known range for private networks.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ notify_client()

static void notify_client ( enum GNUNET_NAT_AddressClass  ac,
struct ClientHandle ch,
int  add,
const void *  addr,
size_t  addr_len 
)
static

Notify client about a change in the list of addresses this peer has.

Parameters
acaddress class of the entry in the list that changed
chclient to contact
addGNUNET_YES to add, GNUNET_NO to remove
addrthe address that changed
addr_lennumber of bytes in addr

Definition at line 660 of file gnunet-service-nat.c.

References GNUNET_NAT_AddressChangeNotificationMessage::add_remove, GNUNET_NAT_AddressChangeNotificationMessage::addr_class, env, GNUNET_a2s(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_memcpy, GNUNET_MESSAGE_TYPE_NAT_ADDRESS_CHANGE, GNUNET_MQ_msg_extra, GNUNET_MQ_send(), ClientHandle::mq, and msg.

Referenced by check_notify_client(), notify_client_external_ipv4_change(), and upnp_addr_change_cb().

665 {
666  struct GNUNET_MQ_Envelope *env;
668 
670  "Notifying client about %s of IP %s\n",
671  add ? "addition" : "removal",
672  GNUNET_a2s (addr,
673  addr_len));
674  env = GNUNET_MQ_msg_extra (msg,
675  addr_len,
677  msg->add_remove = htonl (add);
678  msg->addr_class = htonl (ac);
679  GNUNET_memcpy (&msg[1],
680  addr,
681  addr_len);
682  GNUNET_MQ_send (ch->mq,
683  env);
684 }
Service notifying the client about changes in the set of addresses it has.
Definition: nat.h:201
struct GNUNET_MessageHeader * msg
Definition: 005.c:2
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
#define GNUNET_MQ_msg_extra(mvar, esize, type)
Allocate an envelope, with extra space allocated after the space needed by the message struct...
Definition: gnunet_mq_lib.h:52
const char * GNUNET_a2s(const struct sockaddr *addr, socklen_t addrlen)
Convert a "struct sockaddr*" (IPv4 or IPv6 address) to a string (for printing debug messages)...
uint32_t addr_class
Type of the address, an enum GNUNET_NAT_AddressClass in NBO.
Definition: nat.h:216
int32_t add_remove
GNUNET_YES to add, GNUNET_NO to remove the address from the list.
Definition: nat.h:211
static struct GNUNET_MQ_Envelope * ac
Handle to current GNUNET_PEERINFO_add_peer() operation.
struct GNUNET_MQ_Envelope * env
Definition: 005.c:1
struct GNUNET_MQ_Handle * mq
The message queue to this client.
#define GNUNET_MESSAGE_TYPE_NAT_ADDRESS_CHANGE
Message to from NAT service notifying us that one of our addresses changed.
static int add
Desired action is to add a record.
#define GNUNET_log(kind,...)
void GNUNET_MQ_send(struct GNUNET_MQ_Handle *mq, struct GNUNET_MQ_Envelope *ev)
Send a message with the given message queue.
Definition: mq.c:353
Here is the call graph for this function:
Here is the caller graph for this function:

◆ check_notify_client()

static void check_notify_client ( struct LocalAddressList delta,
struct ClientHandle ch,
int  add 
)
static

Check if we should bother to notify this client about this address change, and if so, do it.

Parameters
deltathe entry in the list that changed
chclient to check
addGNUNET_YES to add, GNUNET_NO to remove

Definition at line 696 of file gnunet-service-nat.c.

References LocalAddressList::ac, LocalAddressList::addr, LocalAddressList::af, ClientHandle::caddrs, ClientHandle::flags, GNUNET_break, GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_memcmp, GNUNET_memcpy, GNUNET_NAT_AC_EXTERN, GNUNET_NAT_RF_ADDRESSES, is_nat_v4(), is_nat_v6(), match_ipv4(), match_ipv6(), notify_client(), ClientHandle::num_caddrs, and ClientAddress::ss.

Referenced by handle_register(), lookup_hole_external(), notify_client_external_ipv4_change(), notify_clients(), and process_external_ip().

699 {
700  size_t alen;
701  struct sockaddr_in v4;
702  struct sockaddr_in6 v6;
703 
704  if (0 == (ch->flags & GNUNET_NAT_RF_ADDRESSES))
705  {
707  "Not notifying client as it does not care about addresses\n");
708  return;
709  }
710  switch (delta->af)
711  {
712  case AF_INET:
713  alen = sizeof(struct sockaddr_in);
714  GNUNET_memcpy (&v4,
715  &delta->addr,
716  alen);
717 
718  /* Check for client notifications */
719  for (unsigned int i = 0; i < ch->num_caddrs; i++)
720  {
721  const struct sockaddr_in *c4;
722 
723  if (AF_INET != ch->caddrs[i].ss.ss_family)
724  continue; /* IPv4 not relevant */
725  c4 = (const struct sockaddr_in *) &ch->caddrs[i].ss;
726  if (match_ipv4 ("127.0.0.1", &c4->sin_addr, 8) &&
727  (0 != c4->sin_addr.s_addr) &&
728  (! match_ipv4 ("127.0.0.1", &v4.sin_addr, 8)))
729  continue; /* bound to loopback, but this is not loopback */
730  if ((! match_ipv4 ("127.0.0.1", &c4->sin_addr, 8)) &&
731  match_ipv4 ("127.0.0.1", &v4.sin_addr, 8))
732  continue; /* bound to non-loopback, but this is loopback */
733  if ((0 != (delta->ac & GNUNET_NAT_AC_EXTERN)) &&
734  (0 != c4->sin_addr.s_addr) &&
735  (! is_nat_v4 (&v4.sin_addr)))
736  continue; /* based on external-IP, but this IP is not
737  from private address range. */
738  if ((0 != GNUNET_memcmp (&v4.sin_addr,
739  &c4->sin_addr)) &&
740  (0 != c4->sin_addr.s_addr) &&
741  (! is_nat_v4 (&c4->sin_addr)))
742  continue; /* this IP is not from private address range,
743  and IP does not match. */
744 
745  /* OK, IP seems relevant, notify client */
746  if (0 == htons (v4.sin_port))
747  v4.sin_port = c4->sin_port;
748  notify_client (delta->ac,
749  ch,
750  add,
751  &v4,
752  alen);
753  }
754  break;
755 
756  case AF_INET6:
757  alen = sizeof(struct sockaddr_in6);
758  GNUNET_memcpy (&v6,
759  &delta->addr,
760  alen);
761  for (unsigned int i = 0; i < ch->num_caddrs; i++)
762  {
763  const struct sockaddr_in6 *c6;
764 
765  if (AF_INET6 != ch->caddrs[i].ss.ss_family)
766  continue; /* IPv4 not relevant */
767  c6 = (const struct sockaddr_in6 *) &ch->caddrs[i].ss;
768  if (match_ipv6 ("::1", &c6->sin6_addr, 128) &&
769  (0 != GNUNET_memcmp (&c6->sin6_addr,
770  &in6addr_any)) &&
771  (! match_ipv6 ("::1", &v6.sin6_addr, 128)))
772  continue; /* bound to loopback, but this is not loopback */
773  if ((! match_ipv6 ("::1", &c6->sin6_addr, 128)) &&
774  match_ipv6 ("::1", &v6.sin6_addr, 128))
775  continue; /* bound to non-loopback, but this is loopback */
776  if ((0 != (delta->ac & GNUNET_NAT_AC_EXTERN)) &&
777  (0 != GNUNET_memcmp (&c6->sin6_addr,
778  &in6addr_any)) &&
779  (! is_nat_v6 (&v6.sin6_addr)))
780  continue; /* based on external-IP, but this IP is not
781  from private address range. */
782  if ((0 != GNUNET_memcmp (&v6.sin6_addr,
783  &c6->sin6_addr)) &&
784  (0 != GNUNET_memcmp (&c6->sin6_addr,
785  &in6addr_any)) &&
786  (! is_nat_v6 (&c6->sin6_addr)))
787  continue; /* this IP is not from private address range,
788  and IP does not match. */
789  if ((match_ipv6 ("fe80::", &c6->sin6_addr, 10)) &&
790  (0 != GNUNET_memcmp (&c6->sin6_addr,
791  &in6addr_any)) &&
792  (0 != GNUNET_memcmp (&v6.sin6_addr,
793  &c6->sin6_addr)) &&
794  (0 == (delta->ac & GNUNET_NAT_AC_EXTERN)))
795  continue; /* client bound to link-local, and the other address
796  does not match and is not an external IP */
797 
798  /* OK, IP seems relevant, notify client */
799  if (0 == htons (v6.sin6_port))
800  v6.sin6_port = c6->sin6_port;
801  notify_client (delta->ac,
802  ch,
803  add,
804  &v6,
805  alen);
806  }
807  break;
808 
809  default:
810  GNUNET_break (0);
811  return;
812  }
813 }
static int match_ipv6(const char *network, const struct in6_addr *ip, uint8_t bits)
Check if ip is in network with bits netmask.
static void notify_client(enum GNUNET_NAT_AddressClass ac, struct ClientHandle *ch, int add, const void *addr, size_t addr_len)
Notify client about a change in the list of addresses this peer has.
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
Addresses that should be our external IP address on the outside of a NAT.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
struct sockaddr_storage addr
The address itself (i.e.
static int is_nat_v4(const struct in_addr *ip)
Test if the given IPv4 address is in a known range for private networks.
static int match_ipv4(const char *network, const struct in_addr *ip, uint8_t bits)
Check if ip is in network with bits netmask.
uint16_t num_caddrs
Number of addresses that this service is bound to.
struct ClientAddress * caddrs
Array of addresses used by the service.
static int add
Desired action is to add a record.
#define GNUNET_memcmp(a, b)
Compare memory in a and b, where both must be of the same pointer type.
#define GNUNET_log(kind,...)
int af
Address family.
enum GNUNET_NAT_AddressClass ac
What type of address is this?
enum GNUNET_NAT_RegisterFlags flags
What does this client care about?
struct sockaddr_storage ss
Network address used by the client.
This client wants to be informed about changes to our applicable addresses.
Definition: nat.h:82
static int is_nat_v6(const struct in6_addr *ip)
Test if the given IPv6 address is in a known range for private networks.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ notify_clients()

static void notify_clients ( struct LocalAddressList delta,
int  add 
)
static

Notify all clients about a change in the list of addresses this peer has.

Parameters
deltathe entry in the list that changed
addGNUNET_YES to add, GNUNET_NO to remove

Definition at line 824 of file gnunet-service-nat.c.

References ch, and check_notify_client().

Referenced by run_scan().

826 {
827  for (struct ClientHandle *ch = ch_head;
828  NULL != ch;
829  ch = ch->next)
830  check_notify_client (delta,
831  ch,
832  add);
833 }
static struct GNUNET_CADET_Channel * ch
Channel handle.
Definition: gnunet-cadet.c:117
static void check_notify_client(struct LocalAddressList *delta, struct ClientHandle *ch, int add)
Check if we should bother to notify this client about this address change, and if so...
static struct ClientHandle * ch_head
Head of client DLL.
Struct containing information about a client, handle to connect to it, and any pending messages that ...
static int add
Desired action is to add a record.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ notify_client_external_ipv4_change()

static void notify_client_external_ipv4_change ( void *  cls,
const struct in_addr *  v4,
int  add 
)
static

Tell relevant client about a change in our external IPv4 address.

Parameters
clsclient to check if it cares and possibly notify
v4the external address that changed
addGNUNET_YES to add, GNUNET_NO to remove

Definition at line 845 of file gnunet-service-nat.c.

References LocalAddressList::ac, LocalAddressList::addr, LocalAddressList::af, ClientHandle::caddrs, ch, check_notify_client(), ClientHandle::ext_dns_port, GNUNET_a2s(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_NAT_AC_EXTERN, GNUNET_NAT_AC_GLOBAL, GNUNET_NAT_AC_LAN, GNUNET_NAT_AC_MANUAL, GNUNET_NO, GNUNET_YES, ClientHandle::hole_external, is_nat_v4(), ClientHandle::natted_address, notify_client(), ClientHandle::num_caddrs, ClientHandle::section_name, and ClientAddress::ss.

Referenced by handle_register().

848 {
849  struct ClientHandle *ch = cls;
850  struct sockaddr_in sa;
851  int have_v4;
852 
853  /* (0) check if this impacts 'hole_external' */
854  if ((NULL != ch->hole_external) &&
855  (0 == strcasecmp (ch->hole_external,
856  "AUTO")))
857  {
858  struct LocalAddressList lal;
859  struct sockaddr_in *s4;
860 
862  "Detected eternal IP, can now back-fill AUTO:%u in hole punching specification of `%s'\n",
863  (unsigned int) ch->ext_dns_port,
864  ch->section_name);
865  memset (&lal, 0, sizeof(lal));
866  s4 = (struct sockaddr_in *) &lal.addr;
867  s4->sin_family = AF_INET;
868  s4->sin_port = htons (ch->ext_dns_port);
869  s4->sin_addr = *v4;
870  lal.af = AF_INET;
872  check_notify_client (&lal,
873  ch,
874  add);
875  }
876 
877  /* (1) check if client cares. */
878  if (! ch->natted_address)
879  return;
880  have_v4 = GNUNET_NO;
881  for (unsigned int i = 0; i < ch->num_caddrs; i++)
882  {
883  const struct sockaddr_storage *ss = &ch->caddrs[i].ss;
884 
885  if (AF_INET != ss->ss_family)
886  continue;
887  have_v4 = GNUNET_YES;
888  break;
889  }
890  if (GNUNET_NO == have_v4)
891  return; /* IPv6-only */
892 
893  /* (2) build address info */
894  memset (&sa,
895  0,
896  sizeof(sa));
897  sa.sin_family = AF_INET;
898  sa.sin_addr = *v4;
899  sa.sin_port = htons (0);
900 
902  "Detected eternal IP %s, notifying client of external IP (without port)\n",
903  GNUNET_a2s ((const struct sockaddr *) &sa,
904  sizeof(sa)));
905  /* (3) notify client of change */
909  ch,
910  add,
911  &sa,
912  sizeof(sa));
913 }
static struct GNUNET_CADET_Channel * ch
Channel handle.
Definition: gnunet-cadet.c:117
static void check_notify_client(struct LocalAddressList *delta, struct ClientHandle *ch, int add)
Check if we should bother to notify this client about this address change, and if so...
Addresses that were manually configured by the user.
uint16_t ext_dns_port
Port number we found in hole_external.
int natted_address
Is any of the caddrs in a reserved subnet for NAT?
char * hole_external
External DNS name and port given by user due to manual hole punching.
static void notify_client(enum GNUNET_NAT_AddressClass ac, struct ClientHandle *ch, int add, const void *addr, size_t addr_len)
Notify client about a change in the list of addresses this peer has.
Addresses that should be our external IP address on the outside of a NAT.
#define GNUNET_NO
Definition: gnunet_common.h:78
char * section_name
Name of the configuration section this client cares about.
List of local addresses this system has.
static int is_nat_v4(const struct in_addr *ip)
Test if the given IPv4 address is in a known range for private networks.
uint16_t num_caddrs
Number of addresses that this service is bound to.
const char * GNUNET_a2s(const struct sockaddr *addr, socklen_t addrlen)
Convert a "struct sockaddr*" (IPv4 or IPv6 address) to a string (for printing debug messages)...
Struct containing information about a client, handle to connect to it, and any pending messages that ...
Addresses that are global (i.e.
struct ClientAddress * caddrs
Array of addresses used by the service.
static int add
Desired action is to add a record.
Addresses useful in the local wired network, i.e.
#define GNUNET_log(kind,...)
#define GNUNET_YES
Definition: gnunet_common.h:77
struct sockaddr_storage ss
Network address used by the client.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ reversal_callback()

static void reversal_callback ( void *  cls,
const struct sockaddr_in *  ra 
)
static

We got a connection reversal request from another peer.

Notify applicable clients.

Parameters
clsclosure with the struct LocalAddressList
raIP address of the peer who wants us to connect to it

Definition at line 924 of file gnunet-service-nat.c.

References LocalAddressList::addr, LocalAddressList::af, ch, env, GNUNET_assert, GNUNET_memcpy, GNUNET_MESSAGE_TYPE_NAT_CONNECTION_REVERSAL_REQUESTED, GNUNET_MQ_msg_extra, GNUNET_MQ_send(), GNUNET_NO, GNUNET_YES, GNUNET_CADET_Channel::mq, and ClientAddress::ss.

Referenced by GNUNET_NAT_register(), and run_scan().

926 {
927  struct LocalAddressList *lal = cls;
928  const struct sockaddr_in *l4;
929 
930  GNUNET_assert (AF_INET == lal->af);
931  l4 = (const struct sockaddr_in *) &lal->addr;
932  for (struct ClientHandle *ch = ch_head;
933  NULL != ch;
934  ch = ch->next)
935  {
937  struct GNUNET_MQ_Envelope *env;
938  int match;
939 
940  /* Check if client is in applicable range for ICMP NAT traversal
941  for this local address */
942  if (! ch->natted_address)
943  continue;
944  match = GNUNET_NO;
945  for (unsigned int i = 0; i < ch->num_caddrs; i++)
946  {
947  struct ClientAddress *ca = &ch->caddrs[i];
948  const struct sockaddr_in *c4;
949 
950  if (AF_INET != ca->ss.ss_family)
951  continue;
952  c4 = (const struct sockaddr_in *) &ca->ss;
953  if ((0 != c4->sin_addr.s_addr) &&
954  (l4->sin_addr.s_addr != c4->sin_addr.s_addr))
955  continue;
956  match = GNUNET_YES;
957  break;
958  }
959  if (! match)
960  continue;
961 
962  /* Notify applicable client about connection reversal request */
963  env = GNUNET_MQ_msg_extra (crrm,
964  sizeof(struct sockaddr_in),
966  GNUNET_memcpy (&crrm[1],
967  ra,
968  sizeof(struct sockaddr_in));
969  GNUNET_MQ_send (ch->mq,
970  env);
971  }
972 }
static struct GNUNET_CADET_Channel * ch
Channel handle.
Definition: gnunet-cadet.c:117
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_MESSAGE_TYPE_NAT_CONNECTION_REVERSAL_REQUESTED
Message to from NAT service notifying us that connection reversal was requested by another peer...
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
static struct ClientHandle * ch_head
Head of client DLL.
#define GNUNET_NO
Definition: gnunet_common.h:78
List of local addresses this system has.
struct sockaddr_storage addr
The address itself (i.e.
#define GNUNET_MQ_msg_extra(mvar, esize, type)
Allocate an envelope, with extra space allocated after the space needed by the message struct...
Definition: gnunet_mq_lib.h:52
Service telling a client that connection reversal was requested.
Definition: nat.h:186
Struct containing information about a client, handle to connect to it, and any pending messages that ...
struct GNUNET_MQ_Handle * mq
Message Queue for the channel (which we are implementing).
Definition: cadet_api.c:106
struct GNUNET_MQ_Envelope * env
Definition: 005.c:1
Information we track per client address.
int af
Address family.
#define GNUNET_YES
Definition: gnunet_common.h:77
void GNUNET_MQ_send(struct GNUNET_MQ_Handle *mq, struct GNUNET_MQ_Envelope *ev)
Send a message with the given message queue.
Definition: mq.c:353
struct sockaddr_storage ss
Network address used by the client.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ run_scan()

static void run_scan ( void *  cls)
static

Task we run periodically to scan for network interfaces.

Parameters
clsNULL

Definition at line 981 of file gnunet-service-nat.c.

References free_lal(), GN_nat_status_changed(), GN_start_gnunet_nat_server_(), GNUNET_a2s(), GNUNET_CONTAINER_DLL_insert, GNUNET_CONTAINER_DLL_remove, GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_log, GNUNET_NAT_AC_LAN, GNUNET_NO, GNUNET_OS_network_interfaces_list(), GNUNET_SCHEDULER_add_delayed(), GNUNET_YES, ifc_proc(), IfcProcContext::lal_head, IfcProcContext::lal_tail, LocalAddressList::next, notify_clients(), reversal_callback(), and SCAN_FREQ.

Referenced by run().

982 {
983  struct IfcProcContext ifc_ctx;
984  int found;
985  int have_nat;
986  struct LocalAddressList *lnext;
987 
989  &run_scan,
990  NULL);
991  memset (&ifc_ctx,
992  0,
993  sizeof(ifc_ctx));
995  &ifc_ctx);
996  /* remove addresses that disappeared */
997  for (struct LocalAddressList *lal = lal_head;
998  NULL != lal;
999  lal = lnext)
1000  {
1001  lnext = lal->next;
1002  found = GNUNET_NO;
1003  for (struct LocalAddressList *pos = ifc_ctx.lal_head;
1004  NULL != pos;
1005  pos = pos->next)
1006  {
1007  if ((pos->af == lal->af) &&
1008  (0 == memcmp (&lal->addr,
1009  &pos->addr,
1010  (AF_INET == lal->af)
1011  ? sizeof(struct sockaddr_in)
1012  : sizeof(struct sockaddr_in6))))
1013  {
1014  found = GNUNET_YES;
1015  }
1016  }
1017  if (GNUNET_NO == found)
1018  {
1019  notify_clients (lal,
1020  GNUNET_NO);
1021  free_lal (lal);
1022  }
1023  }
1024 
1025  /* add addresses that appeared */
1026  have_nat = GNUNET_NO;
1027  for (struct LocalAddressList *pos = ifc_ctx.lal_head;
1028  NULL != pos;
1029  pos = ifc_ctx.lal_head)
1030  {
1031  found = GNUNET_NO;
1032  if (GNUNET_NAT_AC_LAN == (GNUNET_NAT_AC_LAN & pos->ac))
1033  have_nat = GNUNET_YES;
1034  for (struct LocalAddressList *lal = lal_head;
1035  NULL != lal;
1036  lal = lal->next)
1037  {
1038  if ((pos->af == lal->af) &&
1039  (0 == memcmp (&lal->addr,
1040  &pos->addr,
1041  (AF_INET == lal->af)
1042  ? sizeof(struct sockaddr_in)
1043  : sizeof(struct sockaddr_in6))))
1044  found = GNUNET_YES;
1045  }
1046  GNUNET_CONTAINER_DLL_remove (ifc_ctx.lal_head,
1047  ifc_ctx.lal_tail,
1048  pos);
1049  if (GNUNET_YES == found)
1050  {
1051  GNUNET_free (pos);
1052  }
1053  else
1054  {
1055  notify_clients (pos,
1056  GNUNET_YES);
1058  lal_tail,
1059  pos);
1060  if ((AF_INET == pos->af) &&
1061  (NULL == pos->hc) &&
1062  (0 != (GNUNET_NAT_AC_LAN & pos->ac)))
1063  {
1064  const struct sockaddr_in *s4
1065  = (const struct sockaddr_in *) &pos->addr;
1066 
1068  "Found NATed local address %s, starting NAT server\n",
1069  GNUNET_a2s ((const struct sockaddr *) &pos->addr,
1070  sizeof(*s4)));
1071  pos->hc = GN_start_gnunet_nat_server_ (&s4->sin_addr,
1073  pos,
1074  cfg);
1075  }
1076  }
1077  }
1078  GN_nat_status_changed (have_nat);
1079 }
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
static void free_lal(struct LocalAddressList *lal)
Remove and free an entry from the lal_head DLL.
static void run_scan(void *cls)
Task we run periodically to scan for network interfaces.
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
static int ifc_proc(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 struct LocalAddressList * lal_tail
Tail of DLL of local addresses.
Closure for ifc_proc.
#define GNUNET_NO
Definition: gnunet_common.h:78
void GNUNET_OS_network_interfaces_list(GNUNET_OS_NetworkInterfaceProcessor proc, void *proc_cls)
Enumerate all network interfaces.
Definition: os_network.c:396
List of local addresses this system has.
static struct GNUNET_SCHEDULER_Task * scan_task
Task scheduled to periodically scan our network interfaces.
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:1253
static void reversal_callback(void *cls, const struct sockaddr_in *ra)
We got a connection reversal request from another peer.
#define SCAN_FREQ
How often should we ask the OS about a list of active network interfaces?
const char * GNUNET_a2s(const struct sockaddr *addr, socklen_t addrlen)
Convert a "struct sockaddr*" (IPv4 or IPv6 address) to a string (for printing debug messages)...
Addresses useful in the local wired network, i.e.
static const struct GNUNET_CONFIGURATION_Handle * cfg
Handle to our current configuration.
#define GNUNET_log(kind,...)
#define GNUNET_YES
Definition: gnunet_common.h:77
void GN_nat_status_changed(int have_nat)
We have changed our opinion about being NATed in the first place.
static void notify_clients(struct LocalAddressList *delta, int add)
Notify all clients about a change in the list of addresses this peer has.
static struct LocalAddressList * lal_head
Head of DLL of local addresses.
struct HelperContext * GN_start_gnunet_nat_server_(const struct in_addr *internal_address, GN_ReversalCallback cb, void *cb_cls, const struct GNUNET_CONFIGURATION_Handle *cfg)
Start the gnunet-helper-nat-server and process incoming requests.
#define GNUNET_free(ptr)
Wrapper around free.
struct LocalAddressList * next
This is a linked list.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ upnp_addr_change_cb()

static void upnp_addr_change_cb ( void *  cls,
int  add_remove,
const struct sockaddr *  addr,
socklen_t  addrlen,
enum GNUNET_NAT_StatusCode  result 
)
static

Function called whenever our set of external addresses as created by upnpc changes.

Parameters
clsclosure with our struct ClientHandle *
add_removeGNUNET_YES to mean the new public IP address, GNUNET_NO to mean the previous (now invalid) one, GNUNET_SYSERR indicates an error
addreither the previous or the new public IP address
addrlenactual length of the addr
resultGNUNET_NAT_ERROR_SUCCESS on success, otherwise the specific error code

Definition at line 1094 of file gnunet-service-nat.c.

References ac, ch, dyndns_lookup(), GNUNET_a2s(), GNUNET_assert, GNUNET_break, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_INFO, GNUNET_ERROR_TYPE_WARNING, GNUNET_log, GNUNET_NAT_AC_EXTERN, GNUNET_NAT_AC_LAN, GNUNET_NAT_ERROR_EXTERNAL_IP_ADDRESS_INVALID, GNUNET_NAT_ERROR_EXTERNAL_IP_UTILITY_FAILED, GNUNET_NAT_ERROR_EXTERNAL_IP_UTILITY_NOT_FOUND, GNUNET_NAT_ERROR_EXTERNAL_IP_UTILITY_OUTPUT_INVALID, GNUNET_NAT_ERROR_IPC_FAILURE, GNUNET_NAT_ERROR_SUCCESS, GNUNET_NAT_ERROR_UPNPC_FAILED, GNUNET_NAT_ERROR_UPNPC_NOT_FOUND, GNUNET_NAT_ERROR_UPNPC_PORTMAP_FAILED, GNUNET_NAT_ERROR_UPNPC_TIMEOUT, is_nat_v4(), is_nat_v6(), and notify_client().

Referenced by handle_register().

1099 {
1100  struct ClientHandle *ch = cls;
1102 
1103  switch (result)
1104  {
1106  GNUNET_assert (NULL != addr);
1107  break;
1108 
1113  "Running upnpc failed: %d\n",
1114  result);
1115  return;
1116 
1119  "external-ip binary not found\n");
1120  return;
1121 
1124  "upnpc binary not found\n");
1125  return;
1126 
1129  "external-ip binary could not be run\n");
1130  return;
1131 
1134  "upnpc failed to create port mapping\n");
1135  return;
1136 
1139  "Invalid output from upnpc\n");
1140  return;
1141 
1144  "Invalid address returned by upnpc\n");
1145  return;
1146 
1147  default:
1148  GNUNET_break (0); /* should not be possible */
1149  return;
1150  }
1151  switch (addr->sa_family)
1152  {
1153  case AF_INET:
1154  ac = is_nat_v4 (&((const struct sockaddr_in *) addr)->sin_addr)
1157  break;
1158 
1159  case AF_INET6:
1160  ac = is_nat_v6 (&((const struct sockaddr_in6 *) addr)->sin6_addr)
1163  break;
1164 
1165  default:
1166  GNUNET_break (0);
1167  return;
1168  }
1170  "upnp external address %s: %s\n",
1171  add_remove ? "added" : "removed",
1172  GNUNET_a2s (addr,
1173  addrlen));
1174  notify_client (ac,
1175  ch,
1176  add_remove,
1177  addr,
1178  addrlen);
1179 }
static struct GNUNET_CADET_Channel * ch
Channel handle.
Definition: gnunet-cadet.c:117
GNUNET_NAT_AddressClass
Some addresses contain sensitive information or are not suitable for global distribution.
`upnpc&#39; command failed to establish port mapping
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
static void notify_client(enum GNUNET_NAT_AddressClass ac, struct ClientHandle *ch, int add, const void *addr, size_t addr_len)
Notify client about a change in the list of addresses this peer has.
`upnpc&#39; command took too long, process killed
Addresses that should be our external IP address on the outside of a NAT.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
`external-ip&#39; command output invalid
static int is_nat_v4(const struct in_addr *ip)
Test if the given IPv4 address is in a known range for private networks.
static int result
Global testing status.
const char * GNUNET_a2s(const struct sockaddr *addr, socklen_t addrlen)
Convert a "struct sockaddr*" (IPv4 or IPv6 address) to a string (for printing debug messages)...
Struct containing information about a client, handle to connect to it, and any pending messages that ...
static struct GNUNET_MQ_Envelope * ac
Handle to current GNUNET_PEERINFO_add_peer() operation.
`external-ip&#39; command not found
Addresses useful in the local wired network, i.e.
Failed to run upnpc command.
#define GNUNET_log(kind,...)
"no valid address was returned by `external-ip&#39;"
Failed to run external-ip command.
static int is_nat_v6(const struct in6_addr *ip)
Test if the given IPv6 address is in a known range for private networks.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ dyndns_lookup()

static void dyndns_lookup ( void *  cls)
static

Resolve the hole_external name to figure out our external address from a manually punched hole.

The port number has already been parsed, this task is responsible for periodically doing a DNS lookup.

Parameters
chclient handle to act upon

Definition at line 1307 of file gnunet-service-nat.c.

References ch, ClientHandle::ext_addr_head, ClientHandle::ext_dns, ClientHandle::ext_dns_port, ClientHandle::ext_dns_task, GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_RESOLVER_ip_get(), GNUNET_TIME_UNIT_MINUTES, GNUNET_YES, ClientHandle::hole_external, LocalAddressList::next, LocalAddressList::old, process_external_ip(), and ClientHandle::section_name.

Referenced by lookup_hole_external(), process_external_ip(), and upnp_addr_change_cb().

1308 {
1309  struct ClientHandle *ch = cls;
1310  struct LocalAddressList *lal;
1311 
1313  "Performing DNS lookup for punched hole given for `%s' as `%s:%u'\n",
1314  ch->section_name,
1315  ch->hole_external,
1316  (unsigned int) ch->ext_dns_port);
1317  for (lal = ch->ext_addr_head; NULL != lal; lal = lal->next)
1318  lal->old = GNUNET_YES;
1319  ch->ext_dns_task = NULL;
1321  AF_UNSPEC,
1324  ch);
1325 }
static struct GNUNET_CADET_Channel * ch
Channel handle.
Definition: gnunet-cadet.c:117
uint16_t ext_dns_port
Port number we found in hole_external.
#define GNUNET_TIME_UNIT_MINUTES
One minute.
char * hole_external
External DNS name and port given by user due to manual hole punching.
struct GNUNET_SCHEDULER_Task * ext_dns_task
Task for periodically re-running the ext_dns DNS lookup.
struct GNUNET_RESOLVER_RequestHandle * GNUNET_RESOLVER_ip_get(const char *hostname, int af, struct GNUNET_TIME_Relative timeout, GNUNET_RESOLVER_AddressCallback callback, void *callback_cls)
Convert a string to one or more IP addresses.
Definition: resolver_api.c:939
static void process_external_ip(void *cls, const struct sockaddr *addr, socklen_t addrlen)
Our (external) hostname was resolved.
char * section_name
Name of the configuration section this client cares about.
List of local addresses this system has.
int old
GNUNET_YES if we saw this one in the previous iteration, but not in the current iteration and thus mi...
struct GNUNET_RESOLVER_RequestHandle * ext_dns
Handle for (DYN)DNS lookup of our external IP as given in hole_external.
Struct containing information about a client, handle to connect to it, and any pending messages that ...
struct LocalAddressList * ext_addr_head
DLL of external IP addresses as given in hole_external.
#define GNUNET_log(kind,...)
#define GNUNET_YES
Definition: gnunet_common.h:77
struct LocalAddressList * next
This is a linked list.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ process_external_ip()

static void process_external_ip ( void *  cls,
const struct sockaddr *  addr,
socklen_t  addrlen 
)
static

Our (external) hostname was resolved.

Update lists of current external IPs (note that DNS may return multiple addresses!) and notify client accordingly.

Parameters
clsthe struct ClientHandle
addrNULL on error, otherwise result of DNS lookup
addrlennumber of bytes in addr

Definition at line 1204 of file gnunet-service-nat.c.

References LocalAddressList::ac, LocalAddressList::addr, LocalAddressList::af, ch, check_notify_client(), dyndns_frequency, dyndns_lookup(), ClientHandle::ext_addr_head, ClientHandle::ext_addr_tail, ClientHandle::ext_dns, ClientHandle::ext_dns_port, ClientHandle::ext_dns_task, GNUNET_a2s(), GNUNET_break, GNUNET_CONTAINER_DLL_insert, GNUNET_CONTAINER_DLL_remove, GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_log, GNUNET_memcpy, GNUNET_NAT_AC_GLOBAL, GNUNET_NAT_AC_MANUAL, GNUNET_new, GNUNET_NO, GNUNET_SCHEDULER_add_delayed(), GNUNET_YES, ClientHandle::hole_external, LocalAddressList::next, LocalAddressList::old, and ClientAddress::ss.

Referenced by dyndns_lookup().

1207 {
1208  struct ClientHandle *ch = cls;
1209  struct LocalAddressList *lal;
1210  struct sockaddr_storage ss;
1211  struct sockaddr_in *v4;
1212  struct sockaddr_in6 *v6;
1213 
1214  if (NULL == addr)
1215  {
1216  struct LocalAddressList *laln;
1217 
1218  ch->ext_dns = NULL;
1219  ch->ext_dns_task
1221  &dyndns_lookup,
1222  ch);
1223  /* Current iteration is over, remove 'old' IPs now */
1224  for (lal = ch->ext_addr_head; NULL != lal; lal = laln)
1225  {
1226  laln = lal->next;
1227  if (GNUNET_YES == lal->old)
1228  {
1230  ch->ext_addr_tail,
1231  lal);
1232  check_notify_client (lal,
1233  ch,
1234  GNUNET_NO);
1235  GNUNET_free (lal);
1236  }
1237  }
1238  return;
1239  }
1241  "Got IP `%s' for external address `%s'\n",
1242  GNUNET_a2s (addr,
1243  addrlen),
1244  ch->hole_external);
1245 
1246  /* build sockaddr storage with port number */
1247  memset (&ss,
1248  0,
1249  sizeof(ss));
1250  GNUNET_memcpy (&ss,
1251  addr,
1252  addrlen);
1253  switch (addr->sa_family)
1254  {
1255  case AF_INET:
1256  v4 = (struct sockaddr_in *) &ss;
1257  v4->sin_port = htons (ch->ext_dns_port);
1258  break;
1259 
1260  case AF_INET6:
1261  v6 = (struct sockaddr_in6 *) &ss;
1262  v6->sin6_port = htons (ch->ext_dns_port);
1263  break;
1264 
1265  default:
1266  GNUNET_break (0);
1267  return;
1268  }
1269  /* See if 'ss' matches any of our known addresses */
1270  for (lal = ch->ext_addr_head; NULL != lal; lal = lal->next)
1271  {
1272  if (GNUNET_NO == lal->old)
1273  continue; /* already processed, skip */
1274  if ((addr->sa_family == lal->addr.ss_family) &&
1275  (0 == memcmp (&ss,
1276  &lal->addr,
1277  addrlen)))
1278  {
1279  /* Address unchanged, remember so we do not remove */
1280  lal->old = GNUNET_NO;
1281  return; /* done here */
1282  }
1283  }
1284  /* notify client, and remember IP for later removal! */
1285  lal = GNUNET_new (struct LocalAddressList);
1286  lal->addr = ss;
1287  lal->af = ss.ss_family;
1290  ch->ext_addr_tail,
1291  lal);
1292  check_notify_client (lal,
1293  ch,
1294  GNUNET_YES);
1295 }
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
static struct GNUNET_CADET_Channel * ch
Channel handle.
Definition: gnunet-cadet.c:117
static void check_notify_client(struct LocalAddressList *delta, struct ClientHandle *ch, int add)
Check if we should bother to notify this client about this address change, and if so...
Addresses that were manually configured by the user.
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
uint16_t ext_dns_port
Port number we found in hole_external.
char * hole_external
External DNS name and port given by user due to manual hole punching.
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
#define GNUNET_NO
Definition: gnunet_common.h:78
struct GNUNET_SCHEDULER_Task * ext_dns_task
Task for periodically re-running the ext_dns DNS lookup.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
List of local addresses this system has.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
struct sockaddr_storage addr
The address itself (i.e.
int old
GNUNET_YES if we saw this one in the previous iteration, but not in the current iteration and thus mi...
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:1253
struct GNUNET_RESOLVER_RequestHandle * ext_dns
Handle for (DYN)DNS lookup of our external IP as given in hole_external.
const char * GNUNET_a2s(const struct sockaddr *addr, socklen_t addrlen)
Convert a "struct sockaddr*" (IPv4 or IPv6 address) to a string (for printing debug messages)...
struct LocalAddressList * ext_addr_tail
DLL of external IP addresses as given in hole_external.
Struct containing information about a client, handle to connect to it, and any pending messages that ...
Addresses that are global (i.e.
struct LocalAddressList * ext_addr_head
DLL of external IP addresses as given in hole_external.
#define GNUNET_log(kind,...)
int af
Address family.
enum GNUNET_NAT_AddressClass ac
What type of address is this?
#define GNUNET_YES
Definition: gnunet_common.h:77
static struct GNUNET_TIME_Relative dyndns_frequency
How often do we scan for changes in how our external (dyndns) hostname resolves?
static void dyndns_lookup(void *cls)
Resolve the hole_external name to figure out our external address from a manually punched hole...
#define GNUNET_free(ptr)
Wrapper around free.
struct LocalAddressList * next
This is a linked list.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ lookup_hole_external()

static void lookup_hole_external ( struct ClientHandle ch)
static

Resolve the hole_external name to figure out our external address from a manually punched hole.

The given name may be "AUTO" in which case we should use the IP address(es) we have from upnpc or other methods. The name can also be an IP address, in which case we do not need to do DNS resolution. Finally, we also need to parse the port number.

Parameters
chclient handle to act upon

Definition at line 1340 of file gnunet-service-nat.c.

References _, LocalAddressList::ac, LocalAddressList::addr, LocalAddressList::af, check_notify_client(), dyndns_lookup(), ClientHandle::ext_addr_head, ClientHandle::ext_addr_tail, ClientHandle::ext_dns_port, ClientHandle::ext_dns_task, GNUNET_CONTAINER_DLL_insert, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_WARNING, GNUNET_free, GNUNET_log, GNUNET_NAT_AC_GLOBAL, GNUNET_NAT_AC_MANUAL, GNUNET_new, GNUNET_SCHEDULER_add_now(), GNUNET_YES, ClientHandle::hole_external, port, and ClientHandle::section_name.

Referenced by handle_register().

1341 {
1342  char *port;
1343  unsigned int pnum;
1344  struct sockaddr_in *s4;
1345  struct LocalAddressList *lal;
1346 
1347  port = strrchr (ch->hole_external, ':');
1348  if (NULL == port)
1349  {
1351  _ ("Malformed punched hole specification `%s' (lacks port)\n"),
1352  ch->hole_external);
1353  return;
1354  }
1355  if ((1 != sscanf (port + 1,
1356  "%u",
1357  &pnum)) ||
1358  (pnum > 65535))
1359  {
1361  _ (
1362  "Invalid port number in punched hole specification `%s' (lacks port)\n"),
1363  port + 1);
1364  return;
1365  }
1366  ch->ext_dns_port = (uint16_t) pnum;
1367  *port = '\0';
1368 
1369  lal = GNUNET_new (struct LocalAddressList);
1370  if ('[' == *ch->hole_external)
1371  {
1372  struct sockaddr_in6 *s6 = (struct sockaddr_in6 *) &lal->addr;
1373 
1374  s6->sin6_family = AF_INET6;
1375  if (']' != (ch->hole_external[strlen (ch->hole_external) - 1]))
1376  {
1378  _ ("Malformed punched hole specification `%s' (lacks `]')\n"),
1379  ch->hole_external);
1380  GNUNET_free (lal);
1381  return;
1382  }
1383  ch->hole_external[strlen (ch->hole_external) - 1] = '\0';
1384  if (1 != inet_pton (AF_INET6,
1385  ch->hole_external + 1,
1386  &s6->sin6_addr))
1387  {
1389  _ (
1390  "Malformed punched hole specification `%s' (IPv6 address invalid)"),
1391  ch->hole_external + 1);
1392  GNUNET_free (lal);
1393  return;
1394  }
1395  s6->sin6_port = htons (ch->ext_dns_port);
1396  lal->af = AF_INET6;
1399  ch->ext_addr_tail,
1400  lal);
1401  check_notify_client (lal,
1402  ch,
1403  GNUNET_YES);
1404  return;
1405  }
1406 
1407  s4 = (struct sockaddr_in *) &lal->addr;
1408  s4->sin_family = AF_INET;
1409  if (1 == inet_pton (AF_INET,
1410  ch->hole_external,
1411  &s4->sin_addr))
1412  {
1414  "IPv4 punched hole given for `%s' via `%s:%u'\n",
1415  ch->section_name,
1416  ch->hole_external,
1417  (unsigned int) ch->ext_dns_port);
1418  s4->sin_port = htons (ch->ext_dns_port);
1419  lal->af = AF_INET;
1422  ch->ext_addr_tail,
1423  lal);
1424  check_notify_client (lal,
1425  ch,
1426  GNUNET_YES);
1427  return;
1428  }
1429  if (0 == strcasecmp (ch->hole_external,
1430  "AUTO"))
1431  {
1432  /* handled in #notify_client_external_ipv4_change() */
1433  GNUNET_free (lal);
1434  return;
1435  }
1436  /* got a DNS name, trigger lookup! */
1437  GNUNET_free (lal);
1438  ch->ext_dns_task
1440  ch);
1441 }
static void check_notify_client(struct LocalAddressList *delta, struct ClientHandle *ch, int add)
Check if we should bother to notify this client about this address change, and if so...
Addresses that were manually configured by the user.
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
uint16_t ext_dns_port
Port number we found in hole_external.
char * hole_external
External DNS name and port given by user due to manual hole punching.
struct GNUNET_SCHEDULER_Task * ext_dns_task
Task for periodically re-running the ext_dns DNS lookup.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
char * section_name
Name of the configuration section this client cares about.
List of local addresses this system has.
struct sockaddr_storage addr
The address itself (i.e.
#define _(String)
GNU gettext support macro.
Definition: platform.h:181
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:1280
struct LocalAddressList * ext_addr_tail
DLL of external IP addresses as given in hole_external.
Addresses that are global (i.e.
struct LocalAddressList * ext_addr_head
DLL of external IP addresses as given in hole_external.
static uint16_t port
Port number.
Definition: gnunet-bcd.c:81
#define GNUNET_log(kind,...)
int af
Address family.
enum GNUNET_NAT_AddressClass ac
What type of address is this?
#define GNUNET_YES
Definition: gnunet_common.h:77
static void dyndns_lookup(void *cls)
Resolve the hole_external name to figure out our external address from a manually punched hole...
#define GNUNET_free(ptr)
Wrapper around free.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ handle_register()

static void handle_register ( void *  cls,
const struct GNUNET_NAT_RegisterMessage message 
)
static

Handler for GNUNET_MESSAGE_TYPE_NAT_REGISTER message from client.

We remember the client for updates upon future NAT events.

Parameters
clsclient who sent the message
messagethe message received

Definition at line 1452 of file gnunet-service-nat.c.

References ClientHandle::caddrs, ch, check_notify_client(), ClientHandle::client, enable_upnp, ClientHandle::external_monitor, GNUNET_NAT_RegisterMessage::flags, ClientHandle::flags, GN_external_ipv4_monitor_start(), GNUNET_assert, GNUNET_break, GNUNET_CONFIGURATION_get_value_string(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_memcpy, GNUNET_NAT_mini_map_start(), GNUNET_new_array, GNUNET_NO, GNUNET_OK, GNUNET_SERVICE_client_continue(), GNUNET_SERVICE_client_drop(), GNUNET_strndup, GNUNET_YES, GNUNET_NAT_RegisterMessage::header, ClientHandle::hole_external, is_nat_v4(), is_nat_v6(), lookup_hole_external(), ClientAddress::mh, ClientHandle::natted_address, LocalAddressList::next, notify_client_external_ipv4_change(), GNUNET_NAT_RegisterMessage::num_addrs, ClientHandle::num_caddrs, port, GNUNET_NAT_RegisterMessage::proto, ClientHandle::proto, ClientHandle::section_name, GNUNET_MessageHeader::size, ClientAddress::ss, GNUNET_NAT_RegisterMessage::str_len, and upnp_addr_change_cb().

1454 {
1455  struct ClientHandle *ch = cls;
1456  const char *off;
1457  size_t left;
1458 
1459  if ((0 != ch->proto) ||
1460  (NULL != ch->caddrs))
1461  {
1462  /* double registration not allowed */
1463  GNUNET_break (0);
1465  return;
1466  }
1467  ch->flags = message->flags;
1468  ch->proto = message->proto;
1469  ch->num_caddrs = ntohs (message->num_addrs);
1470  ch->caddrs = GNUNET_new_array (ch->num_caddrs,
1471  struct ClientAddress);
1472  left = ntohs (message->header.size) - sizeof(*message);
1473  off = (const char *) &message[1];
1474  for (unsigned int i = 0; i < ch->num_caddrs; i++)
1475  {
1476  const struct sockaddr *sa = (const struct sockaddr *) off;
1477  size_t alen;
1478  uint16_t port;
1479  int is_nat;
1480 
1481  if (sizeof(sa_family_t) > left)
1482  {
1483  GNUNET_break (0);
1485  return;
1486  }
1487  is_nat = GNUNET_NO;
1488  switch (sa->sa_family)
1489  {
1490  case AF_INET:
1491  {
1492  struct sockaddr_in s4;
1493 
1494  GNUNET_memcpy (&s4,
1495  off,
1496  sizeof(struct sockaddr_in));
1497  alen = sizeof(struct sockaddr_in);
1498  if (is_nat_v4 (&s4.sin_addr))
1499  is_nat = GNUNET_YES;
1500  port = ntohs (s4.sin_port);
1501  }
1502  break;
1503 
1504  case AF_INET6:
1505  {
1506  struct sockaddr_in6 s6;
1507 
1508  GNUNET_memcpy (&s6,
1509  off,
1510  sizeof(struct sockaddr_in6));
1511  alen = sizeof(struct sockaddr_in6);
1512  if (is_nat_v6 (&s6.sin6_addr))
1513  is_nat = GNUNET_YES;
1514  port = ntohs (s6.sin6_port);
1515  }
1516  break;
1517 
1518 #if AF_UNIX
1519  case AF_UNIX:
1520  alen = sizeof(struct sockaddr_un);
1521  port = 0;
1522  break;
1523 #endif
1524  default:
1525  GNUNET_break (0);
1527  return;
1528  }
1529  /* store address */
1530  GNUNET_assert (alen <= left);
1531  GNUNET_assert (alen <= sizeof(struct sockaddr_storage));
1532  GNUNET_memcpy (&ch->caddrs[i].ss,
1533  off,
1534  alen);
1535 
1536  /* If applicable, try UPNPC NAT punching */
1537  if ((is_nat) &&
1538  (enable_upnp) &&
1539  ((IPPROTO_TCP == ch->proto) ||
1540  (IPPROTO_UDP == ch->proto)))
1541  {
1542  ch->natted_address = GNUNET_YES;
1543  ch->caddrs[i].mh
1544  = GNUNET_NAT_mini_map_start (port,
1545  IPPROTO_TCP == ch->proto,
1547  ch);
1548  }
1549 
1550  off += alen;
1551  }
1552 
1553  ch->section_name
1554  = GNUNET_strndup (off,
1555  ntohs (message->str_len));
1557  "Received REGISTER message from client for subsystem `%s'\n",
1558  ch->section_name);
1559  if (GNUNET_OK ==
1561  ch->section_name,
1562  "HOLE_EXTERNAL",
1563  &ch->hole_external))
1564  lookup_hole_external (ch);
1565 
1566  /* Actually send IP address list to client */
1567  for (struct LocalAddressList *lal = lal_head;
1568  NULL != lal;
1569  lal = lal->next)
1570  {
1571  check_notify_client (lal,
1572  ch,
1573  GNUNET_YES);
1574  }
1575  /* Also consider IPv4 determined by `external-ip` */
1576  ch->external_monitor
1578  ch);
1580 }
static struct GNUNET_CADET_Channel * ch
Channel handle.
Definition: gnunet-cadet.c:117
static void check_notify_client(struct LocalAddressList *delta, struct ClientHandle *ch, int add)
Check if we should bother to notify this client about this address change, and if so...
struct GNUNET_NAT_MiniHandle * GNUNET_NAT_mini_map_start(uint16_t port, int is_tcp, GNUNET_NAT_MiniAddressCallback ac, void *ac_cls)
Start mapping the given port using (mini)upnpc.
int natted_address
Is any of the caddrs in a reserved subnet for NAT?
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
char * hole_external
External DNS name and port given by user due to manual hole punching.
uint8_t proto
Client&#39;s IPPROTO, e.g.
Definition: nat.h:109
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
uint16_t str_len
Number of bytes in the string that follow which specifies a section name in the configuration.
Definition: nat.h:115
#define GNUNET_NO
Definition: gnunet_common.h:78
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format...
char * section_name
Name of the configuration section this client cares about.
List of local addresses this system has.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
static int is_nat_v4(const struct in_addr *ip)
Test if the given IPv4 address is in a known range for private networks.
#define GNUNET_new_array(n, type)
Allocate a size n array with structs or unions of the given type.
uint16_t num_caddrs
Number of addresses that this service is bound to.
uint16_t num_addrs
Number of addresses that this service is bound to that follow.
Definition: nat.h:122
uint8_t flags
An enum GNUNET_NAT_RegisterFlags.
Definition: nat.h:104
void GNUNET_SERVICE_client_drop(struct GNUNET_SERVICE_Client *c)
Ask the server to disconnect from the given client.
Definition: service.c:2324
static void notify_client_external_ipv4_change(void *cls, const struct in_addr *v4, int add)
Tell relevant client about a change in our external IPv4 address.
struct GNUNET_SERVICE_Client * client
The handle to this client.
int 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.
Struct containing information about a client, handle to connect to it, and any pending messages that ...
struct GN_ExternalIPMonitor * external_monitor
Handle for monitoring external IP changes.
static void upnp_addr_change_cb(void *cls, int add_remove, const struct sockaddr *addr, socklen_t addrlen, enum GNUNET_NAT_StatusCode result)
Function called whenever our set of external addresses as created by upnpc changes.
struct ClientAddress * caddrs
Array of addresses used by the service.
struct GNUNET_NAT_MiniHandle * mh
Handle to active UPnP request where we asked upnpc to open a port at the NAT.
static const struct GNUNET_CONFIGURATION_Handle * cfg
Handle to our current configuration.
#define GNUNET_strndup(a, length)
Wrapper around GNUNET_xstrndup_.
struct GNUNET_MessageHeader header
Header with type GNUNET_MESSAGE_TYPE_NAT_REGISTER.
Definition: nat.h:99
int enable_upnp
Is UPnP enabled? GNUNET_YES if enabled, GNUNET_NO if disabled, GNUNET_SYSERR if configuration enabled...
uint8_t proto
Client&#39;s IPPROTO, e.g.
Information we track per client address.
static uint16_t port
Port number.
Definition: gnunet-bcd.c:81
#define GNUNET_log(kind,...)
#define GNUNET_YES
Definition: gnunet_common.h:77
struct GN_ExternalIPMonitor * GN_external_ipv4_monitor_start(GN_NotifyExternalIPv4Change cb, void *cb_cls)
Start monitoring external IPv4 addresses.
static void lookup_hole_external(struct ClientHandle *ch)
Resolve the hole_external name to figure out our external address from a manually punched hole...
enum GNUNET_NAT_RegisterFlags flags
What does this client care about?
struct sockaddr_storage ss
Network address used by the client.
void GNUNET_SERVICE_client_continue(struct GNUNET_SERVICE_Client *c)
Continue receiving further messages from the given client.
Definition: service.c:2243
static int is_nat_v6(const struct in6_addr *ip)
Test if the given IPv6 address is in a known range for private networks.
static struct LocalAddressList * lal_head
Head of DLL of local addresses.
struct LocalAddressList * next
This is a linked list.
Here is the call graph for this function:

◆ check_stun()

static int check_stun ( void *  cls,
const struct GNUNET_NAT_HandleStunMessage message 
)
static

Check validity of GNUNET_MESSAGE_TYPE_NAT_HANDLE_STUN message from client.

Parameters
clsclient who sent the message
messagethe message received
Returns
GNUNET_OK if message is well-formed

Definition at line 1592 of file gnunet-service-nat.c.

References GNUNET_break, GNUNET_OK, GNUNET_SYSERR, GNUNET_NAT_HandleStunMessage::header, GNUNET_NAT_HandleStunMessage::payload_size, GNUNET_NAT_HandleStunMessage::sender_addr_size, and GNUNET_MessageHeader::size.

1594 {
1595  size_t sa_len = ntohs (message->sender_addr_size);
1596  size_t expect = sa_len + ntohs (message->payload_size);
1597 
1598  if (ntohs (message->header.size) - sizeof(*message) != expect)
1599  {
1600  GNUNET_break (0);
1601  return GNUNET_SYSERR;
1602  }
1603  if (sa_len < sizeof(sa_family_t))
1604  {
1605  GNUNET_break (0);
1606  return GNUNET_SYSERR;
1607  }
1608  return GNUNET_OK;
1609 }
uint16_t payload_size
Number of bytes of payload included, in NBO.
Definition: nat.h:149
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format...
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
uint16_t sender_addr_size
Size of the sender address included, in NBO.
Definition: nat.h:144
#define GNUNET_SYSERR
Definition: gnunet_common.h:76
struct GNUNET_MessageHeader header
Header with type GNUNET_MESSAGE_TYPE_NAT_HANDLE_STUN.
Definition: nat.h:139

◆ notify_clients_stun_change()

static void notify_clients_stun_change ( const struct sockaddr_in *  ip,
int  add 
)
static

Notify all clients about our external IP address as reported by the STUN server.

Parameters
ipthe external IP
addGNUNET_YES to add, GNUNET_NO to remove

Definition at line 1620 of file gnunet-service-nat.c.

References GNUNET_NAT_AddressChangeNotificationMessage::add_remove, GNUNET_NAT_AddressChangeNotificationMessage::addr_class, ch, env, GNUNET_memcpy, GNUNET_MESSAGE_TYPE_NAT_ADDRESS_CHANGE, GNUNET_MQ_msg_extra, GNUNET_MQ_send(), GNUNET_NAT_AC_EXTERN, GNUNET_NAT_AC_GLOBAL, GNUNET_CADET_Channel::mq, and msg.

Referenced by handle_stun(), and stun_ip_timeout().

1622 {
1623  for (struct ClientHandle *ch = ch_head;
1624  NULL != ch;
1625  ch = ch->next)
1626  {
1627  struct sockaddr_in v4;
1629  struct GNUNET_MQ_Envelope *env;
1630 
1631  if (! ch->natted_address)
1632  continue;
1633  v4 = *ip;
1634  v4.sin_port = htons (0);
1635  env = GNUNET_MQ_msg_extra (msg,
1636  sizeof(v4),
1638  msg->add_remove = htonl ((int32_t) add);
1639  msg->addr_class = htonl (GNUNET_NAT_AC_EXTERN
1641  GNUNET_memcpy (&msg[1],
1642  &v4,
1643  sizeof(v4));
1644  GNUNET_MQ_send (ch->mq,
1645  env);
1646  }
1647 }
Service notifying the client about changes in the set of addresses it has.
Definition: nat.h:201
static struct GNUNET_CADET_Channel * ch
Channel handle.
Definition: gnunet-cadet.c:117
struct GNUNET_MessageHeader * msg
Definition: 005.c:2
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
Addresses that should be our external IP address on the outside of a NAT.
static struct ClientHandle * ch_head
Head of client DLL.
#define GNUNET_MQ_msg_extra(mvar, esize, type)
Allocate an envelope, with extra space allocated after the space needed by the message struct...
Definition: gnunet_mq_lib.h:52
uint32_t addr_class
Type of the address, an enum GNUNET_NAT_AddressClass in NBO.
Definition: nat.h:216
Struct containing information about a client, handle to connect to it, and any pending messages that ...
Addresses that are global (i.e.
struct GNUNET_MQ_Handle * mq
Message Queue for the channel (which we are implementing).
Definition: cadet_api.c:106
int32_t add_remove
GNUNET_YES to add, GNUNET_NO to remove the address from the list.
Definition: nat.h:211
struct GNUNET_MQ_Envelope * env
Definition: 005.c:1
#define GNUNET_MESSAGE_TYPE_NAT_ADDRESS_CHANGE
Message to from NAT service notifying us that one of our addresses changed.
static int add
Desired action is to add a record.
void GNUNET_MQ_send(struct GNUNET_MQ_Handle *mq, struct GNUNET_MQ_Envelope *ev)
Send a message with the given message queue.
Definition: mq.c:353
Here is the call graph for this function:
Here is the caller graph for this function:

◆ stun_ip_timeout()

static void stun_ip_timeout ( void *  cls)
static

Function to be called when we decide that an external IP address as told to us by a STUN server has gone stale.

Parameters
clsthe struct StunExternalIP to drop

Definition at line 1658 of file gnunet-service-nat.c.

References StunExternalIP::external_addr, GNUNET_CONTAINER_DLL_remove, GNUNET_free, GNUNET_NO, notify_clients_stun_change(), and StunExternalIP::timeout_task.

Referenced by handle_stun().

1659 {
1660  struct StunExternalIP *se = cls;
1661 
1662  se->timeout_task = NULL;
1664  GNUNET_NO);
1666  se_tail,
1667  se);
1668  GNUNET_free (se);
1669 }
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
External IP address as given to us via some STUN server.
#define GNUNET_NO
Definition: gnunet_common.h:78
static struct StunExternalIP * se_tail
Kept in a DLL.
struct sockaddr_in external_addr
Our external IP address as reported by the STUN server.
static void notify_clients_stun_change(const struct sockaddr_in *ip, int add)
Notify all clients about our external IP address as reported by the STUN server.
struct GNUNET_SCHEDULER_Task * timeout_task
Task we run to remove this entry when it is stale.
static struct StunExternalIP * se_head
Kept in a DLL.
#define GNUNET_free(ptr)
Wrapper around free.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ handle_stun()

static void handle_stun ( void *  cls,
const struct GNUNET_NAT_HandleStunMessage message 
)
static

Handler for GNUNET_MESSAGE_TYPE_NAT_HANDLE_STUN message from client.

Parameters
clsclient who sent the message
messagethe message received

Definition at line 1680 of file gnunet-service-nat.c.

References buf, ch, ClientHandle::client, StunExternalIP::external_addr, GNUNET_break, GNUNET_CONTAINER_DLL_insert, GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_memcmp, GNUNET_memcpy, GNUNET_NAT_stun_handle_packet_(), GNUNET_new, GNUNET_NO, GNUNET_OK, GNUNET_SCHEDULER_add_delayed(), GNUNET_SCHEDULER_cancel(), GNUNET_SERVICE_client_continue(), GNUNET_SERVICE_client_drop(), GNUNET_YES, StunExternalIP::next, notify_clients_stun_change(), payload, GNUNET_NAT_HandleStunMessage::payload_size, GNUNET_NAT_HandleStunMessage::sender_addr_size, stun_ip_timeout(), StunExternalIP::stun_server_addr, StunExternalIP::stun_server_addr_len, stun_stale_timeout, and StunExternalIP::timeout_task.

1682 {
1683  struct ClientHandle *ch = cls;
1684  const char *buf = (const char *) &message[1];
1685  const struct sockaddr *sa;
1686  const void *payload;
1687  size_t sa_len;
1688  size_t payload_size;
1689  struct sockaddr_in external_addr;
1690 
1691  sa_len = ntohs (message->sender_addr_size);
1692  payload_size = ntohs (message->payload_size);
1693  sa = (const struct sockaddr *) &buf[0];
1694  payload = (const struct sockaddr *) &buf[sa_len];
1695  switch (sa->sa_family)
1696  {
1697  case AF_INET:
1698  if (sa_len != sizeof(struct sockaddr_in))
1699  {
1700  GNUNET_break (0);
1702  return;
1703  }
1704  break;
1705 
1706  case AF_INET6:
1707  if (sa_len != sizeof(struct sockaddr_in6))
1708  {
1709  GNUNET_break (0);
1711  return;
1712  }
1713  break;
1714  }
1716  "Received HANDLE_STUN message from client\n");
1717  if (GNUNET_OK ==
1719  payload_size,
1720  &external_addr))
1721  {
1722  /* We now know that a server at "sa" claims that
1723  we are visible at IP "external_addr".
1724 
1725  We should (for some fixed period of time) tell
1726  all of our clients that listen to a NAT'ed address
1727  that they might want to consider the given 'external_ip'
1728  as their public IP address (this includes TCP and UDP
1729  clients, even if only UDP sends STUN requests).
1730 
1731  If we do not get a renewal, the "external_addr" should be
1732  removed again. The timeout frequency should be configurable
1733  (with a sane default), so that the UDP plugin can tell how
1734  often to re-request STUN.
1735  */struct StunExternalIP *se;
1736 
1737  /* Check if we had a prior response from this STUN server */
1738  for (se = se_head; NULL != se; se = se->next)
1739  {
1740  if ((se->stun_server_addr_len != sa_len) ||
1741  (0 != memcmp (sa,
1742  &se->stun_server_addr,
1743  sa_len)))
1744  continue; /* different STUN server */
1745  if (0 != GNUNET_memcmp (&external_addr,
1746  &se->external_addr))
1747  {
1748  /* external IP changed, update! */
1750  GNUNET_NO);
1753  GNUNET_YES);
1754  }
1755  /* update timeout */
1757  se->timeout_task
1759  &stun_ip_timeout,
1760  se);
1761  return;
1762  }
1763  /* STUN server is completely new, create fresh entry */
1764  se = GNUNET_new (struct StunExternalIP);
1767  sa,
1768  sa_len);
1769  se->stun_server_addr_len = sa_len;
1771  &stun_ip_timeout,
1772  se);
1774  se_tail,
1775  se);
1777  GNUNET_NO);
1778  }
1780 }
static struct GNUNET_TIME_Relative stun_stale_timeout
Timeout to use when STUN data is considered stale.
External IP address as given to us via some STUN server.
static struct GNUNET_CADET_Channel * ch
Channel handle.
Definition: gnunet-cadet.c:117
size_t stun_server_addr_len
Number of bytes used in stun_server_addr.
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
uint16_t payload_size
Number of bytes of payload included, in NBO.
Definition: nat.h:149
#define GNUNET_NO
Definition: gnunet_common.h:78
static struct StunExternalIP * se_tail
Kept in a DLL.
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
#define GNUNET_new(type)
Allocate a struct or union of the given type.
struct sockaddr_in external_addr
Our external IP address as reported by the STUN server.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
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:1253
uint16_t sender_addr_size
Size of the sender address included, in NBO.
Definition: nat.h:144
int GNUNET_NAT_stun_handle_packet_(const void *data, size_t len, struct sockaddr_in *arg)
Handle an incoming STUN response.
static char buf[2048]
void GNUNET_SERVICE_client_drop(struct GNUNET_SERVICE_Client *c)
Ask the server to disconnect from the given client.
Definition: service.c:2324
struct GNUNET_SERVICE_Client * client
The handle to this client.
static void stun_ip_timeout(void *cls)
Function to be called when we decide that an external IP address as told to us by a STUN server has g...
Struct containing information about a client, handle to connect to it, and any pending messages that ...
static void notify_clients_stun_change(const struct sockaddr_in *ip, int add)
Notify all clients about our external IP address as reported by the STUN server.
static unsigned long long payload
How much data are we currently storing in the database?
#define GNUNET_memcmp(a, b)
Compare memory in a and b, where both must be of the same pointer type.
#define GNUNET_log(kind,...)
struct GNUNET_SCHEDULER_Task * timeout_task
Task we run to remove this entry when it is stale.
#define GNUNET_YES
Definition: gnunet_common.h:77
struct StunExternalIP * next
Kept in a DLL.
void GNUNET_SERVICE_client_continue(struct GNUNET_SERVICE_Client *c)
Continue receiving further messages from the given client.
Definition: service.c:2243
static struct StunExternalIP * se_head
Kept in a DLL.
struct sockaddr_storage stun_server_addr
Address of the reporting STUN server.
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:966
Here is the call graph for this function:

◆ check_request_connection_reversal()

static int check_request_connection_reversal ( void *  cls,
const struct GNUNET_NAT_RequestConnectionReversalMessage message 
)
static

Check validity of GNUNET_MESSAGE_TYPE_NAT_REQUEST_CONNECTION_REVERSAL message from client.

Parameters
clsclient who sent the message
messagethe message received
Returns
GNUNET_OK if message is well-formed

Definition at line 1793 of file gnunet-service-nat.c.

References GNUNET_break, GNUNET_OK, GNUNET_SYSERR, GNUNET_NAT_RequestConnectionReversalMessage::header, GNUNET_NAT_RequestConnectionReversalMessage::local_addr_size, GNUNET_NAT_RequestConnectionReversalMessage::remote_addr_size, and GNUNET_MessageHeader::size.

1797 {
1798  size_t expect;
1799 
1800  expect = ntohs (message->local_addr_size)
1801  + ntohs (message->remote_addr_size);
1802  if (ntohs (message->header.size) - sizeof(*message) != expect)
1803  {
1804  GNUNET_break (0);
1805  return GNUNET_SYSERR;
1806  }
1807  return GNUNET_OK;
1808 }
uint16_t remote_addr_size
Size of the remote address included, in NBO.
Definition: nat.h:175
struct GNUNET_MessageHeader header
Header with type GNUNET_MESSAGE_TYPE_NAT_REQUEST_CONNECTION_REVERSAL.
Definition: nat.h:165
uint16_t local_addr_size
Size of the local address included, in NBO.
Definition: nat.h:170
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format...
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
#define GNUNET_SYSERR
Definition: gnunet_common.h:76

◆ handle_request_connection_reversal()

static void handle_request_connection_reversal ( void *  cls,
const struct GNUNET_NAT_RequestConnectionReversalMessage message 
)
static

Handler for GNUNET_MESSAGE_TYPE_NAT_REQUEST_CONNECTION_REVERSAL message from client.

Parameters
clsclient who sent the message
messagethe message received

Definition at line 1819 of file gnunet-service-nat.c.

References _, buf, ch, ClientHandle::client, GN_request_connection_reversal(), GNUNET_break_op, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_WARNING, GNUNET_log, GNUNET_memcpy, GNUNET_OK, GNUNET_SERVICE_client_continue(), GNUNET_SERVICE_client_drop(), GNUNET_NAT_RequestConnectionReversalMessage::local_addr_size, GNUNET_NAT_RequestConnectionReversalMessage::remote_addr_size, and ret.

1823 {
1824  struct ClientHandle *ch = cls;
1825  const char *buf = (const char *) &message[1];
1826  size_t local_sa_len = ntohs (message->local_addr_size);
1827  size_t remote_sa_len = ntohs (message->remote_addr_size);
1828  struct sockaddr_in l4;
1829  struct sockaddr_in r4;
1830  int ret;
1831 
1833  "Received REQUEST CONNECTION REVERSAL message from client\n");
1834  if (local_sa_len != sizeof(struct sockaddr_in))
1835  {
1836  GNUNET_break_op (0);
1838  return;
1839  }
1840  if (remote_sa_len != sizeof(struct sockaddr_in))
1841  {
1842  GNUNET_break_op (0);
1844  return;
1845  }
1846  GNUNET_memcpy (&l4,
1847  buf,
1848  sizeof(struct sockaddr_in));
1849  GNUNET_break_op (AF_INET == l4.sin_family);
1850  buf += sizeof(struct sockaddr_in);
1851  GNUNET_memcpy (&r4,
1852  buf,
1853  sizeof(struct sockaddr_in));
1854  GNUNET_break_op (AF_INET == r4.sin_family);
1855  ret = GN_request_connection_reversal (&l4.sin_addr,
1856  ntohs (l4.sin_port),
1857  &r4.sin_addr,
1858  cfg);
1859  if (GNUNET_OK != ret)
1861  _ ("Connection reversal request failed\n"));
1863 }
static struct GNUNET_CADET_Channel * ch
Channel handle.
Definition: gnunet-cadet.c:117
uint16_t remote_addr_size
Size of the remote address included, in NBO.
Definition: nat.h:175
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
static int ret
Return value of the commandline.
Definition: gnunet-abd.c:81
uint16_t local_addr_size
Size of the local address included, in NBO.
Definition: nat.h:170
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
#define _(String)
GNU gettext support macro.
Definition: platform.h:181
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
static char buf[2048]
void GNUNET_SERVICE_client_drop(struct GNUNET_SERVICE_Client *c)
Ask the server to disconnect from the given client.
Definition: service.c:2324
struct GNUNET_SERVICE_Client * client
The handle to this client.
Struct containing information about a client, handle to connect to it, and any pending messages that ...
static const struct GNUNET_CONFIGURATION_Handle * cfg
Handle to our current configuration.
int GN_request_connection_reversal(const struct in_addr *internal_address, uint16_t internal_port, const struct in_addr *remote_v4, const struct GNUNET_CONFIGURATION_Handle *cfg)
We want to connect to a peer that is behind NAT.
#define GNUNET_log(kind,...)
void GNUNET_SERVICE_client_continue(struct GNUNET_SERVICE_Client *c)
Continue receiving further messages from the given client.
Definition: service.c:2243
Here is the call graph for this function:

◆ shutdown_task()

static void shutdown_task ( void *  cls)
static

Task run during shutdown.

Parameters
clsunused

Definition at line 1872 of file gnunet-service-nat.c.

References destroy_lal(), GN_nat_status_changed(), GNUNET_CONTAINER_DLL_remove, GNUNET_free, GNUNET_NO, GNUNET_SCHEDULER_cancel(), GNUNET_STATISTICS_destroy(), and StunExternalIP::timeout_task.

Referenced by run().

1873 {
1874  struct StunExternalIP *se;
1875 
1876  while (NULL != (se = se_head))
1877  {
1879  se_tail,
1880  se);
1882  GNUNET_free (se);
1883  }
1885  if (NULL != scan_task)
1886  {
1888  scan_task = NULL;
1889  }
1890  if (NULL != stats)
1891  {
1893  GNUNET_NO);
1894  stats = NULL;
1895  }
1896  destroy_lal ();
1897 }
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
External IP address as given to us via some STUN server.
static struct GNUNET_STATISTICS_Handle * stats
Handle to the statistics service.
#define GNUNET_NO
Definition: gnunet_common.h:78
static struct StunExternalIP * se_tail
Kept in a DLL.
void GNUNET_STATISTICS_destroy(struct GNUNET_STATISTICS_Handle *h, int sync_first)
Destroy a handle (free all state associated with it).
static struct GNUNET_SCHEDULER_Task * scan_task
Task scheduled to periodically scan our network interfaces.
static void destroy_lal()
Free the DLL starting at lal_head.
struct GNUNET_SCHEDULER_Task * timeout_task
Task we run to remove this entry when it is stale.
void GN_nat_status_changed(int have_nat)
We have changed our opinion about being NATed in the first place.
static struct StunExternalIP * se_head
Kept in a DLL.
#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:966
Here is the call graph for this function:
Here is the caller graph for this function:

◆ run()

static void run ( void *  cls,
const struct GNUNET_CONFIGURATION_Handle c,
struct GNUNET_SERVICE_Handle service 
)
static

Setup NAT service.

Parameters
clsclosure
cconfiguration to use
servicethe initialized service

Definition at line 1908 of file gnunet-service-nat.c.

References _, DYNDNS_FREQUENCY, dyndns_frequency, enable_ipscan, enable_upnp, GNUNET_CONFIGURATION_get_value_time(), GNUNET_CONFIGURATION_get_value_yesno(), GNUNET_ERROR_TYPE_ERROR, GNUNET_log, GNUNET_NO, GNUNET_OK, GNUNET_OS_check_helper_binary(), GNUNET_SCHEDULER_add_now(), GNUNET_SCHEDULER_add_shutdown(), GNUNET_STATISTICS_create(), GNUNET_SYSERR, GNUNET_TIME_UNIT_HOURS, GNUNET_YES, run_scan(), shutdown_task(), and stun_stale_timeout.

Referenced by client_disconnect_cb().

1911 {
1912  cfg = c;
1913  if (GNUNET_OK !=
1915  "NAT",
1916  "STUN_STALE",
1919 
1920  /* Check for UPnP */
1921  enable_upnp
1923  "NAT",
1924  "ENABLE_UPNP");
1925  if (GNUNET_YES == enable_upnp)
1926  {
1927  /* check if it works */
1928  if (GNUNET_SYSERR ==
1930  GNUNET_NO,
1931  NULL))
1932  {
1934  _ (
1935  "UPnP enabled in configuration, but UPnP client `upnpc` command not found, disabling UPnP\n"));
1937  }
1938  }
1939  if (GNUNET_OK !=
1941  "nat",
1942  "DYNDNS_FREQUENCY",
1943  &dyndns_frequency))
1945 
1948  "NAT",
1949  "ENABLE_IPSCAN");
1950 
1952  NULL);
1954  cfg);
1955  if (GNUNET_YES == enable_ipscan)
1957  NULL);
1958 }
static struct GNUNET_TIME_Relative stun_stale_timeout
Timeout to use when STUN data is considered stale.
static void run_scan(void *cls)
Task we run periodically to scan for network interfaces.
int GNUNET_CONFIGURATION_get_value_time(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, struct GNUNET_TIME_Relative *time)
Get a configuration value that should be a relative time.
#define GNUNET_TIME_UNIT_HOURS
One hour.
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_shutdown(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run on shutdown, that is when a CTRL-C signal is received, or when GNUNET_SCHEDULER_shutdown() is being invoked.
Definition: scheduler.c:1300
struct GNUNET_STATISTICS_Handle * GNUNET_STATISTICS_create(const char *subsystem, const struct GNUNET_CONFIGURATION_Handle *cfg)
Get handle for the statistics service.
static struct GNUNET_STATISTICS_Handle * stats
Handle to the statistics service.
#define GNUNET_NO
Definition: gnunet_common.h:78
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
int GNUNET_OS_check_helper_binary(const char *binary, int check_suid, const char *params)
Check whether an executable exists and possibly if the suid bit is set on the file.
static struct GNUNET_SCHEDULER_Task * scan_task
Task scheduled to periodically scan our network interfaces.
#define _(String)
GNU gettext support macro.
Definition: platform.h:181
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:1280
#define DYNDNS_FREQUENCY
How often do we scan for changes in how our external (dyndns) hostname resolves?
int enable_ipscan
Is IP Scanning enabled? GNUNET_YES if enabled, GNUNET_NO if disabled, without, only explicitly specif...
static void shutdown_task(void *cls)
Task run during shutdown.
#define GNUNET_SYSERR
Definition: gnunet_common.h:76
static const struct GNUNET_CONFIGURATION_Handle * cfg
Handle to our current configuration.
int enable_upnp
Is UPnP enabled? GNUNET_YES if enabled, GNUNET_NO if disabled, GNUNET_SYSERR if configuration enabled...
#define GNUNET_log(kind,...)
#define GNUNET_YES
Definition: gnunet_common.h:77
static struct GNUNET_TIME_Relative dyndns_frequency
How often do we scan for changes in how our external (dyndns) hostname resolves?
int GNUNET_CONFIGURATION_get_value_yesno(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option)
Get a configuration value that should be in a set of "YES" or "NO".
Here is the call graph for this function:
Here is the caller graph for this function:

◆ client_connect_cb()

static void* client_connect_cb ( void *  cls,
struct GNUNET_SERVICE_Client c,
struct GNUNET_MQ_Handle mq 
)
static

Callback called when a client connects to the service.

Parameters
clsclosure for the service
cthe new client that connected to the service
mqthe message queue used to send messages to the client
Returns
a struct ClientHandle

Definition at line 1970 of file gnunet-service-nat.c.

References ch, ClientHandle::client, GNUNET_CONTAINER_DLL_insert, GNUNET_new, mq, and ClientHandle::mq.

Referenced by client_disconnect_cb().

1973 {
1974  struct ClientHandle *ch;
1975 
1976  ch = GNUNET_new (struct ClientHandle);
1977  ch->mq = mq;
1978  ch->client = c;
1980  ch_tail,
1981  ch);
1982  return ch;
1983 }
static struct GNUNET_CADET_Channel * ch
Channel handle.
Definition: gnunet-cadet.c:117
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
static struct ClientHandle * ch_head
Head of client DLL.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
static struct ClientHandle * ch_tail
Tail of client DLL.
struct GNUNET_SERVICE_Client * client
The handle to this client.
Struct containing information about a client, handle to connect to it, and any pending messages that ...
struct GNUNET_MQ_Handle * mq
The message queue to this client.
struct GNUNET_MQ_Handle * mq
Definition: 003.c:5
Here is the caller graph for this function:

◆ client_disconnect_cb()

static void client_disconnect_cb ( void *  cls,
struct GNUNET_SERVICE_Client c,
void *  internal_cls 
)
static

Callback called when a client disconnected from the service.

Parameters
clsclosure for the service
cthe client that disconnected
internal_clsa struct ClientHandle *

Definition at line 1994 of file gnunet-service-nat.c.

References __attribute__, ClientHandle::caddrs, ch, client_connect_cb(), ClientHandle::ext_addr_head, ClientHandle::ext_addr_tail, ClientHandle::ext_dns, ClientHandle::ext_dns_task, ClientHandle::external_monitor, GN_external_ipv4_monitor_stop(), GNUNET_CONTAINER_DLL_remove, GNUNET_free, GNUNET_free_non_null, GNUNET_MESSAGE_TYPE_NAT_HANDLE_STUN, GNUNET_MESSAGE_TYPE_NAT_REGISTER, GNUNET_MESSAGE_TYPE_NAT_REQUEST_CONNECTION_REVERSAL, GNUNET_MQ_handler_end, GNUNET_MQ_hd_var_size, GNUNET_NAT_mini_map_stop(), GNUNET_RESOLVER_request_cancel(), GNUNET_SCHEDULER_cancel(), GNUNET_SERVICE_MAIN(), GNUNET_SERVICE_OPTION_NONE, ClientHandle::hole_external, ClientAddress::mh, ClientHandle::num_caddrs, run(), and ClientHandle::section_name.

1997 {
1998  struct ClientHandle *ch = internal_cls;
1999  struct LocalAddressList *lal;
2000 
2002  ch_tail,
2003  ch);
2004  for (unsigned int i = 0; i < ch->num_caddrs; i++)
2005  {
2006  if (NULL != ch->caddrs[i].mh)
2007  {
2009  ch->caddrs[i].mh = NULL;
2010  }
2011  }
2013  while (NULL != (lal = ch->ext_addr_head))
2014  {
2016  ch->ext_addr_tail,
2017  lal);
2018  GNUNET_free (lal);
2019  }
2020  if (NULL != ch->ext_dns_task)
2021  {
2023  ch->ext_dns_task = NULL;
2024  }
2025  if (NULL != ch->external_monitor)
2026  {
2028  ch->external_monitor = NULL;
2029  }
2030  if (NULL != ch->ext_dns)
2031  {
2033  ch->ext_dns = NULL;
2034  }
2037  GNUNET_free (ch);
2038 }
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
static struct GNUNET_CADET_Channel * ch
Channel handle.
Definition: gnunet-cadet.c:117
void GNUNET_RESOLVER_request_cancel(struct GNUNET_RESOLVER_RequestHandle *rh)
Cancel a request that is still pending with the resolver.
char * hole_external
External DNS name and port given by user due to manual hole punching.
void GN_external_ipv4_monitor_stop(struct GN_ExternalIPMonitor *mon)
Stop calling monitor.
static struct ClientHandle * ch_head
Head of client DLL.
struct GNUNET_SCHEDULER_Task * ext_dns_task
Task for periodically re-running the ext_dns DNS lookup.
#define GNUNET_free_non_null(ptr)
Free the memory pointed to by ptr if ptr is not NULL.
char * section_name
Name of the configuration section this client cares about.
List of local addresses this system has.
static struct ClientHandle * ch_tail
Tail of client DLL.
void GNUNET_NAT_mini_map_stop(struct GNUNET_NAT_MiniHandle *mini)
Remove a mapping created with (mini)upnpc.
struct GNUNET_RESOLVER_RequestHandle * ext_dns
Handle for (DYN)DNS lookup of our external IP as given in hole_external.
uint16_t num_caddrs
Number of addresses that this service is bound to.
struct LocalAddressList * ext_addr_tail
DLL of external IP addresses as given in hole_external.
Struct containing information about a client, handle to connect to it, and any pending messages that ...
struct GN_ExternalIPMonitor * external_monitor
Handle for monitoring external IP changes.
struct ClientAddress * caddrs
Array of addresses used by the service.
struct GNUNET_NAT_MiniHandle * mh
Handle to active UPnP request where we asked upnpc to open a port at the NAT.
struct LocalAddressList * ext_addr_head
DLL of external IP addresses as given in hole_external.
#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:966
Here is the call graph for this function:

◆ GNUNET_SERVICE_MAIN()

GNUNET_SERVICE_MAIN ( "nat"  ,
GNUNET_SERVICE_OPTION_NONE  ,
run,
client_connect_cb,
client_disconnect_cb,
NULL  ,
GNUNET_MQ_hd_var_size(register, GNUNET_MESSAGE_TYPE_NAT_REGISTER, struct GNUNET_NAT_RegisterMessage, NULL)  ,
GNUNET_MQ_hd_var_size(stun, GNUNET_MESSAGE_TYPE_NAT_HANDLE_STUN, struct GNUNET_NAT_HandleStunMessage, NULL)  ,
GNUNET_MQ_hd_var_size(request_connection_reversal, GNUNET_MESSAGE_TYPE_NAT_REQUEST_CONNECTION_REVERSAL, struct GNUNET_NAT_RequestConnectionReversalMessage, NULL)  ,
GNUNET_MQ_handler_end()   
)

Define "main" method using service macro.

Referenced by client_disconnect_cb().

Here is the caller graph for this function:

Variable Documentation

◆ stun_stale_timeout

struct GNUNET_TIME_Relative stun_stale_timeout
static

Timeout to use when STUN data is considered stale.

Definition at line 280 of file gnunet-service-nat.c.

Referenced by handle_stun(), and run().

◆ dyndns_frequency

struct GNUNET_TIME_Relative dyndns_frequency
static

How often do we scan for changes in how our external (dyndns) hostname resolves?

Definition at line 285 of file gnunet-service-nat.c.

Referenced by process_external_ip(), and run().

◆ cfg

const struct GNUNET_CONFIGURATION_Handle* cfg
static

Handle to our current configuration.

Definition at line 290 of file gnunet-service-nat.c.

◆ stats

struct GNUNET_STATISTICS_Handle* stats
static

Handle to the statistics service.

Definition at line 295 of file gnunet-service-nat.c.

◆ scan_task

struct GNUNET_SCHEDULER_Task* scan_task
static

Task scheduled to periodically scan our network interfaces.

Definition at line 300 of file gnunet-service-nat.c.

◆ ch_head

struct ClientHandle* ch_head
static

Head of client DLL.

Definition at line 305 of file gnunet-service-nat.c.

◆ ch_tail

struct ClientHandle* ch_tail
static

Tail of client DLL.

Definition at line 310 of file gnunet-service-nat.c.

◆ lal_head

struct LocalAddressList* lal_head
static

Head of DLL of local addresses.

Definition at line 315 of file gnunet-service-nat.c.

◆ lal_tail

struct LocalAddressList* lal_tail
static

Tail of DLL of local addresses.

Definition at line 320 of file gnunet-service-nat.c.

◆ se_head

struct StunExternalIP* se_head
static

Kept in a DLL.

Definition at line 325 of file gnunet-service-nat.c.

◆ se_tail

struct StunExternalIP* se_tail
static

Kept in a DLL.

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

◆ enable_upnp

int enable_upnp

Is UPnP enabled? GNUNET_YES if enabled, GNUNET_NO if disabled, GNUNET_SYSERR if configuration enabled but binary is unavailable.

Definition at line 336 of file gnunet-service-nat.c.

Referenced by GN_nat_status_changed(), handle_register(), and run().

◆ enable_ipscan

int enable_ipscan

Is IP Scanning enabled? GNUNET_YES if enabled, GNUNET_NO if disabled, without, only explicitly specified IPs will be handled (HOLE_EXTERNAL)

Definition at line 342 of file gnunet-service-nat.c.

Referenced by run().