aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/include/gnunet_nat_lib.h50
-rw-r--r--src/nat/gnunet-nat-server.c2
-rw-r--r--src/nat/nat.c301
-rw-r--r--src/nat/nat.conf7
-rw-r--r--src/nat/nat_stun.c553
-rw-r--r--src/nat/nat_test.c4
-rw-r--r--src/nat/test_nat.c2
-rw-r--r--src/nat/test_stun.c94
-rw-r--r--src/transport/plugin_transport_http_server.c2
-rw-r--r--src/transport/plugin_transport_tcp.c5
-rw-r--r--src/transport/plugin_transport_udp.c14
-rw-r--r--src/transport/plugin_transport_udp.h5
12 files changed, 757 insertions, 282 deletions
diff --git a/src/include/gnunet_nat_lib.h b/src/include/gnunet_nat_lib.h
index 7a8343d28..6c4362c90 100644
--- a/src/include/gnunet_nat_lib.h
+++ b/src/include/gnunet_nat_lib.h
@@ -170,6 +170,8 @@ enum GNUNET_NAT_StatusCode
170 */ 170 */
171 GNUNET_NAT_ERROR_HELPER_NAT_CLIENT_NOT_FOUND, 171 GNUNET_NAT_ERROR_HELPER_NAT_CLIENT_NOT_FOUND,
172 172
173
174
173 /** 175 /**
174 * 176 *
175 */ 177 */
@@ -217,7 +219,8 @@ GNUNET_NAT_register (const struct GNUNET_CONFIGURATION_Handle *cfg,
217 const socklen_t *addrlens, 219 const socklen_t *addrlens,
218 GNUNET_NAT_AddressCallback address_callback, 220 GNUNET_NAT_AddressCallback address_callback,
219 GNUNET_NAT_ReversalCallback reversal_callback, 221 GNUNET_NAT_ReversalCallback reversal_callback,
220 void *callback_cls); 222 void *callback_cls,
223 struct GNUNET_NETWORK_Handle* sock );
221 224
222 225
223/** 226/**
@@ -455,22 +458,43 @@ GNUNET_NAT_autoconfig_start (const struct GNUNET_CONFIGURATION_Handle *cfg,
455void 458void
456GNUNET_NAT_autoconfig_cancel (struct GNUNET_NAT_AutoHandle *ah); 459GNUNET_NAT_autoconfig_cancel (struct GNUNET_NAT_AutoHandle *ah);
457 460
461/**
462 * Handle for active STUN Requests.
463 */
464struct GNUNET_NAT_STUN_Handle;
465
466
467
468
469/**
470 * Function called with the result from NAT request.
471 *
472 * @param cls closure
473 * @param diff minimal suggested changes to the original configuration
474 * to make it work (as best as we can)
475 * @param result #GNUNET_NAT_ERROR_SUCCESS on success, otherwise the specific error code
476 */
477typedef void
478(*GNUNET_NAT_stun_RequestCallback)(void *cls,
479 enum GNUNET_NAT_StatusCode result);
458 480
459struct GNUNET_NAT_StunRequestHandle;
460 481
461/** 482/**
462 * Make Generic STUN request and 483 * Make Generic STUN request and
463 * Send a generic stun request to the server specified using the specified socket. 484 * Send a generic stun request to the server specified using the specified socket.
464 * possibly waiting for a reply and filling the 'reply' field with 485 * possibly waiting for a reply and filling the 'reply' field with
465 * the externally visible address. 486 * the externally visible address.
466 *c 487 *
488
467 * @param server, the address of the stun server 489 * @param server, the address of the stun server
468 * @param port, port of the stun server 490 * @param port, port of the stun server
469 * @param sock the socket used to send the request 491 * @param sock the socket used to send the request
470 * @return GNUNET_NAT_StunRequestHandle on success, NULL on error. 492 * @return GNUNET_NAT_STUN_Handle on success, NULL on error.
471 */ 493 */
472struct GNUNET_NAT_StunRequestHandle * 494struct GNUNET_NAT_STUN_Handle *
473GNUNET_NAT_stun_make_request(char * server, int port, struct GNUNET_NETWORK_Handle * sock); 495GNUNET_NAT_stun_make_request(char * server, int port,
496 struct GNUNET_NETWORK_Handle * sock, GNUNET_NAT_stun_RequestCallback cb,
497 void *cb_cls);
474 498
475 499
476/** 500/**
@@ -489,6 +513,20 @@ GNUNET_NAT_stun_make_request(char * server, int port, struct GNUNET_NETWORK_Hand
489int 513int
490GNUNET_NAT_stun_handle_packet(const uint8_t *data, size_t len,struct sockaddr_in *arg); 514GNUNET_NAT_stun_handle_packet(const uint8_t *data, size_t len,struct sockaddr_in *arg);
491 515
516/**
517 * CHECK if is a valid STUN packet sending to GNUNET_NAT_stun_handle_packet
518 *
519 * @param cls, NAT callback
520 * @param data, pointer where we will set the type
521 * @param len, pointer where we will set the type
522 * @param st, pointer where we will set the type
523 *
524 * @return, 0 on IGNORE, -1 if the packet is invalid ( not a stun packet)
525 */
526int
527GNUNET_NAT_try_decode_stun_packet(void *cls, const uint8_t *data, size_t len);
528
529
492 530
493#endif 531#endif
494 532
diff --git a/src/nat/gnunet-nat-server.c b/src/nat/gnunet-nat-server.c
index a5a5b4bed..66b5ee3da 100644
--- a/src/nat/gnunet-nat-server.c
+++ b/src/nat/gnunet-nat-server.c
@@ -58,7 +58,7 @@ try_anat (uint32_t dst_ipv4, uint16_t dport, int is_tcp)
58 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 58 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
59 "Asking for connection reversal with %x and code %u\n", 59 "Asking for connection reversal with %x and code %u\n",
60 (unsigned int) dst_ipv4, (unsigned int) dport); 60 (unsigned int) dst_ipv4, (unsigned int) dport);
61 h = GNUNET_NAT_register (cfg, is_tcp, dport, 0, NULL, NULL, NULL, NULL, NULL); 61 h = GNUNET_NAT_register (cfg, is_tcp, dport, 0, NULL, NULL, NULL, NULL, NULL, NULL);
62 memset (&sa, 0, sizeof (sa)); 62 memset (&sa, 0, sizeof (sa));
63 sa.sin_family = AF_INET; 63 sa.sin_family = AF_INET;
64#if HAVE_SOCKADDR_IN_SIN_LEN 64#if HAVE_SOCKADDR_IN_SIN_LEN
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) &&
diff --git a/src/nat/nat.conf b/src/nat/nat.conf
index 86522d994..9afa0aad0 100644
--- a/src/nat/nat.conf
+++ b/src/nat/nat.conf
@@ -48,6 +48,13 @@ IFC_SCAN_FREQUENCY = 15 min
48# for our hostname (to get our own IP) 48# for our hostname (to get our own IP)
49DYNDNS_FREQUENCY = 7 min 49DYNDNS_FREQUENCY = 7 min
50 50
51# SHOULD USE STUN ?
52USE_STUN = YES
53STUN_FREQUENCY = 2 min
54# Default list of stun servers
55STUN_SERVERS = stun.services.mozilla.com:3478 stun2.l.google.com:19302
56
57
51[gnunet-nat-server] 58[gnunet-nat-server]
52HOSTNAME = gnunet.org 59HOSTNAME = gnunet.org
53PORT = 5724 60PORT = 5724
diff --git a/src/nat/nat_stun.c b/src/nat/nat_stun.c
index 9419074a7..5e502c29e 100644
--- a/src/nat/nat_stun.c
+++ b/src/nat/nat_stun.c
@@ -48,6 +48,7 @@
48 48
49#define LOG(kind,...) GNUNET_log_from (kind, "stun", __VA_ARGS__) 49#define LOG(kind,...) GNUNET_log_from (kind, "stun", __VA_ARGS__)
50 50
51#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 15)
51 52
52 53
53/** 54/**
@@ -55,28 +56,44 @@
55 * the request prior to the timeout or successful execution. Also 56 * the request prior to the timeout or successful execution. Also
56 * used to track our internal state for the request. 57 * used to track our internal state for the request.
57 */ 58 */
58struct GNUNET_NAT_StunRequestHandle { 59struct GNUNET_NAT_STUN_Handle {
59 60
60 /** 61 /**
61 * Handle to a pending DNS lookup request. 62 * Handle to a pending DNS lookup request.
62 */ 63 */
63 struct GNUNET_RESOLVER_RequestHandle *dns_active; 64 struct GNUNET_RESOLVER_RequestHandle *dns_active;
64 65
65 66
66 /** 67 /**
67 * Handle to the listen socket 68 * Handle to the listen socket
68 */ 69 */
69 struct GNUNET_NETWORK_Handle * sock; 70 struct GNUNET_NETWORK_Handle * sock;
71
72 /**
73 * Stun server address
74 */
75 char *stun_server ;
76
77 /**
78 * STUN port
79 */
80 int stun_port;
70 81
71 /** 82 /**
72 * Stun server address 83 * Function to call when a error occours
84 */
85 GNUNET_NAT_stun_RequestCallback cb;
86
87 /**
88 * Closure for @e cb.
73 */ 89 */
74 char *stun_server ; 90 void *cb_cls;
75 91
76 /** 92 /**
77 * STUN port 93 * Do we got a DNS resolution successfully ?
78 */ 94 */
79 int stun_port; 95 int dns_success;
96
80 97
81}; 98};
82 99
@@ -84,7 +101,7 @@ struct GNUNET_NAT_StunRequestHandle {
84 101
85/* here we store credentials extracted from a message */ 102/* here we store credentials extracted from a message */
86struct StunState { 103struct StunState {
87 uint16_t attr; 104 uint16_t attr;
88}; 105};
89 106
90 107
@@ -96,7 +113,7 @@ struct StunState {
96 */ 113 */
97static int decode_class(int msg) 114static int decode_class(int msg)
98{ 115{
99 return ((msg & 0x0010) >> 4) | ((msg & 0x0100) >> 7); 116 return ((msg & 0x0010) >> 4) | ((msg & 0x0100) >> 7);
100} 117}
101 118
102/** 119/**
@@ -107,7 +124,7 @@ static int decode_class(int msg)
107 */ 124 */
108static int decode_method(int msg) 125static int decode_method(int msg)
109{ 126{
110 return (msg & 0x000f) | ((msg & 0x00e0) >> 1) | ((msg & 0x3e00) >> 2); 127 return (msg & 0x000f) | ((msg & 0x00e0) >> 1) | ((msg & 0x3e00) >> 2);
111} 128}
112 129
113/** 130/**
@@ -119,8 +136,8 @@ static int decode_method(int msg)
119 */ 136 */
120static int encode_message(StunClasses msg_class, StunMethods method) 137static int encode_message(StunClasses msg_class, StunMethods method)
121{ 138{
122 return ((msg_class & 1) << 4) | ((msg_class & 2) << 7) | 139 return ((msg_class & 1) << 4) | ((msg_class & 2) << 7) |
123 (method & 0x000f) | ((method & 0x0070) << 1) | ((method & 0x0f800) << 2); 140 (method & 0x000f) | ((method & 0x0070) << 1) | ((method & 0x0f800) << 2);
124} 141}
125 142
126/** 143/**
@@ -132,41 +149,41 @@ static int encode_message(StunClasses msg_class, StunMethods method)
132static const char *stun_msg2str(int msg) 149static const char *stun_msg2str(int msg)
133{ 150{
134 151
135 const struct { enum StunClasses value; const char *name; } classes[] = { 152 const struct { enum StunClasses value; const char *name; } classes[] = {
136 { STUN_REQUEST, "Request" }, 153 { STUN_REQUEST, "Request" },
137 { STUN_INDICATION, "Indication" }, 154 { STUN_INDICATION, "Indication" },
138 { STUN_RESPONSE, "Response" }, 155 { STUN_RESPONSE, "Response" },
139 { STUN_ERROR_RESPONSE, "Error Response" }, 156 { STUN_ERROR_RESPONSE, "Error Response" },
140 { 0, NULL } 157 { 0, NULL }
141 }; 158 };
142 159
143 const struct { enum StunMethods value; const char *name; } methods[] = { 160 const struct { enum StunMethods value; const char *name; } methods[] = {
144 { STUN_BINDING, "Binding" }, 161 { STUN_BINDING, "Binding" },
145 { 0, NULL } 162 { 0, NULL }
146 }; 163 };
147 164
148 static char result[32]; 165 static char result[32];
149 const char *msg_class = NULL; 166 const char *msg_class = NULL;
150 const char *method = NULL; 167 const char *method = NULL;
151 int i; 168 int i;
152 int value; 169 int value;
153 170
154 value = decode_class(msg); 171 value = decode_class(msg);
155 for (i = 0; classes[i].name; i++) { 172 for (i = 0; classes[i].name; i++) {
156 msg_class = classes[i].name; 173 msg_class = classes[i].name;
157 if (classes[i].value == value) 174 if (classes[i].value == value)
158 break; 175 break;
159 } 176 }
160 value = decode_method(msg); 177 value = decode_method(msg);
161 for (i = 0; methods[i].name; i++) { 178 for (i = 0; methods[i].name; i++) {
162 method = methods[i].name; 179 method = methods[i].name;
163 if (methods[i].value == value) 180 if (methods[i].value == value)
164 break; 181 break;
165 } 182 }
166 snprintf(result, sizeof(result), "%s %s", 183 snprintf(result, sizeof(result), "%s %s",
167 method ? : "Unknown Method", 184 method ? : "Unknown Method",
168 msg_class ? : "Unknown Class Message"); 185 msg_class ? : "Unknown Class Message");
169 return result; 186 return result;
170} 187}
171 188
172/** 189/**
@@ -177,35 +194,35 @@ static const char *stun_msg2str(int msg)
177 */ 194 */
178static const char *stun_attr2str(int msg) 195static const char *stun_attr2str(int msg)
179{ 196{
180 const struct { enum StunAttributes value; const char *name; } attrs[] = { 197 const struct { enum StunAttributes value; const char *name; } attrs[] = {
181 { STUN_MAPPED_ADDRESS, "Mapped Address" }, 198 { STUN_MAPPED_ADDRESS, "Mapped Address" },
182 { STUN_RESPONSE_ADDRESS, "Response Address" }, 199 { STUN_RESPONSE_ADDRESS, "Response Address" },
183 { STUN_CHANGE_ADDRESS, "Change Address" }, 200 { STUN_CHANGE_ADDRESS, "Change Address" },
184 { STUN_SOURCE_ADDRESS, "Source Address" }, 201 { STUN_SOURCE_ADDRESS, "Source Address" },
185 { STUN_CHANGED_ADDRESS, "Changed Address" }, 202 { STUN_CHANGED_ADDRESS, "Changed Address" },
186 { STUN_USERNAME, "Username" }, 203 { STUN_USERNAME, "Username" },
187 { STUN_PASSWORD, "Password" }, 204 { STUN_PASSWORD, "Password" },
188 { STUN_MESSAGE_INTEGRITY, "Message Integrity" }, 205 { STUN_MESSAGE_INTEGRITY, "Message Integrity" },
189 { STUN_ERROR_CODE, "Error Code" }, 206 { STUN_ERROR_CODE, "Error Code" },
190 { STUN_UNKNOWN_ATTRIBUTES, "Unknown Attributes" }, 207 { STUN_UNKNOWN_ATTRIBUTES, "Unknown Attributes" },
191 { STUN_REFLECTED_FROM, "Reflected From" }, 208 { STUN_REFLECTED_FROM, "Reflected From" },
192 { STUN_REALM, "Realm" }, 209 { STUN_REALM, "Realm" },
193 { STUN_NONCE, "Nonce" }, 210 { STUN_NONCE, "Nonce" },
194 { STUN_XOR_MAPPED_ADDRESS, "XOR Mapped Address" }, 211 { STUN_XOR_MAPPED_ADDRESS, "XOR Mapped Address" },
195 { STUN_MS_VERSION, "MS Version" }, 212 { STUN_MS_VERSION, "MS Version" },
196 { STUN_MS_XOR_MAPPED_ADDRESS, "MS XOR Mapped Address" }, 213 { STUN_MS_XOR_MAPPED_ADDRESS, "MS XOR Mapped Address" },
197 { STUN_SOFTWARE, "Software" }, 214 { STUN_SOFTWARE, "Software" },
198 { STUN_ALTERNATE_SERVER, "Alternate Server" }, 215 { STUN_ALTERNATE_SERVER, "Alternate Server" },
199 { STUN_FINGERPRINT, "Fingerprint" }, 216 { STUN_FINGERPRINT, "Fingerprint" },
200 { 0, NULL } 217 { 0, NULL }
201 }; 218 };
202 int i; 219 int i;
203 220
204 for (i = 0; attrs[i].name; i++) { 221 for (i = 0; attrs[i].name; i++) {
205 if (attrs[i].value == msg) 222 if (attrs[i].value == msg)
206 return attrs[i].name; 223 return attrs[i].name;
207 } 224 }
208 return "Unknown Attribute"; 225 return "Unknown Attribute";
209} 226}
210 227
211 228
@@ -219,22 +236,22 @@ static const char *stun_attr2str(int msg)
219 */ 236 */
220static int stun_process_attr(struct StunState *state, struct stun_attr *attr) 237static int stun_process_attr(struct StunState *state, struct stun_attr *attr)
221{ 238{
222 LOG (GNUNET_ERROR_TYPE_INFO, 239 LOG (GNUNET_ERROR_TYPE_INFO,
223 "Found STUN Attribute %s (%04x), length %d\n", 240 "Found STUN Attribute %s (%04x), length %d\n",
224 stun_attr2str(ntohs(attr->attr)), ntohs(attr->attr), ntohs(attr->len)); 241 stun_attr2str(ntohs(attr->attr)), ntohs(attr->attr), ntohs(attr->len));
225 242
226 switch (ntohs(attr->attr)) { 243 switch (ntohs(attr->attr)) {
227 case STUN_MAPPED_ADDRESS: 244 case STUN_MAPPED_ADDRESS:
228 case STUN_XOR_MAPPED_ADDRESS: 245 case STUN_XOR_MAPPED_ADDRESS:
229 case STUN_MS_XOR_MAPPED_ADDRESS: 246 case STUN_MS_XOR_MAPPED_ADDRESS:
230 break; 247 break;
231 default: 248 default:
232 LOG (GNUNET_ERROR_TYPE_INFO, 249 LOG (GNUNET_ERROR_TYPE_INFO,
233 "Ignoring STUN Attribute %s (%04x), length %d\n", 250 "Ignoring STUN Attribute %s (%04x), length %d\n",
234 stun_attr2str(ntohs(attr->attr)), ntohs(attr->attr), ntohs(attr->len)); 251 stun_attr2str(ntohs(attr->attr)), ntohs(attr->attr), ntohs(attr->len));
235 252
236 } 253 }
237 return 0; 254 return 0;
238} 255}
239 256
240 257
@@ -247,11 +264,11 @@ static int stun_process_attr(struct StunState *state, struct stun_attr *attr)
247static void 264static void
248generate_request_id(struct stun_header *req) 265generate_request_id(struct stun_header *req)
249{ 266{
250 int x; 267 int x;
251 req->magic = htonl(STUN_MAGIC_COOKIE); 268 req->magic = htonl(STUN_MAGIC_COOKIE);
252 for (x = 0; x < 3; x++) 269 for (x = 0; x < 3; x++)
253 req->id.id[x] = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE, 270 req->id.id[x] = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE,
254 UINT32_MAX); 271 UINT32_MAX);
255} 272}
256 273
257 274
@@ -295,6 +312,8 @@ stun_get_mapped(struct StunState *st, struct stun_attr *attr,struct sockaddr_in
295 } 312 }
296 313
297 st->attr = type; 314 st->attr = type;
315 /*TODO: Detect Family*/
316 sa->sin_family = AF_INET;
298 sa->sin_port = returned_addr->port ^ htons(ntohl(magic) >> 16); 317 sa->sin_port = returned_addr->port ^ htons(ntohl(magic) >> 16);
299 sa->sin_addr.s_addr = returned_addr->addr ^ magic; 318 sa->sin_addr.s_addr = returned_addr->addr ^ magic;
300 return 0; 319 return 0;
@@ -312,94 +331,109 @@ stun_get_mapped(struct StunState *st, struct stun_attr *attr,struct sockaddr_in
312 * @param len, the length of the packet 331 * @param len, the length of the packet
313 * @param arg, sockaddr_in where we will set our discovered packet 332 * @param arg, sockaddr_in where we will set our discovered packet
314 * 333 *
315 * @return, 0 on OK, -1 if the packet is invalid ( not a stun packet) 334 * @return, GNUNET_OK on OK, GNUNET_NO if the packet is invalid ( not a stun packet)
316 */ 335 */
317int 336int
318GNUNET_NAT_stun_handle_packet(const uint8_t *data, size_t len,struct sockaddr_in *arg) 337GNUNET_NAT_stun_handle_packet(const uint8_t *data, size_t len,struct sockaddr_in *arg)
319{ 338{
320 struct stun_header *hdr = (struct stun_header *)data; 339 struct stun_header *hdr = (struct stun_header *)data;
321 struct stun_attr *attr; 340 struct stun_attr *attr;
322 struct StunState st; 341 struct StunState st;
323 int ret = STUN_IGNORE; 342 int ret = GNUNET_OK;
324 343
325 uint32_t advertised_message_size; 344 uint32_t advertised_message_size;
326 uint32_t message_magic_cookie; 345 uint32_t message_magic_cookie;
327 346
328 347
329 /* On entry, 'len' is the length of the udp payload. After the 348 /* On entry, 'len' is the length of the udp payload. After the
330 * initial checks it becomes the size of unprocessed options, 349 * initial checks it becomes the size of unprocessed options,
331 * while 'data' is advanced accordingly. 350 * while 'data' is advanced accordingly.
332 */ 351 */
333 if (len < sizeof(struct stun_header)) { 352 if (len < sizeof(struct stun_header)) {
334 LOG (GNUNET_ERROR_TYPE_INFO, 353 LOG (GNUNET_ERROR_TYPE_INFO,
335 "STUN packet too short (only %d, wanting at least %d)\n", (int) len, (int) sizeof(struct stun_header)); 354 "STUN packet too short (only %d, wanting at least %d)\n", (int) len, (int) sizeof(struct stun_header));
336 GNUNET_break_op (0); 355 GNUNET_break_op (0);
337 return -1; 356 return GNUNET_NO;
338 } 357 }
339 /* Skip header as it is already in hdr */ 358 /* Skip header as it is already in hdr */
340 len -= sizeof(struct stun_header); 359 len -= sizeof(struct stun_header);
341 data += sizeof(struct stun_header); 360 data += sizeof(struct stun_header);
342 361
343 /* len as advertised in the message */ 362 /* len as advertised in the message */
344 advertised_message_size = ntohs(hdr->msglen); 363 advertised_message_size = ntohs(hdr->msglen);
345 364
346 message_magic_cookie = ntohl(hdr->magic); 365 message_magic_cookie = ntohl(hdr->magic);
347 /* Compare if the cookie match */ 366 /* Compare if the cookie match */
348 if(STUN_MAGIC_COOKIE != message_magic_cookie){ 367 if(STUN_MAGIC_COOKIE != message_magic_cookie){
349 LOG (GNUNET_ERROR_TYPE_INFO, 368 LOG (GNUNET_ERROR_TYPE_INFO,
350 "Invalid magic cookie \n"); 369 "Invalid magic cookie \n");
351 GNUNET_break_op (0); 370 GNUNET_break_op (0);
352 return -1; 371 return GNUNET_NO;
353 } 372 }
354 373
355 374
356 LOG (GNUNET_ERROR_TYPE_INFO, "STUN Packet, msg %s (%04x), length: %d\n", stun_msg2str(ntohs(hdr->msgtype)), ntohs(hdr->msgtype), advertised_message_size); 375 LOG (GNUNET_ERROR_TYPE_INFO, "STUN Packet, msg %s (%04x), length: %d\n", stun_msg2str(ntohs(hdr->msgtype)), ntohs(hdr->msgtype), advertised_message_size);
357 376
358 377
359 if (advertised_message_size > len) { 378 if (advertised_message_size > len) {
360 LOG (GNUNET_ERROR_TYPE_INFO, "Scrambled STUN packet length (got %d, expecting %d)\n", advertised_message_size, (int)len); 379 LOG (GNUNET_ERROR_TYPE_INFO, "Scrambled STUN packet length (got %d, expecting %d)\n", advertised_message_size, (int)len);
361 GNUNET_break_op (0); 380 GNUNET_break_op (0);
362 return -1; 381 return GNUNET_NO;
363 } else { 382 } else {
364 len = advertised_message_size; 383 len = advertised_message_size;
365 } 384 }
366 /* Zero the struct */ 385 /* Zero the struct */
367 memset(&st,0, sizeof(st)); 386 memset(&st,0, sizeof(st));
368 387
369 while (len > 0) { 388 while (len > 0) {
370 if (len < sizeof(struct stun_attr)) { 389 if (len < sizeof(struct stun_attr)) {
371 LOG (GNUNET_ERROR_TYPE_INFO, "Attribute too short (got %d, expecting %d)\n", (int)len, (int) sizeof(struct stun_attr)); 390 LOG (GNUNET_ERROR_TYPE_INFO, "Attribute too short (got %d, expecting %d)\n", (int)len, (int) sizeof(struct stun_attr));
372 GNUNET_break_op (0); 391 GNUNET_break_op (0);
373 break; 392 break;
374 } 393 }
375 attr = (struct stun_attr *)data; 394 attr = (struct stun_attr *)data;
376 395
377 /* compute total attribute length */ 396 /* compute total attribute length */
378 advertised_message_size = ntohs(attr->len) + sizeof(struct stun_attr); 397 advertised_message_size = ntohs(attr->len) + sizeof(struct stun_attr);
379 398
380 /* Check if we still have space in our buffer */ 399 /* Check if we still have space in our buffer */
381 if (advertised_message_size > len ) { 400 if (advertised_message_size > len ) {
382 LOG (GNUNET_ERROR_TYPE_INFO, "Inconsistent Attribute (length %d exceeds remaining msg len %d)\n", advertised_message_size, (int)len); 401 LOG (GNUNET_ERROR_TYPE_INFO, "Inconsistent Attribute (length %d exceeds remaining msg len %d)\n", advertised_message_size, (int)len);
383 GNUNET_break_op (0); 402 GNUNET_break_op (0);
384 break; 403 break;
385 } 404 }
386 405
387 406
388 stun_get_mapped(&st, attr, arg, hdr->magic); 407 stun_get_mapped(&st, attr, arg, hdr->magic);
389 408
390 if (stun_process_attr(&st, attr)) { 409 if (stun_process_attr(&st, attr)) {
391 LOG (GNUNET_ERROR_TYPE_INFO, "Failed to handle attribute %s (%04x)\n", stun_attr2str(ntohs(attr->attr)), ntohs(attr->attr)); 410 LOG (GNUNET_ERROR_TYPE_INFO, "Failed to handle attribute %s (%04x)\n", stun_attr2str(ntohs(attr->attr)), ntohs(attr->attr));
392 break; 411 break;
393 } 412 }
394 /* Clear attribute id: in case previous entry was a string, 413 /** Clear attribute id: in case previous entry was a string,
395 * this will act as the terminator for the string. 414 * this will act as the terminator for the string.
396 */ 415 **/
397 attr->attr = 0; 416 attr->attr = 0;
398 data += advertised_message_size; 417 data += advertised_message_size;
399 len -= advertised_message_size; 418 len -= advertised_message_size;
400 } 419 ret = GNUNET_OK;
401 420 }
402 return ret; 421
422 return ret;
423}
424
425
426
427/**
428 * Clean-up used memory
429 *
430 * @param cls our `struct GNUNET_NAT_STUN_Handle *`
431 */
432void clean(struct GNUNET_NAT_STUN_Handle * handle)
433{
434 GNUNET_free(handle->stun_server);
435 GNUNET_free(handle);
436
403} 437}
404 438
405 439
@@ -407,97 +441,120 @@ GNUNET_NAT_stun_handle_packet(const uint8_t *data, size_t len,struct sockaddr_in
407/** 441/**
408 * Try to establish a connection given the specified address. 442 * Try to establish a connection given the specified address.
409 * 443 *
410 * @param cls our `struct GNUNET_NAT_StunRequestHandle *` 444 * @param cls our `struct GNUNET_NAT_STUN_Handle *`
411 * @param addr address to try, NULL for "last call" 445 * @param addr address to try, NULL for "last call"
412 * @param addrlen length of @a addr 446 * @param addrlen length of @a addr
413 */ 447 */
414static void 448static void
415stun_dns_callback (void *cls, 449stun_dns_callback (void *cls,
416 const struct sockaddr *addr, 450 const struct sockaddr *addr,
417 socklen_t addrlen) { 451 socklen_t addrlen) {
452
453
454 struct GNUNET_NAT_STUN_Handle *request = cls;
418 455
456 struct stun_header *req;
457 uint8_t reqdata[1024];
458 int reqlen;
459 struct sockaddr_in server;
419 460
420 struct GNUNET_NAT_StunRequestHandle *request = cls;
421 461
422 struct stun_header *req; 462 if(NULL == request) {
423 uint8_t reqdata[1024];
424 int reqlen;
425 struct sockaddr_in server;
426 463
427 if(NULL == request) { 464 if( GNUNET_NO == request->dns_success){
428 LOG (GNUNET_ERROR_TYPE_INFO, "Empty request\n"); 465 LOG (GNUNET_ERROR_TYPE_INFO, "Empty request\n");
429 /* FIXME clean up ? */ 466 clean(request);
430 return; 467 request->cb(request->cb_cls, GNUNET_NAT_ERROR_INTERNAL_NETWORK_ERROR);
431 } 468 }
469 return;
470 }
432 471
433 if (NULL == addr) { 472 if (NULL == addr) {
434 request->dns_active = NULL; 473 request->dns_active = NULL;
435 LOG (GNUNET_ERROR_TYPE_INFO, "Error resolving host %s\n", request->stun_server);
436 /* FIXME clean up? */
437 return;
438 }
439 474
475 if( GNUNET_NO == request->dns_success){
476 LOG (GNUNET_ERROR_TYPE_INFO, "Error resolving host %s\n", request->stun_server);
477 clean(request);
478 request->cb(request->cb_cls, GNUNET_NAT_ERROR_INTERNAL_NETWORK_ERROR);
479 }
440 480
441 memset(&server,0, sizeof(server)); 481 return;
442 server.sin_family = AF_INET; 482 }
443 server.sin_addr = ((struct sockaddr_in *)addr)->sin_addr;
444 server.sin_port = htons(request->stun_port);
445 483
446 484
447 /*Craft the simplest possible STUN packet. A request binding*/ 485 request->dns_success= GNUNET_YES;
448 req = (struct stun_header *)reqdata; 486 memset(&server,0, sizeof(server));
449 generate_request_id(req); 487 server.sin_family = AF_INET;
450 reqlen = 0; 488 server.sin_addr = ((struct sockaddr_in *)addr)->sin_addr;
451 req->msgtype = 0; 489 server.sin_port = htons(request->stun_port);
452 req->msglen = 0; 490
453 req->msglen = htons(reqlen); 491
454 req->msgtype = htons(encode_message(STUN_REQUEST, STUN_BINDING)); 492 /*Craft the simplest possible STUN packet. A request binding*/
493 req = (struct stun_header *)reqdata;
494 generate_request_id(req);
495 reqlen = 0;
496 req->msgtype = 0;
497 req->msglen = 0;
498 req->msglen = htons(reqlen);
499 req->msgtype = htons(encode_message(STUN_REQUEST, STUN_BINDING));
500
501 /* Send the packet */
502 if (-1 == GNUNET_NETWORK_socket_sendto (request->sock, req, ntohs(req->msglen) + sizeof(*req),
503 (const struct sockaddr *) &server, sizeof (server)))
504 {
505 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "Fail to sendto");
506 clean(request);
507 request->cb(request->cb_cls, GNUNET_NAT_ERROR_INTERNAL_NETWORK_ERROR);
508 return;
509 }
455 510
456 /* Send the packet */
457 if (-1 == GNUNET_NETWORK_socket_sendto (request->sock, req, ntohs(req->msglen) + sizeof(*req),
458 (const struct sockaddr *) &server, sizeof (server)))
459 {
460 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "Fail to sendto");
461 }
462 511
463} 512}
464 513
465 514
515
516
517
466/** 518/**
467 * Make Generic STUN request and 519 * Make Generic STUN request and
468 * Send a generic stun request to the server specified using the specified socket. 520 * Send a generic stun request to the server specified using the specified socket.
469 * possibly waiting for a reply and filling the 'reply' field with 521 * possibly waiting for a reply and filling the 'reply' field with
470 * the externally visible address. 522 * the externally visible address.
471 *c 523 *
472 * @param server, the address of the stun server 524 * @param server, the address of the stun server
473 * @param port, port of the stun server 525 * @param port, port of the stun server
474 * @param sock the socket used to send the request 526 * @param sock the socket used to send the request
475 * @return GNUNET_NAT_StunRequestHandle on success, NULL on error. 527 * @return GNUNET_NAT_STUN_Handle on success, NULL on error.
476 */ 528 */
477struct GNUNET_NAT_StunRequestHandle * 529struct GNUNET_NAT_STUN_Handle *
478GNUNET_NAT_stun_make_request(char * server, int port, struct GNUNET_NETWORK_Handle * sock) 530GNUNET_NAT_stun_make_request(char * server, int port,
531 struct GNUNET_NETWORK_Handle * sock,GNUNET_NAT_stun_RequestCallback cb,
532 void *cb_cls)
479{ 533{
480 534
481 struct GNUNET_NAT_StunRequestHandle *rh; 535 struct GNUNET_NAT_STUN_Handle *rh;
536
537 rh = GNUNET_malloc (sizeof (struct GNUNET_NAT_STUN_Handle));
538 rh->sock = sock;
482 539
483 rh = GNUNET_malloc (sizeof (struct GNUNET_NAT_StunRequestHandle)); 540 char * server_copy = GNUNET_strdup (server);
484 rh->sock = sock;
485 541
486 char * server_copy = GNUNET_malloc (1 + strlen (server)); 542 rh->cb = cb;
487 if (server_copy) { 543 rh->cb_cls = cb_cls;
488 strcpy (server_copy, server); 544 rh->stun_server = server_copy;
489 }else{ 545 rh->stun_port = port;
490 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "Failed to allocate string"); 546 rh->dns_success = GNUNET_NO;
491 /* FIXME: cleanup rh? */ 547
492 return NULL; 548 rh->dns_active = GNUNET_RESOLVER_ip_get (server_copy, AF_INET,
493 } 549 TIMEOUT,
550 &stun_dns_callback, rh);
551
552 if(rh->dns_active == NULL)
553 {
554 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "Failed DNS");
555 return NULL;
556 }
494 557
495 rh->stun_server = server_copy;
496 rh->stun_port = port;
497 rh->dns_active = GNUNET_RESOLVER_ip_get (rh->stun_server, AF_INET,
498 GNUNET_CONNECTION_CONNECT_RETRY_TIMEOUT,
499 &stun_dns_callback, rh);
500 /* FIXME: error handling NULL==dns_active, callback function? */
501 558
502 return rh; 559 return rh;
503} 560}
diff --git a/src/nat/nat_test.c b/src/nat/nat_test.c
index eda969502..3ee80ecae 100644
--- a/src/nat/nat_test.c
+++ b/src/nat/nat_test.c
@@ -444,7 +444,7 @@ GNUNET_NAT_test_start (const struct GNUNET_CONFIGURATION_Handle *cfg,
444 = GNUNET_NAT_register (cfg, is_tcp, 0, 0, 444 = GNUNET_NAT_register (cfg, is_tcp, 0, 0,
445 NULL, NULL, 445 NULL, NULL,
446 &addr_cb, 446 &addr_cb,
447 &reversal_cb, nh); 447 &reversal_cb, nh, NULL);
448 } 448 }
449 else 449 else
450 { 450 {
@@ -490,7 +490,7 @@ GNUNET_NAT_test_start (const struct GNUNET_CONFIGURATION_Handle *cfg,
490 (GNUNET_YES == is_tcp) ? "tcp" : "udp"); 490 (GNUNET_YES == is_tcp) ? "tcp" : "udp");
491 nh->nat = GNUNET_NAT_register (cfg, is_tcp, adv_port, 1, 491 nh->nat = GNUNET_NAT_register (cfg, is_tcp, adv_port, 1,
492 addrs, addrlens, 492 addrs, addrlens,
493 &addr_cb, NULL, nh); 493 &addr_cb, NULL, nh, NULL);
494 if (NULL == nh->nat) 494 if (NULL == nh->nat)
495 { 495 {
496 LOG (GNUNET_ERROR_TYPE_ERROR, 496 LOG (GNUNET_ERROR_TYPE_ERROR,
diff --git a/src/nat/test_nat.c b/src/nat/test_nat.c
index d62d156a2..b1d90ca31 100644
--- a/src/nat/test_nat.c
+++ b/src/nat/test_nat.c
@@ -143,7 +143,7 @@ run (void *cls, char *const *args, const char *cfgfile,
143 143
144 nat = GNUNET_NAT_register (cfg, GNUNET_YES /* tcp */ , 144 nat = GNUNET_NAT_register (cfg, GNUNET_YES /* tcp */ ,
145 2086, 1, (const struct sockaddr **) &addr, 145 2086, 1, (const struct sockaddr **) &addr,
146 &data.addrlen, &addr_callback, NULL, NULL); 146 &data.addrlen, &addr_callback, NULL, NULL, NULL);
147 GNUNET_free (addr); 147 GNUNET_free (addr);
148 GNUNET_SCHEDULER_add_delayed (TIMEOUT, &stop, nat); 148 GNUNET_SCHEDULER_add_delayed (TIMEOUT, &stop, nat);
149} 149}
diff --git a/src/nat/test_stun.c b/src/nat/test_stun.c
index f0956d021..e75d55bd0 100644
--- a/src/nat/test_stun.c
+++ b/src/nat/test_stun.c
@@ -23,7 +23,7 @@
23 * 23 *
24 * @file nat/test_stun.c 24 * @file nat/test_stun.c
25 * @brief Testcase for STUN library 25 * @brief Testcase for STUN library
26 * @author Bruno Souza Cabral - Major rewrite. 26 * @author Bruno Souza Cabral
27 27
28 * 28 *
29 */ 29 */
@@ -40,13 +40,19 @@
40#define LOG(kind,...) GNUNET_log_from (kind, "test-stun", __VA_ARGS__) 40#define LOG(kind,...) GNUNET_log_from (kind, "test-stun", __VA_ARGS__)
41 41
42/** 42/**
43 * Time to wait before stopping NAT, in seconds
44 */
45#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
46
47
48/**
43 * The port the test service is running on (default 7895) 49 * The port the test service is running on (default 7895)
44 */ 50 */
45static unsigned long port = 7895; 51static unsigned long port = 7895;
46static int ret = 1; 52static int ret = 1;
47 53
48static char *stun_server = "stun.ekiga.net"; 54static char *stun_server = "stun2.l.google.com";
49static int stun_port = 3478; 55static int stun_port = 19302;
50 56
51/** 57/**
52 * The listen socket of the service for IPv4 58 * The listen socket of the service for IPv4
@@ -85,23 +91,26 @@ do_udp_read (void *cls,
85 ssize_t rlen; 91 ssize_t rlen;
86 struct sockaddr_in answer; 92 struct sockaddr_in answer;
87 93
94 printf("UDP READ\n");
95
88 96
89 if ((0 != (tc->reason & GNUNET_SCHEDULER_REASON_READ_READY)) && 97 if ((0 != (tc->reason & GNUNET_SCHEDULER_REASON_READ_READY)) &&
90 (GNUNET_NETWORK_fdset_isset (tc->read_ready, 98 (GNUNET_NETWORK_fdset_isset (tc->read_ready,
91 lsock4))) 99 lsock4)))
92 { 100 {
93 rlen = GNUNET_NETWORK_socket_recv (lsock4, reply_buf, sizeof (reply_buf)); 101 rlen = GNUNET_NETWORK_socket_recv (lsock4, reply_buf, sizeof (reply_buf));
94 102
95 103
96 //Lets handle the packet 104 //Lets handle the packet
97 memset(&answer, 0, sizeof(struct sockaddr_in)); 105 memset(&answer, 0, sizeof(struct sockaddr_in));
98 GNUNET_NAT_stun_handle_packet(reply_buf,rlen, &answer); 106 GNUNET_NAT_stun_handle_packet(reply_buf,rlen, &answer);
99 107
100 //Print the answer 108 //Print the answer
101 //TODO: Delete the object
102 ret = 0; 109 ret = 0;
103 print_answer(&answer); 110 print_answer(&answer);
104 111
112 //Destroy the connection
113 GNUNET_NETWORK_socket_close(lsock4);
105 114
106 } 115 }
107 116
@@ -144,13 +153,38 @@ bind_v4 ()
144 return ls; 153 return ls;
145} 154}
146 155
156/**
157 * Function that terminates the test.
158 */
159static void
160stop ()
161{
162 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Stopping NAT and quitting...\n");
163
164 printf("Stopped !!\n");
165 //Clean task
166 if(NULL != ltask4)
167 GNUNET_SCHEDULER_cancel (ltask4);
168
169 //Clean socket
170 if(NULL != ltask4)
171 GNUNET_NETWORK_socket_close (lsock4);
172
173}
174
175
176static void request_callback(void *cls,
177enum GNUNET_NAT_StatusCode result)
178{
179 ret = result;
180 stop();
181 printf("Called back\n");
182};
147 183
148 184
149/** 185/**
150 * Main function run with scheduler. 186 * Main function run with scheduler.
151 */ 187 */
152
153
154static void 188static void
155run (void *cls, char *const *args, const char *cfgfile, 189run (void *cls, char *const *args, const char *cfgfile,
156 const struct GNUNET_CONFIGURATION_Handle *cfg) 190 const struct GNUNET_CONFIGURATION_Handle *cfg)
@@ -162,29 +196,26 @@ run (void *cls, char *const *args, const char *cfgfile,
162 if (NULL == lsock4) 196 if (NULL == lsock4)
163 { 197 {
164 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "bind"); 198 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "bind");
199 GNUNET_SCHEDULER_shutdown ();
200 return;
165 } 201 }
166 else 202 else
167 { 203 {
168 printf("Binded, now will call add_read\n");
169 //Lets call our function now when it accepts 204 //Lets call our function now when it accepts
170 ltask4 = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, 205 ltask4 = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
171 lsock4, &do_udp_read, NULL); 206 lsock4, &do_udp_read, NULL);
172 /* So you read once and what will happen if you get an irregular message? Repeat and add timeout */ 207 /* So you read once and what will happen if you get an irregular message? Repeat and add timeout */
173 208
174 } 209 }
175 if(NULL == lsock4 ) 210
176 {
177 /* FIXME: duplicate check */
178 GNUNET_SCHEDULER_shutdown ();
179 return;
180 }
181 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 211 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
182 "Service listens on port %u\n", 212 "Service listens on port %u\n",
183 port); 213 port);
184 printf("Start main event\n"); 214 printf("Start main event\n");
185 GNUNET_NAT_stun_make_request(stun_server, stun_port, lsock4); 215 GNUNET_NAT_stun_make_request(stun_server, stun_port, lsock4, &request_callback, NULL);
186 //Main event 216 printf("Made the requeest\n");
187 //main_task = GNUNET_SCHEDULER_add_delayed (timeout, &do_timeout, nh); 217
218 //GNUNET_SCHEDULER_add_delayed (TIMEOUT, &stop, NULL);
188 219
189} 220}
190 221
@@ -198,13 +229,38 @@ main (int argc, char *const argv[])
198 229
199 char *const argv_prog[] = { 230 char *const argv_prog[] = {
200 "test-stun", 231 "test-stun",
232 "-c",
233 "test_stun.conf",
201 NULL 234 NULL
202 }; 235 };
203 GNUNET_log_setup ("test-stun", 236 GNUNET_log_setup ("test-stun",
204 "WARNING", 237 "WARNING",
205 NULL); 238 NULL);
206 239
207 GNUNET_PROGRAM_run (1, argv_prog, "test-stun", "nohelp", options, &run, NULL); 240 /* Lets start resolver */
241 char *fn;
242 struct GNUNET_OS_Process *proc;
243
244 fn = GNUNET_OS_get_libexec_binary_path ("gnunet-service-resolver");
245 proc = GNUNET_OS_start_process (GNUNET_YES,
246 GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
247 NULL, NULL, NULL,
248 fn,
249 "gnunet-service-resolver",
250 "-c", "test_stun.conf", NULL);
251 GNUNET_assert (NULL != proc);
252
253 GNUNET_PROGRAM_run (3, argv_prog, "test-stun", "nohelp", options, &run, NULL);
254
255 /* Now kill the resolver */
256 if (0 != GNUNET_OS_process_kill (proc, GNUNET_TERM_SIG))
257 {
258 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill");
259 }
260 GNUNET_OS_process_wait (proc);
261 GNUNET_OS_process_destroy (proc);
262 proc = NULL;
263
208 264
209 return ret; 265 return ret;
210} 266}
diff --git a/src/transport/plugin_transport_http_server.c b/src/transport/plugin_transport_http_server.c
index b4130f945..0000a604d 100644
--- a/src/transport/plugin_transport_http_server.c
+++ b/src/transport/plugin_transport_http_server.c
@@ -2761,7 +2761,7 @@ server_start_report_addresses (struct HTTP_Server_Plugin *plugin)
2761 plugin->port, 2761 plugin->port,
2762 (unsigned int) res, 2762 (unsigned int) res,
2763 (const struct sockaddr **) addrs, addrlens, 2763 (const struct sockaddr **) addrs, addrlens,
2764 &server_nat_port_map_callback, NULL, plugin); 2764 &server_nat_port_map_callback, NULL, plugin, NULL);
2765 while (res > 0) 2765 while (res > 0)
2766 { 2766 {
2767 res--; 2767 res--;
diff --git a/src/transport/plugin_transport_tcp.c b/src/transport/plugin_transport_tcp.c
index ec66a4388..b4bcde60f 100644
--- a/src/transport/plugin_transport_tcp.c
+++ b/src/transport/plugin_transport_tcp.c
@@ -2960,7 +2960,7 @@ libgnunet_plugin_transport_tcp_init (void *cls)
2960 (const struct sockaddr **) addrs, addrlens, 2960 (const struct sockaddr **) addrs, addrlens,
2961 &tcp_nat_port_map_callback, 2961 &tcp_nat_port_map_callback,
2962 &try_connection_reversal, 2962 &try_connection_reversal,
2963 plugin); 2963 plugin, NULL);
2964 for (ret = ret_s -1; ret >= 0; ret--) 2964 for (ret = ret_s -1; ret >= 0; ret--)
2965 GNUNET_free (addrs[ret]); 2965 GNUNET_free (addrs[ret]);
2966 GNUNET_free_non_null (addrs); 2966 GNUNET_free_non_null (addrs);
@@ -2976,7 +2976,8 @@ libgnunet_plugin_transport_tcp_init (void *cls)
2976 NULL, 2976 NULL,
2977 NULL, 2977 NULL,
2978 &try_connection_reversal, 2978 &try_connection_reversal,
2979 plugin); 2979 plugin,
2980 NULL);
2980 } 2981 }
2981 api = GNUNET_new (struct GNUNET_TRANSPORT_PluginFunctions); 2982 api = GNUNET_new (struct GNUNET_TRANSPORT_PluginFunctions);
2982 api->cls = plugin; 2983 api->cls = plugin;
diff --git a/src/transport/plugin_transport_udp.c b/src/transport/plugin_transport_udp.c
index 91839bbff..d031e6008 100644
--- a/src/transport/plugin_transport_udp.c
+++ b/src/transport/plugin_transport_udp.c
@@ -2854,6 +2854,13 @@ udp_select_read (struct Plugin *plugin,
2854 /* Connection failure or something. Not a protocol violation. */ 2854 /* Connection failure or something. Not a protocol violation. */
2855 return; 2855 return;
2856 } 2856 }
2857
2858
2859 /* PROCESS STUN PACKET */
2860 if(GNUNET_NAT_try_decode_stun_packet(plugin->nat,(uint8_t *)buf, size ))
2861 return;
2862
2863
2857 if (size < sizeof(struct GNUNET_MessageHeader)) 2864 if (size < sizeof(struct GNUNET_MessageHeader))
2858 { 2865 {
2859 LOG (GNUNET_ERROR_TYPE_WARNING, 2866 LOG (GNUNET_ERROR_TYPE_WARNING,
@@ -2866,6 +2873,10 @@ udp_select_read (struct Plugin *plugin,
2866 GNUNET_break_op (0); 2873 GNUNET_break_op (0);
2867 return; 2874 return;
2868 } 2875 }
2876
2877
2878
2879
2869 msg = (const struct GNUNET_MessageHeader *) buf; 2880 msg = (const struct GNUNET_MessageHeader *) buf;
2870 LOG (GNUNET_ERROR_TYPE_DEBUG, 2881 LOG (GNUNET_ERROR_TYPE_DEBUG,
2871 "UDP received %u-byte message from `%s' type %u\n", 2882 "UDP received %u-byte message from `%s' type %u\n",
@@ -3533,7 +3544,8 @@ setup_sockets (struct Plugin *plugin,
3533 addrlens, 3544 addrlens,
3534 &udp_nat_port_map_callback, 3545 &udp_nat_port_map_callback,
3535 NULL, 3546 NULL,
3536 plugin); 3547 plugin,
3548 plugin->sockv4);
3537 return sockets_created; 3549 return sockets_created;
3538} 3550}
3539 3551
diff --git a/src/transport/plugin_transport_udp.h b/src/transport/plugin_transport_udp.h
index 603e13e1a..5f8366636 100644
--- a/src/transport/plugin_transport_udp.h
+++ b/src/transport/plugin_transport_udp.h
@@ -190,6 +190,11 @@ struct Plugin
190 struct GNUNET_NAT_Handle *nat; 190 struct GNUNET_NAT_Handle *nat;
191 191
192 /** 192 /**
193 * Handle to NAT traversal support.
194 */
195 struct GNUNET_NAT_STUN_Handle *stun;
196
197 /**
193 * The read socket for IPv4 198 * The read socket for IPv4
194 */ 199 */
195 struct GNUNET_NETWORK_Handle *sockv4; 200 struct GNUNET_NETWORK_Handle *sockv4;