From d7d0448410816d04fb68cd2d3245a5813f087244 Mon Sep 17 00:00:00 2001 From: t3sserakt Date: Thu, 23 Apr 2020 15:03:41 +0200 Subject: [PATCH] added reolver --- src/transport/Makefile.am | 14 +- src/transport/gnunet-communicator-tcp.c | 379 ++++++++++++++++-------- 2 files changed, 266 insertions(+), 127 deletions(-) diff --git a/src/transport/Makefile.am b/src/transport/Makefile.am index 3028b29b4..15f3f5647 100644 --- a/src/transport/Makefile.am +++ b/src/transport/Makefile.am @@ -673,13 +673,13 @@ TESTS += \ test_transport_api_timeout_udp \ test_transport_api_udp_nat \ test_transport_api_reliability_udp \ -test_quota_compliance_udp \ -test_communicator_basic-unix \ -test_communicator_basic-tcp \ -test_communicator_basic-udp \ -test_communicator_rekey-tcp \ -test_communicator_rekey-udp \ -test_communicator_backchannel-udp + test_quota_compliance_udp \ + test_communicator_basic-unix \ + test_communicator_basic-tcp \ + test_communicator_basic-udp \ + test_communicator_rekey-tcp \ + test_communicator_rekey-udp \ + test_communicator_backchannel-udp endif endif diff --git a/src/transport/gnunet-communicator-tcp.c b/src/transport/gnunet-communicator-tcp.c index 045a57d0f..b9d023e54 100644 --- a/src/transport/gnunet-communicator-tcp.c +++ b/src/transport/gnunet-communicator-tcp.c @@ -40,6 +40,8 @@ #include "gnunet_nt_lib.h" #include "gnunet_nat_service.h" #include "gnunet_statistics_service.h" +#include "gnunet_ats_transport_service.h" +#include "transport.h" #include "gnunet_transport_communication_service.h" /** @@ -485,7 +487,6 @@ struct ProtoQueue size_t ibuf_off; }; - /** * ID of listen task */ @@ -556,6 +557,11 @@ static struct ProtoQueue *proto_head; */ static struct ProtoQueue *proto_tail; +/** + * Handle for DNS lookup of bindto address + */ +struct GNUNET_RESOLVER_RequestHandle *resolve_request_handle; + /** * We have been notified that our listen socket has something to @@ -1096,26 +1102,13 @@ queue_read (void *cls) queue_finish (queue); } - -/** - * Convert TCP bind specification to a `struct sockaddr *` - * - * @param bindto bind specification to convert - * @param[out] sock_len set to the length of the address - * @return converted bindto specification - */ static struct sockaddr * -tcp_address_to_sockaddr (const char *bindto, socklen_t *sock_len) +tcp_address_to_sockaddr_port_only (const char *bindto, unsigned int port, socklen_t *sock_len) { + struct sockaddr *in; - unsigned int port; - char dummy[2]; - char *colon; - char *cp; - if (1 == sscanf (bindto, "%u%1s", &port, dummy)) - { - /* interpreting value as just a PORT number */ + /* interpreting value as just a PORT number */ if (port > UINT16_MAX) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, @@ -1154,46 +1147,80 @@ tcp_address_to_sockaddr (const char *bindto, socklen_t *sock_len) in = (struct sockaddr *) i6; } return in; +} + +static char * +extract_ipv6_address (char *cp) +{ + + const char *start; + + start = cp; + if (('[' == *cp) && (']' == cp[strlen (cp) - 1])) + { + start++; /* skip over '[' */ + cp[strlen (cp) - 1] = '\0'; /* eat ']' */ } - cp = GNUNET_strdup (bindto); - colon = strrchr (cp, ':'); + + return start; +} + +static unsigned int +extract_port(char *colon) +{ + unsigned int port; + char dummy[2]; if (NULL != colon) - { - /* interpet value after colon as port */ - *colon = '\0'; - colon++; - if (1 == sscanf (colon, "%u%1s", &port, dummy)) { - /* interpreting value as just a PORT number */ - if (port > UINT16_MAX) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "BINDTO specification `%s' invalid: value too large for port\n", - bindto); - GNUNET_free (cp); - return NULL; - } + /* interpet value after colon as port */ + *colon = '\0'; + colon++; + if (1 == sscanf (colon, "%u%1s", &port, dummy)) + { + /* interpreting value as just a PORT number */ + if (port > UINT16_MAX) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Port `%s' invalid: value too large for port\n", + port); + //GNUNET_free (cp); + return NULL; + } + } + else + { + GNUNET_log ( + GNUNET_ERROR_TYPE_ERROR, + "BINDTO specification invalid: last ':' not followed by number\n"); + //GNUNET_free (cp); + return NULL; + } } - else + else { - GNUNET_log ( - GNUNET_ERROR_TYPE_ERROR, - "BINDTO specification `%s' invalid: last ':' not followed by number\n", - bindto); - GNUNET_free (cp); - return NULL; + /* interpret missing port as 0, aka pick any free one */ + port = 0; } - } - else - { - /* interpret missing port as 0, aka pick any free one */ - port = 0; - } + + return port; +} + +static struct sockaddr * +tcp_address_to_sockaddr_numeric (socklen_t *sock_len, struct sockaddr_in v4, struct sockaddr_in6 v6, char *colon) +{ + + unsigned int port; + struct sockaddr *in; + + port = extract_port(colon); + + if (NULL == port) + return NULL; + { /* try IPv4 */ - struct sockaddr_in v4; - if (1 == inet_pton (AF_INET, cp, &v4.sin_addr)) + if (NULL != &v4.sin_addr) { v4.sin_family = AF_INET; v4.sin_port = htons ((uint16_t) port); @@ -1202,22 +1229,14 @@ tcp_address_to_sockaddr (const char *bindto, socklen_t *sock_len) #endif in = GNUNET_memdup (&v4, sizeof(v4)); *sock_len = sizeof(v4); - GNUNET_free (cp); + //GNUNET_free (cp); return in; } } { /* try IPv6 */ - struct sockaddr_in6 v6; - const char *start; - start = cp; - if (('[' == *cp) && (']' == cp[strlen (cp) - 1])) - { - start++; /* skip over '[' */ - cp[strlen (cp) - 1] = '\0'; /* eat ']' */ - } - if (1 == inet_pton (AF_INET6, start, &v6.sin6_addr)) + if (NULL != &v6.sin6_addr) { v6.sin6_family = AF_INET6; v6.sin6_port = htons ((uint16_t) port); @@ -1226,15 +1245,48 @@ tcp_address_to_sockaddr (const char *bindto, socklen_t *sock_len) #endif in = GNUNET_memdup (&v6, sizeof(v6)); *sock_len = sizeof(v6); - GNUNET_free (cp); + //GNUNET_free (cp); return in; } } - /* #5528 FIXME (feature!): maybe also try getnameinfo()? */ - GNUNET_free (cp); + //GNUNET_free (cp); return NULL; } +/** + * Convert TCP bind specification to a `struct sockaddr *` + * + * @param bindto bind specification to convert + * @param[out] sock_len set to the length of the address + * @return converted bindto specification + */ +static struct sockaddr * +tcp_address_to_sockaddr (const char *bindto, socklen_t *sock_len) +{ + struct sockaddr *in; + unsigned int port; + char dummy[2]; + char *colon; + char *cp; + struct sockaddr_in v4; + struct sockaddr_in6 v6; + const char *start; + socklen_t in_len; + + cp = GNUNET_strdup (bindto); + start = extract_ipv6_address (cp); + + if (1 == sscanf (bindto, "%u%1s", &port, dummy)) + { + in = tcp_address_to_sockaddr_port_only (bindto, port, sock_len); + } + else if (1 == inet_pton (AF_INET, cp, &v4.sin_addr) || 1 == inet_pton (AF_INET6, start, &v6.sin6_addr)) + { + colon = strrchr (cp, ':'); + in = tcp_address_to_sockaddr_numeric (&in_len, v4, v6, colon); + } +} + /** * Setup cipher for outgoing data stream based on target and @@ -1885,7 +1937,6 @@ queue_read_kx (void *cls) queue->read_task = GNUNET_SCHEDULER_add_now (&queue_read, queue); } - /** * Function called by the transport service to initialize a * message queue given address information about another peer. @@ -1905,24 +1956,27 @@ queue_read_kx (void *cls) * invalid */ static int -mq_init (void *cls, const struct GNUNET_PeerIdentity *peer, const char *address) +mq_init (void *cls, const struct GNUNET_PeerIdentity *peer, + struct GNUNET_TRANSPORT_CommunicatorHandle *ch, + const struct GNUNET_TRANSPORT_CreateQueue *cq) { struct Queue *queue; const char *path; struct sockaddr *in; socklen_t in_len; struct GNUNET_NETWORK_Handle *sock; + const char *addr = (const char *) &cq[1]; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Connecting to %s\n", address); - if (0 != strncmp (address, + "Connecting to %s\n", addr); + if (0 != strncmp (addr, COMMUNICATOR_ADDRESS_PREFIX "-", strlen (COMMUNICATOR_ADDRESS_PREFIX "-"))) { GNUNET_break_op (0); return GNUNET_SYSERR; } - path = &address[strlen (COMMUNICATOR_ADDRESS_PREFIX "-")]; + path = &addr[strlen (COMMUNICATOR_ADDRESS_PREFIX "-")]; in = tcp_address_to_sockaddr (path, &in_len); sock = GNUNET_NETWORK_socket_create (in->sa_family, SOCK_STREAM, IPPROTO_TCP); @@ -1940,7 +1994,7 @@ mq_init (void *cls, const struct GNUNET_PeerIdentity *peer, const char *address) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "connect to `%s' failed: %s", - address, + addr, strerror (errno)); GNUNET_NETWORK_socket_close (sock); GNUNET_free (in); @@ -1968,7 +2022,6 @@ mq_init (void *cls, const struct GNUNET_PeerIdentity *peer, const char *address) return GNUNET_OK; } - /** * Iterator over all message queues to clean up. * @@ -2113,78 +2166,74 @@ nat_address_cb (void *cls, } } - -/** - * Setup communicator and launch network interactions. - * - * @param cls NULL (always) - * @param args remaining command-line arguments - * @param cfgfile name of the configuration file used (for saving, can be NULL!) - * @param c configuration - */ static void -run (void *cls, - char *const *args, - const char *cfgfile, - const struct GNUNET_CONFIGURATION_Handle *c) +init_own_socket (void *cls, struct sockaddr *resolved_in, socklen_t in_len) { - char *bindto; + struct sockaddr *in; - socklen_t in_len; struct sockaddr_storage in_sto; socklen_t sto_len; + struct sockaddr_in *v4; + struct sockaddr_in6 *v6; + char ipstr[INET6_ADDRSTRLEN]; - (void) cls; - cfg = c; - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_string (cfg, - COMMUNICATOR_CONFIG_SECTION, - "BINDTO", - &bindto)) - { - GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, - COMMUNICATOR_CONFIG_SECTION, - "BINDTO"); - return; - } - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_number (cfg, - COMMUNICATOR_CONFIG_SECTION, - "MAX_QUEUE_LENGTH", - &max_queue_length)) - max_queue_length = DEFAULT_MAX_QUEUE_LENGTH; - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_time (cfg, - COMMUNICATOR_CONFIG_SECTION, - "REKEY_INTERVAL", - &rekey_interval)) - rekey_interval = DEFAULT_REKEY_INTERVAL; - - in = tcp_address_to_sockaddr (bindto, &in_len); - if (NULL == in) + unsigned int port = cls; + if (NULL == resolved_in) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Failed to setup TCP socket address with path `%s'\n", - bindto); - GNUNET_free (bindto); + "Failed to setup TCP socket address\n"); + //TODO Where do we cancel the request + //GNUNET_RESOLVER_request_cancel (resolve_request_handle); + //TODO check where to free after moving code around + //GNUNET_free (bindto); return; } + + inet_ntop(resolved_in->sa_family, resolved_in, ipstr, sizeof(ipstr)); + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "resolved address %s\n", + ipstr); + listen_sock = - GNUNET_NETWORK_socket_create (in->sa_family, SOCK_STREAM, IPPROTO_TCP); + GNUNET_NETWORK_socket_create (resolved_in->sa_family, SOCK_STREAM, IPPROTO_TCP); if (NULL == listen_sock) { GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "socket"); + //GNUNET_RESOLVER_request_cancel (resolve_request_handle); GNUNET_free (in); - GNUNET_free (bindto); + //GNUNET_free (bindto); return; } + + if (AF_INET == resolved_in->sa_family) + { + v4 = GNUNET_new (struct sockaddr_in); + v4->sin_family = AF_INET; + v4->sin_port = htons ((uint16_t) port); +#if HAVE_SOCKADDR_IN_SIN_LEN + v4->sin_len = sizeof(struct sockaddr_in); +#endif + in = GNUNET_memdup (v4, sizeof(v4)); + }else if (AF_INET6 == in->sa_family) + { + v6 = GNUNET_new (struct sockaddr_in6); + v6->sin6_family = AF_INET6; + v6->sin6_port = htons ((uint16_t) port); +#if HAVE_SOCKADDR_IN_SIN_LEN + v6->sin6_len = sizeof(sizeof(struct sockaddr_in6)); +#endif + in = GNUNET_memdup (v6, sizeof(v6)); + } + if (GNUNET_OK != GNUNET_NETWORK_socket_bind (listen_sock, in, in_len)) { - GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "bind", bindto); + //GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "bind", bindto); + //GNUNET_RESOLVER_request_cancel (resolve_request_handle); GNUNET_NETWORK_socket_close (listen_sock); listen_sock = NULL; GNUNET_free (in); - GNUNET_free (bindto); + //GNUNET_free (bindto); return; } if (GNUNET_OK != @@ -2196,7 +2245,7 @@ run (void *cls, GNUNET_NETWORK_socket_close (listen_sock); listen_sock = NULL; GNUNET_free (in); - GNUNET_free (bindto); + //GNUNET_free (bindto); } /* We might have bound to port 0, allowing the OS to figure it out; thus, get the real IN-address from the socket */ @@ -2209,7 +2258,7 @@ run (void *cls, sto_len = in_len; } GNUNET_free (in); - GNUNET_free (bindto); + //GNUNET_free (bindto); in = (struct sockaddr *) &in_sto; in_len = sto_len; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, @@ -2225,6 +2274,7 @@ run (void *cls, GNUNET_ERROR_TYPE_ERROR, _ ( "Transport service is lacking key configuration settings. Exiting.\n")); + GNUNET_RESOLVER_request_cancel (resolve_request_handle); GNUNET_SCHEDULER_shutdown (); return; } @@ -2246,6 +2296,7 @@ run (void *cls, if (NULL == ch) { GNUNET_break (0); + GNUNET_RESOLVER_request_cancel (resolve_request_handle); GNUNET_SCHEDULER_shutdown (); return; } @@ -2258,6 +2309,94 @@ run (void *cls, &nat_address_cb, NULL /* FIXME: support reversal: #5529 */, NULL /* closure */); + +} + +/** + * Setup communicator and launch network interactions. + * + * @param cls NULL (always) + * @param args remaining command-line arguments + * @param cfgfile name of the configuration file used (for saving, can be NULL!) + * @param c configuration + */ +static void +run (void *cls, + char *const *args, + const char *cfgfile, + const struct GNUNET_CONFIGURATION_Handle *c) +{ + char *bindto; + struct sockaddr *in; + socklen_t in_len; + struct sockaddr_in v4; + struct sockaddr_in6 v6; + char *cp; + char *colon; + char *start; + unsigned int port; + char dummy[2]; + + + (void) cls; + cfg = c; + if (GNUNET_OK != + GNUNET_CONFIGURATION_get_value_string (cfg, + COMMUNICATOR_CONFIG_SECTION, + "BINDTO", + &bindto)) + { + GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, + COMMUNICATOR_CONFIG_SECTION, + "BINDTO"); + return; + } + if (GNUNET_OK != + GNUNET_CONFIGURATION_get_value_number (cfg, + COMMUNICATOR_CONFIG_SECTION, + "MAX_QUEUE_LENGTH", + &max_queue_length)) + max_queue_length = DEFAULT_MAX_QUEUE_LENGTH; + if (GNUNET_OK != + GNUNET_CONFIGURATION_get_value_time (cfg, + COMMUNICATOR_CONFIG_SECTION, + "REKEY_INTERVAL", + &rekey_interval)) + rekey_interval = DEFAULT_REKEY_INTERVAL; + + cp = GNUNET_strdup (bindto); + start = extract_ipv6_address (cp); + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "We try with path `%s'\n", + bindto); + + if (1 == sscanf (bindto, "%u%1s", &port, dummy)) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "We think it is port only\n"); + in = tcp_address_to_sockaddr_port_only (bindto, port, &in_len); + init_own_socket (bindto, &in, &in_len); + } + else if (1 == inet_pton (AF_INET, cp, &v4.sin_addr) || 1 == inet_pton (AF_INET6, start, &v6.sin6_addr)) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "We think it is address and port\n"); + colon = strrchr (cp, ':'); + in = tcp_address_to_sockaddr_numeric (&in_len, v4, v6, &colon); + init_own_socket (bindto, &in, &in_len); + }else + { + colon = strrchr (cp, ':'); + port = extract_port(colon); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "We try to resolve\n"); + resolve_request_handle = GNUNET_RESOLVER_ip_get (cp, + AF_UNSPEC, + GNUNET_TIME_UNIT_MINUTES, + &init_own_socket, + port); + } } -- 2.25.1