aboutsummaryrefslogtreecommitdiff
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
parent1082a8e39e4f3d9b908b14995653ac262f640adb (diff)
downloadgnunet-f28533eb5fbd2b8e00bb351eb9fd1da322c70505.tar.gz
gnunet-f28533eb5fbd2b8e00bb351eb9fd1da322c70505.zip
preparations for proper manual hole punching support in new NAT API
-rw-r--r--doc/man/gnunet-nat.110
-rw-r--r--src/include/gnunet_nat_service.h5
-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
6 files changed, 73 insertions, 39 deletions
diff --git a/doc/man/gnunet-nat.1 b/doc/man/gnunet-nat.1
index 2ba236399..5bdbb21eb 100644
--- a/doc/man/gnunet-nat.1
+++ b/doc/man/gnunet-nat.1
@@ -39,8 +39,8 @@ Assuming we are listening at ADDRESS for connection reversal requests.
39Ask the peer at ADDRESS for connection reversal, using the local address for the target address of the reversal. 39Ask the peer at ADDRESS for connection reversal, using the local address for the target address of the reversal.
40 40
41.B 41.B
42.IP "\-p PORT, \-\-port=PORT" 42.IP "\-p ADDRESS, \-\-punch=ADDRESS"
43Use PORT as our external port for advertising for incoming requests. 43A hole was punched manually through the NAT. We should use ADDRESS as our external hostname and port for advertising for incoming requests. The special hostname 'AUTO' can be used to indicate that GNUnet should determine the external IP address by other means (such as upnpc), and just take the port number from ADDRESS.
44 44
45.B 45.B
46.IP "\-s, \-\-stun" 46.IP "\-s, \-\-stun"
@@ -89,6 +89,12 @@ Initiate connection reversal request:
89 89
90 # gnunet-nat FIXME 90 # gnunet-nat FIXME
91 91
92\fBManual hole punching:\fR
93
94Assume manually punched NAT, but determine external IP automatically:
95
96 # gnunet-nat -t -p AUTO:8080
97
92\fBSTUN-based XXX:\fR 98\fBSTUN-based XXX:\fR
93 99
94XXX: 100XXX:
diff --git a/src/include/gnunet_nat_service.h b/src/include/gnunet_nat_service.h
index d9ce0e6f9..1620c9433 100644
--- a/src/include/gnunet_nat_service.h
+++ b/src/include/gnunet_nat_service.h
@@ -180,8 +180,7 @@ struct GNUNET_NAT_Handle;
180 * 180 *
181 * @param cfg configuration to use 181 * @param cfg configuration to use
182 * @param proto protocol this is about, IPPROTO_TCP or IPPROTO_UDP 182 * @param proto protocol this is about, IPPROTO_TCP or IPPROTO_UDP
183 * @param adv_port advertised port (port we are either bound to or that our OS 183 * @param hole_external hostname and port of manually punched hole in NAT, otherwise NULL (or empty string)
184 * locally performs redirection from to our bound port).
185 * @param num_addrs number of addresses in @a addrs 184 * @param num_addrs number of addresses in @a addrs
186 * @param addrs list of local addresses packets should be redirected to 185 * @param addrs list of local addresses packets should be redirected to
187 * @param addrlens actual lengths of the addresses in @a addrs 186 * @param addrlens actual lengths of the addresses in @a addrs
@@ -194,7 +193,7 @@ struct GNUNET_NAT_Handle;
194struct GNUNET_NAT_Handle * 193struct GNUNET_NAT_Handle *
195GNUNET_NAT_register (const struct GNUNET_CONFIGURATION_Handle *cfg, 194GNUNET_NAT_register (const struct GNUNET_CONFIGURATION_Handle *cfg,
196 uint8_t proto, 195 uint8_t proto,
197 uint16_t adv_port, 196 const char *hole_external,
198 unsigned int num_addrs, 197 unsigned int num_addrs,
199 const struct sockaddr **addrs, 198 const struct sockaddr **addrs,
200 const socklen_t *addrlens, 199 const socklen_t *addrlens,
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;