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 339 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().

340 {
342  lal_tail,
343  lal);
344  if (NULL != lal->hc)
345  {
347  "Lost NATed local address %s, stopping NAT server\n",
348  GNUNET_a2s((const struct sockaddr *)&lal->addr,
349  sizeof(struct sockaddr_in)));
350 
352  lal->hc = NULL;
353  }
354  GNUNET_free(lal);
355 }
#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 362 of file gnunet-service-nat.c.

References free_lal().

Referenced by shutdown_task().

363 {
364  struct LocalAddressList *lal;
365 
366  while (NULL != (lal = lal_head))
367  free_lal(lal);
368 }
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 380 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.

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

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

References GNUNET_assert, and GNUNET_YES.

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

445 {
446  struct in_addr net;
447 
448  if (0 == ip->s_addr)
449  return GNUNET_YES;
450  if (0 == bits)
451  return GNUNET_YES;
452  GNUNET_assert(1 == inet_pton(AF_INET,
453  network,
454  &net));
455  return !((ip->s_addr ^ net.s_addr) & htonl(0xFFFFFFFFu << (32 - bits)));
456 }
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_YES
Definition: gnunet_common.h:77
Here is the caller graph for this function:

◆ match_ipv6()

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

Check if ip is in network with bits netmask.

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

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

References GNUNET_assert, GNUNET_memcmp, GNUNET_NO, and GNUNET_YES.

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

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

◆ is_nat_v4()

static int is_nat_v4 ( const struct in_addr *  ip)
static

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

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

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

513 {
514  return
515  match_ipv4("10.0.0.0", ip, 8) || /* RFC 1918 */
516  match_ipv4("100.64.0.0", ip, 10) || /* CG-NAT, RFC 6598 */
517  match_ipv4("192.168.0.0", ip, 12) || /* RFC 1918 */
518  match_ipv4("169.254.0.0", ip, 16) || /* AUTO, RFC 3927 */
519  match_ipv4("172.16.0.0", ip, 16); /* RFC 1918 */
520 }
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 531 of file gnunet-service-nat.c.

References match_ipv6().

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

532 {
533  return
534  match_ipv6("fc00::", ip, 7) || /* RFC 4193 */
535  match_ipv6("fec0::", ip, 10) || /* RFC 3879 */
536  match_ipv6("fe80::", ip, 10); /* RFC 4291, link-local */
537 }
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 570 of file gnunet-service-nat.c.

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

Referenced by run_scan().

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

◆ notify_client()

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

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

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

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

653 {
654  struct GNUNET_MQ_Envelope *env;
656 
658  "Notifying client about %s of IP %s\n",
659  add ? "addition" : "removal",
660  GNUNET_a2s(addr,
661  addr_len));
662  env = GNUNET_MQ_msg_extra(msg,
663  addr_len,
665  msg->add_remove = htonl(add);
666  msg->addr_class = htonl(ac);
667  GNUNET_memcpy(&msg[1],
668  addr,
669  addr_len);
670  GNUNET_MQ_send(ch->mq,
671  env);
672 }
Service notifying the client about changes in the set of addresses it has.
Definition: nat.h:196
struct GNUNET_MessageHeader * msg
Definition: 005.c:2
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
#define GNUNET_MQ_msg_extra(mvar, esize, type)
Allocate an envelope, with extra space allocated after the space needed by the message struct...
Definition: gnunet_mq_lib.h:52
const char * GNUNET_a2s(const struct sockaddr *addr, socklen_t addrlen)
Convert a "struct sockaddr*" (IPv4 or IPv6 address) to a string (for printing debug messages)...
uint32_t addr_class
Type of the address, an enum GNUNET_NAT_AddressClass in NBO.
Definition: nat.h:210
int32_t add_remove
GNUNET_YES to add, GNUNET_NO to remove the address from the list.
Definition: nat.h:205
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:351
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 684 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().

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

References ch, and check_notify_client().

Referenced by run_scan().

814 {
815  for (struct ClientHandle *ch = ch_head;
816  NULL != ch;
817  ch = ch->next)
818  check_notify_client(delta,
819  ch,
820  add);
821 }
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 833 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().

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

◆ reversal_callback()

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

We got a connection reversal request from another peer.

Notify applicable clients.

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

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

914 {
915  struct LocalAddressList *lal = cls;
916  const struct sockaddr_in *l4;
917 
918  GNUNET_assert(AF_INET == lal->af);
919  l4 = (const struct sockaddr_in *)&lal->addr;
920  for (struct ClientHandle *ch = ch_head;
921  NULL != ch;
922  ch = ch->next)
923  {
925  struct GNUNET_MQ_Envelope *env;
926  int match;
927 
928  /* Check if client is in applicable range for ICMP NAT traversal
929  for this local address */
930  if (!ch->natted_address)
931  continue;
932  match = GNUNET_NO;
933  for (unsigned int i = 0; i < ch->num_caddrs; i++)
934  {
935  struct ClientAddress *ca = &ch->caddrs[i];
936  const struct sockaddr_in *c4;
937 
938  if (AF_INET != ca->ss.ss_family)
939  continue;
940  c4 = (const struct sockaddr_in *)&ca->ss;
941  if ((0 != c4->sin_addr.s_addr) &&
942  (l4->sin_addr.s_addr != c4->sin_addr.s_addr))
943  continue;
944  match = GNUNET_YES;
945  break;
946  }
947  if (!match)
948  continue;
949 
950  /* Notify applicable client about connection reversal request */
951  env = GNUNET_MQ_msg_extra(crrm,
952  sizeof(struct sockaddr_in),
954  GNUNET_memcpy(&crrm[1],
955  ra,
956  sizeof(struct sockaddr_in));
958  env);
959  }
960 }
static struct GNUNET_CADET_Channel * ch
Channel handle.
Definition: gnunet-cadet.c:117
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_MESSAGE_TYPE_NAT_CONNECTION_REVERSAL_REQUESTED
Message to from NAT service notifying us that connection reversal was requested by another peer...
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
static struct ClientHandle * ch_head
Head of client DLL.
#define GNUNET_NO
Definition: gnunet_common.h:78
List of local addresses this system has.
struct sockaddr_storage addr
The address itself (i.e.
#define GNUNET_MQ_msg_extra(mvar, esize, type)
Allocate an envelope, with extra space allocated after the space needed by the message struct...
Definition: gnunet_mq_lib.h:52
Service telling a client that connection reversal was requested.
Definition: nat.h:182
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:104
struct GNUNET_MQ_Envelope * env
Definition: 005.c:1
Information we track per client address.
int af
Address family.
#define GNUNET_YES
Definition: gnunet_common.h:77
void GNUNET_MQ_send(struct GNUNET_MQ_Handle *mq, struct GNUNET_MQ_Envelope *ev)
Send a message with the given message queue.
Definition: mq.c:351
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 969 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().

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

◆ upnp_addr_change_cb()

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

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

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

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

1087 {
1088  struct ClientHandle *ch = cls;
1090 
1091  switch (result)
1092  {
1094  GNUNET_assert(NULL != addr);
1095  break;
1096 
1101  "Running upnpc failed: %d\n",
1102  result);
1103  return;
1104 
1107  "external-ip binary not found\n");
1108  return;
1109 
1112  "upnpc binary not found\n");
1113  return;
1114 
1117  "external-ip binary could not be run\n");
1118  return;
1119 
1122  "upnpc failed to create port mapping\n");
1123  return;
1124 
1127  "Invalid output from upnpc\n");
1128  return;
1129 
1132  "Invalid address returned by upnpc\n");
1133  return;
1134 
1135  default:
1136  GNUNET_break(0); /* should not be possible */
1137  return;
1138  }
1139  switch (addr->sa_family)
1140  {
1141  case AF_INET:
1142  ac = is_nat_v4(&((const struct sockaddr_in *)addr)->sin_addr)
1145  break;
1146 
1147  case AF_INET6:
1148  ac = is_nat_v6(&((const struct sockaddr_in6 *)addr)->sin6_addr)
1151  break;
1152 
1153  default:
1154  GNUNET_break(0);
1155  return;
1156  }
1158  "upnp external address %s: %s\n",
1159  add_remove ? "added" : "removed",
1160  GNUNET_a2s(addr,
1161  addrlen));
1162  notify_client(ac,
1163  ch,
1164  add_remove,
1165  addr,
1166  addrlen);
1167 }
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 1295 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().

1296 {
1297  struct ClientHandle *ch = cls;
1298  struct LocalAddressList *lal;
1299 
1301  "Performing DNS lookup for punched hole given for `%s' as `%s:%u'\n",
1302  ch->section_name,
1303  ch->hole_external,
1304  (unsigned int)ch->ext_dns_port);
1305  for (lal = ch->ext_addr_head; NULL != lal; lal = lal->next)
1306  lal->old = GNUNET_YES;
1307  ch->ext_dns_task = NULL;
1309  AF_UNSPEC,
1312  ch);
1313 }
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:933
static void process_external_ip(void *cls, const struct sockaddr *addr, socklen_t addrlen)
Our (external) hostname was resolved.
char * section_name
Name of the configuration section this client cares about.
List of local addresses this system has.
int old
GNUNET_YES if we saw this one in the previous iteration, but not in the current iteration and thus mi...
struct GNUNET_RESOLVER_RequestHandle * ext_dns
Handle for (DYN)DNS lookup of our external IP as given in hole_external.
Struct containing information about a client, handle to connect to it, and any pending messages that ...
struct LocalAddressList * ext_addr_head
DLL of external IP addresses as given in hole_external.
#define GNUNET_log(kind,...)
#define GNUNET_YES
Definition: gnunet_common.h:77
struct LocalAddressList * next
This is a linked list.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ process_external_ip()

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

Our (external) hostname was resolved.

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

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

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

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

◆ lookup_hole_external()

static void lookup_hole_external ( struct ClientHandle ch)
static

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

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

Parameters
chclient handle to act upon

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

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

Referenced by handle_register().

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

◆ handle_register()

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

Handler for GNUNET_MESSAGE_TYPE_NAT_REGISTER message from client.

We remember the client for updates upon future NAT events.

Parameters
clsclient who sent the message
messagethe message received

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

1440 {
1441  struct ClientHandle *ch = cls;
1442  const char *off;
1443  size_t left;
1444 
1445  if ((0 != ch->proto) ||
1446  (NULL != ch->caddrs))
1447  {
1448  /* double registration not allowed */
1449  GNUNET_break(0);
1451  return;
1452  }
1453  ch->flags = message->flags;
1454  ch->proto = message->proto;
1455  ch->num_caddrs = ntohs(message->num_addrs);
1457  struct ClientAddress);
1458  left = ntohs(message->header.size) - sizeof(*message);
1459  off = (const char *)&message[1];
1460  for (unsigned int i = 0; i < ch->num_caddrs; i++)
1461  {
1462  const struct sockaddr *sa = (const struct sockaddr *)off;
1463  size_t alen;
1464  uint16_t port;
1465  int is_nat;
1466 
1467  if (sizeof(sa_family_t) > left)
1468  {
1469  GNUNET_break(0);
1471  return;
1472  }
1473  is_nat = GNUNET_NO;
1474  switch (sa->sa_family)
1475  {
1476  case AF_INET:
1477  {
1478  struct sockaddr_in s4;
1479 
1480  GNUNET_memcpy(&s4,
1481  off,
1482  sizeof(struct sockaddr_in));
1483  alen = sizeof(struct sockaddr_in);
1484  if (is_nat_v4(&s4.sin_addr))
1485  is_nat = GNUNET_YES;
1486  port = ntohs(s4.sin_port);
1487  }
1488  break;
1489 
1490  case AF_INET6:
1491  {
1492  struct sockaddr_in6 s6;
1493 
1494  GNUNET_memcpy(&s6,
1495  off,
1496  sizeof(struct sockaddr_in6));
1497  alen = sizeof(struct sockaddr_in6);
1498  if (is_nat_v6(&s6.sin6_addr))
1499  is_nat = GNUNET_YES;
1500  port = ntohs(s6.sin6_port);
1501  }
1502  break;
1503 
1504 #if AF_UNIX
1505  case AF_UNIX:
1506  alen = sizeof(struct sockaddr_un);
1507  port = 0;
1508  break;
1509 #endif
1510  default:
1511  GNUNET_break(0);
1513  return;
1514  }
1515  /* store address */
1516  GNUNET_assert(alen <= left);
1517  GNUNET_assert(alen <= sizeof(struct sockaddr_storage));
1518  GNUNET_memcpy(&ch->caddrs[i].ss,
1519  off,
1520  alen);
1521 
1522  /* If applicable, try UPNPC NAT punching */
1523  if ((is_nat) &&
1524  (enable_upnp) &&
1525  ((IPPROTO_TCP == ch->proto) ||
1526  (IPPROTO_UDP == ch->proto)))
1527  {
1528  ch->natted_address = GNUNET_YES;
1529  ch->caddrs[i].mh
1531  IPPROTO_TCP == ch->proto,
1533  ch);
1534  }
1535 
1536  off += alen;
1537  }
1538 
1539  ch->section_name
1540  = GNUNET_strndup(off,
1541  ntohs(message->str_len));
1543  "Received REGISTER message from client for subsystem `%s'\n",
1544  ch->section_name);
1545  if (GNUNET_OK ==
1547  ch->section_name,
1548  "HOLE_EXTERNAL",
1549  &ch->hole_external))
1551 
1552  /* Actually send IP address list to client */
1553  for (struct LocalAddressList *lal = lal_head;
1554  NULL != lal;
1555  lal = lal->next)
1556  {
1557  check_notify_client(lal,
1558  ch,
1559  GNUNET_YES);
1560  }
1561  /* Also consider IPv4 determined by `external-ip` */
1562  ch->external_monitor
1564  ch);
1566 }
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:107
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
uint16_t str_len
Number of bytes in the string that follow which specifies a section name in the configuration.
Definition: nat.h:113
#define GNUNET_NO
Definition: gnunet_common.h:78
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format...
char * section_name
Name of the configuration section this client cares about.
List of local addresses this system has.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
static int is_nat_v4(const struct in_addr *ip)
Test if the given IPv4 address is in a known range for private networks.
#define GNUNET_new_array(n, type)
Allocate a size n array with structs or unions of the given type.
uint16_t num_caddrs
Number of addresses that this service is bound to.
uint16_t num_addrs
Number of addresses that this service is bound to that follow.
Definition: nat.h:120
uint8_t flags
An enum GNUNET_NAT_RegisterFlags.
Definition: nat.h:102
void GNUNET_SERVICE_client_drop(struct GNUNET_SERVICE_Client *c)
Ask the server to disconnect from the given client.
Definition: service.c:2315
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:97
int enable_upnp
Is UPnP enabled? GNUNET_YES if enabled, GNUNET_NO if disabled, GNUNET_SYSERR if configuration enabled...
uint8_t proto
Client&#39;s IPPROTO, e.g.
Information we track per client address.
static uint16_t port
Port number.
Definition: gnunet-bcd.c:81
#define GNUNET_log(kind,...)
#define GNUNET_YES
Definition: gnunet_common.h:77
struct GN_ExternalIPMonitor * GN_external_ipv4_monitor_start(GN_NotifyExternalIPv4Change cb, void *cb_cls)
Start monitoring external IPv4 addresses.
static void lookup_hole_external(struct ClientHandle *ch)
Resolve the hole_external name to figure out our external address from a manually punched hole...
enum GNUNET_NAT_RegisterFlags flags
What does this client care about?
struct sockaddr_storage ss
Network address used by the client.
void GNUNET_SERVICE_client_continue(struct GNUNET_SERVICE_Client *c)
Continue receiving further messages from the given client.
Definition: service.c:2234
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 1578 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.

1580 {
1581  size_t sa_len = ntohs(message->sender_addr_size);
1582  size_t expect = sa_len + ntohs(message->payload_size);
1583 
1584  if (ntohs(message->header.size) - sizeof(*message) != expect)
1585  {
1586  GNUNET_break(0);
1587  return GNUNET_SYSERR;
1588  }
1589  if (sa_len < sizeof(sa_family_t))
1590  {
1591  GNUNET_break(0);
1592  return GNUNET_SYSERR;
1593  }
1594  return GNUNET_OK;
1595 }
uint16_t payload_size
Number of bytes of payload included, in NBO.
Definition: nat.h:146
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format...
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
uint16_t sender_addr_size
Size of the sender address included, in NBO.
Definition: nat.h:141
#define GNUNET_SYSERR
Definition: gnunet_common.h:76
struct GNUNET_MessageHeader header
Header with type GNUNET_MESSAGE_TYPE_NAT_HANDLE_STUN.
Definition: nat.h:136

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

1608 {
1609  for (struct ClientHandle *ch = ch_head;
1610  NULL != ch;
1611  ch = ch->next)
1612  {
1613  struct sockaddr_in v4;
1615  struct GNUNET_MQ_Envelope *env;
1616 
1617  if (!ch->natted_address)
1618  continue;
1619  v4 = *ip;
1620  v4.sin_port = htons(0);
1621  env = GNUNET_MQ_msg_extra(msg,
1622  sizeof(v4),
1624  msg->add_remove = htonl((int32_t)add);
1625  msg->addr_class = htonl(GNUNET_NAT_AC_EXTERN |
1627  GNUNET_memcpy(&msg[1],
1628  &v4,
1629  sizeof(v4));
1630  GNUNET_MQ_send(ch->mq,
1631  env);
1632  }
1633 }
Service notifying the client about changes in the set of addresses it has.
Definition: nat.h:196
static struct GNUNET_CADET_Channel * ch
Channel handle.
Definition: gnunet-cadet.c:117
struct GNUNET_MessageHeader * msg
Definition: 005.c:2
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
Addresses that should be our external IP address on the outside of a NAT.
static struct ClientHandle * ch_head
Head of client DLL.
#define GNUNET_MQ_msg_extra(mvar, esize, type)
Allocate an envelope, with extra space allocated after the space needed by the message struct...
Definition: gnunet_mq_lib.h:52
uint32_t addr_class
Type of the address, an enum GNUNET_NAT_AddressClass in NBO.
Definition: nat.h:210
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:104
int32_t add_remove
GNUNET_YES to add, GNUNET_NO to remove the address from the list.
Definition: nat.h:205
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:351
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 1644 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().

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

◆ handle_stun()

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

Handler for GNUNET_MESSAGE_TYPE_NAT_HANDLE_STUN message from client.

Parameters
clsclient who sent the message
messagethe message received

Definition at line 1666 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.

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

1782 {
1783  size_t expect;
1784 
1785  expect = ntohs(message->local_addr_size)
1786  + ntohs(message->remote_addr_size);
1787  if (ntohs(message->header.size) - sizeof(*message) != expect)
1788  {
1789  GNUNET_break(0);
1790  return GNUNET_SYSERR;
1791  }
1792  return GNUNET_OK;
1793 }
uint16_t remote_addr_size
Size of the remote address included, in NBO.
Definition: nat.h:171
struct GNUNET_MessageHeader header
Header with type GNUNET_MESSAGE_TYPE_NAT_REQUEST_CONNECTION_REVERSAL.
Definition: nat.h:161
uint16_t local_addr_size
Size of the local address included, in NBO.
Definition: nat.h:166
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format...
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
#define GNUNET_SYSERR
Definition: gnunet_common.h:76

◆ handle_request_connection_reversal()

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

Handler for GNUNET_MESSAGE_TYPE_NAT_REQUEST_CONNECTION_REVERSAL message from client.

Parameters
clsclient who sent the message
messagethe message received

Definition at line 1804 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.

1806 {
1807  struct ClientHandle *ch = cls;
1808  const char *buf = (const char *)&message[1];
1809  size_t local_sa_len = ntohs(message->local_addr_size);
1810  size_t remote_sa_len = ntohs(message->remote_addr_size);
1811  struct sockaddr_in l4;
1812  struct sockaddr_in r4;
1813  int ret;
1814 
1816  "Received REQUEST CONNECTION REVERSAL message from client\n");
1817  if (local_sa_len != sizeof(struct sockaddr_in))
1818  {
1819  GNUNET_break_op(0);
1821  return;
1822  }
1823  if (remote_sa_len != sizeof(struct sockaddr_in))
1824  {
1825  GNUNET_break_op(0);
1827  return;
1828  }
1829  GNUNET_memcpy(&l4,
1830  buf,
1831  sizeof(struct sockaddr_in));
1832  GNUNET_break_op(AF_INET == l4.sin_family);
1833  buf += sizeof(struct sockaddr_in);
1834  GNUNET_memcpy(&r4,
1835  buf,
1836  sizeof(struct sockaddr_in));
1837  GNUNET_break_op(AF_INET == r4.sin_family);
1838  ret = GN_request_connection_reversal(&l4.sin_addr,
1839  ntohs(l4.sin_port),
1840  &r4.sin_addr,
1841  cfg);
1842  if (GNUNET_OK != ret)
1844  _("Connection reversal request failed\n"));
1846 }
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:171
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
uint16_t local_addr_size
Size of the local address included, in NBO.
Definition: nat.h:166
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
static int ret
Final status code.
Definition: gnunet-arm.c:89
#define _(String)
GNU gettext support macro.
Definition: platform.h:181
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
static char buf[2048]
void GNUNET_SERVICE_client_drop(struct GNUNET_SERVICE_Client *c)
Ask the server to disconnect from the given client.
Definition: service.c:2315
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:2234
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 1855 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().

1856 {
1857  struct StunExternalIP *se;
1858 
1859  while (NULL != (se = se_head))
1860  {
1862  se_tail,
1863  se);
1865  GNUNET_free(se);
1866  }
1868  if (NULL != scan_task)
1869  {
1871  scan_task = NULL;
1872  }
1873  if (NULL != stats)
1874  {
1876  GNUNET_NO);
1877  stats = NULL;
1878  }
1879  destroy_lal();
1880 }
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
External IP address as given to us via some STUN server.
static struct GNUNET_STATISTICS_Handle * stats
Handle to the statistics service.
#define GNUNET_NO
Definition: gnunet_common.h:78
static struct StunExternalIP * se_tail
Kept in a DLL.
void GNUNET_STATISTICS_destroy(struct GNUNET_STATISTICS_Handle *h, int sync_first)
Destroy a handle (free all state associated with it).
static struct GNUNET_SCHEDULER_Task * scan_task
Task scheduled to periodically scan our network interfaces.
static void destroy_lal()
Free the DLL starting at lal_head.
struct GNUNET_SCHEDULER_Task * timeout_task
Task we run to remove this entry when it is stale.
void GN_nat_status_changed(int have_nat)
We have changed our opinion about being NATed in the first place.
static struct StunExternalIP * se_head
Kept in a DLL.
#define GNUNET_free(ptr)
Wrapper around free.
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:956
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 1891 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().

1894 {
1895  cfg = c;
1896  if (GNUNET_OK !=
1898  "NAT",
1899  "STUN_STALE",
1902 
1903  /* Check for UPnP */
1904  enable_upnp
1906  "NAT",
1907  "ENABLE_UPNP");
1908  if (GNUNET_YES == enable_upnp)
1909  {
1910  /* check if it works */
1911  if (GNUNET_SYSERR ==
1913  GNUNET_NO,
1914  NULL))
1915  {
1917  _("UPnP enabled in configuration, but UPnP client `upnpc` command not found, disabling UPnP\n"));
1919  }
1920  }
1921  if (GNUNET_OK !=
1923  "nat",
1924  "DYNDNS_FREQUENCY",
1925  &dyndns_frequency))
1927 
1929  NULL);
1931  cfg);
1933  NULL);
1934 }
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:1284
struct GNUNET_STATISTICS_Handle * GNUNET_STATISTICS_create(const char *subsystem, const struct GNUNET_CONFIGURATION_Handle *cfg)
Get handle for the statistics service.
static struct GNUNET_STATISTICS_Handle * stats
Handle to the statistics service.
#define GNUNET_NO
Definition: gnunet_common.h:78
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
int GNUNET_OS_check_helper_binary(const char *binary, int check_suid, const char *params)
Check whether an executable exists and possibly if the suid bit is set on the file.
static struct GNUNET_SCHEDULER_Task * scan_task
Task scheduled to periodically scan our network interfaces.
#define _(String)
GNU gettext support macro.
Definition: platform.h:181
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_now(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run as soon as possible.
Definition: scheduler.c:1264
#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:76
static const struct GNUNET_CONFIGURATION_Handle * cfg
Handle to our current configuration.
int enable_upnp
Is UPnP enabled? GNUNET_YES if enabled, GNUNET_NO if disabled, GNUNET_SYSERR if configuration enabled...
#define GNUNET_log(kind,...)
#define GNUNET_YES
Definition: gnunet_common.h:77
static struct GNUNET_TIME_Relative dyndns_frequency
How often do we scan for changes in how our external (dyndns) hostname resolves?
int GNUNET_CONFIGURATION_get_value_yesno(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option)
Get a configuration value that should be in a set of "YES" or "NO".
Here is the call graph for this function:
Here is the caller graph for this function:

◆ client_connect_cb()

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

Callback called when a client connects to the service.

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

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

1949 {
1950  struct ClientHandle *ch;
1951 
1952  ch = GNUNET_new(struct ClientHandle);
1953  ch->mq = mq;
1954  ch->client = c;
1956  ch_tail,
1957  ch);
1958  return ch;
1959 }
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 1970 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.

1973 {
1974  struct ClientHandle *ch = internal_cls;
1975  struct LocalAddressList *lal;
1976 
1978  ch_tail,
1979  ch);
1980  for (unsigned int i = 0; i < ch->num_caddrs; i++)
1981  {
1982  if (NULL != ch->caddrs[i].mh)
1983  {
1985  ch->caddrs[i].mh = NULL;
1986  }
1987  }
1989  while (NULL != (lal = ch->ext_addr_head))
1990  {
1992  ch->ext_addr_tail,
1993  lal);
1994  GNUNET_free(lal);
1995  }
1996  if (NULL != ch->ext_dns_task)
1997  {
1999  ch->ext_dns_task = NULL;
2000  }
2001  if (NULL != ch->external_monitor)
2002  {
2004  ch->external_monitor = NULL;
2005  }
2006  if (NULL != ch->ext_dns)
2007  {
2009  ch->ext_dns = NULL;
2010  }
2013  GNUNET_free(ch);
2014 }
#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:956
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 274 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 279 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 284 of file gnunet-service-nat.c.

◆ stats

struct GNUNET_STATISTICS_Handle* stats
static

Handle to the statistics service.

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

◆ ch_head

struct ClientHandle* ch_head
static

Head of client DLL.

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

◆ ch_tail

struct ClientHandle* ch_tail
static

Tail of client DLL.

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

◆ lal_head

struct LocalAddressList* lal_head
static

Head of DLL of local addresses.

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

◆ lal_tail

struct LocalAddressList* lal_tail
static

Tail of DLL of local addresses.

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

◆ se_head

struct StunExternalIP* se_head
static

Kept in a DLL.

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

◆ se_tail

struct StunExternalIP* se_tail
static

Kept in a DLL.

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

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