diff --git a/doc/json_configuration.md b/doc/json_configuration.md
index 9aa1bc8..dcb0023 100644
--- a/doc/json_configuration.md
+++ b/doc/json_configuration.md
@@ -239,7 +239,7 @@ Each event is composed of the following elements, all of which are optional exce
* `label` -- The name by which the event is identified. See the definition of `label` in the ABNF grammar below for permissible values.
-* `priority` -- The priority of routes that have this event as their `parent-event` (see `routes` below). Lower number means higher priority.
+* `priority` -- The priority of routes that have this event as their `parent-event` (see `routes` below). Lower number means higher priority. If omitted, the priority is 0, the highest priority.
* `config` -- The configuration to associate with routes with this `parent-event`, as above for `config-update`.
diff --git a/src/actions.c b/src/actions.c
index 755c80e..21ae8e0 100644
--- a/src/actions.c
+++ b/src/actions.c
@@ -143,12 +143,12 @@ WOLFSENTRY_LOCAL wolfsentry_errcode_t wolfsentry_action_insert_1(
goto out;
if ((ret = wolfsentry_id_allocate(WOLFSENTRY_CONTEXT_ARGS_OUT, &new->header)) < 0)
goto out;
- if (id)
- *id = new->header.id;
if ((ret = wolfsentry_table_ent_insert(WOLFSENTRY_CONTEXT_ARGS_OUT, &new->header, &wolfsentry->actions->header, 1 /* unique_p */)) < 0) {
ret = WOLFSENTRY_ERROR_RECODE(ret);
goto out;
}
+ if (id != NULL)
+ *id = new->header.id;
ret = WOLFSENTRY_ERROR_ENCODE(OK);
out:
diff --git a/src/events.c b/src/events.c
index 6d92a88..1c4c276 100644
--- a/src/events.c
+++ b/src/events.c
@@ -77,6 +77,37 @@ static wolfsentry_errcode_t wolfsentry_event_init_1(const char *label, int label
WOLFSENTRY_RETURN_OK;
}
+/* callers hold the context lock, which is what the plain flag write relies on */
+static wolfsentry_errcode_t wolfsentry_event_aux_owner_add(struct wolfsentry_event *aux_event) {
+ wolfsentry_refcount_t owners;
+
+ WOLFSENTRY_ATOMIC_INCREMENT_UNSIGNED_SAFELY_BY_ONE(aux_event->aux_owner_count, owners);
+ if (owners == 0)
+ WOLFSENTRY_ERROR_RETURN(OVERFLOW_AVERTED);
+ if (! WOLFSENTRY_CHECK_BITS(aux_event->flags, WOLFSENTRY_EVENT_FLAG_IS_SUBEVENT))
+ WOLFSENTRY_SET_BITS(aux_event->flags, WOLFSENTRY_EVENT_FLAG_IS_SUBEVENT);
+ WOLFSENTRY_RETURN_OK;
+}
+
+/* may run without the context lock when a deleted owner is finally freed, so only the atomic count changes here; the mark is resynced under the lock */
+static wolfsentry_errcode_t wolfsentry_event_aux_owner_remove(struct wolfsentry_event *aux_event) {
+ wolfsentry_refcount_t owners;
+
+ WOLFSENTRY_ATOMIC_DECREMENT_UNSIGNED_SAFELY_BY_ONE(aux_event->aux_owner_count, owners);
+ if (owners == MAX_UINT_OF(aux_event->aux_owner_count))
+ WOLFSENTRY_ERROR_RETURN(INTERNAL_CHECK_FATAL);
+ WOLFSENTRY_RETURN_OK;
+}
+
+static void wolfsentry_event_aux_owner_resync_mark(struct wolfsentry_event *event) {
+ if ((WOLFSENTRY_ATOMIC_LOAD(event->aux_owner_count) == 0) &&
+ WOLFSENTRY_CHECK_BITS(event->flags, WOLFSENTRY_EVENT_FLAG_IS_SUBEVENT))
+ {
+ WOLFSENTRY_CLEAR_BITS(event->flags, WOLFSENTRY_EVENT_FLAG_IS_SUBEVENT);
+ }
+ WOLFSENTRY_RETURN_VOID;
+}
+
static void wolfsentry_event_free(WOLFSENTRY_CONTEXT_ARGS_IN, struct wolfsentry_event *event) {
WOLFSENTRY_WARN_ON_FAILURE(wolfsentry_action_list_delete_all(WOLFSENTRY_CONTEXT_ARGS_OUT, &event->post_action_list));
WOLFSENTRY_WARN_ON_FAILURE(wolfsentry_action_list_delete_all(WOLFSENTRY_CONTEXT_ARGS_OUT, &event->insert_action_list));
@@ -149,6 +180,10 @@ WOLFSENTRY_LOCAL wolfsentry_errcode_t wolfsentry_event_clone_bare(
memcpy(*new_event, src_event, new_size);
WOLFSENTRY_TABLE_ENT_HEADER_RESET(**new_ent);
+ /* no route in a route-free clone can depend on the copied layout */
+ if (WOLFSENTRY_CHECK_BITS(flags, WOLFSENTRY_CLONE_FLAG_NO_ROUTES))
+ WOLFSENTRY_CLEAR_BITS((*new_event)->flags, WOLFSENTRY_EVENT_FLAG_IS_PARENT_EVENT);
+
WOLFSENTRY_LIST_HEADER_RESET((*new_event)->post_action_list.header);
WOLFSENTRY_LIST_HEADER_RESET((*new_event)->insert_action_list.header);
WOLFSENTRY_LIST_HEADER_RESET((*new_event)->match_action_list.header);
@@ -157,6 +192,8 @@ WOLFSENTRY_LOCAL wolfsentry_errcode_t wolfsentry_event_clone_bare(
WOLFSENTRY_LIST_HEADER_RESET((*new_event)->decision_action_list.header);
(*new_event)->aux_event = NULL;
+ (*new_event)->aux_owner_count = 0;
+ WOLFSENTRY_CLEAR_BITS((*new_event)->flags, WOLFSENTRY_EVENT_FLAG_IS_SUBEVENT);
if (src_event->config) {
if (((*new_event)->config = WOLFSENTRY_MALLOC_1(dest_context->hpi.allocator, sizeof *(*new_event)->config)) == NULL) {
@@ -257,6 +294,8 @@ WOLFSENTRY_LOCAL wolfsentry_errcode_t wolfsentry_event_clone_resolve(
}
WOLFSENTRY_REFCOUNT_INCREMENT(new_event->aux_event->header.refcount, ret);
WOLFSENTRY_RERETURN_IF_ERROR(ret);
+ ret = wolfsentry_event_aux_owner_add(new_event->aux_event);
+ WOLFSENTRY_RERETURN_IF_ERROR(ret);
}
WOLFSENTRY_RETURN_OK;
@@ -289,12 +328,12 @@ WOLFSENTRY_API wolfsentry_errcode_t wolfsentry_event_insert(
wolfsentry_event_free(WOLFSENTRY_CONTEXT_ARGS_OUT, new);
WOLFSENTRY_ERROR_UNLOCK_AND_RERETURN(ret);
}
- if (id)
- *id = new->header.id;
if ((ret = wolfsentry_table_ent_insert(WOLFSENTRY_CONTEXT_ARGS_OUT, &new->header, &wolfsentry->events->header, 1 /* unique_p */)) < 0) {
wolfsentry_event_free(WOLFSENTRY_CONTEXT_ARGS_OUT, new);
WOLFSENTRY_ERROR_UNLOCK_AND_RETURN_RECODED(ret);
}
+ if (id)
+ *id = new->header.id;
WOLFSENTRY_ERROR_UNLOCK_AND_RERETURN(ret);
}
@@ -306,7 +345,17 @@ WOLFSENTRY_API const char *wolfsentry_event_get_label(const struct wolfsentry_ev
WOLFSENTRY_API wolfsentry_event_flags_t wolfsentry_event_get_flags(const struct wolfsentry_event *event)
{
- return event ? event->flags : WOLFSENTRY_EVENT_FLAG_NONE;
+ wolfsentry_event_flags_t flags;
+
+ if (event == NULL)
+ return WOLFSENTRY_EVENT_FLAG_NONE;
+ /* an owner freed without the context lock only drops the count, so derive the mark from it */
+ flags = event->flags;
+ if (WOLFSENTRY_ATOMIC_LOAD(event->aux_owner_count) > 0)
+ WOLFSENTRY_SET_BITS(flags, WOLFSENTRY_EVENT_FLAG_IS_SUBEVENT);
+ else
+ WOLFSENTRY_CLEAR_BITS(flags, WOLFSENTRY_EVENT_FLAG_IS_SUBEVENT);
+ return flags;
}
WOLFSENTRY_API const struct wolfsentry_event *wolfsentry_event_get_aux_event(const struct wolfsentry_event *event)
@@ -319,7 +368,7 @@ static wolfsentry_errcode_t wolfsentry_event_get_1(WOLFSENTRY_CONTEXT_ARGS_IN, c
WOLFSENTRY_STACKBUF(
struct wolfsentry_event,
label,
- WOLFSENTRY_MAX_LABEL_BYTES,
+ WOLFSENTRY_MAX_LABEL_BYTES + 1,
target);
struct wolfsentry_event *event_1 = &target.target;
@@ -356,27 +405,56 @@ WOLFSENTRY_API wolfsentry_errcode_t wolfsentry_event_get_config(WOLFSENTRY_CONTE
WOLFSENTRY_ERROR_UNLOCK_AND_RERETURN(ret);
}
+static int wolfsentry_event_has_routes(const struct wolfsentry_context *wolfsentry, const struct wolfsentry_event *event) {
+ const struct wolfsentry_table_ent_header *ent;
+
+ if (WOLFSENTRY_CHECK_BITS(event->flags, WOLFSENTRY_EVENT_FLAG_IS_PARENT_EVENT))
+ return 1;
+ /* an aux event parents the ephemeral routes its owners generate */
+ if (WOLFSENTRY_ATOMIC_LOAD(event->aux_owner_count) != 0)
+ return 1;
+ /* beyond the table's own reference, each live route, deleted or not, holds one */
+ if (WOLFSENTRY_ATOMIC_LOAD(event->header.refcount) > 1)
+ return 1;
+ for (ent = wolfsentry_table_first(&wolfsentry->routes->header); ent != NULL; ent = ent->next) {
+ if (((const struct wolfsentry_route *)ent)->parent_event == event)
+ return 1;
+ }
+ return 0;
+}
+
WOLFSENTRY_API wolfsentry_errcode_t wolfsentry_event_update_config(WOLFSENTRY_CONTEXT_ARGS_IN, const char *label, int label_len, const struct wolfsentry_eventconfig *config) {
struct wolfsentry_event *event;
+ const struct wolfsentry_eventconfig_internal *current_config;
+ struct wolfsentry_eventconfig_internal new_config;
wolfsentry_errcode_t ret;
+ if (config == NULL)
+ WOLFSENTRY_ERROR_RETURN(INVALID_ARG);
+
WOLFSENTRY_MUTEX_OR_RETURN();
ret = wolfsentry_event_get_1(WOLFSENTRY_CONTEXT_ARGS_OUT, label, label_len, &event);
WOLFSENTRY_UNLOCK_AND_RERETURN_IF_ERROR(ret);
+ ret = wolfsentry_eventconfig_load(config, &new_config);
+ WOLFSENTRY_UNLOCK_AND_RERETURN_IF_ERROR(ret);
+
+ current_config = (event->config != NULL) ? event->config : &wolfsentry->config;
+
+ /* existing routes were allocated, and are accessed and freed, using the event's current layout */
+ if (wolfsentry_event_has_routes(wolfsentry, event) &&
+ ((new_config.config.route_private_data_size != current_config->config.route_private_data_size) ||
+ (new_config.config.route_private_data_alignment != current_config->config.route_private_data_alignment)))
+ WOLFSENTRY_ERROR_UNLOCK_AND_RETURN(INCOMPATIBLE_STATE);
+
if (event->config == NULL) {
if ((event->config = (struct wolfsentry_eventconfig_internal *)WOLFSENTRY_MALLOC(sizeof *event->config)) == NULL)
WOLFSENTRY_ERROR_UNLOCK_AND_RETURN(SYS_RESOURCE_FAILED);
- if ((ret = wolfsentry_eventconfig_load(config, event->config)) < 0) {
- WOLFSENTRY_FREE(event->config);
- event->config = NULL;
- }
- WOLFSENTRY_ERROR_UNLOCK_AND_RERETURN(ret);
- } else {
- ret = wolfsentry_eventconfig_load(config, event->config);
- WOLFSENTRY_ERROR_UNLOCK_AND_RERETURN(ret);
}
+ memcpy(event->config, &new_config, sizeof *event->config);
+
+ WOLFSENTRY_UNLOCK_AND_RETURN_OK;
}
WOLFSENTRY_API wolfsentry_errcode_t wolfsentry_event_get_reference(WOLFSENTRY_CONTEXT_ARGS_IN, const char *label, int label_len, struct wolfsentry_event **event) {
@@ -418,6 +496,8 @@ WOLFSENTRY_API wolfsentry_errcode_t wolfsentry_event_drop_reference(WOLFSENTRY_C
if (refs_left > 0)
WOLFSENTRY_RETURN_OK;
if (event->aux_event) {
+ ret = wolfsentry_event_aux_owner_remove(event->aux_event);
+ WOLFSENTRY_RERETURN_IF_ERROR(ret);
ret = wolfsentry_event_drop_reference(WOLFSENTRY_CONTEXT_ARGS_OUT, event->aux_event, NULL);
WOLFSENTRY_RERETURN_IF_ERROR(ret);
event->aux_event = NULL;
@@ -613,45 +693,52 @@ WOLFSENTRY_API wolfsentry_errcode_t wolfsentry_event_set_aux_event(
int aux_event_label_len)
{
wolfsentry_errcode_t ret;
- struct wolfsentry_event *event, *aux_event = NULL;
+ struct wolfsentry_event *event, *aux_event = NULL, *old_aux_event;
WOLFSENTRY_MUTEX_OR_RETURN();
ret = wolfsentry_event_get_reference(WOLFSENTRY_CONTEXT_ARGS_OUT, event_label, event_label_len, &event);
WOLFSENTRY_UNLOCK_AND_RERETURN_IF_ERROR(ret);
- if (WOLFSENTRY_CHECK_BITS(event->flags, WOLFSENTRY_EVENT_FLAG_IS_SUBEVENT)) {
+ /* the owner count is authoritative; a mark left by an owner freed without the lock is cleared here */
+ if (WOLFSENTRY_ATOMIC_LOAD(event->aux_owner_count) != 0) {
ret = WOLFSENTRY_ERROR_ENCODE(INCOMPATIBLE_STATE);
goto out;
}
+ wolfsentry_event_aux_owner_resync_mark(event);
if (aux_event_label) {
ret = wolfsentry_event_get_reference(WOLFSENTRY_CONTEXT_ARGS_OUT, aux_event_label, aux_event_label_len, &aux_event);
if (ret < 0) {
aux_event = NULL;
goto out;
}
- if (WOLFSENTRY_CHECK_BITS(aux_event->flags, WOLFSENTRY_EVENT_FLAG_IS_PARENT_EVENT)) {
+ if ((aux_event == event) ||
+ WOLFSENTRY_CHECK_BITS(aux_event->flags, WOLFSENTRY_EVENT_FLAG_IS_PARENT_EVENT)) {
ret = WOLFSENTRY_ERROR_ENCODE(INCOMPATIBLE_STATE);
goto out;
}
} else
aux_event = NULL;
- if (event->aux_event)
- WOLFSENTRY_WARN_ON_FAILURE(wolfsentry_event_drop_reference(WOLFSENTRY_CONTEXT_ARGS_OUT, event->aux_event, NULL /* action_results */));
+ if (aux_event != NULL) {
+ ret = wolfsentry_event_aux_owner_add(aux_event);
+ if (ret < 0)
+ goto out;
+ }
+
+ old_aux_event = event->aux_event;
event->aux_event = aux_event;
+ if (old_aux_event != NULL) {
+ WOLFSENTRY_WARN_ON_FAILURE(wolfsentry_event_aux_owner_remove(old_aux_event));
+ wolfsentry_event_aux_owner_resync_mark(old_aux_event);
+ WOLFSENTRY_WARN_ON_FAILURE(wolfsentry_event_drop_reference(WOLFSENTRY_CONTEXT_ARGS_OUT, old_aux_event, NULL /* action_results */));
+ }
ret = WOLFSENTRY_ERROR_ENCODE(OK);
out:
WOLFSENTRY_WARN_ON_FAILURE(wolfsentry_event_drop_reference(WOLFSENTRY_CONTEXT_ARGS_OUT, event, NULL /* action_results */));
- if (aux_event) {
- if (ret < 0)
- WOLFSENTRY_WARN_ON_FAILURE(wolfsentry_event_drop_reference(WOLFSENTRY_CONTEXT_ARGS_OUT, aux_event, NULL /* action_results */));
- else {
- if (! WOLFSENTRY_CHECK_BITS(aux_event->flags, WOLFSENTRY_EVENT_FLAG_IS_SUBEVENT))
- WOLFSENTRY_SET_BITS(aux_event->flags, WOLFSENTRY_EVENT_FLAG_IS_SUBEVENT);
- }
- }
+ if ((aux_event != NULL) && (ret < 0))
+ WOLFSENTRY_WARN_ON_FAILURE(wolfsentry_event_drop_reference(WOLFSENTRY_CONTEXT_ARGS_OUT, aux_event, NULL /* action_results */));
WOLFSENTRY_ERROR_UNLOCK_AND_RERETURN(ret);
}
diff --git a/src/json/load_config.c b/src/json/load_config.c
index 732f17a..2246d8c 100644
--- a/src/json/load_config.c
+++ b/src/json/load_config.c
@@ -1100,7 +1100,7 @@ static wolfsentry_errcode_t handle_event_clause(struct wolfsentry_json_process_s
}
if ((jps->cur_depth == 3) && (type == JSON_STRING) && (! strcmp(jps->cur_keyname, "label"))) {
- if (data_size >= sizeof jps->o_u_c.event.label)
+ if (data_size > sizeof jps->o_u_c.event.label)
WOLFSENTRY_ERROR_RETURN(STRING_ARG_TOO_LONG);
memcpy(jps->o_u_c.event.label, data, data_size);
jps->o_u_c.event.label_len = (int)data_size;
diff --git a/src/wolfsentry_internal.h b/src/wolfsentry_internal.h
index 484c591..014be0a 100644
--- a/src/wolfsentry_internal.h
+++ b/src/wolfsentry_internal.h
@@ -340,6 +340,7 @@ struct wolfsentry_event {
* policy for the ephemeral route.
*/
+ wolfsentry_refcount_t aux_owner_count; /* events whose aux_event is this one */
byte label_len;
char label[WOLFSENTRY_FLEXIBLE_ARRAY_SIZE];
diff --git a/tests/unittests.c b/tests/unittests.c
index 7a75686..6d707c3 100644
--- a/tests/unittests.c
+++ b/tests/unittests.c
@@ -3469,6 +3469,1580 @@ static int test_dynamic_rules(void) {
WOLFSENTRY_RETURN_OK;
}
+static int test_event_max_length_label(void) {
+ struct wolfsentry_context *wolfsentry;
+ wolfsentry_ent_id_t id;
+ struct wolfsentry_event *event;
+ struct wolfsentry_eventconfig eventconfig;
+ char label[WOLFSENTRY_MAX_LABEL_BYTES + 1];
+
+ WOLFSENTRY_THREAD_HEADER_CHECKED(WOLFSENTRY_THREAD_FLAG_NONE);
+
+ WOLFSENTRY_EXIT_ON_FAILURE(
+ wolfsentry_init_ex(
+ wolfsentry_build_settings,
+ WOLFSENTRY_CONTEXT_ARGS_OUT_EX(WOLFSENTRY_TEST_HPI),
+ NULL /* default_config */,
+ &wolfsentry,
+ WOLFSENTRY_INIT_FLAG_NONE));
+
+ memset(label, 'm', WOLFSENTRY_MAX_LABEL_BYTES);
+ label[WOLFSENTRY_MAX_LABEL_BYTES] = 0;
+
+ WOLFSENTRY_EXIT_ON_FAILURE(
+ wolfsentry_event_insert(
+ WOLFSENTRY_CONTEXT_ARGS_OUT,
+ label,
+ WOLFSENTRY_LENGTH_NULL_TERMINATED,
+ 10,
+ NULL /* config */,
+ WOLFSENTRY_EVENT_FLAG_NONE,
+ &id));
+
+ WOLFSENTRY_EXIT_ON_FAILURE(
+ wolfsentry_event_get_reference(
+ WOLFSENTRY_CONTEXT_ARGS_OUT,
+ label,
+ WOLFSENTRY_LENGTH_NULL_TERMINATED,
+ &event));
+
+ WOLFSENTRY_EXIT_ON_FALSE(id == wolfsentry_get_object_id(event));
+
+ WOLFSENTRY_EXIT_ON_FAILURE(
+ wolfsentry_event_drop_reference(
+ WOLFSENTRY_CONTEXT_ARGS_OUT,
+ event,
+ NULL /* action_results */));
+
+ WOLFSENTRY_EXIT_ON_FAILURE(
+ wolfsentry_event_get_config(
+ WOLFSENTRY_CONTEXT_ARGS_OUT,
+ label,
+ WOLFSENTRY_MAX_LABEL_BYTES,
+ &eventconfig));
+
+ WOLFSENTRY_EXIT_ON_FAILURE(
+ wolfsentry_event_delete(
+ WOLFSENTRY_CONTEXT_ARGS_OUT,
+ label,
+ WOLFSENTRY_LENGTH_NULL_TERMINATED,
+ NULL /* action_results */));
+
+ WOLFSENTRY_EXIT_UNLESS_EXPECTED_FAILURE(
+ ITEM_NOT_FOUND,
+ wolfsentry_event_get_reference(
+ WOLFSENTRY_CONTEXT_ARGS_OUT,
+ label,
+ WOLFSENTRY_LENGTH_NULL_TERMINATED,
+ &event));
+
+ WOLFSENTRY_EXIT_ON_FAILURE(wolfsentry_shutdown(WOLFSENTRY_CONTEXT_ARGS_OUT_EX(&wolfsentry)));
+
+ WOLFSENTRY_EXIT_ON_FAILURE(WOLFSENTRY_THREAD_TAILER(WOLFSENTRY_THREAD_FLAG_NONE));
+
+ WOLFSENTRY_RETURN_OK;
+}
+
+static int test_event_max_length_label_lookups(void) {
+ struct wolfsentry_context *wolfsentry;
+ wolfsentry_ent_id_t id;
+ struct wolfsentry_action_list_ent *cursor;
+ const char *action_label;
+ int action_label_len;
+ struct wolfsentry_eventconfig eventconfig;
+ int n_actions = 0;
+ char label[WOLFSENTRY_MAX_LABEL_BYTES + 1];
+#ifdef WOLFSENTRY_HAVE_DESIGNATED_INITIALIZERS
+ static const struct wolfsentry_eventconfig config = { .route_private_data_size = PRIVATE_DATA_SIZE, .route_private_data_alignment = PRIVATE_DATA_ALIGNMENT, .max_connection_count = 10 };
+#else
+ static const struct wolfsentry_eventconfig config = { PRIVATE_DATA_SIZE, PRIVATE_DATA_ALIGNMENT, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+#endif
+
+ WOLFSENTRY_THREAD_HEADER_CHECKED(WOLFSENTRY_THREAD_FLAG_NONE);
+
+ WOLFSENTRY_EXIT_ON_FAILURE(
+ wolfsentry_init_ex(
+ wolfsentry_build_settings,
+ WOLFSENTRY_CONTEXT_ARGS_OUT_EX(WOLFSENTRY_TEST_HPI),
+ NULL /* default_config */,
+ &wolfsentry,
+ WOLFSENTRY_INIT_FLAG_NONE));
+
+ memset(label, 'n', WOLFSENTRY_MAX_LABEL_BYTES);
+ label[WOLFSENTRY_MAX_LABEL_BYTES] = 0;
+
+ WOLFSENTRY_EXIT_ON_FAILURE(
+ wolfsentry_action_insert(
+ WOLFSENTRY_CONTEXT_ARGS_OUT,
+ "max-label-action",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED,
+ WOLFSENTRY_ACTION_FLAG_NONE,
+ wolfsentry_action_dummy_callback,
+ NULL /* handler_context */,
+ &id));
+
+ WOLFSENTRY_EXIT_ON_FAILURE(
+ wolfsentry_event_insert(
+ WOLFSENTRY_CONTEXT_ARGS_OUT,
+ label,
+ WOLFSENTRY_LENGTH_NULL_TERMINATED,
+ 10,
+ NULL /* config */,
+ WOLFSENTRY_EVENT_FLAG_NONE,
+ &id));
+
+ WOLFSENTRY_EXIT_ON_FAILURE(
+ wolfsentry_event_update_config(
+ WOLFSENTRY_CONTEXT_ARGS_OUT,
+ label,
+ WOLFSENTRY_LENGTH_NULL_TERMINATED,
+ &config));
+
+ WOLFSENTRY_EXIT_ON_FAILURE(
+ wolfsentry_event_get_config(
+ WOLFSENTRY_CONTEXT_ARGS_OUT,
+ label,
+ WOLFSENTRY_LENGTH_NULL_TERMINATED,
+ &eventconfig));
+
+ WOLFSENTRY_EXIT_ON_FALSE(eventconfig.route_private_data_size == config.route_private_data_size);
+
+ WOLFSENTRY_EXIT_ON_FAILURE(
+ wolfsentry_event_action_append(
+ WOLFSENTRY_CONTEXT_ARGS_OUT,
+ label,
+ WOLFSENTRY_LENGTH_NULL_TERMINATED,
+ WOLFSENTRY_ACTION_TYPE_MATCH,
+ "max-label-action",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED));
+
+ WOLFSENTRY_EXIT_ON_FAILURE(wolfsentry_context_lock_shared(WOLFSENTRY_CONTEXT_ARGS_OUT));
+
+ WOLFSENTRY_EXIT_ON_FAILURE(
+ wolfsentry_event_action_list_start(
+ WOLFSENTRY_CONTEXT_ARGS_OUT,
+ label,
+ WOLFSENTRY_LENGTH_NULL_TERMINATED,
+ WOLFSENTRY_ACTION_TYPE_MATCH,
+ &cursor));
+
+ while (wolfsentry_event_action_list_next(
+ WOLFSENTRY_CONTEXT_ARGS_OUT,
+ &cursor,
+ &action_label,
+ &action_label_len) >= 0) {
+ WOLFSENTRY_EXIT_ON_FALSE(strcmp(action_label, "max-label-action") == 0);
+ ++n_actions;
+ }
+
+ WOLFSENTRY_EXIT_ON_FALSE(n_actions == 1);
+
+ WOLFSENTRY_EXIT_ON_FAILURE(
+ wolfsentry_event_action_list_done(
+ WOLFSENTRY_CONTEXT_ARGS_OUT,
+ &cursor));
+
+ WOLFSENTRY_EXIT_ON_FAILURE(wolfsentry_context_unlock(WOLFSENTRY_CONTEXT_ARGS_OUT));
+
+ WOLFSENTRY_EXIT_ON_FAILURE(
+ wolfsentry_event_action_delete(
+ WOLFSENTRY_CONTEXT_ARGS_OUT,
+ label,
+ WOLFSENTRY_LENGTH_NULL_TERMINATED,
+ WOLFSENTRY_ACTION_TYPE_MATCH,
+ "max-label-action",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED));
+
+ WOLFSENTRY_EXIT_ON_FAILURE(wolfsentry_shutdown(WOLFSENTRY_CONTEXT_ARGS_OUT_EX(&wolfsentry)));
+
+ WOLFSENTRY_EXIT_ON_FAILURE(WOLFSENTRY_THREAD_TAILER(WOLFSENTRY_THREAD_FLAG_NONE));
+
+ WOLFSENTRY_RETURN_OK;
+}
+
+static int test_event_insert_failure_leaves_id_untouched(void) {
+ struct wolfsentry_context *wolfsentry;
+ wolfsentry_ent_id_t id, id_before;
+
+ WOLFSENTRY_THREAD_HEADER_CHECKED(WOLFSENTRY_THREAD_FLAG_NONE);
+
+ WOLFSENTRY_EXIT_ON_FAILURE(
+ wolfsentry_init_ex(
+ wolfsentry_build_settings,
+ WOLFSENTRY_CONTEXT_ARGS_OUT_EX(WOLFSENTRY_TEST_HPI),
+ NULL /* default_config */,
+ &wolfsentry,
+ WOLFSENTRY_INIT_FLAG_NONE));
+
+ WOLFSENTRY_EXIT_ON_FAILURE(
+ wolfsentry_event_insert(
+ WOLFSENTRY_CONTEXT_ARGS_OUT,
+ "id_out_event",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED,
+ 10,
+ NULL /* config */,
+ WOLFSENTRY_EVENT_FLAG_NONE,
+ &id));
+
+ id_before = id;
+
+ WOLFSENTRY_EXIT_UNLESS_EXPECTED_FAILURE(
+ ITEM_ALREADY_PRESENT,
+ wolfsentry_event_insert(
+ WOLFSENTRY_CONTEXT_ARGS_OUT,
+ "id_out_event",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED,
+ 10,
+ NULL /* config */,
+ WOLFSENTRY_EVENT_FLAG_NONE,
+ &id));
+
+ WOLFSENTRY_EXIT_ON_FALSE(id == id_before);
+
+ WOLFSENTRY_EXIT_ON_FAILURE(wolfsentry_shutdown(WOLFSENTRY_CONTEXT_ARGS_OUT_EX(&wolfsentry)));
+
+ WOLFSENTRY_EXIT_ON_FAILURE(WOLFSENTRY_THREAD_TAILER(WOLFSENTRY_THREAD_FLAG_NONE));
+
+ WOLFSENTRY_RETURN_OK;
+}
+
+static int test_event_update_config_null(void) {
+ struct wolfsentry_context *wolfsentry;
+ wolfsentry_ent_id_t id;
+ struct wolfsentry_eventconfig global_eventconfig, eventconfig;
+#ifdef WOLFSENTRY_HAVE_DESIGNATED_INITIALIZERS
+ static const struct wolfsentry_eventconfig config = { .route_private_data_size = PRIVATE_DATA_SIZE, .route_private_data_alignment = PRIVATE_DATA_ALIGNMENT, .max_connection_count = 10 };
+#else
+ static const struct wolfsentry_eventconfig config = { PRIVATE_DATA_SIZE, PRIVATE_DATA_ALIGNMENT, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+#endif
+
+ WOLFSENTRY_THREAD_HEADER_CHECKED(WOLFSENTRY_THREAD_FLAG_NONE);
+
+ WOLFSENTRY_EXIT_ON_FAILURE(
+ wolfsentry_init_ex(
+ wolfsentry_build_settings,
+ WOLFSENTRY_CONTEXT_ARGS_OUT_EX(WOLFSENTRY_TEST_HPI),
+ &config,
+ &wolfsentry,
+ WOLFSENTRY_INIT_FLAG_NONE));
+
+ WOLFSENTRY_EXIT_ON_FAILURE(
+ wolfsentry_event_insert(
+ WOLFSENTRY_CONTEXT_ARGS_OUT,
+ "null_config_event",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED,
+ 10,
+ NULL /* config */,
+ WOLFSENTRY_EVENT_FLAG_NONE,
+ &id));
+
+ WOLFSENTRY_EXIT_ON_FAILURE(
+ wolfsentry_event_get_config(
+ WOLFSENTRY_CONTEXT_ARGS_OUT,
+ "null_config_event",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED,
+ &global_eventconfig));
+
+ WOLFSENTRY_EXIT_UNLESS_EXPECTED_FAILURE(
+ INVALID_ARG,
+ wolfsentry_event_update_config(
+ WOLFSENTRY_CONTEXT_ARGS_OUT,
+ "null_config_event",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED,
+ NULL /* config */));
+
+ WOLFSENTRY_EXIT_ON_FAILURE(
+ wolfsentry_event_get_config(
+ WOLFSENTRY_CONTEXT_ARGS_OUT,
+ "null_config_event",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED,
+ &eventconfig));
+
+ WOLFSENTRY_EXIT_ON_FALSE((eventconfig.route_private_data_size == global_eventconfig.route_private_data_size) &&
+ (eventconfig.route_private_data_alignment == global_eventconfig.route_private_data_alignment) &&
+ (eventconfig.max_connection_count == global_eventconfig.max_connection_count));
+ WOLFSENTRY_EXIT_ON_FALSE(eventconfig.max_connection_count == config.max_connection_count);
+
+ WOLFSENTRY_EXIT_ON_FAILURE(wolfsentry_shutdown(WOLFSENTRY_CONTEXT_ARGS_OUT_EX(&wolfsentry)));
+
+ WOLFSENTRY_EXIT_ON_FAILURE(WOLFSENTRY_THREAD_TAILER(WOLFSENTRY_THREAD_FLAG_NONE));
+
+ WOLFSENTRY_RETURN_OK;
+}
+
+static int test_event_update_config_layout_with_routes(void) {
+ struct wolfsentry_context *wolfsentry, *ctx_clone;
+ wolfsentry_ent_id_t id;
+ wolfsentry_action_res_t action_results;
+ struct wolfsentry_eventconfig eventconfig;
+ wolfsentry_route_flags_t flags = WOLFSENTRY_ROUTE_FLAG_TCPLIKE_PORT_NUMBERS | WOLFSENTRY_ROUTE_FLAG_DIRECTION_IN;
+ struct {
+ struct wolfsentry_sockaddr sa;
+ byte addr_buf[4];
+ } remote, local;
+#ifdef WOLFSENTRY_HAVE_DESIGNATED_INITIALIZERS
+ static const struct wolfsentry_eventconfig config = { .route_private_data_size = PRIVATE_DATA_SIZE, .route_private_data_alignment = PRIVATE_DATA_ALIGNMENT, .max_connection_count = 10 };
+ static const struct wolfsentry_eventconfig config2 = { .route_private_data_size = PRIVATE_DATA_SIZE * 2, .route_private_data_alignment = PRIVATE_DATA_ALIGNMENT * 2, .max_connection_count = 15 };
+ static const struct wolfsentry_eventconfig config2_more_connections = { .route_private_data_size = PRIVATE_DATA_SIZE * 2, .route_private_data_alignment = PRIVATE_DATA_ALIGNMENT * 2, .max_connection_count = 20 };
+#else
+ static const struct wolfsentry_eventconfig config = { PRIVATE_DATA_SIZE, PRIVATE_DATA_ALIGNMENT, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+ static const struct wolfsentry_eventconfig config2 = { PRIVATE_DATA_SIZE * 2, PRIVATE_DATA_ALIGNMENT * 2, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+ static const struct wolfsentry_eventconfig config2_more_connections = { PRIVATE_DATA_SIZE * 2, PRIVATE_DATA_ALIGNMENT * 2, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+#endif
+
+ WOLFSENTRY_THREAD_HEADER_CHECKED(WOLFSENTRY_THREAD_FLAG_NONE);
+
+ WOLFSENTRY_EXIT_ON_FAILURE(
+ wolfsentry_init_ex(
+ wolfsentry_build_settings,
+ WOLFSENTRY_CONTEXT_ARGS_OUT_EX(WOLFSENTRY_TEST_HPI),
+ &config,
+ &wolfsentry,
+ WOLFSENTRY_INIT_FLAG_NONE));
+
+ remote.sa.sa_family = local.sa.sa_family = AF_INET;
+ remote.sa.sa_proto = local.sa.sa_proto = IPPROTO_TCP;
+ remote.sa.sa_port = 12345;
+ local.sa.sa_port = 443;
+ remote.sa.addr_len = local.sa.addr_len = sizeof remote.addr_buf * BITS_PER_BYTE;
+ remote.sa.interface = local.sa.interface = 1;
+ memcpy(remote.sa.addr, "\0\1\2\3", sizeof remote.addr_buf);
+ memcpy(local.sa.addr, "\377\376\375\374", sizeof local.addr_buf);
+
+ WOLFSENTRY_EXIT_ON_FAILURE(
+ wolfsentry_event_insert(
+ WOLFSENTRY_CONTEXT_ARGS_OUT,
+ "owns_routes",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED,
+ 10,
+ &config2,
+ WOLFSENTRY_EVENT_FLAG_NONE,
+ &id));
+
+ WOLFSENTRY_EXIT_ON_FAILURE(
+ wolfsentry_event_insert(
+ WOLFSENTRY_CONTEXT_ARGS_OUT,
+ "owns_routes_inherited",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED,
+ 10,
+ NULL /* config */,
+ WOLFSENTRY_EVENT_FLAG_NONE,
+ &id));
+
+ WOLFSENTRY_EXIT_ON_FAILURE(
+ wolfsentry_event_insert(
+ WOLFSENTRY_CONTEXT_ARGS_OUT,
+ "owns_no_routes",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED,
+ 10,
+ &config2,
+ WOLFSENTRY_EVENT_FLAG_NONE,
+ &id));
+
+ WOLFSENTRY_EXIT_ON_FAILURE(
+ wolfsentry_route_insert(
+ WOLFSENTRY_CONTEXT_ARGS_OUT,
+ NULL /* caller_arg */,
+ &remote.sa,
+ &local.sa,
+ flags,
+ "owns_routes",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED,
+ &id,
+ &action_results));
+
+ memcpy(remote.sa.addr, "\4\5\6\7", sizeof remote.addr_buf);
+
+ WOLFSENTRY_EXIT_ON_FAILURE(
+ wolfsentry_route_insert(
+ WOLFSENTRY_CONTEXT_ARGS_OUT,
+ NULL /* caller_arg */,
+ &remote.sa,
+ &local.sa,
+ flags,
+ "owns_routes_inherited",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED,
+ &id,
+ &action_results));
+
+ WOLFSENTRY_EXIT_UNLESS_EXPECTED_FAILURE(
+ INCOMPATIBLE_STATE,
+ wolfsentry_event_update_config(
+ WOLFSENTRY_CONTEXT_ARGS_OUT,
+ "owns_routes",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED,
+ &config));
+
+ WOLFSENTRY_EXIT_ON_FAILURE(
+ wolfsentry_event_get_config(
+ WOLFSENTRY_CONTEXT_ARGS_OUT,
+ "owns_routes",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED,
+ &eventconfig));
+
+ WOLFSENTRY_EXIT_ON_FALSE((eventconfig.route_private_data_size == config2.route_private_data_size) &&
+ (eventconfig.route_private_data_alignment == config2.route_private_data_alignment) &&
+ (eventconfig.max_connection_count == config2.max_connection_count));
+
+ WOLFSENTRY_EXIT_ON_FAILURE(
+ wolfsentry_event_update_config(
+ WOLFSENTRY_CONTEXT_ARGS_OUT,
+ "owns_routes",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED,
+ &config2_more_connections));
+
+ WOLFSENTRY_EXIT_ON_FAILURE(
+ wolfsentry_event_get_config(
+ WOLFSENTRY_CONTEXT_ARGS_OUT,
+ "owns_routes",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED,
+ &eventconfig));
+
+ WOLFSENTRY_EXIT_ON_FALSE(eventconfig.max_connection_count == config2_more_connections.max_connection_count);
+
+ WOLFSENTRY_EXIT_UNLESS_EXPECTED_FAILURE(
+ INCOMPATIBLE_STATE,
+ wolfsentry_event_update_config(
+ WOLFSENTRY_CONTEXT_ARGS_OUT,
+ "owns_routes_inherited",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED,
+ &config2));
+
+ WOLFSENTRY_EXIT_ON_FAILURE(
+ wolfsentry_event_update_config(
+ WOLFSENTRY_CONTEXT_ARGS_OUT,
+ "owns_routes_inherited",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED,
+ &config));
+
+ WOLFSENTRY_EXIT_ON_FAILURE(
+ wolfsentry_action_insert(
+ WOLFSENTRY_CONTEXT_ARGS_OUT,
+ "layout-insert-action",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED,
+ WOLFSENTRY_ACTION_FLAG_NONE,
+ wolfsentry_action_dummy_callback,
+ NULL /* handler_context */,
+ &id));
+
+ WOLFSENTRY_EXIT_ON_FAILURE(
+ wolfsentry_event_insert(
+ WOLFSENTRY_CONTEXT_ARGS_OUT,
+ "owns_routes_with_insert_action",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED,
+ 10,
+ &config2,
+ WOLFSENTRY_EVENT_FLAG_NONE,
+ &id));
+
+ WOLFSENTRY_EXIT_ON_FAILURE(
+ wolfsentry_event_action_append(
+ WOLFSENTRY_CONTEXT_ARGS_OUT,
+ "owns_routes_with_insert_action",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED,
+ WOLFSENTRY_ACTION_TYPE_INSERT,
+ "layout-insert-action",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED));
+
+ memcpy(remote.sa.addr, "\10\11\12\13", sizeof remote.addr_buf);
+
+ WOLFSENTRY_EXIT_ON_FAILURE(
+ wolfsentry_route_insert(
+ WOLFSENTRY_CONTEXT_ARGS_OUT,
+ NULL /* caller_arg */,
+ &remote.sa,
+ &local.sa,
+ flags,
+ "owns_routes_with_insert_action",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED,
+ &id,
+ &action_results));
+
+ WOLFSENTRY_EXIT_UNLESS_EXPECTED_FAILURE(
+ INCOMPATIBLE_STATE,
+ wolfsentry_event_update_config(
+ WOLFSENTRY_CONTEXT_ARGS_OUT,
+ "owns_routes_with_insert_action",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED,
+ &config));
+
+ WOLFSENTRY_EXIT_ON_FAILURE(
+ wolfsentry_event_update_config(
+ WOLFSENTRY_CONTEXT_ARGS_OUT,
+ "owns_no_routes",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED,
+ &config));
+
+ WOLFSENTRY_EXIT_ON_FAILURE(
+ wolfsentry_event_get_config(
+ WOLFSENTRY_CONTEXT_ARGS_OUT,
+ "owns_no_routes",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED,
+ &eventconfig));
+
+ WOLFSENTRY_EXIT_ON_FALSE((eventconfig.route_private_data_size == config.route_private_data_size) &&
+ (eventconfig.route_private_data_alignment == config.route_private_data_alignment));
+
+ /* a clone without routes has no route using the old layout */
+ WOLFSENTRY_EXIT_ON_FAILURE(wolfsentry_context_clone(WOLFSENTRY_CONTEXT_ARGS_OUT, &ctx_clone, WOLFSENTRY_CLONE_FLAG_NO_ROUTES));
+
+ WOLFSENTRY_EXIT_ON_FAILURE(
+ wolfsentry_event_update_config(
+ WOLFSENTRY_CONTEXT_ARGS_OUT_EX(ctx_clone),
+ "owns_routes",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED,
+ &config));
+
+ WOLFSENTRY_EXIT_ON_FAILURE(wolfsentry_context_free(WOLFSENTRY_CONTEXT_ARGS_OUT_EX(&ctx_clone)));
+
+ WOLFSENTRY_EXIT_ON_FAILURE(wolfsentry_context_clone(WOLFSENTRY_CONTEXT_ARGS_OUT, &ctx_clone, WOLFSENTRY_CLONE_FLAG_NONE));
+
+ WOLFSENTRY_EXIT_UNLESS_EXPECTED_FAILURE(
+ INCOMPATIBLE_STATE,
+ wolfsentry_event_update_config(
+ WOLFSENTRY_CONTEXT_ARGS_OUT_EX(ctx_clone),
+ "owns_routes",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED,
+ &config));
+
+ WOLFSENTRY_EXIT_ON_FAILURE(wolfsentry_context_free(WOLFSENTRY_CONTEXT_ARGS_OUT_EX(&ctx_clone)));
+
+ WOLFSENTRY_EXIT_ON_FAILURE(wolfsentry_shutdown(WOLFSENTRY_CONTEXT_ARGS_OUT_EX(&wolfsentry)));
+
+ WOLFSENTRY_EXIT_ON_FAILURE(WOLFSENTRY_THREAD_TAILER(WOLFSENTRY_THREAD_FLAG_NONE));
+
+ WOLFSENTRY_RETURN_OK;
+}
+
+static int test_event_aux_event_self_reference(void) {
+ struct wolfsentry_context *wolfsentry;
+ wolfsentry_ent_id_t id;
+ struct wolfsentry_event *event;
+
+ WOLFSENTRY_THREAD_HEADER_CHECKED(WOLFSENTRY_THREAD_FLAG_NONE);
+
+ WOLFSENTRY_EXIT_ON_FAILURE(
+ wolfsentry_init_ex(
+ wolfsentry_build_settings,
+ WOLFSENTRY_CONTEXT_ARGS_OUT_EX(WOLFSENTRY_TEST_HPI),
+ NULL /* default_config */,
+ &wolfsentry,
+ WOLFSENTRY_INIT_FLAG_NONE));
+
+ WOLFSENTRY_EXIT_ON_FAILURE(
+ wolfsentry_event_insert(
+ WOLFSENTRY_CONTEXT_ARGS_OUT,
+ "self_aux_event",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED,
+ 10,
+ NULL /* config */,
+ WOLFSENTRY_EVENT_FLAG_NONE,
+ &id));
+
+ WOLFSENTRY_EXIT_UNLESS_EXPECTED_FAILURE(
+ INCOMPATIBLE_STATE,
+ wolfsentry_event_set_aux_event(
+ WOLFSENTRY_CONTEXT_ARGS_OUT,
+ "self_aux_event",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED,
+ "self_aux_event",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED));
+
+ WOLFSENTRY_EXIT_ON_FAILURE(
+ wolfsentry_event_get_reference(
+ WOLFSENTRY_CONTEXT_ARGS_OUT,
+ "self_aux_event",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED,
+ &event));
+
+ WOLFSENTRY_EXIT_ON_TRUE(wolfsentry_event_get_aux_event(event) != NULL);
+ WOLFSENTRY_EXIT_ON_TRUE(WOLFSENTRY_CHECK_BITS(wolfsentry_event_get_flags(event), WOLFSENTRY_EVENT_FLAG_IS_SUBEVENT));
+
+ WOLFSENTRY_EXIT_ON_FAILURE(
+ wolfsentry_event_drop_reference(
+ WOLFSENTRY_CONTEXT_ARGS_OUT,
+ event,
+ NULL /* action_results */));
+
+ WOLFSENTRY_EXIT_ON_FAILURE(
+ wolfsentry_event_delete(
+ WOLFSENTRY_CONTEXT_ARGS_OUT,
+ "self_aux_event",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED,
+ NULL /* action_results */));
+
+ WOLFSENTRY_EXIT_ON_FAILURE(wolfsentry_shutdown(WOLFSENTRY_CONTEXT_ARGS_OUT_EX(&wolfsentry)));
+
+ WOLFSENTRY_EXIT_ON_FAILURE(WOLFSENTRY_THREAD_TAILER(WOLFSENTRY_THREAD_FLAG_NONE));
+
+ WOLFSENTRY_RETURN_OK;
+}
+
+static int test_event_aux_event_reuse_after_clear(void) {
+ struct wolfsentry_context *wolfsentry, *ctx_clone;
+ struct wolfsentry_event *deleted_owner;
+ struct wolfsentry_event *held_aux;
+ wolfsentry_ent_id_t id;
+
+ WOLFSENTRY_THREAD_HEADER_CHECKED(WOLFSENTRY_THREAD_FLAG_NONE);
+
+ WOLFSENTRY_EXIT_ON_FAILURE(
+ wolfsentry_init_ex(
+ wolfsentry_build_settings,
+ WOLFSENTRY_CONTEXT_ARGS_OUT_EX(WOLFSENTRY_TEST_HPI),
+ NULL /* default_config */,
+ &wolfsentry,
+ WOLFSENTRY_INIT_FLAG_NONE));
+
+ WOLFSENTRY_EXIT_ON_FAILURE(
+ wolfsentry_event_insert(
+ WOLFSENTRY_CONTEXT_ARGS_OUT,
+ "aux_a",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED,
+ 10,
+ NULL /* config */,
+ WOLFSENTRY_EVENT_FLAG_NONE,
+ &id));
+
+ WOLFSENTRY_EXIT_ON_FAILURE(
+ wolfsentry_event_insert(
+ WOLFSENTRY_CONTEXT_ARGS_OUT,
+ "aux_b",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED,
+ 10,
+ NULL /* config */,
+ WOLFSENTRY_EVENT_FLAG_NONE,
+ &id));
+
+ WOLFSENTRY_EXIT_ON_FAILURE(
+ wolfsentry_event_insert(
+ WOLFSENTRY_CONTEXT_ARGS_OUT,
+ "aux_c",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED,
+ 10,
+ NULL /* config */,
+ WOLFSENTRY_EVENT_FLAG_NONE,
+ &id));
+
+ WOLFSENTRY_EXIT_ON_FAILURE(
+ wolfsentry_event_insert(
+ WOLFSENTRY_CONTEXT_ARGS_OUT,
+ "aux_d",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED,
+ 10,
+ NULL /* config */,
+ WOLFSENTRY_EVENT_FLAG_NONE,
+ &id));
+
+ /* a -> b, then clear: b is free to own an aux event of its own */
+ WOLFSENTRY_EXIT_ON_FAILURE(
+ wolfsentry_event_set_aux_event(
+ WOLFSENTRY_CONTEXT_ARGS_OUT,
+ "aux_a",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED,
+ "aux_b",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED));
+
+ WOLFSENTRY_EXIT_UNLESS_EXPECTED_FAILURE(
+ INCOMPATIBLE_STATE,
+ wolfsentry_event_set_aux_event(
+ WOLFSENTRY_CONTEXT_ARGS_OUT,
+ "aux_b",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED,
+ "aux_c",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED));
+
+ WOLFSENTRY_EXIT_ON_FAILURE(
+ wolfsentry_event_set_aux_event(
+ WOLFSENTRY_CONTEXT_ARGS_OUT,
+ "aux_a",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED,
+ NULL,
+ 0));
+
+ WOLFSENTRY_EXIT_ON_FAILURE(
+ wolfsentry_event_set_aux_event(
+ WOLFSENTRY_CONTEXT_ARGS_OUT,
+ "aux_b",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED,
+ "aux_c",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED));
+
+ /* c is now an aux event, so it cannot own one */
+ WOLFSENTRY_EXIT_UNLESS_EXPECTED_FAILURE(
+ INCOMPATIBLE_STATE,
+ wolfsentry_event_set_aux_event(
+ WOLFSENTRY_CONTEXT_ARGS_OUT,
+ "aux_c",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED,
+ "aux_d",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED));
+
+ /* replacing a's aux event releases the old one */
+ WOLFSENTRY_EXIT_ON_FAILURE(
+ wolfsentry_event_set_aux_event(
+ WOLFSENTRY_CONTEXT_ARGS_OUT,
+ "aux_a",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED,
+ "aux_c",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED));
+
+ WOLFSENTRY_EXIT_ON_FAILURE(
+ wolfsentry_event_set_aux_event(
+ WOLFSENTRY_CONTEXT_ARGS_OUT,
+ "aux_b",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED,
+ NULL,
+ 0));
+
+ WOLFSENTRY_EXIT_UNLESS_EXPECTED_FAILURE(
+ INCOMPATIBLE_STATE,
+ wolfsentry_event_set_aux_event(
+ WOLFSENTRY_CONTEXT_ARGS_OUT,
+ "aux_c",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED,
+ "aux_d",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED));
+
+ WOLFSENTRY_EXIT_ON_FAILURE(
+ wolfsentry_event_set_aux_event(
+ WOLFSENTRY_CONTEXT_ARGS_OUT,
+ "aux_a",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED,
+ "aux_d",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED));
+
+ WOLFSENTRY_EXIT_ON_FAILURE(
+ wolfsentry_event_set_aux_event(
+ WOLFSENTRY_CONTEXT_ARGS_OUT,
+ "aux_c",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED,
+ "aux_b",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED));
+
+ WOLFSENTRY_EXIT_ON_FAILURE(
+ wolfsentry_event_insert(
+ WOLFSENTRY_CONTEXT_ARGS_OUT,
+ "owner_one",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED,
+ 10,
+ NULL /* config */,
+ WOLFSENTRY_EVENT_FLAG_NONE,
+ &id));
+
+ WOLFSENTRY_EXIT_ON_FAILURE(
+ wolfsentry_event_insert(
+ WOLFSENTRY_CONTEXT_ARGS_OUT,
+ "owner_two",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED,
+ 10,
+ NULL /* config */,
+ WOLFSENTRY_EVENT_FLAG_NONE,
+ &id));
+
+ WOLFSENTRY_EXIT_ON_FAILURE(
+ wolfsentry_event_insert(
+ WOLFSENTRY_CONTEXT_ARGS_OUT,
+ "shared_aux",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED,
+ 10,
+ NULL /* config */,
+ WOLFSENTRY_EVENT_FLAG_NONE,
+ &id));
+
+ WOLFSENTRY_EXIT_ON_FAILURE(
+ wolfsentry_event_insert(
+ WOLFSENTRY_CONTEXT_ARGS_OUT,
+ "other_aux",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED,
+ 10,
+ NULL /* config */,
+ WOLFSENTRY_EVENT_FLAG_NONE,
+ &id));
+
+ WOLFSENTRY_EXIT_ON_FAILURE(
+ wolfsentry_event_set_aux_event(
+ WOLFSENTRY_CONTEXT_ARGS_OUT,
+ "owner_one",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED,
+ "shared_aux",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED));
+
+ WOLFSENTRY_EXIT_ON_FAILURE(
+ wolfsentry_event_set_aux_event(
+ WOLFSENTRY_CONTEXT_ARGS_OUT,
+ "owner_two",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED,
+ "shared_aux",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED));
+
+ /* owner_one is deleted from the table but stays alive, and still owns shared_aux */
+ WOLFSENTRY_EXIT_ON_FAILURE(
+ wolfsentry_event_get_reference(
+ WOLFSENTRY_CONTEXT_ARGS_OUT,
+ "owner_one",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED,
+ &deleted_owner));
+
+ WOLFSENTRY_EXIT_ON_FAILURE(
+ wolfsentry_event_delete(
+ WOLFSENTRY_CONTEXT_ARGS_OUT,
+ "owner_one",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED,
+ NULL /* action_results */));
+
+ WOLFSENTRY_EXIT_ON_FAILURE(
+ wolfsentry_event_set_aux_event(
+ WOLFSENTRY_CONTEXT_ARGS_OUT,
+ "owner_two",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED,
+ NULL,
+ 0));
+
+ WOLFSENTRY_EXIT_UNLESS_EXPECTED_FAILURE(
+ INCOMPATIBLE_STATE,
+ wolfsentry_event_set_aux_event(
+ WOLFSENTRY_CONTEXT_ARGS_OUT,
+ "shared_aux",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED,
+ "other_aux",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED));
+
+ WOLFSENTRY_EXIT_ON_FAILURE(
+ wolfsentry_event_drop_reference(
+ WOLFSENTRY_CONTEXT_ARGS_OUT,
+ deleted_owner,
+ NULL /* action_results */));
+
+ /* freeing the deleted owner released shared_aux, which can now own an aux event */
+ WOLFSENTRY_EXIT_ON_FAILURE(
+ wolfsentry_event_set_aux_event(
+ WOLFSENTRY_CONTEXT_ARGS_OUT,
+ "shared_aux",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED,
+ "other_aux",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED));
+
+ WOLFSENTRY_EXIT_ON_FAILURE(
+ wolfsentry_event_insert(
+ WOLFSENTRY_CONTEXT_ARGS_OUT,
+ "held_aux",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED,
+ 10,
+ NULL /* config */,
+ WOLFSENTRY_EVENT_FLAG_NONE,
+ &id));
+
+ WOLFSENTRY_EXIT_ON_FAILURE(
+ wolfsentry_event_insert(
+ WOLFSENTRY_CONTEXT_ARGS_OUT,
+ "held_target",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED,
+ 10,
+ NULL /* config */,
+ WOLFSENTRY_EVENT_FLAG_NONE,
+ &id));
+
+ /* an ordinary reference on the aux event is not ownership */
+ WOLFSENTRY_EXIT_ON_FAILURE(
+ wolfsentry_event_get_reference(
+ WOLFSENTRY_CONTEXT_ARGS_OUT,
+ "held_aux",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED,
+ &held_aux));
+
+ WOLFSENTRY_EXIT_ON_FAILURE(
+ wolfsentry_event_set_aux_event(
+ WOLFSENTRY_CONTEXT_ARGS_OUT,
+ "owner_two",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED,
+ "held_aux",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED));
+
+ WOLFSENTRY_EXIT_UNLESS_EXPECTED_FAILURE(
+ INCOMPATIBLE_STATE,
+ wolfsentry_event_set_aux_event(
+ WOLFSENTRY_CONTEXT_ARGS_OUT,
+ "held_aux",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED,
+ "held_target",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED));
+
+ WOLFSENTRY_EXIT_ON_FAILURE(
+ wolfsentry_event_set_aux_event(
+ WOLFSENTRY_CONTEXT_ARGS_OUT,
+ "owner_two",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED,
+ NULL,
+ 0));
+
+ WOLFSENTRY_EXIT_ON_FAILURE(
+ wolfsentry_event_set_aux_event(
+ WOLFSENTRY_CONTEXT_ARGS_OUT,
+ "held_aux",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED,
+ "held_target",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED));
+
+ WOLFSENTRY_EXIT_ON_FAILURE(
+ wolfsentry_event_drop_reference(
+ WOLFSENTRY_CONTEXT_ARGS_OUT,
+ held_aux,
+ NULL /* action_results */));
+
+ /* a clone rebuilds the aux ownership graph, independently of the source */
+ WOLFSENTRY_EXIT_ON_FAILURE(wolfsentry_context_clone(WOLFSENTRY_CONTEXT_ARGS_OUT, &ctx_clone, WOLFSENTRY_CLONE_FLAG_NONE));
+
+ WOLFSENTRY_EXIT_UNLESS_EXPECTED_FAILURE(
+ INCOMPATIBLE_STATE,
+ wolfsentry_event_set_aux_event(
+ WOLFSENTRY_CONTEXT_ARGS_OUT_EX(ctx_clone),
+ "aux_b",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED,
+ "owner_two",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED));
+
+ WOLFSENTRY_EXIT_ON_FAILURE(
+ wolfsentry_event_set_aux_event(
+ WOLFSENTRY_CONTEXT_ARGS_OUT_EX(ctx_clone),
+ "aux_c",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED,
+ NULL,
+ 0));
+
+ WOLFSENTRY_EXIT_ON_FAILURE(
+ wolfsentry_event_set_aux_event(
+ WOLFSENTRY_CONTEXT_ARGS_OUT_EX(ctx_clone),
+ "aux_b",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED,
+ "owner_two",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED));
+
+ WOLFSENTRY_EXIT_UNLESS_EXPECTED_FAILURE(
+ INCOMPATIBLE_STATE,
+ wolfsentry_event_set_aux_event(
+ WOLFSENTRY_CONTEXT_ARGS_OUT,
+ "aux_b",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED,
+ "owner_two",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED));
+
+ WOLFSENTRY_EXIT_ON_FAILURE(wolfsentry_context_free(WOLFSENTRY_CONTEXT_ARGS_OUT_EX(&ctx_clone)));
+
+ WOLFSENTRY_EXIT_ON_FAILURE(wolfsentry_shutdown(WOLFSENTRY_CONTEXT_ARGS_OUT_EX(&wolfsentry)));
+
+ WOLFSENTRY_EXIT_ON_FAILURE(WOLFSENTRY_THREAD_TAILER(WOLFSENTRY_THREAD_FLAG_NONE));
+
+ WOLFSENTRY_RETURN_OK;
+}
+
+static int test_event_aux_mark_cleared_on_owner_free(void) {
+ struct wolfsentry_context *wolfsentry;
+ struct wolfsentry_event *aux;
+ wolfsentry_ent_id_t id;
+
+ WOLFSENTRY_THREAD_HEADER_CHECKED(WOLFSENTRY_THREAD_FLAG_NONE);
+
+ WOLFSENTRY_EXIT_ON_FAILURE(
+ wolfsentry_init_ex(
+ wolfsentry_build_settings,
+ WOLFSENTRY_CONTEXT_ARGS_OUT_EX(WOLFSENTRY_TEST_HPI),
+ NULL /* default_config */,
+ &wolfsentry,
+ WOLFSENTRY_INIT_FLAG_NONE));
+
+ WOLFSENTRY_EXIT_ON_FAILURE(wolfsentry_event_insert(WOLFSENTRY_CONTEXT_ARGS_OUT, "mark_owner", WOLFSENTRY_LENGTH_NULL_TERMINATED, 10, NULL /* config */, WOLFSENTRY_EVENT_FLAG_NONE, &id));
+ WOLFSENTRY_EXIT_ON_FAILURE(wolfsentry_event_insert(WOLFSENTRY_CONTEXT_ARGS_OUT, "mark_aux", WOLFSENTRY_LENGTH_NULL_TERMINATED, 10, NULL /* config */, WOLFSENTRY_EVENT_FLAG_NONE, &id));
+ WOLFSENTRY_EXIT_ON_FAILURE(wolfsentry_event_set_aux_event(WOLFSENTRY_CONTEXT_ARGS_OUT, "mark_owner", WOLFSENTRY_LENGTH_NULL_TERMINATED, "mark_aux", WOLFSENTRY_LENGTH_NULL_TERMINATED));
+ WOLFSENTRY_EXIT_ON_FAILURE(wolfsentry_event_get_reference(WOLFSENTRY_CONTEXT_ARGS_OUT, "mark_aux", WOLFSENTRY_LENGTH_NULL_TERMINATED, &aux));
+ WOLFSENTRY_EXIT_ON_FALSE(WOLFSENTRY_CHECK_BITS(wolfsentry_event_get_flags(aux), WOLFSENTRY_EVENT_FLAG_IS_SUBEVENT));
+
+ /* freeing the only owner leaves the aux event with no owners */
+ WOLFSENTRY_EXIT_ON_FAILURE(wolfsentry_event_delete(WOLFSENTRY_CONTEXT_ARGS_OUT, "mark_owner", WOLFSENTRY_LENGTH_NULL_TERMINATED, NULL /* action_results */));
+ WOLFSENTRY_EXIT_ON_TRUE(WOLFSENTRY_CHECK_BITS(wolfsentry_event_get_flags(aux), WOLFSENTRY_EVENT_FLAG_IS_SUBEVENT));
+
+ WOLFSENTRY_EXIT_ON_FAILURE(wolfsentry_event_drop_reference(WOLFSENTRY_CONTEXT_ARGS_OUT, aux, NULL /* action_results */));
+ WOLFSENTRY_EXIT_ON_FAILURE(wolfsentry_shutdown(WOLFSENTRY_CONTEXT_ARGS_OUT_EX(&wolfsentry)));
+ WOLFSENTRY_EXIT_ON_FAILURE(WOLFSENTRY_THREAD_TAILER(WOLFSENTRY_THREAD_FLAG_NONE));
+ WOLFSENTRY_RETURN_OK;
+}
+
+static int test_event_aux_event_rejects_subevent_owner(void) {
+ struct wolfsentry_context *wolfsentry;
+ wolfsentry_ent_id_t id;
+
+ WOLFSENTRY_THREAD_HEADER_CHECKED(WOLFSENTRY_THREAD_FLAG_NONE);
+
+ WOLFSENTRY_EXIT_ON_FAILURE(
+ wolfsentry_init_ex(
+ wolfsentry_build_settings,
+ WOLFSENTRY_CONTEXT_ARGS_OUT_EX(WOLFSENTRY_TEST_HPI),
+ NULL /* default_config */,
+ &wolfsentry,
+ WOLFSENTRY_INIT_FLAG_NONE));
+
+ WOLFSENTRY_EXIT_ON_FAILURE(
+ wolfsentry_event_insert(
+ WOLFSENTRY_CONTEXT_ARGS_OUT,
+ "subevent_a",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED,
+ 10,
+ NULL /* config */,
+ WOLFSENTRY_EVENT_FLAG_NONE,
+ &id));
+
+ WOLFSENTRY_EXIT_ON_FAILURE(
+ wolfsentry_event_insert(
+ WOLFSENTRY_CONTEXT_ARGS_OUT,
+ "subevent_b",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED,
+ 10,
+ NULL /* config */,
+ WOLFSENTRY_EVENT_FLAG_NONE,
+ &id));
+
+ WOLFSENTRY_EXIT_ON_FAILURE(
+ wolfsentry_event_insert(
+ WOLFSENTRY_CONTEXT_ARGS_OUT,
+ "subevent_c",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED,
+ 10,
+ NULL /* config */,
+ WOLFSENTRY_EVENT_FLAG_NONE,
+ &id));
+
+ WOLFSENTRY_EXIT_ON_FAILURE(
+ wolfsentry_event_set_aux_event(
+ WOLFSENTRY_CONTEXT_ARGS_OUT,
+ "subevent_a",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED,
+ "subevent_b",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED));
+
+ WOLFSENTRY_EXIT_UNLESS_EXPECTED_FAILURE(
+ INCOMPATIBLE_STATE,
+ wolfsentry_event_set_aux_event(
+ WOLFSENTRY_CONTEXT_ARGS_OUT,
+ "subevent_b",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED,
+ "subevent_c",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED));
+
+ WOLFSENTRY_EXIT_ON_FAILURE(wolfsentry_shutdown(WOLFSENTRY_CONTEXT_ARGS_OUT_EX(&wolfsentry)));
+
+ WOLFSENTRY_EXIT_ON_FAILURE(WOLFSENTRY_THREAD_TAILER(WOLFSENTRY_THREAD_FLAG_NONE));
+
+ WOLFSENTRY_RETURN_OK;
+}
+
+static int test_event_aux_event_rejects_parent_event(void) {
+ struct wolfsentry_context *wolfsentry;
+ wolfsentry_ent_id_t id;
+ wolfsentry_action_res_t action_results;
+ wolfsentry_route_flags_t flags = WOLFSENTRY_ROUTE_FLAG_TCPLIKE_PORT_NUMBERS | WOLFSENTRY_ROUTE_FLAG_DIRECTION_IN;
+ struct {
+ struct wolfsentry_sockaddr sa;
+ byte addr_buf[4];
+ } remote, local;
+
+ WOLFSENTRY_THREAD_HEADER_CHECKED(WOLFSENTRY_THREAD_FLAG_NONE);
+
+ WOLFSENTRY_EXIT_ON_FAILURE(
+ wolfsentry_init_ex(
+ wolfsentry_build_settings,
+ WOLFSENTRY_CONTEXT_ARGS_OUT_EX(WOLFSENTRY_TEST_HPI),
+ NULL /* default_config */,
+ &wolfsentry,
+ WOLFSENTRY_INIT_FLAG_NONE));
+
+ WOLFSENTRY_EXIT_ON_FAILURE(
+ wolfsentry_event_insert(
+ WOLFSENTRY_CONTEXT_ARGS_OUT,
+ "route_parent",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED,
+ 10,
+ NULL /* config */,
+ WOLFSENTRY_EVENT_FLAG_NONE,
+ &id));
+
+ WOLFSENTRY_EXIT_ON_FAILURE(
+ wolfsentry_event_insert(
+ WOLFSENTRY_CONTEXT_ARGS_OUT,
+ "route_owner",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED,
+ 10,
+ NULL /* config */,
+ WOLFSENTRY_EVENT_FLAG_NONE,
+ &id));
+
+ remote.sa.sa_family = local.sa.sa_family = AF_INET;
+ remote.sa.sa_proto = local.sa.sa_proto = IPPROTO_TCP;
+ remote.sa.sa_port = 12345;
+ local.sa.sa_port = 443;
+ remote.sa.addr_len = local.sa.addr_len = sizeof remote.addr_buf * BITS_PER_BYTE;
+ remote.sa.interface = local.sa.interface = 1;
+ memcpy(remote.sa.addr, "\0\1\2\3", sizeof remote.addr_buf);
+ memcpy(local.sa.addr, "\377\376\375\374", sizeof local.addr_buf);
+
+ WOLFSENTRY_EXIT_ON_FAILURE(
+ wolfsentry_route_insert(
+ WOLFSENTRY_CONTEXT_ARGS_OUT,
+ NULL /* caller_arg */,
+ &remote.sa,
+ &local.sa,
+ flags,
+ "route_parent",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED,
+ &id,
+ &action_results));
+
+ WOLFSENTRY_EXIT_UNLESS_EXPECTED_FAILURE(
+ INCOMPATIBLE_STATE,
+ wolfsentry_event_set_aux_event(
+ WOLFSENTRY_CONTEXT_ARGS_OUT,
+ "route_owner",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED,
+ "route_parent",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED));
+
+ WOLFSENTRY_EXIT_ON_FAILURE(wolfsentry_shutdown(WOLFSENTRY_CONTEXT_ARGS_OUT_EX(&wolfsentry)));
+
+ WOLFSENTRY_EXIT_ON_FAILURE(WOLFSENTRY_THREAD_TAILER(WOLFSENTRY_THREAD_FLAG_NONE));
+
+ WOLFSENTRY_RETURN_OK;
+}
+
+#ifndef WOLFSENTRY_NO_JSON
+
+static int event_priority_check_winner(const char *priority_clause, int expect_accept) {
+ struct wolfsentry_context *wolfsentry;
+ wolfsentry_errcode_t ret;
+ wolfsentry_ent_id_t route_id;
+ wolfsentry_route_flags_t inexact_matches;
+ wolfsentry_action_res_t action_results;
+ char err_buf[512];
+ char json[2048];
+ int json_len;
+ struct {
+ struct wolfsentry_sockaddr sa;
+ byte addr_buf[4];
+ } remote, local;
+
+ WOLFSENTRY_THREAD_HEADER_CHECKED(WOLFSENTRY_THREAD_FLAG_NONE);
+
+ WOLFSENTRY_EXIT_ON_FAILURE(
+ wolfsentry_init_ex(
+ wolfsentry_build_settings,
+ WOLFSENTRY_CONTEXT_ARGS_OUT_EX(WOLFSENTRY_TEST_HPI),
+ NULL /* default_config */,
+ &wolfsentry,
+ WOLFSENTRY_INIT_FLAG_NONE));
+
+ json_len = snprintf(
+ json, sizeof json,
+ "{ \"wolfsentry-config-version\" : 1,"
+ " \"events-insert\" : ["
+ " { \"label\" : \"first-event\" %s },"
+ " { \"label\" : \"second-event\", \"priority\" : 1 } ],"
+ " \"static-routes-insert\" : ["
+ " { \"parent-event\" : \"first-event\", \"direction-in\" : true,"
+ " \"green-listed\" : true, \"penalty-boxed\" : false, \"family\" : %u,"
+ " \"remote\" : { \"address\" : \"10.0.0.0\", \"prefix-bits\" : 8 },"
+ " \"local\" : { \"address\" : \"10.0.0.0\", \"prefix-bits\" : 8 } },"
+ " { \"parent-event\" : \"second-event\", \"direction-in\" : true,"
+ " \"green-listed\" : false, \"penalty-boxed\" : true, \"family\" : %u,"
+ " \"remote\" : { \"address\" : \"10.1.2.3\" },"
+ " \"local\" : { \"address\" : \"10.0.0.0\", \"prefix-bits\" : 8 } } ] }",
+ priority_clause, (unsigned int)AF_INET, (unsigned int)AF_INET);
+ WOLFSENTRY_EXIT_ON_TRUE((json_len < 0) || ((size_t)json_len >= sizeof json));
+
+ ret = wolfsentry_config_json_oneshot(
+ WOLFSENTRY_CONTEXT_ARGS_OUT,
+ (unsigned char *)json,
+ (size_t)json_len,
+ WOLFSENTRY_CONFIG_LOAD_FLAG_NONE,
+ err_buf,
+ sizeof err_buf);
+ if (ret < 0)
+ (void)fprintf(stderr, "%s\n", err_buf);
+ WOLFSENTRY_EXIT_ON_FAILURE(ret);
+
+ memset(&remote, 0, sizeof remote);
+ memset(&local, 0, sizeof local);
+ remote.sa.sa_family = local.sa.sa_family = AF_INET;
+ remote.sa.sa_proto = local.sa.sa_proto = IPPROTO_TCP;
+ remote.sa.sa_port = 12345;
+ local.sa.sa_port = 443;
+ remote.sa.addr_len = local.sa.addr_len = sizeof remote.addr_buf * BITS_PER_BYTE;
+ remote.sa.interface = local.sa.interface = 1;
+ memcpy(remote.sa.addr, "\12\1\2\3", sizeof remote.addr_buf);
+ memcpy(local.sa.addr, "\12\11\11\11", sizeof local.addr_buf);
+
+ WOLFSENTRY_EXIT_ON_FAILURE(
+ wolfsentry_route_event_dispatch(
+ WOLFSENTRY_CONTEXT_ARGS_OUT,
+ &remote.sa,
+ &local.sa,
+ WOLFSENTRY_ROUTE_FLAG_DIRECTION_IN,
+ NULL /* event_label */,
+ 0 /* event_label_len */,
+ NULL /* caller_arg */,
+ &route_id,
+ &inexact_matches,
+ &action_results));
+
+ if (expect_accept) {
+ WOLFSENTRY_EXIT_ON_FALSE(WOLFSENTRY_CHECK_BITS(action_results, WOLFSENTRY_ACTION_RES_ACCEPT));
+ WOLFSENTRY_EXIT_ON_TRUE(WOLFSENTRY_CHECK_BITS(action_results, WOLFSENTRY_ACTION_RES_REJECT));
+ } else {
+ WOLFSENTRY_EXIT_ON_TRUE(WOLFSENTRY_CHECK_BITS(action_results, WOLFSENTRY_ACTION_RES_ACCEPT));
+ WOLFSENTRY_EXIT_ON_FALSE(WOLFSENTRY_CHECK_BITS(action_results, WOLFSENTRY_ACTION_RES_REJECT));
+ }
+
+ WOLFSENTRY_EXIT_ON_FAILURE(wolfsentry_shutdown(WOLFSENTRY_CONTEXT_ARGS_OUT_EX(&wolfsentry)));
+
+ WOLFSENTRY_EXIT_ON_FAILURE(WOLFSENTRY_THREAD_TAILER(WOLFSENTRY_THREAD_FLAG_NONE));
+
+ WOLFSENTRY_RETURN_OK;
+}
+
+static int test_event_default_priority(void) {
+ /* an omitted priority behaves as priority 0, the highest */
+ WOLFSENTRY_EXIT_ON_FAILURE(event_priority_check_winner("", 1));
+ WOLFSENTRY_EXIT_ON_FAILURE(event_priority_check_winner(", \"priority\" : 0", 1));
+ WOLFSENTRY_EXIT_ON_FAILURE(event_priority_check_winner(", \"priority\" : 2", 0));
+
+ WOLFSENTRY_RETURN_OK;
+}
+
+static int test_json_event_max_length_label(void) {
+ struct wolfsentry_context *wolfsentry;
+ wolfsentry_errcode_t ret;
+ struct wolfsentry_eventconfig config;
+ char label[WOLFSENTRY_MAX_LABEL_BYTES + 1];
+ char err_buf[512];
+ char json[WOLFSENTRY_MAX_LABEL_BYTES + 128];
+ int json_len;
+
+ WOLFSENTRY_THREAD_HEADER_CHECKED(WOLFSENTRY_THREAD_FLAG_NONE);
+
+ WOLFSENTRY_EXIT_ON_FAILURE(
+ wolfsentry_init_ex(
+ wolfsentry_build_settings,
+ WOLFSENTRY_CONTEXT_ARGS_OUT_EX(WOLFSENTRY_TEST_HPI),
+ NULL /* default_config */,
+ &wolfsentry,
+ WOLFSENTRY_INIT_FLAG_NONE));
+
+ memset(label, 'L', sizeof label);
+
+ json_len = snprintf(
+ json, sizeof json,
+ "{ \"wolfsentry-config-version\" : 1, \"events-insert\" : [ { \"label\" : \"%.*s\" } ] }",
+ (int)WOLFSENTRY_MAX_LABEL_BYTES, label);
+ WOLFSENTRY_EXIT_ON_TRUE((json_len < 0) || ((size_t)json_len >= sizeof json));
+ ret = wolfsentry_config_json_oneshot(
+ WOLFSENTRY_CONTEXT_ARGS_OUT,
+ (unsigned char *)json,
+ (size_t)json_len,
+ WOLFSENTRY_CONFIG_LOAD_FLAG_NONE,
+ err_buf,
+ sizeof err_buf);
+ if (ret < 0)
+ (void)fprintf(stderr, "%s\n", err_buf);
+ WOLFSENTRY_EXIT_ON_FAILURE(ret);
+ WOLFSENTRY_EXIT_ON_FAILURE(
+ wolfsentry_event_get_config(
+ WOLFSENTRY_CONTEXT_ARGS_OUT,
+ label,
+ (int)WOLFSENTRY_MAX_LABEL_BYTES,
+ &config));
+
+ json_len = snprintf(
+ json, sizeof json,
+ "{ \"wolfsentry-config-version\" : 1, \"events-insert\" : [ { \"label\" : \"%.*s\" } ] }",
+ (int)WOLFSENTRY_MAX_LABEL_BYTES + 1, label);
+ WOLFSENTRY_EXIT_ON_TRUE((json_len < 0) || ((size_t)json_len >= sizeof json));
+ WOLFSENTRY_EXIT_UNLESS_EXPECTED_FAILURE(
+ STRING_ARG_TOO_LONG,
+ wolfsentry_config_json_oneshot(
+ WOLFSENTRY_CONTEXT_ARGS_OUT,
+ (unsigned char *)json,
+ (size_t)json_len,
+ WOLFSENTRY_CONFIG_LOAD_FLAG_NONE,
+ err_buf,
+ sizeof err_buf));
+
+ WOLFSENTRY_EXIT_ON_FAILURE(wolfsentry_shutdown(WOLFSENTRY_CONTEXT_ARGS_OUT_EX(&wolfsentry)));
+
+ WOLFSENTRY_EXIT_ON_FAILURE(WOLFSENTRY_THREAD_TAILER(WOLFSENTRY_THREAD_FLAG_NONE));
+
+ WOLFSENTRY_RETURN_OK;
+}
+
+#endif /* !WOLFSENTRY_NO_JSON */
+
+static wolfsentry_errcode_t test_action_insert_noop(
+ WOLFSENTRY_CONTEXT_ARGS_IN,
+ const struct wolfsentry_action *action,
+ void *handler_arg,
+ void *caller_arg,
+ const struct wolfsentry_event *trigger_event,
+ wolfsentry_action_type_t action_type,
+ const struct wolfsentry_route *target_route,
+ struct wolfsentry_route_table *route_table,
+ struct wolfsentry_route *rule_route,
+ wolfsentry_action_res_t *action_results)
+{
+ WOLFSENTRY_CONTEXT_ARGS_NOT_USED;
+ (void)action;
+ (void)handler_arg;
+ (void)caller_arg;
+ (void)trigger_event;
+ (void)action_type;
+ (void)target_route;
+ (void)route_table;
+ (void)rule_route;
+ (void)action_results;
+ WOLFSENTRY_RETURN_OK;
+}
+
+static int test_action_insert_failure_leaves_id_untouched(void) {
+ struct wolfsentry_context *wolfsentry;
+ wolfsentry_ent_id_t id, id_before;
+
+ WOLFSENTRY_THREAD_HEADER_CHECKED(WOLFSENTRY_THREAD_FLAG_NONE);
+
+ WOLFSENTRY_EXIT_ON_FAILURE(
+ wolfsentry_init_ex(
+ wolfsentry_build_settings,
+ WOLFSENTRY_CONTEXT_ARGS_OUT_EX(WOLFSENTRY_TEST_HPI),
+ NULL /* default_config */,
+ &wolfsentry,
+ WOLFSENTRY_INIT_FLAG_NONE));
+
+ WOLFSENTRY_EXIT_ON_FAILURE(
+ wolfsentry_action_insert(
+ WOLFSENTRY_CONTEXT_ARGS_OUT,
+ "id_out_action",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED,
+ WOLFSENTRY_ACTION_FLAG_NONE,
+ test_action_insert_noop,
+ NULL /* handler_arg */,
+ &id));
+
+ id_before = id;
+
+ WOLFSENTRY_EXIT_UNLESS_EXPECTED_FAILURE(
+ ITEM_ALREADY_PRESENT,
+ wolfsentry_action_insert(
+ WOLFSENTRY_CONTEXT_ARGS_OUT,
+ "id_out_action",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED,
+ WOLFSENTRY_ACTION_FLAG_NONE,
+ test_action_insert_noop,
+ NULL /* handler_arg */,
+ &id));
+
+ WOLFSENTRY_EXIT_ON_FALSE(id == id_before);
+
+ WOLFSENTRY_EXIT_ON_FAILURE(wolfsentry_shutdown(WOLFSENTRY_CONTEXT_ARGS_OUT_EX(&wolfsentry)));
+
+ WOLFSENTRY_EXIT_ON_FAILURE(WOLFSENTRY_THREAD_TAILER(WOLFSENTRY_THREAD_FLAG_NONE));
+
+ WOLFSENTRY_RETURN_OK;
+}
+
+static int test_event_aux_event_layout_pinned(void) {
+ struct wolfsentry_context *wolfsentry;
+ wolfsentry_ent_id_t id;
+#ifdef WOLFSENTRY_HAVE_DESIGNATED_INITIALIZERS
+ static const struct wolfsentry_eventconfig config = { .route_private_data_size = PRIVATE_DATA_SIZE, .route_private_data_alignment = PRIVATE_DATA_ALIGNMENT, .max_connection_count = 10 };
+ static const struct wolfsentry_eventconfig config2 = { .route_private_data_size = PRIVATE_DATA_SIZE * 2, .route_private_data_alignment = PRIVATE_DATA_ALIGNMENT * 2, .max_connection_count = 15 };
+#else
+ static const struct wolfsentry_eventconfig config = { PRIVATE_DATA_SIZE, PRIVATE_DATA_ALIGNMENT, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+ static const struct wolfsentry_eventconfig config2 = { PRIVATE_DATA_SIZE * 2, PRIVATE_DATA_ALIGNMENT * 2, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+#endif
+
+ WOLFSENTRY_THREAD_HEADER_CHECKED(WOLFSENTRY_THREAD_FLAG_NONE);
+
+ WOLFSENTRY_EXIT_ON_FAILURE(
+ wolfsentry_init_ex(
+ wolfsentry_build_settings,
+ WOLFSENTRY_CONTEXT_ARGS_OUT_EX(WOLFSENTRY_TEST_HPI),
+ &config,
+ &wolfsentry,
+ WOLFSENTRY_INIT_FLAG_NONE));
+
+ WOLFSENTRY_EXIT_ON_FAILURE(
+ wolfsentry_event_insert(
+ WOLFSENTRY_CONTEXT_ARGS_OUT,
+ "layout_aux_owner",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED,
+ 10,
+ NULL /* config */,
+ WOLFSENTRY_EVENT_FLAG_NONE,
+ &id));
+
+ WOLFSENTRY_EXIT_ON_FAILURE(
+ wolfsentry_event_insert(
+ WOLFSENTRY_CONTEXT_ARGS_OUT,
+ "layout_aux",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED,
+ 10,
+ &config,
+ WOLFSENTRY_EVENT_FLAG_NONE,
+ &id));
+
+ WOLFSENTRY_EXIT_ON_FAILURE(
+ wolfsentry_event_set_aux_event(
+ WOLFSENTRY_CONTEXT_ARGS_OUT,
+ "layout_aux_owner",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED,
+ "layout_aux",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED));
+
+ WOLFSENTRY_EXIT_UNLESS_EXPECTED_FAILURE(
+ INCOMPATIBLE_STATE,
+ wolfsentry_event_update_config(
+ WOLFSENTRY_CONTEXT_ARGS_OUT,
+ "layout_aux",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED,
+ &config2));
+
+ WOLFSENTRY_EXIT_ON_FAILURE(
+ wolfsentry_event_set_aux_event(
+ WOLFSENTRY_CONTEXT_ARGS_OUT,
+ "layout_aux_owner",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED,
+ NULL /* aux_event_label */,
+ 0));
+
+ WOLFSENTRY_EXIT_ON_FAILURE(
+ wolfsentry_event_update_config(
+ WOLFSENTRY_CONTEXT_ARGS_OUT,
+ "layout_aux",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED,
+ &config2));
+
+ WOLFSENTRY_EXIT_ON_FAILURE(wolfsentry_shutdown(WOLFSENTRY_CONTEXT_ARGS_OUT_EX(&wolfsentry)));
+
+ WOLFSENTRY_EXIT_ON_FAILURE(WOLFSENTRY_THREAD_TAILER(WOLFSENTRY_THREAD_FLAG_NONE));
+
+ WOLFSENTRY_RETURN_OK;
+}
+
+static int test_event_layout_guard_held_deleted_route(void) {
+ struct wolfsentry_context *wolfsentry;
+ wolfsentry_ent_id_t id;
+ wolfsentry_action_res_t action_results;
+ struct wolfsentry_route *route = NULL;
+ wolfsentry_route_flags_t flags = WOLFSENTRY_ROUTE_FLAG_TCPLIKE_PORT_NUMBERS | WOLFSENTRY_ROUTE_FLAG_DIRECTION_IN;
+ struct {
+ struct wolfsentry_sockaddr sa;
+ byte addr_buf[4];
+ } remote, local;
+#ifdef WOLFSENTRY_HAVE_DESIGNATED_INITIALIZERS
+ static const struct wolfsentry_eventconfig config = { .route_private_data_size = PRIVATE_DATA_SIZE, .route_private_data_alignment = PRIVATE_DATA_ALIGNMENT, .max_connection_count = 10 };
+ static const struct wolfsentry_eventconfig config2 = { .route_private_data_size = PRIVATE_DATA_SIZE * 2, .route_private_data_alignment = PRIVATE_DATA_ALIGNMENT * 2, .max_connection_count = 15 };
+#else
+ static const struct wolfsentry_eventconfig config = { PRIVATE_DATA_SIZE, PRIVATE_DATA_ALIGNMENT, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+ static const struct wolfsentry_eventconfig config2 = { PRIVATE_DATA_SIZE * 2, PRIVATE_DATA_ALIGNMENT * 2, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+#endif
+
+ WOLFSENTRY_THREAD_HEADER_CHECKED(WOLFSENTRY_THREAD_FLAG_NONE);
+
+ WOLFSENTRY_EXIT_ON_FAILURE(
+ wolfsentry_init_ex(
+ wolfsentry_build_settings,
+ WOLFSENTRY_CONTEXT_ARGS_OUT_EX(WOLFSENTRY_TEST_HPI),
+ &config,
+ &wolfsentry,
+ WOLFSENTRY_INIT_FLAG_NONE));
+
+ WOLFSENTRY_EXIT_ON_FAILURE(
+ wolfsentry_action_insert(
+ WOLFSENTRY_CONTEXT_ARGS_OUT,
+ "layout_insert_action",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED,
+ WOLFSENTRY_ACTION_FLAG_NONE,
+ test_action_insert_noop,
+ NULL /* handler_arg */,
+ &id));
+
+ WOLFSENTRY_EXIT_ON_FAILURE(
+ wolfsentry_event_insert(
+ WOLFSENTRY_CONTEXT_ARGS_OUT,
+ "layout_held_parent",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED,
+ 10,
+ &config,
+ WOLFSENTRY_EVENT_FLAG_NONE,
+ &id));
+
+ WOLFSENTRY_EXIT_ON_FAILURE(
+ wolfsentry_event_action_append(
+ WOLFSENTRY_CONTEXT_ARGS_OUT,
+ "layout_held_parent",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED,
+ WOLFSENTRY_ACTION_TYPE_INSERT,
+ "layout_insert_action",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED));
+
+ remote.sa.sa_family = local.sa.sa_family = AF_INET;
+ remote.sa.sa_proto = local.sa.sa_proto = IPPROTO_TCP;
+ remote.sa.sa_port = 12345;
+ local.sa.sa_port = 443;
+ remote.sa.addr_len = local.sa.addr_len = sizeof remote.addr_buf * BITS_PER_BYTE;
+ remote.sa.interface = local.sa.interface = 1;
+ memcpy(remote.sa.addr, "\0\1\2\3", sizeof remote.addr_buf);
+ memcpy(local.sa.addr, "\377\376\375\374", sizeof local.addr_buf);
+
+ WOLFSENTRY_CLEAR_ALL_BITS(action_results);
+ WOLFSENTRY_EXIT_ON_FAILURE(
+ wolfsentry_route_insert_and_check_out(
+ WOLFSENTRY_CONTEXT_ARGS_OUT,
+ NULL /* caller_arg */,
+ &remote.sa,
+ &local.sa,
+ flags,
+ "layout_held_parent",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED,
+ &route,
+ &action_results));
+
+ WOLFSENTRY_CLEAR_ALL_BITS(action_results);
+ WOLFSENTRY_EXIT_ON_FAILURE(
+ wolfsentry_route_delete_by_id(
+ WOLFSENTRY_CONTEXT_ARGS_OUT,
+ NULL /* caller_arg */,
+ route->header.id,
+ NULL /* trigger_label */,
+ 0,
+ &action_results));
+
+ WOLFSENTRY_EXIT_UNLESS_EXPECTED_FAILURE(
+ INCOMPATIBLE_STATE,
+ wolfsentry_event_update_config(
+ WOLFSENTRY_CONTEXT_ARGS_OUT,
+ "layout_held_parent",
+ WOLFSENTRY_LENGTH_NULL_TERMINATED,
+ &config2));
+
+ WOLFSENTRY_CLEAR_ALL_BITS(action_results);
+ WOLFSENTRY_EXIT_ON_FAILURE(
+ wolfsentry_route_drop_reference(
+ WOLFSENTRY_CONTEXT_ARGS_OUT,
+ route,
+ &action_results));
+
+ WOLFSENTRY_EXIT_ON_FAILURE(wolfsentry_shutdown(WOLFSENTRY_CONTEXT_ARGS_OUT_EX(&wolfsentry)));
+
+ WOLFSENTRY_EXIT_ON_FAILURE(WOLFSENTRY_THREAD_TAILER(WOLFSENTRY_THREAD_FLAG_NONE));
+
+ WOLFSENTRY_RETURN_OK;
+}
+
#endif /* TEST_DYNAMIC_RULES */
#ifdef TEST_USER_VALUES
@@ -5749,6 +7323,98 @@ int main(int argc, char* argv[]) {
(void)fprintf(stderr, "test_dynamic_rules failed, " WOLFSENTRY_ERROR_FMT "\n", WOLFSENTRY_ERROR_FMT_ARGS(ret));
err = 1;
}
+
+ ret = test_event_max_length_label();
+ if (! WOLFSENTRY_ERROR_CODE_IS(ret, OK)) {
+ (void)fprintf(stderr, "test_event_max_length_label failed, " WOLFSENTRY_ERROR_FMT "\n", WOLFSENTRY_ERROR_FMT_ARGS(ret));
+ err = 1;
+ }
+
+ ret = test_event_max_length_label_lookups();
+ if (! WOLFSENTRY_ERROR_CODE_IS(ret, OK)) {
+ (void)fprintf(stderr, "test_event_max_length_label_lookups failed, " WOLFSENTRY_ERROR_FMT "\n", WOLFSENTRY_ERROR_FMT_ARGS(ret));
+ err = 1;
+ }
+
+ ret = test_event_insert_failure_leaves_id_untouched();
+ if (! WOLFSENTRY_ERROR_CODE_IS(ret, OK)) {
+ (void)fprintf(stderr, "test_event_insert_failure_leaves_id_untouched failed, " WOLFSENTRY_ERROR_FMT "\n", WOLFSENTRY_ERROR_FMT_ARGS(ret));
+ err = 1;
+ }
+
+ ret = test_event_update_config_null();
+ if (! WOLFSENTRY_ERROR_CODE_IS(ret, OK)) {
+ (void)fprintf(stderr, "test_event_update_config_null failed, " WOLFSENTRY_ERROR_FMT "\n", WOLFSENTRY_ERROR_FMT_ARGS(ret));
+ err = 1;
+ }
+
+ ret = test_event_update_config_layout_with_routes();
+ if (! WOLFSENTRY_ERROR_CODE_IS(ret, OK)) {
+ (void)fprintf(stderr, "test_event_update_config_layout_with_routes failed, " WOLFSENTRY_ERROR_FMT "\n", WOLFSENTRY_ERROR_FMT_ARGS(ret));
+ err = 1;
+ }
+
+ ret = test_event_aux_event_self_reference();
+ if (! WOLFSENTRY_ERROR_CODE_IS(ret, OK)) {
+ (void)fprintf(stderr, "test_event_aux_event_self_reference failed, " WOLFSENTRY_ERROR_FMT "\n", WOLFSENTRY_ERROR_FMT_ARGS(ret));
+ err = 1;
+ }
+
+ ret = test_event_aux_event_reuse_after_clear();
+ if (! WOLFSENTRY_ERROR_CODE_IS(ret, OK)) {
+ (void)fprintf(stderr, "test_event_aux_event_reuse_after_clear failed, " WOLFSENTRY_ERROR_FMT "\n", WOLFSENTRY_ERROR_FMT_ARGS(ret));
+ err = 1;
+ }
+
+ ret = test_event_aux_mark_cleared_on_owner_free();
+ if (! WOLFSENTRY_ERROR_CODE_IS(ret, OK)) {
+ (void)fprintf(stderr, "test_event_aux_mark_cleared_on_owner_free failed, " WOLFSENTRY_ERROR_FMT "\n", WOLFSENTRY_ERROR_FMT_ARGS(ret));
+ err = 1;
+ }
+
+ ret = test_event_aux_event_rejects_subevent_owner();
+ if (! WOLFSENTRY_ERROR_CODE_IS(ret, OK)) {
+ (void)fprintf(stderr, "test_event_aux_event_rejects_subevent_owner failed, " WOLFSENTRY_ERROR_FMT "\n", WOLFSENTRY_ERROR_FMT_ARGS(ret));
+ err = 1;
+ }
+
+ ret = test_event_aux_event_rejects_parent_event();
+ if (! WOLFSENTRY_ERROR_CODE_IS(ret, OK)) {
+ (void)fprintf(stderr, "test_event_aux_event_rejects_parent_event failed, " WOLFSENTRY_ERROR_FMT "\n", WOLFSENTRY_ERROR_FMT_ARGS(ret));
+ err = 1;
+ }
+
+#ifndef WOLFSENTRY_NO_JSON
+ ret = test_event_default_priority();
+ if (! WOLFSENTRY_ERROR_CODE_IS(ret, OK)) {
+ (void)fprintf(stderr, "test_event_default_priority failed, " WOLFSENTRY_ERROR_FMT "\n", WOLFSENTRY_ERROR_FMT_ARGS(ret));
+ err = 1;
+ }
+
+ ret = test_json_event_max_length_label();
+ if (! WOLFSENTRY_ERROR_CODE_IS(ret, OK)) {
+ (void)fprintf(stderr, "test_json_event_max_length_label failed, " WOLFSENTRY_ERROR_FMT "\n", WOLFSENTRY_ERROR_FMT_ARGS(ret));
+ err = 1;
+ }
+#endif
+
+ ret = test_action_insert_failure_leaves_id_untouched();
+ if (! WOLFSENTRY_ERROR_CODE_IS(ret, OK)) {
+ (void)fprintf(stderr, "test_action_insert_failure_leaves_id_untouched failed, " WOLFSENTRY_ERROR_FMT "\n", WOLFSENTRY_ERROR_FMT_ARGS(ret));
+ err = 1;
+ }
+
+ ret = test_event_aux_event_layout_pinned();
+ if (! WOLFSENTRY_ERROR_CODE_IS(ret, OK)) {
+ (void)fprintf(stderr, "test_event_aux_event_layout_pinned failed, " WOLFSENTRY_ERROR_FMT "\n", WOLFSENTRY_ERROR_FMT_ARGS(ret));
+ err = 1;
+ }
+
+ ret = test_event_layout_guard_held_deleted_route();
+ if (! WOLFSENTRY_ERROR_CODE_IS(ret, OK)) {
+ (void)fprintf(stderr, "test_event_layout_guard_held_deleted_route failed, " WOLFSENTRY_ERROR_FMT "\n", WOLFSENTRY_ERROR_FMT_ARGS(ret));
+ err = 1;
+ }
#endif
#ifdef TEST_USER_VALUES
diff --git a/wolfsentry/wolfsentry.h b/wolfsentry/wolfsentry.h
index 225980b..612a771 100644
--- a/wolfsentry/wolfsentry.h
+++ b/wolfsentry/wolfsentry.h
@@ -2801,7 +2801,7 @@ WOLFSENTRY_API wolfsentry_errcode_t wolfsentry_event_get_config(
\param label_len the length of the label
\param config the updated configuration
- \return WOLFSENTRY_IS_SUCCESS(ret) is true on success.
+ \return WOLFSENTRY_IS_SUCCESS(ret) is true on success. Once any route has used the event as its parent, or while the event is another event's aux event or is otherwise referenced, changes to `route_private_data_size` or `route_private_data_alignment` are rejected with `INCOMPATIBLE_STATE`, even after that route is deleted, because a deleted route can still be held by a checked-out reference.
\sa WOLFSENTRY_CONTEXT_ARGS_IN
*/