REST: nothing triggers rest
[oweals/gnunet.git] / src / nat / gnunet-service-nat.c
index ccb37d2f926e5d84abfd4b4df99a08580e21809d..8d771f474d8706748363ea522b3ab092c5857cd9 100644 (file)
@@ -2,20 +2,20 @@
   This file is part of GNUnet.
   Copyright (C) 2016, 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 Affero General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-  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.
+     SPDX-License-Identifier: AGPL3.0-or-later
  */
 
 /**
@@ -485,9 +485,8 @@ match_ipv6 (const char *network,
                                 network,
                                 &net));
   memset (&mask, 0, sizeof (mask));
-  if (0 == memcmp (&mask,
-                  ip,
-                  sizeof (mask)))
+  if (0 == GNUNET_memcmp (&mask,
+                  ip))
     return GNUNET_YES;
   off = 0;
   while (bits > 8)
@@ -662,6 +661,11 @@ notify_client (enum GNUNET_NAT_AddressClass ac,
   struct GNUNET_MQ_Envelope *env;
   struct GNUNET_NAT_AddressChangeNotificationMessage *msg;
 
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Notifying client about %s of IP %s\n",
+              add ? "addition" : "removal",
+              GNUNET_a2s (addr,
+                          addr_len));
   env = GNUNET_MQ_msg_extra (msg,
                             addr_len,
                             GNUNET_MESSAGE_TYPE_NAT_ADDRESS_CHANGE);
@@ -693,7 +697,11 @@ check_notify_client (struct LocalAddressList *delta,
   struct sockaddr_in6 v6;
 
   if (0 == (ch->flags & GNUNET_NAT_RF_ADDRESSES))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Not notifying client as it does not care about addresses\n");
     return;
+  }
   switch (delta->af)
   {
   case AF_INET:
@@ -715,25 +723,23 @@ check_notify_client (struct LocalAddressList *delta,
           (! match_ipv4 ("127.0.0.1", &v4.sin_addr, 8)) )
        continue; /* bound to loopback, but this is not loopback */
       if ( (! match_ipv4 ("127.0.0.1", &c4->sin_addr, 8) ) &&
-          (0 != c4->sin_addr.s_addr) &&
           match_ipv4 ("127.0.0.1", &v4.sin_addr, 8) )
        continue; /* bound to non-loopback, but this is loopback */
-      if ( (0 != (ch->flags & GNUNET_NAT_AC_EXTERN)) &&
-          (0 != c4->sin_addr.s_addr) &&
-          (! is_nat_v4 (&v4.sin_addr)) )
-       continue; /* based on external-IP, but this IP is not
-                    from private address range. */
-      if ( (0 != memcmp (&v4.sin_addr,
-                        &c4->sin_addr,
-                        sizeof (struct in_addr))) &&
-          (0 != c4->sin_addr.s_addr) &&
-          ( (! is_nat_v4 (&c4->sin_addr)) ||
-            (0 == (ch->flags & GNUNET_NAT_AC_EXTERN))) )
+      if ( (0 != (delta->ac & GNUNET_NAT_AC_EXTERN)) &&
+           (0 != c4->sin_addr.s_addr) &&
+           (! is_nat_v4 (&v4.sin_addr)) )
+       continue; /* based on external-IP, but this IP is not
+                    from private address range. */
+      if ( (0 != GNUNET_memcmp (&v4.sin_addr,
+                         &c4->sin_addr)) &&
+           (0 != c4->sin_addr.s_addr) &&
+           (! is_nat_v4 (&c4->sin_addr)) )
        continue; /* this IP is not from private address range,
                     and IP does not match. */
 
       /* OK, IP seems relevant, notify client */
-      v4.sin_port = c4->sin_port;
+      if (0 == htons (v4.sin_port))
+        v4.sin_port = c4->sin_port;
       notify_client (delta->ac,
                     ch,
                     add,
@@ -754,46 +760,38 @@ check_notify_client (struct LocalAddressList *delta,
        continue; /* IPv4 not relevant */
       c6 = (const struct sockaddr_in6 *) &ch->caddrs[i].ss;
       if ( match_ipv6 ("::1", &c6->sin6_addr, 128) &&
-          (0 != memcmp (&c6->sin6_addr,
-                        &in6addr_any,
-                        sizeof (struct in6_addr))) &&
+          (0 != GNUNET_memcmp (&c6->sin6_addr,
+                        &in6addr_any)) &&
           (! match_ipv6 ("::1", &v6.sin6_addr, 128)) )
        continue; /* bound to loopback, but this is not loopback */
       if ( (! match_ipv6 ("::1", &c6->sin6_addr, 128) ) &&
-          (0 != memcmp (&c6->sin6_addr,
-                        &in6addr_any,
-                        sizeof (struct in6_addr))) &&
           match_ipv6 ("::1", &v6.sin6_addr, 128) )
        continue; /* bound to non-loopback, but this is loopback */
-      if ( (0 != (ch->flags & GNUNET_NAT_AC_EXTERN)) &&
-          (0 != memcmp (&c6->sin6_addr,
-                        &in6addr_any,
-                        sizeof (struct in6_addr))) &&
+      if ( (0 != (delta->ac & GNUNET_NAT_AC_EXTERN)) &&
+           (0 != GNUNET_memcmp (&c6->sin6_addr,
+                        &in6addr_any)) &&
           (! is_nat_v6 (&v6.sin6_addr)) )
        continue; /* based on external-IP, but this IP is not
                     from private address range. */
-      if ( (0 != memcmp (&v6.sin6_addr,
-                        &c6->sin6_addr,
-                        sizeof (struct in6_addr))) &&
-          (0 != memcmp (&c6->sin6_addr,
-                        &in6addr_any,
-                        sizeof (struct in6_addr))) &&
+      if ( (0 != GNUNET_memcmp (&v6.sin6_addr,
+                        &c6->sin6_addr)) &&
+          (0 != GNUNET_memcmp (&c6->sin6_addr,
+                        &in6addr_any)) &&
           (! is_nat_v6 (&c6->sin6_addr)) )
        continue; /* this IP is not from private address range,
                     and IP does not match. */
       if ( (match_ipv6 ("fe80::", &c6->sin6_addr, 10)) &&
-          (0 != memcmp (&c6->sin6_addr,
-                        &in6addr_any,
-                        sizeof (struct in6_addr))) &&
-          (0 != memcmp (&v6.sin6_addr,
-                        &c6->sin6_addr,
-                        sizeof (struct in6_addr))) &&
+          (0 != GNUNET_memcmp (&c6->sin6_addr,
+                        &in6addr_any)) &&
+          (0 != GNUNET_memcmp (&v6.sin6_addr,
+                        &c6->sin6_addr)) &&
           (0 == (delta->ac & GNUNET_NAT_AC_EXTERN)) )
        continue; /* client bound to link-local, and the other address
                     does not match and is not an external IP */
 
       /* OK, IP seems relevant, notify client */
-      v6.sin6_port = c6->sin6_port;
+      if (0 == htons (v6.sin6_port))
+        v6.sin6_port = c6->sin6_port;
       notify_client (delta->ac,
                     ch,
                     add,
@@ -853,6 +851,10 @@ notify_client_external_ipv4_change (void *cls,
     struct LocalAddressList lal;
     struct sockaddr_in *s4;
 
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Detected eternal IP, can now back-fill AUTO:%u in hole punching specification of `%s'\n",
+                (unsigned int) ch->ext_dns_port,
+                ch->section_name);
     memset (&lal, 0, sizeof (lal));
     s4 = (struct sockaddr_in *) &lal.addr;
     s4->sin_family = AF_INET;
@@ -868,8 +870,6 @@ notify_client_external_ipv4_change (void *cls,
   /* (1) check if client cares. */
   if (! ch->natted_address)
     return;
-  if (0 == (GNUNET_NAT_RF_ADDRESSES & ch->flags))
-    return;
   have_v4 = GNUNET_NO;
   for (unsigned int i=0;i<ch->num_caddrs;i++)
   {
@@ -891,6 +891,10 @@ notify_client_external_ipv4_change (void *cls,
   sa.sin_addr = *v4;
   sa.sin_port = htons (0);
 
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Detected eternal IP %s, notifying client of external IP (without port)\n",
+              GNUNET_a2s ((const struct sockaddr *) &sa,
+                          sizeof (sa)));
   /* (3) notify client of change */
   notify_client (is_nat_v4 (v4)
                 ? GNUNET_NAT_AC_EXTERN | GNUNET_NAT_AC_LAN
@@ -1055,7 +1059,8 @@ run_scan (void *cls)
 
        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                    "Found NATed local address %s, starting NAT server\n",
-                   GNUNET_a2s ((void *) &pos->addr, sizeof (*s4)));
+                   GNUNET_a2s ((const struct sockaddr *) &pos->addr,
+                                sizeof (*s4)));
        pos->hc = GN_start_gnunet_nat_server_ (&s4->sin_addr,
                                               &reversal_callback,
                                               pos);
@@ -1103,6 +1108,10 @@ upnp_addr_change_cb (void *cls,
     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
                "external-ip binary not found\n");
     return;
+  case GNUNET_NAT_ERROR_UPNPC_NOT_FOUND:
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+               "upnpc binary not found\n");
+    return;
   case GNUNET_NAT_ERROR_EXTERNAL_IP_UTILITY_FAILED:
     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
                "external-ip binary could not be run\n");
@@ -1217,8 +1226,12 @@ process_external_ip (void *cls,
              ch->hole_external);
 
   /* build sockaddr storage with port number */
-  memset (&ss, 0, sizeof (ss));
-  memcpy (&ss, addr, addrlen);
+  memset (&ss,
+          0,
+          sizeof (ss));
+  GNUNET_memcpy (&ss,
+                 addr,
+                 addrlen);
   switch (addr->sa_family)
   {
   case AF_INET:
@@ -1276,6 +1289,11 @@ dyndns_lookup (void *cls)
   struct ClientHandle *ch = cls;
   struct LocalAddressList *lal;
 
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Performing DNS lookup for punched hole given for `%s' as `%s:%u'\n",
+              ch->section_name,
+              ch->hole_external,
+              (unsigned int) ch->ext_dns_port);
   for (lal = ch->ext_addr_head; NULL != lal; lal = lal->next)
     lal->old = GNUNET_YES;
   ch->ext_dns_task = NULL;
@@ -1370,6 +1388,11 @@ lookup_hole_external (struct ClientHandle *ch)
                      ch->hole_external,
                      &s4->sin_addr))
   {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "IPv4 punched hole given for `%s' via `%s:%u'\n",
+                ch->section_name,
+                ch->hole_external,
+                (unsigned int) ch->ext_dns_port);
     s4->sin_port = htons (ch->ext_dns_port);
     lal->af = AF_INET;
     lal->ac = GNUNET_NAT_AC_GLOBAL | GNUNET_NAT_AC_MANUAL;
@@ -1419,8 +1442,6 @@ handle_register (void *cls,
     GNUNET_SERVICE_client_drop (ch->client);
     return;
   }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-             "Received REGISTER message from client\n");
   ch->flags = message->flags;
   ch->proto = message->proto;
   ch->num_caddrs = ntohs (message->num_addrs);
@@ -1430,8 +1451,8 @@ handle_register (void *cls,
   off = (const char *) &message[1];
   for (unsigned int i=0;i<ch->num_caddrs;i++)
   {
-    size_t alen;
     const struct sockaddr *sa = (const struct sockaddr *) off;
+    size_t alen;
     uint16_t port;
     int is_nat;
 
@@ -1446,22 +1467,28 @@ handle_register (void *cls,
     {
     case AF_INET:
       {
-       const struct sockaddr_in *s4 = (const struct sockaddr_in *) sa;
+        struct sockaddr_in s4;
 
+        GNUNET_memcpy (&s4,
+                       off,
+                       sizeof (struct sockaddr_in));
        alen = sizeof (struct sockaddr_in);
-       if (is_nat_v4 (&s4->sin_addr))
+       if (is_nat_v4 (&s4.sin_addr))
          is_nat = GNUNET_YES;
-       port = ntohs (s4->sin_port);
+       port = ntohs (s4.sin_port);
       }
       break;
     case AF_INET6:
       {
-       const struct sockaddr_in6 *s6 = (const struct sockaddr_in6 *) sa;
+        struct sockaddr_in6 s6;
 
+        GNUNET_memcpy (&s6,
+                       off,
+                       sizeof (struct sockaddr_in6));
        alen = sizeof (struct sockaddr_in6);
-       if (is_nat_v6 (&s6->sin6_addr))
+       if (is_nat_v6 (&s6.sin6_addr))
          is_nat = GNUNET_YES;
-       port = ntohs (s6->sin6_port);
+       port = ntohs (s6.sin6_port);
       }
       break;
 #if AF_UNIX
@@ -1479,7 +1506,7 @@ handle_register (void *cls,
     GNUNET_assert (alen <= left);
     GNUNET_assert (alen <= sizeof (struct sockaddr_storage));
     GNUNET_memcpy (&ch->caddrs[i].ss,
-                  sa,
+                  off,
                   alen);
 
     /* If applicable, try UPNPC NAT punching */
@@ -1502,6 +1529,9 @@ handle_register (void *cls,
   ch->section_name
     = GNUNET_strndup (off,
                      ntohs (message->str_len));
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+             "Received REGISTER message from client for subsystem `%s'\n",
+              ch->section_name);
   if (GNUNET_OK ==
       GNUNET_CONFIGURATION_get_value_string (cfg,
                                             ch->section_name,
@@ -1688,9 +1718,8 @@ handle_stun (void *cls,
                         &se->stun_server_addr,
                         sa_len)) )
        continue; /* different STUN server */
-      if (0 != memcmp (&external_addr,
-                      &se->external_addr,
-                      sizeof (struct sockaddr_in)))
+      if (0 != GNUNET_memcmp (&external_addr,
+                      &se->external_addr))
       {
        /* external IP changed, update! */
        notify_clients_stun_change (&se->external_addr,