Check that you are not present in trail twice
[oweals/gnunet.git] / src / transport / plugin_transport_udp_broadcasting.c
index 0503e413a04d163eff6706e6ac0eb0a5f3ddd447..9ed1bff65a155b80ff69f959e3ce20d4ae2bea6c 100644 (file)
@@ -135,6 +135,7 @@ broadcast_ipv6_mst_cb (void *cls, void *client,
 {
   struct Plugin *plugin = cls;
   struct Mstv6Context *mc = client;
+  struct GNUNET_HELLO_Address *address;
   const struct GNUNET_MessageHeader *hello;
   const struct UDP_Beacon_Message *msg;
   struct GNUNET_ATS_Information atsi;
@@ -155,19 +156,12 @@ broadcast_ipv6_mst_cb (void *cls, void *client,
   GNUNET_break (ntohl(mc->ats_address_network_type) != GNUNET_ATS_NET_UNSPECIFIED);
 
   hello = (struct GNUNET_MessageHeader *) &msg[1];
-  plugin->env->receive (plugin->env->cls,
-                       &msg->sender,
-                       hello,
-                        NULL,
-                        (const char *) &mc->addr,
-                        sizeof (mc->addr));
-  plugin->env->update_address_metrics (plugin->env->cls,
-                                      &msg->sender,
-                                      (const char *) &mc->addr,
-                                      sizeof (mc->addr),
-                                      NULL,
-                                      &atsi, 1);
-
+  address = GNUNET_HELLO_address_allocate (&msg->sender, PLUGIN_NAME,
+      (const char *) &mc->addr, sizeof (mc->addr), GNUNET_HELLO_ADDRESS_INFO_INBOUND);
+  plugin->env->receive (plugin->env->cls, address, NULL, hello);
+  plugin->env->update_address_metrics (plugin->env->cls, address,
+                                      NULL, &atsi, 1);
+  GNUNET_HELLO_address_free (address);
   GNUNET_STATISTICS_update (plugin->env->stats,
                             _
                             ("# IPv6 multicast HELLO beacons received via udp"),
@@ -183,6 +177,7 @@ broadcast_ipv4_mst_cb (void *cls, void *client,
 {
   struct Plugin *plugin = cls;
   struct Mstv4Context *mc = client;
+  struct GNUNET_HELLO_Address *address;
   const struct GNUNET_MessageHeader *hello;
   const struct UDP_Beacon_Message *msg;
   struct GNUNET_ATS_Information atsi;
@@ -204,19 +199,12 @@ broadcast_ipv4_mst_cb (void *cls, void *client,
   GNUNET_break (ntohl(mc->ats_address_network_type) != GNUNET_ATS_NET_UNSPECIFIED);
 
   hello = (struct GNUNET_MessageHeader *) &msg[1];
-  plugin->env->receive (plugin->env->cls,
-                       &msg->sender,
-                       hello,
-                        NULL,
-                        (const char *) &mc->addr,
-                        sizeof (mc->addr));
-
-  plugin->env->update_address_metrics (plugin->env->cls,
-                                      &msg->sender,
-                                      (const char *) &mc->addr,
-                                      sizeof (mc->addr),
-                                      NULL,
-                                      &atsi, 1);
+  address = GNUNET_HELLO_address_allocate (&msg->sender, PLUGIN_NAME,
+      (const char *) &mc->addr, sizeof (mc->addr), GNUNET_HELLO_ADDRESS_INFO_INBOUND);
+  plugin->env->receive (plugin->env->cls, address, NULL, hello);
+  plugin->env->update_address_metrics (plugin->env->cls, address,
+                                       NULL, &atsi, 1);
+  GNUNET_HELLO_address_free (address);
 
   GNUNET_STATISTICS_update (plugin->env->stats,
                             _("# IPv4 broadcast HELLO beacons received via udp"),
@@ -228,7 +216,7 @@ broadcast_ipv4_mst_cb (void *cls, void *client,
 
 void
 udp_broadcast_receive (struct Plugin *plugin,
-                       const char * buf,
+                       const char *buf,
                        ssize_t size,
                        const struct sockaddr *addr,
                        size_t addrlen)
@@ -242,7 +230,7 @@ udp_broadcast_receive (struct Plugin *plugin,
          size, GNUNET_a2s ((const struct sockaddr *) addr, addrlen));
     struct Mstv4Context *mc;
 
-    mc = GNUNET_malloc (sizeof (struct Mstv4Context));
+    mc = GNUNET_new (struct Mstv4Context);
     struct sockaddr_in *av4 = (struct sockaddr_in *) addr;
 
     mc->addr.ipv4_addr = av4->sin_addr.s_addr;
@@ -263,7 +251,7 @@ udp_broadcast_receive (struct Plugin *plugin,
          size, GNUNET_a2s ((const struct sockaddr *) &addr, addrlen));
     struct Mstv6Context *mc;
 
-    mc = GNUNET_malloc (sizeof (struct Mstv6Context));
+    mc = GNUNET_new (struct Mstv6Context);
     struct sockaddr_in6 *av6 = (struct sockaddr_in6 *) addr;
 
     mc->addr.ipv6_addr = av6->sin6_addr;
@@ -485,6 +473,7 @@ iface_proc (void *cls,
 {
   struct Plugin *plugin = cls;
   struct BroadcastAddress *ba;
+  struct GNUNET_ATS_Information network;
 
   if (NULL == addr)
     return GNUNET_OK;
@@ -499,11 +488,19 @@ iface_proc (void *cls,
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "netmask %s for interface %s %p\n ",
               GNUNET_a2s (netmask, addrlen), name, netmask);
 
+  network = plugin->env->get_address_type (plugin->env->cls, broadcast_addr, addrlen);
+  if (GNUNET_ATS_NET_LOOPBACK == ntohl(network.value))
+  {
+    /* Broadcasting on loopback does not make sense */
+    return GNUNET_YES;
+  }
+
   ba = GNUNET_new (struct BroadcastAddress);
   ba->plugin = plugin;
   ba->addr = GNUNET_malloc (addrlen);
   memcpy (ba->addr, broadcast_addr, addrlen);
   ba->addrlen = addrlen;
+
   if ( (GNUNET_YES == plugin->enable_ipv4) &&
        (NULL != plugin->sockv4) &&
        (addrlen == sizeof (struct sockaddr_in)) )
@@ -515,7 +512,7 @@ iface_proc (void *cls,
     char *filename;
 
     GNUNET_asprintf (&filename,
-                     "/dev/power/%s",
+                     "/dev/cryogenic/%s",
                      name);
     if (0 == ACCESS (name, R_OK))
     {
@@ -570,7 +567,7 @@ iface_proc (void *cls,
       char *filename;
 
       GNUNET_asprintf (&filename,
-                       "/dev/power/%s",
+                       "/dev/cryogenic/%s",
                        name);
       if (0 == ACCESS (name, R_OK))
       {
@@ -599,13 +596,23 @@ setup_broadcast (struct Plugin *plugin,
   const struct GNUNET_MessageHeader *hello;
 
   hello = plugin->env->get_our_hello ();
-  if (GNUNET_YES == GNUNET_HELLO_is_friend_only((const struct GNUNET_HELLO_Message *) hello))
+  if (GNUNET_YES ==
+      GNUNET_HELLO_is_friend_only ((const struct GNUNET_HELLO_Message *) hello))
   {
     LOG (GNUNET_ERROR_TYPE_WARNING,
          _("Disabling HELLO broadcasting due to friend-to-friend only configuration!\n"));
     return;
   }
 
+  /* always create tokenizers */
+  plugin->broadcast_ipv4_mst =
+    GNUNET_SERVER_mst_create (&broadcast_ipv4_mst_cb, plugin);
+  plugin->broadcast_ipv6_mst =
+    GNUNET_SERVER_mst_create (&broadcast_ipv6_mst_cb, plugin);
+
+  if (GNUNET_YES != plugin->enable_broadcasting)
+    return; /* We do not send, just receive */
+
   /* create IPv4 broadcast socket */
   if ((GNUNET_YES == plugin->enable_ipv4) && (NULL != plugin->sockv4))
   {
@@ -619,13 +626,8 @@ setup_broadcast (struct Plugin *plugin,
            _("Failed to set IPv4 broadcast option for broadcast socket on port %d\n"),
            ntohs (server_addrv4->sin_port));
     }
-    else
-    {
-      plugin->broadcast_ipv4_mst =
-          GNUNET_SERVER_mst_create (broadcast_ipv4_mst_cb, plugin);
-      LOG (GNUNET_ERROR_TYPE_DEBUG, "IPv4 Broadcasting running\n");
-    }
   }
+  /* create IPv6 multicast socket */
   if ((GNUNET_YES == plugin->enable_ipv6) && (plugin->sockv6 != NULL))
   {
     memset (&plugin->ipv6_multicast_address, 0, sizeof (struct sockaddr_in6));
@@ -634,8 +636,6 @@ setup_broadcast (struct Plugin *plugin,
                               &plugin->ipv6_multicast_address.sin6_addr));
     plugin->ipv6_multicast_address.sin6_family = AF_INET6;
     plugin->ipv6_multicast_address.sin6_port = htons (plugin->port);
-    plugin->broadcast_ipv6_mst =
-      GNUNET_SERVER_mst_create (broadcast_ipv6_mst_cb, plugin);
   }
   GNUNET_OS_network_interfaces_list (&iface_proc, plugin);
 }
@@ -644,53 +644,65 @@ setup_broadcast (struct Plugin *plugin,
 void
 stop_broadcast (struct Plugin *plugin)
 {
-  while (plugin->broadcast_head != NULL)
+  if (GNUNET_YES == plugin->enable_broadcasting)
   {
-    struct BroadcastAddress *p = plugin->broadcast_head;
-
-    if (p->broadcast_task != GNUNET_SCHEDULER_NO_TASK)
+    /* Disable broadcasting */
+    while (plugin->broadcast_head != NULL)
     {
-      GNUNET_SCHEDULER_cancel (p->broadcast_task);
-      p->broadcast_task = GNUNET_SCHEDULER_NO_TASK;
-    }
-    if ((GNUNET_YES == plugin->enable_ipv6) &&
-        (NULL != plugin->sockv6) &&
-        (p->addrlen == sizeof (struct sockaddr_in6)))
-    {
-      /* Create IPv6 multicast request */
-      struct ipv6_mreq multicastRequest;
-      const struct sockaddr_in6 *s6 = (const struct sockaddr_in6 *) p->addr;
-
-      multicastRequest.ipv6mr_multiaddr =
-        plugin->ipv6_multicast_address.sin6_addr;
-      multicastRequest.ipv6mr_interface = s6->sin6_scope_id;
+      struct BroadcastAddress *p = plugin->broadcast_head;
 
-      /* Leave the multicast group */
-      if (GNUNET_OK ==
-          GNUNET_NETWORK_socket_setsockopt
-          (plugin->sockv6, IPPROTO_IPV6, IPV6_LEAVE_GROUP,
-           &multicastRequest, sizeof (multicastRequest)))
+      if (p->broadcast_task != GNUNET_SCHEDULER_NO_TASK)
       {
-        GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, setsockopt);
+        GNUNET_SCHEDULER_cancel (p->broadcast_task);
+        p->broadcast_task = GNUNET_SCHEDULER_NO_TASK;
       }
-      else
+      if ((GNUNET_YES == plugin->enable_ipv6) &&
+          (NULL != plugin->sockv6) &&
+          (p->addrlen == sizeof (struct sockaddr_in6)))
       {
-        LOG (GNUNET_ERROR_TYPE_DEBUG, "IPv6 multicasting stopped\n");
+        /* Create IPv6 multicast request */
+        struct ipv6_mreq multicastRequest;
+        const struct sockaddr_in6 *s6 = (const struct sockaddr_in6 *) p->addr;
+
+        multicastRequest.ipv6mr_multiaddr =
+          plugin->ipv6_multicast_address.sin6_addr;
+        multicastRequest.ipv6mr_interface = s6->sin6_scope_id;
+
+        /* Leave the multicast group */
+        if (GNUNET_OK ==
+            GNUNET_NETWORK_socket_setsockopt
+            (plugin->sockv6, IPPROTO_IPV6, IPV6_LEAVE_GROUP,
+             &multicastRequest, sizeof (multicastRequest)))
+        {
+          GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "setsockopt");
+        }
+        else
+        {
+          LOG (GNUNET_ERROR_TYPE_DEBUG, "IPv6 multicasting stopped\n");
+        }
       }
-    }
 
 #if LINUX
     GNUNET_DISK_file_close(p->cryogenic_fd);
 #endif
-    GNUNET_CONTAINER_DLL_remove (plugin->broadcast_head,
-                                 plugin->broadcast_tail, p);
-    GNUNET_free (p->addr);
-    GNUNET_free (p);
+      GNUNET_CONTAINER_DLL_remove (plugin->broadcast_head,
+                                   plugin->broadcast_tail, p);
+      GNUNET_free (p->addr);
+      GNUNET_free (p);
+    }
   }
-  if (plugin->broadcast_ipv4_mst != NULL)
+
+  /* Destroy MSTs */
+  if (NULL != plugin->broadcast_ipv4_mst)
+  {
     GNUNET_SERVER_mst_destroy (plugin->broadcast_ipv4_mst);
-  if (plugin->broadcast_ipv6_mst != NULL)
+    plugin->broadcast_ipv4_mst = NULL;
+  }
+  if (NULL != plugin->broadcast_ipv6_mst)
+  {
     GNUNET_SERVER_mst_destroy (plugin->broadcast_ipv6_mst);
+    plugin->broadcast_ipv6_mst = NULL;
+  }
 }
 
 /* end of plugin_transport_udp_broadcasting.c */