summaryrefslogtreecommitdiff
path: root/src/ipcpd/normal/enroll.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/ipcpd/normal/enroll.c')
-rw-r--r--src/ipcpd/normal/enroll.c457
1 files changed, 246 insertions, 211 deletions
diff --git a/src/ipcpd/normal/enroll.c b/src/ipcpd/normal/enroll.c
index a33239a0..7f93ed3a 100644
--- a/src/ipcpd/normal/enroll.c
+++ b/src/ipcpd/normal/enroll.c
@@ -22,19 +22,19 @@
#define _POSIX_C_SOURCE 199309L
-#define OUROBOROS_PREFIX "enrollment"
+#define OUROBOROS_PREFIX "Enrollment"
#include <ouroboros/endian.h>
#include <ouroboros/errno.h>
-#include <ouroboros/cdap.h>
#include <ouroboros/time_utils.h>
#include <ouroboros/dev.h>
#include <ouroboros/logs.h>
#include <ouroboros/rib.h>
#include <ouroboros/errno.h>
-#include "ae.h"
#include "connmgr.h"
+#include "enroll.h"
+#include "ipcp.h"
#include "ribconfig.h"
#include <assert.h>
@@ -42,302 +42,337 @@
#include <string.h>
#include <pthread.h>
-/* Symbolic, will return current time */
-#define TIME_NAME "localtime"
-#define TIME_PATH DLR TIME_NAME
+#include "enroll.pb-c.h"
+typedef EnrollMsg enroll_msg_t;
+typedef IpcpConfigMsg ipcp_config_msg_t;
+typedef DifInfoMsg dif_info_msg_t;
+
+#define ENROLL_AE "Enrollment"
+#define ENROLL_PROTO "OEP" /* Ouroboros enrollment protocol */
#define ENROLL_WARN_TIME_OFFSET 20
+#define ENROLL_BUF_LEN 1024
+
+enum enroll_state {
+ ENROLL_NULL = 0,
+ ENROLL_INIT,
+ ENROLL_RUNNING
+};
struct {
- struct ae * ae;
- struct cdap * cdap;
- pthread_t listener;
+ struct ipcp_config conf;
+ enum enroll_state state;
+ pthread_t listener;
} enroll;
-static void * enroll_handle(void * o)
+static int send_rcv_enroll_msg(int fd)
{
- struct cdap * cdap;
- struct conn conn;
- cdap_key_t key;
- enum cdap_opcode oc;
- char * name;
- uint8_t * buf;
- uint8_t * data;
- ssize_t len;
- uint32_t flags;
+ enroll_msg_t req = ENROLL_MSG__INIT;
+ enroll_msg_t * reply;
+ uint8_t buf[ENROLL_BUF_LEN];
+ ssize_t len;
+ ssize_t delta_t;
+ struct timespec t0;
+ struct timespec rtt;
- bool boot_r = false;
- bool members_r = false;
+ req.code = ENROLL_CODE__ENROLL_REQ;
- char * boot_ro = BOOT_PATH;
- char * members_ro = MEMBERS_PATH;
+ len = enroll_msg__get_packed_size(&req);
+ if (len < 0) {
+ log_dbg("Failed pack request message.");
+ return -1;
+ }
- cdap = (struct cdap *) o;
+ enroll_msg__pack(&req, buf);
- assert(cdap);
+ clock_gettime(CLOCK_REALTIME, &t0);
- while (true) {
- if (connmgr_wait(enroll.ae, &conn)) {
- log_err("Failed to get next connection.");
- continue;
- }
+ if (flow_write(fd, buf, len)) {
+ log_dbg("Failed to send request message.");
+ return -1;
+ }
- if (cdap_add_flow(cdap, conn.flow_info.fd)) {
- log_warn("Failed to add flow to CDAP.");
- flow_dealloc(conn.flow_info.fd);
- continue;
- }
+ len = flow_read(fd, buf, ENROLL_BUF_LEN);
+ if (len < 0) {
+ log_dbg("No enrollment reply received.");
+ return -1;
+ }
- while (!(boot_r && members_r)) {
- key = cdap_request_wait(cdap, &oc, &name, &data,
- (size_t *) &len , &flags);
- assert(key >= 0);
- assert(name);
-
- if (data != NULL) {
- free(data);
- log_warn("Received data with enroll request.");
- }
-
- if (oc != CDAP_READ) {
- log_warn("Invalid request.");
- cdap_reply_send(cdap, key, -1, NULL, 0);
- free(name);
- continue;
- }
-
- if (strcmp(name, boot_ro) == 0) {
- boot_r = true;
- } else if (strcmp(name, members_ro) == 0) {
- members_r = true;
- } else if (strcmp(name, TIME_PATH) == 0) {
- struct timespec t;
- uint64_t buf[2];
- clock_gettime(CLOCK_REALTIME, &t);
- buf[0] = hton64(t.tv_sec);
- buf[1] = hton64(t.tv_nsec);
- cdap_reply_send(cdap, key, 0, buf, sizeof(buf));
- free(name);
- continue;
- } else {
- log_warn("Illegal read: %s.", name);
- cdap_reply_send(cdap, key, -1, NULL, 0);
- free(name);
- continue;
- }
-
- len = rib_pack(name, &buf, PACK_HASH_ROOT);
- if (len < 0) {
- log_err("Failed to pack %s.", name);
- cdap_reply_send(cdap, key, -1, NULL, 0);
- free(name);
- continue;
- }
-
- log_dbg("Packed %s (%zu bytes).", name, len);
-
- free(name);
-
- if (cdap_reply_send(cdap, key, 0, buf, len)) {
- log_err("Failed to send CDAP reply.");
- free(buf);
- continue;
- }
-
- free(buf);
- }
+ log_dbg("Received enrollment info (%zd bytes).", len);
- log_dbg("Sent boot info to new member.");
+ reply = enroll_msg__unpack(NULL, len, buf);
+ if (reply == NULL) {
+ log_dbg("No enrollment response.");
+ return -1;
+ }
- cdap_del_flow(cdap, conn.flow_info.fd);
- flow_dealloc(conn.flow_info.fd);
+ if (reply->code != ENROLL_CODE__ENROLL_BOOT) {
+ log_dbg("Failed to unpack enrollment response.");
+ enroll_msg__free_unpacked(reply, NULL);
+ return -1;
+ }
- boot_r = members_r = false;
+ if (!(reply->has_t_sec && reply->has_t_nsec)) {
+ log_dbg("No time in response message.");
+ enroll_msg__free_unpacked(reply, NULL);
+ return -1;
}
+ clock_gettime(CLOCK_REALTIME, &rtt);
+
+ delta_t = ts_diff_ms(&t0, &rtt);
+
+ rtt.tv_sec = reply->t_sec;
+ rtt.tv_nsec = reply->t_nsec;
+
+ if (labs(ts_diff_ms(&t0, &rtt)) - delta_t > ENROLL_WARN_TIME_OFFSET)
+ log_warn("Clock offset above threshold.");
+
+ strcpy(enroll.conf.dif_info.dif_name, reply->conf->dif_info->dif_name);
+ enroll.conf.type = reply->conf->ipcp_type;
+ enroll.conf.addr_size = reply->conf->addr_size;
+ enroll.conf.fd_size = reply->conf->fd_size;
+ enroll.conf.has_ttl = reply->conf->has_ttl;
+ enroll.conf.addr_auth_type = reply->conf->addr_auth_type;
+ enroll.conf.routing_type = reply->conf->routing_type;
+ enroll.conf.dif_info.dir_hash_algo
+ = reply->conf->dif_info->dir_hash_algo;
+
+ enroll_msg__free_unpacked(reply, NULL);
+
return 0;
}
-int enroll_boot(const char * dst)
+static ssize_t enroll_pack(uint8_t ** buf)
{
- struct cdap * cdap;
- cdap_key_t * key;
- uint8_t * data;
- size_t len;
- struct conn conn;
+ enroll_msg_t msg = ENROLL_MSG__INIT;
+ ipcp_config_msg_t config = IPCP_CONFIG_MSG__INIT;
+ dif_info_msg_t dif_info = DIF_INFO_MSG__INIT;
+ struct timespec now;
+ ssize_t len;
+
+ clock_gettime(CLOCK_REALTIME, &now);
+
+ msg.code = ENROLL_CODE__ENROLL_BOOT;
+ msg.has_t_sec = true;
+ msg.t_sec = now.tv_sec;
+ msg.has_t_nsec = true;
+ msg.t_nsec = now.tv_nsec;
+ msg.conf = &config;
+
+ config.ipcp_type = enroll.conf.type;
+ config.has_addr_size = true;
+ config.addr_size = enroll.conf.addr_size;
+ config.has_fd_size = true;
+ config.fd_size = enroll.conf.fd_size;
+ config.has_has_ttl = true;
+ config.has_ttl = enroll.conf.has_ttl;
+ config.has_addr_auth_type = true;
+ config.addr_auth_type = enroll.conf.addr_auth_type;
+ config.has_routing_type = true;
+ config.routing_type = enroll.conf.routing_type;
+ config.dif_info = &dif_info;
+
+ dif_info.dif_name = (char *) enroll.conf.dif_info.dif_name;
+ dif_info.dir_hash_algo = enroll.conf.dif_info.dir_hash_algo;
+
+ len = enroll_msg__get_packed_size(&msg);
+
+ *buf = malloc(len);
+ if (*buf == NULL)
+ return -1;
- struct timespec t0;
- struct timespec rtt;
+ enroll_msg__pack(&msg, *buf);
- ssize_t delta_t;
+ return len;
+}
- char * boot_ro = BOOT_PATH;
- char * members_ro = MEMBERS_PATH;
+static void * enroll_handle(void * o)
+{
+ struct conn conn;
+ uint8_t buf[ENROLL_BUF_LEN];
+ uint8_t * reply;
+ ssize_t len;
+ enroll_msg_t * msg;
- cdap = cdap_create();
- if (cdap == NULL) {
- log_err("Failed to instantiate CDAP.");
- return -1;
- }
+ (void) o;
- if (connmgr_alloc(enroll.ae, dst, NULL, &conn)) {
- log_err("Failed to get connection.");
- cdap_destroy(cdap);
- return -1;
- }
+ while (true) {
+ if (connmgr_wait(AEID_ENROLL, &conn)) {
+ log_err("Failed to get next connection.");
+ continue;
+ }
- if (cdap_add_flow(cdap, conn.flow_info.fd)) {
- log_warn("Failed to add flow to CDAP.");
- cdap_destroy(cdap);
- flow_dealloc(conn.flow_info.fd);
- return -1;
- }
+ len = flow_read(conn.flow_info.fd, buf, ENROLL_BUF_LEN);
+ if (len < 0) {
+ log_err("Failed to read from flow.");
+ connmgr_dealloc(AEID_ENROLL, &conn);
+ continue;
+ }
- log_dbg("Getting boot information from %s.", dst);
+ msg = enroll_msg__unpack(NULL, len, buf);
+ if (msg == NULL) {
+ log_err("Failed to unpack message.");
+ connmgr_dealloc(AEID_ENROLL, &conn);
+ continue;
+ }
- clock_gettime(CLOCK_REALTIME, &t0);
+ if (msg->code != ENROLL_CODE__ENROLL_REQ) {
+ log_err("Wrong message type.");
+ connmgr_dealloc(AEID_ENROLL, &conn);
+ enroll_msg__free_unpacked(msg, NULL);
+ continue;
+ }
- key = cdap_request_send(cdap, CDAP_READ, TIME_PATH, NULL, 0, 0);
- if (key == NULL || key[0] == INVALID_CDAP_KEY) {
- log_err("Failed to send CDAP request.");
- cdap_destroy(cdap);
- flow_dealloc(conn.flow_info.fd);
- return -1;
- }
+ log_dbg("Enrolling a new neighbor.");
- if (cdap_reply_wait(cdap, key[0], &data, &len)) {
- log_err("Failed to get CDAP reply.");
- free(key);
- cdap_destroy(cdap);
- flow_dealloc(conn.flow_info.fd);
- return -1;
- }
+ enroll_msg__free_unpacked(msg, NULL);
- free(key);
+ len = enroll_pack(&reply);
+ if (reply == NULL) {
+ log_err("Failed to pack enrollment message.");
+ connmgr_dealloc(AEID_ENROLL, &conn);
+ continue;
+ }
- clock_gettime(CLOCK_REALTIME, &rtt);
+ log_dbg("Sending enrollment info (%zd bytes).", len);
- delta_t = ts_diff_ms(&t0, &rtt);
+ if (flow_write(conn.flow_info.fd, reply, len)) {
+ log_err("Failed respond to enrollment request.");
+ connmgr_dealloc(AEID_ENROLL, &conn);
+ free(reply);
+ continue;
+ }
- assert(len == 2 * sizeof (uint64_t));
+ free(reply);
- rtt.tv_sec = ntoh64(((uint64_t *) data)[0]);
- rtt.tv_nsec = ntoh64(((uint64_t *) data)[1]);
+ len = flow_read(conn.flow_info.fd, buf, ENROLL_BUF_LEN);
+ if (len < 0) {
+ log_err("Failed to read from flow.");
+ connmgr_dealloc(AEID_ENROLL, &conn);
+ continue;
+ }
- if (labs(ts_diff_ms(&t0, &rtt)) - delta_t > ENROLL_WARN_TIME_OFFSET)
- log_warn("Clock offset above threshold.");
+ msg = enroll_msg__unpack(NULL, len, buf);
+ if (msg == NULL) {
+ log_err("Failed to unpack message.");
+ connmgr_dealloc(AEID_ENROLL, &conn);
+ continue;
+ }
- free(data);
+ if (msg->code != ENROLL_CODE__ENROLL_DONE || !msg->has_result) {
+ log_err("Wrong message type.");
+ enroll_msg__free_unpacked(msg, NULL);
+ connmgr_dealloc(AEID_ENROLL, &conn);
+ continue;
+ }
- key = cdap_request_send(cdap, CDAP_READ, boot_ro, NULL, 0, 0);
- if (key == NULL || key[0] == INVALID_CDAP_KEY) {
- log_err("Failed to send CDAP request.");
- cdap_destroy(cdap);
- flow_dealloc(conn.flow_info.fd);
- return -1;
- }
+ if (msg->result == 0)
+ log_dbg("Neighbor enrollment successful.");
+ else
+ log_dbg("Neigbor reported failed enrollment.");
- if (cdap_reply_wait(cdap, key[0], &data, &len)) {
- log_err("Failed to get CDAP reply.");
- free(key);
- cdap_destroy(cdap);
- flow_dealloc(conn.flow_info.fd);
- return -1;
+ connmgr_dealloc(AEID_ENROLL, &conn);
}
- free(key);
+ return 0;
+}
- log_dbg("Packed information received (%zu bytes).", len);
+int enroll_boot(struct conn * conn,
+ const char * dst)
+{
+ log_dbg("Getting boot information from %s.", dst);
- if (rib_unpack(data, len, UNPACK_CREATE)) {
- log_warn("Error unpacking RIB data.");
- rib_del(boot_ro);
- free(data);
- cdap_destroy(cdap);
- flow_dealloc(conn.flow_info.fd);
+ if (send_rcv_enroll_msg(conn->flow_info.fd)) {
+ log_err("Failed to enroll.");
return -1;
}
- log_dbg("Packed information inserted into RIB.");
+ return 0;
+}
- key = cdap_request_send(cdap, CDAP_READ, members_ro, NULL, 0, 0);
- if (key == NULL || key[0] == INVALID_CDAP_KEY) {
- log_err("Failed to send CDAP request.");
- cdap_destroy(cdap);
- flow_dealloc(conn.flow_info.fd);
- return -1;
- }
+int enroll_done(struct conn * conn,
+ int result)
+{
+ enroll_msg_t msg = ENROLL_MSG__INIT;
+ uint8_t buf[ENROLL_BUF_LEN];
+ ssize_t len;
- if (cdap_reply_wait(cdap, key[0], &data, &len)) {
- log_err("Failed to get CDAP reply.");
- free(key);
- cdap_destroy(cdap);
- flow_dealloc(conn.flow_info.fd);
+ msg.code = ENROLL_CODE__ENROLL_DONE;
+ msg.has_result = true;
+ msg.result = result;
+
+ len = enroll_msg__get_packed_size(&msg);
+ if (len < 0) {
+ log_dbg("Failed pack request message.");
return -1;
}
- free(key);
-
- log_dbg("Packed information received (%zu bytes).", len);
+ enroll_msg__pack(&msg, buf);
- if (rib_unpack(data, len, UNPACK_CREATE)) {
- log_warn("Error unpacking RIB data.");
- rib_del(boot_ro);
- free(data);
- cdap_destroy(cdap);
- flow_dealloc(conn.flow_info.fd);
+ if (flow_write(conn->flow_info.fd, buf, len)) {
+ log_dbg("Failed to send acknowledgment.");
return -1;
}
- log_dbg("Packed information inserted into RIB.");
+ return 0;
+}
+
+void enroll_bootstrap(const struct ipcp_config * conf)
+{
+ assert(conf);
- cdap_destroy(cdap);
- flow_dealloc(conn.flow_info.fd);
+ memcpy(&enroll.conf, conf, sizeof(enroll.conf));
+}
- return 0;
+struct ipcp_config * enroll_get_conf(void)
+{
+ return &enroll.conf;
}
int enroll_init(void)
{
struct conn_info info;
- enroll.cdap = cdap_create();
- if (enroll.cdap == NULL) {
- log_err("Failed to instantiate CDAP.");
- return -1;
- }
-
memset(&info, 0, sizeof(info));
strcpy(info.ae_name, ENROLL_AE);
- strcpy(info.protocol, CDAP_PROTO);
+ strcpy(info.protocol, ENROLL_PROTO);
info.pref_version = 1;
info.pref_syntax = PROTO_GPB;
+ info.addr = 0;
- enroll.ae = connmgr_ae_create(info);
- if (enroll.ae == NULL) {
- cdap_destroy(enroll.cdap);
+ if (connmgr_ae_init(AEID_ENROLL, &info, NULL)) {
+ log_err("Failed to register with connmgr.");
return -1;
}
+ enroll.state = ENROLL_INIT;
+
return 0;
}
void enroll_fini(void)
{
- pthread_join(enroll.listener, NULL);
- cdap_destroy(enroll.cdap);
- connmgr_ae_destroy(enroll.ae);
+ if (enroll.state == ENROLL_RUNNING)
+ pthread_join(enroll.listener, NULL);
+
+ connmgr_ae_fini(AEID_ENROLL);
}
int enroll_start(void)
{
- if (pthread_create(&enroll.listener, NULL, enroll_handle, enroll.cdap))
+ if (pthread_create(&enroll.listener, NULL, enroll_handle, NULL))
return -1;
+ enroll.state = ENROLL_RUNNING;
+
return 0;
}
void enroll_stop(void)
{
- pthread_cancel(enroll.listener);
+ if (enroll.state == ENROLL_RUNNING)
+ pthread_cancel(enroll.listener);
+
+ enroll.state = ENROLL_INIT;
}