--- a/net/netfilter/nfnetlink_acct.c +++ b/net/netfilter/nfnetlink_acct.c @@ -32,6 +32,7 @@ struct nf_acct { atomic64_t pkts; atomic64_t bytes; + atomic_t fmt; struct list_head head; atomic_t refcnt; char name[NFACCT_NAME_MAX]; @@ -63,9 +64,14 @@ if (matching) { if (nlh->nlmsg_flags & NLM_F_REPLACE) { - /* reset counters if you request a replacement. */ + /* reset counters if you request a replacement... */ atomic64_set(&matching->pkts, 0); atomic64_set(&matching->bytes, 0); + /* ... and change the format */ + if (tb[NFACCT_FMT]) { + atomic_set(&matching->fmt, + be32_to_cpu(nla_get_be32(tb[NFACCT_FMT]))); + } return 0; } return -EBUSY; @@ -85,6 +91,10 @@ atomic64_set(&nfacct->pkts, be64_to_cpu(nla_get_be64(tb[NFACCT_PKTS]))); } + if (tb[NFACCT_FMT]) { + atomic_set(&nfacct->fmt, + be32_to_cpu(nla_get_be32(tb[NFACCT_FMT]))); + } atomic_set(&nfacct->refcnt, 1); list_add_tail_rcu(&nfacct->head, &nfnl_acct_list); return 0; @@ -121,6 +131,7 @@ } if (nla_put_be64(skb, NFACCT_PKTS, cpu_to_be64(pkts)) || nla_put_be64(skb, NFACCT_BYTES, cpu_to_be64(bytes)) || + nla_put_be32(skb, NFACCT_FMT, htonl(atomic_read(&acct->fmt))) || nla_put_be32(skb, NFACCT_USE, htonl(atomic_read(&acct->refcnt)))) goto nla_put_failure; @@ -265,6 +276,7 @@ [NFACCT_NAME] = { .type = NLA_NUL_STRING, .len = NFACCT_NAME_MAX-1 }, [NFACCT_BYTES] = { .type = NLA_U64 }, [NFACCT_PKTS] = { .type = NLA_U64 }, + [NFACCT_FMT] = { .type = NLA_U32 }, }; static const struct nfnl_callback nfnl_acct_cb[NFNL_MSG_ACCT_MAX] = { --- a/include/uapi/linux/netfilter/nfnetlink_acct.h +++ b/include/uapi/linux/netfilter/nfnetlink_acct.h @@ -18,6 +18,7 @@ NFACCT_NAME, NFACCT_PKTS, NFACCT_BYTES, + NFACCT_FMT, NFACCT_USE, __NFACCT_MAX };