PA(trie_t) tries;
A(int) weights;
A(bool) reverses;
+ A(bool) partiales;
int soft_threshold;
int hard_threshold;
unsigned is_email :1;
+ unsigned is_hostname :1;
+
unsigned match_sender :1;
unsigned match_recipient :1;
- unsigned is_hostname :1;
unsigned match_helo :1;
unsigned match_client :1;
unsigned match_reverse :1;
array_deep_wipe((*config)->tries, trie_delete);
array_wipe((*config)->weights);
array_wipe((*config)->reverses);
+ array_wipe((*config)->partiales);
p_delete(config);
}
}
--end;
}
if (end != map.end) {
- syslog(LOG_WARNING, "file %s miss a final \\n, ignoring last line",
- file);
+ warn("file %s miss a final \\n, ignoring last line",
+ file);
}
db = trie_new();
eol = end;
}
if (eol - p >= BUFSIZ) {
- syslog(LOG_ERR, "unreasonnable long line");
+ err("unreasonnable long line");
file_map_close(&map);
trie_delete(&db);
return NULL;
#define PARSE_CHECK(Expr, Str, ...) \
if (!(Expr)) { \
- syslog(LOG_ERR, Str, ##__VA_ARGS__); \
+ err(Str, ##__VA_ARGS__); \
strlist_config_delete(&config); \
return false; \
}
bool lock = false;
int weight = 0;
bool reverse = false;
+ bool partial = false;
trie_t *trie = NULL;
const char *current = param->value;
const char *p = m_strchrnul(param->value, ':');
break;
case 1:
+ if (p - current > (ssize_t)strlen("partial-")
+ && strncmp(current, "partial-", strlen("partial-")) == 0) {
+ partial = true;
+ current += strlen("partial-");
+ }
if ((p - current) == 6 && strncmp(current, "suffix", 6) == 0) {
reverse = true;
} else if ((p - current) == 6 && strncmp(current, "prefix", 6) == 0) {
array_add(config->tries, trie);
array_add(config->weights, weight);
array_add(config->reverses, reverse);
+ array_add(config->partiales, partial);
break;
}
if (i != 3) {
CASE(HELO_NAME, helo, hostname);
CASE(CLIENT_NAME, client, hostname);
CASE(REVERSE_CLIENT_NAME, reverse, hostname);
+ CASE(SENDER_DOMAIN, sender, hostname);
+ CASE(RECIPIENT_DOMAIN, recipient, hostname);
CASE(SENDER, sender, email);
CASE(RECIPIENT, recipient, email);
#undef CASE
if (config->is_email &&
((config->match_sender && query->state < SMTP_MAIL)
|| (config->match_recipient && query->state != SMTP_RCPT))) {
- syslog(LOG_WARNING, "trying to match an email against a field that is not "
- "available in current protocol state");
+ warn("trying to match an email against a field that is not "
+ "available in current protocol state");
return HTK_ABORT;
} else if (config->is_hostname && config->match_helo && query->state < SMTP_HELO) {
- syslog(LOG_WARNING, "trying to match hostname against helo before helo "
- "is received");
+ warn("trying to match hostname against helo before helo is received");
return HTK_ABORT;
}
#define LOOKUP(Flag, Field) \
- if (config->match_ ## Flag) { \
- const int len = m_strlen(query->Field); \
- strlist_copy(normal, query->Field, len, false); \
- strlist_copy(reverse, query->Field, len, true); \
- for (int i = 0 ; i < config->tries.len ; ++i) { \
- const int weight = array_elt(config->weights, i); \
- const trie_t *trie = array_elt(config->tries, i); \
- const bool rev = array_elt(config->reverses, i); \
- if (trie_lookup(trie, rev ? reverse : normal)) { \
- sum += weight; \
- } \
- } \
+ if (config->match_ ## Flag) { \
+ const int len = m_strlen(query->Field); \
+ strlist_copy(normal, query->Field, len, false); \
+ strlist_copy(reverse, query->Field, len, true); \
+ for (uint32_t i = 0 ; i < config->tries.len ; ++i) { \
+ const int weight = array_elt(config->weights, i); \
+ const trie_t *trie = array_elt(config->tries, i); \
+ const bool rev = array_elt(config->reverses, i); \
+ const bool part = array_elt(config->partiales, i); \
+ if ((!part && trie_lookup(trie, rev ? reverse : normal)) \
+ || (part && trie_prefix(trie, rev ? reverse : normal))) { \
+ sum += weight; \
+ if (sum >= config->hard_threshold) { \
+ return HTK_HARD_MATCH; \
+ } \
+ } \
+ } \
}
if (config->is_email) {
LOOKUP(sender, sender);
LOOKUP(helo, helo_name);
LOOKUP(client, client_name);
LOOKUP(reverse, reverse_client_name);
+ LOOKUP(recipient, recipient_domain);
+ LOOKUP(sender, sender_domain);
}
#undef LOOKUP
if (sum >= config->hard_threshold) {