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