tolerate additional IPv4 address now available for gnunet.org
[oweals/gnunet.git] / src / transport / plugin_transport_tcp.c
index 10ea01cec3cd569dbefb2cf01d9aef3e605fa7eb..a0dd8061701545cfebcf854af1dc8b5e02dee01d 100644 (file)
@@ -2,20 +2,20 @@
   This file is part of GNUnet
   Copyright (C) 2002--2015 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
  */
 /**
  * @file transport/plugin_transport_tcp.c
@@ -71,6 +71,21 @@ struct GNUNET_SERVER_TransmitHandle;
  */
 struct GNUNET_CONNECTION_Handle;
 
+/**
+ * @brief handle for a network service
+ */
+struct LEGACY_SERVICE_Context;
+
+
+/**
+ * Stops a service that was started with #GNUNET_SERVICE_start().
+ *
+ * @param srv service to stop
+ */
+void
+LEGACY_SERVICE_stop (struct LEGACY_SERVICE_Context *srv);
+
+
 
 /**
  * Function called to notify a client about the connection begin ready
@@ -269,6 +284,34 @@ struct GNUNET_SERVER_MessageHandler
 
 };
 
+
+/**
+ * Options for the service (bitmask).
+ */
+enum LEGACY_SERVICE_Options
+{
+  /**
+   * Use defaults.  Terminates all client connections and the listen
+   * sockets immediately upon receiving the shutdown signal.
+   */
+  LEGACY_SERVICE_OPTION_NONE = 0,
+
+  /**
+   * Do not trigger server shutdown on signal at all; instead, allow
+   * for the user to terminate the server explicitly when needed
+   * by calling #LEGACY_SERVICE_shutdown().
+   */
+  LEGACY_SERVICE_OPTION_MANUAL_SHUTDOWN = 1,
+
+  /**
+   * Trigger a SOFT server shutdown on signals, allowing active
+   * non-monitor clients to complete their transactions.
+   */
+  LEGACY_SERVICE_OPTION_SOFT_SHUTDOWN = 2
+};
+
+
+
 /**
  * Ask the server to disconnect from the given client.  This is the
  * same as passing #GNUNET_SYSERR to #GNUNET_SERVER_receive_done,
@@ -453,7 +496,7 @@ GNUNET_SERVER_client_drop (struct GNUNET_SERVER_Client *client);
  * @param cfg configuration to use
  */
 typedef void
-(*GNUNET_SERVICE_Main) (void *cls,
+(*LEGACY_SERVICE_Main) (void *cls,
                         struct GNUNET_SERVER_Handle *server,
                         const struct GNUNET_CONFIGURATION_Handle *cfg);
 
@@ -818,7 +861,7 @@ struct GNUNET_ATS_Session
   /**
    * Network type of the address.
    */
-  enum GNUNET_ATS_Network_Type scope;
+  enum GNUNET_NetworkType scope;
 
   /**
    * Are we still expecting the welcome message? (#GNUNET_YES/#GNUNET_NO)
@@ -919,7 +962,7 @@ struct Plugin
   /**
    * Handle to the network service.
    */
-  struct GNUNET_SERVICE_Context *service;
+  struct LEGACY_SERVICE_Context *service;
 
   /**
    * Handle to the server for this service.
@@ -1387,6 +1430,8 @@ notify_session_monitor (struct Plugin *plugin,
  * 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
@@ -1395,6 +1440,7 @@ notify_session_monitor (struct Plugin *plugin,
  */
 static void
 tcp_nat_port_map_callback (void *cls,
+                          void **app_ctx,
                            int add_remove,
                           enum GNUNET_NAT_AddressClass ac,
                           const struct sockaddr *addr,
@@ -1407,6 +1453,7 @@ tcp_nat_port_map_callback (void *cls,
   void *arg;
   size_t args;
 
+  (void) app_ctx;
   LOG (GNUNET_ERROR_TYPE_INFO,
        "NAT notification to %s address `%s'\n",
        (GNUNET_YES == add_remove) ? "add" : "remove",
@@ -1424,6 +1471,12 @@ tcp_nat_port_map_callback (void *cls,
     args = sizeof (t4);
     break;
   case AF_INET6:
+    if (IN6_IS_ADDR_LINKLOCAL (&((struct sockaddr_in6 *) addr)->sin6_addr))
+    {
+      /* skip link local, we don't allow them in
+         #tcp_plugin_check_address() */
+      return;
+    }
     GNUNET_assert(addrlen == sizeof(struct sockaddr_in6));
     memset (&t6, 0, sizeof(t6));
     GNUNET_memcpy (&t6.ipv6_addr,
@@ -1849,7 +1902,7 @@ reschedule_session_timeout (struct GNUNET_ATS_Session *s)
 static struct GNUNET_ATS_Session *
 create_session (struct Plugin *plugin,
                 const struct GNUNET_HELLO_Address *address,
-                enum GNUNET_ATS_Network_Type scope,
+                enum GNUNET_NetworkType scope,
                 struct GNUNET_SERVER_Client *client,
                 int is_nat)
 {
@@ -2395,7 +2448,7 @@ tcp_plugin_get_session (void *cls,
   const struct IPv4TcpAddress *t4;
   const struct IPv6TcpAddress *t6;
   unsigned int options;
-  enum GNUNET_ATS_Network_Type net_type;
+  enum GNUNET_NetworkType net_type;
   unsigned int is_natd = GNUNET_NO;
   size_t addrlen;
 #ifdef TCP_STEALTH
@@ -2498,7 +2551,7 @@ tcp_plugin_get_session (void *cls,
   net_type = plugin->env->get_address_type (plugin->env->cls,
                                             sb,
                                             sbs);
-  GNUNET_break (net_type != GNUNET_ATS_NET_UNSPECIFIED);
+  GNUNET_break (net_type != GNUNET_NT_UNSPECIFIED);
 
   if ( (is_natd == GNUNET_YES) &&
        (addrlen == sizeof(struct IPv6TcpAddress)) )
@@ -3129,8 +3182,6 @@ handle_tcp_welcome (void *cls,
                    sizeof(struct GNUNET_PeerIdentity)))
   {
     /* refuse connections from ourselves */
-    GNUNET_SERVER_receive_done (client,
-                                GNUNET_SYSERR);
     if (GNUNET_OK ==
         GNUNET_SERVER_client_get_address (client,
                                           &vaddr,
@@ -3142,6 +3193,8 @@ handle_tcp_welcome (void *cls,
            GNUNET_a2s (vaddr, alen));
       GNUNET_free (vaddr);
     }
+    GNUNET_SERVER_receive_done (client,
+                                GNUNET_SYSERR);
     return;
   }
 
@@ -3222,7 +3275,7 @@ handle_tcp_welcome (void *cls,
                                                                alen),
                                 client,
                                 GNUNET_NO);
-      GNUNET_break (GNUNET_ATS_NET_UNSPECIFIED != session->scope);
+      GNUNET_break (GNUNET_NT_UNSPECIFIED != session->scope);
       GNUNET_HELLO_address_free (address);
       LOG (GNUNET_ERROR_TYPE_DEBUG,
            "Creating new%s session %p for peer `%s' client %p\n",
@@ -3305,12 +3358,13 @@ handle_tcp_data (void *cls,
   if (NULL == session)
   {
     /* No inbound session found */
-    void *vaddr;
+    void *vaddr = NULL;
     size_t alen;
 
-    GNUNET_SERVER_client_get_address (client,
-                                      &vaddr,
-                                      &alen);
+    GNUNET_assert (GNUNET_OK ==
+                  GNUNET_SERVER_client_get_address (client,
+                                                    &vaddr,
+                                                    &alen));
     LOG (GNUNET_ERROR_TYPE_ERROR,
          "Received unexpected %u bytes of type %u from `%s'\n",
          (unsigned int) ntohs (message->size),
@@ -3326,7 +3380,7 @@ handle_tcp_data (void *cls,
   if (GNUNET_YES == session->expecting_welcome)
   {
     /* Session is expecting WELCOME message */
-    void *vaddr;
+    void *vaddr = NULL;
     size_t alen;
 
     GNUNET_SERVER_client_get_address (client,
@@ -3346,7 +3400,7 @@ handle_tcp_data (void *cls,
 
   session->last_activity = GNUNET_TIME_absolute_get ();
   {
-    void *vaddr;
+    void *vaddr = NULL;
     size_t alen;
 
     GNUNET_SERVER_client_get_address (client,
@@ -3581,7 +3635,7 @@ try_connection_reversal (void *cls,
  * @param session the session
  * @return the network type in HBO or #GNUNET_SYSERR
  */
-static enum GNUNET_ATS_Network_Type
+static enum GNUNET_NetworkType
 tcp_plugin_get_network (void *cls,
                         struct GNUNET_ATS_Session *session)
 {
@@ -3596,7 +3650,7 @@ tcp_plugin_get_network (void *cls,
  * @param address the address
  * @return the network type
  */
-static enum GNUNET_ATS_Network_Type
+static enum GNUNET_NetworkType
 tcp_plugin_get_network_for_address (void *cls,
                                     const struct GNUNET_HELLO_Address *address)
 {
@@ -3641,7 +3695,7 @@ tcp_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,
@@ -3733,7 +3787,7 @@ libgnunet_plugin_transport_tcp_init (void *cls)
   struct GNUNET_TRANSPORT_PluginEnvironment *env = cls;
   struct GNUNET_TRANSPORT_PluginFunctions *api;
   struct Plugin *plugin;
-  struct GNUNET_SERVICE_Context *service;
+  struct LEGACY_SERVICE_Context *service;
   unsigned long long aport;
   unsigned long long bport;
   unsigned long long max_connections;
@@ -3788,9 +3842,9 @@ libgnunet_plugin_transport_tcp_init (void *cls)
     aport = 0;
   if (0 != bport)
   {
-    service = GNUNET_SERVICE_start ("transport-tcp",
+    service = LEGACY_SERVICE_start ("transport-tcp",
                                     env->cfg,
-                                    GNUNET_SERVICE_OPTION_NONE);
+                                    LEGACY_SERVICE_OPTION_NONE);
     if (NULL == service)
     {
       LOG (GNUNET_ERROR_TYPE_WARNING,
@@ -3821,7 +3875,7 @@ libgnunet_plugin_transport_tcp_init (void *cls)
   {
 #ifdef TCP_STEALTH
     plugin->myoptions |= TCP_OPTIONS_TCP_STEALTH;
-    lsocks = GNUNET_SERVICE_get_listen_sockets (service);
+    lsocks = LEGACY_SERVICE_get_listen_sockets (service);
     if (NULL != lsocks)
     {
       uint32_t len = sizeof (struct WelcomeMessage);
@@ -3914,7 +3968,7 @@ libgnunet_plugin_transport_tcp_init (void *cls)
   plugin->service = service;
   if (NULL != service)
   {
-    plugin->server = GNUNET_SERVICE_get_server (service);
+    plugin->server = LEGACY_SERVICE_get_server (service);
   }
   else
   {
@@ -3977,7 +4031,7 @@ libgnunet_plugin_transport_tcp_init (void *cls)
     GNUNET_NAT_unregister (plugin->nat);
   GNUNET_CONTAINER_multipeermap_destroy (plugin->sessionmap);
   if (NULL != service)
-    GNUNET_SERVICE_stop (service);
+    LEGACY_SERVICE_stop (service);
   GNUNET_free (plugin);
   GNUNET_free_non_null (api);
   return NULL;
@@ -4030,7 +4084,7 @@ libgnunet_plugin_transport_tcp_done (void *cls)
   }
 
   if (NULL != plugin->service)
-    GNUNET_SERVICE_stop (plugin->service);
+    LEGACY_SERVICE_stop (plugin->service);
   else
     GNUNET_SERVER_destroy (plugin->server);
   GNUNET_free (plugin->handlers);