gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[GNUnet-SVN] r22810 - gnunet/src/gns


From: gnunet
Subject: [GNUnet-SVN] r22810 - gnunet/src/gns
Date: Fri, 20 Jul 2012 22:17:19 +0200

Author: grothoff
Date: 2012-07-20 22:17:19 +0200 (Fri, 20 Jul 2012)
New Revision: 22810

Modified:
   gnunet/src/gns/Makefile.am
   gnunet/src/gns/gnunet-dns2gns.c
Log:
ns2gns

Modified: gnunet/src/gns/Makefile.am
===================================================================
--- gnunet/src/gns/Makefile.am  2012-07-20 17:59:58 UTC (rev 22809)
+++ gnunet/src/gns/Makefile.am  2012-07-20 20:17:19 UTC (rev 22810)
@@ -293,6 +293,7 @@
   $(top_builddir)/src/gns/libgnunetgns.la \
   $(top_builddir)/src/util/libgnunetutil.la \
   $(top_builddir)/src/namestore/libgnunetnamestore.la \
+  $(top_builddir)/src/dns/libgnunetdnsparser.la \
   $(GN_LIBINTL)
 
 gnunet_gns_proxy_SOURCES = \

Modified: gnunet/src/gns/gnunet-dns2gns.c
===================================================================
--- gnunet/src/gns/gnunet-dns2gns.c     2012-07-20 17:59:58 UTC (rev 22809)
+++ gnunet/src/gns/gnunet-dns2gns.c     2012-07-20 20:17:19 UTC (rev 22810)
@@ -24,24 +24,81 @@
  */
 #include "platform.h"
 #include <gnunet_util_lib.h>
-#include <gnunet_namestore_service.h>
+#include <gnunet_dnsparser_lib.h>
+#include <gnunet_gns_service.h>
 
 /**
+ * Timeout for DNS requests.
+ */
+#define TIMEOUT GNUNET_TIME_UNIT_MINUTES
+
+/**
  * Data kept per request.
  */
 struct Request
 {
+  /**
+   * Socket to use for sending the reply.
+   */
+  struct GNUNET_NETWORK_Handle *lsock;
 
+  /**
+   * Destination address to use.
+   */
+  const void *addr;
+
+  /**
+   * Initially, this is the DNS request, it will then be
+   * converted to the DNS response.
+   */
+  struct GNUNET_DNSPARSER_Packet *packet;
+  
+  /**
+   * Our GNS request handle.
+   */
+  struct GNUNET_GNS_LookupRequest *lookup;
+
+  /**
+   * Task run on timeout or shutdown to clean up without
+   * response.
+   */
+  GNUNET_SCHEDULER_TaskIdentifier timeout_task;
+
+  /**
+   * Number of bytes in 'addr'.
+   */ 
+  size_t addr_len;
+
 };
 
 
 /**
- * Listen socket.
+ * Handle to GNS resolver.
  */
-static struct GNUNET_NETWORK_Handle *listen_socket;
+struct GNUNET_GNS_Handle *gns;
 
+/**
+ * Listen socket for IPv4.
+ */
+static struct GNUNET_NETWORK_Handle *listen_socket4;
 
 /**
+ * Listen socket for IPv6.
+ */
+static struct GNUNET_NETWORK_Handle *listen_socket6;
+
+/**
+ * Task for IPv4 socket.
+ */
+static GNUNET_SCHEDULER_TaskIdentifier t4;
+
+/**
+ * Task for IPv6 socket.
+ */
+static GNUNET_SCHEDULER_TaskIdentifier t6;
+
+
+/**
  * Task run on shutdown.  Cleans up everything.
  *
  * @param cls unused
@@ -51,10 +108,240 @@
 do_shutdown (void *cls,
             const struct GNUNET_SCHEDULER_TaskContext *tc)
 {
+  if (GNUNET_SCHEDULER_NO_TASK != t4)
+    GNUNET_SCHEDULER_cancel (t4);
+  if (GNUNET_SCHEDULER_NO_TASK != t6)
+    GNUNET_SCHEDULER_cancel (t6);
+  if (NULL != listen_socket4)
+  {
+    GNUNET_NETWORK_socket_close (listen_socket4);
+    listen_socket4 = NULL;
+  }
+  if (NULL != listen_socket6)
+  {
+    GNUNET_NETWORK_socket_close (listen_socket6);
+    listen_socket6 = NULL;
+  }
+  GNUNET_GNS_disconnect (gns);
+  gns = NULL;
 }
 
 
 /**
+ * Send the response for the given request and clean up.
+ *
+ * @param request context for the request.
+ */
+static void
+send_response (struct Request *request)
+{
+  char *buf;
+  size_t size;
+  
+  if (GNUNET_SYSERR ==
+      GNUNET_DNSPARSER_pack (request->packet,
+                            UINT16_MAX /* is this not too much? */,
+                            &buf,
+                            &size))
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                 _("Failed to pack DNS response into UDP packet!\n"));
+    }
+  else
+    {
+      if (size !=
+         GNUNET_NETWORK_socket_sendto (request->lsock,
+                                       buf, size,
+                                       request->addr,
+                                       request->addr_len))
+       GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "sendto");
+      GNUNET_free (buf);
+    }
+  GNUNET_SCHEDULER_cancel (request->timeout_task);
+  GNUNET_DNSPARSER_free_packet (request->packet);
+  GNUNET_free (request);
+}
+
+
+/**
+ * Task run on timeout.  Cleans up request.
+ *
+ * @param cls 'struct Request' of the request to clean up
+ * @param tc scheduler context
+ */
+static void
+do_timeout (void *cls,
+           const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  struct Request *request = cls;
+
+  GNUNET_DNSPARSER_free_packet (request->packet);
+  GNUNET_GNS_cancel_lookup_request (request->lookup);
+  GNUNET_free (request);
+}
+
+
+/**
+ * Iterator called on obtained result for a GNS
+ * lookup
+ *
+ * @param cls closure
+ * @param name "name" of the original lookup
+ * @param rd_count number of records
+ * @param rd the records in reply
+ */
+static void
+result_processor (void *cls,
+                 uint32_t rd_count,
+                 const struct GNUNET_NAMESTORE_RecordData *rd)
+{
+  struct Request *request = cls;
+
+  // FIXME: is 'processor' called only once or
+  // possibly more than once?
+  request->lookup = NULL;
+  GNUNET_break (0);
+  // FIXME: convert 'rd' to response here...
+  send_response (request);
+}
+
+
+/**
+ * Handle DNS request.
+ *
+ * @param lsock socket to use for sending the reply
+ * @param addr address to use for sending the reply
+ * @param addr_len number of bytes in addr
+ * @param udp_msg DNS request payload
+ * @param udp_msg_size number of bytes in udp_msg 
+ */
+static void
+handle_request (struct GNUNET_NETWORK_Handle *lsock,
+               const void *addr,
+               size_t addr_len,
+               const char *udp_msg,
+               size_t udp_msg_size)
+{
+  struct Request *request;
+  struct GNUNET_DNSPARSER_Packet *packet;
+
+  packet = GNUNET_DNSPARSER_parse (udp_msg, udp_msg_size);
+  if (NULL == packet)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                 _("Received malformed DNS request from %s\n"),
+                 GNUNET_a2s (addr, addr_len));
+      return;
+    }
+  request = GNUNET_malloc (sizeof (struct Request) + addr_len);
+  request->lsock = lsock;
+  request->packet = packet;
+  request->addr = &request[1];
+  request->addr_len = addr_len;
+  memcpy (&request[1], addr, addr_len);
+  request->timeout_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT,
+                                                       &do_timeout,
+                                                       request);
+  // FIXME: extract name and type from 'request->packet'
+  const char *name = "foo";
+  enum GNUNET_GNS_RecordType type = GNUNET_GNS_RECORD_A;
+  request->lookup = GNUNET_GNS_lookup (gns,
+                                      name,
+                                      type,
+                                      GNUNET_NO,
+                                      NULL,
+                                      &result_processor,
+                                      request);
+}
+
+
+/**
+ * Task to read IPv4 DNS packets.
+ *
+ * @param cls the 'listen_socket4'
+ * @param tc scheduler context
+ */ 
+static void
+read_dns4 (void *cls,
+          const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  struct sockaddr_in v4;
+  socklen_t addrlen;
+  ssize_t size;
+
+  GNUNET_assert (listen_socket4 == cls);
+  t4 = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
+                                     listen_socket4,
+                                     &read_dns4,
+                                     listen_socket4);
+  if (0 == (GNUNET_SCHEDULER_REASON_READ_READY & tc->reason))
+    return; /* shutdown? */
+  size = GNUNET_NETWORK_socket_recvfrom_amount (listen_socket4);
+  if (0 > size)
+    {
+      GNUNET_break (0);
+      return; /* read error!? */
+    }
+  {
+    char buf[size];
+    
+    addrlen = sizeof (v4);
+    GNUNET_break (size == 
+                 GNUNET_NETWORK_socket_recvfrom (listen_socket4,
+                                                 buf,
+                                                 size,
+                                                 (struct sockaddr *) &v4,
+                                                 &addrlen));
+    handle_request (listen_socket4, &v4, addrlen,
+                   buf, size);
+  }
+}
+
+
+/**
+ * Task to read IPv6 DNS packets.
+ *
+ * @param cls the 'listen_socket6'
+ * @param tc scheduler context
+ */ 
+static void
+read_dns6 (void *cls,
+          const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  struct sockaddr_in6 v6;
+  socklen_t addrlen;
+  ssize_t size;
+
+  GNUNET_assert (listen_socket6 == cls);
+  t6 = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
+                                     listen_socket6,
+                                     &read_dns6,
+                                     listen_socket6);
+  if (0 == (GNUNET_SCHEDULER_REASON_READ_READY & tc->reason))
+    return; /* shutdown? */
+  size = GNUNET_NETWORK_socket_recvfrom_amount (listen_socket6);
+  if (0 > size)
+    {
+      GNUNET_break (0);
+      return; /* read error!? */
+    }
+  {
+    char buf[size];
+    
+    addrlen = sizeof (v6);
+    GNUNET_break (size == 
+                 GNUNET_NETWORK_socket_recvfrom (listen_socket6,
+                                                 buf,
+                                                 size,
+                                                 (struct sockaddr *) &v6,
+                                                 &addrlen));
+    handle_request (listen_socket6, &v6, addrlen,
+                   buf, size);
+  }
+}
+
+
+/**
  * Main function that will be run.
  *
  * @param cls closure
@@ -66,6 +353,69 @@
 run (void *cls, char *const *args, const char *cfgfile,
      const struct GNUNET_CONFIGURATION_Handle *cfg)
 {
+  gns = GNUNET_GNS_connect (cfg);
+  if (NULL == gns)
+    return;
+  listen_socket4 = GNUNET_NETWORK_socket_create (PF_INET,
+                                                SOCK_DGRAM, 
+                                                IPPROTO_UDP);
+  if (NULL != listen_socket4)
+    {
+      struct sockaddr_in v4;
+
+      memset (&v4, 0, sizeof (v4));
+      v4.sin_family = AF_INET;
+#if HAVE_SOCKADDR_IN_SIN_LEN
+      v4.sin_len = sizeof (v4);
+#endif
+      v4.sin_port = htons (53);
+      if (GNUNET_OK !=
+         GNUNET_NETWORK_socket_bind (listen_socket4,
+                                     (struct sockaddr *) &v4,
+                                     sizeof (v4)))
+       {
+         GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "bind");
+         GNUNET_NETWORK_socket_close (listen_socket4);
+         listen_socket4 = NULL;
+       }
+    }
+  listen_socket6 = GNUNET_NETWORK_socket_create (PF_INET6,
+                                               SOCK_DGRAM, 
+                                               IPPROTO_UDP);
+  if (NULL != listen_socket6)
+    {
+      struct sockaddr_in6 v6;
+
+      memset (&v6, 0, sizeof (v6));
+      v6.sin6_family = AF_INET6;
+#if HAVE_SOCKADDR_IN_SIN_LEN
+      v6.sin6_len = sizeof (v6);
+#endif
+      v6.sin6_port = htons (53);
+      if (GNUNET_OK !=
+         GNUNET_NETWORK_socket_bind (listen_socket6,
+                                     (struct sockaddr *) &v6,
+                                     sizeof (v6)))
+       {
+         GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "bind");
+         GNUNET_NETWORK_socket_close (listen_socket6);
+         listen_socket6 = NULL;
+       }
+    }
+  if ( (NULL == listen_socket4) &&
+       (NULL == listen_socket6) )
+    return;
+  if (NULL != listen_socket4)
+    t4 = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
+                                       listen_socket4,
+                                       &read_dns4,
+                                       listen_socket4);
+  if (NULL != listen_socket6)
+    t6 = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
+                                       listen_socket6,
+                                       &read_dns6,
+                                       listen_socket6);
+
   GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
                                &do_shutdown, NULL);
 }




reply via email to

[Prev in Thread] Current Thread [Next in Thread]