]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blobdiff - net/ipv4/fib_rules.c
Merge branch 'core-rcu-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
[mirror_ubuntu-artful-kernel.git] / net / ipv4 / fib_rules.c
index d3db718be51d17282becc0864d050adfcc77522f..56151982f74efb26dab4abad429f473ba8b06cba 100644 (file)
@@ -153,7 +153,7 @@ static struct fib_table *fib_empty_table(struct net *net)
        u32 id;
 
        for (id = 1; id <= RT_TABLE_MAX; id++)
-               if (fib_get_table(net, id) == NULL)
+               if (!fib_get_table(net, id))
                        return fib_new_table(net, id);
        return NULL;
 }
@@ -174,12 +174,17 @@ static int fib4_rule_configure(struct fib_rule *rule, struct sk_buff *skb,
        if (frh->tos & ~IPTOS_TOS_MASK)
                goto errout;
 
+       /* split local/main if they are not already split */
+       err = fib_unmerge(net);
+       if (err)
+               goto errout;
+
        if (rule->table == RT_TABLE_UNSPEC) {
                if (rule->action == FR_ACT_TO_TBL) {
                        struct fib_table *table;
 
                        table = fib_empty_table(net);
-                       if (table == NULL) {
+                       if (!table) {
                                err = -ENOBUFS;
                                goto errout;
                        }
@@ -189,10 +194,10 @@ static int fib4_rule_configure(struct fib_rule *rule, struct sk_buff *skb,
        }
 
        if (frh->src_len)
-               rule4->src = nla_get_be32(tb[FRA_SRC]);
+               rule4->src = nla_get_in_addr(tb[FRA_SRC]);
 
        if (frh->dst_len)
-               rule4->dst = nla_get_be32(tb[FRA_DST]);
+               rule4->dst = nla_get_in_addr(tb[FRA_DST]);
 
 #ifdef CONFIG_IP_ROUTE_CLASSID
        if (tb[FRA_FLOW]) {
@@ -209,21 +214,31 @@ static int fib4_rule_configure(struct fib_rule *rule, struct sk_buff *skb,
        rule4->tos = frh->tos;
 
        net->ipv4.fib_has_custom_rules = true;
+       fib_flush_external(rule->fr_net);
+
        err = 0;
 errout:
        return err;
 }
 
-static void fib4_rule_delete(struct fib_rule *rule)
+static int fib4_rule_delete(struct fib_rule *rule)
 {
        struct net *net = rule->fr_net;
-#ifdef CONFIG_IP_ROUTE_CLASSID
-       struct fib4_rule *rule4 = (struct fib4_rule *) rule;
+       int err;
 
-       if (rule4->tclassid)
+       /* split local/main if they are not already split */
+       err = fib_unmerge(net);
+       if (err)
+               goto errout;
+
+#ifdef CONFIG_IP_ROUTE_CLASSID
+       if (((struct fib4_rule *)rule)->tclassid)
                net->ipv4.fib_num_tclassid_users--;
 #endif
        net->ipv4.fib_has_custom_rules = true;
+       fib_flush_external(rule->fr_net);
+errout:
+       return err;
 }
 
 static int fib4_rule_compare(struct fib_rule *rule, struct fib_rule_hdr *frh,
@@ -245,10 +260,10 @@ static int fib4_rule_compare(struct fib_rule *rule, struct fib_rule_hdr *frh,
                return 0;
 #endif
 
-       if (frh->src_len && (rule4->src != nla_get_be32(tb[FRA_SRC])))
+       if (frh->src_len && (rule4->src != nla_get_in_addr(tb[FRA_SRC])))
                return 0;
 
-       if (frh->dst_len && (rule4->dst != nla_get_be32(tb[FRA_DST])))
+       if (frh->dst_len && (rule4->dst != nla_get_in_addr(tb[FRA_DST])))
                return 0;
 
        return 1;
@@ -264,9 +279,9 @@ static int fib4_rule_fill(struct fib_rule *rule, struct sk_buff *skb,
        frh->tos = rule4->tos;
 
        if ((rule4->dst_len &&
-            nla_put_be32(skb, FRA_DST, rule4->dst)) ||
+            nla_put_in_addr(skb, FRA_DST, rule4->dst)) ||
            (rule4->src_len &&
-            nla_put_be32(skb, FRA_SRC, rule4->src)))
+            nla_put_in_addr(skb, FRA_SRC, rule4->src)))
                goto nla_put_failure;
 #ifdef CONFIG_IP_ROUTE_CLASSID
        if (rule4->tclassid &&