From ccf6004e61a5379954aed85be6ed49ab7e886a7d Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Thu, 25 Aug 2016 12:51:21 +0000 Subject: [PATCH] ensure binding multiple ports to the same service descriptor works (again) with the correct mapping of ports --- src/exit/gnunet-daemon-exit.c | 39 +++++++++++++++-------------------- src/include/gnunet_tun_lib.h | 17 ++++++++++++++- src/tun/regex.c | 23 +++++++++++++++++++++ src/vpn/gnunet-service-vpn.c | 21 +++++++++++++------ 4 files changed, 71 insertions(+), 29 deletions(-) diff --git a/src/exit/gnunet-daemon-exit.c b/src/exit/gnunet-daemon-exit.c index aa96583c0..496ca25f8 100644 --- a/src/exit/gnunet-daemon-exit.c +++ b/src/exit/gnunet-daemon-exit.c @@ -153,12 +153,6 @@ struct LocalService */ struct GNUNET_CADET_Port *port; - /** - * Port I am listening on within GNUnet for this service, in host - * byte order. (as we may redirect ports). - */ - uint16_t my_port; - /** * #GNUNET_YES if this is a UDP service, otherwise TCP. */ @@ -836,31 +830,33 @@ store_service (int proto, uint16_t destination_port, struct LocalService *service) { - char key[sizeof (struct GNUNET_HashCode) + sizeof (uint16_t)]; + struct GNUNET_HashCode cadet_port; + service->name = GNUNET_strdup (name); GNUNET_TUN_service_name_to_hash (name, &service->descriptor); - service->name = GNUNET_strdup (name); - GNUNET_memcpy (&key[0], - &destination_port, - sizeof (uint16_t)); - GNUNET_memcpy (&key[sizeof(uint16_t)], - &service->descriptor, - sizeof (struct GNUNET_HashCode)); + GNUNET_TUN_compute_service_cadet_port (&service->descriptor, + destination_port, + &cadet_port); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Opening CADET port %s for SERVICE exit %s on port %u\n", + GNUNET_h2s (&cadet_port), + name, + (unsigned int) destination_port); service->port = GNUNET_CADET_open_port (cadet_handle, - &service->descriptor, + &cadet_port, &new_service_channel, service); service->is_udp = (IPPROTO_UDP == proto); if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put (services, - (struct GNUNET_HashCode *) key, + &cadet_port, service, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)) { - free_service_record (NULL, - (struct GNUNET_HashCode *) key, - service); + GNUNET_CADET_close_port (service->port); + GNUNET_free_non_null (service->name); + GNUNET_free (service); GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Got duplicate service records for `%s:%u'\n"), name, @@ -3322,8 +3318,8 @@ add_services (int proto, GNUNET_assert (slen >= 8); n = GNUNET_strndup (name, slen - 8 /* remove .gnunet. */); - for (redirect = strtok (cpy, " "); redirect != NULL; - redirect = strtok (NULL, " ")) + for (redirect = strtok (cpy, " ;"); redirect != NULL; + redirect = strtok (NULL, " ;")) { if (NULL == (hostname = strstr (redirect, ":"))) { @@ -3368,7 +3364,6 @@ add_services (int proto, serv = GNUNET_new (struct LocalService); serv->address.proto = proto; - serv->my_port = (uint16_t) local_port; serv->address.port = remote_port; if (0 == strcmp ("localhost4", hostname)) diff --git a/src/include/gnunet_tun_lib.h b/src/include/gnunet_tun_lib.h index 9b98ab13b..822a661cf 100644 --- a/src/include/gnunet_tun_lib.h +++ b/src/include/gnunet_tun_lib.h @@ -910,12 +910,27 @@ GNUNET_TUN_ipv4policy2regex (const char *policy); * the network. * * @param service_name a string - * @param hc corresponding hash + * @param[out] hc corresponding hash */ void GNUNET_TUN_service_name_to_hash (const char *service_name, struct GNUNET_HashCode *hc); + +/** + * Compute the CADET port given a service descriptor + * (returned from #GNUNET_TUN_service_name_to_hash) and + * a TCP/UDP port @a ip_port. + * + * @param desc service shared secret + * @param ip_port TCP/UDP port, use 0 for ICMP + * @param[out] cadet_port CADET port to use + */ +void +GNUNET_TUN_compute_service_cadet_port (const struct GNUNET_HashCode *desc, + uint16_t ip_port, + struct GNUNET_HashCode *cadet_port); + #endif /** @} */ /* end of group */ diff --git a/src/tun/regex.c b/src/tun/regex.c index f1ebb85f4..d48fe1da8 100644 --- a/src/tun/regex.c +++ b/src/tun/regex.c @@ -810,4 +810,27 @@ GNUNET_TUN_service_name_to_hash (const char *service_name, } +/** + * Compute the CADET port given a service descriptor + * (returned from #GNUNET_TUN_service_name_to_hash) and + * a TCP/UDP port @a ip_port. + * + * @param desc service shared secret + * @param ip_port TCP/UDP port, use 0 for ICMP + * @param[out] cadet_port CADET port to use + */ +void +GNUNET_TUN_compute_service_cadet_port (const struct GNUNET_HashCode *desc, + uint16_t ip_port, + struct GNUNET_HashCode *cadet_port) +{ + uint16_t be_port = htons (ip_port); + + *cadet_port = *desc; + GNUNET_memcpy (cadet_port, + &be_port, + sizeof (uint16_t)); +} + + /* end of regex.c */ diff --git a/src/vpn/gnunet-service-vpn.c b/src/vpn/gnunet-service-vpn.c index 629b59173..d18530dab 100644 --- a/src/vpn/gnunet-service-vpn.c +++ b/src/vpn/gnunet-service-vpn.c @@ -795,13 +795,19 @@ create_channel_to_destination (struct DestinationChannel *dt, ts->af = client_af; ts->destination = *dt->destination; ts->destination.heap_node = NULL; /* copy is NOT in destination heap */ + ts->destination_port = dt->destination_port; if (dt->destination->is_service) { + struct GNUNET_HashCode cadet_port; + + GNUNET_TUN_compute_service_cadet_port (&ts->destination.details.service_destination.service_descriptor, + ts->destination_port, + &cadet_port); ts->channel = GNUNET_CADET_channel_create (cadet_handle, ts, &dt->destination->details.service_destination.target, - &ts->destination.details.service_destination.service_descriptor, + &cadet_port, GNUNET_CADET_OPTION_DEFAULT); if (NULL == ts->channel) { @@ -810,10 +816,10 @@ create_channel_to_destination (struct DestinationChannel *dt, return NULL; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Creating channel %p to peer %s offering service %s\n", - ts->channel, + "Creating channel to peer %s offering service %s on port %u\n", GNUNET_i2s (&dt->destination->details.service_destination.target), - GNUNET_h2s (&ts->destination.details.service_destination.service_descriptor)); + GNUNET_h2s (&ts->destination.details.service_destination.service_descriptor), + (unsigned int) ts->destination_port); } else { @@ -1072,7 +1078,9 @@ route_packet (struct DestinationEntry *destination, GNUNET_h2s (&destination->details.service_destination.service_descriptor), GNUNET_i2s (&destination->details.service_destination.target)); } - dt = destination->dt_head; + for (dt = destination->dt_head; NULL != dt; dt = dt->next) + if (dt->destination_port == destination_port) + break; } if (NULL == dt) { @@ -1094,7 +1102,8 @@ route_packet (struct DestinationEntry *destination, GNUNET_h2s (&key)); /* need to either use the existing channel from the destination (if still available) or create a fresh one */ - ts = create_channel_to_destination (dt, af); + ts = create_channel_to_destination (dt, + af); if (NULL == ts) return; /* now bind existing "unbound" channel to our IP/port tuple */ -- 2.25.1