diff options
author | Christian Grothoff <christian@grothoff.org> | 2016-11-30 12:17:19 +0100 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2016-11-30 12:17:19 +0100 |
commit | 8a5c5861114433d0d267885bb29f21a0c160d1f4 (patch) | |
tree | 6e166602f71e6d65a89a9d7591fdbce496c5f1e2 /src | |
parent | dedcc8ae3d460670dd990f7e79d41ed6c8af87d4 (diff) | |
download | gnunet-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.c | 156 | ||||
-rw-r--r-- | src/nat/nat.conf | 3 | ||||
-rw-r--r-- | src/nat/nat_api_stun.c | 3 |
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 | */ | ||
149 | struct 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 | */ | ||
189 | static struct GNUNET_TIME_Relative stun_stale_timeout; | ||
190 | |||
191 | /** | ||
147 | * Handle to our current configuration. | 192 | * Handle to our current configuration. |
148 | */ | 193 | */ |
149 | static const struct GNUNET_CONFIGURATION_Handle *cfg; | 194 | static const struct GNUNET_CONFIGURATION_Handle *cfg; |
@@ -178,6 +223,16 @@ static struct LocalAddressList *lal_head; | |||
178 | */ | 223 | */ |
179 | static struct LocalAddressList *lal_tail; | 224 | static struct LocalAddressList *lal_tail; |
180 | 225 | ||
226 | /** | ||
227 | * Kept in a DLL. | ||
228 | */ | ||
229 | static struct StunExternalIP *se_head; | ||
230 | |||
231 | /** | ||
232 | * Kept in a DLL. | ||
233 | */ | ||
234 | static 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 | */ | ||
417 | static void | ||
418 | notify_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 | */ | ||
432 | static void | ||
433 | stun_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, | |||
579 | static void | 713 | static void |
580 | shutdown_task (void *cls) | 714 | shutdown_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 |
55 | STUN_SERVERS = stun.gnunet.org stun.services.mozilla.com:3478 stun.ekiga.net:3478 | 55 | STUN_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? | ||
58 | STUN_STALE = 60 min | ||
59 | |||
57 | 60 | ||
58 | [gnunet-nat-server] | 61 | [gnunet-nat-server] |
59 | HOSTNAME = gnunet.org | 62 | HOSTNAME = 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); |