aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/fib_rules.h4
-rw-r--r--include/linux/rtnetlink.h8
-rw-r--r--include/net/fib_rules.h7
-rw-r--r--net/core/fib_rules.c5
-rw-r--r--net/decnet/dn_fib.c7
-rw-r--r--net/decnet/dn_route.c1
-rw-r--r--net/decnet/dn_table.c1
-rw-r--r--net/ipv4/fib_frontend.c7
-rw-r--r--net/ipv4/fib_rules.c1
-rw-r--r--net/ipv4/fib_semantics.c1
-rw-r--r--net/ipv4/route.c1
-rw-r--r--net/ipv6/fib6_rules.c1
-rw-r--r--net/ipv6/route.c13
13 files changed, 45 insertions, 12 deletions
diff --git a/include/linux/fib_rules.h b/include/linux/fib_rules.h
index 5e503f0ca6e4..19a82b6c1c1f 100644
--- a/include/linux/fib_rules.h
+++ b/include/linux/fib_rules.h
@@ -36,6 +36,10 @@ enum
36 FRA_UNUSED5, 36 FRA_UNUSED5,
37 FRA_FWMARK, /* netfilter mark (IPv4) */ 37 FRA_FWMARK, /* netfilter mark (IPv4) */
38 FRA_FLOW, /* flow/class id */ 38 FRA_FLOW, /* flow/class id */
39 FRA_UNUSED6,
40 FRA_UNUSED7,
41 FRA_UNUSED8,
42 FRA_TABLE, /* Extended table id */
39 __FRA_MAX 43 __FRA_MAX
40}; 44};
41 45
diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h
index 0aaffa2ae666..ea422a539a03 100644
--- a/include/linux/rtnetlink.h
+++ b/include/linux/rtnetlink.h
@@ -264,6 +264,7 @@ enum rtattr_type_t
264 RTA_CACHEINFO, 264 RTA_CACHEINFO,
265 RTA_SESSION, 265 RTA_SESSION,
266 RTA_MP_ALGO, 266 RTA_MP_ALGO,
267 RTA_TABLE,
267 __RTA_MAX 268 __RTA_MAX
268}; 269};
269 270
@@ -717,6 +718,13 @@ extern void __rtnl_unlock(void);
717 } \ 718 } \
718} while(0) 719} while(0)
719 720
721static inline u32 rtm_get_table(struct rtattr **rta, u8 table)
722{
723 return RTA_GET_U32(rta[RTA_TABLE-1]);
724rtattr_failure:
725 return table;
726}
727
720#endif /* __KERNEL__ */ 728#endif /* __KERNEL__ */
721 729
722 730
diff --git a/include/net/fib_rules.h b/include/net/fib_rules.h
index 61375d9e53f8..8e2f473d3e82 100644
--- a/include/net/fib_rules.h
+++ b/include/net/fib_rules.h
@@ -74,6 +74,13 @@ static inline void fib_rule_put(struct fib_rule *rule)
74 call_rcu(&rule->rcu, fib_rule_put_rcu); 74 call_rcu(&rule->rcu, fib_rule_put_rcu);
75} 75}
76 76
77static inline u32 frh_get_table(struct fib_rule_hdr *frh, struct nlattr **nla)
78{
79 if (nla[FRA_TABLE])
80 return nla_get_u32(nla[FRA_TABLE]);
81 return frh->table;
82}
83
77extern int fib_rules_register(struct fib_rules_ops *); 84extern int fib_rules_register(struct fib_rules_ops *);
78extern int fib_rules_unregister(struct fib_rules_ops *); 85extern int fib_rules_unregister(struct fib_rules_ops *);
79 86
diff --git a/net/core/fib_rules.c b/net/core/fib_rules.c
index 6cdad24038e2..873b04d5df81 100644
--- a/net/core/fib_rules.c
+++ b/net/core/fib_rules.c
@@ -187,7 +187,7 @@ int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
187 187
188 rule->action = frh->action; 188 rule->action = frh->action;
189 rule->flags = frh->flags; 189 rule->flags = frh->flags;
190 rule->table = frh->table; 190 rule->table = frh_get_table(frh, tb);
191 191
192 if (!rule->pref && ops->default_pref) 192 if (!rule->pref && ops->default_pref)
193 rule->pref = ops->default_pref(); 193 rule->pref = ops->default_pref();
@@ -245,7 +245,7 @@ int fib_nl_delrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
245 if (frh->action && (frh->action != rule->action)) 245 if (frh->action && (frh->action != rule->action))
246 continue; 246 continue;
247 247
248 if (frh->table && (frh->table != rule->table)) 248 if (frh->table && (frh_get_table(frh, tb) != rule->table))
249 continue; 249 continue;
250 250
251 if (tb[FRA_PRIORITY] && 251 if (tb[FRA_PRIORITY] &&
@@ -291,6 +291,7 @@ static int fib_nl_fill_rule(struct sk_buff *skb, struct fib_rule *rule,
291 291
292 frh = nlmsg_data(nlh); 292 frh = nlmsg_data(nlh);
293 frh->table = rule->table; 293 frh->table = rule->table;
294 NLA_PUT_U32(skb, FRA_TABLE, rule->table);
294 frh->res1 = 0; 295 frh->res1 = 0;
295 frh->res2 = 0; 296 frh->res2 = 0;
296 frh->action = rule->action; 297 frh->action = rule->action;
diff --git a/net/decnet/dn_fib.c b/net/decnet/dn_fib.c
index 7b3bf5c3d720..fb596373daa8 100644
--- a/net/decnet/dn_fib.c
+++ b/net/decnet/dn_fib.c
@@ -491,7 +491,8 @@ static int dn_fib_check_attr(struct rtmsg *r, struct rtattr **rta)
491 if (attr) { 491 if (attr) {
492 if (RTA_PAYLOAD(attr) < 4 && RTA_PAYLOAD(attr) != 2) 492 if (RTA_PAYLOAD(attr) < 4 && RTA_PAYLOAD(attr) != 2)
493 return -EINVAL; 493 return -EINVAL;
494 if (i != RTA_MULTIPATH && i != RTA_METRICS) 494 if (i != RTA_MULTIPATH && i != RTA_METRICS &&
495 i != RTA_TABLE)
495 rta[i-1] = (struct rtattr *)RTA_DATA(attr); 496 rta[i-1] = (struct rtattr *)RTA_DATA(attr);
496 } 497 }
497 } 498 }
@@ -508,7 +509,7 @@ int dn_fib_rtm_delroute(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
508 if (dn_fib_check_attr(r, rta)) 509 if (dn_fib_check_attr(r, rta))
509 return -EINVAL; 510 return -EINVAL;
510 511
511 tb = dn_fib_get_table(r->rtm_table, 0); 512 tb = dn_fib_get_table(rtm_get_table(rta, r->rtm_table), 0);
512 if (tb) 513 if (tb)
513 return tb->delete(tb, r, (struct dn_kern_rta *)rta, nlh, &NETLINK_CB(skb)); 514 return tb->delete(tb, r, (struct dn_kern_rta *)rta, nlh, &NETLINK_CB(skb));
514 515
@@ -524,7 +525,7 @@ int dn_fib_rtm_newroute(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
524 if (dn_fib_check_attr(r, rta)) 525 if (dn_fib_check_attr(r, rta))
525 return -EINVAL; 526 return -EINVAL;
526 527
527 tb = dn_fib_get_table(r->rtm_table, 1); 528 tb = dn_fib_get_table(rtm_get_table(rta, r->rtm_table), 1);
528 if (tb) 529 if (tb)
529 return tb->insert(tb, r, (struct dn_kern_rta *)rta, nlh, &NETLINK_CB(skb)); 530 return tb->insert(tb, r, (struct dn_kern_rta *)rta, nlh, &NETLINK_CB(skb));
530 531
diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c
index 5e6f4616ca10..4c963213fba5 100644
--- a/net/decnet/dn_route.c
+++ b/net/decnet/dn_route.c
@@ -1486,6 +1486,7 @@ static int dn_rt_fill_info(struct sk_buff *skb, u32 pid, u32 seq,
1486 r->rtm_src_len = 0; 1486 r->rtm_src_len = 0;
1487 r->rtm_tos = 0; 1487 r->rtm_tos = 0;
1488 r->rtm_table = RT_TABLE_MAIN; 1488 r->rtm_table = RT_TABLE_MAIN;
1489 RTA_PUT_U32(skb, RTA_TABLE, RT_TABLE_MAIN);
1489 r->rtm_type = rt->rt_type; 1490 r->rtm_type = rt->rt_type;
1490 r->rtm_flags = (rt->rt_flags & ~0xFFFF) | RTM_F_CLONED; 1491 r->rtm_flags = (rt->rt_flags & ~0xFFFF) | RTM_F_CLONED;
1491 r->rtm_scope = RT_SCOPE_UNIVERSE; 1492 r->rtm_scope = RT_SCOPE_UNIVERSE;
diff --git a/net/decnet/dn_table.c b/net/decnet/dn_table.c
index 1601ee5406a8..eca7c1e10c80 100644
--- a/net/decnet/dn_table.c
+++ b/net/decnet/dn_table.c
@@ -278,6 +278,7 @@ static int dn_fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
278 rtm->rtm_src_len = 0; 278 rtm->rtm_src_len = 0;
279 rtm->rtm_tos = 0; 279 rtm->rtm_tos = 0;
280 rtm->rtm_table = tb_id; 280 rtm->rtm_table = tb_id;
281 RTA_PUT_U32(skb, RTA_TABLE, tb_id);
281 rtm->rtm_flags = fi->fib_flags; 282 rtm->rtm_flags = fi->fib_flags;
282 rtm->rtm_scope = scope; 283 rtm->rtm_scope = scope;
283 rtm->rtm_type = type; 284 rtm->rtm_type = type;
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c
index 06f4b23f6f57..2696ede52de2 100644
--- a/net/ipv4/fib_frontend.c
+++ b/net/ipv4/fib_frontend.c
@@ -294,7 +294,8 @@ static int inet_check_attr(struct rtmsg *r, struct rtattr **rta)
294 if (attr) { 294 if (attr) {
295 if (RTA_PAYLOAD(attr) < 4) 295 if (RTA_PAYLOAD(attr) < 4)
296 return -EINVAL; 296 return -EINVAL;
297 if (i != RTA_MULTIPATH && i != RTA_METRICS) 297 if (i != RTA_MULTIPATH && i != RTA_METRICS &&
298 i != RTA_TABLE)
298 *rta = (struct rtattr*)RTA_DATA(attr); 299 *rta = (struct rtattr*)RTA_DATA(attr);
299 } 300 }
300 } 301 }
@@ -310,7 +311,7 @@ int inet_rtm_delroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
310 if (inet_check_attr(r, rta)) 311 if (inet_check_attr(r, rta))
311 return -EINVAL; 312 return -EINVAL;
312 313
313 tb = fib_get_table(r->rtm_table); 314 tb = fib_get_table(rtm_get_table(rta, r->rtm_table));
314 if (tb) 315 if (tb)
315 return tb->tb_delete(tb, r, (struct kern_rta*)rta, nlh, &NETLINK_CB(skb)); 316 return tb->tb_delete(tb, r, (struct kern_rta*)rta, nlh, &NETLINK_CB(skb));
316 return -ESRCH; 317 return -ESRCH;
@@ -325,7 +326,7 @@ int inet_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
325 if (inet_check_attr(r, rta)) 326 if (inet_check_attr(r, rta))
326 return -EINVAL; 327 return -EINVAL;
327 328
328 tb = fib_new_table(r->rtm_table); 329 tb = fib_new_table(rtm_get_table(rta, r->rtm_table));
329 if (tb) 330 if (tb)
330 return tb->tb_insert(tb, r, (struct kern_rta*)rta, nlh, &NETLINK_CB(skb)); 331 return tb->tb_insert(tb, r, (struct kern_rta*)rta, nlh, &NETLINK_CB(skb));
331 return -ENOBUFS; 332 return -ENOBUFS;
diff --git a/net/ipv4/fib_rules.c b/net/ipv4/fib_rules.c
index 58fb91b00fdf..0330b9cc4b58 100644
--- a/net/ipv4/fib_rules.c
+++ b/net/ipv4/fib_rules.c
@@ -184,6 +184,7 @@ static struct nla_policy fib4_rule_policy[FRA_MAX+1] __read_mostly = {
184 [FRA_DST] = { .type = NLA_U32 }, 184 [FRA_DST] = { .type = NLA_U32 },
185 [FRA_FWMARK] = { .type = NLA_U32 }, 185 [FRA_FWMARK] = { .type = NLA_U32 },
186 [FRA_FLOW] = { .type = NLA_U32 }, 186 [FRA_FLOW] = { .type = NLA_U32 },
187 [FRA_TABLE] = { .type = NLA_U32 },
187}; 188};
188 189
189static int fib4_rule_configure(struct fib_rule *rule, struct sk_buff *skb, 190static int fib4_rule_configure(struct fib_rule *rule, struct sk_buff *skb,
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c
index c7a112b5a185..ab753df20a39 100644
--- a/net/ipv4/fib_semantics.c
+++ b/net/ipv4/fib_semantics.c
@@ -953,6 +953,7 @@ fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
953 rtm->rtm_src_len = 0; 953 rtm->rtm_src_len = 0;
954 rtm->rtm_tos = tos; 954 rtm->rtm_tos = tos;
955 rtm->rtm_table = tb_id; 955 rtm->rtm_table = tb_id;
956 RTA_PUT_U32(skb, RTA_TABLE, tb_id);
956 rtm->rtm_type = type; 957 rtm->rtm_type = type;
957 rtm->rtm_flags = fi->fib_flags; 958 rtm->rtm_flags = fi->fib_flags;
958 rtm->rtm_scope = scope; 959 rtm->rtm_scope = scope;
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index b873cbcdd0b8..12128b82c9dc 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -2652,6 +2652,7 @@ static int rt_fill_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
2652 r->rtm_src_len = 0; 2652 r->rtm_src_len = 0;
2653 r->rtm_tos = rt->fl.fl4_tos; 2653 r->rtm_tos = rt->fl.fl4_tos;
2654 r->rtm_table = RT_TABLE_MAIN; 2654 r->rtm_table = RT_TABLE_MAIN;
2655 RTA_PUT_U32(skb, RTA_TABLE, RT_TABLE_MAIN);
2655 r->rtm_type = rt->rt_type; 2656 r->rtm_type = rt->rt_type;
2656 r->rtm_scope = RT_SCOPE_UNIVERSE; 2657 r->rtm_scope = RT_SCOPE_UNIVERSE;
2657 r->rtm_protocol = RTPROT_UNSPEC; 2658 r->rtm_protocol = RTPROT_UNSPEC;
diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c
index 22a2fdb09831..2c4fbc855e6c 100644
--- a/net/ipv6/fib6_rules.c
+++ b/net/ipv6/fib6_rules.c
@@ -129,6 +129,7 @@ static struct nla_policy fib6_rule_policy[RTA_MAX+1] __read_mostly = {
129 [FRA_PRIORITY] = { .type = NLA_U32 }, 129 [FRA_PRIORITY] = { .type = NLA_U32 },
130 [FRA_SRC] = { .minlen = sizeof(struct in6_addr) }, 130 [FRA_SRC] = { .minlen = sizeof(struct in6_addr) },
131 [FRA_DST] = { .minlen = sizeof(struct in6_addr) }, 131 [FRA_DST] = { .minlen = sizeof(struct in6_addr) },
132 [FRA_TABLE] = { .type = NLA_U32 },
132}; 133};
133 134
134static int fib6_rule_configure(struct fib_rule *rule, struct sk_buff *skb, 135static int fib6_rule_configure(struct fib_rule *rule, struct sk_buff *skb,
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index e08d84063c1f..843c5509fced 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -1859,7 +1859,8 @@ int inet6_rtm_delroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
1859 1859
1860 if (inet6_rtm_to_rtmsg(r, arg, &rtmsg)) 1860 if (inet6_rtm_to_rtmsg(r, arg, &rtmsg))
1861 return -EINVAL; 1861 return -EINVAL;
1862 return ip6_route_del(&rtmsg, nlh, arg, &NETLINK_CB(skb), r->rtm_table); 1862 return ip6_route_del(&rtmsg, nlh, arg, &NETLINK_CB(skb),
1863 rtm_get_table(arg, r->rtm_table));
1863} 1864}
1864 1865
1865int inet6_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) 1866int 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 1870
1870 if (inet6_rtm_to_rtmsg(r, arg, &rtmsg)) 1871 if (inet6_rtm_to_rtmsg(r, arg, &rtmsg))
1871 return -EINVAL; 1872 return -EINVAL;
1872 return ip6_route_add(&rtmsg, nlh, arg, &NETLINK_CB(skb), r->rtm_table); 1873 return ip6_route_add(&rtmsg, nlh, arg, &NETLINK_CB(skb),
1874 rtm_get_table(arg, r->rtm_table));
1873} 1875}
1874 1876
1875struct rt6_rtnl_dump_arg 1877struct rt6_rtnl_dump_arg
@@ -1887,6 +1889,7 @@ static int rt6_fill_node(struct sk_buff *skb, struct rt6_info *rt,
1887 struct nlmsghdr *nlh; 1889 struct nlmsghdr *nlh;
1888 unsigned char *b = skb->tail; 1890 unsigned char *b = skb->tail;
1889 struct rta_cacheinfo ci; 1891 struct rta_cacheinfo ci;
1892 u32 table;
1890 1893
1891 if (prefix) { /* user wants prefix routes only */ 1894 if (prefix) { /* user wants prefix routes only */
1892 if (!(rt->rt6i_flags & RTF_PREFIX_RT)) { 1895 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 rtm->rtm_src_len = rt->rt6i_src.plen; 1905 rtm->rtm_src_len = rt->rt6i_src.plen;
1903 rtm->rtm_tos = 0; 1906 rtm->rtm_tos = 0;
1904 if (rt->rt6i_table) 1907 if (rt->rt6i_table)
1905 rtm->rtm_table = rt->rt6i_table->tb6_id; 1908 table = rt->rt6i_table->tb6_id;
1906 else 1909 else
1907 rtm->rtm_table = RT6_TABLE_UNSPEC; 1910 table = RT6_TABLE_UNSPEC;
1911 rtm->rtm_table = table;
1912 RTA_PUT_U32(skb, RTA_TABLE, table);
1908 if (rt->rt6i_flags&RTF_REJECT) 1913 if (rt->rt6i_flags&RTF_REJECT)
1909 rtm->rtm_type = RTN_UNREACHABLE; 1914 rtm->rtm_type = RTN_UNREACHABLE;
1910 else if (rt->rt6i_dev && (rt->rt6i_dev->flags&IFF_LOOPBACK)) 1915 else if (rt->rt6i_dev && (rt->rt6i_dev->flags&IFF_LOOPBACK))