Deal with double name-pointer chases 59/9459/3
authorDave Barach <dave@barachs.net>
Thu, 16 Nov 2017 15:01:12 +0000 (10:01 -0500)
committerFlorin Coras <florin.coras@gmail.com>
Thu, 16 Nov 2017 16:56:17 +0000 (16:56 +0000)
Change-Id: I153b07b4348133535b16b6bf55527d19a6b927c6
Signed-off-by: Dave Barach <dave@barachs.net>
src/vnet/dns/dns.c

index d361aa1..cf76439 100644 (file)
@@ -1075,10 +1075,11 @@ vnet_dns_response_to_reply (u8 * response,
   dns_rr_t *rr;
   int i, limit;
   u8 len;
-  u8 *curpos, *pos;
+  u8 *curpos, *pos, *pos2;
   u16 flags;
   u16 rcode;
   u32 ttl;
+  int pointer_chase;
 
   h = (dns_header_t *) response;
   flags = clib_net_to_host_u16 (h->flags);
@@ -1134,29 +1135,42 @@ vnet_dns_response_to_reply (u8 * response,
 
   for (i = 0; i < limit; i++)
     {
-      pos = curpos;
+      pos = pos2 = curpos;
+      pointer_chase = 0;
 
       /* Expect pointer chases in the answer section... */
-      if ((pos[0] & 0xC0) == 0xC0)
-       curpos += 2;
-      else
+      if ((pos2[0] & 0xC0) == 0xC0)
        {
-         len = *pos++;
-         while (len)
+         pos = pos2 + 2;
+         pos2 = response + ((pos2[0] & 0x3f) << 8) + pos2[1];
+         pointer_chase = 1;
+       }
+
+      len = *pos2++;
+
+      while (len)
+       {
+         pos2 += len;
+         if ((pos2[0] & 0xc0) == 0xc0)
            {
-             if ((pos[0] & 0xC0) == 0xC0)
-               {
-                 curpos = pos + 2;
-                 goto curpos_set;
-               }
-             pos += len;
-             len = *pos++;
+             /*
+              * If we've already done one pointer chase,
+              * do not move the pos pointer.
+              */
+             if (pointer_chase == 0)
+               pos = pos2 + 2;
+             pos2 = response + ((pos2[0] & 0x3f) << 8) + pos2[1];
+             len = *pos2++;
+             pointer_chase = 1;
            }
-         curpos = pos;
+         else
+           len = *pos2++;
        }
 
-    curpos_set:
-      rr = (dns_rr_t *) curpos;
+      if (pointer_chase == 0)
+       pos = pos2;
+
+      rr = (dns_rr_t *) pos;
 
       switch (clib_net_to_host_u16 (rr->type))
        {
@@ -1176,13 +1190,15 @@ vnet_dns_response_to_reply (u8 * response,
            *min_ttlp = ttl;
          rmp->ip6_set = 1;
          break;
+
        default:
          break;
        }
       /* Might as well stop ASAP */
       if (rmp->ip4_set && rmp->ip6_set)
        break;
-      curpos += sizeof (*rr) + clib_net_to_host_u16 (rr->rdlength);
+      pos += sizeof (*rr) + clib_net_to_host_u16 (rr->rdlength);
+      curpos = pos;
     }
 
   if ((rmp->ip4_set + rmp->ip6_set) == 0)
@@ -1200,13 +1216,14 @@ vnet_dns_response_to_name (u8 * response,
   dns_rr_t *rr;
   int i, limit;
   u8 len;
-  u8 *curpos, *pos;
+  u8 *curpos, *pos, *pos2;
   u16 flags;
   u16 rcode;
   u8 *name;
   u32 ttl;
   u8 *junk __attribute__ ((unused));
   int name_set = 0;
+  int pointer_chase;
 
   h = (dns_header_t *) response;
   flags = clib_net_to_host_u16 (h->flags);
@@ -1262,29 +1279,42 @@ vnet_dns_response_to_name (u8 * response,
 
   for (i = 0; i < limit; i++)
     {
-      pos = curpos;
+      pos = pos2 = curpos;
+      pointer_chase = 0;
 
       /* Expect pointer chases in the answer section... */
-      if ((pos[0] & 0xC0) == 0xC0)
-       curpos += 2;
-      else
+      if ((pos2[0] & 0xC0) == 0xC0)
        {
-         len = *pos++;
-         while (len)
+         pos = pos2 + 2;
+         pos2 = response + ((pos2[0] & 0x3f) << 8) + pos2[1];
+         pointer_chase = 1;
+       }
+
+      len = *pos2++;
+
+      while (len)
+       {
+         pos2 += len;
+         if ((pos2[0] & 0xc0) == 0xc0)
            {
-             if ((pos[0] & 0xC0) == 0xC0)
-               {
-                 curpos = pos + 2;
-                 goto curpos_set;
-               }
-             pos += len;
-             len = *pos++;
+             /*
+              * If we've already done one pointer chase,
+              * do not move the pos pointer.
+              */
+             if (pointer_chase == 0)
+               pos = pos2 + 2;
+             pos2 = response + ((pos2[0] & 0x3f) << 8) + pos2[1];
+             len = *pos2++;
+             pointer_chase = 1;
            }
-         curpos = pos;
+         else
+           len = *pos2++;
        }
 
-    curpos_set:
-      rr = (dns_rr_t *) curpos;
+      if (pointer_chase == 0)
+       pos = pos2;
+
+      rr = (dns_rr_t *) pos;
 
       switch (clib_net_to_host_u16 (rr->type))
        {
@@ -1292,7 +1322,7 @@ vnet_dns_response_to_name (u8 * response,
          name = vnet_dns_labels_to_name (rr->rdata, response, &junk);
          memcpy (rmp->name, name, vec_len (name));
          ttl = clib_net_to_host_u32 (rr->ttl);
-         if (*min_ttlp)
+         if (min_ttlp)
            *min_ttlp = ttl;
          rmp->name[vec_len (name)] = 0;
          name_set = 1;
@@ -1303,7 +1333,8 @@ vnet_dns_response_to_name (u8 * response,
       /* Might as well stop ASAP */
       if (name_set == 1)
        break;
-      curpos += sizeof (*rr) + clib_net_to_host_u16 (rr->rdlength);
+      pos += sizeof (*rr) + clib_net_to_host_u16 (rr->rdlength);
+      curpos = pos;
     }
 
   if (name_set == 0)
@@ -1700,7 +1731,7 @@ format_dns_reply_data (u8 * s, va_list * args)
   u8 *pos, *pos2;
   dns_rr_t *rr;
   int i;
-  int initial_pointer_chase = 0;
+  int pointer_chase = 0;
   u16 *tp;
   u16 rrtype_host_byte_order;
 
@@ -1710,11 +1741,11 @@ format_dns_reply_data (u8 * s, va_list * args)
     s = format (s, "    ");
 
   /* chase pointer? almost always yes here... */
-  if (pos2[0] == 0xc0)
+  if ((pos2[0] & 0xc0) == 0xc0)
     {
-      pos2 = reply + pos2[1];
-      pos += 2;
-      initial_pointer_chase = 1;
+      pos = pos2 + 2;
+      pos2 = reply + ((pos2[0] & 0x3f) << 8) + pos2[1];
+      pointer_chase = 1;
     }
 
   len = *pos2++;
@@ -1727,7 +1758,20 @@ format_dns_reply_data (u8 * s, va_list * args)
            vec_add1 (s, *pos2);
          pos2++;
        }
-      len = *pos2++;
+      if ((pos2[0] & 0xc0) == 0xc0)
+       {
+         /*
+          * If we've already done one pointer chase,
+          * do not move the pos pointer.
+          */
+         if (pointer_chase == 0)
+           pos = pos2 + 2;
+         pos2 = reply + ((pos2[0] & 0x3f) << 8) + pos2[1];
+         len = *pos2++;
+         pointer_chase = 1;
+       }
+      else
+       len = *pos2++;
       if (len)
        {
          if (verbose > 1)
@@ -1740,7 +1784,7 @@ format_dns_reply_data (u8 * s, va_list * args)
        }
     }
 
-  if (initial_pointer_chase == 0)
+  if (pointer_chase == 0)
     pos = pos2;
 
   rr = (dns_rr_t *) pos;
@@ -1826,8 +1870,11 @@ format_dns_reply_data (u8 * s, va_list * args)
          pos2 = rr->rdata;
 
          /* chase pointer? */
-         if (pos2[0] == 0xc0)
-           pos2 = reply + pos2[1];
+         if ((pos2[0] & 0xc0) == 0xc0)
+           {
+             pos = pos2 + 2;
+             pos2 = reply + ((pos2[0] & 0x3f) << 8) + pos2[1];
+           }
 
          len = *pos2++;
 
@@ -2270,7 +2317,7 @@ VLIB_CLI_COMMAND (dns_cache_add_del_command) =
 };
 /* *INDENT-ON* */
 
-#define DNS_FORMAT_TEST 1
+#define DNS_FORMAT_TEST 0
 
 #if DNS_FORMAT_TEST > 0
 #if 0
@@ -2334,8 +2381,80 @@ static u8 dns_reply_data_initializer[] = {
   0x03, 0x63, 0x6f, 0x6d, 0x06, 0x61, 0x6b, 0x61, 0x64,
   0x6e, 0x73, 0x03, 0x6e, 0x65, 0x74, 0x00,
 };
-#else
+
+/* bind8 (linux widget, w/ nasty double pointer chasees */
+static u8 dns_reply_data_initializer[] = {
+  /* 0 */
+  0x00, 0x01, 0x81, 0x80, 0x00, 0x01, 0x00, 0x08,
+  /* 8 */
+  0x00, 0x06, 0x00, 0x06, 0x0a, 0x6f, 0x72, 0x69,
+  /* 16 */
+  0x67, 0x69, 0x6e, 0x2d, 0x77, 0x77, 0x77, 0x05,
+  /* 24 */
+  0x63, 0x69, 0x73, 0x63, 0x6f, 0x03, 0x63, 0x6f,
+  /* 32 */
+  0x6d, 0x00, 0x00, 0xff, 0x00, 0x01, 0x0a, 0x6f,
+  /* 40 */
+  0x72, 0x69, 0x67, 0x69, 0x6e, 0x2d, 0x77, 0x77,
+  /* 48 */
+  0x77, 0x05, 0x43, 0x49, 0x53, 0x43, 0x4f, 0xc0,
+
+  /* 56 */
+  0x1d, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x05,
+
+  /* 64 */
+  0x9a, 0x00, 0x18, 0x15, 0x72, 0x63, 0x64,
+  0x6e, 0x39, 0x2d, 0x31, 0x34, 0x70, 0x2d, 0x64, 0x63,
+  0x7a, 0x30, 0x35, 0x6e, 0x2d, 0x67, 0x73, 0x73, 0x31,
+  0xc0, 0x17, 0xc0, 0x26, 0x00, 0x02, 0x00, 0x01, 0x00,
+  0x00, 0x05, 0x9a, 0x00, 0x1a, 0x17, 0x61, 0x6c, 0x6c,
+  0x6e, 0x30, 0x31, 0x2d, 0x61, 0x67, 0x30, 0x39, 0x2d,
+  0x64, 0x63, 0x7a, 0x30, 0x33, 0x6e, 0x2d, 0x67, 0x73,
+  0x73, 0x31, 0xc0, 0x17, 0xc0, 0x26, 0x00, 0x02, 0x00,
+  0x01, 0x00, 0x00, 0x05, 0x9a, 0x00, 0x10, 0x0d, 0x72,
+  0x74, 0x70, 0x35, 0x2d, 0x64, 0x6d, 0x7a, 0x2d, 0x67,
+  0x73, 0x73, 0x31, 0xc0, 0x17, 0xc0, 0x26, 0x00, 0x02,
+  0x00, 0x01, 0x00, 0x00, 0x05, 0x9a, 0x00, 0x18, 0x15,
+  0x6d, 0x74, 0x76, 0x35, 0x2d, 0x61, 0x70, 0x31, 0x30,
+  0x2d, 0x64, 0x63, 0x7a, 0x30, 0x36, 0x6e, 0x2d, 0x67,
+  0x73, 0x73, 0x31, 0xc0, 0x17, 0xc0, 0x26, 0x00, 0x02,
+  0x00, 0x01, 0x00, 0x00, 0x05, 0x9a, 0x00, 0x1b, 0x18,
+  0x73, 0x6e, 0x67, 0x64, 0x63, 0x30, 0x31, 0x2d, 0x61,
+  0x62, 0x30, 0x37, 0x2d, 0x64, 0x63, 0x7a, 0x30, 0x31,
+  0x6e, 0x2d, 0x67, 0x73, 0x73, 0x31, 0xc0, 0x17, 0xc0,
+  0x26, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x05, 0x9a,
+  0x00, 0x1a, 0x17, 0x61, 0x65, 0x72, 0x30, 0x31, 0x2d,
+  0x72, 0x34, 0x63, 0x32, 0x35, 0x2d, 0x64, 0x63, 0x7a,
+  0x30, 0x31, 0x6e, 0x2d, 0x67, 0x73, 0x73, 0x31, 0xc0,
+  0x17, 0xc0, 0x26, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00,
+  0x00, 0x81, 0x00, 0x04, 0x48, 0xa3, 0x04, 0xa1, 0xc0,
+  0x26, 0x00, 0x1c, 0x00, 0x01, 0x00, 0x00, 0x00, 0x82,
+  0x00, 0x10, 0x20, 0x01, 0x04, 0x20, 0x12, 0x01, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a,
+  0xc0, 0x0c, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x05,
+  0x9a, 0x00, 0x02, 0xc0, 0xf4, 0xc0, 0x0c, 0x00, 0x02,
+  0x00, 0x01, 0x00, 0x00, 0x05, 0x9a, 0x00, 0x02, 0xc0,
+  0xcd, 0xc0, 0x0c, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00,
+  0x05, 0x9a, 0x00, 0x02, 0xc0, 0x8d, 0xc0, 0x0c, 0x00,
+  0x02, 0x00, 0x01, 0x00, 0x00, 0x05, 0x9a, 0x00, 0x02,
+  0xc0, 0x43, 0xc0, 0x0c, 0x00, 0x02, 0x00, 0x01, 0x00,
+  0x00, 0x05, 0x9a, 0x00, 0x02, 0xc0, 0xa9, 0xc0, 0x0c,
+  0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x05, 0x9a, 0x00,
+  0x02, 0xc0, 0x67, 0xc0, 0x8d, 0x00, 0x01, 0x00, 0x01,
+  0x00, 0x00, 0x07, 0x08, 0x00, 0x04, 0x40, 0x66, 0xf6,
+  0x05, 0xc0, 0xa9, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00,
+  0x07, 0x08, 0x00, 0x04, 0xad, 0x24, 0xe0, 0x64, 0xc0,
+  0x43, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x07, 0x08,
+  0x00, 0x04, 0x48, 0xa3, 0x04, 0x1c, 0xc0, 0xf4, 0x00,
+  0x01, 0x00, 0x01, 0x00, 0x00, 0x07, 0x08, 0x00, 0x04,
+  0xad, 0x26, 0xd4, 0x6c, 0xc0, 0x67, 0x00, 0x01, 0x00,
+  0x01, 0x00, 0x00, 0x07, 0x08, 0x00, 0x04, 0xad, 0x25,
+  0x90, 0x64, 0xc0, 0xcd, 0x00, 0x01, 0x00, 0x01, 0x00,
+  0x00, 0x07, 0x08, 0x00, 0x04, 0xad, 0x27, 0x70, 0x44,
+};
+
 /* google.com */
+#else
 static u8 dns_reply_data_initializer[] =
   { 0x0, 0x0, 0x81, 0x80, 0x0, 0x1, 0x0, 0xe, 0x0, 0x0, 0x0, 0x0, 0x6,
   0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x3, 0x63, 0x6f, 0x6d, 0x0, 0x0, 0xff,