convert fs publish to MQ
[oweals/gnunet.git] / src / gnsrecord / plugin_gnsrecord_dns.c
index b52dee3745afd5ce93b424cee919aab6fc8b53b2..09125b9d5e4bf29b236b59e76c9818be152d2d32 100644 (file)
@@ -1,6 +1,6 @@
 /*
      This file is part of GNUnet
-     (C) 2013, 2014 Christian Grothoff (and other contributing authors)
+     Copyright (C) 2013, 2014 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
@@ -14,8 +14,8 @@
 
      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.
+     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+     Boston, MA 02110-1301, USA.
 */
 
 /**
@@ -44,7 +44,6 @@ dns_value_to_string (void *cls,
                      const void *data,
                      size_t data_size)
 {
-  const char *cdata;
   char* result;
   char tmp[INET6_ADDRSTRLEN];
 
@@ -231,23 +230,26 @@ dns_value_to_string (void *cls,
   case GNUNET_DNSPARSER_TYPE_TLSA:
     {
       const struct GNUNET_TUN_DnsTlsaRecord *tlsa;
-      char* tlsa_str;
+      char *tlsa_str;
+      char *hex;
 
-      cdata = data;
-      if ( (data_size <= sizeof (struct GNUNET_TUN_DnsTlsaRecord)) ||
-          ('\0' != cdata[data_size - 1]) )
+      if (data_size < sizeof (struct GNUNET_TUN_DnsTlsaRecord))
        return NULL; /* malformed */
       tlsa = data;
+      hex = GNUNET_DNSPARSER_bin_to_hex (&tlsa[1],
+                                         data_size - sizeof (struct GNUNET_TUN_DnsTlsaRecord));
       if (0 == GNUNET_asprintf (&tlsa_str,
                                "%u %u %u %s",
                                (unsigned int) tlsa->usage,
                                (unsigned int) tlsa->selector,
                                (unsigned int) tlsa->matching_type,
-                               (const char *) &tlsa[1]))
+                               hex))
       {
+        GNUNET_free (hex);
        GNUNET_free (tlsa_str);
        return NULL;
       }
+      GNUNET_free (hex);
       return tlsa_str;
     }
   default:
@@ -256,6 +258,74 @@ dns_value_to_string (void *cls,
 }
 
 
+/**
+ * Convert RFC 4394 Mnemonics to the corresponding integer values.
+ *
+ * @param mnemonic string to look up
+ * @return the value, 0 if not found
+ */
+static unsigned int
+rfc4394_mnemonic_to_value (const char *mnemonic)
+{
+  static struct {
+    const char *mnemonic;
+    unsigned int val;
+  } table[] = {
+    { "PKIX", 1 },
+    { "SPKI", 2 },
+    { "PGP", 3 },
+    { "IPKIX", 4 },
+    { "ISPKI", 5 },
+    { "IPGP", 6 },
+    { "ACPKIX", 7},
+    { "IACPKIX", 8},
+    { "URI", 253},
+    { "OID", 254},
+    { NULL, 0 }
+  };
+  unsigned int i;
+
+  for (i=0;NULL != table[i].mnemonic;i++)
+    if (0 == strcasecmp (mnemonic,
+                         table[i].mnemonic))
+      return table[i].val;
+  return 0;
+}
+
+
+/**
+ * Convert RFC 4034 algorithm types to the corresponding integer values.
+ *
+ * @param mnemonic string to look up
+ * @return the value, 0 if not found
+ */
+static unsigned int
+rfc4034_mnemonic_to_value (const char *mnemonic)
+{
+  static struct {
+    const char *mnemonic;
+    unsigned int val;
+  } table[] = {
+    { "RSAMD5", 1 },
+    { "DH", 2 },
+    { "DSA", 3 },
+    { "ECC", 4 },
+    { "RSASHA1", 5 },
+    { "INDIRECT", 252 },
+    { "PRIVATEDNS", 253 },
+    { "PRIVATEOID", 254 },
+    { NULL, 0 }
+  };
+  unsigned int i;
+
+  for (i=0;NULL != table[i].mnemonic;i++)
+    if (0 == strcasecmp (mnemonic,
+                         table[i].mnemonic))
+      return table[i].val;
+  return 0;
+}
+
+
 /**
  * Convert human-readable version of a 'value' of a record to the binary
  * representation.
@@ -354,12 +424,12 @@ dns_string_to_value (void *cls,
 
       sdup = GNUNET_strdup (s);
       typep = strtok (sdup, " ");
-      /* TODO: add typep mnemonic conversion according to RFC 4398 */
       if ( (NULL == typep) ||
-           (1 != SSCANF (typep,
-                         "%u",
-                         &type)) ||
-           (type > UINT16_MAX) )
+           ( (0 == (type = rfc4394_mnemonic_to_value (typep))) &&
+             ( (1 != SSCANF (typep,
+                             "%u",
+                             &type)) ||
+               (type > UINT16_MAX) ) ) )
       {
         GNUNET_free (sdup);
         return GNUNET_SYSERR;
@@ -375,12 +445,12 @@ dns_string_to_value (void *cls,
         return GNUNET_SYSERR;
       }
       algp = strtok (NULL, " ");
-      /* TODO: add algp mnemonic conversion according to RFC 4398/RFC 4034 */
       if ( (NULL == algp) ||
-           (1 != sscanf (algp,
-                         "%u",
-                         &alg)) ||
-           (alg > UINT8_MAX) )
+           ( (0 == (type = rfc4034_mnemonic_to_value (typep))) &&
+             ( (1 != sscanf (algp,
+                             "%u",
+                             &alg)) ||
+               (alg > UINT8_MAX) ) ) )
       {
         GNUNET_free (sdup);
         return GNUNET_SYSERR;
@@ -418,7 +488,6 @@ dns_string_to_value (void *cls,
           GNUNET_free (cert_data);
           return GNUNET_SYSERR;
         }
-        GNUNET_free (cert_data);
         *data_size = off;
         *data = GNUNET_malloc (off);
         memcpy (*data, certbuf, off);
@@ -549,7 +618,7 @@ dns_string_to_value (void *cls,
       unsigned int port;
       size_t off;
 
-      if (2 != SSCANF(s,
+      if (4 != SSCANF(s,
                       "%u %u %u %253s",
                       &priority,
                       &weight,
@@ -603,23 +672,40 @@ dns_string_to_value (void *cls,
       unsigned int usage;
       unsigned int selector;
       unsigned int matching_type;
+      size_t slen = strlen (s) + 1;
+      char hex[slen];
 
-      *data_size = sizeof (struct GNUNET_TUN_DnsTlsaRecord) + strlen (s) - 6;
-      *data = tlsa = GNUNET_malloc (*data_size);
       if (4 != SSCANF (s,
                        "%u %u %u %s",
-                       (char*)&tlsa[1]))
+                       &usage,
+                       &selector,
+                       &matching_type,
+                       hex))
       {
         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                     _("Unable to parse TLSA record string `%s'\n"),
                     s);
         *data_size = 0;
-        GNUNET_free (tlsa);
         return GNUNET_SYSERR;
       }
+
+      *data_size = sizeof (struct GNUNET_TUN_DnsTlsaRecord) + strlen (hex) / 2;
+      *data = tlsa = GNUNET_malloc (*data_size);
       tlsa->usage = (uint8_t) usage;
       tlsa->selector = (uint8_t) selector;
       tlsa->matching_type = (uint8_t) matching_type;
+      if (strlen (hex) / 2 !=
+          GNUNET_DNSPARSER_hex_to_bin (hex,
+                                       &tlsa[1]))
+      {
+        GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                    _("Unable to parse TLSA record string `%s'\n"),
+                    s);
+        GNUNET_free (*data);
+        *data = NULL;
+        *data_size = 0;
+        return GNUNET_SYSERR;
+      }
       return GNUNET_OK;
     }
   default:
@@ -644,7 +730,9 @@ static struct {
   { "MX", GNUNET_DNSPARSER_TYPE_MX },
   { "TXT", GNUNET_DNSPARSER_TYPE_TXT },
   { "AAAA", GNUNET_DNSPARSER_TYPE_AAAA },
+  { "SRV", GNUNET_DNSPARSER_TYPE_SRV },
   { "TLSA", GNUNET_DNSPARSER_TYPE_TLSA },
+  { "CERT", GNUNET_DNSPARSER_TYPE_CERT },
   { NULL, UINT32_MAX }
 };