config-filter.c revision 5d03d9f439e41c90215a3c938ffebe4c2a8ae257
2e37d45867d081db150ab78dad303b9077aea24fTimo Sirainen/* Copyright (c) 2005-2010 Dovecot authors, see the included COPYING file */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen#include "lib.h"
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen#include "array.h"
f242fa00989e452ecffba917f20f885f509d0f8fTimo Sirainen#include "settings-parser.h"
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen#include "master-service-settings.h"
bca919b207e27d0d08b431bdb0f2ac099ef8b512Timo Sirainen#include "config-parser.h"
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen#include "config-filter.h"
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainenstruct config_filter_context {
7a7d2aa11e46195e2d92d6c337d7e78052a5ce67Timo Sirainen pool_t pool;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct config_filter_parser *const *parsers;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen};
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenstatic bool config_filter_match_service(const struct config_filter *mask,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen const struct config_filter *filter)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen{
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (mask->service != NULL) {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (filter->service == NULL)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return FALSE;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (mask->service[0] == '!') {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen /* not service */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (strcmp(filter->service, mask->service + 1) == 0)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return FALSE;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen } else {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (strcmp(filter->service, mask->service) != 0)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return FALSE;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen }
4c1deab456fe8877bf025d11843167ac1f36327aTimo Sirainen }
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return TRUE;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen}
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenstatic bool config_filter_match_rest(const struct config_filter *mask,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen const struct config_filter *filter)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen{
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (mask->local_host != NULL) {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (filter->local_host == NULL)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return FALSE;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (strcmp(filter->local_host, mask->local_host) != 0)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return FALSE;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen }
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (mask->remote_host != NULL) {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (filter->remote_host == NULL)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return FALSE;
f6aaada6101dd43cd80fe965ff1ab9bfaf776252Timo Sirainen if (strcmp(filter->remote_host, mask->remote_host) != 0)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return FALSE;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen }
ddb018bc886680f462463b2c87f983fdedbf6cf0Timo Sirainen /* FIXME: it's not comparing full masks */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (mask->remote_bits != 0 && mask->remote_host == NULL) {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (filter->remote_bits == 0)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return FALSE;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (!net_is_in_network(&filter->remote_net, &mask->remote_net,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen mask->remote_bits))
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return FALSE;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen }
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (mask->local_bits != 0 && mask->local_host == NULL) {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (filter->local_bits == 0)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return FALSE;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (!net_is_in_network(&filter->local_net, &mask->local_net,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen mask->local_bits))
04c3ac276103b56185119bcff9a66de7a8bb0e68Timo Sirainen return FALSE;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen }
02d72ab3d606033e9a720274ddc3dd83a0ad070dTimo Sirainen return TRUE;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen}
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenbool config_filter_match(const struct config_filter *mask,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen const struct config_filter *filter)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen{
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (!config_filter_match_service(mask, filter))
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return FALSE;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
c18ff860dc22960fd37c272d929f889c7939a2c8Timo Sirainen return config_filter_match_rest(mask, filter);
04c3ac276103b56185119bcff9a66de7a8bb0e68Timo Sirainen}
04c3ac276103b56185119bcff9a66de7a8bb0e68Timo Sirainen
5fb3f13537dffd15a31e997da133a721c0728af8Timo Sirainenbool config_filters_equal(const struct config_filter *f1,
5fb3f13537dffd15a31e997da133a721c0728af8Timo Sirainen const struct config_filter *f2)
5fb3f13537dffd15a31e997da133a721c0728af8Timo Sirainen{
5fb3f13537dffd15a31e997da133a721c0728af8Timo Sirainen if (null_strcmp(f1->service, f2->service) != 0)
5fb3f13537dffd15a31e997da133a721c0728af8Timo Sirainen return FALSE;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen if (f1->remote_bits != f2->remote_bits)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return FALSE;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (!net_ip_compare(&f1->remote_net, &f2->remote_net))
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen return FALSE;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen if (f1->local_bits != f2->local_bits)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return FALSE;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (!net_ip_compare(&f1->local_net, &f2->local_net))
d22301419109ed4a38351715e6760011421dadecTimo Sirainen return FALSE;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (null_strcmp(f1->remote_host, f2->remote_host) != 0)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return FALSE;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (null_strcmp(f1->local_host, f2->local_host) != 0)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return FALSE;
3b32bc12710240f86465a00fbb2bd1ef030e6c40Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return TRUE;
d22301419109ed4a38351715e6760011421dadecTimo Sirainen}
d22301419109ed4a38351715e6760011421dadecTimo Sirainen
d22301419109ed4a38351715e6760011421dadecTimo Sirainenstruct config_filter_context *config_filter_init(pool_t pool)
d22301419109ed4a38351715e6760011421dadecTimo Sirainen{
d22301419109ed4a38351715e6760011421dadecTimo Sirainen struct config_filter_context *ctx;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen ctx = p_new(pool, struct config_filter_context, 1);
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen ctx->pool = pool;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return ctx;
d22301419109ed4a38351715e6760011421dadecTimo Sirainen}
d22301419109ed4a38351715e6760011421dadecTimo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenvoid config_filter_deinit(struct config_filter_context **_ctx)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen{
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct config_filter_context *ctx = *_ctx;
df00412606a00714a6e85383fa87fbdc7cc1fb5bTimo Sirainen unsigned int i;
df00412606a00714a6e85383fa87fbdc7cc1fb5bTimo Sirainen
df00412606a00714a6e85383fa87fbdc7cc1fb5bTimo Sirainen *_ctx = NULL;
df00412606a00714a6e85383fa87fbdc7cc1fb5bTimo Sirainen
df00412606a00714a6e85383fa87fbdc7cc1fb5bTimo Sirainen for (i = 0; ctx->parsers[i] != NULL; i++)
df00412606a00714a6e85383fa87fbdc7cc1fb5bTimo Sirainen config_filter_parsers_free(ctx->parsers[i]->parsers);
df00412606a00714a6e85383fa87fbdc7cc1fb5bTimo Sirainen pool_unref(&ctx->pool);
df00412606a00714a6e85383fa87fbdc7cc1fb5bTimo Sirainen}
df00412606a00714a6e85383fa87fbdc7cc1fb5bTimo Sirainen
df00412606a00714a6e85383fa87fbdc7cc1fb5bTimo Sirainenvoid config_filter_add_all(struct config_filter_context *ctx,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct config_filter_parser *const *parsers)
d22301419109ed4a38351715e6760011421dadecTimo Sirainen{
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen ctx->parsers = parsers;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen}
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
d22301419109ed4a38351715e6760011421dadecTimo Sirainenstatic int
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenconfig_filter_parser_cmp(struct config_filter_parser *const *p1,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct config_filter_parser *const *p2)
d22301419109ed4a38351715e6760011421dadecTimo Sirainen{
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen const struct config_filter *f1 = &(*p1)->filter, *f2 = &(*p2)->filter;
df00412606a00714a6e85383fa87fbdc7cc1fb5bTimo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen /* remote and local are first, although it doesn't really
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen matter which one comes first */
1dd054126238349e1a7d3d1ffe7f8bc5fdbacb7aTimo Sirainen if (f1->local_bits > f2->local_bits)
1dd054126238349e1a7d3d1ffe7f8bc5fdbacb7aTimo Sirainen return -1;
1dd054126238349e1a7d3d1ffe7f8bc5fdbacb7aTimo Sirainen if (f1->local_bits < f2->local_bits)
1dd054126238349e1a7d3d1ffe7f8bc5fdbacb7aTimo Sirainen return 1;
5b62dea2f88165f3f4d87bba9011343f3ff415ffTimo Sirainen
1dd054126238349e1a7d3d1ffe7f8bc5fdbacb7aTimo Sirainen if (f1->remote_bits > f2->remote_bits)
1dd054126238349e1a7d3d1ffe7f8bc5fdbacb7aTimo Sirainen return -1;
1dd054126238349e1a7d3d1ffe7f8bc5fdbacb7aTimo Sirainen if (f1->remote_bits < f2->remote_bits)
1dd054126238349e1a7d3d1ffe7f8bc5fdbacb7aTimo Sirainen return 1;
1dd054126238349e1a7d3d1ffe7f8bc5fdbacb7aTimo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (f1->service != NULL && f2->service == NULL)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return -1;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (f1->service == NULL && f2->service != NULL)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return 1;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return 0;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen}
d22301419109ed4a38351715e6760011421dadecTimo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenstatic struct config_filter_parser *const *
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenconfig_filter_find_all(struct config_filter_context *ctx,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen const struct config_filter *filter,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct master_service_settings_output *output_r)
ddb018bc886680f462463b2c87f983fdedbf6cf0Timo Sirainen{
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen ARRAY_TYPE(config_filter_parsers) matches;
5b62dea2f88165f3f4d87bba9011343f3ff415ffTimo Sirainen unsigned int i;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen memset(output_r, 0, sizeof(*output_r));
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen t_array_init(&matches, 8);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen for (i = 0; ctx->parsers[i] != NULL; i++) {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen const struct config_filter *mask = &ctx->parsers[i]->filter;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (!config_filter_match_service(mask, filter))
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen continue;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (mask->local_bits > 0)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen output_r->service_uses_local = TRUE;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (mask->remote_bits > 0)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen output_r->service_uses_remote = TRUE;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (config_filter_match_rest(mask, filter)) {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (mask->local_bits > 0)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen output_r->used_local = TRUE;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (mask->remote_bits > 0)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen output_r->used_remote = TRUE;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen array_append(&matches, &ctx->parsers[i], 1);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen }
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen }
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen array_sort(&matches, config_filter_parser_cmp);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen (void)array_append_space(&matches);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return array_idx(&matches, 0);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen}
c18ff860dc22960fd37c272d929f889c7939a2c8Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenstatic bool
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenconfig_filter_is_superset(const struct config_filter *sup,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen const struct config_filter *filter)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen{
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen /* assume that both of the filters match the same subset, so we don't
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen need to compare IPs and service name. */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (sup->local_bits > filter->local_bits)
dd4f30895ebbddd77e000472fbadcb3128ae2883Timo Sirainen return FALSE;
dd4f30895ebbddd77e000472fbadcb3128ae2883Timo Sirainen if (sup->remote_bits > filter->remote_bits)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return FALSE;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (sup->service != NULL && filter->service == NULL)
dd4f30895ebbddd77e000472fbadcb3128ae2883Timo Sirainen return FALSE;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return TRUE;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen}
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
c18ff860dc22960fd37c272d929f889c7939a2c8Timo Sirainenstatic int
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenconfig_module_parser_apply_changes(struct config_module_parser *dest,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen const struct config_filter_parser *src,
dd4f30895ebbddd77e000472fbadcb3128ae2883Timo Sirainen pool_t pool, const char **error_r)
dd4f30895ebbddd77e000472fbadcb3128ae2883Timo Sirainen{
dd4f30895ebbddd77e000472fbadcb3128ae2883Timo Sirainen unsigned int i;
dd4f30895ebbddd77e000472fbadcb3128ae2883Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen for (i = 0; dest[i].root != NULL; i++) {
dd4f30895ebbddd77e000472fbadcb3128ae2883Timo Sirainen if (settings_parser_apply_changes(dest[i].parser,
6d2c938f017a2fc55ae476f88839f03a3d3c5fbdTimo Sirainen src->parsers[i].parser, pool,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen error_r) < 0) {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen *error_r = t_strdup_printf("Conflict in setting %s "
6d2c938f017a2fc55ae476f88839f03a3d3c5fbdTimo Sirainen "found from filter at %s", *error_r,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen src->file_and_line);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return -1;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen }
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen }
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return 0;
46219292a55094fa49aae33eee681ed075d30e17Timo Sirainen}
46219292a55094fa49aae33eee681ed075d30e17Timo Sirainen
46219292a55094fa49aae33eee681ed075d30e17Timo Sirainenint config_filter_parsers_get(struct config_filter_context *ctx, pool_t pool,
46219292a55094fa49aae33eee681ed075d30e17Timo Sirainen const struct config_filter *filter,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct config_module_parser **parsers_r,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct master_service_settings_output *output_r,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen const char **error_r)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen{
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct config_filter_parser *const *src;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct config_module_parser *dest;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen const char *error, **error_p;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen unsigned int i, count;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen src = config_filter_find_all(ctx, filter, output_r);
ee9254cc7875519a9c71cc58a40610e6f320e907Timo Sirainen
29337701451b9c9f9dd26b2aec23a31ab5203822Timo Sirainen /* all of them should have the same number of parsers.
29337701451b9c9f9dd26b2aec23a31ab5203822Timo Sirainen duplicate our initial parsers from the first match */
29337701451b9c9f9dd26b2aec23a31ab5203822Timo Sirainen for (count = 0; src[0]->parsers[count].root != NULL; count++) ;
29337701451b9c9f9dd26b2aec23a31ab5203822Timo Sirainen dest = p_new(pool, struct config_module_parser, count + 1);
29337701451b9c9f9dd26b2aec23a31ab5203822Timo Sirainen for (i = 0; i < count; i++) {
29337701451b9c9f9dd26b2aec23a31ab5203822Timo Sirainen dest[i] = src[0]->parsers[i];
29337701451b9c9f9dd26b2aec23a31ab5203822Timo Sirainen dest[i].parser =
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen settings_parser_dup(src[0]->parsers[i].parser, pool);
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen }
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
fa7c76955c6bc62689fbdf39318194f85905e6e2Timo Sirainen /* apply the changes from rest of the matches */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen for (i = 1; src[i] != NULL; i++) {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (config_filter_is_superset(&src[i]->filter,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen &src[i-1]->filter))
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen error_p = NULL;
46219292a55094fa49aae33eee681ed075d30e17Timo Sirainen else
dd4f30895ebbddd77e000472fbadcb3128ae2883Timo Sirainen error_p = &error;
dd4f30895ebbddd77e000472fbadcb3128ae2883Timo Sirainen
dd4f30895ebbddd77e000472fbadcb3128ae2883Timo Sirainen if (config_module_parser_apply_changes(dest, src[i], pool,
dd4f30895ebbddd77e000472fbadcb3128ae2883Timo Sirainen error_p) < 0) {
dd4f30895ebbddd77e000472fbadcb3128ae2883Timo Sirainen config_filter_parsers_free(dest);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen *error_r = error;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return -1;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen }
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen }
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen *parsers_r = dest;
dd4f30895ebbddd77e000472fbadcb3128ae2883Timo Sirainen return 0;
dd4f30895ebbddd77e000472fbadcb3128ae2883Timo Sirainen}
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenvoid config_filter_parsers_free(struct config_module_parser *parsers)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen{
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen unsigned int i;
888ab4e17f7441b4dcca4a01886d055b57f4586dTimo Sirainen
dd4f30895ebbddd77e000472fbadcb3128ae2883Timo Sirainen for (i = 0; parsers[i].root != NULL; i++)
888ab4e17f7441b4dcca4a01886d055b57f4586dTimo Sirainen settings_parser_deinit(&parsers[i].parser);
888ab4e17f7441b4dcca4a01886d055b57f4586dTimo Sirainen}
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen