tolerate additional IPv4 address now available for gnunet.org
[oweals/gnunet.git] / src / gns / gnunet-service-gns_interceptor.c
index adb09ca7f2463340430b08723aeb98ce15fb9f86..d5a84f6a0da91453aa9a608ce3440de7fde92924 100644 (file)
@@ -1,38 +1,37 @@
 /*
      This file is part of GNUnet.
-     (C) 2009, 2010, 2011 Christian Grothoff (and other contributing authors)
+     Copyright (C) 2009-2013 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., 59 Temple Place - Suite 330,
-     Boston, MA 02111-1307, USA.
+     SPDX-License-Identifier: AGPL3.0-or-later
 */
-
 /**
- *
  * @file gns/gnunet-service-gns_interceptor.c
  * @brief GNUnet GNS interceptor logic
  * @author Martin Schanzenbach
+ * @author Christian Grothoff
  */
 #include "platform.h"
 #include "gnunet_util_lib.h"
-#include "gnunet_transport_service.h"
 #include "gnunet_dns_service.h"
 #include "gnunet_dnsparser_lib.h"
+#include "gnunet-service-gns.h"
 #include "gnunet-service-gns_resolver.h"
+#include "gnunet-service-gns_interceptor.h"
 #include "gns.h"
 
-#define MAX_DNS_LABEL_LENGTH 63
 
 /**
  * Handle to a DNS intercepted
  */
 struct InterceptLookupHandle
 {
-  /* the request handle to reply to */
+
+  /**
+   * We keep these in a DLL.
+   */
+  struct InterceptLookupHandle *next;
+
+  /**
+   * We keep these in a DLL.
+   */
+  struct InterceptLookupHandle *prev;
+
+  /**
+   * the request handle to reply to
+   */
   struct GNUNET_DNS_RequestHandle *request_handle;
-  
-  /* the dns parser packet received */
+
+  /**
+   * the dns parser packet received
+   */
   struct GNUNET_DNSPARSER_Packet *packet;
-  
-  /* the query parsed from the packet */
-  struct GNUNET_DNSPARSER_Query *query;
+
+  /**
+   * Handle for the lookup operation.
+   */
+  struct GNS_ResolverHandle *lookup;
+
 };
 
 
@@ -57,19 +74,15 @@ struct InterceptLookupHandle
 static struct GNUNET_DNS_Handle *dns_handle;
 
 /**
- * The root zone for this interceptor
+ * Head of the DLL.
  */
-static struct GNUNET_CRYPTO_ShortHashCode our_zone;
+static struct InterceptLookupHandle *ilh_head;
 
 /**
- * Our priv key
+ * Tail of the DLL.
  */
-static struct GNUNET_CRYPTO_RsaPrivateKey *our_key;
+static struct InterceptLookupHandle *ilh_tail;
 
-/**
- * Default timeout
- */
-static struct GNUNET_TIME_Relative default_lookup_timeout;
 
 /**
  * Reply to dns request with the result from our lookup.
@@ -79,316 +92,307 @@ static struct GNUNET_TIME_Relative default_lookup_timeout;
  * @param rd the record data
  */
 static void
-reply_to_dns(void* cls, uint32_t rd_count,
-             const struct GNUNET_NAMESTORE_RecordData *rd)
+reply_to_dns (void *cls, uint32_t rd_count,
+             const struct GNUNET_GNSRECORD_Data *rd)
 {
-  int i;
+  struct InterceptLookupHandle *ilh = cls;
+  struct GNUNET_DNSPARSER_Packet *packet = ilh->packet;
+  struct GNUNET_DNSPARSER_Query *query = &packet->queries[0];
+  uint32_t i;
   size_t len;
   int ret;
   char *buf;
-  struct InterceptLookupHandle* ilh = (struct InterceptLookupHandle*)cls;
-  struct GNUNET_DNSPARSER_Packet *packet = ilh->packet;
-  unsigned int num_answers = 0;
-  
-  
-  /**
-   * Put records in the DNS packet and modify it
-   * to a response
-   */
+  unsigned int num_answers;
+  unsigned int skip_answers;
+  unsigned int skip_additional;
+  size_t off = 0;
+
+  /* Put records in the DNS packet */
+  num_answers = 0;
   for (i=0; i < rd_count; i++)
-  {
-    if (rd[i].record_type == ilh->query->type)
+    if (rd[i].record_type == query->type)
       num_answers++;
-  }
-
-  struct GNUNET_DNSPARSER_Record answer_records[num_answers];
-  struct GNUNET_DNSPARSER_Record additional_records[rd_count-(num_answers)];
-  packet->answers = answer_records;
-  packet->additional_records = additional_records;
+  skip_answers = 0;
+  skip_additional = 0;
 
-  for (i=0; i < rd_count; i++)
   {
-    GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-               "Adding type %d to DNS response\n", rd[i].record_type);
-    GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Name: %s\n", ilh->query->name);
-    GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Record %d/%d\n", i+1, rd_count);
-    GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Record len %d\n", rd[i].data_size);
-    
-    if (rd[i].record_type == ilh->query->type)
+    struct GNUNET_DNSPARSER_Record answer_records[num_answers];
+    struct GNUNET_DNSPARSER_Record additional_records[rd_count - num_answers];
+
+    packet->answers = answer_records;
+    packet->additional_records = additional_records;
+    /* FIXME: need to handle #GNUNET_GNSRECORD_RF_SHADOW_RECORD option
+       (by ignoring records where this flag is set if there is any
+       other record of that type in the result set) */
+    for (i=0; i < rd_count; i++)
     {
-      answer_records[i].name = ilh->query->name;
-      answer_records[i].type = rd[i].record_type;
-      switch(rd[i].record_type)
+      if (rd[i].record_type == query->type)
       {
-       case GNUNET_GNS_RECORD_TYPE_NS:
-       case GNUNET_GNS_RECORD_TYPE_CNAME:
-       case GNUNET_GNS_RECORD_TYPE_PTR:
-         answer_records[i].data.hostname = (char*)rd[i].data;
-         break;
-       case GNUNET_GNS_RECORD_TYPE_SOA:
-         answer_records[i].data.soa =
-           (struct GNUNET_DNSPARSER_SoaRecord *)rd[i].data;
-         break;
-       case GNUNET_GNS_RECORD_MX:
-         answer_records[i].data.mx =
-           (struct GNUNET_DNSPARSER_MxRecord *)rd[i].data;
-         break;
-       default:
-        answer_records[i].data.raw.data_len = rd[i].data_size;
-        answer_records[i].data.raw.data = (char*)rd[i].data;
+       answer_records[i - skip_answers].name = query->name;
+       answer_records[i - skip_answers].type = rd[i].record_type;
+       switch(rd[i].record_type)
+       {
+       case GNUNET_DNSPARSER_TYPE_NS:
+       case GNUNET_DNSPARSER_TYPE_CNAME:
+       case GNUNET_DNSPARSER_TYPE_PTR:
+         answer_records[i - skip_answers].data.hostname
+           = GNUNET_DNSPARSER_parse_name (rd[i].data,
+                                          rd[i].data_size,
+                                          &off);
+         if ( (off != rd[i].data_size) ||
+              (NULL == answer_records[i].data.hostname) )
+         {
+           GNUNET_break_op (0);
+           skip_answers++;
+         }
+         break;
+       case GNUNET_DNSPARSER_TYPE_SOA:
+         answer_records[i - skip_answers].data.soa
+           = GNUNET_DNSPARSER_parse_soa (rd[i].data,
+                                         rd[i].data_size,
+                                         &off);
+         if ( (off != rd[i].data_size) ||
+              (NULL == answer_records[i].data.soa) )
+         {
+           GNUNET_break_op (0);
+           skip_answers++;
+         }
+         break;
+       case GNUNET_DNSPARSER_TYPE_SRV:
+         /* FIXME: SRV is not yet supported */
+         skip_answers++;
+         break;
+       case GNUNET_DNSPARSER_TYPE_MX:
+         answer_records[i - skip_answers].data.mx
+           = GNUNET_DNSPARSER_parse_mx (rd[i].data,
+                                        rd[i].data_size,
+                                        &off);
+         if ( (off != rd[i].data_size) ||
+              (NULL == answer_records[i].data.hostname) )
+         {
+           GNUNET_break_op (0);
+           skip_answers++;
+         }
+         break;
+       default:
+         answer_records[i - skip_answers].data.raw.data_len = rd[i].data_size;
+         answer_records[i - skip_answers].data.raw.data = (char*)rd[i].data;
+         break;
+       }
+       GNUNET_break (0 == (rd[i - skip_answers].flags & GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION));
+       answer_records[i - skip_answers].expiration_time.abs_value_us = rd[i].expiration_time;
+       answer_records[i - skip_answers].dns_traffic_class = GNUNET_TUN_DNS_CLASS_INTERNET;
+      }
+      else
+      {
+       additional_records[i - skip_additional].name = query->name;
+       additional_records[i - skip_additional].type = rd[i].record_type;
+       switch(rd[i].record_type)
+       {
+       case GNUNET_DNSPARSER_TYPE_NS:
+       case GNUNET_DNSPARSER_TYPE_CNAME:
+       case GNUNET_DNSPARSER_TYPE_PTR:
+         additional_records[i - skip_additional].data.hostname
+           = GNUNET_DNSPARSER_parse_name (rd[i].data,
+                                          rd[i].data_size,
+                                          &off);
+         if ( (off != rd[i].data_size) ||
+              (NULL == additional_records[i].data.hostname) )
+         {
+           GNUNET_break_op (0);
+           skip_additional++;
+         }
+         break;
+       case GNUNET_DNSPARSER_TYPE_SOA:
+         additional_records[i - skip_additional].data.soa
+           = GNUNET_DNSPARSER_parse_soa (rd[i].data,
+                                         rd[i].data_size,
+                                         &off);
+         if ( (off != rd[i].data_size) ||
+              (NULL == additional_records[i].data.hostname) )
+         {
+           GNUNET_break_op (0);
+           skip_additional++;
+         }
+         break;
+       case GNUNET_DNSPARSER_TYPE_MX:
+         additional_records[i - skip_additional].data.mx
+           = GNUNET_DNSPARSER_parse_mx (rd[i].data,
+                                        rd[i].data_size,
+                                        &off);
+         if ( (off != rd[i].data_size) ||
+              (NULL == additional_records[i].data.hostname) )
+         {
+           GNUNET_break_op (0);
+           skip_additional++;
+         }
+         break;
+       case GNUNET_DNSPARSER_TYPE_SRV:
+         /* FIXME: SRV is not yet supported */
+         skip_answers++;
+         break;
+       default:
+         additional_records[i - skip_additional].data.raw.data_len = rd[i].data_size;
+         additional_records[i - skip_additional].data.raw.data = (char*)rd[i].data;
+         break;
+       }
+       GNUNET_break (0 == (rd[i - skip_additional].flags & GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION));
+       additional_records[i - skip_additional].expiration_time.abs_value_us = rd[i].expiration_time;
+       additional_records[i - skip_additional].dns_traffic_class = GNUNET_TUN_DNS_CLASS_INTERNET;
       }
-      answer_records[i].expiration_time = rd[i].expiration;
-      answer_records[i].class = GNUNET_DNSPARSER_CLASS_INTERNET;//hmmn
     }
+    packet->num_answers = num_answers - skip_answers;
+    packet->num_additional_records = rd_count - num_answers - skip_additional;
+    packet->flags.authoritative_answer = 1;
+    if (NULL == rd)
+      packet->flags.return_code = GNUNET_TUN_DNS_RETURN_CODE_NAME_ERROR;
     else
+      packet->flags.return_code = GNUNET_TUN_DNS_RETURN_CODE_NO_ERROR;
+    packet->flags.query_or_response = 1;
+    ret = GNUNET_DNSPARSER_pack (packet,
+                                1024, /* maximum allowed size for DNS reply */
+                                &buf,
+                                &len);
+    if (GNUNET_OK != ret)
     {
-      additional_records[i].name = ilh->query->name;
-      additional_records[i].type = rd[i].record_type;
-      switch(rd[i].record_type)
-      {
-       case GNUNET_GNS_RECORD_TYPE_NS:
-       case GNUNET_GNS_RECORD_TYPE_CNAME:
-       case GNUNET_GNS_RECORD_TYPE_PTR:
-         additional_records[i].data.hostname = (char*)rd[i].data;
-         break;
-       case GNUNET_GNS_RECORD_TYPE_SOA:
-         additional_records[i].data.soa =
-           (struct GNUNET_DNSPARSER_SoaRecord *)rd[i].data;
-         break;
-       case GNUNET_GNS_RECORD_MX:
-         additional_records[i].data.mx =
-           (struct GNUNET_DNSPARSER_MxRecord *)rd[i].data;
-         break;
-       default:
-        additional_records[i].data.raw.data_len = rd[i].data_size;
-        additional_records[i].data.raw.data = (char*)rd[i].data;
-      }
-      additional_records[i].expiration_time = rd[i].expiration;
-      additional_records[i].class = GNUNET_DNSPARSER_CLASS_INTERNET;//hmmn
+      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                 _("Error converting GNS response to DNS response!\n"));
+      if (GNUNET_NO == ret)
+        GNUNET_free (buf);
     }
+    else
+    {
+      GNUNET_DNS_request_answer (ilh->request_handle,
+                                len,
+                                buf);
+      GNUNET_free (buf);
+    }
+    packet->num_answers = 0;
+    packet->answers = NULL;
+    packet->num_additional_records = 0;
+    packet->additional_records = NULL;
+    GNUNET_DNSPARSER_free_packet (packet);
   }
-  
-  packet->num_answers = num_answers;
-  packet->num_additional_records = rd_count-(num_answers);
-  
-  packet->flags.authoritative_answer = 1;
-
-  if (rd == NULL)
-    packet->flags.return_code = GNUNET_DNSPARSER_RETURN_CODE_NAME_ERROR;
-  else
-    packet->flags.return_code = GNUNET_DNSPARSER_RETURN_CODE_NO_ERROR;
-  
-  packet->flags.query_or_response = 1;
-
-  
-  /**
-   * Reply to DNS
-   */
-  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-             "Building DNS response\n");
-  ret = GNUNET_DNSPARSER_pack (packet,
-                               1024, /* FIXME magic from dns redirector */
-                               &buf,
-                               &len);
-  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-             "Built DNS response! (ret=%d,len=%d)\n", ret, len);
-  if (ret == GNUNET_OK)
-  {
-    GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-               "Answering DNS request\n");
-    GNUNET_DNS_request_answer(ilh->request_handle,
-                              len,
-                              buf);
-
-    GNUNET_free(buf);
-    GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Answered DNS request\n");
-  }
-  else
-  {
-    GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
-               "Error building DNS response! (ret=%d)", ret);
-  }
-  
-  packet->num_answers = 0;
-  packet->answers = NULL;
-  packet->num_additional_records = 0;
-  packet->additional_records = NULL;
-  GNUNET_DNSPARSER_free_packet(packet);
-  GNUNET_free(ilh);
-}
-
-
-/**
- * Entry point for name resolution
- * Setup a new query and try to resolve
- *
- * @param request the request handle of the DNS request from a client
- * @param p the DNS query packet we received
- * @param q the DNS query we received parsed from p
- */
-static void
-start_resolution_for_dns(struct GNUNET_DNS_RequestHandle *request,
-                          struct GNUNET_DNSPARSER_Packet *p,
-                          struct GNUNET_DNSPARSER_Query *q)
-{
-  struct InterceptLookupHandle* ilh;
-  
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Starting resolution for %s (type=%d)!\n",
-              q->name, q->type);
-  
-  ilh = GNUNET_malloc(sizeof(struct InterceptLookupHandle));
-  ilh->packet = p;
-  ilh->query = q;
-  ilh->request_handle = request;
-  
-  /* Start resolution in our zone */
-  gns_resolver_lookup_record(our_zone, our_zone, q->type, q->name,
-                             our_key,
-                             default_lookup_timeout,
-                             &reply_to_dns, ilh);
+  GNUNET_CONTAINER_DLL_remove (ilh_head, ilh_tail, ilh);
+  GNUNET_free (ilh);
 }
 
 
-
 /**
- * The DNS request handler
- * Called for every incoming DNS request.
+ * The DNS request handler.  Called for every incoming DNS request.
  *
- * @param cls closure
+ * @param cls closure, unused
  * @param rh request handle to user for reply
- * @param request_length number of bytes in request
- * @param request udp payload of the DNS request
+ * @param request_length number of bytes in @a request
+ * @param request UDP payload of the DNS request
  */
 static void
-handle_dns_request(void *cls,
-                   struct GNUNET_DNS_RequestHandle *rh,
-                   size_t request_length,
-                   const char *request)
+handle_dns_request (void *cls,
+                   struct GNUNET_DNS_RequestHandle *rh,
+                   size_t request_length,
+                   const char *request)
 {
   struct GNUNET_DNSPARSER_Packet *p;
+  struct InterceptLookupHandle *ilh;
+  struct GNUNET_CRYPTO_EcdsaPublicKey zone;
 
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Hijacked a DNS request...processing\n");
-  p = GNUNET_DNSPARSER_parse (request, request_length);
-  
-  if (NULL == p)
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+             "Hijacked a DNS request. Processing.\n");
+  if (NULL == (p = GNUNET_DNSPARSER_parse (request, request_length)))
   {
     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                "Received malformed DNS packet, leaving it untouched\n");
+                "Received malformed DNS packet, leaving it untouched.\n");
     GNUNET_DNS_request_forward (rh);
     GNUNET_DNSPARSER_free_packet (p);
     return;
   }
-  
-  /**
-   * Check tld and decide if we or
-   * legacy dns is responsible
-   *
-   * FIXME now in theory there could be more than 1 query in the request
-   * but if this is case we get into trouble:
-   * either we query the GNS or the DNS. We cannot do both!
-   * So I suggest to either only allow a single query per request or
-   * only allow GNS or DNS requests.
-   * The way it is implemented here now is buggy and will lead to erratic
-   * behaviour (if multiple queries are present).
-   */
-  if (p->num_queries == 0)
+
+  /* Check TLD and decide if we or legacy dns is responsible */
+  if (1 != p->num_queries)
   {
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "No Queries in DNS packet... forwarding\n");
+                "Not exactly one query in DNS packet. Forwarding untouched.\n");
     GNUNET_DNS_request_forward (rh);
     GNUNET_DNSPARSER_free_packet(p);
     return;
   }
 
-  if (p->num_queries > 1)
-  {
-    /* Note: We could also look for .gnunet */
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                ">1 queriy in DNS packet... odd. We only process #1\n");
-  }
-
-  
-  /**
-   * Check for .gnunet/.zkey
-   */
-  
-  if ((is_gnunet_tld(p->queries[0].name) == GNUNET_YES) ||
-      (is_zkey_tld(p->queries[0].name) == GNUNET_YES) ||
-      (strcmp(p->queries[0].name, GNUNET_GNS_TLD) == 0))
+  /* Check for GNS TLDs. */
+  if (GNUNET_YES ==
+      GNS_find_tld (GNS_get_tld (p->queries[0].name),
+                    &zone))
   {
-    start_resolution_for_dns(rh, p, p->queries);
-  }
-  else
-  {
-    /**
-     * This request does not concern us. Forward to real DNS.
-     */
-    GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-               "Request for %s is forwarded to DNS\n", p->queries[0].name);
-    GNUNET_DNS_request_forward (rh);
-    GNUNET_DNSPARSER_free_packet (p);
+    /* Start resolution in GNS */
+    ilh = GNUNET_new (struct InterceptLookupHandle);
+    GNUNET_CONTAINER_DLL_insert (ilh_head,
+                                 ilh_tail,
+                                 ilh);
+    ilh->packet = p;
+    ilh->request_handle = rh;
+    ilh->lookup = GNS_resolver_lookup (&zone,
+                                      p->queries[0].type,
+                                      p->queries[0].name,
+                                      GNUNET_NO,
+                                      &reply_to_dns, ilh);
+    return;
   }
-
+  /* This request does not concern us. Forward to real DNS. */
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+             "Request for `%s' is forwarded to DNS untouched.\n",
+             p->queries[0].name);
+  GNUNET_DNS_request_forward (rh);
+  GNUNET_DNSPARSER_free_packet (p);
 }
 
 
 /**
  * Initialized the interceptor
  *
- * @param zone the zone to work in
- * @param key the prov key of the zone (can be null, needed for caching)
  * @param c the configuration
- * @return GNUNET_OK on success
+ * @return #GNUNET_OK on success
  */
 int
-gns_interceptor_init(struct GNUNET_CRYPTO_ShortHashCode zone,
-                     struct GNUNET_CRYPTO_RsaPrivateKey *key,
-                     const struct GNUNET_CONFIGURATION_Handle *c)
+GNS_interceptor_init (const struct GNUNET_CONFIGURATION_Handle *c)
 {
-  unsigned long long default_lookup_timeout_secs = 0;
-
-  GNUNET_log(GNUNET_ERROR_TYPE_INFO,
-             "DNS hijacking enabled... connecting to service.\n");
-
-  our_zone = zone;
-  our_key = key;
-  /**
-   * Do gnunet dns init here
-   */
-  dns_handle = GNUNET_DNS_connect(c,
-                                  GNUNET_DNS_FLAG_PRE_RESOLUTION,
-                                  &handle_dns_request, /* rh */
-                                  NULL); /* Closure */
-
-  if (GNUNET_OK ==
-      GNUNET_CONFIGURATION_get_value_number(c, "gns",
-                                            "DEFAULT_LOOKUP_TIMEOUT",
-                                            &default_lookup_timeout_secs))
-  {
-    default_lookup_timeout = GNUNET_TIME_relative_multiply(
-                                                  GNUNET_TIME_UNIT_SECONDS,
-                                                  default_lookup_timeout_secs);
-  }
-
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+             "DNS hijacking enabled. Connecting to DNS service.\n");
+  dns_handle = GNUNET_DNS_connect (c,
+                                  GNUNET_DNS_FLAG_PRE_RESOLUTION,
+                                  &handle_dns_request,
+                                  NULL);
   if (NULL == dns_handle)
   {
-    GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
-             "Failed to connect to the dnsservice!\n");
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+               _("Failed to connect to the DNS service!\n"));
     return GNUNET_SYSERR;
   }
-
   return GNUNET_YES;
 }
 
+
 /**
  * Disconnect from interceptor
  */
 void
-gns_interceptor_stop(void)
+GNS_interceptor_done ()
 {
-  if (dns_handle)
-    GNUNET_DNS_disconnect(dns_handle);
+  struct InterceptLookupHandle *ilh;
+
+  while (NULL != (ilh = ilh_head))
+  {
+    GNUNET_CONTAINER_DLL_remove (ilh_head,
+                                 ilh_tail,
+                                 ilh);
+    GNS_resolver_lookup_cancel (ilh->lookup);
+    GNUNET_DNS_request_drop (ilh->request_handle);
+    GNUNET_DNSPARSER_free_packet (ilh->packet);
+    GNUNET_free (ilh);
+  }
+  if (NULL != dns_handle)
+  {
+    GNUNET_DNS_disconnect (dns_handle);
+    dns_handle = NULL;
+  }
 }
 
-/* end of gns_interceptor.c */
+/* end of gnunet-service-gns_interceptor.c */