aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/man/gnunet-nat.110
-rw-r--r--src/gns/gnunet-gns-proxy.c3
-rw-r--r--src/include/gnunet_nat_service.h9
-rw-r--r--src/nat/gnunet-helper-nat-server.c115
-rw-r--r--src/nat/gnunet-nat.c25
-rw-r--r--src/nat/gnunet-service-nat.c210
-rw-r--r--src/nat/gnunet-service-nat_helper.c80
-rw-r--r--src/nat/gnunet-service-nat_helper.h2
-rw-r--r--src/nat/nat.h24
-rw-r--r--src/nat/nat_api.c31
10 files changed, 347 insertions, 162 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/gns/gnunet-gns-proxy.c b/src/gns/gnunet-gns-proxy.c
index ef9c7bf62..3a38970a8 100644
--- a/src/gns/gnunet-gns-proxy.c
+++ b/src/gns/gnunet-gns-proxy.c
@@ -1761,7 +1761,8 @@ create_response (void *cls,
1761 { 1761 {
1762 1762
1763 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1763 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1764 "Processing %lu bytes UPLOAD\n", *upload_data_size); 1764 "Processing %u bytes UPLOAD\n",
1765 (unsigned int) *upload_data_size);
1765 1766
1766 /* FIXME: This must be set or a header with Transfer-Encoding: chunked. Else 1767 /* FIXME: This must be set or a header with Transfer-Encoding: chunked. Else
1767 * upload callback is not called! 1768 * upload callback is not called!
diff --git a/src/include/gnunet_nat_service.h b/src/include/gnunet_nat_service.h
index 4df17b531..1620c9433 100644
--- a/src/include/gnunet_nat_service.h
+++ b/src/include/gnunet_nat_service.h
@@ -155,15 +155,11 @@ typedef void
155 * reversal. 155 * reversal.
156 * 156 *
157 * @param cls closure 157 * @param cls closure
158 * @param local_addr address where we received the request
159 * @param local_addrlen actual length of the @a local_addr
160 * @param remote_addr public IP address of the other peer 158 * @param remote_addr public IP address of the other peer
161 * @param remote_addrlen actual length of the @a remote_addr 159 * @param remote_addrlen actual length of the @a remote_addr
162 */ 160 */
163typedef void 161typedef void
164(*GNUNET_NAT_ReversalCallback) (void *cls, 162(*GNUNET_NAT_ReversalCallback) (void *cls,
165 const struct sockaddr *local_addr,
166 socklen_t local_addrlen,
167 const struct sockaddr *remote_addr, 163 const struct sockaddr *remote_addr,
168 socklen_t remote_addrlen); 164 socklen_t remote_addrlen);
169 165
@@ -184,8 +180,7 @@ struct GNUNET_NAT_Handle;
184 * 180 *
185 * @param cfg configuration to use 181 * @param cfg configuration to use
186 * @param proto protocol this is about, IPPROTO_TCP or IPPROTO_UDP 182 * @param proto protocol this is about, IPPROTO_TCP or IPPROTO_UDP
187 * @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)
188 * locally performs redirection from to our bound port).
189 * @param num_addrs number of addresses in @a addrs 184 * @param num_addrs number of addresses in @a addrs
190 * @param addrs list of local addresses packets should be redirected to 185 * @param addrs list of local addresses packets should be redirected to
191 * @param addrlens actual lengths of the addresses in @a addrs 186 * @param addrlens actual lengths of the addresses in @a addrs
@@ -198,7 +193,7 @@ struct GNUNET_NAT_Handle;
198struct GNUNET_NAT_Handle * 193struct GNUNET_NAT_Handle *
199GNUNET_NAT_register (const struct GNUNET_CONFIGURATION_Handle *cfg, 194GNUNET_NAT_register (const struct GNUNET_CONFIGURATION_Handle *cfg,
200 uint8_t proto, 195 uint8_t proto,
201 uint16_t adv_port, 196 const char *hole_external,
202 unsigned int num_addrs, 197 unsigned int num_addrs,
203 const struct sockaddr **addrs, 198 const struct sockaddr **addrs,
204 const socklen_t *addrlens, 199 const socklen_t *addrlens,
diff --git a/src/nat/gnunet-helper-nat-server.c b/src/nat/gnunet-helper-nat-server.c
index 8c3df749d..ef8e97482 100644
--- a/src/nat/gnunet-helper-nat-server.c
+++ b/src/nat/gnunet-helper-nat-server.c
@@ -264,8 +264,11 @@ send_icmp_echo (const struct in_addr *my_ip)
264 ip_pkt.src_ip = my_ip->s_addr; 264 ip_pkt.src_ip = my_ip->s_addr;
265 ip_pkt.dst_ip = dummy.s_addr; 265 ip_pkt.dst_ip = dummy.s_addr;
266 ip_pkt.checksum = 266 ip_pkt.checksum =
267 htons (calc_checksum ((uint16_t *) & ip_pkt, sizeof (struct ip_header))); 267 htons (calc_checksum ((uint16_t *) & ip_pkt,
268 memcpy (&packet[off], &ip_pkt, sizeof (struct ip_header)); 268 sizeof (struct ip_header)));
269 memcpy (&packet[off],
270 &ip_pkt,
271 sizeof (struct ip_header));
269 off += sizeof (struct ip_header); 272 off += sizeof (struct ip_header);
270 273
271 icmp_echo.type = ICMP_ECHO; 274 icmp_echo.type = ICMP_ECHO;
@@ -273,9 +276,12 @@ send_icmp_echo (const struct in_addr *my_ip)
273 icmp_echo.checksum = 0; 276 icmp_echo.checksum = 0;
274 icmp_echo.reserved = 0; 277 icmp_echo.reserved = 0;
275 icmp_echo.checksum = 278 icmp_echo.checksum =
276 htons (calc_checksum 279 htons (calc_checksum
277 ((uint16_t *) & icmp_echo, sizeof (struct icmp_echo_header))); 280 ((uint16_t *) & icmp_echo,
278 memcpy (&packet[off], &icmp_echo, sizeof (struct icmp_echo_header)); 281 sizeof (struct icmp_echo_header)));
282 memcpy (&packet[off],
283 &icmp_echo,
284 sizeof (struct icmp_echo_header));
279 off += sizeof (struct icmp_echo_header); 285 off += sizeof (struct icmp_echo_header);
280 286
281 memset (&dst, 0, sizeof (dst)); 287 memset (&dst, 0, sizeof (dst));
@@ -284,17 +290,24 @@ send_icmp_echo (const struct in_addr *my_ip)
284 dst.sin_len = sizeof (struct sockaddr_in); 290 dst.sin_len = sizeof (struct sockaddr_in);
285#endif 291#endif
286 dst.sin_addr = dummy; 292 dst.sin_addr = dummy;
287 err = 293 err = sendto (rawsock,
288 sendto (rawsock, packet, off, 0, (struct sockaddr *) &dst, sizeof (dst)); 294 packet,
295 off,
296 0,
297 (struct sockaddr *) &dst,
298 sizeof (dst));
289 if (err < 0) 299 if (err < 0)
290 { 300 {
291#if VERBOSE 301#if VERBOSE
292 fprintf (stderr, "sendto failed: %s\n", strerror (errno)); 302 fprintf (stderr,
303 "sendto failed: %s\n",
304 strerror (errno));
293#endif 305#endif
294 } 306 }
295 else if (sizeof (packet) != err) 307 else if (sizeof (packet) != err)
296 { 308 {
297 fprintf (stderr, "Error: partial send of ICMP message\n"); 309 fprintf (stderr,
310 "Error: partial send of ICMP message\n");
298 } 311 }
299} 312}
300 313
@@ -315,16 +328,24 @@ send_udp ()
315#endif 328#endif
316 dst.sin_addr = dummy; 329 dst.sin_addr = dummy;
317 dst.sin_port = htons (NAT_TRAV_PORT); 330 dst.sin_port = htons (NAT_TRAV_PORT);
318 err = sendto (udpsock, NULL, 0, 0, (struct sockaddr *) &dst, sizeof (dst)); 331 err = sendto (udpsock,
332 NULL,
333 0,
334 0,
335 (struct sockaddr *) &dst,
336 sizeof (dst));
319 if (err < 0) 337 if (err < 0)
320 { 338 {
321#if VERBOSE 339#if VERBOSE
322 fprintf (stderr, "sendto failed: %s\n", strerror (errno)); 340 fprintf (stderr,
341 "sendto failed: %s\n",
342 strerror (errno));
323#endif 343#endif
324 } 344 }
325 else if (0 != err) 345 else if (0 != err)
326 { 346 {
327 fprintf (stderr, "Error: partial send of ICMP message\n"); 347 fprintf (stderr,
348 "Error: partial send of ICMP message\n");
328 } 349 }
329} 350}
330 351
@@ -348,11 +369,15 @@ process_icmp_response ()
348 have = read (icmpsock, buf, sizeof (buf)); 369 have = read (icmpsock, buf, sizeof (buf));
349 if (-1 == have) 370 if (-1 == have)
350 { 371 {
351 fprintf (stderr, "Error reading raw socket: %s\n", strerror (errno)); 372 fprintf (stderr,
373 "Error reading raw socket: %s\n",
374 strerror (errno));
352 return; 375 return;
353 } 376 }
354#if VERBOSE 377#if VERBOSE
355 fprintf (stderr, "Received message of %u bytes\n", (unsigned int) have); 378 fprintf (stderr,
379 "Received message of %u bytes\n",
380 (unsigned int) have);
356#endif 381#endif
357 if (have < 382 if (have <
358 (ssize_t) (sizeof (struct ip_header) + 383 (ssize_t) (sizeof (struct ip_header) +
@@ -433,15 +458,27 @@ setup_raw_socket ()
433 const int one = 1; 458 const int one = 1;
434 459
435 if (-1 == 460 if (-1 ==
436 setsockopt (rawsock, SOL_SOCKET, SO_BROADCAST, (char *) &one, sizeof (one))) 461 setsockopt (rawsock,
462 SOL_SOCKET,
463 SO_BROADCAST,
464 (char *) &one,
465 sizeof (one)))
437 { 466 {
438 fprintf (stderr, "setsockopt failed: %s\n", strerror (errno)); 467 fprintf (stderr,
468 "setsockopt failed: %s\n",
469 strerror (errno));
439 return -1; 470 return -1;
440 } 471 }
441 if (-1 == 472 if (-1 ==
442 setsockopt (rawsock, IPPROTO_IP, IP_HDRINCL, (char *) &one, sizeof (one))) 473 setsockopt (rawsock,
474 IPPROTO_IP,
475 IP_HDRINCL,
476 (char *) &one,
477 sizeof (one)))
443 { 478 {
444 fprintf (stderr, "setsockopt failed: %s\n", strerror (errno)); 479 fprintf (stderr,
480 "setsockopt failed: %s\n",
481 strerror (errno));
445 return -1; 482 return -1;
446 } 483 }
447 return 0; 484 return 0;
@@ -492,7 +529,8 @@ make_udp_socket (const struct in_addr *my_ip)
492 529
493 530
494int 531int
495main (int argc, char *const *argv) 532main (int argc,
533 char *const *argv)
496{ 534{
497 struct in_addr external; 535 struct in_addr external;
498 fd_set rs; 536 fd_set rs;
@@ -504,11 +542,15 @@ main (int argc, char *const *argv)
504 int global_ret; 542 int global_ret;
505 543
506 /* Create an ICMP raw socket for reading (we'll check errors later) */ 544 /* Create an ICMP raw socket for reading (we'll check errors later) */
507 icmpsock = socket (AF_INET, SOCK_RAW, IPPROTO_ICMP); 545 icmpsock = socket (AF_INET,
546 SOCK_RAW,
547 IPPROTO_ICMP);
508 icmp_eno = errno; 548 icmp_eno = errno;
509 549
510 /* Create an (ICMP) raw socket for writing (we'll check errors later) */ 550 /* Create an (ICMP) raw socket for writing (we'll check errors later) */
511 rawsock = socket (AF_INET, SOCK_RAW, IPPROTO_RAW); 551 rawsock = socket (AF_INET,
552 SOCK_RAW,
553 IPPROTO_RAW);
512 raw_eno = errno; 554 raw_eno = errno;
513 udpsock = -1; 555 udpsock = -1;
514 556
@@ -517,14 +559,18 @@ main (int argc, char *const *argv)
517#ifdef HAVE_SETRESUID 559#ifdef HAVE_SETRESUID
518 if (0 != setresuid (uid, uid, uid)) 560 if (0 != setresuid (uid, uid, uid))
519 { 561 {
520 fprintf (stderr, "Failed to setresuid: %s\n", strerror (errno)); 562 fprintf (stderr,
563 "Failed to setresuid: %s\n",
564 strerror (errno));
521 global_ret = 1; 565 global_ret = 1;
522 goto error_exit; 566 goto error_exit;
523 } 567 }
524#else 568#else
525 if (0 != (setuid (uid) | seteuid (uid))) 569 if (0 != (setuid (uid) | seteuid (uid)))
526 { 570 {
527 fprintf (stderr, "Failed to setuid: %s\n", strerror (errno)); 571 fprintf (stderr,
572 "Failed to setuid: %s\n",
573 strerror (errno));
528 global_ret = 2; 574 global_ret = 2;
529 goto error_exit; 575 goto error_exit;
530 } 576 }
@@ -540,13 +586,16 @@ main (int argc, char *const *argv)
540 } 586 }
541 if (1 != inet_pton (AF_INET, argv[1], &external)) 587 if (1 != inet_pton (AF_INET, argv[1], &external))
542 { 588 {
543 fprintf (stderr, "Error parsing IPv4 address: %s\n", strerror (errno)); 589 fprintf (stderr,
590 "Error parsing IPv4 address: %s\n",
591 strerror (errno));
544 global_ret = 4; 592 global_ret = 4;
545 goto error_exit; 593 goto error_exit;
546 } 594 }
547 if (1 != inet_pton (AF_INET, DUMMY_IP, &dummy)) 595 if (1 != inet_pton (AF_INET, DUMMY_IP, &dummy))
548 { 596 {
549 fprintf (stderr, "Internal error converting dummy IP to binary.\n"); 597 fprintf (stderr,
598 "Internal error converting dummy IP to binary.\n");
550 global_ret = 5; 599 global_ret = 5;
551 goto error_exit; 600 goto error_exit;
552 } 601 }
@@ -554,7 +603,9 @@ main (int argc, char *const *argv)
554 /* error checking icmpsock */ 603 /* error checking icmpsock */
555 if (-1 == icmpsock) 604 if (-1 == icmpsock)
556 { 605 {
557 fprintf (stderr, "Error opening RAW socket: %s\n", strerror (icmp_eno)); 606 fprintf (stderr,
607 "Error opening RAW socket: %s\n",
608 strerror (icmp_eno));
558 global_ret = 6; 609 global_ret = 6;
559 goto error_exit; 610 goto error_exit;
560 } 611 }
@@ -562,7 +613,9 @@ main (int argc, char *const *argv)
562 { 613 {
563 /* this could happen if we were started with a large number of already-open 614 /* this could happen if we were started with a large number of already-open
564 file descriptors... */ 615 file descriptors... */
565 fprintf (stderr, "Socket number too large (%d > %u)\n", icmpsock, 616 fprintf (stderr,
617 "Socket number too large (%d > %u)\n",
618 icmpsock,
566 (unsigned int) FD_SETSIZE); 619 (unsigned int) FD_SETSIZE);
567 global_ret = 7; 620 global_ret = 7;
568 goto error_exit; 621 goto error_exit;
@@ -571,7 +624,9 @@ main (int argc, char *const *argv)
571 /* error checking rawsock */ 624 /* error checking rawsock */
572 if (-1 == rawsock) 625 if (-1 == rawsock)
573 { 626 {
574 fprintf (stderr, "Error opening RAW socket: %s\n", strerror (raw_eno)); 627 fprintf (stderr,
628 "Error opening RAW socket: %s\n",
629 strerror (raw_eno));
575 global_ret = 8; 630 global_ret = 8;
576 goto error_exit; 631 goto error_exit;
577 } 632 }
@@ -601,7 +656,9 @@ main (int argc, char *const *argv)
601 { 656 {
602 if (errno == EINTR) 657 if (errno == EINTR)
603 continue; 658 continue;
604 fprintf (stderr, "select failed: %s\n", strerror (errno)); 659 fprintf (stderr,
660 "select failed: %s\n",
661 strerror (errno));
605 break; 662 break;
606 } 663 }
607 if (1 == getppid ()) /* Check the parent process id, if 1 the parent has died, so we should die too */ 664 if (1 == getppid ()) /* Check the parent process id, if 1 the parent has died, so we should die too */
diff --git a/src/nat/gnunet-nat.c b/src/nat/gnunet-nat.c
index 4d0ed5723..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.
@@ -338,15 +339,11 @@ address_cb (void *cls,
338 * reversal. 339 * reversal.
339 * 340 *
340 * @param cls closure, NULL 341 * @param cls closure, NULL
341 * @param local_addr address where we received the request
342 * @param local_addrlen actual length of the @a local_addr
343 * @param remote_addr public IP address of the other peer 342 * @param remote_addr public IP address of the other peer
344 * @param remote_addrlen actual length of the @a remote_addr 343 * @param remote_addrlen actual length of the @a remote_addr
345 */ 344 */
346static void 345static void
347reversal_cb (void *cls, 346reversal_cb (void *cls,
348 const struct sockaddr *local_addr,
349 socklen_t local_addrlen,
350 const struct sockaddr *remote_addr, 347 const struct sockaddr *remote_addr,
351 socklen_t remote_addrlen) 348 socklen_t remote_addrlen)
352{ 349{
@@ -572,7 +569,7 @@ run (void *cls,
572 { 569 {
573 nh = GNUNET_NAT_register (c, 570 nh = GNUNET_NAT_register (c,
574 proto, 571 proto,
575 (uint16_t) adv_port, 572 hole_external,
576 1, 573 1,
577 (const struct sockaddr **) &local_sa, 574 (const struct sockaddr **) &local_sa,
578 &local_len, 575 &local_len,
@@ -580,6 +577,14 @@ run (void *cls,
580 (listen_reversal) ? &reversal_cb : NULL, 577 (listen_reversal) ? &reversal_cb : NULL,
581 NULL); 578 NULL);
582 } 579 }
580 else if (listen_reversal)
581 {
582 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
583 "Use of `-W` only effective in combination with `-i`\n");
584 global_ret = 1;
585 GNUNET_SCHEDULER_shutdown ();
586 return;
587 }
583 588
584 if (NULL != remote_addr) 589 if (NULL != remote_addr)
585 { 590 {
@@ -693,9 +698,9 @@ main (int argc,
693 {'r', "remote", "ADDRESS", 698 {'r', "remote", "ADDRESS",
694 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"),
695 GNUNET_YES, &GNUNET_GETOPT_set_string, &remote_addr }, 700 GNUNET_YES, &GNUNET_GETOPT_set_string, &remote_addr },
696 {'p', "port", NULL, 701 {'p', "punched", NULL,
697 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"),
698 GNUNET_YES, &GNUNET_GETOPT_set_uint, &adv_port }, 703 GNUNET_YES, &GNUNET_GETOPT_set_string, &hole_external },
699 {'s', "stun", NULL, 704 {'s', "stun", NULL,
700 gettext_noop ("enable STUN processing"), 705 gettext_noop ("enable STUN processing"),
701 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 762175437..e29f37108 100644
--- a/src/nat/gnunet-service-nat.c
+++ b/src/nat/gnunet-service-nat.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2016 GNUnet e.V. 3 Copyright (C) 2016, 2017 GNUnet e.V.
4 4
5 GNUnet is free software; you can redistribute it and/or modify 5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published 6 it under the terms of the GNU General Public License as published
@@ -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 */
@@ -176,6 +183,12 @@ struct LocalAddressList
176 struct LocalAddressList *prev; 183 struct LocalAddressList *prev;
177 184
178 /** 185 /**
186 * Context for a gnunet-helper-nat-server used to listen
187 * for ICMP messages to this client for connection reversal.
188 */
189 struct HelperContext *hc;
190
191 /**
179 * The address itself (i.e. `struct sockaddr_in` or `struct 192 * The address itself (i.e. `struct sockaddr_in` or `struct
180 * sockaddr_in6`, in the respective byte order). 193 * sockaddr_in6`, in the respective byte order).
181 */ 194 */
@@ -383,6 +396,31 @@ static struct in_addr mini_external_ipv4;
383 396
384 397
385/** 398/**
399 * Remove and free an entry from the #lal_head DLL.
400 *
401 * @param lal entry to free
402 */
403static void
404free_lal (struct LocalAddressList *lal)
405{
406 GNUNET_CONTAINER_DLL_remove (lal_head,
407 lal_tail,
408 lal);
409 if (NULL != lal->hc)
410 {
411 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
412 "Lost NATed local address %s, stopping NAT server\n",
413 GNUNET_a2s ((const struct sockaddr *) &lal->addr,
414 sizeof (struct sockaddr_in)));
415
416 GN_stop_gnunet_nat_server_ (lal->hc);
417 lal->hc = NULL;
418 }
419 GNUNET_free (lal);
420}
421
422
423/**
386 * Free the DLL starting at #lal_head. 424 * Free the DLL starting at #lal_head.
387 */ 425 */
388static void 426static void
@@ -391,12 +429,7 @@ destroy_lal ()
391 struct LocalAddressList *lal; 429 struct LocalAddressList *lal;
392 430
393 while (NULL != (lal = lal_head)) 431 while (NULL != (lal = lal_head))
394 { 432 free_lal (lal);
395 GNUNET_CONTAINER_DLL_remove (lal_head,
396 lal_tail,
397 lal);
398 GNUNET_free (lal);
399 }
400} 433}
401 434
402 435
@@ -448,7 +481,14 @@ check_register (void *cls,
448 GNUNET_break (0); 481 GNUNET_break (0);
449 return GNUNET_SYSERR; 482 return GNUNET_SYSERR;
450 } 483 }
451 } 484 off += alen;
485 left -= alen;
486 }
487 if (left != ntohs (message->hole_external_len))
488 {
489 GNUNET_break (0);
490 return GNUNET_SYSERR;
491 }
452 return GNUNET_OK; 492 return GNUNET_OK;
453} 493}
454 494
@@ -718,10 +758,12 @@ check_notify_client (struct LocalAddressList *delta,
718 GNUNET_memcpy (&v4, 758 GNUNET_memcpy (&v4,
719 &delta->addr, 759 &delta->addr,
720 alen); 760 alen);
761
762 /* Check for client notifications */
721 for (unsigned int i=0;i<ch->num_caddrs;i++) 763 for (unsigned int i=0;i<ch->num_caddrs;i++)
722 { 764 {
723 const struct sockaddr_in *c4; 765 const struct sockaddr_in *c4;
724 766
725 if (AF_INET != ch->caddrs[i].ss.ss_family) 767 if (AF_INET != ch->caddrs[i].ss.ss_family)
726 return; /* IPv4 not relevant */ 768 return; /* IPv4 not relevant */
727 c4 = (const struct sockaddr_in *) &ch->caddrs[i].ss; 769 c4 = (const struct sockaddr_in *) &ch->caddrs[i].ss;
@@ -857,40 +899,37 @@ check_notify_client_external_ipv4_change (const struct in_addr *v4,
857 int add) 899 int add)
858{ 900{
859 struct sockaddr_in sa; 901 struct sockaddr_in sa;
860 uint16_t port; 902 int have_v4;
861 uint16_t bport;
862 903
863 /* (1) check if client cares. */ 904 /* (1) check if client cares. */
864 if (! ch->natted_address) 905 if (! ch->natted_address)
865 return; 906 return;
866 if (0 == (GNUNET_NAT_RF_ADDRESSES & ch->flags)) 907 if (0 == (GNUNET_NAT_RF_ADDRESSES & ch->flags))
867 return; 908 return;
868 bport = 0; 909 have_v4 = GNUNET_NO;
869 for (unsigned int i=0;i<ch->num_caddrs;i++) 910 for (unsigned int i=0;i<ch->num_caddrs;i++)
870 { 911 {
871 const struct sockaddr_storage *ss = &ch->caddrs[i].ss; 912 const struct sockaddr_storage *ss = &ch->caddrs[i].ss;
872 913
873 if (AF_INET != ss->ss_family) 914 if (AF_INET != ss->ss_family)
874 continue; 915 continue;
875 bport = ntohs (((const struct sockaddr_in *) ss)->sin_port); 916 have_v4 = GNUNET_YES;
917 break;
876 } 918 }
877 if (0 == bport) 919 if (GNUNET_NO == have_v4)
878 return; /* IPv6-only */ 920 return; /* IPv6-only */
879 921
880 /* (2) figure out external port, build sockaddr */ 922 /* build address info */
881 port = ch->adv_port;
882 if (0 == port)
883 port = bport;
884 memset (&sa, 923 memset (&sa,
885 0, 924 0,
886 sizeof (sa)); 925 sizeof (sa));
887 sa.sin_family = AF_INET; 926 sa.sin_family = AF_INET;
888 sa.sin_addr = *v4; 927 sa.sin_addr = *v4;
889 sa.sin_port = htons (port); 928 sa.sin_port = htons (0);
890 929
891 /* (3) notify client of change */ 930 /* (3) notify client of change */
892 notify_client (is_nat_v4 (v4) 931 notify_client (is_nat_v4 (v4)
893 ? GNUNET_NAT_AC_EXTERN | GNUNET_NAT_AC_LAN_PRIVATE 932 ? GNUNET_NAT_AC_EXTERN | GNUNET_NAT_AC_LAN
894 : GNUNET_NAT_AC_EXTERN | GNUNET_NAT_AC_GLOBAL, 933 : GNUNET_NAT_AC_EXTERN | GNUNET_NAT_AC_GLOBAL,
895 ch, 934 ch,
896 add, 935 add,
@@ -1006,6 +1045,65 @@ run_external_ip (void *cls)
1006 1045
1007 1046
1008/** 1047/**
1048 * We got a connection reversal request from another peer.
1049 * Notify applicable clients.
1050 *
1051 * @param cls closure with the `struct LocalAddressList`
1052 * @param ra IP address of the peer who wants us to connect to it
1053 */
1054static void
1055reversal_callback (void *cls,
1056 const struct sockaddr_in *ra)
1057{
1058 struct LocalAddressList *lal = cls;
1059 const struct sockaddr_in *l4;
1060
1061 GNUNET_assert (AF_INET == lal->af);
1062 l4 = (const struct sockaddr_in *) &lal->addr;
1063 for (struct ClientHandle *ch = ch_head;
1064 NULL != ch;
1065 ch = ch->next)
1066 {
1067 struct GNUNET_NAT_ConnectionReversalRequestedMessage *crrm;
1068 struct GNUNET_MQ_Envelope *env;
1069 int match;
1070
1071 /* Check if client is in applicable range for ICMP NAT traversal
1072 for this local address */
1073 if (! ch->natted_address)
1074 continue;
1075 match = GNUNET_NO;
1076 for (unsigned int i=0;i<ch->num_caddrs;i++)
1077 {
1078 struct ClientAddress *ca = &ch->caddrs[i];
1079 const struct sockaddr_in *c4;
1080
1081 if (AF_INET != ca->ss.ss_family)
1082 continue;
1083 c4 = (const struct sockaddr_in *) &ca->ss;
1084 if ( (0 != c4->sin_addr.s_addr) &&
1085 (l4->sin_addr.s_addr != c4->sin_addr.s_addr) )
1086 continue;
1087 match = GNUNET_YES;
1088 break;
1089 }
1090 if (! match)
1091 continue;
1092
1093 /* Notify applicable client about connection reversal request */
1094 env = GNUNET_MQ_msg_extra (crrm,
1095 sizeof (struct sockaddr_in),
1096 GNUNET_MESSAGE_TYPE_NAT_CONNECTION_REVERSAL_REQUESTED);
1097 GNUNET_memcpy (&crrm[1],
1098 ra,
1099 sizeof (struct sockaddr_in));
1100 GNUNET_MQ_send (ch->mq,
1101 env);
1102 }
1103}
1104
1105
1106/**
1009 * Task we run periodically to scan for network interfaces. 1107 * Task we run periodically to scan for network interfaces.
1010 * 1108 *
1011 * @param cls NULL 1109 * @param cls NULL
@@ -1016,6 +1114,7 @@ run_scan (void *cls)
1016 struct IfcProcContext ifc_ctx; 1114 struct IfcProcContext ifc_ctx;
1017 int found; 1115 int found;
1018 int have_nat; 1116 int have_nat;
1117 struct LocalAddressList *lnext;
1019 1118
1020 scan_task = GNUNET_SCHEDULER_add_delayed (SCAN_FREQ, 1119 scan_task = GNUNET_SCHEDULER_add_delayed (SCAN_FREQ,
1021 &run_scan, 1120 &run_scan,
@@ -1028,8 +1127,9 @@ run_scan (void *cls)
1028 /* remove addresses that disappeared */ 1127 /* remove addresses that disappeared */
1029 for (struct LocalAddressList *lal = lal_head; 1128 for (struct LocalAddressList *lal = lal_head;
1030 NULL != lal; 1129 NULL != lal;
1031 lal = lal->next) 1130 lal = lnext)
1032 { 1131 {
1132 lnext = lal->next;
1033 found = GNUNET_NO; 1133 found = GNUNET_NO;
1034 for (struct LocalAddressList *pos = ifc_ctx.lal_head; 1134 for (struct LocalAddressList *pos = ifc_ctx.lal_head;
1035 NULL != pos; 1135 NULL != pos;
@@ -1041,18 +1141,23 @@ run_scan (void *cls)
1041 (AF_INET == lal->af) 1141 (AF_INET == lal->af)
1042 ? sizeof (struct sockaddr_in) 1142 ? sizeof (struct sockaddr_in)
1043 : sizeof (struct sockaddr_in6))) ) 1143 : sizeof (struct sockaddr_in6))) )
1144 {
1044 found = GNUNET_YES; 1145 found = GNUNET_YES;
1146 }
1045 } 1147 }
1046 if (GNUNET_NO == found) 1148 if (GNUNET_NO == found)
1149 {
1047 notify_clients (lal, 1150 notify_clients (lal,
1048 GNUNET_NO); 1151 GNUNET_NO);
1152 free_lal (lal);
1153 }
1049 } 1154 }
1050 1155
1051 /* add addresses that appeared */ 1156 /* add addresses that appeared */
1052 have_nat = GNUNET_NO; 1157 have_nat = GNUNET_NO;
1053 for (struct LocalAddressList *pos = ifc_ctx.lal_head; 1158 for (struct LocalAddressList *pos = ifc_ctx.lal_head;
1054 NULL != pos; 1159 NULL != pos;
1055 pos = pos->next) 1160 pos = ifc_ctx.lal_head)
1056 { 1161 {
1057 found = GNUNET_NO; 1162 found = GNUNET_NO;
1058 if (GNUNET_NAT_AC_LAN == (GNUNET_NAT_AC_LAN & pos->ac)) 1163 if (GNUNET_NAT_AC_LAN == (GNUNET_NAT_AC_LAN & pos->ac))
@@ -1069,9 +1174,35 @@ run_scan (void *cls)
1069 : sizeof (struct sockaddr_in6))) ) 1174 : sizeof (struct sockaddr_in6))) )
1070 found = GNUNET_YES; 1175 found = GNUNET_YES;
1071 } 1176 }
1072 if (GNUNET_NO == found) 1177 GNUNET_CONTAINER_DLL_remove (ifc_ctx.lal_head,
1178 ifc_ctx.lal_tail,
1179 pos);
1180 if (GNUNET_YES == found)
1181 {
1182 GNUNET_free (pos);
1183 }
1184 else
1185 {
1073 notify_clients (pos, 1186 notify_clients (pos,
1074 GNUNET_YES); 1187 GNUNET_YES);
1188 GNUNET_CONTAINER_DLL_insert (lal_head,
1189 lal_tail,
1190 pos);
1191 if ( (AF_INET == pos->af) &&
1192 (NULL == pos->hc) &&
1193 (0 != (GNUNET_NAT_AC_LAN & pos->ac)) )
1194 {
1195 const struct sockaddr_in *s4
1196 = (const struct sockaddr_in *) &pos->addr;
1197
1198 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
1199 "Found NATed local address %s, starting NAT server\n",
1200 GNUNET_a2s ((void *) &pos->addr, sizeof (*s4)));
1201 pos->hc = GN_start_gnunet_nat_server_ (&s4->sin_addr,
1202 &reversal_callback,
1203 pos);
1204 }
1205 }
1075 } 1206 }
1076 if ( (GNUNET_YES == have_nat) && 1207 if ( (GNUNET_YES == have_nat) &&
1077 (GNUNET_YES == enable_upnp) && 1208 (GNUNET_YES == enable_upnp) &&
@@ -1096,10 +1227,6 @@ run_scan (void *cls)
1096 probe_external_ip_op = NULL; 1227 probe_external_ip_op = NULL;
1097 } 1228 }
1098 } 1229 }
1099
1100 destroy_lal ();
1101 lal_head = ifc_ctx.lal_head;
1102 lal_tail = ifc_ctx.lal_tail;
1103} 1230}
1104 1231
1105 1232
@@ -1164,12 +1291,12 @@ upnp_addr_change_cb (void *cls,
1164 { 1291 {
1165 case AF_INET: 1292 case AF_INET:
1166 ac = is_nat_v4 (&((const struct sockaddr_in *) addr)->sin_addr) 1293 ac = is_nat_v4 (&((const struct sockaddr_in *) addr)->sin_addr)
1167 ? GNUNET_NAT_AC_LAN_PRIVATE 1294 ? GNUNET_NAT_AC_LAN
1168 : GNUNET_NAT_AC_EXTERN; 1295 : GNUNET_NAT_AC_EXTERN;
1169 break; 1296 break;
1170 case AF_INET6: 1297 case AF_INET6:
1171 ac = is_nat_v6 (&((const struct sockaddr_in6 *) addr)->sin6_addr) 1298 ac = is_nat_v6 (&((const struct sockaddr_in6 *) addr)->sin6_addr)
1172 ? GNUNET_NAT_AC_LAN_PRIVATE 1299 ? GNUNET_NAT_AC_LAN
1173 : GNUNET_NAT_AC_EXTERN; 1300 : GNUNET_NAT_AC_EXTERN;
1174 break; 1301 break;
1175 default: 1302 default:
@@ -1216,7 +1343,6 @@ handle_register (void *cls,
1216 "Received REGISTER message from client\n"); 1343 "Received REGISTER message from client\n");
1217 ch->flags = message->flags; 1344 ch->flags = message->flags;
1218 ch->proto = message->proto; 1345 ch->proto = message->proto;
1219 ch->adv_port = ntohs (message->adv_port);
1220 ch->num_caddrs = ntohs (message->num_addrs); 1346 ch->num_caddrs = ntohs (message->num_addrs);
1221 ch->caddrs = GNUNET_new_array (ch->num_caddrs, 1347 ch->caddrs = GNUNET_new_array (ch->num_caddrs,
1222 struct ClientAddress); 1348 struct ClientAddress);
@@ -1292,6 +1418,11 @@ handle_register (void *cls,
1292 1418
1293 off += alen; 1419 off += alen;
1294 } 1420 }
1421
1422 ch->hole_external
1423 = GNUNET_strndup (off,
1424 ntohs (message->hole_external_len));
1425
1295 /* Actually send IP address list to client */ 1426 /* Actually send IP address list to client */
1296 for (struct LocalAddressList *lal = lal_head; 1427 for (struct LocalAddressList *lal = lal_head;
1297 NULL != lal; 1428 NULL != lal;
@@ -1363,7 +1494,7 @@ notify_clients_stun_change (const struct sockaddr_in *ip,
1363 if (! ch->natted_address) 1494 if (! ch->natted_address)
1364 continue; 1495 continue;
1365 v4 = *ip; 1496 v4 = *ip;
1366 v4.sin_port = htons (ch->adv_port); 1497 v4.sin_port = htons (0);
1367 env = GNUNET_MQ_msg_extra (msg, 1498 env = GNUNET_MQ_msg_extra (msg,
1368 sizeof (v4), 1499 sizeof (v4),
1369 GNUNET_MESSAGE_TYPE_NAT_ADDRESS_CHANGE); 1500 GNUNET_MESSAGE_TYPE_NAT_ADDRESS_CHANGE);
@@ -2045,6 +2176,7 @@ client_disconnect_cb (void *cls,
2045 } 2176 }
2046 } 2177 }
2047 GNUNET_free_non_null (ch->caddrs); 2178 GNUNET_free_non_null (ch->caddrs);
2179 GNUNET_free (ch->hole_external);
2048 GNUNET_free (ch); 2180 GNUNET_free (ch);
2049} 2181}
2050 2182
diff --git a/src/nat/gnunet-service-nat_helper.c b/src/nat/gnunet-service-nat_helper.c
index 379603ae2..7e5051d65 100644
--- a/src/nat/gnunet-service-nat_helper.c
+++ b/src/nat/gnunet-service-nat_helper.c
@@ -28,7 +28,6 @@
28#include "gnunet_util_lib.h" 28#include "gnunet_util_lib.h"
29#include "gnunet-service-nat_helper.h" 29#include "gnunet-service-nat_helper.h"
30 30
31#define LOG(kind,...) GNUNET_log_from (kind, "nat", __VA_ARGS__)
32 31
33/** 32/**
34 * Information we keep per NAT helper process. 33 * Information we keep per NAT helper process.
@@ -39,7 +38,7 @@ struct HelperContext
39 /** 38 /**
40 * IP address we pass to the NAT helper. 39 * IP address we pass to the NAT helper.
41 */ 40 */
42 const char *internal_address; 41 struct in_addr internal_address;
43 42
44 /** 43 /**
45 * Function to call if we receive a reversal request. 44 * Function to call if we receive a reversal request.
@@ -133,11 +132,11 @@ nat_server_read (void *cls)
133 sizeof (mybuf)); 132 sizeof (mybuf));
134 if (bytes < 1) 133 if (bytes < 1)
135 { 134 {
136 LOG (GNUNET_ERROR_TYPE_DEBUG, 135 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
137 "Finished reading from server stdout with code: %d\n", 136 "Finished reading from server stdout with code: %d\n",
138 bytes); 137 bytes);
139 if (0 != GNUNET_OS_process_kill (h->server_proc, 138 if (0 != GNUNET_OS_process_kill (h->server_proc,
140- GNUNET_TERM_SIG)) 139 GNUNET_TERM_SIG))
141 GNUNET_log_from_strerror (GNUNET_ERROR_TYPE_WARNING, 140 GNUNET_log_from_strerror (GNUNET_ERROR_TYPE_WARNING,
142 "nat", 141 "nat",
143 "kill"); 142 "kill");
@@ -183,10 +182,9 @@ nat_server_read (void *cls)
183 &sin_addr.sin_addr))) 182 &sin_addr.sin_addr)))
184 { 183 {
185 /* should we restart gnunet-helper-nat-server? */ 184 /* should we restart gnunet-helper-nat-server? */
186 LOG (GNUNET_ERROR_TYPE_WARNING, 185 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
187 "nat", 186 _("gnunet-helper-nat-server generated malformed address `%s'\n"),
188 _("gnunet-helper-nat-server generated malformed address `%s'\n"), 187 mybuf);
189 mybuf);
190 h->server_read_task 188 h->server_read_task
191 = GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, 189 = GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
192 h->server_stdout_handle, 190 h->server_stdout_handle,
@@ -195,10 +193,10 @@ nat_server_read (void *cls)
195 return; 193 return;
196 } 194 }
197 sin_addr.sin_port = htons ((uint16_t) port); 195 sin_addr.sin_port = htons ((uint16_t) port);
198 LOG (GNUNET_ERROR_TYPE_DEBUG, 196 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
199 "gnunet-helper-nat-server read: %s:%d\n", 197 "gnunet-helper-nat-server read: %s:%d\n",
200 mybuf, 198 mybuf,
201 port); 199 port);
202 h->cb (h->cb_cls, 200 h->cb (h->cb_cls,
203 &sin_addr); 201 &sin_addr);
204 h->server_read_task 202 h->server_read_task
@@ -220,6 +218,7 @@ restart_nat_server (void *cls)
220{ 218{
221 struct HelperContext *h = cls; 219 struct HelperContext *h = cls;
222 char *binary; 220 char *binary;
221 char ia[INET_ADDRSTRLEN];
223 222
224 h->server_read_task = NULL; 223 h->server_read_task = NULL;
225 h->server_stdout 224 h->server_stdout
@@ -232,10 +231,15 @@ restart_nat_server (void *cls)
232 try_again (h); 231 try_again (h);
233 return; 232 return;
234 } 233 }
235 LOG (GNUNET_ERROR_TYPE_DEBUG, 234 GNUNET_assert (NULL !=
236 "Starting `%s' at `%s'\n", 235 inet_ntop (AF_INET,
237 "gnunet-helper-nat-server", 236 &h->internal_address,
238 h->internal_address); 237 ia,
238 sizeof (ia)));
239 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
240 "Starting `%s' at `%s'\n",
241 "gnunet-helper-nat-server",
242 ia);
239 /* Start the server process */ 243 /* Start the server process */
240 binary 244 binary
241 = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-nat-server"); 245 = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-nat-server");
@@ -247,15 +251,14 @@ restart_nat_server (void *cls)
247 NULL, 251 NULL,
248 binary, 252 binary,
249 "gnunet-helper-nat-server", 253 "gnunet-helper-nat-server",
250 h->internal_address, 254 ia,
251 NULL); 255 NULL);
252 GNUNET_free (binary); 256 GNUNET_free (binary);
253 if (NULL == h->server_proc) 257 if (NULL == h->server_proc)
254 { 258 {
255 LOG (GNUNET_ERROR_TYPE_WARNING, 259 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
256 "nat", 260 _("Failed to start %s\n"),
257 _("Failed to start %s\n"), 261 "gnunet-helper-nat-server");
258 "gnunet-helper-nat-server");
259 GNUNET_DISK_pipe_close (h->server_stdout); 262 GNUNET_DISK_pipe_close (h->server_stdout);
260 h->server_stdout = NULL; 263 h->server_stdout = NULL;
261 try_again (h); 264 try_again (h);
@@ -285,7 +288,7 @@ restart_nat_server (void *cls)
285 * @return NULL on error 288 * @return NULL on error
286 */ 289 */
287struct HelperContext * 290struct HelperContext *
288GN_start_gnunet_nat_server_ (const char *internal_address, 291GN_start_gnunet_nat_server_ (const struct in_addr *internal_address,
289 GN_ReversalCallback cb, 292 GN_ReversalCallback cb,
290 void *cb_cls) 293 void *cb_cls)
291{ 294{
@@ -294,8 +297,8 @@ GN_start_gnunet_nat_server_ (const char *internal_address,
294 h = GNUNET_new (struct HelperContext); 297 h = GNUNET_new (struct HelperContext);
295 h->cb = cb; 298 h->cb = cb;
296 h->cb_cls = cb_cls; 299 h->cb_cls = cb_cls;
297 h->internal_address 300 h->internal_address = *internal_address;
298 = internal_address; 301 restart_nat_server (h);
299 if (NULL == h->server_stdout) 302 if (NULL == h->server_stdout)
300 { 303 {
301 GN_stop_gnunet_nat_server_ (h); 304 GN_stop_gnunet_nat_server_ (h);
@@ -323,9 +326,8 @@ GN_stop_gnunet_nat_server_ (struct HelperContext *h)
323 { 326 {
324 if (0 != GNUNET_OS_process_kill (h->server_proc, 327 if (0 != GNUNET_OS_process_kill (h->server_proc,
325 GNUNET_TERM_SIG)) 328 GNUNET_TERM_SIG))
326 GNUNET_log_from_strerror (GNUNET_ERROR_TYPE_WARNING, 329 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
327 "nat", 330 "kill");
328 "kill");
329 GNUNET_OS_process_wait (h->server_proc); 331 GNUNET_OS_process_wait (h->server_proc);
330 GNUNET_OS_process_destroy (h->server_proc); 332 GNUNET_OS_process_destroy (h->server_proc);
331 h->server_proc = NULL; 333 h->server_proc = NULL;
@@ -370,9 +372,8 @@ GN_request_connection_reversal (const struct in_addr *internal_address,
370 intv4, 372 intv4,
371 INET_ADDRSTRLEN)) 373 INET_ADDRSTRLEN))
372 { 374 {
373 GNUNET_log_from_strerror (GNUNET_ERROR_TYPE_WARNING, 375 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
374 "nat", 376 "inet_ntop");
375 "inet_ntop");
376 return GNUNET_SYSERR; 377 return GNUNET_SYSERR;
377 } 378 }
378 if (NULL == inet_ntop (AF_INET, 379 if (NULL == inet_ntop (AF_INET,
@@ -380,20 +381,19 @@ GN_request_connection_reversal (const struct in_addr *internal_address,
380 remv4, 381 remv4,
381 INET_ADDRSTRLEN)) 382 INET_ADDRSTRLEN))
382 { 383 {
383 GNUNET_log_from_strerror (GNUNET_ERROR_TYPE_WARNING, 384 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
384 "nat", 385 "inet_ntop");
385 "inet_ntop");
386 return GNUNET_SYSERR; 386 return GNUNET_SYSERR;
387 } 387 }
388 GNUNET_snprintf (port_as_string, 388 GNUNET_snprintf (port_as_string,
389 sizeof (port_as_string), 389 sizeof (port_as_string),
390 "%d", 390 "%d",
391 internal_port); 391 internal_port);
392 LOG (GNUNET_ERROR_TYPE_DEBUG, 392 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
393 _("Running gnunet-helper-nat-client %s %s %u\n"), 393 _("Running gnunet-helper-nat-client %s %s %u\n"),
394 intv4, 394 intv4,
395 remv4, 395 remv4,
396 internal_port); 396 internal_port);
397 binary 397 binary
398 = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-nat-client"); 398 = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-nat-client");
399 proc 399 proc
diff --git a/src/nat/gnunet-service-nat_helper.h b/src/nat/gnunet-service-nat_helper.h
index d3f1a757c..026526b05 100644
--- a/src/nat/gnunet-service-nat_helper.h
+++ b/src/nat/gnunet-service-nat_helper.h
@@ -56,7 +56,7 @@ typedef void
56 * @return NULL on error 56 * @return NULL on error
57 */ 57 */
58struct HelperContext * 58struct HelperContext *
59GN_start_gnunet_nat_server_ (const char *internal_address, 59GN_start_gnunet_nat_server_ (const struct in_addr *internal_address,
60 GN_ReversalCallback cb, 60 GN_ReversalCallback cb,
61 void *cb_cls); 61 void *cb_cls);
62 62
diff --git a/src/nat/nat.h b/src/nat/nat.h
index 3356b19ce..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
@@ -191,19 +195,7 @@ struct GNUNET_NAT_ConnectionReversalRequestedMessage
191 */ 195 */
192 struct GNUNET_MessageHeader header; 196 struct GNUNET_MessageHeader header;
193 197
194 /** 198 /* followed by a `struct sockaddr_in` */
195 * Size of the local address where we received the request, in NBO.
196 */
197 uint16_t local_addr_size;
198
199 /**
200 * Size of the remote address making the request, in NBO.
201 */
202 uint16_t remote_addr_size;
203
204 /* followed by a `struct sockaddr` of @e local_addr_size bytes */
205
206 /* followed by a `struct sockaddr` of @e remote_addr_size bytes */
207 199
208}; 200};
209 201
diff --git a/src/nat/nat_api.c b/src/nat/nat_api.c
index 481bc6fde..e4dfc1629 100644
--- a/src/nat/nat_api.c
+++ b/src/nat/nat_api.c
@@ -176,14 +176,7 @@ check_connection_reversal_request (void *cls,
176{ 176{
177 if (ntohs (crm->header.size) != 177 if (ntohs (crm->header.size) !=
178 sizeof (*crm) + 178 sizeof (*crm) +
179 ntohs (crm->local_addr_size) + 179 sizeof (struct sockaddr_in) )
180 ntohs (crm->remote_addr_size) )
181 {
182 GNUNET_break (0);
183 return GNUNET_SYSERR;
184 }
185 if ( (sizeof (struct sockaddr_in) != ntohs (crm->local_addr_size)) ||
186 (sizeof (struct sockaddr_in) != ntohs (crm->remote_addr_size)) )
187 { 180 {
188 GNUNET_break (0); 181 GNUNET_break (0);
189 return GNUNET_SYSERR; 182 return GNUNET_SYSERR;
@@ -203,13 +196,9 @@ handle_connection_reversal_request (void *cls,
203 const struct GNUNET_NAT_ConnectionReversalRequestedMessage *crm) 196 const struct GNUNET_NAT_ConnectionReversalRequestedMessage *crm)
204{ 197{
205 struct GNUNET_NAT_Handle *nh = cls; 198 struct GNUNET_NAT_Handle *nh = cls;
206 const struct sockaddr_in *local_sa = (const struct sockaddr_in *) &crm[1];
207 const struct sockaddr_in *remote_sa = &local_sa[1];
208 199
209 nh->reversal_callback (nh->callback_cls, 200 nh->reversal_callback (nh->callback_cls,
210 (const struct sockaddr *) local_sa, 201 (const struct sockaddr *) &crm[1],
211 sizeof (struct sockaddr_in),
212 (const struct sockaddr *) remote_sa,
213 sizeof (struct sockaddr_in)); 202 sizeof (struct sockaddr_in));
214} 203}
215 204
@@ -380,8 +369,7 @@ do_connect (void *cls)
380 * 369 *
381 * @param cfg configuration to use 370 * @param cfg configuration to use
382 * @param proto protocol this is about, IPPROTO_TCP or IPPROTO_UDP 371 * @param proto protocol this is about, IPPROTO_TCP or IPPROTO_UDP
383 * @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)
384 * locally performs redirection from to our bound port).
385 * @param num_addrs number of addresses in @a addrs 373 * @param num_addrs number of addresses in @a addrs
386 * @param addrs list of local addresses packets should be redirected to 374 * @param addrs list of local addresses packets should be redirected to
387 * @param addrlens actual lengths of the addresses in @a addrs 375 * @param addrlens actual lengths of the addresses in @a addrs
@@ -394,7 +382,7 @@ do_connect (void *cls)
394struct GNUNET_NAT_Handle * 382struct GNUNET_NAT_Handle *
395GNUNET_NAT_register (const struct GNUNET_CONFIGURATION_Handle *cfg, 383GNUNET_NAT_register (const struct GNUNET_CONFIGURATION_Handle *cfg,
396 uint8_t proto, 384 uint8_t proto,
397 uint16_t adv_port, 385 const char *hole_external,
398 unsigned int num_addrs, 386 unsigned int num_addrs,
399 const struct sockaddr **addrs, 387 const struct sockaddr **addrs,
400 const socklen_t *addrlens, 388 const socklen_t *addrlens,
@@ -405,11 +393,17 @@ GNUNET_NAT_register (const struct GNUNET_CONFIGURATION_Handle *cfg,
405 struct GNUNET_NAT_Handle *nh; 393 struct GNUNET_NAT_Handle *nh;
406 struct GNUNET_NAT_RegisterMessage *rm; 394 struct GNUNET_NAT_RegisterMessage *rm;
407 size_t len; 395 size_t len;
396 size_t hole_external_len;
408 char *off; 397 char *off;
409 398
410 len = 0; 399 len = 0;
411 for (unsigned int i=0;i<num_addrs;i++) 400 for (unsigned int i=0;i<num_addrs;i++)
412 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;
413 if ( (len > GNUNET_SERVER_MAX_MESSAGE_SIZE - sizeof (*rm)) || 407 if ( (len > GNUNET_SERVER_MAX_MESSAGE_SIZE - sizeof (*rm)) ||
414 (num_addrs > UINT16_MAX) ) 408 (num_addrs > UINT16_MAX) )
415 { 409 {
@@ -425,7 +419,7 @@ GNUNET_NAT_register (const struct GNUNET_CONFIGURATION_Handle *cfg,
425 if (NULL != reversal_callback) 419 if (NULL != reversal_callback)
426 rm->flags |= GNUNET_NAT_RF_REVERSAL; 420 rm->flags |= GNUNET_NAT_RF_REVERSAL;
427 rm->proto = proto; 421 rm->proto = proto;
428 rm->adv_port = htons (adv_port); 422 rm->hole_external_len = htons (hole_external_len);
429 rm->num_addrs = htons ((uint16_t) num_addrs); 423 rm->num_addrs = htons ((uint16_t) num_addrs);
430 off = (char *) &rm[1]; 424 off = (char *) &rm[1];
431 for (unsigned int i=0;i<num_addrs;i++) 425 for (unsigned int i=0;i<num_addrs;i++)
@@ -464,6 +458,9 @@ GNUNET_NAT_register (const struct GNUNET_CONFIGURATION_Handle *cfg,
464 addrlens[i]); 458 addrlens[i]);
465 off += addrlens[i]; 459 off += addrlens[i];
466 } 460 }
461 GNUNET_memcpy (off,
462 hole_external,
463 hole_external_len);
467 464
468 nh = GNUNET_new (struct GNUNET_NAT_Handle); 465 nh = GNUNET_new (struct GNUNET_NAT_Handle);
469 nh->reg = &rm->header; 466 nh->reg = &rm->header;