Commit 9e762a4a authored by Patrick McHardy's avatar Patrick McHardy Committed by David S. Miller

[NET]: Introduce RTA_TABLE/FRA_TABLE attributes

Introduce RTA_TABLE route attribute and FRA_TABLE routing rule attribute
to hold 32 bit routing table IDs. Usespace compatibility is provided by
continuing to accept and send the rtm_table field, but because of its
limited size it can only carry the low 8 bits of the table ID. This
implies that if larger IDs are used, _all_ userspace programs using them
need to use RTA_TABLE.
Signed-off-by: default avatarPatrick McHardy <kaber@trash.net>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 2dfe55b4
...@@ -36,6 +36,10 @@ enum ...@@ -36,6 +36,10 @@ enum
FRA_UNUSED5, FRA_UNUSED5,
FRA_FWMARK, /* netfilter mark (IPv4) */ FRA_FWMARK, /* netfilter mark (IPv4) */
FRA_FLOW, /* flow/class id */ FRA_FLOW, /* flow/class id */
FRA_UNUSED6,
FRA_UNUSED7,
FRA_UNUSED8,
FRA_TABLE, /* Extended table id */
__FRA_MAX __FRA_MAX
}; };
......
...@@ -264,6 +264,7 @@ enum rtattr_type_t ...@@ -264,6 +264,7 @@ enum rtattr_type_t
RTA_CACHEINFO, RTA_CACHEINFO,
RTA_SESSION, RTA_SESSION,
RTA_MP_ALGO, RTA_MP_ALGO,
RTA_TABLE,
__RTA_MAX __RTA_MAX
}; };
...@@ -717,6 +718,13 @@ extern void __rtnl_unlock(void); ...@@ -717,6 +718,13 @@ extern void __rtnl_unlock(void);
} \ } \
} while(0) } while(0)
static inline u32 rtm_get_table(struct rtattr **rta, u8 table)
{
return RTA_GET_U32(rta[RTA_TABLE-1]);
rtattr_failure:
return table;
}
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
......
...@@ -74,6 +74,13 @@ static inline void fib_rule_put(struct fib_rule *rule) ...@@ -74,6 +74,13 @@ static inline void fib_rule_put(struct fib_rule *rule)
call_rcu(&rule->rcu, fib_rule_put_rcu); call_rcu(&rule->rcu, fib_rule_put_rcu);
} }
static inline u32 frh_get_table(struct fib_rule_hdr *frh, struct nlattr **nla)
{
if (nla[FRA_TABLE])
return nla_get_u32(nla[FRA_TABLE]);
return frh->table;
}
extern int fib_rules_register(struct fib_rules_ops *); extern int fib_rules_register(struct fib_rules_ops *);
extern int fib_rules_unregister(struct fib_rules_ops *); extern int fib_rules_unregister(struct fib_rules_ops *);
......
...@@ -187,7 +187,7 @@ int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) ...@@ -187,7 +187,7 @@ int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
rule->action = frh->action; rule->action = frh->action;
rule->flags = frh->flags; rule->flags = frh->flags;
rule->table = frh->table; rule->table = frh_get_table(frh, tb);
if (!rule->pref && ops->default_pref) if (!rule->pref && ops->default_pref)
rule->pref = ops->default_pref(); rule->pref = ops->default_pref();
...@@ -245,7 +245,7 @@ int fib_nl_delrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) ...@@ -245,7 +245,7 @@ int fib_nl_delrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
if (frh->action && (frh->action != rule->action)) if (frh->action && (frh->action != rule->action))
continue; continue;
if (frh->table && (frh->table != rule->table)) if (frh->table && (frh_get_table(frh, tb) != rule->table))
continue; continue;
if (tb[FRA_PRIORITY] && if (tb[FRA_PRIORITY] &&
...@@ -291,6 +291,7 @@ static int fib_nl_fill_rule(struct sk_buff *skb, struct fib_rule *rule, ...@@ -291,6 +291,7 @@ static int fib_nl_fill_rule(struct sk_buff *skb, struct fib_rule *rule,
frh = nlmsg_data(nlh); frh = nlmsg_data(nlh);
frh->table = rule->table; frh->table = rule->table;
NLA_PUT_U32(skb, FRA_TABLE, rule->table);
frh->res1 = 0; frh->res1 = 0;
frh->res2 = 0; frh->res2 = 0;
frh->action = rule->action; frh->action = rule->action;
......
...@@ -491,7 +491,8 @@ static int dn_fib_check_attr(struct rtmsg *r, struct rtattr **rta) ...@@ -491,7 +491,8 @@ static int dn_fib_check_attr(struct rtmsg *r, struct rtattr **rta)
if (attr) { if (attr) {
if (RTA_PAYLOAD(attr) < 4 && RTA_PAYLOAD(attr) != 2) if (RTA_PAYLOAD(attr) < 4 && RTA_PAYLOAD(attr) != 2)
return -EINVAL; return -EINVAL;
if (i != RTA_MULTIPATH && i != RTA_METRICS) if (i != RTA_MULTIPATH && i != RTA_METRICS &&
i != RTA_TABLE)
rta[i-1] = (struct rtattr *)RTA_DATA(attr); rta[i-1] = (struct rtattr *)RTA_DATA(attr);
} }
} }
...@@ -508,7 +509,7 @@ int dn_fib_rtm_delroute(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) ...@@ -508,7 +509,7 @@ int dn_fib_rtm_delroute(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
if (dn_fib_check_attr(r, rta)) if (dn_fib_check_attr(r, rta))
return -EINVAL; return -EINVAL;
tb = dn_fib_get_table(r->rtm_table, 0); tb = dn_fib_get_table(rtm_get_table(rta, r->rtm_table), 0);
if (tb) if (tb)
return tb->delete(tb, r, (struct dn_kern_rta *)rta, nlh, &NETLINK_CB(skb)); return tb->delete(tb, r, (struct dn_kern_rta *)rta, nlh, &NETLINK_CB(skb));
...@@ -524,7 +525,7 @@ int dn_fib_rtm_newroute(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) ...@@ -524,7 +525,7 @@ int dn_fib_rtm_newroute(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
if (dn_fib_check_attr(r, rta)) if (dn_fib_check_attr(r, rta))
return -EINVAL; return -EINVAL;
tb = dn_fib_get_table(r->rtm_table, 1); tb = dn_fib_get_table(rtm_get_table(rta, r->rtm_table), 1);
if (tb) if (tb)
return tb->insert(tb, r, (struct dn_kern_rta *)rta, nlh, &NETLINK_CB(skb)); return tb->insert(tb, r, (struct dn_kern_rta *)rta, nlh, &NETLINK_CB(skb));
......
...@@ -1486,6 +1486,7 @@ static int dn_rt_fill_info(struct sk_buff *skb, u32 pid, u32 seq, ...@@ -1486,6 +1486,7 @@ static int dn_rt_fill_info(struct sk_buff *skb, u32 pid, u32 seq,
r->rtm_src_len = 0; r->rtm_src_len = 0;
r->rtm_tos = 0; r->rtm_tos = 0;
r->rtm_table = RT_TABLE_MAIN; r->rtm_table = RT_TABLE_MAIN;
RTA_PUT_U32(skb, RTA_TABLE, RT_TABLE_MAIN);
r->rtm_type = rt->rt_type; r->rtm_type = rt->rt_type;
r->rtm_flags = (rt->rt_flags & ~0xFFFF) | RTM_F_CLONED; r->rtm_flags = (rt->rt_flags & ~0xFFFF) | RTM_F_CLONED;
r->rtm_scope = RT_SCOPE_UNIVERSE; r->rtm_scope = RT_SCOPE_UNIVERSE;
......
...@@ -278,6 +278,7 @@ static int dn_fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event, ...@@ -278,6 +278,7 @@ static int dn_fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
rtm->rtm_src_len = 0; rtm->rtm_src_len = 0;
rtm->rtm_tos = 0; rtm->rtm_tos = 0;
rtm->rtm_table = tb_id; rtm->rtm_table = tb_id;
RTA_PUT_U32(skb, RTA_TABLE, tb_id);
rtm->rtm_flags = fi->fib_flags; rtm->rtm_flags = fi->fib_flags;
rtm->rtm_scope = scope; rtm->rtm_scope = scope;
rtm->rtm_type = type; rtm->rtm_type = type;
......
...@@ -294,7 +294,8 @@ static int inet_check_attr(struct rtmsg *r, struct rtattr **rta) ...@@ -294,7 +294,8 @@ static int inet_check_attr(struct rtmsg *r, struct rtattr **rta)
if (attr) { if (attr) {
if (RTA_PAYLOAD(attr) < 4) if (RTA_PAYLOAD(attr) < 4)
return -EINVAL; return -EINVAL;
if (i != RTA_MULTIPATH && i != RTA_METRICS) if (i != RTA_MULTIPATH && i != RTA_METRICS &&
i != RTA_TABLE)
*rta = (struct rtattr*)RTA_DATA(attr); *rta = (struct rtattr*)RTA_DATA(attr);
} }
} }
...@@ -310,7 +311,7 @@ int inet_rtm_delroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) ...@@ -310,7 +311,7 @@ int inet_rtm_delroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
if (inet_check_attr(r, rta)) if (inet_check_attr(r, rta))
return -EINVAL; return -EINVAL;
tb = fib_get_table(r->rtm_table); tb = fib_get_table(rtm_get_table(rta, r->rtm_table));
if (tb) if (tb)
return tb->tb_delete(tb, r, (struct kern_rta*)rta, nlh, &NETLINK_CB(skb)); return tb->tb_delete(tb, r, (struct kern_rta*)rta, nlh, &NETLINK_CB(skb));
return -ESRCH; return -ESRCH;
...@@ -325,7 +326,7 @@ int inet_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) ...@@ -325,7 +326,7 @@ int inet_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
if (inet_check_attr(r, rta)) if (inet_check_attr(r, rta))
return -EINVAL; return -EINVAL;
tb = fib_new_table(r->rtm_table); tb = fib_new_table(rtm_get_table(rta, r->rtm_table));
if (tb) if (tb)
return tb->tb_insert(tb, r, (struct kern_rta*)rta, nlh, &NETLINK_CB(skb)); return tb->tb_insert(tb, r, (struct kern_rta*)rta, nlh, &NETLINK_CB(skb));
return -ENOBUFS; return -ENOBUFS;
......
...@@ -184,6 +184,7 @@ static struct nla_policy fib4_rule_policy[FRA_MAX+1] __read_mostly = { ...@@ -184,6 +184,7 @@ static struct nla_policy fib4_rule_policy[FRA_MAX+1] __read_mostly = {
[FRA_DST] = { .type = NLA_U32 }, [FRA_DST] = { .type = NLA_U32 },
[FRA_FWMARK] = { .type = NLA_U32 }, [FRA_FWMARK] = { .type = NLA_U32 },
[FRA_FLOW] = { .type = NLA_U32 }, [FRA_FLOW] = { .type = NLA_U32 },
[FRA_TABLE] = { .type = NLA_U32 },
}; };
static int fib4_rule_configure(struct fib_rule *rule, struct sk_buff *skb, static int fib4_rule_configure(struct fib_rule *rule, struct sk_buff *skb,
......
...@@ -953,6 +953,7 @@ fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event, ...@@ -953,6 +953,7 @@ fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
rtm->rtm_src_len = 0; rtm->rtm_src_len = 0;
rtm->rtm_tos = tos; rtm->rtm_tos = tos;
rtm->rtm_table = tb_id; rtm->rtm_table = tb_id;
RTA_PUT_U32(skb, RTA_TABLE, tb_id);
rtm->rtm_type = type; rtm->rtm_type = type;
rtm->rtm_flags = fi->fib_flags; rtm->rtm_flags = fi->fib_flags;
rtm->rtm_scope = scope; rtm->rtm_scope = scope;
......
...@@ -2652,6 +2652,7 @@ static int rt_fill_info(struct sk_buff *skb, u32 pid, u32 seq, int event, ...@@ -2652,6 +2652,7 @@ static int rt_fill_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
r->rtm_src_len = 0; r->rtm_src_len = 0;
r->rtm_tos = rt->fl.fl4_tos; r->rtm_tos = rt->fl.fl4_tos;
r->rtm_table = RT_TABLE_MAIN; r->rtm_table = RT_TABLE_MAIN;
RTA_PUT_U32(skb, RTA_TABLE, RT_TABLE_MAIN);
r->rtm_type = rt->rt_type; r->rtm_type = rt->rt_type;
r->rtm_scope = RT_SCOPE_UNIVERSE; r->rtm_scope = RT_SCOPE_UNIVERSE;
r->rtm_protocol = RTPROT_UNSPEC; r->rtm_protocol = RTPROT_UNSPEC;
......
...@@ -129,6 +129,7 @@ static struct nla_policy fib6_rule_policy[RTA_MAX+1] __read_mostly = { ...@@ -129,6 +129,7 @@ static struct nla_policy fib6_rule_policy[RTA_MAX+1] __read_mostly = {
[FRA_PRIORITY] = { .type = NLA_U32 }, [FRA_PRIORITY] = { .type = NLA_U32 },
[FRA_SRC] = { .minlen = sizeof(struct in6_addr) }, [FRA_SRC] = { .minlen = sizeof(struct in6_addr) },
[FRA_DST] = { .minlen = sizeof(struct in6_addr) }, [FRA_DST] = { .minlen = sizeof(struct in6_addr) },
[FRA_TABLE] = { .type = NLA_U32 },
}; };
static int fib6_rule_configure(struct fib_rule *rule, struct sk_buff *skb, static int fib6_rule_configure(struct fib_rule *rule, struct sk_buff *skb,
......
...@@ -1859,7 +1859,8 @@ int inet6_rtm_delroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) ...@@ -1859,7 +1859,8 @@ int inet6_rtm_delroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
if (inet6_rtm_to_rtmsg(r, arg, &rtmsg)) if (inet6_rtm_to_rtmsg(r, arg, &rtmsg))
return -EINVAL; return -EINVAL;
return ip6_route_del(&rtmsg, nlh, arg, &NETLINK_CB(skb), r->rtm_table); return ip6_route_del(&rtmsg, nlh, arg, &NETLINK_CB(skb),
rtm_get_table(arg, r->rtm_table));
} }
int inet6_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) int inet6_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
...@@ -1869,7 +1870,8 @@ int inet6_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) ...@@ -1869,7 +1870,8 @@ int inet6_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
if (inet6_rtm_to_rtmsg(r, arg, &rtmsg)) if (inet6_rtm_to_rtmsg(r, arg, &rtmsg))
return -EINVAL; return -EINVAL;
return ip6_route_add(&rtmsg, nlh, arg, &NETLINK_CB(skb), r->rtm_table); return ip6_route_add(&rtmsg, nlh, arg, &NETLINK_CB(skb),
rtm_get_table(arg, r->rtm_table));
} }
struct rt6_rtnl_dump_arg struct rt6_rtnl_dump_arg
...@@ -1887,6 +1889,7 @@ static int rt6_fill_node(struct sk_buff *skb, struct rt6_info *rt, ...@@ -1887,6 +1889,7 @@ static int rt6_fill_node(struct sk_buff *skb, struct rt6_info *rt,
struct nlmsghdr *nlh; struct nlmsghdr *nlh;
unsigned char *b = skb->tail; unsigned char *b = skb->tail;
struct rta_cacheinfo ci; struct rta_cacheinfo ci;
u32 table;
if (prefix) { /* user wants prefix routes only */ if (prefix) { /* user wants prefix routes only */
if (!(rt->rt6i_flags & RTF_PREFIX_RT)) { if (!(rt->rt6i_flags & RTF_PREFIX_RT)) {
...@@ -1902,9 +1905,11 @@ static int rt6_fill_node(struct sk_buff *skb, struct rt6_info *rt, ...@@ -1902,9 +1905,11 @@ static int rt6_fill_node(struct sk_buff *skb, struct rt6_info *rt,
rtm->rtm_src_len = rt->rt6i_src.plen; rtm->rtm_src_len = rt->rt6i_src.plen;
rtm->rtm_tos = 0; rtm->rtm_tos = 0;
if (rt->rt6i_table) if (rt->rt6i_table)
rtm->rtm_table = rt->rt6i_table->tb6_id; table = rt->rt6i_table->tb6_id;
else else
rtm->rtm_table = RT6_TABLE_UNSPEC; table = RT6_TABLE_UNSPEC;
rtm->rtm_table = table;
RTA_PUT_U32(skb, RTA_TABLE, table);
if (rt->rt6i_flags&RTF_REJECT) if (rt->rt6i_flags&RTF_REJECT)
rtm->rtm_type = RTN_UNREACHABLE; rtm->rtm_type = RTN_UNREACHABLE;
else if (rt->rt6i_dev && (rt->rt6i_dev->flags&IFF_LOOPBACK)) else if (rt->rt6i_dev && (rt->rt6i_dev->flags&IFF_LOOPBACK))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment