diff options
-rw-r--r-- | src/transport/plugin_transport_tcp.c | 695 | ||||
-rw-r--r-- | src/transport/plugin_transport_udp.c | 39 | ||||
-rw-r--r-- | src/transport/test_transport_api_tcp_peer1.conf | 1 | ||||
-rw-r--r-- | src/transport/test_transport_api_tcp_peer2.conf | 5 |
4 files changed, 688 insertions, 52 deletions
diff --git a/src/transport/plugin_transport_tcp.c b/src/transport/plugin_transport_tcp.c index f6ba584eb..7fa586588 100644 --- a/src/transport/plugin_transport_tcp.c +++ b/src/transport/plugin_transport_tcp.c | |||
@@ -62,6 +62,50 @@ struct WelcomeMessage | |||
62 | 62 | ||
63 | }; | 63 | }; |
64 | 64 | ||
65 | /** | ||
66 | * Basically a WELCOME message, but with the purpose | ||
67 | * of giving the waiting peer a client handle to use | ||
68 | */ | ||
69 | struct TCP_NAT_ProbeMessage | ||
70 | { | ||
71 | /** | ||
72 | * Type is GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_NAT_PROBE. | ||
73 | */ | ||
74 | struct GNUNET_MessageHeader header; | ||
75 | |||
76 | /** | ||
77 | * Identity of the sender of the message. | ||
78 | */ | ||
79 | struct GNUNET_PeerIdentity clientIdentity; | ||
80 | |||
81 | }; | ||
82 | |||
83 | /** | ||
84 | * Context for sending a NAT probe via TCP. | ||
85 | */ | ||
86 | struct TCPProbeContext | ||
87 | { | ||
88 | /** | ||
89 | * Probe connection. | ||
90 | */ | ||
91 | struct GNUNET_CONNECTION_Handle *sock; | ||
92 | |||
93 | /** | ||
94 | * Message to be sent. | ||
95 | */ | ||
96 | struct TCP_NAT_ProbeMessage message; | ||
97 | |||
98 | /** | ||
99 | * Handle to the transmission. | ||
100 | */ | ||
101 | struct GNUNET_CONNECTION_TransmitHandle *transmit_handle; | ||
102 | |||
103 | /** | ||
104 | * Transport plugin handle. | ||
105 | */ | ||
106 | struct Plugin *plugin; | ||
107 | }; | ||
108 | |||
65 | 109 | ||
66 | /** | 110 | /** |
67 | * Network format for IPv4 addresses. | 111 | * Network format for IPv4 addresses. |
@@ -98,7 +142,6 @@ struct IPv6TcpAddress | |||
98 | 142 | ||
99 | }; | 143 | }; |
100 | 144 | ||
101 | |||
102 | /** | 145 | /** |
103 | * Encapsulation of all of the state of the plugin. | 146 | * Encapsulation of all of the state of the plugin. |
104 | */ | 147 | */ |
@@ -248,6 +291,26 @@ struct Plugin | |||
248 | */ | 291 | */ |
249 | struct GNUNET_CONNECTION_Handle *lsock; | 292 | struct GNUNET_CONNECTION_Handle *lsock; |
250 | 293 | ||
294 | /* | ||
295 | * stdout pipe handle for the gnunet-nat-server process | ||
296 | */ | ||
297 | struct GNUNET_DISK_PipeHandle *server_stdout; | ||
298 | |||
299 | /* | ||
300 | * stdout file handle (for reading) for the gnunet-nat-server process | ||
301 | */ | ||
302 | const struct GNUNET_DISK_FileHandle *server_stdout_handle; | ||
303 | |||
304 | /** | ||
305 | * ID of select gnunet-nat-server stdout read task | ||
306 | */ | ||
307 | GNUNET_SCHEDULER_TaskIdentifier server_read_task; | ||
308 | |||
309 | /** | ||
310 | * The process id of the server process (if behind NAT) | ||
311 | */ | ||
312 | pid_t server_pid; | ||
313 | |||
251 | /** | 314 | /** |
252 | * List of open TCP sessions. | 315 | * List of open TCP sessions. |
253 | */ | 316 | */ |
@@ -275,6 +338,22 @@ struct Plugin | |||
275 | struct GNUNET_RESOLVER_RequestHandle *hostname_dns; | 338 | struct GNUNET_RESOLVER_RequestHandle *hostname_dns; |
276 | 339 | ||
277 | /** | 340 | /** |
341 | * Map of peers we have tried to contact behind a NAT | ||
342 | */ | ||
343 | struct GNUNET_CONTAINER_MultiHashMap *nat_wait_conns; | ||
344 | |||
345 | /** | ||
346 | * The external address given to us by the user. Must be actual | ||
347 | * outside visible address for NAT punching to work. | ||
348 | */ | ||
349 | char *external_address; | ||
350 | |||
351 | /** | ||
352 | * The internal address given to us by the user (or discovered). | ||
353 | */ | ||
354 | char *internal_address; | ||
355 | |||
356 | /** | ||
278 | * ID of task used to update our addresses when one expires. | 357 | * ID of task used to update our addresses when one expires. |
279 | */ | 358 | */ |
280 | GNUNET_SCHEDULER_TaskIdentifier address_update_task; | 359 | GNUNET_SCHEDULER_TaskIdentifier address_update_task; |
@@ -290,6 +369,16 @@ struct Plugin | |||
290 | */ | 369 | */ |
291 | uint16_t adv_port; | 370 | uint16_t adv_port; |
292 | 371 | ||
372 | /** | ||
373 | * Is this transport configured to be behind a NAT? | ||
374 | */ | ||
375 | int behind_nat; | ||
376 | |||
377 | /** | ||
378 | * Is this transport configured to allow connections to NAT'd peers? | ||
379 | */ | ||
380 | int allow_nat; | ||
381 | |||
293 | }; | 382 | }; |
294 | 383 | ||
295 | 384 | ||
@@ -373,25 +462,31 @@ find_session_by_client (struct Plugin *plugin, | |||
373 | return ret; | 462 | return ret; |
374 | } | 463 | } |
375 | 464 | ||
376 | |||
377 | /** | 465 | /** |
378 | * Create a new session. Also queues a welcome message. | 466 | * Create a new session. Also queues a welcome message. |
379 | * | 467 | * |
380 | * @param plugin us | 468 | * @param plugin us |
381 | * @param target peer to connect to | 469 | * @param target peer to connect to |
382 | * @param client client to use | 470 | * @param client client to use |
471 | * @param is_nat this a NAT session, we should wait for a client to | ||
472 | * connect to us from an address, then assign that to | ||
473 | * the session | ||
383 | * @return new session object | 474 | * @return new session object |
384 | */ | 475 | */ |
385 | static struct Session * | 476 | static struct Session * |
386 | create_session (struct Plugin *plugin, | 477 | create_session (struct Plugin *plugin, |
387 | const struct GNUNET_PeerIdentity *target, | 478 | const struct GNUNET_PeerIdentity *target, |
388 | struct GNUNET_SERVER_Client *client) | 479 | struct GNUNET_SERVER_Client *client, int is_nat) |
389 | { | 480 | { |
390 | struct Session *ret; | 481 | struct Session *ret; |
391 | struct PendingMessage *pm; | 482 | struct PendingMessage *pm; |
392 | struct WelcomeMessage welcome; | 483 | struct WelcomeMessage welcome; |
393 | 484 | ||
394 | GNUNET_assert (client != NULL); | 485 | if (is_nat != GNUNET_YES) |
486 | GNUNET_assert (client != NULL); | ||
487 | else | ||
488 | GNUNET_assert (client == NULL); | ||
489 | |||
395 | #if DEBUG_TCP | 490 | #if DEBUG_TCP |
396 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, | 491 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, |
397 | "tcp", | 492 | "tcp", |
@@ -401,8 +496,11 @@ create_session (struct Plugin *plugin, | |||
401 | ret = GNUNET_malloc (sizeof (struct Session)); | 496 | ret = GNUNET_malloc (sizeof (struct Session)); |
402 | ret->last_activity = GNUNET_TIME_absolute_get (); | 497 | ret->last_activity = GNUNET_TIME_absolute_get (); |
403 | ret->plugin = plugin; | 498 | ret->plugin = plugin; |
404 | ret->next = plugin->sessions; | 499 | if (is_nat != GNUNET_YES) /* If not a NAT WAIT conn, add it to global list */ |
405 | plugin->sessions = ret; | 500 | { |
501 | ret->next = plugin->sessions; | ||
502 | plugin->sessions = ret; | ||
503 | } | ||
406 | ret->client = client; | 504 | ret->client = client; |
407 | ret->target = *target; | 505 | ret->target = *target; |
408 | ret->expecting_welcome = GNUNET_YES; | 506 | ret->expecting_welcome = GNUNET_YES; |
@@ -421,10 +519,11 @@ create_session (struct Plugin *plugin, | |||
421 | GNUNET_CONTAINER_DLL_insert (ret->pending_messages_head, | 519 | GNUNET_CONTAINER_DLL_insert (ret->pending_messages_head, |
422 | ret->pending_messages_tail, | 520 | ret->pending_messages_tail, |
423 | pm); | 521 | pm); |
424 | GNUNET_STATISTICS_update (plugin->env->stats, | 522 | if (is_nat != GNUNET_YES) |
425 | gettext_noop ("# TCP sessions active"), | 523 | GNUNET_STATISTICS_update (plugin->env->stats, |
426 | 1, | 524 | gettext_noop ("# TCP sessions active"), |
427 | GNUNET_NO); | 525 | 1, |
526 | GNUNET_NO); | ||
428 | return ret; | 527 | return ret; |
429 | } | 528 | } |
430 | 529 | ||
@@ -724,6 +823,54 @@ select_better_session (struct Session *s1, | |||
724 | 823 | ||
725 | 824 | ||
726 | /** | 825 | /** |
826 | * We learned about a peer (possibly behind NAT) so run the | ||
827 | * gnunet-nat-client to send dummy ICMP responses | ||
828 | * | ||
829 | * @param plugin the plugin for this transport | ||
830 | * @param addr the address of the peer | ||
831 | * @param addrlen the length of the address | ||
832 | */ | ||
833 | void | ||
834 | run_gnunet_nat_client (struct Plugin *plugin, const char *addr, size_t addrlen) | ||
835 | { | ||
836 | char inet4[INET_ADDRSTRLEN]; | ||
837 | char *address_as_string; | ||
838 | char *port_as_string; | ||
839 | pid_t pid; | ||
840 | const struct sockaddr *sa = (const struct sockaddr *)addr; | ||
841 | |||
842 | if (addrlen < sizeof (struct sockaddr)) | ||
843 | return; | ||
844 | switch (sa->sa_family) | ||
845 | { | ||
846 | case AF_INET: | ||
847 | if (addrlen != sizeof (struct sockaddr_in)) | ||
848 | return; | ||
849 | inet_ntop (AF_INET, | ||
850 | &((struct sockaddr_in *) sa)->sin_addr, | ||
851 | inet4, INET_ADDRSTRLEN); | ||
852 | address_as_string = GNUNET_strdup (inet4); | ||
853 | break; | ||
854 | case AF_INET6: | ||
855 | default: | ||
856 | return; | ||
857 | } | ||
858 | |||
859 | GNUNET_asprintf(&port_as_string, "%d", plugin->adv_port); | ||
860 | #if DEBUG_UDP_NAT | ||
861 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "tcp", | ||
862 | _("Running gnunet-nat-client with arguments: %s %s %d\n"), plugin->external_address, address_as_string, plugin->adv_port); | ||
863 | #endif | ||
864 | |||
865 | /* Start the client process */ | ||
866 | pid = GNUNET_OS_start_process(NULL, NULL, "gnunet-nat-client", "gnunet-nat-client", plugin->external_address, address_as_string, port_as_string, NULL); | ||
867 | GNUNET_free(address_as_string); | ||
868 | GNUNET_free(port_as_string); | ||
869 | GNUNET_OS_process_wait (pid); | ||
870 | } | ||
871 | |||
872 | |||
873 | /** | ||
727 | * Function that can be used by the transport service to transmit | 874 | * Function that can be used by the transport service to transmit |
728 | * a message using the plugin. Note that in the case of a | 875 | * a message using the plugin. Note that in the case of a |
729 | * peer disconnecting, the continuation MUST be called | 876 | * peer disconnecting, the continuation MUST be called |
@@ -757,7 +904,7 @@ select_better_session (struct Session *s1, | |||
757 | * @param cont_cls closure for cont | 904 | * @param cont_cls closure for cont |
758 | * @return number of bytes used (on the physical network, with overheads); | 905 | * @return number of bytes used (on the physical network, with overheads); |
759 | * -1 on hard errors (i.e. address invalid); 0 is a legal value | 906 | * -1 on hard errors (i.e. address invalid); 0 is a legal value |
760 | * and does NOT mean that the message was not transmitted (DV) | 907 | * and does NOT mean that the message was not transmitted (DV and NAT) |
761 | */ | 908 | */ |
762 | static ssize_t | 909 | static ssize_t |
763 | tcp_plugin_send (void *cls, | 910 | tcp_plugin_send (void *cls, |
@@ -784,6 +931,7 @@ tcp_plugin_send (void *cls, | |||
784 | struct sockaddr_in6 a6; | 931 | struct sockaddr_in6 a6; |
785 | const struct IPv4TcpAddress *t4; | 932 | const struct IPv4TcpAddress *t4; |
786 | const struct IPv6TcpAddress *t6; | 933 | const struct IPv6TcpAddress *t6; |
934 | unsigned int is_natd; | ||
787 | 935 | ||
788 | GNUNET_STATISTICS_update (plugin->env->stats, | 936 | GNUNET_STATISTICS_update (plugin->env->stats, |
789 | gettext_noop ("# bytes TCP was asked to transmit"), | 937 | gettext_noop ("# bytes TCP was asked to transmit"), |
@@ -792,6 +940,7 @@ tcp_plugin_send (void *cls, | |||
792 | /* FIXME: we could do this cheaper with a hash table | 940 | /* FIXME: we could do this cheaper with a hash table |
793 | where we could restrict the iteration to entries that match | 941 | where we could restrict the iteration to entries that match |
794 | the target peer... */ | 942 | the target peer... */ |
943 | is_natd = GNUNET_NO; | ||
795 | if (session == NULL) | 944 | if (session == NULL) |
796 | { | 945 | { |
797 | cand_session = NULL; | 946 | cand_session = NULL; |
@@ -860,6 +1009,8 @@ tcp_plugin_send (void *cls, | |||
860 | #endif | 1009 | #endif |
861 | a6.sin6_family = AF_INET6; | 1010 | a6.sin6_family = AF_INET6; |
862 | a6.sin6_port = t6->t6_port; | 1011 | a6.sin6_port = t6->t6_port; |
1012 | if (t6->t6_port == 0) | ||
1013 | is_natd = GNUNET_YES; | ||
863 | memcpy (&a6.sin6_addr, | 1014 | memcpy (&a6.sin6_addr, |
864 | &t6->ipv6_addr, | 1015 | &t6->ipv6_addr, |
865 | sizeof (struct in6_addr)); | 1016 | sizeof (struct in6_addr)); |
@@ -876,6 +1027,8 @@ tcp_plugin_send (void *cls, | |||
876 | #endif | 1027 | #endif |
877 | a4.sin_family = AF_INET; | 1028 | a4.sin_family = AF_INET; |
878 | a4.sin_port = t4->t_port; | 1029 | a4.sin_port = t4->t_port; |
1030 | if (t4->t_port == 0) | ||
1031 | is_natd = GNUNET_YES; | ||
879 | a4.sin_addr.s_addr = t4->ipv4_addr; | 1032 | a4.sin_addr.s_addr = t4->ipv4_addr; |
880 | sb = &a4; | 1033 | sb = &a4; |
881 | sbs = sizeof (a4); | 1034 | sbs = sizeof (a4); |
@@ -889,6 +1042,47 @@ tcp_plugin_send (void *cls, | |||
889 | GNUNET_break (0); | 1042 | GNUNET_break (0); |
890 | return -1; | 1043 | return -1; |
891 | } | 1044 | } |
1045 | |||
1046 | if ((is_natd == GNUNET_YES) && (addrlen == sizeof (struct IPv6TcpAddress))) | ||
1047 | return -1; /* NAT client only works with IPv4 addresses */ | ||
1048 | |||
1049 | if ( (plugin->allow_nat == GNUNET_YES) && (is_natd == GNUNET_YES) && | ||
1050 | (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains(plugin->nat_wait_conns, &target->hashPubKey))) | ||
1051 | { | ||
1052 | session = create_session (plugin, | ||
1053 | target, | ||
1054 | NULL, is_natd); | ||
1055 | |||
1056 | /* create new message entry */ | ||
1057 | pm = GNUNET_malloc (sizeof (struct PendingMessage) + msgbuf_size); | ||
1058 | pm->msg = (const char*) &pm[1]; | ||
1059 | memcpy (&pm[1], msg, msgbuf_size); | ||
1060 | pm->message_size = msgbuf_size; | ||
1061 | pm->timeout = GNUNET_TIME_relative_to_absolute (timeout); | ||
1062 | pm->transmit_cont = cont; | ||
1063 | pm->transmit_cont_cls = cont_cls; | ||
1064 | |||
1065 | /* append pm to pending_messages list */ | ||
1066 | GNUNET_CONTAINER_DLL_insert_after (session->pending_messages_head, | ||
1067 | session->pending_messages_tail, | ||
1068 | session->pending_messages_tail, | ||
1069 | pm); | ||
1070 | |||
1071 | GNUNET_CONTAINER_multihashmap_put(plugin->nat_wait_conns, &target->hashPubKey, session, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY); | ||
1072 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, | ||
1073 | "tcp", | ||
1074 | "Created NAT WAIT connection to `%4s' at `%s'\n", | ||
1075 | GNUNET_i2s (target), | ||
1076 | GNUNET_a2s (sb, sbs)); | ||
1077 | |||
1078 | run_gnunet_nat_client(plugin, addr, addrlen); | ||
1079 | return 0; | ||
1080 | } | ||
1081 | else if ((plugin->allow_nat == GNUNET_YES) && (is_natd == GNUNET_YES) && (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains(plugin->nat_wait_conns, &target->hashPubKey))) | ||
1082 | { | ||
1083 | /* Only do one NAT punch attempt per peer identity */ | ||
1084 | return -1; | ||
1085 | } | ||
892 | sa = GNUNET_CONNECTION_create_from_sockaddr (plugin->env->sched, | 1086 | sa = GNUNET_CONNECTION_create_from_sockaddr (plugin->env->sched, |
893 | af, sb, sbs, | 1087 | af, sb, sbs, |
894 | GNUNET_SERVER_MAX_MESSAGE_SIZE); | 1088 | GNUNET_SERVER_MAX_MESSAGE_SIZE); |
@@ -917,7 +1111,7 @@ tcp_plugin_send (void *cls, | |||
917 | session = create_session (plugin, | 1111 | session = create_session (plugin, |
918 | target, | 1112 | target, |
919 | GNUNET_SERVER_connect_socket (plugin->server, | 1113 | GNUNET_SERVER_connect_socket (plugin->server, |
920 | sa)); | 1114 | sa), is_natd); |
921 | session->connect_addr = GNUNET_malloc (addrlen); | 1115 | session->connect_addr = GNUNET_malloc (addrlen); |
922 | memcpy (session->connect_addr, | 1116 | memcpy (session->connect_addr, |
923 | addr, | 1117 | addr, |
@@ -1194,6 +1388,107 @@ tcp_plugin_check_address (void *cls, void *addr, size_t addrlen) | |||
1194 | return GNUNET_OK; | 1388 | return GNUNET_OK; |
1195 | } | 1389 | } |
1196 | 1390 | ||
1391 | /** | ||
1392 | * We've received a nat probe from this peer via TCP. Finish | ||
1393 | * creating the client session and resume sending of queued | ||
1394 | * messages. | ||
1395 | * | ||
1396 | * @param cls closure | ||
1397 | * @param client identification of the client | ||
1398 | * @param message the actual message | ||
1399 | */ | ||
1400 | static void | ||
1401 | handle_tcp_nat_probe (void *cls, | ||
1402 | struct GNUNET_SERVER_Client *client, | ||
1403 | const struct GNUNET_MessageHeader *message) | ||
1404 | { | ||
1405 | struct Plugin *plugin = cls; | ||
1406 | struct Session *session; | ||
1407 | struct TCP_NAT_ProbeMessage *tcp_nat_probe; | ||
1408 | size_t alen; | ||
1409 | void *vaddr; | ||
1410 | struct IPv4TcpAddress *t4; | ||
1411 | struct IPv6TcpAddress *t6; | ||
1412 | const struct sockaddr_in *s4; | ||
1413 | const struct sockaddr_in6 *s6; | ||
1414 | |||
1415 | /* We have received a TCP NAT probe, meaning we (hopefully) initiated | ||
1416 | * a connection to this peer by running gnunet-nat-client. This peer | ||
1417 | * received the punch message and now wants us to use the new connection | ||
1418 | * as the default for that peer. Do so and then send a WELCOME message | ||
1419 | * so we can really be connected! | ||
1420 | */ | ||
1421 | if (ntohs(message->size) != sizeof(struct TCP_NAT_ProbeMessage)) | ||
1422 | { | ||
1423 | GNUNET_break_op(0); | ||
1424 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
1425 | return; | ||
1426 | } | ||
1427 | tcp_nat_probe = (struct TCP_NAT_ProbeMessage *)message; | ||
1428 | |||
1429 | if (GNUNET_CONTAINER_multihashmap_contains(plugin->nat_wait_conns, &tcp_nat_probe->clientIdentity.hashPubKey) == GNUNET_YES) | ||
1430 | { | ||
1431 | session = GNUNET_CONTAINER_multihashmap_get(plugin->nat_wait_conns, &tcp_nat_probe->clientIdentity.hashPubKey); | ||
1432 | GNUNET_assert(session != NULL); | ||
1433 | GNUNET_SERVER_client_keep (client); | ||
1434 | session->client = client; | ||
1435 | |||
1436 | if (GNUNET_OK == | ||
1437 | GNUNET_SERVER_client_get_address (client, &vaddr, &alen)) | ||
1438 | { | ||
1439 | #if DEBUG_TCP | ||
1440 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, | ||
1441 | "tcp", | ||
1442 | "Found address `%s' for incoming connection %p\n", | ||
1443 | GNUNET_a2s (vaddr, alen), | ||
1444 | client); | ||
1445 | #endif | ||
1446 | if (alen == sizeof (struct sockaddr_in)) | ||
1447 | { | ||
1448 | s4 = vaddr; | ||
1449 | t4 = GNUNET_malloc (sizeof (struct IPv4TcpAddress)); | ||
1450 | t4->t_port = s4->sin_port; | ||
1451 | t4->ipv4_addr = s4->sin_addr.s_addr; | ||
1452 | session->connect_addr = t4; | ||
1453 | session->connect_alen = sizeof (struct IPv4TcpAddress); | ||
1454 | } | ||
1455 | else if (alen == sizeof (struct sockaddr_in6)) | ||
1456 | { | ||
1457 | s6 = vaddr; | ||
1458 | t6 = GNUNET_malloc (sizeof (struct IPv6TcpAddress)); | ||
1459 | t6->t6_port = s6->sin6_port; | ||
1460 | memcpy (&t6->ipv6_addr, | ||
1461 | &s6->sin6_addr, | ||
1462 | sizeof (struct in6_addr)); | ||
1463 | session->connect_addr = t6; | ||
1464 | session->connect_alen = sizeof (struct IPv6TcpAddress); | ||
1465 | } | ||
1466 | |||
1467 | session->connect_addr = GNUNET_malloc (alen); | ||
1468 | memcpy (session->connect_addr, | ||
1469 | vaddr, | ||
1470 | alen); | ||
1471 | session->connect_alen = alen; | ||
1472 | GNUNET_free (vaddr); | ||
1473 | } | ||
1474 | else | ||
1475 | { | ||
1476 | /* FIXME: free partial session? */ | ||
1477 | } | ||
1478 | |||
1479 | |||
1480 | session->next = plugin->sessions; | ||
1481 | plugin->sessions = session; | ||
1482 | |||
1483 | GNUNET_STATISTICS_update (plugin->env->stats, | ||
1484 | gettext_noop ("# TCP sessions active"), | ||
1485 | 1, | ||
1486 | GNUNET_NO); | ||
1487 | /*GNUNET_SERVER_connect_socket (plugin->server, | ||
1488 | client);*/ | ||
1489 | } | ||
1490 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
1491 | } | ||
1197 | 1492 | ||
1198 | /** | 1493 | /** |
1199 | * We've received a welcome from this peer via TCP. Possibly create a | 1494 | * We've received a welcome from this peer via TCP. Possibly create a |
@@ -1235,7 +1530,7 @@ handle_tcp_welcome (void *cls, | |||
1235 | { | 1530 | { |
1236 | GNUNET_SERVER_client_keep (client); | 1531 | GNUNET_SERVER_client_keep (client); |
1237 | session = create_session (plugin, | 1532 | session = create_session (plugin, |
1238 | &wm->clientIdentity, client); | 1533 | &wm->clientIdentity, client, GNUNET_NO); |
1239 | session->inbound = GNUNET_YES; | 1534 | session->inbound = GNUNET_YES; |
1240 | if (GNUNET_OK == | 1535 | if (GNUNET_OK == |
1241 | GNUNET_SERVER_client_get_address (client, &vaddr, &alen)) | 1536 | GNUNET_SERVER_client_get_address (client, &vaddr, &alen)) |
@@ -1342,14 +1637,14 @@ handle_tcp_data (void *cls, | |||
1342 | struct Session *session; | 1637 | struct Session *session; |
1343 | struct GNUNET_TIME_Relative delay; | 1638 | struct GNUNET_TIME_Relative delay; |
1344 | 1639 | ||
1345 | if (GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_WELCOME == ntohs(message->type)) | 1640 | if ((GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_WELCOME == ntohs(message->type)) || (ntohs(message->type) == GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_NAT_PROBE)) |
1346 | { | 1641 | { |
1347 | /* We don't want to propagate WELCOME messages up! */ | 1642 | /* We don't want to propagate WELCOME messages up! */ |
1348 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | 1643 | GNUNET_SERVER_receive_done (client, GNUNET_OK); |
1349 | return; | 1644 | return; |
1350 | } | 1645 | } |
1351 | session = find_session_by_client (plugin, client); | 1646 | session = find_session_by_client (plugin, client); |
1352 | if ( (NULL == session) || (GNUNET_NO != session->expecting_welcome)) | 1647 | if ( (NULL == session) || (GNUNET_YES == session->expecting_welcome)) |
1353 | { | 1648 | { |
1354 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | 1649 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); |
1355 | return; | 1650 | return; |
@@ -1386,6 +1681,7 @@ handle_tcp_data (void *cls, | |||
1386 | static struct GNUNET_SERVER_MessageHandler my_handlers[] = { | 1681 | static struct GNUNET_SERVER_MessageHandler my_handlers[] = { |
1387 | {&handle_tcp_welcome, NULL, GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_WELCOME, | 1682 | {&handle_tcp_welcome, NULL, GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_WELCOME, |
1388 | sizeof (struct WelcomeMessage)}, | 1683 | sizeof (struct WelcomeMessage)}, |
1684 | {&handle_tcp_nat_probe, NULL, GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_NAT_PROBE, sizeof (struct TCP_NAT_ProbeMessage)}, | ||
1389 | {&handle_tcp_data, NULL, GNUNET_MESSAGE_TYPE_ALL, 0}, | 1685 | {&handle_tcp_data, NULL, GNUNET_MESSAGE_TYPE_ALL, 0}, |
1390 | {NULL, NULL, 0, 0} | 1686 | {NULL, NULL, 0, 0} |
1391 | }; | 1687 | }; |
@@ -1453,7 +1749,10 @@ process_interfaces (void *cls, | |||
1453 | if (af == AF_INET) | 1749 | if (af == AF_INET) |
1454 | { | 1750 | { |
1455 | t4.ipv4_addr = ((struct sockaddr_in *) addr)->sin_addr.s_addr; | 1751 | t4.ipv4_addr = ((struct sockaddr_in *) addr)->sin_addr.s_addr; |
1456 | t4.t_port = htons (plugin->adv_port); | 1752 | if (plugin->behind_nat) |
1753 | t4.t_port = htons(0); | ||
1754 | else | ||
1755 | t4.t_port = htons (plugin->adv_port); | ||
1457 | arg = &t4; | 1756 | arg = &t4; |
1458 | args = sizeof (t4); | 1757 | args = sizeof (t4); |
1459 | } | 1758 | } |
@@ -1467,7 +1766,10 @@ process_interfaces (void *cls, | |||
1467 | memcpy (&t6.ipv6_addr, | 1766 | memcpy (&t6.ipv6_addr, |
1468 | &((struct sockaddr_in6 *) addr)->sin6_addr, | 1767 | &((struct sockaddr_in6 *) addr)->sin6_addr, |
1469 | sizeof (struct in6_addr)); | 1768 | sizeof (struct in6_addr)); |
1470 | t6.t6_port = htons (plugin->adv_port); | 1769 | if (plugin->behind_nat) |
1770 | t6.t6_port = htons(0); | ||
1771 | else | ||
1772 | t6.t6_port = htons (plugin->adv_port); | ||
1471 | arg = &t6; | 1773 | arg = &t6; |
1472 | args = sizeof (t6); | 1774 | args = sizeof (t6); |
1473 | } | 1775 | } |
@@ -1508,9 +1810,267 @@ process_hostname_ips (void *cls, | |||
1508 | plugin->hostname_dns = NULL; | 1810 | plugin->hostname_dns = NULL; |
1509 | return; | 1811 | return; |
1510 | } | 1812 | } |
1813 | /* FIXME: Can we figure out our external address here so it doesn't need to be user specified? */ | ||
1511 | process_interfaces (plugin, "<hostname>", GNUNET_YES, addr, addrlen); | 1814 | process_interfaces (plugin, "<hostname>", GNUNET_YES, addr, addrlen); |
1512 | } | 1815 | } |
1513 | 1816 | ||
1817 | /** | ||
1818 | * We can now send a probe message, copy into buffer to really send. | ||
1819 | * | ||
1820 | * @param cls closure, a struct TCPProbeContext | ||
1821 | * @param size max size to copy | ||
1822 | * @param buf buffer to copy message to | ||
1823 | */ | ||
1824 | static size_t notify_send_probe (void *cls, | ||
1825 | size_t size, void *buf) | ||
1826 | { | ||
1827 | struct TCPProbeContext *tcp_probe_ctx = cls; | ||
1828 | |||
1829 | if (buf == NULL) | ||
1830 | { | ||
1831 | return 0; | ||
1832 | } | ||
1833 | |||
1834 | GNUNET_assert(size >= sizeof(tcp_probe_ctx->message)); | ||
1835 | memcpy(buf, &tcp_probe_ctx->message, sizeof(tcp_probe_ctx->message)); | ||
1836 | GNUNET_SERVER_connect_socket (tcp_probe_ctx->plugin->server, | ||
1837 | tcp_probe_ctx->sock); | ||
1838 | |||
1839 | GNUNET_free(tcp_probe_ctx); | ||
1840 | return sizeof(tcp_probe_ctx->message); | ||
1841 | } | ||
1842 | |||
1843 | /* | ||
1844 | * @param cls the plugin handle | ||
1845 | * @param tc the scheduling context (for rescheduling this function again) | ||
1846 | * | ||
1847 | * We have been notified that gnunet-nat-server has written something to stdout. | ||
1848 | * Handle the output, then reschedule this function to be called again once | ||
1849 | * more is available. | ||
1850 | * | ||
1851 | */ | ||
1852 | static void | ||
1853 | tcp_plugin_server_read (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
1854 | { | ||
1855 | struct Plugin *plugin = cls; | ||
1856 | char mybuf[40]; | ||
1857 | ssize_t bytes; | ||
1858 | memset(&mybuf, 0, sizeof(mybuf)); | ||
1859 | int i; | ||
1860 | int port; | ||
1861 | char *port_start; | ||
1862 | struct sockaddr_in in_addr; | ||
1863 | struct TCPProbeContext *tcp_probe_ctx; | ||
1864 | struct GNUNET_CONNECTION_Handle *sock; | ||
1865 | |||
1866 | if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN) | ||
1867 | return; | ||
1868 | |||
1869 | bytes = GNUNET_DISK_file_read(plugin->server_stdout_handle, &mybuf, sizeof(mybuf)); | ||
1870 | |||
1871 | if (bytes < 1) | ||
1872 | { | ||
1873 | #if DEBUG_UDP_NAT | ||
1874 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "tcp", | ||
1875 | _("Finished reading from server stdout with code: %d\n"), bytes); | ||
1876 | #endif | ||
1877 | return; | ||
1878 | } | ||
1879 | |||
1880 | port = 0; | ||
1881 | port_start = NULL; | ||
1882 | for (i = 0; i < sizeof(mybuf); i++) | ||
1883 | { | ||
1884 | if (mybuf[i] == '\n') | ||
1885 | mybuf[i] = '\0'; | ||
1886 | |||
1887 | if ((mybuf[i] == ':') && (i + 1 < sizeof(mybuf))) | ||
1888 | { | ||
1889 | mybuf[i] = '\0'; | ||
1890 | port_start = &mybuf[i + 1]; | ||
1891 | } | ||
1892 | } | ||
1893 | |||
1894 | if (port_start != NULL) | ||
1895 | port = atoi(port_start); | ||
1896 | else | ||
1897 | { | ||
1898 | plugin->server_read_task = | ||
1899 | GNUNET_SCHEDULER_add_read_file (plugin->env->sched, | ||
1900 | GNUNET_TIME_UNIT_FOREVER_REL, | ||
1901 | plugin->server_stdout_handle, &tcp_plugin_server_read, plugin); | ||
1902 | return; | ||
1903 | } | ||
1904 | |||
1905 | #if DEBUG_UDP_NAT | ||
1906 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "tcp", | ||
1907 | _("nat-server-read read: %s port %d\n"), &mybuf, port); | ||
1908 | #endif | ||
1909 | |||
1910 | |||
1911 | if (inet_pton(AF_INET, &mybuf[0], &in_addr.sin_addr) != 1) | ||
1912 | { | ||
1913 | |||
1914 | GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, "tcp", | ||
1915 | _("nat-server-read malformed address\n"), &mybuf, port); | ||
1916 | |||
1917 | plugin->server_read_task = | ||
1918 | GNUNET_SCHEDULER_add_read_file (plugin->env->sched, | ||
1919 | GNUNET_TIME_UNIT_FOREVER_REL, | ||
1920 | plugin->server_stdout_handle, &tcp_plugin_server_read, plugin); | ||
1921 | return; | ||
1922 | } | ||
1923 | |||
1924 | /** | ||
1925 | * We have received an ICMP response, ostensibly from a non-NAT'd peer | ||
1926 | * that wants to connect to us! Send a message to establish a connection. | ||
1927 | */ | ||
1928 | sock = GNUNET_CONNECTION_create_from_sockaddr (plugin->env->sched, AF_INET, (struct sockaddr *)&in_addr, | ||
1929 | sizeof(in_addr), GNUNET_SERVER_MAX_MESSAGE_SIZE); | ||
1930 | |||
1931 | if (sock == NULL) | ||
1932 | { | ||
1933 | plugin->server_read_task = | ||
1934 | GNUNET_SCHEDULER_add_read_file (plugin->env->sched, | ||
1935 | GNUNET_TIME_UNIT_FOREVER_REL, | ||
1936 | plugin->server_stdout_handle, &tcp_plugin_server_read, plugin); | ||
1937 | return; | ||
1938 | } | ||
1939 | else | ||
1940 | { | ||
1941 | tcp_probe_ctx = GNUNET_malloc(sizeof(struct TCPProbeContext)); | ||
1942 | |||
1943 | tcp_probe_ctx->message.header.size = htons(sizeof(struct TCP_NAT_ProbeMessage)); | ||
1944 | tcp_probe_ctx->message.header.type = htons(GNUNET_MESSAGE_TYPE_TRANSPORT_TCP_NAT_PROBE); | ||
1945 | memcpy(&tcp_probe_ctx->message.clientIdentity, plugin->env->my_identity, sizeof(struct GNUNET_PeerIdentity)); | ||
1946 | tcp_probe_ctx->plugin = plugin; | ||
1947 | |||
1948 | tcp_probe_ctx->transmit_handle = GNUNET_CONNECTION_notify_transmit_ready (sock, | ||
1949 | ntohs(tcp_probe_ctx->message.header.size), | ||
1950 | GNUNET_TIME_UNIT_FOREVER_REL, | ||
1951 | ¬ify_send_probe, tcp_probe_ctx); | ||
1952 | |||
1953 | } | ||
1954 | |||
1955 | plugin->server_read_task = | ||
1956 | GNUNET_SCHEDULER_add_read_file (plugin->env->sched, | ||
1957 | GNUNET_TIME_UNIT_FOREVER_REL, | ||
1958 | plugin->server_stdout_handle, &tcp_plugin_server_read, plugin); | ||
1959 | } | ||
1960 | |||
1961 | /** | ||
1962 | * Start the gnunet-nat-server process for users behind NAT. | ||
1963 | * | ||
1964 | * @param plugin the transport plugin | ||
1965 | * | ||
1966 | * @return GNUNET_YES if process was started, GNUNET_SYSERR on error | ||
1967 | */ | ||
1968 | static int | ||
1969 | tcp_transport_start_nat_server(struct Plugin *plugin) | ||
1970 | { | ||
1971 | |||
1972 | plugin->server_stdout = GNUNET_DISK_pipe(GNUNET_YES); | ||
1973 | if (plugin->server_stdout == NULL) | ||
1974 | return GNUNET_SYSERR; | ||
1975 | |||
1976 | #if DEBUG_TCP_NAT | ||
1977 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, | ||
1978 | "tcp", | ||
1979 | "Starting gnunet-nat-server process cmd: %s %s\n", "gnunet-nat-server", plugin->internal_address); | ||
1980 | #endif | ||
1981 | /* Start the server process */ | ||
1982 | plugin->server_pid = GNUNET_OS_start_process(NULL, plugin->server_stdout, "gnunet-nat-server", "gnunet-nat-server", plugin->internal_address, NULL); | ||
1983 | if (plugin->server_pid == GNUNET_SYSERR) | ||
1984 | { | ||
1985 | #if DEBUG_TCP_NAT | ||
1986 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, | ||
1987 | "tcp", | ||
1988 | "Failed to start gnunet-nat-server process\n"); | ||
1989 | #endif | ||
1990 | return GNUNET_SYSERR; | ||
1991 | } | ||
1992 | /* Close the write end of the read pipe */ | ||
1993 | GNUNET_DISK_pipe_close_end(plugin->server_stdout, GNUNET_DISK_PIPE_END_WRITE); | ||
1994 | |||
1995 | plugin->server_stdout_handle = GNUNET_DISK_pipe_handle(plugin->server_stdout, GNUNET_DISK_PIPE_END_READ); | ||
1996 | plugin->server_read_task = | ||
1997 | GNUNET_SCHEDULER_add_read_file (plugin->env->sched, | ||
1998 | GNUNET_TIME_UNIT_FOREVER_REL, | ||
1999 | plugin->server_stdout_handle, &tcp_plugin_server_read, plugin); | ||
2000 | return GNUNET_YES; | ||
2001 | } | ||
2002 | |||
2003 | /** | ||
2004 | * Return the actual path to a file found in the current | ||
2005 | * PATH environment variable. | ||
2006 | * | ||
2007 | * @param binary the name of the file to find | ||
2008 | */ | ||
2009 | static char * | ||
2010 | get_path_from_PATH (char *binary) | ||
2011 | { | ||
2012 | char *path; | ||
2013 | char *pos; | ||
2014 | char *end; | ||
2015 | char *buf; | ||
2016 | const char *p; | ||
2017 | |||
2018 | p = getenv ("PATH"); | ||
2019 | if (p == NULL) | ||
2020 | return NULL; | ||
2021 | path = GNUNET_strdup (p); /* because we write on it */ | ||
2022 | buf = GNUNET_malloc (strlen (path) + 20); | ||
2023 | pos = path; | ||
2024 | |||
2025 | while (NULL != (end = strchr (pos, ':'))) | ||
2026 | { | ||
2027 | *end = '\0'; | ||
2028 | sprintf (buf, "%s/%s", pos, binary); | ||
2029 | if (GNUNET_DISK_file_test (buf) == GNUNET_YES) | ||
2030 | { | ||
2031 | GNUNET_free (path); | ||
2032 | return buf; | ||
2033 | } | ||
2034 | pos = end + 1; | ||
2035 | } | ||
2036 | sprintf (buf, "%s/%s", pos, binary); | ||
2037 | if (GNUNET_DISK_file_test (buf) == GNUNET_YES) | ||
2038 | { | ||
2039 | GNUNET_free (path); | ||
2040 | return buf; | ||
2041 | } | ||
2042 | GNUNET_free (buf); | ||
2043 | GNUNET_free (path); | ||
2044 | return NULL; | ||
2045 | } | ||
2046 | |||
2047 | /** | ||
2048 | * Check whether the suid bit is set on a file. | ||
2049 | * Attempts to find the file using the current | ||
2050 | * PATH environment variable as a search path. | ||
2051 | * | ||
2052 | * @param binary the name of the file to check | ||
2053 | */ | ||
2054 | static int | ||
2055 | check_gnunet_nat_binary(char *binary) | ||
2056 | { | ||
2057 | struct stat statbuf; | ||
2058 | char *p; | ||
2059 | |||
2060 | p = get_path_from_PATH (binary); | ||
2061 | if (p == NULL) | ||
2062 | return GNUNET_NO; | ||
2063 | if (0 != STAT (p, &statbuf)) | ||
2064 | { | ||
2065 | GNUNET_free (p); | ||
2066 | return GNUNET_SYSERR; | ||
2067 | } | ||
2068 | GNUNET_free (p); | ||
2069 | if ( (0 != (statbuf.st_mode & S_ISUID)) && | ||
2070 | (statbuf.st_uid == 0) ) | ||
2071 | return GNUNET_YES; | ||
2072 | return GNUNET_NO; | ||
2073 | } | ||
1514 | 2074 | ||
1515 | /** | 2075 | /** |
1516 | * Entry point for the plugin. | 2076 | * Entry point for the plugin. |
@@ -1528,6 +2088,10 @@ libgnunet_plugin_transport_tcp_init (void *cls) | |||
1528 | unsigned long long aport; | 2088 | unsigned long long aport; |
1529 | unsigned long long bport; | 2089 | unsigned long long bport; |
1530 | unsigned int i; | 2090 | unsigned int i; |
2091 | int behind_nat; | ||
2092 | int allow_nat; | ||
2093 | char *internal_address; | ||
2094 | char *external_address; | ||
1531 | 2095 | ||
1532 | service = GNUNET_SERVICE_start ("transport-tcp", env->sched, env->cfg); | 2096 | service = GNUNET_SERVICE_start ("transport-tcp", env->sched, env->cfg); |
1533 | if (service == NULL) | 2097 | if (service == NULL) |
@@ -1539,6 +2103,73 @@ libgnunet_plugin_transport_tcp_init (void *cls) | |||
1539 | "tcp"); | 2103 | "tcp"); |
1540 | return NULL; | 2104 | return NULL; |
1541 | } | 2105 | } |
2106 | |||
2107 | if (GNUNET_YES == GNUNET_CONFIGURATION_get_value_yesno (env->cfg, | ||
2108 | "transport-tcp", | ||
2109 | "BEHIND_NAT")) | ||
2110 | { | ||
2111 | /* We are behind nat (according to the user) */ | ||
2112 | if (check_gnunet_nat_binary("gnunet-nat-server") == GNUNET_YES) | ||
2113 | behind_nat = GNUNET_YES; | ||
2114 | else | ||
2115 | { | ||
2116 | behind_nat = GNUNET_NO; | ||
2117 | GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, "tcp", "Configuration specified you are behind a NAT, but gnunet-nat-server is not installed properly (suid bit not set)!\n"); | ||
2118 | } | ||
2119 | } | ||
2120 | else | ||
2121 | behind_nat = GNUNET_NO; /* We are not behind nat! */ | ||
2122 | |||
2123 | if (GNUNET_YES == GNUNET_CONFIGURATION_get_value_yesno (env->cfg, | ||
2124 | "transport-tcp", | ||
2125 | "ALLOW_NAT")) | ||
2126 | { | ||
2127 | if (check_gnunet_nat_binary("gnunet-nat-client") == GNUNET_YES) | ||
2128 | allow_nat = GNUNET_YES; /* We will try to connect to NAT'd peers */ | ||
2129 | else | ||
2130 | { | ||
2131 | allow_nat = GNUNET_NO; | ||
2132 | GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, "tcp", "Configuration specified you want to connect to NAT'd peers, but gnunet-nat-client is not installed properly (suid bit not set)!\n"); | ||
2133 | } | ||
2134 | |||
2135 | } | ||
2136 | else | ||
2137 | allow_nat = GNUNET_NO; /* We don't want to try to help NAT'd peers */ | ||
2138 | |||
2139 | external_address = NULL; | ||
2140 | if (((GNUNET_YES == behind_nat) || (GNUNET_YES == allow_nat)) && (GNUNET_OK != | ||
2141 | GNUNET_CONFIGURATION_get_value_string (env->cfg, | ||
2142 | "transport-tcp", | ||
2143 | "EXTERNAL_ADDRESS", | ||
2144 | &external_address))) | ||
2145 | { | ||
2146 | GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, | ||
2147 | "tcp", | ||
2148 | _ | ||
2149 | ("Require EXTERNAL_ADDRESS for service `%s' in configuration (either BEHIND_NAT or ALLOW_NAT set to YES)!\n"), | ||
2150 | "transport-tcp"); | ||
2151 | GNUNET_SERVICE_stop (service); | ||
2152 | return NULL; | ||
2153 | } | ||
2154 | |||
2155 | internal_address = NULL; | ||
2156 | if ((GNUNET_YES == behind_nat) && (GNUNET_OK != | ||
2157 | GNUNET_CONFIGURATION_get_value_string (env->cfg, | ||
2158 | "transport-tcp", | ||
2159 | "INTERNAL_ADDRESS", | ||
2160 | &internal_address))) | ||
2161 | { | ||
2162 | GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, | ||
2163 | "tcp", | ||
2164 | _ | ||
2165 | ("Require INTERNAL_ADDRESS for service `%s' in configuration!\n"), | ||
2166 | "transport-tcp"); | ||
2167 | GNUNET_SERVICE_stop (service); | ||
2168 | GNUNET_free_non_null(external_address); | ||
2169 | return NULL; | ||
2170 | } | ||
2171 | |||
2172 | |||
1542 | aport = 0; | 2173 | aport = 0; |
1543 | if ((GNUNET_OK != | 2174 | if ((GNUNET_OK != |
1544 | GNUNET_CONFIGURATION_get_value_number (env->cfg, | 2175 | GNUNET_CONFIGURATION_get_value_number (env->cfg, |
@@ -1557,14 +2188,44 @@ libgnunet_plugin_transport_tcp_init (void *cls) | |||
1557 | _ | 2188 | _ |
1558 | ("Require valid port number for service `%s' in configuration!\n"), | 2189 | ("Require valid port number for service `%s' in configuration!\n"), |
1559 | "transport-tcp"); | 2190 | "transport-tcp"); |
2191 | GNUNET_free_non_null(external_address); | ||
2192 | GNUNET_free_non_null(internal_address); | ||
1560 | GNUNET_SERVICE_stop (service); | 2193 | GNUNET_SERVICE_stop (service); |
1561 | return NULL; | 2194 | return NULL; |
1562 | } | 2195 | } |
2196 | |||
2197 | if (behind_nat) | ||
2198 | { | ||
2199 | if (GNUNET_YES != tcp_transport_start_nat_server(plugin)) | ||
2200 | { | ||
2201 | GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, | ||
2202 | "tcp", | ||
2203 | _ | ||
2204 | ("Failed to start %s required for NAT in %s!\n"), | ||
2205 | "gnunet-nat-server" | ||
2206 | "transport-tcp"); | ||
2207 | GNUNET_free_non_null(external_address); | ||
2208 | GNUNET_free_non_null(internal_address); | ||
2209 | GNUNET_SERVICE_stop (service); | ||
2210 | return NULL; | ||
2211 | } | ||
2212 | } | ||
2213 | |||
2214 | if (allow_nat) | ||
2215 | { | ||
2216 | plugin->nat_wait_conns = GNUNET_CONTAINER_multihashmap_create(100); | ||
2217 | GNUNET_assert(plugin->nat_wait_conns != NULL); | ||
2218 | } | ||
2219 | |||
1563 | if (aport == 0) | 2220 | if (aport == 0) |
1564 | aport = bport; | 2221 | aport = bport; |
1565 | plugin = GNUNET_malloc (sizeof (struct Plugin)); | 2222 | plugin = GNUNET_malloc (sizeof (struct Plugin)); |
1566 | plugin->open_port = bport; | 2223 | plugin->open_port = bport; |
1567 | plugin->adv_port = aport; | 2224 | plugin->adv_port = aport; |
2225 | plugin->external_address = external_address; | ||
2226 | plugin->internal_address = internal_address; | ||
2227 | plugin->behind_nat = behind_nat; | ||
2228 | plugin->allow_nat = allow_nat; | ||
1568 | plugin->env = env; | 2229 | plugin->env = env; |
1569 | plugin->lsock = NULL; | 2230 | plugin->lsock = NULL; |
1570 | api = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_PluginFunctions)); | 2231 | api = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_PluginFunctions)); |
diff --git a/src/transport/plugin_transport_udp.c b/src/transport/plugin_transport_udp.c index f36f587ad..10bbf2972 100644 --- a/src/transport/plugin_transport_udp.c +++ b/src/transport/plugin_transport_udp.c | |||
@@ -1296,15 +1296,14 @@ udp_transport_server_start (void *cls) | |||
1296 | socklen_t addrlen; | 1296 | socklen_t addrlen; |
1297 | int sockets_created; | 1297 | int sockets_created; |
1298 | 1298 | ||
1299 | /* Pipe to read from started processes stdout (on read end) */ | ||
1300 | plugin->server_stdout = GNUNET_DISK_pipe(GNUNET_YES); | ||
1301 | |||
1302 | sockets_created = 0; | 1299 | sockets_created = 0; |
1303 | if (plugin->server_stdout == NULL) | ||
1304 | return sockets_created; | ||
1305 | 1300 | ||
1306 | if (plugin->behind_nat == GNUNET_YES) | 1301 | if (plugin->behind_nat == GNUNET_YES) |
1307 | { | 1302 | { |
1303 | /* Pipe to read from started processes stdout (on read end) */ | ||
1304 | plugin->server_stdout = GNUNET_DISK_pipe(GNUNET_YES); | ||
1305 | if (plugin->server_stdout == NULL) | ||
1306 | return sockets_created; | ||
1308 | #if DEBUG_UDP_NAT | 1307 | #if DEBUG_UDP_NAT |
1309 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, | 1308 | GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, |
1310 | "udp", | 1309 | "udp", |
@@ -1410,32 +1409,6 @@ udp_transport_server_start (void *cls) | |||
1410 | 1409 | ||
1411 | 1410 | ||
1412 | /** | 1411 | /** |
1413 | * Check if the given port is plausible (must be either | ||
1414 | * our listen port or our advertised port). If it is | ||
1415 | * neither, we return one of these two ports at random. | ||
1416 | * | ||
1417 | * @return either in_port or a more plausible port | ||
1418 | */ | ||
1419 | static uint16_t | ||
1420 | check_port (struct Plugin *plugin, uint16_t in_port) | ||
1421 | { | ||
1422 | |||
1423 | /* FIXME: remember what ports we are using to better respond to this */ | ||
1424 | return in_port; | ||
1425 | /* | ||
1426 | for (i = plugin->starting_port; i < plugin->num_ports + plugin->starting_port; i++) | ||
1427 | { | ||
1428 | if (in_port == i) | ||
1429 | return in_port; | ||
1430 | } | ||
1431 | |||
1432 | return GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, | ||
1433 | plugin->num_ports) + plugin->starting_port; | ||
1434 | */ | ||
1435 | } | ||
1436 | |||
1437 | |||
1438 | /** | ||
1439 | * Another peer has suggested an address for this peer and transport | 1412 | * Another peer has suggested an address for this peer and transport |
1440 | * plugin. Check that this could be a valid address. This function | 1413 | * plugin. Check that this could be a valid address. This function |
1441 | * is not expected to 'validate' the address in the sense of trying to | 1414 | * is not expected to 'validate' the address in the sense of trying to |
@@ -1468,12 +1441,12 @@ udp_check_address (void *cls, void *addr, size_t addrlen) | |||
1468 | if (addrlen == sizeof (struct sockaddr_in)) | 1441 | if (addrlen == sizeof (struct sockaddr_in)) |
1469 | { | 1442 | { |
1470 | v4 = (struct sockaddr_in *) buf; | 1443 | v4 = (struct sockaddr_in *) buf; |
1471 | v4->sin_port = htons (check_port (plugin, ntohs (v4->sin_port))); | 1444 | v4->sin_port = htons (plugin->port); |
1472 | } | 1445 | } |
1473 | else | 1446 | else |
1474 | { | 1447 | { |
1475 | v6 = (struct sockaddr_in6 *) buf; | 1448 | v6 = (struct sockaddr_in6 *) buf; |
1476 | v6->sin6_port = htons (check_port (plugin, ntohs (v6->sin6_port))); | 1449 | v6->sin6_port = htons (plugin->port); |
1477 | } | 1450 | } |
1478 | 1451 | ||
1479 | #if DEBUG_UDP_NAT | 1452 | #if DEBUG_UDP_NAT |
diff --git a/src/transport/test_transport_api_tcp_peer1.conf b/src/transport/test_transport_api_tcp_peer1.conf index f5bdc2063..e3778cd8e 100644 --- a/src/transport/test_transport_api_tcp_peer1.conf +++ b/src/transport/test_transport_api_tcp_peer1.conf | |||
@@ -39,6 +39,7 @@ ACCEPT_FROM6 = ::1; | |||
39 | ACCEPT_FROM = 127.0.0.1; | 39 | ACCEPT_FROM = 127.0.0.1; |
40 | NEIGHBOUR_LIMIT = 50 | 40 | NEIGHBOUR_LIMIT = 50 |
41 | BINARY = gnunet-service-transport | 41 | BINARY = gnunet-service-transport |
42 | #BINARY = /home/mrwiggles/documents/research/gnunet/gnunet-ng/src/transport/.libs/gnunet-service-transport | ||
42 | CONFIG = $DEFAULTCONFIG | 43 | CONFIG = $DEFAULTCONFIG |
43 | HOME = $SERVICEHOME | 44 | HOME = $SERVICEHOME |
44 | HOSTNAME = localhost | 45 | HOSTNAME = localhost |
diff --git a/src/transport/test_transport_api_tcp_peer2.conf b/src/transport/test_transport_api_tcp_peer2.conf index f2c22e336..6362ebd27 100644 --- a/src/transport/test_transport_api_tcp_peer2.conf +++ b/src/transport/test_transport_api_tcp_peer2.conf | |||
@@ -33,17 +33,18 @@ MINIMUM-FRIENDS = 0 | |||
33 | [transport] | 33 | [transport] |
34 | PLUGINS = tcp | 34 | PLUGINS = tcp |
35 | DEBUG = NO | 35 | DEBUG = NO |
36 | # PREFIX = | 36 | #DEBUG = YES |
37 | ACCEPT_FROM6 = ::1; | 37 | ACCEPT_FROM6 = ::1; |
38 | ACCEPT_FROM = 127.0.0.1; | 38 | ACCEPT_FROM = 127.0.0.1; |
39 | NEIGHBOUR_LIMIT = 50 | 39 | NEIGHBOUR_LIMIT = 50 |
40 | #BINARY = /home/mrwiggles/documents/research/gnunet/gnunet-ng/src/transport/.libs/gnunet-service-transport | ||
40 | BINARY = gnunet-service-transport | 41 | BINARY = gnunet-service-transport |
41 | CONFIG = $DEFAULTCONFIG | 42 | CONFIG = $DEFAULTCONFIG |
42 | HOME = $SERVICEHOME | 43 | HOME = $SERVICEHOME |
43 | HOSTNAME = localhost | 44 | HOSTNAME = localhost |
44 | PORT = 22365 | 45 | PORT = 22365 |
45 | UNIXPATH = /tmp/gnunet-p2-service-transport.sock | 46 | UNIXPATH = /tmp/gnunet-p2-service-transport.sock |
46 | #PREFIX = xterm -T transport1 -e gdb --command=cmd --args | 47 | #PREFIX = xterm -T transport2 -e gdb --command=cmd --args |
47 | #PREFIX = valgrind --leak-check=full | 48 | #PREFIX = valgrind --leak-check=full |
48 | 49 | ||
49 | [peerinfo] | 50 | [peerinfo] |