aboutsummaryrefslogtreecommitdiffstats
path: root/net/netfilter
diff options
context:
space:
mode:
authorEric Leblond <eric@regit.org>2013-10-10 07:41:44 -0400
committerPablo Neira Ayuso <pablo@netfilter.org>2013-10-14 12:01:00 -0400
commit5e94846686d027a4c8ecc5d9d52b18036d3e8f7a (patch)
tree46b3537f5307e673fc1746bed655e9bc5d6e72e4 /net/netfilter
parent99633ab29b2131b68089a6c7f60458390860e044 (diff)
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 the create command and specifying the position, the rule is inserted after the rule with the handle equal to the provided position. Regarding notification, the position attribute specifies the handle of the previous rule to make sure we don't point to any stale rule in notifications coming from the commit path. This patch includes the following fix from Pablo: * nf_tables: fix rule deletion event reporting Signed-off-by: Eric Leblond <eric@regit.org> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'net/netfilter')
-rw-r--r--net/netfilter/nf_tables_api.c38
1 files changed, 32 insertions, 6 deletions
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
index e1ee85047ec1..0f140663ec71 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -1273,6 +1273,7 @@ static const struct nla_policy nft_rule_policy[NFTA_RULE_MAX + 1] = {
1273 [NFTA_RULE_HANDLE] = { .type = NLA_U64 }, 1273 [NFTA_RULE_HANDLE] = { .type = NLA_U64 },
1274 [NFTA_RULE_EXPRESSIONS] = { .type = NLA_NESTED }, 1274 [NFTA_RULE_EXPRESSIONS] = { .type = NLA_NESTED },
1275 [NFTA_RULE_COMPAT] = { .type = NLA_NESTED }, 1275 [NFTA_RULE_COMPAT] = { .type = NLA_NESTED },
1276 [NFTA_RULE_POSITION] = { .type = NLA_U64 },
1276}; 1277};
1277 1278
1278static int nf_tables_fill_rule_info(struct sk_buff *skb, u32 portid, u32 seq, 1279static int nf_tables_fill_rule_info(struct sk_buff *skb, u32 portid, u32 seq,
@@ -1285,9 +1286,10 @@ static int nf_tables_fill_rule_info(struct sk_buff *skb, u32 portid, u32 seq,
1285 struct nfgenmsg *nfmsg; 1286 struct nfgenmsg *nfmsg;
1286 const struct nft_expr *expr, *next; 1287 const struct nft_expr *expr, *next;
1287 struct nlattr *list; 1288 struct nlattr *list;
1289 const struct nft_rule *prule;
1290 int type = event | NFNL_SUBSYS_NFTABLES << 8;
1288 1291
1289 event |= NFNL_SUBSYS_NFTABLES << 8; 1292 nlh = nlmsg_put(skb, portid, seq, type, sizeof(struct nfgenmsg),
1290 nlh = nlmsg_put(skb, portid, seq, event, sizeof(struct nfgenmsg),
1291 flags); 1293 flags);
1292 if (nlh == NULL) 1294 if (nlh == NULL)
1293 goto nla_put_failure; 1295 goto nla_put_failure;
@@ -1304,6 +1306,13 @@ static int nf_tables_fill_rule_info(struct sk_buff *skb, u32 portid, u32 seq,
1304 if (nla_put_be64(skb, NFTA_RULE_HANDLE, cpu_to_be64(rule->handle))) 1306 if (nla_put_be64(skb, NFTA_RULE_HANDLE, cpu_to_be64(rule->handle)))
1305 goto nla_put_failure; 1307 goto nla_put_failure;
1306 1308
1309 if ((event != NFT_MSG_DELRULE) && (rule->list.prev != &chain->rules)) {
1310 prule = list_entry(rule->list.prev, struct nft_rule, list);
1311 if (nla_put_be64(skb, NFTA_RULE_POSITION,
1312 cpu_to_be64(prule->handle)))
1313 goto nla_put_failure;
1314 }
1315
1307 list = nla_nest_start(skb, NFTA_RULE_EXPRESSIONS); 1316 list = nla_nest_start(skb, NFTA_RULE_EXPRESSIONS);
1308 if (list == NULL) 1317 if (list == NULL)
1309 goto nla_put_failure; 1318 goto nla_put_failure;
@@ -1499,7 +1508,7 @@ static int nf_tables_newrule(struct sock *nlsk, struct sk_buff *skb,
1499 unsigned int size, i, n; 1508 unsigned int size, i, n;
1500 int err, rem; 1509 int err, rem;
1501 bool create; 1510 bool create;
1502 u64 handle; 1511 u64 handle, pos_handle;
1503 1512
1504 create = nlh->nlmsg_flags & NLM_F_CREATE ? true : false; 1513 create = nlh->nlmsg_flags & NLM_F_CREATE ? true : false;
1505 1514
@@ -1533,6 +1542,16 @@ static int nf_tables_newrule(struct sock *nlsk, struct sk_buff *skb,
1533 handle = nf_tables_alloc_handle(table); 1542 handle = nf_tables_alloc_handle(table);
1534 } 1543 }
1535 1544
1545 if (nla[NFTA_RULE_POSITION]) {
1546 if (!(nlh->nlmsg_flags & NLM_F_CREATE))
1547 return -EOPNOTSUPP;
1548
1549 pos_handle = be64_to_cpu(nla_get_be64(nla[NFTA_RULE_POSITION]));
1550 old_rule = __nf_tables_rule_lookup(chain, pos_handle);
1551 if (IS_ERR(old_rule))
1552 return PTR_ERR(old_rule);
1553 }
1554
1536 nft_ctx_init(&ctx, skb, nlh, afi, table, chain, nla); 1555 nft_ctx_init(&ctx, skb, nlh, afi, table, chain, nla);
1537 1556
1538 n = 0; 1557 n = 0;
@@ -1573,9 +1592,16 @@ static int nf_tables_newrule(struct sock *nlsk, struct sk_buff *skb,
1573 list_replace_rcu(&old_rule->list, &rule->list); 1592 list_replace_rcu(&old_rule->list, &rule->list);
1574 nf_tables_rule_destroy(old_rule); 1593 nf_tables_rule_destroy(old_rule);
1575 } else if (nlh->nlmsg_flags & NLM_F_APPEND) 1594 } else if (nlh->nlmsg_flags & NLM_F_APPEND)
1576 list_add_tail_rcu(&rule->list, &chain->rules); 1595 if (old_rule)
1577 else 1596 list_add_rcu(&rule->list, &old_rule->list);
1578 list_add_rcu(&rule->list, &chain->rules); 1597 else
1598 list_add_tail_rcu(&rule->list, &chain->rules);
1599 else {
1600 if (old_rule)
1601 list_add_tail_rcu(&rule->list, &old_rule->list);
1602 else
1603 list_add_rcu(&rule->list, &chain->rules);
1604 }
1579 1605
1580 nf_tables_rule_notify(skb, nlh, table, chain, rule, NFT_MSG_NEWRULE, 1606 nf_tables_rule_notify(skb, nlh, table, chain, rule, NFT_MSG_NEWRULE,
1581 nlh->nlmsg_flags & (NLM_F_APPEND | NLM_F_REPLACE), 1607 nlh->nlmsg_flags & (NLM_F_APPEND | NLM_F_REPLACE),