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) |
