#include "platform.h"
#include "gnunet_util_lib.h"
#include "gnunet_constants.h"
-#include "gnunet_signatures.h"
-#include "gnunet_conversation_service.h"
-#include "gnunet_dnsparser_lib.h"
#include "gnunet_gnsrecord_lib.h"
+#include "gnunet_gnsrecord_plugin.h"
#include "gnunet_tun_lib.h"
#define LOG(kind,...) GNUNET_log_from (kind, "gnsrecord",__VA_ARGS__)
+/**
+ * Handle for a plugin.
+ */
+struct Plugin
+{
+ /**
+ * Name of the shared library.
+ */
+ char *library_name;
+
+ /**
+ * Plugin API.
+ */
+ struct GNUNET_GNSRECORD_PluginFunctions *api;
+};
+
+
+/**
+ * Array of our plugins.
+ */
+static struct Plugin **gns_plugins;
+
+/**
+ * Size of the 'plugins' array.
+ */
+static unsigned int num_plugins;
+
+/**
+ * Global to mark if we've run the initialization.
+ */
+static int once;
+
+
+/**
+ * Add a plugin to the list managed by the block library.
+ *
+ * @param cls NULL
+ * @param library_name name of the plugin
+ * @param lib_ret the plugin API
+ */
+static void
+add_plugin (void *cls,
+ const char *library_name,
+ void *lib_ret)
+{
+ struct GNUNET_GNSRECORD_PluginFunctions *api = lib_ret;
+ struct Plugin *plugin;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Loading block plugin `%s'\n",
+ library_name);
+ plugin = GNUNET_new (struct Plugin);
+ plugin->api = api;
+ plugin->library_name = GNUNET_strdup (library_name);
+ GNUNET_array_append (gns_plugins, num_plugins, plugin);
+}
+
+
+/**
+ * Loads all plugins (lazy initialization).
+ */
+static void
+init ()
+{
+ if (1 == once)
+ return;
+ once = 1;
+ GNUNET_PLUGIN_load_all ("libgnunet_plugin_gnsrecord_", NULL,
+ &add_plugin, NULL);
+}
+
+
+/**
+ * Dual function to #init().
+ */
+void __attribute__ ((destructor))
+GNSRECORD_fini ()
+{
+ unsigned int i;
+ struct Plugin *plugin;
+
+ for (i = 0; i < num_plugins; i++)
+ {
+ plugin = gns_plugins[i];
+ GNUNET_break (NULL ==
+ GNUNET_PLUGIN_unload (plugin->library_name,
+ plugin->api));
+ GNUNET_free (plugin->library_name);
+ GNUNET_free (plugin);
+ }
+ GNUNET_free_non_null (gns_plugins);
+ gns_plugins = NULL;
+ once = 0;
+ num_plugins = 0;
+}
+
+
/**
* Convert the 'value' of a record to a string.
*
const void *data,
size_t data_size)
{
- const char *cdata;
- char* result;
- char tmp[INET6_ADDRSTRLEN];
+ unsigned int i;
+ struct Plugin *plugin;
+ char *ret;
- switch (type)
+ init ();
+ for (i = 0; i < num_plugins; i++)
{
- case 0:
- return NULL;
- case GNUNET_DNSPARSER_TYPE_A:
- if (data_size != sizeof (struct in_addr))
- return NULL;
- if (NULL == inet_ntop (AF_INET, data, tmp, sizeof (tmp)))
- return NULL;
- return GNUNET_strdup (tmp);
- case GNUNET_DNSPARSER_TYPE_NS:
- {
- char *ns;
- size_t off;
-
- off = 0;
- ns = GNUNET_DNSPARSER_parse_name (data,
- data_size,
- &off);
- if ( (NULL == ns) ||
- (off != data_size) )
- {
- GNUNET_break_op (0);
- return NULL;
- }
- return ns;
- }
- case GNUNET_DNSPARSER_TYPE_CNAME:
- {
- char *cname;
- size_t off;
-
- off = 0;
- cname = GNUNET_DNSPARSER_parse_name (data,
- data_size,
- &off);
- if ( (NULL == cname) ||
- (off != data_size) )
- {
- GNUNET_break_op (0);
- GNUNET_free_non_null (cname);
- return NULL;
- }
- return cname;
- }
- case GNUNET_DNSPARSER_TYPE_SOA:
- {
- struct GNUNET_DNSPARSER_SoaRecord *soa;
- size_t off;
-
- off = 0;
- soa = GNUNET_DNSPARSER_parse_soa (data,
- data_size,
- &off);
- if ( (NULL == soa) ||
- (off != data_size) )
- {
- GNUNET_break_op (0);
- return NULL;
- }
- GNUNET_asprintf (&result,
- "rname=%s mname=%s %lu,%lu,%lu,%lu,%lu",
- soa->rname,
- soa->mname,
- soa->serial,
- soa->refresh,
- soa->retry,
- soa->expire,
- soa->minimum_ttl);
- GNUNET_DNSPARSER_free_soa (soa);
- return result;
- }
- case GNUNET_DNSPARSER_TYPE_PTR:
- {
- char *ptr;
- size_t off;
-
- off = 0;
- ptr = GNUNET_DNSPARSER_parse_name (data,
- data_size,
- &off);
- if ( (NULL == ptr) ||
- (off != data_size) )
- {
- GNUNET_break_op (0);
- GNUNET_free_non_null (ptr);
- return NULL;
- }
- return ptr;
- }
- case GNUNET_DNSPARSER_TYPE_MX:
- {
- struct GNUNET_DNSPARSER_MxRecord *mx;
- size_t off;
-
- off = 0;
- mx = GNUNET_DNSPARSER_parse_mx (data,
- data_size,
- &off);
- if ( (NULL == mx) ||
- (off != data_size) )
- {
- GNUNET_break_op (0);
- GNUNET_free_non_null (mx);
- return NULL;
- }
- GNUNET_asprintf (&result,
- "%hu,%s",
- mx->preference,
- mx->mxhost);
- GNUNET_DNSPARSER_free_mx (mx);
- return result;
- }
- case GNUNET_DNSPARSER_TYPE_TXT:
- return GNUNET_strndup (data, data_size);
- case GNUNET_DNSPARSER_TYPE_AAAA:
- if (data_size != sizeof (struct in6_addr))
- return NULL;
- if (NULL == inet_ntop (AF_INET6, data, tmp, sizeof (tmp)))
- return NULL;
- return GNUNET_strdup (tmp);
- case GNUNET_GNSRECORD_TYPE_PKEY:
- if (data_size != sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey))
- return NULL;
- return GNUNET_CRYPTO_ecdsa_public_key_to_string (data);
- case GNUNET_GNSRECORD_TYPE_PHONE:
- {
- const struct GNUNET_CONVERSATION_PhoneRecord *pr;
- char *ret;
- char *pkey;
-
- if (data_size != sizeof (struct GNUNET_CONVERSATION_PhoneRecord))
- return NULL;
- pr = data;
- if (0 != ntohl (pr->version))
- return NULL;
- pkey = GNUNET_CRYPTO_eddsa_public_key_to_string (&pr->peer.public_key);
- GNUNET_asprintf (&ret,
- "%u-%s",
- ntohl (pr->line),
- pkey);
- GNUNET_free (pkey);
+ plugin = gns_plugins[i];
+ if (NULL != (ret = plugin->api->value_to_string (plugin->api->cls,
+ type,
+ data,
+ data_size)))
return ret;
- }
- case GNUNET_GNSRECORD_TYPE_PSEU:
- return GNUNET_strndup (data, data_size);
- case GNUNET_GNSRECORD_TYPE_LEHO:
- return GNUNET_strndup (data, data_size);
- case GNUNET_GNSRECORD_TYPE_VPN:
- {
- const struct GNUNET_TUN_GnsVpnRecord *vpn;
- char* vpn_str;
-
- cdata = data;
- if ( (data_size <= sizeof (struct GNUNET_TUN_GnsVpnRecord)) ||
- ('\0' != cdata[data_size - 1]) )
- return NULL; /* malformed */
- vpn = data;
- if (0 == GNUNET_asprintf (&vpn_str, "%u %s %s",
- (unsigned int) ntohs (vpn->proto),
- (const char*) GNUNET_i2s_full (&vpn->peer),
- (const char*) &vpn[1]))
- {
- GNUNET_free (vpn_str);
- return NULL;
- }
- return vpn_str;
- }
- case GNUNET_GNSRECORD_TYPE_GNS2DNS:
- {
- char *ns;
- size_t off;
-
- off = 0;
- ns = GNUNET_DNSPARSER_parse_name (data,
- data_size,
- &off);
- if ( (NULL == ns) ||
- (off != data_size) )
- {
- GNUNET_break_op (0);
- GNUNET_free_non_null (ns);
- return NULL;
- }
- return ns;
- }
- case GNUNET_DNSPARSER_TYPE_SRV:
- {
- struct GNUNET_DNSPARSER_SrvRecord *srv;
- size_t off;
-
- off = 0;
- srv = GNUNET_DNSPARSER_parse_srv ("+", /* FIXME: is this OK? */
- data,
- data_size,
- &off);
- if ( (NULL == srv) ||
- (off != data_size) )
- {
- GNUNET_break_op (0);
- return NULL;
- }
- GNUNET_asprintf (&result,
- "%d %d %d _%s._%s.%s",
- srv->priority,
- srv->weight,
- srv->port,
- srv->service,
- srv->proto,
- srv->domain_name);
- GNUNET_DNSPARSER_free_srv (srv);
- return result;
- }
- case GNUNET_DNSPARSER_TYPE_TLSA:
- {
- const struct GNUNET_TUN_DnsTlsaRecord *tlsa;
- char* tlsa_str;
-
- cdata = data;
- if ( (data_size <= sizeof (struct GNUNET_TUN_DnsTlsaRecord)) ||
- ('\0' != cdata[data_size - 1]) )
- return NULL; /* malformed */
- tlsa = data;
- if (0 == GNUNET_asprintf (&tlsa_str,
- "%c %c %c %s",
- tlsa->usage,
- tlsa->selector,
- tlsa->matching_type,
- (const char *) &tlsa[1]))
- {
- GNUNET_free (tlsa_str);
- return NULL;
- }
- return tlsa_str;
- }
- default:
- GNUNET_break (0);
}
- GNUNET_break (0); // not implemented
return NULL;
}
void **data,
size_t *data_size)
{
- struct in_addr value_a;
- struct in6_addr value_aaaa;
- struct GNUNET_CRYPTO_EcdsaPublicKey pkey;
- struct GNUNET_TUN_GnsVpnRecord *vpn;
- struct GNUNET_TUN_DnsTlsaRecord *tlsa;
- char s_peer[103 + 1];
- char s_serv[253 + 1];
- unsigned int proto;
-
- if (NULL == s)
- return GNUNET_SYSERR;
- switch (type)
+ unsigned int i;
+ struct Plugin *plugin;
+
+ init ();
+ for (i = 0; i < num_plugins; i++)
{
- case 0:
- LOG (GNUNET_ERROR_TYPE_ERROR,
- _("Unsupported record type %d\n"),
- (int) type);
- return GNUNET_SYSERR;
- case GNUNET_DNSPARSER_TYPE_A:
- if (1 != inet_pton (AF_INET, s, &value_a))
- {
- LOG (GNUNET_ERROR_TYPE_ERROR,
- _("Unable to parse IPv4 address `%s'\n"),
- s);
- return GNUNET_SYSERR;
- }
- *data = GNUNET_malloc (sizeof (struct in_addr));
- memcpy (*data, &value_a, sizeof (value_a));
- *data_size = sizeof (value_a);
- return GNUNET_OK;
- case GNUNET_DNSPARSER_TYPE_NS:
- {
- char nsbuf[256];
- size_t off;
-
- off = 0;
- if (GNUNET_OK !=
- GNUNET_DNSPARSER_builder_add_name (nsbuf,
- sizeof (nsbuf),
- &off,
- s))
- {
- LOG (GNUNET_ERROR_TYPE_ERROR,
- _("Failed to serialize NS record with value `%s'\n"),
- s);
- return GNUNET_SYSERR;
- }
- *data_size = off;
- *data = GNUNET_malloc (off);
- memcpy (*data, nsbuf, off);
- return GNUNET_OK;
- }
- case GNUNET_DNSPARSER_TYPE_CNAME:
- {
- char cnamebuf[256];
- size_t off;
-
- off = 0;
- if (GNUNET_OK !=
- GNUNET_DNSPARSER_builder_add_name (cnamebuf,
- sizeof (cnamebuf),
- &off,
- s))
- {
- LOG (GNUNET_ERROR_TYPE_ERROR,
- _("Failed to serialize CNAME record with value `%s'\n"),
- s);
- return GNUNET_SYSERR;
- }
- *data_size = off;
- *data = GNUNET_malloc (off);
- memcpy (*data, cnamebuf, off);
- return GNUNET_OK;
- }
- case GNUNET_DNSPARSER_TYPE_SOA:
- {
- struct GNUNET_DNSPARSER_SoaRecord soa;
- char soabuf[540];
- char soa_rname[253 + 1];
- char soa_mname[253 + 1];
- unsigned int soa_serial;
- unsigned int soa_refresh;
- unsigned int soa_retry;
- unsigned int soa_expire;
- unsigned int soa_min;
- size_t off;
-
- if (7 != SSCANF (s,
- "rname=%253s mname=%253s %u,%u,%u,%u,%u",
- soa_rname, soa_mname,
- &soa_serial, &soa_refresh, &soa_retry, &soa_expire, &soa_min))
- {
- LOG (GNUNET_ERROR_TYPE_ERROR,
- _("Unable to parse SOA record `%s'\n"),
- s);
- return GNUNET_SYSERR;
- }
- soa.mname = soa_mname;
- soa.rname = soa_rname;
- soa.serial = (uint32_t) soa_serial;
- soa.refresh =(uint32_t) soa_refresh;
- soa.retry = (uint32_t) soa_retry;
- soa.expire = (uint32_t) soa_expire;
- soa.minimum_ttl = (uint32_t) soa_min;
- off = 0;
- if (GNUNET_OK !=
- GNUNET_DNSPARSER_builder_add_soa (soabuf,
- sizeof (soabuf),
- &off,
- &soa))
- {
- LOG (GNUNET_ERROR_TYPE_ERROR,
- _("Failed to serialize SOA record with mname `%s' and rname `%s'\n"),
- soa_mname,
- soa_rname);
- return GNUNET_SYSERR;
- }
- *data_size = off;
- *data = GNUNET_malloc (off);
- memcpy (*data, soabuf, off);
- return GNUNET_OK;
- }
- case GNUNET_DNSPARSER_TYPE_PTR:
- {
- char ptrbuf[256];
- size_t off;
-
- off = 0;
- if (GNUNET_OK !=
- GNUNET_DNSPARSER_builder_add_name (ptrbuf,
- sizeof (ptrbuf),
- &off,
- s))
- {
- LOG (GNUNET_ERROR_TYPE_ERROR,
- _("Failed to serialize PTR record with value `%s'\n"),
- s);
- return GNUNET_SYSERR;
- }
- *data_size = off;
- *data = GNUNET_malloc (off);
- memcpy (*data, ptrbuf, off);
- return GNUNET_OK;
- }
- case GNUNET_DNSPARSER_TYPE_MX:
- {
- struct GNUNET_DNSPARSER_MxRecord mx;
- char mxbuf[258];
- char mxhost[253 + 1];
- uint16_t mx_pref;
- size_t off;
-
- if (2 != SSCANF(s, "%hu,%253s", &mx_pref, mxhost))
- {
- LOG (GNUNET_ERROR_TYPE_ERROR,
- _("Unable to parse MX record `%s'\n"),
- s);
- return GNUNET_SYSERR;
- }
- mx.preference = mx_pref;
- mx.mxhost = mxhost;
- off = 0;
-
- if (GNUNET_OK !=
- GNUNET_DNSPARSER_builder_add_mx (mxbuf,
- sizeof (mxbuf),
- &off,
- &mx))
- {
- LOG (GNUNET_ERROR_TYPE_ERROR,
- _("Failed to serialize MX record with hostname `%s'\n"),
- mxhost);
- return GNUNET_SYSERR;
- }
- *data_size = off;
- *data = GNUNET_malloc (off);
- memcpy (*data, mxbuf, off);
+ plugin = gns_plugins[i];
+ if (GNUNET_OK == plugin->api->string_to_value (plugin->api->cls,
+ type,
+ s,
+ data,
+ data_size))
return GNUNET_OK;
- }
- case GNUNET_DNSPARSER_TYPE_TXT:
- *data = GNUNET_strdup (s);
- *data_size = strlen (s);
- return GNUNET_OK;
- case GNUNET_DNSPARSER_TYPE_AAAA:
- if (1 != inet_pton (AF_INET6, s, &value_aaaa))
- {
- LOG (GNUNET_ERROR_TYPE_ERROR,
- _("Unable to parse IPv6 address `%s'\n"),
- s);
- return GNUNET_SYSERR;
- }
- *data = GNUNET_malloc (sizeof (struct in6_addr));
- *data_size = sizeof (struct in6_addr);
- memcpy (*data, &value_aaaa, sizeof (value_aaaa));
- return GNUNET_OK;
- case GNUNET_GNSRECORD_TYPE_PKEY:
- if (GNUNET_OK !=
- GNUNET_CRYPTO_ecdsa_public_key_from_string (s, strlen (s), &pkey))
- {
- LOG (GNUNET_ERROR_TYPE_ERROR,
- _("Unable to parse PKEY record `%s'\n"),
- s);
- return GNUNET_SYSERR;
- }
- *data = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPublicKey);
- memcpy (*data, &pkey, sizeof (pkey));
- *data_size = sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey);
- return GNUNET_OK;
- case GNUNET_GNSRECORD_TYPE_PHONE:
- {
- struct GNUNET_CONVERSATION_PhoneRecord *pr;
- unsigned int line;
- const char *dash;
- struct GNUNET_PeerIdentity peer;
-
- if ( (NULL == (dash = strchr (s, '-'))) ||
- (1 != sscanf (s, "%u-", &line)) ||
- (GNUNET_OK !=
- GNUNET_CRYPTO_eddsa_public_key_from_string (dash + 1,
- strlen (dash + 1),
- &peer.public_key)) )
- {
- LOG (GNUNET_ERROR_TYPE_ERROR,
- _("Unable to parse PHONE record `%s'\n"),
- s);
- return GNUNET_SYSERR;
- }
- pr = GNUNET_new (struct GNUNET_CONVERSATION_PhoneRecord);
- pr->version = htonl (0);
- pr->line = htonl ((uint32_t) line);
- pr->peer = peer;
- *data = pr;
- *data_size = sizeof (struct GNUNET_CONVERSATION_PhoneRecord);
- return GNUNET_OK;
- }
- case GNUNET_GNSRECORD_TYPE_PSEU:
- *data = GNUNET_strdup (s);
- *data_size = strlen (s);
- return GNUNET_OK;
- case GNUNET_GNSRECORD_TYPE_LEHO:
- *data = GNUNET_strdup (s);
- *data_size = strlen (s);
- return GNUNET_OK;
- case GNUNET_GNSRECORD_TYPE_VPN:
- if (3 != SSCANF (s,"%u %103s %253s",
- &proto, s_peer, s_serv))
- {
- LOG (GNUNET_ERROR_TYPE_ERROR,
- _("Unable to parse VPN record string `%s'\n"),
- s);
- return GNUNET_SYSERR;
- }
- *data_size = sizeof (struct GNUNET_TUN_GnsVpnRecord) + strlen (s_serv) + 1;
- *data = vpn = GNUNET_malloc (*data_size);
- if (GNUNET_OK != GNUNET_CRYPTO_eddsa_public_key_from_string ((char*) s_peer,
- strlen (s_peer),
- &vpn->peer.public_key))
- {
- GNUNET_free (vpn);
- *data_size = 0;
- return GNUNET_SYSERR;
- }
- vpn->proto = htons ((uint16_t) proto);
- strcpy ((char*)&vpn[1], s_serv);
- return GNUNET_OK;
- case GNUNET_GNSRECORD_TYPE_GNS2DNS:
- {
- char nsbuf[256];
- size_t off;
-
- off = 0;
- if (GNUNET_OK !=
- GNUNET_DNSPARSER_builder_add_name (nsbuf,
- sizeof (nsbuf),
- &off,
- s))
- {
- LOG (GNUNET_ERROR_TYPE_ERROR,
- _("Failed to serialize GNS2DNS record with value `%s'\n"),
- s);
- return GNUNET_SYSERR;
- }
- *data_size = off;
- *data = GNUNET_malloc (off);
- memcpy (*data, nsbuf, off);
- return GNUNET_OK;
- }
- case GNUNET_DNSPARSER_TYPE_TLSA:
- *data_size = sizeof (struct GNUNET_TUN_DnsTlsaRecord) + strlen (s) - 6;
- *data = tlsa = GNUNET_malloc (*data_size);
- if (4 != SSCANF (s, "%c %c %c %s",
- &tlsa->usage,
- &tlsa->selector,
- &tlsa->matching_type,
- (char*)&tlsa[1]))
- {
- LOG (GNUNET_ERROR_TYPE_ERROR,
- _("Unable to parse TLSA record string `%s'\n"),
- s);
- *data_size = 0;
- GNUNET_free (tlsa);
- return GNUNET_SYSERR;
- }
- return GNUNET_OK;
- default:
- LOG (GNUNET_ERROR_TYPE_ERROR,
- _("Unsupported record type %d\n"),
- (int) type);
- return GNUNET_SYSERR;
}
+ return GNUNET_SYSERR;
}
-/**
- * Mapping of record type numbers to human-readable
- * record type names.
- */
-static struct {
- const char *name;
- uint32_t number;
-} name_map[] = {
- { "A", GNUNET_DNSPARSER_TYPE_A },
- { "NS", GNUNET_DNSPARSER_TYPE_NS },
- { "CNAME", GNUNET_DNSPARSER_TYPE_CNAME },
- { "SOA", GNUNET_DNSPARSER_TYPE_SOA },
- { "PTR", GNUNET_DNSPARSER_TYPE_PTR },
- { "MX", GNUNET_DNSPARSER_TYPE_MX },
- { "TXT", GNUNET_DNSPARSER_TYPE_TXT },
- { "AAAA", GNUNET_DNSPARSER_TYPE_AAAA },
- { "PKEY", GNUNET_GNSRECORD_TYPE_PKEY },
- { "PSEU", GNUNET_GNSRECORD_TYPE_PSEU },
- { "LEHO", GNUNET_GNSRECORD_TYPE_LEHO },
- { "VPN", GNUNET_GNSRECORD_TYPE_VPN },
- { "GNS2DNS", GNUNET_GNSRECORD_TYPE_GNS2DNS },
- { "PHONE", GNUNET_GNSRECORD_TYPE_PHONE },
- { "TLSA", GNUNET_DNSPARSER_TYPE_TLSA },
- { NULL, UINT32_MAX }
-};
-
-
/**
* Convert a type name (i.e. "AAAA") to the corresponding number.
*
GNUNET_GNSRECORD_typename_to_number (const char *dns_typename)
{
unsigned int i;
+ struct Plugin *plugin;
+ uint32_t ret;
- i=0;
- while ( (name_map[i].name != NULL) &&
- (0 != strcasecmp (dns_typename, name_map[i].name)) )
- i++;
- return name_map[i].number;
+ init ();
+ for (i = 0; i < num_plugins; i++)
+ {
+ plugin = gns_plugins[i];
+ if (UINT32_MAX != (ret = plugin->api->typename_to_number (plugin->api->cls,
+ dns_typename)))
+ return ret;
+ }
+ return UINT32_MAX;
}
GNUNET_GNSRECORD_number_to_typename (uint32_t type)
{
unsigned int i;
+ struct Plugin *plugin;
+ const char * ret;
- i=0;
- while ( (name_map[i].name != NULL) &&
- (type != name_map[i].number) )
- i++;
- return name_map[i].name;
+ init ();
+ for (i = 0; i < num_plugins; i++)
+ {
+ plugin = gns_plugins[i];
+ if (NULL != (ret = plugin->api->number_to_typename (plugin->api->cls,
+ type)))
+ return ret;
+ }
+ return NULL;
}
-
-/* end of namestore_common.c */
+/* end of gnsrecord.c */