From: Antonio Ospite <ao2@xxxxxx> Add a new FMT_ZEROED_CHAIN_COUNTS and use it in the save_chain() callbacks to implement the '-Z' option for xtables-save as well. Having zeroed chain counters is particularly useful when using a version control system (like git) to track the saved iptables rules, to minimize the delta between different ruleset versions. Signed-off-by: Antonio Ospite <ao2@xxxxxx> --- include/xtables.h | 1 + iptables/nft-arp.c | 3 ++- iptables/nft-bridge.c | 3 ++- iptables/nft-shared.c | 8 +++++++- iptables/nft-shared.h | 6 ++++-- iptables/nft.c | 4 ++-- iptables/nft.h | 2 +- iptables/xtables-save.c | 9 +++++---- 8 files changed, 24 insertions(+), 12 deletions(-) diff --git a/include/xtables.h b/include/xtables.h index 4aa084a..0aaca74 100644 --- a/include/xtables.h +++ b/include/xtables.h @@ -550,6 +550,7 @@ extern void xtables_save_string(const char *value); #define FMT_LINENUMBERS 0x0100 #define FMT_EBT_SAVE 0x0200 #define FMT_C_COUNTS 0x0400 +#define FMT_ZEROED_CHAIN_COUNTS 0x0800 #define FMT_PRINT_RULE (FMT_NOCOUNTS | FMT_OPTIONS | FMT_VIA \ | FMT_NUMERIC | FMT_NOTABLE) diff --git a/iptables/nft-arp.c b/iptables/nft-arp.c index 637da42..4ec2287 100644 --- a/iptables/nft-arp.c +++ b/iptables/nft-arp.c @@ -679,7 +679,8 @@ out: return ret; } -static void nft_arp_save_chain(const struct nftnl_chain *c, const char *policy) +static void nft_arp_save_chain(const struct nftnl_chain *c, const char *policy, + unsigned int format) { const char *chain = nftnl_chain_get_str(c, NFTNL_CHAIN_NAME); diff --git a/iptables/nft-bridge.c b/iptables/nft-bridge.c index ddfbee1..10b1dda 100644 --- a/iptables/nft-bridge.c +++ b/iptables/nft-bridge.c @@ -502,7 +502,8 @@ static void nft_bridge_print_rule(struct nftnl_rule *r, unsigned int num, } static void nft_bridge_save_chain(const struct nftnl_chain *c, - const char *policy) + const char *policy, + unsigned int format) { const char *chain = nftnl_chain_get_str(c, NFTNL_CHAIN_NAME); diff --git a/iptables/nft-shared.c b/iptables/nft-shared.c index 1c09277..0b7d380 100644 --- a/iptables/nft-shared.c +++ b/iptables/nft-shared.c @@ -832,12 +832,18 @@ void save_counters(const void *data) (unsigned long long)cs->counters.bcnt); } -void nft_ipv46_save_chain(const struct nftnl_chain *c, const char *policy) +void nft_ipv46_save_chain(const struct nftnl_chain *c, const char *policy, + unsigned int format) { const char *chain = nftnl_chain_get_str(c, NFTNL_CHAIN_NAME); uint64_t pkts = nftnl_chain_get_u64(c, NFTNL_CHAIN_PACKETS); uint64_t bytes = nftnl_chain_get_u64(c, NFTNL_CHAIN_BYTES); + if (format & FMT_ZEROED_CHAIN_COUNTS) { + pkts = 0; + bytes = 0; + } + printf(":%s %s [%"PRIu64":%"PRIu64"]\n", chain, policy ?: "-", pkts, bytes); } diff --git a/iptables/nft-shared.h b/iptables/nft-shared.h index 019c1f2..0603c6b 100644 --- a/iptables/nft-shared.h +++ b/iptables/nft-shared.h @@ -93,7 +93,8 @@ struct nft_family_ops { unsigned int format); void (*save_rule)(const void *data, unsigned int format); void (*save_counters)(const void *data); - void (*save_chain)(const struct nftnl_chain *c, const char *policy); + void (*save_chain)(const struct nftnl_chain *c, const char *policy, + unsigned int format); void (*proto_parse)(struct iptables_command_state *cs, struct xtables_args *args); void (*post_parse)(int command, struct iptables_command_state *cs, @@ -156,7 +157,8 @@ void save_rule_details(const struct iptables_command_state *cs, const char *outiface, unsigned const char *outiface_mask); void save_counters(const void *data); -void nft_ipv46_save_chain(const struct nftnl_chain *c, const char *policy); +void nft_ipv46_save_chain(const struct nftnl_chain *c, const char *policy, + unsigned int format); void save_matches_and_target(const struct iptables_command_state *cs, bool goto_flag, const void *fw, unsigned int format); diff --git a/iptables/nft.c b/iptables/nft.c index a297d98..e1fd802 100644 --- a/iptables/nft.c +++ b/iptables/nft.c @@ -1507,7 +1507,7 @@ static const char *policy_name[NF_ACCEPT+1] = { [NF_ACCEPT] = "ACCEPT", }; -int nft_chain_save(struct nft_handle *h, struct nftnl_chain_list *list) +int nft_chain_save(struct nft_handle *h, struct nftnl_chain_list *list, unsigned int format) { struct nftnl_chain_list_iter *iter; struct nft_family_ops *ops; @@ -1541,7 +1541,7 @@ int nft_chain_save(struct nft_handle *h, struct nftnl_chain_list *list) } if (ops->save_chain) - ops->save_chain(c, policy); + ops->save_chain(c, policy, format); c = nftnl_chain_list_iter_next(iter); } diff --git a/iptables/nft.h b/iptables/nft.h index 56dc207..25f6dcf 100644 --- a/iptables/nft.h +++ b/iptables/nft.h @@ -84,7 +84,7 @@ struct nftnl_chain; int nft_chain_set(struct nft_handle *h, const char *table, const char *chain, const char *policy, const struct xt_counters *counters); struct nftnl_chain_list *nft_chain_list_get(struct nft_handle *h, const char *table); -int nft_chain_save(struct nft_handle *h, struct nftnl_chain_list *list); +int nft_chain_save(struct nft_handle *h, struct nftnl_chain_list *list, unsigned int format); int nft_chain_user_add(struct nft_handle *h, const char *chain, const char *table); int nft_chain_user_del(struct nft_handle *h, const char *chain, const char *table, bool verbose); int nft_chain_user_flush(struct nft_handle *h, struct nftnl_chain_list *list, diff --git a/iptables/xtables-save.c b/iptables/xtables-save.c index cee9137..59ad89b 100644 --- a/iptables/xtables-save.c +++ b/iptables/xtables-save.c @@ -30,6 +30,7 @@ #define prog_vers xtables_globals.program_version static bool show_counters = false; +static bool display_zero_counters = false; static const struct option options[] = { {.name = "counters", .has_arg = false, .val = 'c'}, @@ -86,7 +87,7 @@ __do_output(struct nft_handle *h, const char *tablename, bool counters) /* Dump out chain names first, * thereby preventing dependency conflicts */ - nft_chain_save(h, chain_list); + nft_chain_save(h, chain_list, display_zero_counters ? FMT_ZEROED_CHAIN_COUNTS : 0); nft_rule_save(h, tablename, counters ? 0 : FMT_NOCOUNTS); now = time(NULL); @@ -151,7 +152,7 @@ xtables_save_main(int family, const char *progname, int argc, char *argv[]) show_counters = true; break; case 'Z': - fprintf(stderr, "-Z/--zero option is not implemented yet\n"); + display_zero_counters = true; break; case 't': /* Select specific table. */ @@ -278,7 +279,7 @@ static int __ebt_save(struct nft_handle *h, const char *tablename, bool counters /* Dump out chain names first, * thereby preventing dependency conflicts */ - nft_chain_save(h, chain_list); + nft_chain_save(h, chain_list, display_zero_counters ? FMT_ZEROED_CHAIN_COUNTS : 0); nft_rule_save(h, tablename, format); printf("\n"); return 0; @@ -405,7 +406,7 @@ int xtables_arp_save_main(int argc, char **argv) } printf("*filter\n"); - nft_chain_save(&h, nft_chain_list_get(&h, "filter")); + nft_chain_save(&h, nft_chain_list_get(&h, "filter"), display_zero_counters ? FMT_ZEROED_CHAIN_COUNTS : 0); nft_rule_save(&h, "filter", show_counters ? 0 : FMT_NOCOUNTS); printf("\n"); nft_fini(&h); -- 2.20.1