GNUnet 0.22.2
gnunet-service-nat.c File Reference

network address translation traversal service More...

Include dependency graph for gnunet-service-nat.c:

Go to the source code of this file.

Data Structures

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

Macros

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

Functions

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

Variables

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

Detailed Description

network address translation traversal service

Author
Christian Grothoff

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

TODO:

  • migrate test cases to new NAT service
  • add new traceroute-based logic for external IP detection
  • implement & test STUN processing to classify NAT; basically, open port & try different methods.

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

◆ AUTOCONFIG_TIMEOUT

#define AUTOCONFIG_TIMEOUT
Value:
#define GNUNET_TIME_UNIT_SECONDS
One second.
struct GNUNET_TIME_Relative GNUNET_TIME_relative_multiply(struct GNUNET_TIME_Relative rel, unsigned long long factor)
Multiply relative time by a given factor.
Definition: time.c:486

How long do we wait until we forcefully terminate autoconfiguration?

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

◆ DYNDNS_FREQUENCY

#define DYNDNS_FREQUENCY
Value:
#define GNUNET_TIME_UNIT_MINUTES
One minute.

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

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

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

349{
351 lal_tail,
352 lal);
353 if (NULL != lal->hc)
354 {
356 "Lost NATed local address %s, stopping NAT server\n",
357 GNUNET_a2s ((const struct sockaddr *) &lal->addr,
358 sizeof(struct sockaddr_in)));
359
361 lal->hc = NULL;
362 }
363 GNUNET_free (lal);
364}
static struct LocalAddressList * lal_head
Head of DLL of local addresses.
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.
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
#define GNUNET_log(kind,...)
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).
@ GNUNET_ERROR_TYPE_MESSAGE
#define GNUNET_free(ptr)
Wrapper around free.
struct HelperContext * hc
Context for a gnunet-helper-nat-server used to listen for ICMP messages to this client for connection...
struct sockaddr_storage addr
The address itself (i.e.

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

Referenced by destroy_lal(), and run_scan().

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

372{
373 struct LocalAddressList *lal;
374
375 while (NULL != (lal = lal_head))
376 free_lal (lal);
377}
static void free_lal(struct LocalAddressList *lal)
Remove and free an entry from the lal_head DLL.
List of local addresses this system has.

References free_lal(), and lal_head.

Referenced by shutdown_task().

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

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

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.

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

454{
455 struct in_addr net;
456
457 if (0 == ip->s_addr)
458 return GNUNET_YES;
459 if (0 == bits)
460 return GNUNET_YES;
461 GNUNET_assert (1 == inet_pton (AF_INET,
462 network,
463 &net));
464 return ! ((ip->s_addr ^ net.s_addr) & htonl (0xFFFFFFFFu << (32 - bits)));
465}
@ GNUNET_YES
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.

References GNUNET_assert, and GNUNET_YES.

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

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

480{
481 struct in6_addr net;
482 struct in6_addr mask;
483 unsigned int off;
484
485 if (0 == bits)
486 return GNUNET_YES;
487 GNUNET_assert (1 == inet_pton (AF_INET6,
488 network,
489 &net));
490 memset (&mask, 0, sizeof(mask));
491 if (0 == GNUNET_memcmp (&mask,
492 ip))
493 return GNUNET_YES;
494 off = 0;
495 while (bits > 8)
496 {
497 mask.s6_addr[off++] = 0xFF;
498 bits -= 8;
499 }
500 while (bits > 0)
501 {
502 mask.s6_addr[off] = (mask.s6_addr[off] >> 1) + 0x80;
503 bits--;
504 }
505 for (unsigned j = 0; j < sizeof(struct in6_addr) / sizeof(uint32_t); j++)
506 if (((((uint32_t *) ip)[j] & ((uint32_t *) &mask)[j])) !=
507 (((uint32_t *) &net)[j] & ((int *) &mask)[j]))
508 return GNUNET_NO;
509 return GNUNET_YES;
510}
#define GNUNET_memcmp(a, b)
Compare memory in a and b, where both must be of the same pointer type.
@ GNUNET_NO

References GNUNET_assert, GNUNET_memcmp, GNUNET_NO, and GNUNET_YES.

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

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

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

References match_ipv4().

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

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

541{
542 return
543 match_ipv6 ("fc00::", ip, 7) || /* RFC 4193 */
544 match_ipv6 ("fec0::", ip, 10) || /* RFC 3879 */
545 match_ipv6 ("fe80::", ip, 10); /* RFC 4291, link-local */
546}
static int match_ipv6(const char *network, const struct in6_addr *ip, uint8_t bits)
Check if ip is in network with bits netmask.

References match_ipv6().

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

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

587{
588 struct IfcProcContext *ifc_ctx = cls;
589 struct LocalAddressList *lal;
590 size_t alen;
591 const struct in_addr *ip4;
592 const struct in6_addr *ip6;
594
595 switch (addr->sa_family)
596 {
597 case AF_INET:
598 alen = sizeof(struct sockaddr_in);
599 ip4 = &((const struct sockaddr_in *) addr)->sin_addr;
600 if (match_ipv4 ("127.0.0.0", ip4, 8))
602 else if (is_nat_v4 (ip4))
604 else
606 break;
607
608 case AF_INET6:
609 alen = sizeof(struct sockaddr_in6);
610 ip6 = &((const struct sockaddr_in6 *) addr)->sin6_addr;
611 if (match_ipv6 ("::1", ip6, 128))
613 else if (is_nat_v6 (ip6))
615 else
617 if ((ip6->s6_addr[11] == 0xFF) &&
618 (ip6->s6_addr[12] == 0xFE))
619 {
620 /* contains a MAC, be extra careful! */
622 }
623 break;
624
625#if AF_UNIX
626 case AF_UNIX:
627 GNUNET_break (0);
628 return GNUNET_OK;
629#endif
630 default:
631 GNUNET_break (0);
632 return GNUNET_OK;
633 }
634 lal = GNUNET_malloc (sizeof(*lal));
635 lal->af = addr->sa_family;
636 lal->ac = ac;
637 GNUNET_memcpy (&lal->addr,
638 addr,
639 alen);
641 ifc_ctx->lal_tail,
642 lal);
643 return GNUNET_OK;
644}
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 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_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.
#define GNUNET_malloc(size)
Wrapper around malloc.
GNUNET_NAT_AddressClass
Some addresses contain sensitive information or are not suitable for global distribution.
@ GNUNET_NAT_AC_LAN
Addresses useful in the local wired network, i.e.
@ GNUNET_NAT_AC_GLOBAL
Addresses that are global (i.e.
@ GNUNET_NAT_AC_PRIVATE
Flag for addresses that are highly sensitive (i.e.
@ GNUNET_NAT_AC_LOOPBACK
Loopback addresses, only useful under special circumstances.
Closure for ifc_proc.
struct LocalAddressList * lal_head
Head of DLL of local addresses.
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?

References LocalAddressList::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().

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

663{
664 struct GNUNET_MQ_Envelope *env;
666
668 "Notifying client about %s of IP %s\n",
669 add ? "addition" : "removal",
670 GNUNET_a2s (addr,
671 addr_len));
673 addr_len,
675 msg->add_remove = htonl (add);
676 msg->addr_class = htonl (ac);
677 GNUNET_memcpy (&msg[1],
678 addr,
679 addr_len);
681 env);
682}
struct GNUNET_MessageHeader * msg
Definition: 005.c:2
struct GNUNET_MQ_Envelope * env
Definition: 005.c:1
static struct GNUNET_CADET_Channel * ch
Channel handle.
Definition: gnunet-cadet.c:117
static int add
Desired action is to add a record.
@ GNUNET_ERROR_TYPE_DEBUG
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:305
#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:61
#define GNUNET_MESSAGE_TYPE_NAT_ADDRESS_CHANGE
Message to from NAT service notifying us that one of our addresses changed.
struct GNUNET_MQ_Handle * mq
Message Queue for the channel (which we are implementing).
Definition: cadet.h:142
Service notifying the client about changes in the set of addresses it has.
Definition: nat.h:202

References add, ch, env, GNUNET_a2s(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_memcpy, GNUNET_MESSAGE_TYPE_NAT_ADDRESS_CHANGE, GNUNET_MQ_msg_extra, GNUNET_MQ_send(), GNUNET_CADET_Channel::mq, and msg.

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

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

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

References add, ch, delta, 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(), and notify_client().

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

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

824{
825 for (struct ClientHandle *ch = ch_head;
826 NULL != ch;
827 ch = ch->next)
829 ch,
830 add);
831}
static struct ClientHandle * ch_head
Head of client DLL.
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 containing information about a client, handle to connect to it, and any pending messages that ...

References add, ch, ch_head, check_notify_client(), and delta.

Referenced by run_scan().

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

846{
847 struct ClientHandle *ch = cls;
848 struct sockaddr_in sa;
849 int have_v4;
850
851 /* (0) check if this impacts 'hole_external' */
852 if ((NULL != ch->hole_external) &&
853 (0 == strcasecmp (ch->hole_external,
854 "AUTO")))
855 {
856 struct LocalAddressList lal;
857 struct sockaddr_in *s4;
858
860 "Detected eternal IP, can now back-fill AUTO:%u in hole punching specification of `%s'\n",
861 (unsigned int) ch->ext_dns_port,
862 ch->section_name);
863 memset (&lal, 0, sizeof(lal));
864 s4 = (struct sockaddr_in *) &lal.addr;
865 s4->sin_family = AF_INET;
866 s4->sin_port = htons (ch->ext_dns_port);
867 s4->sin_addr = *v4;
868 lal.af = AF_INET;
871 ch,
872 add);
873 }
874
875 /* (1) check if client cares. */
876 if (! ch->natted_address)
877 return;
878 have_v4 = GNUNET_NO;
879 for (unsigned int i = 0; i < ch->num_caddrs; i++)
880 {
881 const struct sockaddr_storage *ss = &ch->caddrs[i].ss;
882
883 if (AF_INET != ss->ss_family)
884 continue;
885 have_v4 = GNUNET_YES;
886 break;
887 }
888 if (GNUNET_NO == have_v4)
889 return; /* IPv6-only */
890
891 /* (2) build address info */
892 memset (&sa,
893 0,
894 sizeof(sa));
895 sa.sin_family = AF_INET;
896 sa.sin_addr = *v4;
897 sa.sin_port = htons (0);
898
900 "Detected eternal IP %s, notifying client of external IP (without port)\n",
901 GNUNET_a2s ((const struct sockaddr *) &sa,
902 sizeof(sa)));
903 /* (3) notify client of change */
907 ch,
908 add,
909 &sa,
910 sizeof(sa));
911}
@ GNUNET_NAT_AC_MANUAL
Addresses that were manually configured by the user.

References LocalAddressList::ac, add, LocalAddressList::addr, LocalAddressList::af, ch, check_notify_client(), 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, is_nat_v4(), and notify_client().

Referenced by handle_register().

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

924{
925 struct LocalAddressList *lal = cls;
926 const struct sockaddr_in *l4;
927
928 GNUNET_assert (AF_INET == lal->af);
929 l4 = (const struct sockaddr_in *) &lal->addr;
930 for (struct ClientHandle *ch = ch_head;
931 NULL != ch;
932 ch = ch->next)
933 {
935 struct GNUNET_MQ_Envelope *env;
936 int match;
937
938 /* Check if client is in applicable range for ICMP NAT traversal
939 for this local address */
940 if (! ch->natted_address)
941 continue;
942 match = GNUNET_NO;
943 for (unsigned int i = 0; i < ch->num_caddrs; i++)
944 {
945 struct ClientAddress *ca = &ch->caddrs[i];
946 const struct sockaddr_in *c4;
947
948 if (AF_INET != ca->ss.ss_family)
949 continue;
950 c4 = (const struct sockaddr_in *) &ca->ss;
951 if ((0 != c4->sin_addr.s_addr) &&
952 (l4->sin_addr.s_addr != c4->sin_addr.s_addr))
953 continue;
954 match = GNUNET_YES;
955 break;
956 }
957 if (! match)
958 continue;
959
960 /* Notify applicable client about connection reversal request */
961 env = GNUNET_MQ_msg_extra (crrm,
962 sizeof(struct sockaddr_in),
964 GNUNET_memcpy (&crrm[1],
965 ra,
966 sizeof(struct sockaddr_in));
968 env);
969 }
970}
#define GNUNET_MESSAGE_TYPE_NAT_CONNECTION_REVERSAL_REQUESTED
Message to from NAT service notifying us that connection reversal was requested by another peer.
Information we track per client address.
struct sockaddr_storage ss
Network address used by the client.
Service telling a client that connection reversal was requested.
Definition: nat.h:187

References LocalAddressList::addr, LocalAddressList::af, ch, ch_head, 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().

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

980{
981 struct IfcProcContext ifc_ctx;
982 int found;
983 int have_nat;
984 struct LocalAddressList *lnext;
985
987 &run_scan,
988 NULL);
989 memset (&ifc_ctx,
990 0,
991 sizeof(ifc_ctx));
993 &ifc_ctx);
994 /* remove addresses that disappeared */
995 for (struct LocalAddressList *lal = lal_head;
996 NULL != lal;
997 lal = lnext)
998 {
999 lnext = lal->next;
1000 found = GNUNET_NO;
1001 for (struct LocalAddressList *pos = ifc_ctx.lal_head;
1002 NULL != pos;
1003 pos = pos->next)
1004 {
1005 if ((pos->af == lal->af) &&
1006 (0 == memcmp (&lal->addr,
1007 &pos->addr,
1008 (AF_INET == lal->af)
1009 ? sizeof(struct sockaddr_in)
1010 : sizeof(struct sockaddr_in6))))
1011 {
1012 found = GNUNET_YES;
1013 }
1014 }
1015 if (GNUNET_NO == found)
1016 {
1017 notify_clients (lal,
1018 GNUNET_NO);
1019 free_lal (lal);
1020 }
1021 }
1022
1023 /* add addresses that appeared */
1024 have_nat = GNUNET_NO;
1025 for (struct LocalAddressList *pos = ifc_ctx.lal_head;
1026 NULL != pos;
1027 pos = ifc_ctx.lal_head)
1028 {
1029 found = GNUNET_NO;
1030 if (GNUNET_NAT_AC_LAN == (GNUNET_NAT_AC_LAN & pos->ac))
1031 have_nat = GNUNET_YES;
1032 for (struct LocalAddressList *lal = lal_head;
1033 NULL != lal;
1034 lal = lal->next)
1035 {
1036 if ((pos->af == lal->af) &&
1037 (0 == memcmp (&lal->addr,
1038 &pos->addr,
1039 (AF_INET == lal->af)
1040 ? sizeof(struct sockaddr_in)
1041 : sizeof(struct sockaddr_in6))))
1042 found = GNUNET_YES;
1043 }
1044 GNUNET_CONTAINER_DLL_remove (ifc_ctx.lal_head,
1045 ifc_ctx.lal_tail,
1046 pos);
1047 if (GNUNET_YES == found)
1048 {
1049 GNUNET_free (pos);
1050 }
1051 else
1052 {
1053 notify_clients (pos,
1054 GNUNET_YES);
1056 lal_tail,
1057 pos);
1058 if ((AF_INET == pos->af) &&
1059 (NULL == pos->hc) &&
1060 (0 != (GNUNET_NAT_AC_LAN & pos->ac)))
1061 {
1062 const struct sockaddr_in *s4
1063 = (const struct sockaddr_in *) &pos->addr;
1064
1066 "Found NATed local address %s, starting NAT server\n",
1067 GNUNET_a2s ((const struct sockaddr *) &pos->addr,
1068 sizeof(*s4)));
1069 pos->hc = GN_start_gnunet_nat_server_ (&s4->sin_addr,
1071 pos,
1072 cfg);
1073 }
1074 }
1075 }
1076 GN_nat_status_changed (have_nat);
1077}
static const struct GNUNET_CONFIGURATION_Handle * cfg
Handle to our current configuration.
static void notify_clients(struct LocalAddressList *delta, int add)
Notify all clients about a change in the list of addresses this peer has.
static void run_scan(void *cls)
Task we run periodically to scan for network interfaces.
static struct GNUNET_SCHEDULER_Task * scan_task
Task scheduled to periodically scan our network interfaces.
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?
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.
void GN_nat_status_changed(int have_nat)
We have changed our opinion about being NATed in the first place.
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.
void GNUNET_OS_network_interfaces_list(GNUNET_OS_NetworkInterfaceProcessor proc, void *proc_cls)
Enumerate all network interfaces.
Definition: os_network.c:397
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_delayed(struct GNUNET_TIME_Relative delay, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay.
Definition: scheduler.c:1277
struct LocalAddressList * next
This is a linked list.

References cfg, 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(), lal_head, IfcProcContext::lal_head, lal_tail, IfcProcContext::lal_tail, LocalAddressList::next, notify_clients(), reversal_callback(), run_scan(), SCAN_FREQ, and scan_task.

Referenced by run(), and run_scan().

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

1097{
1098 struct ClientHandle *ch = cls;
1100
1101 switch (result)
1102 {
1104 GNUNET_assert (NULL != addr);
1105 break;
1106
1111 "Running upnpc failed: %d\n",
1112 result);
1113 return;
1114
1117 "external-ip binary not found\n");
1118 return;
1119
1122 "upnpc binary not found\n");
1123 return;
1124
1127 "external-ip binary could not be run\n");
1128 return;
1129
1132 "upnpc failed to create port mapping\n");
1133 return;
1134
1137 "Invalid output from upnpc\n");
1138 return;
1139
1142 "Invalid address returned by upnpc\n");
1143 return;
1144
1145 default:
1146 GNUNET_break (0); /* should not be possible */
1147 return;
1148 }
1149 switch (addr->sa_family)
1150 {
1151 case AF_INET:
1152 ac = is_nat_v4 (&((const struct sockaddr_in *) addr)->sin_addr)
1155 break;
1156
1157 case AF_INET6:
1158 ac = is_nat_v6 (&((const struct sockaddr_in6 *) addr)->sin6_addr)
1161 break;
1162
1163 default:
1164 GNUNET_break (0);
1165 return;
1166 }
1168 "upnp external address %s: %s\n",
1169 add_remove ? "added" : "removed",
1170 GNUNET_a2s (addr,
1171 addrlen));
1172 notify_client (ac,
1173 ch,
1174 add_remove,
1175 addr,
1176 addrlen);
1177}
static int result
Global testing status.
@ GNUNET_ERROR_TYPE_WARNING
@ GNUNET_ERROR_TYPE_INFO
@ GNUNET_NAT_ERROR_UPNPC_NOT_FOUND
upnpc command not found
@ GNUNET_NAT_ERROR_UPNPC_TIMEOUT
‘upnpc’ command took too long, process killed
@ GNUNET_NAT_ERROR_SUCCESS
Just the default.
@ GNUNET_NAT_ERROR_EXTERNAL_IP_UTILITY_OUTPUT_INVALID
‘external-ip’ command output invalid
@ GNUNET_NAT_ERROR_UPNPC_FAILED
Failed to run upnpc command.
@ GNUNET_NAT_ERROR_EXTERNAL_IP_UTILITY_FAILED
Failed to run external-ip command.
@ GNUNET_NAT_ERROR_UPNPC_PORTMAP_FAILED
‘upnpc’ command failed to establish port mapping
@ GNUNET_NAT_ERROR_EXTERNAL_IP_UTILITY_NOT_FOUND
‘external-ip’ command not found
@ GNUNET_NAT_ERROR_IPC_FAILURE
IPC Failure.
@ GNUNET_NAT_ERROR_EXTERNAL_IP_ADDRESS_INVALID
"no valid address was returned by `external-ip'"

References ch, 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(), notify_client(), and result.

Referenced by handle_register().

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
clsclient handle to act upon

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

1306{
1307 struct ClientHandle *ch = cls;
1308 struct LocalAddressList *lal;
1309
1311 "Performing DNS lookup for punched hole given for `%s' as `%s:%u'\n",
1312 ch->section_name,
1313 ch->hole_external,
1314 (unsigned int) ch->ext_dns_port);
1315 for (lal = ch->ext_addr_head; NULL != lal; lal = lal->next)
1316 lal->old = GNUNET_YES;
1317 ch->ext_dns_task = NULL;
1318 ch->ext_dns = GNUNET_RESOLVER_ip_get (ch->hole_external,
1319 AF_UNSPEC,
1322 ch);
1323}
static void process_external_ip(void *cls, const struct sockaddr *addr, socklen_t addrlen)
Our (external) hostname was resolved.
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:940
int old
GNUNET_YES if we saw this one in the previous iteration, but not in the current iteration and thus mi...

References ch, GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_RESOLVER_ip_get(), GNUNET_TIME_UNIT_MINUTES, GNUNET_YES, LocalAddressList::next, LocalAddressList::old, and process_external_ip().

Referenced by lookup_hole_external(), and process_external_ip().

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

1205{
1206 struct ClientHandle *ch = cls;
1207 struct LocalAddressList *lal;
1208 struct sockaddr_storage ss;
1209 struct sockaddr_in *v4;
1210 struct sockaddr_in6 *v6;
1211
1212 if (NULL == addr)
1213 {
1214 struct LocalAddressList *laln;
1215
1216 ch->ext_dns = NULL;
1217 ch->ext_dns_task
1220 ch);
1221 /* Current iteration is over, remove 'old' IPs now */
1222 for (lal = ch->ext_addr_head; NULL != lal; lal = laln)
1223 {
1224 laln = lal->next;
1225 if (GNUNET_YES == lal->old)
1226 {
1227 GNUNET_CONTAINER_DLL_remove (ch->ext_addr_head,
1228 ch->ext_addr_tail,
1229 lal);
1231 ch,
1232 GNUNET_NO);
1233 GNUNET_free (lal);
1234 }
1235 }
1236 return;
1237 }
1239 "Got IP `%s' for external address `%s'\n",
1241 addrlen),
1242 ch->hole_external);
1243
1244 /* build sockaddr storage with port number */
1245 memset (&ss,
1246 0,
1247 sizeof(ss));
1248 GNUNET_memcpy (&ss,
1249 addr,
1250 addrlen);
1251 switch (addr->sa_family)
1252 {
1253 case AF_INET:
1254 v4 = (struct sockaddr_in *) &ss;
1255 v4->sin_port = htons (ch->ext_dns_port);
1256 break;
1257
1258 case AF_INET6:
1259 v6 = (struct sockaddr_in6 *) &ss;
1260 v6->sin6_port = htons (ch->ext_dns_port);
1261 break;
1262
1263 default:
1264 GNUNET_break (0);
1265 return;
1266 }
1267 /* See if 'ss' matches any of our known addresses */
1268 for (lal = ch->ext_addr_head; NULL != lal; lal = lal->next)
1269 {
1270 if (GNUNET_NO == lal->old)
1271 continue; /* already processed, skip */
1272 if ((addr->sa_family == lal->addr.ss_family) &&
1273 (0 == memcmp (&ss,
1274 &lal->addr,
1275 addrlen)))
1276 {
1277 /* Address unchanged, remember so we do not remove */
1278 lal->old = GNUNET_NO;
1279 return; /* done here */
1280 }
1281 }
1282 /* notify client, and remember IP for later removal! */
1283 lal = GNUNET_new (struct LocalAddressList);
1284 lal->addr = ss;
1285 lal->af = ss.ss_family;
1287 GNUNET_CONTAINER_DLL_insert (ch->ext_addr_head,
1288 ch->ext_addr_tail,
1289 lal);
1291 ch,
1292 GNUNET_YES);
1293}
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_new(type)
Allocate a struct or union of the given type.

References LocalAddressList::ac, LocalAddressList::addr, LocalAddressList::af, ch, check_notify_client(), dyndns_frequency, dyndns_lookup(), 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, LocalAddressList::next, and LocalAddressList::old.

Referenced by dyndns_lookup().

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

1339{
1340 char *port;
1341 unsigned int pnum;
1342 struct sockaddr_in *s4;
1343 struct LocalAddressList *lal;
1344
1345 port = strrchr (ch->hole_external, ':');
1346 if (NULL == port)
1347 {
1349 _ ("Malformed punched hole specification `%s' (lacks port)\n"),
1350 ch->hole_external);
1351 return;
1352 }
1353 if ((1 != sscanf (port + 1,
1354 "%u",
1355 &pnum)) ||
1356 (pnum > 65535))
1357 {
1359 _ (
1360 "Invalid port number in punched hole specification `%s' (lacks port)\n"),
1361 port + 1);
1362 return;
1363 }
1364 ch->ext_dns_port = (uint16_t) pnum;
1365 *port = '\0';
1366
1367 lal = GNUNET_new (struct LocalAddressList);
1368 if ('[' == *ch->hole_external)
1369 {
1370 struct sockaddr_in6 *s6 = (struct sockaddr_in6 *) &lal->addr;
1371
1372 s6->sin6_family = AF_INET6;
1373 if (']' != (ch->hole_external[strlen (ch->hole_external) - 1]))
1374 {
1376 _ ("Malformed punched hole specification `%s' (lacks `]')\n"),
1377 ch->hole_external);
1378 GNUNET_free (lal);
1379 return;
1380 }
1381 ch->hole_external[strlen (ch->hole_external) - 1] = '\0';
1382 if (1 != inet_pton (AF_INET6,
1383 ch->hole_external + 1,
1384 &s6->sin6_addr))
1385 {
1387 _ (
1388 "Malformed punched hole specification `%s' (IPv6 address invalid)"),
1389 ch->hole_external + 1);
1390 GNUNET_free (lal);
1391 return;
1392 }
1393 s6->sin6_port = htons (ch->ext_dns_port);
1394 lal->af = AF_INET6;
1396 GNUNET_CONTAINER_DLL_insert (ch->ext_addr_head,
1397 ch->ext_addr_tail,
1398 lal);
1400 ch,
1401 GNUNET_YES);
1402 return;
1403 }
1404
1405 s4 = (struct sockaddr_in *) &lal->addr;
1406 s4->sin_family = AF_INET;
1407 if (1 == inet_pton (AF_INET,
1408 ch->hole_external,
1409 &s4->sin_addr))
1410 {
1412 "IPv4 punched hole given for `%s' via `%s:%u'\n",
1413 ch->section_name,
1414 ch->hole_external,
1415 (unsigned int) ch->ext_dns_port);
1416 s4->sin_port = htons (ch->ext_dns_port);
1417 lal->af = AF_INET;
1419 GNUNET_CONTAINER_DLL_insert (ch->ext_addr_head,
1420 ch->ext_addr_tail,
1421 lal);
1423 ch,
1424 GNUNET_YES);
1425 return;
1426 }
1427 if (0 == strcasecmp (ch->hole_external,
1428 "AUTO"))
1429 {
1430 /* handled in #notify_client_external_ipv4_change() */
1431 GNUNET_free (lal);
1432 return;
1433 }
1434 /* got a DNS name, trigger lookup! */
1435 GNUNET_free (lal);
1436 ch->ext_dns_task
1438 ch);
1439}
static uint16_t port
Port number.
Definition: gnunet-bcd.c:146
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:1304
#define _(String)
GNU gettext support macro.
Definition: platform.h:179

References _, LocalAddressList::ac, LocalAddressList::addr, LocalAddressList::af, ch, check_notify_client(), dyndns_lookup(), 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, and port.

Referenced by handle_register().

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

1452{
1453 struct ClientHandle *ch = cls;
1454 const char *off;
1455 size_t left;
1456
1457 if ((0 != ch->proto) ||
1458 (NULL != ch->caddrs))
1459 {
1460 /* double registration not allowed */
1461 GNUNET_break (0);
1463 return;
1464 }
1465 ch->flags = message->flags;
1466 ch->proto = message->proto;
1467 ch->num_caddrs = ntohs (message->num_addrs);
1468 ch->caddrs = GNUNET_new_array (ch->num_caddrs,
1469 struct ClientAddress);
1470 left = ntohs (message->header.size) - sizeof(*message);
1471 off = (const char *) &message[1];
1472 for (unsigned int i = 0; i < ch->num_caddrs; i++)
1473 {
1474 const struct sockaddr *sa = (const struct sockaddr *) off;
1475 size_t alen;
1476 uint16_t port;
1477 int is_nat;
1478
1479 if (sizeof(sa_family_t) > left)
1480 {
1481 GNUNET_break (0);
1483 return;
1484 }
1485 is_nat = GNUNET_NO;
1486 switch (sa->sa_family)
1487 {
1488 case AF_INET:
1489 {
1490 struct sockaddr_in s4;
1491
1492 GNUNET_memcpy (&s4,
1493 off,
1494 sizeof(struct sockaddr_in));
1495 alen = sizeof(struct sockaddr_in);
1496 if (is_nat_v4 (&s4.sin_addr))
1497 is_nat = GNUNET_YES;
1498 port = ntohs (s4.sin_port);
1499 }
1500 break;
1501
1502 case AF_INET6:
1503 {
1504 struct sockaddr_in6 s6;
1505
1506 GNUNET_memcpy (&s6,
1507 off,
1508 sizeof(struct sockaddr_in6));
1509 alen = sizeof(struct sockaddr_in6);
1510 if (is_nat_v6 (&s6.sin6_addr))
1511 is_nat = GNUNET_YES;
1512 port = ntohs (s6.sin6_port);
1513 }
1514 break;
1515
1516#if AF_UNIX
1517 case AF_UNIX:
1518 alen = sizeof(struct sockaddr_un);
1519 port = 0;
1520 break;
1521#endif
1522 default:
1523 GNUNET_break (0);
1525 return;
1526 }
1527 /* store address */
1528 GNUNET_assert (alen <= left);
1529 GNUNET_assert (alen <= sizeof(struct sockaddr_storage));
1530 GNUNET_memcpy (&ch->caddrs[i].ss,
1531 off,
1532 alen);
1533
1534 /* If applicable, try UPNPC NAT punching */
1535 if ((is_nat) &&
1536 (enable_upnp) &&
1537 ((IPPROTO_TCP == ch->proto) ||
1538 (IPPROTO_UDP == ch->proto)))
1539 {
1540 ch->natted_address = GNUNET_YES;
1541 ch->caddrs[i].mh
1543 IPPROTO_TCP == ch->proto,
1545 ch);
1546 }
1547
1548 off += alen;
1549 }
1550
1551 ch->section_name
1552 = GNUNET_strndup (off,
1553 ntohs (message->str_len));
1555 "Received REGISTER message from client for subsystem `%s'\n",
1556 ch->section_name);
1557 if (GNUNET_OK ==
1559 ch->section_name,
1560 "HOLE_EXTERNAL",
1561 &ch->hole_external))
1563
1564 /* Actually send IP address list to client */
1565 for (struct LocalAddressList *lal = lal_head;
1566 NULL != lal;
1567 lal = lal->next)
1568 {
1570 ch,
1571 GNUNET_YES);
1572 }
1573 /* Also consider IPv4 determined by `external-ip` */
1574 ch->external_monitor
1576 ch);
1578}
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.
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.
static void lookup_hole_external(struct ClientHandle *ch)
Resolve the hole_external name to figure out our external address from a manually punched hole.
int enable_upnp
Is UPnP enabled? GNUNET_YES if enabled, GNUNET_NO if disabled, GNUNET_SYSERR if configuration enabled...
struct GN_ExternalIPMonitor * GN_external_ipv4_monitor_start(GN_NotifyExternalIPv4Change cb, void *cb_cls)
Start monitoring external IPv4 addresses.
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.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_string(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, char **value)
Get a configuration value that should be a string.
#define GNUNET_strndup(a, length)
Wrapper around GNUNET_xstrndup_.
#define GNUNET_new_array(n, type)
Allocate a size n array with structs or unions of the given type.
void GNUNET_SERVICE_client_drop(struct GNUNET_SERVICE_Client *c)
Ask the server to disconnect from the given client.
Definition: service.c:2418
void GNUNET_SERVICE_client_continue(struct GNUNET_SERVICE_Client *c)
Continue receiving further messages from the given client.
Definition: service.c:2389
uint8_t flags
An enum GNUNET_NAT_RegisterFlags.
Definition: nat.h:104
uint8_t proto
Client's IPPROTO, e.g.
Definition: nat.h:109

References cfg, ch, check_notify_client(), enable_upnp, GNUNET_NAT_RegisterMessage::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, is_nat_v4(), is_nat_v6(), lal_head, lookup_hole_external(), LocalAddressList::next, notify_client_external_ipv4_change(), GNUNET_NAT_RegisterMessage::num_addrs, port, GNUNET_NAT_RegisterMessage::proto, GNUNET_MessageHeader::size, GNUNET_NAT_RegisterMessage::str_len, and upnp_addr_change_cb().

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

1592{
1593 size_t sa_len = ntohs (message->sender_addr_size);
1594 size_t expect = sa_len + ntohs (message->payload_size);
1595
1596 if (ntohs (message->header.size) - sizeof(*message) != expect)
1597 {
1598 GNUNET_break (0);
1599 return GNUNET_SYSERR;
1600 }
1601 if (sa_len < sizeof(sa_family_t))
1602 {
1603 GNUNET_break (0);
1604 return GNUNET_SYSERR;
1605 }
1606 return GNUNET_OK;
1607}
struct GNUNET_MessageHeader header
Header with type GNUNET_MESSAGE_TYPE_NAT_HANDLE_STUN.
Definition: nat.h:139
uint16_t payload_size
Number of bytes of payload included, in NBO.
Definition: nat.h:149
uint16_t sender_addr_size
Size of the sender address included, in NBO.
Definition: nat.h:144

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.

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

1620{
1621 for (struct ClientHandle *ch = ch_head;
1622 NULL != ch;
1623 ch = ch->next)
1624 {
1625 struct sockaddr_in v4;
1627 struct GNUNET_MQ_Envelope *env;
1628
1629 if (! ch->natted_address)
1630 continue;
1631 v4 = *ip;
1632 v4.sin_port = htons (0);
1634 sizeof(v4),
1636 msg->add_remove = htonl ((int32_t) add);
1637 msg->addr_class = htonl (GNUNET_NAT_AC_EXTERN
1639 GNUNET_memcpy (&msg[1],
1640 &v4,
1641 sizeof(v4));
1643 env);
1644 }
1645}

References add, ch, ch_head, 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_add_global_address(), handle_stun(), and stun_ip_timeout().

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

1657{
1658 struct StunExternalIP *se = cls;
1659
1660 se->timeout_task = NULL;
1662 GNUNET_NO);
1664 se_tail,
1665 se);
1666 GNUNET_free (se);
1667}
static struct StunExternalIP * se_head
Kept in a DLL.
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 struct StunExternalIP * se_tail
Kept in a DLL.
External IP address as given to us via some STUN server.
struct GNUNET_SCHEDULER_Task * timeout_task
Task we run to remove this entry when it is stale.
struct sockaddr_in external_addr
Our external IP address as reported by the STUN server.

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

Referenced by handle_stun().

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

1680{
1681 struct ClientHandle *ch = cls;
1682 const char *buf = (const char *) &message[1];
1683 const struct sockaddr *sa;
1684 const void *payload;
1685 size_t sa_len;
1686 size_t payload_size;
1687 struct sockaddr_in external_addr;
1688
1689 sa_len = ntohs (message->sender_addr_size);
1690 payload_size = ntohs (message->payload_size);
1691 sa = (const struct sockaddr *) &buf[0];
1692 payload = (const struct sockaddr *) &buf[sa_len];
1693 switch (sa->sa_family)
1694 {
1695 case AF_INET:
1696 if (sa_len != sizeof(struct sockaddr_in))
1697 {
1698 GNUNET_break (0);
1700 return;
1701 }
1702 break;
1703
1704 case AF_INET6:
1705 if (sa_len != sizeof(struct sockaddr_in6))
1706 {
1707 GNUNET_break (0);
1709 return;
1710 }
1711 break;
1712 }
1714 "Received HANDLE_STUN message from client\n");
1715 if (GNUNET_OK ==
1717 payload_size,
1718 &external_addr))
1719 {
1720 /* We now know that a server at "sa" claims that
1721 we are visible at IP "external_addr".
1722
1723 We should (for some fixed period of time) tell
1724 all of our clients that listen to a NAT'ed address
1725 that they might want to consider the given 'external_ip'
1726 as their public IP address (this includes TCP and UDP
1727 clients, even if only UDP sends STUN requests).
1728
1729 If we do not get a renewal, the "external_addr" should be
1730 removed again. The timeout frequency should be configurable
1731 (with a sane default), so that the UDP plugin can tell how
1732 often to re-request STUN.
1733 */struct StunExternalIP *se;
1734
1735 /* Check if we had a prior response from this STUN server */
1736 for (se = se_head; NULL != se; se = se->next)
1737 {
1738 if ((se->stun_server_addr_len != sa_len) ||
1739 (0 != memcmp (sa,
1740 &se->stun_server_addr,
1741 sa_len)))
1742 continue; /* different STUN server */
1743 if (0 != GNUNET_memcmp (&external_addr,
1744 &se->external_addr))
1745 {
1746 /* external IP changed, update! */
1748 GNUNET_NO);
1751 GNUNET_YES);
1752 }
1753 /* update timeout */
1755 se->timeout_task
1758 se);
1759 return;
1760 }
1761 /* STUN server is completely new, create fresh entry */
1762 se = GNUNET_new (struct StunExternalIP);
1765 sa,
1766 sa_len);
1767 se->stun_server_addr_len = sa_len;
1770 se);
1772 se_tail,
1773 se);
1775 GNUNET_NO);
1776 }
1778}
static unsigned long long payload
How much data are we currently storing in the database?
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...
static struct GNUNET_TIME_Relative stun_stale_timeout
Timeout to use when STUN data is considered stale.
int GNUNET_NAT_stun_handle_packet_(const void *data, size_t len, struct sockaddr_in *arg)
Handle an incoming STUN response.
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:980
size_t stun_server_addr_len
Number of bytes used in stun_server_addr.
struct sockaddr_storage stun_server_addr
Address of the reporting STUN server.
struct StunExternalIP * next
Kept in a DLL.

References ch, 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, se_head, se_tail, 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.

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

1795{
1796 size_t expect;
1797
1798 expect = ntohs (message->local_addr_size)
1799 + ntohs (message->remote_addr_size);
1800 if (ntohs (message->header.size) - sizeof(*message) != expect)
1801 {
1802 GNUNET_break (0);
1803 return GNUNET_SYSERR;
1804 }
1805 return GNUNET_OK;
1806}
struct GNUNET_MessageHeader header
Header with type GNUNET_MESSAGE_TYPE_NAT_REQUEST_CONNECTION_REVERSAL.
Definition: nat.h:165
uint16_t local_addr_size
Size of the local address included, in NBO.
Definition: nat.h:170
uint16_t remote_addr_size
Size of the remote address included, in NBO.
Definition: nat.h:175

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.

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

1820{
1821 struct ClientHandle *ch = cls;
1822 const char *buf = (const char *) &message[1];
1823 size_t local_sa_len = ntohs (message->local_addr_size);
1824 size_t remote_sa_len = ntohs (message->remote_addr_size);
1825 struct sockaddr_in l4;
1826 struct sockaddr_in r4;
1827 int ret;
1828
1830 "Received REQUEST CONNECTION REVERSAL message from client\n");
1831 if (local_sa_len != sizeof(struct sockaddr_in))
1832 {
1833 GNUNET_break_op (0);
1835 return;
1836 }
1837 if (remote_sa_len != sizeof(struct sockaddr_in))
1838 {
1839 GNUNET_break_op (0);
1841 return;
1842 }
1843 GNUNET_memcpy (&l4,
1844 buf,
1845 sizeof(struct sockaddr_in));
1846 GNUNET_break_op (AF_INET == l4.sin_family);
1847 buf += sizeof(struct sockaddr_in);
1848 GNUNET_memcpy (&r4,
1849 buf,
1850 sizeof(struct sockaddr_in));
1851 GNUNET_break_op (AF_INET == r4.sin_family);
1852 ret = GN_request_connection_reversal (&l4.sin_addr,
1853 ntohs (l4.sin_port),
1854 &r4.sin_addr,
1855 cfg);
1856 if (GNUNET_OK != ret)
1858 _ ("Connection reversal request failed\n"));
1860}
static int ret
Final status code.
Definition: gnunet-arm.c:93
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_break_op(cond)
Use this for assertion violations caused by other peers (i.e.

References _, cfg, ch, 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.

Here is the call graph for this function:

◆ check_add_global_address()

static enum GNUNET_GenericReturnValue check_add_global_address ( void *  cls,
const struct GNUNET_NAT_AddGlobalAddressMessage message 
)
static

Check validity of GNUNET_MESSAGE_TYPE_NAT_ADD_GLOBAL_ADDRESS message from client.

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

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

1875{
1876 //const char *buf = (const char *) &message[1];
1877 //uint16_t blen = ntohs (message->address_length);
1878 size_t left = ntohs (message->header.size) - sizeof(*message);
1879
1880 if (left != ntohs (message->address_length))
1881 {
1882 GNUNET_break_op (0);
1883 return GNUNET_SYSERR;
1884 }
1885 /* if ('\0' != buf[blen - 1]) */
1886 /* { */
1887 /* GNUNET_break_op (0); */
1888 /* return GNUNET_SYSERR; */
1889 /* } */
1890 return GNUNET_OK;
1891}
struct GNUNET_MessageHeader header
Header with type GNUNET_MESSAGE_TYPE_NAT_ADD_GLOBAL_ADDRESS.
Definition: nat.h:229
unsigned int address_length
Length of the address following the struct, in NBO.
Definition: nat.h:234

References GNUNET_NAT_AddGlobalAddressMessage::address_length, GNUNET_break_op, GNUNET_OK, GNUNET_SYSERR, GNUNET_NAT_AddGlobalAddressMessage::header, and GNUNET_MessageHeader::size.

◆ handle_add_global_address()

static void handle_add_global_address ( void *  cls,
const struct GNUNET_NAT_AddGlobalAddressMessage message 
)
static

Handle GNUNET_MESSAGE_TYPE_NAT_ADD_GLOBAL_ADDRESS message from client.

Parameters
clsclient who sent the message
messagethe message received

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

1905{
1906 struct ClientHandle *ch = cls;
1907 const char *buf = (const char *) &message[1];
1908 //uint16_t blen = ntohs (message->address_length);
1909 struct sockaddr_in sockaddr_ipv4 = {
1910 .sin_family = AF_INET
1911 };
1912
1913 //GNUNET_assert ('\0' == buf[blen - 1]);
1914 if (1 != inet_pton (AF_INET,
1915 buf,
1916 &sockaddr_ipv4.sin_addr))
1917 {
1919 "natting address %s length %u no ipv4\n",
1920 buf,
1921 message->address_length);
1922 GNUNET_break (0);
1924 return;
1925 }
1926 notify_clients_stun_change (&sockaddr_ipv4,
1927 GNUNET_YES);
1929}

References GNUNET_NAT_AddGlobalAddressMessage::address_length, ch, GNUNET_break, GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_SERVICE_client_continue(), GNUNET_YES, and notify_clients_stun_change().

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

1939{
1940 struct StunExternalIP *se;
1941
1942 while (NULL != (se = se_head))
1943 {
1945 se_tail,
1946 se);
1948 GNUNET_free (se);
1949 }
1951 if (NULL != scan_task)
1952 {
1954 scan_task = NULL;
1955 }
1956 if (NULL != stats)
1957 {
1959 GNUNET_NO);
1960 stats = NULL;
1961 }
1962 destroy_lal ();
1963}
static struct GNUNET_STATISTICS_Handle * stats
Handle to the statistics service.
static void destroy_lal()
Free the DLL starting at lal_head.
void GNUNET_STATISTICS_destroy(struct GNUNET_STATISTICS_Handle *h, int sync_first)
Destroy a handle (free all state associated with it).

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

Referenced by run().

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

1977{
1978 cfg = c;
1979 if (GNUNET_OK !=
1981 "NAT",
1982 "STUN_STALE",
1985
1986 /* Check for UPnP */
1989 "NAT",
1990 "ENABLE_UPNP");
1991 if (GNUNET_YES == enable_upnp)
1992 {
1993 /* check if it works */
1994 if (GNUNET_SYSERR ==
1996 GNUNET_NO,
1997 NULL))
1998 {
2000 _ (
2001 "UPnP enabled in configuration, but UPnP client `upnpc` command not found, disabling UPnP\n"));
2003 }
2004 }
2005 if (GNUNET_OK !=
2007 "nat",
2008 "DYNDNS_FREQUENCY",
2011
2014 "NAT",
2015 "ENABLE_IPSCAN");
2016
2018 NULL);
2020 cfg);
2023 NULL);
2024}
int enable_ipscan
Is IP Scanning enabled? GNUNET_YES if enabled, GNUNET_NO if disabled, without, only explicitly specif...
static void shutdown_task(void *cls)
Task run during shutdown.
#define DYNDNS_FREQUENCY
How often do we scan for changes in how our external (dyndns) hostname resolves?
enum GNUNET_GenericReturnValue 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".
enum GNUNET_GenericReturnValue 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.
@ GNUNET_ERROR_TYPE_ERROR
enum GNUNET_GenericReturnValue GNUNET_OS_check_helper_binary(const char *binary, bool check_suid, const char *params)
Check whether an executable exists and possibly if the suid bit is set on the file.
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,...
Definition: scheduler.c:1339
struct GNUNET_STATISTICS_Handle * GNUNET_STATISTICS_create(const char *subsystem, const struct GNUNET_CONFIGURATION_Handle *cfg)
Get handle for the statistics service.
#define GNUNET_TIME_UNIT_HOURS
One hour.

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

Here is the call 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 2036 of file gnunet-service-nat.c.

2039{
2040 struct ClientHandle *ch;
2041
2042 ch = GNUNET_new (struct ClientHandle);
2043 ch->mq = mq;
2044 ch->client = c;
2046 ch_tail,
2047 ch);
2048 return ch;
2049}
struct GNUNET_MQ_Handle * mq
Definition: 003.c:5
static struct ClientHandle * ch_tail
Tail of client DLL.

References ch, ch_head, ch_tail, GNUNET_CONTAINER_DLL_insert, GNUNET_new, mq, and GNUNET_CADET_Channel::mq.

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

2063{
2064 struct ClientHandle *ch = internal_cls;
2065 struct LocalAddressList *lal;
2066
2068 ch_tail,
2069 ch);
2070 for (unsigned int i = 0; i < ch->num_caddrs; i++)
2071 {
2072 if (NULL != ch->caddrs[i].mh)
2073 {
2074 GNUNET_NAT_mini_map_stop (ch->caddrs[i].mh);
2075 ch->caddrs[i].mh = NULL;
2076 }
2077 }
2078 GNUNET_free (ch->caddrs);
2079 while (NULL != (lal = ch->ext_addr_head))
2080 {
2081 GNUNET_CONTAINER_DLL_remove (ch->ext_addr_head,
2082 ch->ext_addr_tail,
2083 lal);
2084 GNUNET_free (lal);
2085 }
2086 if (NULL != ch->ext_dns_task)
2087 {
2088 GNUNET_SCHEDULER_cancel (ch->ext_dns_task);
2089 ch->ext_dns_task = NULL;
2090 }
2091 if (NULL != ch->external_monitor)
2092 {
2093 GN_external_ipv4_monitor_stop (ch->external_monitor);
2094 ch->external_monitor = NULL;
2095 }
2096 if (NULL != ch->ext_dns)
2097 {
2099 ch->ext_dns = NULL;
2100 }
2101 GNUNET_free (ch->hole_external);
2102 GNUNET_free (ch->section_name);
2103 GNUNET_free (ch);
2104}
void GN_external_ipv4_monitor_stop(struct GN_ExternalIPMonitor *mon)
Stop calling monitor.
void GNUNET_NAT_mini_map_stop(struct GNUNET_NAT_MiniHandle *mini)
Remove a mapping created with (mini)upnpc.
void GNUNET_RESOLVER_request_cancel(struct GNUNET_RESOLVER_RequestHandle *rh)
Cancel a request that is still pending with the resolver.

References ch, ch_head, ch_tail, GN_external_ipv4_monitor_stop(), GNUNET_CONTAINER_DLL_remove, GNUNET_free, GNUNET_NAT_mini_map_stop(), GNUNET_RESOLVER_request_cancel(), and GNUNET_SCHEDULER_cancel().

Here is the call graph for this function:

◆ GNUNET_SERVICE_MAIN()

Define "main" method using service macro.

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 278 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 283 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 288 of file gnunet-service-nat.c.

Referenced by handle_register(), handle_request_connection_reversal(), run(), and run_scan().

◆ stats

struct GNUNET_STATISTICS_Handle* stats
static

Handle to the statistics service.

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

Referenced by run(), and shutdown_task().

◆ scan_task

struct GNUNET_SCHEDULER_Task* scan_task
static

Task scheduled to periodically scan our network interfaces.

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

Referenced by run(), run_scan(), and shutdown_task().

◆ ch_head

struct ClientHandle* ch_head
static

◆ ch_tail

struct ClientHandle* ch_tail
static

Tail of client DLL.

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

Referenced by client_connect_cb(), and client_disconnect_cb().

◆ lal_head

struct LocalAddressList* lal_head
static

Head of DLL of local addresses.

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

Referenced by destroy_lal(), free_lal(), handle_register(), and run_scan().

◆ lal_tail

struct LocalAddressList* lal_tail
static

Tail of DLL of local addresses.

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

Referenced by free_lal(), and run_scan().

◆ se_head

struct StunExternalIP* se_head
static

Kept in a DLL.

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

Referenced by handle_stun(), shutdown_task(), and stun_ip_timeout().

◆ se_tail

struct StunExternalIP* se_tail
static

Kept in a DLL.

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

Referenced by handle_stun(), shutdown_task(), and stun_ip_timeout().

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

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

◆ enable_ipscan

int enable_ipscan

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

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

Referenced by run().