summaryrefslogtreecommitdiff
path: root/src
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
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')
-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
-rw-r--r--src/irmd/CMakeLists.txt37
-rw-r--r--src/irmd/config.h.in6
-rw-r--r--src/irmd/configfile.c837
-rw-r--r--src/irmd/configfile.h29
-rw-r--r--src/irmd/ipcp.c21
-rw-r--r--src/irmd/ipcp.h7
-rw-r--r--src/irmd/irmd.h61
-rw-r--r--src/irmd/main.c150
-rw-r--r--src/irmd/registry.c1
-rw-r--r--src/irmd/utils.h2
-rw-r--r--src/lib/CMakeLists.txt18
-rw-r--r--src/lib/dev.c15
-rw-r--r--src/lib/enroll.proto40
-rw-r--r--src/lib/ipcp_config.proto18
-rw-r--r--src/lib/ipcpd_messages.proto2
-rw-r--r--src/lib/irm.c63
-rw-r--r--src/lib/irmd_messages.proto2
-rw-r--r--src/lib/protobuf.c438
-rw-r--r--src/lib/serdes-oep.c155
-rw-r--r--src/lib/sockets.c48
-rw-r--r--src/tools/irm/irm_ipcp_bootstrap.c9
28 files changed, 1870 insertions, 423 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))
diff --git a/src/irmd/CMakeLists.txt b/src/irmd/CMakeLists.txt
index 59d0d103..fb1e6ca2 100644
--- a/src/irmd/CMakeLists.txt
+++ b/src/irmd/CMakeLists.txt
@@ -4,6 +4,39 @@ include_directories(${CMAKE_CURRENT_BINARY_DIR})
include_directories(${CMAKE_SOURCE_DIR}/include)
include_directories(${CMAKE_BINARY_DIR}/include)
+find_library(TOML_LIBRARIES toml QUIET)
+if (TOML_LIBRARIES)
+ set(DISABLE_CONFIGFILE FALSE CACHE BOOL
+ "Disable configuration file support")
+ if (NOT DISABLE_CONFIGFILE)
+ set(OUROBOROS_CONFIG_DIR /etc/ouroboros/ CACHE STRING
+ "Configuration directory")
+ set(OUROBOROS_CONFIG_FILE irmd.conf CACHE STRING
+ "Name of the IRMd configuration file")
+ set(HAVE_TOML TRUE)
+ message(STATUS "Found TOML C99 library: " ${TOML_LIBRARIES})
+ message(STATUS "Configuration file support enabled")
+ message(STATUS "Configuration directory: ${OUROBOROS_CONFIG_DIR}")
+ set(INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_BINDIR}")
+ configure_file("${CMAKE_SOURCE_DIR}/irmd.conf.in"
+ "${CMAKE_BINARY_DIR}/irmd.conf.example" @ONLY)
+ install(FILES "${CMAKE_BINARY_DIR}/irmd.conf.example"
+ DESTINATION "${OUROBOROS_CONFIG_DIR}")
+ unset(INSTALL_DIR)
+ mark_as_advanced(TOML_LIBRARIES)
+ else ()
+ message(STATUS "Configuration file support disabled by user")
+ unset(OUROBOROS_CONFIG_FILE CACHE)
+ unset(OUROBOROS_CONFIG_DIR CACHE)
+ set(HAVE_TOML FALSE)
+ endif ()
+else ()
+ message(STATUS "Install tomlc99 for config file support")
+ message(STATUS " https://github.com/cktan/tomlc99")
+ unset(DISABLE_CONFIGFILE CACHE)
+ unset(HAVE_TOML)
+endif ()
+
set(IRMD_REQ_ARR_TIMEOUT 500 CACHE STRING
"Timeout for an application to respond to a new flow (ms)")
set(IRMD_FLOW_TIMEOUT 5000 CACHE STRING
@@ -31,6 +64,7 @@ set(SOURCE_FILES
proc_table.c
prog_table.c
ipcp.c
+ configfile.c
irm_flow.c
main.c
registry.c
@@ -39,7 +73,8 @@ set(SOURCE_FILES
add_executable (irmd ${SOURCE_FILES})
-target_link_libraries (irmd LINK_PUBLIC ouroboros-common)
+target_link_libraries (irmd LINK_PUBLIC ouroboros-common
+ ${TOML_LIBRARIES} ${CONFINI_LIBRARIES})
include(AddCompileFlags)
if (CMAKE_BUILD_TYPE MATCHES "Debug*")
diff --git a/src/irmd/config.h.in b/src/irmd/config.h.in
index a6979504..10ccaa52 100644
--- a/src/irmd/config.h.in
+++ b/src/irmd/config.h.in
@@ -47,9 +47,15 @@
#define IRMD_MIN_THREADS @IRMD_MIN_THREADS@
#define IRMD_ADD_THREADS @IRMD_ADD_THREADS@
+#define OUROBOROS_CONFIG_DIR "@OUROBOROS_CONFIG_DIR@"
+#define OUROBOROS_CONFIG_FILE "@OUROBOROS_CONFIG_FILE@"
+
#cmakedefine HAVE_FUSE
#ifdef HAVE_FUSE
#define FUSE_PREFIX "@FUSE_PREFIX@"
#endif
+#cmakedefine HAVE_TOML
+#cmakedefine HAVE_CONFINI
+#cmakedefine OUROBOROS_CONFIG_INI
#cmakedefine HAVE_LIBGCRYPT
diff --git a/src/irmd/configfile.c b/src/irmd/configfile.c
new file mode 100644
index 00000000..787edb49
--- /dev/null
+++ b/src/irmd/configfile.c
@@ -0,0 +1,837 @@
+/*
+ * Ouroboros - Copyright (C) 2016 - 2023
+ *
+ * The IPC Resource Manager / Configuration from file
+ *
+ * Dimitri Staessens <dimitri@ouroboros.rocks>
+ * Sander Vrijders <sander@ouroboros.rocks>
+ *
+ * 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/.
+ */
+
+
+#include "config.h"
+
+#if defined (HAVE_TOML)
+
+#define _XOPEN_SOURCE 500
+
+#define OUROBOROS_PREFIX "irmd/configuration"
+
+#include <toml.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <string.h>
+#include <arpa/inet.h>
+
+#include <ouroboros/errno.h>
+#include <ouroboros/ipcp.h>
+#include <ouroboros/logs.h>
+
+#include "irmd.h"
+#include "configfile.h"
+#include "utils.h"
+
+#define ERRBUFSZ 200
+
+static int toml_hash(toml_table_t * table,
+ struct layer_info * info)
+{
+ toml_datum_t hash;
+
+ hash = toml_string_in(table, "hash");
+ if (!hash.ok) {
+ log_dbg("No hash specified, using default.");
+ return 0;
+ }
+
+ if (strcmp(hash.u.s, "SHA3_224") == 0) {
+ info->dir_hash_algo = DIR_HASH_SHA3_224;
+ } else if (strcmp(hash.u.s, "SHA3_256") == 0) {
+ info->dir_hash_algo = DIR_HASH_SHA3_256;
+ } else if (strcmp(hash.u.s, "SHA3_384") == 0) {
+ info->dir_hash_algo = DIR_HASH_SHA3_384;
+ } else if (strcmp(hash.u.s, "SHA3_512") == 0) {
+ info->dir_hash_algo = DIR_HASH_SHA3_512;
+ } else {
+ log_err("Unknown hash algorithm: %s.", hash.u.s);
+ free(hash.u.s);
+ return -1;
+ }
+
+ free(hash.u.s);
+
+ return 0;
+}
+
+static int toml_local(toml_table_t * table,
+ struct ipcp_config * conf)
+{
+ *conf = local_default_conf;
+
+ return toml_hash(table, &conf->layer_info);
+}
+
+static int toml_eth_dev(toml_table_t * table,
+ struct eth_config * conf)
+{
+ toml_datum_t dev;
+
+ dev = toml_string_in(table, "dev");
+ if (!dev.ok) {
+ log_err("Missing device.");
+ return -1;
+ }
+
+ if (strlen(dev.u.s) > DEV_NAME_SIZE) {
+ log_err("Device name too long: %s", dev.u.s);
+ free(dev.u.s);
+ return -1;
+ }
+
+ strcpy(conf->dev, dev.u.s);
+ free(dev.u.s);
+
+ return 0;
+}
+
+static int toml_eth_llc(toml_table_t * table,
+ struct ipcp_config * conf)
+{
+ *conf = eth_llc_default_conf;
+
+ if (toml_hash(table, &conf->layer_info) < 0)
+ return -1;
+
+ return toml_eth_dev(table, &conf->eth);
+}
+
+
+static int toml_ethertype(toml_table_t * table,
+ struct eth_config * conf)
+{
+ toml_datum_t ethertype;
+
+ ethertype = toml_int_in(table, "ethertype");
+ if (ethertype.ok)
+ conf->ethertype = ethertype.u.i;
+
+ if (conf->ethertype < 0x0600 || conf->ethertype == 0xFFFF)
+ return -1;
+
+ return 0;
+}
+
+static int toml_eth_dix(toml_table_t * table,
+ struct ipcp_config * conf)
+{
+ *conf = eth_dix_default_conf;
+
+ if (toml_hash(table, &conf->layer_info) < 0)
+ return -1;
+
+ if (toml_eth_dev(table, &conf->eth) < 0)
+ return -1;
+
+ if (toml_ethertype(table, &conf->eth) < 0) {
+ log_err("Ethertype not in valid range.");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int toml_udp(toml_table_t * table,
+ struct ipcp_config * conf)
+{
+ toml_datum_t ip;
+ toml_datum_t port;
+ toml_datum_t dns;
+
+ *conf = udp_default_conf;
+
+ ip = toml_string_in(table, "ip");
+ if (!ip.ok) {
+ log_err("No IP address specified!");
+ goto fail_ip;
+ }
+
+ if (inet_pton (AF_INET, ip.u.s, &conf->udp.ip_addr) != 1) {
+ log_err("Failed to parse IPv4 address %s.", ip.u.s);
+ goto fail_addr;
+ }
+
+ port = toml_int_in(table, "port");
+ if (port.ok)
+ conf->udp.port = port.u.i;
+
+ dns = toml_string_in(table, "dns");
+ if (dns.ok) {
+ if (inet_pton(AF_INET, dns.u.s, &conf->udp.dns_addr) < 0) {
+ log_err("Failed to parse DNS address %s.", ip.u.s);
+ goto fail_dns;
+ }
+
+ free(dns.u.s);
+ }
+
+ free(ip.u.s);
+
+ return 0;
+
+ fail_dns:
+ free(dns.u.s);
+ fail_addr:
+ free(ip.u.s);
+ fail_ip:
+ return -1;
+}
+
+static int toml_broadcast(toml_table_t * table,
+ struct ipcp_config * conf)
+{
+ (void) table;
+ (void) conf;
+
+ /* Nothing to do here. */
+
+ return 0;
+}
+
+static int toml_routing(toml_table_t * table,
+ struct dt_config * conf)
+{
+ toml_datum_t routing;
+
+ routing = toml_string_in(table, "routing");
+ if (routing.ok) {
+ if (strcmp(routing.u.s, "link-state") == 0)
+ conf->routing_type = ROUTING_LINK_STATE;
+ else if (strcmp(routing.u.s, "lfa") == 0)
+ conf->routing_type = ROUTING_LINK_STATE_LFA;
+ else if (strcmp(routing.u.s, "ecmp") == 0)
+ conf->routing_type = ROUTING_LINK_STATE_ECMP;
+ else
+ conf->routing_type = ROUTING_INVALID;
+ free(routing.u.s);
+ }
+
+ if (conf->routing_type == ROUTING_INVALID)
+ return -1;
+
+ return 0;
+}
+
+static int toml_addr_auth(toml_table_t * table,
+ struct uni_config * conf)
+{
+ toml_datum_t addr_auth;
+
+ addr_auth = toml_string_in(table, "addr-auth");
+ if (addr_auth.ok) {
+ if (strcmp(addr_auth.u.s, "flat") == 0)
+ conf->addr_auth_type = ADDR_AUTH_FLAT_RANDOM;
+ else
+ conf->addr_auth_type = ADDR_AUTH_INVALID;
+ free(addr_auth.u.s);
+ }
+
+ if (conf->addr_auth_type == ADDR_AUTH_INVALID)
+ return -1;
+
+ return 0;
+}
+
+static int toml_congestion(toml_table_t * table,
+ struct uni_config * conf)
+{
+ toml_datum_t congestion;
+
+ congestion = toml_string_in(table, "congestion");
+ if (congestion.ok) {
+ if (strcmp(congestion.u.s, "none") == 0)
+ conf->cong_avoid = CA_NONE;
+ else if (strcmp(congestion.u.s, "lfa") == 0)
+ conf->cong_avoid = CA_MB_ECN;
+ else
+ conf->cong_avoid = CA_INVALID;
+ free(congestion.u.s);
+
+ }
+
+ if (conf->cong_avoid == CA_INVALID)
+ return -1;
+
+ return 0;
+}
+
+static int toml_dt(toml_table_t * table,
+ struct dt_config * conf)
+{
+ toml_datum_t addr;
+ toml_datum_t eid;
+ toml_datum_t ttl;
+
+ addr = toml_int_in(table, "addr_size");
+ if (addr.ok)
+ conf->addr_size = addr.u.i;
+
+ eid = toml_int_in(table, "eid_size");
+ if (eid.ok)
+ conf->eid_size = eid.u.i;
+
+ ttl = toml_int_in(table, "max_ttl");
+ if (ttl.ok)
+ conf->max_ttl = ttl.u.i;
+
+ if (toml_routing(table, conf) < 0) {
+ log_err("Invalid routing option.");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int toml_unicast(toml_table_t * table,
+ struct ipcp_config * conf)
+{
+
+
+ *conf = uni_default_conf;
+
+ if (toml_hash(table, &conf->layer_info) < 0)
+ return -1;
+
+ if (toml_dt(table, &conf->unicast.dt) < 0) {
+ log_err("Invalid DT configuration.");
+ return -1;
+ }
+
+ if (toml_addr_auth(table, &conf->unicast) < 0) {
+ log_err("Invalid address authority");
+ return -1;
+ }
+
+ if (toml_congestion(table, &conf->unicast) < 0) {
+ log_err("Invalid congestion avoidance algorithm.");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int toml_autobind(toml_table_t * table,
+ pid_t pid,
+ const char * name,
+ const char * layer)
+{
+ toml_datum_t autobind;
+
+ autobind = toml_bool_in(table, "autobind");
+ if (!autobind.ok)
+ return 0;
+
+ if (bind_process(pid, name) < 0) {
+ log_err("Failed to bind IPCP process %d to %s.", pid, name);
+ return -1;
+ }
+
+ if (layer != NULL && bind_process(pid, layer) < 0) {
+ log_err("Failed to bind IPCP process %d to %s.", pid, layer);
+ return -1;
+ }
+
+ return 0;
+}
+
+static int toml_register(toml_table_t * table,
+ pid_t pid)
+{
+ toml_array_t * reg;
+ int i;
+ int ret = 0;
+
+ reg = toml_array_in(table, "reg");
+ if (reg == NULL)
+ return 0;
+
+ for (i = 0; ret == 0; i++) {
+ toml_datum_t name;
+
+ name = toml_string_at(reg, i);
+ if (!name.ok)
+ break;
+
+ log_dbg("Registering %s in %d", name.u.s, pid);
+
+ ret = name_create(name.u.s, LB_SPILL);
+ if (ret < 0 && ret != -ENAME) {
+ free(name.u.s);
+ break;
+ }
+
+ ret = name_reg(name.u.s, pid);
+ free(name.u.s);
+ }
+
+ return ret;
+}
+
+static int toml_connect(toml_table_t * table,
+ pid_t pid)
+{
+ toml_array_t * conn;
+ int i;
+ int ret = 0;
+
+ conn = toml_array_in(table, "conn");
+ if (conn == NULL)
+ return 0;
+
+ for (i=0; ret == 0; i++) {
+ toml_datum_t dst;
+ qosspec_t qs = qos_raw;
+
+ dst = toml_string_at(conn, i);
+ if (!dst.ok)
+ break;
+
+ log_dbg("Connecting %d to %s", pid, dst.u.s);
+
+ ret = connect_ipcp(pid, dst.u.s, MGMT_COMP, qs);
+ if (ret == 0)
+ ret = connect_ipcp(pid, dst.u.s, DT_COMP, qs);
+
+ free(dst.u.s);
+ }
+
+ return ret;
+}
+
+static int toml_ipcp(toml_table_t * table,
+ const char * name,
+ struct ipcp_config * conf)
+{
+ toml_datum_t bootstrap;
+ toml_datum_t enrol;
+ pid_t pid;
+ int ret;
+
+ log_dbg("Found IPCP %s in configuration file.", name);
+
+ pid = create_ipcp(name, conf->type);
+ if (pid < 0) {
+ log_err("Failed to create IPCP %s.", name);
+ return -1;
+ }
+
+ bootstrap = toml_string_in(table, "bootstrap");
+ enrol = toml_string_in(table, "enrol");
+
+ if (bootstrap.ok && enrol.ok) {
+ log_err("Ignoring bootstrap for IPCP %s.", name);
+ free(bootstrap.u.s);
+ bootstrap.ok = false;
+ }
+
+ if (!bootstrap.ok && !enrol.ok) {
+ log_dbg("Nothing more to do for %s.", name);
+ return 0;
+ }
+
+ if (enrol.ok) {
+ char layer[LAYER_NAME_SIZE + 1];
+ ret = enroll_ipcp(pid, enrol.u.s);
+ free(enrol.u.s);
+ if (ret < 0) {
+ log_err("Failed to enrol %s.", name);
+ return -1;
+ }
+
+ if (get_layer_for_ipcp(pid, layer) < 0)
+ return -1;
+
+ if (toml_autobind(table, pid, name, layer))
+ return -1;
+
+ if (toml_register(table, pid) < 0) {
+ log_err("Failed to register names.");
+ return -1;
+ }
+
+ if (toml_connect(table, pid) < 0) {
+ log_err("Failed to register names.");
+ return -1;
+ }
+
+ return 0;
+ }
+
+ assert(bootstrap.ok);
+
+ if (strlen(bootstrap.u.s) > LAYER_NAME_SIZE) {
+ log_err("Layer name too long: %s", bootstrap.u.s);
+ free(bootstrap.u.s);
+ return -1;
+ }
+
+ switch (conf->type) {
+ case IPCP_LOCAL:
+ ret = toml_local(table, conf);
+ break;
+ case IPCP_ETH_DIX:
+ ret = toml_eth_dix(table, conf);
+ break;
+ case IPCP_ETH_LLC:
+ ret = toml_eth_llc(table, conf);
+ break;
+ case IPCP_UDP:
+ ret = toml_udp(table, conf);
+ break;
+ case IPCP_BROADCAST:
+ ret = toml_broadcast(table, conf);
+ break;
+ case IPCP_UNICAST:
+ ret = toml_unicast(table, conf);
+ break;
+ default:
+ log_err("Invalid IPCP type");
+ ret = -1;
+ }
+
+ if (ret < 0)
+ return -1;
+
+ strcpy(conf->layer_info.layer_name, bootstrap.u.s);
+ free(bootstrap.u.s);
+
+ if (bootstrap_ipcp(pid, conf) < 0)
+ return -1;
+
+ if (toml_autobind(table, pid, name, conf->layer_info.layer_name) < 0)
+ return -1;
+
+ if (toml_register(table, pid) < 0) {
+ log_err("Failed to register names.");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int toml_ipcp_list(toml_table_t * table,
+ enum ipcp_type type)
+{
+ int i = 0;
+ int ret = 0;
+
+ for (i = 0; ret == 0; i++) {
+ const char * key;
+ struct ipcp_config conf;
+
+ key = toml_key_in(table, i);
+ if (key == NULL)
+ break;
+
+ memset(&conf, 0, sizeof(conf));
+
+ conf.type = type;
+
+ ret = toml_ipcp(toml_table_in(table, key), key, &conf);
+ }
+
+ return ret;
+}
+
+static int args_to_argv(const char * args,
+ char *** argv)
+{
+ char * tok;
+ char * str;
+ int argc = 0;
+
+ str = (char *) args;
+
+ tok = strtok(str, " ");
+ while (tok != NULL) {
+ tok = strtok(NULL, " ");
+ argc++;
+ }
+
+ *argv = malloc((argc + 1) * sizeof(**argv));
+ if (*argv == NULL)
+ goto fail_malloc;
+
+ argc = 0;
+ tok = strtok(str, " ");
+ while (tok != NULL) {
+ (*argv)[argc] = malloc((strlen(tok) + 1) * sizeof(***argv));
+ if (*argv[argc] == NULL)
+ goto fail_malloc2;
+
+ strcpy((*argv)[argc++], tok);
+ tok = strtok(NULL, " ");
+ }
+
+ (*argv)[argc] = NULL;
+
+ return argc;
+
+ fail_malloc2:
+ argvfree(*argv);
+ fail_malloc:
+ return -1;
+
+}
+
+static int toml_prog(char * prog,
+ const char * args,
+ const char * name)
+{
+ uint16_t flags = 0;
+ int argc = 0;
+ char ** argv;
+ int ret;
+
+ if (args != NULL)
+ flags |= BIND_AUTO;
+
+ argc = args_to_argv(args, &argv);
+ if (argc < 0) {
+ log_err("Failed to parse arguments: %s", args);
+ return -1;
+ }
+
+ ret = bind_program(prog, name, flags, argc, argv);
+ if (ret < 0)
+ log_err("Failed to bind program %s %s for name %s.",
+ prog, args, name);
+
+ argvfree(argv);
+
+ return ret;
+}
+
+static int toml_prog_list(toml_array_t * progs,
+ toml_array_t * args,
+ const char * name)
+{
+ int ret = 0;
+ int i;
+
+ for (i = 0; ret == 0; i++) {
+ toml_datum_t prog;
+ toml_datum_t arg;
+
+ prog = toml_string_at(progs, i);
+ if (!prog.ok)
+ break;
+
+ if (args == NULL) {
+ ret = toml_prog(prog.u.s, NULL, name);
+ } else {
+ arg = toml_string_at(args, i);
+ if (!arg.ok) {
+ args = NULL; /* no more arguments in list. */
+ assert(arg.u.s == NULL);
+ }
+
+ ret = toml_prog(prog.u.s, arg.u.s, name);
+
+ if (arg.ok)
+ free(arg.u.s);
+ }
+
+ free(prog.u.s);
+ }
+
+ return ret;
+}
+
+static int toml_name(toml_table_t * table,
+ const char * name)
+{
+ toml_array_t * progs;
+ toml_array_t * args;
+ toml_datum_t lb;
+ enum pol_balance lb_pol = LB_SPILL;
+
+ log_dbg("Found service name %s in configuration file.", name);
+
+ lb = toml_string_in(table, "lb");
+ if (lb.ok) {
+ if (strcmp(lb.u.s, "spill") == 0)
+ lb_pol = LB_SPILL;
+ else if (strcmp(lb.u.s, "round-robin") == 0)
+ lb_pol = LB_RR;
+ else
+ lb_pol = LB_INVALID;
+ free(lb.u.s);
+ }
+
+ if (lb_pol == LB_INVALID) {
+ log_err("Invalid load-balancing policy for %s.", name);
+ return -1;
+ }
+
+ if (name_create(name, lb_pol) < 0) {
+ log_err("Failed to create name %s.", name);
+ return -1;
+ }
+
+ progs = toml_array_in(table, "prog");
+ if (progs == NULL)
+ return 0;
+
+ args = toml_array_in(table, "args");
+ if (toml_prog_list(progs, args, name) < 0)
+ return -1;
+
+ return 0;
+}
+
+static int toml_name_list(toml_table_t * table)
+{
+ int i = 0;
+ int ret = 0;
+
+ for (i = 0; ret == 0; i++) {
+ const char * key;
+
+ key = toml_key_in(table, i);
+ if (key == NULL)
+ break;
+
+ ret = toml_name(toml_table_in(table, key), key);
+ }
+
+ return ret;
+ return 0;
+}
+
+static int toml_toplevel(toml_table_t * table,
+ const char * key)
+{
+ toml_table_t * subtable;
+
+ subtable = toml_table_in(table, key);
+
+ if (strcmp(key, "local") == 0)
+ return toml_ipcp_list(subtable, IPCP_LOCAL);
+ else if (strcmp(key, "eth-dix") == 0)
+ return toml_ipcp_list(subtable, IPCP_ETH_DIX);
+ else if (strcmp(key, "eth-llc") == 0)
+ return toml_ipcp_list(subtable, IPCP_ETH_LLC);
+ else if (strcmp(key, "udp") == 0)
+ return toml_ipcp_list(subtable, IPCP_UDP);
+ else if (strcmp(key, "broadcast") == 0)
+ return toml_ipcp_list(subtable, IPCP_BROADCAST);
+ else if (strcmp(key, "unicast") == 0)
+ return toml_ipcp_list(subtable, IPCP_UNICAST);
+ else if (strcmp(key, "name") == 0)
+ return toml_name_list(subtable);
+
+ log_err("Unkown toplevel key: %s.", key);
+ return -1;
+}
+
+static int toml_load(toml_table_t * table)
+{
+ int i = 0;
+ int ret = 0;
+
+ for (i = 0; ret == 0; i++) {
+ const char * key;
+
+ key = toml_key_in(table, i);
+ if (key == NULL)
+ break;
+
+ ret = toml_toplevel(table, key);
+ }
+
+ return ret;
+}
+
+static int toml_cfg(FILE * fp)
+{
+ toml_table_t * table;
+ char errbuf[ERRBUFSZ + 1];
+
+ assert(fp != NULL);
+
+ table = toml_parse_file(fp, errbuf, sizeof(errbuf));
+ if (table == NULL) {
+ log_err("Failed to parse config file: %s.", errbuf);
+ goto fail_parse;
+ }
+
+ if (toml_load(table) < 0) {
+ log_err("Failed to load configuration.");
+ goto fail_load;
+ }
+
+ toml_free(table);
+
+ return 0;
+
+ fail_load:
+ toml_free(table);
+ fail_parse:
+ return -1;
+}
+
+int irm_configure(const char * path)
+{
+ FILE * fp;
+ char * rp;
+
+ if (path == NULL)
+ return 0;
+
+ rp = realpath(path, NULL);
+ if (rp == NULL) {
+ log_warn("Failed to resolve path for %s", path);
+ return 0;
+ }
+
+ log_info("Reading configuration from file %s", rp);
+
+ fp = fopen(rp, "r");
+ if (fp == NULL) {
+ log_err("Failed to open config file: %s\n", strerror(errno));
+ goto fail_fopen;
+ }
+
+ if (toml_cfg(fp) < 0) {
+ log_err("Failed to load config file.");
+ goto fail_cfg;
+ }
+
+ fclose(fp);
+ free(rp);
+
+ return 0;
+
+ fail_cfg:
+ fclose(fp);
+ fail_fopen:
+ free(rp);
+ return -1;
+}
+
+#endif /* HAVE_TOML */
diff --git a/src/irmd/configfile.h b/src/irmd/configfile.h
new file mode 100644
index 00000000..586bff96
--- /dev/null
+++ b/src/irmd/configfile.h
@@ -0,0 +1,29 @@
+/*
+ * Ouroboros - Copyright (C) 2016 - 2023
+ *
+ * The IPC Resource Manager / Configuration from file
+ *
+ * Dimitri Staessens <dimitri@ouroboros.rocks>
+ * Sander Vrijders <sander@ouroboros.rocks>
+ *
+ * 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/.
+ */
+
+
+#ifndef OUROBOROS_IRMD_CONFIGURATION_H
+#define OUROBOROS_IRMD_CONFIGURATION_H
+
+int irm_configure(const char * path);
+
+#endif /* OUROBOROS_IRMD_CONFIGURATION_H */
diff --git a/src/irmd/ipcp.c b/src/irmd/ipcp.c
index 182fb087..c062809c 100644
--- a/src/irmd/ipcp.c
+++ b/src/irmd/ipcp.c
@@ -20,7 +20,7 @@
* Foundation, Inc., http://www.fsf.org/about/contact/.
*/
-#define _POSIX_C_SOURCE 199309L
+#define _POSIX_C_SOURCE 200112L
#include "config.h"
@@ -194,9 +194,9 @@ int ipcp_destroy(pid_t pid)
return 0;
}
-int ipcp_bootstrap(pid_t pid,
- ipcp_config_msg_t * conf,
- struct layer_info * info)
+int ipcp_bootstrap(pid_t pid,
+ struct ipcp_config * conf,
+ struct layer_info * info)
{
ipcp_msg_t msg = IPCP_MSG__INIT;
ipcp_msg_t * recv_msg = NULL;
@@ -206,9 +206,10 @@ int ipcp_bootstrap(pid_t pid,
return -EINVAL;
msg.code = IPCP_MSG_CODE__IPCP_BOOTSTRAP;
- msg.conf = conf;
+ msg.conf = ipcp_config_s_to_msg(conf);
recv_msg = send_recv_ipcp_msg(pid, &msg);
+ ipcp_config_msg__free_unpacked(msg.conf, NULL);
if (recv_msg == NULL)
return -EIPCP;
@@ -285,7 +286,6 @@ int ipcp_connect(pid_t pid,
qosspec_t qs)
{
ipcp_msg_t msg = IPCP_MSG__INIT;
- qosspec_msg_t qs_msg = QOSSPEC_MSG__INIT;
int ret = -1;
ipcp_msg_t * recv_msg;
@@ -294,10 +294,10 @@ int ipcp_connect(pid_t pid,
msg.comp = (char *) component;
msg.has_pid = true;
msg.pid = pid;
- qs_msg = spec_to_msg(&qs);
- msg.qosspec = &qs_msg;
+ msg.qosspec = qos_spec_s_to_msg(&qs);
recv_msg = send_recv_ipcp_msg(pid, &msg);
+ free(msg.qosspec);
if (recv_msg == NULL)
return -EIPCP;
@@ -438,7 +438,6 @@ static int __ipcp_flow_alloc(pid_t pid,
size_t dlen)
{
ipcp_msg_t msg = IPCP_MSG__INIT;
- qosspec_msg_t qs_msg;
ipcp_msg_t * recv_msg = NULL;
int ret = -1;
@@ -453,13 +452,13 @@ static int __ipcp_flow_alloc(pid_t pid,
msg.has_hash = true;
msg.hash.len = len;
msg.hash.data = (uint8_t *) dst;
- qs_msg = spec_to_msg(&qs);
- msg.qosspec = &qs_msg;
+ msg.qosspec = qos_spec_s_to_msg(&qs);;
msg.has_pk = true;
msg.pk.data = (uint8_t *) data;
msg.pk.len = (uint32_t) dlen;
recv_msg = send_recv_ipcp_msg(pid, &msg);
+ free(msg.qosspec);
if (recv_msg == NULL)
return -EIPCP;
diff --git a/src/irmd/ipcp.h b/src/irmd/ipcp.h
index 40347e86..ad96ad1c 100644
--- a/src/irmd/ipcp.h
+++ b/src/irmd/ipcp.h
@@ -21,6 +21,7 @@
*/
#include <ouroboros/ipcp.h>
+#include <ouroboros/protobuf.h>
#include <ouroboros/sockets.h>
#include <sys/types.h>
@@ -37,9 +38,9 @@ int ipcp_enroll(pid_t pid,
const char * dst,
struct layer_info * info);
-int ipcp_bootstrap(pid_t pid,
- ipcp_config_msg_t * conf,
- struct layer_info * info);
+int ipcp_bootstrap(pid_t pid,
+ struct ipcp_config * conf,
+ struct layer_info * info);
int ipcp_connect(pid_t pid,
const char * dst,
diff --git a/src/irmd/irmd.h b/src/irmd/irmd.h
new file mode 100644
index 00000000..92c26818
--- /dev/null
+++ b/src/irmd/irmd.h
@@ -0,0 +1,61 @@
+/*
+ * Ouroboros - Copyright (C) 2016 - 2023
+ *
+ * The IPC Resource Manager
+ *
+ * Dimitri Staessens <dimitri@ouroboros.rocks>
+ * Sander Vrijders <sander@ouroboros.rocks>
+ *
+ * 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/.
+ */
+
+#ifndef OUROBOROS_IRMD_H
+#define OUROBOROS_IRMD_H
+
+#include <ouroboros/ipcp.h>
+#include <ouroboros/irm.h>
+
+int create_ipcp(const char * name,
+ enum ipcp_type type);
+
+int bootstrap_ipcp(pid_t pid,
+ struct ipcp_config * conf);
+
+int enroll_ipcp(pid_t pid,
+ const char * dst);
+
+int connect_ipcp(pid_t pid,
+ const char * dst,
+ const char * component,
+ qosspec_t qs);
+
+int get_layer_for_ipcp(pid_t pid,
+ char * buf);
+
+int name_create(const char * name,
+ enum pol_balance pol);
+
+int name_reg(const char * name,
+ pid_t pid);
+
+int bind_process(pid_t pid,
+ const char * name);
+
+int bind_program(char * prog,
+ const char * name,
+ uint16_t flags,
+ int argc,
+ char ** argv);
+
+#endif /* OUROBOROS_IRMD_H*/ \ No newline at end of file
diff --git a/src/irmd/main.c b/src/irmd/main.c
index 4277be3d..b2f83388 100644
--- a/src/irmd/main.c
+++ b/src/irmd/main.c
@@ -49,9 +49,11 @@
#include "utils.h"
#include "registry.h"
+#include "irmd.h"
#include "irm_flow.h"
#include "proc_table.h"
#include "ipcp.h"
+#include "configfile.h"
#include <sys/socket.h>
#include <sys/un.h>
@@ -123,7 +125,9 @@ struct {
struct bmp * flow_ids; /* flow_ids for flows */
struct list_head irm_flows; /* flow information */
pthread_rwlock_t flows_lock; /* lock for flows */
-
+#ifdef HAVE_TOML
+ char * cfg_file; /* configuration file path */
+#endif
struct lockfile * lf; /* single irmd per system */
struct shm_rdrbuff * rdrb; /* rdrbuff for packets */
@@ -363,7 +367,7 @@ static struct ipcp_entry * get_ipcp_by_dst_name(const char * name,
list_for_each_safe(p, h, &irmd.ipcps) {
struct ipcp_entry * e = list_entry(p, struct ipcp_entry, next);
- if (e->layer == NULL || e->pid == src)
+ if (e->layer == NULL || e->pid == src || e->type == IPCP_BROADCAST)
continue;
len = IPCP_HASH_LEN(e);
@@ -395,8 +399,31 @@ static struct ipcp_entry * get_ipcp_by_dst_name(const char * name,
return NULL;
}
-static pid_t create_ipcp(const char * name,
- enum ipcp_type type)
+int get_layer_for_ipcp(pid_t pid,
+ char * buf)
+{
+ struct ipcp_entry * entry;
+
+ pthread_rwlock_rdlock(&irmd.reg_lock);
+
+ entry = get_ipcp_entry_by_pid(pid);
+ if (entry == NULL || entry->layer == NULL)
+ goto fail;
+
+ strcpy(buf, entry->layer);
+
+ pthread_rwlock_unlock(&irmd.reg_lock);
+
+ return 0;
+
+ fail:
+ pthread_rwlock_unlock(&irmd.reg_lock);
+ return -1;
+}
+
+
+pid_t create_ipcp(const char * name,
+ enum ipcp_type type)
{
struct pid_el * ppid;
struct ipcp_entry * entry;
@@ -524,8 +551,8 @@ static int destroy_ipcp(pid_t pid)
return 0;
}
-static int bootstrap_ipcp(pid_t pid,
- ipcp_config_msg_t * conf)
+int bootstrap_ipcp(pid_t pid,
+ struct ipcp_config * conf)
{
struct ipcp_entry * entry;
struct layer_info info;
@@ -539,7 +566,7 @@ static int bootstrap_ipcp(pid_t pid,
return -1;
}
- if (entry->type != (enum ipcp_type) conf->ipcp_type) {
+ if (entry->type != conf->type) {
pthread_rwlock_unlock(&irmd.reg_lock);
log_err("Configuration does not match IPCP type.");
return -1;
@@ -563,13 +590,13 @@ static int bootstrap_ipcp(pid_t pid,
pthread_rwlock_unlock(&irmd.reg_lock);
log_info("Bootstrapped IPCP %d in layer %s.",
- pid, conf->layer_info->layer_name);
+ pid, conf->layer_info.layer_name);
return 0;
}
-static int enroll_ipcp(pid_t pid,
- char * dst)
+int enroll_ipcp(pid_t pid,
+ const char * dst)
{
struct ipcp_entry * entry = NULL;
struct layer_info info;
@@ -622,10 +649,10 @@ static int enroll_ipcp(pid_t pid,
return 0;
}
-static int connect_ipcp(pid_t pid,
- const char * dst,
- const char * component,
- qosspec_t qs)
+int connect_ipcp(pid_t pid,
+ const char * dst,
+ const char * component,
+ qosspec_t qs)
{
struct ipcp_entry * entry = NULL;
@@ -693,11 +720,11 @@ static int disconnect_ipcp(pid_t pid,
return 0;
}
-static int bind_program(char * prog,
- char * name,
- uint16_t flags,
- int argc,
- char ** argv)
+int bind_program(char * prog,
+ const char * name,
+ uint16_t flags,
+ int argc,
+ char ** argv)
{
char * progs;
char ** argv_dup = NULL;
@@ -719,21 +746,21 @@ static int bind_program(char * prog,
return -ENOMEM;
}
- if ((flags & BIND_AUTO) && argc) {
+ if ((flags & BIND_AUTO) && argc > 0) {
/* We need to duplicate argv and set argv[0] to prog. */
argv_dup = malloc((argc + 2) * sizeof(*argv_dup));
argv_dup[0] = strdup(prog);
for (i = 1; i <= argc; ++i) {
argv_dup[i] = strdup(argv[i - 1]);
- if (argv_dup[i] == NULL) {
- pthread_rwlock_unlock(&irmd.reg_lock);
- argvfree(argv_dup);
- log_err("Failed to bind program "
- "%s to %s.",
- prog, name);
- free(progs);
- return -ENOMEM;
- }
+ if (argv_dup[i] != NULL)
+ continue;
+
+ pthread_rwlock_unlock(&irmd.reg_lock);
+ log_err("Failed to bind program %s to %s.",
+ prog, name);
+ argvfree(argv_dup);
+ free(progs);
+ return -ENOMEM;
}
argv_dup[argc + 1] = NULL;
}
@@ -771,8 +798,8 @@ static int bind_program(char * prog,
return 0;
}
-static int bind_process(pid_t pid,
- char * name)
+int bind_process(pid_t pid,
+ const char * name)
{
char * name_dup = NULL;
struct proc_entry * e = NULL;
@@ -952,8 +979,8 @@ static ssize_t list_ipcps(ipcp_info_msg_t *** ipcps,
return -ENOMEM;
}
-static int name_create(const char * name,
- enum pol_balance pol)
+int name_create(const char * name,
+ enum pol_balance pol)
{
struct reg_entry * re;
struct list_head * p;
@@ -964,8 +991,8 @@ static int name_create(const char * name,
if (registry_has_name(&irmd.registry, name)) {
pthread_rwlock_unlock(&irmd.reg_lock);
- log_err("Registry entry for %s already exists.", name);
- return -ENAME;
+ log_warn("Registry entry for %s already exists.", name);
+ return 0;
}
re = registry_add_name(&irmd.registry, name);
@@ -1084,8 +1111,8 @@ static ssize_t list_names(name_info_msg_t *** names,
return -ENOMEM;
}
-static int name_reg(const char * name,
- pid_t pid)
+int name_reg(const char * name,
+ pid_t pid)
{
size_t len;
struct ipcp_entry * ipcp;
@@ -1403,8 +1430,7 @@ static int flow_alloc(pid_t pid,
int state;
uint8_t * hash;
- log_info("Allocating flow for %d to %s.\n",
- pid, dst);
+ log_info("Allocating flow for %d to %s.", pid, dst);
ipcp = join ? get_ipcp_entry_by_layer(dst)
: get_ipcp_by_dst_name(dst, pid);
@@ -1967,12 +1993,13 @@ static void * mainloop(void * o)
(void) o;
while (true) {
- irm_msg_t * ret_msg;
- struct irm_flow e;
- struct timespec * timeo = NULL;
- struct timespec ts = {0, 0};
- struct cmd * cmd;
- int result;
+ irm_msg_t * ret_msg;
+ struct irm_flow e;
+ struct ipcp_config conf;
+ struct timespec * timeo = NULL;
+ struct timespec ts = {0, 0};
+ struct cmd * cmd;
+ int result;
memset(&e, 0, sizeof(e));
@@ -2035,14 +2062,15 @@ static void * mainloop(void * o)
result = destroy_ipcp(msg->pid);
break;
case IRM_MSG_CODE__IRM_BOOTSTRAP_IPCP:
- result = bootstrap_ipcp(msg->pid, msg->conf);
+ conf = ipcp_config_msg_to_s(msg->conf);
+ result = bootstrap_ipcp(msg->pid, &conf);
break;
case IRM_MSG_CODE__IRM_ENROLL_IPCP:
result = enroll_ipcp(msg->pid, msg->dst);
break;
case IRM_MSG_CODE__IRM_CONNECT_IPCP:
result = connect_ipcp(msg->pid, msg->dst, msg->comp,
- msg_to_spec(msg->qosspec));
+ qos_spec_msg_to_s(msg->qosspec));
break;
case IRM_MSG_CODE__IRM_DISCONNECT_IPCP:
result = disconnect_ipcp(msg->pid, msg->dst, msg->comp);
@@ -2091,13 +2119,11 @@ static void * mainloop(void * o)
result = flow_accept(msg->pid, timeo, &e,
msg->pk.data, msg->pk.len);
if (result == 0) {
- qosspec_msg_t qs_msg;
ret_msg->has_flow_id = true;
ret_msg->flow_id = e.flow_id;
ret_msg->has_pid = true;
ret_msg->pid = e.n_1_pid;
- qs_msg = spec_to_msg(&e.qs);
- ret_msg->qosspec = &qs_msg;
+ ret_msg->qosspec = qos_spec_s_to_msg(&e.qs);
ret_msg->has_pk = true;
ret_msg->pk.data = e.data;
ret_msg->pk.len = e.len;
@@ -2109,7 +2135,7 @@ static void * mainloop(void * o)
assert(msg->pk.len > 0 ? msg->pk.data != NULL
: msg->pk.data == NULL);
result = flow_alloc(msg->pid, msg->dst,
- msg_to_spec(msg->qosspec),
+ qos_spec_msg_to_s(msg->qosspec),
timeo, &e, false, msg->pk.data,
msg->pk.len);
if (result == 0) {
@@ -2127,7 +2153,7 @@ static void * mainloop(void * o)
case IRM_MSG_CODE__IRM_FLOW_JOIN:
assert(msg->pk.len == 0 && msg->pk.data == NULL);
result = flow_alloc(msg->pid, msg->dst,
- msg_to_spec(msg->qosspec),
+ qos_spec_msg_to_s(msg->qosspec),
timeo, &e, true, NULL, 0);
if (result == 0) {
ret_msg->has_flow_id = true;
@@ -2150,7 +2176,7 @@ static void * mainloop(void * o)
&e,
msg->hash.data,
msg->mpl,
- msg_to_spec(msg->qosspec),
+ qos_spec_msg_to_s(msg->qosspec),
msg->pk.data,
msg->pk.len);
if (result == 0) {
@@ -2199,8 +2225,6 @@ static void * mainloop(void * o)
irm_msg__pack(ret_msg, buffer.data);
- /* Can't free the qosspec. */
- ret_msg->qosspec = NULL;
irm_msg__free_unpacked(ret_msg, NULL);
pthread_cleanup_push(__cleanup_close_ptr, &sfd);
@@ -2493,6 +2517,9 @@ static int irm_init(void)
static void usage(void)
{
printf("Usage: irmd \n"
+#ifdef OUROBOROS_CONFIG_INI
+ " [--config <path> (Path to configuration file)]\n"
+#endif
" [--stdout (Log to stdout instead of system log)]\n"
" [--version (Print version number and exit)]\n"
"\n");
@@ -2566,6 +2593,9 @@ static void irm_stop(void)
static void irm_argparse(int argc,
char ** argv)
{
+#ifdef HAVE_TOML
+ irmd.cfg_file = OUROBOROS_CONFIG_DIR OUROBOROS_CONFIG_FILE;
+#endif
argc--;
argv++;
while (argc > 0) {
@@ -2579,6 +2609,12 @@ static void irm_argparse(int argc,
OUROBOROS_VERSION_MINOR,
OUROBOROS_VERSION_PATCH);
exit(EXIT_SUCCESS);
+#ifdef HAVE_TOML
+ } else if (strcmp (*argv, "--config") == 0) {
+ irmd.cfg_file = *(argv + 1);
+ argc -= 2;
+ argv += 2;
+#endif
} else {
usage();
exit(EXIT_FAILURE);
@@ -2613,6 +2649,10 @@ int main(int argc,
if (irm_start() < 0)
goto fail_irm_start;
+#ifdef HAVE_TOML
+ if (irm_configure(irmd.cfg_file) < 0)
+ irmd_set_state(IRMD_NULL);
+#endif
irm_sigwait(sigset);
irm_stop();
diff --git a/src/irmd/registry.c b/src/irmd/registry.c
index c68b9abc..0aebdab7 100644
--- a/src/irmd/registry.c
+++ b/src/irmd/registry.c
@@ -296,6 +296,7 @@ int reg_entry_add_pid(struct reg_entry * e,
list_add(&i->next, &e->reg_pids);
break;
default:
+ free(i);
assert(false);
};
diff --git a/src/irmd/utils.h b/src/irmd/utils.h
index 7fd72cd4..83585f21 100644
--- a/src/irmd/utils.h
+++ b/src/irmd/utils.h
@@ -23,6 +23,8 @@
#ifndef OUROBOROS_IRMD_UTILS_H
#define OUROBOROS_IRMD_UTILS_H
+#include <ouroboros/list.h>
+
#include <sys/types.h>
struct str_el {
diff --git a/src/lib/CMakeLists.txt b/src/lib/CMakeLists.txt
index 74fbb707..1a585249 100644
--- a/src/lib/CMakeLists.txt
+++ b/src/lib/CMakeLists.txt
@@ -4,13 +4,18 @@ include_directories(${CMAKE_CURRENT_BINARY_DIR})
include_directories(${CMAKE_SOURCE_DIR}/include)
include_directories(${CMAKE_BINARY_DIR}/include)
-protobuf_generate_c(IRM_PROTO_SRCS IRM_PROTO_HDRS irmd_messages.proto)
-protobuf_generate_c(IPCP_PROTO_SRCS IPCP_PROTO_HDRS ipcpd_messages.proto)
protobuf_generate_c(QOSSPEC_PROTO_SRCS QOSSPEC_PROTO_HDRS
qosspec.proto)
-protobuf_generate_c(LAYER_CONFIG_PROTO_SRCS LAYER_CONFIG_PROTO_HDRS
+protobuf_generate_c(IPCP_CONFIG_PROTO_SRCS IPCP_CONFIG_PROTO_HDRS
ipcp_config.proto)
-protobuf_generate_c(CACEP_PROTO_SRCS CACEP_PROTO_HDRS cacep.proto)
+protobuf_generate_c(ENROLL_PROTO_SRCS ENROLL_PROTO_HDRS
+ enroll.proto)
+protobuf_generate_c(CACEP_PROTO_SRCS CACEP_PROTO_HDRS
+ cacep.proto)
+protobuf_generate_c(IRM_PROTO_SRCS IRM_PROTO_HDRS
+ irmd_messages.proto)
+protobuf_generate_c(IPCP_PROTO_SRCS IPCP_PROTO_HDRS
+ ipcpd_messages.proto)
if (NOT APPLE)
find_library(LIBRT_LIBRARIES rt)
@@ -253,9 +258,11 @@ set(SOURCE_FILES_COMMON
logs.c
md5.c
notifier.c
+ protobuf.c
qoscube.c
random.c
rib.c
+ serdes-oep.c
sha3.c
shm_flow_set.c
shm_rbuff.c
@@ -269,7 +276,8 @@ configure_file("${CMAKE_CURRENT_SOURCE_DIR}/config.h.in"
"${CMAKE_CURRENT_BINARY_DIR}/config.h" @ONLY)
add_library(ouroboros-common SHARED ${SOURCE_FILES_COMMON} ${IRM_PROTO_SRCS}
- ${IPCP_PROTO_SRCS} ${LAYER_CONFIG_PROTO_SRCS} ${QOSSPEC_PROTO_SRCS})
+ ${IPCP_PROTO_SRCS} ${IPCP_CONFIG_PROTO_SRCS} ${QOSSPEC_PROTO_SRCS}
+ ${ENROLL_PROTO_SRCS})
add_library(ouroboros-dev SHARED ${SOURCE_FILES_DEV} ${CACEP_PROTO_SRCS})
diff --git a/src/lib/dev.c b/src/lib/dev.c
index c46bbdd7..e84efe55 100644
--- a/src/lib/dev.c
+++ b/src/lib/dev.c
@@ -39,6 +39,7 @@
#include <ouroboros/fccntl.h>
#include <ouroboros/bitmap.h>
#include <ouroboros/np1_flow.h>
+#include <ouroboros/protobuf.h>
#include <ouroboros/pthread.h>
#include <ouroboros/random.h>
#include <ouroboros/shm_flow_set.h>
@@ -795,7 +796,7 @@ int flow_accept(qosspec_t * qs,
crypt_dh_pkp_destroy(pkp);
fd = flow_init(recv_msg->flow_id, recv_msg->pid,
- msg_to_spec(recv_msg->qosspec), s,
+ qos_spec_msg_to_s(recv_msg->qosspec), s,
recv_msg->mpl);
irm_msg__free_unpacked(recv_msg, NULL);
@@ -827,7 +828,6 @@ static int __flow_alloc(const char * dst,
bool join)
{
irm_msg_t msg = IRM_MSG__INIT;
- qosspec_msg_t qs_msg = QOSSPEC_MSG__INIT;
irm_msg_t * recv_msg;
int fd;
void * pkp = NULL; /* public key pair */
@@ -846,8 +846,7 @@ static int __flow_alloc(const char * dst,
msg.dst = (char *) dst;
msg.has_pid = true;
msg.pid = getpid();
- qs_msg = spec_to_msg(qs);
- msg.qosspec = &qs_msg;
+ msg.qosspec = qos_spec_s_to_msg(qs);
if (timeo != NULL) {
msg.has_timeo_sec = true;
@@ -871,6 +870,8 @@ static int __flow_alloc(const char * dst,
}
recv_msg = send_recv_irm_msg(&msg);
+ qosspec_msg__free_unpacked(msg.qosspec, NULL);
+
if (recv_msg == NULL)
goto fail_send;
@@ -1832,7 +1833,6 @@ int ipcp_flow_req_arr(const uint8_t * dst,
{
irm_msg_t msg = IRM_MSG__INIT;
irm_msg_t * recv_msg;
- qosspec_msg_t qs_msg;
int fd;
assert(dst != NULL);
@@ -1843,8 +1843,7 @@ int ipcp_flow_req_arr(const uint8_t * dst,
msg.has_hash = true;
msg.hash.len = len;
msg.hash.data = (uint8_t *) dst;
- qs_msg = spec_to_msg(&qs);
- msg.qosspec = &qs_msg;
+ msg.qosspec = qos_spec_s_to_msg(&qs);
msg.has_mpl = true;
msg.mpl = mpl;
msg.has_pk = true;
@@ -1852,6 +1851,8 @@ int ipcp_flow_req_arr(const uint8_t * dst,
msg.pk.len = dlen;
recv_msg = send_recv_irm_msg(&msg);
+ qosspec_msg__free_unpacked(msg.qosspec, NULL);
+
if (recv_msg == NULL)
return -EIRMD;
diff --git a/src/lib/enroll.proto b/src/lib/enroll.proto
new file mode 100644
index 00000000..34ca1847
--- /dev/null
+++ b/src/lib/enroll.proto
@@ -0,0 +1,40 @@
+/*
+ * Ouroboros - Copyright (C) 2016 - 2023
+ *
+ * Enrollment protocol
+ *
+ * Dimitri Staessens <dimitri@ouroboros.rocks>
+ * Sander Vrijders <sander@ouroboros.rocks>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * version 2.1 as published by the Free Software Foundation.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., http://www.fsf.org/about/contact/.
+ */
+
+syntax = "proto2";
+import "ipcp_config.proto";
+
+message enroll_req_msg {
+ /* TODO authentication */
+ required uint32 magic = 1;
+}
+
+message enroll_resp_msg {
+ required int64 t_sec = 1;
+ required int32 t_nsec = 2;
+ required int32 response = 3;
+ optional ipcp_config_msg conf = 4;
+}
+
+message enroll_ack_msg {
+ required int32 response = 1;
+}
diff --git a/src/lib/ipcp_config.proto b/src/lib/ipcp_config.proto
index c6481b09..1ff304f1 100644
--- a/src/lib/ipcp_config.proto
+++ b/src/lib/ipcp_config.proto
@@ -42,7 +42,7 @@ message uni_config_msg {
message eth_config_msg {
required string dev = 1;
- optional uint32 ethertype = 2;
+ required uint32 ethertype = 2;
}
message udp_config_msg {
@@ -53,22 +53,8 @@ message udp_config_msg {
message ipcp_config_msg {
required layer_info_msg layer_info = 1;
- required int32 ipcp_type = 2;
+ required uint32 ipcp_type = 2;
optional uni_config_msg unicast = 3;
optional udp_config_msg udp = 4;
optional eth_config_msg eth = 5;
}
-
-enum enroll_code {
- ENROLL_REQ = 1;
- ENROLL_BOOT = 2;
- ENROLL_DONE = 4;
-};
-
-message enroll_msg {
- required enroll_code code = 1;
- optional ipcp_config_msg conf = 2;
- optional int64 t_sec = 3;
- optional uint32 t_nsec = 4;
- optional int32 result = 5;
-}; \ No newline at end of file
diff --git a/src/lib/ipcpd_messages.proto b/src/lib/ipcpd_messages.proto
index c9853677..05831fa0 100644
--- a/src/lib/ipcpd_messages.proto
+++ b/src/lib/ipcpd_messages.proto
@@ -1,7 +1,7 @@
/*
* Ouroboros - Copyright (C) 2016 - 2023
*
- * IPCPd message
+ * Messages sent to IPCPds
*
* Dimitri Staessens <dimitri@ouroboros.rocks>
* Sander Vrijders <sander@ouroboros.rocks>
diff --git a/src/lib/irm.c b/src/lib/irm.c
index 2a8aa05c..75071260 100644
--- a/src/lib/irm.c
+++ b/src/lib/irm.c
@@ -31,6 +31,7 @@
#include <ouroboros/irm.h>
#include <ouroboros/utils.h>
#include <ouroboros/sockets.h>
+#include <ouroboros/protobuf.h>
#include <stdbool.h>
#include <string.h>
@@ -98,15 +99,9 @@ int irm_destroy_ipcp(pid_t pid)
int irm_bootstrap_ipcp(pid_t pid,
const struct ipcp_config * conf)
{
- irm_msg_t msg = IRM_MSG__INIT;
- ipcp_config_msg_t cfg_msg = IPCP_CONFIG_MSG__INIT;
- layer_info_msg_t layer_info_msg = LAYER_INFO_MSG__INIT;
- dt_config_msg_t dt_cfg_msg = DT_CONFIG_MSG__INIT;
- uni_config_msg_t uni_cfg_msg = UNI_CONFIG_MSG__INIT;
- eth_config_msg_t eth_cfg_msg = ETH_CONFIG_MSG__INIT;
- udp_config_msg_t udp_cfg_msg = UDP_CONFIG_MSG__INIT;
- irm_msg_t * recv_msg = NULL;
- int ret = -1;
+ irm_msg_t msg = IRM_MSG__INIT;
+ irm_msg_t * recv_msg;
+ int ret;
if (pid == -1 || conf == NULL)
return -EINVAL;
@@ -114,48 +109,10 @@ int irm_bootstrap_ipcp(pid_t pid,
msg.code = IRM_MSG_CODE__IRM_BOOTSTRAP_IPCP;
msg.has_pid = true;
msg.pid = pid;
-
- cfg_msg.ipcp_type = conf->type;
- layer_info_msg.layer_name = (char *) conf->layer_info.layer_name;
- layer_info_msg.dir_hash_algo = conf->layer_info.dir_hash_algo;
-
- switch (conf->type) {
- case IPCP_UNICAST:
- dt_cfg_msg.addr_size = conf->unicast.dt.addr_size;
- dt_cfg_msg.eid_size = conf->unicast.dt.eid_size;
- dt_cfg_msg.max_ttl = conf->unicast.dt.max_ttl;
- dt_cfg_msg.routing_type = conf->unicast.dt.routing_type;
- uni_cfg_msg.dt = &dt_cfg_msg;
- uni_cfg_msg.addr_auth_type = conf->unicast.addr_auth_type;
- uni_cfg_msg.cong_avoid = conf->unicast.cong_avoid;
- cfg_msg.unicast = &uni_cfg_msg;
- break;
- case IPCP_UDP:
- udp_cfg_msg.ip_addr = conf->udp.ip_addr;
- udp_cfg_msg.dns_addr = conf->udp.dns_addr;
- udp_cfg_msg.port = conf->udp.port;
- cfg_msg.udp = &udp_cfg_msg;
- break;
- case IPCP_LOCAL:
- /* FALLTHRU */
- case IPCP_BROADCAST:
- break;
- case IPCP_ETH_DIX:
- eth_cfg_msg.has_ethertype = true;
- eth_cfg_msg.ethertype = conf->eth.ethertype;
- /* FALLTHRU */
- case IPCP_ETH_LLC:
- eth_cfg_msg.dev = conf->eth.dev;
- cfg_msg.eth = &eth_cfg_msg;
- break;
- default:
- return -EIPCPTYPE;
- }
-
- cfg_msg.layer_info = &layer_info_msg;
- msg.conf = &cfg_msg;
+ msg.conf = ipcp_config_s_to_msg(conf);
recv_msg = send_recv_irm_msg(&msg);
+ ipcp_config_msg__free_unpacked(msg.conf, NULL);
if (recv_msg == NULL)
return -EIRMD;
@@ -175,8 +132,7 @@ int irm_connect_ipcp(pid_t pid,
const char * component,
qosspec_t qs)
{
- irm_msg_t msg = IRM_MSG__INIT;
- qosspec_msg_t qs_msg = QOSSPEC_MSG__INIT;
+ irm_msg_t msg = IRM_MSG__INIT;
irm_msg_t * recv_msg;
int ret;
@@ -186,10 +142,11 @@ int irm_connect_ipcp(pid_t pid,
msg.comp = (char *) component;
msg.has_pid = true;
msg.pid = pid;
- qs_msg = spec_to_msg(&qs);
- msg.qosspec = &qs_msg;
+ msg.qosspec = qos_spec_s_to_msg(&qs);
recv_msg = send_recv_irm_msg(&msg);
+ qosspec_msg__free_unpacked(msg.qosspec, NULL);
+
if (recv_msg == NULL)
return -EIRMD;
diff --git a/src/lib/irmd_messages.proto b/src/lib/irmd_messages.proto
index 8c8c4ca8..8cf5da9e 100644
--- a/src/lib/irmd_messages.proto
+++ b/src/lib/irmd_messages.proto
@@ -1,7 +1,7 @@
/*
* Ouroboros - Copyright (C) 2016 - 2023
*
- * IRMd message
+ * Messages sent to IRMd
*
* Dimitri Staessens <dimitri@ouroboros.rocks>
* Sander Vrijders <sander@ouroboros.rocks>
diff --git a/src/lib/protobuf.c b/src/lib/protobuf.c
new file mode 100644
index 00000000..0855305f
--- /dev/null
+++ b/src/lib/protobuf.c
@@ -0,0 +1,438 @@
+/*
+ * Ouroboros - Copyright (C) 2016 - 2023
+ *
+ * Protobuf syntax conversion
+ *
+ * Dimitri Staessens <dimitri@ouroboros.rocks>
+ * Sander Vrijders <sander@ouroboros.rocks>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * version 2.1 as published by the Free Software Foundation.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., http://www.fsf.org/about/contact/.
+ */
+
+#define _DEFAULT_SOURCE
+
+#include <ouroboros/protobuf.h>
+
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+layer_info_msg_t * layer_info_s_to_msg(const struct layer_info * s)
+{
+ layer_info_msg_t * msg;
+
+ assert(s != NULL);
+
+ msg = malloc(sizeof(*msg));
+ if (msg == NULL)
+ goto fail_malloc;
+
+ layer_info_msg__init(msg);
+
+ msg->layer_name = strdup(s->layer_name);
+ if (msg->layer_name == NULL)
+ goto fail_msg;
+
+ msg->dir_hash_algo = s->dir_hash_algo;
+
+ return msg;
+
+ fail_msg:
+ layer_info_msg__free_unpacked(msg, NULL);
+ fail_malloc:
+ return NULL;
+}
+
+struct layer_info layer_info_msg_to_s(const layer_info_msg_t * msg)
+{
+ struct layer_info s;
+
+ assert(msg != NULL);
+ assert(strlen(msg->layer_name) <= LAYER_NAME_SIZE);
+
+ s.dir_hash_algo = msg->dir_hash_algo;
+ strcpy(s.layer_name, msg->layer_name);
+
+ return s;
+}
+
+dt_config_msg_t * dt_config_s_to_msg(const struct dt_config * s)
+{
+ dt_config_msg_t * msg;
+
+ assert(s != NULL);
+
+ msg = malloc(sizeof(*msg));
+ if (msg == NULL)
+ return NULL;
+
+ dt_config_msg__init(msg);
+
+ msg->addr_size = s->addr_size;
+ msg->eid_size = s->eid_size;
+ msg->max_ttl = s->max_ttl;
+ msg->routing_type = s->routing_type;
+
+ return msg;
+}
+
+struct dt_config dt_config_msg_to_s(const dt_config_msg_t * msg)
+{
+ struct dt_config s;
+
+ assert(msg != NULL);
+
+ s.addr_size = msg->addr_size;
+ s.eid_size = msg->eid_size;
+ s.max_ttl = msg->max_ttl;
+ s.routing_type = msg->routing_type;
+
+ return s;
+}
+
+uni_config_msg_t * uni_config_s_to_msg(const struct uni_config * s)
+{
+ uni_config_msg_t * msg;
+
+ assert(s != NULL);
+
+ msg = malloc(sizeof(*msg));
+ if (msg == NULL)
+ goto fail_malloc;
+
+ uni_config_msg__init(msg);
+
+ msg->dt = dt_config_s_to_msg(&s->dt);
+ if (msg->dt == NULL)
+ goto fail_msg;
+
+ msg->addr_auth_type = s->addr_auth_type;
+ msg->cong_avoid = s->cong_avoid;
+
+ return msg;
+
+ fail_msg:
+ uni_config_msg__free_unpacked(msg, NULL);
+ fail_malloc:
+ return NULL;
+}
+
+struct uni_config uni_config_msg_to_s(const uni_config_msg_t * msg)
+{
+ struct uni_config s;
+
+ s.dt = dt_config_msg_to_s(msg->dt);
+
+ s.addr_auth_type = msg->addr_auth_type;
+ s.cong_avoid = msg->cong_avoid;
+
+ return s;
+}
+
+udp_config_msg_t * udp_config_s_to_msg(const struct udp_config * s)
+{
+ udp_config_msg_t * msg;
+
+ assert(s != NULL);
+
+ msg = malloc(sizeof(*msg));
+ if (msg == NULL)
+ return NULL;
+
+ udp_config_msg__init(msg);
+
+ msg->ip_addr = s->ip_addr;
+ msg->dns_addr = s->dns_addr;
+ msg->port = s->port;
+
+ return msg;
+}
+
+struct udp_config udp_config_msg_to_s(const udp_config_msg_t * msg)
+{
+ struct udp_config s;
+
+ assert(msg != NULL);
+
+ s.ip_addr = msg->ip_addr;
+ s.dns_addr = msg->dns_addr;
+ s.port = msg->port;
+
+ return s;
+}
+
+eth_config_msg_t * eth_config_s_to_msg(const struct eth_config * s)
+{
+ eth_config_msg_t * msg;
+
+ assert(s != NULL);
+
+ msg = malloc(sizeof(*msg));
+ if (msg == NULL)
+ goto fail_malloc;
+
+ eth_config_msg__init(msg);
+
+ msg->dev = strdup(s->dev);
+ if (msg->dev == NULL)
+ goto fail_msg;
+
+ msg->ethertype = s->ethertype;
+
+ return msg;
+
+ fail_msg:
+ eth_config_msg__free_unpacked(msg, NULL);
+ fail_malloc:
+ return NULL;
+}
+
+struct eth_config eth_config_msg_to_s(const eth_config_msg_t * msg)
+{
+ struct eth_config s;
+
+ assert(msg != NULL);
+ assert(strlen(msg->dev) <= DEV_NAME_SIZE);
+
+ strcpy(s.dev, msg->dev);
+ s.ethertype = msg->ethertype;
+
+ return s;
+}
+
+
+ipcp_config_msg_t * ipcp_config_s_to_msg(const struct ipcp_config * s)
+{
+ ipcp_config_msg_t * msg;
+
+ assert(s != NULL);
+
+ msg = malloc(sizeof(*msg));
+ if (msg == NULL)
+ goto fail_malloc;
+
+ ipcp_config_msg__init(msg);
+
+ switch (s->type) {
+ case IPCP_LOCAL:
+ break;
+ case IPCP_UNICAST:
+ msg->unicast = uni_config_s_to_msg(&s->unicast);
+ if (msg->unicast == NULL)
+ goto fail_msg;
+ break;
+ case IPCP_BROADCAST:
+ break;
+ case IPCP_ETH_LLC:
+ /* FALLTHRU */
+ case IPCP_ETH_DIX:
+ msg->eth = eth_config_s_to_msg(&s->eth);
+ if (msg->eth == NULL)
+ goto fail_msg;
+ break;
+ case IPCP_UDP:
+ msg->udp = udp_config_s_to_msg(&s->udp);
+ if (msg->udp == NULL)
+ goto fail_msg;
+ break;
+ default:
+ /* No checks here */
+ break;
+ }
+
+ msg->ipcp_type = s->type;
+
+ msg->layer_info = layer_info_s_to_msg(&s->layer_info);
+ if (msg->layer_info == NULL)
+ goto fail_msg;
+
+ return msg;
+
+ fail_msg:
+ ipcp_config_msg__free_unpacked(msg, NULL);
+ fail_malloc:
+ return NULL;
+}
+
+struct ipcp_config ipcp_config_msg_to_s(const ipcp_config_msg_t * msg)
+{
+ struct ipcp_config s;
+
+ assert(msg != NULL);
+
+ s.type = msg->ipcp_type;
+
+ s.layer_info = layer_info_msg_to_s(msg->layer_info);
+
+ switch(msg->ipcp_type) {
+ case IPCP_LOCAL:
+ break;
+ case IPCP_UNICAST:
+ s.unicast = uni_config_msg_to_s(msg->unicast);
+ break;
+ case IPCP_ETH_LLC:
+ /* FALLTHRU */
+ case IPCP_ETH_DIX:
+ s.eth = eth_config_msg_to_s(msg->eth);
+ break;
+ case IPCP_UDP:
+ s.udp = udp_config_msg_to_s(msg->udp);
+ break;
+ case IPCP_BROADCAST:
+ break;
+ default:
+ /* No checks here */
+ break;
+ }
+
+ return s;
+}
+
+qosspec_msg_t * qos_spec_s_to_msg(const struct qos_spec * s)
+{
+ struct qos_spec spec;
+ qosspec_msg_t * msg;
+
+ msg = malloc(sizeof(*msg));
+ if (msg == NULL)
+ return NULL;
+
+ qosspec_msg__init(msg);
+
+ spec = (s == NULL ? qos_raw : *s);
+
+ msg->delay = spec.delay;
+ msg->bandwidth = spec.bandwidth;
+ msg->availability = spec.availability;
+ msg->loss = spec.loss;
+ msg->ber = spec.ber;
+ msg->in_order = spec.in_order;
+ msg->max_gap = spec.max_gap;
+ msg->cypher_s = spec.cypher_s;
+ msg->timeout = spec.timeout;
+
+ return msg;
+}
+
+struct qos_spec qos_spec_msg_to_s(const qosspec_msg_t * msg)
+{
+ struct qos_spec s;
+
+ assert(msg != NULL);
+
+ s.delay = msg->delay;
+ s.bandwidth = msg->bandwidth;
+ s.availability = msg->availability;
+ s.loss = msg->loss;
+ s.ber = msg->ber;
+ s.in_order = msg->in_order;
+ s.max_gap = msg->max_gap;
+ s.cypher_s = msg->cypher_s;
+ s.timeout = msg->timeout;
+
+ return s;
+}
+
+enroll_req_msg_t * enroll_req_s_to_msg(void)
+{
+ enroll_req_msg_t * msg;
+
+ msg = malloc(sizeof(*msg));
+ if (msg == NULL)
+ return NULL;
+
+ enroll_req_msg__init(msg);
+
+ msg->magic = 0xC0FFEE;
+
+ return msg;
+}
+
+int enroll_req_msg_to_s(const enroll_req_msg_t * msg)
+{
+ (void) msg;
+
+ assert(msg != NULL);
+
+ return 0;
+}
+
+enroll_resp_msg_t * enroll_resp_s_to_msg(const struct enroll_resp * s)
+{
+ enroll_resp_msg_t * msg;
+
+ assert(s != NULL);
+
+ msg = malloc(sizeof(*msg));
+ if (msg == NULL)
+ goto fail_malloc;
+
+ enroll_resp_msg__init(msg);
+
+ msg->t_sec = s->t.tv_sec;
+ msg->t_nsec = s->t.tv_nsec;
+ msg->response = s->response;
+
+ if (msg->response < 0)
+ return msg;
+
+ msg->conf = ipcp_config_s_to_msg(&s->conf);
+ if (msg->conf == NULL)
+ goto fail_conf;
+
+ return msg;
+
+ fail_conf:
+ enroll_resp_msg__free_unpacked(msg, NULL);
+ fail_malloc:
+ return NULL;
+}
+
+struct enroll_resp enroll_resp_msg_to_s(enroll_resp_msg_t * msg)
+{
+ struct enroll_resp s;
+
+ assert (msg != NULL);
+
+ s.response = msg->response;
+ if (s.response >= 0)
+ s.conf = ipcp_config_msg_to_s(msg->conf);
+
+ s.t.tv_sec = msg->t_sec;
+ s.t.tv_nsec = msg->t_nsec;
+
+ return s;
+}
+
+enroll_ack_msg_t * enroll_ack_s_to_msg(int response)
+{
+ enroll_ack_msg_t * msg;
+
+ msg = malloc(sizeof(*msg));
+ if (msg == NULL)
+ return NULL;
+
+ enroll_ack_msg__init(msg);
+
+ msg->response = response;
+
+ return msg;
+}
+
+int enroll_ack_msg_to_s(const enroll_ack_msg_t * msg)
+{
+ assert(msg != NULL);
+
+ return msg->response;
+}
diff --git a/src/lib/serdes-oep.c b/src/lib/serdes-oep.c
new file mode 100644
index 00000000..cae5c598
--- /dev/null
+++ b/src/lib/serdes-oep.c
@@ -0,0 +1,155 @@
+/*
+ * Ouroboros - Copyright (C) 2016 - 2023
+ *
+ * Ouroboros Enrollment Protocol - serialization/deserialization
+ *
+ * Dimitri Staessens <dimitri@ouroboros.rocks>
+ * Sander Vrijders <sander@ouroboros.rocks>
+ *
+ * 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/.
+ */
+
+#define _POSIX_C_SOURCE 200112L
+
+#include <ouroboros/protobuf.h>
+#include <ouroboros/serdes-oep.h>
+
+
+ssize_t enroll_req_ser(buffer_t buf)
+{
+ enroll_req_msg_t * msg;
+ ssize_t sz;
+
+ msg = enroll_req_s_to_msg();
+ if (msg == NULL)
+ goto fail_msg;
+
+ sz = enroll_req_msg__get_packed_size(msg);
+ if (sz < 0 || (size_t) sz > buf.len)
+ goto fail_pack;
+
+ enroll_req_msg__pack(msg, buf.data);
+
+ enroll_req_msg__free_unpacked(msg, NULL);
+
+ return sz;
+
+ fail_pack:
+ enroll_req_msg__free_unpacked(msg, NULL);
+ fail_msg:
+ return -1;
+}
+
+int enroll_req_des(const buffer_t buf)
+{
+ enroll_req_msg_t * msg;
+
+ msg = enroll_req_msg__unpack(NULL, buf.len, buf.data);
+ if (msg == NULL)
+ return -1;
+
+ /* Nothing in request yet, if it unpacks, it's good. */
+
+ enroll_req_msg__free_unpacked(msg, NULL);
+
+ return 0;
+}
+
+ssize_t enroll_resp_ser(const struct enroll_resp * resp,
+ buffer_t buf)
+{
+ enroll_resp_msg_t * msg;
+ ssize_t sz;
+
+ msg = enroll_resp_s_to_msg(resp);
+ if (msg == NULL)
+ goto fail_msg;
+
+ sz = enroll_resp_msg__get_packed_size(msg);
+ if (sz < 0 || (size_t) sz > buf.len)
+ goto fail_pack;
+
+ msg->t_sec = resp->t.tv_sec;
+ msg->t_nsec = resp->t.tv_nsec;
+
+ enroll_resp_msg__pack(msg, buf.data);
+
+ enroll_resp_msg__free_unpacked(msg, NULL);
+
+ return sz;
+
+ fail_pack:
+ enroll_resp_msg__free_unpacked(msg, NULL);
+ fail_msg:
+ return -1;
+}
+
+int enroll_resp_des(struct enroll_resp * resp,
+ const buffer_t buf)
+{
+ enroll_resp_msg_t * msg;
+
+ msg = enroll_resp_msg__unpack(NULL, buf.len, buf.data);
+ if (msg == NULL)
+ return -1;
+
+ *resp = enroll_resp_msg_to_s(msg);
+
+ enroll_resp_msg__free_unpacked(msg, NULL);
+
+ return 0;
+}
+
+ssize_t enroll_ack_ser(const int response,
+ buffer_t buf)
+{
+ enroll_ack_msg_t * msg;
+ ssize_t sz;
+
+ msg = enroll_ack_s_to_msg(response);
+ if (msg == NULL)
+ goto fail_msg;
+
+ sz = enroll_ack_msg__get_packed_size(msg);
+ if (sz < 0 || (size_t) sz > buf.len)
+ goto fail_pack;
+
+ enroll_ack_msg__pack(msg, buf.data);
+
+ enroll_ack_msg__free_unpacked(msg, NULL);
+
+ return sz;
+
+ fail_pack:
+ enroll_ack_msg__free_unpacked(msg, NULL);
+ fail_msg:
+ return -1;
+
+}
+
+int enroll_ack_des(int * response,
+ const buffer_t buf)
+{
+ enroll_ack_msg_t * msg;
+
+ msg = enroll_ack_msg__unpack(NULL, buf.len, buf.data);
+ if (msg == NULL)
+ return -1;
+
+ *response = enroll_ack_msg_to_s(msg);
+
+ enroll_ack_msg__free_unpacked(msg, NULL);
+
+ return 0;
+} \ No newline at end of file
diff --git a/src/lib/sockets.c b/src/lib/sockets.c
index c82d622f..bb594115 100644
--- a/src/lib/sockets.c
+++ b/src/lib/sockets.c
@@ -100,6 +100,7 @@ int server_socket_open(char * file_name)
return sockfd;
}
+__attribute__((no_sanitize_address))
irm_msg_t * send_recv_irm_msg(irm_msg_t * msg)
{
int sockfd;
@@ -117,18 +118,18 @@ irm_msg_t * send_recv_irm_msg(irm_msg_t * msg)
return NULL;
}
- pthread_cleanup_push(__cleanup_close_ptr, &sockfd);
-
irm_msg__pack(msg, buf);
+ pthread_cleanup_push(__cleanup_close_ptr, &sockfd);
+
if (write(sockfd, buf, len) != -1)
len = read(sockfd, buf, SOCK_BUF_SIZE);
+ pthread_cleanup_pop(true);
+
if (len > 0)
recv_msg = irm_msg__unpack(NULL, len, buf);
- pthread_cleanup_pop(true);
-
return recv_msg;
}
@@ -165,42 +166,3 @@ char * ipcp_sock_path(pid_t pid)
return full_name;
}
-
-qosspec_msg_t spec_to_msg(const qosspec_t * qs)
-{
- qosspec_t spec;
- qosspec_msg_t msg = QOSSPEC_MSG__INIT;
-
- spec = (qs == NULL ? qos_raw : *qs);
-
- msg.delay = spec.delay;
- msg.bandwidth = spec.bandwidth;
- msg.availability = spec.availability;
- msg.loss = spec.loss;
- msg.ber = spec.ber;
- msg.in_order = spec.in_order;
- msg.max_gap = spec.max_gap;
- msg.cypher_s = spec.cypher_s;
- msg.timeout = spec.timeout;
-
- return msg;
-}
-
-qosspec_t msg_to_spec(const qosspec_msg_t * msg)
-{
- qosspec_t spec;
-
- assert(msg);
-
- spec.delay = msg->delay;
- spec.bandwidth = msg->bandwidth;
- spec.availability = msg->availability;
- spec.loss = msg->loss;
- spec.ber = msg->ber;
- spec.in_order = msg->in_order;
- spec.max_gap = msg->max_gap;
- spec.cypher_s = msg->cypher_s;
- spec.timeout = msg->timeout;
-
- return spec;
-}
diff --git a/src/tools/irm/irm_ipcp_bootstrap.c b/src/tools/irm/irm_ipcp_bootstrap.c
index 2e90b82c..5d0ce680 100644
--- a/src/tools/irm/irm_ipcp_bootstrap.c
+++ b/src/tools/irm/irm_ipcp_bootstrap.c
@@ -193,7 +193,7 @@ int do_bootstrap_ipcp(int argc,
ethertype = strtol(*(argv + 1), NULL, 0);
else
ethertype = strtol(*(argv + 1), NULL, 16);
- if (ethertype < 0x0600 || ethertype == 0xFFFF) {
+ if (ethertype < 0x0600 || ethertype >= 0xFFFF) {
printf("Invalid Ethertype: \"%s\".\n"
"Recommended range: 0xA000-0xEFFF.\n",
*(argv + 1));
@@ -332,7 +332,12 @@ int do_bootstrap_ipcp(int argc,
case IPCP_ETH_LLC:
if (dev == NULL)
goto fail_usage;
- conf.eth.dev = dev;
+ if (strlen(dev) > DEV_NAME_SIZE) {
+ printf("Device name too long.\n\n");
+ goto fail_usage;
+ }
+
+ strcpy(conf.eth.dev, dev);
break;
case IPCP_BROADCAST:
/* FALLTHRU */