aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2016-11-30 12:17:19 +0100
committerChristian Grothoff <christian@grothoff.org>2016-11-30 12:17:19 +0100
commit8a5c5861114433d0d267885bb29f21a0c160d1f4 (patch)
tree6e166602f71e6d65a89a9d7591fdbce496c5f1e2 /src
parentdedcc8ae3d460670dd990f7e79d41ed6c8af87d4 (diff)
downloadgnunet-8a5c5861114433d0d267885bb29f21a0c160d1f4.tar.gz
gnunet-8a5c5861114433d0d267885bb29f21a0c160d1f4.zip
implement keeping and timeout of NAT STUN data
Diffstat (limited to 'src')
-rw-r--r--src/nat/gnunet-service-nat.c156
-rw-r--r--src/nat/nat.conf3
-rw-r--r--src/nat/nat_api_stun.c3
3 files changed, 158 insertions, 4 deletions
diff --git a/src/nat/gnunet-service-nat.c b/src/nat/gnunet-service-nat.c
index d8a343857..f4755659f 100644
--- a/src/nat/gnunet-service-nat.c
+++ b/src/nat/gnunet-service-nat.c
@@ -144,6 +144,51 @@ struct LocalAddressList
144 144
145 145
146/** 146/**
147 * External IP address as given to us via some STUN server.
148 */
149struct StunExternalIP
150{
151 /**
152 * Kept in a DLL.
153 */
154 struct StunExternalIP *next;
155
156 /**
157 * Kept in a DLL.
158 */
159 struct StunExternalIP *prev;
160
161 /**
162 * Task we run to remove this entry when it is stale.
163 */
164 struct GNUNET_SCHEDULER_Task *timeout_task;
165
166 /**
167 * Our external IP address as reported by the
168 * STUN server.
169 */
170 struct sockaddr_in external_addr;
171
172 /**
173 * Address of the reporting STUN server. Used to
174 * detect when a STUN server changes its opinion
175 * to more quickly remove stale results.
176 */
177 struct sockaddr_storage stun_server_addr;
178
179 /**
180 * Number of bytes used in @e stun_server_addr.
181 */
182 size_t stun_server_addr_len;
183};
184
185
186/**
187 * Timeout to use when STUN data is considered stale.
188 */
189static struct GNUNET_TIME_Relative stun_stale_timeout;
190
191/**
147 * Handle to our current configuration. 192 * Handle to our current configuration.
148 */ 193 */
149static const struct GNUNET_CONFIGURATION_Handle *cfg; 194static const struct GNUNET_CONFIGURATION_Handle *cfg;
@@ -178,6 +223,16 @@ static struct LocalAddressList *lal_head;
178 */ 223 */
179static struct LocalAddressList *lal_tail; 224static struct LocalAddressList *lal_tail;
180 225
226/**
227 * Kept in a DLL.
228 */
229static struct StunExternalIP *se_head;
230
231/**
232 * Kept in a DLL.
233 */
234static struct StunExternalIP *se_tail;
235
181 236
182/** 237/**
183 * Free the DLL starting at #lal_head. 238 * Free the DLL starting at #lal_head.
@@ -353,6 +408,43 @@ check_stun (void *cls,
353 408
354 409
355/** 410/**
411 * Notify all clients about our external IP address
412 * as reported by the STUN server.
413 *
414 * @param ip the external IP
415 * @param add #GNUNET_YES to add, #GNUNET_NO to remove
416 */
417static void
418notify_clients_stun_change (const struct sockaddr_in *ip,
419 int add)
420{
421 /* FIXME: notify clients about add/drop */
422}
423
424
425/**
426 * Function to be called when we decide that an
427 * external IP address as told to us by a STUN
428 * server has gone stale.
429 *
430 * @param cls the `struct StunExternalIP` to drop
431 */
432static void
433stun_ip_timeout (void *cls)
434{
435 struct StunExternalIP *se = cls;
436
437 se->timeout_task = NULL;
438 notify_clients_stun_change (&se->external_addr,
439 GNUNET_NO);
440 GNUNET_CONTAINER_DLL_remove (se_head,
441 se_tail,
442 se);
443 GNUNET_free (se);
444}
445
446
447/**
356 * Handler for #GNUNET_MESSAGE_TYPE_NAT_HANDLE_STUN message from 448 * Handler for #GNUNET_MESSAGE_TYPE_NAT_HANDLE_STUN message from
357 * client. 449 * client.
358 * 450 *
@@ -401,8 +493,7 @@ handle_stun (void *cls,
401 payload_size, 493 payload_size,
402 &external_addr)) 494 &external_addr))
403 { 495 {
404 /* FIXME: do something with "external_addr"! We 496 /* We now know that a server at "sa" claims that
405 now know that a server at "sa" claims that
406 we are visible at IP "external_addr". 497 we are visible at IP "external_addr".
407 498
408 We should (for some fixed period of time) tell 499 We should (for some fixed period of time) tell
@@ -416,7 +507,50 @@ handle_stun (void *cls,
416 (with a sane default), so that the UDP plugin can tell how 507 (with a sane default), so that the UDP plugin can tell how
417 often to re-request STUN. 508 often to re-request STUN.
418 */ 509 */
419 510 struct StunExternalIP *se;
511
512 /* Check if we had a prior response from this STUN server */
513 for (se = se_head; NULL != se; se = se->next)
514 {
515 if ( (se->stun_server_addr_len != sa_len) ||
516 (0 != memcmp (sa,
517 &se->stun_server_addr,
518 sa_len)) )
519 continue; /* different STUN server */
520 if (0 != memcmp (&external_addr,
521 &se->external_addr,
522 sizeof (struct sockaddr_in)))
523 {
524 /* external IP changed, update! */
525 notify_clients_stun_change (&se->external_addr,
526 GNUNET_NO);
527 se->external_addr = external_addr;
528 notify_clients_stun_change (&se->external_addr,
529 GNUNET_YES);
530 }
531 /* update timeout */
532 GNUNET_SCHEDULER_cancel (se->timeout_task);
533 se->timeout_task
534 = GNUNET_SCHEDULER_add_delayed (stun_stale_timeout,
535 &stun_ip_timeout,
536 se);
537 return;
538 }
539 /* STUN server is completely new, create fresh entry */
540 se = GNUNET_new (struct StunExternalIP);
541 se->external_addr = external_addr;
542 GNUNET_memcpy (&se->stun_server_addr,
543 sa,
544 sa_len);
545 se->stun_server_addr_len = sa_len;
546 se->timeout_task = GNUNET_SCHEDULER_add_delayed (stun_stale_timeout,
547 &stun_ip_timeout,
548 se);
549 GNUNET_CONTAINER_DLL_insert (se_head,
550 se_tail,
551 se);
552 notify_clients_stun_change (&se->external_addr,
553 GNUNET_NO);
420 } 554 }
421 GNUNET_SERVICE_client_continue (ch->client); 555 GNUNET_SERVICE_client_continue (ch->client);
422} 556}
@@ -579,6 +713,16 @@ handle_autoconfig_request (void *cls,
579static void 713static void
580shutdown_task (void *cls) 714shutdown_task (void *cls)
581{ 715{
716 struct StunExternalIP *se;
717
718 while (NULL != (se = se_head))
719 {
720 GNUNET_CONTAINER_DLL_remove (se_head,
721 se_tail,
722 se);
723 GNUNET_SCHEDULER_cancel (se->timeout_task);
724 GNUNET_free (se);
725 }
582 if (NULL != scan_task) 726 if (NULL != scan_task)
583 { 727 {
584 GNUNET_SCHEDULER_cancel (scan_task); 728 GNUNET_SCHEDULER_cancel (scan_task);
@@ -979,6 +1123,12 @@ run (void *cls,
979 struct GNUNET_SERVICE_Handle *service) 1123 struct GNUNET_SERVICE_Handle *service)
980{ 1124{
981 cfg = c; 1125 cfg = c;
1126 if (GNUNET_OK !=
1127 GNUNET_CONFIGURATION_get_value_time (cfg,
1128 "NAT",
1129 "STUN_STALE",
1130 &stun_stale_timeout))
1131 stun_stale_timeout = GNUNET_TIME_UNIT_HOURS;
982 GNUNET_SCHEDULER_add_shutdown (&shutdown_task, 1132 GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
983 NULL); 1133 NULL);
984 stats = GNUNET_STATISTICS_create ("nat", 1134 stats = GNUNET_STATISTICS_create ("nat",
diff --git a/src/nat/nat.conf b/src/nat/nat.conf
index 4b1add109..4493a6ec9 100644
--- a/src/nat/nat.conf
+++ b/src/nat/nat.conf
@@ -54,6 +54,9 @@ STUN_FREQUENCY = 5 min
54# Default list of stun servers 54# Default list of stun servers
55STUN_SERVERS = stun.gnunet.org stun.services.mozilla.com:3478 stun.ekiga.net:3478 55STUN_SERVERS = stun.gnunet.org stun.services.mozilla.com:3478 stun.ekiga.net:3478
56 56
57# After how long do we consider STUN data stale?
58STUN_STALE = 60 min
59
57 60
58[gnunet-nat-server] 61[gnunet-nat-server]
59HOSTNAME = gnunet.org 62HOSTNAME = gnunet.org
diff --git a/src/nat/nat_api_stun.c b/src/nat/nat_api_stun.c
index 0d4ba86d1..8f5a5f8f6 100644
--- a/src/nat/nat_api_stun.c
+++ b/src/nat/nat_api_stun.c
@@ -229,7 +229,8 @@ GNUNET_NAT_stun_make_request (const char *server,
229 rh->dns_active = GNUNET_RESOLVER_ip_get (rh->stun_server, 229 rh->dns_active = GNUNET_RESOLVER_ip_get (rh->stun_server,
230 AF_INET, 230 AF_INET,
231 TIMEOUT, 231 TIMEOUT,
232 &stun_dns_callback, rh); 232 &stun_dns_callback,
233 rh);
233 if (NULL == rh->dns_active) 234 if (NULL == rh->dns_active)
234 { 235 {
235 GNUNET_NAT_stun_make_request_cancel (rh); 236 GNUNET_NAT_stun_make_request_cancel (rh);