From 89b58eaa2706c54aeb0a48252d1cfbd2b5ae01b7 Mon Sep 17 00:00:00 2001 From: Dimitri Staessens Date: Sat, 4 Mar 2023 03:48:48 +0100 Subject: 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 Signed-off-by: Sander Vrijders --- src/ipcpd/broadcast/main.c | 2 +- src/ipcpd/common/enroll.c | 241 +++++++++++++++++---------------------------- src/ipcpd/common/enroll.h | 4 +- src/ipcpd/eth/eth.c | 7 +- src/ipcpd/ipcp.c | 76 +++----------- src/ipcpd/ipcp.h | 2 + src/ipcpd/unicast/main.c | 2 +- 7 files changed, 109 insertions(+), 225 deletions(-) (limited to 'src/ipcpd') 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 #include #include -#include +#include #include "common/connmgr.h" #include "common/enroll.h" @@ -45,9 +45,6 @@ #include #include -#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 #include #include +#include #include #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 #include #include +#include +#include #include #include 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)) -- cgit v1.2.3