]> git.ipfire.org Git - thirdparty/nftables.git/commitdiff
mnl: support bpf id decode in nft list hooks
authorFlorian Westphal <fw@strlen.de>
Tue, 16 May 2023 16:24:29 +0000 (18:24 +0200)
committerFlorian Westphal <fw@strlen.de>
Mon, 22 May 2023 19:00:56 +0000 (21:00 +0200)
This allows 'nft list hooks' to also display the bpf program id
attached.  Example:

hook input {
  -0000000128 nf_hook_run_bpf id 6
  ..

Signed-off-by: Florian Westphal <fw@strlen.de>
include/linux/netfilter/nfnetlink_hook.h
src/mnl.c

index bbcd285b22e1093d2db91f72c1fd280b4f9a49a2..84a561a74b9820edc5d037e986fb46ad948ef903 100644 (file)
@@ -32,8 +32,12 @@ enum nfnl_hook_attributes {
 /**
  * enum nfnl_hook_chain_info_attributes - chain description
  *
- * NFNLA_HOOK_INFO_DESC: nft chain and table name (enum nft_table_attributes) (NLA_NESTED)
- * NFNLA_HOOK_INFO_TYPE: chain type (enum nfnl_hook_chaintype) (NLA_U32)
+ * @NFNLA_HOOK_INFO_DESC: nft chain and table name (NLA_NESTED)
+ * @NFNLA_HOOK_INFO_TYPE: chain type (enum nfnl_hook_chaintype) (NLA_U32)
+ *
+ * NFNLA_HOOK_INFO_DESC depends on NFNLA_HOOK_INFO_TYPE value:
+ *   NFNL_HOOK_TYPE_NFTABLES: enum nft_table_attributes
+ *   NFNL_HOOK_TYPE_BPF: enum nfnl_hook_bpf_attributes
  */
 enum nfnl_hook_chain_info_attributes {
        NFNLA_HOOK_INFO_UNSPEC,
@@ -55,10 +59,24 @@ enum nfnl_hook_chain_desc_attributes {
 /**
  * enum nfnl_hook_chaintype - chain type
  *
- * @NFNL_HOOK_TYPE_NFTABLES nf_tables base chain
+ * @NFNL_HOOK_TYPE_NFTABLES: nf_tables base chain
+ * @NFNL_HOOK_TYPE_BPF: bpf program
  */
 enum nfnl_hook_chaintype {
        NFNL_HOOK_TYPE_NFTABLES = 0x1,
+       NFNL_HOOK_TYPE_BPF,
+};
+
+/**
+ * enum nfnl_hook_bpf_attributes - bpf prog description
+ *
+ * @NFNLA_HOOK_BPF_ID: bpf program id (NLA_U32)
+ */
+enum nfnl_hook_bpf_attributes {
+       NFNLA_HOOK_BPF_UNSPEC,
+       NFNLA_HOOK_BPF_ID,
+       __NFNLA_HOOK_BPF_MAX,
 };
+#define NFNLA_HOOK_BPF_MAX (__NFNLA_HOOK_BPF_MAX - 1)
 
 #endif /* _NFNL_HOOK_H */
index adc0bd3d61cfca9c683aaebf89a2f60485abc4d5..91775c41b24616b60ef5d3b376cee1e81505c7ee 100644 (file)
--- a/src/mnl.c
+++ b/src/mnl.c
@@ -2273,6 +2273,27 @@ static int dump_nf_attr_chain_cb(const struct nlattr *attr, void *data)
        return MNL_CB_OK;
 }
 
+static int dump_nf_attr_bpf_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, NFNLA_HOOK_BPF_MAX) < 0)
+               return MNL_CB_OK;
+
+       switch(type) {
+       case NFNLA_HOOK_BPF_ID:
+                if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
+                        return MNL_CB_ERROR;
+               break;
+       default:
+               return MNL_CB_OK;
+       }
+
+       tb[type] = attr;
+       return MNL_CB_OK;
+}
+
 struct dump_nf_hook_data {
        struct list_head *hook_list;
        int family;
@@ -2332,6 +2353,23 @@ static int dump_nf_hooks(const struct nlmsghdr *nlh, void *_data)
                                hook->chain = xstrdup(chainname);
                        }
                        hook->chain_family = mnl_attr_get_u8(info[NFNLA_CHAIN_FAMILY]);
+               } else if (type == NFNL_HOOK_TYPE_BPF) {
+                       struct nlattr *info[NFNLA_HOOK_BPF_MAX + 1] = {};
+
+                       if (mnl_attr_parse_nested(nested[NFNLA_HOOK_INFO_DESC],
+                                                 dump_nf_attr_bpf_cb, info) < 0) {
+                               basehook_free(hook);
+                               return -1;
+                       }
+
+                       if (info[NFNLA_HOOK_BPF_ID]) {
+                               char tmpbuf[16];
+
+                               snprintf(tmpbuf, sizeof(tmpbuf), "id %u",
+                                        ntohl(mnl_attr_get_u32(info[NFNLA_HOOK_BPF_ID])));
+
+                               hook->chain = xstrdup(tmpbuf);
+                       }
                }
        }
        if (tb[NFNLA_HOOK_HOOKNUM])
@@ -2453,6 +2491,8 @@ static void print_hooks(struct netlink_ctx *ctx, int family, struct list_head *h
 
                if (hook->table && hook->chain)
                        fprintf(fp, " chain %s %s %s", family2str(hook->chain_family), hook->table, hook->chain);
+               else if (hook->hookfn && hook->chain)
+                       fprintf(fp, " %s %s", hook->hookfn, hook->chain);
                else if (hook->hookfn) {
                        fprintf(fp, " %s", hook->hookfn);
                }