Patchwork [11/11] netfilter: nf_tables: include NLM_F_APPEND/NLM_F_REPLACE flags in rule notification

login
register
mail settings
Submitter Patrick McHardy
Date Dec. 12, 2012, 6:47 p.m.
Message ID <1355338061-5517-12-git-send-email-kaber@trash.net>
Download mbox | patch
Permalink /patch/205621/
State Accepted
Headers show

Comments

Patrick McHardy - Dec. 12, 2012, 6:47 p.m.
From: Patrick McHardy <kaber@trash.net>

Since the ruleset is ordered, userspace needs to know about NLM_F_APPEND to
properly interpret a NEWRULE message. In case of replacement we usually don't
send a DELX+NEWX message but a NEWX message with the NLM_F_REPLACE flag.

Signed-off-by: Patrick McHardy <kaber@trash.net>
---
 net/netfilter/nf_tables_api.c | 21 ++++++++++-----------
 1 Datei geändert, 10 Zeilen hinzugefügt(+), 11 Zeilen entfernt(-)

Patch

diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
index bbd463e..c4e4baa 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -1126,7 +1126,7 @@  static const struct nla_policy nft_rule_policy[NFTA_RULE_MAX + 1] = {
 };
 
 static int nf_tables_fill_rule_info(struct sk_buff *skb, u32 portid, u32 seq,
-				    int event, int family,
+				    int event, u32 flags, int family,
 				    const struct nft_table *table,
 				    const struct nft_chain *chain,
 				    const struct nft_rule *rule)
@@ -1137,7 +1137,8 @@  static int nf_tables_fill_rule_info(struct sk_buff *skb, u32 portid, u32 seq,
 	struct nlattr *list;
 
 	event |= NFNL_SUBSYS_NFTABLES << 8;
-	nlh = nlmsg_put(skb, portid, seq, event, sizeof(struct nfgenmsg), 0);
+	nlh = nlmsg_put(skb, portid, seq, event, sizeof(struct nfgenmsg),
+			flags);
 	if (nlh == NULL)
 		goto nla_put_failure;
 	nlh->nlmsg_flags	= portid ? NLM_F_MULTI : 0;
@@ -1179,7 +1180,7 @@  static int nf_tables_rule_notify(const struct sk_buff *oskb,
 				 const struct nft_table *table,
 				 const struct nft_chain *chain,
 				 const struct nft_rule *rule,
-				 int event, int family)
+				 int event, u32 flags, int family)
 {
 	struct sk_buff *skb;
 	u32 portid = NETLINK_CB(oskb).portid;
@@ -1197,7 +1198,7 @@  static int nf_tables_rule_notify(const struct sk_buff *oskb,
 	if (skb == NULL)
 		goto err;
 
-	err = nf_tables_fill_rule_info(skb, portid, seq, event,
+	err = nf_tables_fill_rule_info(skb, portid, seq, event, flags,
 				       family, table, chain, rule);
 	if (err < 0) {
 		kfree_skb(skb);
@@ -1237,7 +1238,7 @@  static int nf_tables_dump_rules(struct sk_buff *skb,
 						       sizeof(cb->args) - sizeof(cb->args[0]));
 					if (nf_tables_fill_rule_info(skb, NETLINK_CB(cb->skb).portid,
 								      cb->nlh->nlmsg_seq,
-								      NFT_MSG_NEWRULE,
+								      NFT_MSG_NEWRULE, 0,
 								      afi->family, table, chain, rule) < 0)
 						goto done;
 cont:
@@ -1292,7 +1293,7 @@  static int nf_tables_getrule(struct sock *nlsk, struct sk_buff *skb,
 		return -ENOMEM;
 
 	err = nf_tables_fill_rule_info(skb2, NETLINK_CB(skb).portid,
-				       nlh->nlmsg_seq, NFT_MSG_NEWRULE,
+				       nlh->nlmsg_seq, NFT_MSG_NEWRULE, 0,
 				       family, table, chain, rule);
 	if (err < 0)
 		goto err;
@@ -1415,9 +1416,6 @@  static int nf_tables_newrule(struct sock *nlsk, struct sk_buff *skb,
 
 	if (nlh->nlmsg_flags & NLM_F_REPLACE) {
 		list_replace_rcu(&old_rule->list, &rule->list);
-
-		nf_tables_rule_notify(skb, nlh, table, chain, old_rule,
-				      NFT_MSG_DELRULE, nfmsg->nfgen_family);
 		nf_tables_rule_destroy(old_rule);
 	} else if (nlh->nlmsg_flags & NLM_F_APPEND)
 		list_add_tail_rcu(&rule->list, &chain->rules);
@@ -1425,6 +1423,7 @@  static int nf_tables_newrule(struct sock *nlsk, struct sk_buff *skb,
 		list_add_rcu(&rule->list, &chain->rules);
 
 	nf_tables_rule_notify(skb, nlh, table, chain, rule, NFT_MSG_NEWRULE,
+			      nlh->nlmsg_flags & (NLM_F_APPEND | NLM_F_REPLACE),
 			      nfmsg->nfgen_family);
 	return 0;
 
@@ -1470,7 +1469,7 @@  static int nf_tables_delrule(struct sock *nlsk, struct sk_buff *skb,
 		list_del_rcu(&rule->list);
 
 		nf_tables_rule_notify(skb, nlh, table, chain, rule,
-				      NFT_MSG_DELRULE, family);
+				      NFT_MSG_DELRULE, 0, family);
 		nf_tables_rule_destroy(rule);
 	} else {
 		/* Remove all rules in this chain */
@@ -1478,7 +1477,7 @@  static int nf_tables_delrule(struct sock *nlsk, struct sk_buff *skb,
 			list_del_rcu(&rule->list);
 
 			nf_tables_rule_notify(skb, nlh, table, chain, rule,
-					      NFT_MSG_DELRULE, family);
+					      NFT_MSG_DELRULE, 0, family);
 			nf_tables_rule_destroy(rule);
 		}
 	}