summaryrefslogtreecommitdiff
path: root/src/irmd/reg
diff options
context:
space:
mode:
authorDimitri Staessens <dimitri@ouroboros.rocks>2026-08-16 18:55:15 +0000
committerSander Vrijders <sander@ouroboros.rocks>2026-08-31 08:31:45 +0200
commit5c239c128c04883dbed6d66f574edf8b48d11e11 (patch)
tree6dfcc043c81bd10e1366172b9db5cf5ce93bb8d8 /src/irmd/reg
parenta830ed966eb3b7d6dbcc43e42a7b6b7c5d796c6a (diff)
downloadouroboros-5c239c128c04883dbed6d66f574edf8b48d11e11.tar.gz
ouroboros-5c239c128c04883dbed6d66f574edf8b48d11e11.zip
lib: Replace shim IPCPs with points of attachment
Removes the UDP and Ethernet shim IPCPs. The unicast and broadcast IPCPs can now directly attach to a "legacy" socket. We adopt Saltzer's Point-of-Attachment terminology, also advocated in Day's "Patterns in Network Architecture". The "poa" component manages these PoA's with one management thread, one link monitoring thread and one thread per attached point. For Ethernet PoA's the irm connect and enroll can resolve the destination IPCP or Layer name with a broadcast name query over the attached PoAs (first reply wins). UDP PoA's require a destination IP address or FQDN. attach to a local endpoint (required both server and client side): irm ipcp poa attach name a udp 10.0.0.1 irm ipcp poa attach name a udp 10.0.0.1:3435 irm ipcp poa attach name a udp [::1]:3435 irm ipcp poa attach name a eth dev eth0 irm ipcp poa attach name a eth dev eth0 ethertype 0xA000 release a PoA (refused while it carries a flow): irm ipcp poa detach name a udp 10.0.0.1:3435 irm ipcp poa detach name a eth eth0 list an IPCP's PoAs: irm ipcp poa list name a connect to a peer, by name or at an address: irm ipcp connect name b dst a irm ipcp connect name b dst a eth irm ipcp connect name b dst a eth dev eth0 irm ipcp connect name b dst a udp 10.0.0.1:3435 irm ipcp connect name b dst a udp peer.example.com:3435 disconnect by peer name, no address: irm ipcp disconnect name b dst a irm ipcp disconnect name b dst a component mgmt enroll has the same shape as connect: irm ipcp enroll name b layer lr autobind irm ipcp enroll name b layer lr autobind eth dev eth0 irm ipcp enroll name b layer lr autobind udp 10.0.0.1:3435 the IRMd config file attaches PoAs and names peers the same way: udp = [ "10.0.0.1", "10.0.0.1:3436" ] eth = [ "eth0", {dev="eth1", ethertype=0xA007} ] enrol={dst="LAN", eth={dev="eth0"}} conn=[{dst="lan3", eth={}}, {dst="lan4", udp="10.0.0.1:3435"}] Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
Diffstat (limited to 'src/irmd/reg')
-rw-r--r--src/irmd/reg/flow.c3
-rw-r--r--src/irmd/reg/flow.h2
-rw-r--r--src/irmd/reg/name.c1
-rw-r--r--src/irmd/reg/reg.c73
-rw-r--r--src/irmd/reg/reg.h251
-rw-r--r--src/irmd/reg/tests/reg_test.c2
6 files changed, 208 insertions, 124 deletions
diff --git a/src/irmd/reg/flow.c b/src/irmd/reg/flow.c
index 8be2dfc7..63c9199b 100644
--- a/src/irmd/reg/flow.c
+++ b/src/irmd/reg/flow.c
@@ -126,6 +126,9 @@ static int create_rbuffs(struct reg_flow * flow,
assert(flow->n_1_rb == NULL);
flow->info.n_1_pid = info->n_1_pid;
+ if (flow->poa)
+ return 0;
+
flow->n_1_rb = ssm_rbuff_create(info->n_1_pid, info->id);
if (flow->n_1_rb == NULL)
goto fail_n_1_rb;
diff --git a/src/irmd/reg/flow.h b/src/irmd/reg/flow.h
index 166bed61..c7021a0f 100644
--- a/src/irmd/reg/flow.h
+++ b/src/irmd/reg/flow.h
@@ -48,6 +48,8 @@ struct reg_flow {
char name[NAME_SIZE + 1];
bool direct;
+ bool poa; /* transport is a point of attachment */
+ void * oap_ctx; /* key exchange, prepare -> complete */
/* Tier-2 re-key state (encrypted flows only) */
struct {
diff --git a/src/irmd/reg/name.c b/src/irmd/reg/name.c
index a3621fc3..08426033 100644
--- a/src/irmd/reg/name.c
+++ b/src/irmd/reg/name.c
@@ -1,4 +1,3 @@
-
/*
* Ouroboros - Copyright (C) 2016 - 2026
*
diff --git a/src/irmd/reg/reg.c b/src/irmd/reg/reg.c
index ebf3959d..a302fa15 100644
--- a/src/irmd/reg/reg.c
+++ b/src/irmd/reg/reg.c
@@ -2119,6 +2119,77 @@ bool reg_flow_is_direct(int flow_id)
return ret;
}
+bool reg_flow_is_poa(int flow_id)
+{
+ struct reg_flow * flow;
+ bool ret;
+
+ pthread_mutex_lock(&reg.mtx);
+
+ flow = __reg_get_flow(flow_id);
+
+ ret = flow != NULL && flow->poa;
+
+ pthread_mutex_unlock(&reg.mtx);
+
+ return ret;
+}
+
+int reg_flow_set_poa(int flow_id)
+{
+ struct reg_flow * flow;
+ int ret = -1;
+
+ pthread_mutex_lock(&reg.mtx);
+
+ flow = __reg_get_flow(flow_id);
+ if (flow != NULL) {
+ flow->poa = true;
+ ret = 0;
+ }
+
+ pthread_mutex_unlock(&reg.mtx);
+
+ return ret;
+}
+
+int reg_flow_set_oap_ctx(int flow_id,
+ void * ctx)
+{
+ struct reg_flow * flow;
+ int ret = -1;
+
+ pthread_mutex_lock(&reg.mtx);
+
+ flow = __reg_get_flow(flow_id);
+ if (flow != NULL) {
+ flow->oap_ctx = ctx;
+ ret = 0;
+ }
+
+ pthread_mutex_unlock(&reg.mtx);
+
+ return ret;
+}
+
+void * reg_flow_take_oap_ctx(int flow_id)
+{
+ struct reg_flow * flow;
+ void * ctx = NULL;
+
+ pthread_mutex_lock(&reg.mtx);
+
+ flow = __reg_get_flow(flow_id);
+ if (flow != NULL) {
+ ctx = flow->oap_ctx;
+ flow->oap_ctx = NULL;
+ }
+
+ pthread_mutex_unlock(&reg.mtx);
+
+ return ctx;
+}
+
void reg_flow_set_rekey(int flow_id,
bool initiator,
buffer_t peer_crt)
@@ -2607,7 +2678,7 @@ void reg_notify_flow(int flow_id,
pthread_mutex_unlock(&reg.mtx);
}
-/* Wake both endpoints of a direct flow (acceptor and allocator). */
+/* Wake both PoAs of a direct flow (acceptor and allocator). */
void reg_notify_flow_peers(int flow_id,
int event)
{
diff --git a/src/irmd/reg/reg.h b/src/irmd/reg/reg.h
index 8a313d46..6882532c 100644
--- a/src/irmd/reg/reg.h
+++ b/src/irmd/reg/reg.h
@@ -33,138 +33,147 @@
#include "pool.h"
-int reg_init(void);
+int reg_init(void);
-void reg_clear(void);
+void reg_clear(void);
-void reg_fini(void);
+void reg_fini(void);
-int reg_create_flow(struct flow_info * info);
+int reg_create_flow(struct flow_info * info);
-int reg_destroy_flow(int flow_id);
+int reg_destroy_flow(int flow_id);
-bool reg_has_flow(int flow_id);
+bool reg_has_flow(int flow_id);
-int reg_create_proc(const struct proc_info * info);
+int reg_create_proc(const struct proc_info * info);
/* Use this for all processes, including ipcps */
-int reg_destroy_proc(pid_t pid);
+int reg_destroy_proc(pid_t pid);
-bool reg_has_proc(pid_t pid);
+bool reg_has_proc(pid_t pid);
-bool reg_is_proc_privileged(pid_t pid);
+bool reg_is_proc_privileged(pid_t pid);
-int reg_prepare_pool(uid_t uid,
- gid_t gid);
+int reg_prepare_pool(uid_t uid,
+ gid_t gid);
-uid_t reg_get_proc_uid(pid_t pid);
+uid_t reg_get_proc_uid(pid_t pid);
-void reg_kill_all_proc(int signal);
+void reg_kill_all_proc(int signal);
-pid_t reg_get_dead_proc(void);
+pid_t reg_get_dead_proc(void);
-int reg_create_spawned(pid_t pid);
+int reg_create_spawned(pid_t pid);
-bool reg_has_spawned(pid_t pid);
+bool reg_has_spawned(pid_t pid);
-void reg_kill_all_spawned(int signal);
+void reg_kill_all_spawned(int signal);
-int reg_first_spawned(void);
+int reg_first_spawned(void);
-int reg_bind_proc(const char * name,
- pid_t proc);
+int reg_bind_proc(const char * name,
+ pid_t proc);
-int reg_unbind_proc(const char * name,
- pid_t proc);
+int reg_unbind_proc(const char * name,
+ pid_t proc);
-int reg_create_ipcp(const struct ipcp_info * info);
+int reg_create_ipcp(const struct ipcp_info * info);
-bool reg_has_ipcp(pid_t pid);
+bool reg_has_ipcp(pid_t pid);
-int reg_set_layer_for_ipcp(struct ipcp_info * info,
- const struct layer_info * layer);
+int reg_set_layer_for_ipcp(struct ipcp_info * info,
+ const struct layer_info * layer);
-int reg_get_ipcp(struct ipcp_info * info,
- struct layer_info * layer);
+int reg_get_ipcp(struct ipcp_info * info,
+ struct layer_info * layer);
-int reg_get_ipcp_by_layer(struct ipcp_info * info,
- struct layer_info * layer);
+int reg_get_ipcp_by_layer(struct ipcp_info * info,
+ struct layer_info * layer);
/* TODO don't rely on protobuf here */
-int reg_list_ipcps(ipcp_list_msg_t *** msg);
+int reg_list_ipcps(ipcp_list_msg_t *** msg);
-int reg_create_name(const struct name_info * info);
+int reg_create_name(const struct name_info * info);
-int reg_destroy_name(const char * name);
+int reg_destroy_name(const char * name);
-bool reg_has_name(const char * name);
+bool reg_has_name(const char * name);
-int reg_get_name_info(const char * name,
- struct name_info * info);
+int reg_get_name_info(const char * name,
+ struct name_info * info);
-int reg_get_name_for_hash(char * buf,
- enum hash_algo algo,
- const uint8_t * hash);
+int reg_get_name_for_hash(char * buf,
+ enum hash_algo algo,
+ const uint8_t * hash);
-int reg_get_name_for_flow_id(char * buf,
- int flow_id);
+int reg_get_name_for_flow_id(char * buf,
+ int flow_id);
-void reg_set_name_for_flow_id(const char * name,
- int flow_id);
+void reg_set_name_for_flow_id(const char * name,
+ int flow_id);
/* TODO don't rely on protobuf here */
-int reg_list_names(name_info_msg_t *** names);
+int reg_list_names(name_info_msg_t *** names);
-int reg_create_prog(const struct prog_info * info);
+int reg_create_prog(const struct prog_info * info);
-int reg_destroy_prog(const char * name);
+int reg_destroy_prog(const char * name);
-bool reg_has_prog(const char * name);
+bool reg_has_prog(const char * name);
-int reg_get_exec(const char * name,
- char *** exec);
+int reg_get_exec(const char * name,
+ char *** exec);
-int reg_bind_prog(const char * name,
- char ** exec,
- uint8_t flags);
+int reg_bind_prog(const char * name,
+ char ** exec,
+ uint8_t flags);
-int reg_unbind_prog(const char * name,
- const char * prog);
+int reg_unbind_prog(const char * name,
+ const char * prog);
-int reg_prepare_flow_alloc(struct flow_info * info);
+int reg_prepare_flow_alloc(struct flow_info * info);
-int reg_wait_flow_allocated(struct flow_info * info,
+int reg_wait_flow_allocated(struct flow_info * info,
+ buffer_t * pbuf,
+ const struct timespec * abstime);
+
+int reg_respond_alloc(struct flow_info * info,
+ buffer_t * pbuf,
+ int response);
+
+int reg_prepare_flow_accept(struct flow_info * info);
+
+int reg_wait_flow_accepted(struct flow_info * info,
buffer_t * pbuf,
const struct timespec * abstime);
-int reg_respond_alloc(struct flow_info * info,
- buffer_t * pbuf,
- int response);
+int reg_wait_flow_accepting(const char * name,
+ const struct timespec * abstime);
-int reg_prepare_flow_accept(struct flow_info * info);
+int reg_respond_accept(struct flow_info * info,
+ buffer_t * pbuf);
-int reg_wait_flow_accepted(struct flow_info * info,
- buffer_t * pbuf,
- const struct timespec * abstime);
+int reg_prepare_flow_direct(struct flow_info * info,
+ buffer_t * pbuf,
+ uid_t alloc_uid);
-int reg_wait_flow_accepting(const char * name,
- const struct timespec * abstime);
+int reg_respond_flow_direct(int flow_id,
+ buffer_t * pbuf);
+
+int reg_wait_flow_direct(int flow_id,
+ buffer_t * pbuf,
+ const struct timespec * abstime);
-int reg_respond_accept(struct flow_info * info,
- buffer_t * pbuf);
+bool reg_flow_is_direct(int flow_id);
-int reg_prepare_flow_direct(struct flow_info * info,
- buffer_t * pbuf,
- uid_t alloc_uid);
+bool reg_flow_is_poa(int flow_id);
-int reg_respond_flow_direct(int flow_id,
- buffer_t * pbuf);
+int reg_flow_set_poa(int flow_id);
-int reg_wait_flow_direct(int flow_id,
- buffer_t * pbuf,
- const struct timespec * abstime);
+int reg_flow_set_oap_ctx(int flow_id,
+ void * ctx);
-bool reg_flow_is_direct(int flow_id);
+void * reg_flow_take_oap_ctx(int flow_id);
/* Per-flow snapshot for the re-key timer */
struct rekey_info {
@@ -176,70 +185,70 @@ struct rekey_info {
bool direct;
};
-void reg_flow_set_rekey(int flow_id,
- bool initiator,
- buffer_t peer_crt);
+void reg_flow_set_rekey(int flow_id,
+ bool initiator,
+ buffer_t peer_crt);
-int reg_flow_get_peer_crt(int flow_id,
- buffer_t * crt);
+int reg_flow_get_peer_crt(int flow_id,
+ buffer_t * crt);
-int reg_flow_get_epoch(int flow_id);
+int reg_flow_get_epoch(int flow_id);
-bool reg_flow_rekey_pending(int flow_id);
+bool reg_flow_rekey_pending(int flow_id);
-pid_t reg_flow_get_n_1_pid(int flow_id);
+pid_t reg_flow_get_n_1_pid(int flow_id);
-int reg_flow_snapshot_rekey_due(struct rekey_info * snap,
- int max);
+int reg_flow_snapshot_rekey_due(struct rekey_info * snap,
+ int max);
-void reg_flow_clear_in_flight(int flow_id);
+void reg_flow_clear_in_flight(int flow_id);
-bool reg_flow_rekey_begin(int flow_id);
+bool reg_flow_rekey_begin(int flow_id);
-bool reg_flow_rekey_should_yield(int flow_id);
+bool reg_flow_rekey_should_yield(int flow_id);
-int reg_flow_store_pending(int flow_id,
- const uint8_t * seed,
- uint8_t epoch,
- bool initiator);
+int reg_flow_store_pending(int flow_id,
+ const uint8_t * seed,
+ uint8_t epoch,
+ bool initiator);
-int reg_flow_store_pending_direct(int flow_id,
- const uint8_t * seed,
- uint8_t epoch);
+int reg_flow_store_pending_direct(int flow_id,
+ const uint8_t * seed,
+ uint8_t epoch);
-int reg_flow_take_pending(int flow_id,
- uid_t uid,
- pid_t cpid,
- uint8_t * seed,
- uint8_t * epoch,
- bool * initiator);
+int reg_flow_take_pending(int flow_id,
+ uid_t uid,
+ pid_t cpid,
+ uint8_t * seed,
+ uint8_t * epoch,
+ bool * initiator);
-bool reg_flow_rekey_arr_admit(int flow_id,
- pid_t n_1_pid,
- bool is_req);
+bool reg_flow_rekey_arr_admit(int flow_id,
+ pid_t n_1_pid,
+ bool is_req);
-void reg_flow_rekey_arr_done(int flow_id,
- bool is_req);
+void reg_flow_rekey_arr_done(int flow_id,
+ bool is_req);
-bool reg_flow_owned_by(int flow_id,
- uid_t uid);
+bool reg_flow_owned_by(int flow_id,
+ uid_t uid);
-void reg_notify_flow(int flow_id,
- int event);
+void reg_notify_flow(int flow_id,
+ int event);
-void reg_notify_flow_peers(int flow_id,
- int event);
+void reg_notify_flow_peers(int flow_id,
+ int event);
-void reg_dealloc_flow(struct flow_info * info);
+void reg_dealloc_flow(struct flow_info * info);
-void reg_dealloc_flow_resp(struct flow_info * info);
+void reg_dealloc_flow_resp(struct flow_info * info);
-int reg_wait_proc(pid_t pid,
- const struct timespec * abstime);
+int reg_wait_proc(pid_t pid,
+ const struct timespec * abstime);
-int reg_wait_ipcp_boot(struct ipcp_info * ipcp,
- const struct timespec * abstime);
+int reg_wait_ipcp_boot(struct ipcp_info * ipcp,
+ const struct timespec * abstime);
-int reg_respond_ipcp(const struct ipcp_info * info);
+int reg_respond_ipcp(const struct ipcp_info * info);
#endif /* OUROBOROS_IRMD_REG_H */
diff --git a/src/irmd/reg/tests/reg_test.c b/src/irmd/reg/tests/reg_test.c
index a8c1b1fa..ab57241c 100644
--- a/src/irmd/reg/tests/reg_test.c
+++ b/src/irmd/reg/tests/reg_test.c
@@ -746,7 +746,7 @@ static int test_reg_direct_flow_success(void)
reg_dealloc_flow(&info);
if (info.state != FLOW_DEALLOC_PENDING) {
- printf("Same endpoint dealloc changed state.\n");
+ printf("Same PoA dealloc changed state.\n");
goto fail;
}