aboutsummaryrefslogtreecommitdiff
path: root/src/nat
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2017-01-02 19:15:51 +0100
committerChristian Grothoff <christian@grothoff.org>2017-01-02 19:15:51 +0100
commitf28533eb5fbd2b8e00bb351eb9fd1da322c70505 (patch)
tree793b1949dd681414d51ea18c151dd6684efa6b9f /src/nat
parent1082a8e39e4f3d9b908b14995653ac262f640adb (diff)
downloadgnunet-f28533eb5fbd2b8e00bb351eb9fd1da322c70505.tar.gz
gnunet-f28533eb5fbd2b8e00bb351eb9fd1da322c70505.zip
preparations for proper manual hole punching support in new NAT API
Diffstat (limited to 'src/nat')
-rw-r--r--src/nat/gnunet-nat.c13
-rw-r--r--src/nat/gnunet-service-nat.c58
-rw-r--r--src/nat/nat.h10
-rw-r--r--src/nat/nat_api.c16
4 files changed, 63 insertions, 34 deletions
diff --git a/src/nat/gnunet-nat.c b/src/nat/gnunet-nat.c
index a145dc800..81e4549b5 100644
--- a/src/nat/gnunet-nat.c
+++ b/src/nat/gnunet-nat.c
@@ -39,9 +39,10 @@ static int global_ret;
39static struct GNUNET_NAT_AutoHandle *ah; 39static struct GNUNET_NAT_AutoHandle *ah;
40 40
41/** 41/**
42 * Port we advertise. 42 * External hostname and port, if user manually punched
43 * the NAT.
43 */ 44 */
44static unsigned int adv_port; 45static char *hole_external;
45 46
46/** 47/**
47 * Flag set to 1 if we use IPPROTO_UDP. 48 * Flag set to 1 if we use IPPROTO_UDP.
@@ -568,7 +569,7 @@ run (void *cls,
568 { 569 {
569 nh = GNUNET_NAT_register (c, 570 nh = GNUNET_NAT_register (c,
570 proto, 571 proto,
571 (uint16_t) adv_port, 572 hole_external,
572 1, 573 1,
573 (const struct sockaddr **) &local_sa, 574 (const struct sockaddr **) &local_sa,
574 &local_len, 575 &local_len,
@@ -697,9 +698,9 @@ main (int argc,
697 {'r', "remote", "ADDRESS", 698 {'r', "remote", "ADDRESS",
698 gettext_noop ("which remote IP and port should be asked for connection reversal"), 699 gettext_noop ("which remote IP and port should be asked for connection reversal"),
699 GNUNET_YES, &GNUNET_GETOPT_set_string, &remote_addr }, 700 GNUNET_YES, &GNUNET_GETOPT_set_string, &remote_addr },
700 {'p', "port", NULL, 701 {'p', "punched", NULL,
701 gettext_noop ("port to use to advertise"), 702 gettext_noop ("external hostname and port of NAT, if punched manually; use AUTO for hostname for automatic determination of the external IP"),
702 GNUNET_YES, &GNUNET_GETOPT_set_uint, &adv_port }, 703 GNUNET_YES, &GNUNET_GETOPT_set_string, &hole_external },
703 {'s', "stun", NULL, 704 {'s', "stun", NULL,
704 gettext_noop ("enable STUN processing"), 705 gettext_noop ("enable STUN processing"),
705 GNUNET_NO, &GNUNET_GETOPT_set_one, &do_stun }, 706 GNUNET_NO, &GNUNET_GETOPT_set_one, &do_stun },
diff --git a/src/nat/gnunet-service-nat.c b/src/nat/gnunet-service-nat.c
index b547e773a..f432eca18 100644
--- a/src/nat/gnunet-service-nat.c
+++ b/src/nat/gnunet-service-nat.c
@@ -28,9 +28,12 @@
28 * knowledge about the local network topology. 28 * knowledge about the local network topology.
29 * 29 *
30 * TODO: 30 * TODO:
31 * - test ICMP based NAT traversal 31 * - test and document (!) ICMP based NAT traversal
32 * - implement manual hole punching support (incl. DNS
33 * lookup for DynDNS setups!)
32 * - implement "more" autoconfig: 34 * - implement "more" autoconfig:
33 * re-work gnunet-nat-server & integrate! 35 * re-work gnunet-nat-server & integrate!
36 * + test manually punched NAT (how?)
34 * - implement & test STUN processing to classify NAT; 37 * - implement & test STUN processing to classify NAT;
35 * basically, open port & try different methods. 38 * basically, open port & try different methods.
36 * - implement NEW logic for external IP detection 39 * - implement NEW logic for external IP detection
@@ -129,6 +132,16 @@ struct ClientHandle
129 * Array of addresses used by the service. 132 * Array of addresses used by the service.
130 */ 133 */
131 struct ClientAddress *caddrs; 134 struct ClientAddress *caddrs;
135
136 /**
137 * External DNS name and port given by user due to manual
138 * hole punching. Special DNS name 'AUTO' is used to indicate
139 * desire for automatic determination of the external IP
140 * (instead of DNS or manual configuration, i.e. to be used
141 * if the IP keeps changing and we have no DynDNS, but we do
142 * have a hole punched).
143 */
144 char *hole_external;
132 145
133 /** 146 /**
134 * What does this client care about? 147 * What does this client care about?
@@ -141,12 +154,6 @@ struct ClientHandle
141 int natted_address; 154 int natted_address;
142 155
143 /** 156 /**
144 * Port we would like as we are configured to use this one for
145 * advertising (in addition to the one we are binding to).
146 */
147 uint16_t adv_port;
148
149 /**
150 * Number of addresses that this service is bound to. 157 * Number of addresses that this service is bound to.
151 * Length of the @e caddrs array. 158 * Length of the @e caddrs array.
152 */ 159 */
@@ -459,7 +466,14 @@ check_register (void *cls,
459 GNUNET_break (0); 466 GNUNET_break (0);
460 return GNUNET_SYSERR; 467 return GNUNET_SYSERR;
461 } 468 }
462 } 469 off += alen;
470 left -= alen;
471 }
472 if (left != ntohs (message->hole_external_len))
473 {
474 GNUNET_break (0);
475 return GNUNET_SYSERR;
476 }
463 return GNUNET_OK; 477 return GNUNET_OK;
464} 478}
465 479
@@ -870,36 +884,33 @@ check_notify_client_external_ipv4_change (const struct in_addr *v4,
870 int add) 884 int add)
871{ 885{
872 struct sockaddr_in sa; 886 struct sockaddr_in sa;
873 uint16_t port; 887 int have_v4;
874 uint16_t bport;
875 888
876 /* (1) check if client cares. */ 889 /* (1) check if client cares. */
877 if (! ch->natted_address) 890 if (! ch->natted_address)
878 return; 891 return;
879 if (0 == (GNUNET_NAT_RF_ADDRESSES & ch->flags)) 892 if (0 == (GNUNET_NAT_RF_ADDRESSES & ch->flags))
880 return; 893 return;
881 bport = 0; 894 have_v4 = GNUNET_NO;
882 for (unsigned int i=0;i<ch->num_caddrs;i++) 895 for (unsigned int i=0;i<ch->num_caddrs;i++)
883 { 896 {
884 const struct sockaddr_storage *ss = &ch->caddrs[i].ss; 897 const struct sockaddr_storage *ss = &ch->caddrs[i].ss;
885 898
886 if (AF_INET != ss->ss_family) 899 if (AF_INET != ss->ss_family)
887 continue; 900 continue;
888 bport = ntohs (((const struct sockaddr_in *) ss)->sin_port); 901 have_v4 = GNUNET_YES;
902 break;
889 } 903 }
890 if (0 == bport) 904 if (GNUNET_NO == have_v4)
891 return; /* IPv6-only */ 905 return; /* IPv6-only */
892 906
893 /* (2) figure out external port, build sockaddr */ 907 /* build address info */
894 port = ch->adv_port;
895 if (0 == port)
896 port = bport;
897 memset (&sa, 908 memset (&sa,
898 0, 909 0,
899 sizeof (sa)); 910 sizeof (sa));
900 sa.sin_family = AF_INET; 911 sa.sin_family = AF_INET;
901 sa.sin_addr = *v4; 912 sa.sin_addr = *v4;
902 sa.sin_port = htons (port); 913 sa.sin_port = htons (0);
903 914
904 /* (3) notify client of change */ 915 /* (3) notify client of change */
905 notify_client (is_nat_v4 (v4) 916 notify_client (is_nat_v4 (v4)
@@ -1303,7 +1314,6 @@ handle_register (void *cls,
1303 "Received REGISTER message from client\n"); 1314 "Received REGISTER message from client\n");
1304 ch->flags = message->flags; 1315 ch->flags = message->flags;
1305 ch->proto = message->proto; 1316 ch->proto = message->proto;
1306 ch->adv_port = ntohs (message->adv_port);
1307 ch->num_caddrs = ntohs (message->num_addrs); 1317 ch->num_caddrs = ntohs (message->num_addrs);
1308 ch->caddrs = GNUNET_new_array (ch->num_caddrs, 1318 ch->caddrs = GNUNET_new_array (ch->num_caddrs,
1309 struct ClientAddress); 1319 struct ClientAddress);
@@ -1379,6 +1389,11 @@ handle_register (void *cls,
1379 1389
1380 off += alen; 1390 off += alen;
1381 } 1391 }
1392
1393 ch->hole_external
1394 = GNUNET_strndup (off,
1395 ntohs (message->hole_external_len));
1396
1382 /* Actually send IP address list to client */ 1397 /* Actually send IP address list to client */
1383 for (struct LocalAddressList *lal = lal_head; 1398 for (struct LocalAddressList *lal = lal_head;
1384 NULL != lal; 1399 NULL != lal;
@@ -1450,7 +1465,7 @@ notify_clients_stun_change (const struct sockaddr_in *ip,
1450 if (! ch->natted_address) 1465 if (! ch->natted_address)
1451 continue; 1466 continue;
1452 v4 = *ip; 1467 v4 = *ip;
1453 v4.sin_port = htons (ch->adv_port); 1468 v4.sin_port = htons (0);
1454 env = GNUNET_MQ_msg_extra (msg, 1469 env = GNUNET_MQ_msg_extra (msg,
1455 sizeof (v4), 1470 sizeof (v4),
1456 GNUNET_MESSAGE_TYPE_NAT_ADDRESS_CHANGE); 1471 GNUNET_MESSAGE_TYPE_NAT_ADDRESS_CHANGE);
@@ -2132,6 +2147,7 @@ client_disconnect_cb (void *cls,
2132 } 2147 }
2133 } 2148 }
2134 GNUNET_free_non_null (ch->caddrs); 2149 GNUNET_free_non_null (ch->caddrs);
2150 GNUNET_free (ch->hole_external);
2135 GNUNET_free (ch); 2151 GNUNET_free (ch);
2136} 2152}
2137 2153
diff --git a/src/nat/nat.h b/src/nat/nat.h
index 5cb1c1050..af418c7c2 100644
--- a/src/nat/nat.h
+++ b/src/nat/nat.h
@@ -110,10 +110,11 @@ struct GNUNET_NAT_RegisterMessage
110 uint8_t proto; 110 uint8_t proto;
111 111
112 /** 112 /**
113 * Port we would like as we are configured to use this one for 113 * Number of bytes in the string that follow which
114 * advertising (in addition to the one we are binding to). 114 * specify the hostname and port of a manually punched
115 * hole for this client.
115 */ 116 */
116 uint16_t adv_port GNUNET_PACKED; 117 uint16_t hole_external_len GNUNET_PACKED;
117 118
118 /** 119 /**
119 * Number of addresses that this service is bound to that follow. 120 * Number of addresses that this service is bound to that follow.
@@ -124,6 +125,9 @@ struct GNUNET_NAT_RegisterMessage
124 125
125 /* Followed by @e num_addrs addresses of type 'struct 126 /* Followed by @e num_addrs addresses of type 'struct
126 sockaddr' */ 127 sockaddr' */
128
129 /* Followed by @e hole_external_len bytes giving a hostname
130 and port */
127 131
128}; 132};
129 133
diff --git a/src/nat/nat_api.c b/src/nat/nat_api.c
index ab36d6162..e4dfc1629 100644
--- a/src/nat/nat_api.c
+++ b/src/nat/nat_api.c
@@ -369,8 +369,7 @@ do_connect (void *cls)
369 * 369 *
370 * @param cfg configuration to use 370 * @param cfg configuration to use
371 * @param proto protocol this is about, IPPROTO_TCP or IPPROTO_UDP 371 * @param proto protocol this is about, IPPROTO_TCP or IPPROTO_UDP
372 * @param adv_port advertised port (port we are either bound to or that our OS 372 * @param hole_external hostname and port of manually punched hole in NAT, otherwise NULL (or empty string)
373 * locally performs redirection from to our bound port).
374 * @param num_addrs number of addresses in @a addrs 373 * @param num_addrs number of addresses in @a addrs
375 * @param addrs list of local addresses packets should be redirected to 374 * @param addrs list of local addresses packets should be redirected to
376 * @param addrlens actual lengths of the addresses in @a addrs 375 * @param addrlens actual lengths of the addresses in @a addrs
@@ -383,7 +382,7 @@ do_connect (void *cls)
383struct GNUNET_NAT_Handle * 382struct GNUNET_NAT_Handle *
384GNUNET_NAT_register (const struct GNUNET_CONFIGURATION_Handle *cfg, 383GNUNET_NAT_register (const struct GNUNET_CONFIGURATION_Handle *cfg,
385 uint8_t proto, 384 uint8_t proto,
386 uint16_t adv_port, 385 const char *hole_external,
387 unsigned int num_addrs, 386 unsigned int num_addrs,
388 const struct sockaddr **addrs, 387 const struct sockaddr **addrs,
389 const socklen_t *addrlens, 388 const socklen_t *addrlens,
@@ -394,11 +393,17 @@ GNUNET_NAT_register (const struct GNUNET_CONFIGURATION_Handle *cfg,
394 struct GNUNET_NAT_Handle *nh; 393 struct GNUNET_NAT_Handle *nh;
395 struct GNUNET_NAT_RegisterMessage *rm; 394 struct GNUNET_NAT_RegisterMessage *rm;
396 size_t len; 395 size_t len;
396 size_t hole_external_len;
397 char *off; 397 char *off;
398 398
399 len = 0; 399 len = 0;
400 for (unsigned int i=0;i<num_addrs;i++) 400 for (unsigned int i=0;i<num_addrs;i++)
401 len += addrlens[i]; 401 len += addrlens[i];
402 hole_external_len
403 = (NULL == hole_external)
404 ? 0
405 : strlen (hole_external);
406 len += hole_external_len;
402 if ( (len > GNUNET_SERVER_MAX_MESSAGE_SIZE - sizeof (*rm)) || 407 if ( (len > GNUNET_SERVER_MAX_MESSAGE_SIZE - sizeof (*rm)) ||
403 (num_addrs > UINT16_MAX) ) 408 (num_addrs > UINT16_MAX) )
404 { 409 {
@@ -414,7 +419,7 @@ GNUNET_NAT_register (const struct GNUNET_CONFIGURATION_Handle *cfg,
414 if (NULL != reversal_callback) 419 if (NULL != reversal_callback)
415 rm->flags |= GNUNET_NAT_RF_REVERSAL; 420 rm->flags |= GNUNET_NAT_RF_REVERSAL;
416 rm->proto = proto; 421 rm->proto = proto;
417 rm->adv_port = htons (adv_port); 422 rm->hole_external_len = htons (hole_external_len);
418 rm->num_addrs = htons ((uint16_t) num_addrs); 423 rm->num_addrs = htons ((uint16_t) num_addrs);
419 off = (char *) &rm[1]; 424 off = (char *) &rm[1];
420 for (unsigned int i=0;i<num_addrs;i++) 425 for (unsigned int i=0;i<num_addrs;i++)
@@ -453,6 +458,9 @@ GNUNET_NAT_register (const struct GNUNET_CONFIGURATION_Handle *cfg,
453 addrlens[i]); 458 addrlens[i]);
454 off += addrlens[i]; 459 off += addrlens[i];
455 } 460 }
461 GNUNET_memcpy (off,
462 hole_external,
463 hole_external_len);
456 464
457 nh = GNUNET_new (struct GNUNET_NAT_Handle); 465 nh = GNUNET_new (struct GNUNET_NAT_Handle);
458 nh->reg = &rm->header; 466 nh->reg = &rm->header;