GNUnet 0.21.1
nat_api.c File Reference
#include "platform.h"
#include "gnunet_nat_service.h"
#include "nat.h"
#include "nat_stun.h"
Include dependency graph for nat_api.c:

Go to the source code of this file.

Data Structures

struct  AddrEntry
 Entry in DLL of addresses of this peer. More...
 
struct  GNUNET_NAT_Handle
 Handle for active NAT registrations. More...
 

Functions

static void do_connect (void *cls)
 Task to connect to the NAT service. More...
 
static void reconnect (struct GNUNET_NAT_Handle *nh)
 Task to connect to the NAT service. More...
 
static int check_connection_reversal_request (void *cls, const struct GNUNET_NAT_ConnectionReversalRequestedMessage *crm)
 Check connection reversal request. More...
 
static void handle_connection_reversal_request (void *cls, const struct GNUNET_NAT_ConnectionReversalRequestedMessage *crm)
 Handle connection reversal request. More...
 
static int check_address_change_notification (void *cls, const struct GNUNET_NAT_AddressChangeNotificationMessage *acn)
 Check address change notification. More...
 
static void handle_address_change_notification (void *cls, const struct GNUNET_NAT_AddressChangeNotificationMessage *acn)
 Handle connection reversal request. More...
 
static void mq_error_handler (void *cls, enum GNUNET_MQ_Error error)
 Handle queue errors by reconnecting to NAT. More...
 
struct GNUNET_NAT_HandleGNUNET_NAT_register (const struct GNUNET_CONFIGURATION_Handle *cfg, const char *config_section, uint8_t proto, unsigned int num_addrs, const struct sockaddr **addrs, const socklen_t *addrlens, GNUNET_NAT_AddressCallback address_callback, GNUNET_NAT_ReversalCallback reversal_callback, void *callback_cls)
 Attempt to enable port redirection and detect public IP address contacting UPnP or NAT-PMP routers on the local network. More...
 
static char * get_address_without_port (const char *address)
 Get the IP address without the port number. More...
 
void GNUNET_NAT_add_global_address (struct GNUNET_NAT_Handle *nh, char *addr, unsigned int address_length)
 Add global address to the list of addresses and notify clients. More...
 
static enum GNUNET_GenericReturnValue test_stun_packet (const void *data, size_t len)
 Check if an incoming message is a STUN message. More...
 
int GNUNET_NAT_stun_handle_packet (struct GNUNET_NAT_Handle *nh, const struct sockaddr *sender_addr, size_t sender_addr_len, const void *data, size_t data_size)
 Handle an incoming STUN message. More...
 
int GNUNET_NAT_test_address (struct GNUNET_NAT_Handle *nh, const void *addr, socklen_t addrlen)
 Test if the given address is (currently) a plausible IP address for this peer. More...
 
int GNUNET_NAT_request_reversal (struct GNUNET_NAT_Handle *nh, const struct sockaddr_in *local_sa, const struct sockaddr_in *remote_sa)
 We learned about a peer (possibly behind NAT) so run the gnunet-nat-client to send dummy ICMP responses to cause that peer to connect to us (connection reversal). More...
 
void GNUNET_NAT_unregister (struct GNUNET_NAT_Handle *nh)
 Stop port redirection and public IP address detection for the given handle. More...
 

Detailed Description

Author
Christian Grothoff
Milan Bouchet-Valat

Service for handling UPnP and NAT-PMP port forwarding and external IP address retrieval

Definition in file nat_api.c.

Function Documentation

◆ do_connect()

static void do_connect ( void *  cls)
static

Task to connect to the NAT service.

Parameters
clsour struct GNUNET_NAT_Handle *

Definition at line 329 of file nat_api.c.

330{
331 struct GNUNET_NAT_Handle *nh = cls;
334 connection_reversal_request,
337 nh),
339 address_change_notification,
342 nh),
344 };
345 struct GNUNET_MQ_Envelope *env;
346
347 nh->reconnect_task = NULL;
348 nh->mq =
350 "nat",
351 handlers,
353 nh);
354 if (NULL == nh->mq)
355 {
356 reconnect (nh);
357 return;
358 }
361 env);
362}
struct GNUNET_MQ_MessageHandlers handlers[]
Definition: 003.c:1
struct GNUNET_MQ_Envelope * env
Definition: 005.c:1
struct GNUNET_NAT_Handle * nh
Handle for connect to the NAT service.
struct GNUNET_MQ_Handle * GNUNET_CLIENT_connect(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *service_name, const struct GNUNET_MQ_MessageHandler *handlers, GNUNET_MQ_ErrorHandler error_handler, void *error_handler_cls)
Create a message queue to connect to a GNUnet service.
Definition: client.c:1057
struct GNUNET_MQ_Envelope * GNUNET_MQ_msg_copy(const struct GNUNET_MessageHeader *hdr)
Create a new envelope by copying an existing message.
Definition: mq.c:533
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:304
#define GNUNET_MQ_handler_end()
End-marker for the handlers array.
#define GNUNET_MQ_hd_var_size(name, code, str, ctx)
#define GNUNET_MESSAGE_TYPE_NAT_ADDRESS_CHANGE
Message to from NAT service notifying us that one of our addresses changed.
#define GNUNET_MESSAGE_TYPE_NAT_CONNECTION_REVERSAL_REQUESTED
Message to from NAT service notifying us that connection reversal was requested by another peer.
static void mq_error_handler(void *cls, enum GNUNET_MQ_Error error)
Handle queue errors by reconnecting to NAT.
Definition: nat_api.c:314
static void reconnect(struct GNUNET_NAT_Handle *nh)
Task to connect to the NAT service.
Definition: nat_api.c:140
Message handler for a specific message type.
Service notifying the client about changes in the set of addresses it has.
Definition: nat.h:202
Service telling a client that connection reversal was requested.
Definition: nat.h:187
Handle for active NAT registrations.
Definition: nat_api.c:72
const struct GNUNET_CONFIGURATION_Handle * cfg
Configuration we use.
Definition: nat_api.c:76
struct GNUNET_MQ_Handle * mq
Message queue for communicating with the NAT service.
Definition: nat_api.c:81
struct GNUNET_SCHEDULER_Task * reconnect_task
Task scheduled to reconnect to the service.
Definition: nat_api.c:116
struct GNUNET_MessageHeader * reg
Our registration message.
Definition: nat_api.c:86

References GNUNET_NAT_Handle::cfg, env, GNUNET_CLIENT_connect(), GNUNET_MESSAGE_TYPE_NAT_ADDRESS_CHANGE, GNUNET_MESSAGE_TYPE_NAT_CONNECTION_REVERSAL_REQUESTED, GNUNET_MQ_handler_end, GNUNET_MQ_hd_var_size, GNUNET_MQ_msg_copy(), GNUNET_MQ_send(), handlers, GNUNET_NAT_Handle::mq, mq_error_handler(), nh, reconnect(), GNUNET_NAT_Handle::reconnect_task, and GNUNET_NAT_Handle::reg.

Referenced by GNUNET_NAT_register(), and reconnect().

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

◆ reconnect()

static void reconnect ( struct GNUNET_NAT_Handle nh)
static

Task to connect to the NAT service.

Parameters
nhhandle to reconnect

Definition at line 140 of file nat_api.c.

141{
142 struct AddrEntry *ae;
143
144 if (NULL != nh->mq)
145 {
147 nh->mq = NULL;
148 }
149 while (NULL != (ae = nh->ae_head))
150 {
153 &ae->app_ctx,
154 GNUNET_NO,
155 ae->ac,
156 (const struct sockaddr *) &ae[1],
157 ae->addrlen);
158 GNUNET_free (ae);
159 }
163}
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
@ GNUNET_NO
#define GNUNET_free(ptr)
Wrapper around free.
void GNUNET_MQ_destroy(struct GNUNET_MQ_Handle *mq)
Destroy the message queue.
Definition: mq.c:683
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:1278
#define GNUNET_TIME_STD_BACKOFF(r)
Perform our standard exponential back-off calculation, starting at 1 ms and then going by a factor of...
static void do_connect(void *cls)
Task to connect to the NAT service.
Definition: nat_api.c:329
Entry in DLL of addresses of this peer.
Definition: nat_api.c:39
enum GNUNET_NAT_AddressClass ac
Address class of the address.
Definition: nat_api.c:59
void * app_ctx
Place where the application can store data (on add, and retrieve on remove).
Definition: nat_api.c:54
struct GNUNET_TIME_Relative reconnect_delay
How long to wait until we reconnect.
Definition: nat_api.c:121
void * callback_cls
Closure for the various callbacks.
Definition: nat_api.c:111
struct AddrEntry * ae_head
Head of address DLL.
Definition: nat_api.c:91
struct AddrEntry * ae_tail
Tail of address DLL.
Definition: nat_api.c:96
GNUNET_NAT_AddressCallback address_callback
Function to call when our addresses change.
Definition: nat_api.c:101

References AddrEntry::ac, GNUNET_NAT_Handle::address_callback, AddrEntry::addrlen, GNUNET_NAT_Handle::ae_head, GNUNET_NAT_Handle::ae_tail, AddrEntry::app_ctx, GNUNET_NAT_Handle::callback_cls, do_connect(), GNUNET_CONTAINER_DLL_remove, GNUNET_free, GNUNET_MQ_destroy(), GNUNET_NO, GNUNET_SCHEDULER_add_delayed(), GNUNET_TIME_STD_BACKOFF, GNUNET_NAT_Handle::mq, nh, GNUNET_NAT_Handle::reconnect_delay, and GNUNET_NAT_Handle::reconnect_task.

Referenced by do_connect(), handle_address_change_notification(), and mq_error_handler().

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

◆ check_connection_reversal_request()

static int check_connection_reversal_request ( void *  cls,
const struct GNUNET_NAT_ConnectionReversalRequestedMessage crm 
)
static

Check connection reversal request.

Parameters
clsour struct GNUNET_NAT_Handle
crmthe message
Returns
GNUNET_OK if crm is well-formed

Definition at line 174 of file nat_api.c.

177{
178 if (ntohs (crm->header.size) != sizeof(*crm) + sizeof(struct sockaddr_in))
179 {
180 GNUNET_break (0);
181 return GNUNET_SYSERR;
182 }
183 return GNUNET_OK;
184}
@ 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 size
The length of the struct (in bytes, including the length field itself), in big-endian format.
struct GNUNET_MessageHeader header
Header with type GNUNET_MESSAGE_TYPE_NAT_CONNECTION_REVERSAL_REQUESTED.
Definition: nat.h:191

References GNUNET_break, GNUNET_OK, GNUNET_SYSERR, GNUNET_NAT_ConnectionReversalRequestedMessage::header, and GNUNET_MessageHeader::size.

◆ handle_connection_reversal_request()

static void handle_connection_reversal_request ( void *  cls,
const struct GNUNET_NAT_ConnectionReversalRequestedMessage crm 
)
static

Handle connection reversal request.

Parameters
clsour struct GNUNET_NAT_Handle
crmthe message

Definition at line 194 of file nat_api.c.

197{
198 struct GNUNET_NAT_Handle *nh = cls;
199
201 (const struct sockaddr *) &crm[1],
202 sizeof(struct sockaddr_in));
203}
GNUNET_NAT_ReversalCallback reversal_callback
Function to call when another peer requests connection reversal.
Definition: nat_api.c:106

References GNUNET_NAT_Handle::callback_cls, nh, and GNUNET_NAT_Handle::reversal_callback.

◆ check_address_change_notification()

static int check_address_change_notification ( void *  cls,
const struct GNUNET_NAT_AddressChangeNotificationMessage acn 
)
static

Check address change notification.

Parameters
clsour struct GNUNET_NAT_Handle
acnthe message
Returns
GNUNET_OK if crm is well-formed

Definition at line 214 of file nat_api.c.

217{
218 size_t alen = ntohs (acn->header.size) - sizeof(*acn);
219
220 switch (alen)
221 {
222 case sizeof(struct sockaddr_in): {
223 const struct sockaddr_in *s4 = (const struct sockaddr_in *) &acn[1];
224 if (AF_INET != s4->sin_family)
225 {
226 GNUNET_break (0);
227 return GNUNET_SYSERR;
228 }
229 }
230 break;
231
232 case sizeof(struct sockaddr_in6): {
233 const struct sockaddr_in6 *s6 = (const struct sockaddr_in6 *) &acn[1];
234 if (AF_INET6 != s6->sin6_family)
235 {
236 GNUNET_break (0);
237 return GNUNET_SYSERR;
238 }
239 }
240 break;
241
242 default:
243 GNUNET_break (0);
244 return GNUNET_SYSERR;
245 }
246 return GNUNET_OK;
247}
struct GNUNET_MessageHeader header
Header with type GNUNET_MESSAGE_TYPE_NAT_ADDRESS_CHANGE.
Definition: nat.h:206

References GNUNET_break, GNUNET_OK, GNUNET_SYSERR, GNUNET_NAT_AddressChangeNotificationMessage::header, and GNUNET_MessageHeader::size.

◆ handle_address_change_notification()

static void handle_address_change_notification ( void *  cls,
const struct GNUNET_NAT_AddressChangeNotificationMessage acn 
)
static

Handle connection reversal request.

Parameters
clsour struct GNUNET_NAT_Handle
acnthe message

Definition at line 257 of file nat_api.c.

260{
261 struct GNUNET_NAT_Handle *nh = cls;
262 size_t alen = ntohs (acn->header.size) - sizeof(*acn);
263 const struct sockaddr *sa = (const struct sockaddr *) &acn[1];
265 struct AddrEntry *ae;
266
268 "Received address change notification\n");
269 ac = (enum GNUNET_NAT_AddressClass) ntohl (acn->addr_class);
270 if (GNUNET_YES == ntohl (acn->add_remove))
271 {
272 ae = GNUNET_malloc (sizeof(*ae) + alen);
273 ae->ac = ac;
274 ae->addrlen = alen;
275 GNUNET_memcpy (&ae[1], sa, alen);
278 &ae->app_ctx,
279 ntohl (acn->add_remove),
280 ac,
281 sa,
282 alen);
283 }
284 else
285 {
286 for (ae = nh->ae_head; NULL != ae; ae = ae->next)
287 if ((ae->addrlen == alen) && (0 == memcmp (&ae[1], sa, alen)))
288 break;
289 if (NULL == ae)
290 {
291 GNUNET_break (0);
292 reconnect (nh);
293 return;
294 }
297 &ae->app_ctx,
298 ntohl (acn->add_remove),
299 ac,
300 sa,
301 alen);
302 GNUNET_free (ae);
303 }
304}
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
#define GNUNET_log(kind,...)
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
@ GNUNET_YES
@ GNUNET_ERROR_TYPE_DEBUG
#define GNUNET_malloc(size)
Wrapper around malloc.
GNUNET_NAT_AddressClass
Some addresses contain sensitive information or are not suitable for global distribution.
struct AddrEntry * next
DLL.
Definition: nat_api.c:43
socklen_t addrlen
Number of bytes that follow.
Definition: nat_api.c:64
int32_t add_remove
GNUNET_YES to add, GNUNET_NO to remove the address from the list.
Definition: nat.h:211
uint32_t addr_class
Type of the address, an enum GNUNET_NAT_AddressClass in NBO.
Definition: nat.h:216

References AddrEntry::ac, GNUNET_NAT_AddressChangeNotificationMessage::add_remove, GNUNET_NAT_AddressChangeNotificationMessage::addr_class, GNUNET_NAT_Handle::address_callback, AddrEntry::addrlen, GNUNET_NAT_Handle::ae_head, GNUNET_NAT_Handle::ae_tail, AddrEntry::app_ctx, GNUNET_NAT_Handle::callback_cls, GNUNET_break, GNUNET_CONTAINER_DLL_insert, GNUNET_CONTAINER_DLL_remove, GNUNET_ERROR_TYPE_DEBUG, GNUNET_free, GNUNET_log, GNUNET_malloc, GNUNET_memcpy, GNUNET_YES, GNUNET_NAT_AddressChangeNotificationMessage::header, AddrEntry::next, nh, reconnect(), and GNUNET_MessageHeader::size.

Here is the call graph for this function:

◆ mq_error_handler()

static void mq_error_handler ( void *  cls,
enum GNUNET_MQ_Error  error 
)
static

Handle queue errors by reconnecting to NAT.

Parameters
clsthe struct GNUNET_NAT_Handle *
errordetails about the error

Definition at line 314 of file nat_api.c.

316{
317 struct GNUNET_NAT_Handle *nh = cls;
318
319 reconnect (nh);
320}

References nh, and reconnect().

Referenced by do_connect().

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

◆ get_address_without_port()

static char * get_address_without_port ( const char *  address)
static

Get the IP address without the port number.

Parameters
addressThe string contains a communicator prefix, IP address and port like this 'tcp-92.68.150.1:55452'.
Returns
String with prefix and IP address only.

Definition at line 467 of file nat_api.c.

468{
469 const char *colon;
470 char *colon_rest;
471 size_t colon_rest_length;
472 char *address_without_port;
473
474 colon = strchr (address,':');
475 colon_rest = GNUNET_strndup (address, colon - address);
476 colon_rest_length = strlen (colon_rest);
477 address_without_port = GNUNET_strndup (&colon_rest[4], colon_rest_length - 4);
478 GNUNET_free (colon_rest);
479
480 return address_without_port;
481}
static char * address
GNS address for this phone.
#define GNUNET_strndup(a, length)
Wrapper around GNUNET_xstrndup_.

References address, GNUNET_free, and GNUNET_strndup.

◆ test_stun_packet()

static enum GNUNET_GenericReturnValue test_stun_packet ( const void *  data,
size_t  len 
)
static

Check if an incoming message is a STUN message.

Parameters
datathe packet
lenthe length of the packet in data
Returns
GNUNET_YES if data is a STUN packet, GNUNET_NO if the packet is invalid (not a stun packet)

Definition at line 521 of file nat_api.c.

522{
523 const struct stun_header *hdr;
524 const struct stun_attr *attr;
525 uint32_t advertised_message_size;
526 uint32_t message_magic_cookie;
527
528 /* On entry, 'len' is the length of the UDP payload. After the
529 * initial checks it becomes the size of unprocessed options,
530 * while 'data' is advanced accordingly.
531 */
532 if (len < sizeof(struct stun_header))
533 {
535 "STUN packet too short (only %d, wanting at least %d)\n",
536 (int) len,
537 (int) sizeof(struct stun_header));
538 return GNUNET_NO;
539 }
540 hdr = (const struct stun_header *) data;
541 /* Skip header as it is already in hdr */
542 len -= sizeof(struct stun_header);
543 data += sizeof(struct stun_header);
544
545 /* len as advertised in the message */
546 advertised_message_size = ntohs (hdr->msglen);
547
548 message_magic_cookie = ntohl (hdr->magic);
549 /* Compare if the cookie match */
550 if (STUN_MAGIC_COOKIE != message_magic_cookie)
551 {
552 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Invalid magic cookie for STUN\n");
553 return GNUNET_NO;
554 }
555
556 if (advertised_message_size > len)
557 {
559 "Scrambled STUN packet length (got %d, expecting %d)\n",
560 advertised_message_size,
561 (int) len);
562 return GNUNET_NO;
563 }
564 len = advertised_message_size;
565 while (len > 0)
566 {
567 if (len < sizeof(struct stun_attr))
568 {
570 "Attribute too short in STUN packet (got %d, expecting %d)\n",
571 (int) len,
572 (int) sizeof(struct stun_attr));
573 return GNUNET_NO;
574 }
575 attr = (const struct stun_attr *) data;
576
577 /* compute total attribute length */
578 advertised_message_size = ntohs (attr->len) + sizeof(struct stun_attr);
579
580 /* Check if we still have space in our buffer */
581 if (advertised_message_size > len)
582 {
583 GNUNET_log (
585 "Inconsistent Attribute (length %d exceeds remaining msg len %d)\n",
586 advertised_message_size,
587 (int) len);
588 return GNUNET_NO;
589 }
590 data += advertised_message_size;
591 len -= advertised_message_size;
592 }
594 "STUN Packet, msg %04x, length: %d\n",
595 ntohs (hdr->msgtype),
596 advertised_message_size);
597 return GNUNET_OK;
598}
static char * data
The data to insert into the dht.
#define STUN_MAGIC_COOKIE
Definition: nat_stun.h:34
uint16_t len
Definition: nat_stun.h:54
uint16_t attr
Definition: nat_stun.h:53
uint16_t msglen
Definition: nat_stun.h:45
uint16_t msgtype
Definition: nat_stun.h:44
uint32_t magic
Definition: nat_stun.h:46

References stun_attr::attr, data, GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_NO, GNUNET_OK, stun_attr::len, stun_header::magic, stun_header::msglen, stun_header::msgtype, and STUN_MAGIC_COOKIE.

Referenced by GNUNET_NAT_stun_handle_packet().

Here is the caller graph for this function: