]> granicus.if.org Git - libnl/commitdiff
"checkpoint"
authorRich Fought <Rich.Fought@watchguard.com>
Sat, 6 Oct 2012 00:32:20 +0000 (17:32 -0700)
committerRich Fought <Rich.Fought@watchguard.com>
Sat, 6 Oct 2012 00:32:20 +0000 (17:32 -0700)
include/netlink-types.h
include/netlink/netfilter/exp.h
lib/netfilter/exp_obj.c

index 78846957b63a69b16a442f98a25569a2c6f3e7fb..0ee1bda2c22a57ddbde17c946528ce24107b36a3 100644 (file)
@@ -817,10 +817,10 @@ struct nfnl_exp {
     char *          exp_fn;          //optional
     uint8_t         exp_nat_dir;     // optional
 
-    struct nfnl_ct_dir exp_expect; // required
-    struct nfnl_ct_dir exp_master; // required
-    struct nfnl_ct_dir exp_mask;   // required
-    struct nfnl_ct_dir exp_nat;    // optional
+    struct nfnl_exp_dir exp_expect; // required
+    struct nfnl_exp_dir exp_master; // required
+    struct nfnl_exp_dir exp_mask;   // required
+    struct nfnl_exp_dir exp_nat;    // optional
 };
 
 struct nfnl_log {
index 36a28e5b1cbd95cfb1120097cc0b54dd9c30a7c5..7ace0e5614cbe32cc11cdcb6c4a95f3605d70c65 100644 (file)
@@ -26,10 +26,10 @@ extern "C" {
 struct nfnl_exp;
 
 enum nfnl_exp_tuples {
-    NFNL_EXP_EXPECT,
-    NFNL_EXP_MASTER,
-    NFNL_EXP_MASK,
-    NFNL_EXP_NAT
+    NFNL_EXP_TUPLE_EXPECT,
+    NFNL_EXP_TUPLE_MASTER,
+    NFNL_EXP_TUPLE_MASK,
+    NFNL_EXP_TUPLE_NAT
 };
 
 extern struct nl_object_ops exp_obj_ops;
@@ -98,31 +98,28 @@ extern uint8_t nfnl_exp_get_nat_dir(const struct nfnl_exp *, int);
 
 // The int argument specifies which nfnl_ct_dir (expect, master, mask or nat)
 // Expectation objects only use orig, not reply
-extern int  nfnl_exp_test_tuple(const struct nfnl_exp *, int);
 
 extern int  nfnl_exp_set_src(struct nfnl_exp *, int, struct nl_addr *);
+extern int  nfnl_exp_test_src(const struct nfnl_exp *);
 extern struct nl_addr * nfnl_ct_get_src(const struct nfnl_exp *, int);
 
 extern int  nfnl_exp_set_dst(struct nfnl_exp *, int, struct nl_addr *);
+extern int  nfnl_exp_test_dst(const struct nfnl_exp *);
 extern struct nl_addr * nfnl_exp_get_dst(const struct nfnl_exp *, int);
 
-extern int  nfnl_exp_set_l4proto(struct nfnl_exp *, int, uint8_t);
-extern int  nfnl_exp_test_l4proto(const struct nfnl_exp *);
-extern struct uint8_t * nfnl_exp_get_l4proto(const struct nfnl_exp *, int);
+extern void  nfnl_exp_set_l4protonum(struct nfnl_exp *, int, uint8_t);
+extern int  nfnl_exp_test_l4protonum(const struct nfnl_exp *, int);
+extern uint8_t * nfnl_exp_get_l4protonum(const struct nfnl_exp *, int);
 
-extern void nfnl_exp_set_src_port(struct nfnl_exp *, int, uint16_t);
+extern void nfnl_exp_set_ports(struct nfnl_exp *, int, uint16_t, uint16_t);
+extern int nfnl_exp_test_ports(const struct nfnl_exp *, int);
 extern uint16_t nfnl_exp_get_src_port(const struct nfnl_exp *, int);
-
-extern void nfnl_exp_set_dst_port(struct nfnl_exp *, int, uint16_t);
 extern uint16_t nfnl_exp_get_dst_port(const struct nfnl_exp *, int);
 
-extern void nfnl_exp_set_icmp_id(struct nfnl_exp *, int, uint16_t);
+extern void nfnl_exp_set_icmp(struct nfnl_exp *, int, uint16_t, uint8_t, uint8_t);
+extern int nfnl_exp_test_icmp(const struct nfnl_exp *, int);
 extern uint16_t nfnl_exp_get_icmp_id(const struct nfnl_exp *, int);
-
-extern void nfnl_exp_set_icmp_type(struct nfnl_exp *, int, uint8_t);
 extern uint8_t  nfnl_exp_get_icmp_type(const struct nfnl_exp *, int);
-
-extern void nfnl_exp_set_icmp_code(struct nfnl_exp *, int, uint8_t);
 extern uint8_t  nfnl_exp_get_icmp_code(const struct nfnl_exp *, int);
 
 // TODO: Expectation table does support CPU stats get command, not sure if the same
index 4e11edf31001b437f5943c6341c0bb9cf5b820b9..2a45f3e3768320a666c7eb5fb55108e7a6161e45 100644 (file)
 // these parent attributes will include nested attributes.
 
 /** @cond SKIP */
-#define EXP_ATTR_FAMILY             (1UL << 0)
-#define EXP_ATTR_TIMEOUT            (1UL << 1) // 32-bit
-#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_FN                 (1UL << 7) // String
+#define EXP_ATTR_FAMILY               (1UL << 0) // 8-bit
+#define EXP_ATTR_TIMEOUT              (1UL << 1) // 32-bit
+#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_FN                   (1UL << 7) // String
 
 // Tuples
-#define EXP_ATTR_EXPECT             (1UL << 8)  // contains ip, proto
-#define EXP_ATTR_EXPECT_IP          (1UL << 9) // contains src, dst
-#define EXP_ATTR_EXPECT_L4PROTO     (1UL << 10) // contains l4proto # + PORT attrs or ICMP attrs
-#define EXP_ATTR_EXPECT_L4PROTO_NUM (1UL << 11)
-#define EXP_ATTR_MASTER             (1UL << 12) // contains ip, proto
-#define EXP_ATTR_MASTER_IP          (1UL << 13) // contains src, dst
-#define EXP_ATTR_MASTER_L4PROTO     (1UL << 14) // contains l4proto # + PORT attrs or ICMP attrs
-#define EXP_ATTR_MASTER_L4PROTO_NUM (1UL << 15)
-#define EXP_ATTR_MASK               (1UL << 16) // contains ip, proto
-#define EXP_ATTR_MASK_IP            (1UL << 17) // contains src, dst
-#define EXP_ATTR_MASK_L4PROTO       (1UL << 18) // contains l4proto # + PORT attrs or ICMP attrs
-#define EXP_ATTR_MASK_L4PROTO_NUM   (1UL << 19)
-#define EXP_ATTR_NAT                (1UL << 20) // contains ip, proto
-#define EXP_ATTR_NAT_IP             (1UL << 21) // contains src, dst
-#define EXP_ATTR_NAT_L4PROTO        (1UL << 22) // contains l4proto # + PORT attrs or ICMP attrs
-#define EXP_ATTR_NAT_L4PROTO_NUM    (1UL << 23)
-
-#define EXP_ATTR_NAT_DIR            (1UL << 24)
+#define EXP_ATTR_EXPECT_IP_SRC        (1UL << 8)
+#define EXP_ATTR_EXPECT_IP_DST        (1UL << 9)
+#define EXP_ATTR_EXPECT_L4PROTO_NUM   (1UL << 10) // contains l4proto # + PORT attrs or ICMP attrs
+#define EXP_ATTR_EXPECT_L4PROTO_PORTS (1UL << 11)
+#define EXP_ATTR_EXPECT_L4PROTO_ICMP  (1UL << 12)
+#define EXP_ATTR_MASTER_IP_SRC        (1UL << 13)
+#define EXP_ATTR_MASTER_IP_DST        (1UL << 14)
+#define EXP_ATTR_MASTER_L4PROTO_NUM   (1UL << 15) // contains l4proto # + PORT attrs or ICMP attrs
+#define EXP_ATTR_MASTER_L4PROTO_PORTS (1UL << 16)
+#define EXP_ATTR_MASTER_L4PROTO_ICMP  (1UL << 17)
+#define EXP_ATTR_MASK_IP_SRC          (1UL << 18)
+#define EXP_ATTR_MASK_IP_DST          (1UL << 19)
+#define EXP_ATTR_MASK_L4PROTO_NUM     (1UL << 20) // contains l4proto # + PORT attrs or ICMP attrs
+#define EXP_ATTR_MASK_L4PROTO_PORTS   (1UL << 21)
+#define EXP_ATTR_MASK_L4PROTO_ICMP    (1UL << 22)
+#define EXP_ATTR_NAT_IP_SRC           (1UL << 23)
+#define EXP_ATTR_NAT_IP_DST           (1UL << 24)
+#define EXP_ATTR_NAT_L4PROTO_NUM      (1UL << 25) // contains l4proto # + PORT attrs or ICMP attrs
+#define EXP_ATTR_NAT_L4PROTO_PORTS    (1UL << 26)
+#define EXP_ATTR_NAT_L4PROTO_ICMP     (1UL << 27)
+
+#define EXP_ATTR_NAT_DIR              (1UL << 28)
 /** @endcond */
 
 static void exp_free_data(struct nl_object *c)
@@ -145,6 +149,12 @@ static int exp_clone(struct nl_object *_dst, struct nl_object *_src)
         dst->exp_nat.dst = addr;
     }
 
+    if (src->exp_fn)
+        dst->exp_fn = strdup(src->exp_fn)
+
+    if (src->exp_helper_name)
+        dst->exp_helper_name = strdup(src->exp_helper_name);
+
        return 0;
 }
 
@@ -174,15 +184,16 @@ static void ct_dump_tuples(struct nfnl_exp *exp, struct nl_dump_params *p)
 {
        struct nl_addr *tuple_src, *tuple_dst;
        int tuple_sport = 0, tuple_dport = 0;
-       int i = NFNL_EXP_EXPECT;
+       int i = NFNL_EXP_TUPLE_EXPECT;
        int icmp = 0;
 
-       for (i; i <= NFNL_EXP_NAT; i++) {
+       for (i; i <= NFNL_EXP_TUPLE_NAT; i++) {
 
-        if (nfnl_exp_test_tuple(exp, i)) {
-
-        tuple_src = nfnl_ct_get_src(exp, i);
-        tuple_dst = nfnl_ct_get_dst(exp, i);
+        // Test needed for NAT case
+           if (nfnl_exp_test_src(exp, i))
+            tuple_src = nfnl_exp_get_src(exp, i);
+        if (nfnl_exp_test_dst(exp, i))
+            tuple_dst = nfnl_exp_get_dst(exp, i);
 
         // Don't have tests for individual ports/types/codes/ids,
         // just test L4 Proto.  Ugly, but can't do much else without
@@ -294,77 +305,25 @@ static void ct_dump_stats(struct nl_object *a, struct nl_dump_params *p)
 }
 */
 
-static int exp_cmp_tuples_loose(struct nfnl_ct_dir *a, struct nfnl_ct_dir *b)
-{
-    // Must return 0 for match, 1 for mismatch
-    // Parent attribute, so must reflect lower level attribute diffs
-    int d = exp_cmp_tuples_ip_loose(a, b);
-    if (d == 0) {
-        d = exp_cmp_tuples_proto(&a->proto, &b->proto))
-    }
-    return d;
-}
-
-static int exp_cmp_tuples(struct nfnl_exp_dir *a, struct nfnl_exp_dir *b)
-{
-    // Must return 0 for match, 1 for mismatch
-    // Parent attribute, so must reflect lower level attribute diffs
-    int d = exp_cmp_tuples_ip(a, b);
-    if (d == 0) {
-        d = exp_cmp_tuples_proto(&a->proto, &b->proto))
-    }
-    return d;
-}
-
-static int exp_cmp_tuples_ip_loose(struct nfnl_exp_dir *a, struct nfnl_exp_dir *b) {
+static int exp_cmp_l4proto_ports (union nfnl_exp_protodata *a, union nfnl_exp_protodata *b) {
     // Must return 0 for match, 1 for mismatch
-    int d = nl_addr_cmp_prefix(a->src, b->src);
+    int d = 0;
+    d = ( (a->port.src != b->port.src) ||
+          (a->port.dst != b->port.dst) );
 
-    if (d == 0) {
-        d = nl_addr_cmp_prefix(a->dst, b->dst);
-    }
     return d;
 }
 
-
-static int exp_cmp_tuples_ip(struct nfnl_exp_dir *a, struct nfnl_exp_dir *b) {
+static int exp_cmp_l4proto_icmp (union nfnl_exp_protodata *a, union nfnl_exp_protodata *b) {
     // Must return 0 for match, 1 for mismatch
-    int d = nl_addr_cmp(a->src, b->src);
-
-    if (d == 0) {
-        d = nl_addr_cmp(a->dst, b->dst);
-    }
-    return d;
-}
-
-
-static int exp_cmp_tuples_proto(struct nfnl_exp_proto *a, struct nfnl_exp_proto *b) {
-    // Must return 0 for match, 1 for mismatch
-
-    // Parent attribute, so must reflect lower level attribute diffs
-    int d = exp_cmp_tuples_protonum(a->l4protonum, b->l4protonum);
-
-    if (d == 0) {
-        // Check actual proto data
-        if (a->l4protonum == IPPROTO_ICMP ||
-            a->l4protonum == IPPROTO_ICMPV6) {
-            d == ( (a->l4protodata.icmp.code != b->l4protodata.icmp.code) ||
-                   (a->l4protodata.icmp.type != b->l4protodata.icmp.type) ||
-                   (a->l4protodata.icmp.id != b->l4protodata.icmp.id) )
-        } else {
-            d == ( (a->l4protodata.port.src != b->l4protodata.port.src) ||
-                   (a->l4protodata.port.dst != b->l4protodata.icmp.dst) )
-        }
-    }
+    int d = 0;
+    d = ( (a->icmp.code != b->icmp.code) ||
+          (a->icmp.type != b->icmp.type) ||
+          (a->icmp.id != b->icmp.id) );
 
     return d;
 }
 
-static int exp_cmp_tuples_protonum(uint8_t a, uint8_t b) {
-    // Must return 0 for match, 1 for mismatch
-    return (a != b)
-}
-
 static int exp_compare(struct nl_object *_a, struct nl_object *_b,
                                        uint32_t attrs, int flags)
 {
@@ -374,73 +333,97 @@ static int exp_compare(struct nl_object *_a, struct nl_object *_b,
 
 #define EXP_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, EXP_ATTR_##ATTR, a, b, EXPR)
 #define EXP_DIFF_VAL(ATTR, FIELD) EXP_DIFF(ATTR, a->FIELD != b->FIELD)
-#define EXP_DIFF_STRING(ATTR, FIELD) EXP_DIFF(ATTR, (strncmp(a->FIELD, b->FIELD, 16) != 0))
-
-#define EXP_DIFF_TUPLE(ATTR, FIELD) \
-    ((flags & LOOSE_COMPARISON) \
-        ? EXP_DIFF(ATTR, exp_cmp_tuples_loose(a->FIELD, b->FIELD)) \
-        : EXP_DIFF(ATTR, exp_cmp_tuples(a->FIELD, b->FIELD)))
-
-#define EXP_DIFF_IP(ATTR, FIELD) \
-    ((flags & LOOSE_COMPARISON) \
-        ? EXP_DIFF(ATTR, exp_cmp_tuples_ip_loose(a->FIELD, b->FIELD)) \
-        : EXP_DIFF(ATTR, exp_cmp_tuples_ip(a->FIELD, b->FIELD)))
-
-#define EXP_DIFF_PROTO(ATTR, FIELD) \
-        EXP_DIFF(ATTR, exp_cmp_tuples_proto(a->FIELD, b->FIELD))
-
-        diff |= EXP_DIFF_VAL(FAMILY,        exp_family);
-        diff |= EXP_DIFF_VAL(TIMEOUT,       exp_timeout);
-        diff |= EXP_DIFF_VAL(ID,            exp_id);
-        diff |= EXP_DIFF_VAL(ZONE,          exp_zone);
-        diff |= EXP_DIFF_VAL(CLASS,         exp_class);
-        diff |= EXP_DIFF_VAL(FLAGS,         exp_flags);
-        diff |= EXP_DIFF_VAL(NAT_DIR,       exp_flags);
-
-        diff |= EXP_DIFF(FLAGS, (a->exp_flags ^ b->exp_flags));
-
-#undef CT_DIFF
-#undef CT_DIFF_VAL
+#define EXP_DIFF_STRING(ATTR, FIELD) EXP_DIFF(ATTR, (strcmp(a->FIELD, b->FIELD) != 0))
+#define EXP_DIFF_ADDR(ATTR, FIELD) \
+        ((flags & LOOSE_COMPARISON) \
+        ? EXP_DIFF(ATTR, nl_addr_cmp_prefix(a->FIELD, b->FIELD)) \
+        : EXP_DIFF(ATTR, nl_addr_cmp(a->FIELD, b->FIELD)))
+#define EXP_DIFF_L4PROTO_PORTS(ATTR, FIELD) \
+         EXP_DIFF(ATTR, exp_cmp_l4proto_ports(a->FIELD, b->FIELD))
+#define EXP_DIFF_L4PROTO_ICMP(ATTR, FIELD) \
+         EXP_DIFF(ATTR, exp_cmp_l4proto_icmp(a->FIELD, b->FIELD))
+
+        diff |= EXP_DIFF_VAL(FAMILY,             exp_family);
+        diff |= EXP_DIFF_VAL(TIMEOUT,            exp_timeout);
+        diff |= EXP_DIFF_VAL(ID,                 exp_id);
+        diff |= EXP_DIFF_VAL(ZONE,               exp_zone);
+        diff |= EXP_DIFF_VAL(CLASS,              exp_class);
+        diff |= EXP_DIFF_VAL(FLAGS,              exp_flags);
+        diff |= EXP_DIFF_VAL(NAT_DIR,            exp_nat_dir);
+
+        diff |= EXP_DIFF_STRING(FN,              exp_fn);
+        diff |= EXP_DIFF_STRING(HELPER_NAME,     exp_helper_name);
+
+        diff |= EXP_DIFF_ADDR(EXPECT_IP_SRC,     exp_expect.src);
+        diff |= EXP_DIFF_ADDR(EXPECT_IP_DST,     exp_expect.dst);
+        diff |= EXP_DIFF_VAL(EXPECT_L4PROTO_NUM, exp_expect.proto.l4protonum);
+        diff |= EXP_DIFF_L4PROTO_PORTS(EXPECT_L4PROTO_PORTS, exp_expect.proto.l4protodata.port);
+        diff |= EXP_DIFF_L4PROTO_ICMP(EXPECT_L4PROTO_ICMP, exp_expect.proto.l4protodata.icmp);
+
+        diff |= EXP_DIFF_ADDR(MASTER_IP_SRC,           exp_master.src);
+        diff |= EXP_DIFF_ADDR(MASTER_IP_DST,           exp_master.dst);
+        diff |= EXP_DIFF_VAL(MASTER_L4PROTO_NUM, exp_master.proto.l4protonum);
+        diff |= EXP_DIFF_L4PROTO_PORTS(MASTER_L4PROTO_PORTS, exp_master.proto.l4protodata.port);
+        diff |= EXP_DIFF_L4PROTO_ICMP(MASTER_L4PROTO_ICMP, exp_master.proto.l4protodata.icmp);
+
+        diff |= EXP_DIFF_ADDR(MASK_IP_SRC,             exp_mask.src);
+        diff |= EXP_DIFF_ADDR(MASK_IP_DST,             exp_mask.dst);
+        diff |= EXP_DIFF_VAL(MASK_L4PROTO_NUM,   exp_mask.proto.l4protonum);
+        diff |= EXP_DIFF_L4PROTO_PORTS(MASK_L4PROTO_PORTS, exp_mask.proto.l4protodata.port);
+        diff |= EXP_DIFF_L4PROTO_ICMP(MASK_L4PROTO_ICMP, exp_mask.proto.l4protodata.icmp);
+
+        diff |= EXP_DIFF_ADDR(NAT_IP_SRC,              exp_nat.src);
+        diff |= EXP_DIFF_ADDR(NAT_IP_DST,              exp_nat.dst);
+        diff |= EXP_DIFF_VAL(NAT_L4PROTO_NUM,    exp_nat.proto.l4protonum);
+        diff |= EXP_DIFF_L4PROTO_PORTS(NAT_L4PROTO_PORTS, exp_nat.proto.l4protodata.port);
+        diff |= EXP_DIFF_L4PROTO_ICMP(NAT_L4PROTO_ICMP, exp_nat.proto.l4protodata.icmp);
+
+#undef EXP_DIFF
+#undef EXP_DIFF_VAL
 #undef EXP_DIFF_STRING
-#undef CT_DIFF_TUPLE
-#undef CT_DIFF_IP
-#undef CT_DIFF_PROTO
-
-       return diff;
-}
-
-static const struct trans_tbl ct_attrs[] = {
-       __ADD(CT_ATTR_FAMILY,           family)
-       __ADD(CT_ATTR_PROTO,            proto)
-       __ADD(CT_ATTR_TCP_STATE,        tcpstate)
-       __ADD(CT_ATTR_STATUS,           status)
-       __ADD(CT_ATTR_TIMEOUT,          timeout)
-       __ADD(CT_ATTR_MARK,             mark)
-       __ADD(CT_ATTR_USE,              use)
-       __ADD(CT_ATTR_ID,               id)
-       __ADD(CT_ATTR_ORIG_SRC,         origsrc)
-       __ADD(CT_ATTR_ORIG_DST,         origdst)
-       __ADD(CT_ATTR_ORIG_SRC_PORT,    origsrcport)
-       __ADD(CT_ATTR_ORIG_DST_PORT,    origdstport)
-       __ADD(CT_ATTR_ORIG_ICMP_ID,     origicmpid)
-       __ADD(CT_ATTR_ORIG_ICMP_TYPE,   origicmptype)
-       __ADD(CT_ATTR_ORIG_ICMP_CODE,   origicmpcode)
-       __ADD(CT_ATTR_ORIG_PACKETS,     origpackets)
-       __ADD(CT_ATTR_ORIG_BYTES,       origbytes)
-       __ADD(CT_ATTR_REPL_SRC,         replysrc)
-       __ADD(CT_ATTR_REPL_DST,         replydst)
-       __ADD(CT_ATTR_REPL_SRC_PORT,    replysrcport)
-       __ADD(CT_ATTR_REPL_DST_PORT,    replydstport)
-       __ADD(CT_ATTR_REPL_ICMP_ID,     replyicmpid)
-       __ADD(CT_ATTR_REPL_ICMP_TYPE,   replyicmptype)
-       __ADD(CT_ATTR_REPL_ICMP_CODE,   replyicmpcode)
-       __ADD(CT_ATTR_REPL_PACKETS,     replypackets)
-       __ADD(CT_ATTR_REPL_BYTES,       replybytes)
+#undef EXP_DIFF_ADDR
+#undef EXP_DIFF_L4PROTO_PORTS
+#undef EXP_DIFF_L4PROTO_ICMP
+
+    return diff;
+}
+
+// CLI arguments?
+static const struct trans_tbl exp_attrs[] = {
+    __ADD(EXP_ATTR_FAMILY,              family)
+    __ADD(EXP_ATTR_TIMEOUT,             timeout)
+    __ADD(EXP_ATTR_ID,                  id)
+    __ADD(EXP_ATTR_HELPER_NAME,         helpername)
+    __ADD(EXP_ATTR_ZONE,                zone)
+    __ADD(EXP_ATTR_CLASS,               class)
+    __ADD(EXP_ATTR_FLAGS,               flags)
+    __ADD(EXP_ATTR_FN,                  function)
+    __ADD(EXP_ATTR_EXPECT_IP_SRC,       expectipsrc)
+    __ADD(EXP_ATTR_EXPECT_IP_DST,       expectipdst)
+    __ADD(EXP_ATTR_EXPECT_L4PROTO_NUM,  expectprotonum)
+    __ADD(EXP_ATTR_EXPECT_L4PROTO_PORTS,expectports)
+    __ADD(EXP_ATTR_EXPECT_L4PROTO_ICMP ,expecticmp)
+    __ADD(EXP_ATTR_MASTER_IP_SRC,       masteripsrc)
+    __ADD(EXP_ATTR_MASTER_IP_DST,       masteripdst)
+    __ADD(EXP_ATTR_MASTER_L4PROTO_NUM,  masterprotonum)
+    __ADD(EXP_ATTR_MASTER_L4PROTO_PORTS,masterports)
+    __ADD(EXP_ATTR_MASTER_L4PROTO_ICMP ,mastericmp)
+    __ADD(EXP_ATTR_MASK_IP_SRC,         maskipsrc)
+    __ADD(EXP_ATTR_MASK_IP_DST,         maskipdst)
+    __ADD(EXP_ATTR_MASK_L4PROTO_NUM,    maskprotonum)
+    __ADD(EXP_ATTR_MASK_L4PROTO_PORTS,  maskports)
+    __ADD(EXP_ATTR_MASK_L4PROTO_ICMP ,  maskicmp)
+    __ADD(EXP_ATTR_NAT_IP_SRC,          natipsrc)
+    __ADD(EXP_ATTR_NAT_IP_DST,          natipdst)
+    __ADD(EXP_ATTR_NAT_L4PROTO_NUM,     natprotonum)
+    __ADD(EXP_ATTR_NAT_L4PROTO_PORTS,   natports)
+    __ADD(EXP_ATTR_NAT_L4PROTO_ICMP,    naticmp)
+    __ADD(EXP_ATTR_NAT_DIR,             natdir)
 };
 
-static char *ct_attrs2str(int attrs, char *buf, size_t len)
+static char *exp_attrs2str(int attrs, char *buf, size_t len)
 {
-       return __flags2str(attrs, buf, len, ct_attrs, ARRAY_SIZE(ct_attrs));
+       return __flags2str(attrs, buf, len, exp_attrs, ARRAY_SIZE(exp_attrs));
 }
 
 /**
@@ -448,19 +431,19 @@ static char *ct_attrs2str(int attrs, char *buf, size_t len)
  * @{
  */
 
-struct nfnl_ct *nfnl_ct_alloc(void)
+struct nfnl_exp *nfnl_exp_alloc(void)
 {
-       return (struct nfnl_ct *) nl_object_alloc(&ct_obj_ops);
+       return (struct nfnl_exp *) nl_object_alloc(&exp_obj_ops);
 }
 
-void nfnl_ct_get(struct nfnl_ct *ct)
+void nfnl_exp_get(struct nfnl_exp *exp)
 {
-       nl_object_get((struct nl_object *) ct);
+       nl_object_get((struct nl_object *) exp);
 }
 
-void nfnl_ct_put(struct nfnl_ct *ct)
+void nfnl_exp_put(struct nfnl_exp *exp)
 {
-       nl_object_put((struct nl_object *) ct);
+       nl_object_put((struct nl_object *) exp);
 }
 
 /** @} */
@@ -484,22 +467,6 @@ uint8_t nfnl_exp_get_family(const struct nfnl_exp *exp)
                return AF_UNSPEC;
 }
 
-void nfnl_exp_set_proto(struct nfnl_exp *exp, uint8_t proto)
-{
-       exp->exp_proto = proto;
-       exp->ce_mask |= EXP_ATTR_PROTO;
-}
-
-int nfnl_exp_test_proto(const struct nfnl_exp *exp)
-{
-       return !!(exp->ce_mask & EXP_ATTR_PROTO);
-}
-
-uint8_t nfnl_exp_get_proto(const struct nfnl_exp *ct)
-{
-       return exp->ct_proto;
-}
-
 void nfnl_exp_set_flags(struct nfnl_exp *exp, uint32_t flags)
 {
        exp->exp_flags |= flags;
@@ -512,7 +479,7 @@ void nfnl_exp_unset_flags(struct nfnl_exp *exp, uint32_t flags)
        exp->ce_mask |= EXP_ATTR_FLAGS;
 }
 
-uint32_t nfnl_exp_get_status(const struct nfnl_exp *exp)
+uint32_t nfnl_exp_get_flags(const struct nfnl_exp *exp)
 {
        return exp->exp_flags;
 }
@@ -525,11 +492,11 @@ static const struct trans_tbl flag_table[] = {
 
 char * nfnl_exp_flags2str(int flags, char *buf, size_t len)
 {
-       return __flags2str(flags, buf, len, status_flags,
+       return __flags2str(flags, buf, len, flag_table,
                           ARRAY_SIZE(flag_table));
 }
 
-int nfnl_exp_str2status(const char *name)
+int nfnl_exp_str2flags(const char *name)
 {
        return __str2flags(name, flag_table, ARRAY_SIZE(flag_table));
 }
@@ -566,6 +533,75 @@ uint32_t nfnl_exp_get_id(const struct nfnl_exp *exp)
        return exp->exp_id;
 }
 
+static struct nfnl_exp_dir *exp_get_dir(struct nfnl_exp *exp, int tuple)
+{
+    struct nfnl_exp_dir *dir = NULL;
+
+    switch (tuple) {
+        case NFNL_EXP_TUPLE_MASTER:
+            dir = &exp->exp_master;
+            break;
+        case NFNL_EXP_TUPLE_MASK:
+            dir = &exp->exp_mask;
+            break;
+        case NFNL_EXP_TUPLE_NAT:
+            dir = &exp->exp_nat;
+            break;
+        case NFNL_EXP_TUPLE_EXPECT:
+        default :
+            dir = &exp->exp_expect;
+            break;
+    }
+    return dir;
+}
+
+static int exp_get_src_attr(int tuple)
+{
+    int attr = 0;
+
+    switch (tuple) {
+        case NFNL_EXP_TUPLE_MASTER:
+            attr = EXP_ATTR_MASTER_IP_SRC;
+            break;
+        case NFNL_EXP_TUPLE_MASK:
+            attr = EXP_ATTR_MASK_IP_SRC;
+            break;
+        case NFNL_EXP_TUPLE_NAT:
+            attr = EXP_ATTR_NAT_IP_SRC;
+            break;
+        case NFNL_EXP_TUPLE_EXPECT:
+        default :
+            attr = EXP_ATTR_EXPECT_IP_SRC;
+            break;
+    }
+
+    return attr;
+}
+
+static int exp_get_dst_attr(int tuple)
+{
+    int attr = 0;
+
+    switch (tuple) {
+        case NFNL_EXP_TUPLE_MASTER:
+            attr = EXP_ATTR_MASTER_IP_DST;
+            break;
+        case NFNL_EXP_TUPLE_MASK:
+            attr = EXP_ATTR_MASK_IP_DST;
+            break;
+        case NFNL_EXP_TUPLE_NAT:
+            attr = EXP_ATTR_NAT_IP_DST;
+            break;
+        case NFNL_EXP_TUPLE_EXPECT:
+        default :
+            attr = EXP_ATTR_EXPECT_IP_DST;
+            break;
+    }
+
+    return attr;
+}
+
+
 static int exp_set_addr(struct nfnl_exp *exp, struct nl_addr *addr,
                           int attr, struct nl_addr ** exp_addr)
 {
@@ -587,104 +623,172 @@ static int exp_set_addr(struct nfnl_exp *exp, struct nl_addr *addr,
 
 int nfnl_exp_set_src(struct nfnl_exp *exp, int tuple, struct nl_addr *addr)
 {
-       struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig;
-       int attr = repl ? CT_ATTR_REPL_SRC : CT_ATTR_ORIG_SRC;
-
-        switch (tuple) {
-            case :
-                dir = &exp->exp_expect;
-                attr = EXP_ATTR_
-                break;
-            case :
-                dir = &exp->exp_master;
-                break;
-            case :
-                dir = &exp->exp_mask;
-                break;
-            case :
-                dir = &exp->exp_nat;
-            default :
-        }
+       struct nfnl_exp_dir *dir = exp_get_dir(exp, tuple);
 
-       return ct_set_addr(ct, addr, attr, &dir->src);
+       return exp_set_addr(exp, addr, exp_get_src_attr(tuple), &dir->src);
 }
 
-int nfnl_ct_set_dst(struct nfnl_ct *ct, int repl, struct nl_addr *addr)
+int nfnl_exp_set_dst(struct nfnl_exp *exp, int tuple, struct nl_addr *addr)
 {
-       struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig;
-       int attr = repl ? CT_ATTR_REPL_DST : CT_ATTR_ORIG_DST;
-       return ct_set_addr(ct, addr, attr, &dir->dst);
+    struct nfnl_exp_dir *dir = exp_get_dir(exp, tuple);
+
+    return exp_set_addr(exp, addr, exp_get_dst_attr(tuple), &dir->dst);
 }
 
-struct nl_addr *nfnl_ct_get_src(const struct nfnl_ct *ct, int repl)
+int nfnl_exp_test_src(const struct nfnl_exp *exp, int tuple)
 {
-       const struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig;
-       int attr = repl ? CT_ATTR_REPL_SRC : CT_ATTR_ORIG_SRC;
-       if (!(ct->ce_mask & attr))
+    return !!(exp->ce_mask & exp_get_src_attr(tuple));
+}
+
+int nfnl_exp_test_dst(const struct nfnl_exp *exp, int tuple)
+{
+
+    return !!(exp->ce_mask & exp_get_dst_attr(tuple));
+}
+
+struct nl_addr *nfnl_exp_get_src(const struct nfnl_exp *exp, int tuple)
+{
+       const struct nfnl_exp_dir *dir = exp_get_dir(exp, tuple);
+
+    if (!(exp->ce_mask & exp_get_src_attr(tuple)))
                return NULL;
        return dir->src;
 }
 
-struct nl_addr *nfnl_ct_get_dst(const struct nfnl_ct *ct, int repl)
+struct nl_addr *nfnl_exp_get_dst(const struct nfnl_exp *exp, int tuple)
 {
-       const struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig;
-       int attr = repl ? CT_ATTR_REPL_DST : CT_ATTR_ORIG_DST;
-       if (!(ct->ce_mask & attr))
+       const struct nfnl_exp_dir *dir = exp_get_dir(exp, tuple);
+
+       if (!(exp->ce_mask & exp_get_dst_attr(tuple)))
                return NULL;
        return dir->dst;
 }
 
-void nfnl_ct_set_src_port(struct nfnl_ct *ct, int repl, uint16_t port)
+static int exp_get_l4protonum_attr(int tuple)
+{
+    int attr = 0;
+
+    switch (tuple) {
+        case NFNL_EXP_TUPLE_MASTER:
+            attr = EXP_ATTR_MASTER_L4PROTO_NUM;
+            break;
+        case NFNL_EXP_TUPLE_MASK:
+            attr = EXP_ATTR_MASK_L4PROTO_NUM;
+            break;
+        case NFNL_EXP_TUPLE_NAT:
+            attr = EXP_ATTR_NAT_L4PROTO_NUM;
+            break;
+        case NFNL_EXP_TUPLE_EXPECT:
+        default :
+            attr = EXP_ATTR_EXPECT_L4PROTO_NUM;
+            break;
+    }
+
+    return attr;
+}
+
+void nfnl_exp_set_l4protonum(struct nfnl_exp *exp, int tuple, uint8_t l4protonum)
 {
-       struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig;
-       int attr = repl ? CT_ATTR_REPL_SRC_PORT : CT_ATTR_ORIG_SRC_PORT;
+    const struct nfnl_exp_dir *dir = exp_get_dir(exp, tuple);
 
-       dir->proto.port.src = port;
-       ct->ce_mask |= attr;
+    dir->proto.l4protonum = l4protonum;
+    exp->ce_mask |= exp_get_l4protonum_attr(exp, tuple);
 }
 
-int nfnl_ct_test_src_port(const struct nfnl_ct *ct, int repl)
+int nfnl_exp_test_l4protonum(const struct nfnl_exp *exp, int tuple)
 {
-       int attr = repl ? CT_ATTR_REPL_SRC_PORT : CT_ATTR_ORIG_SRC_PORT;
-       return !!(ct->ce_mask & attr);
+    return !!(exp->ce_mask & exp_get_l4protonum_attr(exp, tuple));
 }
 
-uint16_t nfnl_ct_get_src_port(const struct nfnl_ct *ct, int repl)
+struct uint8_t * nfnl_exp_get_l4protonum(const struct nfnl_exp *exp, int tuple)
 {
-       const struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig;
+    const struct nfnl_exp_dir *dir = exp_get_dir(exp, tuple);
+    return dir->proto.l4protonum;
+}
+
+static int exp_get_l4ports_attr(int tuple)
+{
+    int attr = 0;
+
+    switch (tuple) {
+        case NFNL_EXP_TUPLE_MASTER:
+            attr = EXP_ATTR_MASTER_L4PROTO_PORTS;
+            break;
+        case NFNL_EXP_TUPLE_MASK:
+            attr = EXP_ATTR_MASK_L4PROTO_PORTS;
+            break;
+        case NFNL_EXP_TUPLE_NAT:
+            attr = EXP_ATTR_NAT_L4PROTO_PORTS;
+            break;
+        case NFNL_EXP_TUPLE_EXPECT:
+        default :
+            attr = EXP_ATTR_EXPECT_L4PROTO_PORTS;
+            break;
+    }
 
-       return dir->proto.port.src;
+    return attr;
 }
 
-void nfnl_ct_set_dst_port(struct nfnl_ct *ct, int repl, uint16_t port)
+void nfnl_exp_set_src_ports(struct nfnl_exp *exp, int tuple, uint16_t srcport, uint16_t dstport)
 {
-       struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig;
-       int attr = repl ? CT_ATTR_REPL_DST_PORT : CT_ATTR_ORIG_DST_PORT;
+       struct nfnl_exp_dir *dir = exp_get_dir(exp, tuple);
 
-       dir->proto.port.dst = port;
-       ct->ce_mask |= attr;
+       dir->proto.l4protodata.port.src = srcport;
+       dir->proto.l4protodata.port.dst = dstport;
+
+       exp->ce_mask |= exp_get_l4ports_attr(tuple);
 }
 
-int nfnl_ct_test_dst_port(const struct nfnl_ct *ct, int repl)
+int nfnl_exp_test_ports(const struct nfnl_exp *exp, int tuple)
 {
-       int attr = repl ? CT_ATTR_REPL_DST_PORT : CT_ATTR_ORIG_DST_PORT;
-       return !!(ct->ce_mask & attr);
+       return !!(exp->ce_mask & exp_get_l4ports_attr(tuple));
 }
 
-uint16_t nfnl_ct_get_dst_port(const struct nfnl_ct *ct, int repl)
+uint16_t nfnl_exp_get_src_port(const struct nfnl_exp *exp, int tuple)
 {
-       const struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig;
+       const struct nfnl_exp_dir *dir = exp_get_dir(exp, tuple);
+       return dir->proto.l4protodata.port.src;
+}
 
-       return dir->proto.port.dst;
+uint16_t nfnl_exp_get_dst_port(const struct nfnl_exp *exp, int tuple)
+{
+    const struct nfnl_exp_dir *dir = exp_get_dir(exp, tuple);
+
+       return dir->proto.l4protodata.port.dst;
 }
 
-void nfnl_ct_set_icmp_id(struct nfnl_ct *ct, int repl, uint16_t id)
+static int exp_get_l4icmp_attr(int tuple)
 {
-       struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig;
-       int attr = repl ? CT_ATTR_REPL_ICMP_ID : CT_ATTR_ORIG_ICMP_ID;
+    int attr = 0;
 
-       dir->proto.icmp.id = id;
-       ct->ce_mask |= attr;
+    switch (tuple) {
+        case NFNL_EXP_TUPLE_MASTER:
+            attr = EXP_ATTR_MASTER_L4PROTO_ICMP;
+            break;
+        case NFNL_EXP_TUPLE_MASK:
+            attr = EXP_ATTR_MASK_L4PROTO_ICMP;
+            break;
+        case NFNL_EXP_TUPLE_NAT:
+            attr = EXP_ATTR_NAT_L4PROTO_ICMP;
+            break;
+        case NFNL_EXP_TUPLE_EXPECT:
+        default :
+            attr = EXP_ATTR_EXPECT_L4PROTO_ICMP;
+            break;
+    }
+
+    return attr;
+}
+
+void nfnl_ct_set_icmp(struct nfnl_exp *exp, int tuple, uint16_t id, uint8_t type, uint8_t, code)
+{
+       struct nfnl_exp_dir *dir = exp_get_dir(exp, tuple);
+
+       dir->proto.l4protodata.icmp.id = id;
+       dir->proto.l4protodata.icmp.type = type;
+    dir->proto.l4protodata.icmp.code = code;
+
+       exp->ce_mask |= exp_get_l4icmp_attr(tuple);
 }
 
 int nfnl_ct_test_icmp_id(const struct nfnl_ct *ct, int repl)