Merge branch 'credentials' of git+ssh://gnunet.org/gnunet into credentials
[oweals/gnunet.git] / src / nat / gnunet-nat-server.c
index ae831db0866ca54539efedd2362f5ec8334a9c5e..6722deefba0ab4716e66b71c37e017ab8df9f615 100644 (file)
@@ -1,6 +1,6 @@
 /*
      This file is part of GNUnet.
-     (C) 2011 Christian Grothoff (and other contributing authors)
+     Copyright (C) 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
 
      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., 59 Temple Place - Suite 330,
-     Boston, MA 02111-1307, USA.
+     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+     Boston, MA 02110-1301, USA.
 */
 
 /**
  * @file src/nat/gnunet-nat-server.c
  * @brief Daemon to run on 'gnunet.org' to help test NAT traversal code
  * @author Christian Grothoff
- *
  */
 #include "platform.h"
 #include "gnunet_util_lib.h"
@@ -30,6 +29,7 @@
 #include "gnunet_protocols.h"
 #include "nat.h"
 
+
 /**
  * Our server.
  */
@@ -40,32 +40,38 @@ static struct GNUNET_SERVER_Handle *server;
  */
 static const struct GNUNET_CONFIGURATION_Handle *cfg;
 
+
 /**
  * Try contacting the peer using autonomous
  * NAT traveral method.
  *
  * @param dst_ipv4 IPv4 address to send the fake ICMP message
  * @param dport destination port to include in ICMP message
- * @param is_tcp mark for TCP (GNUNET_YES)  or UDP (GNUNET_NO)
+ * @param is_tcp mark for TCP (#GNUNET_YES)  or UDP (#GNUNET_NO)
  */
 static void
 try_anat (uint32_t dst_ipv4,
-         uint16_t dport,
-         int is_tcp)
+          uint16_t dport,
+          int is_tcp)
 {
   struct GNUNET_NAT_Handle *h;
   struct sockaddr_in sa;
 
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Asking for connection reversal with %x and code %u\n",
+              (unsigned int) dst_ipv4,
+              (unsigned int) dport);
   h = GNUNET_NAT_register (cfg,
-                          is_tcp,
-                          dport,
-                          0, NULL, NULL,
-                          NULL, NULL, NULL);
+                           is_tcp,
+                           dport,
+                           0,
+                           NULL, NULL, NULL, NULL, NULL, NULL);
   memset (&sa, 0, sizeof (sa));
+  sa.sin_family = AF_INET;
 #if HAVE_SOCKADDR_IN_SIN_LEN
   sa.sin_len = sizeof (sa);
 #endif
-  sa.sin_addr.s_addr = dst_ipv4; 
+  sa.sin_addr.s_addr = dst_ipv4;
   GNUNET_NAT_run_client (h, &sa);
   GNUNET_NAT_unregister (h);
 }
@@ -74,16 +80,16 @@ try_anat (uint32_t dst_ipv4,
 /**
  * Closure for 'tcp_send'.
  */
-struct TcpContext 
+struct TcpContext
 {
   /**
    * TCP  socket.
    */
   struct GNUNET_NETWORK_Handle *s;
 
-  /** 
+  /**
    * Data to transmit.
-   */  
+   */
   uint16_t data;
 };
 
@@ -92,105 +98,132 @@ struct TcpContext
  * Task called by the scheduler once we can do the TCP send
  * (or once we failed to connect...).
  *
- * @param ctx the 'struct TcpContext'
- * @param tc scheduler context
+ * @param cls the 'struct TcpContext'
  */
 static void
-tcp_send (void *cls,
-         const struct GNUNET_SCHEDULER_TaskContext *tc)
+tcp_send (void *cls)
 {
   struct TcpContext *ctx = cls;
-
-  if ( (NULL != tc->write_ready) &&
-       (GNUNET_NETWORK_fdset_isset (tc->write_ready, 
-                                   ctx->s)) )
+  const struct GNUNET_SCHEDULER_TaskContext *tc;
+
+  tc = GNUNET_SCHEDULER_get_task_context ();
+  if ((NULL != tc->write_ready) &&
+      (GNUNET_NETWORK_fdset_isset (tc->write_ready, ctx->s)))
+  {
+    if (-1 ==
+        GNUNET_NETWORK_socket_send (ctx->s, &ctx->data, sizeof (ctx->data)))
     {
-      if (-1 == GNUNET_NETWORK_socket_send (ctx->s, &ctx->data, sizeof (ctx->data)))
-       GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "send");
-      GNUNET_NETWORK_socket_shutdown (ctx->s, SHUT_RDWR);
+      GNUNET_log_strerror (GNUNET_ERROR_TYPE_DEBUG, "send");
     }
+    GNUNET_NETWORK_socket_shutdown (ctx->s, SHUT_RDWR);
+  }
   GNUNET_NETWORK_socket_close (ctx->s);
   GNUNET_free (ctx);
 }
 
 
 /**
- * Try to send 'data' to the
- * IP 'dst_ipv4' at port 'dport' via TCP.
- * 
- * @param dst_ivp4 target IP
+ * Try to send @a data to the
+ * IP @a dst_ipv4' at port @a dport via TCP.
+ *
+ * @param dst_ipv4 target IP
  * @param dport target port
  * @param data data to send
  */
 static void
 try_send_tcp (uint32_t dst_ipv4,
-             uint16_t dport,
-             uint16_t data)
+              uint16_t dport,
+              uint16_t data)
 {
   struct GNUNET_NETWORK_Handle *s;
   struct sockaddr_in sa;
   struct TcpContext *ctx;
 
-  s = GNUNET_NETWORK_socket_create (AF_UNIX, SOCK_STREAM, 0);
+  s = GNUNET_NETWORK_socket_create (AF_INET,
+                                    SOCK_STREAM,
+                                    0);
   if (NULL == s)
-    {
-      GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "socket");
-      return;
-    }
+  {
+    GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
+                         "socket");
+    return;
+  }
   memset (&sa, 0, sizeof (sa));
+  sa.sin_family = AF_INET;
 #if HAVE_SOCKADDR_IN_SIN_LEN
   sa.sin_len = sizeof (sa);
 #endif
-  sa.sin_addr.s_addr = dst_ipv4; 
+  sa.sin_addr.s_addr = dst_ipv4;
   sa.sin_port = htons (dport);
-  if ( (GNUNET_OK != 
-       GNUNET_NETWORK_socket_connect (s, 
-                                      (const struct sockaddr*) &sa, sizeof (sa))) &&
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Sending TCP message to `%s'\n",
+              GNUNET_a2s ((struct sockaddr *) &sa,
+                          sizeof (sa)));
+  if ( (GNUNET_OK !=
+        GNUNET_NETWORK_socket_connect (s,
+                                       (const struct sockaddr *) &sa,
+                                       sizeof (sa))) &&
        (errno != EINPROGRESS) )
-    {
-      GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "connect");
-      GNUNET_NETWORK_socket_close (s);
-      return;
-    }
-  ctx = GNUNET_malloc (sizeof (struct TcpContext));
+  {
+    GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
+                         "connect");
+    GNUNET_NETWORK_socket_close (s);
+    return;
+  }
+  ctx = GNUNET_new (struct TcpContext);
   ctx->s = s;
   ctx->data = data;
   GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_SECONDS,
-                                 s,
-                                 &tcp_send, ctx);
+                                  s,
+                                  &tcp_send,
+                                  ctx);
 }
 
 
 /**
- * Try to send 'data' to the
- * IP 'dst_ipv4' at port 'dport' via UDP.
- * 
- * @param dst_ivp4 target IP
+ * Try to send @a data to the
+ * IP @a dst_ipv4' at port @a dport via UDP.
+ *
+ * @param dst_ipv4 target IP
  * @param dport target port
  * @param data data to send
  */
 static void
 try_send_udp (uint32_t dst_ipv4,
-             uint16_t dport,
-             uint16_t data)
+              uint16_t dport,
+              uint16_t data)
 {
   struct GNUNET_NETWORK_Handle *s;
   struct sockaddr_in sa;
 
-  s = GNUNET_NETWORK_socket_create (AF_UNIX, SOCK_DGRAM, 0);
+  s = GNUNET_NETWORK_socket_create (AF_INET,
+                                    SOCK_DGRAM,
+                                    0);
   if (NULL == s)
-    {
-      GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "socket");
-      return;
-    }
+  {
+    GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
+                         "socket");
+    return;
+  }
   memset (&sa, 0, sizeof (sa));
+  sa.sin_family = AF_INET;
 #if HAVE_SOCKADDR_IN_SIN_LEN
   sa.sin_len = sizeof (sa);
 #endif
-  sa.sin_addr.s_addr = dst_ipv4; 
+  sa.sin_addr.s_addr = dst_ipv4;
   sa.sin_port = htons (dport);
-  if (-1 == GNUNET_NETWORK_socket_sendto (s, &data, sizeof(data), (const struct sockaddr*) &sa, sizeof (sa)))
-    GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "sendto");
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Sending UDP packet to `%s'\n",
+              GNUNET_a2s ((struct sockaddr *) &sa,
+                          sizeof (sa)));
+  if (-1 ==
+      GNUNET_NETWORK_socket_sendto (s,
+                                    &data,
+                                    sizeof (data),
+                                    (const struct sockaddr *) &sa,
+                                    sizeof (sa)))
+    GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
+                         "sendto");
   GNUNET_NETWORK_socket_close (s);
 }
 
@@ -198,7 +231,7 @@ try_send_udp (uint32_t dst_ipv4,
 /**
  * We've received a request to probe a NAT
  * traversal. Do it.
- * 
+ *
  * @param cls unused
  * @param client handle to client (we always close)
  * @param msg message with details about what to test
@@ -211,30 +244,34 @@ test (void *cls,
   const struct GNUNET_NAT_TestMessage *tm;
   uint16_t dport;
 
-  tm = (const struct GNUNET_NAT_TestMessage*) msg;
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Received test request\n");
+  tm = (const struct GNUNET_NAT_TestMessage *) msg;
   dport = ntohs (tm->dport);
   if (0 == dport)
     try_anat (tm->dst_ipv4,
-             ntohs (tm->data),
-             (int) ntohl (tm->is_tcp));
+              ntohs (tm->data),
+              (int) ntohl (tm->is_tcp));
   else if (GNUNET_YES == ntohl (tm->is_tcp))
-    try_send_tcp (tm->dst_ipv4, dport, tm->data);
+    try_send_tcp (tm->dst_ipv4,
+                  dport,
+                  tm->data);
   else
-    try_send_udp (tm->dst_ipv4, dport, tm->data);
+    try_send_udp (tm->dst_ipv4,
+                  dport,
+                  tm->data);
   GNUNET_SERVER_receive_done (client,
-                             GNUNET_NO);
+                              GNUNET_NO);
 }
 
 
 /**
  * Task run during shutdown.
  *
- * @param ctx unused
- * @param tc scheduler context
+ * @param cls unused
  */
 static void
-shutdown_task (void *cls,
-              const struct GNUNET_SCHEDULER_TaskContext *tc)
+shutdown_task (void *cls)
 {
   GNUNET_SERVER_destroy (server);
   server = NULL;
@@ -255,55 +292,52 @@ run (void *cls,
      const char *cfgfile,
      const struct GNUNET_CONFIGURATION_Handle *c)
 {
-  static const struct GNUNET_SERVER_MessageHandler handlers[] =
-      {
-       { &test, NULL, GNUNET_MESSAGE_TYPE_NAT_TEST, sizeof (struct GNUNET_NAT_TestMessage) },
-       { NULL, NULL, 0, 0 }
-      };
+  static const struct GNUNET_SERVER_MessageHandler handlers[] = {
+    {&test, NULL, GNUNET_MESSAGE_TYPE_NAT_TEST,
+     sizeof (struct GNUNET_NAT_TestMessage)},
+    {NULL, NULL, 0, 0}
+  };
   unsigned int port;
   struct sockaddr_in in4;
   struct sockaddr_in6 in6;
-  socklen_t slen[] =
-    {
-      sizeof (in4),
-      sizeof (in6), 
-      0
-    };
-  struct sockaddr *sa[] =
-    {
-      (struct sockaddr*) &in4,
-      (struct sockaddr*) &in6,
-      NULL
-    };
+
+  socklen_t slen[] = {
+    sizeof (in4),
+    sizeof (in6),
+    0
+  };
+  struct sockaddr *sa[] = {
+    (struct sockaddr *) &in4,
+    (struct sockaddr *) &in6,
+    NULL
+  };
 
   cfg = c;
-  if ( (args[0] == NULL) || 
-       (1 != SSCANF (args[0], "%u", &port)) ||
-       (0 == port) ||
-       (65536 >= port) )
-    {
-      fprintf (stderr,
-              _("Please pass valid port number as the first argument!\n"));
-      return;
-    }
-  memset (&in4, 0, sizeof (in4)); 
-  memset (&in6, 0, sizeof (in6)); 
+  if ((args[0] == NULL) || (1 != SSCANF (args[0], "%u", &port)) || (0 == port)
+      || (65536 <= port))
+  {
+    FPRINTF (stderr,
+             _
+             ("Please pass valid port number as the first argument! (got `%s')\n"),
+             args[0]);
+    return;
+  }
+  memset (&in4, 0, sizeof (in4));
+  memset (&in6, 0, sizeof (in6));
+  in4.sin_family = AF_INET;
   in4.sin_port = htons ((uint16_t) port);
+  in6.sin6_family = AF_INET6;
   in6.sin6_port = htons ((uint16_t) port);
 #if HAVE_SOCKADDR_IN_SIN_LEN
-  in4.sin_len = sizeof (in);
+  in4.sin_len = sizeof (in4);
   in6.sin6_len = sizeof (in6);
 #endif
-  server = GNUNET_SERVER_create (NULL, NULL,
-                                (struct sockaddr*const*) sa,
-                                slen,
-                                GNUNET_TIME_UNIT_SECONDS,
-                                GNUNET_YES);
-  GNUNET_SERVER_add_handlers (server,
-                             handlers);
-  GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
-                               &shutdown_task,
-                               NULL);
+  server =
+      GNUNET_SERVER_create (NULL, NULL, (struct sockaddr * const *) sa, slen,
+                            GNUNET_TIME_UNIT_SECONDS, GNUNET_YES);
+  GNUNET_SERVER_add_handlers (server, handlers);
+  GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
+                                NULL);
 }
 
 
@@ -321,13 +355,18 @@ main (int argc, char *const argv[])
     GNUNET_GETOPT_OPTION_END
   };
 
+  if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
+    return 2;
+
   if (GNUNET_OK !=
-      GNUNET_PROGRAM_run (argc, argv, 
-                         "gnunet-nat-server [options] PORT", 
-                         _("GNUnet NAT traversal test helper daemon"), 
-                         options,
-                         &run, NULL))
+      GNUNET_PROGRAM_run (argc, argv, "gnunet-nat-server [options] PORT",
+                          _("GNUnet NAT traversal test helper daemon"), options,
+                          &run, NULL))
+  {
+    GNUNET_free ((void*) argv);
     return 1;
+  }
+  GNUNET_free ((void*) argv);
   return 0;
 }