GNUnet  0.10.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   GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
 How long do we wait until we forcefully terminate autoconfiguration? More...
 
#define DYNDNS_FREQUENCY   GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 7)
 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...
 

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   GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)

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   GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 7)

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

Definition at line 68 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 347 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().

348 {
350  lal_tail,
351  lal);
352  if (NULL != lal->hc)
353  {
355  "Lost NATed local address %s, stopping NAT server\n",
356  GNUNET_a2s ((const struct sockaddr *) &lal->addr,
357  sizeof (struct sockaddr_in)));
358 
360  lal->hc = NULL;
361  }
362  GNUNET_free (lal);
363 }
#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 370 of file gnunet-service-nat.c.

References free_lal().

Referenced by shutdown_task().

371 {
372  struct LocalAddressList *lal;
373 
374  while (NULL != (lal = lal_head))
375  free_lal (lal);
376 }
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 388 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.

390 {
391  uint16_t num_addrs = ntohs (message->num_addrs);
392  const char *off = (const char *) &message[1];
393  size_t left = ntohs (message->header.size) - sizeof (*message);
394 
395  for (unsigned int i=0;i<num_addrs;i++)
396  {
397  size_t alen;
398  const struct sockaddr *sa = (const struct sockaddr *) off;
399 
400  if (sizeof (sa_family_t) > left)
401  {
402  GNUNET_break (0);
403  return GNUNET_SYSERR;
404  }
405  switch (sa->sa_family)
406  {
407  case AF_INET:
408  alen = sizeof (struct sockaddr_in);
409  break;
410  case AF_INET6:
411  alen = sizeof (struct sockaddr_in6);
412  break;
413 #if AF_UNIX
414  case AF_UNIX:
415  alen = sizeof (struct sockaddr_un);
416  break;
417 #endif
418  default:
419  GNUNET_break (0);
420  return GNUNET_SYSERR;
421  }
422  if (alen > left)
423  {
424  GNUNET_break (0);
425  return GNUNET_SYSERR;
426  }
427  off += alen;
428  left -= alen;
429  }
430  if (left != ntohs (message->str_len))
431  {
432  GNUNET_break (0);
433  return GNUNET_SYSERR;
434  }
435  return GNUNET_OK;
436 }
uint16_t str_len
Number of bytes in the string that follow which specifies a section name in the configuration.
Definition: nat.h:117
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:78
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:124
#define GNUNET_SYSERR
Definition: gnunet_common.h:79
struct GNUNET_MessageHeader header
Header with type GNUNET_MESSAGE_TYPE_NAT_REGISTER.
Definition: nat.h:101

◆ 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 448 of file gnunet-service-nat.c.

References GNUNET_assert, GNUNET_YES, and inet_pton().

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

451 {
452  struct in_addr net;
453 
454  if (0 == ip->s_addr)
455  return GNUNET_YES;
456  if (0 == bits)
457  return GNUNET_YES;
458  GNUNET_assert (1 == inet_pton (AF_INET,
459  network,
460  &net));
461  return ! ((ip->s_addr ^ net.s_addr) & htonl (0xFFFFFFFFu << (32 - bits)));
462 }
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
static int inet_pton(int af, const char *cp, struct in_addr *buf)
Convert IPv4 address from text to binary form.
#define GNUNET_YES
Definition: gnunet_common.h:80
Here is the call graph for this function:
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 474 of file gnunet-service-nat.c.

References GNUNET_assert, GNUNET_memcmp, GNUNET_NO, GNUNET_YES, and inet_pton().

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

477 {
478  struct in6_addr net;
479  struct in6_addr mask;
480  unsigned int off;
481 
482  if (0 == bits)
483  return GNUNET_YES;
484  GNUNET_assert (1 == inet_pton (AF_INET6,
485  network,
486  &net));
487  memset (&mask, 0, sizeof (mask));
488  if (0 == GNUNET_memcmp (&mask,
489  ip))
490  return GNUNET_YES;
491  off = 0;
492  while (bits > 8)
493  {
494  mask.s6_addr[off++] = 0xFF;
495  bits -= 8;
496  }
497  while (bits > 0)
498  {
499  mask.s6_addr[off] = (mask.s6_addr[off] >> 1) + 0x80;
500  bits--;
501  }
502  for (unsigned j = 0; j < sizeof (struct in6_addr) / sizeof (uint32_t); j++)
503  if (((((uint32_t *) ip)[j] & ((uint32_t *) &mask)[j])) !=
504  (((uint32_t *) &net)[j] & ((int *) &mask)[j]))
505  return GNUNET_NO;
506  return GNUNET_YES;
507 }
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_NO
Definition: gnunet_common.h:81
#define GNUNET_memcmp(a, b)
Compare memory in a and b, where both must be of the same pointer type.
static int inet_pton(int af, const char *cp, struct in_addr *buf)
Convert IPv4 address from text to binary form.
#define GNUNET_YES
Definition: gnunet_common.h:80
Here is the call graph for this function:
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 518 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().

519 {
520  return
521  match_ipv4 ("10.0.0.0", ip, 8) || /* RFC 1918 */
522  match_ipv4 ("100.64.0.0", ip, 10) || /* CG-NAT, RFC 6598 */
523  match_ipv4 ("192.168.0.0", ip, 12) || /* RFC 1918 */
524  match_ipv4 ("169.254.0.0", ip, 16) || /* AUTO, RFC 3927 */
525  match_ipv4 ("172.16.0.0", ip, 16); /* RFC 1918 */
526 }
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 537 of file gnunet-service-nat.c.

References match_ipv6().

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

538 {
539  return
540  match_ipv6 ("fc00::", ip, 7) || /* RFC 4193 */
541  match_ipv6 ("fec0::", ip, 10) || /* RFC 3879 */
542  match_ipv6 ("fe80::", ip, 10); /* RFC 4291, link-local */
543 }
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 579 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, ip4, ip6, is_nat_v4(), is_nat_v6(), IfcProcContext::lal_head, IfcProcContext::lal_tail, match_ipv4(), and match_ipv6().

Referenced by run_scan().

586 {
587  struct IfcProcContext *ifc_ctx = cls;
588  struct LocalAddressList *lal;
589  size_t alen;
590  const struct in_addr *ip4;
591  const struct in6_addr *ip6;
593 
594  switch (addr->sa_family)
595  {
596  case AF_INET:
597  alen = sizeof (struct sockaddr_in);
598  ip4 = &((const struct sockaddr_in *) addr)->sin_addr;
599  if (match_ipv4 ("127.0.0.0", ip4, 8))
601  else if (is_nat_v4 (ip4))
602  ac = GNUNET_NAT_AC_LAN;
603  else
605  break;
606  case AF_INET6:
607  alen = sizeof (struct sockaddr_in6);
608  ip6 = &((const struct sockaddr_in6 *) addr)->sin6_addr;
609  if (match_ipv6 ("::1", ip6, 128))
611  else if (is_nat_v6 (ip6))
612  ac = GNUNET_NAT_AC_LAN;
613  else
615  if ( (ip6->s6_addr[11] == 0xFF) &&
616  (ip6->s6_addr[12] == 0xFE) )
617  {
618  /* contains a MAC, be extra careful! */
619  ac |= GNUNET_NAT_AC_PRIVATE;
620  }
621  break;
622 #if AF_UNIX
623  case AF_UNIX:
624  GNUNET_break (0);
625  return GNUNET_OK;
626 #endif
627  default:
628  GNUNET_break (0);
629  return GNUNET_OK;
630  }
631  lal = GNUNET_malloc (sizeof (*lal));
632  lal->af = addr->sa_family;
633  lal->ac = ac;
634  GNUNET_memcpy (&lal->addr,
635  addr,
636  alen);
638  ifc_ctx->lal_tail,
639  lal);
640  return GNUNET_OK;
641 }
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_OK
Named constants for return values.
Definition: gnunet_common.h:78
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.
#define GNUNET_memcpy(dst, src, n)
static int match_ipv4(const char *network, const struct in_addr *ip, uint8_t bits)
Check if ip is in network with bits netmask.
GUID ip4
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?
GUID ip6
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 655 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().

660 {
661  struct GNUNET_MQ_Envelope *env;
663 
665  "Notifying client about %s of IP %s\n",
666  add ? "addition" : "removal",
667  GNUNET_a2s (addr,
668  addr_len));
669  env = GNUNET_MQ_msg_extra (msg,
670  addr_len,
672  msg->add_remove = htonl (add);
673  msg->addr_class = htonl (ac);
674  GNUNET_memcpy (&msg[1],
675  addr,
676  addr_len);
677  GNUNET_MQ_send (ch->mq,
678  env);
679 }
Service notifying the client about changes in the set of addresses it has.
Definition: nat.h:206
struct GNUNET_MessageHeader * msg
Definition: 005.c:2
#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
#define GNUNET_memcpy(dst, src, n)
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:221
int32_t add_remove
GNUNET_YES to add, GNUNET_NO to remove the address from the list.
Definition: nat.h:216
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 691 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().

694 {
695  size_t alen;
696  struct sockaddr_in v4;
697  struct sockaddr_in6 v6;
698 
699  if (0 == (ch->flags & GNUNET_NAT_RF_ADDRESSES))
700  {
702  "Not notifying client as it does not care about addresses\n");
703  return;
704  }
705  switch (delta->af)
706  {
707  case AF_INET:
708  alen = sizeof (struct sockaddr_in);
709  GNUNET_memcpy (&v4,
710  &delta->addr,
711  alen);
712 
713  /* Check for client notifications */
714  for (unsigned int i=0;i<ch->num_caddrs;i++)
715  {
716  const struct sockaddr_in *c4;
717 
718  if (AF_INET != ch->caddrs[i].ss.ss_family)
719  continue; /* IPv4 not relevant */
720  c4 = (const struct sockaddr_in *) &ch->caddrs[i].ss;
721  if ( match_ipv4 ("127.0.0.1", &c4->sin_addr, 8) &&
722  (0 != c4->sin_addr.s_addr) &&
723  (! match_ipv4 ("127.0.0.1", &v4.sin_addr, 8)) )
724  continue; /* bound to loopback, but this is not loopback */
725  if ( (! match_ipv4 ("127.0.0.1", &c4->sin_addr, 8) ) &&
726  match_ipv4 ("127.0.0.1", &v4.sin_addr, 8) )
727  continue; /* bound to non-loopback, but this is loopback */
728  if ( (0 != (delta->ac & GNUNET_NAT_AC_EXTERN)) &&
729  (0 != c4->sin_addr.s_addr) &&
730  (! is_nat_v4 (&v4.sin_addr)) )
731  continue; /* based on external-IP, but this IP is not
732  from private address range. */
733  if ( (0 != GNUNET_memcmp (&v4.sin_addr,
734  &c4->sin_addr)) &&
735  (0 != c4->sin_addr.s_addr) &&
736  (! is_nat_v4 (&c4->sin_addr)) )
737  continue; /* this IP is not from private address range,
738  and IP does not match. */
739 
740  /* OK, IP seems relevant, notify client */
741  if (0 == htons (v4.sin_port))
742  v4.sin_port = c4->sin_port;
743  notify_client (delta->ac,
744  ch,
745  add,
746  &v4,
747  alen);
748  }
749  break;
750  case AF_INET6:
751  alen = sizeof (struct sockaddr_in6);
752  GNUNET_memcpy (&v6,
753  &delta->addr,
754  alen);
755  for (unsigned int i=0;i<ch->num_caddrs;i++)
756  {
757  const struct sockaddr_in6 *c6;
758 
759  if (AF_INET6 != ch->caddrs[i].ss.ss_family)
760  continue; /* IPv4 not relevant */
761  c6 = (const struct sockaddr_in6 *) &ch->caddrs[i].ss;
762  if ( match_ipv6 ("::1", &c6->sin6_addr, 128) &&
763  (0 != GNUNET_memcmp (&c6->sin6_addr,
764  &in6addr_any)) &&
765  (! match_ipv6 ("::1", &v6.sin6_addr, 128)) )
766  continue; /* bound to loopback, but this is not loopback */
767  if ( (! match_ipv6 ("::1", &c6->sin6_addr, 128) ) &&
768  match_ipv6 ("::1", &v6.sin6_addr, 128) )
769  continue; /* bound to non-loopback, but this is loopback */
770  if ( (0 != (delta->ac & GNUNET_NAT_AC_EXTERN)) &&
771  (0 != GNUNET_memcmp (&c6->sin6_addr,
772  &in6addr_any)) &&
773  (! is_nat_v6 (&v6.sin6_addr)) )
774  continue; /* based on external-IP, but this IP is not
775  from private address range. */
776  if ( (0 != GNUNET_memcmp (&v6.sin6_addr,
777  &c6->sin6_addr)) &&
778  (0 != GNUNET_memcmp (&c6->sin6_addr,
779  &in6addr_any)) &&
780  (! is_nat_v6 (&c6->sin6_addr)) )
781  continue; /* this IP is not from private address range,
782  and IP does not match. */
783  if ( (match_ipv6 ("fe80::", &c6->sin6_addr, 10)) &&
784  (0 != GNUNET_memcmp (&c6->sin6_addr,
785  &in6addr_any)) &&
786  (0 != GNUNET_memcmp (&v6.sin6_addr,
787  &c6->sin6_addr)) &&
788  (0 == (delta->ac & GNUNET_NAT_AC_EXTERN)) )
789  continue; /* client bound to link-local, and the other address
790  does not match and is not an external IP */
791 
792  /* OK, IP seems relevant, notify client */
793  if (0 == htons (v6.sin6_port))
794  v6.sin6_port = c6->sin6_port;
795  notify_client (delta->ac,
796  ch,
797  add,
798  &v6,
799  alen);
800  }
801  break;
802  default:
803  GNUNET_break (0);
804  return;
805  }
806 }
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.
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.
#define GNUNET_memcpy(dst, src, n)
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:84
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 817 of file gnunet-service-nat.c.

References ch, and check_notify_client().

Referenced by run_scan().

819 {
820  for (struct ClientHandle *ch = ch_head;
821  NULL != ch;
822  ch = ch->next)
823  check_notify_client (delta,
824  ch,
825  add);
826 }
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 838 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().

841 {
842  struct ClientHandle *ch = cls;
843  struct sockaddr_in sa;
844  int have_v4;
845 
846  /* (0) check if this impacts 'hole_external' */
847  if ( (NULL != ch->hole_external) &&
848  (0 == strcasecmp (ch->hole_external,
849  "AUTO")) )
850  {
851  struct LocalAddressList lal;
852  struct sockaddr_in *s4;
853 
855  "Detected eternal IP, can now back-fill AUTO:%u in hole punching specification of `%s'\n",
856  (unsigned int) ch->ext_dns_port,
857  ch->section_name);
858  memset (&lal, 0, sizeof (lal));
859  s4 = (struct sockaddr_in *) &lal.addr;
860  s4->sin_family = AF_INET;
861  s4->sin_port = htons (ch->ext_dns_port);
862  s4->sin_addr = *v4;
863  lal.af = AF_INET;
865  check_notify_client (&lal,
866  ch,
867  add);
868  }
869 
870  /* (1) check if client cares. */
871  if (! ch->natted_address)
872  return;
873  have_v4 = GNUNET_NO;
874  for (unsigned int i=0;i<ch->num_caddrs;i++)
875  {
876  const struct sockaddr_storage *ss = &ch->caddrs[i].ss;
877 
878  if (AF_INET != ss->ss_family)
879  continue;
880  have_v4 = GNUNET_YES;
881  break;
882  }
883  if (GNUNET_NO == have_v4)
884  return; /* IPv6-only */
885 
886  /* (2) build address info */
887  memset (&sa,
888  0,
889  sizeof (sa));
890  sa.sin_family = AF_INET;
891  sa.sin_addr = *v4;
892  sa.sin_port = htons (0);
893 
895  "Detected eternal IP %s, notifying client of external IP (without port)\n",
896  GNUNET_a2s ((const struct sockaddr *) &sa,
897  sizeof (sa)));
898  /* (3) notify client of change */
902  ch,
903  add,
904  &sa,
905  sizeof (sa));
906 }
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:81
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:80
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 917 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().

919 {
920  struct LocalAddressList *lal = cls;
921  const struct sockaddr_in *l4;
922 
923  GNUNET_assert (AF_INET == lal->af);
924  l4 = (const struct sockaddr_in *) &lal->addr;
925  for (struct ClientHandle *ch = ch_head;
926  NULL != ch;
927  ch = ch->next)
928  {
930  struct GNUNET_MQ_Envelope *env;
931  int match;
932 
933  /* Check if client is in applicable range for ICMP NAT traversal
934  for this local address */
935  if (! ch->natted_address)
936  continue;
937  match = GNUNET_NO;
938  for (unsigned int i=0;i<ch->num_caddrs;i++)
939  {
940  struct ClientAddress *ca = &ch->caddrs[i];
941  const struct sockaddr_in *c4;
942 
943  if (AF_INET != ca->ss.ss_family)
944  continue;
945  c4 = (const struct sockaddr_in *) &ca->ss;
946  if ( (0 != c4->sin_addr.s_addr) &&
947  (l4->sin_addr.s_addr != c4->sin_addr.s_addr) )
948  continue;
949  match = GNUNET_YES;
950  break;
951  }
952  if (! match)
953  continue;
954 
955  /* Notify applicable client about connection reversal request */
956  env = GNUNET_MQ_msg_extra (crrm,
957  sizeof (struct sockaddr_in),
959  GNUNET_memcpy (&crrm[1],
960  ra,
961  sizeof (struct sockaddr_in));
962  GNUNET_MQ_send (ch->mq,
963  env);
964  }
965 }
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...
static struct ClientHandle * ch_head
Head of client DLL.
#define GNUNET_NO
Definition: gnunet_common.h:81
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
#define GNUNET_memcpy(dst, src, n)
Service telling a client that connection reversal was requested.
Definition: nat.h:190
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:107
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:80
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 974 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().

975 {
976  struct IfcProcContext ifc_ctx;
977  int found;
978  int have_nat;
979  struct LocalAddressList *lnext;
980 
982  &run_scan,
983  NULL);
984  memset (&ifc_ctx,
985  0,
986  sizeof (ifc_ctx));
988  &ifc_ctx);
989  /* remove addresses that disappeared */
990  for (struct LocalAddressList *lal = lal_head;
991  NULL != lal;
992  lal = lnext)
993  {
994  lnext = lal->next;
995  found = GNUNET_NO;
996  for (struct LocalAddressList *pos = ifc_ctx.lal_head;
997  NULL != pos;
998  pos = pos->next)
999  {
1000  if ( (pos->af == lal->af) &&
1001  (0 == memcmp (&lal->addr,
1002  &pos->addr,
1003  (AF_INET == lal->af)
1004  ? sizeof (struct sockaddr_in)
1005  : sizeof (struct sockaddr_in6))) )
1006  {
1007  found = GNUNET_YES;
1008  }
1009  }
1010  if (GNUNET_NO == found)
1011  {
1012  notify_clients (lal,
1013  GNUNET_NO);
1014  free_lal (lal);
1015  }
1016  }
1017 
1018  /* add addresses that appeared */
1019  have_nat = GNUNET_NO;
1020  for (struct LocalAddressList *pos = ifc_ctx.lal_head;
1021  NULL != pos;
1022  pos = ifc_ctx.lal_head)
1023  {
1024  found = GNUNET_NO;
1025  if (GNUNET_NAT_AC_LAN == (GNUNET_NAT_AC_LAN & pos->ac))
1026  have_nat = GNUNET_YES;
1027  for (struct LocalAddressList *lal = lal_head;
1028  NULL != lal;
1029  lal = lal->next)
1030  {
1031  if ( (pos->af == lal->af) &&
1032  (0 == memcmp (&lal->addr,
1033  &pos->addr,
1034  (AF_INET == lal->af)
1035  ? sizeof (struct sockaddr_in)
1036  : sizeof (struct sockaddr_in6))) )
1037  found = GNUNET_YES;
1038  }
1039  GNUNET_CONTAINER_DLL_remove (ifc_ctx.lal_head,
1040  ifc_ctx.lal_tail,
1041  pos);
1042  if (GNUNET_YES == found)
1043  {
1044  GNUNET_free (pos);
1045  }
1046  else
1047  {
1048  notify_clients (pos,
1049  GNUNET_YES);
1051  lal_tail,
1052  pos);
1053  if ( (AF_INET == pos->af) &&
1054  (NULL == pos->hc) &&
1055  (0 != (GNUNET_NAT_AC_LAN & pos->ac)) )
1056  {
1057  const struct sockaddr_in *s4
1058  = (const struct sockaddr_in *) &pos->addr;
1059 
1061  "Found NATed local address %s, starting NAT server\n",
1062  GNUNET_a2s ((const struct sockaddr *) &pos->addr,
1063  sizeof (*s4)));
1064  pos->hc = GN_start_gnunet_nat_server_ (&s4->sin_addr,
1066  pos,
1067  cfg);
1068  }
1069  }
1070  }
1071  GN_nat_status_changed (have_nat);
1072 }
#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:81
void GNUNET_OS_network_interfaces_list(GNUNET_OS_NetworkInterfaceProcessor proc, void *proc_cls)
Enumerate all network interfaces.
Definition: os_network.c:388
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:1246
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:80
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 1087 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().

1092 {
1093  struct ClientHandle *ch = cls;
1095 
1096  switch (result)
1097  {
1099  GNUNET_assert (NULL != addr);
1100  break;
1105  "Running upnpc failed: %d\n",
1106  result);
1107  return;
1110  "external-ip binary not found\n");
1111  return;
1114  "upnpc binary not found\n");
1115  return;
1118  "external-ip binary could not be run\n");
1119  return;
1122  "upnpc failed to create port mapping\n");
1123  return;
1126  "Invalid output from upnpc\n");
1127  return;
1130  "Invalid address returned by upnpc\n");
1131  return;
1132  default:
1133  GNUNET_break (0); /* should not be possible */
1134  return;
1135  }
1136  switch (addr->sa_family)
1137  {
1138  case AF_INET:
1139  ac = is_nat_v4 (&((const struct sockaddr_in *) addr)->sin_addr)
1142  break;
1143  case AF_INET6:
1144  ac = is_nat_v6 (&((const struct sockaddr_in6 *) addr)->sin6_addr)
1147  break;
1148  default:
1149  GNUNET_break (0);
1150  return;
1151  }
1153  "upnp external address %s: %s\n",
1154  add_remove ? "added" : "removed",
1155  GNUNET_a2s (addr,
1156  addrlen));
1157  notify_client (ac,
1158  ch,
1159  add_remove,
1160  addr,
1161  addrlen);
1162 }
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 1288 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().

1289 {
1290  struct ClientHandle *ch = cls;
1291  struct LocalAddressList *lal;
1292 
1294  "Performing DNS lookup for punched hole given for `%s' as `%s:%u'\n",
1295  ch->section_name,
1296  ch->hole_external,
1297  (unsigned int) ch->ext_dns_port);
1298  for (lal = ch->ext_addr_head; NULL != lal; lal = lal->next)
1299  lal->old = GNUNET_YES;
1300  ch->ext_dns_task = NULL;
1302  AF_UNSPEC,
1305  ch);
1306 }
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:927
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:80
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 1187 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().

1190 {
1191  struct ClientHandle *ch = cls;
1192  struct LocalAddressList *lal;
1193  struct sockaddr_storage ss;
1194  struct sockaddr_in *v4;
1195  struct sockaddr_in6 *v6;
1196 
1197  if (NULL == addr)
1198  {
1199  struct LocalAddressList *laln;
1200 
1201  ch->ext_dns = NULL;
1202  ch->ext_dns_task
1204  &dyndns_lookup,
1205  ch);
1206  /* Current iteration is over, remove 'old' IPs now */
1207  for (lal = ch->ext_addr_head; NULL != lal; lal = laln)
1208  {
1209  laln = lal->next;
1210  if (GNUNET_YES == lal->old)
1211  {
1213  ch->ext_addr_tail,
1214  lal);
1215  check_notify_client (lal,
1216  ch,
1217  GNUNET_NO);
1218  GNUNET_free (lal);
1219  }
1220  }
1221  return;
1222  }
1224  "Got IP `%s' for external address `%s'\n",
1225  GNUNET_a2s (addr,
1226  addrlen),
1227  ch->hole_external);
1228 
1229  /* build sockaddr storage with port number */
1230  memset (&ss,
1231  0,
1232  sizeof (ss));
1233  GNUNET_memcpy (&ss,
1234  addr,
1235  addrlen);
1236  switch (addr->sa_family)
1237  {
1238  case AF_INET:
1239  v4 = (struct sockaddr_in *) &ss;
1240  v4->sin_port = htons (ch->ext_dns_port);
1241  break;
1242  case AF_INET6:
1243  v6 = (struct sockaddr_in6 *) &ss;
1244  v6->sin6_port = htons (ch->ext_dns_port);
1245  break;
1246  default:
1247  GNUNET_break (0);
1248  return;
1249  }
1250  /* See if 'ss' matches any of our known addresses */
1251  for (lal = ch->ext_addr_head; NULL != lal; lal = lal->next)
1252  {
1253  if (GNUNET_NO == lal->old)
1254  continue; /* already processed, skip */
1255  if ( (addr->sa_family == lal->addr.ss_family) &&
1256  (0 == memcmp (&ss,
1257  &lal->addr,
1258  addrlen)) )
1259  {
1260  /* Address unchanged, remember so we do not remove */
1261  lal->old = GNUNET_NO;
1262  return; /* done here */
1263  }
1264  }
1265  /* notify client, and remember IP for later removal! */
1266  lal = GNUNET_new (struct LocalAddressList);
1267  lal->addr = ss;
1268  lal->af = ss.ss_family;
1271  ch->ext_addr_tail,
1272  lal);
1273  check_notify_client (lal,
1274  ch,
1275  GNUNET_YES);
1276 }
#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_NO
Definition: gnunet_common.h:81
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:1246
#define GNUNET_memcpy(dst, src, n)
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:80
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 1321 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, inet_pton(), port, and ClientHandle::section_name.

Referenced by handle_register().

1322 {
1323  char *port;
1324  unsigned int pnum;
1325  struct sockaddr_in *s4;
1326  struct LocalAddressList *lal;
1327 
1328  port = strrchr (ch->hole_external, ':');
1329  if (NULL == port)
1330  {
1332  _("Malformed punched hole specification `%s' (lacks port)\n"),
1333  ch->hole_external);
1334  return;
1335  }
1336  if ( (1 != sscanf (port + 1,
1337  "%u",
1338  &pnum)) ||
1339  (pnum > 65535) )
1340  {
1342  _("Invalid port number in punched hole specification `%s' (lacks port)\n"),
1343  port + 1);
1344  return;
1345  }
1346  ch->ext_dns_port = (uint16_t) pnum;
1347  *port = '\0';
1348 
1349  lal = GNUNET_new (struct LocalAddressList);
1350  if ('[' == *ch->hole_external)
1351  {
1352  struct sockaddr_in6 *s6 = (struct sockaddr_in6 *) &lal->addr;
1353 
1354  s6->sin6_family = AF_INET6;
1355  if (']' != (ch->hole_external[strlen(ch->hole_external)-1]))
1356  {
1358  _("Malformed punched hole specification `%s' (lacks `]')\n"),
1359  ch->hole_external);
1360  GNUNET_free (lal);
1361  return;
1362  }
1363  ch->hole_external[strlen(ch->hole_external)-1] = '\0';
1364  if (1 != inet_pton (AF_INET6,
1365  ch->hole_external + 1,
1366  &s6->sin6_addr))
1367  {
1369  _("Malformed punched hole specification `%s' (IPv6 address invalid)"),
1370  ch->hole_external + 1);
1371  GNUNET_free (lal);
1372  return;
1373  }
1374  s6->sin6_port = htons (ch->ext_dns_port);
1375  lal->af = AF_INET6;
1378  ch->ext_addr_tail,
1379  lal);
1380  check_notify_client (lal,
1381  ch,
1382  GNUNET_YES);
1383  return;
1384  }
1385 
1386  s4 = (struct sockaddr_in *) &lal->addr;
1387  s4->sin_family = AF_INET;
1388  if (1 == inet_pton (AF_INET,
1389  ch->hole_external,
1390  &s4->sin_addr))
1391  {
1393  "IPv4 punched hole given for `%s' via `%s:%u'\n",
1394  ch->section_name,
1395  ch->hole_external,
1396  (unsigned int) ch->ext_dns_port);
1397  s4->sin_port = htons (ch->ext_dns_port);
1398  lal->af = AF_INET;
1401  ch->ext_addr_tail,
1402  lal);
1403  check_notify_client (lal,
1404  ch,
1405  GNUNET_YES);
1406  return;
1407  }
1408  if (0 == strcasecmp (ch->hole_external,
1409  "AUTO"))
1410  {
1411  /* handled in #notify_client_external_ipv4_change() */
1412  GNUNET_free (lal);
1413  return;
1414  }
1415  /* got a DNS name, trigger lookup! */
1416  GNUNET_free (lal);
1417  ch->ext_dns_task
1419  ch);
1420 }
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:208
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:1273
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:79
static int inet_pton(int af, const char *cp, struct in_addr *buf)
Convert IPv4 address from text to binary form.
#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:80
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 1431 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().

1433 {
1434  struct ClientHandle *ch = cls;
1435  const char *off;
1436  size_t left;
1437 
1438  if ( (0 != ch->proto) ||
1439  (NULL != ch->caddrs) )
1440  {
1441  /* double registration not allowed */
1442  GNUNET_break (0);
1444  return;
1445  }
1446  ch->flags = message->flags;
1447  ch->proto = message->proto;
1448  ch->num_caddrs = ntohs (message->num_addrs);
1449  ch->caddrs = GNUNET_new_array (ch->num_caddrs,
1450  struct ClientAddress);
1451  left = ntohs (message->header.size) - sizeof (*message);
1452  off = (const char *) &message[1];
1453  for (unsigned int i=0;i<ch->num_caddrs;i++)
1454  {
1455  const struct sockaddr *sa = (const struct sockaddr *) off;
1456  size_t alen;
1457  uint16_t port;
1458  int is_nat;
1459 
1460  if (sizeof (sa_family_t) > left)
1461  {
1462  GNUNET_break (0);
1464  return;
1465  }
1466  is_nat = GNUNET_NO;
1467  switch (sa->sa_family)
1468  {
1469  case AF_INET:
1470  {
1471  struct sockaddr_in s4;
1472 
1473  GNUNET_memcpy (&s4,
1474  off,
1475  sizeof (struct sockaddr_in));
1476  alen = sizeof (struct sockaddr_in);
1477  if (is_nat_v4 (&s4.sin_addr))
1478  is_nat = GNUNET_YES;
1479  port = ntohs (s4.sin_port);
1480  }
1481  break;
1482  case AF_INET6:
1483  {
1484  struct sockaddr_in6 s6;
1485 
1486  GNUNET_memcpy (&s6,
1487  off,
1488  sizeof (struct sockaddr_in6));
1489  alen = sizeof (struct sockaddr_in6);
1490  if (is_nat_v6 (&s6.sin6_addr))
1491  is_nat = GNUNET_YES;
1492  port = ntohs (s6.sin6_port);
1493  }
1494  break;
1495 #if AF_UNIX
1496  case AF_UNIX:
1497  alen = sizeof (struct sockaddr_un);
1498  port = 0;
1499  break;
1500 #endif
1501  default:
1502  GNUNET_break (0);
1504  return;
1505  }
1506  /* store address */
1507  GNUNET_assert (alen <= left);
1508  GNUNET_assert (alen <= sizeof (struct sockaddr_storage));
1509  GNUNET_memcpy (&ch->caddrs[i].ss,
1510  off,
1511  alen);
1512 
1513  /* If applicable, try UPNPC NAT punching */
1514  if ( (is_nat) &&
1515  (enable_upnp) &&
1516  ( (IPPROTO_TCP == ch->proto) ||
1517  (IPPROTO_UDP == ch->proto) ) )
1518  {
1519  ch->natted_address = GNUNET_YES;
1520  ch->caddrs[i].mh
1521  = GNUNET_NAT_mini_map_start (port,
1522  IPPROTO_TCP == ch->proto,
1524  ch);
1525  }
1526 
1527  off += alen;
1528  }
1529 
1530  ch->section_name
1531  = GNUNET_strndup (off,
1532  ntohs (message->str_len));
1534  "Received REGISTER message from client for subsystem `%s'\n",
1535  ch->section_name);
1536  if (GNUNET_OK ==
1538  ch->section_name,
1539  "HOLE_EXTERNAL",
1540  &ch->hole_external))
1541  lookup_hole_external (ch);
1542 
1543  /* Actually send IP address list to client */
1544  for (struct LocalAddressList *lal = lal_head;
1545  NULL != lal;
1546  lal = lal->next)
1547  {
1548  check_notify_client (lal,
1549  ch,
1550  GNUNET_YES);
1551  }
1552  /* Also consider IPv4 determined by `external-ip` */
1553  ch->external_monitor
1555  ch);
1557 }
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:111
uint16_t str_len
Number of bytes in the string that follow which specifies a section name in the configuration.
Definition: nat.h:117
#define GNUNET_NO
Definition: gnunet_common.h:81
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:78
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_memcpy(dst, src, n)
#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:124
uint8_t flags
An enum GNUNET_NAT_RegisterFlags.
Definition: nat.h:106
void GNUNET_SERVICE_client_drop(struct GNUNET_SERVICE_Client *c)
Ask the server to disconnect from the given client.
Definition: service.c:2618
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:101
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:79
#define GNUNET_log(kind,...)
#define GNUNET_YES
Definition: gnunet_common.h:80
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:2533
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 1569 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.

1571 {
1572  size_t sa_len = ntohs (message->sender_addr_size);
1573  size_t expect = sa_len + ntohs (message->payload_size);
1574 
1575  if (ntohs (message->header.size) - sizeof (*message) != expect)
1576  {
1577  GNUNET_break (0);
1578  return GNUNET_SYSERR;
1579  }
1580  if (sa_len < sizeof (sa_family_t))
1581  {
1582  GNUNET_break (0);
1583  return GNUNET_SYSERR;
1584  }
1585  return GNUNET_OK;
1586 }
uint16_t payload_size
Number of bytes of payload included, in NBO.
Definition: nat.h:152
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:78
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:147
#define GNUNET_SYSERR
Definition: gnunet_common.h:79
struct GNUNET_MessageHeader header
Header with type GNUNET_MESSAGE_TYPE_NAT_HANDLE_STUN.
Definition: nat.h:142

◆ 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 1597 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().

1599 {
1600  for (struct ClientHandle *ch = ch_head;
1601  NULL != ch;
1602  ch = ch->next)
1603  {
1604  struct sockaddr_in v4;
1606  struct GNUNET_MQ_Envelope *env;
1607 
1608  if (! ch->natted_address)
1609  continue;
1610  v4 = *ip;
1611  v4.sin_port = htons (0);
1612  env = GNUNET_MQ_msg_extra (msg,
1613  sizeof (v4),
1615  msg->add_remove = htonl ((int32_t) add);
1616  msg->addr_class = htonl (GNUNET_NAT_AC_EXTERN |
1618  GNUNET_memcpy (&msg[1],
1619  &v4,
1620  sizeof (v4));
1621  GNUNET_MQ_send (ch->mq,
1622  env);
1623  }
1624 }
Service notifying the client about changes in the set of addresses it has.
Definition: nat.h:206
static struct GNUNET_CADET_Channel * ch
Channel handle.
Definition: gnunet-cadet.c:117
struct GNUNET_MessageHeader * msg
Definition: 005.c:2
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
#define GNUNET_memcpy(dst, src, n)
uint32_t addr_class
Type of the address, an enum GNUNET_NAT_AddressClass in NBO.
Definition: nat.h:221
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:107
int32_t add_remove
GNUNET_YES to add, GNUNET_NO to remove the address from the list.
Definition: nat.h:216
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 1635 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().

1636 {
1637  struct StunExternalIP *se = cls;
1638 
1639  se->timeout_task = NULL;
1641  GNUNET_NO);
1643  se_tail,
1644  se);
1645  GNUNET_free (se);
1646 }
#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:81
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 1657 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.

1659 {
1660  struct ClientHandle *ch = cls;
1661  const char *buf = (const char *) &message[1];
1662  const struct sockaddr *sa;
1663  const void *payload;
1664  size_t sa_len;
1665  size_t payload_size;
1666  struct sockaddr_in external_addr;
1667 
1668  sa_len = ntohs (message->sender_addr_size);
1669  payload_size = ntohs (message->payload_size);
1670  sa = (const struct sockaddr *) &buf[0];
1671  payload = (const struct sockaddr *) &buf[sa_len];
1672  switch (sa->sa_family)
1673  {
1674  case AF_INET:
1675  if (sa_len != sizeof (struct sockaddr_in))
1676  {
1677  GNUNET_break (0);
1679  return;
1680  }
1681  break;
1682  case AF_INET6:
1683  if (sa_len != sizeof (struct sockaddr_in6))
1684  {
1685  GNUNET_break (0);
1687  return;
1688  }
1689  break;
1690  }
1692  "Received HANDLE_STUN message from client\n");
1693  if (GNUNET_OK ==
1695  payload_size,
1696  &external_addr))
1697  {
1698  /* We now know that a server at "sa" claims that
1699  we are visible at IP "external_addr".
1700 
1701  We should (for some fixed period of time) tell
1702  all of our clients that listen to a NAT'ed address
1703  that they might want to consider the given 'external_ip'
1704  as their public IP address (this includes TCP and UDP
1705  clients, even if only UDP sends STUN requests).
1706 
1707  If we do not get a renewal, the "external_addr" should be
1708  removed again. The timeout frequency should be configurable
1709  (with a sane default), so that the UDP plugin can tell how
1710  often to re-request STUN.
1711  */
1712  struct StunExternalIP *se;
1713 
1714  /* Check if we had a prior response from this STUN server */
1715  for (se = se_head; NULL != se; se = se->next)
1716  {
1717  if ( (se->stun_server_addr_len != sa_len) ||
1718  (0 != memcmp (sa,
1719  &se->stun_server_addr,
1720  sa_len)) )
1721  continue; /* different STUN server */
1722  if (0 != GNUNET_memcmp (&external_addr,
1723  &se->external_addr))
1724  {
1725  /* external IP changed, update! */
1727  GNUNET_NO);
1730  GNUNET_YES);
1731  }
1732  /* update timeout */
1734  se->timeout_task
1736  &stun_ip_timeout,
1737  se);
1738  return;
1739  }
1740  /* STUN server is completely new, create fresh entry */
1741  se = GNUNET_new (struct StunExternalIP);
1744  sa,
1745  sa_len);
1746  se->stun_server_addr_len = sa_len;
1748  &stun_ip_timeout,
1749  se);
1751  se_tail,
1752  se);
1754  GNUNET_NO);
1755  }
1757 }
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.
uint16_t payload_size
Number of bytes of payload included, in NBO.
Definition: nat.h:152
#define GNUNET_NO
Definition: gnunet_common.h:81
static struct StunExternalIP * se_tail
Kept in a DLL.
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:78
#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:1246
#define GNUNET_memcpy(dst, src, n)
uint16_t sender_addr_size
Size of the sender address included, in NBO.
Definition: nat.h:147
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:2618
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:80
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:2533
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:965
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 1770 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.

1772 {
1773  size_t expect;
1774 
1775  expect = ntohs (message->local_addr_size)
1776  + ntohs (message->remote_addr_size);
1777  if (ntohs (message->header.size) - sizeof (*message) != expect)
1778  {
1779  GNUNET_break (0);
1780  return GNUNET_SYSERR;
1781  }
1782  return GNUNET_OK;
1783 }
uint16_t remote_addr_size
Size of the remote address included, in NBO.
Definition: nat.h:178
struct GNUNET_MessageHeader header
Header with type GNUNET_MESSAGE_TYPE_NAT_REQUEST_CONNECTION_REVERSAL.
Definition: nat.h:168
uint16_t local_addr_size
Size of the local address included, in NBO.
Definition: nat.h:173
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:78
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:79

◆ 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 1794 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.

1796 {
1797  struct ClientHandle *ch = cls;
1798  const char *buf = (const char *) &message[1];
1799  size_t local_sa_len = ntohs (message->local_addr_size);
1800  size_t remote_sa_len = ntohs (message->remote_addr_size);
1801  struct sockaddr_in l4;
1802  struct sockaddr_in r4;
1803  int ret;
1804 
1806  "Received REQUEST CONNECTION REVERSAL message from client\n");
1807  if (local_sa_len != sizeof (struct sockaddr_in))
1808  {
1809  GNUNET_break_op (0);
1811  return;
1812  }
1813  if (remote_sa_len != sizeof (struct sockaddr_in))
1814  {
1815  GNUNET_break_op (0);
1817  return;
1818  }
1819  GNUNET_memcpy (&l4,
1820  buf,
1821  sizeof (struct sockaddr_in));
1822  GNUNET_break_op (AF_INET == l4.sin_family);
1823  buf += sizeof (struct sockaddr_in);
1824  GNUNET_memcpy (&r4,
1825  buf,
1826  sizeof (struct sockaddr_in));
1827  GNUNET_break_op (AF_INET == r4.sin_family);
1828  ret = GN_request_connection_reversal (&l4.sin_addr,
1829  ntohs (l4.sin_port),
1830  &r4.sin_addr,
1831  cfg);
1832  if (GNUNET_OK != ret)
1834  _("Connection reversal request failed\n"));
1836 }
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:178
uint16_t local_addr_size
Size of the local address included, in NBO.
Definition: nat.h:173
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:78
static int ret
Final status code.
Definition: gnunet-arm.c:89
#define _(String)
GNU gettext support macro.
Definition: platform.h:208
#define GNUNET_memcpy(dst, src, n)
#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:2618
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:2533
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 1845 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().

1846 {
1847  struct StunExternalIP *se;
1848 
1849  while (NULL != (se = se_head))
1850  {
1852  se_tail,
1853  se);
1855  GNUNET_free (se);
1856  }
1858  if (NULL != scan_task)
1859  {
1861  scan_task = NULL;
1862  }
1863  if (NULL != stats)
1864  {
1866  GNUNET_NO);
1867  stats = NULL;
1868  }
1869  destroy_lal ();
1870 }
#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:81
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:965
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 1881 of file gnunet-service-nat.c.

References _, DYNDNS_FREQUENCY, dyndns_frequency, 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().

1884 {
1885  cfg = c;
1886  if (GNUNET_OK !=
1888  "NAT",
1889  "STUN_STALE",
1892 
1893  /* Check for UPnP */
1894  enable_upnp
1896  "NAT",
1897  "ENABLE_UPNP");
1898  if (GNUNET_YES == enable_upnp)
1899  {
1900  /* check if it works */
1901  if (GNUNET_SYSERR ==
1903  GNUNET_NO,
1904  NULL))
1905  {
1907  _("UPnP enabled in configuration, but UPnP client `upnpc` command not found, disabling UPnP\n"));
1909  }
1910  }
1911  if (GNUNET_OK !=
1913  "nat",
1914  "DYNDNS_FREQUENCY",
1915  &dyndns_frequency))
1917 
1919  NULL);
1921  cfg);
1923  NULL);
1924 }
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:1293
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:81
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:78
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:208
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:1273
#define DYNDNS_FREQUENCY
How often do we scan for changes in how our external (dyndns) hostname resolves?
static void shutdown_task(void *cls)
Task run during shutdown.
#define GNUNET_SYSERR
Definition: gnunet_common.h:79
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:80
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 1936 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().

1939 {
1940  struct ClientHandle *ch;
1941 
1942  ch = GNUNET_new (struct ClientHandle);
1943  ch->mq = mq;
1944  ch->client = c;
1946  ch_tail,
1947  ch);
1948  return ch;
1949 }
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 1960 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.

1963 {
1964  struct ClientHandle *ch = internal_cls;
1965  struct LocalAddressList *lal;
1966 
1968  ch_tail,
1969  ch);
1970  for (unsigned int i=0;i<ch->num_caddrs;i++)
1971  {
1972  if (NULL != ch->caddrs[i].mh)
1973  {
1975  ch->caddrs[i].mh = NULL;
1976  }
1977  }
1979  while (NULL != (lal = ch->ext_addr_head))
1980  {
1982  ch->ext_addr_tail,
1983  lal);
1984  GNUNET_free (lal);
1985  }
1986  if (NULL != ch->ext_dns_task)
1987  {
1989  ch->ext_dns_task = NULL;
1990  }
1991  if (NULL != ch->external_monitor)
1992  {
1994  ch->external_monitor = NULL;
1995  }
1996  if (NULL != ch->ext_dns)
1997  {
1999  ch->ext_dns = NULL;
2000  }
2003  GNUNET_free (ch);
2004 }
#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:965
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 282 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 287 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 292 of file gnunet-service-nat.c.

◆ stats

struct GNUNET_STATISTICS_Handle* stats
static

Handle to the statistics service.

Definition at line 297 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 302 of file gnunet-service-nat.c.

◆ ch_head

struct ClientHandle* ch_head
static

Head of client DLL.

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

◆ ch_tail

struct ClientHandle* ch_tail
static

Tail of client DLL.

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

◆ lal_head

struct LocalAddressList* lal_head
static

Head of DLL of local addresses.

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

◆ lal_tail

struct LocalAddressList* lal_tail
static

Tail of DLL of local addresses.

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

◆ se_head

struct StunExternalIP* se_head
static

Kept in a DLL.

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

◆ se_tail

struct StunExternalIP* se_tail
static

Kept in a DLL.

Definition at line 332 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 338 of file gnunet-service-nat.c.

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