summaryrefslogtreecommitdiff
path: root/src/ipcpd/unicast/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/ipcpd/unicast/main.c')
-rw-r--r--src/ipcpd/unicast/main.c378
1 files changed, 378 insertions, 0 deletions
diff --git a/src/ipcpd/unicast/main.c b/src/ipcpd/unicast/main.c
new file mode 100644
index 00000000..c159b26d
--- /dev/null
+++ b/src/ipcpd/unicast/main.c
@@ -0,0 +1,378 @@
+/*
+ * Ouroboros - Copyright (C) 2016 - 2019
+ *
+ * Unicast IPC Process
+ *
+ * Dimitri Staessens <[email protected]>
+ * Sander Vrijders <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., http://www.fsf.org/about/contact/.
+ */
+
+#if defined(__linux__) || defined(__CYGWIN__)
+#define _DEFAULT_SOURCE
+#else
+#define _POSIX_C_SOURCE 200809L
+#endif
+
+#include "config.h"
+
+#define OUROBOROS_PREFIX "unicast-ipcp"
+
+#include <ouroboros/errno.h>
+#include <ouroboros/hash.h>
+#include <ouroboros/ipcp-dev.h>
+#include <ouroboros/logs.h>
+#include <ouroboros/notifier.h>
+#include <ouroboros/rib.h>
+#include <ouroboros/time_utils.h>
+
+#include "addr_auth.h"
+#include "connmgr.h"
+#include "dir.h"
+#include "dt.h"
+#include "enroll.h"
+#include "fa.h"
+#include "ipcp.h"
+
+#include <stdbool.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <inttypes.h>
+
+#define THIS_TYPE IPCP_UNICAST
+
+static int initialize_components(const struct ipcp_config * conf)
+{
+ ipcpi.layer_name = strdup(conf->layer_info.layer_name);
+ if (ipcpi.layer_name == NULL) {
+ log_err("Failed to set layer name.");
+ goto fail_layer_name;
+ }
+
+ ipcpi.dir_hash_algo = conf->layer_info.dir_hash_algo;
+
+ assert(ipcp_dir_hash_len() != 0);
+
+ if (addr_auth_init(conf->addr_auth_type,
+ &conf->addr_size)) {
+ log_err("Failed to init address authority.");
+ goto fail_addr_auth;
+ }
+
+ ipcpi.dt_addr = addr_auth_address();
+ if (ipcpi.dt_addr == 0) {
+ log_err("Failed to get a valid address.");
+ goto fail_addr_auth;
+ }
+
+ log_dbg("IPCP got address %" PRIu64 ".", ipcpi.dt_addr);
+
+ if (dt_init(conf->routing_type,
+ conf->pff_type,
+ conf->addr_size,
+ conf->eid_size,
+ conf->max_ttl)) {
+ log_err("Failed to initialize data transfer component.");
+ goto fail_dt;
+ }
+
+ if (fa_init()) {
+ log_err("Failed to initialize flow allocator component.");
+ goto fail_fa;
+ }
+
+ if (dir_init()) {
+ log_err("Failed to initialize directory.");
+ goto fail_dir;
+ }
+
+ ipcp_set_state(IPCP_INIT);
+
+ return 0;
+
+ fail_dir:
+ fa_fini();
+ fail_fa:
+ dt_fini();
+ fail_dt:
+ addr_auth_fini();
+ fail_addr_auth:
+ free(ipcpi.layer_name);
+ fail_layer_name:
+ return -1;
+}
+
+static void finalize_components(void)
+{
+ dir_fini();
+
+ fa_fini();
+
+ dt_fini();
+
+ addr_auth_fini();
+
+ free(ipcpi.layer_name);
+}
+
+static int start_components(void)
+{
+ assert(ipcp_get_state() == IPCP_INIT);
+
+ ipcp_set_state(IPCP_OPERATIONAL);
+
+ if (fa_start()) {
+ log_err("Failed to start flow allocator.");
+ goto fail_fa_start;
+ }
+
+ if (enroll_start()) {
+ log_err("Failed to start enrollment.");
+ goto fail_enroll_start;
+ }
+
+ if (connmgr_start()) {
+ log_err("Failed to start AP connection manager.");
+ goto fail_connmgr_start;
+ }
+
+ return 0;
+
+ fail_connmgr_start:
+ enroll_stop();
+ fail_enroll_start:
+ fa_stop();
+ fail_fa_start:
+ ipcp_set_state(IPCP_INIT);
+ return -1;
+}
+
+static void stop_components(void)
+{
+ assert(ipcp_get_state() == IPCP_OPERATIONAL ||
+ ipcp_get_state() == IPCP_SHUTDOWN);
+
+ connmgr_stop();
+
+ enroll_stop();
+
+ fa_stop();
+
+ ipcp_set_state(IPCP_INIT);
+}
+
+static int bootstrap_components(void)
+{
+ if (dir_bootstrap()) {
+ log_err("Failed to bootstrap directory.");
+ dt_stop();
+ return -1;
+ }
+
+ return 0;
+}
+
+static int unicast_ipcp_enroll(const char * dst,
+ struct layer_info * info)
+{
+ struct conn conn;
+
+ if (connmgr_alloc(COMPID_ENROLL, dst, NULL, &conn)) {
+ log_err("Failed to get connection.");
+ goto fail_er_flow;
+ }
+
+ /* Get boot state from peer. */
+ if (enroll_boot(&conn)) {
+ log_err("Failed to get boot information.");
+ goto fail_enroll_boot;
+ }
+
+ if (initialize_components(enroll_get_conf())) {
+ log_err("Failed to initialize IPCP components.");
+ goto fail_enroll_boot;
+ }
+
+ if (dt_start()) {
+ log_err("Failed to initialize IPCP components.");
+ goto fail_dt_start;
+ }
+
+ if (start_components()) {
+ log_err("Failed to start components.");
+ goto fail_start_comp;
+ }
+
+ if (enroll_done(&conn, 0))
+ log_warn("Failed to confirm enrollment with peer.");
+
+ if (connmgr_dealloc(COMPID_ENROLL, &conn))
+ log_warn("Failed to deallocate enrollment flow.");
+
+ log_info("Enrolled with %s.", dst);
+
+ info->dir_hash_algo = ipcpi.dir_hash_algo;
+ strcpy(info->layer_name, ipcpi.layer_name);
+
+ return 0;
+
+ fail_start_comp:
+ dt_stop();
+ fail_dt_start:
+ finalize_components();
+ fail_enroll_boot:
+ connmgr_dealloc(COMPID_ENROLL, &conn);
+ fail_er_flow:
+ return -1;
+}
+
+static int unicast_ipcp_bootstrap(const struct ipcp_config * conf)
+{
+ assert(conf);
+ assert(conf->type == THIS_TYPE);
+
+ enroll_bootstrap(conf);
+
+ if (initialize_components(conf)) {
+ log_err("Failed to init IPCP components.");
+ goto fail_init;
+ }
+
+ if (dt_start()) {
+ log_err("Failed to initialize IPCP components.");
+ goto fail_dt_start;
+ };
+
+ if (start_components()) {
+ log_err("Failed to init IPCP components.");
+ goto fail_start;
+ }
+
+ if (bootstrap_components()) {
+ log_err("Failed to bootstrap IPCP components.");
+ goto fail_bootstrap;
+ }
+
+ log_dbg("Bootstrapped in layer %s.", conf->layer_info.layer_name);
+
+ return 0;
+
+ fail_bootstrap:
+ stop_components();
+ fail_start:
+ dt_stop();
+ fail_dt_start:
+ finalize_components();
+ fail_init:
+ return -1;
+}
+
+static int unicast_ipcp_query(const uint8_t * dst)
+{
+ return dir_query(dst) ? 0 : -1;
+}
+
+static struct ipcp_ops unicast_ops = {
+ .ipcp_bootstrap = unicast_ipcp_bootstrap,
+ .ipcp_enroll = unicast_ipcp_enroll,
+ .ipcp_connect = connmgr_ipcp_connect,
+ .ipcp_disconnect = connmgr_ipcp_disconnect,
+ .ipcp_reg = dir_reg,
+ .ipcp_unreg = dir_unreg,
+ .ipcp_query = unicast_ipcp_query,
+ .ipcp_flow_alloc = fa_alloc,
+ .ipcp_flow_join = NULL,
+ .ipcp_flow_alloc_resp = fa_alloc_resp,
+ .ipcp_flow_dealloc = fa_dealloc
+};
+
+int main(int argc,
+ char * argv[])
+{
+ if (ipcp_init(argc, argv, &unicast_ops) < 0) {
+ log_err("Failed to init IPCP.");
+ goto fail_init;
+ }
+
+ /* These components must be init at creation. */
+ if (rib_init(ipcpi.name)) {
+ log_err("Failed to initialize RIB.");
+ goto fail_rib_init;
+ }
+
+ if (notifier_init()) {
+ log_err("Failed to initialize notifier component.");
+ goto fail_notifier_init;
+ }
+
+ if (connmgr_init()) {
+ log_err("Failed to initialize connection manager.");
+ goto fail_connmgr_init;
+ }
+
+ if (enroll_init()) {
+ log_err("Failed to initialize enrollment component.");
+ goto fail_enroll_init;
+ }
+
+ if (ipcp_boot() < 0) {
+ log_err("Failed to boot IPCP.");
+ goto fail_boot;
+ }
+
+ if (ipcp_create_r(0)) {
+ log_err("Failed to notify IRMd we are initialized.");
+ ipcp_set_state(IPCP_NULL);
+ goto fail_create_r;
+ }
+
+ ipcp_shutdown();
+
+ if (ipcp_get_state() == IPCP_SHUTDOWN) {
+ dt_stop();
+ stop_components();
+ finalize_components();
+ }
+
+ enroll_fini();
+
+ connmgr_fini();
+
+ notifier_fini();
+
+ rib_fini();
+
+ ipcp_fini();
+
+ exit(EXIT_SUCCESS);
+
+ fail_create_r:
+ ipcp_shutdown();
+ fail_boot:
+ enroll_fini();
+ fail_enroll_init:
+ connmgr_fini();
+ fail_connmgr_init:
+ notifier_fini();
+ fail_notifier_init:
+ rib_fini();
+ fail_rib_init:
+ ipcp_fini();
+ fail_init:
+ ipcp_create_r(-1);
+ exit(EXIT_FAILURE);
+}