Newer kernels support conntrack zones, which help to partition the conntrack table into virtual conntrack tables. This patch is for adding support for the optional attribute, adds setters and getters, and adds support for the zone ID in the conntrack dumper. An example entry in NL_DUMP_LINE format looks like: tcp SYN_SENT 10.128.128.99:43354 <-> 10.128.129.20:22 zone 1 Signed-off-by: Holger Eitzenberger Index: libnl-next/include/netlink-private/types.h =================================================================== --- libnl-next.orig/include/netlink-private/types.h +++ libnl-next/include/netlink-private/types.h @@ -792,6 +792,7 @@ struct nfnl_ct { uint32_t ct_mark; uint32_t ct_use; uint32_t ct_id; + uint16_t ct_zone; struct nfnl_ct_dir ct_orig; struct nfnl_ct_dir ct_repl; Index: libnl-next/include/netlink/netfilter/ct.h =================================================================== --- libnl-next.orig/include/netlink/netfilter/ct.h +++ libnl-next/include/netlink/netfilter/ct.h @@ -90,6 +90,10 @@ extern void nfnl_ct_set_id(struct nfnl_c extern int nfnl_ct_test_id(const struct nfnl_ct *); extern uint32_t nfnl_ct_get_id(const struct nfnl_ct *); +extern void nfnl_ct_set_zone(struct nfnl_ct *, uint16_t); +extern int nfnl_ct_test_zone(const struct nfnl_ct *); +extern uint16_t nfnl_ct_get_zone(const struct nfnl_ct *); + extern int nfnl_ct_set_src(struct nfnl_ct *, int, struct nl_addr *); extern struct nl_addr * nfnl_ct_get_src(const struct nfnl_ct *, int); Index: libnl-next/lib/netfilter/ct.c =================================================================== --- libnl-next.orig/lib/netfilter/ct.c +++ libnl-next/lib/netfilter/ct.c @@ -55,6 +55,7 @@ static struct nla_policy ct_policy[CTA_M [CTA_COUNTERS_REPLY] = { .type = NLA_NESTED }, [CTA_USE] = { .type = NLA_U32 }, [CTA_ID] = { .type = NLA_U32 }, + [CTA_ZONE] = { .type = NLA_U16 }, //[CTA_NAT_DST] }; @@ -369,6 +370,8 @@ int nfnlmsg_ct_parse(struct nlmsghdr *nl nfnl_ct_set_use(ct, ntohl(nla_get_u32(tb[CTA_USE]))); if (tb[CTA_ID]) nfnl_ct_set_id(ct, ntohl(nla_get_u32(tb[CTA_ID]))); + if (tb[CTA_ZONE]) + nfnl_ct_set_zone(ct, ntohs(nla_get_u16(tb[CTA_ZONE]))); if (tb[CTA_COUNTERS_ORIG]) { err = ct_parse_counters(ct, 0, tb[CTA_COUNTERS_ORIG]); Index: libnl-next/lib/netfilter/ct_obj.c =================================================================== --- libnl-next.orig/lib/netfilter/ct_obj.c +++ libnl-next/lib/netfilter/ct_obj.c @@ -52,6 +52,7 @@ #define CT_ATTR_REPL_PACKETS (1UL << 24) #define CT_ATTR_REPL_BYTES (1UL << 25) #define CT_ATTR_TIMESTAMP (1UL << 26) +#define CT_ATTR_ZONE (1UL << 27) /** @endcond */ static void ct_free_data(struct nl_object *c) @@ -193,6 +194,9 @@ static void ct_dump_line(struct nl_objec if (nfnl_ct_test_mark(ct) && nfnl_ct_get_mark(ct)) nl_dump(p, "mark %u ", nfnl_ct_get_mark(ct)); + if (nfnl_ct_test_zone(ct)) + nl_dump(p, "zone %hu ", nfnl_ct_get_zone(ct)); + if (nfnl_ct_test_timestamp(ct)) { const struct nfnl_ct_timestamp *tstamp = nfnl_ct_get_timestamp(ct); int64_t delta_time = tstamp->stop - tstamp->start; @@ -584,6 +588,22 @@ uint32_t nfnl_ct_get_id(const struct nfn return ct->ct_id; } +void nfnl_ct_set_zone(struct nfnl_ct *ct, uint16_t zone) +{ + ct->ct_zone = zone; + ct->ce_mask |= CT_ATTR_ZONE; +} + +int nfnl_ct_test_zone(const struct nfnl_ct *ct) +{ + return !!(ct->ce_mask & CT_ATTR_ZONE); +} + +uint16_t nfnl_ct_get_zone(const struct nfnl_ct *ct) +{ + return ct->ct_zone; +} + static int ct_set_addr(struct nfnl_ct *ct, struct nl_addr *addr, int attr, struct nl_addr ** ct_addr) {