summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRich Fought <Rich.Fought@watchguard.com>2012-10-12 17:44:27 -0700
committerRich Fought <Rich.Fought@watchguard.com>2012-10-12 17:44:27 -0700
commit07418658a6dae7243f2b7d51aebe9ad0299b40ad (patch)
tree99a416d779ecbc1c88177c347203f30e0daffb97
parent416459570ff8e714c9e072e42984db7f6ba8b977 (diff)
downloadlibnl-07418658a6dae7243f2b7d51aebe9ad0299b40ad.tar.gz
define advanced attributes out
-rw-r--r--include/netlink/netfilter/exp.h32
-rw-r--r--lib/netfilter/exp.c128
-rw-r--r--lib/netfilter/exp_obj.c75
3 files changed, 179 insertions, 56 deletions
diff --git a/include/netlink/netfilter/exp.h b/include/netlink/netfilter/exp.h
index bb4c98e..89a9d01 100644
--- a/include/netlink/netfilter/exp.h
+++ b/include/netlink/netfilter/exp.h
@@ -19,6 +19,19 @@
#include <netlink/cache.h>
#include <netlink/msg.h>
+#include <linux/version.h>
+
+#if CTA_EXPECT_MAX > CTA_EXPECT_HELP_NAME
+#define NLE_ZONE
+#elseif CTA_EXPECT_MAX > CTA_EXPECT_ZONE
+#define NLE_ZONE
+#define NLE_FLAGS
+#elseif (CTA_EXPECT_MAX > CTA_EXPECT_FLAGS)
+#define NLE_ZONE
+#define NLE_FLAGS
+#define NLE_NAT_FN_CLASS
+#endif
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -29,7 +42,10 @@ enum nfnl_exp_tuples {
NFNL_EXP_TUPLE_EXPECT,
NFNL_EXP_TUPLE_MASTER,
NFNL_EXP_TUPLE_MASK,
- NFNL_EXP_TUPLE_NAT
+#ifdef NLE_NAT_FN_CLASS
+ NFNL_EXP_TUPLE_NAT,
+#endif
+ NFNL_EXP_TUPLE_MAX
};
extern struct nl_object_ops exp_obj_ops;
@@ -72,17 +88,22 @@ extern int nfnl_exp_set_helper_name(struct nfnl_exp *, void *);
extern int nfnl_exp_test_helper_name(const struct nfnl_exp *);
extern const char * nfnl_exp_get_helper_name(const struct nfnl_exp *);
+#ifdef NLE_ZONE
extern void nfnl_exp_set_zone(struct nfnl_exp *, uint16_t);
extern int nfnl_exp_test_zone(const struct nfnl_exp *);
extern uint16_t nfnl_exp_get_zone(const struct nfnl_exp *);
+#endif
-extern void nfnl_exp_set_class(struct nfnl_exp *, uint32_t);
-extern int nfnl_exp_test_class(const struct nfnl_exp *);
-extern uint32_t nfnl_exp_get_class(const struct nfnl_exp *);
-
+#ifdef NLE_FLAGS
extern void nfnl_exp_set_flags(struct nfnl_exp *, uint32_t);
extern int nfnl_exp_test_flags(const struct nfnl_exp *);
extern uint32_t nfnl_exp_get_flags(const struct nfnl_exp *);
+#endif
+
+#ifdef NLE_NAT_FN_CLASS
+extern void nfnl_exp_set_class(struct nfnl_exp *, uint32_t);
+extern int nfnl_exp_test_class(const struct nfnl_exp *);
+extern uint32_t nfnl_exp_get_class(const struct nfnl_exp *);
extern int nfnl_exp_set_fn(struct nfnl_exp *, void *);
extern int nfnl_exp_test_fn(const struct nfnl_exp *);
@@ -91,6 +112,7 @@ extern const char * nfnl_exp_get_fn(const struct nfnl_exp *);
extern void nfnl_exp_set_nat_dir(struct nfnl_exp *, uint8_t);
extern int nfnl_exp_test_nat_dir(const struct nfnl_exp *);
extern uint8_t nfnl_exp_get_nat_dir(const struct nfnl_exp *);
+#endif
// The int argument specifies which nfnl_exp_dir (expect, master, mask or nat)
// Expectation objects only use orig, not reply
diff --git a/lib/netfilter/exp.c b/lib/netfilter/exp.c
index 26eaf0c..cbe1b95 100644
--- a/lib/netfilter/exp.c
+++ b/lib/netfilter/exp.c
@@ -37,12 +37,16 @@ static struct nla_policy exp_policy[CTA_EXPECT_MAX+1] = {
[CTA_EXPECT_TIMEOUT] = { .type = NLA_U32 },
[CTA_EXPECT_ID] = { .type = NLA_U32 },
[CTA_EXPECT_HELP_NAME] = { .type = NLA_STRING },
-#if 0
- [CTA_EXPECT_ZONE] = { .type = NLA_U16 }, // In latest kernel header
- [CTA_EXPECT_FLAGS] = { .type = NLA_U32 }, // In latest kernel header
- [CTA_EXPECT_CLASS] = { .type = NLA_U32 }, // In libnetfilter_conntrack include/linux/linux_nfnetlink_conntrack.h
- [CTA_EXPECT_NAT] = { .type = NLA_NESTED }, // In libnetfilter_conntrack include/linux/linux_nfnetlink_conntrack.h
- [CTA_EXPECT_FN] = { .type = NLA_STRING }, // In libnetfilter_conntrack include/linux/linux_nfnetlink_conntrack.h
+#ifdef NLE_ZONE
+ [CTA_EXPECT_ZONE] = { .type = NLA_U16 }, // Added in kernel 2.6.34
+#endif
+#ifdef NLE_FLAGS
+ [CTA_EXPECT_FLAGS] = { .type = NLA_U32 }, // Added in kernel 2.6.37
+#endif
+#ifdef NLE_NAT_FN_CLASS
+ [CTA_EXPECT_CLASS] = { .type = NLA_U32 }, // Added in kernel 3.5
+ [CTA_EXPECT_NAT] = { .type = NLA_NESTED }, // Added in kernel 3.5
+ [CTA_EXPECT_FN] = { .type = NLA_STRING }, // Added in kernel 3.5
#endif
};
@@ -59,10 +63,10 @@ static struct nla_policy exp_ip_policy[CTA_IP_MAX+1] = {
};
static struct nla_policy exp_proto_policy[CTA_PROTO_MAX+1] = {
- [CTA_PROTO_NUM] = { .type = NLA_U8 },
+ [CTA_PROTO_NUM] = { .type = NLA_U8 },
[CTA_PROTO_SRC_PORT] = { .type = NLA_U16 },
[CTA_PROTO_DST_PORT] = { .type = NLA_U16 },
- [CTA_PROTO_ICMP_ID] = { .type = NLA_U16 },
+ [CTA_PROTO_ICMP_ID] = { .type = NLA_U16 },
[CTA_PROTO_ICMP_TYPE] = { .type = NLA_U8 },
[CTA_PROTO_ICMP_CODE] = { .type = NLA_U8 },
[CTA_PROTO_ICMPV6_ID] = { .type = NLA_U16 },
@@ -70,6 +74,12 @@ static struct nla_policy exp_proto_policy[CTA_PROTO_MAX+1] = {
[CTA_PROTO_ICMPV6_CODE] = { .type = NLA_U8 },
};
+#ifdef NLE_NAT_FN_CLASS
+static struct nla_policy exp_nat_policy[CTA_EXPECT_NAT_MAX+1] = {
+ [CTA_EXPECT_NAT_DIR] = { .type = NLA_U8 },
+ [CTA_EXPECT_NAT_TUPLE] = { .type = NLA_NESTED },
+};
+#endif
static int exp_parse_ip(struct nfnl_exp *exp, int tuple, struct nlattr *attr)
{
@@ -182,6 +192,29 @@ static int exp_parse_tuple(struct nfnl_exp *exp, int tuple, struct nlattr *attr)
return 0;
}
+#ifdef NLE_NAT_FN_CLASS
+static int exp_parse_nat(struct nfnl_exp *exp, struct nlattr *attr)
+{
+ struct nlattr *tb[CTA_EXPECT_NAT_MAX+1];
+ int err;
+
+ err = nla_parse_nested(tb, CTA_EXPECT_NAT_MAX, attr, exp_nat_policy);
+ if (err < 0)
+ return err;
+
+ if (tb[CTA_EXPECT_NAT_DIR])
+ nfnl_exp_set_nat_dir(exp, nla_get_u8(tb[CTA_EXPECT_NAT_DIR]));
+
+ if (tb[CTA_EXPECT_NAT_TUPLE]) {
+ err = exp_parse_tuple(exp, NFNL_EXP_TUPLE_NAT, tb[CTA_EXPECT_NAT_TUPLE]);
+ if (err < 0)
+ return err;
+ }
+
+ return 0;
+}
+#endif
+
int nfnlmsg_exp_group(struct nlmsghdr *nlh)
{
switch (nfnlmsg_subtype(nlh)) {
@@ -232,13 +265,41 @@ int nfnlmsg_exp_parse(struct nlmsghdr *nlh, struct nfnl_exp **result)
goto errout;
}
+#ifdef NLE_NAT_FN_CLASS
+ if (tb[CTA_EXPECT_NAT])
+ err = exp_parse_nat(exp, tb[CTA_EXPECT_MASK]);
+ if (err < 0)
+ goto errout;
+
+ if (tb[CTA_EXPECT_CLASS])
+ nfnl_exp_set_class(exp, ntohl(nla_get_u32(tb[CTA_EXPECT_CLASS])));
+
+ if (tb[CTA_EXPECT_FN])
+ nfnl_exp_set_fn(exp, nla_data(tb[CTA_EXPECT_FN]));
+
+#endif
+
+
if (tb[CTA_EXPECT_TIMEOUT])
nfnl_exp_set_timeout(exp, ntohl(nla_get_u32(tb[CTA_EXPECT_TIMEOUT])));
+
if (tb[CTA_EXPECT_ID])
nfnl_exp_set_id(exp, ntohl(nla_get_u32(tb[CTA_EXPECT_ID])));
- if (tb[CTA_EXPECT_HELP_NAME])
+
+ if (tb[CTA_EXPECT_HELP_NAME])
nfnl_exp_set_helper_name(exp, nla_data(tb[CTA_EXPECT_HELP_NAME]));
+#ifdef NLE_ZONE
+ if (tb[CTA_EXPECT_ZONE])
+ nfnl_exp_set_zone(exp, ntohs(nla_get_u16(tb[CTA_EXPECT_ZONE])));
+#endif
+
+#ifdef NLE_FLAGS
+ if (tb[CTA_EXPECT_FLAGS])
+ nfnl_exp_set_flags(exp, ntohl(nla_get_u32(tb[CTA_EXPECT_FLAGS])));
+#endif
+
+
*result = exp;
return 0;
@@ -364,6 +425,30 @@ nla_put_failure:
return -NLE_MSGSIZE;
}
+#ifdef NLE_NAT_FN_CLASS
+static int nfnl_exp_build_nat(struct nl_msg *msg, const struct nfnl_exp *exp)
+{
+ struct nlattr *nat;
+ int err;
+
+ nat = nla_nest_start(msg, CTA_EXPECT_NAT);
+
+ if (nfnl_exp_test_nat_dir(exp)) {
+ NLA_PUT_U8(msg, CTA_EXPECT_NAT_DIR,
+ nfnl_exp_get_nat_dir(exp));
+ }
+
+ if ((err = nfnl_exp_build_tuple(msg, exp, CTA_EXPECT_NAT_TUPLE)) < 0)
+ goto nla_put_failure;
+
+ nla_nest_end(msg, nat);
+ return 0;
+
+nla_put_failure:
+ return -NLE_MSGSIZE;
+}
+#endif
+
static int nfnl_exp_build_message(const struct nfnl_exp *exp, int cmd, int flags,
struct nl_msg **result)
{
@@ -384,7 +469,20 @@ static int nfnl_exp_build_message(const struct nfnl_exp *exp, int cmd, int flags
if ((err = nfnl_exp_build_tuple(msg, exp, CTA_EXPECT_MASK)) < 0)
goto err_out;
- // FIXME timeout and helper name
+#ifdef NLE_NAT_FN_CLASS
+ if (nfnl_exp_test_src(exp, NFNL_EXP_TUPLE_NAT)) {
+ if ((err = nfnl_exp_build_nat(msg, exp)) < 0)
+ goto err_out;
+ }
+
+ if (nfnl_exp_test_class(exp))
+ NLA_PUT_U32(msg, CTA_EXPECT_CLASS, htonl(nfnl_exp_get_class(exp)));
+
+ if (nfnl_exp_test_fn(exp))
+ NLA_PUT_STRING(msg, CTA_EXPECT_FN, nfnl_exp_get_fn(exp));
+
+#endif
+
if (nfnl_exp_test_id(exp))
NLA_PUT_U32(msg, CTA_EXPECT_ID, htonl(nfnl_exp_get_id(exp)));
@@ -394,6 +492,16 @@ static int nfnl_exp_build_message(const struct nfnl_exp *exp, int cmd, int flags
if (nfnl_exp_test_helper_name(exp))
NLA_PUT_STRING(msg, CTA_EXPECT_HELP_NAME, nfnl_exp_get_helper_name(exp));
+#ifdef NLE_ZONE
+ if (nfnl_exp_test_zone(exp))
+ NLA_PUT_U16(msg, CTA_EXPECT_ZONE, htons(nfnl_exp_get_zone(exp)));
+#endif
+
+#ifdef NLE_FLAGS
+ if (nfnl_exp_test_flags(exp))
+ NLA_PUT_U32(msg, CTA_EXPECT_FLAGS, htonl(nfnl_exp_get_flags(exp)));
+#endif
+
*result = msg;
return 0;
diff --git a/lib/netfilter/exp_obj.c b/lib/netfilter/exp_obj.c
index 69ba324..daf4b09 100644
--- a/lib/netfilter/exp_obj.c
+++ b/lib/netfilter/exp_obj.c
@@ -33,10 +33,9 @@
#define EXP_ATTR_ID (1UL << 2) // 32-bit
#define EXP_ATTR_HELPER_NAME (1UL << 3) // string (16 bytes max)
#define EXP_ATTR_ZONE (1UL << 4) // 16-bit
-#define EXP_ATTR_CLASS (1UL << 5) // 32-bit ???
-#define EXP_ATTR_FLAGS (1UL << 6) // 32-bit
+#define EXP_ATTR_FLAGS (1UL << 5) // 32-bit
+#define EXP_ATTR_CLASS (1UL << 6) // 32-bit ???
#define EXP_ATTR_FN (1UL << 7) // String ???
-
// Tuples
#define EXP_ATTR_EXPECT_IP_SRC (1UL << 8)
#define EXP_ATTR_EXPECT_IP_DST (1UL << 9)
@@ -188,7 +187,7 @@ static void exp_dump_tuples(struct nfnl_exp *exp, struct nl_dump_params *p)
int i = 0;
char buf[64];
- for (i = NFNL_EXP_TUPLE_EXPECT; i <= NFNL_EXP_TUPLE_NAT; i++) {
+ for (i = NFNL_EXP_TUPLE_EXPECT; i < NFNL_EXP_TUPLE_MAX; i++) {
tuple_src = NULL;
tuple_dst = NULL;
tuple_sport = 0;
@@ -216,8 +215,10 @@ static void exp_dump_tuples(struct nfnl_exp *exp, struct nl_dump_params *p)
dump_icmp(p, exp, 0);
}
+#ifdef NLE_NAT_FN_CLASS
if (nfnl_exp_test_nat_dir(exp))
nl_dump(p, "nat dir %s ", exp->exp_nat_dir);
+#endif
}
@@ -254,18 +255,22 @@ static void exp_dump_details(struct nl_object *a, struct nl_dump_params *p)
if (nfnl_exp_test_helper_name(exp))
nl_dump(p, "helper %s ", exp->exp_helper_name);
+#ifdef NLE_NAT_FN_CLASS
if (nfnl_exp_test_fn(exp))
nl_dump(p, "fn %s ", exp->exp_fn);
- if (nfnl_exp_test_zone(exp))
- nl_dump(p, "zone %u ", nfnl_exp_get_zone(exp));
-
if (nfnl_exp_test_class(exp))
nl_dump(p, "class %u ", nfnl_exp_get_class(exp));
+#endif
- if (nfnl_exp_test_flags(exp))
- nl_dump(p, "<");
+#ifdef NLE_ZONE
+ if (nfnl_exp_test_zone(exp))
+ nl_dump(p, "zone %u ", nfnl_exp_get_zone(exp));
+#endif
+#ifdef NLE_FLAGS
+ if (nfnl_exp_test_flags(exp))
+ nl_dump(p, "<");
#define PRINT_FLAG(str) \
{ nl_dump(p, "%s%s", fp++ ? "," : "", (str)); }
@@ -279,40 +284,10 @@ static void exp_dump_details(struct nl_object *a, struct nl_dump_params *p)
if (nfnl_exp_test_flags(exp))
nl_dump(p, ">");
- nl_dump(p, "\n");
-}
+#endif
-/*
-static void ct_dump_stats(struct nl_object *a, struct nl_dump_params *p)
-{
- struct nfnl_ct *ct = (struct nfnl_ct *) a;
- double res;
- char *unit;
- uint64_t packets;
- const char * const names[] = {"rx", "tx"};
- int i;
-
- ct_dump_details(a, p);
-
- if (!nfnl_ct_test_bytes(ct, 0) ||
- !nfnl_ct_test_packets(ct, 0) ||
- !nfnl_ct_test_bytes(ct, 1) ||
- !nfnl_ct_test_packets(ct, 1))
- {
- nl_dump_line(p, " Statistics are not available.\n");
- nl_dump_line(p, " Please set sysctl net.netfilter.nf_conntrack_acct=1\n");
- nl_dump_line(p, " (Require kernel 2.6.27)\n");
- return;
- }
-
- nl_dump_line(p, " # packets volume\n");
- for (i=0; i<=1; i++) {
- res = nl_cancel_down_bytes(nfnl_ct_get_bytes(ct, i), &unit);
- packets = nfnl_ct_get_packets(ct, i);
- nl_dump_line(p, " %s %10" PRIu64 " %7.2f %s\n", names[i], packets, res, unit);
- }
+ nl_dump(p, "\n");
}
-*/
static int exp_cmp_l4proto_ports (union nfnl_exp_protodata *a, union nfnl_exp_protodata *b) {
// Must return 0 for match, 1 for mismatch
@@ -637,6 +612,7 @@ uint8_t nfnl_exp_get_nat_dir(const struct nfnl_exp *exp)
return exp->exp_nat_dir;
}
+#ifdef NLE_NAT_FN_CLASS
#define EXP_GET_TUPLE(e, t) \
(t == NFNL_EXP_TUPLE_MASTER) ? \
&(e->exp_master) : \
@@ -644,6 +620,13 @@ uint8_t nfnl_exp_get_nat_dir(const struct nfnl_exp *exp)
&(e->exp_mask) : \
(t == NFNL_EXP_TUPLE_NAT) ? \
&(e->exp_nat) : &(exp->exp_expect)
+#else
+#define EXP_GET_TUPLE(e, t) \
+ (t == NFNL_EXP_TUPLE_MASTER) ? \
+ &(e->exp_master) : \
+ (t == NFNL_EXP_TUPLE_MASK) ? \
+ &(e->exp_mask) : &(exp->exp_expect)
+#endif
static int exp_get_src_attr(int tuple)
{
@@ -656,9 +639,11 @@ static int exp_get_src_attr(int tuple)
case NFNL_EXP_TUPLE_MASK:
attr = EXP_ATTR_MASK_IP_SRC;
break;
+#ifdef NLE_NAT_FN_CLASS
case NFNL_EXP_TUPLE_NAT:
attr = EXP_ATTR_NAT_IP_SRC;
break;
+#endif
case NFNL_EXP_TUPLE_EXPECT:
default :
attr = EXP_ATTR_EXPECT_IP_SRC;
@@ -679,9 +664,11 @@ static int exp_get_dst_attr(int tuple)
case NFNL_EXP_TUPLE_MASK:
attr = EXP_ATTR_MASK_IP_DST;
break;
+#ifdef NLE_NAT_FN_CLASS
case NFNL_EXP_TUPLE_NAT:
attr = EXP_ATTR_NAT_IP_DST;
break;
+#endif
case NFNL_EXP_TUPLE_EXPECT:
default :
attr = EXP_ATTR_EXPECT_IP_DST;
@@ -765,9 +752,11 @@ static int exp_get_l4protonum_attr(int tuple)
case NFNL_EXP_TUPLE_MASK:
attr = EXP_ATTR_MASK_L4PROTO_NUM;
break;
+#ifdef NLE_NAT_FN_CLASS
case NFNL_EXP_TUPLE_NAT:
attr = EXP_ATTR_NAT_L4PROTO_NUM;
break;
+#endif
case NFNL_EXP_TUPLE_EXPECT:
default :
attr = EXP_ATTR_EXPECT_L4PROTO_NUM;
@@ -807,9 +796,11 @@ static int exp_get_l4ports_attr(int tuple)
case NFNL_EXP_TUPLE_MASK:
attr = EXP_ATTR_MASK_L4PROTO_PORTS;
break;
+#ifdef NLE_NAT_FN_CLASS
case NFNL_EXP_TUPLE_NAT:
attr = EXP_ATTR_NAT_L4PROTO_PORTS;
break;
+#endif
case NFNL_EXP_TUPLE_EXPECT:
default :
attr = EXP_ATTR_EXPECT_L4PROTO_PORTS;
@@ -858,9 +849,11 @@ static int exp_get_l4icmp_attr(int tuple)
case NFNL_EXP_TUPLE_MASK:
attr = EXP_ATTR_MASK_L4PROTO_ICMP;
break;
+#ifdef NLE_NAT_FN_CLASS
case NFNL_EXP_TUPLE_NAT:
attr = EXP_ATTR_NAT_L4PROTO_ICMP;
break;
+#endif
case NFNL_EXP_TUPLE_EXPECT:
default :
attr = EXP_ATTR_EXPECT_L4PROTO_ICMP;