aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Tomanek <stefan.tomanek@wertarbyte.de>2013-08-02 11:19:56 -0400
committerDavid S. Miller <davem@davemloft.net>2013-08-02 18:24:22 -0400
commit6ef94cfafba159d6b1a902ccb3349ac6a34ff6ad (patch)
treef2d7afebf4534ea50273165f4b0798aed704a37c
parentd1c53c8e870cdedb6fc9550f41c558bab45b5219 (diff)
fib_rules: add route suppression based on ifgroup
This change adds the ability to suppress a routing decision based upon the interface group the selected interface belongs to. This allows it to exclude specific devices from a routing decision. Signed-off-by: Stefan Tomanek <stefan.tomanek@wertarbyte.de> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/net/fib_rules.h2
-rw-r--r--include/uapi/linux/fib_rules.h2
-rw-r--r--net/core/fib_rules.c10
-rw-r--r--net/ipv4/fib_rules.c23
-rw-r--r--net/ipv6/fib6_rules.c16
5 files changed, 43 insertions, 10 deletions
diff --git a/include/net/fib_rules.h b/include/net/fib_rules.h
index 2f286dce9259..d13c461b4b59 100644
--- a/include/net/fib_rules.h
+++ b/include/net/fib_rules.h
@@ -18,6 +18,7 @@ struct fib_rule {
18 u32 pref; 18 u32 pref;
19 u32 flags; 19 u32 flags;
20 u32 table; 20 u32 table;
21 int suppress_ifgroup;
21 u8 table_prefixlen_min; 22 u8 table_prefixlen_min;
22 u8 action; 23 u8 action;
23 u32 target; 24 u32 target;
@@ -84,6 +85,7 @@ struct fib_rules_ops {
84 [FRA_FWMASK] = { .type = NLA_U32 }, \ 85 [FRA_FWMASK] = { .type = NLA_U32 }, \
85 [FRA_TABLE] = { .type = NLA_U32 }, \ 86 [FRA_TABLE] = { .type = NLA_U32 }, \
86 [FRA_TABLE_PREFIXLEN_MIN] = { .type = NLA_U8 }, \ 87 [FRA_TABLE_PREFIXLEN_MIN] = { .type = NLA_U8 }, \
88 [FRA_SUPPRESS_IFGROUP] = { .type = NLA_U32 }, \
87 [FRA_GOTO] = { .type = NLA_U32 } 89 [FRA_GOTO] = { .type = NLA_U32 }
88 90
89static inline void fib_rule_get(struct fib_rule *rule) 91static inline void fib_rule_get(struct fib_rule *rule)
diff --git a/include/uapi/linux/fib_rules.h b/include/uapi/linux/fib_rules.h
index 59cd31b3455e..63e31166e85b 100644
--- a/include/uapi/linux/fib_rules.h
+++ b/include/uapi/linux/fib_rules.h
@@ -44,7 +44,7 @@ enum {
44 FRA_FWMARK, /* mark */ 44 FRA_FWMARK, /* mark */
45 FRA_FLOW, /* flow/class id */ 45 FRA_FLOW, /* flow/class id */
46 FRA_UNUSED6, 46 FRA_UNUSED6,
47 FRA_UNUSED7, 47 FRA_SUPPRESS_IFGROUP,
48 FRA_TABLE_PREFIXLEN_MIN, 48 FRA_TABLE_PREFIXLEN_MIN,
49 FRA_TABLE, /* Extended table id */ 49 FRA_TABLE, /* Extended table id */
50 FRA_FWMASK, /* mask for netfilter mark */ 50 FRA_FWMASK, /* mask for netfilter mark */
diff --git a/net/core/fib_rules.c b/net/core/fib_rules.c
index 2ef5040c99c8..5040a61bf28a 100644
--- a/net/core/fib_rules.c
+++ b/net/core/fib_rules.c
@@ -343,6 +343,9 @@ static int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr* nlh)
343 if (tb[FRA_TABLE_PREFIXLEN_MIN]) 343 if (tb[FRA_TABLE_PREFIXLEN_MIN])
344 rule->table_prefixlen_min = nla_get_u8(tb[FRA_TABLE_PREFIXLEN_MIN]); 344 rule->table_prefixlen_min = nla_get_u8(tb[FRA_TABLE_PREFIXLEN_MIN]);
345 345
346 if (tb[FRA_SUPPRESS_IFGROUP])
347 rule->suppress_ifgroup = nla_get_u32(tb[FRA_SUPPRESS_IFGROUP]);
348
346 if (!tb[FRA_PRIORITY] && ops->default_pref) 349 if (!tb[FRA_PRIORITY] && ops->default_pref)
347 rule->pref = ops->default_pref(ops); 350 rule->pref = ops->default_pref(ops);
348 351
@@ -529,6 +532,7 @@ static inline size_t fib_rule_nlmsg_size(struct fib_rules_ops *ops,
529 + nla_total_size(4) /* FRA_PRIORITY */ 532 + nla_total_size(4) /* FRA_PRIORITY */
530 + nla_total_size(4) /* FRA_TABLE */ 533 + nla_total_size(4) /* FRA_TABLE */
531 + nla_total_size(1) /* FRA_TABLE_PREFIXLEN_MIN */ 534 + nla_total_size(1) /* FRA_TABLE_PREFIXLEN_MIN */
535 + nla_total_size(4) /* FRA_SUPPRESS_IFGROUP */
532 + nla_total_size(4) /* FRA_FWMARK */ 536 + nla_total_size(4) /* FRA_FWMARK */
533 + nla_total_size(4); /* FRA_FWMASK */ 537 + nla_total_size(4); /* FRA_FWMASK */
534 538
@@ -588,6 +592,12 @@ static int fib_nl_fill_rule(struct sk_buff *skb, struct fib_rule *rule,
588 (rule->target && 592 (rule->target &&
589 nla_put_u32(skb, FRA_GOTO, rule->target))) 593 nla_put_u32(skb, FRA_GOTO, rule->target)))
590 goto nla_put_failure; 594 goto nla_put_failure;
595
596 if (rule->suppress_ifgroup != -1) {
597 if (nla_put_u32(skb, FRA_SUPPRESS_IFGROUP, rule->suppress_ifgroup))
598 goto nla_put_failure;
599 }
600
591 if (ops->fill(rule, skb, frh) < 0) 601 if (ops->fill(rule, skb, frh) < 0)
592 goto nla_put_failure; 602 goto nla_put_failure;
593 603
diff --git a/net/ipv4/fib_rules.c b/net/ipv4/fib_rules.c
index 9f2906679d1f..b78fd28970c9 100644
--- a/net/ipv4/fib_rules.c
+++ b/net/ipv4/fib_rules.c
@@ -103,16 +103,27 @@ errout:
103 103
104static bool fib4_rule_suppress(struct fib_rule *rule, struct fib_lookup_arg *arg) 104static bool fib4_rule_suppress(struct fib_rule *rule, struct fib_lookup_arg *arg)
105{ 105{
106 struct fib_result *result = (struct fib_result *) arg->result;
107 struct net_device *dev = result->fi->fib_dev;
108
106 /* do not accept result if the route does 109 /* do not accept result if the route does
107 * not meet the required prefix length 110 * not meet the required prefix length
108 */ 111 */
109 struct fib_result *result = (struct fib_result *) arg->result; 112 if (result->prefixlen < rule->table_prefixlen_min)
110 if (result->prefixlen < rule->table_prefixlen_min) { 113 goto suppress_route;
111 if (!(arg->flags & FIB_LOOKUP_NOREF)) 114
112 fib_info_put(result->fi); 115 /* do not accept result if the route uses a device
113 return true; 116 * belonging to a forbidden interface group
114 } 117 */
118 if (rule->suppress_ifgroup != -1 && dev && dev->group == rule->suppress_ifgroup)
119 goto suppress_route;
120
115 return false; 121 return false;
122
123suppress_route:
124 if (!(arg->flags & FIB_LOOKUP_NOREF))
125 fib_info_put(result->fi);
126 return true;
116} 127}
117 128
118static int fib4_rule_match(struct fib_rule *rule, struct flowi *fl, int flags) 129static int fib4_rule_match(struct fib_rule *rule, struct flowi *fl, int flags)
diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c
index 554a4fbabfb3..36283267e2f8 100644
--- a/net/ipv6/fib6_rules.c
+++ b/net/ipv6/fib6_rules.c
@@ -122,14 +122,24 @@ out:
122static bool fib6_rule_suppress(struct fib_rule *rule, struct fib_lookup_arg *arg) 122static bool fib6_rule_suppress(struct fib_rule *rule, struct fib_lookup_arg *arg)
123{ 123{
124 struct rt6_info *rt = (struct rt6_info *) arg->result; 124 struct rt6_info *rt = (struct rt6_info *) arg->result;
125 struct net_device *dev = rt->rt6i_idev->dev;
125 /* do not accept result if the route does 126 /* do not accept result if the route does
126 * not meet the required prefix length 127 * not meet the required prefix length
127 */ 128 */
128 if (rt->rt6i_dst.plen < rule->table_prefixlen_min) { 129 if (rt->rt6i_dst.plen < rule->table_prefixlen_min)
130 goto suppress_route;
131
132 /* do not accept result if the route uses a device
133 * belonging to a forbidden interface group
134 */
135 if (rule->suppress_ifgroup != -1 && dev && dev->group == rule->suppress_ifgroup)
136 goto suppress_route;
137
138 return false;
139
140suppress_route:
129 ip6_rt_put(rt); 141 ip6_rt_put(rt);
130 return true; 142 return true;
131 }
132 return false;
133} 143}
134 144
135static int fib6_rule_match(struct fib_rule *rule, struct flowi *fl, int flags) 145static int fib6_rule_match(struct fib_rule *rule, struct flowi *fl, int flags)