From be5d9120e81e4a9a6d44457990112f30d0d214bb Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Sat, 26 Mar 2016 10:04:48 +0000 Subject: nft monitor [ trace ] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ... can now display nftables nftrace debug information. $ nft filter input tcp dport 10000 nftrace set 1 $ nft filter input icmp type echo-request nftrace set 1 $ nft -nn monitor trace trace id e1f5055f ip filter input packet: iif eth0 ether saddr 63:f6:4b:00:54:52 ether daddr c9:4b:a9:00:54:52 ip saddr 192.168.122.1 ip daddr 192.168.122.83 ip tos 0 ip ttl 64 ip id 32315 ip length 84 icmp type echo-request icmp code 0 icmp id 10087 icmp sequence 1 trace id e1f5055f ip filter input rule icmp type echo-request nftrace set 1 (verdict continue) trace id e1f5055f ip filter input verdict continue trace id e1f5055f ip filter input trace id 74e47ad2 ip filter input packet: iif vlan0 ether saddr 63:f6:4b:00:54:52 ether daddr c9:4b:a9:00:54:52 vlan pcp 0 vlan cfi 1 vlan id 1000 ip saddr 10.0.0.1 ip daddr 10.0.0.2 ip tos 0 ip ttl 64 ip id 49030 ip length 84 icmp type echo-request icmp code 0 icmp id 10095 icmp sequence 1 trace id 74e47ad2 ip filter input rule icmp type echo-request nftrace set 1 (verdict continue) trace id 74e47ad2 ip filter input verdict continue trace id 74e47ad2 ip filter input trace id 3030de23 ip filter input packet: iif vlan0 ether saddr 63:f6:4b:00:54:52 ether daddr c9:4b:a9:00:54:52 vlan pcp 0 vlan cfi 1 vlan id 1000 ip saddr 10.0.0.1 ip daddr 10.0.0.2 ip tos 16 ip ttl 64 ip id 59062 ip length 60 tcp sport 55438 tcp dport 10000 tcp flags == syn tcp window 29200 trace id 3030de23 ip filter input rule tcp dport 10000 nftrace set 1 (verdict continue) trace id 3030de23 ip filter input verdict continue trace id 3030de23 ip filter input Based on a patch from Florian Westphal, which again was based on a patch from Markus Kötter. Signed-off-by: Patrick McHardy --- src/rule.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 52 insertions(+), 9 deletions(-) (limited to 'src/rule.c') diff --git a/src/rule.c b/src/rule.c index 2fe67454..cd7f84e0 100644 --- a/src/rule.c +++ b/src/rule.c @@ -396,6 +396,17 @@ void rule_print(const struct rule *rule) printf(" # handle %" PRIu64, rule->handle.handle.id); } +struct rule *rule_lookup(const struct chain *chain, uint64_t handle) +{ + struct rule *rule; + + list_for_each_entry(rule, &chain->rules, list) { + if (rule->handle.handle.id == handle) + return rule; + } + return NULL; +} + struct scope *scope_init(struct scope *scope, const struct scope *parent) { scope->parent = parent; @@ -1198,27 +1209,59 @@ static int do_command_rename(struct netlink_ctx *ctx, struct cmd *cmd) return 0; } -static int do_command_monitor(struct netlink_ctx *ctx, struct cmd *cmd) +static bool need_cache(const struct cmd *cmd) { - struct table *t; - struct set *s; - struct netlink_mon_handler monhandler; - - /* cache only needed if monitoring: + /* * - new rules in default format * - new elements */ if (((cmd->monitor->flags & (1 << NFT_MSG_NEWRULE)) && (cmd->monitor->format == NFTNL_OUTPUT_DEFAULT)) || (cmd->monitor->flags & (1 << NFT_MSG_NEWSETELEM))) - monhandler.cache_needed = true; - else - monhandler.cache_needed = false; + return true; + + if (cmd->monitor->flags & (1 << NFT_MSG_TRACE)) + return true; + return false; +} + +static int do_command_monitor(struct netlink_ctx *ctx, struct cmd *cmd) +{ + struct table *t; + struct set *s; + struct netlink_mon_handler monhandler; + + monhandler.cache_needed = need_cache(cmd); if (monhandler.cache_needed) { + struct rule *rule, *nrule; + struct chain *chain; + int ret; + list_for_each_entry(t, &table_list, list) { list_for_each_entry(s, &t->sets, list) s->init = set_expr_alloc(&cmd->location); + + if (!(cmd->monitor->flags & (1 << NFT_MSG_TRACE))) + continue; + + /* When tracing we'd like to translate the rule handle + * we receive in the trace messages to the actual rule + * struct to print that out. Populate rule cache now. + */ + ret = netlink_list_table(ctx, &t->handle, + &internal_location); + + if (ret != 0) + /* Shouldn't happen and doesn't break things + * too badly + */ + continue; + + list_for_each_entry_safe(rule, nrule, &ctx->list, list) { + chain = chain_lookup(t, &rule->handle); + list_move_tail(&rule->list, &chain->rules); + } } } -- cgit v1.2.3