diff options
author | Stefan Tomanek <stefan.tomanek@wertarbyte.de> | 2013-08-02 11:19:56 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-08-02 18:24:22 -0400 |
commit | 6ef94cfafba159d6b1a902ccb3349ac6a34ff6ad (patch) | |
tree | f2d7afebf4534ea50273165f4b0798aed704a37c | |
parent | d1c53c8e870cdedb6fc9550f41c558bab45b5219 (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.h | 2 | ||||
-rw-r--r-- | include/uapi/linux/fib_rules.h | 2 | ||||
-rw-r--r-- | net/core/fib_rules.c | 10 | ||||
-rw-r--r-- | net/ipv4/fib_rules.c | 23 | ||||
-rw-r--r-- | net/ipv6/fib6_rules.c | 16 |
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 | ||
89 | static inline void fib_rule_get(struct fib_rule *rule) | 91 | static 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 | ||
104 | static bool fib4_rule_suppress(struct fib_rule *rule, struct fib_lookup_arg *arg) | 104 | static 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 | |||
123 | suppress_route: | ||
124 | if (!(arg->flags & FIB_LOOKUP_NOREF)) | ||
125 | fib_info_put(result->fi); | ||
126 | return true; | ||
116 | } | 127 | } |
117 | 128 | ||
118 | static int fib4_rule_match(struct fib_rule *rule, struct flowi *fl, int flags) | 129 | static 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: | |||
122 | static bool fib6_rule_suppress(struct fib_rule *rule, struct fib_lookup_arg *arg) | 122 | static 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 | |||
140 | suppress_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 | ||
135 | static int fib6_rule_match(struct fib_rule *rule, struct flowi *fl, int flags) | 145 | static int fib6_rule_match(struct fib_rule *rule, struct flowi *fl, int flags) |