config-filter.c revision 5d03d9f439e41c90215a3c938ffebe4c2a8ae257
2e37d45867d081db150ab78dad303b9077aea24fTimo Sirainen/* Copyright (c) 2005-2010 Dovecot authors, see the included COPYING file */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenstatic bool config_filter_match_service(const struct config_filter *mask,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen /* not service */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (strcmp(filter->service, mask->service + 1) == 0)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (strcmp(filter->service, mask->service) != 0)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenstatic bool config_filter_match_rest(const struct config_filter *mask,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (strcmp(filter->local_host, mask->local_host) != 0)
f6aaada6101dd43cd80fe965ff1ab9bfaf776252Timo Sirainen if (strcmp(filter->remote_host, mask->remote_host) != 0)
ddb018bc886680f462463b2c87f983fdedbf6cf0Timo Sirainen /* FIXME: it's not comparing full masks */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (mask->remote_bits != 0 && mask->remote_host == NULL) {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (!net_is_in_network(&filter->remote_net, &mask->remote_net,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (mask->local_bits != 0 && mask->local_host == NULL) {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (!net_is_in_network(&filter->local_net, &mask->local_net,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenbool config_filter_match(const struct config_filter *mask,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (!config_filter_match_service(mask, filter))
c18ff860dc22960fd37c272d929f889c7939a2c8Timo Sirainen return config_filter_match_rest(mask, filter);
5fb3f13537dffd15a31e997da133a721c0728af8Timo Sirainenbool config_filters_equal(const struct config_filter *f1,
5fb3f13537dffd15a31e997da133a721c0728af8Timo Sirainen if (null_strcmp(f1->service, f2->service) != 0)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (!net_ip_compare(&f1->remote_net, &f2->remote_net))
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (!net_ip_compare(&f1->local_net, &f2->local_net))
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (null_strcmp(f1->remote_host, f2->remote_host) != 0)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (null_strcmp(f1->local_host, f2->local_host) != 0)
d22301419109ed4a38351715e6760011421dadecTimo Sirainenstruct config_filter_context *config_filter_init(pool_t pool)
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen ctx = p_new(pool, struct config_filter_context, 1);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenvoid config_filter_deinit(struct config_filter_context **_ctx)
df00412606a00714a6e85383fa87fbdc7cc1fb5bTimo Sirainen unsigned int i;
df00412606a00714a6e85383fa87fbdc7cc1fb5bTimo Sirainen config_filter_parsers_free(ctx->parsers[i]->parsers);
df00412606a00714a6e85383fa87fbdc7cc1fb5bTimo Sirainenvoid config_filter_add_all(struct config_filter_context *ctx,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenconfig_filter_parser_cmp(struct config_filter_parser *const *p1,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen const struct config_filter *f1 = &(*p1)->filter, *f2 = &(*p2)->filter;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen /* remote and local are first, although it doesn't really
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen matter which one comes first */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (f1->service != NULL && f2->service == NULL)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (f1->service == NULL && f2->service != NULL)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenstatic struct config_filter_parser *const *
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenconfig_filter_find_all(struct config_filter_context *ctx,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct master_service_settings_output *output_r)
5b62dea2f88165f3f4d87bba9011343f3ff415ffTimo Sirainen unsigned int i;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen const struct config_filter *mask = &ctx->parsers[i]->filter;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (!config_filter_match_service(mask, filter))
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen array_sort(&matches, config_filter_parser_cmp);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenconfig_filter_is_superset(const struct config_filter *sup,
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->service != NULL && filter->service == NULL)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenconfig_module_parser_apply_changes(struct config_module_parser *dest,
dd4f30895ebbddd77e000472fbadcb3128ae2883Timo Sirainen unsigned int i;
dd4f30895ebbddd77e000472fbadcb3128ae2883Timo Sirainen if (settings_parser_apply_changes(dest[i].parser,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen *error_r = t_strdup_printf("Conflict in setting %s "
46219292a55094fa49aae33eee681ed075d30e17Timo Sirainenint config_filter_parsers_get(struct config_filter_context *ctx, pool_t pool,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct master_service_settings_output *output_r,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen const char **error_r)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen unsigned int i, count;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen src = config_filter_find_all(ctx, filter, output_r);
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++) {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen settings_parser_dup(src[0]->parsers[i].parser, pool);
fa7c76955c6bc62689fbdf39318194f85905e6e2Timo Sirainen /* apply the changes from rest of the matches */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (config_filter_is_superset(&src[i]->filter,
dd4f30895ebbddd77e000472fbadcb3128ae2883Timo Sirainen if (config_module_parser_apply_changes(dest, src[i], pool,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenvoid config_filter_parsers_free(struct config_module_parser *parsers)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen unsigned int i;