From 07418658a6dae7243f2b7d51aebe9ad0299b40ad Mon Sep 17 00:00:00 2001 From: Rich Fought Date: Fri, 12 Oct 2012 17:44:27 -0700 Subject: define advanced attributes out --- include/netlink/netfilter/exp.h | 32 ++++++++-- lib/netfilter/exp.c | 128 ++++++++++++++++++++++++++++++++++++---- lib/netfilter/exp_obj.c | 75 +++++++++++------------ 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 #include +#include + +#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; -- cgit v0.12