gnunet-svn
[Top][All Lists]
Advanced

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

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


From: gnunet
Subject: [GNUnet-SVN] r30575 - gnunet/src/gns
Date: Wed, 6 Nov 2013 21:30:18 +0100

Author: grothoff
Date: 2013-11-06 21:30:18 +0100 (Wed, 06 Nov 2013)
New Revision: 30575

Modified:
   gnunet/src/gns/gnunet-service-gns_resolver.c
   gnunet/src/gns/test_gns_ns_lookup.sh
Log:
-improve testcase to actually test #3093

Modified: gnunet/src/gns/gnunet-service-gns_resolver.c
===================================================================
--- gnunet/src/gns/gnunet-service-gns_resolver.c        2013-11-06 17:46:36 UTC 
(rev 30574)
+++ gnunet/src/gns/gnunet-service-gns_resolver.c        2013-11-06 20:30:18 UTC 
(rev 30575)
@@ -214,6 +214,30 @@
 
 
 /**
+ * Information we keep during the resolution of an
+ * IP address for a DNS server while handling a
+ * GNS2DNS record.
+ */
+struct Gns2DnsContext
+{
+
+  /**
+   * DNS domain in which the resolution will continue
+   * (first part of the GNS2DNS record).
+   */
+  char *ns;
+
+  /**
+   * Handle for the resolution of the IP part of the
+   * GNS2DNS record.  Will return to us the addresses
+   * of the DNS resolver to use.
+   */
+  struct GNS_ResolverHandle *rh;
+
+};
+
+
+/**
  * Handle to a currenty pending resolution.  On result (positive or
  * negative) the #GNS_ResultProcessor is called.
  */
@@ -241,11 +265,17 @@
   GNS_ResultProcessor proc;
 
   /**
-   * closure passed to proc
+   * closure passed to @e proc
    */
   void* proc_cls;
 
   /**
+   * Handle used during GNS2DNS resolution for looking up the
+   * IP address of the DNS server.
+   */
+  struct Gns2DnsContext *g2dc;
+
+  /**
    * Handle for DHT lookups. should be NULL if no lookups are in progress
    */
   struct GNUNET_DHT_GetHandle *get_handle;
@@ -1145,6 +1175,135 @@
 
 
 /**
+ * We've resolved the IP address for the DNS resolver to use
+ * after encountering a GNS2DNS record.
+ *
+ * TODO: Right now we only foward the request to ONE DNS resolver,
+ * even if we get multiple IP addresses back; a correct implementation
+ * should try all DNS resolvers.
+ *
+ * @param cls the `struct GNS_ResolverHandle` where we encountered
+ *            the GNS2DNS record
+ * @param rd_count number of records in @a rd
+ * @param rd addresses for the DNS resolver  (presumably)
+ */
+static void
+handle_gns2dns_result (void *cls,
+                       unsigned int rd_count,
+                       const struct GNUNET_GNSRECORD_Data *rd)
+{
+  struct GNS_ResolverHandle *rh = cls;
+  struct AuthorityChain *ac;
+  unsigned int j;
+  struct sockaddr *sa;
+  struct sockaddr_in v4;
+  struct sockaddr_in6 v6;
+  size_t sa_len;
+
+  /* find suitable A/AAAA record */
+  rh->g2dc->rh = NULL;
+  sa = NULL;
+  sa_len = 0;
+  for (j=0;j<rd_count;j++)
+  {
+    switch (rd[j].record_type)
+    {
+    case GNUNET_DNSPARSER_TYPE_A:
+      if (sizeof (struct in_addr) != rd[j].data_size)
+      {
+        GNUNET_break_op (0);
+        rh->proc (rh->proc_cls, 0, NULL);
+        GNS_resolver_lookup_cancel (rh);
+        return;
+      }
+      /* FIXME: might want to check if we support IPv4 here,
+         and otherwise skip this one and hope we find another */
+      memset (&v4, 0, sizeof (v4));
+      sa_len = sizeof (v4);
+      v4.sin_family = AF_INET;
+      v4.sin_port = htons (53);
+#if HAVE_SOCKADDR_IN_SIN_LEN
+      v4.sin_len = (u_char) sa_len;
+#endif
+      memcpy (&v4.sin_addr,
+              rd[j].data,
+              sizeof (struct in_addr));
+      sa = (struct sockaddr *) &v4;
+      break;
+    case GNUNET_DNSPARSER_TYPE_AAAA:
+      if (sizeof (struct in6_addr) != rd[j].data_size)
+      {
+        GNUNET_break_op (0);
+        rh->proc (rh->proc_cls, 0, NULL);
+        GNS_resolver_lookup_cancel (rh);
+        return;
+      }
+      /* FIXME: might want to check if we support IPv6 here,
+         and otherwise skip this one and hope we find another */
+      memset (&v6, 0, sizeof (v6));
+      sa_len = sizeof (v6);
+      v6.sin6_family = AF_INET6;
+      v6.sin6_port = htons (53);
+#if HAVE_SOCKADDR_IN_SIN_LEN
+      v6.sin6_len = (u_char) sa_len;
+#endif
+      memcpy (&v6.sin6_addr,
+              rd[j].data,
+              sizeof (struct in6_addr));
+      sa = (struct sockaddr *) &v6;
+      break;
+    default:
+      break;
+    }
+    if (NULL != sa)
+      break;
+  }
+  if (NULL == sa)
+  {
+    /* we cannot continue; NS without A/AAAA */
+    rh->proc (rh->proc_cls, 0, NULL);
+    GNS_resolver_lookup_cancel (rh);
+    return;
+  }
+  /* expand authority chain */
+  ac = GNUNET_new (struct AuthorityChain);
+  ac->rh = rh;
+  strcpy (ac->authority_info.dns_authority.name,
+          rh->g2dc->ns);
+  memcpy (&ac->authority_info.dns_authority.dns_ip,
+          sa,
+          sa_len);
+  /* for DNS recursion, the label is the full DNS name,
+     created from the remainder of the GNS name and the
+     name in the NS record */
+  GNUNET_asprintf (&ac->label,
+                   "%.*s%s%s",
+                   (int) rh->name_resolution_pos,
+                   rh->name,
+                   (0 != rh->name_resolution_pos) ? "." : "",
+                   rh->g2dc->ns);
+  GNUNET_free (rh->g2dc->ns);
+  GNUNET_free (rh->g2dc);
+  rh->g2dc = NULL;
+  GNUNET_CONTAINER_DLL_insert_tail (rh->ac_head,
+                                    rh->ac_tail,
+                                    ac);
+  if (strlen (ac->label) > GNUNET_DNSPARSER_MAX_NAME_LENGTH)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                _("GNS lookup resulted in DNS name that is too long (`%s')\n"),
+                ac->label);
+    rh->proc (rh->proc_cls, 0, NULL);
+    GNS_resolver_lookup_cancel (rh);
+    return;
+  }
+  /* recurse */
+  rh->task_id = GNUNET_SCHEDULER_add_now (&recursive_resolution,
+                                          rh);
+}
+
+
+/**
  * Process a records that were decrypted from a block.
  *
  * @param cls closure with the `struct GNS_ResolverHandle`
@@ -1159,11 +1318,6 @@
   struct GNS_ResolverHandle *rh = cls;
   struct AuthorityChain *ac;
   unsigned int i;
-  unsigned int j;
-  struct sockaddr *sa;
-  struct sockaddr_in v4;
-  struct sockaddr_in6 v6;
-  size_t sa_len;
   char *cname;
   struct VpnContext *vpn_ctx;
   const struct GNUNET_TUN_GnsVpnRecord *vpn;
@@ -1532,126 +1686,67 @@
       return;
     case GNUNET_GNSRECORD_TYPE_GNS2DNS:
       {
-       char *ns;
        /* resolution continues within DNS */
-       if (GNUNET_DNSPARSER_MAX_NAME_LENGTH < rd[i].data_size)
+        struct Gns2DnsContext *g2dc;
+        char *ip;
+        char *at;
+        char *cp;
+        char *ns;
+
+        cp = GNUNET_strndup (rd[i].data,
+                             rd[i].data_size);
+        at = strchr (cp, '@');
+       if (NULL == at)
        {
          GNUNET_break_op (0);
          rh->proc (rh->proc_cls, 0, NULL);
          GNS_resolver_lookup_cancel (rh);
          return;
        }
-       /* find associated A/AAAA record */
-       sa = NULL;
-       sa_len = 0;
-       for (j=0;j<rd_count;j++)
-       {
-         switch (rd[j].record_type)
-           {
-           case GNUNET_DNSPARSER_TYPE_A:
-             if (sizeof (struct in_addr) != rd[j].data_size)
-             {
-               GNUNET_break_op (0);
-               rh->proc (rh->proc_cls, 0, NULL);
-               GNS_resolver_lookup_cancel (rh);
-               return;
-             }
-             /* FIXME: might want to check if we support IPv4 here,
-                and otherwise skip this one and hope we find another */
-             memset (&v4, 0, sizeof (v4));
-             sa_len = sizeof (v4);
-             v4.sin_family = AF_INET;
-             v4.sin_port = htons (53);
-#if HAVE_SOCKADDR_IN_SIN_LEN
-             v4.sin_len = (u_char) sa_len;
-#endif
-             memcpy (&v4.sin_addr,
-                     rd[j].data,
-                     sizeof (struct in_addr));
-             sa = (struct sockaddr *) &v4;
-             break;
-           case GNUNET_DNSPARSER_TYPE_AAAA:
-             if (sizeof (struct in6_addr) != rd[j].data_size)
-             {
-               GNUNET_break_op (0);
-               rh->proc (rh->proc_cls, 0, NULL);
-               GNS_resolver_lookup_cancel (rh);
-               return;
-             }
-             /* FIXME: might want to check if we support IPv6 here,
-                and otherwise skip this one and hope we find another */
-             memset (&v6, 0, sizeof (v6));
-             sa_len = sizeof (v6);
-             v6.sin6_family = AF_INET6;
-             v6.sin6_port = htons (53);
-#if HAVE_SOCKADDR_IN_SIN_LEN
-             v6.sin6_len = (u_char) sa_len;
-#endif
-             memcpy (&v6.sin6_addr,
-                     rd[j].data,
-                     sizeof (struct in6_addr));
-             sa = (struct sockaddr *) &v6;
-             break;
-           default:
-             break;
-           }
-         if (NULL != sa)
-           break;
-       }
-       if (NULL == sa)
-       {
-         /* we cannot continue; NS without A/AAAA */
-         rh->proc (rh->proc_cls, 0, NULL);
-         GNS_resolver_lookup_cancel (rh);
-         return;
-       }
-       /* expand authority chain */
-       ac = GNUNET_new (struct AuthorityChain);
-       ac->rh = rh;
-       off = 0;
-       ns = GNUNET_DNSPARSER_parse_name (rd[i].data,
-                                         rd[i].data_size,
-                                         &off);
-       if ( (NULL == ns) ||
-            (off != rd[i].data_size) )
-       {
-         GNUNET_break_op (0); /* record not well-formed */
-         rh->proc (rh->proc_cls, 0, NULL);
-         GNS_resolver_lookup_cancel (rh);
-         GNUNET_free_non_null (ns);
-         GNUNET_free (ac);
-         return;
-       }
-       strcpy (ac->authority_info.dns_authority.name,
-               ns);
-       memcpy (&ac->authority_info.dns_authority.dns_ip,
-               sa,
-               sa_len);
-       /* for DNS recursion, the label is the full DNS name,
-          created from the remainder of the GNS name and the
-          name in the NS record */
-       GNUNET_asprintf (&ac->label,
-                        "%.*s%s%s",
-                        (int) rh->name_resolution_pos,
-                        rh->name,
-                        (0 != rh->name_resolution_pos) ? "." : "",
-                        ns);
-       GNUNET_free (ns);
-       GNUNET_CONTAINER_DLL_insert_tail (rh->ac_head,
-                                         rh->ac_tail,
-                                         ac);
-       if (strlen (ac->label) > GNUNET_DNSPARSER_MAX_NAME_LENGTH)
-       {
-         GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                     _("GNS lookup resulted in DNS name that is too long 
(`%s')\n"),
-                     ac->label);
-         rh->proc (rh->proc_cls, 0, NULL);
-         GNS_resolver_lookup_cancel (rh);
-         return;
-       }
-       /* recurse */
-       rh->task_id = GNUNET_SCHEDULER_add_now (&recursive_resolution,
-                                               rh);
+        *at = '\0';
+        off = 0;
+        ns = GNUNET_DNSPARSER_parse_name (cp,
+                                          strlen (cp),
+                                          &off);
+        if ( (NULL == ns) ||
+             (off != strlen (cp)) )
+        {
+          GNUNET_break_op (0); /* record not well-formed */
+          rh->proc (rh->proc_cls, 0, NULL);
+          GNS_resolver_lookup_cancel (rh);
+          GNUNET_free (cp);
+          return;
+        }
+        off++; /* skip '@' */
+        ip = GNUNET_DNSPARSER_parse_name (cp,
+                                          strlen (at + 1),
+                                          &off);
+        if ( (NULL == ip) ||
+             (off != rd[i].data_size) )
+        {
+          GNUNET_break_op (0); /* record not well-formed */
+          rh->proc (rh->proc_cls, 0, NULL);
+          GNS_resolver_lookup_cancel (rh);
+          GNUNET_free (ns);
+          GNUNET_free (cp);
+          return;
+        }
+        GNUNET_free (cp);
+        /* resolve 'ip' to determine the IP(s) of the DNS
+           resolver to use */
+        g2dc = GNUNET_new (struct Gns2DnsContext);
+        g2dc->ns = ns;
+        g2dc->rh = GNUNET_new (struct GNS_ResolverHandle);
+        g2dc->rh->authority_zone = rh->ac_tail->authority_info.gns_authority;
+        g2dc->rh->name = ip;
+        g2dc->rh->name_resolution_pos = strlen (ip);
+        g2dc->rh->proc = &handle_gns2dns_result;
+        g2dc->rh->proc_cls = rh;
+        g2dc->rh->record_type = GNUNET_GNSRECORD_TYPE_ANY;
+        g2dc->rh->only_cached = GNUNET_NO;
+        g2dc->rh->loop_limiter = rh->loop_limiter + 1;
+        rh->g2dc = g2dc;
+        start_resolver_lookup (g2dc->rh);
        return;
       }
     case GNUNET_DNSPARSER_TYPE_CNAME:
@@ -2000,7 +2095,41 @@
 {
   struct AuthorityChain *ac;
   char *y;
+  struct in_addr v4;
+  struct in6_addr v6;
 
+  if (1 == inet_pton (AF_INET,
+                      rh->name,
+                      &v4))
+  {
+    /* name is IPv4 address, pretend it's an A record */
+    struct GNUNET_GNSRECORD_Data rd;
+
+    rd.data = &v4;
+    rd.data_size = sizeof (v4);
+    rd.expiration_time = UINT64_MAX;
+    rd.record_type = GNUNET_DNSPARSER_TYPE_A;
+    rd.flags = 0;
+    rh->proc (rh->proc_cls, 1, &rd);
+    GNS_resolver_lookup_cancel (rh);
+    return;
+  }
+  if (1 == inet_pton (AF_INET6,
+                      rh->name,
+                      &v6))
+  {
+    /* name is IPv6 address, pretend it's an AAAA record */
+    struct GNUNET_GNSRECORD_Data rd;
+
+    rd.data = &v6;
+    rd.data_size = sizeof (v6);
+    rd.expiration_time = UINT64_MAX;
+    rd.record_type = GNUNET_DNSPARSER_TYPE_AAAA;
+    rd.flags = 0;
+    rh->proc (rh->proc_cls, 1, &rd);
+    GNS_resolver_lookup_cancel (rh);
+    return;
+  }
   if ( ( (GNUNET_YES == is_canonical (rh->name)) &&
         (0 != strcmp (GNUNET_GNS_TLD, rh->name)) ) ||
        ( (GNUNET_YES != is_gnu_tld (rh->name)) &&
@@ -2143,6 +2272,23 @@
     GNUNET_free (ac->label);
     GNUNET_free (ac);
   }
+  if (NULL != rh->g2dc)
+  {
+    /* rh->g2dc->rh is NOT in the DLL yet, so to enable us
+       using GNS_resolver_lookup_cancel here, we need to
+       add it first... */
+    if (NULL != rh->g2dc->rh)
+    {
+      GNUNET_CONTAINER_DLL_insert (rlh_head,
+                                   rlh_tail,
+                                   rh->g2dc->rh);
+      GNS_resolver_lookup_cancel (rh->g2dc->rh);
+      rh->g2dc->rh = NULL;
+    }
+    GNUNET_free (rh->g2dc->ns);
+    GNUNET_free (rh->g2dc);
+    rh->g2dc = NULL;
+  }
   if (GNUNET_SCHEDULER_NO_TASK != rh->task_id)
   {
     GNUNET_SCHEDULER_cancel (rh->task_id);

Modified: gnunet/src/gns/test_gns_ns_lookup.sh
===================================================================
--- gnunet/src/gns/test_gns_ns_lookup.sh        2013-11-06 17:46:36 UTC (rev 
30574)
+++ gnunet/src/gns/test_gns_ns_lookup.sh        2013-11-06 20:30:18 UTC (rev 
30575)
@@ -1,34 +1,57 @@
 #!/bin/bash
 trap "gnunet-arm -e -c test_gns_lookup.conf" SIGINT
 rm -r `gnunet-config -c test_gns_lookup.conf -s PATHS -o GNUNET_HOME -f`
-TEST_DOMAIN="www.homepage.gnu"
-TEST_DOMAIN_ALT="homepage.gnu"
-TEST_DOMAIN_ALT2="uk.homepage.gnu"
+# IP address of 'uk.gnunet.org'
 TEST_IP_ALT2="81.187.252.184"
+# IP address of 'www.gnunet.org'
 TEST_IP="131.159.74.67"
+# IPv6 address of 'gnunet.org'
 TEST_IP6="2001:4ca0:2001:42:225:90ff:fe6b:d60"
-TEST_IP_GNS2DNS="184.172.157.218"
+# permissive DNS resolver we will use for the test
+TEST_IP_GNS2DNS="8.8.8.8"
+
+# main label used during resolution
 TEST_RECORD_NAME="homepage"
-TEST_RECORD_GNS2DNS="gnunet.org"
+# various names we will use for resolution
+TEST_DOMAIN="www.${TEST_RECORD_NAME}.gnu"
+TEST_DOMAIN_ALT="${TEST_RECORD_NAME}.gnu"
+TEST_DOMAIN_ALT2="uk.${TEST_RECORD_NAME}.gnu"
+
+# helper record for pointing to the DNS resolver
+TEST_RESOLVER_LABEL="resolver"
+# GNS2DNS record value: delegate to DNS domain 'gnunet.org'
+# using the TEST_RESOLVER_LABEL DNS server for resolution
+TEST_RECORD_GNS2DNS="address@hidden"
+
 gnunet-arm -s -c test_gns_lookup.conf
 gnunet-identity -C testego -c test_gns_lookup.conf
-gnunet-namestore -p -z testego -a -n $TEST_RECORD_NAME -t A -V 
$TEST_IP_GNS2DNS -e never -c test_gns_lookup.conf
+
+# set IP address for DNS resolver for resolving in gnunet.org domain
+gnunet-namestore -p -z testego -a -n $TEST_RESOLVER_LABEL -t A -V 
$TEST_IP_GNS2DNS -e never -c test_gns_lookup.conf
+# map 'homepage.gnu' to 'gnunet.org' in DNS
 gnunet-namestore -p -z testego -a -n $TEST_RECORD_NAME -t GNS2DNS -V 
$TEST_RECORD_GNS2DNS -e never -c test_gns_lookup.conf
+
+# lookup 'www.gnunet.org', IPv4
 RES_IP=$(timeout 5 gnunet-gns --raw -z testego -u $TEST_DOMAIN -t A -c 
test_gns_lookup.conf)
+# lookup 'www.gnunet.org', IPv6
 RES_IP6=$(timeout 5 gnunet-gns --raw -z testego -u $TEST_DOMAIN -t AAAA -c 
test_gns_lookup.conf)
+# lookup 'gnunet.org', IPv4
 RES_IP_ALT=$(timeout 5 gnunet-gns --raw -z testego -u $TEST_DOMAIN_ALT -t A -c 
test_gns_lookup.conf)
+# lookup 'uk.gnunet.org', IPv4
 RES_IP_ALT2=$(timeout 5 gnunet-gns --raw -z testego -u $TEST_DOMAIN_ALT2 -t A 
-c test_gns_lookup.conf)
-gnunet-namestore -z testego -d -n www -t A -V $TEST_IP -e never -c 
test_gns_lookup.conf
+
+# clean up
+gnunet-namestore -z testego -d -n $TEST_RESOLVER_LABEL -t A -V 
$TEST_IP_GNS2DNS -e never -c test_gns_lookup.conf
 gnunet-namestore -z testego -d -n $TEST_RECORD_NAME -t GNS2DNS -V 
$TEST_RECORD_GNS2DNS -e never -c test_gns_lookup.conf
 gnunet-identity -D testego -c test_gns_lookup.conf
 gnunet-arm -e -c test_gns_lookup.conf
-
+ret=0
 if [ "$RES_IP" == "$TEST_IP" ]
 then
   echo "PASS: Resolved $TEST_DOMAIN to $RES_IP."
 else
   echo "Failed to resolve to proper IP for $TEST_DOMAIN, got $RES_IP, wanted 
$TEST_IP."
-  exit 1
+  ret=1
 fi
 
 if [ "$RES_IP6" == "$TEST_IP6" ]
@@ -36,7 +59,7 @@
   echo "PASS: Resolved $TEST_DOMAIN to $RES_IP6."
 else
   echo "Failed to resolve to proper IP for $TEST_DOMAIN, got $RES_IP6, wanted 
$TEST_IP6."
-  exit 1
+  ret=1
 fi
 
 if [ "$RES_IP_ALT" == "$TEST_IP" ]
@@ -44,14 +67,14 @@
   echo "PASS: Resolved $TEST_DOMAIN_ALT to $RES_IP_ALT."
 else
   echo "Failed to resolve to proper IP for $TEST_DOMAIN_ALT, got $RES_IP_ALT, 
wanted $TEST_IP."
-  exit 1
+  ret=1
 fi
 
 if [ "$RES_IP_ALT2" == "$TEST_IP_ALT2" ]
 then
   echo "PASS: Resolved $TEST_DOMAIN_ALT2 to $RES_IP_ALT2."
-  exit 0
 else
   echo "Failed to resolve to proper IP for $TEST_DOMAIN_ALT2, got 
$RES_IP_ALT2, wanted $TEST_IP_ALT2."
-  exit 1
+  ret=1
 fi
+exit $ret




reply via email to

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