#include "match.hpp"
#include <vector>
typedef Match*(*getinst_t)(Match*, const char*, size_t);
static __attribute__((init_priority(101))) std::vector<std::pair<const char*, getinst_t> > matches;
void register_match(const char* type, getinst_t getinst) {
matches.push_back(std::pair<const char*, getinst_t>(type, getinst));
}
Match::Match(Match* n, size_t mi, size_t ma): next(n), mymin(mi), mymax(ma), min(mi), max(ma) {
}
Match::~Match() {
if (next) delete next; // bubble up
}
bool Match::runall(packet_t* p, size_t off, NFQ::result_t& result) {
if (off + p->dlen < min) return true;
if (off > max) return false; // never again
Match* inst = this;
do {
inst->run(p, off, result);
inst = inst->next;
} while (inst);
return true;
}
Match* Match::parse(Match* list, const char* buf, size_t len) {
while (len && (*buf == ' ' || *buf == '\t')) {
buf++;
len--;
}
for (std::vector<std::pair<const char*, getinst_t> >::iterator it = matches.begin(); it != matches.end(); it++) {
size_t tl = strlen(it->first);
if (tl <= len && strncmp(buf, it->first, tl) == 0 && (buf[tl] == ' ' || buf[tl] == '\t')) {
Match* inst = it->second(list, buf+tl+1, len-tl-1);
if (inst && !inst->is_valid()) {
LOG("cannot parse '%s' match '%.*s'", it->first, (int)len, buf);
delete inst;
inst = NULL;
} else if (inst && list) {
inst->min = MIN(inst->min, list->min);
inst->max = MAX(inst->max, list->max);
}
return inst;
}
}
LOG("cannot find match for list line '%.*s'", (int)len, buf);
return NULL;
}