aboutsummaryrefslogtreecommitdiff
path: root/src/nat/nat.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nat/nat.c')
-rw-r--r--src/nat/nat.c301
1 files changed, 300 insertions, 1 deletions
diff --git a/src/nat/nat.c b/src/nat/nat.c
index 9eb7e7e7b..f5b1123c6 100644
--- a/src/nat/nat.c
+++ b/src/nat/nat.c
@@ -57,6 +57,12 @@
57 57
58 58
59/** 59/**
60 * How often do we check a STUN server ?
61 */
62#define STUN_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 2)
63
64
65/**
60 * Where did the given local address originate from? 66 * Where did the given local address originate from?
61 * To be used for debugging as well as in the future 67 * To be used for debugging as well as in the future
62 * to remove all addresses from a certain source when 68 * to remove all addresses from a certain source when
@@ -171,6 +177,35 @@ struct MiniList
171 177
172 178
173/** 179/**
180 * List of STUN servers
181 */
182struct StunServerList
183{
184
185 /**
186 * Doubly-linked list.
187 */
188 struct StunServerList *next;
189
190 /**
191 * Doubly-linked list.
192 */
193 struct StunServerList *prev;
194
195 /**
196 * Address
197 */
198 char * address;
199
200 /**
201 * Server Port
202 */
203 uint16_t port;
204
205};
206
207
208/**
174 * Handle for active NAT registrations. 209 * Handle for active NAT registrations.
175 */ 210 */
176struct GNUNET_NAT_Handle 211struct GNUNET_NAT_Handle
@@ -366,6 +401,46 @@ struct GNUNET_NAT_Handle
366 */ 401 */
367 uint16_t adv_port; 402 uint16_t adv_port;
368 403
404 /**
405 * Should we use STUN ?
406 */
407 int use_stun;
408
409 /**
410 * How often should se check STUN ?
411 */
412 struct GNUNET_TIME_Relative stun_frequency;
413
414 /**
415 * STUN socket
416 */
417 struct GNUNET_NETWORK_Handle* socket;
418
419 /*
420 * Am I waiting for a STUN response ?
421 */
422 int waiting_stun;
423
424 /**
425 * STUN request task
426 */
427 struct GNUNET_SCHEDULER_Task * stun_task;
428
429 /**
430 * Head of List of STUN servers
431 */
432 struct StunServerList *stun_servers_head;
433
434 /**
435 * Tail of List of STUN servers
436 */
437 struct StunServerList *stun_servers_tail;
438
439 /**
440 * Actual STUN Server
441 */
442 struct StunServerList *actual_stun_server;
443
369}; 444};
370 445
371 446
@@ -379,6 +454,20 @@ static void
379start_gnunet_nat_server (struct GNUNET_NAT_Handle *h); 454start_gnunet_nat_server (struct GNUNET_NAT_Handle *h);
380 455
381 456
457
458
459/**
460 * Call task to process STUN
461 *
462 * @param cls handle to NAT
463 * @param tc TaskContext
464 */
465
466static void
467process_stun (void *cls,
468 const struct GNUNET_SCHEDULER_TaskContext *tc);
469
470
382/** 471/**
383 * Remove all addresses from the list of 'local' addresses 472 * Remove all addresses from the list of 'local' addresses
384 * that originated from the given source. 473 * that originated from the given source.
@@ -1013,6 +1102,113 @@ list_interfaces (void *cls,
1013} 1102}
1014 1103
1015 1104
1105
1106/**
1107 * Callback if the STun request have a error
1108 *
1109 * @param cls the NAT handle
1110 * @param result , the status
1111 */
1112static void stun_request_callback(void *cls,
1113 enum GNUNET_NAT_StatusCode result)
1114{
1115
1116 struct GNUNET_NAT_Handle *h = cls;
1117
1118 h->waiting_stun = GNUNET_NO;
1119 LOG (GNUNET_ERROR_TYPE_WARNING,
1120 "Error processing a STUN request");
1121
1122};
1123
1124/**
1125 * Check if STUN can decode the packet
1126 *
1127 * @param cls the NAT handle
1128 * @param data, packet
1129 * @param len, packet lenght
1130 *
1131 * @return GNUNET_NO if it can't decode, GNUNET_YES if is a packet
1132 */
1133int
1134GNUNET_NAT_try_decode_stun_packet(void *cls, const uint8_t *data, size_t len)
1135{
1136 struct GNUNET_NAT_Handle *h = cls;
1137 struct sockaddr_in answer;
1138
1139 /* We are not expecting a STUN message*/
1140 if(!h->waiting_stun)
1141 return GNUNET_NO;
1142
1143 /* Empty the answer structure */
1144 memset(&answer, 0, sizeof(struct sockaddr_in));
1145
1146 /*Lets handle the packet*/
1147 int valid = GNUNET_NAT_stun_handle_packet(data,len, &answer);
1148 if(valid)
1149 {
1150 LOG (GNUNET_ERROR_TYPE_DEBUG,
1151 "Stun server returned IP %s , with port %d \n", inet_ntoa(answer.sin_addr), ntohs(answer.sin_port));
1152 /* ADD IP AS VALID*/
1153 add_to_address_list (h, LAL_EXTERNAL_IP, (const struct sockaddr *) &answer,
1154 sizeof (struct sockaddr_in));
1155 h->waiting_stun = GNUNET_NO;
1156 return GNUNET_YES;
1157 }
1158 else
1159 {
1160 return GNUNET_NO;
1161 }
1162
1163
1164
1165}
1166
1167/**
1168 * Task to do a STUN request
1169 *
1170 * @param cls the NAT handle
1171 * @param tc scheduler context
1172 */
1173static void
1174process_stun (void *cls,
1175 const struct GNUNET_SCHEDULER_TaskContext *tc)
1176{
1177 struct GNUNET_NAT_Handle *h = cls;
1178
1179 LOG (GNUNET_ERROR_TYPE_DEBUG,
1180 "I will do a STUN request\n");
1181
1182
1183 h->stun_task = NULL;
1184 h->waiting_stun = GNUNET_YES;
1185
1186 struct StunServerList* elem = h->actual_stun_server;
1187
1188 /* Make the request */
1189 LOG (GNUNET_ERROR_TYPE_DEBUG,
1190 "I will request the stun server %s:%i !\n", elem->address, elem->port);
1191
1192 GNUNET_NAT_stun_make_request(elem->address, elem->port, h->socket, &stun_request_callback, NULL);
1193
1194 h->stun_task =
1195 GNUNET_SCHEDULER_add_delayed (h->stun_frequency,
1196 &process_stun, h);
1197
1198 /* Set actual Server*/
1199 if(elem->next)
1200 {
1201 h->actual_stun_server = elem->next;
1202 }
1203 else
1204 {
1205 h->actual_stun_server = h->stun_servers_head;
1206 }
1207
1208}
1209
1210
1211
1016/** 1212/**
1017 * Task to do a lookup on our hostname for IP addresses. 1213 * Task to do a lookup on our hostname for IP addresses.
1018 * 1214 *
@@ -1242,6 +1438,7 @@ add_from_bind (struct GNUNET_NAT_Handle *h)
1242 * @param address_callback function to call everytime the public IP address changes 1438 * @param address_callback function to call everytime the public IP address changes
1243 * @param reversal_callback function to call if someone wants connection reversal from us 1439 * @param reversal_callback function to call if someone wants connection reversal from us
1244 * @param callback_cls closure for callbacks 1440 * @param callback_cls closure for callbacks
1441 * @param sock used socket
1245 * @return NULL on error, otherwise handle that can be used to unregister 1442 * @return NULL on error, otherwise handle that can be used to unregister
1246 */ 1443 */
1247struct GNUNET_NAT_Handle * 1444struct GNUNET_NAT_Handle *
@@ -1253,7 +1450,8 @@ GNUNET_NAT_register (const struct GNUNET_CONFIGURATION_Handle *cfg,
1253 const socklen_t *addrlens, 1450 const socklen_t *addrlens,
1254 GNUNET_NAT_AddressCallback address_callback, 1451 GNUNET_NAT_AddressCallback address_callback,
1255 GNUNET_NAT_ReversalCallback reversal_callback, 1452 GNUNET_NAT_ReversalCallback reversal_callback,
1256 void *callback_cls) 1453 void *callback_cls,
1454 struct GNUNET_NETWORK_Handle* sock )
1257{ 1455{
1258 struct GNUNET_NAT_Handle *h; 1456 struct GNUNET_NAT_Handle *h;
1259 struct in_addr in_addr; 1457 struct in_addr in_addr;
@@ -1355,6 +1553,17 @@ GNUNET_NAT_register (const struct GNUNET_CONFIGURATION_Handle *cfg,
1355 h->enable_upnp = GNUNET_NO; 1553 h->enable_upnp = GNUNET_NO;
1356 } 1554 }
1357 1555
1556 /* STUN */
1557 h->use_stun =
1558 GNUNET_CONFIGURATION_get_value_yesno (cfg, "nat",
1559 "USE_STUN");
1560
1561 if (GNUNET_OK !=
1562 GNUNET_CONFIGURATION_get_value_time (cfg, "nat", "STUN_FREQUENCY",
1563 &h->stun_frequency))
1564 h->stun_frequency = STUN_FREQUENCY;
1565
1566
1358 /* Check if NAT was hole-punched */ 1567 /* Check if NAT was hole-punched */
1359 if ((NULL != h->address_callback) && 1568 if ((NULL != h->address_callback) &&
1360 (NULL != h->external_address) && 1569 (NULL != h->external_address) &&
@@ -1363,6 +1572,7 @@ GNUNET_NAT_register (const struct GNUNET_CONFIGURATION_Handle *cfg,
1363 h->dns_task = GNUNET_SCHEDULER_add_now (&resolve_dns, h); 1572 h->dns_task = GNUNET_SCHEDULER_add_now (&resolve_dns, h);
1364 h->enable_nat_server = GNUNET_NO; 1573 h->enable_nat_server = GNUNET_NO;
1365 h->enable_upnp = GNUNET_NO; 1574 h->enable_upnp = GNUNET_NO;
1575 h->use_stun = GNUNET_NO;
1366 } 1576 }
1367 else 1577 else
1368 { 1578 {
@@ -1370,6 +1580,95 @@ GNUNET_NAT_register (const struct GNUNET_CONFIGURATION_Handle *cfg,
1370 "No external IP address given to add to our list of addresses\n"); 1580 "No external IP address given to add to our list of addresses\n");
1371 } 1581 }
1372 1582
1583 /* ENABLE STUN ONLY ON UDP*/
1584 if(!is_tcp && (NULL != sock) && h->use_stun ) {
1585 h->socket = sock;
1586 h->actual_stun_server = NULL;
1587
1588 /* Lets process the servers*/
1589 char *stun_servers;
1590
1591 size_t urls;
1592 int pos;
1593 size_t pos_port;
1594
1595 if (GNUNET_OK !=
1596 GNUNET_CONFIGURATION_get_value_string (cfg, "nat", "STUN_SERVERS",
1597 &stun_servers))
1598 {
1599 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_WARNING,
1600 "nat", "STUN_SERVERS");
1601 }
1602
1603 urls = 0;
1604 h->stun_servers_head = NULL;
1605 h->stun_servers_tail = NULL;
1606 h->actual_stun_server = NULL;
1607 if (strlen (stun_servers) > 0)
1608 {
1609 pos = strlen (stun_servers) - 1;
1610 pos_port = 0;
1611 while (pos >= 0)
1612 {
1613 if (stun_servers[pos] == ':')
1614 {
1615 pos_port = pos + 1;
1616 }
1617 if ((stun_servers[pos] == ' ') || (0 == pos))
1618 {
1619
1620 /*Check if we do have a port*/
1621 if((0 == pos_port) || (pos_port <= pos))
1622 {
1623 LOG (GNUNET_ERROR_TYPE_WARNING,
1624 "STUN server format mistake\n");
1625 break;
1626 }
1627
1628 urls++;
1629
1630 struct StunServerList* ml = GNUNET_new (struct StunServerList);
1631
1632 ml->next = NULL;
1633 ml->prev = NULL;
1634
1635 ml->port = atoi(&stun_servers[pos_port]);
1636 stun_servers[pos_port-1] = '\0';
1637
1638 /* Remove trailing space */
1639 if(stun_servers[pos] == ' ')
1640 ml->address = GNUNET_strdup (&stun_servers[pos + 1]);
1641 else
1642 ml->address = GNUNET_strdup (&stun_servers[pos]);
1643
1644 LOG (GNUNET_ERROR_TYPE_DEBUG,
1645 "Found STUN server %s port %i !!!\n", ml->address, ml->port);
1646
1647 GNUNET_CONTAINER_DLL_insert (h->stun_servers_head, h->stun_servers_tail, ml);
1648 /* Make sure that we STOP if is the last one*/
1649 if(0== pos)
1650 break;
1651 }
1652
1653 pos--;
1654 }
1655 }
1656 if (urls == 0)
1657 {
1658 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_WARNING,
1659 "nat", "STUN_SERVERS");
1660 }
1661 else
1662 {
1663 /* Set the actual STUN server*/
1664 h->actual_stun_server = h->stun_servers_head;
1665 }
1666
1667 h->stun_task = GNUNET_SCHEDULER_add_now(&process_stun,
1668 h);
1669 }
1670
1671
1373 /* Test for SUID binaries */ 1672 /* Test for SUID binaries */
1374 binary = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-nat-server"); 1673 binary = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-nat-server");
1375 if ((h->behind_nat == GNUNET_YES) && (GNUNET_YES == h->enable_nat_server) && 1674 if ((h->behind_nat == GNUNET_YES) && (GNUNET_YES == h->enable_nat_server) &&