diff options
author | Christian Grothoff <christian@grothoff.org> | 2011-06-25 06:24:01 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2011-06-25 06:24:01 +0000 |
commit | 8a3016481ba6aeb36de3950a56e641dda53ca544 (patch) | |
tree | 0c5468ec6e5d2165ad5931940e0b8439d09398de /src/transport/plugin_transport_tcp.c | |
parent | b6d4eeb39fd0cd41df164bd0959f58b08aa45e83 (diff) | |
download | gnunet-8a3016481ba6aeb36de3950a56e641dda53ca544.tar.gz gnunet-8a3016481ba6aeb36de3950a56e641dda53ca544.zip |
the big NAT change
Diffstat (limited to 'src/transport/plugin_transport_tcp.c')
-rw-r--r-- | src/transport/plugin_transport_tcp.c | 1259 |
1 files changed, 99 insertions, 1160 deletions
diff --git a/src/transport/plugin_transport_tcp.c b/src/transport/plugin_transport_tcp.c index 491c536ca..a8eee970c 100644 --- a/src/transport/plugin_transport_tcp.c +++ b/src/transport/plugin_transport_tcp.c | |||
@@ -38,15 +38,10 @@ | |||
38 | #include "gnunet_transport_plugin.h" | 38 | #include "gnunet_transport_plugin.h" |
39 | #include "transport.h" | 39 | #include "transport.h" |
40 | 40 | ||
41 | #define DEBUG_TCP GNUNET_NO | 41 | #define DEBUG_TCP GNUNET_YES |
42 | 42 | ||
43 | #define DEBUG_TCP_NAT GNUNET_YES | 43 | #define DEBUG_TCP_NAT GNUNET_YES |
44 | 44 | ||
45 | /** | ||
46 | * How long until we give up on transmitting the welcome message? | ||
47 | */ | ||
48 | #define HOSTNAME_RESOLVE_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5) | ||
49 | |||
50 | 45 | ||
51 | /** | 46 | /** |
52 | * Initial handshake message for a session. | 47 | * Initial handshake message for a session. |
@@ -136,7 +131,7 @@ struct IPv4TcpAddress | |||
136 | /** | 131 | /** |
137 | * Port number, in network byte order. | 132 | * Port number, in network byte order. |
138 | */ | 133 | */ |
139 | uint16_t t_port GNUNET_PACKED; | 134 | uint16_t t4_port GNUNET_PACKED; |
140 | 135 | ||
141 | }; | 136 | }; |
142 | 137 | ||
@@ -166,52 +161,6 @@ struct Plugin; | |||
166 | 161 | ||
167 | 162 | ||
168 | /** | 163 | /** |
169 | * Local network addresses (actual IP address follows this struct). | ||
170 | * PORT is NOT included! | ||
171 | */ | ||
172 | struct LocalAddrList | ||
173 | { | ||
174 | |||
175 | /** | ||
176 | * This is a doubly linked list. | ||
177 | */ | ||
178 | struct LocalAddrList *next; | ||
179 | |||
180 | /** | ||
181 | * This is a doubly linked list. | ||
182 | */ | ||
183 | struct LocalAddrList *prev; | ||
184 | |||
185 | /** | ||
186 | * Link to plugin. | ||
187 | */ | ||
188 | struct Plugin *plugin; | ||
189 | |||
190 | /** | ||
191 | * Handle to NAT holes we've tried to punch for this address. | ||
192 | */ | ||
193 | struct GNUNET_NAT_Handle *nat; | ||
194 | |||
195 | /** | ||
196 | * Pointer to a 'struct IPv4/V6TcpAddress' describing our external IP and port | ||
197 | * as obtained from the NAT by automatic port mapping. | ||
198 | */ | ||
199 | void *external_nat_address; | ||
200 | |||
201 | /** | ||
202 | * Number of bytes in 'external_nat_address' | ||
203 | */ | ||
204 | size_t ena_size; | ||
205 | |||
206 | /** | ||
207 | * Number of bytes of the address that follow | ||
208 | */ | ||
209 | size_t size; | ||
210 | |||
211 | }; | ||
212 | |||
213 | |||
214 | /** | ||
215 | * Information kept for each message that is yet to | 164 | * Information kept for each message that is yet to |
216 | * be transmitted. | 165 | * be transmitted. |
217 | */ | 166 | */ |
@@ -365,24 +314,9 @@ struct Plugin | |||
365 | struct GNUNET_CONNECTION_Handle *lsock; | 314 | struct GNUNET_CONNECTION_Handle *lsock; |
366 | 315 | ||
367 | /** | 316 | /** |
368 | * stdout pipe handle for the gnunet-nat-server process | 317 | * Our handle to the NAT module. |
369 | */ | ||
370 | struct GNUNET_DISK_PipeHandle *server_stdout; | ||
371 | |||
372 | /** | ||
373 | * stdout file handle (for reading) for the gnunet-nat-server process | ||
374 | */ | 318 | */ |
375 | const struct GNUNET_DISK_FileHandle *server_stdout_handle; | 319 | struct GNUNET_NAT_Handle *nat; |
376 | |||
377 | /** | ||
378 | * ID of select gnunet-nat-server stdout read task | ||
379 | */ | ||
380 | GNUNET_SCHEDULER_TaskIdentifier server_read_task; | ||
381 | |||
382 | /** | ||
383 | * The process id of the server process (if behind NAT) | ||
384 | */ | ||
385 | struct GNUNET_OS_Process *server_proc; | ||
386 | 320 | ||
387 | /** | 321 | /** |
388 | * List of open TCP sessions. | 322 | * List of open TCP sessions. |
@@ -406,48 +340,10 @@ struct Plugin | |||
406 | struct GNUNET_SERVER_MessageHandler *handlers; | 340 | struct GNUNET_SERVER_MessageHandler *handlers; |
407 | 341 | ||
408 | /** | 342 | /** |
409 | * Handle for request of hostname resolution, non-NULL if pending. | ||
410 | */ | ||
411 | struct GNUNET_RESOLVER_RequestHandle *hostname_dns; | ||
412 | |||
413 | /** | ||
414 | * Map of peers we have tried to contact behind a NAT | 343 | * Map of peers we have tried to contact behind a NAT |
415 | */ | 344 | */ |
416 | struct GNUNET_CONTAINER_MultiHashMap *nat_wait_conns; | 345 | struct GNUNET_CONTAINER_MultiHashMap *nat_wait_conns; |
417 | 346 | ||
418 | /** | ||
419 | * The external address given to us by the user. Used for HELLOs | ||
420 | * and address validation. | ||
421 | */ | ||
422 | char *external_address; | ||
423 | |||
424 | /** | ||
425 | * The internal address given to us by the user (or discovered). | ||
426 | * Used for NAT traversal (ICMP method), but not as a 'validateable' | ||
427 | * address in HELLOs. | ||
428 | */ | ||
429 | char *internal_address; | ||
430 | |||
431 | /** | ||
432 | * Address given for us to bind to (ONLY). | ||
433 | */ | ||
434 | char *bind_address; | ||
435 | |||
436 | /** | ||
437 | * use local addresses? | ||
438 | */ | ||
439 | int use_localaddresses; | ||
440 | |||
441 | /** | ||
442 | * List of our IP addresses. | ||
443 | */ | ||
444 | struct LocalAddrList *lal_head; | ||
445 | |||
446 | /** | ||
447 | * Tail of our IP address list. | ||
448 | */ | ||
449 | struct LocalAddrList *lal_tail; | ||
450 | |||
451 | /** | 347 | /** |
452 | * List of active TCP probes. | 348 | * List of active TCP probes. |
453 | */ | 349 | */ |
@@ -484,31 +380,6 @@ struct Plugin | |||
484 | */ | 380 | */ |
485 | uint16_t adv_port; | 381 | uint16_t adv_port; |
486 | 382 | ||
487 | /** | ||
488 | * Is this transport configured to be behind a NAT? | ||
489 | */ | ||
490 | int behind_nat; | ||
491 | |||
492 | /** | ||
493 | * Has the NAT been punched? | ||
494 | */ | ||
495 | int nat_punched; | ||
496 | |||
497 | /** | ||
498 | * Is this transport configured to allow connections to NAT'd peers? | ||
499 | */ | ||
500 | int enable_nat_client; | ||
501 | |||
502 | /** | ||
503 | * Should we run the gnunet-nat-server? | ||
504 | */ | ||
505 | int enable_nat_server; | ||
506 | |||
507 | /** | ||
508 | * Are we allowed to try UPnP/PMP for NAT traversal? | ||
509 | */ | ||
510 | int enable_upnp; | ||
511 | |||
512 | }; | 383 | }; |
513 | 384 | ||
514 | 385 | ||
@@ -549,30 +420,34 @@ plugin_tcp_access_check (void *cls, | |||
549 | * @param addrlen actual lenght of the address | 420 | * @param addrlen actual lenght of the address |
550 | */ | 421 | */ |
551 | static void | 422 | static void |
552 | nat_port_map_callback (void *cls, | 423 | tcp_nat_port_map_callback (void *cls, |
553 | int add_remove, | 424 | int add_remove, |
554 | const struct sockaddr *addr, | 425 | const struct sockaddr *addr, |
555 | socklen_t addrlen) | 426 | socklen_t addrlen) |
556 | { | 427 | { |
557 | struct LocalAddrList *lal = cls; | 428 | struct Plugin *plugin = cls; |
558 | struct Plugin *plugin = lal->plugin; | ||
559 | int af; | ||
560 | struct IPv4TcpAddress t4; | 429 | struct IPv4TcpAddress t4; |
561 | struct IPv6TcpAddress t6; | 430 | struct IPv6TcpAddress t6; |
562 | void *arg; | 431 | void *arg; |
563 | uint16_t args; | 432 | size_t args; |
564 | 433 | ||
434 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, | ||
435 | "tcp", | ||
436 | "NPMC called with %d for address `%s'\n", | ||
437 | add_remove, | ||
438 | GNUNET_a2s (addr, addrlen)); | ||
565 | /* convert 'addr' to our internal format */ | 439 | /* convert 'addr' to our internal format */ |
566 | af = addr->sa_family; | 440 | switch (addr->sa_family) |
567 | switch (af) | ||
568 | { | 441 | { |
569 | case AF_INET: | 442 | case AF_INET: |
443 | GNUNET_assert (addrlen == sizeof (struct sockaddr_in)); | ||
570 | t4.ipv4_addr = ((struct sockaddr_in *) addr)->sin_addr.s_addr; | 444 | t4.ipv4_addr = ((struct sockaddr_in *) addr)->sin_addr.s_addr; |
571 | t4.t_port = ((struct sockaddr_in *) addr)->sin_port; | 445 | t4.t4_port = ((struct sockaddr_in *) addr)->sin_port; |
572 | arg = &t4; | 446 | arg = &t4; |
573 | args = sizeof (t4); | 447 | args = sizeof (t4); |
574 | break; | 448 | break; |
575 | case AF_INET6: | 449 | case AF_INET6: |
450 | GNUNET_assert (addrlen == sizeof (struct sockaddr_in6)); | ||
576 | memcpy (&t6.ipv6_addr, | 451 | memcpy (&t6.ipv6_addr, |
577 | &((struct sockaddr_in6 *) addr)->sin6_addr, | 452 | &((struct sockaddr_in6 *) addr)->sin6_addr, |
578 | sizeof (struct in6_addr)); | 453 | sizeof (struct in6_addr)); |
@@ -583,154 +458,11 @@ nat_port_map_callback (void *cls, | |||
583 | default: | 458 | default: |
584 | GNUNET_break (0); | 459 | GNUNET_break (0); |
585 | return; | 460 | return; |
586 | } | ||
587 | |||
588 | /* modify our published address list */ | ||
589 | if (GNUNET_YES == add_remove) | ||
590 | { | ||
591 | plugin->env->notify_address (plugin->env->cls, | ||
592 | "tcp", | ||
593 | arg, args, GNUNET_TIME_UNIT_FOREVER_REL); | ||
594 | GNUNET_free_non_null (lal->external_nat_address); | ||
595 | lal->external_nat_address = GNUNET_memdup (arg, args); | ||
596 | lal->ena_size = args; | ||
597 | } | ||
598 | else | ||
599 | { | ||
600 | plugin->env->notify_address (plugin->env->cls, | ||
601 | "tcp", | ||
602 | arg, args, GNUNET_TIME_UNIT_ZERO); | ||
603 | GNUNET_free_non_null (lal->external_nat_address); | ||
604 | lal->ena_size = 0; | ||
605 | } | ||
606 | } | ||
607 | |||
608 | |||
609 | /** | ||
610 | * Add the given address to the list of 'local' addresses, thereby | ||
611 | * making it a 'legal' address for this peer to have. | ||
612 | * | ||
613 | * @param plugin the plugin | ||
614 | * @param arg the address, either an IPv4 or an IPv6 IP address | ||
615 | * @param arg_size number of bytes in arg | ||
616 | */ | ||
617 | static void | ||
618 | add_to_address_list (struct Plugin *plugin, | ||
619 | const void *arg, | ||
620 | size_t arg_size) | ||
621 | { | ||
622 | struct LocalAddrList *lal; | ||
623 | struct sockaddr_in v4; | ||
624 | struct sockaddr_in6 v6; | ||
625 | const struct sockaddr *sa; | ||
626 | socklen_t salen; | ||
627 | |||
628 | lal = plugin->lal_head; | ||
629 | while (NULL != lal) | ||
630 | { | ||
631 | if ( (lal->size == arg_size) && | ||
632 | (0 == memcmp (&lal[1], arg, arg_size)) ) | ||
633 | return; | ||
634 | lal = lal->next; | ||
635 | } | ||
636 | lal = GNUNET_malloc (sizeof (struct LocalAddrList) + arg_size); | ||
637 | lal->plugin = plugin; | ||
638 | lal->size = arg_size; | ||
639 | memcpy (&lal[1], arg, arg_size); | ||
640 | GNUNET_CONTAINER_DLL_insert (plugin->lal_head, | ||
641 | plugin->lal_tail, | ||
642 | lal); | ||
643 | if (plugin->open_port == 0) | ||
644 | return; /* we're not listening at all... */ | ||
645 | if (arg_size == sizeof (struct in_addr)) | ||
646 | { | ||
647 | memset (&v4, 0, sizeof (v4)); | ||
648 | v4.sin_family = AF_INET; | ||
649 | v4.sin_port = htons (plugin->open_port); | ||
650 | memcpy (&v4.sin_addr, arg, arg_size); | ||
651 | #if HAVE_SOCKADDR_IN_SIN_LEN | ||
652 | v4.sin_len = sizeof (struct sockaddr_in); | ||
653 | #endif | ||
654 | sa = (const struct sockaddr*) &v4; | ||
655 | salen = sizeof (v4); | ||
656 | } | ||
657 | else if (arg_size == sizeof (struct in6_addr)) | ||
658 | { | ||
659 | memset (&v6, 0, sizeof (v6)); | ||
660 | v6.sin6_family = AF_INET6; | ||
661 | v6.sin6_port = htons (plugin->open_port); | ||
662 | memcpy (&v6.sin6_addr, arg, arg_size); | ||
663 | #if HAVE_SOCKADDR_IN_SIN_LEN | ||
664 | v6.sin6_len = sizeof (struct sockaddr_in6); | ||
665 | #endif | ||
666 | sa = (const struct sockaddr*) &v6; | ||
667 | salen = sizeof (v6); | ||
668 | } | ||
669 | else | ||
670 | { | ||
671 | GNUNET_break (0); | ||
672 | return; | ||
673 | } | 461 | } |
674 | if ( (plugin->behind_nat == GNUNET_YES) && | 462 | /* modify our published address list */ |
675 | (plugin->enable_upnp == GNUNET_YES) ) | 463 | plugin->env->notify_address (plugin->env->cls, |
676 | lal->nat = GNUNET_NAT_register (plugin->env->cfg, | 464 | add_remove, |
677 | sa, salen, | 465 | arg, args); |
678 | &nat_port_map_callback, | ||
679 | lal); | ||
680 | } | ||
681 | |||
682 | |||
683 | /** | ||
684 | * Check if the given address is in the list of 'local' addresses. | ||
685 | * | ||
686 | * @param plugin the plugin | ||
687 | * @param arg the address, either an IPv4 or an IPv6 IP address | ||
688 | * @param arg_size number of bytes in arg | ||
689 | * @return GNUNET_OK if this is one of our IPs, GNUNET_SYSERR if not | ||
690 | */ | ||
691 | static int | ||
692 | check_local_addr (struct Plugin *plugin, | ||
693 | const void *arg, | ||
694 | size_t arg_size) | ||
695 | { | ||
696 | struct LocalAddrList *lal; | ||
697 | |||
698 | lal = plugin->lal_head; | ||
699 | while (NULL != lal) | ||
700 | { | ||
701 | if ( (lal->size == arg_size) && | ||
702 | (0 == memcmp (&lal[1], arg, arg_size)) ) | ||
703 | return GNUNET_OK; | ||
704 | lal = lal->next; | ||
705 | } | ||
706 | return GNUNET_SYSERR; | ||
707 | } | ||
708 | |||
709 | |||
710 | /** | ||
711 | * Check if the given address is in the list of 'mapped' addresses. | ||
712 | * | ||
713 | * @param plugin the plugin | ||
714 | * @param arg the address, either a 'struct IPv4TcpAddress' or a 'struct IPv6TcpAddress' | ||
715 | * @param arg_size number of bytes in arg | ||
716 | * @return GNUNET_OK if this is one of our IPs, GNUNET_SYSERR if not | ||
717 | */ | ||
718 | static int | ||
719 | check_mapped_addr (struct Plugin *plugin, | ||
720 | const void *arg, | ||
721 | size_t arg_size) | ||
722 | { | ||
723 | struct LocalAddrList *lal; | ||
724 | |||
725 | lal = plugin->lal_head; | ||
726 | while (NULL != lal) | ||
727 | { | ||
728 | if ( (lal->ena_size == arg_size) && | ||
729 | (0 == memcmp (lal->external_nat_address, arg, arg_size)) ) | ||
730 | return GNUNET_OK; | ||
731 | lal = lal->next; | ||
732 | } | ||
733 | return GNUNET_SYSERR; | ||
734 | } | 466 | } |
735 | 467 | ||
736 | 468 | ||
@@ -772,7 +504,7 @@ tcp_address_to_string (void *cls, | |||
772 | { | 504 | { |
773 | t4 = addr; | 505 | t4 = addr; |
774 | af = AF_INET; | 506 | af = AF_INET; |
775 | port = ntohs (t4->t_port); | 507 | port = ntohs (t4->t4_port); |
776 | memcpy (&a4, &t4->ipv4_addr, sizeof (a4)); | 508 | memcpy (&a4, &t4->ipv4_addr, sizeof (a4)); |
777 | sb = &a4; | 509 | sb = &a4; |
778 | } | 510 | } |
@@ -1186,64 +918,6 @@ select_better_session (struct Session *s1, | |||
1186 | } | 918 | } |
1187 | 919 | ||
1188 | 920 | ||
1189 | /** | ||
1190 | * We learned about a peer (possibly behind NAT) so run the | ||
1191 | * gnunet-nat-client to send dummy ICMP responses. | ||
1192 | * | ||
1193 | * @param plugin the plugin for this transport | ||
1194 | * @param sa the address of the peer (IPv4-only) | ||
1195 | */ | ||
1196 | static void | ||
1197 | run_gnunet_nat_client (struct Plugin *plugin, | ||
1198 | const struct sockaddr_in *sa) | ||
1199 | { | ||
1200 | char inet4[INET_ADDRSTRLEN]; | ||
1201 | char port_as_string[6]; | ||
1202 | struct GNUNET_OS_Process *proc; | ||
1203 | |||
1204 | if (plugin->internal_address == NULL) | ||
1205 | { | ||
1206 | GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, | ||
1207 | "tcp", | ||
1208 | _("Internal IP address not known, cannot use ICMP NAT traversal method\n")); | ||
1209 | return; | ||
1210 | } | ||
1211 | GNUNET_assert (sa->sin_family == AF_INET); | ||
1212 | if (NULL == inet_ntop (AF_INET, | ||
1213 | &sa->sin_addr, | ||
1214 | inet4, INET_ADDRSTRLEN)) | ||
1215 | { | ||
1216 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "inet_ntop"); | ||
1217 | return; | ||
1218 | } | ||
1219 | GNUNET_snprintf(port_as_string, | ||
1220 | sizeof (port_as_string), | ||
1221 | "%d", | ||
1222 | plugin->adv_port); | ||
1223 | #if DEBUG_TCP_NAT | ||
1224 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, | ||
1225 | "tcp", | ||
1226 | _("Running gnunet-nat-client %s %s %u\n"), | ||
1227 | plugin->internal_address, | ||
1228 | inet4, | ||
1229 | (unsigned int) plugin->adv_port); | ||
1230 | #endif | ||
1231 | proc = GNUNET_OS_start_process (NULL, | ||
1232 | NULL, | ||
1233 | "gnunet-nat-client", | ||
1234 | "gnunet-nat-client", | ||
1235 | plugin->internal_address, | ||
1236 | inet4, | ||
1237 | port_as_string, | ||
1238 | NULL); | ||
1239 | if (NULL == proc) | ||
1240 | return; | ||
1241 | /* we know that the gnunet-nat-client will terminate virtually | ||
1242 | instantly */ | ||
1243 | GNUNET_OS_process_wait (proc); | ||
1244 | GNUNET_OS_process_close (proc); | ||
1245 | } | ||
1246 | |||
1247 | 921 | ||
1248 | /** | 922 | /** |
1249 | * Function that can be used by the transport service to transmit | 923 | * Function that can be used by the transport service to transmit |
@@ -1400,8 +1074,8 @@ tcp_plugin_send (void *cls, | |||
1400 | a4.sin_len = sizeof (a4); | 1074 | a4.sin_len = sizeof (a4); |
1401 | #endif | 1075 | #endif |
1402 | a4.sin_family = AF_INET; | 1076 | a4.sin_family = AF_INET; |
1403 | a4.sin_port = t4->t_port; | 1077 | a4.sin_port = t4->t4_port; |
1404 | if (t4->t_port == 0) | 1078 | if (t4->t4_port == 0) |
1405 | is_natd = GNUNET_YES; | 1079 | is_natd = GNUNET_YES; |
1406 | a4.sin_addr.s_addr = t4->ipv4_addr; | 1080 | a4.sin_addr.s_addr = t4->ipv4_addr; |
1407 | sb = &a4; | 1081 | sb = &a4; |
@@ -1422,8 +1096,8 @@ tcp_plugin_send (void *cls, | |||
1422 | if (0 == plugin->max_connections) | 1096 | if (0 == plugin->max_connections) |
1423 | return -1; /* saturated */ | 1097 | return -1; /* saturated */ |
1424 | 1098 | ||
1425 | if ( (plugin->enable_nat_client == GNUNET_YES) && | 1099 | if ( (is_natd == GNUNET_YES) && |
1426 | (is_natd == GNUNET_YES) && | 1100 | (NULL != plugin->nat) && |
1427 | (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains(plugin->nat_wait_conns, | 1101 | (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains(plugin->nat_wait_conns, |
1428 | &target->hashPubKey)) ) | 1102 | &target->hashPubKey)) ) |
1429 | { | 1103 | { |
@@ -1466,11 +1140,10 @@ tcp_plugin_send (void *cls, | |||
1466 | GNUNET_i2s (target), | 1140 | GNUNET_i2s (target), |
1467 | GNUNET_a2s (sb, sbs)); | 1141 | GNUNET_a2s (sb, sbs)); |
1468 | #endif | 1142 | #endif |
1469 | run_gnunet_nat_client (plugin, &a4); | 1143 | GNUNET_NAT_run_client (plugin->nat, &a4); |
1470 | return 0; | 1144 | return 0; |
1471 | } | 1145 | } |
1472 | if ( (plugin->enable_nat_client == GNUNET_YES) && | 1146 | if ( (is_natd == GNUNET_YES) && |
1473 | (is_natd == GNUNET_YES) && | ||
1474 | (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains(plugin->nat_wait_conns, | 1147 | (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains(plugin->nat_wait_conns, |
1475 | &target->hashPubKey)) ) | 1148 | &target->hashPubKey)) ) |
1476 | { | 1149 | { |
@@ -1697,9 +1370,9 @@ tcp_plugin_address_pretty_printer (void *cls, | |||
1697 | t4 = addr; | 1370 | t4 = addr; |
1698 | memset (&a4, 0, sizeof (a4)); | 1371 | memset (&a4, 0, sizeof (a4)); |
1699 | a4.sin_family = AF_INET; | 1372 | a4.sin_family = AF_INET; |
1700 | a4.sin_port = t4->t_port; | 1373 | a4.sin_port = t4->t4_port; |
1701 | a4.sin_addr.s_addr = t4->ipv4_addr; | 1374 | a4.sin_addr.s_addr = t4->ipv4_addr; |
1702 | port = ntohs (t4->t_port); | 1375 | port = ntohs (t4->t4_port); |
1703 | sb = &a4; | 1376 | sb = &a4; |
1704 | sbs = sizeof (a4); | 1377 | sbs = sizeof (a4); |
1705 | } | 1378 | } |
@@ -1773,14 +1446,12 @@ tcp_plugin_check_address (void *cls, | |||
1773 | if (addrlen == sizeof (struct IPv4TcpAddress)) | 1446 | if (addrlen == sizeof (struct IPv4TcpAddress)) |
1774 | { | 1447 | { |
1775 | v4 = (struct IPv4TcpAddress *) addr; | 1448 | v4 = (struct IPv4TcpAddress *) addr; |
1776 | if (GNUNET_OK == | ||
1777 | check_mapped_addr (plugin, v4, sizeof (struct IPv4TcpAddress))) | ||
1778 | return GNUNET_OK; | ||
1779 | if (GNUNET_OK != | 1449 | if (GNUNET_OK != |
1780 | check_port (plugin, ntohs (v4->t_port))) | 1450 | check_port (plugin, ntohs (v4->t4_port))) |
1781 | return GNUNET_SYSERR; | 1451 | return GNUNET_SYSERR; |
1782 | if (GNUNET_OK != | 1452 | if (GNUNET_OK != |
1783 | check_local_addr (plugin, &v4->ipv4_addr, sizeof (struct in_addr))) | 1453 | GNUNET_NAT_test_address (plugin->nat, |
1454 | &v4->ipv4_addr, sizeof (struct in_addr))) | ||
1784 | return GNUNET_SYSERR; | 1455 | return GNUNET_SYSERR; |
1785 | } | 1456 | } |
1786 | else | 1457 | else |
@@ -1791,14 +1462,12 @@ tcp_plugin_check_address (void *cls, | |||
1791 | GNUNET_break_op (0); | 1462 | GNUNET_break_op (0); |
1792 | return GNUNET_SYSERR; | 1463 | return GNUNET_SYSERR; |
1793 | } | 1464 | } |
1794 | if (GNUNET_OK == | ||
1795 | check_mapped_addr (plugin, v6, sizeof (struct IPv6TcpAddress))) | ||
1796 | return GNUNET_OK; | ||
1797 | if (GNUNET_OK != | 1465 | if (GNUNET_OK != |
1798 | check_port (plugin, ntohs (v6->t6_port))) | 1466 | check_port (plugin, ntohs (v6->t6_port))) |
1799 | return GNUNET_SYSERR; | 1467 | return GNUNET_SYSERR; |
1800 | if (GNUNET_OK != | 1468 | if (GNUNET_OK != |
1801 | check_local_addr (plugin, &v6->ipv6_addr, sizeof (struct in6_addr))) | 1469 | GNUNET_NAT_test_address (plugin->nat, |
1470 | &v6->ipv6_addr, sizeof (struct in6_addr))) | ||
1802 | return GNUNET_SYSERR; | 1471 | return GNUNET_SYSERR; |
1803 | } | 1472 | } |
1804 | return GNUNET_OK; | 1473 | return GNUNET_OK; |
@@ -1903,7 +1572,7 @@ handle_tcp_nat_probe (void *cls, | |||
1903 | case AF_INET: | 1572 | case AF_INET: |
1904 | s4 = vaddr; | 1573 | s4 = vaddr; |
1905 | t4 = GNUNET_malloc (sizeof (struct IPv4TcpAddress)); | 1574 | t4 = GNUNET_malloc (sizeof (struct IPv4TcpAddress)); |
1906 | t4->t_port = s4->sin_port; | 1575 | t4->t4_port = s4->sin_port; |
1907 | t4->ipv4_addr = s4->sin_addr.s_addr; | 1576 | t4->ipv4_addr = s4->sin_addr.s_addr; |
1908 | session->connect_addr = t4; | 1577 | session->connect_addr = t4; |
1909 | session->connect_alen = sizeof (struct IPv4TcpAddress); | 1578 | session->connect_alen = sizeof (struct IPv4TcpAddress); |
@@ -2016,7 +1685,7 @@ handle_tcp_welcome (void *cls, | |||
2016 | { | 1685 | { |
2017 | s4 = vaddr; | 1686 | s4 = vaddr; |
2018 | t4 = GNUNET_malloc (sizeof (struct IPv4TcpAddress)); | 1687 | t4 = GNUNET_malloc (sizeof (struct IPv4TcpAddress)); |
2019 | t4->t_port = s4->sin_port; | 1688 | t4->t4_port = s4->sin_port; |
2020 | t4->ipv4_addr = s4->sin_addr.s_addr; | 1689 | t4->ipv4_addr = s4->sin_addr.s_addr; |
2021 | session->connect_addr = t4; | 1690 | session->connect_addr = t4; |
2022 | session->connect_alen = sizeof (struct IPv4TcpAddress); | 1691 | session->connect_alen = sizeof (struct IPv4TcpAddress); |
@@ -2215,228 +1884,6 @@ disconnect_notify (void *cls, | |||
2215 | } | 1884 | } |
2216 | 1885 | ||
2217 | 1886 | ||
2218 | static int check_localaddress (const struct sockaddr *addr, socklen_t addrlen) | ||
2219 | { | ||
2220 | uint32_t res = 0; | ||
2221 | int local = GNUNET_NO; | ||
2222 | int af = addr->sa_family; | ||
2223 | switch (af) | ||
2224 | { | ||
2225 | case AF_INET: | ||
2226 | { | ||
2227 | uint32_t netmask = 0x7F000000; | ||
2228 | uint32_t address = ntohl (((struct sockaddr_in *) addr)->sin_addr.s_addr); | ||
2229 | res = (address >> 24) ^ (netmask >> 24); | ||
2230 | if (res != 0) | ||
2231 | local = GNUNET_NO; | ||
2232 | else | ||
2233 | local = GNUNET_YES; | ||
2234 | #if DEBUG_TCP | ||
2235 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2236 | "Checking IPv4 address `%s': %s\n", GNUNET_a2s (addr, addrlen), (local==GNUNET_YES) ? "local" : "global"); | ||
2237 | #endif | ||
2238 | break; | ||
2239 | } | ||
2240 | case AF_INET6: | ||
2241 | { | ||
2242 | if (IN6_IS_ADDR_LOOPBACK (&((struct sockaddr_in6 *) addr)->sin6_addr) || | ||
2243 | IN6_IS_ADDR_LINKLOCAL (&((struct sockaddr_in6 *) addr)->sin6_addr)) | ||
2244 | local = GNUNET_YES; | ||
2245 | else | ||
2246 | local = GNUNET_NO; | ||
2247 | #if DEBUG_TCP | ||
2248 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2249 | "Checking IPv6 address `%s' : %s\n", GNUNET_a2s (addr, addrlen), (local==GNUNET_YES) ? "local" : "global"); | ||
2250 | #endif | ||
2251 | break; | ||
2252 | } | ||
2253 | } | ||
2254 | return local; | ||
2255 | } | ||
2256 | |||
2257 | /** | ||
2258 | * Add the IP of our network interface to the list of | ||
2259 | * our internal IP addresses. | ||
2260 | * | ||
2261 | * @param cls the 'struct Plugin*' | ||
2262 | * @param name name of the interface | ||
2263 | * @param isDefault do we think this may be our default interface | ||
2264 | * @param addr address of the interface | ||
2265 | * @param addrlen number of bytes in addr | ||
2266 | * @return GNUNET_OK to continue iterating | ||
2267 | */ | ||
2268 | static int | ||
2269 | process_interfaces (void *cls, | ||
2270 | const char *name, | ||
2271 | int isDefault, | ||
2272 | const struct sockaddr *addr, socklen_t addrlen) | ||
2273 | { | ||
2274 | struct Plugin *plugin = cls; | ||
2275 | int af; | ||
2276 | struct IPv4TcpAddress t4; | ||
2277 | struct IPv6TcpAddress t6; | ||
2278 | struct IPv4TcpAddress t4_nat; | ||
2279 | struct IPv6TcpAddress t6_nat; | ||
2280 | void *arg; | ||
2281 | uint16_t args; | ||
2282 | void *arg_nat; | ||
2283 | char buf[INET6_ADDRSTRLEN]; | ||
2284 | |||
2285 | af = addr->sa_family; | ||
2286 | arg_nat = NULL; | ||
2287 | |||
2288 | if (plugin->use_localaddresses == GNUNET_NO) | ||
2289 | { | ||
2290 | if (GNUNET_YES == check_localaddress (addr, addrlen)) | ||
2291 | { | ||
2292 | #if DEBUG_TCP | ||
2293 | GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, | ||
2294 | "tcp", | ||
2295 | "Not notifying transport of address `%s' (local address)\n", | ||
2296 | GNUNET_a2s (addr, addrlen)); | ||
2297 | #endif | ||
2298 | return GNUNET_OK; | ||
2299 | } | ||
2300 | } | ||
2301 | |||
2302 | switch (af) | ||
2303 | { | ||
2304 | case AF_INET: | ||
2305 | t4.ipv4_addr = ((struct sockaddr_in *) addr)->sin_addr.s_addr; | ||
2306 | GNUNET_assert (NULL != inet_ntop(AF_INET, | ||
2307 | &t4.ipv4_addr, | ||
2308 | buf, | ||
2309 | sizeof (buf))); | ||
2310 | if ( (plugin->bind_address != NULL) && | ||
2311 | (0 != strcmp(buf, plugin->bind_address)) ) | ||
2312 | { | ||
2313 | #if DEBUG_TCP | ||
2314 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, | ||
2315 | "tcp", | ||
2316 | "Not notifying transport of address `%s' (does not match bind address)\n", | ||
2317 | GNUNET_a2s (addr, addrlen)); | ||
2318 | #endif | ||
2319 | return GNUNET_OK; | ||
2320 | } | ||
2321 | if ( (plugin->internal_address == NULL) && | ||
2322 | (isDefault) ) | ||
2323 | plugin->internal_address = GNUNET_strdup (buf); | ||
2324 | add_to_address_list (plugin, &t4.ipv4_addr, sizeof (struct in_addr)); | ||
2325 | if (plugin->behind_nat == GNUNET_YES) | ||
2326 | { | ||
2327 | /* Also advertise as NAT (with port 0) */ | ||
2328 | t4_nat.ipv4_addr = ((struct sockaddr_in *) addr)->sin_addr.s_addr; | ||
2329 | t4_nat.t_port = htons(0); | ||
2330 | arg_nat = &t4_nat; | ||
2331 | } | ||
2332 | t4.t_port = htons (plugin->adv_port); | ||
2333 | arg = &t4; | ||
2334 | args = sizeof (t4); | ||
2335 | break; | ||
2336 | case AF_INET6: | ||
2337 | if ( (IN6_IS_ADDR_LINKLOCAL (&((struct sockaddr_in6 *) addr)->sin6_addr)) || | ||
2338 | (GNUNET_YES == GNUNET_CONFIGURATION_get_value_yesno(plugin->env->cfg, | ||
2339 | "nat", | ||
2340 | "DISABLEV6")) ) | ||
2341 | { | ||
2342 | /* skip link local addresses */ | ||
2343 | return GNUNET_OK; | ||
2344 | } | ||
2345 | memcpy (&t6.ipv6_addr, | ||
2346 | &((struct sockaddr_in6 *) addr)->sin6_addr, | ||
2347 | sizeof (struct in6_addr)); | ||
2348 | |||
2349 | /* check bind address */ | ||
2350 | GNUNET_assert (NULL != inet_ntop(AF_INET6, | ||
2351 | &t6.ipv6_addr, | ||
2352 | buf, | ||
2353 | sizeof (buf))); | ||
2354 | |||
2355 | if ( (plugin->bind_address != NULL) && | ||
2356 | (0 != strcmp(buf, plugin->bind_address)) ) | ||
2357 | { | ||
2358 | #if DEBUG_TCP | ||
2359 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, | ||
2360 | "tcp", | ||
2361 | "Not notifying transport of address `%s' (does not match bind address)\n", | ||
2362 | GNUNET_a2s (addr, addrlen)); | ||
2363 | #endif | ||
2364 | return GNUNET_OK; | ||
2365 | } | ||
2366 | |||
2367 | add_to_address_list (plugin, | ||
2368 | &t6.ipv6_addr, | ||
2369 | sizeof (struct in6_addr)); | ||
2370 | if (plugin->behind_nat == GNUNET_YES) | ||
2371 | { | ||
2372 | /* Also advertise as NAT (with port 0) */ | ||
2373 | memcpy (&t6_nat.ipv6_addr, | ||
2374 | &((struct sockaddr_in6 *) addr)->sin6_addr, | ||
2375 | sizeof (struct in6_addr)); | ||
2376 | t6_nat.t6_port = htons(0); | ||
2377 | arg_nat = &t6; | ||
2378 | } | ||
2379 | t6.t6_port = htons (plugin->adv_port); | ||
2380 | arg = &t6; | ||
2381 | args = sizeof (t6); | ||
2382 | break; | ||
2383 | default: | ||
2384 | GNUNET_break (0); | ||
2385 | return GNUNET_OK; | ||
2386 | } | ||
2387 | if (plugin->adv_port != 0) | ||
2388 | { | ||
2389 | #if DEBUG_TCP | ||
2390 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, | ||
2391 | "tcp", | ||
2392 | "Found address `%s' (%s) len %d\n", | ||
2393 | GNUNET_a2s (addr, addrlen), name, args); | ||
2394 | #endif | ||
2395 | plugin->env->notify_address (plugin->env->cls, | ||
2396 | "tcp", | ||
2397 | arg, args, GNUNET_TIME_UNIT_FOREVER_REL); | ||
2398 | } | ||
2399 | |||
2400 | if (arg_nat != NULL) | ||
2401 | { | ||
2402 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, | ||
2403 | "tcp", | ||
2404 | _("Found address `%s' (%s) len %d\n"), | ||
2405 | GNUNET_a2s (addr, addrlen), name, args); | ||
2406 | plugin->env->notify_address (plugin->env->cls, | ||
2407 | "tcp", | ||
2408 | arg_nat, args, GNUNET_TIME_UNIT_FOREVER_REL); | ||
2409 | } | ||
2410 | |||
2411 | return GNUNET_OK; | ||
2412 | } | ||
2413 | |||
2414 | |||
2415 | /** | ||
2416 | * Function called by the resolver for each address obtained from DNS | ||
2417 | * for our own hostname. Add the addresses to the list of our | ||
2418 | * external IP addresses. | ||
2419 | * | ||
2420 | * @param cls closure | ||
2421 | * @param addr one of the addresses of the host, NULL for the last address | ||
2422 | * @param addrlen length of the address | ||
2423 | */ | ||
2424 | static void | ||
2425 | process_hostname_ips (void *cls, | ||
2426 | const struct sockaddr *addr, socklen_t addrlen) | ||
2427 | { | ||
2428 | struct Plugin *plugin = cls; | ||
2429 | |||
2430 | if (addr == NULL) | ||
2431 | { | ||
2432 | plugin->hostname_dns = NULL; | ||
2433 | return; | ||
2434 | } | ||
2435 | /* FIXME: Can we figure out our external address here so it doesn't need to be user specified? */ | ||
2436 | process_interfaces (plugin, "<hostname>", GNUNET_YES, addr, addrlen); | ||
2437 | } | ||
2438 | |||
2439 | |||
2440 | /** | 1887 | /** |
2441 | * We can now send a probe message, copy into buffer to really send. | 1888 | * We can now send a probe message, copy into buffer to really send. |
2442 | * | 1889 | * |
@@ -2475,112 +1922,36 @@ notify_send_probe (void *cls, | |||
2475 | 1922 | ||
2476 | 1923 | ||
2477 | /** | 1924 | /** |
2478 | * We have been notified that gnunet-nat-server has written something to stdout. | 1925 | * Function called by the NAT subsystem suggesting another peer wants |
2479 | * Handle the output, then reschedule this function to be called again once | 1926 | * to connect to us via connection reversal. Try to connect back to the |
2480 | * more is available. | 1927 | * given IP. |
2481 | * | 1928 | * |
2482 | * @param cls the plugin handle | 1929 | * @param cls closure |
2483 | * @param tc the scheduling context | 1930 | * @param addr address to try |
1931 | * @param addrlen number of bytes in addr | ||
2484 | */ | 1932 | */ |
2485 | static void | 1933 | static void |
2486 | tcp_plugin_server_read (void *cls, | 1934 | try_connection_reversal (void *cls, |
2487 | const struct GNUNET_SCHEDULER_TaskContext *tc) | 1935 | const struct sockaddr *addr, |
1936 | socklen_t addrlen) | ||
2488 | { | 1937 | { |
2489 | struct Plugin *plugin = cls; | 1938 | struct Plugin *plugin = cls; |
2490 | char mybuf[40]; | ||
2491 | ssize_t bytes; | ||
2492 | size_t i; | ||
2493 | int port; | ||
2494 | const char *port_start; | ||
2495 | struct sockaddr_in sin_addr; | ||
2496 | struct TCPProbeContext *tcp_probe_ctx; | ||
2497 | struct GNUNET_CONNECTION_Handle *sock; | 1939 | struct GNUNET_CONNECTION_Handle *sock; |
2498 | 1940 | struct TCPProbeContext *tcp_probe_ctx; | |
2499 | if ( (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0) | ||
2500 | return; | ||
2501 | memset (mybuf, 0, sizeof(mybuf)); | ||
2502 | bytes = GNUNET_DISK_file_read(plugin->server_stdout_handle, | ||
2503 | mybuf, | ||
2504 | sizeof(mybuf)); | ||
2505 | if (bytes < 1) | ||
2506 | { | ||
2507 | #if DEBUG_TCP_NAT | ||
2508 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, | ||
2509 | "tcp", | ||
2510 | "Finished reading from server stdout with code: %d\n", | ||
2511 | bytes); | ||
2512 | #endif | ||
2513 | /* FIXME: consider process_wait here? */ | ||
2514 | return; | ||
2515 | } | ||
2516 | |||
2517 | port_start = NULL; | ||
2518 | for (i = 0; i < sizeof(mybuf); i++) | ||
2519 | { | ||
2520 | if (mybuf[i] == '\n') | ||
2521 | { | ||
2522 | mybuf[i] = '\0'; | ||
2523 | break; | ||
2524 | } | ||
2525 | if ( (mybuf[i] == ':') && (i + 1 < sizeof(mybuf)) ) | ||
2526 | { | ||
2527 | mybuf[i] = '\0'; | ||
2528 | port_start = &mybuf[i + 1]; | ||
2529 | } | ||
2530 | } | ||
2531 | |||
2532 | /* construct socket address of sender */ | ||
2533 | memset (&sin_addr, 0, sizeof (sin_addr)); | ||
2534 | sin_addr.sin_family = AF_INET; | ||
2535 | #if HAVE_SOCKADDR_IN_SIN_LEN | ||
2536 | sin_addr.sin_len = sizeof (sin_addr); | ||
2537 | #endif | ||
2538 | if ( (NULL == port_start) || | ||
2539 | (1 != sscanf (port_start, "%d", &port)) || | ||
2540 | (-1 == inet_pton(AF_INET, mybuf, &sin_addr.sin_addr)) ) | ||
2541 | { | ||
2542 | /* should we restart gnunet-nat-server? */ | ||
2543 | GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, | ||
2544 | "tcp", | ||
2545 | _("gnunet-nat-server generated malformed address `%s'\n"), | ||
2546 | mybuf); | ||
2547 | plugin->server_read_task | ||
2548 | = GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, | ||
2549 | plugin->server_stdout_handle, | ||
2550 | &tcp_plugin_server_read, | ||
2551 | plugin); | ||
2552 | return; | ||
2553 | } | ||
2554 | sin_addr.sin_port = htons((uint16_t) port); | ||
2555 | #if DEBUG_TCP_NAT | ||
2556 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, | ||
2557 | "tcp", | ||
2558 | "gnunet-nat-server read: %s:%d\n", | ||
2559 | mybuf, port); | ||
2560 | #endif | ||
2561 | 1941 | ||
2562 | /** | 1942 | /** |
2563 | * We have received an ICMP response, ostensibly from a peer | 1943 | * We have received an ICMP response, ostensibly from a peer |
2564 | * that wants to connect to us! Send a message to establish a connection. | 1944 | * that wants to connect to us! Send a message to establish a connection. |
2565 | */ | 1945 | */ |
2566 | sock = GNUNET_CONNECTION_create_from_sockaddr (AF_INET, | 1946 | sock = GNUNET_CONNECTION_create_from_sockaddr (AF_INET, |
2567 | (const struct sockaddr *)&sin_addr, | 1947 | addr, |
2568 | sizeof (sin_addr)); | 1948 | addrlen); |
2569 | if (sock == NULL) | 1949 | if (sock == NULL) |
2570 | { | 1950 | { |
2571 | /* failed for some odd reason (out of sockets?); ignore attempt */ | 1951 | /* failed for some odd reason (out of sockets?); ignore attempt */ |
2572 | plugin->server_read_task = | ||
2573 | GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, | ||
2574 | plugin->server_stdout_handle, | ||
2575 | &tcp_plugin_server_read, | ||
2576 | plugin); | ||
2577 | return; | 1952 | return; |
2578 | } | 1953 | } |
2579 | 1954 | ||
2580 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, | ||
2581 | "Sending TCP probe message to `%s:%u'!\n", | ||
2582 | mybuf, | ||
2583 | (unsigned int) port); | ||
2584 | /* FIXME: do we need to track these probe context objects so that | 1955 | /* FIXME: do we need to track these probe context objects so that |
2585 | we can clean them up on plugin unload? */ | 1956 | we can clean them up on plugin unload? */ |
2586 | tcp_probe_ctx | 1957 | tcp_probe_ctx |
@@ -2603,251 +1974,6 @@ tcp_plugin_server_read (void *cls, | |||
2603 | GNUNET_TIME_UNIT_FOREVER_REL, | 1974 | GNUNET_TIME_UNIT_FOREVER_REL, |
2604 | ¬ify_send_probe, tcp_probe_ctx); | 1975 | ¬ify_send_probe, tcp_probe_ctx); |
2605 | 1976 | ||
2606 | plugin->server_read_task = | ||
2607 | GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, | ||
2608 | plugin->server_stdout_handle, | ||
2609 | &tcp_plugin_server_read, | ||
2610 | plugin); | ||
2611 | } | ||
2612 | |||
2613 | |||
2614 | /** | ||
2615 | * Start the gnunet-nat-server process for users behind NAT. | ||
2616 | * | ||
2617 | * @param plugin the transport plugin | ||
2618 | * @return GNUNET_YES if process was started, GNUNET_SYSERR on error | ||
2619 | */ | ||
2620 | static int | ||
2621 | tcp_transport_start_nat_server (struct Plugin *plugin) | ||
2622 | { | ||
2623 | if (plugin->internal_address == NULL) | ||
2624 | return GNUNET_SYSERR; | ||
2625 | plugin->server_stdout = GNUNET_DISK_pipe (GNUNET_YES, | ||
2626 | GNUNET_NO, | ||
2627 | GNUNET_YES); | ||
2628 | if (plugin->server_stdout == NULL) | ||
2629 | return GNUNET_SYSERR; | ||
2630 | #if DEBUG_TCP_NAT | ||
2631 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, | ||
2632 | "tcp" | ||
2633 | "Starting %s %s\n", "gnunet-nat-server", plugin->internal_address); | ||
2634 | #endif | ||
2635 | /* Start the server process */ | ||
2636 | plugin->server_proc = GNUNET_OS_start_process (NULL, | ||
2637 | plugin->server_stdout, | ||
2638 | "gnunet-nat-server", | ||
2639 | "gnunet-nat-server", | ||
2640 | plugin->internal_address, | ||
2641 | NULL); | ||
2642 | if (plugin->server_proc == NULL) | ||
2643 | { | ||
2644 | GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, | ||
2645 | "tcp", | ||
2646 | _("Failed to start %s\n"), | ||
2647 | "gnunet-nat-server"); | ||
2648 | GNUNET_DISK_pipe_close (plugin->server_stdout); | ||
2649 | plugin->server_stdout = NULL; | ||
2650 | return GNUNET_SYSERR; | ||
2651 | } | ||
2652 | /* Close the write end of the read pipe */ | ||
2653 | GNUNET_DISK_pipe_close_end(plugin->server_stdout, | ||
2654 | GNUNET_DISK_PIPE_END_WRITE); | ||
2655 | plugin->server_stdout_handle | ||
2656 | = GNUNET_DISK_pipe_handle (plugin->server_stdout, | ||
2657 | GNUNET_DISK_PIPE_END_READ); | ||
2658 | plugin->server_read_task | ||
2659 | = GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, | ||
2660 | plugin->server_stdout_handle, | ||
2661 | &tcp_plugin_server_read, | ||
2662 | plugin); | ||
2663 | return GNUNET_YES; | ||
2664 | } | ||
2665 | |||
2666 | |||
2667 | /** | ||
2668 | * Return the actual path to a file found in the current | ||
2669 | * PATH environment variable. | ||
2670 | * | ||
2671 | * @param binary the name of the file to find | ||
2672 | * @return path to binary, NULL if not found | ||
2673 | */ | ||
2674 | static char * | ||
2675 | get_path_from_PATH (const char *binary) | ||
2676 | { | ||
2677 | char *path; | ||
2678 | char *pos; | ||
2679 | char *end; | ||
2680 | char *buf; | ||
2681 | const char *p; | ||
2682 | |||
2683 | p = getenv ("PATH"); | ||
2684 | if (p == NULL) | ||
2685 | { | ||
2686 | GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, | ||
2687 | "tcp", | ||
2688 | _("PATH environment variable is unset.\n")); | ||
2689 | return NULL; | ||
2690 | } | ||
2691 | path = GNUNET_strdup (p); /* because we write on it */ | ||
2692 | buf = GNUNET_malloc (strlen (path) + 20); | ||
2693 | pos = path; | ||
2694 | |||
2695 | while (NULL != (end = strchr (pos, PATH_SEPARATOR))) | ||
2696 | { | ||
2697 | *end = '\0'; | ||
2698 | sprintf (buf, "%s/%s", pos, binary); | ||
2699 | if (GNUNET_DISK_file_test (buf) == GNUNET_YES) | ||
2700 | { | ||
2701 | GNUNET_free (path); | ||
2702 | return buf; | ||
2703 | } | ||
2704 | pos = end + 1; | ||
2705 | } | ||
2706 | sprintf (buf, "%s/%s", pos, binary); | ||
2707 | if (GNUNET_DISK_file_test (buf) == GNUNET_YES) | ||
2708 | { | ||
2709 | GNUNET_free (path); | ||
2710 | return buf; | ||
2711 | } | ||
2712 | GNUNET_free (buf); | ||
2713 | GNUNET_free (path); | ||
2714 | return NULL; | ||
2715 | } | ||
2716 | |||
2717 | |||
2718 | /** | ||
2719 | * Check whether the suid bit is set on a file. | ||
2720 | * Attempts to find the file using the current | ||
2721 | * PATH environment variable as a search path. | ||
2722 | * | ||
2723 | * @param binary the name of the file to check | ||
2724 | * @return GNUNET_YES if the file is SUID, | ||
2725 | * GNUNET_NO if not, | ||
2726 | * GNUNET_SYSERR on error | ||
2727 | */ | ||
2728 | static int | ||
2729 | check_gnunet_nat_binary (const char *binary) | ||
2730 | { | ||
2731 | struct stat statbuf; | ||
2732 | char *p; | ||
2733 | #ifdef MINGW | ||
2734 | SOCKET rawsock; | ||
2735 | char *binaryexe; | ||
2736 | |||
2737 | GNUNET_asprintf (&binaryexe, "%s.exe", binary); | ||
2738 | p = get_path_from_PATH (binaryexe); | ||
2739 | free (binaryexe); | ||
2740 | #else | ||
2741 | p = get_path_from_PATH (binary); | ||
2742 | #endif | ||
2743 | if (p == NULL) | ||
2744 | { | ||
2745 | GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, | ||
2746 | "tcp", | ||
2747 | _("Could not find binary `%s' in PATH!\n"), | ||
2748 | binary); | ||
2749 | return GNUNET_NO; | ||
2750 | } | ||
2751 | if (0 != STAT (p, &statbuf)) | ||
2752 | { | ||
2753 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
2754 | _("stat (%s) failed: %s\n"), | ||
2755 | p, | ||
2756 | STRERROR (errno)); | ||
2757 | GNUNET_free (p); | ||
2758 | return GNUNET_SYSERR; | ||
2759 | } | ||
2760 | GNUNET_free (p); | ||
2761 | #ifndef MINGW | ||
2762 | if ( (0 != (statbuf.st_mode & S_ISUID)) && | ||
2763 | (statbuf.st_uid == 0) ) | ||
2764 | return GNUNET_YES; | ||
2765 | return GNUNET_NO; | ||
2766 | #else | ||
2767 | rawsock = socket (AF_INET, SOCK_RAW, IPPROTO_ICMP); | ||
2768 | if (INVALID_SOCKET == rawsock) | ||
2769 | { | ||
2770 | DWORD err = GetLastError (); | ||
2771 | GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, | ||
2772 | "tcp", | ||
2773 | "socket (AF_INET, SOCK_RAW, IPPROTO_ICMP) failed! GLE = %d\n", err); | ||
2774 | return GNUNET_NO; /* not running as administrator */ | ||
2775 | } | ||
2776 | closesocket (rawsock); | ||
2777 | return GNUNET_YES; | ||
2778 | #endif | ||
2779 | } | ||
2780 | |||
2781 | |||
2782 | /** | ||
2783 | * Our (external) hostname was resolved. | ||
2784 | * | ||
2785 | * @param cls the 'struct Plugin' | ||
2786 | * @param addr NULL on error, otherwise result of DNS lookup | ||
2787 | * @param addrlen number of bytes in addr | ||
2788 | */ | ||
2789 | static void | ||
2790 | process_external_ip (void *cls, | ||
2791 | const struct sockaddr *addr, | ||
2792 | socklen_t addrlen) | ||
2793 | { | ||
2794 | struct Plugin *plugin = cls; | ||
2795 | const struct sockaddr_in *s; | ||
2796 | struct IPv4TcpAddress t4; | ||
2797 | char buf[INET_ADDRSTRLEN]; | ||
2798 | |||
2799 | plugin->ext_dns = NULL; | ||
2800 | if (addr == NULL) | ||
2801 | return; | ||
2802 | GNUNET_assert (addrlen == sizeof (struct sockaddr_in)); | ||
2803 | s = (const struct sockaddr_in *) addr; | ||
2804 | t4.ipv4_addr = s->sin_addr.s_addr; | ||
2805 | if ( (plugin->behind_nat == GNUNET_YES) && | ||
2806 | (plugin->enable_nat_server == GNUNET_YES) ) | ||
2807 | { | ||
2808 | t4.t_port = htons(0); | ||
2809 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, | ||
2810 | "tcp", | ||
2811 | "Notifying transport of address %s:%d\n", | ||
2812 | plugin->external_address, | ||
2813 | 0); | ||
2814 | } | ||
2815 | else | ||
2816 | { | ||
2817 | t4.t_port = htons(plugin->adv_port); | ||
2818 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, | ||
2819 | "tcp", | ||
2820 | "Notifying transport of address %s:%d\n", | ||
2821 | plugin->external_address, | ||
2822 | (int) plugin->adv_port); | ||
2823 | } | ||
2824 | |||
2825 | if ((plugin->bind_address != NULL) && (plugin->behind_nat == GNUNET_NO)) | ||
2826 | { | ||
2827 | GNUNET_assert (NULL != inet_ntop(AF_INET, | ||
2828 | &t4.ipv4_addr, | ||
2829 | buf, | ||
2830 | sizeof (buf))); | ||
2831 | if (0 != strcmp (plugin->bind_address, buf)) | ||
2832 | { | ||
2833 | GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, | ||
2834 | "tcp", | ||
2835 | "NAT is not enabled and specific bind address `%s' differs from external address `%s'! Not notifying about external address `%s'\n", | ||
2836 | plugin->bind_address, | ||
2837 | plugin->external_address, | ||
2838 | plugin->external_address); | ||
2839 | return; | ||
2840 | } | ||
2841 | } | ||
2842 | |||
2843 | add_to_address_list (plugin, | ||
2844 | &t4.ipv4_addr, | ||
2845 | sizeof (struct in_addr)); | ||
2846 | |||
2847 | plugin->env->notify_address (plugin->env->cls, | ||
2848 | "tcp", | ||
2849 | &t4, sizeof(t4), | ||
2850 | GNUNET_TIME_UNIT_FOREVER_REL); | ||
2851 | } | 1977 | } |
2852 | 1978 | ||
2853 | 1979 | ||
@@ -2875,146 +2001,16 @@ libgnunet_plugin_transport_tcp_init (void *cls) | |||
2875 | unsigned long long bport; | 2001 | unsigned long long bport; |
2876 | unsigned long long max_connections; | 2002 | unsigned long long max_connections; |
2877 | unsigned int i; | 2003 | unsigned int i; |
2878 | int behind_nat; | ||
2879 | int nat_punched; | ||
2880 | int enable_nat_client; | ||
2881 | int enable_nat_server; | ||
2882 | int enable_upnp; | ||
2883 | int use_localaddresses; | ||
2884 | char *internal_address; | ||
2885 | char *external_address; | ||
2886 | char *bind_address; | ||
2887 | struct sockaddr_in in_addr; | ||
2888 | struct GNUNET_TIME_Relative idle_timeout; | 2004 | struct GNUNET_TIME_Relative idle_timeout; |
2005 | int ret; | ||
2006 | struct sockaddr **addrs; | ||
2007 | socklen_t *addrlens; | ||
2889 | 2008 | ||
2890 | behind_nat = GNUNET_CONFIGURATION_get_value_yesno (env->cfg, | ||
2891 | "nat", | ||
2892 | "BEHIND_NAT"); | ||
2893 | nat_punched = GNUNET_CONFIGURATION_get_value_yesno (env->cfg, | ||
2894 | "nat", | ||
2895 | "NAT_PUNCHED"); | ||
2896 | enable_nat_client = GNUNET_CONFIGURATION_get_value_yesno (env->cfg, | ||
2897 | "nat", | ||
2898 | "ENABLE_NAT_CLIENT"); | ||
2899 | enable_nat_server = GNUNET_CONFIGURATION_get_value_yesno (env->cfg, | ||
2900 | "nat", | ||
2901 | "ENABLE_NAT_SERVER"); | ||
2902 | enable_upnp = GNUNET_CONFIGURATION_get_value_yesno (env->cfg, | ||
2903 | "nat", | ||
2904 | "ENABLE_UPNP"); | ||
2905 | |||
2906 | if ( (GNUNET_YES == enable_nat_server) && | ||
2907 | (GNUNET_YES != check_gnunet_nat_binary("gnunet-nat-server")) ) | ||
2908 | { | ||
2909 | enable_nat_server = GNUNET_NO; | ||
2910 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
2911 | _("Configuration requires `%s', but binary is not installed properly (SUID bit not set). Option disabled.\n"), | ||
2912 | "gnunet-nat-server"); | ||
2913 | } | ||
2914 | |||
2915 | if ( (GNUNET_YES == enable_nat_client) && | ||
2916 | (GNUNET_YES != check_gnunet_nat_binary("gnunet-nat-client")) ) | ||
2917 | { | ||
2918 | enable_nat_client = GNUNET_NO; | ||
2919 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
2920 | _("Configuration requires `%s', but binary is not installed properly (SUID bit not set). Option disabled.\n"), | ||
2921 | "gnunet-nat-client"); | ||
2922 | } | ||
2923 | |||
2924 | external_address = NULL; | ||
2925 | if (GNUNET_OK == | ||
2926 | GNUNET_CONFIGURATION_have_value (env->cfg, | ||
2927 | "nat", | ||
2928 | "EXTERNAL_ADDRESS")) | ||
2929 | { | ||
2930 | (void) GNUNET_CONFIGURATION_get_value_string (env->cfg, | ||
2931 | "nat", | ||
2932 | "EXTERNAL_ADDRESS", | ||
2933 | &external_address); | ||
2934 | } | ||
2935 | |||
2936 | if ( (external_address != NULL) && | ||
2937 | (inet_pton(AF_INET, external_address, &in_addr.sin_addr) != 1) ) | ||
2938 | { | ||
2939 | |||
2940 | GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, | ||
2941 | "tcp", | ||
2942 | _("Malformed %s `%s' given in configuration!\n"), | ||
2943 | "EXTERNAL_ADDRESS", | ||
2944 | external_address); | ||
2945 | return NULL; | ||
2946 | } | ||
2947 | if ( (external_address == NULL) && | ||
2948 | (nat_punched == GNUNET_YES) ) | ||
2949 | { | ||
2950 | nat_punched = GNUNET_NO; | ||
2951 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
2952 | _("Configuration says NAT was punched, but `%s' is not given. Option ignored.\n"), | ||
2953 | "EXTERNAL_ADDRESS"); | ||
2954 | } | ||
2955 | |||
2956 | if (GNUNET_YES == nat_punched) | ||
2957 | { | ||
2958 | enable_nat_server = GNUNET_NO; | ||
2959 | enable_upnp = GNUNET_NO; | ||
2960 | } | ||
2961 | |||
2962 | bind_address = NULL; | ||
2963 | if (GNUNET_YES == GNUNET_CONFIGURATION_get_value_string (env->cfg, | ||
2964 | "nat", | ||
2965 | "BINDTO", | ||
2966 | &bind_address)) | ||
2967 | { | ||
2968 | GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, | ||
2969 | "tcp", | ||
2970 | _("Binding TCP plugin to specific address: `%s'\n"), | ||
2971 | bind_address); | ||
2972 | } | ||
2973 | |||
2974 | internal_address = NULL; | ||
2975 | if (GNUNET_OK == | ||
2976 | GNUNET_CONFIGURATION_have_value (env->cfg, | ||
2977 | "nat", | ||
2978 | "INTERNAL_ADDRESS")) | ||
2979 | { | ||
2980 | (void) GNUNET_CONFIGURATION_get_value_string (env->cfg, | ||
2981 | "nat", | ||
2982 | "INTERNAL_ADDRESS", | ||
2983 | &internal_address); | ||
2984 | } | ||
2985 | |||
2986 | if ( (internal_address != NULL) && | ||
2987 | (inet_pton(AF_INET, internal_address, &in_addr.sin_addr) != 1) ) | ||
2988 | { | ||
2989 | GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, | ||
2990 | "tcp", | ||
2991 | _("Malformed %s `%s' given in configuration!\n"), | ||
2992 | "INTERNAL_ADDRESS", | ||
2993 | internal_address); | ||
2994 | GNUNET_free_non_null(internal_address); | ||
2995 | GNUNET_free_non_null(external_address); | ||
2996 | return NULL; | ||
2997 | } | ||
2998 | |||
2999 | if ((bind_address != NULL) && (internal_address != NULL)) | ||
3000 | { | ||
3001 | if (0 != strcmp(internal_address, bind_address )) | ||
3002 | { | ||
3003 | GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, | ||
3004 | "tcp", | ||
3005 | "Specific bind address `%s' and internal address `%s' must not differ, forcing internal address to bind address!\n", | ||
3006 | bind_address, internal_address); | ||
3007 | GNUNET_free (internal_address); | ||
3008 | internal_address = bind_address; | ||
3009 | GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, | ||
3010 | "tcp","New internal address `%s'\n", internal_address); | ||
3011 | } | ||
3012 | } | ||
3013 | if (GNUNET_OK != | 2009 | if (GNUNET_OK != |
3014 | GNUNET_CONFIGURATION_get_value_number (env->cfg, | 2010 | GNUNET_CONFIGURATION_get_value_number (env->cfg, |
3015 | "transport-tcp", | 2011 | "transport-tcp", |
3016 | "MAX_CONNECTIONS", | 2012 | "MAX_CONNECTIONS", |
3017 | &max_connections)) | 2013 | &max_connections)) |
3018 | max_connections = 128; | 2014 | max_connections = 128; |
3019 | 2015 | ||
3020 | aport = 0; | 2016 | aport = 0; |
@@ -3035,25 +2031,15 @@ libgnunet_plugin_transport_tcp_init (void *cls) | |||
3035 | "tcp", | 2031 | "tcp", |
3036 | _("Require valid port number for service `%s' in configuration!\n"), | 2032 | _("Require valid port number for service `%s' in configuration!\n"), |
3037 | "transport-tcp"); | 2033 | "transport-tcp"); |
3038 | GNUNET_free_non_null(external_address); | ||
3039 | GNUNET_free_non_null(internal_address); | ||
3040 | return NULL; | 2034 | return NULL; |
3041 | } | 2035 | } |
3042 | |||
3043 | use_localaddresses = GNUNET_CONFIGURATION_get_value_yesno (env->cfg, | ||
3044 | "transport-tcp", | ||
3045 | "USE_LOCALADDR"); | ||
3046 | if (use_localaddresses == GNUNET_SYSERR) | ||
3047 | use_localaddresses = GNUNET_NO; | ||
3048 | |||
3049 | if (aport == 0) | 2036 | if (aport == 0) |
3050 | aport = bport; | 2037 | aport = bport; |
3051 | if (bport == 0) | 2038 | if (bport == 0) |
3052 | aport = 0; | 2039 | aport = 0; |
3053 | |||
3054 | if (bport != 0) | 2040 | if (bport != 0) |
3055 | { | 2041 | { |
3056 | service = GNUNET_SERVICE_start ("transport-tcp", env->cfg); | 2042 | service = GNUNET_SERVICE_start ("transport-tcp", env->cfg); |
3057 | if (service == NULL) | 2043 | if (service == NULL) |
3058 | { | 2044 | { |
3059 | GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, | 2045 | GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, |
@@ -3065,21 +2051,45 @@ libgnunet_plugin_transport_tcp_init (void *cls) | |||
3065 | else | 2051 | else |
3066 | service = NULL; | 2052 | service = NULL; |
3067 | 2053 | ||
2054 | |||
2055 | |||
3068 | plugin = GNUNET_malloc (sizeof (struct Plugin)); | 2056 | plugin = GNUNET_malloc (sizeof (struct Plugin)); |
3069 | plugin->max_connections = max_connections; | 2057 | plugin->max_connections = max_connections; |
3070 | plugin->open_port = bport; | 2058 | plugin->open_port = bport; |
3071 | plugin->adv_port = aport; | 2059 | plugin->adv_port = aport; |
3072 | plugin->bind_address = bind_address; | ||
3073 | plugin->external_address = external_address; | ||
3074 | plugin->internal_address = internal_address; | ||
3075 | plugin->behind_nat = behind_nat; | ||
3076 | plugin->nat_punched = nat_punched; | ||
3077 | plugin->enable_nat_client = enable_nat_client; | ||
3078 | plugin->enable_nat_server = enable_nat_server; | ||
3079 | plugin->enable_upnp = enable_upnp; | ||
3080 | plugin->use_localaddresses = use_localaddresses; | ||
3081 | plugin->env = env; | 2060 | plugin->env = env; |
3082 | plugin->lsock = NULL; | 2061 | plugin->lsock = NULL; |
2062 | if ( (service != NULL) && | ||
2063 | (GNUNET_SYSERR != | ||
2064 | (ret = GNUNET_SERVICE_get_server_addresses ("transport-tcp", | ||
2065 | env->cfg, | ||
2066 | &addrs, | ||
2067 | &addrlens))) ) | ||
2068 | { | ||
2069 | plugin->nat = GNUNET_NAT_register (env->cfg, | ||
2070 | GNUNET_YES, | ||
2071 | aport, | ||
2072 | (unsigned int) ret, | ||
2073 | (const struct sockaddr **) addrs, | ||
2074 | addrlens, | ||
2075 | &tcp_nat_port_map_callback, | ||
2076 | &try_connection_reversal, | ||
2077 | plugin); | ||
2078 | while (ret > 0) | ||
2079 | GNUNET_free (addrs[--ret]); | ||
2080 | GNUNET_free_non_null (addrs); | ||
2081 | GNUNET_free_non_null (addrlens); | ||
2082 | } | ||
2083 | else | ||
2084 | { | ||
2085 | plugin->nat = GNUNET_NAT_register (env->cfg, | ||
2086 | GNUNET_YES, | ||
2087 | 0, | ||
2088 | 0, NULL, NULL, | ||
2089 | NULL, | ||
2090 | &try_connection_reversal, | ||
2091 | plugin); | ||
2092 | } | ||
3083 | api = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_PluginFunctions)); | 2093 | api = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_PluginFunctions)); |
3084 | api->cls = plugin; | 2094 | api->cls = plugin; |
3085 | api->send = &tcp_plugin_send; | 2095 | api->send = &tcp_plugin_send; |
@@ -3105,8 +2115,9 @@ libgnunet_plugin_transport_tcp_init (void *cls) | |||
3105 | _("Failed to find option %s in section %s!\n"), | 2115 | _("Failed to find option %s in section %s!\n"), |
3106 | "TIMEOUT", | 2116 | "TIMEOUT", |
3107 | "transport-tcp"); | 2117 | "transport-tcp"); |
3108 | GNUNET_free_non_null(external_address); | 2118 | if (plugin->nat != NULL) |
3109 | GNUNET_free_non_null(internal_address); | 2119 | GNUNET_NAT_unregister (plugin->nat); |
2120 | GNUNET_free (plugin); | ||
3110 | GNUNET_free (api); | 2121 | GNUNET_free (api); |
3111 | return NULL; | 2122 | return NULL; |
3112 | } | 2123 | } |
@@ -3123,33 +2134,7 @@ libgnunet_plugin_transport_tcp_init (void *cls) | |||
3123 | GNUNET_SERVER_disconnect_notify (plugin->server, | 2134 | GNUNET_SERVER_disconnect_notify (plugin->server, |
3124 | &disconnect_notify, | 2135 | &disconnect_notify, |
3125 | plugin); | 2136 | plugin); |
3126 | GNUNET_OS_network_interfaces_list (&process_interfaces, plugin); | 2137 | plugin->nat_wait_conns = GNUNET_CONTAINER_multihashmap_create(16); |
3127 | |||
3128 | if ( (plugin->behind_nat == GNUNET_YES) && | ||
3129 | (plugin->enable_nat_server == GNUNET_YES) && | ||
3130 | (GNUNET_YES != tcp_transport_start_nat_server(plugin)) ) | ||
3131 | { | ||
3132 | GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, | ||
3133 | "tcp", | ||
3134 | _("Failed to start %s required for NAT in %s!\n"), | ||
3135 | "gnunet-nat-server" | ||
3136 | "transport-tcp"); | ||
3137 | GNUNET_free_non_null(external_address); | ||
3138 | GNUNET_free_non_null(internal_address); | ||
3139 | if (service != NULL) | ||
3140 | GNUNET_SERVICE_stop (service); | ||
3141 | else | ||
3142 | GNUNET_SERVER_destroy (plugin->server); | ||
3143 | GNUNET_free (api); | ||
3144 | return NULL; | ||
3145 | } | ||
3146 | |||
3147 | if (enable_nat_client == GNUNET_YES) | ||
3148 | { | ||
3149 | plugin->nat_wait_conns = GNUNET_CONTAINER_multihashmap_create(16); | ||
3150 | GNUNET_assert (plugin->nat_wait_conns != NULL); | ||
3151 | } | ||
3152 | |||
3153 | if (bport != 0) | 2138 | if (bport != 0) |
3154 | GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, | 2139 | GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, |
3155 | "tcp", | 2140 | "tcp", |
@@ -3164,20 +2149,6 @@ libgnunet_plugin_transport_tcp_init (void *cls) | |||
3164 | "tcp", | 2149 | "tcp", |
3165 | _("TCP transport advertises itself as being on port %llu\n"), | 2150 | _("TCP transport advertises itself as being on port %llu\n"), |
3166 | aport); | 2151 | aport); |
3167 | |||
3168 | plugin->hostname_dns = GNUNET_RESOLVER_hostname_resolve (AF_UNSPEC, | ||
3169 | HOSTNAME_RESOLVE_TIMEOUT, | ||
3170 | &process_hostname_ips, | ||
3171 | plugin); | ||
3172 | |||
3173 | if (plugin->external_address != NULL) | ||
3174 | { | ||
3175 | plugin->ext_dns = GNUNET_RESOLVER_ip_get (plugin->external_address, | ||
3176 | AF_INET, | ||
3177 | GNUNET_TIME_UNIT_MINUTES, | ||
3178 | &process_external_ip, | ||
3179 | plugin); | ||
3180 | } | ||
3181 | return api; | 2152 | return api; |
3182 | } | 2153 | } |
3183 | 2154 | ||
@@ -3191,36 +2162,17 @@ libgnunet_plugin_transport_tcp_done (void *cls) | |||
3191 | struct GNUNET_TRANSPORT_PluginFunctions *api = cls; | 2162 | struct GNUNET_TRANSPORT_PluginFunctions *api = cls; |
3192 | struct Plugin *plugin = api->cls; | 2163 | struct Plugin *plugin = api->cls; |
3193 | struct Session *session; | 2164 | struct Session *session; |
3194 | struct LocalAddrList *lal; | ||
3195 | struct TCPProbeContext *tcp_probe; | 2165 | struct TCPProbeContext *tcp_probe; |
3196 | 2166 | ||
3197 | if (plugin->ext_dns != NULL) | ||
3198 | { | ||
3199 | GNUNET_RESOLVER_request_cancel (plugin->ext_dns); | ||
3200 | plugin->ext_dns = NULL; | ||
3201 | } | ||
3202 | while (NULL != (session = plugin->sessions)) | 2167 | while (NULL != (session = plugin->sessions)) |
3203 | disconnect_session (session); | 2168 | disconnect_session (session); |
3204 | if (NULL != plugin->hostname_dns) | ||
3205 | { | ||
3206 | GNUNET_RESOLVER_request_cancel (plugin->hostname_dns); | ||
3207 | plugin->hostname_dns = NULL; | ||
3208 | } | ||
3209 | if (plugin->service != NULL) | 2169 | if (plugin->service != NULL) |
3210 | GNUNET_SERVICE_stop (plugin->service); | 2170 | GNUNET_SERVICE_stop (plugin->service); |
3211 | else | 2171 | else |
3212 | GNUNET_SERVER_destroy (plugin->server); | 2172 | GNUNET_SERVER_destroy (plugin->server); |
3213 | GNUNET_free (plugin->handlers); | 2173 | GNUNET_free (plugin->handlers); |
3214 | while (NULL != (lal = plugin->lal_head)) | 2174 | if (plugin->nat != NULL) |
3215 | { | 2175 | GNUNET_NAT_unregister (plugin->nat); |
3216 | GNUNET_CONTAINER_DLL_remove (plugin->lal_head, | ||
3217 | plugin->lal_tail, | ||
3218 | lal); | ||
3219 | if (lal->nat != NULL) | ||
3220 | GNUNET_NAT_unregister (lal->nat); | ||
3221 | GNUNET_free_non_null (lal->external_nat_address); | ||
3222 | GNUNET_free (lal); | ||
3223 | } | ||
3224 | while (NULL != (tcp_probe = plugin->probe_head)) | 2176 | while (NULL != (tcp_probe = plugin->probe_head)) |
3225 | { | 2177 | { |
3226 | GNUNET_CONTAINER_DLL_remove (plugin->probe_head, | 2178 | GNUNET_CONTAINER_DLL_remove (plugin->probe_head, |
@@ -3229,19 +2181,6 @@ libgnunet_plugin_transport_tcp_done (void *cls) | |||
3229 | GNUNET_CONNECTION_destroy (tcp_probe->sock, GNUNET_NO); | 2181 | GNUNET_CONNECTION_destroy (tcp_probe->sock, GNUNET_NO); |
3230 | GNUNET_free (tcp_probe); | 2182 | GNUNET_free (tcp_probe); |
3231 | } | 2183 | } |
3232 | |||
3233 | if ((plugin->behind_nat == GNUNET_YES) && | ||
3234 | (plugin->enable_nat_server == GNUNET_YES)) | ||
3235 | { | ||
3236 | if (0 != GNUNET_OS_process_kill (plugin->server_proc, SIGTERM)) | ||
3237 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill"); | ||
3238 | GNUNET_OS_process_wait (plugin->server_proc); | ||
3239 | GNUNET_OS_process_close (plugin->server_proc); | ||
3240 | plugin->server_proc = NULL; | ||
3241 | } | ||
3242 | GNUNET_free_non_null(plugin->bind_address); | ||
3243 | GNUNET_free_non_null(plugin->internal_address); | ||
3244 | GNUNET_free_non_null(plugin->external_address); | ||
3245 | GNUNET_free (plugin); | 2184 | GNUNET_free (plugin); |
3246 | GNUNET_free (api); | 2185 | GNUNET_free (api); |
3247 | return NULL; | 2186 | return NULL; |