|
@@ -16,6 +16,7 @@
|
|
|
#include <net/net_namespace.h>
|
|
|
#include <net/sock.h>
|
|
|
#include <net/fib_rules.h>
|
|
|
+#include <net/ip_tunnels.h>
|
|
|
|
|
|
int fib_default_rule_add(struct fib_rules_ops *ops,
|
|
|
u32 pref, u32 table, u32 flags)
|
|
@@ -186,6 +187,9 @@ static int fib_rule_match(struct fib_rule *rule, struct fib_rules_ops *ops,
|
|
|
if ((rule->mark ^ fl->flowi_mark) & rule->mark_mask)
|
|
|
goto out;
|
|
|
|
|
|
+ if (rule->tun_id && (rule->tun_id != fl->flowi_tun_key.tun_id))
|
|
|
+ goto out;
|
|
|
+
|
|
|
ret = ops->match(rule, fl, flags);
|
|
|
out:
|
|
|
return (rule->flags & FIB_RULE_INVERT) ? !ret : ret;
|
|
@@ -330,6 +334,9 @@ static int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr* nlh)
|
|
|
if (tb[FRA_FWMASK])
|
|
|
rule->mark_mask = nla_get_u32(tb[FRA_FWMASK]);
|
|
|
|
|
|
+ if (tb[FRA_TUN_ID])
|
|
|
+ rule->tun_id = nla_get_be64(tb[FRA_TUN_ID]);
|
|
|
+
|
|
|
rule->action = frh->action;
|
|
|
rule->flags = frh->flags;
|
|
|
rule->table = frh_get_table(frh, tb);
|
|
@@ -407,6 +414,9 @@ static int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr* nlh)
|
|
|
if (unresolved)
|
|
|
ops->unresolved_rules++;
|
|
|
|
|
|
+ if (rule->tun_id)
|
|
|
+ ip_tunnel_need_metadata();
|
|
|
+
|
|
|
notify_rule_change(RTM_NEWRULE, rule, ops, nlh, NETLINK_CB(skb).portid);
|
|
|
flush_route_cache(ops);
|
|
|
rules_ops_put(ops);
|
|
@@ -473,6 +483,10 @@ static int fib_nl_delrule(struct sk_buff *skb, struct nlmsghdr* nlh)
|
|
|
(rule->mark_mask != nla_get_u32(tb[FRA_FWMASK])))
|
|
|
continue;
|
|
|
|
|
|
+ if (tb[FRA_TUN_ID] &&
|
|
|
+ (rule->tun_id != nla_get_be64(tb[FRA_TUN_ID])))
|
|
|
+ continue;
|
|
|
+
|
|
|
if (!ops->compare(rule, frh, tb))
|
|
|
continue;
|
|
|
|
|
@@ -487,6 +501,9 @@ static int fib_nl_delrule(struct sk_buff *skb, struct nlmsghdr* nlh)
|
|
|
goto errout;
|
|
|
}
|
|
|
|
|
|
+ if (rule->tun_id)
|
|
|
+ ip_tunnel_unneed_metadata();
|
|
|
+
|
|
|
list_del_rcu(&rule->list);
|
|
|
|
|
|
if (rule->action == FR_ACT_GOTO) {
|
|
@@ -535,7 +552,8 @@ static inline size_t fib_rule_nlmsg_size(struct fib_rules_ops *ops,
|
|
|
+ nla_total_size(4) /* FRA_SUPPRESS_PREFIXLEN */
|
|
|
+ nla_total_size(4) /* FRA_SUPPRESS_IFGROUP */
|
|
|
+ nla_total_size(4) /* FRA_FWMARK */
|
|
|
- + nla_total_size(4); /* FRA_FWMASK */
|
|
|
+ + nla_total_size(4) /* FRA_FWMASK */
|
|
|
+ + nla_total_size(8); /* FRA_TUN_ID */
|
|
|
|
|
|
if (ops->nlmsg_payload)
|
|
|
payload += ops->nlmsg_payload(rule);
|
|
@@ -591,7 +609,9 @@ static int fib_nl_fill_rule(struct sk_buff *skb, struct fib_rule *rule,
|
|
|
((rule->mark_mask || rule->mark) &&
|
|
|
nla_put_u32(skb, FRA_FWMASK, rule->mark_mask)) ||
|
|
|
(rule->target &&
|
|
|
- nla_put_u32(skb, FRA_GOTO, rule->target)))
|
|
|
+ nla_put_u32(skb, FRA_GOTO, rule->target)) ||
|
|
|
+ (rule->tun_id &&
|
|
|
+ nla_put_be64(skb, FRA_TUN_ID, rule->tun_id)))
|
|
|
goto nla_put_failure;
|
|
|
|
|
|
if (rule->suppress_ifgroup != -1) {
|