diff options
-rw-r--r-- | doc/man/gnunet-nat.1 | 10 | ||||
-rw-r--r-- | src/gns/gnunet-gns-proxy.c | 3 | ||||
-rw-r--r-- | src/include/gnunet_nat_service.h | 9 | ||||
-rw-r--r-- | src/nat/gnunet-helper-nat-server.c | 115 | ||||
-rw-r--r-- | src/nat/gnunet-nat.c | 25 | ||||
-rw-r--r-- | src/nat/gnunet-service-nat.c | 210 | ||||
-rw-r--r-- | src/nat/gnunet-service-nat_helper.c | 80 | ||||
-rw-r--r-- | src/nat/gnunet-service-nat_helper.h | 2 | ||||
-rw-r--r-- | src/nat/nat.h | 24 | ||||
-rw-r--r-- | src/nat/nat_api.c | 31 |
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. | |||
39 | Ask the peer at ADDRESS for connection reversal, using the local address for the target address of the reversal. | 39 | Ask 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" |
43 | Use PORT as our external port for advertising for incoming requests. | 43 | A 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 | |||
94 | Assume 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 | ||
94 | XXX: | 100 | XXX: |
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 | */ |
163 | typedef void | 161 | typedef 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; | |||
198 | struct GNUNET_NAT_Handle * | 193 | struct GNUNET_NAT_Handle * |
199 | GNUNET_NAT_register (const struct GNUNET_CONFIGURATION_Handle *cfg, | 194 | GNUNET_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 | ||
494 | int | 531 | int |
495 | main (int argc, char *const *argv) | 532 | main (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; | |||
39 | static struct GNUNET_NAT_AutoHandle *ah; | 39 | static 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 | */ |
44 | static unsigned int adv_port; | 45 | static 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 | */ |
346 | static void | 345 | static void |
347 | reversal_cb (void *cls, | 346 | reversal_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 | */ | ||
403 | static void | ||
404 | free_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 | */ |
388 | static void | 426 | static 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 | */ | ||
1054 | static void | ||
1055 | reversal_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 | */ |
287 | struct HelperContext * | 290 | struct HelperContext * |
288 | GN_start_gnunet_nat_server_ (const char *internal_address, | 291 | GN_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 | */ |
58 | struct HelperContext * | 58 | struct HelperContext * |
59 | GN_start_gnunet_nat_server_ (const char *internal_address, | 59 | GN_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) | |||
394 | struct GNUNET_NAT_Handle * | 382 | struct GNUNET_NAT_Handle * |
395 | GNUNET_NAT_register (const struct GNUNET_CONFIGURATION_Handle *cfg, | 383 | GNUNET_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; |