/* 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 */
/******************************************************************************/
/*
MATCH_EMPTY,
} condition;
- char *value;
- ssize_t value_len;
+ static_str_t value;
} match_condition_t;
ARRAY(match_condition_t)
"is empty"
};
-#define CONDITION_INIT { PTK_UNKNOWN, false, MATCH_UNKNOWN, NULL, 0 }
+#define CONDITION_INIT { PTK_UNKNOWN, false, MATCH_UNKNOWN, { NULL, 0 } }
typedef struct match_config_t {
A(match_condition_t) conditions;
static inline void match_condition_wipe(match_condition_t *condition)
{
- p_delete(&condition->value);
- condition->value_len = 0;
+ char *str = (char*)condition->value.str;
+ p_delete(&str);
+ condition->value.str = NULL;
+ condition->value.len = 0;
}
static void match_config_delete(match_config_t **config)
condition.field = policy_tokenize(p, n - p);
PARSE_CHECK(condition.field >= PTK_HELO_NAME
&& condition.field < PTK_SMTPD_ACCESS_POLICY,
- "invalid field name %.*s", n - p, p);
+ "invalid field name %.*s", (int)(n - p), p);
p = skipspaces(n);
n = p + 1;
PARSE_CHECK(IS_OP_START(*p) && IS_OP_END(*n),
if (condition.condition != MATCH_EMPTY) {
p = skipspaces(n + 1);
PARSE_CHECK(*p, "no value defined to check the condition");
- condition.value_len = param->value_len - (p - param->value);
- condition.value = p_dupstr(p, condition.value_len);
+ condition.value.len = param->value_len - (p - param->value);
+ condition.value.str = p_dupstr(p, condition.value.len);
}
array_add(config->conditions, condition);
} break;
static inline bool match_condition(const match_condition_t *cond, const query_t *query)
{
- const char *field = NULL;
- switch (cond->field) {
-#define CASE(Up, Low) \
- case PTK_ ## Up: field = query->Low; break;
- CASE(HELO_NAME, helo_name)
- CASE(QUEUE_ID, queue_id)
- CASE(SENDER, sender)
- CASE(RECIPIENT, recipient)
- CASE(RECIPIENT_COUNT, recipient_count)
- CASE(CLIENT_ADDRESS, client_address)
- CASE(CLIENT_NAME, client_name)
- CASE(REVERSE_CLIENT_NAME, reverse_client_name)
- CASE(INSTANCE, instance)
- CASE(SASL_METHOD, sasl_method)
- CASE(SASL_USERNAME, sasl_username)
- CASE(SASL_SENDER, sasl_sender)
- CASE(SIZE, size)
- CASE(CCERT_SUBJECT, ccert_subject)
- CASE(CCERT_ISSUER, ccert_issuer)
- CASE(CCERT_FINGERPRINT, ccert_fingerprint)
- CASE(ENCRYPTION_PROTOCOL, encryption_protocol)
- CASE(ENCRYPTION_CIPHER, encryption_cipher)
- CASE(ENCRYPTION_KEYSIZE, encryption_keysize)
- CASE(ETRN_DOMAIN, etrn_domain)
- CASE(STRESS, stress)
-#undef CASE
- default: return false;
- }
+ const static_str_t *field = query_field_for_id(query, cond->field);
debug("running condition: \"%s\" %s %s\"%s\"",
- field, condition_names[cond->condition],
+ field->str, condition_names[cond->condition],
cond->case_sensitive ? "" : "(alternative) ",
- cond->value ? cond->value : "(none)");
+ cond->value.str ? cond->value.str : "(none)");
switch (cond->condition) {
case MATCH_EQUAL:
case MATCH_DIFFER:
- if (field == NULL) {
+ if (field == NULL || field->str == NULL) {
return cond->condition != MATCH_DIFFER;
}
if (cond->case_sensitive) {
- return !!((strcmp(field, cond->value) == 0)
+ return !!((strcmp(field->str, cond->value.str) == 0)
^ (cond->condition == MATCH_DIFFER));
} else {
- return !!((ascii_strcasecmp(field, cond->value) == 0)
+ return !!((ascii_strcasecmp(field->str, cond->value.str) == 0)
^ (cond->condition == MATCH_DIFFER));
}
break;
case MATCH_CONTAINS:
- if (field == NULL) {
+ if (field == NULL || field->str == NULL) {
return false;
}
if (cond->case_sensitive) {
- return strstr(field, cond->value);
+ return strstr(field->str, cond->value.str);
} else {
- return m_stristrn(field, cond->value, cond->value_len);
+ return m_stristrn(field->str, cond->value.str, cond->value.len);
}
break;
case MATCH_CONTAINED:
- if (field == NULL) {
+ if (field == NULL || field->str == NULL) {
return false;
}
if (cond->case_sensitive) {
- return strstr(cond->value, field);
+ return strstr(cond->value.str, field->str);
} else {
- return m_stristr(cond->value, field);
+ return m_stristr(cond->value.str, field->str);
}
break;
case MATCH_EMPTY:
- return !!((field == NULL || *field == '\0') ^ (!cond->case_sensitive));
+ return !!((field == NULL || field->len == 0) ^ (!cond->case_sensitive));
default:
assert(false && "invalid condition type");
return true;
}
-static filter_result_t match_filter(const filter_t *filter, const query_t *query)
+static filter_result_t match_filter(const filter_t *filter, const query_t *query,
+ filter_context_t *context)
{
const match_config_t *config = filter->data;
foreach (const match_condition_t *condition, config->conditions) {
static int match_init(void)
{
filter_type_t type = filter_register("match", match_filter_constructor,
- match_filter_destructor, match_filter);
+ match_filter_destructor, match_filter,
+ NULL, NULL);
/* Hooks.
*/
(void)filter_hook_register(type, "abort");