/* products derived from this software without specific prior written */
/* permission. */
/* */
-/* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND */
-/* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE */
-/* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR */
-/* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS */
-/* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR */
-/* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF */
-/* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS */
-/* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN */
-/* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) */
-/* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF */
-/* THE POSSIBILITY OF SUCH DAMAGE. */
+/* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS */
+/* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED */
+/* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE */
+/* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY */
+/* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL */
+/* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS */
+/* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) */
+/* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, */
+/* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN */
+/* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE */
+/* POSSIBILITY OF SUCH DAMAGE. */
+/* */
+/* Copyright (c) 2006-2008 the Authors */
+/* see AUTHORS and source files for details */
/******************************************************************************/
/*
#include "query.h"
#define DAEMON_NAME "postlicyd"
-#define DAEMON_VERSION "0.3"
+#define DAEMON_VERSION "0.5"
#define DEFAULT_PORT 10000
#define RUNAS_USER "nobody"
#define RUNAS_GROUP "nogroup"
if (filter_running > 0) {
return true;
}
+ log_state = "refreshing ";
+ info("reloading configuration");
bool ret = config_reload(mconfig);
+ log_state = "";
foreach (client_t **server, busy) {
client_io_ro(*server);
}}
/* Write reply "action=ACTION [text]" */
buffer_addstr(buf, "action=");
- buffer_ensure(buf, m_strlen(message) + 64);
-
- ssize_t size = array_size(*buf) - array_len(*buf);
- ssize_t format_size = query_format(array_ptr(*buf, array_len(*buf)),
- size, message, query);
- if (format_size == -1) {
+ if (!query_format_buffer(buf, message, query)) {
buffer_addstr(buf, message);
- } else if (format_size > size) {
- buffer_ensure(buf, format_size + 1);
- query_format(array_ptr(*buf, array_len(*buf)),
- array_size(*buf) - array_len(*buf),
- message, query);
- array_len(*buf) += format_size;
- } else {
- array_len(*buf) += format_size;
}
buffer_addstr(buf, "\n\n");
static const filter_t *next_filter(client_t *pcy, const filter_t *filter,
const query_t *query, const filter_hook_t *hook, bool *ok) {
+ char log_prefix[BUFSIZ];
+ log_prefix[0] = '\0';
+
+#define log_reply(Level, Msg, ...) \
+ if (log_level >= LOG_ ## Level) { \
+ if (log_prefix[0] == '\0') { \
+ query_format(log_prefix, BUFSIZ, \
+ config->log_format && config->log_format[0] ? \
+ config->log_format : DEFAULT_LOG_FORMAT, query); \
+ } \
+ __log(LOG_ ## Level, "%s: " Msg, log_prefix, ##__VA_ARGS__); \
+ }
+
if (hook != NULL) {
query_context_t *context = client_data(pcy);
if (hook->counter >= 0 && hook->counter < MAX_COUNTERS && hook->cost > 0) {
context->context.counters[hook->counter] += hook->cost;
- debug("request client=%s, from=<%s>, to=<%s>: added %d to counter %d (now %u)",
- query->client_name,
- query->sender == NULL ? "undefined" : query->sender,
- query->recipient == NULL ? "undefined" : query->recipient,
- hook->cost, hook->counter, context->context.counters[hook->counter]);
+ log_reply(DEBUG, "added %d to counter %d (now %u)",
+ hook->cost, hook->counter,
+ context->context.counters[hook->counter]);
}
}
if (hook == NULL) {
- warn("request client=%s, from=<%s>, to=<%s>: aborted",
- query->client_name,
- query->sender == NULL ? "undefined" : query->sender,
- query->recipient == NULL ? "undefined" : query->recipient);
+ log_reply(WARNING, "aborted");
*ok = false;
return NULL;
} else if (hook->async) {
- debug("request client=%s, from=<%s>, to=<%s>: "
- "asynchronous filter from filter %s",
- query->client_name,
- query->sender == NULL ? "undefined" : query->sender,
- query->recipient == NULL ? "undefined" : query->recipient,
- filter->name);
+ log_reply(WARNING, "asynchronous filter from filter %s", filter->name);
*ok = true;
return NULL;
} else if (hook->postfix) {
- info("request client=%s, from=<%s>, to=<%s>: "
- "awswer %s from filter %s: \"%s\"",
- query->client_name,
- query->sender == NULL ? "undefined" : query->sender,
- query->recipient == NULL ? "undefined" : query->recipient,
- htokens[hook->type], filter->name, hook->value);
+ log_reply(INFO, "answer %s from filter %s: \"%s\"",
+ htokens[hook->type], filter->name, hook->value);
policy_answer(pcy, hook->value);
*ok = true;
return NULL;
} else {
- debug("request client=%s, from=<%s>, to=<%s>: "
- "awswer %s from filter %s: next filter %s",
- query->client_name,
- query->sender == NULL ? "undefined" : query->sender,
- query->recipient == NULL ? "undefined" : query->recipient,
- htokens[hook->type], filter->name,
- (array_ptr(config->filters, hook->filter_id))->name);
+ log_reply(DEBUG, "answer %s from filter %s: next filter %s",
+ htokens[hook->type], filter->name,
+ (array_ptr(config->filters, hook->filter_id))->name);
return array_ptr(config->filters, hook->filter_id);
}
+#undef log_reply
}
static bool policy_process(client_t *pcy, const config_t *mconfig)
const query_t* query = &context->query;
const filter_t *filter;
if (mconfig->entry_points[query->state] == -1) {
- warn("no filter defined for current protocol_state (%d)", query->state);
+ warn("no filter defined for current protocol_state (%s)", smtp_state_names[query->state].str);
return false;
}
if (context->context.current_filter != NULL) {
query->eoq = eoq + strlen("\n\n");
/* The instance changed => reset the static context */
- if (query->instance == NULL || strcmp(context->context.instance, query->instance) != 0) {
+ if (query->instance.str == NULL || query->instance.len == 0
+ || strcmp(context->context.instance, query->instance.str) != 0) {
filter_context_clean(&context->context);
- m_strcat(context->context.instance, 64, query->instance);
+ m_strcat(context->context.instance, 64, query->instance.str);
}
client_io_none(pcy);
return policy_process(pcy, mconfig) ? 0 : -1;
" -f stay in foreground\n"
" -d grow logging level\n"
" -u unsafe mode (don't drop privileges)\n"
+ " -c check-conf\n"
, stderr);
}
bool daemonize = true;
int port = DEFAULT_PORT;
bool port_from_cli = false;
+ bool check_conf = false;
- for (int c = 0; (c = getopt(argc, argv, "ufd" "l:p:")) >= 0; ) {
+ for (int c = 0; (c = getopt(argc, argv, "hufdc" "l:p:")) >= 0; ) {
switch (c) {
case 'p':
pidfile = optarg;
case 'd':
++log_level;
break;
+ case 'c':
+ check_conf = true;
+ daemonize = false;
+ unsafe = true;
+ break;
default:
usage();
return EXIT_FAILURE;
return EXIT_FAILURE;
}
- info("starting %s v%s...", DAEMON_NAME, DAEMON_VERSION);
+ if (check_conf) {
+ return config_check(argv[optind]) ? EXIT_SUCCESS : EXIT_FAILURE;
+ }
+ info("%s v%s...", DAEMON_NAME, DAEMON_VERSION);
if (pidfile_open(pidfile) < 0) {
crit("unable to write pidfile %s", pidfile);