summaryrefslogtreecommitdiff
path: root/src/filter.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/filter.c')
-rw-r--r--src/filter.c78
1 files changed, 67 insertions, 11 deletions
diff --git a/src/filter.c b/src/filter.c
index afefbfa..1ae2cc5 100644
--- a/src/filter.c
+++ b/src/filter.c
@@ -1,6 +1,7 @@
/*
- * (C) 2006-2008 by Pablo Neira Ayuso <pablo@netfilter.org>
- *
+ * (C) 2006-2012 by Pablo Neira Ayuso <pablo@netfilter.org>
+ * (C) 2011-2012 by Vyatta Inc <http://www.vyatta.com>
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
@@ -32,8 +33,8 @@
struct ct_filter {
int logic[CT_FILTER_MAX];
- u_int32_t l4protomap[IPPROTO_MAX/32];
- u_int16_t statemap[IPPROTO_MAX];
+ uint32_t l4protomap[IPPROTO_MAX/32];
+ uint16_t statemap[IPPROTO_MAX];
struct hashtable *h;
struct hashtable *h6;
struct vector *v;
@@ -372,8 +373,8 @@ static inline int ct_filter_sanity_check(const struct nf_conntrack *ct)
switch(nfct_get_attr_u8(ct, ATTR_L3PROTO)) {
case AF_INET:
- if (!nfct_attr_is_set(ct, ATTR_IPV4_SRC) ||
- !nfct_attr_is_set(ct, ATTR_IPV4_DST)) {
+ if (!nfct_attr_is_set(ct, ATTR_ORIG_IPV4_SRC) ||
+ !nfct_attr_is_set(ct, ATTR_REPL_IPV4_SRC)) {
dlog(LOG_ERR, "missing IPv4 address. "
"You forgot to load "
"nf_conntrack_ipv4?");
@@ -381,8 +382,8 @@ static inline int ct_filter_sanity_check(const struct nf_conntrack *ct)
}
break;
case AF_INET6:
- if (!nfct_attr_is_set(ct, ATTR_IPV6_SRC) ||
- !nfct_attr_is_set(ct, ATTR_IPV6_DST)) {
+ if (!nfct_attr_is_set(ct, ATTR_ORIG_IPV6_SRC) ||
+ !nfct_attr_is_set(ct, ATTR_REPL_IPV6_SRC)) {
dlog(LOG_ERR, "missing IPv6 address. "
"You forgot to load "
"nf_conntrack_ipv6?");
@@ -406,6 +407,51 @@ int ct_filter_conntrack(const struct nf_conntrack *ct, int userspace)
return 0;
}
+static inline int
+ct_filter_master_sanity_check(const struct nf_conntrack *master)
+{
+ if (master == NULL) {
+ dlog(LOG_ERR, "no master tuple in expectation");
+ return 0;
+ }
+
+ if (!nfct_attr_is_set(master, ATTR_L3PROTO)) {
+ dlog(LOG_ERR, "missing layer 3 protocol");
+ return 0;
+ }
+
+ switch (nfct_get_attr_u8(master, ATTR_L3PROTO)) {
+ case AF_INET:
+ if (!nfct_attr_is_set(master, ATTR_IPV4_SRC) ||
+ !nfct_attr_is_set(master, ATTR_IPV4_DST)) {
+ dlog(LOG_ERR, "missing IPv4 address. "
+ "You forgot to load nf_conntrack_ipv4?");
+ return 0;
+ }
+ break;
+ case AF_INET6:
+ if (!nfct_attr_is_set(master, ATTR_IPV6_SRC) ||
+ !nfct_attr_is_set(master, ATTR_IPV6_DST)) {
+ dlog(LOG_ERR, "missing IPv6 address. "
+ "You forgot to load nf_conntrack_ipv6?");
+ return 0;
+ }
+ break;
+ }
+ return 1;
+}
+
+int ct_filter_master(const struct nf_conntrack *master)
+{
+ if (!ct_filter_master_sanity_check(master))
+ return 1;
+
+ /* Check if we've got a master conntrack for this expectation in our
+ * caches. If there is not, we don't want this expectation either.
+ */
+ return STATE(mode)->internal->exp.find(master) ? 0 : 1;
+}
+
struct exp_filter {
struct list_head list;
};
@@ -449,7 +495,7 @@ int exp_filter_add(struct exp_filter *f, const char *helper_name)
return -1;
list_for_each_entry(item, &f->list, head) {
- if (strncmp(item->helper_name, helper_name,
+ if (strncasecmp(item->helper_name, helper_name,
NFCT_HELPER_NAME_MAX) == 0) {
return -1;
}
@@ -472,10 +518,20 @@ int exp_filter_find(struct exp_filter *f, const struct nf_expect *exp)
return 1;
list_for_each_entry(item, &f->list, head) {
- const char *name = nfexp_get_attr(exp, ATTR_EXP_HELPER_NAME);
+ const char *name;
+
+ if (nfexp_attr_is_set(exp, ATTR_EXP_HELPER_NAME))
+ name = nfexp_get_attr(exp, ATTR_EXP_HELPER_NAME);
+ else {
+ /* No helper name, this is likely to be a kernel older
+ * which does not include the helper name, just skip
+ * this so we don't crash.
+ */
+ return 0;
+ }
/* we allow partial matching to support things like sip-PORT. */
- if (strncmp(item->helper_name, name,
+ if (strncasecmp(item->helper_name, name,
strlen(item->helper_name)) == 0) {
return 1;
}