summaryrefslogtreecommitdiff
path: root/src/ipcpd
diff options
context:
space:
mode:
authorDimitri Staessens <dimitri@ouroboros.rocks>2023-03-04 03:48:48 +0100
committerSander Vrijders <sander@ouroboros.rocks>2023-03-08 15:59:37 +0100
commit89b58eaa2706c54aeb0a48252d1cfbd2b5ae01b7 (patch)
tree891c4a2de37e06fdb8879741911a6b7ff2f1b4b8 /src/ipcpd
parentf16b4a1954ab4fbca0ec403f6a04c80375328921 (diff)
downloadouroboros-89b58eaa2706c54aeb0a48252d1cfbd2b5ae01b7.tar.gz
ouroboros-89b58eaa2706c54aeb0a48252d1cfbd2b5ae01b7.zip
irmd: Add configuration file support
This adds initial support for configuration files using the C99 TOML parser (to be installed separately from https://github.com/cktan/tomlc99). The default location for the IRMd configuration file is /etc/ouroboros/irmd.conf. This is configurable at build time. An example file will be installed in the configuration directory with the name irmd.conf.example. Config file support can be disabled using the DISABLE_CONFIGFILE build option. There were some refactors and changes to the configuration messages and protobuf files. This works towards consolidation of protobuf C as an option for more generic handling of serialization/deserialization of various messages. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
Diffstat (limited to 'src/ipcpd')
-rw-r--r--src/ipcpd/broadcast/main.c2
-rw-r--r--src/ipcpd/common/enroll.c241
-rw-r--r--src/ipcpd/common/enroll.h4
-rw-r--r--src/ipcpd/eth/eth.c7
-rw-r--r--src/ipcpd/ipcp.c76
-rw-r--r--src/ipcpd/ipcp.h2
-rw-r--r--src/ipcpd/unicast/main.c2
7 files changed, 109 insertions, 225 deletions
diff --git a/src/ipcpd/broadcast/main.c b/src/ipcpd/broadcast/main.c
index d0becc63..804741f0 100644
--- a/src/ipcpd/broadcast/main.c
+++ b/src/ipcpd/broadcast/main.c
@@ -139,7 +139,7 @@ static int broadcast_ipcp_enroll(const char * dst,
goto fail_start_comp;
}
- if (enroll_done(&conn, 0))
+ if (enroll_ack(&conn, 0))
log_warn("Failed to confirm enrollment with peer.");
if (connmgr_dealloc(COMPID_ENROLL, &conn))
diff --git a/src/ipcpd/common/enroll.c b/src/ipcpd/common/enroll.c
index 745829e7..32a5ed93 100644
--- a/src/ipcpd/common/enroll.c
+++ b/src/ipcpd/common/enroll.c
@@ -34,7 +34,7 @@
#include <ouroboros/dev.h>
#include <ouroboros/logs.h>
#include <ouroboros/errno.h>
-#include <ouroboros/sockets.h>
+#include <ouroboros/serdes-oep.h>
#include "common/connmgr.h"
#include "common/enroll.h"
@@ -45,9 +45,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
@@ -67,56 +64,60 @@ struct {
static int send_rcv_enroll_msg(int fd)
{
- 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;
-#ifdef BUILD_IPCP_UNICAST
- uni_config_msg_t * uni_cfg_msg;
-#endif
- req.code = ENROLL_CODE__ENROLL_REQ;
-
- len = enroll_msg__get_packed_size(&req);
+ 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 ret;
+ struct enroll_resp resp;
+
+ buf.data = __buf;
+ buf.len = sizeof(__buf);
+
+ len = enroll_req_ser(buf);
if (len < 0) {
- log_dbg("Failed pack request message.");
+ log_dbg("Failed to pack request message.");
return -1;
}
- enroll_msg__pack(&req, buf);
-
clock_gettime(CLOCK_REALTIME, &t0);
- if (flow_write(fd, buf, len) < 0) {
+ log_dbg("Sending request message.");
+
+ if (flow_write(fd, buf.data, len) < 0) {
log_dbg("Failed to send request message.");
return -1;
}
- len = flow_read(fd, buf, ENROLL_BUF_LEN);
+ log_dbg("Waiting for reply message.");
+
+ len = flow_read(fd, buf.data, buf.len);
if (len < 0) {
- log_dbg("No enrollment reply received.");
+ log_dbg("No reply received.");
return -1;
}
- log_dbg("Received enrollment info (%zd bytes).", len);
+ log_dbg("Received configuration info (%zd bytes).", len);
+
+ msg.data = buf.data;
+ msg.len = len;
- reply = enroll_msg__unpack(NULL, len, buf);
- if (reply == NULL) {
- log_dbg("No enrollment response.");
+ ret = enroll_resp_des(&resp, msg);
+ if (ret < 0) {
+ log_dbg("Failed to unpack response message.");
return -1;
}
- if (reply->code != ENROLL_CODE__ENROLL_BOOT) {
- log_dbg("Failed to unpack enrollment response.");
- enroll_msg__free_unpacked(reply, NULL);
+ if (resp.response < 0) {
+ log_dbg("Remote denied request: %d.", resp.response);
return -1;
}
- if (!(reply->has_t_sec && reply->has_t_nsec)) {
- log_dbg("No time in response message.");
- enroll_msg__free_unpacked(reply, NULL);
+ if (resp.conf.type != ipcpi.type) {
+ log_dbg("Wrong type in enrollment response %d (%d).", resp.conf.type, ipcpi.type);
return -1;
}
@@ -124,168 +125,107 @@ static int send_rcv_enroll_msg(int fd)
delta_t = ts_diff_ms(&t0, &rtt);
- rtt.tv_sec = reply->t_sec;
- rtt.tv_nsec = reply->t_nsec;
+ 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("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
- uni_cfg_msg = reply->conf->unicast;
-
- enroll.conf.unicast.dt.addr_size = uni_cfg_msg->dt->addr_size;
- enroll.conf.unicast.dt.eid_size = uni_cfg_msg->dt->eid_size;
- enroll.conf.unicast.dt.max_ttl = uni_cfg_msg->dt->max_ttl;
- enroll.conf.unicast.dt.routing_type = uni_cfg_msg->dt->routing_type;
- enroll.conf.unicast.addr_auth_type = uni_cfg_msg->addr_auth_type;
- enroll.conf.unicast.cong_avoid = uni_cfg_msg->cong_avoid;
-#endif
- enroll.conf.layer_info.dir_hash_algo
- = reply->conf->layer_info->dir_hash_algo;
- enroll_msg__free_unpacked(reply, NULL);
+ enroll.conf = resp.conf;
return 0;
}
-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;
-#ifdef BUILD_IPCP_UNICAST
- dt_config_msg_t dt_cfg_msg = DT_CONFIG_MSG__INIT;
- uni_config_msg_t uni_cfg_msg = UNI_CONFIG_MSG__INIT;
-#endif
- 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;
-
- config.ipcp_type = enroll.conf.type;
-#ifdef BUILD_IPCP_UNICAST
- dt_cfg_msg.addr_size = enroll.conf.unicast.dt.addr_size;
- dt_cfg_msg.eid_size = enroll.conf.unicast.dt.eid_size;
- dt_cfg_msg.max_ttl = enroll.conf.unicast.dt.max_ttl;
- dt_cfg_msg.routing_type = enroll.conf.unicast.dt.routing_type;
- uni_cfg_msg.dt = &dt_cfg_msg;
- uni_cfg_msg.addr_auth_type = enroll.conf.unicast.addr_auth_type;
- uni_cfg_msg.cong_avoid = enroll.conf.unicast.cong_avoid;
- config.unicast = &uni_cfg_msg;
-#endif
- layer_info.layer_name = (char *) enroll.conf.layer_info.layer_name;
- layer_info.dir_hash_algo = enroll.conf.layer_info.dir_hash_algo;
-
- config.layer_info = &layer_info;
- msg.conf = &config;
-
- len = enroll_msg__get_packed_size(&msg);
-
- *buf = malloc(len);
- if (*buf == NULL)
- return -ENOMEM;
-
- enroll_msg__pack(&msg, *buf);
-
- return 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;
+ struct enroll_resp resp;
+ struct conn conn;
+ uint8_t __buf[ENROLL_BUF_LEN];
+ buffer_t buf;
+ ssize_t len;
+ int response;
(void) o;
+ buf.data = __buf;
+ buf.len = sizeof(__buf);
+
+ resp.conf = enroll.conf;
+
while (true) {
+ buffer_t msg;
+
if (connmgr_wait(COMPID_ENROLL, &conn)) {
log_err("Failed to get next connection.");
continue;
}
- len = flow_read(conn.flow_info.fd, buf, ENROLL_BUF_LEN);
+ log_info("New enrollment connection.");
+
+ 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;
}
- msg = enroll_msg__unpack(NULL, len, buf);
- if (msg == NULL) {
- log_err("Failed to unpack message.");
- connmgr_dealloc(COMPID_ENROLL, &conn);
- continue;
- }
+ log_dbg("Read request from flow (%zd bytes).", len);
+ msg.data = buf.data;
+ msg.len = (size_t) len;
- if (msg->code != ENROLL_CODE__ENROLL_REQ) {
- log_err("Wrong message type.");
+ if (enroll_req_des(msg) < 0) {
+ log_err("Failed to unpack request message.");
connmgr_dealloc(COMPID_ENROLL, &conn);
- enroll_msg__free_unpacked(msg, NULL);
continue;
}
+ /* TODO: authentication */
+
log_dbg("Enrolling a new neighbor.");
- enroll_msg__free_unpacked(msg, NULL);
+ clock_gettime(CLOCK_REALTIME, &resp.t);
- len = enroll_pack(&reply);
+ resp.response = 0;
+
+ len = enroll_resp_ser(&resp, buf);
if (len < 0) {
- log_err("Failed to pack enrollment message.");
+ log_err("Failed to pack reply.");
connmgr_dealloc(COMPID_ENROLL, &conn);
continue;
}
log_dbg("Sending enrollment info (%zd bytes).", len);
- if (flow_write(conn.flow_info.fd, reply, len) < 0) {
- log_err("Failed respond to enrollment request.");
+ if (flow_write(conn.flow_info.fd, buf.data, len) < 0) {
+ log_err("Failed respond to request.");
connmgr_dealloc(COMPID_ENROLL, &conn);
- free(reply);
continue;
}
- free(reply);
-
- 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;
}
- 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_DONE || !msg->has_result) {
- log_err("Wrong message type.");
- enroll_msg__free_unpacked(msg, NULL);
+ if (enroll_ack_des(&response, msg) < 0) {
+ log_err("Failed to unpack acknowledgment.");
connmgr_dealloc(COMPID_ENROLL, &conn);
continue;
}
-
- if (msg->result == 0)
- log_dbg("Neighbor enrollment successful.");
+ if (response == 0)
+ log_info("Neighbor enrollment successful.");
else
- log_dbg("Neigbor reported failed enrollment.");
-
- enroll_msg__free_unpacked(msg, NULL);
+ log_info("Neigbor enrolment failed at remote.");
connmgr_dealloc(COMPID_ENROLL, &conn);
+
+ log_info("Enrollment connection closed.");
}
return 0;
@@ -293,36 +233,35 @@ static void * enroll_handle(void * o)
int enroll_boot(struct conn * conn)
{
- log_dbg("Getting boot information.");
+ log_dbg("Starting enrollment.");
if (send_rcv_enroll_msg(conn->flow_info.fd)) {
log_err("Failed to enroll.");
return -1;
}
+ log_dbg("Enrollment complete.");
+
return 0;
}
-int enroll_done(struct conn * conn,
- int result)
+int enroll_ack(struct conn * conn,
+ int result)
{
- enroll_msg_t msg = ENROLL_MSG__INIT;
- uint8_t buf[ENROLL_BUF_LEN];
- ssize_t len;
+ 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);
+ len = enroll_ack_ser(result, buf);
if (len < 0) {
- log_dbg("Failed pack request message.");
+ log_err("Failed to pack acknowledgement.");
return -1;
}
- enroll_msg__pack(&msg, buf);
-
- if (flow_write(conn->flow_info.fd, buf, len) < 0) {
+ if (flow_write(conn->flow_info.fd, buf.data, len) < 0) {
log_dbg("Failed to send acknowledgment.");
return -1;
}
diff --git a/src/ipcpd/common/enroll.h b/src/ipcpd/common/enroll.h
index bbb84561..fa22923f 100644
--- a/src/ipcpd/common/enroll.h
+++ b/src/ipcpd/common/enroll.h
@@ -39,8 +39,8 @@ void enroll_bootstrap(const struct ipcp_config * conf);
int enroll_boot(struct conn * conn);
-int enroll_done(struct conn * conn,
- int result);
+int enroll_ack(struct conn * conn,
+ int result);
struct ipcp_config * enroll_get_conf(void);
diff --git a/src/ipcpd/eth/eth.c b/src/ipcpd/eth/eth.c
index 6e0cb179..6d9d78ba 100644
--- a/src/ipcpd/eth/eth.c
+++ b/src/ipcpd/eth/eth.c
@@ -1283,11 +1283,6 @@ static int eth_ipcp_bootstrap(const struct ipcp_config * conf)
ipcpi.dir_hash_algo = conf->layer_info.dir_hash_algo;
strcpy(ipcpi.layer_name, conf->layer_info.layer_name);
- if (conf->eth.dev == NULL) {
- log_err("Device name is NULL.");
- return -1;
- }
-
if (strlen(conf->eth.dev) >= IFNAMSIZ) {
log_err("Invalid device name: %s.", conf->eth.dev);
return -1;
@@ -1298,7 +1293,7 @@ static int eth_ipcp_bootstrap(const struct ipcp_config * conf)
#ifdef BUILD_ETH_DIX
if (conf->eth.ethertype < 0x0600 || conf->eth.ethertype == 0xFFFF) {
- log_err("Invalid Ethertype.");
+ log_err("Invalid Ethertype: %d.", conf->eth.ethertype);
return -1;
}
eth_data.ethertype = htons(conf->eth.ethertype);
diff --git a/src/ipcpd/ipcp.c b/src/ipcpd/ipcp.c
index 5d9c6e7a..103c0804 100644
--- a/src/ipcpd/ipcp.c
+++ b/src/ipcpd/ipcp.c
@@ -47,6 +47,7 @@
#include <ouroboros/bitmap.h>
#include <ouroboros/np1_flow.h>
#include <ouroboros/rib.h>
+#include <ouroboros/protobuf.h>
#include <ouroboros/pthread.h>
#include "ipcp.h"
@@ -263,12 +264,9 @@ static void free_msg(void * o)
static void handle_bootstrap(ipcp_config_msg_t * conf_msg,
- layer_info_msg_t * layer_info_msg,
ipcp_msg_t * ret_msg)
{
struct ipcp_config conf;
- enum ipcp_type ipcp_type;
- uni_config_msg_t * uni_cfg_msg;
if (ipcpi.ops->ipcp_bootstrap == NULL) {
log_err("Bootstrap unsupported.");
@@ -282,58 +280,13 @@ static void handle_bootstrap(ipcp_config_msg_t * conf_msg,
return;
}
- conf.type = conf_msg->ipcp_type;
-
- strcpy(conf.layer_info.layer_name, conf_msg->layer_info->layer_name);
-
- ipcp_type = conf_msg->ipcp_type;
-
- conf.layer_info.dir_hash_algo = conf_msg->layer_info->dir_hash_algo;
-
- switch(ipcp_type) {
- case IPCP_LOCAL:
- break;
- case IPCP_UNICAST:
- uni_cfg_msg = conf_msg->unicast;
-
- conf.unicast.dt.addr_size = uni_cfg_msg->dt->addr_size;
- conf.unicast.dt.eid_size = uni_cfg_msg->dt->eid_size;
- conf.unicast.dt.max_ttl = uni_cfg_msg->dt->max_ttl;
- conf.unicast.dt.routing_type = uni_cfg_msg->dt->routing_type;
- conf.unicast.addr_auth_type = uni_cfg_msg->addr_auth_type;
- conf.unicast.cong_avoid = uni_cfg_msg->cong_avoid;
- break;
- case IPCP_ETH_DIX:
- conf.eth.ethertype = conf_msg->eth->ethertype;
- /* FALLTHRU */
- case IPCP_ETH_LLC:
- conf.eth.dev = conf_msg->eth->dev;
- break;
- case IPCP_UDP:
- conf.udp.ip_addr = conf_msg->udp->ip_addr;
- conf.udp.dns_addr = conf_msg->udp->dns_addr;
- conf.udp.port = conf_msg->udp->port;
- conf.layer_info.dir_hash_algo = HASH_MD5;
- break;
- case IPCP_BROADCAST:
- conf.layer_info.dir_hash_algo = HASH_SHA3_256;
- break;
- default:
- log_err("Unknown IPCP type: %d.", conf_msg->ipcp_type);
- ret_msg->result = -EIPCP;
- return;
- }
-
+ conf = ipcp_config_msg_to_s(conf_msg);
ret_msg->result = ipcpi.ops->ipcp_bootstrap(&conf);
- if (ret_msg->result == 0) {
- layer_info_msg->layer_name = strdup(conf.layer_info.layer_name);
- layer_info_msg->dir_hash_algo = conf.layer_info.dir_hash_algo;
- ret_msg->layer_info = layer_info_msg;
- }
+ if (ret_msg->result == 0)
+ ret_msg->layer_info = layer_info_s_to_msg(&conf.layer_info);
}
static void handle_enroll(const char * dst,
- layer_info_msg_t * layer_info_msg,
ipcp_msg_t * ret_msg)
{
struct layer_info info;
@@ -351,12 +304,8 @@ static void handle_enroll(const char * dst,
}
ret_msg->result = ipcpi.ops->ipcp_enroll(dst, &info);
- if (ret_msg->result == 0) {
- layer_info_msg->layer_name = strdup(info.layer_name);
- layer_info_msg->dir_hash_algo = info.dir_hash_algo;
- ret_msg->layer_info = layer_info_msg;
-
- }
+ if (ret_msg->result == 0)
+ ret_msg->layer_info = layer_info_s_to_msg(&info);
}
static void handle_connect(const char * dst,
@@ -563,7 +512,6 @@ static void * mainloop(void * o)
while (true) {
ipcp_msg_t ret_msg = IPCP_MSG__INIT;
- layer_info_msg_t layer_info_msg = LAYER_INFO_MSG__INIT;
qosspec_t qs;
struct cmd * cmd;
@@ -600,13 +548,13 @@ static void * mainloop(void * o)
switch (msg->code) {
case IPCP_MSG_CODE__IPCP_BOOTSTRAP:
- handle_bootstrap(msg->conf, &layer_info_msg, &ret_msg);
+ handle_bootstrap(msg->conf, &ret_msg);
break;
case IPCP_MSG_CODE__IPCP_ENROLL:
- handle_enroll(msg->dst, &layer_info_msg, &ret_msg);
+ handle_enroll(msg->dst, &ret_msg);
break;
case IPCP_MSG_CODE__IPCP_CONNECT:
- qs = msg_to_spec(msg->qosspec);
+ qs = qos_spec_msg_to_s(msg->qosspec);
handle_connect(msg->dst, msg->comp, qs, &ret_msg);
break;
case IPCP_MSG_CODE__IPCP_DISCONNECT:
@@ -628,7 +576,7 @@ static void * mainloop(void * o)
assert(msg->hash.len == ipcp_dir_hash_len());
assert(msg->pk.len > 0 ? msg->pk.data != NULL
: msg->pk.data == NULL);
- qs = msg_to_spec(msg->qosspec);
+ qs = qos_spec_msg_to_s(msg->qosspec);
handle_flow_alloc(msg->pid, msg->flow_id,
msg->hash.data, qs,
msg->pk.data, msg->pk.len,
@@ -636,7 +584,7 @@ static void * mainloop(void * o)
break;
case IPCP_MSG_CODE__IPCP_FLOW_JOIN:
assert(msg->hash.len == ipcp_dir_hash_len());
- qs = msg_to_spec(msg->qosspec);
+ qs = qos_spec_msg_to_s(msg->qosspec);
handle_flow_join(msg->pid, msg->flow_id,
msg->hash.data, qs, &ret_msg);
break;
@@ -680,7 +628,7 @@ static void * mainloop(void * o)
ipcp_msg__pack(&ret_msg, buffer.data);
if (ret_msg.layer_info != NULL)
- free(ret_msg.layer_info->layer_name);
+ layer_info_msg__free_unpacked(ret_msg.layer_info, NULL);
pthread_cleanup_push(__cleanup_close_ptr, &sfd);
pthread_cleanup_push(free, buffer.data)
diff --git a/src/ipcpd/ipcp.h b/src/ipcpd/ipcp.h
index 9e7a7223..31d58ff2 100644
--- a/src/ipcpd/ipcp.h
+++ b/src/ipcpd/ipcp.h
@@ -26,6 +26,8 @@
#include <ouroboros/hash.h>
#include <ouroboros/ipcp.h>
#include <ouroboros/list.h>
+#include <ouroboros/protobuf.h>
+#include <ouroboros/qos.h>
#include <ouroboros/sockets.h>
#include <ouroboros/tpm.h>
diff --git a/src/ipcpd/unicast/main.c b/src/ipcpd/unicast/main.c
index 1318ec2f..8092449b 100644
--- a/src/ipcpd/unicast/main.c
+++ b/src/ipcpd/unicast/main.c
@@ -218,7 +218,7 @@ static int unicast_ipcp_enroll(const char * dst,
goto fail_start_comp;
}
- if (enroll_done(&conn, 0))
+ if (enroll_ack(&conn, 0))
log_warn("Failed to confirm enrollment with peer.");
if (connmgr_dealloc(COMPID_ENROLL, &conn))