aboutsummaryrefslogtreecommitdiffstats
path: root/net/core/fib_rules.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/core/fib_rules.c')
-rw-r--r--net/core/fib_rules.c14
1 files changed, 9 insertions, 5 deletions
diff --git a/net/core/fib_rules.c b/net/core/fib_rules.c
index e7ab0c0285b5..c02e63c908da 100644
--- a/net/core/fib_rules.c
+++ b/net/core/fib_rules.c
@@ -12,6 +12,7 @@
12#include <linux/kernel.h> 12#include <linux/kernel.h>
13#include <linux/slab.h> 13#include <linux/slab.h>
14#include <linux/list.h> 14#include <linux/list.h>
15#include <linux/module.h>
15#include <net/net_namespace.h> 16#include <net/net_namespace.h>
16#include <net/sock.h> 17#include <net/sock.h>
17#include <net/fib_rules.h> 18#include <net/fib_rules.h>
@@ -384,8 +385,8 @@ static int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
384 */ 385 */
385 list_for_each_entry(r, &ops->rules_list, list) { 386 list_for_each_entry(r, &ops->rules_list, list) {
386 if (r->action == FR_ACT_GOTO && 387 if (r->action == FR_ACT_GOTO &&
387 r->target == rule->pref) { 388 r->target == rule->pref &&
388 BUG_ON(rtnl_dereference(r->ctarget) != NULL); 389 rtnl_dereference(r->ctarget) == NULL) {
389 rcu_assign_pointer(r->ctarget, rule); 390 rcu_assign_pointer(r->ctarget, rule);
390 if (--ops->unresolved_rules == 0) 391 if (--ops->unresolved_rules == 0)
391 break; 392 break;
@@ -475,8 +476,11 @@ static int fib_nl_delrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
475 476
476 list_del_rcu(&rule->list); 477 list_del_rcu(&rule->list);
477 478
478 if (rule->action == FR_ACT_GOTO) 479 if (rule->action == FR_ACT_GOTO) {
479 ops->nr_goto_rules--; 480 ops->nr_goto_rules--;
481 if (rtnl_dereference(rule->ctarget) == NULL)
482 ops->unresolved_rules--;
483 }
480 484
481 /* 485 /*
482 * Check if this rule is a target to any of them. If so, 486 * Check if this rule is a target to any of them. If so,
@@ -487,7 +491,7 @@ static int fib_nl_delrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
487 if (ops->nr_goto_rules > 0) { 491 if (ops->nr_goto_rules > 0) {
488 list_for_each_entry(tmp, &ops->rules_list, list) { 492 list_for_each_entry(tmp, &ops->rules_list, list) {
489 if (rtnl_dereference(tmp->ctarget) == rule) { 493 if (rtnl_dereference(tmp->ctarget) == rule) {
490 rcu_assign_pointer(tmp->ctarget, NULL); 494 RCU_INIT_POINTER(tmp->ctarget, NULL);
491 ops->unresolved_rules++; 495 ops->unresolved_rules++;
492 } 496 }
493 } 497 }
@@ -545,7 +549,7 @@ static int fib_nl_fill_rule(struct sk_buff *skb, struct fib_rule *rule,
545 frh->flags = rule->flags; 549 frh->flags = rule->flags;
546 550
547 if (rule->action == FR_ACT_GOTO && 551 if (rule->action == FR_ACT_GOTO &&
548 rcu_dereference_raw(rule->ctarget) == NULL) 552 rcu_access_pointer(rule->ctarget) == NULL)
549 frh->flags |= FIB_RULE_UNRESOLVED; 553 frh->flags |= FIB_RULE_UNRESOLVED;
550 554
551 if (rule->iifname[0]) { 555 if (rule->iifname[0]) {