dovecot-2.0: config handling fixes and improvements. Separated m...
dovecot at dovecot.org
dovecot at dovecot.org
Tue May 12 03:10:36 EEST 2009
details: http://hg.dovecot.org/dovecot-2.0/rev/5d0a69504867
changeset: 9263:5d0a69504867
user: Timo Sirainen <tss at iki.fi>
date: Mon May 11 20:10:30 2009 -0400
description:
config handling fixes and improvements. Separated module/service lookups. Added support for per-lip/rip settings.
diffstat:
18 files changed, 462 insertions(+), 78 deletions(-)
src/config/Makefile.am | 2
src/config/all-settings.h | 1
src/config/config-connection.c | 24 ++
src/config/config-filter.c | 120 +++++++++++++
src/config/config-filter.h | 35 +++
src/config/config-parser.c | 272 ++++++++++++++++++++++++------
src/config/config-parser.h | 2
src/config/config-request.c | 21 +-
src/config/config-request.h | 5
src/config/doveconf.c | 27 +-
src/imap/main.c | 2
src/lda/main.c | 2
src/lib-master/master-service-settings.c | 8
src/lib-master/master-service-settings.h | 2
src/lib-storage/mail-storage-service.c | 2
src/lib-storage/mail-storage-service.h | 2
src/login-common/login-settings.c | 11 -
src/pop3/main.c | 2
diffs (truncated from 966 to 300 lines):
diff -r 7604073a4ccc -r 5d0a69504867 src/config/Makefile.am
--- a/src/config/Makefile.am Mon May 11 20:09:33 2009 -0400
+++ b/src/config/Makefile.am Mon May 11 20:10:30 2009 -0400
@@ -28,6 +28,7 @@ common = \
common = \
all-settings.c \
config-connection.c \
+ config-filter.c \
config-parser.c \
config-request.c \
sysinfo-get.c
@@ -43,6 +44,7 @@ noinst_HEADERS = \
noinst_HEADERS = \
all-settings.h \
config-connection.h \
+ config-filter.h \
config-parser.h \
config-request.h \
sysinfo-get.h
diff -r 7604073a4ccc -r 5d0a69504867 src/config/all-settings.h
--- a/src/config/all-settings.h Mon May 11 20:09:33 2009 -0400
+++ b/src/config/all-settings.h Mon May 11 20:10:30 2009 -0400
@@ -7,6 +7,7 @@ struct config_setting_parser_list {
struct setting_parser_context *parser;
void *settings;
};
+ARRAY_DEFINE_TYPE(config_setting_parsers, struct config_setting_parser_list *);
extern struct config_setting_parser_list config_setting_parsers[];
diff -r 7604073a4ccc -r 5d0a69504867 src/config/config-connection.c
--- a/src/config/config-connection.c Mon May 11 20:09:33 2009 -0400
+++ b/src/config/config-connection.c Mon May 11 20:10:30 2009 -0400
@@ -56,16 +56,34 @@ static void config_connection_request(st
static void config_connection_request(struct config_connection *conn,
const char *const *args)
{
- const char *service = "";
+ struct config_filter filter;
+ const char *module = "";
/* [<args>] */
+ memset(&filter, 0, sizeof(filter));
for (; *args != NULL; args++) {
if (strncmp(*args, "service=", 8) == 0)
- service = *args + 8;
+ filter.service = *args + 8;
+ else if (strncmp(*args, "module=", 7) == 0)
+ module = *args + 7;
+ else if (strncmp(*args, "lip=", 4) == 0) {
+ if (net_addr2ip(*args + 4, &filter.local_net) == 0) {
+ filter.local_bits =
+ IPADDR_IS_V4(&filter.local_net) ?
+ 32 : 128;
+ }
+ } else if (strncmp(*args, "rip=", 4) == 0) {
+ if (net_addr2ip(*args + 4, &filter.remote_net) == 0) {
+ filter.remote_bits =
+ IPADDR_IS_V4(&filter.remote_net) ?
+ 32 : 128;
+ }
+ }
}
o_stream_cork(conn->output);
- config_request_handle(service, 0, config_request_output, conn->output);
+ config_request_handle(&filter, module, 0, config_request_output,
+ conn->output);
o_stream_send_str(conn->output, "\n");
o_stream_uncork(conn->output);
}
diff -r 7604073a4ccc -r 5d0a69504867 src/config/config-filter.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/config/config-filter.c Mon May 11 20:10:30 2009 -0400
@@ -0,0 +1,120 @@
+/* Copyright (C) 2005-2009 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "array.h"
+#include "config-filter.h"
+
+struct config_filter_context {
+ pool_t pool;
+ struct config_filter_parser_list *const *parsers;
+};
+
+bool config_filter_match(const struct config_filter *mask,
+ const struct config_filter *filter)
+{
+ if (mask->service != NULL) {
+ if (filter->service == NULL)
+ return FALSE;
+ if (strcasecmp(filter->service, mask->service) != 0)
+ return FALSE;
+ }
+ /* FIXME: it's not comparing full masks */
+ if (mask->remote_bits != 0) {
+ if (filter->remote_bits == 0)
+ return FALSE;
+ if (!net_is_in_network(&filter->remote_net, &mask->remote_net,
+ mask->remote_bits))
+ return FALSE;
+ }
+ if (mask->local_bits != 0) {
+ if (filter->local_bits == 0)
+ return FALSE;
+ if (!net_is_in_network(&filter->local_net, &mask->local_net,
+ mask->local_bits))
+ return FALSE;
+ }
+ return TRUE;
+}
+
+bool config_filters_equal(const struct config_filter *f1,
+ const struct config_filter *f2)
+{
+ if (null_strcmp(f1->service, f2->service) != 0)
+ return FALSE;
+
+ if (f1->remote_bits != f2->remote_bits)
+ return FALSE;
+ if (!net_ip_compare(&f1->remote_net, &f2->remote_net))
+ return FALSE;
+
+ if (f1->local_bits != f2->local_bits)
+ return FALSE;
+ if (!net_ip_compare(&f1->local_net, &f2->local_net))
+ return FALSE;
+
+ return TRUE;
+}
+
+struct config_filter_context *config_filter_init(pool_t pool)
+{
+ struct config_filter_context *ctx;
+
+ ctx = p_new(pool, struct config_filter_context, 1);
+ ctx->pool = pool;
+ return ctx;
+}
+
+void config_filter_deinit(struct config_filter_context **_ctx)
+{
+ struct config_filter_context *ctx = *_ctx;
+
+ *_ctx = NULL;
+
+ pool_unref(&ctx->pool);
+}
+
+void config_filter_add_all(struct config_filter_context *ctx,
+ struct config_filter_parser_list *const *parsers)
+{
+ ctx->parsers = parsers;
+}
+
+static int filter_cmp(const struct config_filter *f1,
+ const struct config_filter *f2)
+{
+ int ret;
+
+ ret = f2->remote_bits - f1->remote_bits;
+ if (ret != 0)
+ return ret;
+
+ ret = f2->local_bits - f1->local_bits;
+ if (ret != 0)
+ return ret;
+
+ if (f1->service != NULL)
+ return -1;
+ else
+ return 1;
+}
+
+const struct config_setting_parser_list *
+config_filter_match_parsers(struct config_filter_context *ctx,
+ const struct config_filter *filter)
+{
+ struct config_filter_parser_list *best = NULL;
+ unsigned int i;
+
+ /* find the filter that best matches what we have.
+ FIXME: this can't really work. we'd want to merge changes from
+ different matches.. requires something larger after all. */
+ for (i = 0; ctx->parsers[i] != NULL; i++) {
+ if (!config_filter_match(&ctx->parsers[i]->filter, filter))
+ continue;
+
+ if (best == NULL ||
+ filter_cmp(&best->filter, &ctx->parsers[i]->filter) > 0)
+ best = ctx->parsers[i];
+ }
+ return best == NULL ? NULL : best->parser_list;
+}
diff -r 7604073a4ccc -r 5d0a69504867 src/config/config-filter.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/config/config-filter.h Mon May 11 20:10:30 2009 -0400
@@ -0,0 +1,35 @@
+#ifndef CONFIG_FILTER_H
+#define CONFIG_FILTER_H
+
+#include "network.h"
+#include "all-settings.h"
+
+struct config_filter {
+ const char *service;
+ struct ip_addr local_net, remote_net;
+ unsigned int local_bits, remote_bits;
+};
+
+struct config_filter_parser_list {
+ struct config_filter filter;
+ struct config_setting_parser_list *parser_list;
+};
+
+struct config_filter_context *config_filter_init(pool_t pool);
+void config_filter_deinit(struct config_filter_context **ctx);
+
+void config_filter_add_all(struct config_filter_context *ctx,
+ struct config_filter_parser_list *const *parsers);
+
+const struct config_setting_parser_list *
+config_filter_match_parsers(struct config_filter_context *ctx,
+ const struct config_filter *filter);
+
+/* Returns TRUE if filter matches mask. */
+bool config_filter_match(const struct config_filter *mask,
+ const struct config_filter *filter);
+/* Returns TRUE if two filters are fully equal. */
+bool config_filters_equal(const struct config_filter *f1,
+ const struct config_filter *f2);
+
+#endif
diff -r 7604073a4ccc -r 5d0a69504867 src/config/config-parser.c
--- a/src/config/config-parser.c Mon May 11 20:09:33 2009 -0400
+++ b/src/config/config-parser.c Mon May 11 20:10:30 2009 -0400
@@ -7,13 +7,19 @@
#include "strescape.h"
#include "istream.h"
#include "settings-parser.h"
-#include "all-settings.h"
+#include "config-filter.h"
#include "config-parser.h"
#include <unistd.h>
#include <fcntl.h>
#define IS_WHITE(c) ((c) == ' ' || (c) == '\t')
+
+struct config_filter_stack {
+ struct config_filter_stack *prev;
+ struct config_filter filter;
+ unsigned int pathlen;
+};
struct input_stack {
struct input_stack *prev;
@@ -22,6 +28,21 @@ struct input_stack {
const char *path;
unsigned int linenum;
};
+
+struct parser_context {
+ pool_t pool;
+ const char *path;
+
+ ARRAY_DEFINE(all_parsers, struct config_filter_parser_list *);
+ /* parsers matching cur_filter */
+ ARRAY_TYPE(config_setting_parsers) cur_parsers;
+ struct config_filter_stack *cur_filter;
+ struct input_stack *cur_input;
+
+ struct config_filter_context *filter;
+};
+
+struct config_filter_context *config_filter;
static const char *info_type_name_find(const struct setting_parser_info *info)
{
@@ -62,13 +83,15 @@ static void config_add_type(struct setti
}
static const char *
-config_parse_line(const char *key, const char *line, const char *section_name)
+config_parsers_parse_line(struct config_setting_parser_list *parsers,
+ const char *key, const char *line,
+ const char *section_name)
{
struct config_setting_parser_list *l;
bool found = FALSE;
int ret;
- for (l = config_setting_parsers; l->module_name != NULL; l++) {
+ for (l = parsers; l->module_name != NULL; l++) {
ret = settings_parse_line(l->parser, line);
if (ret > 0) {
found = TRUE;
@@ -82,6 +105,21 @@ config_parse_line(const char *key, const
}
More information about the dovecot-cvs
mailing list