aboutsummaryrefslogtreecommitdiffstats
path: root/src/libstrongswan/plugins/unbound
diff options
context:
space:
mode:
Diffstat (limited to 'src/libstrongswan/plugins/unbound')
-rw-r--r--src/libstrongswan/plugins/unbound/Makefile.am20
-rw-r--r--src/libstrongswan/plugins/unbound/unbound_plugin.c66
-rw-r--r--src/libstrongswan/plugins/unbound/unbound_plugin.h42
-rw-r--r--src/libstrongswan/plugins/unbound/unbound_resolver.c143
-rw-r--r--src/libstrongswan/plugins/unbound/unbound_resolver.h29
-rw-r--r--src/libstrongswan/plugins/unbound/unbound_response.c259
-rw-r--r--src/libstrongswan/plugins/unbound/unbound_response.h51
-rw-r--r--src/libstrongswan/plugins/unbound/unbound_rr.c164
-rw-r--r--src/libstrongswan/plugins/unbound/unbound_rr.h48
9 files changed, 822 insertions, 0 deletions
diff --git a/src/libstrongswan/plugins/unbound/Makefile.am b/src/libstrongswan/plugins/unbound/Makefile.am
new file mode 100644
index 000000000..efb313407
--- /dev/null
+++ b/src/libstrongswan/plugins/unbound/Makefile.am
@@ -0,0 +1,20 @@
+
+INCLUDES = -I$(top_srcdir)/src/libstrongswan
+
+AM_CFLAGS = -rdynamic -DIPSEC_CONFDIR=\"${sysconfdir}\"
+
+
+if MONOLITHIC
+noinst_LTLIBRARIES = libstrongswan-unbound.la
+else
+plugin_LTLIBRARIES = libstrongswan-unbound.la
+endif
+
+libstrongswan_unbound_la_SOURCES = \
+ unbound_plugin.h unbound_plugin.c \
+ unbound_resolver.c unbound_resolver.h \
+ unbound_rr.h unbound_rr.c \
+ unbound_response.h unbound_response.c
+
+libstrongswan_unbound_la_LDFLAGS = -module -avoid-version
+libstrongswan_unbound_la_LIBADD = -lunbound -lldns
diff --git a/src/libstrongswan/plugins/unbound/unbound_plugin.c b/src/libstrongswan/plugins/unbound/unbound_plugin.c
new file mode 100644
index 000000000..90b95330a
--- /dev/null
+++ b/src/libstrongswan/plugins/unbound/unbound_plugin.c
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2011-2012 Reto Guadagnini
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "unbound_plugin.h"
+
+#include <library.h>
+#include "unbound_resolver.h"
+
+typedef struct private_unbound_plugin_t private_unbound_plugin_t;
+
+/**
+ * private data of unbound_plugin
+ */
+struct private_unbound_plugin_t {
+
+ /**
+ * public functions
+ */
+ unbound_plugin_t public;
+};
+
+METHOD(plugin_t, get_name, char*,
+ private_unbound_plugin_t *this)
+{
+ return "unbound";
+}
+
+METHOD(plugin_t, destroy, void,
+ private_unbound_plugin_t *this)
+{
+ lib->resolver->remove_resolver(lib->resolver, unbound_resolver_create);
+ free(this);
+}
+
+/*
+ * see header file
+ */
+plugin_t *unbound_plugin_create()
+{
+ private_unbound_plugin_t *this;
+
+ INIT(this,
+ .public = {
+ .plugin = {
+ .get_name = _get_name,
+ .destroy = _destroy,
+ },
+ },
+ );
+
+ lib->resolver->add_resolver(lib->resolver, unbound_resolver_create);
+
+ return &this->public.plugin;
+}
diff --git a/src/libstrongswan/plugins/unbound/unbound_plugin.h b/src/libstrongswan/plugins/unbound/unbound_plugin.h
new file mode 100644
index 000000000..1f0d36454
--- /dev/null
+++ b/src/libstrongswan/plugins/unbound/unbound_plugin.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2011-2012 Reto Guadagnini
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup unbound_p unbound
+ * @ingroup plugins
+ *
+ * @defgroup unbound_plugin unbound_plugin
+ * @{ @ingroup unbound_p
+ */
+
+#ifndef unbound_PLUGIN_H_
+#define unbound_PLUGIN_H_
+
+#include <plugins/plugin.h>
+
+typedef struct unbound_plugin_t unbound_plugin_t;
+
+/**
+ * Plugin implementing the resolver interface using the libunbound DNS library.
+ */
+struct unbound_plugin_t {
+
+ /**
+ * implements plugin interface
+ */
+ plugin_t plugin;
+};
+
+#endif /** unbound_PLUGIN_H_ @}*/
diff --git a/src/libstrongswan/plugins/unbound/unbound_resolver.c b/src/libstrongswan/plugins/unbound/unbound_resolver.c
new file mode 100644
index 000000000..44a2c764b
--- /dev/null
+++ b/src/libstrongswan/plugins/unbound/unbound_resolver.c
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2011-2012 Reto Guadagnini
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include <unbound.h>
+#include <errno.h>
+#include <ldns/ldns.h>
+#include <string.h>
+
+#include <library.h>
+#include <utils/debug.h>
+
+#include "unbound_resolver.h"
+#include "unbound_response.h"
+
+/* DNS resolver configuration and DNSSEC trust anchors */
+#define RESOLV_CONF_FILE "/etc/resolv.conf"
+#define TRUST_ANCHOR_FILE IPSEC_CONFDIR "/ipsec.d/dnssec.keys"
+
+typedef struct private_resolver_t private_resolver_t;
+
+/**
+ * private data of a unbound_resolver_t object.
+ */
+struct private_resolver_t {
+
+ /**
+ * Public data
+ */
+ resolver_t public;
+
+ /**
+ * private unbound resolver handle (unbound context)
+ */
+ struct ub_ctx *ctx;
+};
+
+/**
+ * query method implementation
+ */
+METHOD(resolver_t, query, resolver_response_t*,
+ private_resolver_t *this, char *domain, rr_class_t rr_class,
+ rr_type_t rr_type)
+{
+ unbound_response_t *response = NULL;
+ struct ub_result *result = NULL;
+ int ub_retval;
+
+ ub_retval = ub_resolve(this->ctx, domain, rr_type, rr_class, &result);
+ if (ub_retval)
+ {
+ DBG1(DBG_LIB, "unbound resolver error: %s", ub_strerror(ub_retval));
+ ub_resolve_free(result);
+ return NULL;
+ }
+
+ response = unbound_response_create_frm_libub_response(result);
+ if (!response)
+ {
+ DBG1(DBG_LIB, "unbound resolver failed to create response");
+ ub_resolve_free(result);
+ return NULL;
+ }
+ ub_resolve_free(result);
+
+ return (resolver_response_t*)response;
+}
+
+/**
+ * destroy method implementation
+ */
+METHOD(resolver_t, destroy, void,
+ private_resolver_t *this)
+{
+ ub_ctx_delete(this->ctx);
+ free(this);
+}
+
+/*
+ * Described in header.
+ */
+resolver_t *unbound_resolver_create(void)
+{
+ private_resolver_t *this;
+ int ub_retval = 0;
+ char *resolv_conf_file;
+ char *trust_anchor_file;
+
+ resolv_conf_file = lib->settings->get_str(lib->settings,
+ "libstrongswan.plugins.unbound.resolv_conf",
+ RESOLV_CONF_FILE);
+
+ trust_anchor_file = lib->settings->get_str(lib->settings,
+ "libstrongswan.plugins.unbound.trust_anchors",
+ TRUST_ANCHOR_FILE);
+
+ INIT(this,
+ .public = {
+ .query = _query,
+ .destroy = _destroy,
+ },
+ );
+
+ this->ctx = ub_ctx_create();
+ if (!this->ctx)
+ {
+ DBG1(DBG_LIB, "failed to create unbound resolver context");
+ destroy(this);
+ return NULL;
+ }
+
+ DBG1(DBG_CFG, "loading unbound resolver config from '%s'", resolv_conf_file);
+ ub_retval = ub_ctx_resolvconf(this->ctx, resolv_conf_file);
+ if (ub_retval)
+ {
+ DBG1(DBG_CFG, "failed to read the resolver config: %s (%s)",
+ ub_strerror(ub_retval), strerror(errno));
+ destroy(this);
+ return NULL;
+ }
+
+ DBG1(DBG_CFG, "loading unbound trust anchors from '%s'", trust_anchor_file);
+ ub_retval = ub_ctx_add_ta_file(this->ctx, trust_anchor_file);
+ if (ub_retval)
+ {
+ DBG1(DBG_CFG, "failed to load trust anchors: %s (%s)",
+ ub_strerror(ub_retval), strerror(errno));
+ }
+
+ return &this->public;
+}
+
diff --git a/src/libstrongswan/plugins/unbound/unbound_resolver.h b/src/libstrongswan/plugins/unbound/unbound_resolver.h
new file mode 100644
index 000000000..818a717b8
--- /dev/null
+++ b/src/libstrongswan/plugins/unbound/unbound_resolver.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2011-2012 Reto Guadagnini
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup unbound_resolver unbound_resolver
+ * @{ @ingroup unbound_p
+ */
+
+#ifndef unbound_RESOLVER_H_
+#define unbound_RESOLVER_H_
+
+/**
+ * Create a resolver_t instance.
+ */
+resolver_t *unbound_resolver_create(void);
+
+#endif /** LIBunbound_RESOLVER_H_ @}*/
diff --git a/src/libstrongswan/plugins/unbound/unbound_response.c b/src/libstrongswan/plugins/unbound/unbound_response.c
new file mode 100644
index 000000000..6f6c25e89
--- /dev/null
+++ b/src/libstrongswan/plugins/unbound/unbound_response.c
@@ -0,0 +1,259 @@
+/*
+ * Copyright (C) 2012 Reto Guadagnini
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include <resolver/resolver_response.h>
+#include <resolver/rr.h>
+#include "unbound_rr.h"
+#include "unbound_response.h"
+
+#include <library.h>
+#include <utils/debug.h>
+
+#include <unbound.h>
+#include <ldns/ldns.h>
+
+typedef struct private_unbound_response_t private_unbound_response_t;
+
+/**
+ * private data of an unbound_response_t object.
+ */
+struct private_unbound_response_t {
+
+ /**
+ * Public data
+ */
+ unbound_response_t public;
+
+ /**
+ * Original question string
+ */
+ char* query_name;
+
+ /**
+ * Canonical name of the response
+ */
+ char* canon_name;
+
+ /**
+ * Are the some RRs in the RRset of this response?
+ */
+ bool has_data;
+
+ /*
+ * Does the queried name exist?
+ */
+ bool query_name_exist;
+
+ /**
+ * DNSSEC security state
+ */
+ dnssec_status_t security_state;
+
+ /**
+ * RRset
+ */
+ rr_set_t *rr_set;
+};
+
+METHOD(resolver_response_t, get_query_name, char*,
+ private_unbound_response_t *this)
+{
+ return this->query_name;
+}
+
+METHOD(resolver_response_t, get_canon_name, char*,
+ private_unbound_response_t *this)
+{
+ return this->canon_name;
+}
+
+METHOD(resolver_response_t, has_data, bool,
+ private_unbound_response_t *this)
+{
+ return this->has_data;
+}
+
+METHOD(resolver_response_t, query_name_exist, bool,
+ private_unbound_response_t *this)
+{
+ return this->query_name_exist;
+}
+
+METHOD(resolver_response_t, get_security_state, dnssec_status_t,
+ private_unbound_response_t *this)
+{
+ return this->security_state;
+}
+
+METHOD(resolver_response_t, get_rr_set, rr_set_t*,
+ private_unbound_response_t *this)
+{
+ return this->rr_set;
+}
+
+METHOD(resolver_response_t, destroy, void,
+ private_unbound_response_t *this)
+{
+ free(this->query_name);
+ free(this->canon_name);
+ DESTROY_IF(this->rr_set);
+ free(this);
+}
+
+/*
+ * Described in header.
+ */
+unbound_response_t *unbound_response_create_frm_libub_response(
+ struct ub_result *libub_response)
+{
+ private_unbound_response_t *this = NULL;
+
+ INIT(this,
+ .public = {
+ .interface = {
+ .get_query_name = _get_query_name,
+ .get_canon_name = _get_canon_name,
+ .has_data = _has_data,
+ .query_name_exist = _query_name_exist,
+ .get_security_state = _get_security_state,
+ .get_rr_set = _get_rr_set,
+ .destroy = _destroy,
+ },
+ },
+ );
+
+ this->query_name = strdup(libub_response->qname);
+
+ if (libub_response->canonname)
+ {
+ this->canon_name = strdup(libub_response->canonname);
+ }
+
+ this->has_data = libub_response->havedata;
+
+ this->query_name_exist = !(libub_response->nxdomain);
+
+ if (libub_response->secure)
+ {
+ this->security_state = SECURE;
+ }
+ else if (libub_response->bogus)
+ {
+ this->security_state = BOGUS;
+ }
+ else
+ {
+ this->security_state = INDETERMINATE;
+ }
+
+ /**
+ * Create RRset
+ */
+ if (this->query_name_exist && this->has_data)
+ {
+ ldns_pkt *dns_pkt = NULL;
+ ldns_rr_list *orig_rr_list = NULL;
+ size_t orig_rr_count;
+ ldns_rr *orig_rr = NULL;
+ ldns_rdf *orig_rdf = NULL;
+ ldns_status status;
+ linked_list_t *rr_list = NULL, *rrsig_list = NULL;
+ unbound_rr_t *rr = NULL;
+ int i;
+
+ /**Parse the received DNS packet using the ldns library */
+ status = ldns_wire2pkt(&dns_pkt, libub_response->answer_packet,
+ libub_response->answer_len);
+
+ if (status != LDNS_STATUS_OK)
+ {
+ DBG1(DBG_LIB, "failed to parse DNS packet");
+ destroy(this);
+ return NULL;
+ }
+
+ /* Create a list with the queried RRs. If there are corresponding RRSIGs
+ * create also a list with these.
+ */
+ rr_list = linked_list_create();
+
+ orig_rr_list = ldns_pkt_get_section_clone(dns_pkt, LDNS_SECTION_ANSWER);
+ orig_rr_count = ldns_rr_list_rr_count(orig_rr_list);
+
+ for (i = 0; i < orig_rr_count; i++)
+ {
+ orig_rr = ldns_rr_list_rr(orig_rr_list, i);
+
+ if (ldns_rr_get_type(orig_rr) == libub_response->qtype &&
+ ldns_rr_get_class(orig_rr) == libub_response->qclass)
+ {
+ /* RR is part of the queried RRset.
+ * => add it to the list of Resource Records.
+ */
+ rr = unbound_rr_create_frm_ldns_rr(orig_rr);
+ if (rr)
+ {
+ rr_list->insert_last(rr_list, rr);
+ }
+ else
+ {
+ DBG1(DBG_LIB, "failed to create RR");
+ }
+ }
+
+ if (ldns_rr_get_type(orig_rr) == LDNS_RR_TYPE_RRSIG)
+ {
+ orig_rdf = ldns_rr_rrsig_typecovered(orig_rr);
+ if (!orig_rdf)
+ {
+ DBG1(DBG_LIB, "failed to get the type covered by an RRSIG");
+ }
+ else if (ldns_rdf2native_int16(orig_rdf) == libub_response->qtype)
+ {
+ /* The current RR represent a signature (RRSIG)
+ * which belongs to the queried RRset.
+ * => add it to the list of signatures.
+ */
+ rr = unbound_rr_create_frm_ldns_rr(orig_rr);
+ if (rr)
+ {
+ if (!rrsig_list)
+ {
+ rrsig_list = linked_list_create();
+ }
+ rrsig_list->insert_last(rrsig_list, rr);
+ }
+ else
+ {
+ DBG1(DBG_LIB, "failed to create RRSIG");
+ }
+ }
+ else
+ {
+ DBG1(DBG_LIB, "failed to determine the RR type "
+ "covered by RRSIG RR");
+ }
+ }
+ }
+ /**
+ * Create the RRset for which the query was performed.
+ */
+ this->rr_set = rr_set_create(rr_list, rrsig_list);
+
+ ldns_pkt_free(dns_pkt);
+ ldns_rr_list_free(orig_rr_list);
+ }
+ return &this->public;
+}
diff --git a/src/libstrongswan/plugins/unbound/unbound_response.h b/src/libstrongswan/plugins/unbound/unbound_response.h
new file mode 100644
index 000000000..d63ead08b
--- /dev/null
+++ b/src/libstrongswan/plugins/unbound/unbound_response.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2012 Reto Guadagnini
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup unbound_response unbound_response
+ * @{ @ingroup unbound_p
+ */
+
+#ifndef UNBOUND_RESPONSE_H_
+#define UNBOUND_RESPONSE_H_
+
+#include <resolver/resolver_response.h>
+#include <unbound.h>
+
+typedef struct unbound_response_t unbound_response_t;
+
+/**
+ * Implementation of the resolver_response interface using libunbound.
+ *
+ */
+struct unbound_response_t {
+
+ /**
+ * Implements the resolver_response interface
+ */
+ resolver_response_t interface;
+};
+
+/**
+ * Create an unbound_response instance from a response of the unbound library.
+ *
+ * @param a response of the unbound library
+ * @return an unbound_response conforming to the resolver_response
+ * interface, or NULL on failure
+ */
+unbound_response_t *unbound_response_create_frm_libub_response(
+ struct ub_result *libub_response);
+
+#endif /** UNBOUND_RESPONSE_H_ @}*/
diff --git a/src/libstrongswan/plugins/unbound/unbound_rr.c b/src/libstrongswan/plugins/unbound/unbound_rr.c
new file mode 100644
index 000000000..97c3b1933
--- /dev/null
+++ b/src/libstrongswan/plugins/unbound/unbound_rr.c
@@ -0,0 +1,164 @@
+/*
+ * Copyright (C) 2012 Reto Guadagnini
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include <resolver/rr.h>
+
+#include <library.h>
+#include <utils/debug.h>
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "unbound_rr.h"
+
+typedef struct private_unbound_rr_t private_unbound_rr_t;
+
+/**
+ * private data of an unbound_rr_t object.
+ */
+struct private_unbound_rr_t {
+
+ /**
+ * Public data
+ */
+ unbound_rr_t public;
+
+ /**
+ * Owner name
+ */
+ char* name;
+
+ /**
+ * Type
+ */
+ rr_type_t type;
+
+ /**
+ * Class
+ */
+ rr_class_t class;
+
+ /**
+ * TTL
+ */
+ uint32_t ttl;
+
+ /**
+ * Size of the rdata field in octets
+ */
+ uint16_t size;
+
+ /**
+ * RDATA field (array of bytes in network order)
+ */
+ u_char *rdata;
+};
+
+METHOD(rr_t, get_name, char *,
+ private_unbound_rr_t *this)
+{
+ return this->name;
+}
+
+METHOD(rr_t, get_type, rr_type_t,
+ private_unbound_rr_t *this)
+{
+ return this->type;
+}
+
+METHOD(rr_t, get_class, rr_class_t,
+ private_unbound_rr_t *this)
+{
+ return this->class;
+}
+
+METHOD(rr_t, get_ttl, uint32_t,
+ private_unbound_rr_t *this)
+{
+ return this->ttl;
+}
+
+METHOD(rr_t, get_rdata, chunk_t,
+ private_unbound_rr_t *this)
+{
+ return chunk_create(this->rdata, this->size);
+}
+
+METHOD(rr_t, destroy, void,
+ private_unbound_rr_t *this)
+{
+ free(this->name);
+ free(this->rdata);
+ free(this);
+}
+
+/*
+ * Described in header.
+ */
+unbound_rr_t *unbound_rr_create_frm_ldns_rr(ldns_rr *rr)
+{
+ private_unbound_rr_t *this;
+ ldns_status status;
+ ldns_buffer *buf;
+ int i;
+
+ INIT(this,
+ .public = {
+ .interface = {
+ .get_name = _get_name,
+ .get_type = _get_type,
+ .get_class = _get_class,
+ .get_ttl = _get_ttl,
+ .get_rdata = _get_rdata,
+ .destroy = _destroy,
+ },
+ },
+ );
+
+ this->name = ldns_rdf2str(ldns_rr_owner(rr));
+ if (!this->name)
+ {
+ DBG1(DBG_LIB, "failed to parse the owner name of a DNS RR");
+ _destroy(this);
+ return NULL;
+ }
+
+ this->type = ldns_rr_get_type(rr);
+ this->class = ldns_rr_get_class(rr);
+ this->ttl = ldns_rr_ttl(rr);
+ for(i = 0; i < ldns_rr_rd_count(rr); i++)
+ {
+ this->size += ldns_rdf_size(ldns_rr_rdf(rr, i));
+ }
+
+ /**
+ * The ldns library splits the RDATA field of a RR in various rdf.
+ * Here we reassemble these rdf to get the RDATA field of the RR.
+ */
+ buf = ldns_buffer_new(LDNS_MIN_BUFLEN);
+ /* The buffer will be resized automatically by ldns_rr_rdata2buffer_wire() */
+ status = ldns_rr_rdata2buffer_wire(buf, rr);
+
+ if (status != LDNS_STATUS_OK)
+ {
+ DBG1(DBG_LIB, "failed to get the RDATA field of a DNS RR");
+ _destroy(this);
+ return NULL;
+ }
+
+ this->rdata = ldns_buffer_export(buf);
+
+ return &this->public;
+}
diff --git a/src/libstrongswan/plugins/unbound/unbound_rr.h b/src/libstrongswan/plugins/unbound/unbound_rr.h
new file mode 100644
index 000000000..d7c114f86
--- /dev/null
+++ b/src/libstrongswan/plugins/unbound/unbound_rr.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2012 Reto Guadagnini
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup unbound_rr unbound_rr
+ * @{ @ingroup unbound_p
+ */
+
+#ifndef UNBOUND_RR_H_
+#define UNBOUND_RR_H_
+
+#include <resolver/rr.h>
+#include <ldns/ldns.h>
+
+typedef struct unbound_rr_t unbound_rr_t;
+
+/**
+ * Implementation of the Resource Record interface using libunbound and libldns.
+ */
+struct unbound_rr_t {
+
+ /**
+ * Implements the Resource Record interface
+ */
+ rr_t interface;
+};
+
+/**
+ * Create an unbound_rr instance from a Resource Record given by
+ * a ldns_struct_rr from the ldns library.
+ *
+ * @return Resource Record, NULL on error
+ */
+unbound_rr_t *unbound_rr_create_frm_ldns_rr(ldns_rr *rr);
+
+#endif /** UNBOUND_RR_H_ @}*/