Skip to content

Commit

Permalink
option for strict sequential route matching (#605)
Browse files Browse the repository at this point in the history
option for strict sequential route matching
  • Loading branch information
mialinx authored Apr 8, 2024
1 parent 34947dc commit c827bb4
Show file tree
Hide file tree
Showing 8 changed files with 126 additions and 9 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ Set up your CLion to build project in container, [manual](https://github.com/shu

* [include](documentation/configuration.md#include-string)
* [daemonize](documentation/configuration.md#daemonize-yesno)
* [sequential\_routing](documentation/configuration.md#sequential_routing-yesno)
* [priority](documentation/configuration.md#priority-integer)
* [pid\_file](documentation/configuration.md#pid_file-string)
* [unix\_socket\_dir](documentation/configuration.md#unix_socket_dir-string)
Expand Down
10 changes: 10 additions & 0 deletions documentation/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,16 @@ By default Odyssey does not run as a daemon. Set to 'yes' to enable.

`daemonize no`

#### sequential\_routing_ *yes|no*

Try to match routes exactly in config order.

By default, Odyssey tries to match all specific routes first, and then all default ones.
It may be confusing because auth-denying default route can be overridden with more specific auth-permitting route below in the config.
With this option set, Odyssey will match routes exactly in config order, like in HBA files.

`sequential_routing no`

#### priority *integer*

Process priority.
Expand Down
3 changes: 3 additions & 0 deletions sources/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ void od_config_init(od_config_t *config)
{
config->daemonize = 0;
config->priority = 0;
config->sequential_routing = 0;
config->log_debug = 0;
config->log_to_stdout = 1;
config->log_config = 0;
Expand Down Expand Up @@ -245,6 +246,8 @@ void od_config_print(od_config_t *config, od_logger_t *logger)
od_config_yes_no(config->daemonize));
od_log(logger, "config", NULL, NULL, "priority %d",
config->priority);
od_log(logger, "config", NULL, NULL, "sequential_routing %s",
od_config_yes_no(config->sequential_routing));
if (config->pid_file)
od_log(logger, "config", NULL, NULL,
"pid_file %s", config->pid_file);
Expand Down
1 change: 1 addition & 0 deletions sources/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ struct od_config_listen {
struct od_config {
int daemonize;
int priority;
int sequential_routing;
/* logging */
int log_to_stdout;
int log_debug;
Expand Down
9 changes: 9 additions & 0 deletions sources/config_reader.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ typedef enum {
OD_LINCLUDE,
OD_LDAEMONIZE,
OD_LPRIORITY,
OD_LSEQROUTING,
OD_LLOG_TO_STDOUT,
OD_LLOG_DEBUG,
OD_LLOG_CONFIG,
Expand Down Expand Up @@ -154,6 +155,7 @@ static od_keyword_t od_config_keywords[] = {
od_keyword("include", OD_LINCLUDE),
od_keyword("daemonize", OD_LDAEMONIZE),
od_keyword("priority", OD_LPRIORITY),
od_keyword("sequential_routing", OD_LSEQROUTING),
od_keyword("pid_file", OD_LPID_FILE),
od_keyword("unix_socket_dir", OD_LUNIX_SOCKET_DIR),
od_keyword("unix_socket_mode", OD_LUNIX_SOCKET_MODE),
Expand Down Expand Up @@ -2274,6 +2276,13 @@ static int od_config_reader_parse(od_config_reader_t *reader,
goto error;
}
continue;
/* sequential_routing */
case OD_LSEQROUTING:
if (!od_config_reader_yes_no(
reader, &config->sequential_routing)) {
goto error;
}
continue;
/* pid_file */
case OD_LPID_FILE:
if (!od_config_reader_string(reader,
Expand Down
7 changes: 5 additions & 2 deletions sources/router.c
Original file line number Diff line number Diff line change
Expand Up @@ -358,10 +358,12 @@ od_router_status_t od_router_route(od_router_t *router, od_client_t *client)
int salen;
struct sockaddr *saddr;
int rc;
int sequential = instance->config.sequential_routing;
switch (client->type) {
case OD_POOL_CLIENT_INTERNAL:
rule = od_rules_forward(&router->rules, startup->database.value,
startup->user.value, NULL, 1);
startup->user.value, NULL, 1,
sequential);
break;
case OD_POOL_CLIENT_EXTERNAL:
salen = sizeof(sa);
Expand All @@ -372,7 +374,8 @@ od_router_status_t od_router_route(od_router_t *router, od_client_t *client)
return OD_ROUTER_ERROR;
}
rule = od_rules_forward(&router->rules, startup->database.value,
startup->user.value, &sa, 0);
startup->user.value, &sa, 0,
sequential);
break;
case OD_POOL_CLIENT_UNDEF: // create that case for correct work of '-Wswitch' flag
break;
Expand Down
101 changes: 95 additions & 6 deletions sources/rules.c
Original file line number Diff line number Diff line change
Expand Up @@ -257,9 +257,10 @@ void od_rules_unref(od_rule_t *rule)
od_rules_rule_free(rule);
}

od_rule_t *od_rules_forward(od_rules_t *rules, char *db_name, char *user_name,
struct sockaddr_storage *user_addr,
int pool_internal)
static od_rule_t *od_rules_forward_default(od_rules_t *rules, char *db_name,
char *user_name,
struct sockaddr_storage *user_addr,
int pool_internal)
{
od_rule_t *rule_db_user_default = NULL;
od_rule_t *rule_db_default_default = NULL;
Expand Down Expand Up @@ -346,6 +347,64 @@ od_rule_t *od_rules_forward(od_rules_t *rules, char *db_name, char *user_name,
return rule_default_default_default;
}

static od_rule_t *
od_rules_forward_sequential(od_rules_t *rules, char *db_name, char *user_name,
struct sockaddr_storage *user_addr,
int pool_internal)
{
od_list_t *i;
od_rule_t *rule_matched = NULL;
bool db_matched = false, user_matched = false, addr_matched = false;
od_list_foreach(&rules->rules, i)
{
od_rule_t *rule;
rule = od_container_of(i, od_rule_t, link);
}
od_list_foreach(&rules->rules, i)
{
od_rule_t *rule;
rule = od_container_of(i, od_rule_t, link);
if (rule->obsolete) {
continue;
}
if (pool_internal) {
if (rule->pool->routing != OD_RULE_POOL_INTERVAL) {
continue;
}
} else {
if (rule->pool->routing !=
OD_RULE_POOL_CLIENT_VISIBLE) {
continue;
}
}
db_matched = rule->db_is_default ||
(strcmp(rule->db_name, db_name) == 0);
user_matched = rule->user_is_default ||
(strcmp(rule->user_name, user_name) == 0);
addr_matched =
rule->address_range.is_default ||
od_address_validate(&rule->address_range, user_addr);
if (db_matched && user_matched && addr_matched) {
rule_matched = rule;
break;
}
}
assert(rule_matched);
return rule_matched;
}

od_rule_t *od_rules_forward(od_rules_t *rules, char *db_name, char *user_name,
struct sockaddr_storage *user_addr,
int pool_internal, int sequential)
{
if (sequential) {
return od_rules_forward_sequential(rules, db_name, user_name,
user_addr, pool_internal);
}
return od_rules_forward_default(rules, db_name, user_name, user_addr,
pool_internal);
}

od_rule_t *od_rules_match(od_rules_t *rules, char *db_name, char *user_name,
od_address_range_t *address_range, int db_is_default,
int user_is_default, int pool_internal)
Expand Down Expand Up @@ -630,16 +689,25 @@ __attribute__((hot)) int od_rules_merge(od_rules_t *rules, od_rules_t *src,
int count_mark = 0;
int count_deleted = 0;
int count_new = 0;
int src_length = 0;

/* mark all rules for obsoletion */
/* set order for new rules */
od_list_t *i;
od_list_foreach(&src->rules, i)
{
od_rule_t *rule;
rule = od_container_of(i, od_rule_t, link);
rule->order = src_length;
src_length++;
}

/* mark all rules for obsoletion */
od_list_foreach(&rules->rules, i)
{
od_rule_t *rule;
rule = od_container_of(i, od_rule_t, link);
rule->mark = 1;
count_mark++;

od_hashmap_empty(rule->storage->acache);
}

Expand Down Expand Up @@ -741,6 +809,7 @@ __attribute__((hot)) int od_rules_merge(od_rules_t *rules, od_rules_t *src,
if (od_rules_rule_compare(origin, rule)) {
origin->mark = 0;
count_mark--;
origin->order = rule->order;
continue;
/* select rules with changes what needed disconnect */
} else if (!od_rules_rule_compare_to_drop(origin,
Expand Down Expand Up @@ -797,6 +866,26 @@ __attribute__((hot)) int od_rules_merge(od_rules_t *rules, od_rules_t *src,
}
}

/* sort rules according order, leaving obsolete at the end of the list */
od_list_t **sorted = calloc(src_length, sizeof(od_list_t *));
od_list_foreach_safe(&rules->rules, i, n)
{
od_rule_t *rule;
rule = od_container_of(i, od_rule_t, link);
if (rule->obsolete) {
continue;
}
assert(rule->order >= 0 && rule->order < src_length &&
sorted[rule->order] == NULL);
od_list_unlink(&rule->link);
sorted[rule->order] = &rule->link;
}
for (int s = src_length - 1; s >= 0; s--) {
assert(sorted[s] != NULL);
od_list_push(&rules->rules, sorted[s]);
}
free(sorted);

return count_new + count_mark + count_deleted;
}

Expand Down Expand Up @@ -1229,7 +1318,7 @@ int od_rules_cleanup(od_rules_t *rules)
od_list_init(&rules->storages);
#ifdef LDAP_FOUND

/* TODO: cleanup ldap
/* TODO: cleanup ldap
od_list_foreach_safe(&rules->storages, i, n)
{
od_ldap_endpoint_t *endp;
Expand Down
3 changes: 2 additions & 1 deletion sources/rules.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ struct od_rule {
int mark;
int obsolete;
int refs;
int order;

/* id */
char *db_name;
Expand Down Expand Up @@ -174,7 +175,7 @@ void od_rules_unref(od_rule_t *);
int od_rules_compare(od_rule_t *, od_rule_t *);

od_rule_t *od_rules_forward(od_rules_t *, char *, char *,
struct sockaddr_storage *, int);
struct sockaddr_storage *, int, int);

/* search rule with desored characteristik */
od_rule_t *od_rules_match(od_rules_t *rules, char *db_name, char *user_name,
Expand Down

0 comments on commit c827bb4

Please sign in to comment.