-fix (C) notices
[oweals/gnunet.git] / src / nat / nat.c
index 3573ec4978f38ca1b350b20b0746ef017e60cfa5..57961ffafae6926753a48e7cbaf23d0c603e2734 100644 (file)
@@ -1,6 +1,6 @@
 /*
      This file is part of GNUnet.
-     Copyright (C) 2009, 2010, 2011 Christian Grothoff (and other contributing authors)
+     Copyright (C) 2009, 2010, 2011 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
@@ -270,23 +270,28 @@ struct GNUNET_NAT_Handle
   /**
    * ID of select gnunet-helper-nat-server stdout read task
    */
-  struct GNUNET_SCHEDULER_Task * server_read_task;
+  struct GNUNET_SCHEDULER_Task *server_read_task;
 
   /**
    * ID of interface IP-scan task
    */
-  struct GNUNET_SCHEDULER_Task * ifc_task;
+  struct GNUNET_SCHEDULER_Task *ifc_task;
 
   /**
    * ID of hostname DNS lookup task
    */
-  struct GNUNET_SCHEDULER_Task * hostname_task;
+  struct GNUNET_SCHEDULER_Task *hostname_task;
 
   /**
    * ID of DynDNS lookup task
    */
   struct GNUNET_SCHEDULER_Task *dns_task;
 
+  /**
+   * Active STUN request, if any.
+   */
+  struct GNUNET_NAT_STUN_Handle *stun_request;
+
   /**
    * How often do we scan for changes in our IP address from our local
    * interfaces?
@@ -799,6 +804,7 @@ process_interfaces (void *cls,
       GNUNET_free (tun_if);
       return GNUNET_OK;
     }
+    GNUNET_free (tun_if);
   }
   /* skip virtual interfaces created by GNUnet-dns */
   if (GNUNET_OK ==
@@ -814,6 +820,7 @@ process_interfaces (void *cls,
       GNUNET_free (tun_if);
       return GNUNET_OK;
     }
+    GNUNET_free (tun_if);
   }
   /* skip virtual interfaces created by GNUnet-exit */
   if (GNUNET_OK ==
@@ -829,9 +836,9 @@ process_interfaces (void *cls,
       GNUNET_free (tun_if);
       return GNUNET_OK;
     }
+    GNUNET_free (tun_if);
   }
 
-
   switch (addr->sa_family)
   {
   case AF_INET:
@@ -1109,12 +1116,11 @@ list_interfaces (void *cls,
 }
 
 
-
 /**
- * Callback if the STun request have a error
+ * Callback with the result from the STUN request.
  *
  * @param cls the NAT handle
- * @param result the status
+ * @param result the status
  */
 static void
 stun_request_callback (void *cls,
@@ -1122,14 +1128,24 @@ stun_request_callback (void *cls,
 {
   struct GNUNET_NAT_Handle *h = cls;
 
-  if (NULL == h)
-    return;
-  h->waiting_stun = GNUNET_NO;
-
-  if(result != GNUNET_OK)
+  h->stun_request = NULL;
+  switch (result)
   {
+  case GNUNET_NAT_ERROR_INTERNAL_NETWORK_ERROR:
+    LOG (GNUNET_ERROR_TYPE_WARNING,
+         "Failed to transmit STUN request\n");
+    break;
+  case GNUNET_NAT_ERROR_NOT_ONLINE:
     LOG (GNUNET_ERROR_TYPE_WARNING,
-       "Error processing a STUN request");
+         "Failed to resolve STUN server (are we online?)\n");
+    break;
+  case GNUNET_NAT_ERROR_SUCCESS:
+    /* all good, STUN request active */
+    h->waiting_stun = GNUNET_YES;
+    break;
+  default:
+    /* unexpected error code for STUN */
+    GNUNET_break (0);
   }
 }
 
@@ -1153,7 +1169,7 @@ GNUNET_NAT_is_valid_stun_packet (void *cls,
   struct sockaddr_in answer;
 
   /* We are not expecting a STUN message */
-  if (! h->waiting_stun)
+  if (GNUNET_YES != h->waiting_stun)
     return GNUNET_NO;
 
   /* We dont have STUN installed */
@@ -1165,15 +1181,15 @@ GNUNET_NAT_is_valid_stun_packet (void *cls,
           0,
           sizeof(struct sockaddr_in));
 
-  /*Lets handle the packet*/
-  int valid = GNUNET_NAT_stun_handle_packet (data,
-                                             len,
-                                             &answer);
-  if (! valid)
+  /* Lets handle the packet*/
+  if (GNUNET_NO ==
+      GNUNET_NAT_stun_handle_packet (data,
+                                     len,
+                                     &answer))
     return GNUNET_NO;
 
   LOG (GNUNET_ERROR_TYPE_INFO,
-       "Stun server returned %s:%d\n",
+       "STUN server returned %s:%d\n",
        inet_ntoa (answer.sin_addr),
        ntohs (answer.sin_port));
   /* Remove old IPs from previous STUN calls */
@@ -1208,16 +1224,19 @@ process_stun (void *cls,
        "I will request the stun server %s:%i\n",
        elem->address,
        elem->port);
-  if (GNUNET_OK ==
-      GNUNET_NAT_stun_make_request (elem->address,
+  if (NULL != h->stun_request)
+  {
+    GNUNET_NAT_stun_make_request_cancel (h->stun_request);
+    h->stun_request = NULL;
+  }
+  h->waiting_stun = GNUNET_NO;
+  h->stun_request
+    = GNUNET_NAT_stun_make_request (elem->address,
                                     elem->port,
                                     h->socket,
                                     &stun_request_callback,
-                                    NULL))
-  {
-    h->waiting_stun = GNUNET_YES;
-  }
-  else
+                                    h);
+  if (NULL == h->stun_request)
   {
     LOG (GNUNET_ERROR_TYPE_ERROR,
          "STUN request to %s:%i failed\n",
@@ -1226,7 +1245,8 @@ process_stun (void *cls,
   }
   h->stun_task =
     GNUNET_SCHEDULER_add_delayed (h->stun_frequency,
-                                  &process_stun, h);
+                                  &process_stun,
+                                  h);
 
   /* Set actual Server*/
   if (NULL != elem->next)
@@ -1628,39 +1648,38 @@ GNUNET_NAT_register (const struct GNUNET_CONFIGURATION_Handle *cfg,
   {
     char *stun_servers;
     size_t urls;
-    int pos;
+    ssize_t pos;
     size_t pos_port;
 
     h->socket = sock;
     h->actual_stun_server = NULL;
+    stun_servers = NULL;
     /* Lets process the servers*/
-    if (GNUNET_OK !=
-        GNUNET_CONFIGURATION_get_value_string (cfg,
-                                               "nat",
-                                               "STUN_SERVERS",
-                                               &stun_servers))
-    {
-      GNUNET_log_config_missing (GNUNET_ERROR_TYPE_WARNING,
-                                 "nat",
-                                 "STUN_SERVERS");
-    }
-
+    (void) GNUNET_CONFIGURATION_get_value_string (cfg,
+                                                  "nat",
+                                                  "STUN_SERVERS",
+                                                  &stun_servers);
     urls = 0;
     h->stun_servers_head = NULL;
     h->stun_servers_tail = NULL;
     h->actual_stun_server = NULL;
-    if (strlen (stun_servers) > 0)
+    if ( (NULL != stun_servers) &&
+         (strlen (stun_servers) > 0) )
     {
-      pos = strlen (stun_servers) - 1;
       pos_port = 0;
-      while (pos >= 0)
+      for (pos = strlen (stun_servers) - 1;
+           pos >= 0;
+           pos--)
       {
         if (stun_servers[pos] == ':')
         {
           pos_port = pos + 1;
+          stun_servers[pos] = '\0';
+          continue;
         }
         if ((stun_servers[pos] == ' ') || (0 == pos))
         {
+          struct StunServerList *ml;
 
           /*Check if we do have a port*/
           if((0 == pos_port) || (pos_port <= pos))
@@ -1669,49 +1688,39 @@ GNUNET_NAT_register (const struct GNUNET_CONFIGURATION_Handle *cfg,
                  "STUN server format mistake\n");
             break;
           }
-
           urls++;
-
-          struct StunServerList* ml = GNUNET_new (struct StunServerList);
-
+          ml = GNUNET_new (struct StunServerList);
           ml->port = atoi (&stun_servers[pos_port]);
-          stun_servers[pos_port-1] = '\0';
 
           /* Remove trailing space */
           if(stun_servers[pos] == ' ')
             ml->address = GNUNET_strdup (&stun_servers[pos + 1]);
           else
             ml->address = GNUNET_strdup (&stun_servers[pos]);
-
           LOG (GNUNET_ERROR_TYPE_DEBUG,
                "Found STUN server %s:%i\n",
                ml->address,
                ml->port);
-
           GNUNET_CONTAINER_DLL_insert (h->stun_servers_head,
                                        h->stun_servers_tail,
                                        ml);
-          /* Make sure that we STOP if is the last one*/
-          if (0 == pos)
-            break;
         }
-
-        pos--;
       }
     }
-    if (urls == 0)
+    if (0 == urls)
     {
       GNUNET_log_config_missing (GNUNET_ERROR_TYPE_WARNING,
-                                 "nat", "STUN_SERVERS");
+                                 "nat",
+                                 "STUN_SERVERS");
     }
     else
     {
       /* Set the actual STUN server*/
       h->actual_stun_server = h->stun_servers_head;
     }
-
     h->stun_task = GNUNET_SCHEDULER_add_now (&process_stun,
                                              h);
+    GNUNET_free_non_null (stun_servers);
   }
 
 
@@ -1821,10 +1830,18 @@ GNUNET_NAT_unregister (struct GNUNET_NAT_Handle *h)
     GNUNET_SCHEDULER_cancel (h->stun_task);
     h->stun_task = NULL;
   }
+  if (NULL != h->stun_request)
+  {
+    GNUNET_NAT_stun_make_request_cancel (h->stun_request);
+    h->stun_request = NULL;
+  }
   if (NULL != h->server_proc)
   {
-    if (0 != GNUNET_OS_process_kill (h->server_proc, GNUNET_TERM_SIG))
-      GNUNET_log_from_strerror (GNUNET_ERROR_TYPE_WARNING, "nat", "kill");
+    if (0 != GNUNET_OS_process_kill (h->server_proc,
+                                     GNUNET_TERM_SIG))
+      GNUNET_log_from_strerror (GNUNET_ERROR_TYPE_WARNING,
+                                "nat",
+                                "kill");
     GNUNET_OS_process_wait (h->server_proc);
     GNUNET_OS_process_destroy (h->server_proc);
     h->server_proc = NULL;
@@ -1943,6 +1960,7 @@ GNUNET_NAT_test_address (struct GNUNET_NAT_Handle *h,
   struct LocalAddressList *pos;
   const struct sockaddr_in *in4;
   const struct sockaddr_in6 *in6;
+  char pbuf[INET6_ADDRSTRLEN+1];
 
   if ((addrlen != sizeof (struct in_addr)) &&
       (addrlen != sizeof (struct in6_addr)))
@@ -1973,8 +1991,11 @@ GNUNET_NAT_test_address (struct GNUNET_NAT_Handle *h,
   }
   LOG (GNUNET_ERROR_TYPE_WARNING,
        "Asked to validate one of my addresses (%s) and validation failed!\n",
-       GNUNET_a2s (addr,
-                   addrlen));
+       inet_ntop ((addrlen == sizeof(struct in_addr))
+                  ? AF_INET
+                  : AF_INET6,
+                  addr,
+                  pbuf, sizeof (pbuf)));
   return GNUNET_NO;
 }