diff options
author | Florian Westphal <fw@strlen.de> | 2024-08-21 00:12:27 +0200 |
---|---|---|
committer | Pablo Neira Ayuso <pablo@netfilter.org> | 2025-09-01 22:47:56 +0200 |
commit | 76aed4a1603f1a25135a63326be10ffaae97d637 (patch) | |
tree | 0519d9f32e76ed552d14a8e4f718990380cda7b9 | |
parent | d66b9d9c887c17b3d7233cf72b17489867e1e11f (diff) |
src: mnl: always dump all netdev hooks if no interface name was given
commit db70959a5ccf2952b218f51c3d529e186a5a43bb upstream.
Instead of not returning any results for
nft list hooks netdev
Iterate all interfaces and then query all of them.
Signed-off-by: Florian Westphal <fw@strlen.de>
-rw-r--r-- | doc/additional-commands.txt | 116 | ||||
-rw-r--r-- | include/iface.h | 3 | ||||
-rw-r--r-- | src/iface.c | 17 | ||||
-rw-r--r-- | src/mnl.c | 30 |
4 files changed, 159 insertions, 7 deletions
diff --git a/doc/additional-commands.txt b/doc/additional-commands.txt new file mode 100644 index 00000000..2ebc2993 --- /dev/null +++ b/doc/additional-commands.txt @@ -0,0 +1,116 @@ +LIST HOOKS +~~~~~~~~~~ + +This shows the list of functions that have been registered for the +given protocol family, including functions that have been +registered implicitly by kernel modules such as nf_conntrack. + + +[verse] +____ +*list hooks* ['family'] +*list hooks netdev* [ *device* 'DEVICE_NAME' ] +____ + +*list hooks* is enough to display everything that is active +on the system. Hooks in the netdev family are tied to a network +device. If no device name is given, nft will query all network +devices in the current network namespace. +Example Usage: + +.List all active netfilter hooks in either the ip or ip6 stack +-------------------------------------------------------------- +% nft list hooks inet +family ip { + hook prerouting { + -0000000400 ipv4_conntrack_defrag [nf_defrag_ipv4] + -0000000200 ipv4_conntrack_in [nf_conntrack] + -0000000100 nf_nat_ipv4_pre_routing [nf_nat] + } + hook input { + 0000000000 chain inet filter input [nf_tables] + +0000000100 nf_nat_ipv4_local_in [nf_nat] +[..] +-------------------------------------------------------------- + +The above shows a host that has nat, conntrack and ipv4 packet +defragmentation enabled. +For each hook location for the queried family a list of active hooks +using the format + + +*priority* *identifier* [*module_name*] + +will be shown. + +The *priority* value dictates the order in which the hooks are called. +The list is sorted, the lowest number is run first. + +The priority value of hooks registered by the kernel cannot be changed. +For basechains registered by nftables, this value corresponds to the +*priority* value specified in the base chain definition. + +After the numerical value, information about the hook is shown. +For basechains defined in nftables this includes the table family, +the table name and the basechains name. +For hooks coming from kernel modules, the function name is used +instead. + +If a *module name* is given, the hook was registered by the kernel +module with this name. You can use 'modinfo *module name*' to +obtain more information about the module. + +This functionality requires a kernel built with the option + +CONFIG_NETFILTER_NETLINK_HOOK +enabled, either as a module or builtin. The module is named +*nfnetlink_hook*. + +MONITOR +~~~~~~~ +The monitor command allows you to listen to Netlink events produced by the +nf_tables subsystem. These are either related to creation and deletion of +objects or to packets for which *meta nftrace* was enabled. When they +occur, nft will print to stdout the monitored events in either JSON or +native nft format. + + +[verse] +____ +*monitor* [*new* | *destroy*] 'MONITOR_OBJECT' +*monitor* *trace* + +'MONITOR_OBJECT' := *tables* | *chains* | *sets* | *rules* | *elements* | *ruleset* +____ + +To filter events related to a concrete object, use one of the keywords in +'MONITOR_OBJECT'. + +To filter events related to a concrete action, use keyword *new* or *destroy*. + +The second form of invocation takes no further options and exclusively prints +events generated for packets with *nftrace* enabled. + +Hit ^C to finish the monitor operation. + +.Listen to all events, report in native nft format +-------------------------------------------------- +% nft monitor +-------------------------------------------------- + +.Listen to deleted rules, report in JSON format +----------------------------------------------- +% nft -j monitor destroy rules +----------------------------------------------- + +.Listen to both new and destroyed chains, in native nft format +----------------------------------------------------------------- +% nft monitor chains +------------------------------- + +.Listen to ruleset events such as table, chain, rule, set, counters and quotas, in native nft format +---------------------------------------------------------------------------------------------------- +% nft monitor ruleset +--------------------- + +.Trace incoming packets from host 10.0.0.1 +------------------------------------------ +% nft add rule filter input ip saddr 10.0.0.1 meta nftrace set 1 +% nft monitor trace +------------------------------------------ diff --git a/include/iface.h b/include/iface.h index f41ee8be..b61e974f 100644 --- a/include/iface.h +++ b/include/iface.h @@ -2,6 +2,8 @@ #define _NFTABLES_IFACE_H_ #include <net/if.h> +#include <list.h> +#include <stdint.h> struct iface { struct list_head list; @@ -15,4 +17,5 @@ char *nft_if_indextoname(unsigned int ifindex, char *name); void iface_cache_update(void); void iface_cache_release(void); +const struct iface *iface_cache_get_next_entry(const struct iface *prev); #endif diff --git a/src/iface.c b/src/iface.c index 3647778c..a67cb298 100644 --- a/src/iface.c +++ b/src/iface.c @@ -171,3 +171,20 @@ char *nft_if_indextoname(unsigned int ifindex, char *name) } return NULL; } + +const struct iface *iface_cache_get_next_entry(const struct iface *prev) +{ + if (!iface_cache_init) + iface_cache_update(); + + if (list_empty(&iface_list)) + return NULL; + + if (!prev) + return list_first_entry(&iface_list, struct iface, list); + + if (list_is_last(&prev->list, &iface_list)) + return NULL; + + return list_next_entry(prev, list); +} @@ -8,6 +8,8 @@ * Development of this code funded by Astaro AG (http://www.astaro.com/) */ +#include <iface.h> + #include <libmnl/libmnl.h> #include <libnftnl/common.h> #include <libnftnl/ruleset.h> @@ -2159,7 +2161,7 @@ static void basehook_list_add_tail(struct basehook *b, struct list_head *head) list_for_each_entry(hook, head, list) { if (hook->family != b->family) continue; - if (hook->num != b->num) + if (!basehook_eq(hook, b)) continue; if (hook->prio < b->prio) continue; @@ -2504,11 +2506,9 @@ int mnl_nft_dump_nf_hooks(struct netlink_ctx *ctx, int family, const char *devna if (tmp == 0) ret = 0; - if (devname) { - tmp = mnl_nft_dump_nf_hooks(ctx, NFPROTO_NETDEV, devname); - if (tmp == 0) - ret = 0; - } + tmp = mnl_nft_dump_nf_hooks(ctx, NFPROTO_NETDEV, devname); + if (tmp == 0) + ret = 0; return ret; case NFPROTO_INET: @@ -2535,7 +2535,23 @@ int mnl_nft_dump_nf_hooks(struct netlink_ctx *ctx, int family, const char *devna ret = mnl_nft_dump_nf_arp(ctx, family, devname, &hook_list); break; case NFPROTO_NETDEV: - ret = mnl_nft_dump_nf_netdev(ctx, family, devname, &hook_list); + if (devname) { + ret = mnl_nft_dump_nf_netdev(ctx, family, devname, &hook_list); + } else { + const struct iface *iface; + + iface = iface_cache_get_next_entry(NULL); + ret = 0; + + while (iface) { + tmp = mnl_nft_dump_nf_netdev(ctx, family, iface->name, &hook_list); + if (tmp == 0) + ret = 0; + + iface = iface_cache_get_next_entry(iface); + } + } + break; } |