add insert after to nf_tables
Subsystems (2)
cover add insert after to nf_tables
Hello,
The patch
netfilter: nf_tables: add insert operation
adds support for inserting a rule after a handle.
It is followed by the patch
examples: add insert rule example
which is the libnftables example.
I choose to reuse the CREATE operation in the kernel code to avoid to add a new message to netlink. This way we have a sort of 'create after' syntax. This is almost natural IMHO.
BR,
--
Eric
PATCH 1/1 netfilter: nf_tables: add insert operation
By providing a create command and specifying an handle, the rule is inserted after the rule with the provided handle.
--- net/netfilter/nf_tables_api.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-)
net/netfilter/nf_tables_api.c +10 -3
@@ -1563,7 +1563,10 @@ static int nf_tables_newrule(struct sock *nlsk, struct sk_buff *skb,return -EEXIST ;if (nlh->nlmsg_flags &NLM_F_REPLACE ) old_rule = rule; -else +else if (nlh->nlmsg_flags &NLM_F_CREATE ) { + old_rule = rule; + handle =nf_tables_alloc_handle (table); + }else return -EOPNOTSUPP ; }else {if (!create || nlh->nlmsg_flags &NLM_F_REPLACE )
@@ -1626,8 +1629,12 @@ static int nf_tables_newrule(struct sock *nlsk, struct sk_buff *skb, } }else if (nlh->nlmsg_flags &NLM_F_APPEND )list_add_tail_rcu (&rule->list, &chain->rules); -else -list_add_rcu (&rule->list, &chain->rules); +else { +if (old_rule) +list_add_rcu (&rule->list, &old_rule->list); +else +list_add_rcu (&rule->list, &chain->rules); + }if (flags &NFT_RULE_F_COMMIT )list_add (&rule->dirty_list, &chain->dirty_rules);
Signature · 1 line
1.8.3.1
PATCH 1/1 examples: add insert rule example
In reply to Eric LeblondThis program can insert a rule after a rule given by its handle.
--- examples/Makefile.am | 4 + examples/nft-rule-insert.c | 203 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 207 insertions(+) create mode 100644 examples/nft-rule-insert.c
examples/Makefile.am +4 -0
@@ -10,6 +10,7 @@ check_PROGRAMS = nft-table-add \ nft-chain-del \ nft-chain-get \ nft-rule-add \ + nft-rule-insert \ nft-rule-xml-add \ nft-rule-del \ nft-rule-get \
@@ -52,6 +53,9 @@ nft_chain_get_LDADD = ../src/libnftables.la ${LIBMNL_LIBS} ${LIBXML_LIBS} nft_rule_add_SOURCES = nft-rule-add.c nft_rule_add_LDADD = ../src/libnftables.la ${LIBMNL_LIBS} ${LIBXML_LIBS} +nft_rule_insert_SOURCES = nft-rule-insert.c +nft_rule_insert_LDADD = ../src/libnftables.la ${LIBMNL_LIBS} ${LIBXML_LIBS} + nft_rule_xml_add_SOURCES = nft-rule-xml-add.c nft_rule_xml_add_LDADD = ../src/libnftables.la ${LIBMNL_LIBS} ${LIBXML_LIBS}
examples/nft-rule-insert.c new file +203 -0
203 lines not on this page · raw message
Signature · 1 line
1.8.3.1
Hi Eric,
Quoted 11 lines
The patch
netfilter:nf_tables: add insert operation
adds support for inserting a rule after a handle.It is followed by the patch
examples: add insert rule example
which is the libnftables example.I choose to reuse the CREATE operation in the kernel code to avoid to add a new message to netlink. This way we have a sort of 'create after' syntax. This is almost natural IMHO.
There is an issue however: notification.
I don't see how other clients are going to know where to put the rule when updating there own list when they get notified.
They will be notified that a rule as been added successfully, but they will get it as an appended rule.
Here it's a one shot usage: only on creating you need this info, so it would be also provided on notification. Not on the dump obviously. I don't see a direct solution here, since adding an attribute (or a new flag to NFTA_RULE_FLAGS) would be going against current API design.
We have to sort this out.
Tomasz
Pablo Neira Ayuso
maintainerQuoted 14 lines · Tomasz Bursztyka
Hi Eric,
Quoted 11 lines
The patch
netfilter:nf_tables: add insert operation
adds support for inserting a rule after a handle.It is followed by the patch
examples: add insert rule example
which is the libnftables example.I choose to reuse the CREATE operation in the kernel code to avoid to add a new message to netlink. This way we have a sort of 'create after' syntax. This is almost natural IMHO.
Quoted 6 lines
There is an issue however: notification.
I don't see how other clients are going to know where to put the rule when updating there own list when they get notified.They will be notified that a rule as been added successfully, but they will get it as an appended rule.
This can be implemented in user-space.
The user-space daemon can keep a cache of the ordered rule-set. Thus, it can guess the position of the rule-set from the handle.
Hi Pablo,
Quoted 2 lines
The user-space daemon can keep a cache of the ordered rule-set. Thus, it can guess the position of the rule-set from the handle.
Hum, how?
The handle it will get from the notification is the handle of the newly created rule, not the one used to identify the rule for insertion.
Tomasz
Pablo Neira Ayuso
maintainerQuoted 9 lines · Tomasz Bursztyka
Hi Pablo,
Quoted 2 lines
The user-space daemon can keep a cache of the ordered rule-set. Thus, it can guess the position of the rule-set from the handle.
Hum, how?
The handle it will get from the notification is the handle of the newly created rule, not the one used to identify the rule for insertion.
That's right. I don't come with any other way to make it rather than adding a new attribute.
Eric, would you rework the patch to do so?
Hi Pablo,
Quoted 6 lines
Quoted 4 lines
Hum, how?
The handle it will get from the notification is the handle of the newly created rule, not the one used to identify the rule for insertion.That's right. I don't come with any other way to make it rather than adding a new attribute.
Yes, though it breaks the design logic of the current API, somehow.
I mean, attributes are currently reflecting the rule as it is, and are used symmetrically in queries/replies.
Here what we need is a temporary extra attribute, or some sort, only used for the notification.
Either via:
we don't add an element to enum nft_rule_attributes {}, instead we create another enum for attributes only used on notification. like enum nft_rule_extras_notifications_attributes {}
Or via (maybe better for nla policy way of working?):
Adding a nft_rule_attributes as NFTA_RULE_EXTRAS_NOTIFICATIONS as a nested attribute and then enum nft_rule_extras_notifications_attributes {} again, etc etc...
It's just a quick proposal, but my point here is to keep the API semantically sane. So it won't require extra guesses to understand how it's supposed to work
(as it is right now: it's a sane API, besides the lonely NFT_RULE_F_COMMIT in its anonymous enum)
Maybe there is a better way, probably. But you get my point.
Tomasz
Quoted 31 lines · Tomasz Bursztyka
Hi Pablo,
Quoted 6 lines
Quoted 4 lines
Hum, how?
The handle it will get from the notification is the handle of the newly created rule, not the one used to identify the rule for insertion.That's right. I don't come with any other way to make it rather than adding a new attribute.
Yes, though it breaks the design logic of the current API, somehow.
I mean, attributes are currently reflecting the rule as it is, and are used symmetrically in queries/replies.
Here what we need is a temporary extra attribute, or some sort, only used for the notification.
Either via:
we don't add an element to enum
nft_rule_attributes{}, instead we create another enum for attributes only used on notification. like enumnft_rule_extras_notifications_attributes{}Or via (maybe better for nla policy way of working?):
Adding a
nft_rule_attributesasNFTA_RULE_EXTRAS_NOTIFICATIONSas a nested attribute
and then enumnft_rule_extras_notifications_attributes{} again, etc etc...
Quoted 7 lines
It's just a quick proposal, but my point here is to keep the API semantically sane.
So it won't require extra guesses to understand how it's supposed to work (as it is right now: it's a sane API, besides the lonelyNFT_RULE_F_COMMITin its anonymous enum)Maybe there is a better way, probably. But you get my point.
We could instead of using NLA_RULE_HANDLE for the position add a new attribute NLA_RULE_POSITION and use that both for creating rules and for notifications. It would always be set and contain the handle of the rule preceeding the new rule (for NLM_F_APPEND) or the one following it (for !NLM_F_APPEND).
Hi Patrick,
Quoted 6 lines
Quoted 1 line
Quoted 1 line
Maybe there is a better way, probably. But you get my point.
We could instead of using
NLA_RULE_HANDLEfor the position add a new attributeNLA_RULE_POSITIONand use that both for creating rules and for notifications. It would always be set and contain the handle of the rule preceeding the new rule (forNLM_F_APPEND) or the one following it (for !NLM_F_APPEND).
I like that, it follows the current API design logic and it's simpler to implement in both sides. It's much simpler indeed!
Tomasz
Hi,
Quoted 7 lines · Patrick McHardy
Quoted 6 lines · Tomasz Bursztyka
Hi Pablo,
Quoted 4 lines
Quoted 4 lines
Hum, how?
The handle it will get from the notification is the handle of the newly created rule, not the one used to identify the rule for insertion.
...
Quoted 7 lines
LE_F_COMMITin its anonymous enum)Quoted 2 lines
Maybe there is a better way, probably. But you get my point.
We could instead of using
NLA_RULE_HANDLEfor the position add a new attributeNLA_RULE_POSITIONand use that both for creating rules and for notifications.
I like that. Reusing NLA_RULE_HANDLE was making feel somehow uncomfortable.
Quoted 3 lines
It would always be set and contain the handle of
the rule preceeding the new rule (forNLM_F_APPEND) or the one following it (for !NLM_F_APPEND).
Nice, reworking my patches in that direction.
BR,
--
Eric
RFC PATCH v2 1/1 netfilter: nf_tables: add insert operation
This patch adds a new rule attribute NFTA_RULE_POSITION which is used to store the position of a rule relatively to the others. By providing a create command and specifying a position, the rule is inserted after the rule with the handle equal to the provided position.
Regarding notification, the position attribute is added to specify the handle of the previous rule in append mode and the handle of the next rule in the other case.
--- include/uapi/linux/netfilter/nf_tables.h | 1 + net/netfilter/nf_tables_api.c | 32 +++++++++++++++++++++++++++++--- 2 files changed, 30 insertions(+), 3 deletions(-)
include/uapi/linux/netfilter/nf_tables.h +1 -0
@@ -143,6 +143,7 @@ enum nft_rule_attributes {NFTA_RULE_EXPRESSIONS ,NFTA_RULE_FLAGS ,NFTA_RULE_COMPAT , +NFTA_RULE_POSITION , __NFTA_RULE_MAX };#define NFTA_RULE_MAX (__NFTA_RULE_MAX - 1)
net/netfilter/nf_tables_api.c +29 -3
@@ -1267,6 +1267,7 @@ static const struct nla_policy nft_rule_policy[NFTA_RULE_MAX + 1] = { [NFTA_RULE_EXPRESSIONS] = { .type = NLA_NESTED }, [NFTA_RULE_FLAGS] = { .type = NLA_U32 }, [NFTA_RULE_COMPAT] = { .type = NLA_NESTED }, + [NFTA_RULE_POSITION] = { .type = NLA_U64 }, }; static int nf_tables_fill_rule_info(struct sk_buff *skb, u32 portid, u32 seq,
@@ -1298,6 +1299,17 @@ static int nf_tables_fill_rule_info(struct sk_buff *skb, u32 portid, u32 seq,if (nla_put_be64 (skb,NFTA_RULE_HANDLE ,cpu_to_be64 (rule->handle))) goto nla_put_failure; +if (event &NLM_F_APPEND && rule->list.prev) { +if (nla_put_be64 (skb,NFTA_RULE_POSITION , +cpu_to_be64 (((struct nft_rule *)rule->list.prev)->handle))) + goto nla_put_failure; + }else if (rule->list.next) { +if (nla_put_be64 (skb,NFTA_RULE_POSITION , +cpu_to_be64 (((struct nft_rule *)rule->list.next)->handle))) + goto nla_put_failure; + }else + goto nla_put_failure; + list =nla_nest_start (skb,NFTA_RULE_EXPRESSIONS );if (list ==NULL ) goto nla_put_failure;
@@ -1537,7 +1549,7 @@ static int nf_tables_newrule(struct sock *nlsk, struct sk_buff *skb,int err, rem;bool create;u32 flags =0 ; -u64 handle; +u64 handle, pos_handle; create = nlh->nlmsg_flags &NLM_F_CREATE ? true : false;
@@ -1571,6 +1583,16 @@ static int nf_tables_newrule(struct sock *nlsk, struct sk_buff *skb, handle =nf_tables_alloc_handle (table); } +if (nla[NFTA_RULE_POSITION ]) { + pos_handle =be64_to_cpu (nla_get_be64 (nla[NFTA_RULE_POSITION ])); + old_rule =__nf_tables_rule_lookup (chain, pos_handle); +if (IS_ERR (old_rule)) +return PTR_ERR (old_rule); + +if (! (nlh->nlmsg_flags &NLM_F_CREATE )) +return -EOPNOTSUPP ; + } +nft_ctx_init (&ctx, skb, nlh, afi, table, chain, nla); n =0 ;
@@ -1626,8 +1648,12 @@ static int nf_tables_newrule(struct sock *nlsk, struct sk_buff *skb, } }else if (nlh->nlmsg_flags &NLM_F_APPEND )list_add_tail_rcu (&rule->list, &chain->rules); -else -list_add_rcu (&rule->list, &chain->rules); +else { +if (old_rule) +list_add_rcu (&rule->list, &old_rule->list); +else +list_add_rcu (&rule->list, &chain->rules); + }if (flags &NFT_RULE_F_COMMIT )list_add (&rule->dirty_list, &chain->dirty_rules);
Signature · 1 line
1.8.3.1
Pablo Neira Ayuso
maintainerRe: [RFC PATCHv2] netfilter: nf_tables: add insert operation
Hi Eric,
Quoted 40 lines · Eric Leblond
This patch adds a new rule attribute
NFTA_RULE_POSITIONwhich is used to store the position of a rule relatively to the others. By providing a create command and specifying a position, the rule is inserted after the rule with the handle equal to the provided position.
Regarding notification, the position attribute is added to specify the handle of the previous rule in append mode and the handle of the next rule in the other case.Signed-off-by Eric Leblond <[email protected]>--- include/uapi/linux/netfilter/nf_tables.h | 1 + net/netfilter/nf_tables_api.c | 32 +++++++++++++++++++++++++++++--- 2 files changed, 30 insertions(+), 3 deletions(-)include/uapi/linux/netfilter/nf_tables.h +1
-0@@ -143,6 +143,7 @@ enum nft_rule_attributes {NFTA_RULE_EXPRESSIONS ,NFTA_RULE_FLAGS ,NFTA_RULE_COMPAT , +NFTA_RULE_POSITION , __NFTA_RULE_MAX };#define NFTA_RULE_MAX (__NFTA_RULE_MAX - 1)net/netfilter/nf_tables_api.c +1
-0@@ -1267,6 +1267,7 @@ static const struct nla_policy nft_rule_policy[NFTA_RULE_MAX + 1] = { [NFTA_RULE_EXPRESSIONS] = { .type = NLA_NESTED }, [NFTA_RULE_FLAGS] = { .type = NLA_U32 }, [NFTA_RULE_COMPAT] = { .type = NLA_NESTED }, + [NFTA_RULE_POSITION] = { .type = NLA_U64 }, }; static int nf_tables_fill_rule_info(struct sk_buff *skb, u32 portid, u32 seq,
net/netfilter/nf_tables_api.c static int nf_tables_fill_rule_info(struct sk_buff *skb, u32 portid, u32 seq, · line 1302
Quoted 4 lines
net/netfilter/nf_tables_api.c +1
-0@@ -1298,6 +1299,17 @@ static int nf_tables_fill_rule_info(struct sk_buff *skb, u32 portid, u32 seq,if (nla_put_be64 (skb,NFTA_RULE_HANDLE ,cpu_to_be64 (rule->handle))) goto nla_put_failure; +if (event &NLM_F_APPEND && rule->list.prev) {
.prev is always != NULL.
It points to the list head in the first element case. It is set to LIST_POISON2 in case that rule has been deleted.
Quoted 61 lines
net/netfilter/nf_tables_api.c +27
-3+if (nla_put_be64 (skb,NFTA_RULE_POSITION , +cpu_to_be64 (((struct nft_rule *)rule->list.prev)->handle))) + goto nla_put_failure; + }else if (rule->list.next) { +if (nla_put_be64 (skb,NFTA_RULE_POSITION , +cpu_to_be64 (((struct nft_rule *)rule->list.next)->handle))) + goto nla_put_failure; + }else + goto nla_put_failure; + list =nla_nest_start (skb,NFTA_RULE_EXPRESSIONS );if (list ==NULL ) goto nla_put_failure;@@ -1537,7 +1549,7 @@ static int nf_tables_newrule(struct sock *nlsk, struct sk_buff *skb,int err, rem;bool create;u32 flags =0 ; -u64 handle; +u64 handle, pos_handle; create = nlh->nlmsg_flags &NLM_F_CREATE ? true : false;@@ -1571,6 +1583,16 @@ static int nf_tables_newrule(struct sock *nlsk, struct sk_buff *skb, handle =nf_tables_alloc_handle (table); } +if (nla[NFTA_RULE_POSITION ]) { + pos_handle =be64_to_cpu (nla_get_be64 (nla[NFTA_RULE_POSITION ])); + old_rule =__nf_tables_rule_lookup (chain, pos_handle); +if (IS_ERR (old_rule)) +return PTR_ERR (old_rule); + +if (! (nlh->nlmsg_flags &NLM_F_CREATE )) +return -EOPNOTSUPP ; + } +nft_ctx_init (&ctx, skb, nlh, afi, table, chain, nla); n =0 ;@@ -1626,8 +1648,12 @@ static int nf_tables_newrule(struct sock *nlsk, struct sk_buff *skb, } }else if (nlh->nlmsg_flags &NLM_F_APPEND )list_add_tail_rcu (&rule->list, &chain->rules); -else -list_add_rcu (&rule->list, &chain->rules); +else { +if (old_rule) +list_add_rcu (&rule->list, &old_rule->list); +else +list_add_rcu (&rule->list, &chain->rules); + }if (flags &NFT_RULE_F_COMMIT )list_add (&rule->dirty_list, &chain->dirty_rules);Signature · 6 lines
1.8.3.1 -- To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
PATCH v3 1/1 [PATCHv3 nftables insert operation]
Hello,
Here's a rework of previous patch. Kernel patch, libnftables and nftables patches are to follow.
libnftables patchset statistics:
examples/Makefile.am | 4 + examples/nft-rule-insert.c | 204 ++++++++++++++++++++++++++++++++++++ include/libnftables/rule.h | 3 +- include/linux/netfilter/nf_tables.h | 1 + src/rule.c | 29 ++++- 5 files changed, 237 insertions(+), 4 deletions(-)
nftables patchset statistics:
include/rule.h | 2 ++ src/netlink.c | 2 ++ src/netlink_delinearize.c | 2 ++ src/parser.y | 22 ++++++++++++++++++++-- src/rule.c | 2 ++ src/scanner.l | 3 +++ 6 files changed, 31 insertions(+), 2 deletions(-)
BR,
--
Eric
PATCH 1/1 netfilter: nf_tables: add insert operation
This patch adds a new rule attribute NFTA_RULE_POSITION which is used to store the position of a rule relatively to the others. By providing a create command and specifying a position, the rule is inserted after the rule with the handle equal to the provided position.
Regarding notification, the position attribute is added to specify the handle of the previous rule in append mode and the handle of the next rule in the other case.
--- include/uapi/linux/netfilter/nf_tables.h | 1 + net/netfilter/nf_tables_api.c | 47 +++++++++++++++++++++++++++++--- 2 files changed, 44 insertions(+), 4 deletions(-)
include/uapi/linux/netfilter/nf_tables.h +1 -0
@@ -143,6 +143,7 @@ enum nft_rule_attributes {NFTA_RULE_EXPRESSIONS ,NFTA_RULE_FLAGS ,NFTA_RULE_COMPAT , +NFTA_RULE_POSITION , __NFTA_RULE_MAX };#define NFTA_RULE_MAX (__NFTA_RULE_MAX - 1)
net/netfilter/nf_tables_api.c +43 -4
83 lines not on this page · raw message
Signature · 1 line
1.8.3.2
Pablo Neira Ayuso
maintainerRe: [PATCH] netfilter: nf_tables: add insert operation
Hi Eric,
Thanks for this new round, some comments below:
Quoted 48 lines · Eric Leblond
This patch adds a new rule attribute
NFTA_RULE_POSITIONwhich is used to store the position of a rule relatively to the others. By providing a create command and specifying a position, the rule is inserted after the rule with the handle equal to the provided position.
Regarding notification, the position attribute is added to specify the handle of the previous rule in append mode and the handle of the next rule in the other case.Signed-off-by Eric Leblond <[email protected]>--- include/uapi/linux/netfilter/nf_tables.h | 1 + net/netfilter/nf_tables_api.c | 47 +++++++++++++++++++++++++++++--- 2 files changed, 44 insertions(+), 4 deletions(-)include/uapi/linux/netfilter/nf_tables.h +1
-0@@ -143,6 +143,7 @@ enum nft_rule_attributes {NFTA_RULE_EXPRESSIONS ,NFTA_RULE_FLAGS ,NFTA_RULE_COMPAT , +NFTA_RULE_POSITION , __NFTA_RULE_MAX };#define NFTA_RULE_MAX (__NFTA_RULE_MAX - 1)net/netfilter/nf_tables_api.c +2
-0@@ -1267,6 +1267,7 @@ static const struct nla_policy nft_rule_policy[NFTA_RULE_MAX + 1] = { [NFTA_RULE_EXPRESSIONS] = { .type = NLA_NESTED }, [NFTA_RULE_FLAGS] = { .type = NLA_U32 }, [NFTA_RULE_COMPAT] = { .type = NLA_NESTED }, + [NFTA_RULE_POSITION] = { .type = NLA_U64 }, }; static int nf_tables_fill_rule_info(struct sk_buff *skb, u32 portid, u32 seq,@@ -1279,6 +1280,7 @@ static int nf_tables_fill_rule_info(struct sk_buff *skb, u32 portid, u32 seq,struct nfgenmsg *nfmsg;const struct nft_expr *expr, *next;struct nlattr *list; +const struct nft_rule *prule; event |=NFNL_SUBSYS_NFTABLES <<8 ; nlh = nlmsg_put(skb, portid, seq, event, sizeof(struct nfgenmsg),
net/netfilter/nf_tables_api.c static int nf_tables_fill_rule_info(struct sk_buff *skb, u32 portid, u32 seq, · line 1303
Quoted 4 lines
net/netfilter/nf_tables_api.c +1
-0@@ -1298,6 +1300,26 @@ static int nf_tables_fill_rule_info(struct sk_buff *skb, u32 portid, u32 seq,if (nla_put_be64 (skb,NFTA_RULE_HANDLE ,cpu_to_be64 (rule->handle))) goto nla_put_failure; +if (event &NLM_F_APPEND ) {
This should be if (flags & NLM_F_APPEND)
net/netfilter/nf_tables_api.c static int nf_tables_fill_rule_info(struct sk_buff *skb, u32 portid, u32 seq, · line 1304
Quoted 1 line
net/netfilter/nf_tables_api.c +1
-0+ if ((rule->list.prev != LIST_POISON2) &&
You can use event instead to catch the deletion case:
if (event != NFT_MSG_DELRULE)
net/netfilter/nf_tables_api.c static int nf_tables_fill_rule_info(struct sk_buff *skb, u32 portid, u32 seq, · line 1314
Quoted 10 lines
net/netfilter/nf_tables_api.c +10
-0+ (rule->list.prev != &chain->rules)) { + prule =list_entry (rule->list.prev, + struct nft_rule, list); +if (nla_put_be64 (skb,NFTA_RULE_POSITION , +cpu_to_be64 (prule->handle))) + goto nla_put_failure; + } + }else { +if ((rule->list.next !=LIST_POISON1 ) && + (rule->list.next != &chain->rules)) {
You can use list_is_last instead of rule->list.next != &chain->rules.
Unfortunately, there is no list_is_first, but we could ask for mainstream inclusion later on.
Quoted 22 lines
net/netfilter/nf_tables_api.c +9
-1+ prule =list_entry (rule->list.next, + struct nft_rule, list); +if (nla_put_be64 (skb,NFTA_RULE_POSITION , +cpu_to_be64 (prule->handle))) + goto nla_put_failure; + } + } + list =nla_nest_start (skb,NFTA_RULE_EXPRESSIONS );if (list ==NULL ) goto nla_put_failure;@@ -1537,7 +1559,7 @@ static int nf_tables_newrule(struct sock *nlsk, struct sk_buff *skb,int err, rem;bool create;u32 flags =0 ; -u64 handle; +u64 handle, pos_handle; create = nlh->nlmsg_flags &NLM_F_CREATE ? true : false;@@ -1571,6 +1593,16 @@ static int nf_tables_newrule(struct sock *nlsk, struct sk_buff *skb, handle =nf_tables_alloc_handle (table);
net/netfilter/nf_tables_api.c static int nf_tables_newrule(struct sock *nlsk, struct sk_buff *skb, · line 1603
Quoted 10 lines
net/netfilter/nf_tables_api.c +8
-0} +if (nla[NFTA_RULE_POSITION ]) { + pos_handle =be64_to_cpu (nla_get_be64 (nla[NFTA_RULE_POSITION ])); + old_rule =__nf_tables_rule_lookup (chain, pos_handle); +if (IS_ERR (old_rule)) +return PTR_ERR (old_rule); + +if (! (nlh->nlmsg_flags &NLM_F_CREATE )) +return -EOPNOTSUPP ;
Better this checking before the rule lookup.
Quoted 28 lines
net/netfilter/nf_tables_api.c +12
-3+ } +nft_ctx_init (&ctx, skb, nlh, afi, table, chain, nla); n =0 ;@@ -1625,9 +1657,16 @@ static int nf_tables_newrule(struct sock *nlsk, struct sk_buff *skb,nf_tables_rule_destroy (old_rule); } }else if (nlh->nlmsg_flags &NLM_F_APPEND ) -list_add_tail_rcu (&rule->list, &chain->rules); -else -list_add_rcu (&rule->list, &chain->rules); +if (old_rule) +list_add_rcu (&rule->list, &old_rule->list); +else +list_add_tail_rcu (&rule->list, &chain->rules); +else { +if (old_rule) +list_add_tail_rcu (&rule->list, &old_rule->list); +else +list_add_rcu (&rule->list, &chain->rules); + }if (flags &NFT_RULE_F_COMMIT )list_add (&rule->dirty_list, &chain->dirty_rules);Signature · 1 line
1.8.3.2
v4 cover [PATCHv4 nftables insert operation 0/1]
Hello Pablo,
Thanks for the review, here's an update version of the kernel patch. A nftables patch on top of the one I've already provide is also mandatory to have the insert operation working correctly.
BR,
--
Eric
PATCH v4 1/1 netfilter: nf_tables: add insert operation
This patch adds a new rule attribute NFTA_RULE_POSITION which is used to store the position of a rule relatively to the others. By providing a create command and specifying a position, the rule is inserted after the rule with the handle equal to the provided position.
Regarding notification, the position attribute is added to specify the handle of the previous rule in append mode and the handle of the next rule in the other case.
--- include/uapi/linux/netfilter/nf_tables.h | 1 + net/netfilter/nf_tables_api.c | 46 +++++++++++++++++++++++++++++--- 2 files changed, 43 insertions(+), 4 deletions(-)
include/uapi/linux/netfilter/nf_tables.h +1 -0
@@ -143,6 +143,7 @@ enum nft_rule_attributes {NFTA_RULE_EXPRESSIONS ,NFTA_RULE_FLAGS ,NFTA_RULE_COMPAT , +NFTA_RULE_POSITION , __NFTA_RULE_MAX };#define NFTA_RULE_MAX (__NFTA_RULE_MAX - 1)
net/netfilter/nf_tables_api.c +42 -4
82 lines not on this page · raw message
Signature · 1 line
1.8.3.2
Pablo Neira Ayuso
maintainerRe: [PATCHv4] netfilter: nf_tables: add insert operation
Hi Eric,
Quoted 50 lines · Eric Leblond
This patch adds a new rule attribute
NFTA_RULE_POSITIONwhich is used to store the position of a rule relatively to the others. By providing a create command and specifying a position, the rule is inserted after the rule with the handle equal to the provided position.
Regarding notification, the position attribute is added to specify the handle of the previous rule in append mode and the handle of the next rule in the other case.Signed-off-by Eric Leblond <[email protected]>--- include/uapi/linux/netfilter/nf_tables.h | 1 + net/netfilter/nf_tables_api.c | 46 +++++++++++++++++++++++++++++--- 2 files changed, 43 insertions(+), 4 deletions(-)include/uapi/linux/netfilter/nf_tables.h +1
-0@@ -143,6 +143,7 @@ enum nft_rule_attributes {NFTA_RULE_EXPRESSIONS ,NFTA_RULE_FLAGS ,NFTA_RULE_COMPAT , +NFTA_RULE_POSITION , __NFTA_RULE_MAX };#define NFTA_RULE_MAX (__NFTA_RULE_MAX - 1)net/netfilter/nf_tables_api.c +2
-0@@ -1267,6 +1267,7 @@ static const struct nla_policy nft_rule_policy[NFTA_RULE_MAX + 1] = { [NFTA_RULE_EXPRESSIONS] = { .type = NLA_NESTED }, [NFTA_RULE_FLAGS] = { .type = NLA_U32 }, [NFTA_RULE_COMPAT] = { .type = NLA_NESTED }, + [NFTA_RULE_POSITION] = { .type = NLA_U64 }, }; static int nf_tables_fill_rule_info(struct sk_buff *skb, u32 portid, u32 seq,@@ -1279,6 +1280,7 @@ static int nf_tables_fill_rule_info(struct sk_buff *skb, u32 portid, u32 seq,struct nfgenmsg *nfmsg;const struct nft_expr *expr, *next;struct nlattr *list; +const struct nft_rule *prule; event |=NFNL_SUBSYS_NFTABLES <<8 ; nlh = nlmsg_put(skb, portid, seq, event, sizeof(struct nfgenmsg),@@ -1298,6 +1300,26 @@ static int nf_tables_fill_rule_info(struct sk_buff *skb, u32 portid, u32 seq,if (nla_put_be64 (skb,NFTA_RULE_HANDLE ,cpu_to_be64 (rule->handle))) goto nla_put_failure;
net/netfilter/nf_tables_api.c static int nf_tables_fill_rule_info(struct sk_buff *skb, u32 portid, u32 seq, · line 1311
Quoted 10 lines
net/netfilter/nf_tables_api.c +9
-0+if (flags &NLM_F_APPEND ) { +if ((event !=NFT_MSG_DELRULE ) && + (rule->list.prev != &chain->rules)) { + prule =list_entry (rule->list.prev, + struct nft_rule, list); +if (nla_put_be64 (skb,NFTA_RULE_POSITION , +cpu_to_be64 (prule->handle))) + goto nla_put_failure; + }
This looks good but I think we can simplify this to always use .prev.
1) Append: we use .prev. If it's the first rule in the list, skip position attribute.
2) Insert: never dump position attribute as it is always the first rule in the list.
3) At position X: use .prev. If it's the first rule in the list, skip.
That should allows us to remove the else branch below and it should simplify the semantics of NFTA_RULE_POSITION as well.
Quoted 62 lines
net/netfilter/nf_tables_api.c +31
-4+ }else { +if ((event !=NFT_MSG_DELRULE ) && +list_is_last (&rule->list, &chain->rules)) { + prule =list_entry (rule->list.next, + struct nft_rule, list); +if (nla_put_be64 (skb,NFTA_RULE_POSITION , +cpu_to_be64 (prule->handle))) + goto nla_put_failure; + } + } + list =nla_nest_start (skb,NFTA_RULE_EXPRESSIONS );if (list ==NULL ) goto nla_put_failure;@@ -1537,7 +1559,7 @@ static int nf_tables_newrule(struct sock *nlsk, struct sk_buff *skb,int err, rem;bool create;u32 flags =0 ; -u64 handle; +u64 handle, pos_handle; create = nlh->nlmsg_flags &NLM_F_CREATE ? true : false;@@ -1571,6 +1593,15 @@ static int nf_tables_newrule(struct sock *nlsk, struct sk_buff *skb, handle =nf_tables_alloc_handle (table); } +if (nla[NFTA_RULE_POSITION ]) { +if (!(nlh->nlmsg_flags &NLM_F_CREATE )) +return -EOPNOTSUPP ; + pos_handle =be64_to_cpu (nla_get_be64 (nla[NFTA_RULE_POSITION ])); + old_rule =__nf_tables_rule_lookup (chain, pos_handle); +if (IS_ERR (old_rule)) +return PTR_ERR (old_rule); + } +nft_ctx_init (&ctx, skb, nlh, afi, table, chain, nla); n =0 ;@@ -1625,9 +1656,16 @@ static int nf_tables_newrule(struct sock *nlsk, struct sk_buff *skb,nf_tables_rule_destroy (old_rule); } }else if (nlh->nlmsg_flags &NLM_F_APPEND ) -list_add_tail_rcu (&rule->list, &chain->rules); -else -list_add_rcu (&rule->list, &chain->rules); +if (old_rule) +list_add_rcu (&rule->list, &old_rule->list); +else +list_add_tail_rcu (&rule->list, &chain->rules); +else { +if (old_rule) +list_add_tail_rcu (&rule->list, &old_rule->list); +else +list_add_rcu (&rule->list, &chain->rules); + }if (flags &NFT_RULE_F_COMMIT )list_add (&rule->dirty_list, &chain->dirty_rules);Signature · 1 line
1.8.3.2
Re: [PATCHv4] netfilter: nf_tables: add insert operation
Hi,
Quoted 69 lines · Pablo Neira Ayuso
Hi Eric,
Quoted 50 lines · Eric Leblond
This patch adds a new rule attribute
NFTA_RULE_POSITIONwhich is used to store the position of a rule relatively to the others. By providing a create command and specifying a position, the rule is inserted after the rule with the handle equal to the provided position.
Regarding notification, the position attribute is added to specify the handle of the previous rule in append mode and the handle of the next rule in the other case.Signed-off-by Eric Leblond <[email protected]>--- include/uapi/linux/netfilter/nf_tables.h | 1 + net/netfilter/nf_tables_api.c | 46 +++++++++++++++++++++++++++++--- 2 files changed, 43 insertions(+), 4 deletions(-)include/uapi/linux/netfilter/nf_tables.h +1
-0@@ -143,6 +143,7 @@ enum nft_rule_attributes {NFTA_RULE_EXPRESSIONS ,NFTA_RULE_FLAGS ,NFTA_RULE_COMPAT , +NFTA_RULE_POSITION , __NFTA_RULE_MAX };#define NFTA_RULE_MAX (__NFTA_RULE_MAX - 1)net/netfilter/nf_tables_api.c +2
-0@@ -1267,6 +1267,7 @@ static const struct nla_policy nft_rule_policy[NFTA_RULE_MAX + 1] = { [NFTA_RULE_EXPRESSIONS] = { .type = NLA_NESTED }, [NFTA_RULE_FLAGS] = { .type = NLA_U32 }, [NFTA_RULE_COMPAT] = { .type = NLA_NESTED }, + [NFTA_RULE_POSITION] = { .type = NLA_U64 }, }; static int nf_tables_fill_rule_info(struct sk_buff *skb, u32 portid, u32 seq,@@ -1279,6 +1280,7 @@ static int nf_tables_fill_rule_info(struct sk_buff *skb, u32 portid, u32 seq,struct nfgenmsg *nfmsg;const struct nft_expr *expr, *next;struct nlattr *list; +const struct nft_rule *prule; event |=NFNL_SUBSYS_NFTABLES <<8 ; nlh = nlmsg_put(skb, portid, seq, event, sizeof(struct nfgenmsg),@@ -1298,6 +1300,26 @@ static int nf_tables_fill_rule_info(struct sk_buff *skb, u32 portid, u32 seq,if (nla_put_be64 (skb,NFTA_RULE_HANDLE ,cpu_to_be64 (rule->handle))) goto nla_put_failure;net/netfilter/nf_tables_api.c static int nf_tables_fill_rule_info(struct sk_buff *skb, u32 portid, u32 seq, · line 1311
Quoted 10 lines
net/netfilter/nf_tables_api.c +9
-0+if (flags &NLM_F_APPEND ) { +if ((event !=NFT_MSG_DELRULE ) && + (rule->list.prev != &chain->rules)) { + prule =list_entry (rule->list.prev, + struct nft_rule, list); +if (nla_put_be64 (skb,NFTA_RULE_POSITION , +cpu_to_be64 (prule->handle))) + goto nla_put_failure; + }This looks good but I think we can simplify this to always use .prev.
1) Append: we use .prev. If it's the first rule in the list, skip position attribute.
Quoted 7 lines
2) Insert: never dump position attribute as it is always the first rule in the list.
3) At position X: use .prev. If it's the first rule in the list, skip.
That should allows us to remove the else branch below and it should simplify the semantics of
NFTA_RULE_POSITIONas well.
This code is not pretty and I understand your point but we have two type of operations:
* Insert before
* Append after
In both cases, the presence of the NFTA_RULE_POSITION attribute is triggering the switch to this mode. And I think this is a convenient way to update the API.
Furthermore, inside nf_tables_fill_rule_info() we don't have any information to decide that we are in "position X". Only solution to switch to the method you describe would be to introduce a new operation and it seems that was is wanted (it was said in initial discussion).
BR,
Quoted 67 lines
Quoted 63 lines
net/netfilter/nf_tables_api.c +31
-4+ }else { +if ((event !=NFT_MSG_DELRULE ) && +list_is_last (&rule->list, &chain->rules)) { + prule =list_entry (rule->list.next, + struct nft_rule, list); +if (nla_put_be64 (skb,NFTA_RULE_POSITION , +cpu_to_be64 (prule->handle))) + goto nla_put_failure; + } + } + list =nla_nest_start (skb,NFTA_RULE_EXPRESSIONS );if (list ==NULL ) goto nla_put_failure;@@ -1537,7 +1559,7 @@ static int nf_tables_newrule(struct sock *nlsk, struct sk_buff *skb,int err, rem;bool create;u32 flags =0 ; -u64 handle; +u64 handle, pos_handle; create = nlh->nlmsg_flags &NLM_F_CREATE ? true : false;@@ -1571,6 +1593,15 @@ static int nf_tables_newrule(struct sock *nlsk, struct sk_buff *skb, handle =nf_tables_alloc_handle (table); } +if (nla[NFTA_RULE_POSITION ]) { +if (!(nlh->nlmsg_flags &NLM_F_CREATE )) +return -EOPNOTSUPP ; + pos_handle =be64_to_cpu (nla_get_be64 (nla[NFTA_RULE_POSITION ])); + old_rule =__nf_tables_rule_lookup (chain, pos_handle); +if (IS_ERR (old_rule)) +return PTR_ERR (old_rule); + } +nft_ctx_init (&ctx, skb, nlh, afi, table, chain, nla); n =0 ;@@ -1625,9 +1656,16 @@ static int nf_tables_newrule(struct sock *nlsk, struct sk_buff *skb,nf_tables_rule_destroy (old_rule); } }else if (nlh->nlmsg_flags &NLM_F_APPEND ) -list_add_tail_rcu (&rule->list, &chain->rules); -else -list_add_rcu (&rule->list, &chain->rules); +if (old_rule) +list_add_rcu (&rule->list, &old_rule->list); +else +list_add_tail_rcu (&rule->list, &chain->rules); +else { +if (old_rule) +list_add_tail_rcu (&rule->list, &old_rule->list); +else +list_add_rcu (&rule->list, &chain->rules); + }if (flags &NFT_RULE_F_COMMIT )list_add (&rule->dirty_list, &chain->dirty_rules);Signature · 1 line
1.8.3.2--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Pablo Neira Ayuso
maintainerRe: [PATCHv4] netfilter: nf_tables: add insert operation
Hi Eric,
Quoted 80 lines · Eric Leblond
Hi,
Quoted 69 lines · Pablo Neira Ayuso
Hi Eric,
Quoted 50 lines · Eric Leblond
This patch adds a new rule attribute
NFTA_RULE_POSITIONwhich is used to store the position of a rule relatively to the others. By providing a create command and specifying a position, the rule is inserted after the rule with the handle equal to the provided position.
Regarding notification, the position attribute is added to specify the handle of the previous rule in append mode and the handle of the next rule in the other case.Signed-off-by Eric Leblond <[email protected]>--- include/uapi/linux/netfilter/nf_tables.h | 1 + net/netfilter/nf_tables_api.c | 46 +++++++++++++++++++++++++++++--- 2 files changed, 43 insertions(+), 4 deletions(-)include/uapi/linux/netfilter/nf_tables.h +1
-0@@ -143,6 +143,7 @@ enum nft_rule_attributes {NFTA_RULE_EXPRESSIONS ,NFTA_RULE_FLAGS ,NFTA_RULE_COMPAT , +NFTA_RULE_POSITION , __NFTA_RULE_MAX };#define NFTA_RULE_MAX (__NFTA_RULE_MAX - 1)net/netfilter/nf_tables_api.c +2
-0@@ -1267,6 +1267,7 @@ static const struct nla_policy nft_rule_policy[NFTA_RULE_MAX + 1] = { [NFTA_RULE_EXPRESSIONS] = { .type = NLA_NESTED }, [NFTA_RULE_FLAGS] = { .type = NLA_U32 }, [NFTA_RULE_COMPAT] = { .type = NLA_NESTED }, + [NFTA_RULE_POSITION] = { .type = NLA_U64 }, }; static int nf_tables_fill_rule_info(struct sk_buff *skb, u32 portid, u32 seq,@@ -1279,6 +1280,7 @@ static int nf_tables_fill_rule_info(struct sk_buff *skb, u32 portid, u32 seq,struct nfgenmsg *nfmsg;const struct nft_expr *expr, *next;struct nlattr *list; +const struct nft_rule *prule; event |=NFNL_SUBSYS_NFTABLES <<8 ; nlh = nlmsg_put(skb, portid, seq, event, sizeof(struct nfgenmsg),@@ -1298,6 +1300,26 @@ static int nf_tables_fill_rule_info(struct sk_buff *skb, u32 portid, u32 seq,if (nla_put_be64 (skb,NFTA_RULE_HANDLE ,cpu_to_be64 (rule->handle))) goto nla_put_failure;net/netfilter/nf_tables_api.c static int nf_tables_fill_rule_info(struct sk_buff *skb, u32 portid, u32 seq, · line 1311
Quoted 10 lines
net/netfilter/nf_tables_api.c +9
-0+if (flags &NLM_F_APPEND ) { +if ((event !=NFT_MSG_DELRULE ) && + (rule->list.prev != &chain->rules)) { + prule =list_entry (rule->list.prev, + struct nft_rule, list); +if (nla_put_be64 (skb,NFTA_RULE_POSITION , +cpu_to_be64 (prule->handle))) + goto nla_put_failure; + }This looks good but I think we can simplify this to always use .prev.
1) Append: we use .prev. If it's the first rule in the list, skip position attribute.
Quoted 7 lines
2) Insert: never dump position attribute as it is always the first rule in the list.
3) At position X: use .prev. If it's the first rule in the list, skip.
That should allows us to remove the else branch below and it should simplify the semantics of
NFTA_RULE_POSITIONas well.
Quoted 7 lines
This code is not pretty and I understand your point but we have two type of operations:
* Insert before
* Append after
In both cases, the presence of theNFTA_RULE_POSITIONattribute is triggering the switch to this mode. And I think this is a convenient way to update the API.
I see. Then we need to save the append flag to report events correctly in the commit path for the "insert after" case, according to this approach (that's should be easy to resolve though with a follow up patch).
Quoted 2 lines
Furthermore, inside
nf_tables_fill_rule_info()we don't have any information to decide that we are in "position X".
But we know the handle of our .prev node for that new rule we added, that can be used to report back our relative location to it, ie. always return the previous node.
This however results in reporting back a different handle via the event notification in the "insert after" case (instead of the original handle passed via the rule_position attribute).
Quoted 3 lines
Only solution to switch to the method you describe would be to introduce a new operation and it seems that was is wanted (it was said in initial discussion).
Sure, I just wanted to discuss the nf_tables_fill_rule_info path, not questioning the entire patch.
Regards.
--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCHv4] netfilter: nf_tables: add insert operation
Hello Pablo,
Quoted 91 lines · Pablo Neira Ayuso
Hi Eric,
Quoted 80 lines · Eric Leblond
Hi,
Quoted 69 lines · Pablo Neira Ayuso
Hi Eric,
Quoted 50 lines · Eric Leblond
This patch adds a new rule attribute
NFTA_RULE_POSITIONwhich is used to store the position of a rule relatively to the others. By providing a create command and specifying a position, the rule is inserted after the rule with the handle equal to the provided position.
Regarding notification, the position attribute is added to specify the handle of the previous rule in append mode and the handle of the next rule in the other case.Signed-off-by Eric Leblond <[email protected]>--- include/uapi/linux/netfilter/nf_tables.h | 1 + net/netfilter/nf_tables_api.c | 46 +++++++++++++++++++++++++++++--- 2 files changed, 43 insertions(+), 4 deletions(-)include/uapi/linux/netfilter/nf_tables.h +1
-0@@ -143,6 +143,7 @@ enum nft_rule_attributes {NFTA_RULE_EXPRESSIONS ,NFTA_RULE_FLAGS ,NFTA_RULE_COMPAT , +NFTA_RULE_POSITION , __NFTA_RULE_MAX };#define NFTA_RULE_MAX (__NFTA_RULE_MAX - 1)net/netfilter/nf_tables_api.c +2
-0@@ -1267,6 +1267,7 @@ static const struct nla_policy nft_rule_policy[NFTA_RULE_MAX + 1] = { [NFTA_RULE_EXPRESSIONS] = { .type = NLA_NESTED }, [NFTA_RULE_FLAGS] = { .type = NLA_U32 }, [NFTA_RULE_COMPAT] = { .type = NLA_NESTED }, + [NFTA_RULE_POSITION] = { .type = NLA_U64 }, }; static int nf_tables_fill_rule_info(struct sk_buff *skb, u32 portid, u32 seq,@@ -1279,6 +1280,7 @@ static int nf_tables_fill_rule_info(struct sk_buff *skb, u32 portid, u32 seq,struct nfgenmsg *nfmsg;const struct nft_expr *expr, *next;struct nlattr *list; +const struct nft_rule *prule; event |=NFNL_SUBSYS_NFTABLES <<8 ; nlh = nlmsg_put(skb, portid, seq, event, sizeof(struct nfgenmsg),@@ -1298,6 +1300,26 @@ static int nf_tables_fill_rule_info(struct sk_buff *skb, u32 portid, u32 seq,if (nla_put_be64 (skb,NFTA_RULE_HANDLE ,cpu_to_be64 (rule->handle))) goto nla_put_failure;net/netfilter/nf_tables_api.c static int nf_tables_fill_rule_info(struct sk_buff *skb, u32 portid, u32 seq, · line 1311
Quoted 10 lines
net/netfilter/nf_tables_api.c +9
-0+if (flags &NLM_F_APPEND ) { +if ((event !=NFT_MSG_DELRULE ) && + (rule->list.prev != &chain->rules)) { + prule =list_entry (rule->list.prev, + struct nft_rule, list); +if (nla_put_be64 (skb,NFTA_RULE_POSITION , +cpu_to_be64 (prule->handle))) + goto nla_put_failure; + }This looks good but I think we can simplify this to always use .prev.
1) Append: we use .prev. If it's the first rule in the list, skip position attribute.
Quoted 7 lines
2) Insert: never dump position attribute as it is always the first rule in the list.
3) At position X: use .prev. If it's the first rule in the list, skip.
That should allows us to remove the else branch below and it should simplify the semantics of
NFTA_RULE_POSITIONas well.Quoted 7 lines
This code is not pretty and I understand your point but we have two type of operations:
* Insert before
* Append after
In both cases, the presence of theNFTA_RULE_POSITIONattribute is triggering the switch to this mode. And I think this is a convenient way to update the API.
Quoted 4 lines
I see. Then we need to save the append flag to report events correctly in the commit path for the "insert after" case, according to this approach (that's should be easy to resolve though with a follow up patch).
IMHO, it is already there. At start of nf_tables_fill_rule_info, we are doing:
nlh = nlmsg_put(skb, portid, seq, event, sizeof(struct nfgenmsg), flags);
So flags is used as flag inside nlh. And we can get the information during event by checking (nlh->nlmsg_flags & NLM_F_APPEND). I've done some tests with the attached patch and it seems to work well.
So events get insert/append information as well as position. This should be enough for event listeners to follow ruleset evolution.
Quoted 10 lines
Quoted 2 lines
Furthermore, inside
nf_tables_fill_rule_info()we don't have any information to decide that we are in "position X".But we know the handle of our .prev node for that new rule we added, that can be used to report back our relative location to it, ie. always return the previous node.
This however results in reporting back a different handle via the event notification in the "insert after" case (instead of the original handle passed via the
rule_positionattribute).
Yes, getting insert/append information and position is better.
Quoted 6 lines
Quoted 3 lines
Only solution to switch to the method you describe would be to introduce a new operation and it seems that was is wanted (it was said in initial discussion).
Sure, I just wanted to discuss the
nf_tables_fill_rule_infopath, not questioning the entire patch.
Cool :)
BR,
--
Eric
From 86e6e09ebbe2b770547034c2cb6a2239f79f1ce4 Mon Sep 17 00:00:00 2001
From: Eric Leblond <[email protected]>
Date: Tue, 16 Jul 2013 09:12:19 +0200
Subject: [PATCH] after before
--- examples/nft-events.c | 4 ++++ 1 file changed, 4 insertions(+)
examples/nft-events.c +4 -0
@@ -63,6 +63,10 @@ static int rule_cb(const struct nlmsghdr *nlh, int type) goto err_free; } +if (nlh->nlmsg_flags &NLM_F_APPEND ) +printf ("AFTER " ); +else +printf ("BEFORE " );nft_rule_snprintf (buf,sizeof (buf), t,NFT_RULE_O_DEFAULT ,0 );printf ("[%s]\t%s\n" , type ==NFT_MSG_NEWRULE ?"NEW" :"DEL" , buf);
Signature · 1 line
1.8.3.2
Pablo Neira Ayuso
maintainerRe: [PATCHv4] netfilter: nf_tables: add insert operation
Quoted 103 lines · Eric Leblond
Hello Pablo,
Quoted 91 lines · Pablo Neira Ayuso
Hi Eric,
Quoted 80 lines · Eric Leblond
Hi,
Quoted 69 lines · Pablo Neira Ayuso
Hi Eric,
Quoted 50 lines · Eric Leblond
This patch adds a new rule attribute
NFTA_RULE_POSITIONwhich is used to store the position of a rule relatively to the others. By providing a create command and specifying a position, the rule is inserted after the rule with the handle equal to the provided position.
Regarding notification, the position attribute is added to specify the handle of the previous rule in append mode and the handle of the next rule in the other case.Signed-off-by Eric Leblond <[email protected]>--- include/uapi/linux/netfilter/nf_tables.h | 1 + net/netfilter/nf_tables_api.c | 46 +++++++++++++++++++++++++++++--- 2 files changed, 43 insertions(+), 4 deletions(-)include/uapi/linux/netfilter/nf_tables.h +1
-0@@ -143,6 +143,7 @@ enum nft_rule_attributes {NFTA_RULE_EXPRESSIONS ,NFTA_RULE_FLAGS ,NFTA_RULE_COMPAT , +NFTA_RULE_POSITION , __NFTA_RULE_MAX };#define NFTA_RULE_MAX (__NFTA_RULE_MAX - 1)net/netfilter/nf_tables_api.c +2
-0@@ -1267,6 +1267,7 @@ static const struct nla_policy nft_rule_policy[NFTA_RULE_MAX + 1] = { [NFTA_RULE_EXPRESSIONS] = { .type = NLA_NESTED }, [NFTA_RULE_FLAGS] = { .type = NLA_U32 }, [NFTA_RULE_COMPAT] = { .type = NLA_NESTED }, + [NFTA_RULE_POSITION] = { .type = NLA_U64 }, }; static int nf_tables_fill_rule_info(struct sk_buff *skb, u32 portid, u32 seq,@@ -1279,6 +1280,7 @@ static int nf_tables_fill_rule_info(struct sk_buff *skb, u32 portid, u32 seq,struct nfgenmsg *nfmsg;const struct nft_expr *expr, *next;struct nlattr *list; +const struct nft_rule *prule; event |=NFNL_SUBSYS_NFTABLES <<8 ; nlh = nlmsg_put(skb, portid, seq, event, sizeof(struct nfgenmsg),@@ -1298,6 +1300,26 @@ static int nf_tables_fill_rule_info(struct sk_buff *skb, u32 portid, u32 seq,if (nla_put_be64 (skb,NFTA_RULE_HANDLE ,cpu_to_be64 (rule->handle))) goto nla_put_failure;net/netfilter/nf_tables_api.c static int nf_tables_fill_rule_info(struct sk_buff *skb, u32 portid, u32 seq, · line 1311
Quoted 10 lines
net/netfilter/nf_tables_api.c +9
-0+if (flags &NLM_F_APPEND ) { +if ((event !=NFT_MSG_DELRULE ) && + (rule->list.prev != &chain->rules)) { + prule =list_entry (rule->list.prev, + struct nft_rule, list); +if (nla_put_be64 (skb,NFTA_RULE_POSITION , +cpu_to_be64 (prule->handle))) + goto nla_put_failure; + }This looks good but I think we can simplify this to always use .prev.
1) Append: we use .prev. If it's the first rule in the list, skip position attribute.
Quoted 7 lines
2) Insert: never dump position attribute as it is always the first rule in the list.
3) At position X: use .prev. If it's the first rule in the list, skip.
That should allows us to remove the else branch below and it should simplify the semantics of
NFTA_RULE_POSITIONas well.Quoted 7 lines
This code is not pretty and I understand your point but we have two type of operations:
* Insert before
* Append after
In both cases, the presence of theNFTA_RULE_POSITIONattribute is triggering the switch to this mode. And I think this is a convenient way to update the API.Quoted 4 lines
I see. Then we need to save the append flag to report events correctly in the commit path for the "insert after" case, according to this approach (that's should be easy to resolve though with a follow up patch).
IMHO, it is already there. At start of
nf_tables_fill_rule_info, we are doing:
Quoted 6 lines
nlh = nlmsg_put(skb, portid, seq, event, sizeof(struct nfgenmsg), flags);So flags is used as flag inside nlh. And we can get the information during event by checking (
nlh->nlmsg_flags&NLM_F_APPEND). I've done some tests with the attached patch and it seems to work well.
Please, see nf_tables_commit. In that path nf_tables_rule_notify does not get those flags at this moment, so it's returning its position in the insert fashion, ie. pointing to .next.
The problem with pointing to the .next node in the commit path is we are sure that .prev points to an existing rule. However, .next may point to stale rule. So I think we have to notify the position always relative to the .prev pointer to get this working in the commit path.
Regards.
--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCHv4] netfilter: nf_tables: add insert operation
Hi,
Quoted 111 lines · Pablo Neira Ayuso
Quoted 103 lines · Eric Leblond
Hello Pablo,
Quoted 91 lines · Pablo Neira Ayuso
Hi Eric,
Quoted 80 lines · Eric Leblond
Hi,
Quoted 69 lines · Pablo Neira Ayuso
Hi Eric,
Quoted 50 lines · Eric Leblond
This patch adds a new rule attribute
NFTA_RULE_POSITIONwhich is used to store the position of a rule relatively to the others. By providing a create command and specifying a position, the rule is inserted after the rule with the handle equal to the provided position.
Regarding notification, the position attribute is added to specify the handle of the previous rule in append mode and the handle of the next rule in the other case.Signed-off-by Eric Leblond <[email protected]>--- include/uapi/linux/netfilter/nf_tables.h | 1 + net/netfilter/nf_tables_api.c | 46 +++++++++++++++++++++++++++++--- 2 files changed, 43 insertions(+), 4 deletions(-)include/uapi/linux/netfilter/nf_tables.h +1
-0@@ -143,6 +143,7 @@ enum nft_rule_attributes {NFTA_RULE_EXPRESSIONS ,NFTA_RULE_FLAGS ,NFTA_RULE_COMPAT , +NFTA_RULE_POSITION , __NFTA_RULE_MAX };#define NFTA_RULE_MAX (__NFTA_RULE_MAX - 1)net/netfilter/nf_tables_api.c +2
-0@@ -1267,6 +1267,7 @@ static const struct nla_policy nft_rule_policy[NFTA_RULE_MAX + 1] = { [NFTA_RULE_EXPRESSIONS] = { .type = NLA_NESTED }, [NFTA_RULE_FLAGS] = { .type = NLA_U32 }, [NFTA_RULE_COMPAT] = { .type = NLA_NESTED }, + [NFTA_RULE_POSITION] = { .type = NLA_U64 }, }; static int nf_tables_fill_rule_info(struct sk_buff *skb, u32 portid, u32 seq,@@ -1279,6 +1280,7 @@ static int nf_tables_fill_rule_info(struct sk_buff *skb, u32 portid, u32 seq,struct nfgenmsg *nfmsg;const struct nft_expr *expr, *next;struct nlattr *list; +const struct nft_rule *prule; event |=NFNL_SUBSYS_NFTABLES <<8 ; nlh = nlmsg_put(skb, portid, seq, event, sizeof(struct nfgenmsg),@@ -1298,6 +1300,26 @@ static int nf_tables_fill_rule_info(struct sk_buff *skb, u32 portid, u32 seq,if (nla_put_be64 (skb,NFTA_RULE_HANDLE ,cpu_to_be64 (rule->handle))) goto nla_put_failure;net/netfilter/nf_tables_api.c static int nf_tables_fill_rule_info(struct sk_buff *skb, u32 portid, u32 seq, · line 1311
Quoted 10 lines
net/netfilter/nf_tables_api.c +9
-0+if (flags &NLM_F_APPEND ) { +if ((event !=NFT_MSG_DELRULE ) && + (rule->list.prev != &chain->rules)) { + prule =list_entry (rule->list.prev, + struct nft_rule, list); +if (nla_put_be64 (skb,NFTA_RULE_POSITION , +cpu_to_be64 (prule->handle))) + goto nla_put_failure; + }This looks good but I think we can simplify this to always use .prev.
1) Append: we use .prev. If it's the first rule in the list, skip position attribute.
Quoted 7 lines
2) Insert: never dump position attribute as it is always the first rule in the list.
3) At position X: use .prev. If it's the first rule in the list, skip.
That should allows us to remove the else branch below and it should simplify the semantics of
NFTA_RULE_POSITIONas well.Quoted 7 lines
This code is not pretty and I understand your point but we have two type of operations:
* Insert before
* Append after
In both cases, the presence of theNFTA_RULE_POSITIONattribute is triggering the switch to this mode. And I think this is a convenient way to update the API.Quoted 4 lines
I see. Then we need to save the append flag to report events correctly in the commit path for the "insert after" case, according to this approach (that's should be easy to resolve though with a follow up patch).
IMHO, it is already there. At start of
nf_tables_fill_rule_info, we are doing:Quoted 6 lines
nlh = nlmsg_put(skb, portid, seq, event, sizeof(struct nfgenmsg), flags);So flags is used as flag inside nlh. And we can get the information during event by checking (
nlh->nlmsg_flags&NLM_F_APPEND). I've done some tests with the attached patch and it seems to work well.
Quoted 8 lines
Please, see
nf_tables_commit. In that pathnf_tables_rule_notifydoes not get those flags at this moment, so it's returning its position in the insert fashion, ie. pointing to .next.The problem with pointing to the .next node in the commit path is we are sure that .prev points to an existing rule. However, .next may point to stale rule. So I think we have to notify the position always relative to the .prev pointer to get this working in the commit path.
Thanks a lot for the clarification. I'll update the patch.
BR,
--
Eric
PATCH v5 1/1 netfilter: nf_tables: add insert operation
This patch adds a new rule attribute NFTA_RULE_POSITION which is used to store the position of a rule relatively to the others. By providing a create command and specifying a position, the rule is inserted after the rule with the handle equal to the provided position.
Regarding notification, the position attribute is added to specify the handle of the previous rule.
--- include/uapi/linux/netfilter/nf_tables.h | 1 + net/netfilter/nf_tables_api.c | 33 ++++++++++++++++++++++++++++---- 2 files changed, 30 insertions(+), 4 deletions(-)
include/uapi/linux/netfilter/nf_tables.h +1 -0
@@ -143,6 +143,7 @@ enum nft_rule_attributes {NFTA_RULE_EXPRESSIONS ,NFTA_RULE_FLAGS ,NFTA_RULE_COMPAT , +NFTA_RULE_POSITION , __NFTA_RULE_MAX };#define NFTA_RULE_MAX (__NFTA_RULE_MAX - 1)
net/netfilter/nf_tables_api.c +29 -4
@@ -1267,6 +1267,7 @@ static const struct nla_policy nft_rule_policy[NFTA_RULE_MAX + 1] = { [NFTA_RULE_EXPRESSIONS] = { .type = NLA_NESTED }, [NFTA_RULE_FLAGS] = { .type = NLA_U32 }, [NFTA_RULE_COMPAT] = { .type = NLA_NESTED }, + [NFTA_RULE_POSITION] = { .type = NLA_U64 }, }; static int nf_tables_fill_rule_info(struct sk_buff *skb, u32 portid, u32 seq,
@@ -1279,6 +1280,7 @@ static int nf_tables_fill_rule_info(struct sk_buff *skb, u32 portid, u32 seq,struct nfgenmsg *nfmsg;const struct nft_expr *expr, *next;struct nlattr *list; +const struct nft_rule *prule; event |=NFNL_SUBSYS_NFTABLES <<8 ; nlh = nlmsg_put(skb, portid, seq, event, sizeof(struct nfgenmsg),
@@ -1298,6 +1300,13 @@ static int nf_tables_fill_rule_info(struct sk_buff *skb, u32 portid, u32 seq,if (nla_put_be64 (skb,NFTA_RULE_HANDLE ,cpu_to_be64 (rule->handle))) goto nla_put_failure; +if ((event !=NFT_MSG_DELRULE ) && (rule->list.prev != &chain->rules)) { + prule = list_entry(rule->list.prev, struct nft_rule, list); +if (nla_put_be64 (skb,NFTA_RULE_POSITION , +cpu_to_be64 (prule->handle))) + goto nla_put_failure; + } + list =nla_nest_start (skb,NFTA_RULE_EXPRESSIONS );if (list ==NULL ) goto nla_put_failure;
@@ -1537,7 +1546,7 @@ static int nf_tables_newrule(struct sock *nlsk, struct sk_buff *skb,int err, rem;bool create;u32 flags =0 ; -u64 handle; +u64 handle, pos_handle; create = nlh->nlmsg_flags &NLM_F_CREATE ? true : false;
@@ -1571,6 +1580,15 @@ static int nf_tables_newrule(struct sock *nlsk, struct sk_buff *skb, handle =nf_tables_alloc_handle (table); } +if (nla[NFTA_RULE_POSITION ]) { +if (!(nlh->nlmsg_flags &NLM_F_CREATE )) +return -EOPNOTSUPP ; + pos_handle =be64_to_cpu (nla_get_be64 (nla[NFTA_RULE_POSITION ])); + old_rule =__nf_tables_rule_lookup (chain, pos_handle); +if (IS_ERR (old_rule)) +return PTR_ERR (old_rule); + } +nft_ctx_init (&ctx, skb, nlh, afi, table, chain, nla); n =0 ;
@@ -1625,9 +1643,16 @@ static int nf_tables_newrule(struct sock *nlsk, struct sk_buff *skb,nf_tables_rule_destroy (old_rule); } }else if (nlh->nlmsg_flags &NLM_F_APPEND ) -list_add_tail_rcu (&rule->list, &chain->rules); -else -list_add_rcu (&rule->list, &chain->rules); +if (old_rule) +list_add_rcu (&rule->list, &old_rule->list); +else +list_add_tail_rcu (&rule->list, &chain->rules); +else { +if (old_rule) +list_add_tail_rcu (&rule->list, &old_rule->list); +else +list_add_rcu (&rule->list, &chain->rules); + }if (flags &NFT_RULE_F_COMMIT )list_add (&rule->dirty_list, &chain->dirty_rules);
Signature · 1 line
1.8.3.2
Re: [PATCHv5] netfilter: nf_tables: add insert operation
Quoted 7 lines · Eric Leblond
This patch adds a new rule attribute
NFTA_RULE_POSITIONwhich is used to store the position of a rule relatively to the others. By providing a create command and specifying a position, the rule is inserted after the rule with the handle equal to the provided position.
Regarding notification, the position attribute is added to specify the handle of the previous rule.
Applied, thanks a lot Eric!
PATCH 1/1 rule: honor flag argument during rule creation
In reply to Eric Leblond--- src/mnl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
src/mnl.c +1 -1
@@ -61,7 +61,7 @@ int mnl_nft_rule_add(struct mnl_socket *nf_sock, struct nft_rule *nlr, nlh =nft_table_nlmsg_build_hdr (buf,NFT_MSG_NEWRULE ,nft_rule_attr_get_u32 (nlr,NFT_RULE_ATTR_FAMILY ), -NLM_F_APPEND |NLM_F_ACK |NLM_F_CREATE , seq); + flags|NLM_F_ACK |NLM_F_CREATE , seq);nft_rule_nlmsg_build_payload (nlh, nlr);return mnl_talk (nf_sock, nlh, nlh->nlmsg_len,NULL ,NULL );
Signature · 1 line
1.8.3.2
PATCH 1/4 rule: add support for position attribute
In reply to Eric LeblondThis patch adds support for position attribute which can be used to insert a rule at a given position.
--- include/libnftables/rule.h | 1 + include/linux/netfilter/nf_tables.h | 1 + src/rule.c | 23 +++++++++++++++++++++++ 3 files changed, 25 insertions(+)
include/libnftables/rule.h +1 -0
@@ -22,6 +22,7 @@ enum {NFT_RULE_ATTR_FLAGS ,NFT_RULE_ATTR_COMPAT_PROTO ,NFT_RULE_ATTR_COMPAT_FLAGS , + NFT_RULE_ATTR_POSITION, };void nft_rule_attr_unset (struct nft_rule *r,uint16_t attr);
include/linux/netfilter/nf_tables.h +1 -0
@@ -99,6 +99,7 @@ enum nft_rule_attributes {NFTA_RULE_EXPRESSIONS ,NFTA_RULE_FLAGS ,NFTA_RULE_COMPAT , +NFTA_RULE_POSITION , __NFTA_RULE_MAX };#define NFTA_RULE_MAX (__NFTA_RULE_MAX - 1)
src/rule.c +23 -0
@@ -39,6 +39,7 @@ struct nft_rule {uint8_t family;uint32_t rule_flags;uint64_t handle; +uint64_t position;struct {uint32_t flags;uint32_t proto;
@@ -99,6 +100,7 @@ void nft_rule_attr_unset(struct nft_rule *r, uint16_t attr)case NFT_RULE_ATTR_FLAGS :case NFT_RULE_ATTR_COMPAT_PROTO :case NFT_RULE_ATTR_COMPAT_FLAGS : +case NFT_RULE_ATTR_POSITION :case NFT_RULE_ATTR_FAMILY :break ;default :
@@ -127,6 +129,9 @@ void nft_rule_attr_set(struct nft_rule *r, uint16_t attr, const void *data)case NFT_RULE_ATTR_HANDLE : r->handle = *((uint64_t *)data);break ; +case NFT_RULE_ATTR_POSITION : + r->position = *((uint64_t *)data); +break ;case NFT_RULE_ATTR_FLAGS : r->rule_flags = *((uint32_t *)data);break ;
@@ -208,6 +213,12 @@ const void *nft_rule_attr_get(const struct nft_rule *r, uint16_t attr)else return NULL ;break ; +case NFT_RULE_ATTR_POSITION : +if (r->flags & (1 <<NFT_RULE_ATTR_POSITION )) +return &r->position; +else +return NULL ; +break ;default :return NULL ; }
@@ -273,6 +284,8 @@ void nft_rule_nlmsg_build_payload(struct nlmsghdr *nlh, struct nft_rule *r)mnl_attr_put_strz (nlh,NFTA_RULE_CHAIN , r->chain);if (r->flags & (1 <<NFT_RULE_ATTR_HANDLE ))mnl_attr_put_u64 (nlh,NFTA_RULE_HANDLE ,htobe64 (r->handle)); +if (r->flags & (1 <<NFT_RULE_ATTR_POSITION )) +mnl_attr_put_u64 (nlh,NFTA_RULE_POSITION ,htobe64 (r->position));if (r->flags & (1 <<NFT_RULE_ATTR_FLAGS ))mnl_attr_put_u32 (nlh,NFTA_RULE_FLAGS ,htonl (r->rule_flags));
@@ -335,6 +348,12 @@ static int nft_rule_parse_attr_cb(const struct nlattr *attr, void *data)return MNL_CB_ERROR ; }break ; +case NFTA_RULE_POSITION : +if (mnl_attr_validate (attr,MNL_TYPE_U64 ) <0 ) { +perror ("mnl_attr_validate" ); +return MNL_CB_ERROR ; + } +break ; } tb[type] = attr;
@@ -469,6 +488,10 @@ int nft_rule_nlmsg_parse(const struct nlmsghdr *nlh, struct nft_rule *r) ret =nft_rule_parse_expr (tb[NFTA_RULE_EXPRESSIONS ], r);if (tb[NFTA_RULE_COMPAT ]) ret =nft_rule_parse_compat (tb[NFTA_RULE_COMPAT ], r); +if (tb[NFTA_RULE_POSITION ]) { + r->position =be64toh (mnl_attr_get_u64 (tb[NFTA_RULE_POSITION ])); + r->flags |= (1 <<NFT_RULE_ATTR_POSITION ); + } r->family = nfg->nfgen_family; r->flags |= (1 <<NFT_RULE_ATTR_FAMILY );
Signature · 1 line
1.8.3.2
PATCH 2/4 examples: add insert rule example
This program can insert a rule after a rule given by its handle.
--- examples/Makefile.am | 4 + examples/nft-rule-insert.c | 204 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 208 insertions(+) create mode 100644 examples/nft-rule-insert.c
examples/Makefile.am +4 -0
@@ -10,6 +10,7 @@ check_PROGRAMS = nft-table-add \ nft-chain-del \ nft-chain-get \ nft-rule-add \ + nft-rule-insert \ nft-rule-xml-add \ nft-rule-del \ nft-rule-get \
@@ -52,6 +53,9 @@ nft_chain_get_LDADD = ../src/libnftables.la ${LIBMNL_LIBS} ${LIBXML_LIBS} nft_rule_add_SOURCES = nft-rule-add.c nft_rule_add_LDADD = ../src/libnftables.la ${LIBMNL_LIBS} ${LIBXML_LIBS} +nft_rule_insert_SOURCES = nft-rule-insert.c +nft_rule_insert_LDADD = ../src/libnftables.la ${LIBMNL_LIBS} ${LIBXML_LIBS} + nft_rule_xml_add_SOURCES = nft-rule-xml-add.c nft_rule_xml_add_LDADD = ../src/libnftables.la ${LIBMNL_LIBS} ${LIBXML_LIBS}
examples/nft-rule-insert.c new file +204 -0
204 lines not on this page · raw message
Signature · 1 line
1.8.3.2
Re: [libnftables PATCH 2/4] examples: add insert rule example
Quoted 2 lines · Eric Leblond
This program can insert a rule after a rule given by its handle.
Applied, thanks Eric.
PATCH 3/4 rule: display position in default printf
In reply to Eric Leblond--- src/rule.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
src/rule.c +2 -2
@@ -769,9 +769,9 @@ static int nft_rule_snprintf_default(char *buf, size_t size, struct nft_rule *r,struct nft_rule_expr *expr;int ret, len = size, offset =0 ; - ret =snprintf (buf, size,"%s %s %s %" PRIu64"\n" , + ret =snprintf (buf, size,"%s %s %s %" PRIu64" %" PRIu64"\n" ,nft_family2str (r->family), r->table, r->chain, - r->handle); + r->handle, r->position);SNPRINTF_BUFFER_SIZE (ret, size, len, offset);list_for_each_entry (expr, &r->expr_list, head) {
Signature · 1 line
1.8.3.2
Pablo Neira Ayuso
maintainerRe: [libnftables PATCH 3/4] rule: display position in default printf
Also applied, thanks.
PATCH 4/4 rule: change type of function to use const
In reply to Eric LeblondThe function nft_rule_attr_is_set() is doing no modification so it is possible to type it to const.
--- include/libnftables/rule.h | 2 +- src/rule.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
include/libnftables/rule.h +1 -1
@@ -26,7 +26,7 @@ enum { };void nft_rule_attr_unset (struct nft_rule *r,uint16_t attr); -bool nft_rule_attr_is_set (struct nft_rule *r,uint16_t attr); +bool nft_rule_attr_is_set (const struct nft_rule *r,uint16_t attr);void nft_rule_attr_set (struct nft_rule *r,uint16_t attr,const void *data);void nft_rule_attr_set_u32 (struct nft_rule *r,uint16_t attr,uint32_t val);void nft_rule_attr_set_u64 (struct nft_rule *r,uint16_t attr,uint64_t val);
src/rule.c +1 -1
@@ -73,7 +73,7 @@ void nft_rule_free(struct nft_rule *r) }EXPORT_SYMBOL (nft_rule_free); -bool nft_rule_attr_is_set (struct nft_rule *r,uint16_t attr) +bool nft_rule_attr_is_set (const struct nft_rule *r,uint16_t attr) {return r->flags & (1 << attr); }
Signature · 1 line
1.8.3.2
Pablo Neira Ayuso
maintainerRe: [libnftables PATCH 4/4] rule: change type of function to use const
Quoted 2 lines · Eric Leblond
The function
nft_rule_attr_is_set()is doing no modification so it is possible to type it to const.
I have mangled this patch to adapt all other nft_*_attr_is_set as well. This patch is master now, thanks.
Re: [libnftables PATCH 1/4] rule: add support for position attribute
In reply to Eric LeblondQuoted 2 lines · Eric Leblond
This patch adds support for position attribute which can be used to insert a rule at a given position.
Applied, thanks.
PATCH 1/1 Add support for insertion inside rule list
In reply to Eric LeblondThis patch adds support for "insert before" and "add after" rule operation.
The rule handle syntax has an new optional after/before field which take a handle as argument.
Here is two examples:
nft add rule filter output after 5 ip daddr 1.2.3.1 drop nft insert rule filter output before 5 ip daddr 1.2.3.1 drop
--- include/rule.h | 2 ++ src/netlink.c | 2 ++ src/netlink_delinearize.c | 2 ++ src/parser.y | 22 ++++++++++++++++++++-- src/rule.c | 2 ++ src/scanner.l | 3 +++ 6 files changed, 31 insertions(+), 2 deletions(-)
include/rule.h +2 -0
@@ -13,6 +13,7 @@* @chain: chain name (chains and rules only) * @set: set name (sets only) * @handle: rule handle (rules only) +* @position: rule position (rules only) */ struct handle {uint32_t family;
@@ -20,6 +21,7 @@ struct handle {const char *chain;const char *set;uint64_t handle; +uint64_t position; };extern void handle_merge (struct handle *dst,const struct handle *src);
src/netlink.c +2 -0
@@ -105,6 +105,8 @@ struct nft_rule *alloc_nft_rule(const struct handle *h)nft_rule_attr_set_str (nlr,NFT_RULE_ATTR_CHAIN , h->chain);if (h->handle)nft_rule_attr_set_u64 (nlr,NFT_RULE_ATTR_HANDLE , h->handle); +if (h->position) +nft_rule_attr_set_u64 (nlr,NFT_RULE_ATTR_POSITION , h->position);return nlr; }
src/netlink_delinearize.c +2 -0
@@ -796,6 +796,8 @@ struct rule *netlink_delinearize_rule(struct netlink_ctx *ctx, h.table =xstrdup (nft_rule_attr_get_str (nlr,NFT_RULE_ATTR_TABLE )); h.chain =xstrdup (nft_rule_attr_get_str (nlr,NFT_RULE_ATTR_CHAIN )); h.handle =nft_rule_attr_get_u64 (nlr,NFT_RULE_ATTR_HANDLE ); +if (nft_rule_attr_is_set (nlr,NFT_RULE_ATTR_POSITION )) + h.position =nft_rule_attr_get_u64 (nlr,NFT_RULE_ATTR_POSITION ); pctx->rule =rule_alloc (&internal_location, &h); pctx->table =table_lookup (&h);
src/parser.y +20 -2
@@ -326,6 +326,9 @@ static void location_update(struct location *loc, struct location *rhs, int n) %token SNAT "snat" %token DNAT "dnat" +%token BEFORE "before" +%token AFTER "after" + %type <string> identifier string %destructor { xfree($$); } identifier string
@@ -339,7 +342,7 @@ static void location_update(struct location *loc, struct location *rhs, int n) %destructor { handle_free(&$$); } table_spec tables_spec chain_spec chain_identifier ruleid_spec %type <handle> set_spec set_identifier %destructor { handle_free(&$$); } set_spec set_identifier -%type <val> handle_spec family_spec +%type <val> handle_spec family_spec position_spec %type <table> table_block_alloc table_block %destructor { table_free($$); } table_block_alloc
@@ -842,10 +845,25 @@ handle_spec : /* empty */ } ; -ruleid_spec : chain_spec handle_spec +position_spec : /* empty */ + { + $$ = 0; + } + | BEFORE NUM + { + $$ = $2; + } + | AFTER NUM + { + $$ = $2; + } + ; + +ruleid_spec : chain_spec handle_spec position_spec { $$ = $1; $$.handle = $2; + $$.position = $3; } ;
src/rule.c +2 -0
@@ -41,6 +41,8 @@ void handle_merge(struct handle *dst, const struct handle *src) dst->set =xstrdup (src->set);if (dst->handle ==0 ) dst->handle = src->handle; +if (dst->position ==0 ) + dst->position = src->position; }struct set *set_alloc (const struct location *loc)
src/scanner.l +3 -0
@@ -249,6 +249,9 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr}) "flush" { return FLUSH; } "rename" { return RENAME; } +"before" { return BEFORE; } +"after" { return AFTER; } + "counter" { return COUNTER; } "packets" { return PACKETS; } "bytes" { return BYTES; }
Signature · 1 line
1.8.3.2
Pablo Neira Ayuso
maintainerRe: [nftables PATCH] Add support for insertion inside rule list
Hi Eric,
Quoted 7 lines · Eric Leblond
This patch adds support for "insert before" and "add after" rule operation.
The rule handle syntax has an new optional after/before field which take a handle as argument.
Here is two examples:
nft add rule filter output after 5 ip daddr 1.2.3.1 drop nft insert rule filter output before 5 ip daddr 1.2.3.1 drop
While testing this new feature, I noticed that the parser was accepting this:
nft add rule filter output after 5 ip daddr 1.2.3.1 drop nft insert rule filter output after 5 ip daddr 1.2.3.1 drop
Note that 'add' and 'insert' become semantically equivalent, which seems inconsistent to me.
While fixing it using the 'before' and 'after', I noticed that 'add' and 'insert' already tell us where to put the new rule, so 'after' and 'before' were repeating again what we want to do. I have reworked this patch to change this initial syntax:
nft add rule filter output position 5 ip daddr 1.2.3.1 drop nft insert rule filter output position 5 ip daddr 1.2.3.1 drop
We can support the after and before, but that would imply some extra evaluation after the parsing that would make the patch bigger. So I prefered to go the simpler solution.
Please, find the new patch attached. Thanks.
Quoted 1 line
From
f8afcae4af949c1f8c71fc4dbbffdbddbedb7adfMon Sep 17 00:00:00 2001
From: Eric Leblond <[email protected]>
Date: Sat, 6 Jul 2013 17:33:57 +0200
Subject: [PATCH] src: Add support for insertion inside rule list
This patch adds support to insert and to add rule using a rule handle as reference. The rule handle syntax has an new optional position field which take a handle as argument.
Two examples:
nft add rule filter output position 5 ip daddr 1.2.3.1 drop nft insert rule filter output position 5 ip daddr 1.2.3.1 drop
--- include/rule.h | 2 ++ src/mnl.c | 2 +- src/netlink.c | 2 ++ src/netlink_delinearize.c | 2 ++ src/parser.y | 17 +++++++++++++++-- src/rule.c | 2 ++ src/scanner.l | 2 ++ 7 files changed, 26 insertions(+), 3 deletions(-)
include/rule.h +2 -0
@@ -13,6 +13,7 @@* @chain: chain name (chains and rules only) * @set: set name (sets only) * @handle: rule handle (rules only) +* @position: rule position (rules only) */ struct handle {uint32_t family;
@@ -20,6 +21,7 @@ struct handle {const char *chain;const char *set;uint64_t handle; +uint64_t position; };extern void handle_merge (struct handle *dst,const struct handle *src);
src/mnl.c +1 -1
@@ -61,7 +61,7 @@ int mnl_nft_rule_add(struct mnl_socket *nf_sock, struct nft_rule *nlr, nlh =nft_table_nlmsg_build_hdr (buf,NFT_MSG_NEWRULE ,nft_rule_attr_get_u32 (nlr,NFT_RULE_ATTR_FAMILY ), -NLM_F_APPEND |NLM_F_ACK |NLM_F_CREATE , seq); + flags|NLM_F_ACK |NLM_F_CREATE , seq);nft_rule_nlmsg_build_payload (nlh, nlr);return mnl_talk (nf_sock, nlh, nlh->nlmsg_len,NULL ,NULL );
src/netlink.c +2 -0
@@ -105,6 +105,8 @@ struct nft_rule *alloc_nft_rule(const struct handle *h)nft_rule_attr_set_str (nlr,NFT_RULE_ATTR_CHAIN , h->chain);if (h->handle)nft_rule_attr_set_u64 (nlr,NFT_RULE_ATTR_HANDLE , h->handle); +if (h->position) +nft_rule_attr_set_u64 (nlr,NFT_RULE_ATTR_POSITION , h->position);return nlr; }
src/netlink_delinearize.c +2 -0
@@ -796,6 +796,8 @@ struct rule *netlink_delinearize_rule(struct netlink_ctx *ctx, h.table =xstrdup (nft_rule_attr_get_str (nlr,NFT_RULE_ATTR_TABLE )); h.chain =xstrdup (nft_rule_attr_get_str (nlr,NFT_RULE_ATTR_CHAIN )); h.handle =nft_rule_attr_get_u64 (nlr,NFT_RULE_ATTR_HANDLE ); +if (nft_rule_attr_is_set (nlr,NFT_RULE_ATTR_POSITION )) + h.position =nft_rule_attr_get_u64 (nlr,NFT_RULE_ATTR_POSITION ); pctx->rule =rule_alloc (&internal_location, &h); pctx->table =table_lookup (&h);
src/parser.y +15 -2
@@ -326,6 +326,8 @@ static void location_update(struct location *loc, struct location *rhs, int n) %token SNAT "snat" %token DNAT "dnat" +%token POSITION "position" + %type <string> identifier string %destructor { xfree($$); } identifier string
@@ -339,7 +341,7 @@ static void location_update(struct location *loc, struct location *rhs, int n) %destructor { handle_free(&$$); } table_spec tables_spec chain_spec chain_identifier ruleid_spec %type <handle> set_spec set_identifier %destructor { handle_free(&$$); } set_spec set_identifier -%type <val> handle_spec family_spec +%type <val> handle_spec family_spec position_spec %type <table> table_block_alloc table_block %destructor { table_free($$); } table_block_alloc
@@ -842,10 +844,21 @@ handle_spec : /* empty */ } ; -ruleid_spec : chain_spec handle_spec +position_spec : /* empty */ + { + $$ = 0; + } + | POSITION NUM + { + $$ = $2; + } + ; + +ruleid_spec : chain_spec handle_spec position_spec { $$ = $1; $$.handle = $2; + $$.position = $3; } ;
src/rule.c +2 -0
@@ -41,6 +41,8 @@ void handle_merge(struct handle *dst, const struct handle *src) dst->set =xstrdup (src->set);if (dst->handle ==0 ) dst->handle = src->handle; +if (dst->position ==0 ) + dst->position = src->position; }struct set *set_alloc (const struct location *loc)
src/scanner.l +2 -0
@@ -249,6 +249,8 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr}) "flush" { return FLUSH; } "rename" { return RENAME; } +"position" { return POSITION; } + "counter" { return COUNTER; } "packets" { return PACKETS; } "bytes" { return BYTES; }
Signature · 1 line
1.7.10.4
Re: [nftables PATCH] Add support for insertion inside rule list
Hello,
Quoted 11 lines · Pablo Neira Ayuso
Hi Eric,
Quoted 7 lines · Eric Leblond
This patch adds support for "insert before" and "add after" rule operation.
The rule handle syntax has an new optional after/before field which take a handle as argument.
Here is two examples:
nft add rule filter output after 5 ip daddr 1.2.3.1 drop nft insert rule filter output before 5 ip daddr 1.2.3.1 drop
Quoted 8 lines
While testing this new feature, I noticed that the parser was accepting this:
nft add rule filter output after 5 ip daddr 1.2.3.1 drop nft insert rule filter output after 5 ip daddr 1.2.3.1 drop
Note that 'add' and 'insert' become semantically equivalent, which seems inconsistent to me.
Yes, forgot to mention that.
Quoted 11 lines
While fixing it using the 'before' and 'after', I noticed that 'add' and 'insert' already tell us where to put the new rule, so 'after' and 'before' were repeating again what we want to do. I have reworked this patch to change this initial syntax:
nft add rule filter output position 5 ip daddr 1.2.3.1 drop nft insert rule filter output position 5 ip daddr 1.2.3.1 drop
We can support the after and before, but that would imply some extra evaluation after the parsing that would make the patch bigger. So I prefered to go the simpler solution.
I agree with the following modification. I did not find better than this so, it is ok for me :)
Patch tested. It works well.
BR,
--
Eric
Pablo Neira Ayuso
maintainerRe: [nftables PATCH] Add support for insertion inside rule list
On Fri, Jul 19, 2013 at 04:31:27PM +0200, Eric Leblond wrote:
[...]
Quoted 8 lines
Quoted 8 lines
While fixing it using the 'before' and 'after', I noticed that 'add' and 'insert' already tell us where to put the new rule, so 'after' and 'before' were repeating again what we want to do. I have reworked this patch to change this initial syntax:
nft add rule filter output position 5 ip daddr 1.2.3.1 drop nft insert rule filter output position 5 ip daddr 1.2.3.1 drop
Quoted 8 lines
Quoted 3 lines
We can support the after and before, but that would imply some extra evaluation after the parsing that would make the patch bigger. So I prefered to go the simpler solution.
I agree with the following modification. I did not find better than this so, it is ok for me :)
Patch tested. It works well.
I have applied this patch, thanks for testing.
Re: [RFC PATCHv2] netfilter: nf_tables: add insert operation
In reply to Eric LeblondHi Eric,
There is 2 long lines it seems,
net/netfilter/nf_tables_api.c static int nf_tables_fill_rule_info(struct sk_buff *skb, u32 portid, u32 seq, · line 1304
Quoted 2 lines
net/netfilter/nf_tables_api.c +2
-0+if (nla_put_be64 (skb,NFTA_RULE_POSITION , +cpu_to_be64 (((struct nft_rule *)rule->list.prev)->handle)))
Here,
net/netfilter/nf_tables_api.c static int nf_tables_fill_rule_info(struct sk_buff *skb, u32 portid, u32 seq, · line 1308
Quoted 4 lines
net/netfilter/nf_tables_api.c +4
-0+ goto nla_put_failure; + }else if (rule->list.next) { +if (nla_put_be64 (skb,NFTA_RULE_POSITION , +cpu_to_be64 (((struct nft_rule *)rule->list.next)->handle)))
and there.
Tomasz