From 9e62dc8637f210cdeaed784396fecab9b6e5f043 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Sun, 20 Jan 2013 20:19:20 +0100 Subject: xtables-restore: support atomic commit Use new services in nf_tables to support atomic commit. Commit per table, although we support global commit at once, call commit for each table to emulate iptables-restore behaviour by now. Keep table dormant/wake up code in iptables/nft.c as it can be used in the future. Signed-off-by: Pablo Neira Ayuso --- iptables/nft.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) (limited to 'iptables/nft.c') diff --git a/iptables/nft.c b/iptables/nft.c index fd19ff55..f42e4377 100644 --- a/iptables/nft.c +++ b/iptables/nft.c @@ -946,6 +946,10 @@ nft_rule_add(struct nft_handle *h, const char *chain, const char *table, flags |= NLM_F_REPLACE; } + if (h->commit) { + nft_rule_attr_set_u32(r, NFT_RULE_ATTR_FLAGS, + NFT_RULE_F_COMMIT); + } nlh = nft_rule_nlmsg_build_hdr(buf, NFT_MSG_NEWRULE, h->family, flags, h->seq); @@ -1626,6 +1630,11 @@ __nft_rule_flush(struct nft_handle *h, const char *table, const char *chain) nft_rule_attr_set(r, NFT_RULE_ATTR_TABLE, (char *)table); nft_rule_attr_set(r, NFT_RULE_ATTR_CHAIN, (char *)chain); + if (h->commit) { + nft_rule_attr_set_u32(r, NFT_RULE_ATTR_FLAGS, + NFT_RULE_F_COMMIT); + } + /* Delete all rules in this table + chain */ nlh = nft_chain_nlmsg_build_hdr(buf, NFT_MSG_DELRULE, h->family, NLM_F_ACK, h->seq); @@ -2773,6 +2782,10 @@ int nft_rule_delete(struct nft_handle *h, const char *chain, if (r != NULL) { ret = 1; + if (h->commit) { + nft_rule_attr_set_u32(r, NFT_RULE_ATTR_FLAGS, + NFT_RULE_F_COMMIT); + } DEBUGP("deleting rule\n"); __nft_rule_del(h, r); } else @@ -2802,6 +2815,10 @@ int nft_rule_delete_num(struct nft_handle *h, const char *chain, if (r != NULL) { ret = 1; + if (h->commit) { + nft_rule_attr_set_u32(r, NFT_RULE_ATTR_FLAGS, + NFT_RULE_F_COMMIT); + } DEBUGP("deleting rule by number %d\n", rulenum); __nft_rule_del(h, r); } else @@ -2834,6 +2851,10 @@ int nft_rule_replace(struct nft_handle *h, const char *chain, (unsigned long long) nft_rule_attr_get_u64(r, NFT_RULE_ATTR_HANDLE)); + if (h->commit) { + nft_rule_attr_set_u32(r, NFT_RULE_ATTR_FLAGS, + NFT_RULE_F_COMMIT); + } ret = nft_rule_add(h, chain, table, cs, true, nft_rule_attr_get_u64(r, NFT_RULE_ATTR_HANDLE), verbose); @@ -3435,6 +3456,41 @@ next: return 1; } +static int nft_action(struct nft_handle *h, int type) +{ + char buf[MNL_SOCKET_BUFFER_SIZE]; + struct nlmsghdr *nlh; + uint32_t seq; + int ret; + + nlh = mnl_nlmsg_put_header(buf); + nlh->nlmsg_type = (NFNL_SUBSYS_NFTABLES<< 8) | type; + nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; + nlh->nlmsg_seq = seq = time(NULL); + + struct nfgenmsg *nfg = mnl_nlmsg_put_extra_header(nlh, sizeof(*nfg)); + nfg->nfgen_family = AF_INET; + nfg->version = NFNETLINK_V0; + nfg->res_id = 0; + + ret = mnl_talk(h, nlh, NULL, NULL); + if (ret < 0) { + if (errno != EEXIST) + perror("mnl-talk:nft_commit"); + } + return ret; +} + +int nft_commit(struct nft_handle *h) +{ + return nft_action(h, NFT_MSG_COMMIT); +} + +int nft_abort(struct nft_handle *h) +{ + return nft_action(h, NFT_MSG_ABORT); +} + int nft_compatible_revision(const char *name, uint8_t rev, int opt) { struct mnl_socket *nl; -- cgit v1.2.3