aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSchanzenbach, Martin <mschanzenbach@posteo.de>2017-01-04 12:46:29 +0100
committerSchanzenbach, Martin <mschanzenbach@posteo.de>2017-01-04 12:46:29 +0100
commit7122f35e2c00c29b1af31bdd294e93e6fcc84498 (patch)
tree2d352c38d227d6c44d525efdbfd7324e4cec5015 /src
parent3c1b722a8778b9f1f2b7564d3d2709f220e96547 (diff)
parent60c6dfd1fe22a01a3f7723e7e2bb18d52895c527 (diff)
downloadgnunet-7122f35e2c00c29b1af31bdd294e93e6fcc84498.tar.gz
gnunet-7122f35e2c00c29b1af31bdd294e93e6fcc84498.zip
Merge remote-tracking branch 'origin/master' into credentials
Diffstat (limited to 'src')
-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
9 files changed, 339 insertions, 160 deletions
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;