aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/fib_rules.c
diff options
context:
space:
mode:
authorIdo Schimmel <idosch@mellanox.com>2017-03-16 09:08:14 +0100
committerDavid S. Miller <davem@davemloft.net>2017-03-16 10:18:34 -0700
commit5d7bfd141924a5ece21eb612ad3c56612f041c1e (patch)
tree8c50f41a25f577b34c7bf6150a4f922ddf12bb18 /net/ipv4/fib_rules.c
parentipv4: fib_rules: Add notifier info to FIB rules notifications (diff)
downloadlinux-dev-5d7bfd141924a5ece21eb612ad3c56612f041c1e.tar.xz
linux-dev-5d7bfd141924a5ece21eb612ad3c56612f041c1e.zip
ipv4: fib_rules: Dump FIB rules when registering FIB notifier
In commit c3852ef7f2f8 ("ipv4: fib: Replay events when registering FIB notifier") we dumped the FIB tables and replayed the events to the passed notification block. However, we merely sent a RULE_ADD notification in case custom rules were in use. As explained in previous patches, this approach won't work anymore. Instead, we should notify the caller about all the FIB rules and let it act accordingly. Upon registration to the FIB notification chain, replay a RULE_ADD notification for each programmed FIB rule, custom or not. The integrity of the dump is ensured by the mechanism introduced in the above mentioned commit. Prevent regressions by making sure current listeners correctly sanitize the notified rules. Signed-off-by: Ido Schimmel <idosch@mellanox.com> Signed-off-by: Jiri Pirko <jiri@mellanox.com> Acked-by: David Ahern <dsa@cumulusnetworks.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to '')
-rw-r--r--net/ipv4/fib_rules.c19
1 files changed, 16 insertions, 3 deletions
diff --git a/net/ipv4/fib_rules.c b/net/ipv4/fib_rules.c
index 310d24a2e097..778ecf977eb2 100644
--- a/net/ipv4/fib_rules.c
+++ b/net/ipv4/fib_rules.c
@@ -185,6 +185,17 @@ static struct fib_table *fib_empty_table(struct net *net)
return NULL;
}
+static int call_fib_rule_notifier(struct notifier_block *nb, struct net *net,
+ enum fib_event_type event_type,
+ struct fib_rule *rule)
+{
+ struct fib_rule_notifier_info info = {
+ .rule = rule,
+ };
+
+ return call_fib_notifier(nb, net, event_type, &info.info);
+}
+
static int call_fib_rule_notifiers(struct net *net,
enum fib_event_type event_type,
struct fib_rule *rule)
@@ -196,12 +207,14 @@ static int call_fib_rule_notifiers(struct net *net,
return call_fib_notifiers(net, event_type, &info.info);
}
+/* Called with rcu_read_lock() */
void fib_rules_notify(struct net *net, struct notifier_block *nb)
{
- struct fib_notifier_info info;
+ struct fib_rules_ops *ops = net->ipv4.rules_ops;
+ struct fib_rule *rule;
- if (net->ipv4.fib_has_custom_rules)
- call_fib_notifier(nb, net, FIB_EVENT_RULE_ADD, &info);
+ list_for_each_entry_rcu(rule, &ops->rules_list, list)
+ call_fib_rule_notifier(nb, net, FIB_EVENT_RULE_ADD, rule);
}
static const struct nla_policy fib4_rule_policy[FRA_MAX+1] = {