tolerate additional IPv4 address now available for gnunet.org
[oweals/gnunet.git] / src / transport / plugin_transport_udp.c
index c9fb754c103358433ed9694dd661ab9c5cf8e1c7..b05192e063a52324f78585174d2bd7c357bda3f1 100644 (file)
@@ -2,20 +2,20 @@
  This file is part of GNUnet
  Copyright (C) 2010-2017 GNUnet e.V.
 
- GNUnet is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3, or (at your
- option) any later version.
+ GNUnet is free software: you can redistribute it and/or modify it
under the terms of the GNU Affero General Public License as published
+ by the Free Software Foundation, either version 3 of the License,
+ or (at your option) any later version.
 
  GNUnet is distributed in the hope that it will be useful, but
  WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- General Public License for more details.
Affero General Public License for more details.
 
- You should have received a copy of the GNU General Public License
- along with GNUnet; see the file COPYING.  If not, write to the
- Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA.
+ You should have received a copy of the GNU Affero General Public License
+ along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+     SPDX-License-Identifier: AGPL3.0-or-later
  */
 
 /**
@@ -158,6 +158,11 @@ struct GNUNET_ATS_Session
    */
   struct GNUNET_PeerIdentity target;
 
+  /**
+   * Tokenizer for inbound messages.
+   */
+  struct GNUNET_MessageStreamTokenizer *mst;
+
   /**
    * Plugin this session belongs to.
    */
@@ -231,7 +236,7 @@ struct GNUNET_ATS_Session
   /**
    * Network type of the address.
    */
-  enum GNUNET_ATS_Network_Type scope;
+  enum GNUNET_NetworkType scope;
 
   /**
    * Is this session about to be destroyed (sometimes we cannot
@@ -287,7 +292,7 @@ struct DefragContext
   /**
    * Network type the address belongs to.
    */
-  enum GNUNET_ATS_Network_Type network_type;
+  enum GNUNET_NetworkType network_type;
 
   /**
    * Has the @e sender field been initialized yet?
@@ -626,6 +631,11 @@ free_session (struct GNUNET_ATS_Session *s)
     GNUNET_free (s->frag_ctx);
     s->frag_ctx = NULL;
   }
+  if (NULL != s->mst)
+  {
+    GNUNET_MST_destroy (s->mst);
+    s->mst = NULL;
+  }
   GNUNET_free (s);
 }
 
@@ -652,7 +662,7 @@ udp_query_keepalive_factor (void *cls)
  * @param session the session
  * @return the network type
  */
-static enum GNUNET_ATS_Network_Type
+static enum GNUNET_NetworkType
 udp_plugin_get_network (void *cls,
                         struct GNUNET_ATS_Session *session)
 {
@@ -667,7 +677,7 @@ udp_plugin_get_network (void *cls,
  * @param address the address
  * @return the network type
  */
-static enum GNUNET_ATS_Network_Type
+static enum GNUNET_NetworkType
 udp_plugin_get_network_for_address (void *cls,
                                     const struct GNUNET_HELLO_Address *address)
 {
@@ -712,7 +722,7 @@ udp_plugin_get_network_for_address (void *cls,
   else
   {
     GNUNET_break (0);
-    return GNUNET_ATS_NET_UNSPECIFIED;
+    return GNUNET_NT_UNSPECIFIED;
   }
   return plugin->env->get_address_type (plugin->env->cls,
                                         sb,
@@ -1245,31 +1255,45 @@ udp_plugin_check_address (void *cls,
 
   if (sizeof(struct IPv4UdpAddress) == addrlen)
   {
+    struct sockaddr_in s4;
+
     v4 = (const struct IPv4UdpAddress *) addr;
     if (GNUNET_OK != check_port (plugin,
                                  ntohs (v4->u4_port)))
       return GNUNET_SYSERR;
+    memset (&s4, 0, sizeof (s4));
+    s4.sin_family = AF_INET;
+#if HAVE_SOCKADDR_IN_SIN_LEN
+    s4.sin_len = sizeof (s4);
+#endif
+    s4.sin_port = v4->u4_port;
+    s4.sin_addr.s_addr = v4->ipv4_addr;
+
     if (GNUNET_OK !=
-        GNUNET_NAT_test_address (plugin->nat,
-                                 &v4->ipv4_addr,
-                                 sizeof (struct in_addr)))
+       GNUNET_NAT_test_address (plugin->nat,
+                                &s4,
+                                sizeof (struct sockaddr_in)))
       return GNUNET_SYSERR;
   }
   else if (sizeof(struct IPv6UdpAddress) == addrlen)
   {
+    struct sockaddr_in6 s6;
+
     v6 = (const struct IPv6UdpAddress *) addr;
     if (IN6_IS_ADDR_LINKLOCAL (&v6->ipv6_addr))
-    {
-      GNUNET_break_op (0);
-      return GNUNET_SYSERR;
-    }
-    if (GNUNET_OK != check_port (plugin,
-                                 ntohs (v6->u6_port)))
-      return GNUNET_SYSERR;
+      return GNUNET_OK; /* plausible, if unlikely... */
+    memset (&s6, 0, sizeof (s6));
+    s6.sin6_family = AF_INET6;
+#if HAVE_SOCKADDR_IN_SIN_LEN
+    s6.sin6_len = sizeof (s6);
+#endif
+    s6.sin6_port = v6->u6_port;
+    s6.sin6_addr = v6->ipv6_addr;
+
     if (GNUNET_OK !=
-        GNUNET_NAT_test_address (plugin->nat,
-                                 &v6->ipv6_addr,
-                                 sizeof (struct in6_addr)))
+       GNUNET_NAT_test_address (plugin->nat,
+                                &s6,
+                                sizeof(struct sockaddr_in6)))
       return GNUNET_SYSERR;
   }
   else
@@ -1285,6 +1309,8 @@ udp_plugin_check_address (void *cls,
  * Our external IP address/port mapping has changed.
  *
  * @param cls closure, the `struct Plugin`
+ * @param app_ctx[in,out] location where the app can store stuff
+ *                  on add and retrieve it on remove
  * @param add_remove #GNUNET_YES to mean the new public IP address,
  *                   #GNUNET_NO to mean the previous (now invalid) one
  * @param ac address class the address belongs to
@@ -1293,6 +1319,7 @@ udp_plugin_check_address (void *cls,
  */
 static void
 udp_nat_port_map_callback (void *cls,
+                          void **app_ctx,
                            int add_remove,
                           enum GNUNET_NAT_AddressClass ac,
                            const struct sockaddr *addr,
@@ -1305,6 +1332,7 @@ udp_nat_port_map_callback (void *cls,
   void *arg;
   size_t args;
 
+  (void) app_ctx;
   LOG (GNUNET_ERROR_TYPE_DEBUG,
        (GNUNET_YES == add_remove)
        ? "NAT notification to add address `%s'\n"
@@ -1321,10 +1349,7 @@ udp_nat_port_map_callback (void *cls,
       GNUNET_assert (sizeof(struct sockaddr_in) == addrlen);
       i4 = (const struct sockaddr_in *) addr;
       if (0 == ntohs (i4->sin_port))
-      {
-        GNUNET_break (0);
-        return;
-      }
+        return; /* Port = 0 means unmapped, ignore these for UDP. */
       memset (&u4,
               0,
               sizeof(u4));
@@ -1342,10 +1367,7 @@ udp_nat_port_map_callback (void *cls,
       GNUNET_assert (sizeof(struct sockaddr_in6) == addrlen);
       i6 = (const struct sockaddr_in6 *) addr;
       if (0 == ntohs (i6->sin6_port))
-      {
-        GNUNET_break (0);
-        return;
-      }
+        return; /* Port = 0 means unmapped, ignore these for UDP. */
       memset (&u6,
               0,
               sizeof(u6));
@@ -1613,9 +1635,10 @@ enqueue (struct Plugin *plugin,
   if (GNUNET_YES == session->in_destroy)
   {
     GNUNET_break (0);
+    GNUNET_free (udpw);
     return;
   }
-  if (plugin->bytes_in_buffer + udpw->msg_size > INT64_MAX)
+  if (plugin->bytes_in_buffer > INT64_MAX - udpw->msg_size)
   {
     GNUNET_break (0);
   }
@@ -1895,8 +1918,8 @@ enqueue_fragment (void *cls,
   udpw->qc = &qc_fragment_sent;
   udpw->qc_cls = plugin;
   GNUNET_memcpy (udpw->msg_buf,
-          msg,
-          msg_len);
+                msg,
+                msg_len);
   enqueue (plugin,
            udpw);
   if (session->address->address_length == sizeof (struct IPv4UdpAddress))
@@ -2043,7 +2066,7 @@ udp_plugin_send (void *cls,
   if ( (sizeof(struct IPv4UdpAddress) == s->address->address_length) &&
        (NULL == plugin->sockv4) )
     return GNUNET_SYSERR;
-  if (udpmlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
+  if (udpmlen >= GNUNET_MAX_MESSAGE_SIZE)
   {
     GNUNET_break (0);
     return GNUNET_SYSERR;
@@ -2491,18 +2514,16 @@ read_process_ack (struct Plugin *plugin,
  * Message tokenizer has broken up an incomming message. Pass it on
  * to the service.
  *
- * @param cls the `struct Plugin *`
- * @param client the `struct GNUNET_ATS_Session *`
+ * @param cls the `struct GNUNET_ATS_Session *`
  * @param hdr the actual message
  * @return #GNUNET_OK (always)
  */
 static int
 process_inbound_tokenized_messages (void *cls,
-                                    void *client,
                                     const struct GNUNET_MessageHeader *hdr)
 {
-  struct Plugin *plugin = cls;
-  struct GNUNET_ATS_Session *session = client;
+  struct GNUNET_ATS_Session *session = cls;
+  struct Plugin *plugin = session->plugin;
 
   if (GNUNET_YES == session->in_destroy)
     return GNUNET_OK;
@@ -2612,12 +2633,14 @@ session_timeout (void *cls)
 static struct GNUNET_ATS_Session *
 udp_plugin_create_session (void *cls,
                            const struct GNUNET_HELLO_Address *address,
-                           enum GNUNET_ATS_Network_Type network_type)
+                           enum GNUNET_NetworkType network_type)
 {
   struct Plugin *plugin = cls;
   struct GNUNET_ATS_Session *s;
 
   s = GNUNET_new (struct GNUNET_ATS_Session);
+  s->mst = GNUNET_MST_create (&process_inbound_tokenized_messages,
+                              s);
   s->plugin = plugin;
   s->address = GNUNET_HELLO_address_copy (address);
   s->target = address->peer;
@@ -2670,7 +2693,7 @@ udp_plugin_get_session (void *cls,
 {
   struct Plugin *plugin = cls;
   struct GNUNET_ATS_Session *s;
-  enum GNUNET_ATS_Network_Type network_type = GNUNET_ATS_NET_UNSPECIFIED;
+  enum GNUNET_NetworkType network_type = GNUNET_NT_UNSPECIFIED;
   const struct IPv4UdpAddress *udp_v4;
   const struct IPv6UdpAddress *udp_v6;
 
@@ -2722,7 +2745,7 @@ udp_plugin_get_session (void *cls,
                                                   (const struct sockaddr *) &v6,
                                                   sizeof (v6));
   }
-  GNUNET_break (GNUNET_ATS_NET_UNSPECIFIED != network_type);
+  GNUNET_break (GNUNET_NT_UNSPECIFIED != network_type);
   return udp_plugin_create_session (cls,
                                    address,
                                    network_type);
@@ -2743,12 +2766,12 @@ process_udp_message (struct Plugin *plugin,
                      const struct UDPMessage *msg,
                      const union UdpAddress *udp_addr,
                      size_t udp_addr_len,
-                     enum GNUNET_ATS_Network_Type network_type)
+                     enum GNUNET_NetworkType network_type)
 {
   struct GNUNET_ATS_Session *s;
   struct GNUNET_HELLO_Address *address;
 
-  GNUNET_break (GNUNET_ATS_NET_UNSPECIFIED != network_type);
+  GNUNET_break (GNUNET_NT_UNSPECIFIED != network_type);
   if (0 != ntohl (msg->reserved))
   {
     GNUNET_break_op(0);
@@ -2784,12 +2807,11 @@ process_udp_message (struct Plugin *plugin,
   GNUNET_free (address);
 
   s->rc++;
-  GNUNET_SERVER_mst_receive (plugin->mst,
-                             s,
-                             (const char *) &msg[1],
-                             ntohs (msg->header.size) - sizeof(struct UDPMessage),
-                             GNUNET_YES,
-                             GNUNET_NO);
+  GNUNET_MST_from_buffer (s->mst,
+                          (const char *) &msg[1],
+                          ntohs (msg->header.size) - sizeof(struct UDPMessage),
+                          GNUNET_YES,
+                          GNUNET_NO);
   s->rc--;
   if ( (0 == s->rc) &&
        (GNUNET_YES == s->in_destroy) )
@@ -2976,7 +2998,7 @@ read_process_fragment (struct Plugin *plugin,
                        const struct GNUNET_MessageHeader *msg,
                        const union UdpAddress *udp_addr,
                        size_t udp_addr_len,
-                       enum GNUNET_ATS_Network_Type network_type)
+                       enum GNUNET_NetworkType network_type)
 {
   struct DefragContext *d_ctx;
   struct GNUNET_TIME_Absolute now;
@@ -3035,8 +3057,7 @@ read_process_fragment (struct Plugin *plugin,
                                           msg))
   {
     /* keep this 'rc' from expiring */
-    GNUNET_CONTAINER_heap_update_cost (plugin->defrag_ctxs,
-                                       d_ctx->hnode,
+    GNUNET_CONTAINER_heap_update_cost (d_ctx->hnode,
                                        (GNUNET_CONTAINER_HeapCostType) now.abs_value_us);
   }
   if (GNUNET_CONTAINER_heap_get_size (plugin->defrag_ctxs) >
@@ -3077,7 +3098,7 @@ udp_select_read (struct Plugin *plugin,
   const struct sockaddr_in6 *sa6;
   const union UdpAddress *int_addr;
   size_t int_addr_len;
-  enum GNUNET_ATS_Network_Type network_type;
+  enum GNUNET_NetworkType network_type;
 
   fromlen = sizeof (addr);
   memset (&addr,
@@ -3330,13 +3351,13 @@ analyze_send_error (struct Plugin *plugin,
                     socklen_t slen,
                     int error)
 {
-  enum GNUNET_ATS_Network_Type type;
+  enum GNUNET_NetworkType type;
 
   type = plugin->env->get_address_type (plugin->env->cls,
                                         sa,
                                         slen);
-  if ( ( (GNUNET_ATS_NET_LAN == type) ||
-         (GNUNET_ATS_NET_WAN == type) ) &&
+  if ( ( (GNUNET_NT_LAN == type) ||
+         (GNUNET_NT_WAN == type) ) &&
        ( (ENETUNREACH == errno) ||
          (ENETDOWN == errno) ) )
   {
@@ -3522,7 +3543,7 @@ udp_plugin_select_v4 (void *cls)
 {
   struct Plugin *plugin = cls;
   const struct GNUNET_SCHEDULER_TaskContext *tc;
-  
+
   plugin->select_task_v4 = NULL;
   if (NULL == plugin->sockv4)
     return;
@@ -3822,9 +3843,9 @@ libgnunet_plugin_transport_udp_init (void *cls)
   unsigned long long port;
   unsigned long long aport;
   unsigned long long udp_max_bps;
-  unsigned long long enable_v6;
-  unsigned long long enable_broadcasting;
-  unsigned long long enable_broadcasting_recv;
+  int enable_v6;
+  int enable_broadcasting;
+  int enable_broadcasting_recv;
   char *bind4_address;
   char *bind6_address;
   struct GNUNET_TIME_Relative interval;
@@ -3983,8 +4004,6 @@ libgnunet_plugin_transport_udp_init (void *cls)
   p->sessions = GNUNET_CONTAINER_multipeermap_create (16,
                                                       GNUNET_NO);
   p->defrag_ctxs = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
-  p->mst = GNUNET_SERVER_mst_create (&process_inbound_tokenized_messages,
-                                     p);
   GNUNET_BANDWIDTH_tracker_init (&p->tracker,
                                  NULL,
                                  NULL,
@@ -4001,7 +4020,6 @@ libgnunet_plugin_transport_udp_init (void *cls)
         _("Failed to create UDP network sockets\n"));
     GNUNET_CONTAINER_multipeermap_destroy (p->sessions);
     GNUNET_CONTAINER_heap_destroy (p->defrag_ctxs);
-    GNUNET_SERVER_mst_destroy (p->mst);
     if (NULL != p->nat)
       GNUNET_NAT_unregister (p->nat);
     GNUNET_free (p);
@@ -4113,11 +4131,6 @@ libgnunet_plugin_transport_udp_done (void *cls)
     GNUNET_CONTAINER_heap_destroy (plugin->defrag_ctxs);
     plugin->defrag_ctxs = NULL;
   }
-  if (NULL != plugin->mst)
-  {
-    GNUNET_SERVER_mst_destroy (plugin->mst);
-    plugin->mst = NULL;
-  }
   while (NULL != (udpw = plugin->ipv4_queue_head))
   {
     dequeue (plugin,