fixing 2012: network structure alignment now forced to be correct even on W32 using...
[oweals/gnunet.git] / src / nat / nat.c
index 6e20113474c130c14e8aaa0284eab164e38dc46c..9f8fec9a022fc004eb018fe7f2ec6d5d4c649038 100644 (file)
@@ -334,6 +334,11 @@ struct GNUNET_NAT_Handle
    */
   int use_localaddresses;
 
+  /**
+   * Should we return local addresses to clients
+   */
+  int return_localaddress;
+
   /**
    * Should we do a DNS lookup of our hostname to find out our own IP?
    */
@@ -624,12 +629,16 @@ process_hostname_ip (void *cls, const struct sockaddr *addr, socklen_t addrlen)
  * @param name name of the interface
  * @param isDefault do we think this may be our default interface
  * @param addr address of the interface
+ * @param broadcast_addr the broadcast address (can be NULL for unknown or unassigned)
+ * @param netmask the network mask (can be NULL for unknown or unassigned))
  * @param addrlen number of bytes in addr
  * @return GNUNET_OK to continue iterating
  */
 static int
 process_interfaces (void *cls, const char *name, int isDefault,
-                    const struct sockaddr *addr, socklen_t addrlen)
+                    const struct sockaddr *addr,
+                    const struct sockaddr *broadcast_addr,
+                    const struct sockaddr *netmask, socklen_t addrlen)
 {
   struct GNUNET_NAT_Handle *h = cls;
   const struct sockaddr_in *s4;
@@ -642,9 +651,20 @@ process_interfaces (void *cls, const char *name, int isDefault,
   case AF_INET:
     s4 = (struct sockaddr_in *) addr;
     ip = &s4->sin_addr;
+
+    /* Check if address is in 127.0.0.0/8 */
+    uint32_t address = ntohl ((uint32_t) (s4->sin_addr.s_addr));
+    uint32_t value = (address & 0xFF000000) ^ 0x7F000000;
+
+    if ((h->return_localaddress == GNUNET_NO) && (value == 0))
+    {
+      return GNUNET_OK;
+    }
     if (GNUNET_YES == h->use_localaddresses)
+    {
       add_ip_to_address_list (h, LAL_INTERFACE_ADDRESS, &s4->sin_addr,
                               sizeof (struct in_addr));
+    }
     break;
   case AF_INET6:
     s6 = (struct sockaddr_in6 *) addr;
@@ -653,10 +673,17 @@ process_interfaces (void *cls, const char *name, int isDefault,
       /* skip link local addresses */
       return GNUNET_OK;
     }
+    if ((h->return_localaddress == GNUNET_NO) &&
+        (IN6_IS_ADDR_LOOPBACK (&((struct sockaddr_in6 *) addr)->sin6_addr)))
+    {
+      return GNUNET_OK;
+    }
     ip = &s6->sin6_addr;
     if (GNUNET_YES == h->use_localaddresses)
+    {
       add_ip_to_address_list (h, LAL_INTERFACE_ADDRESS, &s6->sin6_addr,
                               sizeof (struct in6_addr));
+    }
     break;
   default:
     GNUNET_break (0);
@@ -1116,6 +1143,10 @@ GNUNET_NAT_register (const struct GNUNET_CONFIGURATION_Handle *cfg, int is_tcp,
       GNUNET_CONFIGURATION_get_value_yesno (cfg, "nat", "ENABLE_UPNP");
   h->use_localaddresses =
       GNUNET_CONFIGURATION_get_value_yesno (cfg, "nat", "USE_LOCALADDR");
+  h->return_localaddress =
+      GNUNET_CONFIGURATION_get_value_yesno (cfg, "nat",
+                                            "RETURN_LOCAL_ADDRESSES");
+
   h->use_hostname =
       GNUNET_CONFIGURATION_get_value_yesno (cfg, "nat", "USE_HOSTNAME");
   h->disable_ipv6 =