diff --git a/include/toxcore/toxcore/genode_logger.h b/include/toxcore/toxcore/genode_logger.h
new file mode 100644
index 0000000..690f722
--- /dev/null
+++ b/include/toxcore/toxcore/genode_logger.h
@@ -0,0 +1,72 @@
+/*
+ * Text logging abstraction.
+ */
+
+/*
+ * This file is part of Tox, the free peer to peer instant messenger.
+ *
+ * Tox 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Tox 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Tox. If not, see .
+ */
+
+#ifndef _TOXCORE__GENODE_LOGGER_H_
+#define _TOXCORE__GENODE_LOGGER_H_
+
+
+/* Libc includes */
+#include
+#include
+#include
+#include
+
+/* Genode includes */
+#include
+
+
+namespace Toxcore {
+
+/* Toxcore includes */
+extern "C" {
+#include "toxcore/logger.h"
+}
+
+ static void logger_genode_handler(void *context, Logger_Level level,
+ const char *file, int line, const char *func,
+ const char *message, void *userdata)
+ {
+ (void)context;
+ (void)userdata;
+
+ switch (level) {
+ case LOGGER_LEVEL_ERROR:
+ Genode::error(file, ":", line, "(", func, "): ", message);\
+ break;
+ case LOGGER_LEVEL_WARNING:
+ Genode::warning(file, ":", line, "(", func, "): ", message);
+ break;
+ default:
+ Genode::log(file, ":", line, "(", func, "): ", message);
+ break;
+ }
+ }
+
+ Logger *new_genode_logger()
+ {
+ Logger *l = logger_new();
+ logger_callback_log(l, logger_genode_handler, nullptr, nullptr);
+ return l;
+ }
+
+}
+
+#endif
diff --git a/lib/import/import-c-toxcore.mk b/lib/import/import-c-toxcore.mk
new file mode 100644
index 0000000..3af463d
--- /dev/null
+++ b/lib/import/import-c-toxcore.mk
@@ -0,0 +1,4 @@
+TOXCORE_PORT_DIR := $(call select_from_ports,c-toxcore)
+
+INC_DIR += $(TOXCORE_PORT_DIR)/include
+INC_DIR += $(call select_from_repositories,include/toxcore)
diff --git a/lib/mk/c-toxcore.mk b/lib/mk/c-toxcore.mk
new file mode 100644
index 0000000..6d33d3f
--- /dev/null
+++ b/lib/mk/c-toxcore.mk
@@ -0,0 +1,17 @@
+include $(REP_DIR)/lib/import/import-c-toxcore.mk
+
+TOXCORE_SRC_DIR = $(TOXCORE_PORT_DIR)/src/lib/c-toxcore
+
+CC_C_OPT += -std=c99 -D_XOPEN_SOURCE
+
+INC_DIR += $(TOXCORE_SRC_DIR)/toxcore
+
+TOXCORE_SRC_C := $(notdir $(wildcard $(TOXCORE_SRC_DIR)/toxcore/*.c))
+
+SRC_C += $(filter-out $(TOXCORE_SRC_FILTER),$(TOXCORE_SRC_C))
+
+LIBS := libsodium libc
+
+vpath %.c $(TOXCORE_SRC_DIR)/toxcore
+
+SHARED_LIB = yes
diff --git a/ports/c-toxcore.hash b/ports/c-toxcore.hash
new file mode 100644
index 0000000..04b931d
--- /dev/null
+++ b/ports/c-toxcore.hash
@@ -0,0 +1 @@
+a240750d0b89cfddd31bb9f79484e93fc83561a4
diff --git a/ports/c-toxcore.port b/ports/c-toxcore.port
new file mode 100644
index 0000000..2b59db2
--- /dev/null
+++ b/ports/c-toxcore.port
@@ -0,0 +1,13 @@
+LICENSE := GPLv3
+VERSION := 0.2.8
+DOWNLOADS := c-toxcore.archive
+
+OWNER := TokTok
+REPO := c-toxcore
+REV := 3f35a84968f100e1e6d3c9df467fd3c82a9ebb13
+URL(c-toxcore) := https://github.com/$(OWNER)/$(REPO)/archive/$(REV).tar.gz
+SHA(c-toxcore) := ff67bf686f5322c3b5a08d0562d5e6fd20e26cf9f4aebba78b948c8f365dae8e
+DIR(c-toxcore) := src/lib/c-toxcore
+
+DIRS := include/toxcore
+DIR_CONTENT(include/toxcore) = src/lib/c-toxcore/toxcore/*.h
diff --git a/run/tox_dht_bootstrap.run b/run/tox_dht_bootstrap.run
new file mode 100644
index 0000000..f9cccdb
--- /dev/null
+++ b/run/tox_dht_bootstrap.run
@@ -0,0 +1,144 @@
+#
+# \brief Test of Tox DHT bootstrap daemon
+# \author Emery Hemingway
+#
+
+if {[have_spec odroid_xu] || [have_spec linux] ||
+ [expr [have_spec imx53] && [have_spec trustzone]]} {
+ puts "Run script does not support this platform."
+ exit 0
+}
+
+set build_components {
+ app/tox_dht_bootstrap
+ drivers/nic
+ lib/vfs/import
+ lib/vfs/lwip
+ server/report_rom
+}
+
+proc gpio_drv { } { if {[have_spec rpi] && [have_spec hw]} { return hw_gpio_drv }
+ if {[have_spec rpi] && [have_spec foc]} { return foc_gpio_drv }
+ return gpio_drv }
+
+lappend_if [have_spec gpio] build_components drivers/gpio
+
+source ${genode_dir}/repos/base/run/platform_drv.inc
+append_platform_drv_build_components
+
+lappend_if [expr {[nic_drv_binary] == "nic_drv"}] build_components drivers/nic
+lappend_if [expr {[nic_drv_binary] == "usb_drv"}] build_components drivers/usb
+
+build $build_components
+
+create_boot_directory
+
+import_from_depot \
+ genodelabs/src/[base_src] \
+ genodelabs/src/init \
+
+append config {
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ }
+
+append_platform_drv_config
+
+append_if [have_spec gpio] config "
+
+
+
+
+ "
+
+append config {
+
+
+
+
+
+
+
+
+ } [nic_drv_config] {
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 2000-01-01 00:00
+ 01234567890123456789
+ 01234567890123456789
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+}
+
+install_config $config
+
+# generic modules
+set boot_modules {
+ libc.lib.so
+ libm.lib.so
+ libsodium.lib.so
+ posix.lib.so
+ c-toxcore.lib.so
+ tox_dht_bootstrap
+ vfs.lib.so
+ vfs_lwip.lib.so
+ report_rom
+}
+
+# platform-specific modules
+append_platform_drv_boot_modules
+
+lappend boot_modules [nic_drv_binary]
+
+lappend_if [have_spec gpio] boot_modules [gpio_drv]
+
+build_boot_image $boot_modules
+
+append_if [have_spec x86] qemu_args " -net nic,model=e1000 "
+append_if [have_spec lan9118] qemu_args " -net nic,model=lan9118 "
+append qemu_args " -net user -net dump,file=[run_dir].pcap"
+append qemu_args " -nographic"
+
+run_genode_until forever
diff --git a/src/app/tox_dht_bootstrap/component.cc b/src/app/tox_dht_bootstrap/component.cc
new file mode 100644
index 0000000..cbffbb6
--- /dev/null
+++ b/src/app/tox_dht_bootstrap/component.cc
@@ -0,0 +1,272 @@
+/*
+ * A simple DHT boostrap node for tox.
+ */
+
+/*
+ * Copyright © 2018 Genode Labs GmbH
+ *
+ * This file is part of Tox, the free peer to peer instant messenger.
+ *
+ * Tox 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Tox 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Tox. If not, see .
+ */
+
+extern "C" {
+#include "toxcore/tox.h"
+#include "toxcore/DHT.h"
+#include "toxcore/LAN_discovery.h"
+#include "toxcore/friend_requests.h"
+#include "toxcore/logger.h"
+#include "toxcore/mono_time.h"
+#include "toxcore/tox.h"
+#include "toxcore/util.h"
+}
+#include "toxcore/genode_logger.h"
+
+/* Genode includes */
+#include
+#include
+#include
+
+
+namespace Tox_dht_bootstrap {
+
+struct Main;
+
+enum {
+ IPV6_ENABLE = false,
+ PORT = 33445
+};
+
+
+typedef Genode::String<65> Key_string;
+
+
+static bool non_zero(Client_data const &peer)
+{
+ for (int i = 0; i < CRYPTO_PUBLIC_KEY_SIZE; ++i)
+ if (peer.public_key[i]) return true;
+ return false;
+}
+
+
+static Key_string encode_key(uint8_t const *bin)
+{
+ static const char alphabet[] = {
+ '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'A', 'B', 'C', 'D', 'E', 'F',
+ };
+
+ char buf[CRYPTO_PUBLIC_KEY_SIZE*2];
+ for (int i = 0; i < CRYPTO_PUBLIC_KEY_SIZE; ++i) {
+ buf[(i<<1)] = alphabet[bin[i]>>4];
+ buf[(i<<1)|1] = alphabet[bin[i]&0xf];
+ }
+
+ return Key_string(Genode::Cstring(buf, CRYPTO_PUBLIC_KEY_SIZE*2));
+}
+
+static uint8_t *hex_string_to_bin(const char *hex_string)
+{
+ if (strlen(hex_string) % 2 != 0) {
+ return nullptr;
+ }
+
+ size_t len = strlen(hex_string) / 2;
+ uint8_t *ret = (uint8_t *)malloc(len);
+
+ const char *pos = hex_string;
+ size_t i;
+
+ for (i = 0; i < len; ++i, pos += 2) {
+ unsigned int val;
+ sscanf(pos, "%02x", &val);
+ ret[i] = val;
+ }
+
+ return ret;
+}
+
+
+void bootstrap_from_config(DHT *dht, Genode::Xml_node const &config)
+{
+ typedef Genode::String Key;
+ typedef Genode::String Host;
+
+ auto const bs_fn = [&] (Genode::Xml_node const &node) {
+ Key key;
+ Host host;
+ uint16_t port = PORT;
+
+ try {
+ node.attribute("ip").value(&host);
+ node.attribute("key").value(&key);
+ port = node.attribute_value("port", port);
+ }
+ catch (...) {
+ Genode::error("Invalid bootstrap node ", node);
+ return;
+ }
+
+ uint8_t *bootstrap_key = hex_string_to_bin(key.string());
+ int res = dht_bootstrap_from_address(
+ dht, host.string(), IPV6_ENABLE, net_htons(port), bootstrap_key);
+ free(bootstrap_key);
+ if (!res)
+ Genode::error("Failed to connect to ", node);
+ };
+
+ config.for_each_sub_node("bootstrap", bs_fn);
+}
+
+}
+
+
+struct Tox_dht_bootstrap::Main
+{
+ Main(const Main&);
+ Main &operator=(const Main&);
+
+ Libc::Env &_env;
+
+ Timer::Connection _timer { _env, "periodic-timeout" };
+
+ Genode::Expanding_reporter _reporter { _env, "dht_state", "dht_state" };
+
+ Logger *logger = Toxcore::new_genode_logger();
+
+ Mono_Time *_mono_time = mono_time_new();
+
+ uint64_t last_LANdiscovery = 0;
+
+ int is_waiting_for_dht_connection = 1;
+
+ DHT *init_dht()
+ {
+ /* Initialize networking -
+ Bind to ip 0.0.0.0 / [::] : PORT */
+ IP ip;
+ ip_init(&ip, IPV6_ENABLE);
+
+ DHT *dht = new_dht(logger, _mono_time, new_networking(logger, ip, PORT), true);
+ Onion *onion = new_onion(_mono_time, dht);
+ Onion_Announce *onion_a = new_onion_announce(_mono_time, dht);
+
+ if (!(onion && onion_a)) {
+ Genode::error("Something failed to initialize");
+ exit(1);
+ }
+
+ Genode::log("Listening on UDP port ", net_ntohs(net_port(dht_get_net(dht))));
+
+ _env.config([&] (Genode::Xml_node const &config) {
+ bootstrap_from_config(dht, config); });
+
+ lan_discovery_init(dht);
+
+ _env.config([&] (Genode::Xml_node const &config) {
+ config.for_each_sub_node("report", [&] (Genode::Xml_node const &node) {
+ if (node.attribute_value("dht", false)) {
+ _report_timeout.construct(_timer, *this, &Main::report, Genode::Microseconds(4*1000*1000));
+ }
+ });
+ });
+
+ return dht;
+ }
+
+ DHT *_dht = init_dht();
+
+ Timer::Periodic_timeout _periodic_timeout {
+ _timer, *this, &Main::run, Genode::Microseconds(1000*1000) };
+
+ Genode::Constructible> _report_timeout { };
+
+ Main(Libc::Env &env) : _env(env) { }
+
+
+ void report(Genode::Duration);
+ void run(Genode::Duration);
+
+ template
+ void for_each_close_peer(FUNC const &func)
+ {
+ for (uint32_t i = 0; i < LCLIENT_LIST; i += LCLIENT_NODES) {
+ for (uint32_t j = 0; j < LCLIENT_NODES; ++j) {
+ Client_data const *peer = dht_get_close_client(_dht, i+j);
+ if (!non_zero(*peer)) break;
+ func((Client_data const &)*peer);
+ }
+ }
+ }
+};
+
+
+void Tox_dht_bootstrap::Main::report(Genode::Duration)
+{
+ mono_time_update(_mono_time);
+
+ Libc::with_libc([&] () {
+ _reporter.generate([&] (Genode::Xml_generator &gen) {
+ uint64_t now = mono_time_get(_mono_time);
+ gen.attribute("timestamp", now);
+ gen.node("base", [&] () {
+ gen.attribute("public", encode_key(dht_get_self_public_key(_dht)));
+ //gen.attribute("secret", encode_key(dht_get_self_secret_key(_dht)));
+ });
+
+ for_each_close_peer([&] (Client_data const &peer) {
+ gen.node("close", [&] () {
+ gen.attribute("public", encode_key(peer.public_key));
+
+ char ip_buf[IP_NTOA_LEN];
+ ip_ntoa(&peer.assoc4.ip_port.ip, ip_buf, sizeof(ip_buf));
+ gen.attribute("ip", (char const *)ip_buf);
+ gen.attribute("port", peer.assoc4.ip_port.port);
+ gen.attribute("timestamp", now - peer.assoc4.timestamp);
+ gen.attribute("last_pinged", now - peer.assoc4.last_pinged);
+ });
+ });
+ });
+ });
+}
+
+
+void Tox_dht_bootstrap::Main::run(Genode::Duration)
+{
+ Libc::with_libc([&] () {
+ mono_time_update(_mono_time);
+
+ if (is_waiting_for_dht_connection && dht_isconnected(_dht)) {
+ Genode::log("Connected to other bootstrap node successfully.\n");
+ is_waiting_for_dht_connection = 0;
+ }
+
+ do_dht(_dht);
+
+ if (mono_time_is_timeout(_mono_time, last_LANdiscovery, is_waiting_for_dht_connection ? 5 : LAN_DISCOVERY_INTERVAL)) {
+ lan_discovery_send(net_htons(PORT), _dht);
+ last_LANdiscovery = mono_time_get(_mono_time);
+ }
+
+ networking_poll(dht_get_net(_dht), nullptr);
+ });
+}
+
+
+void Libc::Component::construct(Libc::Env &env)
+{
+ Libc::with_libc([&] () {
+ static Tox_dht_bootstrap::Main inst(env);
+ });
+}
diff --git a/src/app/tox_dht_bootstrap/target.mk b/src/app/tox_dht_bootstrap/target.mk
new file mode 100644
index 0000000..6b45b60
--- /dev/null
+++ b/src/app/tox_dht_bootstrap/target.mk
@@ -0,0 +1,7 @@
+TARGET = tox_dht_bootstrap
+LIBS += c-toxcore libc
+SRC_CC += component.cc
+
+TOX_PORT := $(call select_from_ports,c-toxcore)
+
+INC_DIR += $(TOX_PORT)/src/lib/toxcore/other