aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorNathan S. Evans <evans@in.tum.de>2010-06-09 15:32:33 +0000
committerNathan S. Evans <evans@in.tum.de>2010-06-09 15:32:33 +0000
commit8346f8d77f92715907e537352abeea84382bd176 (patch)
tree7be49727db5209ce379bfde5510d98c490176b3c /src
parent063a4d7093e93ac2d5bcaa3b0b0f3deabbe4f391 (diff)
downloadgnunet-8346f8d77f92715907e537352abeea84382bd176.tar.gz
gnunet-8346f8d77f92715907e537352abeea84382bd176.zip
first implementation of NAT punching for TCP transport plugin... doubt that it works, but testcases that do NOT use NAT still work. not to be viewed by anyone.
Diffstat (limited to 'src')
-rw-r--r--src/transport/plugin_transport_tcp.c695
-rw-r--r--src/transport/plugin_transport_udp.c39
-rw-r--r--src/transport/test_transport_api_tcp_peer1.conf1
-rw-r--r--src/transport/test_transport_api_tcp_peer2.conf5
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 */
69struct 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 */
86struct 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 */
385static struct Session * 476static struct Session *
386create_session (struct Plugin *plugin, 477create_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 */
833void
834run_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 */
762static ssize_t 909static ssize_t
763tcp_plugin_send (void *cls, 910tcp_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 */
1400static void
1401handle_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,
1386static struct GNUNET_SERVER_MessageHandler my_handlers[] = { 1681static 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 */
1824static 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 */
1852static void
1853tcp_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 &notify_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 */
1968static int
1969tcp_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 */
2009static char *
2010get_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 */
2054static int
2055check_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 */
1419static uint16_t
1420check_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;
39ACCEPT_FROM = 127.0.0.1; 39ACCEPT_FROM = 127.0.0.1;
40NEIGHBOUR_LIMIT = 50 40NEIGHBOUR_LIMIT = 50
41BINARY = gnunet-service-transport 41BINARY = gnunet-service-transport
42#BINARY = /home/mrwiggles/documents/research/gnunet/gnunet-ng/src/transport/.libs/gnunet-service-transport
42CONFIG = $DEFAULTCONFIG 43CONFIG = $DEFAULTCONFIG
43HOME = $SERVICEHOME 44HOME = $SERVICEHOME
44HOSTNAME = localhost 45HOSTNAME = 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]
34PLUGINS = tcp 34PLUGINS = tcp
35DEBUG = NO 35DEBUG = NO
36# PREFIX = 36#DEBUG = YES
37ACCEPT_FROM6 = ::1; 37ACCEPT_FROM6 = ::1;
38ACCEPT_FROM = 127.0.0.1; 38ACCEPT_FROM = 127.0.0.1;
39NEIGHBOUR_LIMIT = 50 39NEIGHBOUR_LIMIT = 50
40#BINARY = /home/mrwiggles/documents/research/gnunet/gnunet-ng/src/transport/.libs/gnunet-service-transport
40BINARY = gnunet-service-transport 41BINARY = gnunet-service-transport
41CONFIG = $DEFAULTCONFIG 42CONFIG = $DEFAULTCONFIG
42HOME = $SERVICEHOME 43HOME = $SERVICEHOME
43HOSTNAME = localhost 44HOSTNAME = localhost
44PORT = 22365 45PORT = 22365
45UNIXPATH = /tmp/gnunet-p2-service-transport.sock 46UNIXPATH = /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]