aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2017-01-05 15:03:41 +0100
committerChristian Grothoff <christian@grothoff.org>2017-01-05 15:03:41 +0100
commit3c31d74877c1243b98e7b31a0d5acab91fc5795e (patch)
tree7e8600c39c86bf210b77e9d685f4fffc68f4fe26 /src
parentc4600a19810f64aeded9804fa3d8c609bf9767c5 (diff)
downloadgnunet-3c31d74877c1243b98e7b31a0d5acab91fc5795e.tar.gz
gnunet-3c31d74877c1243b98e7b31a0d5acab91fc5795e.zip
properly handle DynDNS lookup results
Diffstat (limited to 'src')
-rw-r--r--src/nat/gnunet-service-nat.c225
1 files changed, 155 insertions, 70 deletions
diff --git a/src/nat/gnunet-service-nat.c b/src/nat/gnunet-service-nat.c
index 27e16820f..ffc0f6742 100644
--- a/src/nat/gnunet-service-nat.c
+++ b/src/nat/gnunet-service-nat.c
@@ -29,15 +29,17 @@
29 * 29 *
30 * TODO: 30 * TODO:
31 * - test and document (!) ICMP based NAT traversal 31 * - test and document (!) ICMP based NAT traversal
32 * - implement manual hole punching support (incl. DNS 32 * - implement NEW logic for external IP detection;
33 * lookup for DynDNS setups!) 33 * => introduce higher-level abstraction for external-IPs
34 * for subsystems to hook into!
35 * - implement manual hole punching support (AUTO missing)
36 * - test manual hole punching support
34 * - implement "more" autoconfig: 37 * - implement "more" autoconfig:
35 * + re-work gnunet-nat-server & integrate!
36 * + consider moving autoconfig-logic into separate service! 38 * + consider moving autoconfig-logic into separate service!
39 * + re-work gnunet-nat-server & integrate!
37 * + test manually punched NAT (how?) 40 * + test manually punched NAT (how?)
38 * - implement & test STUN processing to classify NAT; 41 * - implement & test STUN processing to classify NAT;
39 * basically, open port & try different methods. 42 * basically, open port & try different methods.
40 * - implement NEW logic for external IP detection
41 */ 43 */
42#include "platform.h" 44#include "platform.h"
43#include <math.h> 45#include <math.h>
@@ -110,6 +112,53 @@ struct ClientAddress
110 112
111 113
112/** 114/**
115 * List of local addresses this system has.
116 */
117struct LocalAddressList
118{
119 /**
120 * This is a linked list.
121 */
122 struct LocalAddressList *next;
123
124 /**
125 * Previous entry.
126 */
127 struct LocalAddressList *prev;
128
129 /**
130 * Context for a gnunet-helper-nat-server used to listen
131 * for ICMP messages to this client for connection reversal.
132 */
133 struct HelperContext *hc;
134
135 /**
136 * The address itself (i.e. `struct sockaddr_in` or `struct
137 * sockaddr_in6`, in the respective byte order).
138 */
139 struct sockaddr_storage addr;
140
141 /**
142 * Address family. (FIXME: redundant, addr.ss_family! Remove!?)
143 */
144 int af;
145
146 /**
147 * #GNUNET_YES if we saw this one in the previous iteration,
148 * but not in the current iteration and thus might need to
149 * remove it at the end.
150 */
151 int old;
152
153 /**
154 * What type of address is this?
155 */
156 enum GNUNET_NAT_AddressClass ac;
157
158};
159
160
161/**
113 * Internal data structure we track for each of our clients. 162 * Internal data structure we track for each of our clients.
114 */ 163 */
115struct ClientHandle 164struct ClientHandle
@@ -162,15 +211,14 @@ struct ClientHandle
162 struct GNUNET_RESOLVER_RequestHandle *ext_dns; 211 struct GNUNET_RESOLVER_RequestHandle *ext_dns;
163 212
164 /** 213 /**
165 * External IP address as given in @e hole_external. 214 * DLL of external IP addresses as given in @e hole_external.
166 */ 215 */
167 struct sockaddr_storage ext_addr; 216 struct LocalAddressList *ext_addr_head;
168 217
169 /** 218 /**
170 * Do we currently have a valid @e ext_addr which we told the 219 * DLL of external IP addresses as given in @e hole_external.
171 * client about?
172 */ 220 */
173 int ext_addr_set; 221 struct LocalAddressList *ext_addr_tail;
174 222
175 /** 223 /**
176 * Port number we found in @e hole_external. 224 * Port number we found in @e hole_external.
@@ -202,46 +250,6 @@ struct ClientHandle
202 250
203 251
204/** 252/**
205 * List of local addresses this system has.
206 */
207struct LocalAddressList
208{
209 /**
210 * This is a linked list.
211 */
212 struct LocalAddressList *next;
213
214 /**
215 * Previous entry.
216 */
217 struct LocalAddressList *prev;
218
219 /**
220 * Context for a gnunet-helper-nat-server used to listen
221 * for ICMP messages to this client for connection reversal.
222 */
223 struct HelperContext *hc;
224
225 /**
226 * The address itself (i.e. `struct sockaddr_in` or `struct
227 * sockaddr_in6`, in the respective byte order).
228 */
229 struct sockaddr_storage addr;
230
231 /**
232 * Address family.
233 */
234 int af;
235
236 /**
237 * What type of address is this?
238 */
239 enum GNUNET_NAT_AddressClass ac;
240
241};
242
243
244/**
245 * External IP address as given to us via some STUN server. 253 * External IP address as given to us via some STUN server.
246 */ 254 */
247struct StunExternalIP 255struct StunExternalIP
@@ -1382,17 +1390,35 @@ process_external_ip (void *cls,
1382 socklen_t addrlen) 1390 socklen_t addrlen)
1383{ 1391{
1384 struct ClientHandle *ch = cls; 1392 struct ClientHandle *ch = cls;
1393 struct LocalAddressList *lal;
1394 struct sockaddr_storage ss;
1395 struct sockaddr_in *v4;
1396 struct sockaddr_in6 *v6;
1385 1397
1386 if (NULL == addr) 1398 if (NULL == addr)
1387 { 1399 {
1400 struct LocalAddressList *laln;
1401
1388 ch->ext_dns = NULL; 1402 ch->ext_dns = NULL;
1389 ch->ext_dns_task 1403 ch->ext_dns_task
1390 = GNUNET_SCHEDULER_add_delayed (dyndns_frequency, 1404 = GNUNET_SCHEDULER_add_delayed (dyndns_frequency,
1391 &dyndns_lookup, 1405 &dyndns_lookup,
1392 ch); 1406 ch);
1393 /* Current iteration is over, remove 'old' IPs now */ 1407 /* Current iteration is over, remove 'old' IPs now */
1394 // FIXME: remove IPs we did NOT find! 1408 for (lal = ch->ext_addr_head; NULL != lal; lal = laln)
1395 GNUNET_break (0); 1409 {
1410 laln = lal->next;
1411 if (GNUNET_YES == lal->old)
1412 {
1413 GNUNET_CONTAINER_DLL_remove (ch->ext_addr_head,
1414 ch->ext_addr_tail,
1415 lal);
1416 check_notify_client (lal,
1417 ch,
1418 GNUNET_NO);
1419 GNUNET_free (lal);
1420 }
1421 }
1396 return; 1422 return;
1397 } 1423 }
1398 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1424 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -1400,7 +1426,50 @@ process_external_ip (void *cls,
1400 GNUNET_a2s (addr, 1426 GNUNET_a2s (addr,
1401 addrlen), 1427 addrlen),
1402 ch->hole_external); 1428 ch->hole_external);
1403 // FIXME: notify client, and remember IP for later removal! 1429
1430 /* build sockaddr storage with port number */
1431 memset (&ss, 0, sizeof (ss));
1432 memcpy (&ss, addr, addrlen);
1433 switch (addr->sa_family)
1434 {
1435 case AF_INET:
1436 v4 = (struct sockaddr_in *) &ss;
1437 v4->sin_port = htons (ch->ext_dns_port);
1438 break;
1439 case AF_INET6:
1440 v6 = (struct sockaddr_in6 *) &ss;
1441 v6->sin6_port = htons (ch->ext_dns_port);
1442 break;
1443 default:
1444 GNUNET_break (0);
1445 return;
1446 }
1447 /* See if 'ss' matches any of our known addresses */
1448 for (lal = ch->ext_addr_head; NULL != lal; lal = lal->next)
1449 {
1450 if (GNUNET_NO == lal->old)
1451 continue; /* already processed, skip */
1452 if ( (addr->sa_family == lal->addr.ss_family) &&
1453 (0 == memcmp (&ss,
1454 &lal->addr,
1455 addrlen)) )
1456 {
1457 /* Address unchanged, remember so we do not remove */
1458 lal->old = GNUNET_NO;
1459 return; /* done here */
1460 }
1461 }
1462 /* notify client, and remember IP for later removal! */
1463 lal = GNUNET_new (struct LocalAddressList);
1464 lal->addr = ss;
1465 lal->af = ss.ss_family;
1466 lal->ac = GNUNET_NAT_AC_GLOBAL | GNUNET_NAT_AC_MANUAL;
1467 GNUNET_CONTAINER_DLL_insert (ch->ext_addr_head,
1468 ch->ext_addr_tail,
1469 lal);
1470 check_notify_client (lal,
1471 ch,
1472 GNUNET_YES);
1404} 1473}
1405 1474
1406 1475
@@ -1416,7 +1485,10 @@ static void
1416dyndns_lookup (void *cls) 1485dyndns_lookup (void *cls)
1417{ 1486{
1418 struct ClientHandle *ch = cls; 1487 struct ClientHandle *ch = cls;
1488 struct LocalAddressList *lal;
1419 1489
1490 for (lal = ch->ext_addr_head; NULL != lal; lal = lal->next)
1491 lal->old = GNUNET_YES;
1420 ch->ext_dns_task = NULL; 1492 ch->ext_dns_task = NULL;
1421 ch->ext_dns = GNUNET_RESOLVER_ip_get (ch->hole_external, 1493 ch->ext_dns = GNUNET_RESOLVER_ip_get (ch->hole_external,
1422 AF_UNSPEC, 1494 AF_UNSPEC,
@@ -1443,7 +1515,7 @@ lookup_hole_external (struct ClientHandle *ch)
1443 char *port; 1515 char *port;
1444 unsigned int pnum; 1516 unsigned int pnum;
1445 struct sockaddr_in *s4; 1517 struct sockaddr_in *s4;
1446 struct LocalAddressList lal; 1518 struct LocalAddressList *lal;
1447 1519
1448 port = strrchr (ch->hole_external, ':'); 1520 port = strrchr (ch->hole_external, ':');
1449 if (NULL == port) 1521 if (NULL == port)
@@ -1465,17 +1537,19 @@ lookup_hole_external (struct ClientHandle *ch)
1465 } 1537 }
1466 ch->ext_dns_port = (uint16_t) pnum; 1538 ch->ext_dns_port = (uint16_t) pnum;
1467 *port = '\0'; 1539 *port = '\0';
1540
1541 lal = GNUNET_new (struct LocalAddressList);
1468 if ('[' == *ch->hole_external) 1542 if ('[' == *ch->hole_external)
1469 { 1543 {
1470 struct sockaddr_in6 *s6 = (struct sockaddr_in6 *) &ch->ext_addr; 1544 struct sockaddr_in6 *s6 = (struct sockaddr_in6 *) &lal->addr;
1471 1545
1472 memset (s6, 0, sizeof (*s6));
1473 s6->sin6_family = AF_INET6; 1546 s6->sin6_family = AF_INET6;
1474 if (']' != (ch->hole_external[strlen(ch->hole_external)-1])) 1547 if (']' != (ch->hole_external[strlen(ch->hole_external)-1]))
1475 { 1548 {
1476 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 1549 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1477 _("Malformed punched hole specification `%s' (lacks `]')\n"), 1550 _("Malformed punched hole specification `%s' (lacks `]')\n"),
1478 ch->hole_external); 1551 ch->hole_external);
1552 GNUNET_free (lal);
1479 return; 1553 return;
1480 } 1554 }
1481 ch->hole_external[strlen(ch->hole_external)-1] = '\0'; 1555 ch->hole_external[strlen(ch->hole_external)-1] = '\0';
@@ -1486,35 +1560,36 @@ lookup_hole_external (struct ClientHandle *ch)
1486 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 1560 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1487 _("Malformed punched hole specification `%s' (IPv6 address invalid)"), 1561 _("Malformed punched hole specification `%s' (IPv6 address invalid)"),
1488 ch->hole_external + 1); 1562 ch->hole_external + 1);
1563 GNUNET_free (lal);
1489 return; 1564 return;
1490 } 1565 }
1491 s6->sin6_port = htons (ch->ext_dns_port); 1566 s6->sin6_port = htons (ch->ext_dns_port);
1492 memset (&lal, 0, sizeof (lal)); 1567 lal->af = AF_INET6;
1493 GNUNET_memcpy (&lal.addr, s6, sizeof (*s6)); 1568 lal->ac = GNUNET_NAT_AC_GLOBAL | GNUNET_NAT_AC_MANUAL;
1494 lal.af = AF_INET6; 1569 GNUNET_CONTAINER_DLL_insert (ch->ext_addr_head,
1495 lal.ac = GNUNET_NAT_AC_GLOBAL | GNUNET_NAT_AC_MANUAL; 1570 ch->ext_addr_tail,
1496 check_notify_client (&lal, 1571 lal);
1572 check_notify_client (lal,
1497 ch, 1573 ch,
1498 GNUNET_YES); 1574 GNUNET_YES);
1499 ch->ext_addr_set = GNUNET_YES;
1500 return; 1575 return;
1501 } 1576 }
1502 s4 = (struct sockaddr_in *) &ch->ext_addr; 1577
1503 memset (s4, 0, sizeof (*s4)); 1578 s4 = (struct sockaddr_in *) &lal->addr;
1504 s4->sin_family = AF_INET; 1579 s4->sin_family = AF_INET;
1505 if (1 == inet_pton (AF_INET, 1580 if (1 == inet_pton (AF_INET,
1506 ch->hole_external, 1581 ch->hole_external,
1507 &s4->sin_addr)) 1582 &s4->sin_addr))
1508 { 1583 {
1509 s4->sin_port = htons (ch->ext_dns_port); 1584 s4->sin_port = htons (ch->ext_dns_port);
1510 memset (&lal, 0, sizeof (lal)); 1585 lal->af = AF_INET;
1511 GNUNET_memcpy (&lal.addr, s4, sizeof (*s4)); 1586 lal->ac = GNUNET_NAT_AC_GLOBAL | GNUNET_NAT_AC_MANUAL;
1512 lal.af = AF_INET; 1587 GNUNET_CONTAINER_DLL_insert (ch->ext_addr_head,
1513 lal.ac = GNUNET_NAT_AC_GLOBAL | GNUNET_NAT_AC_MANUAL; 1588 ch->ext_addr_tail,
1514 check_notify_client (&lal, 1589 lal);
1590 check_notify_client (lal,
1515 ch, 1591 ch,
1516 GNUNET_YES); 1592 GNUNET_YES);
1517 ch->ext_addr_set = GNUNET_YES;
1518 return; 1593 return;
1519 } 1594 }
1520 if (0 == strcasecmp (ch->hole_external, 1595 if (0 == strcasecmp (ch->hole_external,
@@ -1522,9 +1597,11 @@ lookup_hole_external (struct ClientHandle *ch)
1522 { 1597 {
1523 // FIXME: use `external-ip` address(es)! 1598 // FIXME: use `external-ip` address(es)!
1524 GNUNET_break (0); // not implemented! 1599 GNUNET_break (0); // not implemented!
1600 GNUNET_free (lal);
1525 return; 1601 return;
1526 } 1602 }
1527 /* got a DNS name, trigger lookup! */ 1603 /* got a DNS name, trigger lookup! */
1604 GNUNET_free (lal);
1528 ch->ext_dns_task 1605 ch->ext_dns_task
1529 = GNUNET_SCHEDULER_add_now (&dyndns_lookup, 1606 = GNUNET_SCHEDULER_add_now (&dyndns_lookup,
1530 ch); 1607 ch);
@@ -2386,6 +2463,7 @@ client_disconnect_cb (void *cls,
2386 void *internal_cls) 2463 void *internal_cls)
2387{ 2464{
2388 struct ClientHandle *ch = internal_cls; 2465 struct ClientHandle *ch = internal_cls;
2466 struct LocalAddressList *lal;
2389 2467
2390 GNUNET_CONTAINER_DLL_remove (ch_head, 2468 GNUNET_CONTAINER_DLL_remove (ch_head,
2391 ch_tail, 2469 ch_tail,
@@ -2399,6 +2477,13 @@ client_disconnect_cb (void *cls,
2399 } 2477 }
2400 } 2478 }
2401 GNUNET_free_non_null (ch->caddrs); 2479 GNUNET_free_non_null (ch->caddrs);
2480 while (NULL != (lal = ch->ext_addr_head))
2481 {
2482 GNUNET_CONTAINER_DLL_remove (ch->ext_addr_head,
2483 ch->ext_addr_tail,
2484 lal);
2485 GNUNET_free (lal);
2486 }
2402 if (NULL != ch->ext_dns_task) 2487 if (NULL != ch->ext_dns_task)
2403 { 2488 {
2404 GNUNET_SCHEDULER_cancel (ch->ext_dns_task); 2489 GNUNET_SCHEDULER_cancel (ch->ext_dns_task);