aboutsummaryrefslogtreecommitdiff
path: root/src/transport/plugin_transport_udp.c
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2011-06-25 06:24:01 +0000
committerChristian Grothoff <christian@grothoff.org>2011-06-25 06:24:01 +0000
commit8a3016481ba6aeb36de3950a56e641dda53ca544 (patch)
tree0c5468ec6e5d2165ad5931940e0b8439d09398de /src/transport/plugin_transport_udp.c
parentb6d4eeb39fd0cd41df164bd0959f58b08aa45e83 (diff)
downloadgnunet-8a3016481ba6aeb36de3950a56e641dda53ca544.tar.gz
gnunet-8a3016481ba6aeb36de3950a56e641dda53ca544.zip
the big NAT change
Diffstat (limited to 'src/transport/plugin_transport_udp.c')
-rw-r--r--src/transport/plugin_transport_udp.c1302
1 files changed, 293 insertions, 1009 deletions
diff --git a/src/transport/plugin_transport_udp.c b/src/transport/plugin_transport_udp.c
index 2366a2e16..e5e741df3 100644
--- a/src/transport/plugin_transport_udp.c
+++ b/src/transport/plugin_transport_udp.c
@@ -41,6 +41,7 @@
41#include "gnunet_hello_lib.h" 41#include "gnunet_hello_lib.h"
42#include "gnunet_connection_lib.h" 42#include "gnunet_connection_lib.h"
43#include "gnunet_container_lib.h" 43#include "gnunet_container_lib.h"
44#include "gnunet_nat_lib.h"
44#include "gnunet_os_lib.h" 45#include "gnunet_os_lib.h"
45#include "gnunet_peerinfo_service.h" 46#include "gnunet_peerinfo_service.h"
46#include "gnunet_protocols.h" 47#include "gnunet_protocols.h"
@@ -103,7 +104,7 @@ struct IPv4UdpAddress
103 /** 104 /**
104 * Port number, in network byte order. 105 * Port number, in network byte order.
105 */ 106 */
106 uint16_t u_port GNUNET_PACKED; 107 uint16_t u4_port GNUNET_PACKED;
107}; 108};
108 109
109 110
@@ -211,31 +212,6 @@ struct UDP_NAT_ProbeMessageConfirmation
211 212
212 213
213/** 214/**
214 * Local network addresses (actual IP address follows this struct).
215 * PORT is NOT included!
216 */
217struct LocalAddrList
218{
219
220 /**
221 * This is a doubly linked list.
222 */
223 struct LocalAddrList *next;
224
225 /**
226 * This is a doubly linked list.
227 */
228 struct LocalAddrList *prev;
229
230 /**
231 * Number of bytes of the address that follow
232 */
233 size_t size;
234
235};
236
237
238/**
239 * UDP NAT "Session" 215 * UDP NAT "Session"
240 */ 216 */
241struct PeerSession 217struct PeerSession
@@ -295,11 +271,6 @@ struct UDP_NAT_Probes
295 struct UDP_NAT_Probes *next; 271 struct UDP_NAT_Probes *next;
296 272
297 /** 273 /**
298 * Address string that the server process returned to us
299 */
300 char *address_string;
301
302 /**
303 * Timeout for this set of probes 274 * Timeout for this set of probes
304 */ 275 */
305 struct GNUNET_TIME_Absolute timeout; 276 struct GNUNET_TIME_Absolute timeout;
@@ -360,16 +331,6 @@ struct Plugin
360 struct PeerSession *sessions; 331 struct PeerSession *sessions;
361 332
362 /** 333 /**
363 * Handle for request of hostname resolution, non-NULL if pending.
364 */
365 struct GNUNET_RESOLVER_RequestHandle *hostname_dns;
366
367 /**
368 * ID of task used to update our addresses when one expires.
369 */
370 GNUNET_SCHEDULER_TaskIdentifier address_update_task;
371
372 /**
373 * ID of select task 334 * ID of select task
374 */ 335 */
375 GNUNET_SCHEDULER_TaskIdentifier select_task; 336 GNUNET_SCHEDULER_TaskIdentifier select_task;
@@ -380,17 +341,6 @@ struct Plugin
380 uint16_t port; 341 uint16_t port;
381 342
382 /** 343 /**
383 * The external address given to us by the user. Must be actual
384 * outside visible address for NAT punching to work.
385 */
386 char *external_address;
387
388 /**
389 * The internal address given to us by the user (or discovered).
390 */
391 char *internal_address;
392
393 /**
394 * Address we were told to bind to exclusively (IPv4). 344 * Address we were told to bind to exclusively (IPv4).
395 */ 345 */
396 char *bind_address; 346 char *bind_address;
@@ -401,14 +351,9 @@ struct Plugin
401 char *bind6_address; 351 char *bind6_address;
402 352
403 /** 353 /**
404 * List of our IP addresses. 354 * Handle to NAT traversal support.
405 */ 355 */
406 struct LocalAddrList *lal_head; 356 struct GNUNET_NAT_Handle *nat;
407
408 /**
409 * Tail of our IP address list.
410 */
411 struct LocalAddrList *lal_tail;
412 357
413 /** 358 /**
414 * FD Read set 359 * FD Read set
@@ -416,16 +361,6 @@ struct Plugin
416 struct GNUNET_NETWORK_FDSet *rs; 361 struct GNUNET_NETWORK_FDSet *rs;
417 362
418 /** 363 /**
419 * stdout pipe handle for the gnunet-nat-server process
420 */
421 struct GNUNET_DISK_PipeHandle *server_stdout;
422
423 /**
424 * stdout file handle (for reading) for the gnunet-nat-server process
425 */
426 const struct GNUNET_DISK_FileHandle *server_stdout_handle;
427
428 /**
429 * Probes in flight 364 * Probes in flight
430 */ 365 */
431 struct UDP_NAT_Probes *probes; 366 struct UDP_NAT_Probes *probes;
@@ -440,45 +375,13 @@ struct Plugin
440 */ 375 */
441 struct UDP_Sock_Info udp_sockv6; 376 struct UDP_Sock_Info udp_sockv6;
442 377
443 /**
444 * ID of select gnunet-nat-server stdout read task
445 */
446 GNUNET_SCHEDULER_TaskIdentifier server_read_task;
447
448 /**
449 * Is this transport configured to be behind a NAT?
450 */
451 int behind_nat;
452
453 /**
454 * Is this transport configured to allow connections to NAT'd peers?
455 */
456 int allow_nat;
457
458 /**
459 * Should this transport advertise only NAT addresses (port set to 0)?
460 * If not, all addresses will be duplicated for NAT punching and regular
461 * ports.
462 */
463 int only_nat_addresses;
464
465 /**
466 * use local addresses?
467 */
468 int use_localaddresses;
469
470 /**
471 * The process id of the server process (if behind NAT)
472 */
473 struct GNUNET_OS_Process *server_proc;
474
475}; 378};
476 379
477 380
478/** 381/**
479 * Forward declaration. 382 * Forward declaration.
480 */ 383 */
481void 384static void
482udp_probe_continuation (void *cls, const struct GNUNET_PeerIdentity *target, int result); 385udp_probe_continuation (void *cls, const struct GNUNET_PeerIdentity *target, int result);
483 386
484 387
@@ -489,53 +392,13 @@ udp_probe_continuation (void *cls, const struct GNUNET_PeerIdentity *target, int
489 * @param target the peeridentity of the peer to disconnect 392 * @param target the peeridentity of the peer to disconnect
490 * @return GNUNET_OK on success, GNUNET_SYSERR if the operation failed 393 * @return GNUNET_OK on success, GNUNET_SYSERR if the operation failed
491 */ 394 */
492void 395static void
493udp_disconnect (void *cls, const struct GNUNET_PeerIdentity *target) 396udp_disconnect (void *cls, const struct GNUNET_PeerIdentity *target)
494{ 397{
495 /** TODO: Implement! */ 398 /** TODO: Implement! */
496 return; 399 return;
497} 400}
498 401
499/**
500 * Shutdown the server process (stop receiving inbound traffic). Maybe
501 * restarted later!
502 *
503 * @param cls Handle to the plugin for this transport
504 *
505 * @return returns the number of sockets successfully closed,
506 * should equal the number of sockets successfully opened
507 */
508static int
509udp_transport_server_stop (void *cls)
510{
511 struct Plugin *plugin = cls;
512
513 if (plugin->select_task != GNUNET_SCHEDULER_NO_TASK)
514 {
515 GNUNET_SCHEDULER_cancel (plugin->select_task);
516 plugin->select_task = GNUNET_SCHEDULER_NO_TASK;
517 }
518 if (plugin->udp_sockv4.desc != NULL)
519 {
520 GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (plugin->udp_sockv4.desc));
521 plugin->udp_sockv4.desc = NULL;
522 }
523 if (plugin->udp_sockv6.desc != NULL)
524 {
525 GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (plugin->udp_sockv6.desc));
526 plugin->udp_sockv6.desc = NULL;
527 }
528 if (plugin->behind_nat == GNUNET_YES)
529 {
530 if (0 != GNUNET_OS_process_kill (plugin->server_proc, SIGTERM))
531 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill");
532 GNUNET_OS_process_wait (plugin->server_proc);
533 GNUNET_OS_process_close (plugin->server_proc);
534 plugin->server_proc = NULL;
535 }
536 return GNUNET_OK;
537}
538
539 402
540struct PeerSession * 403struct PeerSession *
541find_session (struct Plugin *plugin, 404find_session (struct Plugin *plugin,
@@ -650,7 +513,7 @@ udp_real_send (void *cls,
650 a4.sin_len = sizeof (a4); 513 a4.sin_len = sizeof (a4);
651#endif 514#endif
652 a4.sin_family = AF_INET; 515 a4.sin_family = AF_INET;
653 a4.sin_port = t4->u_port; 516 a4.sin_port = t4->u4_port;
654 a4.sin_addr.s_addr = t4->ipv4_addr; 517 a4.sin_addr.s_addr = t4->ipv4_addr;
655 sb = &a4; 518 sb = &a4;
656 sbs = sizeof (a4); 519 sbs = sizeof (a4);
@@ -689,51 +552,6 @@ udp_real_send (void *cls,
689 return sent; 552 return sent;
690} 553}
691 554
692/**
693 * We learned about a peer (possibly behind NAT) so run the
694 * gnunet-nat-client to send dummy ICMP responses
695 *
696 * @param plugin the plugin for this transport
697 * @param addr the address of the peer
698 * @param addrlen the length of the address
699 */
700void
701run_gnunet_nat_client (struct Plugin *plugin, const char *addr, size_t addrlen)
702{
703 char addr_buf[INET_ADDRSTRLEN];
704 char *address_as_string;
705 char *port_as_string;
706 struct GNUNET_OS_Process *proc;
707 const struct IPv4UdpAddress *t4;
708
709 GNUNET_assert(addrlen == sizeof(struct IPv4UdpAddress));
710 t4 = (struct IPv4UdpAddress *)addr;
711
712 if (NULL == inet_ntop (AF_INET,
713 &t4->ipv4_addr,
714 addr_buf, INET_ADDRSTRLEN))
715 {
716 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "inet_ntop");
717 return;
718 }
719 address_as_string = GNUNET_strdup (addr_buf);
720 GNUNET_asprintf(&port_as_string, "%d", plugin->port);
721#if DEBUG_UDP
722 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
723 _("Running gnunet-nat-client with arguments: %s %s %d\n"), plugin->external_address, address_as_string, plugin->port);
724#endif
725
726 /* Start the server process */
727 proc = GNUNET_OS_start_process (NULL, NULL, "gnunet-nat-client", "gnunet-nat-client", plugin->external_address, address_as_string, port_as_string, NULL);
728 GNUNET_free(address_as_string);
729 GNUNET_free(port_as_string);
730 if (proc != NULL)
731 {
732 GNUNET_OS_process_wait (proc);
733 GNUNET_OS_process_close (proc);
734 proc = NULL;
735 }
736}
737 555
738/** 556/**
739 * Function that can be used by the transport service to transmit 557 * Function that can be used by the transport service to transmit
@@ -778,6 +596,7 @@ udp_plugin_send (void *cls,
778 struct PeerSession *peer_session; 596 struct PeerSession *peer_session;
779 int other_peer_natd; 597 int other_peer_natd;
780 const struct IPv4UdpAddress *t4; 598 const struct IPv4UdpAddress *t4;
599 struct sockaddr_in sin4;
781 600
782 if (force_address == GNUNET_SYSERR) 601 if (force_address == GNUNET_SYSERR)
783 return GNUNET_SYSERR; 602 return GNUNET_SYSERR;
@@ -787,7 +606,7 @@ udp_plugin_send (void *cls,
787 if (addrlen == sizeof(struct IPv4UdpAddress)) 606 if (addrlen == sizeof(struct IPv4UdpAddress))
788 { 607 {
789 t4 = addr; 608 t4 = addr;
790 if (ntohs(t4->u_port) == 0) 609 if (ntohs(t4->u4_port) == 0)
791 other_peer_natd = GNUNET_YES; 610 other_peer_natd = GNUNET_YES;
792 } 611 }
793 else if (addrlen != sizeof(struct IPv6UdpAddress)) 612 else if (addrlen != sizeof(struct IPv6UdpAddress))
@@ -797,7 +616,8 @@ udp_plugin_send (void *cls,
797 } 616 }
798 617
799 sent = 0; 618 sent = 0;
800 if ((other_peer_natd == GNUNET_YES) && (plugin->allow_nat == GNUNET_YES)) 619 if ( (other_peer_natd == GNUNET_YES) &&
620 (addrlen == sizeof(struct IPv4UdpAddress)) )
801 { 621 {
802 peer_session = find_session(plugin, target); 622 peer_session = find_session(plugin, target);
803 if (peer_session == NULL) /* We have a new peer to add */ 623 if (peer_session == NULL) /* We have a new peer to add */
@@ -830,7 +650,14 @@ udp_plugin_send (void *cls,
830 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 650 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
831 _("Other peer is NAT'd, set up peer session for peer %s\n"), GNUNET_i2s(target)); 651 _("Other peer is NAT'd, set up peer session for peer %s\n"), GNUNET_i2s(target));
832#endif 652#endif
833 run_gnunet_nat_client(plugin, addr, addrlen); 653 memset (&sin4, 0, sizeof (sin4));
654 sin4.sin_family = AF_INET;
655#if HAVE_SOCKADDR_IN_SIN_LEN
656 sin4.sin_len = sizeof (sin4);
657#endif
658 sin4.sin_port = t4->u4_port;
659 sin4.sin_addr.s_addr = t4->ipv4_addr;
660 GNUNET_NAT_run_client (plugin->nat, &sin4);
834 } 661 }
835 else 662 else
836 { 663 {
@@ -881,244 +708,6 @@ udp_plugin_send (void *cls,
881} 708}
882 709
883 710
884static void
885add_to_address_list (struct Plugin *plugin,
886 const void *arg,
887 size_t arg_size)
888{
889 struct LocalAddrList *lal;
890
891 lal = plugin->lal_head;
892 while (NULL != lal)
893 {
894 if ( (lal->size == arg_size) &&
895 (0 == memcmp (&lal[1], arg, arg_size)) )
896 return;
897 lal = lal->next;
898 }
899 lal = GNUNET_malloc (sizeof (struct LocalAddrList) + arg_size);
900 lal->size = arg_size;
901 memcpy (&lal[1], arg, arg_size);
902 GNUNET_CONTAINER_DLL_insert (plugin->lal_head,
903 plugin->lal_tail,
904 lal);
905}
906
907
908static int
909check_local_addr (struct Plugin *plugin,
910 const void *arg,
911 size_t arg_size)
912{
913 struct LocalAddrList *lal;
914
915 lal = plugin->lal_head;
916 while (NULL != lal)
917 {
918 if ( (lal->size == arg_size) &&
919 (0 == memcmp (&lal[1], arg, arg_size)) )
920 return GNUNET_OK;
921 lal = lal->next;
922 }
923 return GNUNET_SYSERR;
924}
925
926static int check_localaddress (const struct sockaddr *addr, socklen_t addrlen)
927{
928 uint32_t res = 0;
929 int local = GNUNET_NO;
930 int af = addr->sa_family;
931 switch (af)
932 {
933 case AF_INET:
934 {
935 uint32_t netmask = 0x7F000000;
936 uint32_t address = ntohl (((struct sockaddr_in *) addr)->sin_addr.s_addr);
937 res = (address >> 24) ^ (netmask >> 24);
938 if (res != 0)
939 local = GNUNET_NO;
940 else
941 local = GNUNET_YES;
942#if DEBUG_UDP
943 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
944 "Checking IPv4 address `%s': %s\n", GNUNET_a2s (addr, addrlen), (local==GNUNET_YES) ? "local" : "global");
945#endif
946 break;
947 }
948 case AF_INET6:
949 {
950 if (IN6_IS_ADDR_LOOPBACK (&((struct sockaddr_in6 *) addr)->sin6_addr) ||
951 IN6_IS_ADDR_LINKLOCAL (&((struct sockaddr_in6 *) addr)->sin6_addr))
952 local = GNUNET_YES;
953 else
954 local = GNUNET_NO;
955#if DEBUG_UDP
956 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
957 "Checking IPv6 address `%s' : %s\n", GNUNET_a2s (addr, addrlen), (local==GNUNET_YES) ? "local" : "global");
958#endif
959 break;
960 }
961 }
962 return local;
963}
964
965
966/**
967 * Add the IP of our network interface to the list of
968 * our external IP addresses.
969 */
970static int
971process_interfaces (void *cls,
972 const char *name,
973 int isDefault,
974 const struct sockaddr *addr, socklen_t addrlen)
975{
976 struct Plugin *plugin = cls;
977 int af;
978 struct IPv4UdpAddress t4;
979 struct IPv6UdpAddress t6;
980 void *arg;
981 uint16_t args;
982 void *addr_nat;
983 char buf[INET6_ADDRSTRLEN];
984
985 addr_nat = NULL;
986 af = addr->sa_family;
987
988 if (plugin->use_localaddresses == GNUNET_NO)
989 {
990 if (GNUNET_YES == check_localaddress (addr, addrlen))
991 {
992#if DEBUG_UDP
993 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
994 "udp",
995 "Not notifying transport of address `%s' (local address)\n",
996 GNUNET_a2s (addr, addrlen));
997#endif
998 return GNUNET_OK;
999 }
1000 }
1001
1002 memset(buf, 0, INET6_ADDRSTRLEN);
1003 if (af == AF_INET)
1004 {
1005 t4.ipv4_addr = ((struct sockaddr_in *) addr)->sin_addr.s_addr;
1006 GNUNET_assert(NULL != inet_ntop(AF_INET, &t4.ipv4_addr, &buf[0], INET_ADDRSTRLEN));
1007 if ((plugin->bind6_address != NULL) || ((plugin->bind_address != NULL) && (0 != strcmp(buf, plugin->bind_address))))
1008 {
1009 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "%s: Not notifying transport of address %s\n", "UDP", GNUNET_a2s (addr, addrlen));
1010 return GNUNET_OK;
1011 }
1012 add_to_address_list (plugin, &t4.ipv4_addr, sizeof (uint32_t));
1013 if ((plugin->behind_nat == GNUNET_YES) && (plugin->only_nat_addresses == GNUNET_YES))
1014 {
1015 t4.u_port = htons (DEFAULT_NAT_PORT);
1016 }
1017 else if (plugin->behind_nat == GNUNET_YES) /* We are behind NAT, but will advertise NAT and normal addresses */
1018 {
1019 addr_nat = GNUNET_malloc(sizeof(t4));
1020 t4.u_port = htons (DEFAULT_NAT_PORT);
1021 memcpy(addr_nat, &t4, sizeof(t4));
1022 t4.u_port = plugin->port;
1023 }
1024 else
1025 {
1026 t4.u_port = htons(plugin->port);
1027 }
1028 arg = &t4;
1029 args = sizeof (t4);
1030 }
1031 else if (af == AF_INET6)
1032 {
1033 if (IN6_IS_ADDR_LINKLOCAL (&((struct sockaddr_in6 *) addr)->sin6_addr))
1034 {
1035 /* skip link local addresses */
1036 return GNUNET_OK;
1037 }
1038 memcpy (&t6.ipv6_addr,
1039 &((struct sockaddr_in6 *) addr)->sin6_addr,
1040 sizeof (struct in6_addr));
1041 GNUNET_assert(NULL != inet_ntop(AF_INET6, &t6.ipv6_addr, &buf[0], INET6_ADDRSTRLEN));
1042 if (((plugin->bind_address != NULL) && (0 != strcmp(buf, plugin->bind_address)))
1043 || ((plugin->bind6_address != NULL) && (0 != strcmp(buf, plugin->bind6_address))))
1044 {
1045 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "%s: Not notifying transport of address %s\n", "UDP", GNUNET_a2s (addr, addrlen));
1046 return GNUNET_OK;
1047 }
1048 add_to_address_list (plugin, &t6.ipv6_addr, sizeof (struct in6_addr));
1049 if ((plugin->behind_nat == GNUNET_YES) && (plugin->only_nat_addresses == GNUNET_YES))
1050 {
1051 t6.u6_port = htons (DEFAULT_NAT_PORT);
1052 }
1053 else if (plugin->behind_nat == GNUNET_YES)
1054 {
1055 addr_nat = GNUNET_malloc(sizeof(t6));
1056 t6.u6_port = htons (DEFAULT_NAT_PORT);
1057 memcpy(addr_nat, &t6, sizeof(t6));
1058 t6.u6_port = plugin->port;
1059 }
1060 else
1061 {
1062 t6.u6_port = htons (plugin->port);
1063 }
1064
1065 arg = &t6;
1066 args = sizeof (t6);
1067 }
1068 else
1069 {
1070 GNUNET_break (0);
1071 return GNUNET_OK;
1072 }
1073
1074 GNUNET_log (GNUNET_ERROR_TYPE_INFO |
1075 GNUNET_ERROR_TYPE_BULK,
1076 _("Found address `%s' (%s)\n"),
1077 GNUNET_a2s (addr, addrlen), name);
1078
1079 if (addr_nat != NULL)
1080 {
1081 plugin->env->notify_address (plugin->env->cls,
1082 "udp",
1083 addr_nat, args, GNUNET_TIME_UNIT_FOREVER_REL);
1084 GNUNET_log (GNUNET_ERROR_TYPE_INFO |
1085 GNUNET_ERROR_TYPE_BULK,
1086 _("Found NAT address `%s' (%s)\n"),
1087 GNUNET_a2s (addr_nat, args), name);
1088 GNUNET_free(addr_nat);
1089 }
1090
1091 plugin->env->notify_address (plugin->env->cls,
1092 "udp",
1093 arg, args, GNUNET_TIME_UNIT_FOREVER_REL);
1094 return GNUNET_OK;
1095}
1096
1097
1098/**
1099 * Function called by the resolver for each address obtained from DNS
1100 * for our own hostname. Add the addresses to the list of our
1101 * external IP addresses.
1102 *
1103 * @param cls closure
1104 * @param addr one of the addresses of the host, NULL for the last address
1105 * @param addrlen length of the address
1106 */
1107static void
1108process_hostname_ips (void *cls,
1109 const struct sockaddr *addr, socklen_t addrlen)
1110{
1111 struct Plugin *plugin = cls;
1112
1113 if (addr == NULL)
1114 {
1115 plugin->hostname_dns = NULL;
1116 return;
1117 }
1118 process_interfaces (plugin, "<hostname>", GNUNET_YES, addr, addrlen);
1119}
1120
1121
1122/** 711/**
1123 * Send UDP probe messages or UDP keepalive messages, depending on the 712 * Send UDP probe messages or UDP keepalive messages, depending on the
1124 * state of the connection. 713 * state of the connection.
@@ -1127,7 +716,8 @@ process_hostname_ips (void *cls,
1127 * @param tc task context for running this 716 * @param tc task context for running this
1128 */ 717 */
1129static void 718static void
1130send_udp_probe_message (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) 719send_udp_probe_message (void *cls,
720 const struct GNUNET_SCHEDULER_TaskContext *tc)
1131{ 721{
1132 struct UDP_NAT_Probes *probe = cls; 722 struct UDP_NAT_Probes *probe = cls;
1133 struct UDP_NAT_ProbeMessage message; 723 struct UDP_NAT_ProbeMessage message;
@@ -1137,12 +727,12 @@ send_udp_probe_message (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc
1137 message.header.size = htons(sizeof(struct UDP_NAT_ProbeMessage)); 727 message.header.size = htons(sizeof(struct UDP_NAT_ProbeMessage));
1138 message.header.type = htons(GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_NAT_PROBE); 728 message.header.type = htons(GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_NAT_PROBE);
1139 /* If they gave us a port, use that. If not, try our port. */ 729 /* If they gave us a port, use that. If not, try our port. */
1140 if (ntohs(probe->addr.u_port) == 0) 730 if (ntohs(probe->addr.u4_port) == 0)
1141 probe->addr.u_port = htons(plugin->port); 731 probe->addr.u4_port = htons(plugin->port);
1142 732
1143#if DEBUG_UDP 733#if DEBUG_UDP
1144 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 734 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1145 _("Sending a probe to port %d\n"), ntohs(probe->addr.u_port)); 735 _("Sending a probe to port %d\n"), ntohs(probe->addr.u4_port));
1146#endif 736#endif
1147 probe->count++; 737 probe->count++;
1148 udp_real_send(plugin, 738 udp_real_send(plugin,
@@ -1158,10 +748,12 @@ send_udp_probe_message (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc
1158/** 748/**
1159 * Continuation for probe sends. If the last probe was sent 749 * Continuation for probe sends. If the last probe was sent
1160 * "successfully", schedule sending of another one. If not, 750 * "successfully", schedule sending of another one. If not,
1161 * 751 * FIXME...
1162 */ 752 */
1163void 753static void
1164udp_probe_continuation (void *cls, const struct GNUNET_PeerIdentity *target, int result) 754udp_probe_continuation (void *cls,
755 const struct GNUNET_PeerIdentity *target,
756 int result)
1165{ 757{
1166 struct UDP_NAT_Probes *probe = cls; 758 struct UDP_NAT_Probes *probe = cls;
1167 /*struct Plugin *plugin = probe->plugin;*/ 759 /*struct Plugin *plugin = probe->plugin;*/
@@ -1170,137 +762,48 @@ udp_probe_continuation (void *cls, const struct GNUNET_PeerIdentity *target, int
1170 { 762 {
1171#if DEBUG_UDP 763#if DEBUG_UDP
1172 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 764 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1173 _("Scheduling next probe for 10000 milliseconds\n")); 765 _("Scheduling next probe for 10000 milliseconds\n"));
1174#endif 766#endif
1175 probe->task = GNUNET_SCHEDULER_add_delayed(GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MILLISECONDS, 10000), &send_udp_probe_message, probe); 767 probe->task = GNUNET_SCHEDULER_add_delayed(GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 10),
768 &send_udp_probe_message, probe);
1176 } 769 }
1177 else /* Destroy the probe context. */ 770 else /* Destroy the probe context. */
1178 { 771 {
1179#if DEBUG_UDP 772#if DEBUG_UDP
1180 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 773 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1181 _("Sending probe didn't go well...\n")); 774 _("Sending probe didn't go well...\n"));
1182#endif 775#endif
1183 } 776 }
1184} 777}
1185 778
1186/**
1187 * Find probe message by address
1188 *
1189 * @param plugin the plugin for this transport
1190 * @param address_string the ip address as a string
1191 */
1192struct UDP_NAT_Probes *
1193find_probe(struct Plugin *plugin, char * address_string)
1194{
1195 struct UDP_NAT_Probes *pos;
1196 779
1197 pos = plugin->probes; 780/**
1198 while (pos != NULL) 781 * FIXME.
1199 if (strcmp(pos->address_string, address_string) == 0)
1200 return pos;
1201
1202 return pos;
1203}
1204
1205
1206/*
1207 * @param cls the plugin handle
1208 * @param tc the scheduling context (for rescheduling this function again)
1209 *
1210 * We have been notified that gnunet-nat-server has written something to stdout.
1211 * Handle the output, then reschedule this function to be called again once
1212 * more is available.
1213 *
1214 */ 782 */
1215static void 783static void
1216udp_plugin_server_read (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) 784udp_plugin_reversal_callback (void *cls,
785 const struct sockaddr *addr,
786 socklen_t addrlen)
1217{ 787{
1218 struct Plugin *plugin = cls; 788 struct Plugin *plugin = cls;
1219 char mybuf[40];
1220 ssize_t bytes;
1221 memset(&mybuf, 0, sizeof(mybuf));
1222 int i;
1223 struct UDP_NAT_Probes *temp_probe; 789 struct UDP_NAT_Probes *temp_probe;
1224 int port; 790 const struct sockaddr_in *inaddr;
1225 char *port_start;
1226 struct IPv4UdpAddress a4;
1227 791
1228 if ( (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0) 792 if (sizeof (struct sockaddr_in) != addrlen)
1229 return;
1230
1231 bytes = GNUNET_DISK_file_read(plugin->server_stdout_handle, &mybuf, sizeof(mybuf));
1232
1233 if (bytes < 1)
1234 {
1235#if DEBUG_UDP
1236 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1237 _("Finished reading from server stdout with code: %d\n"), bytes);
1238#endif
1239 return;
1240 }
1241
1242 port_start = NULL;
1243 for (i = 0; i < sizeof(mybuf); i++)
1244 { 793 {
1245 if (mybuf[i] == '\n') 794 GNUNET_break (0);
1246 mybuf[i] = '\0';
1247
1248 if ((mybuf[i] == ':') && (i + 1 < sizeof(mybuf)))
1249 {
1250 mybuf[i] = '\0';
1251 port_start = &mybuf[i + 1];
1252 }
1253 }
1254
1255 if (port_start != NULL)
1256 port = atoi(port_start);
1257 else
1258 {
1259 plugin->server_read_task =
1260 GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
1261 plugin->server_stdout_handle, &udp_plugin_server_read, plugin);
1262 return;
1263 }
1264
1265#if DEBUG_UDP
1266 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1267 _("nat-server-read read: %s port %d\n"), &mybuf, port);
1268#endif
1269
1270 /**
1271 * We have received an ICMP response, ostensibly from a non-NAT'd peer
1272 * that wants to connect to us! Send a message to establish a connection.
1273 */
1274 if (inet_pton(AF_INET, &mybuf[0], &a4.ipv4_addr) != 1)
1275 {
1276
1277 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1278 _("nat-server-read malformed address\n"), &mybuf, port);
1279
1280 plugin->server_read_task =
1281 GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
1282 plugin->server_stdout_handle, &udp_plugin_server_read, plugin);
1283 return; 795 return;
1284 } 796 }
1285 797 inaddr = (const struct sockaddr_in *) addr;
1286 temp_probe = find_probe(plugin, &mybuf[0]); 798 temp_probe = GNUNET_malloc(sizeof(struct UDP_NAT_Probes));
1287 799 temp_probe->addr.ipv4_addr = inaddr->sin_addr.s_addr;
1288 if (temp_probe == NULL) 800 temp_probe->addr.u4_port = inaddr->sin_port;
1289 { 801 temp_probe->next = plugin->probes;
1290 temp_probe = GNUNET_malloc(sizeof(struct UDP_NAT_Probes)); 802 temp_probe->plugin = plugin;
1291 temp_probe->address_string = strdup(&mybuf[0]); 803 temp_probe->task = GNUNET_SCHEDULER_add_delayed(GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MILLISECONDS, 500),
1292 GNUNET_assert (1 == inet_pton(AF_INET, &mybuf[0], &temp_probe->addr.ipv4_addr)); 804 &send_udp_probe_message,
1293 temp_probe->addr.u_port = htons(port); 805 temp_probe);
1294 temp_probe->next = plugin->probes; 806 plugin->probes = temp_probe;
1295 temp_probe->plugin = plugin;
1296 temp_probe->task = GNUNET_SCHEDULER_add_delayed(GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MILLISECONDS, 500), &send_udp_probe_message, temp_probe);
1297 plugin->probes = temp_probe;
1298 }
1299
1300 plugin->server_read_task =
1301 GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
1302 plugin->server_stdout_handle, &udp_plugin_server_read, plugin);
1303
1304} 807}
1305 808
1306 809
@@ -1322,9 +825,6 @@ udp_demultiplexer(struct Plugin *plugin,
1322 size_t fromlen, struct UDP_Sock_Info *sockinfo) 825 size_t fromlen, struct UDP_Sock_Info *sockinfo)
1323{ 826{
1324 struct UDP_NAT_ProbeMessageReply *outgoing_probe_reply; 827 struct UDP_NAT_ProbeMessageReply *outgoing_probe_reply;
1325 struct UDP_NAT_ProbeMessageConfirmation *outgoing_probe_confirmation;
1326 char addr_buf[INET_ADDRSTRLEN];
1327 struct UDP_NAT_Probes *outgoing_probe;
1328 struct PeerSession *peer_session; 828 struct PeerSession *peer_session;
1329 struct MessageQueue *pending_message; 829 struct MessageQueue *pending_message;
1330 struct MessageQueue *pending_message_temp; 830 struct MessageQueue *pending_message_temp;
@@ -1343,7 +843,7 @@ udp_demultiplexer(struct Plugin *plugin,
1343 GNUNET_assert(sender_addr != NULL); /* Can recvfrom have a NULL address? */ 843 GNUNET_assert(sender_addr != NULL); /* Can recvfrom have a NULL address? */
1344 if (fromlen == sizeof(struct IPv4UdpAddress)) 844 if (fromlen == sizeof(struct IPv4UdpAddress))
1345 { 845 {
1346 incoming_port = ntohs(((struct IPv4UdpAddress *)sender_addr)->u_port); 846 incoming_port = ntohs(((struct IPv4UdpAddress *)sender_addr)->u4_port);
1347 } 847 }
1348 else if (fromlen == sizeof(struct IPv6UdpAddress)) 848 else if (fromlen == sizeof(struct IPv6UdpAddress))
1349 { 849 {
@@ -1386,14 +886,10 @@ udp_demultiplexer(struct Plugin *plugin,
1386#endif 886#endif
1387 if (fromlen == sizeof(struct IPv4UdpAddress)) 887 if (fromlen == sizeof(struct IPv4UdpAddress))
1388 { 888 {
1389 memset(&addr_buf, 0, sizeof(addr_buf)); 889 /* FIXME! */
1390 if (NULL == inet_ntop (AF_INET, 890#if 0
1391 &((struct IPv4UdpAddress *) sender_addr)->ipv4_addr, addr_buf, 891 struct UDP_NAT_ProbeMessageConfirmation *outgoing_probe_confirmation;
1392 INET_ADDRSTRLEN)) 892 struct UDP_NAT_Probes *outgoing_probe;
1393 {
1394 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "inet_ntop");
1395 return;
1396 }
1397 outgoing_probe = find_probe(plugin, &addr_buf[0]); 893 outgoing_probe = find_probe(plugin, &addr_buf[0]);
1398 if (outgoing_probe != NULL) 894 if (outgoing_probe != NULL)
1399 { 895 {
@@ -1425,6 +921,7 @@ udp_demultiplexer(struct Plugin *plugin,
1425 _("Received a probe reply, but have no record of a sent probe!\n")); 921 _("Received a probe reply, but have no record of a sent probe!\n"));
1426#endif 922#endif
1427 } 923 }
924#endif
1428 } 925 }
1429 else 926 else
1430 { 927 {
@@ -1466,7 +963,7 @@ udp_demultiplexer(struct Plugin *plugin,
1466 peer_session->sock = sockinfo->desc; 963 peer_session->sock = sockinfo->desc;
1467 if (peer_session->connect_alen == sizeof(struct IPv4UdpAddress)) 964 if (peer_session->connect_alen == sizeof(struct IPv4UdpAddress))
1468 { 965 {
1469 ((struct IPv4UdpAddress *)peer_session->connect_addr)->u_port = htons(incoming_port); 966 ((struct IPv4UdpAddress *)peer_session->connect_addr)->u4_port = htons(incoming_port);
1470 } 967 }
1471 else if (peer_session->connect_alen == sizeof(struct IPv4UdpAddress)) 968 else if (peer_session->connect_alen == sizeof(struct IPv4UdpAddress))
1472 { 969 {
@@ -1550,13 +1047,12 @@ udp_demultiplexer(struct Plugin *plugin,
1550 1047
1551 1048
1552/* 1049/*
1553 * @param cls the plugin handle
1554 * @param tc the scheduling context (for rescheduling this function again)
1555 *
1556 * We have been notified that our writeset has something to read. We don't 1050 * We have been notified that our writeset has something to read. We don't
1557 * know which socket needs to be read, so we have to check each one 1051 * know which socket needs to be read, so we have to check each one
1558 * Then reschedule this function to be called again once more is available. 1052 * Then reschedule this function to be called again once more is available.
1559 * 1053 *
1054 * @param cls the plugin handle
1055 * @param tc the scheduling context (for rescheduling this function again)
1560 */ 1056 */
1561static void 1057static void
1562udp_plugin_select (void *cls, 1058udp_plugin_select (void *cls,
@@ -1606,7 +1102,7 @@ udp_plugin_select (void *cls,
1606 if (AF_INET == ((struct sockaddr *)addr)->sa_family) 1102 if (AF_INET == ((struct sockaddr *)addr)->sa_family)
1607 { 1103 {
1608 s4 = (const struct sockaddr_in*) &addr; 1104 s4 = (const struct sockaddr_in*) &addr;
1609 t4.u_port = s4->sin_port; 1105 t4.u4_port = s4->sin_port;
1610 t4.ipv4_addr = s4->sin_addr.s_addr; 1106 t4.ipv4_addr = s4->sin_addr.s_addr;
1611 ca = &t4; 1107 ca = &t4;
1612 calen = sizeof (t4); 1108 calen = sizeof (t4);
@@ -1676,187 +1172,6 @@ udp_plugin_select (void *cls,
1676 1172
1677} 1173}
1678 1174
1679/**
1680 * Create a slew of UDP sockets. If possible, use IPv6 and IPv4.
1681 *
1682 * @param cls closure for server start, should be a struct Plugin *
1683 * @return number of sockets created or GNUNET_SYSERR on error
1684*/
1685static int
1686udp_transport_server_start (void *cls)
1687{
1688 struct Plugin *plugin = cls;
1689 struct sockaddr_in serverAddrv4;
1690 struct sockaddr_in6 serverAddrv6;
1691 struct sockaddr *serverAddr;
1692 socklen_t addrlen;
1693 int sockets_created;
1694 int tries;
1695
1696
1697 sockets_created = 0;
1698 if (plugin->behind_nat == GNUNET_YES)
1699 {
1700 /* Pipe to read from started processes stdout (on read end) */
1701 plugin->server_stdout = GNUNET_DISK_pipe(GNUNET_YES, GNUNET_NO, GNUNET_YES);
1702 if (plugin->server_stdout == NULL)
1703 return sockets_created;
1704#if DEBUG_UDP
1705 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1706 "Starting gnunet-nat-server process cmd: %s %s\n",
1707 "gnunet-nat-server",
1708 plugin->internal_address);
1709#endif
1710 /* Start the server process */
1711 plugin->server_proc = GNUNET_OS_start_process(NULL,
1712 plugin->server_stdout,
1713 "gnunet-nat-server",
1714 "gnunet-nat-server",
1715 plugin->internal_address, NULL);
1716 if (plugin->server_proc == NULL)
1717 {
1718#if DEBUG_UDP
1719 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1720 "Failed to start gnunet-nat-server process\n");
1721#endif
1722 return GNUNET_SYSERR;
1723 }
1724 /* Close the write end of the read pipe */
1725 GNUNET_DISK_pipe_close_end(plugin->server_stdout, GNUNET_DISK_PIPE_END_WRITE);
1726
1727 plugin->server_stdout_handle = GNUNET_DISK_pipe_handle(plugin->server_stdout, GNUNET_DISK_PIPE_END_READ);
1728 plugin->server_read_task =
1729 GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
1730 plugin->server_stdout_handle, &udp_plugin_server_read, plugin);
1731 }
1732
1733 if ( (GNUNET_YES !=
1734 GNUNET_CONFIGURATION_get_value_yesno (plugin->env->cfg, "nat",
1735 "DISABLEV6")))
1736 {
1737 plugin->udp_sockv6.desc = GNUNET_NETWORK_socket_create (PF_INET6, SOCK_DGRAM, 0);
1738 if (NULL == plugin->udp_sockv6.desc)
1739 {
1740 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "udp", "socket");
1741 }
1742 else
1743 {
1744 memset (&serverAddrv6, 0, sizeof (serverAddrv6));
1745#if HAVE_SOCKADDR_IN_SIN_LEN
1746 serverAddrv6.sin6_len = sizeof (serverAddrv6);
1747#endif
1748
1749 serverAddrv6.sin6_family = AF_INET6;
1750 serverAddrv6.sin6_addr = in6addr_any;
1751 if (plugin->bind6_address != NULL)
1752 {
1753 if (1 != inet_pton(AF_INET6, plugin->bind6_address, &serverAddrv6.sin6_addr))
1754 return 0;
1755 }
1756
1757 serverAddrv6.sin6_port = htons (plugin->port);
1758 addrlen = sizeof (serverAddrv6);
1759 serverAddr = (struct sockaddr *) &serverAddrv6;
1760#if DEBUG_UDP
1761 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1762 "Binding to IPv6 port %d\n",
1763 ntohs(serverAddrv6.sin6_port));
1764#endif
1765 tries = 0;
1766 while (GNUNET_NETWORK_socket_bind (plugin->udp_sockv6.desc, serverAddr, addrlen) !=
1767 GNUNET_OK)
1768 {
1769 serverAddrv6.sin6_port = htons (GNUNET_CRYPTO_random_u32(GNUNET_CRYPTO_QUALITY_STRONG, 33537) + 32000); /* Find a good, non-root port */
1770#if DEBUG_UDP
1771 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1772 "IPv6 Binding failed, trying new port %d\n",
1773 ntohs(serverAddrv6.sin6_port));
1774#endif
1775 tries++;
1776 if (tries > 10)
1777 {
1778 GNUNET_NETWORK_socket_close (plugin->udp_sockv6.desc);
1779 plugin->udp_sockv6.desc = NULL;
1780 break;
1781 }
1782 }
1783 if (plugin->udp_sockv6.desc != NULL)
1784 {
1785 plugin->udp_sockv6.port = ntohs(serverAddrv6.sin6_port);
1786 sockets_created++;
1787 }
1788 }
1789 }
1790
1791 plugin->udp_sockv4.desc = GNUNET_NETWORK_socket_create (PF_INET, SOCK_DGRAM, 0);
1792 if (NULL == plugin->udp_sockv4.desc)
1793 {
1794 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "socket");
1795 }
1796 else
1797 {
1798 memset (&serverAddrv4, 0, sizeof (serverAddrv4));
1799#if HAVE_SOCKADDR_IN_SIN_LEN
1800 serverAddrv4.sin_len = sizeof (serverAddrv4);
1801#endif
1802 serverAddrv4.sin_family = AF_INET;
1803 serverAddrv4.sin_addr.s_addr = INADDR_ANY;
1804 if (plugin->bind_address != NULL)
1805 {
1806 if (1 != inet_pton(AF_INET, plugin->bind_address, &serverAddrv4.sin_addr))
1807 return 0;
1808 }
1809 serverAddrv4.sin_port = htons (plugin->port);
1810 addrlen = sizeof (serverAddrv4);
1811 serverAddr = (struct sockaddr *) &serverAddrv4;
1812#if DEBUG_UDP
1813 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1814 "Binding to IPv4 port %d\n",
1815 ntohs(serverAddrv4.sin_port));
1816#endif
1817 tries = 0;
1818 while (GNUNET_NETWORK_socket_bind (plugin->udp_sockv4.desc, serverAddr, addrlen) !=
1819 GNUNET_OK)
1820 {
1821 serverAddrv4.sin_port = htons (GNUNET_CRYPTO_random_u32(GNUNET_CRYPTO_QUALITY_STRONG, 33537) + 32000); /* Find a good, non-root port */
1822#if DEBUG_UDP
1823 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1824 "IPv4 Binding failed, trying new port %d\n",
1825 ntohs(serverAddrv4.sin_port));
1826#endif
1827 tries++;
1828 if (tries > 10)
1829 {
1830 GNUNET_NETWORK_socket_close (plugin->udp_sockv4.desc);
1831 plugin->udp_sockv4.desc = NULL;
1832 break;
1833 }
1834 }
1835 if (plugin->udp_sockv4.desc != NULL)
1836 {
1837 plugin->udp_sockv4.port = ntohs(serverAddrv4.sin_port);
1838 sockets_created++;
1839 }
1840 }
1841
1842 plugin->rs = GNUNET_NETWORK_fdset_create ();
1843 GNUNET_NETWORK_fdset_zero (plugin->rs);
1844 if (NULL != plugin->udp_sockv4.desc)
1845 GNUNET_NETWORK_fdset_set (plugin->rs,
1846 plugin->udp_sockv4.desc);
1847 if (NULL != plugin->udp_sockv6.desc)
1848 GNUNET_NETWORK_fdset_set (plugin->rs,
1849 plugin->udp_sockv6.desc);
1850
1851 plugin->select_task =
1852 GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
1853 GNUNET_SCHEDULER_NO_TASK,
1854 GNUNET_TIME_UNIT_FOREVER_REL, plugin->rs,
1855 NULL, &udp_plugin_select, plugin);
1856 return sockets_created;
1857}
1858
1859
1860 1175
1861/** 1176/**
1862 * Check if the given port is plausible (must be either 1177 * Check if the given port is plausible (must be either
@@ -1870,11 +1185,8 @@ udp_transport_server_start (void *cls)
1870static int 1185static int
1871check_port (struct Plugin *plugin, uint16_t in_port) 1186check_port (struct Plugin *plugin, uint16_t in_port)
1872{ 1187{
1873 if ( (plugin->behind_nat == GNUNET_YES) && (in_port == 0) ) 1188 if (in_port == 0)
1874 return GNUNET_OK; 1189 return GNUNET_OK;
1875 if ( (plugin->only_nat_addresses == GNUNET_YES) &&
1876 (plugin->behind_nat == GNUNET_YES) )
1877 return GNUNET_SYSERR; /* odd case... */
1878 if (in_port == plugin->port) 1190 if (in_port == plugin->port)
1879 return GNUNET_OK; 1191 return GNUNET_OK;
1880 return GNUNET_SYSERR; 1192 return GNUNET_SYSERR;
@@ -1898,16 +1210,11 @@ check_port (struct Plugin *plugin, uint16_t in_port)
1898 * 1210 *
1899 */ 1211 */
1900static int 1212static int
1901udp_check_address (void *cls, 1213udp_plugin_check_address (void *cls,
1902 const void *addr, 1214 const void *addr,
1903 size_t addrlen) 1215 size_t addrlen)
1904{ 1216{
1905 struct Plugin *plugin = cls; 1217 struct Plugin *plugin = cls;
1906
1907 const void *sb;
1908 struct in_addr a4;
1909 struct in6_addr a6;
1910 int af;
1911 struct IPv4UdpAddress *v4; 1218 struct IPv4UdpAddress *v4;
1912 struct IPv6UdpAddress *v6; 1219 struct IPv6UdpAddress *v6;
1913 1220
@@ -1917,20 +1224,16 @@ udp_check_address (void *cls,
1917 GNUNET_break_op (0); 1224 GNUNET_break_op (0);
1918 return GNUNET_SYSERR; 1225 return GNUNET_SYSERR;
1919 } 1226 }
1920
1921 if (addrlen == sizeof (struct IPv4UdpAddress)) 1227 if (addrlen == sizeof (struct IPv4UdpAddress))
1922 { 1228 {
1923 v4 = (struct IPv4UdpAddress *) addr; 1229 v4 = (struct IPv4UdpAddress *) addr;
1924 if (GNUNET_OK != 1230 if (GNUNET_OK !=
1925 check_port (plugin, ntohs (v4->u_port))) 1231 check_port (plugin, ntohs (v4->u4_port)))
1926 return GNUNET_SYSERR; 1232 return GNUNET_SYSERR;
1927 if (GNUNET_OK != 1233 if (GNUNET_OK !=
1928 check_local_addr (plugin, &v4->ipv4_addr, sizeof (uint32_t))) 1234 GNUNET_NAT_test_address (plugin->nat,
1235 &v4->ipv4_addr, sizeof (struct in_addr)))
1929 return GNUNET_SYSERR; 1236 return GNUNET_SYSERR;
1930
1931 af = AF_INET;
1932 memcpy (&a4, &v4->ipv4_addr, sizeof (a4));
1933 sb = &a4;
1934 } 1237 }
1935 else 1238 else
1936 { 1239 {
@@ -1944,14 +1247,10 @@ udp_check_address (void *cls,
1944 check_port (plugin, ntohs (v6->u6_port))) 1247 check_port (plugin, ntohs (v6->u6_port)))
1945 return GNUNET_SYSERR; 1248 return GNUNET_SYSERR;
1946 if (GNUNET_OK != 1249 if (GNUNET_OK !=
1947 check_local_addr (plugin, &v6->ipv6_addr, sizeof (struct in6_addr))) 1250 GNUNET_NAT_test_address (plugin->nat,
1251 &v6->ipv6_addr, sizeof (struct in6_addr)))
1948 return GNUNET_SYSERR; 1252 return GNUNET_SYSERR;
1949
1950 af = AF_INET6;
1951 memcpy (&a6, &v6->ipv6_addr, sizeof (a6));
1952 sb = &a6;
1953 } 1253 }
1954
1955 return GNUNET_OK; 1254 return GNUNET_OK;
1956} 1255}
1957 1256
@@ -2028,9 +1327,9 @@ udp_plugin_address_pretty_printer (void *cls,
2028 u4 = addr; 1327 u4 = addr;
2029 memset (&a4, 0, sizeof (a4)); 1328 memset (&a4, 0, sizeof (a4));
2030 a4.sin_family = AF_INET; 1329 a4.sin_family = AF_INET;
2031 a4.sin_port = u4->u_port; 1330 a4.sin_port = u4->u4_port;
2032 a4.sin_addr.s_addr = u4->ipv4_addr; 1331 a4.sin_addr.s_addr = u4->ipv4_addr;
2033 port = ntohs (u4->u_port); 1332 port = ntohs (u4->u4_port);
2034 sb = &a4; 1333 sb = &a4;
2035 sbs = sizeof (a4); 1334 sbs = sizeof (a4);
2036 } 1335 }
@@ -2050,99 +1349,6 @@ udp_plugin_address_pretty_printer (void *cls,
2050 !numeric, timeout, &append_port, ppc); 1349 !numeric, timeout, &append_port, ppc);
2051} 1350}
2052 1351
2053/**
2054 * Return the actual path to a file found in the current
2055 * PATH environment variable.
2056 *
2057 * @param binary the name of the file to find
2058 */
2059static char *
2060get_path_from_PATH (char *binary)
2061{
2062 char *path;
2063 char *pos;
2064 char *end;
2065 char *buf;
2066 const char *p;
2067
2068 p = getenv ("PATH");
2069 if (p == NULL)
2070 return NULL;
2071 path = GNUNET_strdup (p); /* because we write on it */
2072 buf = GNUNET_malloc (strlen (path) + 20);
2073 pos = path;
2074
2075 while (NULL != (end = strchr (pos, PATH_SEPARATOR)))
2076 {
2077 *end = '\0';
2078 sprintf (buf, "%s/%s", pos, binary);
2079 if (GNUNET_DISK_file_test (buf) == GNUNET_YES)
2080 {
2081 GNUNET_free (path);
2082 return buf;
2083 }
2084 pos = end + 1;
2085 }
2086 sprintf (buf, "%s/%s", pos, binary);
2087 if (GNUNET_DISK_file_test (buf) == GNUNET_YES)
2088 {
2089 GNUNET_free (path);
2090 return buf;
2091 }
2092 GNUNET_free (buf);
2093 GNUNET_free (path);
2094 return NULL;
2095}
2096
2097/**
2098 * Check whether the suid bit is set on a file.
2099 * Attempts to find the file using the current
2100 * PATH environment variable as a search path.
2101 *
2102 * @param binary the name of the file to check
2103 */
2104static int
2105check_gnunet_nat_binary(char *binary)
2106{
2107 struct stat statbuf;
2108 char *p;
2109#ifdef MINGW
2110 SOCKET rawsock;
2111#endif
2112
2113#ifdef MINGW
2114 char *binaryexe;
2115 GNUNET_asprintf (&binaryexe, "%s.exe", binary);
2116 p = get_path_from_PATH (binaryexe);
2117 free (binaryexe);
2118#else
2119 p = get_path_from_PATH (binary);
2120#endif
2121 if (p == NULL)
2122 return GNUNET_NO;
2123 if (0 != STAT (p, &statbuf))
2124 {
2125 GNUNET_free (p);
2126 return GNUNET_SYSERR;
2127 }
2128 GNUNET_free (p);
2129#ifndef MINGW
2130 if ( (0 != (statbuf.st_mode & S_ISUID)) &&
2131 (statbuf.st_uid == 0) )
2132 return GNUNET_YES;
2133 return GNUNET_NO;
2134#else
2135 rawsock = socket (AF_INET, SOCK_RAW, IPPROTO_ICMP);
2136 if (INVALID_SOCKET == rawsock)
2137 {
2138 DWORD err = GetLastError ();
2139 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "socket (AF_INET, SOCK_RAW, IPPROTO_ICMP) have failed! GLE = %d\n", err);
2140 return GNUNET_NO; /* not running as administrator */
2141 }
2142 closesocket (rawsock);
2143 return GNUNET_YES;
2144#endif
2145}
2146 1352
2147/** 1353/**
2148 * Function called for a quick conversion of the binary address to 1354 * Function called for a quick conversion of the binary address to
@@ -2182,7 +1388,7 @@ udp_address_to_string (void *cls,
2182 { 1388 {
2183 t4 = addr; 1389 t4 = addr;
2184 af = AF_INET; 1390 af = AF_INET;
2185 port = ntohs (t4->u_port); 1391 port = ntohs (t4->u4_port);
2186 memcpy (&a4, &t4->ipv4_addr, sizeof (a4)); 1392 memcpy (&a4, &t4->ipv4_addr, sizeof (a4));
2187 sb = &a4; 1393 sb = &a4;
2188 } 1394 }
@@ -2197,6 +1403,58 @@ udp_address_to_string (void *cls,
2197 return rbuf; 1403 return rbuf;
2198} 1404}
2199 1405
1406
1407/**
1408 * Our external IP address/port mapping has changed.
1409 *
1410 * @param cls closure, the 'struct LocalAddrList'
1411 * @param add_remove GNUNET_YES to mean the new public IP address, GNUNET_NO to mean
1412 * the previous (now invalid) one
1413 * @param addr either the previous or the new public IP address
1414 * @param addrlen actual lenght of the address
1415 */
1416static void
1417udp_nat_port_map_callback (void *cls,
1418 int add_remove,
1419 const struct sockaddr *addr,
1420 socklen_t addrlen)
1421{
1422 struct Plugin *plugin = cls;
1423 struct IPv4UdpAddress u4;
1424 struct IPv6UdpAddress u6;
1425 void *arg;
1426 size_t args;
1427
1428 /* convert 'addr' to our internal format */
1429 switch (addr->sa_family)
1430 {
1431 case AF_INET:
1432 GNUNET_assert (addrlen == sizeof (struct sockaddr_in));
1433 u4.ipv4_addr = ((struct sockaddr_in *) addr)->sin_addr.s_addr;
1434 u4.u4_port = ((struct sockaddr_in *) addr)->sin_port;
1435 arg = &u4;
1436 args = sizeof (u4);
1437 break;
1438 case AF_INET6:
1439 GNUNET_assert (addrlen == sizeof (struct sockaddr_in6));
1440 memcpy (&u6.ipv6_addr,
1441 &((struct sockaddr_in6 *) addr)->sin6_addr,
1442 sizeof (struct in6_addr));
1443 u6.u6_port = ((struct sockaddr_in6 *) addr)->sin6_port;
1444 arg = &u6;
1445 args = sizeof (u6);
1446 break;
1447 default:
1448 GNUNET_break (0);
1449 return;
1450 }
1451 /* modify our published address list */
1452 plugin->env->notify_address (plugin->env->cls,
1453 add_remove,
1454 arg, args);
1455}
1456
1457
2200/** 1458/**
2201 * The exported method. Makes the core api available via a global and 1459 * The exported method. Makes the core api available via a global and
2202 * returns the udp transport API. 1460 * returns the udp transport API.
@@ -2210,89 +1468,13 @@ libgnunet_plugin_transport_udp_init (void *cls)
2210 struct GNUNET_TRANSPORT_PluginFunctions *api; 1468 struct GNUNET_TRANSPORT_PluginFunctions *api;
2211 struct Plugin *plugin; 1469 struct Plugin *plugin;
2212 int sockets_created; 1470 int sockets_created;
2213 int behind_nat; 1471 struct sockaddr_in serverAddrv4;
2214 int allow_nat; 1472 struct sockaddr_in6 serverAddrv6;
2215 int only_nat_addresses; 1473 struct sockaddr *serverAddr;
2216 int use_localaddresses; 1474 struct sockaddr *addrs[2];
2217 char *internal_address; 1475 socklen_t addrlens[2];
2218 char *external_address; 1476 socklen_t addrlen;
2219 struct IPv4UdpAddress v4_address; 1477 unsigned int tries;
2220
2221 if (GNUNET_YES == GNUNET_CONFIGURATION_get_value_yesno (env->cfg,
2222 "nat",
2223 "BEHIND_NAT"))
2224 {
2225 /* We are behind nat (according to the user) */
2226 if (check_gnunet_nat_binary("gnunet-nat-server") == GNUNET_YES)
2227 behind_nat = GNUNET_YES;
2228 else
2229 {
2230 behind_nat = GNUNET_NO;
2231 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Configuration specified you are behind a NAT, but gnunet-nat-server is not installed properly (suid bit not set)!\n");
2232 }
2233 }
2234 else
2235 behind_nat = GNUNET_NO; /* We are not behind nat! */
2236
2237 if (GNUNET_YES == GNUNET_CONFIGURATION_get_value_yesno (env->cfg,
2238 "nat",
2239 "ALLOW_NAT"))
2240 {
2241 if (check_gnunet_nat_binary("gnunet-nat-client") == GNUNET_YES)
2242 allow_nat = GNUNET_YES; /* We will try to connect to NAT'd peers */
2243 else
2244 {
2245 allow_nat = GNUNET_NO;
2246 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Configuration specified you want to connect to NAT'd peers, but gnunet-nat-client is not installed properly (suid bit not set)!\n");
2247 }
2248
2249 }
2250 else
2251 allow_nat = GNUNET_NO; /* We don't want to try to help NAT'd peers */
2252
2253 if (GNUNET_YES == GNUNET_CONFIGURATION_get_value_yesno (env->cfg,
2254 "nat",
2255 "ONLY_NAT_ADDRESSES"))
2256 only_nat_addresses = GNUNET_YES; /* We will only report our addresses as NAT'd */
2257 else
2258 only_nat_addresses = GNUNET_NO; /* We will report our addresses as NAT'd and non-NAT'd */
2259
2260 external_address = NULL;
2261 if (((GNUNET_YES == behind_nat) || (GNUNET_YES == allow_nat)) && (GNUNET_OK !=
2262 GNUNET_CONFIGURATION_get_value_string (env->cfg,
2263 "nat",
2264 "EXTERNAL_ADDRESS",
2265 &external_address)))
2266 {
2267 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2268 _("Require EXTERNAL_ADDRESS in section `%s' in configuration (either BEHIND_NAT or ALLOW_NAT set to YES)!\n"),
2269 "nat");
2270 return NULL;
2271 }
2272
2273 if ((external_address != NULL) && (inet_pton(AF_INET, external_address, &v4_address.ipv4_addr) != 1))
2274 {
2275 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Malformed EXTERNAL_ADDRESS %s given in configuration!\n", external_address);
2276 }
2277
2278 internal_address = NULL;
2279 if ((GNUNET_YES == behind_nat) && (GNUNET_OK !=
2280 GNUNET_CONFIGURATION_get_value_string (env->cfg,
2281 "nat",
2282 "INTERNAL_ADDRESS",
2283 &internal_address)))
2284 {
2285 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2286 _("Require INTERNAL_ADDRESS in section `%s' in configuration!\n"),
2287 "nat");
2288 GNUNET_free_non_null(external_address);
2289 return NULL;
2290 }
2291
2292 if ((internal_address != NULL) && (inet_pton(AF_INET, internal_address, &v4_address.ipv4_addr) != 1))
2293 {
2294 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Malformed INTERNAL_ADDRESS %s given in configuration!\n", internal_address);
2295 }
2296 1478
2297 if (GNUNET_OK != 1479 if (GNUNET_OK !=
2298 GNUNET_CONFIGURATION_get_value_number (env->cfg, 1480 GNUNET_CONFIGURATION_get_value_number (env->cfg,
@@ -2300,15 +1482,13 @@ libgnunet_plugin_transport_udp_init (void *cls)
2300 "PORT", 1482 "PORT",
2301 &port)) 1483 &port))
2302 port = UDP_NAT_DEFAULT_PORT; 1484 port = UDP_NAT_DEFAULT_PORT;
2303 else if (port > 65535) 1485 if (port > 65535)
2304 { 1486 {
2305 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 1487 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2306 _("Given `%s' option is out of range: %llu > %u\n"), 1488 _("Given `%s' option is out of range: %llu > %u\n"),
2307 "PORT", 1489 "PORT",
2308 port, 1490 port,
2309 65535); 1491 65535);
2310 GNUNET_free_non_null(external_address);
2311 GNUNET_free_non_null(internal_address);
2312 return NULL; 1492 return NULL;
2313 } 1493 }
2314 1494
@@ -2317,26 +1497,9 @@ libgnunet_plugin_transport_udp_init (void *cls)
2317 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 1497 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
2318 _("MTU %llu for `%s' is probably too low!\n"), mtu, 1498 _("MTU %llu for `%s' is probably too low!\n"), mtu,
2319 "UDP"); 1499 "UDP");
2320
2321 use_localaddresses = GNUNET_NO;
2322 if (GNUNET_CONFIGURATION_have_value (env->cfg,
2323 "transport-udp", "USE_LOCALADDR"))
2324 {
2325 use_localaddresses = GNUNET_CONFIGURATION_get_value_yesno (env->cfg,
2326 "transport-udp",
2327 "USE_LOCALADDR");
2328 }
2329
2330 plugin = GNUNET_malloc (sizeof (struct Plugin)); 1500 plugin = GNUNET_malloc (sizeof (struct Plugin));
2331 plugin->external_address = external_address;
2332 plugin->internal_address = internal_address;
2333 plugin->port = port; 1501 plugin->port = port;
2334 plugin->behind_nat = behind_nat;
2335 plugin->allow_nat = allow_nat;
2336 plugin->only_nat_addresses = only_nat_addresses;
2337 plugin->env = env; 1502 plugin->env = env;
2338 plugin->use_localaddresses = use_localaddresses;
2339
2340 api = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_PluginFunctions)); 1503 api = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_PluginFunctions));
2341 api->cls = plugin; 1504 api->cls = plugin;
2342 1505
@@ -2344,70 +1507,191 @@ libgnunet_plugin_transport_udp_init (void *cls)
2344 api->disconnect = &udp_disconnect; 1507 api->disconnect = &udp_disconnect;
2345 api->address_pretty_printer = &udp_plugin_address_pretty_printer; 1508 api->address_pretty_printer = &udp_plugin_address_pretty_printer;
2346 api->address_to_string = &udp_address_to_string; 1509 api->address_to_string = &udp_address_to_string;
2347 api->check_address = &udp_check_address; 1510 api->check_address = &udp_plugin_check_address;
2348 1511
2349 if (GNUNET_YES == GNUNET_CONFIGURATION_get_value_string(env->cfg, "transport-udp", "BINDTO", &plugin->bind_address)) 1512 if (GNUNET_YES == GNUNET_CONFIGURATION_get_value_string(env->cfg,
2350 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Binding udp plugin to specific address: `%s'\n", plugin->bind_address); 1513 "transport-udp",
2351 if (GNUNET_YES == GNUNET_CONFIGURATION_get_value_string(env->cfg, "transport-udp", "BINDTO6", &plugin->bind6_address)) 1514 "BINDTO",
2352 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Binding udp plugin to specific address: `%s'\n", plugin->bind6_address); 1515 &plugin->bind_address))
1516 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1517 "Binding udp plugin to specific address: `%s'\n",
1518 plugin->bind_address);
1519 if (GNUNET_YES == GNUNET_CONFIGURATION_get_value_string(env->cfg,
1520 "transport-udp",
1521 "BINDTO6",
1522 &plugin->bind6_address))
1523 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1524 "Binding udp plugin to specific address: `%s'\n",
1525 plugin->bind6_address);
2353 1526
2354 if (plugin->behind_nat == GNUNET_NO) 1527 sockets_created = 0;
1528 if ( (GNUNET_YES !=
1529 GNUNET_CONFIGURATION_get_value_yesno (plugin->env->cfg,
1530 "gnunetd",
1531 "DISABLEV6")))
2355 { 1532 {
2356 GNUNET_OS_network_interfaces_list (&process_interfaces, plugin); 1533 plugin->udp_sockv6.desc = GNUNET_NETWORK_socket_create (PF_INET6, SOCK_DGRAM, 0);
2357 } 1534 if (NULL == plugin->udp_sockv6.desc)
1535 {
1536 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "udp", "socket");
1537 }
1538 else
1539 {
1540 memset (&serverAddrv6, 0, sizeof (serverAddrv6));
1541#if HAVE_SOCKADDR_IN_SIN_LEN
1542 serverAddrv6.sin6_len = sizeof (serverAddrv6);
1543#endif
2358 1544
2359 plugin->hostname_dns = GNUNET_RESOLVER_hostname_resolve (AF_UNSPEC, 1545 serverAddrv6.sin6_family = AF_INET6;
2360 HOSTNAME_RESOLVE_TIMEOUT, 1546 serverAddrv6.sin6_addr = in6addr_any;
2361 &process_hostname_ips, 1547 if (plugin->bind6_address != NULL)
2362 plugin); 1548 {
1549 if (1 != inet_pton(AF_INET6, plugin->bind6_address, &serverAddrv6.sin6_addr))
1550 return 0;
1551 }
1552 serverAddrv6.sin6_port = htons (plugin->port);
1553 addrlen = sizeof (serverAddrv6);
1554 serverAddr = (struct sockaddr *) &serverAddrv6;
1555#if DEBUG_UDP
1556 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1557 "Binding to IPv6 port %d\n",
1558 ntohs(serverAddrv6.sin6_port));
1559#endif
1560 tries = 0;
1561 while (GNUNET_NETWORK_socket_bind (plugin->udp_sockv6.desc, serverAddr, addrlen) !=
1562 GNUNET_OK)
1563 {
1564 serverAddrv6.sin6_port
1565 = htons (GNUNET_CRYPTO_random_u32(GNUNET_CRYPTO_QUALITY_STRONG, 33537) + 32000); /* Find a good, non-root port */
1566#if DEBUG_UDP
1567 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1568 "IPv6 Binding failed, trying new port %d\n",
1569 ntohs(serverAddrv6.sin6_port));
1570#endif
1571 tries++;
1572 if (tries > 10)
1573 {
1574 GNUNET_NETWORK_socket_close (plugin->udp_sockv6.desc);
1575 plugin->udp_sockv6.desc = NULL;
1576 break;
1577 }
1578 }
1579 if (plugin->udp_sockv6.desc != NULL)
1580 {
1581 plugin->udp_sockv6.port = ntohs(serverAddrv6.sin6_port);
1582 addrs[sockets_created] = (struct sockaddr*) &serverAddrv6;
1583 addrlens[sockets_created] = sizeof (serverAddrv6);
1584 sockets_created++;
1585 }
1586 }
1587 }
2363 1588
2364 if ((plugin->behind_nat == GNUNET_YES) && (inet_pton(AF_INET, plugin->external_address, &v4_address.ipv4_addr) == 1)) 1589 plugin->udp_sockv4.desc = GNUNET_NETWORK_socket_create (PF_INET, SOCK_DGRAM, 0);
1590 if (NULL == plugin->udp_sockv4.desc)
2365 { 1591 {
2366 v4_address.u_port = htons(0); 1592 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "socket");
2367 plugin->env->notify_address (plugin->env->cls,
2368 "udp",
2369 &v4_address, sizeof(v4_address), GNUNET_TIME_UNIT_FOREVER_REL);
2370 add_to_address_list (plugin, &v4_address.ipv4_addr, sizeof (uint32_t));
2371 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Notifying plugin of address %s:0\n", plugin->external_address);
2372 } 1593 }
2373 else if ((plugin->external_address != NULL) && (inet_pton(AF_INET, plugin->external_address, &v4_address.ipv4_addr) == 1)) 1594 else
2374 { 1595 {
2375 v4_address.u_port = htons(plugin->port); 1596 memset (&serverAddrv4, 0, sizeof (serverAddrv4));
2376 plugin->env->notify_address (plugin->env->cls, 1597#if HAVE_SOCKADDR_IN_SIN_LEN
2377 "udp", 1598 serverAddrv4.sin_len = sizeof (serverAddrv4);
2378 &v4_address, sizeof(v4_address), GNUNET_TIME_UNIT_FOREVER_REL); 1599#endif
2379 add_to_address_list (plugin, &v4_address.ipv4_addr, sizeof (uint32_t)); 1600 serverAddrv4.sin_family = AF_INET;
1601 serverAddrv4.sin_addr.s_addr = INADDR_ANY;
1602 if (plugin->bind_address != NULL)
1603 {
1604 if (1 != inet_pton(AF_INET, plugin->bind_address, &serverAddrv4.sin_addr))
1605 return 0;
1606 }
1607 serverAddrv4.sin_port = htons (plugin->port);
1608 addrlen = sizeof (serverAddrv4);
1609 serverAddr = (struct sockaddr *) &serverAddrv4;
1610#if DEBUG_UDP
1611 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1612 "Binding to IPv4 port %d\n",
1613 ntohs(serverAddrv4.sin_port));
1614#endif
1615 tries = 0;
1616 while (GNUNET_NETWORK_socket_bind (plugin->udp_sockv4.desc, serverAddr, addrlen) !=
1617 GNUNET_OK)
1618 {
1619 serverAddrv4.sin_port = htons (GNUNET_CRYPTO_random_u32(GNUNET_CRYPTO_QUALITY_STRONG, 33537) + 32000); /* Find a good, non-root port */
1620#if DEBUG_UDP
1621 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1622 "IPv4 Binding failed, trying new port %d\n",
1623 ntohs(serverAddrv4.sin_port));
1624#endif
1625 tries++;
1626 if (tries > 10)
1627 {
1628 GNUNET_NETWORK_socket_close (plugin->udp_sockv4.desc);
1629 plugin->udp_sockv4.desc = NULL;
1630 break;
1631 }
1632 }
1633 if (plugin->udp_sockv4.desc != NULL)
1634 {
1635 plugin->udp_sockv4.port = ntohs(serverAddrv4.sin_port);
1636 addrs[sockets_created] = (struct sockaddr*) &serverAddrv4;
1637 addrlens[sockets_created] = sizeof (serverAddrv4);
1638 sockets_created++;
1639 }
2380 } 1640 }
2381 1641
2382 sockets_created = udp_transport_server_start (plugin); 1642 plugin->rs = GNUNET_NETWORK_fdset_create ();
1643 GNUNET_NETWORK_fdset_zero (plugin->rs);
1644 if (NULL != plugin->udp_sockv4.desc)
1645 GNUNET_NETWORK_fdset_set (plugin->rs,
1646 plugin->udp_sockv4.desc);
1647 if (NULL != plugin->udp_sockv6.desc)
1648 GNUNET_NETWORK_fdset_set (plugin->rs,
1649 plugin->udp_sockv6.desc);
1650
1651 plugin->select_task =
1652 GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
1653 GNUNET_SCHEDULER_NO_TASK,
1654 GNUNET_TIME_UNIT_FOREVER_REL, plugin->rs,
1655 NULL, &udp_plugin_select, plugin);
2383 if (sockets_created == 0) 1656 if (sockets_created == 0)
2384 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 1657 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2385 _("Failed to open UDP sockets\n")); 1658 _("Failed to open UDP sockets\n"));
1659 plugin->nat = GNUNET_NAT_register (env->cfg,
1660 GNUNET_NO,
1661 port,
1662 sockets_created,
1663 (const struct sockaddr**) addrs, addrlens,
1664 &udp_nat_port_map_callback,
1665 &udp_plugin_reversal_callback,
1666 plugin);
2386 return api; 1667 return api;
2387} 1668}
2388 1669
1670
2389void * 1671void *
2390libgnunet_plugin_transport_udp_done (void *cls) 1672libgnunet_plugin_transport_udp_done (void *cls)
2391{ 1673{
2392 struct GNUNET_TRANSPORT_PluginFunctions *api = cls; 1674 struct GNUNET_TRANSPORT_PluginFunctions *api = cls;
2393 struct Plugin *plugin = api->cls; 1675 struct Plugin *plugin = api->cls;
2394 struct LocalAddrList *lal;
2395 1676
2396 udp_transport_server_stop (plugin); 1677 if (plugin->select_task != GNUNET_SCHEDULER_NO_TASK)
2397 if (NULL != plugin->hostname_dns)
2398 { 1678 {
2399 GNUNET_RESOLVER_request_cancel (plugin->hostname_dns); 1679 GNUNET_SCHEDULER_cancel (plugin->select_task);
2400 plugin->hostname_dns = NULL; 1680 plugin->select_task = GNUNET_SCHEDULER_NO_TASK;
2401 } 1681 }
2402 1682 if (plugin->udp_sockv4.desc != NULL)
2403 GNUNET_NETWORK_fdset_destroy (plugin->rs); 1683 {
2404 while (NULL != (lal = plugin->lal_head)) 1684 GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (plugin->udp_sockv4.desc));
1685 plugin->udp_sockv4.desc = NULL;
1686 }
1687 if (plugin->udp_sockv6.desc != NULL)
2405 { 1688 {
2406 GNUNET_CONTAINER_DLL_remove (plugin->lal_head, 1689 GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (plugin->udp_sockv6.desc));
2407 plugin->lal_tail, 1690 plugin->udp_sockv6.desc = NULL;
2408 lal);
2409 GNUNET_free (lal);
2410 } 1691 }
1692 GNUNET_NETWORK_fdset_destroy (plugin->rs);
1693 GNUNET_NAT_unregister (plugin->nat);
1694 plugin->nat = NULL;
2411 GNUNET_free (plugin); 1695 GNUNET_free (plugin);
2412 GNUNET_free (api); 1696 GNUNET_free (api);
2413 return NULL; 1697 return NULL;