ensure binding multiple ports to the same service descriptor works (again) with the...
authorChristian Grothoff <christian@grothoff.org>
Thu, 25 Aug 2016 12:51:21 +0000 (12:51 +0000)
committerChristian Grothoff <christian@grothoff.org>
Thu, 25 Aug 2016 12:51:21 +0000 (12:51 +0000)
src/exit/gnunet-daemon-exit.c
src/include/gnunet_tun_lib.h
src/tun/regex.c
src/vpn/gnunet-service-vpn.c

index aa96583c0c4aabce6498ebf4c4a6cdb8b709d7b5..496ca25f80391079d82d91cb389434bb8ec5a5ea 100644 (file)
@@ -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))
index 9b98ab13b8de2a45d7d0b42a3948826af95dcacc..822a661cfb2fddde79fbcde3d3953954ef95fc4b 100644 (file)
@@ -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 */
index f1ebb85f477aeb545f54ec24e4dd4ef28eb2f9b7..d48fe1da81f5f9353b66fcd27856624f62971bd8 100644 (file)
@@ -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 */
index 629b59173a26e15466f87fbe01a4b65d65d950ba..d18530dab6a8d38b6da3a4beecb7cc0a0b352693 100644 (file)
@@ -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 */