where applicable, check DNS ID in responses before processing further
authorChristian Grothoff <christian@grothoff.org>
Thu, 5 Apr 2018 14:25:46 +0000 (16:25 +0200)
committerChristian Grothoff <christian@grothoff.org>
Thu, 5 Apr 2018 14:25:46 +0000 (16:25 +0200)
src/dns/dnsstub.c
src/dns/gnunet-service-dns.c
src/exit/gnunet-daemon-exit.c
src/gns/gnunet-dns2gns.c
src/gns/gnunet-service-gns_resolver.c
src/include/gnunet_dns_service.h
src/include/gnunet_dnsparser_lib.h

index 364b6fe28441f752d220455a4742232f7fe6e924..c79502ce9d6ec6f4897bbd269ba4e34d1cfa2cbd 100644 (file)
@@ -235,8 +235,22 @@ get_request_socket (struct GNUNET_DNSSTUB_Context *ctx,
   struct GNUNET_DNSSTUB_RequestSocket *rs;
   struct GNUNET_NETWORK_FDSet *rset;
 
-  rs = &ctx->sockets[GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE,
-                                              DNS_SOCKET_MAX)];
+  for (unsigned int i=0;i<256;i++)
+  {
+    rs = &ctx->sockets[GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE,
+                                                 DNS_SOCKET_MAX)];
+    if (NULL == rs->rc)
+      break;
+  }
+  if (NULL != rs->rc)
+  {
+    /* signal "failure" */
+    rs->rc (rs->rc_cls,
+            rs,
+            NULL,
+            0);
+    rs->rc = NULL;
+  }
   rs->timeout = GNUNET_TIME_relative_to_absolute (REQUEST_TIMEOUT);
   switch (af)
   {
@@ -271,9 +285,11 @@ get_request_socket (struct GNUNET_DNSSTUB_Context *ctx,
     return NULL;
   rset = GNUNET_NETWORK_fdset_create ();
   if (NULL != rs->dnsout4)
-    GNUNET_NETWORK_fdset_set (rset, rs->dnsout4);
+    GNUNET_NETWORK_fdset_set (rset,
+                              rs->dnsout4);
   if (NULL != rs->dnsout6)
-    GNUNET_NETWORK_fdset_set (rset, rs->dnsout6);
+    GNUNET_NETWORK_fdset_set (rset,
+                              rs->dnsout6);
   rs->read_task = GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
                                               REQUEST_TIMEOUT,
                                               rset,
@@ -326,11 +342,11 @@ transmit_query (void *cls)
  *
  * @param ctx stub resolver to use
  * @param sa the socket address
- * @param sa_len the socket length
+ * @param sa_len the length of @a sa
  * @param request DNS request to transmit
- * @param request_len number of bytes in msg
+ * @param request_len number of bytes in @a request
  * @param rc function to call with result
- * @param rc_cls closure for 'rc'
+ * @param rc_cls closure for @a rc
  * @return socket used for the request, NULL on error
  */
 struct GNUNET_DNSSTUB_RequestSocket *
@@ -347,6 +363,7 @@ GNUNET_DNSSTUB_resolve (struct GNUNET_DNSSTUB_Context *ctx,
   if (NULL == (rs = get_request_socket (ctx,
                                         sa->sa_family)))
     return NULL;
+  GNUNET_assert (NULL == rs->rc);
   GNUNET_memcpy (&rs->addr,
                  sa,
                  sa_len);
@@ -389,7 +406,9 @@ GNUNET_DNSSTUB_resolve2 (struct GNUNET_DNSSTUB_Context *ctx,
 
   memset (&v4, 0, sizeof (v4));
   memset (&v6, 0, sizeof (v6));
-  if (1 == inet_pton (AF_INET, ctx->dns_exit, &v4.sin_addr))
+  if (1 == inet_pton (AF_INET,
+                      ctx->dns_exit,
+                      &v4.sin_addr))
   {
     salen = sizeof (v4);
     v4.sin_family = AF_INET;
@@ -400,7 +419,9 @@ GNUNET_DNSSTUB_resolve2 (struct GNUNET_DNSSTUB_Context *ctx,
     sa = (struct sockaddr *) &v4;
     af = AF_INET;
   }
-  else if (1 == inet_pton (AF_INET6, ctx->dns_exit, &v6.sin6_addr))
+  else if (1 == inet_pton (AF_INET6,
+                           ctx->dns_exit,
+                           &v6.sin6_addr))
   {
     salen = sizeof (v6);
     v6.sin6_family = AF_INET6;
@@ -416,8 +437,10 @@ GNUNET_DNSSTUB_resolve2 (struct GNUNET_DNSSTUB_Context *ctx,
     GNUNET_break (0);
     return NULL;
   }
-  if (NULL == (rs = get_request_socket (ctx, af)))
+  if (NULL == (rs = get_request_socket (ctx,
+                                        af)))
     return NULL;
+  GNUNET_assert (NULL == rs->rc);
   if (NULL != rs->dnsout4)
     dnsout = rs->dnsout4;
   else
@@ -430,15 +453,17 @@ GNUNET_DNSSTUB_resolve2 (struct GNUNET_DNSSTUB_Context *ctx,
     return NULL;
   }
   GNUNET_memcpy (&rs->addr,
-         sa,
-         salen);
+                 sa,
+                 salen);
   rs->addrlen = salen;
   rs->rc = rc;
   rs->rc_cls = rc_cls;
   if (GNUNET_SYSERR ==
       GNUNET_NETWORK_socket_sendto (dnsout,
                                    request,
-                                   request_len, sa, salen))
+                                   request_len,
+                                    sa,
+                                    salen))
     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
                _("Failed to send DNS request to %s\n"),
                GNUNET_a2s (sa, salen));
@@ -466,7 +491,9 @@ do_dns_read (struct GNUNET_DNSSTUB_RequestSocket *rs,
   int len;
 
 #ifndef MINGW
-  if (0 != ioctl (GNUNET_NETWORK_get_fd (dnsout), FIONREAD, &len))
+  if (0 != ioctl (GNUNET_NETWORK_get_fd (dnsout),
+                  FIONREAD,
+                  &len))
   {
     /* conservative choice: */
     len = UINT16_MAX;
@@ -484,11 +511,14 @@ do_dns_read (struct GNUNET_DNSSTUB_RequestSocket *rs,
     addrlen = sizeof (addr);
     memset (&addr, 0, sizeof (addr));
     r = GNUNET_NETWORK_socket_recvfrom (dnsout,
-                                       buf, sizeof (buf),
-                                       (struct sockaddr*) &addr, &addrlen);
+                                       buf,
+                                        sizeof (buf),
+                                       (struct sockaddr*) &addr,
+                                        &addrlen);
     if (-1 == r)
     {
-      GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "recvfrom");
+      GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
+                           "recvfrom");
       GNUNET_NETWORK_socket_close (dnsout);
       return GNUNET_SYSERR;
     }
@@ -543,25 +573,32 @@ read_response (void *cls)
   }
   /* read and process ready sockets */
   if ((NULL != rs->dnsout4) &&
-      (GNUNET_NETWORK_fdset_isset (tc->read_ready, rs->dnsout4)) &&
-      (GNUNET_SYSERR == do_dns_read (rs, rs->dnsout4)))
+      (GNUNET_NETWORK_fdset_isset (tc->read_ready,
+                                   rs->dnsout4)) &&
+      (GNUNET_SYSERR == do_dns_read (rs,
+                                     rs->dnsout4)))
     rs->dnsout4 = NULL;
   if ((NULL != rs->dnsout6) &&
-      (GNUNET_NETWORK_fdset_isset (tc->read_ready, rs->dnsout6)) &&
-      (GNUNET_SYSERR == do_dns_read (rs, rs->dnsout6)))
+      (GNUNET_NETWORK_fdset_isset (tc->read_ready,
+                                   rs->dnsout6)) &&
+      (GNUNET_SYSERR == do_dns_read (rs,
+                                     rs->dnsout6)))
     rs->dnsout6 = NULL;
 
   /* re-schedule read task */
   rset = GNUNET_NETWORK_fdset_create ();
   if (NULL != rs->dnsout4)
-    GNUNET_NETWORK_fdset_set (rset, rs->dnsout4);
+    GNUNET_NETWORK_fdset_set (rset,
+                              rs->dnsout4);
   if (NULL != rs->dnsout6)
-    GNUNET_NETWORK_fdset_set (rset, rs->dnsout6);
+    GNUNET_NETWORK_fdset_set (rset,
+                              rs->dnsout6);
   rs->read_task = GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
                                               GNUNET_TIME_absolute_get_remaining (rs->timeout),
                                               rset,
                                               NULL,
-                                              &read_response, rs);
+                                              &read_response,
+                                               rs);
   GNUNET_NETWORK_fdset_destroy (rset);
 }
 
index ffc94afb75073538aeae497761b72c822f34bd77..9feaa841352238a1afca1e1f472c4fcf7f1f39dd 100644 (file)
@@ -729,6 +729,9 @@ process_dns_result (void *cls,
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              "Processing DNS result from stub resolver\n");
   GNUNET_assert (NULL == cls);
+  if (NULL == dns)
+    return; /* ignore */
+
   rr = &requests[dns->id];
   if ( (rr->phase != RP_INTERNET_DNS) ||
        (rr->rs != rs) )
index c624e083e5d6f4170372419b5b5c68ac1cbed732..0b3cc505ac2a4c8780e249716da8659ec7f88db2 100644 (file)
@@ -475,6 +475,8 @@ process_dns_result (void *cls,
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              "Processing DNS result from stub resolver\n");
   GNUNET_assert (NULL == cls);
+  if (NULL == dns)
+    return;
   /* Handle case that this is a reply to a request from a CADET DNS channel */
   ts = channels[dns->id];
   if ( (NULL == ts) ||
index 3d16cd773b49406d5e2f12702c0e3b47e9d14160..47cc6dde0b9be9643b403f11b0ea05618689c172 100644 (file)
@@ -85,6 +85,11 @@ struct Request
    * Number of bytes in @e udp_msg.
    */
   size_t udp_msg_size;
+
+  /**
+   * ID of the original request.
+   */
+  uint16_t original_request_id;
 };
 
 
@@ -255,6 +260,18 @@ dns_result_processor (void *cls,
   struct Request *request = cls;
 
   (void) rs;
+  if (NULL == dns)
+  {
+    /* DNSSTUB gave up, so we trigger timeout early */
+    GNUNET_SCHEDULER_cancel (request->timeout_task);
+    do_timeout (request);
+    return;
+  }
+  if (request->original_request_id != dns->id)
+  {
+    /* for a another query, ignore */
+    return;
+  }
   request->packet = GNUNET_DNSPARSER_parse ((char*)dns,
                                            r);
   send_response (request);
@@ -277,7 +294,6 @@ result_processor (void *cls,
 {
   struct Request *request = cls;
   struct GNUNET_DNSPARSER_Packet *packet;
-  uint32_t i;
   struct GNUNET_DNSPARSER_Record rec;
 
   request->lookup = NULL;
@@ -288,6 +304,7 @@ result_processor (void *cls,
                "Using DNS resolver IP `%s' to resolve `%s'\n",
                dns_ip,
                request->packet->queries[0].name);
+    request->original_request_id = request->packet->id;
     GNUNET_DNSPARSER_free_packet (request->packet);
     request->packet = NULL;
     request->dns_lookup = GNUNET_DNSSTUB_resolve2 (dns_stub,
@@ -296,7 +313,7 @@ result_processor (void *cls,
                                                   &dns_result_processor,
                                                   request);
     return;
-  }  
+  }
   packet = request->packet;
   packet->flags.query_or_response = 1;
   packet->flags.return_code = GNUNET_TUN_DNS_RETURN_CODE_NO_ERROR;
@@ -307,7 +324,7 @@ result_processor (void *cls,
   packet->flags.message_truncated = 0;
   packet->flags.authoritative_answer = 0;
   //packet->flags.opcode = GNUNET_TUN_DNS_OPCODE_STATUS; // ???
-  for (i=0;i<rd_count;i++)
+  for (uint32_t i=0;i<rd_count;i++)
     {
       // FIXME: do we need to hanlde #GNUNET_GNSRECORD_RF_SHADOW_RECORD
       // here? Or should we do this in libgnunetgns?
index 0b86ca267191f46dd64eea040689a00ece67c926..7fbe3a4104c7863b57b65c099be91a125e0c2134 100644 (file)
@@ -383,6 +383,11 @@ struct GNS_ResolverHandle
    */
   unsigned int loop_limiter;
 
+  /**
+   * 16 bit random ID we used in the @e dns_request.
+   */
+  uint16_t original_dns_id;
+
 };
 
 
@@ -843,17 +848,28 @@ dns_result_parser (void *cls,
   unsigned int i;
 
   (void) rs;
-  rh->dns_request = NULL;
-  GNUNET_SCHEDULER_cancel (rh->task_id);
-  rh->task_id = NULL;
+  if (NULL == dns)
+  {
+    rh->dns_request = NULL;
+    GNUNET_SCHEDULER_cancel (rh->task_id);
+    rh->task_id = NULL;
+    rh->proc (rh->proc_cls,
+              0,
+              NULL);
+    GNS_resolver_lookup_cancel (rh);
+    return;
+  }
+  if (rh->original_dns_id != dns->id)
+  {
+    /* DNS answer, but for another query */
+    return;
+  }
   p = GNUNET_DNSPARSER_parse ((const char *) dns,
                              dns_len);
   if (NULL == p)
   {
     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
                _("Failed to parse DNS response\n"));
-    rh->proc (rh->proc_cls, 0, NULL);
-    GNS_resolver_lookup_cancel (rh);
     return;
   }
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -1097,6 +1113,7 @@ recursive_dns_resolution (struct GNS_ResolverHandle *rh)
   }
   else
   {
+    rh->original_dns_id = p->id;
     rh->dns_request = GNUNET_DNSSTUB_resolve (dns_handle,
                                              (const struct sockaddr *) &ac->authority_info.dns_authority.dns_ip,
                                              sa_len,
index 76b708dcf352bb237f7d83d7ecb9779ffb0abd70..017d5a0391949fbb1576eb3b098a2d20924703f5 100644 (file)
@@ -122,10 +122,11 @@ enum GNUNET_DNS_Flags
  * @param request_length number of bytes in request
  * @param request udp payload of the DNS request
  */
-typedef void (*GNUNET_DNS_RequestHandler)(void *cls,
-                                         struct GNUNET_DNS_RequestHandle *rh,
-                                         size_t request_length,
-                                         const char *request);
+typedef void
+(*GNUNET_DNS_RequestHandler)(void *cls,
+                             struct GNUNET_DNS_RequestHandle *rh,
+                             size_t request_length,
+                             const char *request);
 
 
 /**
index 9fe3491d672a734611d6dbad6e0f7194b44eacf9..80a67c3c71eaec7d8171ed354c9450ebf1c251b9 100644 (file)
@@ -49,6 +49,7 @@
 /**
  * A few common DNS types.
  */
+#define GNUNET_DNSPARSER_TYPE_ANY 0
 #define GNUNET_DNSPARSER_TYPE_A 1
 #define GNUNET_DNSPARSER_TYPE_NS 2
 #define GNUNET_DNSPARSER_TYPE_CNAME 5