gnunet-svn
[Top][All Lists]
Advanced

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

[GNUnet-SVN] r18976 - gnunet/src/dns


From: gnunet
Subject: [GNUnet-SVN] r18976 - gnunet/src/dns
Date: Wed, 4 Jan 2012 12:18:25 +0100

Author: grothoff
Date: 2012-01-04 12:18:25 +0100 (Wed, 04 Jan 2012)
New Revision: 18976

Modified:
   gnunet/src/dns/dnsparser.c
Log:
-finishing DNS parser, alas untested

Modified: gnunet/src/dns/dnsparser.c
===================================================================
--- gnunet/src/dns/dnsparser.c  2012-01-04 11:12:27 UTC (rev 18975)
+++ gnunet/src/dns/dnsparser.c  2012-01-04 11:18:25 UTC (rev 18976)
@@ -40,10 +40,102 @@
   uint16_t authority_rcount GNUNET_PACKED;       // number of authority-records
   uint16_t additional_rcount GNUNET_PACKED;       // number of additional 
records
 };
+
+struct query_line
+{
+  uint16_t type GNUNET_PACKED;
+  uint16_t class GNUNET_PACKED;
+};
+
+struct record_line
+{
+  uint16_t type GNUNET_PACKED;
+  uint16_t class GNUNET_PACKED;
+  uint32_t ttl GNUNET_PACKED;
+  uint16_t data_len GNUNET_PACKED;
+};
+
 GNUNET_NETWORK_STRUCT_END
 
 
 /**
+ * Parse name inside of a DNS query or record.
+ *
+ * @param udp_payload entire UDP payload
+ * @param udp_payload_length length of udp_payload
+ * @param off pointer to the offset of the name to parse in the udp_payload 
(to be
+ *                    incremented by the size of the name)
+ * @return name as 0-terminated C string on success, NULL if the payload is 
malformed
+ */
+static char *
+parse_name (const char *udp_payload,
+           size_t udp_payload_length,
+           size_t *off)
+{
+  const uint8_t *input = (const uint8_t *) udp_payload;
+  char *ret;
+  char *tmp;
+  char *xstr;
+  uint8_t len;
+  size_t xoff;
+  
+  ret = GNUNET_strdup ("");
+  while (1)
+  {
+    if (*off == udp_payload_length)
+      goto error;
+    len = input[*off];
+    if (0 == len)
+      break;
+    if (len < 64)
+    {
+      if (*off + 1 + len > udp_payload_length)
+       goto error;
+      GNUNET_asprintf (&tmp,
+                      "%s%.*s.",
+                      ret,
+                      (int) len,
+                      &udp_payload[*off + 1]);
+      GNUNET_free (ret);
+      ret = tmp;
+      off += 1 + len;
+    }
+    else if ((64 | 128) == (len & (64 | 128)) )
+    {
+      /* pointer to string */
+      if (*off + 1 > udp_payload_length)
+       goto error;
+      xoff = ((len - (64 | 128)) << 8) + input[*off+1];
+      xstr = parse_name (udp_payload,
+                        udp_payload_length,
+                        &xoff);
+      GNUNET_asprintf (&tmp,
+                      "%s%s.",
+                      ret,
+                      xstr);
+      GNUNET_free (ret);
+      GNUNET_free (xstr);
+      ret = tmp;
+      off += 2;
+      /* pointers always terminate names */
+      break;
+    } 
+    else
+    {
+      /* neither pointer nor inline string, not supported... */
+      goto error;
+    }
+  }
+  if (0 < strlen(ret))
+    ret[strlen(ret)-1] = '\0'; /* eat tailing '.' */
+  return ret;
+ error:  
+  GNUNET_free (ret);
+  return NULL;
+}
+
+
+/**
  * Parse a DNS query entry.
  *
  * @param udp_payload entire UDP payload
@@ -59,7 +151,22 @@
             size_t *off,
             struct GNUNET_DNSPARSER_Query *q)
 {
-  return GNUNET_SYSERR;
+  char *name;
+  struct query_line ql;
+
+  name = parse_name (udp_payload, 
+                    udp_payload_length,
+                    off);
+  if (NULL == name)
+    return GNUNET_SYSERR;
+  q->name = name;
+  if (*off + sizeof (struct query_line) > udp_payload_length)
+    return GNUNET_SYSERR;
+  memcpy (&ql, &udp_payload[*off], sizeof (ql));
+  *off += sizeof (ql);
+  q->type = ntohs (ql.type);
+  q->class = ntohs (ql.class);
+  return GNUNET_OK;
 }
 
 
@@ -79,11 +186,35 @@
              size_t *off,
              struct GNUNET_DNSPARSER_Record *r)
 {
-  return GNUNET_SYSERR;
+  char *name;
+  struct record_line rl;
+
+  name = parse_name (udp_payload, 
+                    udp_payload_length,
+                    off);
+  if (NULL == name)
+    return GNUNET_SYSERR;
+  r->name = name;
+  if (*off + sizeof (struct record_line) > udp_payload_length)
+    return GNUNET_SYSERR;
+  memcpy (&rl, &udp_payload[*off], sizeof (rl));
+  *off += sizeof (rl);
+  r->type = ntohs (rl.type);
+  r->class = ntohs (rl.class);
+  r->expiration_time = GNUNET_TIME_relative_to_absolute 
(GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS,
+                                                                               
        ntohl (rl.ttl)));
+  r->data_len = ntohs (rl.data_len);
+  if (*off + r->data_len > udp_payload_length)
+    return GNUNET_SYSERR;
+  if (0 == r->data_len)
+    return GNUNET_OK;
+  r->data = GNUNET_malloc (r->data_len);
+  memcpy (r->data, &udp_payload[*off], r->data_len);
+  *off += r->data_len;
+  return GNUNET_OK;  
 }
 
 
-
 /**
  * Parse a UDP payload of a DNS packet in to a nice struct for further
  * processing and manipulation.




reply via email to

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