(no commit message)
[oweals/gnunet.git] / src / transport / plugin_transport_udp_broadcasting.c
index 9bb3990327a8a468d9cee01b4defe51368c065a9..25c942de276c17d7ce3bc30329b5b5068201d721 100644 (file)
@@ -89,8 +89,7 @@ struct Mstv6Context
 };
 
 
-
-void
+int
 broadcast_ipv6_mst_cb (void *cls, void *client,
                        const struct GNUNET_MessageHeader *message)
 {
@@ -98,80 +97,94 @@ broadcast_ipv6_mst_cb (void *cls, void *client,
   struct Plugin *plugin = cls;
   struct Mstv6Context *mc = client;
   const struct GNUNET_MessageHeader *hello;
-  struct UDP_Beacon_Message *msg;
+  const struct UDP_Beacon_Message *msg;
+  struct GNUNET_ATS_Information atsi;
 
-  msg = (struct UDP_Beacon_Message *) message;
+  msg = (const struct UDP_Beacon_Message *) message;
 
   if (GNUNET_MESSAGE_TYPE_TRANSPORT_BROADCAST_BEACON !=
       ntohs (msg->header.type))
-    return;
-#if DEBUG_UDP_BROADCASTING
+    return GNUNET_OK;
   LOG (GNUNET_ERROR_TYPE_DEBUG,
        "Received beacon with %u bytes from peer `%s' via address `%s'\n",
        ntohs (msg->header.size), GNUNET_i2s (&msg->sender),
        udp_address_to_string (NULL, &mc->addr, sizeof (mc->addr)));
-#endif
-  struct GNUNET_ATS_Information atsi[2];
 
   /* setup ATS */
-  atsi[0].type = htonl (GNUNET_ATS_QUALITY_NET_DISTANCE);
-  atsi[0].value = htonl (1);
-  atsi[1].type = htonl (GNUNET_ATS_NETWORK_TYPE);
-  atsi[1].value = mc->ats_address_network_type;
+  atsi.type = htonl (GNUNET_ATS_NETWORK_TYPE);
+  atsi.value = mc->ats_address_network_type;
   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,
-                        (const struct GNUNET_ATS_Information *) &atsi, 2, NULL,
-                        (const char *) &mc->addr, sizeof (mc->addr));
+  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);
 
   GNUNET_STATISTICS_update (plugin->env->stats,
                             _
                             ("# IPv6 multicast HELLO beacons received via udp"),
                             1, GNUNET_NO);
   GNUNET_free (mc);
+  return GNUNET_OK;
 }
 
-void
+
+int
 broadcast_ipv4_mst_cb (void *cls, void *client,
                        const struct GNUNET_MessageHeader *message)
 {
   struct Plugin *plugin = cls;
   struct Mstv4Context *mc = client;
   const struct GNUNET_MessageHeader *hello;
-  struct UDP_Beacon_Message *msg;
+  const struct UDP_Beacon_Message *msg;
+  struct GNUNET_ATS_Information atsi;
 
-  msg = (struct UDP_Beacon_Message *) message;
+  msg = (const struct UDP_Beacon_Message *) message;
 
   if (GNUNET_MESSAGE_TYPE_TRANSPORT_BROADCAST_BEACON !=
       ntohs (msg->header.type))
-    return;
-#if DEBUG_UDP_BROADCASTING
+    return GNUNET_OK;
   LOG (GNUNET_ERROR_TYPE_DEBUG,
        "Received beacon with %u bytes from peer `%s' via address `%s'\n",
        ntohs (msg->header.size), GNUNET_i2s (&msg->sender),
        udp_address_to_string (NULL, &mc->addr, sizeof (mc->addr)));
-#endif
 
-  struct GNUNET_ATS_Information atsi[2];
 
   /* setup ATS */
-  atsi[0].type = htonl (GNUNET_ATS_QUALITY_NET_DISTANCE);
-  atsi[0].value = htonl (1);
-  atsi[1].type = htonl (GNUNET_ATS_NETWORK_TYPE);
-  atsi[1].value = mc->ats_address_network_type;
+  atsi.type = htonl (GNUNET_ATS_NETWORK_TYPE);
+  atsi.value = mc->ats_address_network_type;
   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,
-                        (const struct GNUNET_ATS_Information *) &atsi, 2, NULL,
-                        (const char *) &mc->addr, sizeof (mc->addr));
+  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);
 
   GNUNET_STATISTICS_update (plugin->env->stats,
                             _
                             ("# IPv4 broadcast HELLO beacons received via udp"),
                             1, GNUNET_NO);
   GNUNET_free (mc);
+  return GNUNET_OK;
 }
 
 void
@@ -179,13 +192,11 @@ udp_broadcast_receive (struct Plugin *plugin, const char * buf, ssize_t size, st
 {
   struct GNUNET_ATS_Information ats;
 
-  if (addrlen == sizeof (struct sockaddr_in))
+  if ((GNUNET_YES == plugin->broadcast_ipv4) && (addrlen == sizeof (struct sockaddr_in)))
   {
-#if DEBUG_UDP_BROADCASTING
     LOG (GNUNET_ERROR_TYPE_DEBUG,
          "Received IPv4 HELLO beacon broadcast with %i bytes from address %s\n",
          size, GNUNET_a2s ((const struct sockaddr *) addr, addrlen));
-#endif
     struct Mstv4Context *mc;
 
     mc = GNUNET_malloc (sizeof (struct Mstv4Context));
@@ -195,18 +206,18 @@ udp_broadcast_receive (struct Plugin *plugin, const char * buf, ssize_t size, st
     mc->addr.u4_port = av4->sin_port;
     ats = plugin->env->get_address_type (plugin->env->cls, (const struct sockaddr *) addr, addrlen);
     mc->ats_address_network_type = ats.value;
+
+    GNUNET_assert (NULL != plugin->broadcast_ipv4_mst);
     if (GNUNET_OK !=
         GNUNET_SERVER_mst_receive (plugin->broadcast_ipv4_mst, mc, buf, size,
                                    GNUNET_NO, GNUNET_NO))
       GNUNET_free (mc);
   }
-  else if (addrlen == sizeof (struct sockaddr_in6))
+  else if ((GNUNET_YES == plugin->broadcast_ipv4) && (addrlen == sizeof (struct sockaddr_in6)))
   {
-#if DEBUG_UDP_BROADCASTING
     LOG (GNUNET_ERROR_TYPE_DEBUG,
          "Received IPv6 HELLO beacon broadcast with %i bytes from address %s\n",
          size, GNUNET_a2s ((const struct sockaddr *) &addr, addrlen));
-#endif
     struct Mstv6Context *mc;
 
     mc = GNUNET_malloc (sizeof (struct Mstv6Context));
@@ -216,7 +227,7 @@ udp_broadcast_receive (struct Plugin *plugin, const char * buf, ssize_t size, st
     mc->addr.u6_port = av6->sin6_port;
     ats = plugin->env->get_address_type (plugin->env->cls, (const struct sockaddr *) addr, addrlen);
     mc->ats_address_network_type = ats.value;
-
+    GNUNET_assert (NULL != plugin->broadcast_ipv4_mst);
     if (GNUNET_OK !=
         GNUNET_SERVER_mst_receive (plugin->broadcast_ipv6_mst, mc, buf, size,
                                    GNUNET_NO, GNUNET_NO))
@@ -232,6 +243,8 @@ prepare_beacon (struct Plugin *plugin, struct UDP_Beacon_Message *msg)
 
   const struct GNUNET_MessageHeader *hello;
   hello = plugin->env->get_our_hello ();
+  if (NULL == hello)
+    return 0;
   hello_size = GNUNET_HELLO_size ((struct GNUNET_HELLO_Message *) hello);
   msg_size = hello_size + sizeof (struct UDP_Beacon_Message);
 
@@ -253,16 +266,16 @@ udp_ipv4_broadcast_send (void *cls,
   struct Plugin *plugin = cls;
   int sent;
   uint16_t msg_size;
-  char buf[65536];
+  char buf[65536] GNUNET_ALIGN;
   struct BroadcastAddress *baddr;
 
   plugin->send_ipv4_broadcast_task = GNUNET_SCHEDULER_NO_TASK;
 
   msg_size = prepare_beacon(plugin, (struct UDP_Beacon_Message *) &buf);
-  sent = 0;
+
   baddr = plugin->ipv4_broadcast_head;
   /* just IPv4 */
-  while ((baddr != NULL) && (baddr->addrlen == sizeof (struct sockaddr_in)))
+  while ((msg_size > 0) && (baddr != NULL) && (baddr->addrlen == sizeof (struct sockaddr_in)))
   {
     struct sockaddr_in *addr = (struct sockaddr_in *) baddr->addr;
 
@@ -272,7 +285,19 @@ udp_ipv4_broadcast_send (void *cls,
                                       (const struct sockaddr *) addr,
                                       baddr->addrlen);
     if (sent == GNUNET_SYSERR)
-      GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "sendto");
+    {
+      if ((ENETUNREACH == errno) || (ENETDOWN == errno))
+      {
+        /* "Network unreachable" or "Network down"
+         *
+         * This indicates that we just do not have network connectivity
+         */
+        GNUNET_log (GNUNET_ERROR_TYPE_BULK | GNUNET_ERROR_TYPE_WARNING,
+            "Network connectivity is down, cannot send beacon!\n");
+      }
+      else
+        GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "sendto");
+    }
     else
     {
       LOG (GNUNET_ERROR_TYPE_DEBUG,
@@ -294,18 +319,30 @@ udp_ipv6_broadcast_send (void *cls,
   struct Plugin *plugin = cls;
   int sent;
   uint16_t msg_size;
-  char buf[65536];
+  char buf[65536] GNUNET_ALIGN;
 
   plugin->send_ipv6_broadcast_task = GNUNET_SCHEDULER_NO_TASK;
 
   msg_size = prepare_beacon(plugin, (struct UDP_Beacon_Message *) &buf);
-  sent = 0;
   sent = GNUNET_NETWORK_socket_sendto (plugin->sockv6, &buf, msg_size,
                                     (const struct sockaddr *)
                                     &plugin->ipv6_multicast_address,
                                     sizeof (struct sockaddr_in6));
   if (sent == GNUNET_SYSERR)
-    GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "sendto");
+  {
+    if ((ENETUNREACH == errno) || (ENETDOWN == errno))
+    {
+      /* "Network unreachable" or "Network down"
+       *
+       * This indicates that this system is IPv6 enabled, but does not
+       * have a valid global IPv6 address assigned
+       */
+      GNUNET_log (GNUNET_ERROR_TYPE_BULK | GNUNET_ERROR_TYPE_WARNING,
+          "Network connectivity is down, cannot send beacon!\n");
+    }
+    else
+      GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "sendto");
+  }
   else
   {
     LOG (GNUNET_ERROR_TYPE_DEBUG,
@@ -329,7 +366,6 @@ iface_proc (void *cls, const char *name, int isDefault,
 
   if (addr != NULL)
   {
-#if DEBUG_UDP_BROADCASTING
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "address %s for interface %s %p\n ",
                 GNUNET_a2s (addr, addrlen), name, addr);
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -337,7 +373,6 @@ iface_proc (void *cls, const char *name, int isDefault,
                 GNUNET_a2s (broadcast_addr, addrlen), name, broadcast_addr);
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "netmask %s for interface %s %p\n ",
                 GNUNET_a2s (netmask, addrlen), name, netmask);
-#endif
 
     /* Collecting broadcast addresses */
     if (broadcast_addr != NULL)
@@ -356,11 +391,22 @@ iface_proc (void *cls, const char *name, int isDefault,
 
 
 void
-setup_broadcast (struct Plugin *plugin, struct sockaddr_in6 *serverAddrv6, struct sockaddr_in *serverAddrv4)
+setup_broadcast (struct Plugin *plugin, struct sockaddr_in6 *server_addrv6, struct sockaddr_in *server_addrv4)
 {
+  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))
+  {
+    LOG (GNUNET_ERROR_TYPE_WARNING,
+         _("Disabling HELLO broadcasting due to friend-to-friend only configuration!\n"));
+    return;
+  }
+
+
   /* create IPv4 broadcast socket */
   plugin->broadcast_ipv4 = GNUNET_NO;
-  if (plugin->sockv4 != NULL)
+  if ((GNUNET_YES == plugin->enable_ipv4) && (plugin->sockv4 != NULL))
   {
     int yes = 1;
 
@@ -371,7 +417,7 @@ setup_broadcast (struct Plugin *plugin, struct sockaddr_in6 *serverAddrv6, struc
       LOG (GNUNET_ERROR_TYPE_WARNING,
            _
            ("Failed to set IPv4 broadcast option for broadcast socket on port %d\n"),
-           ntohs (serverAddrv4->sin_port));
+           ntohs (server_addrv4->sin_port));
     }
     else
     {
@@ -388,7 +434,7 @@ setup_broadcast (struct Plugin *plugin, struct sockaddr_in6 *serverAddrv6, struc
   }
 
   plugin->broadcast_ipv6 = GNUNET_NO;
-  if (plugin->sockv6 != NULL)
+  if ((GNUNET_YES == plugin->enable_ipv6) && (plugin->sockv6 != NULL))
   {
     memset (&plugin->ipv6_multicast_address, 0, sizeof (struct sockaddr_in6));
     GNUNET_assert (1 ==
@@ -430,9 +476,7 @@ setup_broadcast (struct Plugin *plugin, struct sockaddr_in6 *serverAddrv6, struc
     }
     else
     {
-#if DEBUG_UDP
       LOG (GNUNET_ERROR_TYPE_DEBUG, "IPv6 broadcasting running\n");
-#endif
       plugin->send_ipv6_broadcast_task =
           GNUNET_SCHEDULER_add_now (&udp_ipv6_broadcast_send, plugin);
       plugin->broadcast_ipv6 = GNUNET_YES;
@@ -483,9 +527,7 @@ stop_broadcast (struct Plugin *plugin)
     }
     else
     {
-#if DEBUG_UDP
       LOG (GNUNET_ERROR_TYPE_DEBUG, "IPv6 Broadcasting stopped\n");
-#endif
     }
 
     if (plugin->send_ipv6_broadcast_task != GNUNET_SCHEDULER_NO_TASK)