}
static void
-config_dump_full_append_filter(string_t *str,
- const struct config_filter *filter,
- enum config_dump_full_dest dest)
+config_dump_full_append_filter_query(string_t *str,
+ const struct config_filter *filter)
{
- if (dest == CONFIG_DUMP_FULL_DEST_STDOUT)
- str_append(str, ":FILTER ");
- unsigned int prefix_len = str_len(str);
-
if (filter->service != NULL) {
if (filter->service[0] != '!') {
str_printfa(str, "protocol=\"%s\" AND ",
net_ip2addr(&filter->remote_net),
filter->remote_bits);
}
+}
+
+static void
+config_dump_full_append_filter(string_t *str,
+ const struct config_filter *filter,
+ enum config_dump_full_dest dest)
+{
+ if (dest == CONFIG_DUMP_FULL_DEST_STDOUT)
+ str_append(str, ":FILTER ");
+ unsigned int prefix_len = str_len(str);
+
+ do {
+ config_dump_full_append_filter_query(str, filter);
+ filter = filter->parent;
+ } while (filter != NULL);
i_assert(str_len(str) > prefix_len);
str_delete(str, str_len(str) - 4, 4);
bool config_filter_match(const struct config_filter *mask,
const struct config_filter *filter)
{
- if (!config_filter_match_service(mask, filter))
- return FALSE;
+ do {
+ if (!config_filter_match_service(mask, filter))
+ return FALSE;
- return config_filter_match_rest(mask, filter);
+ if (!config_filter_match_rest(mask, filter))
+ return FALSE;
+ mask = mask->parent;
+ filter = filter->parent;
+ } while (mask != NULL && filter != NULL);
+ return mask == NULL && filter == NULL;
}
bool config_filters_equal(const struct config_filter *f1,
return TRUE;
}
-
-int config_filter_sort_cmp(const struct config_filter *f1,
- const struct config_filter *f2)
-{
- /* remote and locals are first, although it doesn't really
- matter which one comes first */
- if (f1->local_name != NULL && f2->local_name == NULL)
- return 1;
- if (f1->local_name == NULL && f2->local_name != NULL)
- return -1;
-
- if (f1->local_bits > f2->local_bits)
- return 1;
- if (f1->local_bits < f2->local_bits)
- return -1;
-
- if (f1->remote_bits > f2->remote_bits)
- return 1;
- if (f1->remote_bits < f2->remote_bits)
- return -1;
-
- if (f1->service != NULL && f2->service == NULL)
- return 1;
- if (f1->service == NULL && f2->service != NULL)
- return -1;
- return 0;
-}
#include "net.h"
struct config_filter {
+ struct config_filter *parent;
+
const char *service;
/* local_name is for TLS SNI requests.
both local_name and local_bits can't be set at the same time. */
bool config_filters_equal(const struct config_filter *f1,
const struct config_filter *f2);
-/* Used for sorting filters - doesn't return exact equality. */
-int config_filter_sort_cmp(const struct config_filter *f1,
- const struct config_filter *f2);
-
#endif
{
const struct config_filter *filter = §ion->filter;
- return filter->local_name != NULL || filter->local_bits > 0 ||
- filter->remote_bits > 0;
+ do {
+ if (filter->local_name != NULL || filter->local_bits > 0 ||
+ filter->remote_bits > 0)
+ return TRUE;
+ filter = filter->parent;
+ } while (filter != NULL);
+ return FALSE;
}
static void
struct config_filter_parser *filter_parser;
const char *error;
+ i_zero(filter);
+ filter->parent = parent;
+
if (strcmp(key, "protocol") == 0) {
if (parent->service != NULL)
ctx->error = "Nested protocol { protocol { .. } } block not allowed";
config_line_r->type = CONFIG_LINE_TYPE_SECTION_BEGIN;
}
-static int
-config_filter_parser_cmp(struct config_filter_parser *const *p1,
- struct config_filter_parser *const *p2)
-{
- return config_filter_sort_cmp(&(*p1)->filter, &(*p2)->filter);
-}
-
static int
config_parse_finish(struct config_parser_context *ctx,
enum config_parse_flags flags,
pool_ref(new_config->pool);
p_array_init(&new_config->errors, ctx->pool, 1);
- struct config_filter_parser *global_filter =
- array_idx_elem(&ctx->all_filter_parsers, 0);
- array_sort(&ctx->all_filter_parsers, config_filter_parser_cmp);
- i_assert(global_filter == array_idx_elem(&ctx->all_filter_parsers, 0));
-
array_append_zero(&ctx->all_filter_parsers);
new_config->filter_parsers = array_front(&ctx->all_filter_parsers);
/* Returns the global filter */
struct config_filter_parser *
config_parsed_get_global_filter_parser(struct config_parsed *config);
-/* Returns all filters sorted */
+/* Returns all filters */
struct config_filter_parser *const *
config_parsed_get_filter_parsers(struct config_parsed *config);
void config_parsed_free(struct config_parsed **config);
{
unsigned int indent = 0;
+ if (filter->parent != NULL)
+ indent = config_dump_filter_begin(str, filter->parent);
+
if (filter->local_bits > 0) {
str_printfa(str, "local %s", net_ip2addr(&filter->local_net));