summaryrefslogtreecommitdiff
path: root/src/irmd/reg
diff options
context:
space:
mode:
Diffstat (limited to 'src/irmd/reg')
-rw-r--r--src/irmd/reg/CMakeLists.txt9
-rw-r--r--src/irmd/reg/flow.c54
-rw-r--r--src/irmd/reg/flow.h22
-rw-r--r--src/irmd/reg/ipcp.c3
-rw-r--r--src/irmd/reg/ipcp.h2
-rw-r--r--src/irmd/reg/name.c63
-rw-r--r--src/irmd/reg/name.h17
-rw-r--r--src/irmd/reg/pool.c97
-rw-r--r--src/irmd/reg/pool.h48
-rw-r--r--src/irmd/reg/proc.c38
-rw-r--r--src/irmd/reg/proc.h11
-rw-r--r--src/irmd/reg/prog.c24
-rw-r--r--src/irmd/reg/prog.h5
-rw-r--r--src/irmd/reg/reg.c542
-rw-r--r--src/irmd/reg/reg.h24
-rw-r--r--src/irmd/reg/tests/CMakeLists.txt38
-rw-r--r--src/irmd/reg/tests/flow_test.c59
-rw-r--r--src/irmd/reg/tests/ipcp_test.c4
-rw-r--r--src/irmd/reg/tests/name_test.c12
-rw-r--r--src/irmd/reg/tests/proc_test.c25
-rw-r--r--src/irmd/reg/tests/prog_test.c8
-rw-r--r--src/irmd/reg/tests/reg_test.c306
22 files changed, 951 insertions, 460 deletions
diff --git a/src/irmd/reg/CMakeLists.txt b/src/irmd/reg/CMakeLists.txt
deleted file mode 100644
index d3844908..00000000
--- a/src/irmd/reg/CMakeLists.txt
+++ /dev/null
@@ -1,9 +0,0 @@
-include_directories(${CMAKE_CURRENT_SOURCE_DIR})
-include_directories(${CMAKE_CURRENT_BINARY_DIR})
-
-include_directories(${CMAKE_SOURCE_DIR}/include)
-include_directories(${CMAKE_BINARY_DIR}/include)
-
-if(BUILD_TESTS)
- add_subdirectory(tests)
-endif ()
diff --git a/src/irmd/reg/flow.c b/src/irmd/reg/flow.c
index 4d091b23..93c3e128 100644
--- a/src/irmd/reg/flow.c
+++ b/src/irmd/reg/flow.c
@@ -1,5 +1,5 @@
/*
- * Ouroboros - Copyright (C) 2016 - 2024
+ * Ouroboros - Copyright (C) 2016 - 2026
*
* The IPC Resource Manager - Registry - Flows
*
@@ -66,11 +66,11 @@ struct reg_flow * reg_flow_create(const struct flow_info * info)
static void destroy_rbuffs(struct reg_flow * flow)
{
if (flow->n_rb != NULL)
- shm_rbuff_destroy(flow->n_rb);
+ ssm_rbuff_destroy(flow->n_rb);
flow->n_rb = NULL;
if (flow->n_1_rb != NULL)
- shm_rbuff_destroy(flow->n_1_rb);
+ ssm_rbuff_destroy(flow->n_1_rb);
flow->n_1_rb = NULL;
}
@@ -80,7 +80,7 @@ void reg_flow_destroy(struct reg_flow * flow)
switch(flow->info.state) {
case FLOW_ACCEPT_PENDING:
- clrbuf(flow->data);
+ clrbuf(flow->req_data);
/* FALLTHRU */
default:
destroy_rbuffs(flow);
@@ -89,8 +89,10 @@ void reg_flow_destroy(struct reg_flow * flow)
assert(flow->n_rb == NULL);
assert(flow->n_1_rb == NULL);
- assert(flow->data.data == NULL);
- assert(flow->data.len == 0);
+ assert(flow->req_data.data == NULL);
+ assert(flow->req_data.len == 0);
+ assert(flow->rsp_data.data == NULL);
+ assert(flow->rsp_data.len == 0);
assert(list_is_empty(&flow->next));
@@ -103,22 +105,28 @@ static int create_rbuffs(struct reg_flow * flow,
assert(flow != NULL);
assert(info != NULL);
- flow->n_rb = shm_rbuff_create(info->n_pid, info->id);
+ flow->n_rb = ssm_rbuff_create(info->n_pid, info->id);
if (flow->n_rb == NULL)
goto fail_n_rb;
+ if (ssm_rbuff_mlock(flow->n_rb) < 0)
+ log_warn("Failed to mlock n_rb for flow %d.", info->id);
+
assert(flow->info.n_1_pid == 0);
assert(flow->n_1_rb == NULL);
flow->info.n_1_pid = info->n_1_pid;
- flow->n_1_rb = shm_rbuff_create(info->n_1_pid, info->id);
+ flow->n_1_rb = ssm_rbuff_create(info->n_1_pid, info->id);
if (flow->n_1_rb == NULL)
goto fail_n_1_rb;
+ if (ssm_rbuff_mlock(flow->n_1_rb) < 0)
+ log_warn("Failed to mlock n_1_rb for flow %d.", info->id);
+
return 0;
fail_n_1_rb:
- shm_rbuff_destroy(flow->n_rb);
+ ssm_rbuff_destroy(flow->n_rb);
fail_n_rb:
return -ENOMEM;
}
@@ -172,6 +180,7 @@ int reg_flow_update(struct reg_flow * flow,
}
flow->info.state = info->state;
+ flow->info.uid = info->uid;
*info = flow->info;
@@ -179,30 +188,3 @@ int reg_flow_update(struct reg_flow * flow,
fail:
return -ENOMEM;
}
-
-void reg_flow_set_data(struct reg_flow * flow,
- const buffer_t * buf)
-{
- assert(flow != NULL);
- assert(buf != NULL);
- assert(flow->data.data == NULL);
- assert(flow->data.len == 0);
-
- flow->data = *buf;
-}
-
-void reg_flow_get_data(struct reg_flow * flow,
- buffer_t * buf)
-{
- assert(flow != NULL);
- assert(buf != NULL);
-
- *buf = flow->data;
-
- clrbuf(flow->data);
-}
-
-void reg_flow_free_data(struct reg_flow * flow)
-{
- freebuf(flow->data);
-}
diff --git a/src/irmd/reg/flow.h b/src/irmd/reg/flow.h
index d1e4811c..9a4046d3 100644
--- a/src/irmd/reg/flow.h
+++ b/src/irmd/reg/flow.h
@@ -1,5 +1,5 @@
/*
- * Ouroboros - Copyright (C) 2016 - 2024
+ * Ouroboros - Copyright (C) 2016 - 2026
*
* The IPC Resource Manager - Registry - Flows
*
@@ -28,9 +28,10 @@
#include <ouroboros/name.h>
#include <ouroboros/pthread.h>
#include <ouroboros/qos.h>
-#include <ouroboros/shm_rbuff.h>
+#include <ouroboros/ssm_rbuff.h>
#include <ouroboros/utils.h>
+#include <stdbool.h>
#include <sys/types.h>
#include <time.h>
@@ -40,13 +41,16 @@ struct reg_flow {
struct flow_info info;
int response;
- buffer_t data;
+ buffer_t req_data;
+ buffer_t rsp_data;
struct timespec t0;
char name[NAME_SIZE + 1];
- struct shm_rbuff * n_rb;
- struct shm_rbuff * n_1_rb;
+ bool direct;
+
+ struct ssm_rbuff * n_rb;
+ struct ssm_rbuff * n_1_rb;
};
struct reg_flow * reg_flow_create(const struct flow_info * info);
@@ -56,12 +60,4 @@ void reg_flow_destroy(struct reg_flow * flow);
int reg_flow_update(struct reg_flow * flow,
struct flow_info * info);
-void reg_flow_set_data(struct reg_flow * flow,
- const buffer_t * buf);
-
-void reg_flow_get_data(struct reg_flow * flow,
- buffer_t * buf);
-
-void reg_flow_free_data(struct reg_flow * flow);
-
#endif /* OUROBOROS_IRMD_REG_FLOW_H */
diff --git a/src/irmd/reg/ipcp.c b/src/irmd/reg/ipcp.c
index 474527a4..b193e28f 100644
--- a/src/irmd/reg/ipcp.c
+++ b/src/irmd/reg/ipcp.c
@@ -1,5 +1,5 @@
/*
- * Ouroboros - Copyright (C) 2016 - 2024
+ * Ouroboros - Copyright (C) 2016 - 2026
*
* The IPC Resource Manager - Registry - IPCPs
*
@@ -77,7 +77,6 @@ void reg_ipcp_update(struct reg_ipcp * ipcp,
const struct ipcp_info * info)
{
assert(ipcp != NULL);
- assert(info->state != IPCP_NULL);
ipcp->info = *info;
}
diff --git a/src/irmd/reg/ipcp.h b/src/irmd/reg/ipcp.h
index 375973a7..fe9d3bf1 100644
--- a/src/irmd/reg/ipcp.h
+++ b/src/irmd/reg/ipcp.h
@@ -1,5 +1,5 @@
/*
- * Ouroboros - Copyright (C) 2016 - 2024
+ * Ouroboros - Copyright (C) 2016 - 2026
*
* The IPC Resource Manager - Registry - IPCPs
*
diff --git a/src/irmd/reg/name.c b/src/irmd/reg/name.c
index 4e609711..61a328ec 100644
--- a/src/irmd/reg/name.c
+++ b/src/irmd/reg/name.c
@@ -1,6 +1,6 @@
/*
- * Ouroboros - Copyright (C) 2016 - 2024
+ * Ouroboros - Copyright (C) 2016 - 2026
*
* The IPC Resource Manager - Registry - Names
*
@@ -69,9 +69,9 @@ struct reg_name * reg_name_create(const struct name_info * info)
memset(name, 0, sizeof(*name));
list_head_init(&name->next);
- list_head_init(&name->progs.list);
- list_head_init(&name->procs.list);
- list_head_init(&name->active.list);
+ llist_init(&name->progs);
+ llist_init(&name->procs);
+ llist_init(&name->active);
name->info = *info;
@@ -87,13 +87,9 @@ void reg_name_destroy(struct reg_name * name)
assert(list_is_empty(&name->next));
- assert(name->progs.len == 0);
- assert(name->procs.len == 0);
- assert(name->active.len == 0);
-
- assert(list_is_empty(&name->progs.list));
- assert(list_is_empty(&name->procs.list));
- assert(list_is_empty(&name->active.list));
+ assert(llist_is_empty(&name->progs));
+ assert(llist_is_empty(&name->procs));
+ assert(llist_is_empty(&name->active));
free(name);
}
@@ -106,7 +102,7 @@ static struct proc_entry * __reg_name_get_active(const struct reg_name * name,
assert(name != NULL);
assert(pid > 0);
- list_for_each(p, &name->active.list) {
+ llist_for_each(p, &name->active) {
struct proc_entry * entry;
entry = list_entry(p, struct proc_entry, next);
if (entry->pid == pid)
@@ -122,13 +118,12 @@ static void __reg_name_del_all_active(struct reg_name * name,
struct list_head * p;
struct list_head * h;
- list_for_each_safe(p, h, &name->active.list) {
+ llist_for_each_safe(p, h, &name->active) {
struct proc_entry * entry;
entry = list_entry(p, struct proc_entry, next);
if (entry->pid == pid) {
- list_del(&entry->next);
+ llist_del(&entry->next, &name->active);
free(entry);
- --name->active.len;
}
}
}
@@ -141,7 +136,7 @@ static struct proc_entry * __reg_name_get_proc(const struct reg_name * name,
assert(name != NULL);
assert(pid > 0);
- list_for_each(p, &name->procs.list) {
+ llist_for_each(p, &name->procs) {
struct proc_entry * entry;
entry = list_entry(p, struct proc_entry, next);
if (entry->pid == pid)
@@ -159,7 +154,7 @@ static struct prog_entry * __reg_name_get_prog(const struct reg_name * name,
assert(name != NULL);
assert(prog != NULL);
- list_for_each(p, &name->progs.list) {
+ llist_for_each(p, &name->progs) {
struct prog_entry * entry;
entry = list_entry(p, struct prog_entry, next);
if (strcmp(entry->exec[0], prog) == 0)
@@ -194,17 +189,15 @@ int reg_name_add_active(struct reg_name * name,
switch (name->info.pol_lb) {
case LB_RR: /* Round robin policy. */
- list_add_tail(&entry->next, &name->active.list);
+ llist_add_tail(&entry->next, &name->active);
break;
case LB_SPILL: /* Keep accepting flows on the current process */
- list_add(&entry->next, &name->active.list);
+ llist_add(&entry->next, &name->active);
break;
default:
goto fail_unreachable;
}
- ++name->active.len;
-
return 0;
fail_unreachable:
@@ -223,9 +216,7 @@ void reg_name_del_active(struct reg_name * name,
if (entry == NULL)
return;
- list_del(&entry->next);
-
- --name->active.len;
+ llist_del(&entry->next, &name->active);
free(entry);
}
@@ -236,10 +227,10 @@ pid_t reg_name_get_active(struct reg_name * name)
assert(name != NULL);
- if (list_is_empty(&name->active.list))
+ if (llist_is_empty(&name->active))
return -1;
- e = list_first_entry(&name->active.list, struct proc_entry, next);
+ e = llist_first_entry(&name->active, struct proc_entry, next);
return e->pid;
}
@@ -262,9 +253,7 @@ int reg_name_add_proc(struct reg_name * name,
entry->pid = pid;
- list_add(&entry->next, &name->procs.list);
-
- ++name->procs.len;
+ llist_add(&entry->next, &name->procs);
return 0;
@@ -286,12 +275,10 @@ void reg_name_del_proc(struct reg_name * name,
__reg_name_del_all_active(name, pid);
- list_del(&entry->next);
+ llist_del(&entry->next, &name->procs);
free(entry);
- --name->procs.len;
-
assert(__reg_name_get_proc(name, pid) == NULL);
}
@@ -324,12 +311,10 @@ int reg_name_add_prog(struct reg_name * name,
goto fail_exec;
}
- list_add(&entry->next, &name->progs.list);
+ llist_add(&entry->next, &name->progs);
log_dbg("Add prog %s to name %s.", exec[0], name->info.name);
- ++name->progs.len;
-
return 0;
fail_exec:
@@ -350,12 +335,10 @@ void reg_name_del_prog(struct reg_name * name,
if (entry == NULL)
return;
- list_del(&entry->next);
+ llist_del(&entry->next, &name->progs);
__free_prog_entry(entry);
- --name->progs.len;
-
assert(__reg_name_get_prog(name, prog) == NULL);
}
@@ -372,10 +355,10 @@ char ** reg_name_get_exec(const struct reg_name * name)
{
struct prog_entry * e;
- if (list_is_empty(&name->progs.list))
+ if (llist_is_empty(&name->progs))
return NULL;
- e = list_first_entry(&name->progs.list, struct prog_entry, next);
+ e = llist_first_entry(&name->progs, struct prog_entry, next);
return e->exec;
}
diff --git a/src/irmd/reg/name.h b/src/irmd/reg/name.h
index 30a64e1c..59d6d9bd 100644
--- a/src/irmd/reg/name.h
+++ b/src/irmd/reg/name.h
@@ -1,5 +1,5 @@
/*
- * Ouroboros - Copyright (C) 2016 - 2024
+ * Ouroboros - Copyright (C) 2016 - 2026
*
* The IPC Resource Manager - Registry - Names
*
@@ -38,20 +38,11 @@ struct reg_name {
void * crt;
} cache;
- struct {
- struct list_head list;
- size_t len;
- } progs; /* autostart programs for this name */
+ struct llist progs; /* autostart programs for this name */
- struct {
- struct list_head list;
- size_t len;
- } procs; /* processes bound to this name */
+ struct llist procs; /* processes bound to this name */
- struct {
- struct list_head list;
- size_t len;
- } active; /* processes actively calling accept */
+ struct llist active; /* processes actively calling accept */
};
struct reg_name * reg_name_create(const struct name_info * info);
diff --git a/src/irmd/reg/pool.c b/src/irmd/reg/pool.c
new file mode 100644
index 00000000..4b1486bb
--- /dev/null
+++ b/src/irmd/reg/pool.c
@@ -0,0 +1,97 @@
+/*
+ * Ouroboros - Copyright (C) 2016 - 2026
+ *
+ * The IPC Resource Manager - Registry - Per-User Pools
+ *
+ * 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 200809L
+
+#define OUROBOROS_PREFIX "reg/pool"
+
+#include <ouroboros/logs.h>
+#include <ouroboros/ssm_pool.h>
+
+#include "pool.h"
+
+#include <assert.h>
+#include <stdlib.h>
+
+struct reg_pool * reg_pool_create(uid_t uid,
+ gid_t gid)
+{
+ struct reg_pool * pool;
+
+ pool = malloc(sizeof(*pool));
+ if (pool == NULL) {
+ log_err("Failed to malloc pool.");
+ goto fail_malloc;
+ }
+
+ pool->ssm = ssm_pool_create(uid, gid);
+ if (pool->ssm == NULL) {
+ log_err("Failed to create PUP for uid %d.", uid);
+ goto fail_ssm;
+ }
+
+ list_head_init(&pool->next);
+ pool->uid = uid;
+ pool->gid = gid;
+ pool->refcount = 1;
+
+ log_dbg("Created PUP for uid %d gid %d.", uid, gid);
+
+ return pool;
+
+ fail_ssm:
+ free(pool);
+ fail_malloc:
+ return NULL;
+}
+
+void reg_pool_destroy(struct reg_pool * pool)
+{
+ assert(pool != NULL);
+ assert(pool->refcount == 0);
+
+ log_dbg("Destroying PUP for uid %d.", pool->uid);
+
+ ssm_pool_destroy(pool->ssm);
+
+ assert(list_is_empty(&pool->next));
+
+ free(pool);
+}
+
+void reg_pool_ref(struct reg_pool * pool)
+{
+ assert(pool != NULL);
+ assert(pool->refcount > 0);
+
+ pool->refcount++;
+}
+
+int reg_pool_unref(struct reg_pool * pool)
+{
+ assert(pool != NULL);
+ assert(pool->refcount > 0);
+
+ pool->refcount--;
+
+ return pool->refcount == 0 ? 0 : 1;
+}
diff --git a/src/irmd/reg/pool.h b/src/irmd/reg/pool.h
new file mode 100644
index 00000000..576f491c
--- /dev/null
+++ b/src/irmd/reg/pool.h
@@ -0,0 +1,48 @@
+/*
+ * Ouroboros - Copyright (C) 2016 - 2026
+ *
+ * The IPC Resource Manager - Registry - Per-User Pools
+ *
+ * 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_REG_POOL_H
+#define OUROBOROS_IRMD_REG_POOL_H
+
+#include <ouroboros/list.h>
+#include <ouroboros/ssm_pool.h>
+
+#include <sys/types.h>
+
+struct reg_pool {
+ struct list_head next;
+ uid_t uid;
+ gid_t gid;
+ size_t refcount;
+ struct ssm_pool * ssm;
+};
+
+struct reg_pool * reg_pool_create(uid_t uid,
+ gid_t gid);
+
+void reg_pool_destroy(struct reg_pool * pool);
+
+void reg_pool_ref(struct reg_pool * pool);
+
+int reg_pool_unref(struct reg_pool * pool);
+
+#endif /* OUROBOROS_IRMD_REG_POOL_H */
diff --git a/src/irmd/reg/proc.c b/src/irmd/reg/proc.c
index 9bbdf0eb..8a7e24c9 100644
--- a/src/irmd/reg/proc.c
+++ b/src/irmd/reg/proc.c
@@ -1,5 +1,5 @@
/*
- * Ouroboros - Copyright (C) 2016 - 2024
+ * Ouroboros - Copyright (C) 2016 - 2026
*
* The IPC Resource Manager - Registry - Processes
*
@@ -25,6 +25,7 @@
#define OUROBOROS_PREFIX "reg/proc"
#include <ouroboros/logs.h>
+#include <ouroboros/utils.h>
#include "proc.h"
@@ -54,12 +55,11 @@ static void __reg_proc_clear_names(struct reg_proc * proc)
assert(proc != NULL);
- list_for_each_safe(p, h, &proc->names) {
+ llist_for_each_safe(p, h, &proc->names) {
struct name_entry * entry;
entry = list_entry(p, struct name_entry, next);
- list_del(&entry->next);
+ llist_del(&entry->next, &proc->names);
__free_name_entry(entry);
- proc->n_names--;
}
}
@@ -75,17 +75,18 @@ struct reg_proc * reg_proc_create(const struct proc_info * info)
goto fail_malloc;
}
- proc->set = shm_flow_set_create(info->pid);
+ memset(proc, 0, sizeof(*proc));
+
+ proc->set = ssm_flow_set_create(info->pid);
if (proc->set == NULL) {
log_err("Failed to create flow set for %d.", info->pid);
goto fail_set;
}
list_head_init(&proc->next);
- list_head_init(&proc->names);
+ llist_init(&proc->names);
proc->info = *info;
- proc->n_names = 0;
return proc;
@@ -99,15 +100,13 @@ void reg_proc_destroy(struct reg_proc * proc)
{
assert(proc != NULL);
- shm_flow_set_destroy(proc->set);
+ ssm_flow_set_destroy(proc->set);
__reg_proc_clear_names(proc);
assert(list_is_empty(&proc->next));
- assert(proc->n_names == 0);
-
- assert(list_is_empty(&proc->names));
+ assert(llist_is_empty(&proc->names));
free(proc);
}
@@ -117,7 +116,7 @@ static struct name_entry * __reg_proc_get_name(const struct reg_proc * proc,
{
struct list_head * p;
- list_for_each(p, &proc->names) {
+ llist_for_each(p, &proc->names) {
struct name_entry * entry;
entry = list_entry(p, struct name_entry, next);
if (strcmp(entry->name, name) == 0)
@@ -146,9 +145,7 @@ int reg_proc_add_name(struct reg_proc * proc,
goto fail_name;
}
- list_add(&entry->next, &proc->names);
-
- proc->n_names++;
+ llist_add(&entry->next, &proc->names);
return 0;
@@ -167,12 +164,10 @@ void reg_proc_del_name(struct reg_proc * proc,
if(entry == NULL)
return;
- list_del(&entry->next);
+ llist_del(&entry->next, &proc->names);
__free_name_entry(entry);
- proc->n_names--;
-
assert(__reg_proc_get_name(proc, name) == NULL);
}
@@ -181,3 +176,10 @@ bool reg_proc_has_name(const struct reg_proc * proc,
{
return __reg_proc_get_name(proc, name) != NULL;
}
+
+bool reg_proc_is_privileged(const struct reg_proc * proc)
+{
+ assert(proc != NULL);
+
+ return is_ouroboros_member_uid(proc->info.uid);
+}
diff --git a/src/irmd/reg/proc.h b/src/irmd/reg/proc.h
index 499ecc72..18cc2803 100644
--- a/src/irmd/reg/proc.h
+++ b/src/irmd/reg/proc.h
@@ -1,5 +1,5 @@
/*
- * Ouroboros - Copyright (C) 2016 - 2024
+ * Ouroboros - Copyright (C) 2016 - 2026
*
* The IPC Resource Manager - Registry - Processes
*
@@ -25,17 +25,16 @@
#include <ouroboros/list.h>
#include <ouroboros/proc.h>
-#include <ouroboros/shm_flow_set.h>
+#include <ouroboros/ssm_flow_set.h>
struct reg_proc {
struct list_head next;
struct proc_info info;
- struct list_head names; /* process accepts flows for names */
- size_t n_names; /* number of names */
+ struct llist names; /* process accepts flows for names */
- struct shm_flow_set * set;
+ struct ssm_flow_set * set;
};
struct reg_proc * reg_proc_create(const struct proc_info * info);
@@ -53,4 +52,6 @@ void reg_proc_del_name(struct reg_proc * proc,
bool reg_proc_has_name(const struct reg_proc * proc,
const char * name);
+bool reg_proc_is_privileged(const struct reg_proc * proc);
+
#endif /* OUROBOROS_IRMD_REG_PROC_H */
diff --git a/src/irmd/reg/prog.c b/src/irmd/reg/prog.c
index 9b9e7510..2d7f9f8d 100644
--- a/src/irmd/reg/prog.c
+++ b/src/irmd/reg/prog.c
@@ -1,5 +1,5 @@
/*
- * Ouroboros - Copyright (C) 2016 - 2024
+ * Ouroboros - Copyright (C) 2016 - 2026
*
* The IPC Resource Manager - Registry - Programs
*
@@ -55,12 +55,11 @@ static void __reg_prog_clear_names(struct reg_prog * prog)
assert(prog != NULL);
- list_for_each_safe(p, h, &prog->names) {
+ llist_for_each_safe(p, h, &prog->names) {
struct name_entry * entry;
entry = list_entry(p, struct name_entry, next);
- list_del(&entry->next);
+ llist_del(&entry->next, &prog->names);
__free_name_entry(entry);
- prog->n_names--;
}
}
@@ -77,10 +76,9 @@ struct reg_prog * reg_prog_create(const struct prog_info * info)
}
list_head_init(&p->next);
- list_head_init(&p->names);
+ llist_init(&p->names);
p->info = *info;
- p->n_names = 0;
return p;
@@ -96,9 +94,7 @@ void reg_prog_destroy(struct reg_prog * prog)
assert(list_is_empty(&prog->next));
- assert(prog->n_names == 0);
-
- assert(list_is_empty(&prog->names));
+ assert(llist_is_empty(&prog->names));
free(prog);
}
@@ -108,7 +104,7 @@ static struct name_entry * __reg_prog_get_name(const struct reg_prog * prog,
{
struct list_head * p;
- list_for_each(p, &prog->names) {
+ llist_for_each(p, &prog->names) {
struct name_entry * entry;
entry = list_entry(p, struct name_entry, next);
if (strcmp(entry->name, name) == 0)
@@ -137,9 +133,7 @@ int reg_prog_add_name(struct reg_prog * prog,
goto fail_name;
}
- list_add(&entry->next, &prog->names);
-
- prog->n_names++;
+ llist_add(&entry->next, &prog->names);
return 0;
@@ -158,12 +152,10 @@ void reg_prog_del_name(struct reg_prog * prog,
if (entry == NULL)
return;
- list_del(&entry->next);
+ llist_del(&entry->next, &prog->names);
__free_name_entry(entry);
- prog->n_names--;
-
assert(__reg_prog_get_name(prog, name) == NULL);
}
diff --git a/src/irmd/reg/prog.h b/src/irmd/reg/prog.h
index a98fc6a1..e52b8e15 100644
--- a/src/irmd/reg/prog.h
+++ b/src/irmd/reg/prog.h
@@ -1,5 +1,5 @@
/*
- * Ouroboros - Copyright (C) 2016 - 2024
+ * Ouroboros - Copyright (C) 2016 - 2026
*
* The IPC Resource Manager - Registry - Programs
*
@@ -33,8 +33,7 @@ struct reg_prog {
struct prog_info info;
- struct list_head names; /* names to listen for */
- size_t n_names; /* number of names in list */
+ struct llist names; /* names to listen for */
};
struct reg_prog * reg_prog_create(const struct prog_info * info);
diff --git a/src/irmd/reg/reg.c b/src/irmd/reg/reg.c
index a24a9d1d..0025f695 100644
--- a/src/irmd/reg/reg.c
+++ b/src/irmd/reg/reg.c
@@ -1,5 +1,5 @@
/*
- * Ouroboros - Copyright (C) 2016 - 2024
+ * Ouroboros - Copyright (C) 2016 - 2026
*
The IPC Resource Manager - Registry
*
@@ -35,6 +35,7 @@ The IPC Resource Manager - Registry
#include "flow.h"
#include "ipcp.h"
#include "name.h"
+#include "pool.h"
#include "proc.h"
#include "prog.h"
@@ -46,28 +47,18 @@ The IPC Resource Manager - Registry
#define ID_OFFT 1 /* reserve some flow_ids */
struct {
- struct bmp * flow_ids; /* flow_ids for flows */
-
- struct list_head flows; /* flow information */
- size_t n_flows; /* number of flows */
-
- struct list_head ipcps; /* list of ipcps in system */
- size_t n_ipcps; /* number of ipcps */
-
- struct list_head names; /* registered names known */
- size_t n_names; /* number of names */
-
- struct list_head procs; /* processes */
- size_t n_procs; /* number of processes */
-
- struct list_head progs; /* programs known */
- size_t n_progs; /* number of programs */
-
- struct list_head spawned; /* child processes */
- size_t n_spawned; /* number of child processes */
-
- pthread_mutex_t mtx; /* registry lock */
- pthread_cond_t cond; /* condvar for reg changes */
+ struct bmp * ids; /* flow bitmap */
+
+ struct llist flows; /* list of flows */
+ struct llist ipcps; /* list of ipcps in system */
+ struct llist names; /* registered names known */
+ struct llist pools; /* per-user pools */
+ struct llist procs; /* processes known */
+ struct llist progs; /* programs known */
+ struct llist spawned; /* child processes */
+
+ pthread_mutex_t mtx; /* registry lock */
+ pthread_cond_t cond; /* condvar for reg changes */
} reg;
struct pid_entry {
@@ -81,7 +72,7 @@ static struct reg_flow * __reg_get_flow(int flow_id)
assert(flow_id >= ID_OFFT);
- list_for_each(p, &reg.flows) {
+ llist_for_each(p, &reg.flows) {
struct reg_flow * entry;
entry = list_entry(p, struct reg_flow, next);
if (entry->info.id == flow_id)
@@ -95,7 +86,7 @@ static struct reg_flow * __reg_get_accept_flow(pid_t pid)
{
struct list_head * p;
- list_for_each(p, &reg.flows) {
+ llist_for_each(p, &reg.flows) {
struct reg_flow * entry;
entry = list_entry(p, struct reg_flow, next);
if (entry->info.state != FLOW_ACCEPT_PENDING)
@@ -113,7 +104,7 @@ static struct list_head * __reg_after_flow(int flow_id)
assert(flow_id >= ID_OFFT);
- list_for_each(p, &reg.flows) {
+ llist_for_each(p, &reg.flows) {
struct reg_flow * entry;
entry = list_entry(p, struct reg_flow, next);
if (entry->info.id > flow_id)
@@ -129,7 +120,7 @@ static struct reg_ipcp * __reg_get_ipcp(pid_t pid)
assert(pid > 0);
- list_for_each(p, &reg.ipcps) {
+ llist_for_each(p, &reg.ipcps) {
struct reg_ipcp * entry;
entry = list_entry(p, struct reg_ipcp, next);
if (entry->info.pid == pid)
@@ -143,7 +134,7 @@ static struct reg_ipcp * __reg_get_ipcp_by_layer(const char * layer)
{
struct list_head * p;
- list_for_each(p, &reg.ipcps) {
+ llist_for_each(p, &reg.ipcps) {
struct reg_ipcp * entry;
entry = list_entry(p, struct reg_ipcp, next);
if (strcmp(entry->layer.name, layer) == 0)
@@ -160,7 +151,7 @@ static struct list_head * __reg_after_ipcp(const struct ipcp_info * info)
assert(info != NULL);
- list_for_each(p, &reg.ipcps) {
+ llist_for_each(p, &reg.ipcps) {
struct reg_ipcp * entry;
entry = list_entry(p, struct reg_ipcp, next);
if (entry->info.type < info->type)
@@ -182,7 +173,7 @@ static struct reg_name * __reg_get_name(const char * name)
assert(name != NULL);
- list_for_each(p, &reg.names) {
+ llist_for_each(p, &reg.names) {
struct reg_name * entry;
entry = list_entry(p, struct reg_name, next);
if (strcmp(entry->info.name, name) == 0)
@@ -225,7 +216,7 @@ static struct list_head * __reg_after_name(const char * name)
assert(name != NULL);
- list_for_each(p, &reg.names) {
+ llist_for_each(p, &reg.names) {
struct reg_name * entry;
entry = list_entry(p, struct reg_name, next);
if (strcmp(entry->info.name, name) > 0)
@@ -235,11 +226,25 @@ static struct list_head * __reg_after_name(const char * name)
return p;
}
+static struct reg_pool * __reg_get_pool(uid_t uid)
+{
+ struct list_head * p;
+
+ llist_for_each(p, &reg.pools) {
+ struct reg_pool * entry;
+ entry = list_entry(p, struct reg_pool, next);
+ if (entry->uid == uid)
+ return entry;
+ }
+
+ return NULL;
+}
+
static struct reg_proc * __reg_get_proc(pid_t pid)
{
struct list_head * p;
- list_for_each(p, &reg.procs) {
+ llist_for_each(p, &reg.procs) {
struct reg_proc * entry;
entry = list_entry(p, struct reg_proc, next);
if (entry->info.pid == pid)
@@ -253,7 +258,7 @@ static struct list_head * __reg_after_proc(pid_t pid)
{
struct list_head * p;
- list_for_each(p, &reg.procs) {
+ llist_for_each(p, &reg.procs) {
struct reg_proc * entry;
entry = list_entry(p, struct reg_proc, next);
if (entry->info.pid > pid)
@@ -267,7 +272,7 @@ static void __reg_kill_all_proc(int signal)
{
struct list_head * p;
- list_for_each(p, &reg.procs) {
+ llist_for_each(p, &reg.procs) {
struct reg_proc * entry;
entry = list_entry(p, struct reg_proc, next);
kill(entry->info.pid, signal);
@@ -278,7 +283,7 @@ static pid_t __reg_get_dead_proc(void)
{
struct list_head * p;
- list_for_each(p, &reg.procs) {
+ llist_for_each(p, &reg.procs) {
struct reg_proc * entry;
entry = list_entry(p, struct reg_proc, next);
if (kill(entry->info.pid, 0) < 0)
@@ -293,7 +298,7 @@ static void __reg_cancel_flows_for_proc(pid_t pid)
struct list_head * p;
bool changed = false;
- list_for_each(p, &reg.flows) {
+ llist_for_each(p, &reg.flows) {
struct reg_flow * entry;
entry = list_entry(p, struct reg_flow, next);
if (entry->info.n_pid != pid)
@@ -319,7 +324,7 @@ static struct pid_entry * __reg_get_spawned(pid_t pid)
{
struct list_head * p;
- list_for_each(p, &reg.spawned) {
+ llist_for_each(p, &reg.spawned) {
struct pid_entry * entry;
entry = list_entry(p, struct pid_entry, next);
if (entry->pid == pid)
@@ -333,7 +338,7 @@ static struct list_head * __reg_after_spawned(pid_t pid)
{
struct list_head * p;
- list_for_each(p, &reg.spawned) {
+ llist_for_each(p, &reg.spawned) {
struct pid_entry * entry;
entry = list_entry(p, struct pid_entry, next);
if (entry->pid > pid)
@@ -347,7 +352,7 @@ static void __reg_kill_all_spawned(int signal)
{
struct list_head * p;
- list_for_each(p, &reg.spawned) {
+ llist_for_each(p, &reg.spawned) {
struct pid_entry * entry;
entry = list_entry(p, struct pid_entry, next);
kill(entry->pid, signal);
@@ -356,17 +361,17 @@ static void __reg_kill_all_spawned(int signal)
static pid_t __reg_first_spawned(void)
{
- if (list_is_empty(&reg.spawned))
+ if (llist_is_empty(&reg.spawned))
return -1;
- return list_first_entry(&reg.spawned, struct pid_entry, next)->pid;
+ return llist_first_entry(&reg.spawned, struct pid_entry, next)->pid;
}
static struct reg_prog * __reg_get_prog(const char * name)
{
struct list_head * p;
- list_for_each(p, &reg.progs) {
+ llist_for_each(p, &reg.progs) {
struct reg_prog * entry;
entry = list_entry(p, struct reg_prog, next);
if (strcmp(entry->info.name, name) == 0)
@@ -380,7 +385,7 @@ static char ** __reg_get_exec(const char * name)
{
struct list_head * p;
- list_for_each(p, &reg.names) {
+ llist_for_each(p, &reg.names) {
struct reg_name * entry;
entry = list_entry(p, struct reg_name, next);
if (strcmp(entry->info.name, name) == 0)
@@ -394,7 +399,7 @@ static struct list_head * __reg_after_prog(const char * name)
{
struct list_head * p;
- list_for_each(p, &reg.progs) {
+ llist_for_each(p, &reg.progs) {
struct reg_prog * entry;
entry = list_entry(p, struct reg_prog, next);
if (strcmp(entry->info.name, name) > 0)
@@ -408,7 +413,7 @@ static void __reg_del_name_from_procs(const char * name)
{
struct list_head * p;
- list_for_each(p, &reg.procs) {
+ llist_for_each(p, &reg.procs) {
struct reg_proc * proc;
proc = list_entry(p, struct reg_proc, next);
reg_proc_del_name(proc, name);
@@ -419,7 +424,7 @@ static void __reg_del_name_from_progs(const char * name)
{
struct list_head * p;
- list_for_each(p, &reg.progs) {
+ llist_for_each(p, &reg.progs) {
struct reg_prog * prog;
prog = list_entry(p, struct reg_prog, next);
reg_prog_del_name(prog, name);
@@ -431,13 +436,13 @@ static void __reg_proc_update_names(struct reg_proc * proc)
struct list_head * p;
struct reg_prog * prog;
- assert(list_is_empty(&proc->names));
+ assert(llist_is_empty(&proc->names));
prog = __reg_get_prog(proc->info.prog);
if (prog == NULL)
return;
- list_for_each(p, &reg.names) {
+ llist_for_each(p, &reg.names) {
struct reg_name * name;
name = list_entry(p, struct reg_name, next);
assert(!reg_name_has_proc(name, proc->info.pid));
@@ -452,7 +457,7 @@ static void __reg_del_proc_from_names(pid_t pid)
{
struct list_head * p;
- list_for_each(p, &reg.names) {
+ llist_for_each(p, &reg.names) {
struct reg_name * name;
name = list_entry(p, struct reg_name, next);
reg_name_del_proc(name, pid);
@@ -463,7 +468,7 @@ static void __reg_del_prog_from_names(const char * prog)
{
struct list_head * p;
- list_for_each(p, &reg.names) {
+ llist_for_each(p, &reg.names) {
struct reg_name * name;
name = list_entry(p, struct reg_name, next);
reg_name_del_prog(name, prog);
@@ -478,7 +483,7 @@ static int __reg_add_active_proc(pid_t pid)
assert(pid > 0);
- list_for_each(p, &reg.names) {
+ llist_for_each(p, &reg.names) {
struct reg_name * name;
name = list_entry(p, struct reg_name, next);
if (reg_name_has_proc(name, pid)) {
@@ -500,7 +505,7 @@ static void __reg_del_active_proc(pid_t pid)
assert(pid > 0);
- list_for_each(p, &reg.names) {
+ llist_for_each(p, &reg.names) {
struct reg_name * name;
name = list_entry(p, struct reg_name, next);
reg_name_del_active(name, pid);
@@ -529,20 +534,21 @@ int reg_init(void)
goto fail_cond;
}
- reg.flow_ids = bmp_create(SYS_MAX_FLOWS -ID_OFFT, ID_OFFT);
- if (reg.flow_ids == NULL) {
+ reg.ids = bmp_create(SYS_MAX_FLOWS - ID_OFFT, ID_OFFT);
+ if (reg.ids == NULL) {
log_err("Failed to create flow_ids bitmap.");
goto fail_flow_ids;
}
pthread_condattr_destroy(&cattr);
- list_head_init(&reg.flows);
- list_head_init(&reg.ipcps);
- list_head_init(&reg.names);
- list_head_init(&reg.procs);
- list_head_init(&reg.progs);
- list_head_init(&reg.spawned);
+ llist_init(&reg.flows);
+ llist_init(&reg.ipcps);
+ llist_init(&reg.names);
+ llist_init(&reg.pools);
+ llist_init(&reg.procs);
+ llist_init(&reg.progs);
+ llist_init(&reg.spawned);
return 0;
@@ -563,54 +569,56 @@ void reg_clear(void)
pthread_mutex_lock(&reg.mtx);
- list_for_each_safe(p, h, &reg.spawned) {
+ llist_for_each_safe(p, h, &reg.spawned) {
struct pid_entry * entry;
entry = list_entry(p, struct pid_entry, next);
- list_del(&entry->next);
+ llist_del(&entry->next, &reg.spawned);
free(entry);
- reg.n_spawned--;
}
- list_for_each_safe(p, h, &reg.progs) {
+ llist_for_each_safe(p, h, &reg.progs) {
struct reg_prog * entry;
entry = list_entry(p, struct reg_prog, next);
- list_del(&entry->next);
+ llist_del(&entry->next, &reg.progs);
__reg_del_prog_from_names(entry->info.path);
reg_prog_destroy(entry);
- reg.n_progs--;
}
- list_for_each_safe(p, h, &reg.procs) {
+ llist_for_each_safe(p, h, &reg.procs) {
struct reg_proc * entry;
entry = list_entry(p, struct reg_proc, next);
- list_del(&entry->next);
+ llist_del(&entry->next, &reg.procs);
__reg_del_proc_from_names(entry->info.pid);
reg_proc_destroy(entry);
- reg.n_procs--;
}
- list_for_each_safe(p, h, &reg.flows) {
+ llist_for_each_safe(p, h, &reg.pools) {
+ struct reg_pool * entry;
+ entry = list_entry(p, struct reg_pool, next);
+ llist_del(&entry->next, &reg.pools);
+ entry->refcount = 0; /* Force destroy during cleanup */
+ reg_pool_destroy(entry);
+ }
+
+ llist_for_each_safe(p, h, &reg.flows) {
struct reg_flow * entry;
entry = list_entry(p, struct reg_flow, next);
- list_del(&entry->next);
+ llist_del(&entry->next, &reg.flows);
reg_flow_destroy(entry);
- reg.n_flows--;
}
- list_for_each_safe(p, h, &reg.names) {
+ llist_for_each_safe(p, h, &reg.names) {
struct reg_name * entry;
entry = list_entry(p, struct reg_name, next);
- list_del(&entry->next);
+ llist_del(&entry->next, &reg.names);
reg_name_destroy(entry);
- reg.n_names--;
}
- list_for_each_safe(p, h, &reg.ipcps) {
+ llist_for_each_safe(p, h, &reg.ipcps) {
struct reg_ipcp * entry;
entry = list_entry(p, struct reg_ipcp, next);
- list_del(&entry->next);
+ llist_del(&entry->next, &reg.ipcps);
reg_ipcp_destroy(entry);
- reg.n_ipcps--;
}
pthread_mutex_unlock(&reg.mtx);
@@ -618,21 +626,15 @@ void reg_clear(void)
void reg_fini(void)
{
- assert(list_is_empty(&reg.spawned));
- assert(list_is_empty(&reg.progs));
- assert(list_is_empty(&reg.procs));
- assert(list_is_empty(&reg.names));
- assert(list_is_empty(&reg.ipcps));
- assert(list_is_empty(&reg.flows));
-
- assert(reg.n_spawned == 0);
- assert(reg.n_progs == 0);
- assert(reg.n_procs == 0);
- assert(reg.n_names == 0);
- assert(reg.n_ipcps == 0);
- assert(reg.n_flows == 0);
+ assert(llist_is_empty(&reg.spawned));
+ assert(llist_is_empty(&reg.progs));
+ assert(llist_is_empty(&reg.procs));
+ assert(llist_is_empty(&reg.pools));
+ assert(llist_is_empty(&reg.names));
+ assert(llist_is_empty(&reg.ipcps));
+ assert(llist_is_empty(&reg.flows));
- bmp_destroy(reg.flow_ids);
+ bmp_destroy(reg.ids);
if (pthread_cond_destroy(&reg.cond) != 0)
log_warn("Failed to destroy condvar.");
@@ -652,8 +654,8 @@ int reg_create_flow(struct flow_info * info)
pthread_mutex_lock(&reg.mtx);
- info->id = bmp_allocate(reg.flow_ids);
- if (!bmp_is_id_valid(reg.flow_ids, info->id)) {
+ info->id = bmp_allocate(reg.ids);
+ if (!bmp_is_id_valid(reg.ids, info->id)) {
log_err("Failed to allocate flow id.");
goto fail_id;
}
@@ -664,16 +666,14 @@ int reg_create_flow(struct flow_info * info)
goto fail_flow;
}
- list_add(&f->next, __reg_after_flow(info->id));
-
- reg.n_flows++;
+ llist_add_at(&f->next, __reg_after_flow(info->id), &reg.flows);
pthread_mutex_unlock(&reg.mtx);
return 0;
fail_flow:
- bmp_release(reg.flow_ids, info->id);
+ bmp_release(reg.ids, info->id);
info->id = 0;
fail_id:
pthread_mutex_unlock(&reg.mtx);
@@ -692,11 +692,9 @@ int reg_destroy_flow(int flow_id)
goto no_flow;
}
- list_del(&f->next);
-
- reg.n_flows--;
+ llist_del(&f->next, &reg.flows);
- bmp_release(reg.flow_ids, flow_id);
+ bmp_release(reg.ids, flow_id);
pthread_mutex_unlock(&reg.mtx);
@@ -755,11 +753,10 @@ int reg_create_ipcp(const struct ipcp_info * info)
entry->pid = info->pid;
- list_add_tail(&ipcp->next, __reg_after_ipcp(info));
- list_add(&entry->next, __reg_after_spawned(info->pid));
-
- reg.n_ipcps++;
- reg.n_spawned++;
+ llist_add_tail_at(&ipcp->next, __reg_after_ipcp(info), &reg.ipcps);
+ llist_add_at(&entry->next,
+ __reg_after_spawned(info->pid),
+ &reg.spawned);
pthread_mutex_unlock(&reg.mtx);
@@ -849,16 +846,16 @@ int reg_list_ipcps(ipcp_list_msg_t *** ipcps)
pthread_mutex_lock(&reg.mtx);
- if (reg.n_ipcps == 0)
+ if (llist_is_empty(&reg.ipcps))
goto finish;
- *ipcps = malloc(reg.n_ipcps * sizeof(**ipcps));
+ *ipcps = malloc(reg.ipcps.len * sizeof(**ipcps));
if (*ipcps == NULL) {
log_err("Failed to malloc ipcps.");
goto fail_malloc;
}
- list_for_each(p, &reg.ipcps) {
+ llist_for_each(p, &reg.ipcps) {
struct reg_ipcp * entry;
entry = list_entry(p, struct reg_ipcp, next);
if (__get_ipcp_info(&(*ipcps)[i], entry) < 0)
@@ -900,9 +897,7 @@ int reg_create_name(const struct name_info * info)
goto fail_name;
}
- list_add(&n->next, __reg_after_name(info->name));
-
- reg.n_names++;
+ llist_add_at(&n->next, __reg_after_name(info->name), &reg.names);
pthread_mutex_unlock(&reg.mtx);
return 0;
@@ -931,9 +926,7 @@ int reg_destroy_name(const char * name)
__reg_del_name_from_procs(name);
__reg_del_name_from_progs(name);
- list_del(&n->next);
-
- reg.n_names--;
+ llist_del(&n->next, &reg.names);
pthread_mutex_unlock(&reg.mtx);
@@ -1004,7 +997,7 @@ int reg_get_name_for_hash(char * buf,
pthread_mutex_lock(&reg.mtx);
- list_for_each(p, &reg.names) {
+ llist_for_each(p, &reg.names) {
struct reg_name * n = list_entry(p, struct reg_name, next);
str_hash(algo, thash, n->info.name);
if (memcmp(thash, hash, len) == 0) {
@@ -1046,16 +1039,16 @@ int reg_list_names(name_info_msg_t *** names)
pthread_mutex_lock(&reg.mtx);
- if (reg.n_names == 0)
+ if (llist_is_empty(&reg.names))
goto finish;
- *names = malloc(reg.n_names * sizeof(**names));
+ *names = malloc(reg.names.len * sizeof(**names));
if (*names == NULL) {
log_err("Failed to malloc names.");
goto fail_malloc;
}
- list_for_each(p, &reg.names) {
+ llist_for_each(p, &reg.names) {
struct reg_name * entry;
entry = list_entry(p, struct reg_name, next);
(*names)[i] = name_info_s_to_msg(&entry->info);
@@ -1090,6 +1083,34 @@ int reg_list_names(name_info_msg_t *** names)
return -ENOMEM;
}
+int reg_prepare_pool(uid_t uid,
+ gid_t gid)
+{
+ struct reg_pool * pool;
+
+ if (is_ouroboros_member_uid(uid))
+ return 0;
+
+ pthread_mutex_lock(&reg.mtx);
+
+ pool = __reg_get_pool(uid);
+ if (pool == NULL) {
+ pool = reg_pool_create(uid, gid);
+ if (pool == NULL) {
+ log_err("Failed to create pool for uid %d.", uid);
+ pthread_mutex_unlock(&reg.mtx);
+ return -1;
+ }
+ llist_add(&pool->next, &reg.pools);
+ }
+
+ reg_pool_ref(pool);
+
+ pthread_mutex_unlock(&reg.mtx);
+
+ return 0;
+}
+
int reg_create_proc(const struct proc_info * info)
{
struct reg_proc * proc;
@@ -1100,20 +1121,18 @@ int reg_create_proc(const struct proc_info * info)
if (__reg_get_proc(info->pid) != NULL) {
log_err("Process %d already exists.", info->pid);
- goto fail_proc;
+ goto fail;
}
proc = reg_proc_create(info);
if (proc == NULL) {
log_err("Failed to create process %d.", info->pid);
- goto fail_proc;
+ goto fail;
}
__reg_proc_update_names(proc);
- list_add(&proc->next, __reg_after_proc(info->pid));
-
- reg.n_procs++;
+ llist_add_at(&proc->next, __reg_after_proc(info->pid), &reg.procs);
pthread_cond_broadcast(&reg.cond);
@@ -1121,7 +1140,7 @@ int reg_create_proc(const struct proc_info * info)
return 0;
- fail_proc:
+ fail:
pthread_mutex_unlock(&reg.mtx);
return -1;
}
@@ -1129,6 +1148,7 @@ int reg_create_proc(const struct proc_info * info)
int reg_destroy_proc(pid_t pid)
{
struct reg_proc * proc;
+ struct reg_pool * pool = NULL;
struct pid_entry * spawn;
struct reg_ipcp * ipcp;
@@ -1136,24 +1156,27 @@ int reg_destroy_proc(pid_t pid)
proc = __reg_get_proc(pid);
if (proc != NULL) {
- list_del(&proc->next);
- reg.n_procs--;
+ if (!is_ouroboros_member_uid(proc->info.uid))
+ pool = __reg_get_pool(proc->info.uid);
+ llist_del(&proc->next, &reg.procs);
reg_proc_destroy(proc);
__reg_del_proc_from_names(pid);
__reg_cancel_flows_for_proc(pid);
+ if (pool != NULL && reg_pool_unref(pool) == 0) {
+ llist_del(&pool->next, &reg.pools);
+ reg_pool_destroy(pool);
+ }
}
spawn = __reg_get_spawned(pid);
if (spawn != NULL) {
- list_del(&spawn->next);
- reg.n_spawned--;
+ llist_del(&spawn->next, &reg.spawned);
free(spawn);
}
ipcp = __reg_get_ipcp(pid);
if (ipcp != NULL) {
- list_del(&ipcp->next);
- reg.n_ipcps--;
+ llist_del(&ipcp->next, &reg.ipcps);
reg_ipcp_destroy(ipcp);
}
@@ -1175,6 +1198,38 @@ bool reg_has_proc(pid_t pid)
return ret;
}
+bool reg_is_proc_privileged(pid_t pid)
+{
+ struct reg_proc * proc;
+ bool ret = false;
+
+ pthread_mutex_lock(&reg.mtx);
+
+ proc = __reg_get_proc(pid);
+ if (proc != NULL)
+ ret = reg_proc_is_privileged(proc);
+
+ pthread_mutex_unlock(&reg.mtx);
+
+ return ret;
+}
+
+uid_t reg_get_proc_uid(pid_t pid)
+{
+ struct reg_proc * proc;
+ uid_t ret = 0;
+
+ pthread_mutex_lock(&reg.mtx);
+
+ proc = __reg_get_proc(pid);
+ if (proc != NULL && !is_ouroboros_member_uid(proc->info.uid))
+ ret = proc->info.uid;
+
+ pthread_mutex_unlock(&reg.mtx);
+
+ return ret;
+}
+
void reg_kill_all_proc(int signal)
{
pthread_mutex_lock(&reg.mtx);
@@ -1216,9 +1271,7 @@ int reg_create_spawned(pid_t pid)
entry->pid = pid;
- list_add(&entry->next, __reg_after_spawned(pid));
-
- reg.n_spawned++;
+ llist_add_at(&entry->next, __reg_after_spawned(pid), &reg.spawned);
pthread_mutex_unlock(&reg.mtx);
@@ -1388,9 +1441,7 @@ int reg_create_prog(const struct prog_info * info)
goto fail_prog;
}
- list_add(&prog->next, __reg_after_prog(info->name));
-
- reg.n_progs++;
+ llist_add_at(&prog->next, __reg_after_prog(info->name), &reg.progs);
exists:
pthread_mutex_unlock(&reg.mtx);
@@ -1418,9 +1469,7 @@ int reg_destroy_prog(const char * name)
__reg_del_prog_from_names(prog->info.path);
- list_del(&prog->next);
-
- reg.n_progs--;
+ llist_del(&prog->next, &reg.progs);
pthread_mutex_unlock(&reg.mtx);
@@ -1736,7 +1785,8 @@ int reg_wait_flow_allocated(struct flow_info * info,
}
if (flow != NULL) {
- reg_flow_get_data(flow, pbuf);
+ *pbuf = flow->rsp_data;
+ clrbuf(flow->rsp_data);
*info = flow->info;
}
@@ -1771,8 +1821,8 @@ int reg_respond_alloc(struct flow_info * info,
}
assert(flow->info.state == FLOW_ALLOC_PENDING);
- assert(flow->data.len == 0);
- assert(flow->data.data == NULL);
+ assert(flow->rsp_data.len == 0);
+ assert(flow->rsp_data.data == NULL);
info->n_pid = flow->info.n_pid;
info->n_1_pid = flow->info.n_pid;
@@ -1784,8 +1834,10 @@ int reg_respond_alloc(struct flow_info * info,
flow->response = response;
- if (info->state == FLOW_ALLOCATED)
- reg_flow_set_data(flow, pbuf);
+ if (info->state == FLOW_ALLOCATED) {
+ flow->rsp_data = *pbuf;
+ clrbuf(*pbuf);
+ }
pthread_cond_broadcast(&reg.cond);
@@ -1816,6 +1868,8 @@ int reg_prepare_flow_accept(struct flow_info * info)
ret = reg_flow_update(flow, info);
+ pthread_cond_broadcast(&reg.cond);
+
pthread_mutex_unlock(&reg.mtx);
return ret;
@@ -1893,7 +1947,8 @@ int reg_wait_flow_accepted(struct flow_info * info,
pthread_cleanup_pop(true); /* __cleanup_wait_accept */
if (flow != NULL) {
- reg_flow_get_data(flow, pbuf);
+ *pbuf = flow->req_data;
+ clrbuf(flow->req_data);
*info = flow->info;
}
@@ -1953,8 +2008,63 @@ int reg_respond_accept(struct flow_info * info,
info->n_pid = flow->info.n_pid;
- reg_flow_set_data(flow, pbuf);
- clrbuf(pbuf);
+ flow->req_data = *pbuf;
+ clrbuf(*pbuf);
+
+ if (reg_flow_update(flow, info) < 0) {
+ log_err("Failed to create flow structs.");
+ goto fail_flow;
+ }
+
+ pthread_cond_broadcast(&reg.cond);
+
+ pthread_mutex_unlock(&reg.mtx);
+
+ return 0;
+
+ fail_flow:
+ pthread_mutex_unlock(&reg.mtx);
+ return -1;
+}
+
+int reg_prepare_flow_direct(struct flow_info * info,
+ buffer_t * pbuf,
+ uid_t alloc_uid)
+{
+ struct reg_flow * flow;
+ struct reg_proc * proc;
+ uid_t accept_uid = 0;
+
+ assert(info != NULL);
+ assert(info->state == FLOW_ALLOCATED);
+ assert(info->n_1_pid != 0);
+ assert(pbuf != NULL);
+
+ pthread_mutex_lock(&reg.mtx);
+
+ flow = __reg_get_flow(info->id);
+ if (flow == NULL) {
+ log_err("Flow not found: %d.", info->id);
+ goto fail_flow;
+ }
+
+ assert(flow->info.state == FLOW_ACCEPT_PENDING);
+
+ info->n_pid = flow->info.n_pid;
+
+ proc = __reg_get_proc(info->n_pid);
+ if (proc != NULL && !is_ouroboros_member_uid(proc->info.uid))
+ accept_uid = proc->info.uid;
+
+ if (alloc_uid != accept_uid) {
+ pthread_mutex_unlock(&reg.mtx);
+ return -EPERM;
+ }
+
+ flow->direct = true;
+
+ flow->req_data = *pbuf;
+ clrbuf(*pbuf);
if (reg_flow_update(flow, info) < 0) {
log_err("Failed to create flow structs.");
@@ -1972,6 +2082,109 @@ int reg_respond_accept(struct flow_info * info,
return -1;
}
+bool reg_flow_is_direct(int flow_id)
+{
+ struct reg_flow * flow;
+ bool ret;
+
+ pthread_mutex_lock(&reg.mtx);
+
+ flow = __reg_get_flow(flow_id);
+
+ ret = flow != NULL && flow->direct;
+
+ pthread_mutex_unlock(&reg.mtx);
+
+ return ret;
+}
+
+int reg_respond_flow_direct(int flow_id,
+ buffer_t * pbuf)
+{
+ struct reg_flow * flow;
+
+ assert(pbuf != NULL);
+
+ pthread_mutex_lock(&reg.mtx);
+
+ flow = __reg_get_flow(flow_id);
+ if (flow == NULL) {
+ log_err("Flow %d not found.", flow_id);
+ goto fail;
+ }
+
+ assert(flow->direct);
+ assert(flow->rsp_data.data == NULL);
+
+ flow->rsp_data = *pbuf;
+ clrbuf(*pbuf);
+
+ pthread_cond_broadcast(&reg.cond);
+
+ pthread_mutex_unlock(&reg.mtx);
+
+ return 0;
+ fail:
+ pthread_mutex_unlock(&reg.mtx);
+ return -1;
+}
+
+int reg_wait_flow_direct(int flow_id,
+ buffer_t * pbuf,
+ const struct timespec * abstime)
+{
+ struct reg_flow * flow;
+ int ret = -1;
+
+ assert(pbuf != NULL);
+
+ pthread_mutex_lock(&reg.mtx);
+
+ flow = __reg_get_flow(flow_id);
+ if (flow == NULL)
+ goto fail;
+
+ assert(flow->direct);
+
+ pthread_cleanup_push(__cleanup_mutex_unlock, &reg.mtx);
+
+ while (flow != NULL && flow->rsp_data.data == NULL) {
+ ret = -__timedwait(&reg.cond, &reg.mtx, abstime);
+ if (ret == -ETIMEDOUT)
+ break;
+ flow = __reg_get_flow(flow_id);
+ }
+
+ if (flow != NULL && flow->rsp_data.data != NULL) {
+ *pbuf = flow->rsp_data;
+ clrbuf(flow->rsp_data);
+ ret = 0;
+ }
+
+ pthread_cleanup_pop(true);
+
+ return ret;
+ fail:
+ pthread_mutex_unlock(&reg.mtx);
+ return -1;
+}
+
+static int direct_flow_dealloc(struct reg_flow * flow,
+ pid_t pid)
+{
+ if (!flow->direct)
+ return -1;
+
+ if (pid == flow->info.n_pid && flow->info.n_pid != -1)
+ flow->info.n_pid = -1;
+ else if (pid == flow->info.n_1_pid && flow->info.n_1_pid != -1)
+ flow->info.n_1_pid = -1;
+ else
+ return -1;
+
+ return 0;
+}
+
void reg_dealloc_flow(struct flow_info * info)
{
struct reg_flow * flow;
@@ -1985,13 +2198,32 @@ void reg_dealloc_flow(struct flow_info * info)
flow = __reg_get_flow(info->id);
assert(flow != NULL);
- assert(flow->data.data == NULL);
- assert(flow->data.len == 0);
+ assert(flow->req_data.data == NULL);
+ assert(flow->req_data.len == 0);
+ assert(flow->rsp_data.data == NULL);
+ assert(flow->rsp_data.len == 0);
+
+ info->n_1_pid = flow->info.n_1_pid;
+
+ if (flow->info.state == FLOW_DEALLOC_PENDING) {
+ if (direct_flow_dealloc(flow, info->n_pid) < 0) {
+ info->state = FLOW_DEALLOC_PENDING;
+ pthread_mutex_unlock(&reg.mtx);
+ return;
+ }
+ flow->info.state = FLOW_DEALLOCATED;
+ info->state = FLOW_DEALLOCATED;
+ reg_flow_update(flow, info);
+ pthread_mutex_unlock(&reg.mtx);
+ return;
+ }
+
assert(flow->info.state == FLOW_ALLOCATED);
flow->info.state = FLOW_DEALLOC_PENDING;
info->state = FLOW_DEALLOC_PENDING;
- info->n_1_pid = flow->info.n_1_pid;
+
+ direct_flow_dealloc(flow, info->n_pid);
memset(flow->name, 0, sizeof(flow->name));
@@ -2013,8 +2245,10 @@ void reg_dealloc_flow_resp(struct flow_info * info)
flow = __reg_get_flow(info->id);
assert(flow != NULL);
- assert(flow->data.data == NULL);
- assert(flow->data.len == 0);
+ assert(flow->req_data.data == NULL);
+ assert(flow->req_data.len == 0);
+ assert(flow->rsp_data.data == NULL);
+ assert(flow->rsp_data.len == 0);
assert(flow->info.state == FLOW_DEALLOC_PENDING);
flow->info.state = FLOW_DEALLOCATED;
diff --git a/src/irmd/reg/reg.h b/src/irmd/reg/reg.h
index 7728c80f..6b576471 100644
--- a/src/irmd/reg/reg.h
+++ b/src/irmd/reg/reg.h
@@ -1,5 +1,5 @@
/*
- * Ouroboros - Copyright (C) 2016 - 2024
+ * Ouroboros - Copyright (C) 2016 - 2026
*
* The IPC Resource Manager - Registry
*
@@ -31,6 +31,8 @@
#include <ouroboros/time.h>
#include <ouroboros/utils.h>
+#include "pool.h"
+
int reg_init(void);
void reg_clear(void);
@@ -50,6 +52,13 @@ int reg_destroy_proc(pid_t pid);
bool reg_has_proc(pid_t pid);
+bool reg_is_proc_privileged(pid_t pid);
+
+int reg_prepare_pool(uid_t uid,
+ gid_t gid);
+
+uid_t reg_get_proc_uid(pid_t pid);
+
void reg_kill_all_proc(int signal);
pid_t reg_get_dead_proc(void);
@@ -141,6 +150,19 @@ int reg_wait_flow_accepting(const char * name,
int reg_respond_accept(struct flow_info * info,
buffer_t * pbuf);
+int reg_prepare_flow_direct(struct flow_info * info,
+ buffer_t * pbuf,
+ uid_t alloc_uid);
+
+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);
+
+bool reg_flow_is_direct(int flow_id);
+
void reg_dealloc_flow(struct flow_info * info);
void reg_dealloc_flow_resp(struct flow_info * info);
diff --git a/src/irmd/reg/tests/CMakeLists.txt b/src/irmd/reg/tests/CMakeLists.txt
index 73df911b..e8521545 100644
--- a/src/irmd/reg/tests/CMakeLists.txt
+++ b/src/irmd/reg/tests/CMakeLists.txt
@@ -1,7 +1,9 @@
-get_filename_component(tmp ".." ABSOLUTE)
-get_filename_component(src_folder "${tmp}" NAME)
+get_filename_component(PARENT_PATH ${CMAKE_CURRENT_SOURCE_DIR} DIRECTORY)
+get_filename_component(PARENT_DIR ${PARENT_PATH} NAME)
-create_test_sourcelist(${src_folder}_tests test_suite.c
+compute_test_prefix()
+
+create_test_sourcelist(${PARENT_DIR}_tests test_suite.c
# Add new tests here
flow_test.c
ipcp_test.c
@@ -11,23 +13,21 @@ create_test_sourcelist(${src_folder}_tests test_suite.c
reg_test.c
)
-add_executable(${src_folder}_test ${${src_folder}_tests})
-target_link_libraries(${src_folder}_test ouroboros-common)
+add_executable(${PARENT_DIR}_test ${${PARENT_DIR}_tests})
-if (CMAKE_BUILD_TYPE MATCHES "Debug*")
- add_compile_flags(${src_folder}_test -DCONFIG_OUROBOROS_DEBUG)
-endif ()
+target_include_directories(${PARENT_DIR}_test PRIVATE
+ ${CMAKE_CURRENT_SOURCE_DIR}
+ ${CMAKE_CURRENT_BINARY_DIR}
+ ${CMAKE_SOURCE_DIR}/include
+ ${CMAKE_BINARY_DIR}/include
+ ${CMAKE_SOURCE_DIR}/src/irmd
+ ${CMAKE_BINARY_DIR}/src/irmd
+)
-add_dependencies(check ${src_folder}_test)
+disable_test_logging_for_target(${PARENT_DIR}_test)
+target_link_libraries(${PARENT_DIR}_test PRIVATE ouroboros-common)
+ouroboros_target_debug_definitions(${PARENT_DIR}_test)
-set(tests_to_run ${${src_folder}_tests})
-if(CMAKE_VERSION VERSION_LESS "3.29.0")
- remove(tests_to_run test_suite.c)
-else ()
- list(POP_FRONT tests_to_run)
-endif()
+add_dependencies(build_tests ${PARENT_DIR}_test)
-foreach(test ${tests_to_run})
- get_filename_component(test_name ${test} NAME_WE)
- add_test(irmd/reg/${test_name} ${C_TEST_PATH}/${src_folder}_test ${test_name})
-endforeach(test)
+ouroboros_register_tests(TARGET ${PARENT_DIR}_test TESTS ${${PARENT_DIR}_tests})
diff --git a/src/irmd/reg/tests/flow_test.c b/src/irmd/reg/tests/flow_test.c
index 27fd61b0..7e1c1360 100644
--- a/src/irmd/reg/tests/flow_test.c
+++ b/src/irmd/reg/tests/flow_test.c
@@ -1,5 +1,5 @@
/*
- * Ouroboros - Copyright (C) 2016 - 2024
+ * Ouroboros - Copyright (C) 2016 - 2026
*
* The IPC Resource Manager - Registry - Flows - Unit Tests
*
@@ -22,11 +22,7 @@
#include "../flow.c"
-#include <ouroboros/test.h>
-
-#include <string.h>
-
-#define TEST_DATA "testpiggybackdata"
+#include <test/test.h>
static int test_reg_flow_create_destroy(void)
{
@@ -219,56 +215,6 @@ static int test_reg_flow_assert_fails(void)
return ret;
}
-static int test_flow_data(void)
-{
- struct reg_flow * f;
-
- struct flow_info info = {
- .id = 1,
- .n_pid = 1,
- .qs = qos_raw,
- .state = FLOW_INIT
- };
-
- char * data;
- buffer_t buf;
- buffer_t rcv = {0, NULL};
-
- TEST_START();
-
- data = strdup(TEST_DATA);
- if (data == NULL) {
- printf("Failed to strdup data.\n");
- goto fail;
- }
-
- buf.data = (uint8_t *) data;
- buf.len = strlen(data);
-
- f = reg_flow_create(&info);
- if (f == NULL) {
- printf("Failed to create flow.\n");
- goto fail;
- }
-
- reg_flow_set_data(f, &buf);
-
- reg_flow_get_data(f, &rcv);
-
- freebuf(buf);
- clrbuf(rcv);
-
- reg_flow_destroy(f);
-
- TEST_SUCCESS();
-
- return TEST_RC_SUCCESS;
- fail:
- free(data);
- TEST_FAIL();
- return TEST_RC_FAIL;
-}
-
int flow_test(int argc,
char ** argv)
{
@@ -280,7 +226,6 @@ int flow_test(int argc,
ret |= test_reg_flow_create_destroy();
ret |= test_reg_flow_update();
ret |= test_reg_flow_assert_fails();
- ret |= test_flow_data();
return ret;
}
diff --git a/src/irmd/reg/tests/ipcp_test.c b/src/irmd/reg/tests/ipcp_test.c
index d7d8e524..5279283e 100644
--- a/src/irmd/reg/tests/ipcp_test.c
+++ b/src/irmd/reg/tests/ipcp_test.c
@@ -1,5 +1,5 @@
/*
- * Ouroboros - Copyright (C) 2016 - 2024
+ * Ouroboros - Copyright (C) 2016 - 2026
*
* The IPC Resource Manager - Registry - IPCPs - Unit Tests
*
@@ -20,7 +20,7 @@
* Foundation, Inc., http://www.fsf.org/about/contact/.
*/
-#include <ouroboros/test.h>
+#include <test/test.h>
#include "../ipcp.c"
diff --git a/src/irmd/reg/tests/name_test.c b/src/irmd/reg/tests/name_test.c
index 9071364b..403c8a6c 100644
--- a/src/irmd/reg/tests/name_test.c
+++ b/src/irmd/reg/tests/name_test.c
@@ -1,5 +1,5 @@
/*
- * Ouroboros - Copyright (C) 2016 - 2024
+ * Ouroboros - Copyright (C) 2016 - 2026
*
* The IPC Resource Manager - Registry - Names - Unit Tests
*
@@ -23,7 +23,7 @@
#include "../name.c"
-#include <ouroboros/test.h>
+#include <test/test.h>
#define TEST_PID 65534
#define TEST_PROG "/usr/bin/testprog"
@@ -88,7 +88,7 @@ static int test_reg_name_add_proc(void)
reg_name_del_proc(n, TEST_PID);
- if (n->procs.len != 0) {
+ if (!llist_is_empty(&n->procs)) {
printf("Proc not removed from list.\n");
goto fail;
}
@@ -138,7 +138,7 @@ static int test_reg_name_add_prog(void)
reg_name_del_prog(n, TEST_PROG);
- if (n->progs.len != 0) {
+ if (!llist_is_empty(&n->progs)) {
printf("Prog not removed from list.\n");
goto fail;
}
@@ -263,12 +263,12 @@ static int test_reg_name_add_active(enum pol_balance lb)
reg_name_del_proc(n, TEST_PID);
- if (n->procs.len != 0) {
+ if (!llist_is_empty(&n->procs)) {
printf("Procs list not cleared.\n");
goto fail;
}
- if (n->active.len != 0) {
+ if (!llist_is_empty(&n->active)) {
printf("Active list not cleared.\n");
goto fail;
}
diff --git a/src/irmd/reg/tests/proc_test.c b/src/irmd/reg/tests/proc_test.c
index df0527fb..a85f4039 100644
--- a/src/irmd/reg/tests/proc_test.c
+++ b/src/irmd/reg/tests/proc_test.c
@@ -1,5 +1,5 @@
/*
- * Ouroboros - Copyright (C) 2016 - 2024
+ * Ouroboros - Copyright (C) 2016 - 2026
*
* The IPC Resource Manager - Registry - Processes - Unit Tests
*
@@ -22,18 +22,22 @@
#include "../proc.c"
-#include <ouroboros/test.h>
+#include <test/test.h>
#define TEST_PID 65534
#define TEST_PROG "usr/bin/testprog"
+#define TEST_PROC { \
+ .pid = TEST_PID, \
+ .prog = TEST_PROG, \
+ .uid = getuid(), \
+ .gid = getgid() \
+}
+
static int test_reg_proc_create_destroy(void)
{
struct reg_proc * proc;
- struct proc_info info = {
- .pid = TEST_PID,
- .prog = TEST_PROG
- };
+ struct proc_info info = TEST_PROC;
TEST_START();
@@ -56,10 +60,7 @@ static int test_reg_proc_create_destroy(void)
static int test_reg_proc_add_name(void)
{
struct reg_proc * proc;
- struct proc_info info = {
- .pid = TEST_PID,
- .prog = TEST_PROG
- };
+ struct proc_info info = TEST_PROC;
char * name = "testname";
@@ -76,7 +77,7 @@ static int test_reg_proc_add_name(void)
goto fail;
}
- if (proc->n_names != 1) {
+ if (proc->names.len != 1) {
printf("n_names not updated.\n");
goto fail;
}
@@ -88,7 +89,7 @@ static int test_reg_proc_add_name(void)
reg_proc_del_name(proc, name);
- if (proc->n_names != 0) {
+ if (!llist_is_empty(&proc->names)) {
printf("n_names not updated.\n");
goto fail;
}
diff --git a/src/irmd/reg/tests/prog_test.c b/src/irmd/reg/tests/prog_test.c
index c394c222..91264aba 100644
--- a/src/irmd/reg/tests/prog_test.c
+++ b/src/irmd/reg/tests/prog_test.c
@@ -1,5 +1,5 @@
/*
- * Ouroboros - Copyright (C) 2016 - 2024
+ * Ouroboros - Copyright (C) 2016 - 2026
*
* The IPC Resource Manager - Registry - Programs - Unit Tests
*
@@ -22,7 +22,7 @@
#include "../prog.c"
-#include <ouroboros/test.h>
+#include <test/test.h>
#define TEST_PROG "usr/bin/testprog"
@@ -73,7 +73,7 @@ static int test_reg_prog_add_name(void)
goto fail;
}
- if (prog->n_names != 1) {
+ if (prog->names.len != 1) {
printf("n_names not updated.\n");
goto fail;
}
@@ -85,7 +85,7 @@ static int test_reg_prog_add_name(void)
reg_prog_del_name(prog, name);
- if (prog->n_names != 0) {
+ if (!llist_is_empty(&prog->names)) {
printf("n_names not updated.\n");
goto fail;
}
diff --git a/src/irmd/reg/tests/reg_test.c b/src/irmd/reg/tests/reg_test.c
index 4699beab..b426c0dd 100644
--- a/src/irmd/reg/tests/reg_test.c
+++ b/src/irmd/reg/tests/reg_test.c
@@ -1,5 +1,5 @@
/*
- * Ouroboros - Copyright (C) 2016 - 2024
+ * Ouroboros - Copyright (C) 2016 - 2026
*
* The IPC Resource Manager - Registry - Unit Tests
*
@@ -21,9 +21,11 @@
*/
+#include "../pool.c"
+#undef OUROBOROS_PREFIX
#include "../reg.c"
-#include <ouroboros/test.h>
+#include <test/test.h>
#define TEST_PID 3666
#define TEST_N_1_PID 3999
@@ -35,8 +37,14 @@
#define TEST_DATA "testpbufdata"
#define TEST_DATA2 "testpbufdata2"
#define TEST_LAYER "testlayer"
+#define TEST_PROC_INFO { \
+ .pid = TEST_PID, \
+ .prog = TEST_PROG, \
+ .uid = 0, \
+ .gid = 0 \
+}
#define REG_TEST_FAIL() \
- do { TEST_FAIL(); memset(&reg, 0, sizeof(reg)); abort();} while(0)
+ do { TEST_FAIL(); reg_clear(); return TEST_RC_FAIL;} while(0)
static int test_reg_init(void)
{
@@ -81,7 +89,7 @@ static int test_reg_create_flow(void)
goto fail;
}
- if (reg.n_flows != 1) {
+ if (reg.flows.len != 1) {
printf("n_flows was not updated.\n");
goto fail;
}
@@ -96,8 +104,8 @@ static int test_reg_create_flow(void)
goto fail;
}
- if (reg.n_flows != 0) {
- printf("n_flows was not updated.\n");
+ if (!llist_is_empty(&reg.flows)) {
+ printf("flows.len was not updated.\n");
goto fail;
}
@@ -155,7 +163,7 @@ static int test_reg_allocate_flow_timeout(void)
reg_destroy_flow(info.id);
- if (reg.n_flows != 0) {
+ if (!llist_is_empty(&reg.flows)) {
printf("Flow did not destroy.\n");
goto fail;
}
@@ -189,6 +197,8 @@ static void * test_flow_respond_alloc(void * o)
reg_respond_alloc(info, &pbuf, response);
+ freebuf(pbuf);
+
return (void *) 0;
fail:
return (void *) -1;
@@ -208,6 +218,8 @@ static void * test_flow_respond_accept(void * o)
reg_respond_accept(info, &pbuf);
+ freebuf(pbuf);
+
return (void *) 0;
fail:
return (void *) -1;
@@ -259,6 +271,9 @@ static int test_reg_accept_flow_success(void)
if (reg_wait_flow_accepted(&info, &rbuf, &abstime) < 0) {
printf("Flow allocation failed.\n");
+ pthread_join(thr, NULL);
+ reg_destroy_flow(info.id);
+ reg_fini();
goto fail;
}
@@ -353,6 +368,9 @@ static int test_reg_accept_flow_success_no_crypt(void)
if (reg_wait_flow_accepted(&info, &rbuf, &abstime) < 0 ) {
printf("Flow allocation failed.\n");
+ pthread_join(thr, NULL);
+ reg_destroy_flow(info.id);
+ reg_fini();
goto fail;
}
@@ -446,6 +464,9 @@ static int test_reg_allocate_flow_fail(void)
if (reg_wait_flow_allocated(&info, &buf, &abstime) == 0 ) {
printf("Flow allocation succeeded.\n");
+ pthread_join(thr, NULL);
+ reg_destroy_flow(info.id);
+ reg_fini();
goto fail;
}
@@ -468,6 +489,188 @@ static int test_reg_allocate_flow_fail(void)
return TEST_RC_FAIL;
}
+struct direct_alloc_info {
+ struct flow_info info;
+ buffer_t rsp;
+ struct timespec abstime;
+};
+
+static void * test_flow_alloc_direct(void * o)
+{
+ struct direct_alloc_info * dai;
+ buffer_t req;
+
+ dai = (struct direct_alloc_info *) o;
+
+ req.data = (uint8_t *) strdup(TEST_DATA);
+ if (req.data == NULL) {
+ printf("Failed to strdup req data.\n");
+ goto fail;
+ }
+ req.len = strlen(TEST_DATA) + 1;
+
+ if (reg_prepare_flow_direct(&dai->info, &req, 0) < 0) {
+ printf("Failed to prepare direct flow.\n");
+ freebuf(req);
+ goto fail;
+ }
+
+ if (reg_wait_flow_direct(dai->info.id, &dai->rsp, &dai->abstime) < 0) {
+ printf("Failed to wait direct flow.\n");
+ goto fail;
+ }
+
+ return (void *) 0;
+ fail:
+ return (void *) -1;
+}
+
+static int test_reg_direct_flow_success(void)
+{
+ pthread_t thr;
+ struct timespec abstime;
+ struct timespec timeo = TIMESPEC_INIT_S(1);
+ buffer_t rbuf = BUF_INIT;
+ buffer_t rsp;
+ struct direct_alloc_info dai;
+ void * thr_ret;
+
+ struct flow_info info = {
+ .n_pid = TEST_PID,
+ .qs = qos_raw
+ };
+
+ TEST_START();
+
+ clock_gettime(PTHREAD_COND_CLOCK, &abstime);
+
+ ts_add(&abstime, &timeo, &abstime);
+
+ if (reg_init() < 0) {
+ printf("Failed to init registry.\n");
+ goto fail;
+ }
+
+ if (reg_create_flow(&info) < 0) {
+ printf("Failed to add flow.\n");
+ goto fail;
+ }
+
+ if (reg_prepare_flow_accept(&info) < 0) {
+ printf("Failed to prepare for accept.\n");
+ goto fail;
+ }
+
+ dai.info.id = info.id;
+ dai.info.n_1_pid = TEST_N_1_PID;
+ dai.info.mpl = TEST_MPL;
+ dai.info.qs = qos_data;
+ dai.info.state = FLOW_ALLOCATED;
+ dai.rsp.len = 0;
+ dai.rsp.data = NULL;
+ dai.abstime = abstime;
+
+ pthread_create(&thr, NULL, test_flow_alloc_direct, &dai);
+
+ if (reg_wait_flow_accepted(&info, &rbuf, &abstime) < 0) {
+ printf("Flow accept failed.\n");
+ pthread_join(thr, NULL);
+ reg_destroy_flow(info.id);
+ reg_fini();
+ goto fail;
+ }
+
+ if (info.state != FLOW_ALLOCATED) {
+ printf("Flow not in allocated state.\n");
+ goto fail;
+ }
+
+ if (rbuf.data == NULL) {
+ printf("req_data not received.\n");
+ goto fail;
+ }
+
+ if (strcmp((char *) rbuf.data, TEST_DATA) != 0) {
+ printf("req_data content mismatch.\n");
+ goto fail;
+ }
+
+ freebuf(rbuf);
+
+ if (!reg_flow_is_direct(info.id)) {
+ printf("Flow not marked direct.\n");
+ goto fail;
+ }
+
+ rsp.data = (uint8_t *) strdup(TEST_DATA2);
+ if (rsp.data == NULL) {
+ printf("Failed to strdup rsp data.\n");
+ goto fail;
+ }
+ rsp.len = strlen(TEST_DATA2) + 1;
+
+ if (reg_respond_flow_direct(info.id, &rsp) < 0) {
+ printf("Failed to respond direct.\n");
+ freebuf(rsp);
+ goto fail;
+ }
+
+ pthread_join(thr, &thr_ret);
+
+ if (thr_ret != (void *) 0) {
+ printf("Allocator thread failed.\n");
+ goto fail;
+ }
+
+ if (dai.rsp.data == NULL) {
+ printf("rsp_data not received.\n");
+ goto fail;
+ }
+
+ if (strcmp((char *) dai.rsp.data, TEST_DATA2) != 0) {
+ printf("rsp_data content mismatch.\n");
+ goto fail;
+ }
+
+ freebuf(dai.rsp);
+
+ reg_dealloc_flow(&info);
+
+ if (info.state != FLOW_DEALLOC_PENDING) {
+ printf("Flow not in dealloc pending.\n");
+ goto fail;
+ }
+
+ info.n_pid = TEST_PID;
+
+ reg_dealloc_flow(&info);
+
+ if (info.state != FLOW_DEALLOC_PENDING) {
+ printf("Same endpoint dealloc changed state.\n");
+ goto fail;
+ }
+
+ info.n_pid = TEST_N_1_PID;
+
+ reg_dealloc_flow(&info);
+
+ if (info.state != FLOW_DEALLOCATED) {
+ printf("Flow not deallocated.\n");
+ goto fail;
+ }
+
+ reg_destroy_flow(info.id);
+
+ reg_fini();
+
+ TEST_SUCCESS();
+
+ return TEST_RC_SUCCESS;
+ fail:
+ REG_TEST_FAIL();
+ return TEST_RC_FAIL;
+}
+
static int test_reg_flow(void) {
int rc = 0;
@@ -476,6 +679,7 @@ static int test_reg_flow(void) {
rc |= test_reg_accept_flow_success();
rc |= test_reg_accept_flow_success_no_crypt();
rc |= test_reg_allocate_flow_fail();
+ rc |= test_reg_direct_flow_success();
return rc;
}
@@ -500,7 +704,7 @@ static int test_reg_create_ipcp(void)
goto fail;
}
- if (reg.n_ipcps != 1) {
+ if (reg.ipcps.len != 1) {
printf("n_ipcps was not updated.\n");
goto fail;
}
@@ -515,8 +719,8 @@ static int test_reg_create_ipcp(void)
goto fail;
}
- if (reg.n_ipcps != 0) {
- printf("n_ipcps was not updated.\n");
+ if (reg.ipcps.len != 0) {
+ printf("ipcps.len was not updated.\n");
goto fail;
}
@@ -744,7 +948,7 @@ static int test_reg_create_name(void)
goto fail;
}
- if (reg.n_names != 1) {
+ if (reg.names.len != 1) {
printf("n_names was not updated.\n");
goto fail;
}
@@ -759,7 +963,7 @@ static int test_reg_create_name(void)
goto fail;
}
- if (reg.n_names != 0) {
+ if (!llist_is_empty(&reg.names)) {
printf("n_names was not updated.\n");
goto fail;
}
@@ -843,10 +1047,7 @@ static int test_reg_name(void)
static int test_reg_create_proc(void)
{
- struct proc_info info = {
- .pid = TEST_PID,
- .prog = TEST_PROG
- };
+ struct proc_info info = TEST_PROC_INFO;
TEST_START();
@@ -860,7 +1061,7 @@ static int test_reg_create_proc(void)
goto fail;
}
- if (reg.n_procs != 1) {
+ if (reg.procs.len != 1) {
printf("n_procs was not updated.\n");
goto fail;
}
@@ -875,7 +1076,7 @@ static int test_reg_create_proc(void)
goto fail;
}
- if (reg.n_procs != 0) {
+ if (!llist_is_empty(&reg.procs)) {
printf("n_procs was not updated.\n");
goto fail;
}
@@ -913,7 +1114,7 @@ static int test_reg_spawned(void)
goto fail;
}
- if (reg.n_spawned != 1) {
+ if (reg.spawned.len != 1) {
printf("n_spawned was not updated.\n");
goto fail;
}
@@ -928,7 +1129,7 @@ static int test_reg_spawned(void)
goto fail;
}
- if (reg.n_spawned != 0) {
+ if (!llist_is_empty(&reg.spawned)) {
printf("n_spawned was not updated.\n");
goto fail;
}
@@ -961,7 +1162,7 @@ static int test_reg_create_prog(void)
goto fail;
}
- if (reg.n_progs != 1) {
+ if (reg.progs.len != 1) {
printf("n_progs was not updated.\n");
goto fail;
}
@@ -976,7 +1177,7 @@ static int test_reg_create_prog(void)
goto fail;
}
- if (reg.n_progs != 0) {
+ if (!llist_is_empty(&reg.progs)) {
printf("n_progs was not updated.\n");
goto fail;
}
@@ -1002,10 +1203,7 @@ static int test_reg_prog(void)
static int test_bind_proc(void)
{
- struct proc_info pinfo = {
- .pid = TEST_PID,
- .prog = TEST_PROG
- };
+ struct proc_info pinfo = TEST_PROC_INFO;
struct name_info ninfo = {
.name = TEST_NAME,
@@ -1158,10 +1356,7 @@ static int test_inherit_prog(void)
.name = TEST_PROG
};
- struct proc_info procinfo = {
- .pid = TEST_PID,
- .prog = TEST_PROG
- };
+ struct proc_info procinfo = TEST_PROC_INFO;
char * exec[] = { TEST_PROG, NULL};
@@ -1296,13 +1491,10 @@ static int test_wait_accepting_fail_name(void)
static void * test_call_flow_accept(void * o)
{
struct timespec abstime;
- struct timespec timeo = TIMESPEC_INIT_MS(1);
+ struct timespec timeo = TIMESPEC_INIT_MS(10);
buffer_t pbuf = BUF_INIT;
- struct proc_info pinfo = {
- .pid = TEST_PID,
- .prog = TEST_PROG
- };
+ struct proc_info pinfo = TEST_PROC_INFO;
struct flow_info info = {
.n_pid = pinfo.pid,
@@ -1326,16 +1518,21 @@ static void * test_call_flow_accept(void * o)
info.state = FLOW_ACCEPT_PENDING;
+ reg_prepare_flow_accept(&info);
+
clock_gettime(PTHREAD_COND_CLOCK, &abstime);
ts_add(&abstime, &timeo, &abstime);
- reg_prepare_flow_accept(&info);
-
if (reg_wait_flow_accepted(&info, &pbuf, &abstime) != -ETIMEDOUT) {
printf("Wait allocated did not timeout.\n");
goto fail;
}
+ if (reg_unbind_proc((char *) o, pinfo.pid) < 0) {
+ printf("Failed to unbind proc.\n");
+ goto fail;
+ }
+
reg_destroy_flow(info.id);
reg_destroy_proc(pinfo.pid);
@@ -1347,7 +1544,7 @@ static void * test_call_flow_accept(void * o)
static int test_wait_accepting_success(void)
{
struct timespec abstime;
- struct timespec timeo = TIMESPEC_INIT_S(1);
+ struct timespec timeo = TIMESPEC_INIT_S(10);
pthread_t thr;
int flow_id;
struct name_info ninfo = {
@@ -1375,7 +1572,10 @@ static int test_wait_accepting_success(void)
flow_id = reg_wait_flow_accepting(ninfo.name, &abstime);
if (flow_id < 0) {
- printf("Wait accept did not return a flow id: %d.", flow_id);
+ printf("Wait accept did not return a flow id: %d.\n", flow_id);
+ pthread_join(thr, NULL);
+ reg_destroy_name(TEST_NAME);
+ reg_fini();
goto fail;
}
@@ -1461,7 +1661,7 @@ static void * test_ipcp_respond(void * o)
static int test_wait_ipcp_boot_fail(void)
{
struct timespec abstime;
- struct timespec timeo = TIMESPEC_INIT_S(1);
+ struct timespec timeo = TIMESPEC_INIT_S(10);
pthread_t thr;
struct ipcp_info info = {
.name = TEST_IPCP,
@@ -1471,7 +1671,7 @@ static int test_wait_ipcp_boot_fail(void)
struct ipcp_info resp_info = {
.name = TEST_IPCP,
.pid = TEST_PID,
- .state = IPCP_INIT
+ .state = IPCP_NULL
};
TEST_START();
@@ -1495,6 +1695,9 @@ static int test_wait_ipcp_boot_fail(void)
if (reg_wait_ipcp_boot(&info, &abstime) == 0) {
printf("IPCP boot reported success.\n");
+ pthread_join(thr, NULL);
+ reg_destroy_proc(info.pid);
+ reg_fini();
goto fail;
}
@@ -1505,8 +1708,8 @@ static int test_wait_ipcp_boot_fail(void)
goto fail;
}
- if (reg.n_ipcps != 0) {
- printf("n_ipcps was not updated.\n");
+ if (!llist_is_empty(&reg.ipcps)) {
+ printf("ipcps.len was not updated.\n");
goto fail;
}
@@ -1524,7 +1727,7 @@ static int test_wait_ipcp_boot_success(void)
{
pthread_t thr;
struct timespec abstime;
- struct timespec timeo = TIMESPEC_INIT_S(1);
+ struct timespec timeo = TIMESPEC_INIT_S(10);
struct ipcp_info info = {
.name = TEST_IPCP,
.pid = TEST_PID,
@@ -1557,6 +1760,9 @@ static int test_wait_ipcp_boot_success(void)
if (reg_wait_ipcp_boot(&info, &abstime) < 0) {
printf("IPCP boot failed.\n");
+ pthread_join(thr, NULL);
+ reg_destroy_proc(info.pid);
+ reg_fini();
goto fail;
}
@@ -1564,6 +1770,8 @@ static int test_wait_ipcp_boot_success(void)
if (info.state != IPCP_OPERATIONAL) {
printf("IPCP boot succeeded in non-operational state.\n");
+ reg_destroy_proc(info.pid);
+ reg_fini();
goto fail;
}
@@ -1636,12 +1844,9 @@ static void * test_proc(void * o)
static int test_wait_proc_success(void)
{
struct timespec abstime;
- struct timespec timeo = TIMESPEC_INIT_S(1);
+ struct timespec timeo = TIMESPEC_INIT_S(10);
pthread_t thr;
- struct proc_info info = {
- .pid = TEST_PID,
- .prog = TEST_PROG
- };
+ struct proc_info info = TEST_PROC_INFO;
TEST_START();
@@ -1657,6 +1862,9 @@ static int test_wait_proc_success(void)
if (reg_wait_proc(info.pid, &abstime) < 0) {
printf("Waiting for proc failed.\n");
+ pthread_join(thr, NULL);
+ reg_destroy_proc(info.pid);
+ reg_fini();
goto fail;
}