+static const filter_t *next_filter(client_t *pcy, const filter_t *filter,
+ const query_t *query, const filter_hook_t *hook, bool *ok) {
+#define MESSAGE_FORMAT "request client=%s from=<%s> to=<%s> at %s: "
+#define MESSAGE_PARAMS query->client_name, \
+ query->sender == NULL ? "undefined" : query->sender, \
+ query->recipient == NULL ? "undefined" : query->recipient, \
+ smtp_state_names[query->state]
+
+ 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(MESSAGE_FORMAT "added %d to counter %d (now %u)", MESSAGE_PARAMS,
+ hook->cost, hook->counter, context->context.counters[hook->counter]);
+ }
+ }
+ if (hook == NULL) {
+ warn(MESSAGE_FORMAT "aborted", MESSAGE_PARAMS);
+ *ok = false;
+ return NULL;
+ } else if (hook->async) {
+ debug(MESSAGE_FORMAT "asynchronous filter from filter %s",
+ MESSAGE_PARAMS, filter->name);
+ *ok = true;
+ return NULL;
+ } else if (hook->postfix) {
+ info(MESSAGE_FORMAT "awswer %s from filter %s: \"%s\"", MESSAGE_PARAMS,
+ htokens[hook->type], filter->name, hook->value);
+ policy_answer(pcy, hook->value);
+ *ok = true;
+ return NULL;
+ } else {
+ debug(MESSAGE_FORMAT "awswer %s from filter %s: next filter %s",
+ MESSAGE_PARAMS, htokens[hook->type], filter->name,
+ (array_ptr(config->filters, hook->filter_id))->name);
+ return array_ptr(config->filters, hook->filter_id);
+ }
+#undef MESSAGE_PARAMS
+#undef MESSAGE_FORMAT
+}
+
+static bool policy_process(client_t *pcy, const config_t *mconfig)