All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH nft 0/3] hook dump support
@ 2021-05-21 12:08 Florian Westphal
  2021-05-21 12:08 ` [PATCH nft 1/3] scanner: add list cmd parser scope Florian Westphal
                   ` (2 more replies)
  0 siblings, 3 replies; 5+ messages in thread
From: Florian Westphal @ 2021-05-21 12:08 UTC (permalink / raw)
  To: netfilter-devel; +Cc: Florian Westphal

This adds nft-side support for the hook dump feature.
First patch adds scope for 'list' so that the new "hooks"
keyword won't interfere with table/rule parsing.

Second patch is the dump feature.
Last patch adds a LISTING section to the man page.

There is no libnftnl integration since the hook dump
is technically not related to nftables.

Florian Westphal (3):
  scanner: add list cmd parser scope
  src: add support for base hook dumping
  doc: add LISTING section

 doc/nft.txt                         |  13 ++
 include/linux/netfilter/nf_tables.h |   4 +
 include/mnl.h                       |   3 +
 include/parser.h                    |   1 +
 include/rule.h                      |   1 +
 src/evaluate.c                      |  10 ++
 src/mnl.c                           | 269 +++++++++++++++++++++++++++-
 src/parser_bison.y                  |  51 +++++-
 src/rule.c                          |  13 ++
 src/scanner.l                       |  16 +-
 10 files changed, 371 insertions(+), 10 deletions(-)

-- 
2.26.3


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH nft 1/3] scanner: add list cmd parser scope
  2021-05-21 12:08 [PATCH nft 0/3] hook dump support Florian Westphal
@ 2021-05-21 12:08 ` Florian Westphal
  2021-05-21 12:08 ` [PATCH nft 2/3] src: add support for base hook dumping Florian Westphal
  2021-05-21 12:08 ` [PATCH nft 3/3] doc: add LISTING section Florian Westphal
  2 siblings, 0 replies; 5+ messages in thread
From: Florian Westphal @ 2021-05-21 12:08 UTC (permalink / raw)
  To: netfilter-devel; +Cc: Florian Westphal

Followup patch will add new 'hooks' keyword for
  nft list hooks

Add a scope for list to avoid exposure of the new keyword in nft
rulesets.

Signed-off-by: Florian Westphal <fw@strlen.de>
---
 include/parser.h   |  1 +
 src/parser_bison.y |  3 ++-
 src/scanner.l      | 15 +++++++++------
 3 files changed, 12 insertions(+), 7 deletions(-)

diff --git a/include/parser.h b/include/parser.h
index 1a272ee25b4c..e8635b4c0feb 100644
--- a/include/parser.h
+++ b/include/parser.h
@@ -41,6 +41,7 @@ enum startcond_type {
 	PARSER_SC_SCTP,
 	PARSER_SC_SECMARK,
 	PARSER_SC_VLAN,
+	PARSER_SC_CMD_LIST,
 	PARSER_SC_EXPR_FIB,
 	PARSER_SC_EXPR_HASH,
 	PARSER_SC_EXPR_IPSEC,
diff --git a/src/parser_bison.y b/src/parser_bison.y
index 3a11e6971177..f6c92feb7661 100644
--- a/src/parser_bison.y
+++ b/src/parser_bison.y
@@ -913,6 +913,7 @@ close_scope_ip		: { scanner_pop_start_cond(nft->scanner, PARSER_SC_IP); };
 close_scope_ip6		: { scanner_pop_start_cond(nft->scanner, PARSER_SC_IP6); };
 close_scope_vlan	: { scanner_pop_start_cond(nft->scanner, PARSER_SC_VLAN); };
 close_scope_ipsec	: { scanner_pop_start_cond(nft->scanner, PARSER_SC_EXPR_IPSEC); };
+close_scope_list	: { scanner_pop_start_cond(nft->scanner, PARSER_SC_CMD_LIST); };
 close_scope_limit	: { scanner_pop_start_cond(nft->scanner, PARSER_SC_LIMIT); };
 close_scope_numgen	: { scanner_pop_start_cond(nft->scanner, PARSER_SC_EXPR_NUMGEN); };
 close_scope_quota	: { scanner_pop_start_cond(nft->scanner, PARSER_SC_QUOTA); };
@@ -1004,7 +1005,7 @@ base_cmd		:	/* empty */	add_cmd		{ $$ = $1; }
 			|	INSERT		insert_cmd	{ $$ = $2; }
 			|	DELETE		delete_cmd	{ $$ = $2; }
 			|	GET		get_cmd		{ $$ = $2; }
-			|	LIST		list_cmd	{ $$ = $2; }
+			|	LIST		list_cmd	close_scope_list	{ $$ = $2; }
 			|	RESET		reset_cmd	{ $$ = $2; }
 			|	FLUSH		flush_cmd	{ $$ = $2; }
 			|	RENAME		rename_cmd	{ $$ = $2; }
diff --git a/src/scanner.l b/src/scanner.l
index 5c493e390c2c..c1bc21aa7ecc 100644
--- a/src/scanner.l
+++ b/src/scanner.l
@@ -207,6 +207,7 @@ addrstring	({macaddr}|{ip4addr}|{ip6addr})
 %s SCANSTATE_SCTP
 %s SCANSTATE_SECMARK
 %s SCANSTATE_VLAN
+%s SCANSTATE_CMD_LIST
 %s SCANSTATE_EXPR_FIB
 %s SCANSTATE_EXPR_HASH
 %s SCANSTATE_EXPR_IPSEC
@@ -317,7 +318,7 @@ addrstring	({macaddr}|{ip4addr}|{ip6addr})
 "insert"		{ return INSERT; }
 "delete"		{ return DELETE; }
 "get"			{ return GET; }
-"list"			{ return LIST; }
+"list"			{ scanner_push_start_cond(yyscanner, SCANSTATE_CMD_LIST); return LIST; }
 "reset"			{ return RESET; }
 "flush"			{ return FLUSH; }
 "rename"		{ return RENAME; }
@@ -346,9 +347,14 @@ addrstring	({macaddr}|{ip4addr}|{ip6addr})
 "flow"			{ return FLOW; }
 "offload"		{ return OFFLOAD; }
 "meter"			{ return METER; }
-"meters"		{ return METERS; }
 
-"flowtables"		{ return FLOWTABLES; }
+<SCANSTATE_CMD_LIST>{
+	"meters"		{ return METERS; }
+	"flowtables"		{ return FLOWTABLES; }
+	"limits"		{ return LIMITS; }
+	"secmarks"		{ return SECMARKS; }
+	"synproxys"		{ return SYNPROXYS; }
+}
 
 "counter"		{ scanner_push_start_cond(yyscanner, SCANSTATE_COUNTER); return COUNTER; }
 "name"			{ return NAME; }
@@ -357,8 +363,6 @@ addrstring	({macaddr}|{ip4addr}|{ip6addr})
 
 "counters"		{ return COUNTERS; }
 "quotas"		{ return QUOTAS; }
-"limits"		{ return LIMITS; }
-"synproxys"		{ return SYNPROXYS; }
 
 "log"			{ scanner_push_start_cond(yyscanner, SCANSTATE_STMT_LOG); return LOG; }
 "prefix"		{ return PREFIX; }
@@ -687,7 +691,6 @@ addrstring	({macaddr}|{ip4addr}|{ip6addr})
 }
 
 "secmark"		{ scanner_push_start_cond(yyscanner, SCANSTATE_SECMARK); return SECMARK; }
-"secmarks"		{ return SECMARKS; }
 
 {addrstring}		{
 				yylval->string = xstrdup(yytext);
-- 
2.26.3


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH nft 2/3] src: add support for base hook dumping
  2021-05-21 12:08 [PATCH nft 0/3] hook dump support Florian Westphal
  2021-05-21 12:08 ` [PATCH nft 1/3] scanner: add list cmd parser scope Florian Westphal
@ 2021-05-21 12:08 ` Florian Westphal
  2021-05-21 12:08 ` [PATCH nft 3/3] doc: add LISTING section Florian Westphal
  2 siblings, 0 replies; 5+ messages in thread
From: Florian Westphal @ 2021-05-21 12:08 UTC (permalink / raw)
  To: netfilter-devel; +Cc: Florian Westphal

Example output:
$ nft list hook ip input
family ip hook input {
        +0000000000 nft_do_chain_inet [nf_tables]       # nft table ip filter chain input
        +0000000010 nft_do_chain_inet [nf_tables]       # nft table ip firewalld chain filter_INPUT
        +0000000100 nf_nat_ipv4_local_in [nf_nat]
        +2147483647 ipv4_confirm [nf_conntrack]
}

$ nft list hooks netdev type ingress device lo
family netdev hook ingress device lo {
        +0000000000 nft_do_chain_netdev [nf_tables]
}

$ nft list hooks inet
family ip hook prerouting {
        -0000000400 ipv4_conntrack_defrag [nf_defrag_ipv4]
        -0000000300 iptable_raw_hook [iptable_raw]
        -0000000290 nft_do_chain_inet [nf_tables]       # nft table ip firewalld chain raw_PREROUTING
        -0000000200 ipv4_conntrack_in [nf_conntrack]
        -0000000140 nft_do_chain_inet [nf_tables]       # nft table ip firewalld chain mangle_PREROUTING
        -0000000100 nf_nat_ipv4_pre_routing [nf_nat]
}
...

'nft list hooks' will display everyting except the netdev family
via successive dump request for all family:hook combinations.

Signed-off-by: Florian Westphal <fw@strlen.de>
---
 include/linux/netfilter/nf_tables.h |   4 +
 include/mnl.h                       |   3 +
 include/rule.h                      |   1 +
 src/evaluate.c                      |  10 ++
 src/mnl.c                           | 269 +++++++++++++++++++++++++++-
 src/parser_bison.y                  |  48 ++++-
 src/rule.c                          |  13 ++
 src/scanner.l                       |   1 +
 8 files changed, 346 insertions(+), 3 deletions(-)

diff --git a/include/linux/netfilter/nf_tables.h b/include/linux/netfilter/nf_tables.h
index 75df968d231b..c53b0383ebac 100644
--- a/include/linux/netfilter/nf_tables.h
+++ b/include/linux/netfilter/nf_tables.h
@@ -124,6 +124,7 @@ enum nf_tables_msg_types {
 	NFT_MSG_NEWFLOWTABLE,
 	NFT_MSG_GETFLOWTABLE,
 	NFT_MSG_DELFLOWTABLE,
+	NFT_MSG_GETFNHOOKS,
 	NFT_MSG_MAX,
 };
 
@@ -153,6 +154,9 @@ enum nft_hook_attributes {
 	NFTA_HOOK_PRIORITY,
 	NFTA_HOOK_DEV,
 	NFTA_HOOK_DEVS,
+	NFTA_HOOK_FUNCTION_NAME,
+	NFTA_HOOK_MODULE_NAME,
+	NFTA_HOOK_NFT_CHAIN_INFO,
 	__NFTA_HOOK_MAX
 };
 #define NFTA_HOOK_MAX		(__NFTA_HOOK_MAX - 1)
diff --git a/include/mnl.h b/include/mnl.h
index 979929c31c17..68ec80cd2282 100644
--- a/include/mnl.h
+++ b/include/mnl.h
@@ -82,6 +82,9 @@ int mnl_nft_flowtable_add(struct netlink_ctx *ctx, struct cmd *cmd,
 			  unsigned int flags);
 int mnl_nft_flowtable_del(struct netlink_ctx *ctx, struct cmd *cmd);
 
+int mnl_nft_dump_nf_hooks(struct netlink_ctx *ctx, int family, int hook,
+			  const char *devname);
+
 int mnl_nft_event_listener(struct mnl_socket *nf_sock, unsigned int debug_mask,
 			   struct output_ctx *octx,
 			   int (*cb)(const struct nlmsghdr *nlh, void *data),
diff --git a/include/rule.h b/include/rule.h
index f469db55bf60..357326a3fceb 100644
--- a/include/rule.h
+++ b/include/rule.h
@@ -644,6 +644,7 @@ enum cmd_obj {
 	CMD_OBJ_CT_EXPECT,
 	CMD_OBJ_SYNPROXY,
 	CMD_OBJ_SYNPROXYS,
+	CMD_OBJ_HOOKS,
 };
 
 struct markup {
diff --git a/src/evaluate.c b/src/evaluate.c
index 006b04affbd7..d1c6dd84ec90 100644
--- a/src/evaluate.c
+++ b/src/evaluate.c
@@ -4698,6 +4698,16 @@ static int cmd_evaluate_list(struct eval_ctx *ctx, struct cmd *cmd)
 	case CMD_OBJ_METERS:
 	case CMD_OBJ_MAPS:
 		return 0;
+	case CMD_OBJ_HOOKS:
+		if (cmd->handle.chain.name) {
+			int hooknum = str2hooknum(cmd->handle.family, cmd->handle.chain.name);
+
+			if (hooknum == NF_INET_NUMHOOKS)
+				return chain_not_found(ctx);
+
+			cmd->handle.chain_id = hooknum;
+		}
+		return 0;
 	default:
 		BUG("invalid command object type %u\n", cmd->obj);
 	}
diff --git a/src/mnl.c b/src/mnl.c
index ef45cbd193f9..83612962c98e 100644
--- a/src/mnl.c
+++ b/src/mnl.c
@@ -34,6 +34,17 @@
 #include <stdlib.h>
 #include <utils.h>
 #include <nftables.h>
+#include <linux/netfilter.h>
+#include <linux/netfilter_arp.h>
+
+struct basehook {
+	struct list_head list;
+	const char *module_name;
+	const char *hookfn;
+	const char *table;
+	const char *chain;
+	int prio;
+};
 
 struct mnl_socket *nft_mnl_socket_open(void)
 {
@@ -1874,7 +1885,7 @@ int mnl_nft_event_listener(struct mnl_socket *nf_sock, unsigned int debug_mask,
 			   void *cb_data)
 {
 	/* Set netlink socket buffer size to 16 Mbytes to reduce chances of
- 	 * message loss due to ENOBUFS.
+	 * message loss due to ENOBUFS.
 	 */
 	unsigned int bufsiz = NFTABLES_NLEVENT_BUFSIZ;
 	int fd = mnl_socket_get_fd(nf_sock);
@@ -1918,3 +1929,259 @@ int mnl_nft_event_listener(struct mnl_socket *nf_sock, unsigned int debug_mask,
 	}
 	return ret;
 }
+
+static struct basehook *basehook_alloc(void)
+{
+	return xzalloc(sizeof(struct basehook));
+}
+
+static void basehook_free(struct basehook *b)
+{
+	list_del(&b->list);
+	xfree(b->module_name);
+	xfree(b->hookfn);
+	xfree(b->chain);
+	xfree(b->table);
+	xfree(b);
+}
+
+static void basehook_list_add_tail(struct basehook *b, struct list_head *head)
+{
+	list_add_tail(&b->list, head);
+}
+
+static int dump_nf_attr_cb(const struct nlattr *attr, void *data)
+{
+        int type = mnl_attr_get_type(attr);
+	const struct nlattr **tb = data;
+
+        if (mnl_attr_type_valid(attr, NFTA_HOOK_MAX) < 0)
+                return MNL_CB_OK;
+
+        switch(type) {
+	case NFTA_HOOK_HOOKNUM:
+	case NFTA_HOOK_PRIORITY:
+                if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
+                        return MNL_CB_ERROR;
+		break;
+	case NFTA_HOOK_DEV:
+	case NFTA_HOOK_FUNCTION_NAME:
+	case NFTA_HOOK_MODULE_NAME:
+                if (mnl_attr_validate(attr, MNL_TYPE_STRING) < 0)
+                        return MNL_CB_ERROR;
+		break;
+	case NFTA_HOOK_NFT_CHAIN_INFO:
+                if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0)
+                        return MNL_CB_ERROR;
+		break;
+	default:
+		return MNL_CB_OK;
+	}
+
+	tb[type] = attr;
+	return MNL_CB_OK;
+}
+
+static int dump_nf_attr_chain_cb(const struct nlattr *attr, void *data)
+{
+        int type = mnl_attr_get_type(attr);
+	const struct nlattr **tb = data;
+
+        if (mnl_attr_type_valid(attr, NFTA_CHAIN_MAX) < 0)
+                return MNL_CB_OK;
+
+        switch(type) {
+	case NFTA_CHAIN_TABLE:
+	case NFTA_CHAIN_NAME:
+                if (mnl_attr_validate(attr, MNL_TYPE_NUL_STRING) < 0)
+                        return MNL_CB_ERROR;
+		break;
+	default:
+		return MNL_CB_OK;
+	}
+
+	tb[type] = attr;
+	return MNL_CB_OK;
+}
+
+static int dump_nf_hooks(const struct nlmsghdr *nlh, void *data)
+{
+	const struct nfgenmsg *nfg = mnl_nlmsg_get_payload(nlh);
+	struct nlattr *tb[NFTA_HOOK_MAX + 1] = {};
+	struct list_head *head = data;
+	struct basehook *hook;
+
+	if (check_genid(nlh) < 0)
+		return MNL_CB_ERROR;
+
+        if (mnl_attr_parse(nlh, sizeof(*nfg), dump_nf_attr_cb, tb) < 0)
+                return -1;
+
+	hook = basehook_alloc();
+	hook->prio = ntohl(mnl_attr_get_u32(tb[NFTA_HOOK_PRIORITY]));
+
+	if (tb[NFTA_HOOK_FUNCTION_NAME])
+		hook->hookfn = xstrdup(mnl_attr_get_str(tb[NFTA_HOOK_FUNCTION_NAME]));
+
+	if (tb[NFTA_HOOK_MODULE_NAME])
+		hook->module_name = xstrdup(mnl_attr_get_str(tb[NFTA_HOOK_MODULE_NAME]));
+
+	if (tb[NFTA_HOOK_NFT_CHAIN_INFO]) {
+		struct nlattr *nested[NFTA_CHAIN_MAX + 1] = {};
+
+		if (mnl_attr_parse_nested(tb[NFTA_HOOK_NFT_CHAIN_INFO], dump_nf_attr_chain_cb, nested) < 0)
+			return -1;
+
+		hook->table = xstrdup(mnl_attr_get_str(nested[NFTA_CHAIN_TABLE]));
+		hook->chain = xstrdup(mnl_attr_get_str(nested[NFTA_CHAIN_NAME]));
+	}
+
+	basehook_list_add_tail(hook, head);
+	return MNL_CB_OK;
+}
+
+static int __mnl_nft_dump_nf_hooks(struct netlink_ctx *ctx, uint8_t family, uint8_t hooknum, const char *devname)
+{
+	char buf[MNL_SOCKET_BUFFER_SIZE];
+	struct basehook *hook, *tmp;
+	struct nlmsghdr *nlh;
+	LIST_HEAD(hook_list);
+	FILE *fp;
+	int ret;
+
+	nlh = nftnl_nlmsg_build_hdr(buf, NFT_MSG_GETFNHOOKS, family,
+				    NLM_F_DUMP, ctx->seqnum);
+
+	if (devname)
+		mnl_attr_put_strz(nlh, NFTA_HOOK_DEV, devname);
+
+	mnl_attr_put_u32(nlh, NFTA_HOOK_HOOKNUM, htonl(hooknum));
+
+	ret = nft_mnl_talk(ctx, nlh, nlh->nlmsg_len, dump_nf_hooks, &hook_list);
+	if (ret)
+		return ret;
+
+	if (list_empty(&hook_list))
+		return 0;
+
+	fp = ctx->nft->output.output_fp;
+	fprintf(fp, "family %s hook %s", family2str(family), hooknum2str(family, hooknum));
+	if (devname)
+		fprintf(fp, " device %s", devname);
+
+	fprintf(fp, " {\n");
+
+	list_for_each_entry_safe(hook, tmp, &hook_list, list) {
+		int prio = hook->prio;
+
+		if (prio < 0)
+			fprintf(fp, "\t%011d", prio); /* outputs a '-' sign */
+		else
+			fprintf(fp, "\t+%010u", prio);
+
+		if (hook->hookfn) {
+			fprintf(fp, " %s", hook->hookfn);
+			if (hook->module_name)
+				fprintf(fp, " [%s]", hook->module_name);
+		}
+
+		if (hook->table && hook->chain)
+			fprintf(fp, "\t# nft table %s %s chain %s", family2str(family), hook->table, hook->chain);
+
+		fprintf(fp, "\n");
+		basehook_free(hook);
+	}
+
+	fprintf(fp, "}\n");
+	return ret;
+}
+
+int mnl_nft_dump_nf_hooks(struct netlink_ctx *ctx, int family, int hook, const char *devname)
+{
+	unsigned int i;
+	int ret, err;
+
+	errno = 0;
+	ret = 0;
+
+	switch (family) {
+	case NFPROTO_UNSPEC:
+		if (devname)
+			return mnl_nft_dump_nf_hooks(ctx, NFPROTO_NETDEV, NF_INET_INGRESS, devname);
+
+		err = mnl_nft_dump_nf_hooks(ctx, NFPROTO_INET, hook, NULL);
+		if (err < 0 && errno != EPROTONOSUPPORT)
+			ret = err;
+		err = mnl_nft_dump_nf_hooks(ctx, NFPROTO_ARP, hook, NULL);
+		if (err < 0 && errno != EPROTONOSUPPORT)
+			ret = err;
+		err = mnl_nft_dump_nf_hooks(ctx, NFPROTO_BRIDGE, hook, NULL);
+		if (err < 0 && errno != EPROTONOSUPPORT)
+			ret = err;
+		err = mnl_nft_dump_nf_hooks(ctx, NFPROTO_DECNET, hook, NULL);
+		if (err < 0 && errno != EPROTONOSUPPORT)
+			ret = err;
+		ret = 0;
+		break;
+	case NFPROTO_INET:
+		if (devname) {
+			err = __mnl_nft_dump_nf_hooks(ctx, family, NF_INET_INGRESS, devname);
+			if (err < 0)
+				ret = err;
+		}
+
+		err = mnl_nft_dump_nf_hooks(ctx, NFPROTO_IPV4, hook, NULL);
+		if (err < 0)
+			ret = err;
+		err = mnl_nft_dump_nf_hooks(ctx, NFPROTO_IPV6, hook, NULL);
+		if (err < 0)
+			ret = err;
+
+		break;
+	case NFPROTO_IPV4:
+	case NFPROTO_IPV6:
+	case NFPROTO_BRIDGE:
+		if (hook >= 0)
+			return __mnl_nft_dump_nf_hooks(ctx, family, hook, devname);
+
+		for (i = 0; i <= NF_INET_POST_ROUTING; i++) {
+			err = __mnl_nft_dump_nf_hooks(ctx, family, i, NULL);
+			if (err < 0)
+				err = ret;
+		}
+		break;
+	case NFPROTO_ARP:
+		if (hook >= 0)
+			return __mnl_nft_dump_nf_hooks(ctx, family, hook, devname);
+
+		err = __mnl_nft_dump_nf_hooks(ctx, family, NF_ARP_IN, devname);
+		if (err < 0)
+			ret = err;
+		err = __mnl_nft_dump_nf_hooks(ctx, family, NF_ARP_OUT, devname);
+		if (err < 0)
+			ret = err;
+		break;
+	case NFPROTO_NETDEV:
+		if (hook >= 0)
+			return __mnl_nft_dump_nf_hooks(ctx, family, hook, devname);
+
+		err = __mnl_nft_dump_nf_hooks(ctx, family, NF_INET_INGRESS, devname);
+		if (err < 0)
+			ret = err;
+		break;
+	case NFPROTO_DECNET:
+		if (hook >= 0)
+			return __mnl_nft_dump_nf_hooks(ctx, family, hook, devname);
+#define NF_DN_NUMHOOKS		7
+		for (i = 0; i < NF_DN_NUMHOOKS; i++) {
+			err = __mnl_nft_dump_nf_hooks(ctx, family, i, devname);
+			if (err < 0) {
+				ret = err;
+				break;
+			}
+		}
+		break;
+	}
+
+	return ret;
+}
diff --git a/src/parser_bison.y b/src/parser_bison.y
index f6c92feb7661..136ae105f513 100644
--- a/src/parser_bison.y
+++ b/src/parser_bison.y
@@ -238,6 +238,7 @@ int nft_lex(void *, void *, void *);
 %token TYPEOF			"typeof"
 
 %token HOOK			"hook"
+%token HOOKS			"hooks"
 %token DEVICE			"device"
 %token DEVICES			"devices"
 %token TABLE			"table"
@@ -632,11 +633,15 @@ int nft_lex(void *, void *, void *);
 
 %type <handle>			set_identifier flowtableid_spec flowtable_identifier obj_identifier
 %destructor { handle_free(&$$); } set_identifier flowtableid_spec obj_identifier
+
+%type <handle>			basehook_spec
+%destructor { handle_free(&$$); } basehook_spec
+
 %type <val>			family_spec family_spec_explicit
 %type <val32>			int_num	chain_policy
 %type <prio_spec>		extended_prio_spec prio_spec
-%type <string>			extended_prio_name quota_unit
-%destructor { xfree($$); }	extended_prio_name quota_unit
+%type <string>			extended_prio_name quota_unit	basehook_device_name
+%destructor { xfree($$); }	extended_prio_name quota_unit	basehook_device_name
 
 %type <expr>			dev_spec
 %destructor { xfree($$); }	dev_spec
@@ -1456,6 +1461,45 @@ list_cmd		:	TABLE		table_spec
 			{
 				$$ = cmd_alloc(CMD_LIST, $2, &$4, &@$, NULL);
 			}
+			|	HOOKS	basehook_spec
+			{
+				$$ = cmd_alloc(CMD_LIST, CMD_OBJ_HOOKS, &$2, &@$, NULL);
+			}
+			;
+
+basehook_device_name	:	/* NULL */
+			{
+				$$ = NULL;
+			}
+			|	DEVICE STRING
+			{
+				$$ = $2;
+			}
+			;
+
+basehook_spec		:	ruleset_spec
+			{
+				$$ = $1;
+			}
+			|	ruleset_spec    STRING  basehook_device_name
+			{
+				const char *name = chain_hookname_lookup($2);
+
+				if (name == NULL) {
+					erec_queue(error(&@2, "unknown chain hook"),
+						   state->msgs);
+					xfree($3);
+					YYERROR;
+				}
+
+				$1.chain.name = $2;
+				$1.chain.location = @2;
+				if ($3) {
+					$1.obj.name = $3;
+					$1.obj.location = @3;
+				}
+				$$ = $1;
+			}
 			;
 
 reset_cmd		:	COUNTERS	ruleset_spec
diff --git a/src/rule.c b/src/rule.c
index dcf1646a9c7c..04b3451e917c 100644
--- a/src/rule.c
+++ b/src/rule.c
@@ -2364,6 +2364,17 @@ static int do_list_set(struct netlink_ctx *ctx, struct cmd *cmd,
 	return 0;
 }
 
+static int do_list_hooks(struct netlink_ctx *ctx, struct cmd *cmd)
+{
+	const char *devname = cmd->handle.obj.name;
+	int hooknum = -1;
+
+	if (cmd->handle.chain.name)
+		hooknum = cmd->handle.chain_id;
+
+	return mnl_nft_dump_nf_hooks(ctx, cmd->handle.family, hooknum, devname);
+}
+
 static int do_command_list(struct netlink_ctx *ctx, struct cmd *cmd)
 {
 	struct table *table = NULL;
@@ -2424,6 +2435,8 @@ static int do_command_list(struct netlink_ctx *ctx, struct cmd *cmd)
 		return do_list_flowtable(ctx, cmd, table);
 	case CMD_OBJ_FLOWTABLES:
 		return do_list_flowtables(ctx, cmd);
+	case CMD_OBJ_HOOKS:
+		return do_list_hooks(ctx, cmd);
 	default:
 		BUG("invalid command object type %u\n", cmd->obj);
 	}
diff --git a/src/scanner.l b/src/scanner.l
index c1bc21aa7ecc..6dc1be8908cf 100644
--- a/src/scanner.l
+++ b/src/scanner.l
@@ -354,6 +354,7 @@ addrstring	({macaddr}|{ip4addr}|{ip6addr})
 	"limits"		{ return LIMITS; }
 	"secmarks"		{ return SECMARKS; }
 	"synproxys"		{ return SYNPROXYS; }
+	"hooks"			{ return HOOKS; }
 }
 
 "counter"		{ scanner_push_start_cond(yyscanner, SCANSTATE_COUNTER); return COUNTER; }
-- 
2.26.3


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH nft 3/3] doc: add LISTING section
  2021-05-21 12:08 [PATCH nft 0/3] hook dump support Florian Westphal
  2021-05-21 12:08 ` [PATCH nft 1/3] scanner: add list cmd parser scope Florian Westphal
  2021-05-21 12:08 ` [PATCH nft 2/3] src: add support for base hook dumping Florian Westphal
@ 2021-05-21 12:08 ` Florian Westphal
  2021-05-21 22:43   ` Duncan Roe
  2 siblings, 1 reply; 5+ messages in thread
From: Florian Westphal @ 2021-05-21 12:08 UTC (permalink / raw)
  To: netfilter-devel; +Cc: Florian Westphal

mention various 'nft list' options, such as secmarks, flow tables, and
so on.

Signed-off-by: Florian Westphal <fw@strlen.de>
---
 doc/nft.txt | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/doc/nft.txt b/doc/nft.txt
index a4333d9d55f3..245406fb1335 100644
--- a/doc/nft.txt
+++ b/doc/nft.txt
@@ -684,6 +684,18 @@ and subtraction can be used to set relative priority, e.g. filter + 5 equals to
 *list*:: List all flowtables.
 
 
+LISTING
+-------
+[verse]
+*list { secmarks | synproxys | flow tables | meters | hooks }* ['family']
+*list { secmarks | synproxys | flow tables | meters | hooks } table* ['family'] 'table'
+*list ct { timeout | expectation | helper | helpers } table* ['family'] 'table'
+
+Inspect configured objects.
+*list hooks* shows the full hook pipeline, including those registered by
+kernel modules, such as nf_conntrack.
+
+
 STATEFUL OBJECTS
 ----------------
 [verse]
@@ -691,6 +703,7 @@ STATEFUL OBJECTS
 *delete* 'type' ['family'] 'table' *handle* 'handle'
 *list counters* ['family']
 *list quotas* ['family']
+*list limits* ['family']
 
 Stateful objects are attached to tables and are identified by an unique name.
 They group stateful information from rules, to reference them in rules the
-- 
2.26.3


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH nft 3/3] doc: add LISTING section
  2021-05-21 12:08 ` [PATCH nft 3/3] doc: add LISTING section Florian Westphal
@ 2021-05-21 22:43   ` Duncan Roe
  0 siblings, 0 replies; 5+ messages in thread
From: Duncan Roe @ 2021-05-21 22:43 UTC (permalink / raw)
  To: netfilter-devel; +Cc: Florian Westphal

On Fri, May 21, 2021 at 02:08:46PM +0200, Florian Westphal wrote:
> mention various 'nft list' options, such as secmarks, flow tables, and
> so on.
>
> Signed-off-by: Florian Westphal <fw@strlen.de>
> ---
>  doc/nft.txt | 13 +++++++++++++
>  1 file changed, 13 insertions(+)
>
> diff --git a/doc/nft.txt b/doc/nft.txt
> index a4333d9d55f3..245406fb1335 100644
> --- a/doc/nft.txt
> +++ b/doc/nft.txt
> @@ -684,6 +684,18 @@ and subtraction can be used to set relative priority, e.g. filter + 5 equals to
>  *list*:: List all flowtables.
>
>
> +LISTING
> +-------
> +[verse]
> +*list { secmarks | synproxys | flow tables | meters | hooks }* ['family']
> +*list { secmarks | synproxys | flow tables | meters | hooks } table* ['family'] 'table'
> +*list ct { timeout | expectation | helper | helpers } table* ['family'] 'table'
> +
> +Inspect configured objects.
> +*list hooks* shows the full hook pipeline, including those registered by
> +kernel modules, such as nf_conntrack.
> +
> +
>  STATEFUL OBJECTS
>  ----------------
>  [verse]
> @@ -691,6 +703,7 @@ STATEFUL OBJECTS
>  *delete* 'type' ['family'] 'table' *handle* 'handle'
>  *list counters* ['family']
>  *list quotas* ['family']
> +*list limits* ['family']
>
>  Stateful objects are attached to tables and are identified by an unique name.
>  They group stateful information from rules, to reference them in rules the
> --
> 2.26.3
>

Tiny nit: suggest "by a unique" instead of "by an unique".
"a" reads better to this native en-GB speaker at least.

Cheers ... Duncan.

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2021-05-21 22:43 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-05-21 12:08 [PATCH nft 0/3] hook dump support Florian Westphal
2021-05-21 12:08 ` [PATCH nft 1/3] scanner: add list cmd parser scope Florian Westphal
2021-05-21 12:08 ` [PATCH nft 2/3] src: add support for base hook dumping Florian Westphal
2021-05-21 12:08 ` [PATCH nft 3/3] doc: add LISTING section Florian Westphal
2021-05-21 22:43   ` Duncan Roe

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.