summaryrefslogtreecommitdiff
path: root/src/ipcpd/common/enroll.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/ipcpd/common/enroll.c')
-rw-r--r--src/ipcpd/common/enroll.c372
1 files changed, 162 insertions, 210 deletions
diff --git a/src/ipcpd/common/enroll.c b/src/ipcpd/common/enroll.c
index 090067d8..5e35ce37 100644
--- a/src/ipcpd/common/enroll.c
+++ b/src/ipcpd/common/enroll.c
@@ -1,5 +1,5 @@
/*
- * Ouroboros - Copyright (C) 2016 - 2021
+ * Ouroboros - Copyright (C) 2016 - 2024
*
* Enrollment Task
*
@@ -28,13 +28,11 @@
#define OUROBOROS_PREFIX "enrollment"
-#include <ouroboros/endian.h>
-#include <ouroboros/errno.h>
-#include <ouroboros/time_utils.h>
#include <ouroboros/dev.h>
-#include <ouroboros/logs.h>
#include <ouroboros/errno.h>
-#include <ouroboros/sockets.h>
+#include <ouroboros/logs.h>
+#include <ouroboros/serdes-oep.h>
+#include <ouroboros/time.h>
#include "common/connmgr.h"
#include "common/enroll.h"
@@ -45,9 +43,6 @@
#include <string.h>
#include <pthread.h>
-#include "ipcp_config.pb-c.h"
-typedef EnrollMsg enroll_msg_t;
-
#define ENROLL_COMP "Enrollment"
#define ENROLL_PROTO "OEP" /* Ouroboros enrollment protocol */
#define ENROLL_WARN_TIME_OFFSET 20
@@ -65,261 +60,218 @@ struct {
pthread_t listener;
} enroll;
-static int send_rcv_enroll_msg(int fd)
+static void * enroll_handle(void * o)
{
- 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;
-
- req.code = ENROLL_CODE__ENROLL_REQ;
-
- len = enroll_msg__get_packed_size(&req);
- if (len < 0) {
- log_dbg("Failed pack request message.");
- return -1;
- }
-
- enroll_msg__pack(&req, buf);
+ struct enroll_req req;
+ struct enroll_resp resp;
+ struct enroll_ack ack;
+ struct conn conn;
+ uint8_t __buf[ENROLL_BUF_LEN];
+ buffer_t buf;
+ ssize_t len;
- clock_gettime(CLOCK_REALTIME, &t0);
-
- if (flow_write(fd, buf, len) < 0) {
- log_dbg("Failed to send request message.");
- return -1;
- }
-
- len = flow_read(fd, buf, ENROLL_BUF_LEN);
- if (len < 0) {
- log_dbg("No enrollment reply received.");
- return -1;
- }
-
- log_dbg("Received enrollment info (%zd bytes).", len);
-
- reply = enroll_msg__unpack(NULL, len, buf);
- if (reply == NULL) {
- log_dbg("No enrollment response.");
- return -1;
- }
+ (void) o;
- if (reply->code != ENROLL_CODE__ENROLL_BOOT) {
- log_dbg("Failed to unpack enrollment response.");
- enroll_msg__free_unpacked(reply, NULL);
- return -1;
- }
+ buf.data = __buf;
+ buf.len = sizeof(__buf);
- if (!(reply->has_t_sec && reply->has_t_nsec)) {
- log_dbg("No time in response message.");
- enroll_msg__free_unpacked(reply, NULL);
- return -1;
- }
+ resp.response = 0;
+ resp.conf = enroll.conf;
- clock_gettime(CLOCK_REALTIME, &rtt);
+ while (true) {
+ buffer_t msg;
+ int fd;
- delta_t = ts_diff_ms(&t0, &rtt);
+ if (connmgr_wait(COMPID_ENROLL, &conn)) {
+ log_err("Failed to get next connection.");
+ continue;
+ }
- rtt.tv_sec = reply->t_sec;
- rtt.tv_nsec = reply->t_nsec;
+ fd = conn.flow_info.fd;
- if (labs(ts_diff_ms(&t0, &rtt)) - delta_t > ENROLL_WARN_TIME_OFFSET)
- log_warn("Clock offset above threshold.");
-
- strcpy(enroll.conf.layer_info.layer_name,
- reply->conf->layer_info->layer_name);
- enroll.conf.type = reply->conf->ipcp_type;
-#ifdef BUILD_IPCP_UNICAST
- enroll.conf.addr_size = reply->conf->addr_size;
- enroll.conf.eid_size = reply->conf->eid_size;
- enroll.conf.max_ttl = reply->conf->max_ttl;
- enroll.conf.addr_auth_type = reply->conf->addr_auth_type;
- enroll.conf.routing_type = reply->conf->routing_type;
- enroll.conf.cong_avoid = reply->conf->cong_avoid;
-#endif
- enroll.conf.layer_info.dir_hash_algo
- = reply->conf->layer_info->dir_hash_algo;
- enroll_msg__free_unpacked(reply, NULL);
+ log_info("Incoming enrollment connection on flow %d.", fd);
- return 0;
-}
+ len = flow_read(fd, buf.data, buf.len);
+ if (len < 0) {
+ log_err("Failed to read from flow %d.", fd);
+ goto finish_flow;
+ }
-static ssize_t enroll_pack(uint8_t ** buf)
-{
- enroll_msg_t msg = ENROLL_MSG__INIT;
- ipcp_config_msg_t config = IPCP_CONFIG_MSG__INIT;
- layer_info_msg_t layer_info = LAYER_INFO_MSG__INIT;
- struct timespec now;
- ssize_t len;
+ msg.data = buf.data;
+ msg.len = (size_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;
-#ifdef BUILD_IPCP_UNICAST
- config.has_addr_size = true;
- config.addr_size = enroll.conf.addr_size;
- config.has_eid_size = true;
- config.eid_size = enroll.conf.eid_size;
- config.has_max_ttl = true;
- config.max_ttl = enroll.conf.max_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.has_cong_avoid = true;
- config.cong_avoid = enroll.conf.cong_avoid;
-#endif
- config.layer_info = &layer_info;
+ if (enroll_req_des(&req, msg) < 0) {
+ log_err("Failed to unpack request message.");
+ goto finish_flow;
+ }
- layer_info.layer_name = (char *) enroll.conf.layer_info.layer_name;
- layer_info.dir_hash_algo = enroll.conf.layer_info.dir_hash_algo;
+ log_info_id(req.id, "Handling incoming enrollment.");
- len = enroll_msg__get_packed_size(&msg);
+ /* TODO: authentication, timezone handling (UTC). */
- *buf = malloc(len);
- if (*buf == NULL)
- return -1;
+ ack.result = -100;
- enroll_msg__pack(&msg, *buf);
+ clock_gettime(CLOCK_REALTIME, &resp.t);
- return len;
-}
+ memcpy(resp.id, req.id, ENROLL_ID_LEN);
-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;
+ len = enroll_resp_ser(&resp, buf);
+ if (len < 0) {
+ log_err_id(req.id, "Failed to pack reply.");
+ goto finish_enroll;
+ }
- (void) o;
+ log_dbg_id(req.id, "Sending enrollment info (%zd bytes).", len);
- while (true) {
- if (connmgr_wait(COMPID_ENROLL, &conn)) {
- log_err("Failed to get next connection.");
- continue;
+ if (flow_write(conn.flow_info.fd, buf.data, len) < 0) {
+ log_err_id(req.id, "Failed te send response.");
+ goto finish_enroll;
}
- len = flow_read(conn.flow_info.fd, buf, ENROLL_BUF_LEN);
+ len = flow_read(conn.flow_info.fd, buf.data, buf.len);
if (len < 0) {
- log_err("Failed to read from flow.");
- connmgr_dealloc(COMPID_ENROLL, &conn);
- continue;
+ log_err_id(req.id, "Failed to read from flow.");
+ goto finish_enroll;
}
- msg = enroll_msg__unpack(NULL, len, buf);
- if (msg == NULL) {
- log_err("Failed to unpack message.");
- connmgr_dealloc(COMPID_ENROLL, &conn);
- continue;
- }
+ msg.data = buf.data;
+ msg.len = (size_t) len;
- if (msg->code != ENROLL_CODE__ENROLL_REQ) {
- log_err("Wrong message type.");
- connmgr_dealloc(COMPID_ENROLL, &conn);
- enroll_msg__free_unpacked(msg, NULL);
- continue;
+ if (enroll_ack_des(&ack, msg) < 0) {
+ log_err_id(req.id, "Failed to unpack ack.");
+ goto finish_enroll;
}
- log_dbg("Enrolling a new neighbor.");
-
- enroll_msg__free_unpacked(msg, NULL);
-
- len = enroll_pack(&reply);
- if (reply == NULL) {
- log_err("Failed to pack enrollment message.");
- connmgr_dealloc(COMPID_ENROLL, &conn);
- continue;
+ if (memcmp(req.id, ack.id, ENROLL_ID_LEN) != 0)
+ log_warn_id(req.id, "Enrollment ID mismatch.");
+
+ finish_enroll:
+ switch(ack.result) {
+ case 0:
+ log_info_id(req.id, "Enrollment completed.");
+ break;
+ case -100:
+ log_warn_id(req.id, "Enrollment failed.");
+ break;
+ default:
+ log_warn_id(req.id, "Enrollment failed at remote.");
}
+ finish_flow:
+ connmgr_dealloc(COMPID_ENROLL, &conn);
- log_dbg("Sending enrollment info (%zd bytes).", len);
+ log_info("Enrollment flow %d closed.", fd);
+ }
- if (flow_write(conn.flow_info.fd, reply, len) < 0) {
- log_err("Failed respond to enrollment request.");
- connmgr_dealloc(COMPID_ENROLL, &conn);
- free(reply);
- continue;
- }
+ return 0;
+}
- free(reply);
+int enroll_boot(struct conn * conn,
+ const uint8_t * id)
+{
+ uint8_t __buf[ENROLL_BUF_LEN];
+ buffer_t buf;
+ buffer_t msg;
+ ssize_t len;
+ ssize_t delta_t;
+ struct timespec t0;
+ struct timespec rtt;
+ int fd;
+ int ret;
+ struct enroll_req req;
+ struct enroll_resp resp;
+
+ fd = conn->flow_info.fd;
+
+ buf.data = __buf;
+ buf.len = sizeof(__buf);
+
+ memcpy(req.id, id, ENROLL_ID_LEN);
+
+ len = enroll_req_ser(&req, buf);
+ if (len < 0) {
+ log_err_id(id, "Failed to pack request message.");
+ 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(COMPID_ENROLL, &conn);
- continue;
- }
+ clock_gettime(CLOCK_REALTIME, &t0);
- msg = enroll_msg__unpack(NULL, len, buf);
- if (msg == NULL) {
- log_err("Failed to unpack message.");
- connmgr_dealloc(COMPID_ENROLL, &conn);
- continue;
- }
+ if (flow_write(fd, buf.data, len) < 0) {
+ log_err_id(id, "Failed to send request message.");
+ return -1;
+ }
- if (msg->code != ENROLL_CODE__ENROLL_DONE || !msg->has_result) {
- log_err("Wrong message type.");
- enroll_msg__free_unpacked(msg, NULL);
- connmgr_dealloc(COMPID_ENROLL, &conn);
- continue;
- }
+ len = flow_read(fd, buf.data, buf.len);
+ if (len < 0) {
+ log_err_id(id, "No reply received.");
+ return -1;
+ }
- if (msg->result == 0)
- log_dbg("Neighbor enrollment successful.");
- else
- log_dbg("Neigbor reported failed enrollment.");
+ log_dbg_id(id, "Received configuration info (%zd bytes).", len);
- enroll_msg__free_unpacked(msg, NULL);
+ msg.data = buf.data;
+ msg.len = len;
- connmgr_dealloc(COMPID_ENROLL, &conn);
+ ret = enroll_resp_des(&resp, msg);
+ if (ret < 0) {
+ log_err_id(id, "Failed to unpack response message.");
+ return -1;
}
- return 0;
-}
+ if (memcmp(resp.id, id, ENROLL_ID_LEN) != 0) {
+ log_err_id(id, "Enrollment ID mismatch.");
+ return -1;
+ }
-int enroll_boot(struct conn * conn)
-{
- log_dbg("Getting boot information.");
+ if (resp.response < 0) {
+ log_warn_id(id, "Remote denied request: %d.", resp.response);
+ return -1;
+ }
- if (send_rcv_enroll_msg(conn->flow_info.fd)) {
- log_err("Failed to enroll.");
+ if (resp.conf.type != ipcpi.type) {
+ log_err_id(id, "Wrong type in enrollment response %d (%d).",
+ resp.conf.type, ipcpi.type);
return -1;
}
+ clock_gettime(CLOCK_REALTIME, &rtt);
+
+ delta_t = ts_diff_ms(&t0, &rtt);
+
+ rtt.tv_sec = resp.t.tv_sec;
+ rtt.tv_nsec = resp.t.tv_nsec;
+
+ if (labs(ts_diff_ms(&t0, &rtt)) - delta_t > ENROLL_WARN_TIME_OFFSET)
+ log_warn_id(id, "Clock offset above threshold.");
+
+ enroll.conf = resp.conf;
+
return 0;
}
-int enroll_done(struct conn * conn,
- int result)
+int enroll_ack(struct conn * conn,
+ const uint8_t * id,
+ const int result)
{
- enroll_msg_t msg = ENROLL_MSG__INIT;
- uint8_t buf[ENROLL_BUF_LEN];
- ssize_t len;
+ struct enroll_ack ack;
+ uint8_t __buf[ENROLL_BUF_LEN];
+ buffer_t buf;
+ ssize_t len;
- msg.code = ENROLL_CODE__ENROLL_DONE;
- msg.has_result = true;
- msg.result = result;
+ buf.data = __buf;
+ buf.len = sizeof(__buf);
- len = enroll_msg__get_packed_size(&msg);
+ ack.result = result;
+
+ memcpy(ack.id, id, ENROLL_ID_LEN);
+
+ len = enroll_ack_ser(&ack, buf);
if (len < 0) {
- log_dbg("Failed pack request message.");
+ log_err_id(id, "Failed to pack acknowledgement.");
return -1;
}
- enroll_msg__pack(&msg, buf);
-
- if (flow_write(conn->flow_info.fd, buf, len) < 0) {
- log_dbg("Failed to send acknowledgment.");
+ if (flow_write(conn->flow_info.fd, buf.data, len) < 0) {
+ log_err_id(id, "Failed to send acknowledgment.");
return -1;
}