diff options
Diffstat (limited to 'src/nat/nat.c')
-rw-r--r-- | src/nat/nat.c | 301 |
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 | */ | ||
182 | struct 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 | */ |
176 | struct GNUNET_NAT_Handle | 211 | struct 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 | |||
379 | start_gnunet_nat_server (struct GNUNET_NAT_Handle *h); | 454 | start_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 | |||
466 | static void | ||
467 | process_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 | */ | ||
1112 | static 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 | */ | ||
1133 | int | ||
1134 | GNUNET_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 | */ | ||
1173 | static void | ||
1174 | process_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 | */ |
1247 | struct GNUNET_NAT_Handle * | 1444 | struct 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) && |