diff options
Diffstat (limited to 'src/irmd/reg')
| -rw-r--r-- | src/irmd/reg/CMakeLists.txt | 9 | ||||
| -rw-r--r-- | src/irmd/reg/flow.c | 54 | ||||
| -rw-r--r-- | src/irmd/reg/flow.h | 22 | ||||
| -rw-r--r-- | src/irmd/reg/ipcp.c | 3 | ||||
| -rw-r--r-- | src/irmd/reg/ipcp.h | 2 | ||||
| -rw-r--r-- | src/irmd/reg/name.c | 63 | ||||
| -rw-r--r-- | src/irmd/reg/name.h | 17 | ||||
| -rw-r--r-- | src/irmd/reg/pool.c | 97 | ||||
| -rw-r--r-- | src/irmd/reg/pool.h | 48 | ||||
| -rw-r--r-- | src/irmd/reg/proc.c | 38 | ||||
| -rw-r--r-- | src/irmd/reg/proc.h | 11 | ||||
| -rw-r--r-- | src/irmd/reg/prog.c | 24 | ||||
| -rw-r--r-- | src/irmd/reg/prog.h | 5 | ||||
| -rw-r--r-- | src/irmd/reg/reg.c | 542 | ||||
| -rw-r--r-- | src/irmd/reg/reg.h | 24 | ||||
| -rw-r--r-- | src/irmd/reg/tests/CMakeLists.txt | 38 | ||||
| -rw-r--r-- | src/irmd/reg/tests/flow_test.c | 59 | ||||
| -rw-r--r-- | src/irmd/reg/tests/ipcp_test.c | 4 | ||||
| -rw-r--r-- | src/irmd/reg/tests/name_test.c | 12 | ||||
| -rw-r--r-- | src/irmd/reg/tests/proc_test.c | 25 | ||||
| -rw-r--r-- | src/irmd/reg/tests/prog_test.c | 8 | ||||
| -rw-r--r-- | src/irmd/reg/tests/reg_test.c | 306 |
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, ®.flows) { + llist_for_each(p, ®.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, ®.flows) { + llist_for_each(p, ®.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, ®.flows) { + llist_for_each(p, ®.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, ®.ipcps) { + llist_for_each(p, ®.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, ®.ipcps) { + llist_for_each(p, ®.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, ®.ipcps) { + llist_for_each(p, ®.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, ®.names) { + llist_for_each(p, ®.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, ®.names) { + llist_for_each(p, ®.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, ®.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, ®.procs) { + llist_for_each(p, ®.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, ®.procs) { + llist_for_each(p, ®.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, ®.procs) { + llist_for_each(p, ®.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, ®.procs) { + llist_for_each(p, ®.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, ®.flows) { + llist_for_each(p, ®.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, ®.spawned) { + llist_for_each(p, ®.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, ®.spawned) { + llist_for_each(p, ®.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, ®.spawned) { + llist_for_each(p, ®.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(®.spawned)) + if (llist_is_empty(®.spawned)) return -1; - return list_first_entry(®.spawned, struct pid_entry, next)->pid; + return llist_first_entry(®.spawned, struct pid_entry, next)->pid; } static struct reg_prog * __reg_get_prog(const char * name) { struct list_head * p; - list_for_each(p, ®.progs) { + llist_for_each(p, ®.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, ®.names) { + llist_for_each(p, ®.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, ®.progs) { + llist_for_each(p, ®.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, ®.procs) { + llist_for_each(p, ®.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, ®.progs) { + llist_for_each(p, ®.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, ®.names) { + llist_for_each(p, ®.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, ®.names) { + llist_for_each(p, ®.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, ®.names) { + llist_for_each(p, ®.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, ®.names) { + llist_for_each(p, ®.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, ®.names) { + llist_for_each(p, ®.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(®.flows); - list_head_init(®.ipcps); - list_head_init(®.names); - list_head_init(®.procs); - list_head_init(®.progs); - list_head_init(®.spawned); + llist_init(®.flows); + llist_init(®.ipcps); + llist_init(®.names); + llist_init(®.pools); + llist_init(®.procs); + llist_init(®.progs); + llist_init(®.spawned); return 0; @@ -563,54 +569,56 @@ void reg_clear(void) pthread_mutex_lock(®.mtx); - list_for_each_safe(p, h, ®.spawned) { + llist_for_each_safe(p, h, ®.spawned) { struct pid_entry * entry; entry = list_entry(p, struct pid_entry, next); - list_del(&entry->next); + llist_del(&entry->next, ®.spawned); free(entry); - reg.n_spawned--; } - list_for_each_safe(p, h, ®.progs) { + llist_for_each_safe(p, h, ®.progs) { struct reg_prog * entry; entry = list_entry(p, struct reg_prog, next); - list_del(&entry->next); + llist_del(&entry->next, ®.progs); __reg_del_prog_from_names(entry->info.path); reg_prog_destroy(entry); - reg.n_progs--; } - list_for_each_safe(p, h, ®.procs) { + llist_for_each_safe(p, h, ®.procs) { struct reg_proc * entry; entry = list_entry(p, struct reg_proc, next); - list_del(&entry->next); + llist_del(&entry->next, ®.procs); __reg_del_proc_from_names(entry->info.pid); reg_proc_destroy(entry); - reg.n_procs--; } - list_for_each_safe(p, h, ®.flows) { + llist_for_each_safe(p, h, ®.pools) { + struct reg_pool * entry; + entry = list_entry(p, struct reg_pool, next); + llist_del(&entry->next, ®.pools); + entry->refcount = 0; /* Force destroy during cleanup */ + reg_pool_destroy(entry); + } + + llist_for_each_safe(p, h, ®.flows) { struct reg_flow * entry; entry = list_entry(p, struct reg_flow, next); - list_del(&entry->next); + llist_del(&entry->next, ®.flows); reg_flow_destroy(entry); - reg.n_flows--; } - list_for_each_safe(p, h, ®.names) { + llist_for_each_safe(p, h, ®.names) { struct reg_name * entry; entry = list_entry(p, struct reg_name, next); - list_del(&entry->next); + llist_del(&entry->next, ®.names); reg_name_destroy(entry); - reg.n_names--; } - list_for_each_safe(p, h, ®.ipcps) { + llist_for_each_safe(p, h, ®.ipcps) { struct reg_ipcp * entry; entry = list_entry(p, struct reg_ipcp, next); - list_del(&entry->next); + llist_del(&entry->next, ®.ipcps); reg_ipcp_destroy(entry); - reg.n_ipcps--; } pthread_mutex_unlock(®.mtx); @@ -618,21 +626,15 @@ void reg_clear(void) void reg_fini(void) { - assert(list_is_empty(®.spawned)); - assert(list_is_empty(®.progs)); - assert(list_is_empty(®.procs)); - assert(list_is_empty(®.names)); - assert(list_is_empty(®.ipcps)); - assert(list_is_empty(®.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(®.spawned)); + assert(llist_is_empty(®.progs)); + assert(llist_is_empty(®.procs)); + assert(llist_is_empty(®.pools)); + assert(llist_is_empty(®.names)); + assert(llist_is_empty(®.ipcps)); + assert(llist_is_empty(®.flows)); - bmp_destroy(reg.flow_ids); + bmp_destroy(reg.ids); if (pthread_cond_destroy(®.cond) != 0) log_warn("Failed to destroy condvar."); @@ -652,8 +654,8 @@ int reg_create_flow(struct flow_info * info) pthread_mutex_lock(®.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), ®.flows); pthread_mutex_unlock(®.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(®.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, ®.flows); - bmp_release(reg.flow_ids, flow_id); + bmp_release(reg.ids, flow_id); pthread_mutex_unlock(®.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), ®.ipcps); + llist_add_at(&entry->next, + __reg_after_spawned(info->pid), + ®.spawned); pthread_mutex_unlock(®.mtx); @@ -849,16 +846,16 @@ int reg_list_ipcps(ipcp_list_msg_t *** ipcps) pthread_mutex_lock(®.mtx); - if (reg.n_ipcps == 0) + if (llist_is_empty(®.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, ®.ipcps) { + llist_for_each(p, ®.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), ®.names); pthread_mutex_unlock(®.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, ®.names); pthread_mutex_unlock(®.mtx); @@ -1004,7 +997,7 @@ int reg_get_name_for_hash(char * buf, pthread_mutex_lock(®.mtx); - list_for_each(p, ®.names) { + llist_for_each(p, ®.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(®.mtx); - if (reg.n_names == 0) + if (llist_is_empty(®.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, ®.names) { + llist_for_each(p, ®.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(®.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(®.mtx); + return -1; + } + llist_add(&pool->next, ®.pools); + } + + reg_pool_ref(pool); + + pthread_mutex_unlock(®.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), ®.procs); pthread_cond_broadcast(®.cond); @@ -1121,7 +1140,7 @@ int reg_create_proc(const struct proc_info * info) return 0; - fail_proc: + fail: pthread_mutex_unlock(®.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, ®.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, ®.pools); + reg_pool_destroy(pool); + } } spawn = __reg_get_spawned(pid); if (spawn != NULL) { - list_del(&spawn->next); - reg.n_spawned--; + llist_del(&spawn->next, ®.spawned); free(spawn); } ipcp = __reg_get_ipcp(pid); if (ipcp != NULL) { - list_del(&ipcp->next); - reg.n_ipcps--; + llist_del(&ipcp->next, ®.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(®.mtx); + + proc = __reg_get_proc(pid); + if (proc != NULL) + ret = reg_proc_is_privileged(proc); + + pthread_mutex_unlock(®.mtx); + + return ret; +} + +uid_t reg_get_proc_uid(pid_t pid) +{ + struct reg_proc * proc; + uid_t ret = 0; + + pthread_mutex_lock(®.mtx); + + proc = __reg_get_proc(pid); + if (proc != NULL && !is_ouroboros_member_uid(proc->info.uid)) + ret = proc->info.uid; + + pthread_mutex_unlock(®.mtx); + + return ret; +} + void reg_kill_all_proc(int signal) { pthread_mutex_lock(®.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), ®.spawned); pthread_mutex_unlock(®.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), ®.progs); exists: pthread_mutex_unlock(®.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, ®.progs); pthread_mutex_unlock(®.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(®.cond); @@ -1816,6 +1868,8 @@ int reg_prepare_flow_accept(struct flow_info * info) ret = reg_flow_update(flow, info); + pthread_cond_broadcast(®.cond); + pthread_mutex_unlock(®.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(®.cond); + + pthread_mutex_unlock(®.mtx); + + return 0; + + fail_flow: + pthread_mutex_unlock(®.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(®.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(®.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(®.mtx); + + flow = __reg_get_flow(flow_id); + + ret = flow != NULL && flow->direct; + + pthread_mutex_unlock(®.mtx); + + return ret; +} + +int reg_respond_flow_direct(int flow_id, + buffer_t * pbuf) +{ + struct reg_flow * flow; + + assert(pbuf != NULL); + + pthread_mutex_lock(®.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(®.cond); + + pthread_mutex_unlock(®.mtx); + + return 0; + fail: + pthread_mutex_unlock(®.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(®.mtx); + + flow = __reg_get_flow(flow_id); + if (flow == NULL) + goto fail; + + assert(flow->direct); + + pthread_cleanup_push(__cleanup_mutex_unlock, ®.mtx); + + while (flow != NULL && flow->rsp_data.data == NULL) { + ret = -__timedwait(®.cond, ®.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(®.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(®.mtx); + return; + } + flow->info.state = FLOW_DEALLOCATED; + info->state = FLOW_DEALLOCATED; + reg_flow_update(flow, info); + pthread_mutex_unlock(®.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(®, 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(®.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(®.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(®.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(®.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(®.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(®.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(®.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; } |
