aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6
diff options
context:
space:
mode:
authorLubomir Rintel <lkundrak@v3.sk>2015-03-11 10:39:21 -0400
committerDavid S. Miller <davem@davemloft.net>2015-03-11 23:28:09 -0400
commitc78ba6d64c78634a875d1e316676667cabfea256 (patch)
tree500e33f08cc707c80967c4ae74c49a2d8c8198eb /net/ipv6
parentac70c05b6f2b228f778cbde94f64e5df8a2c4d55 (diff)
ipv6: expose RFC4191 route preference via rtnetlink
This makes it possible to retain the route preference when RAs are handled in userspace. Signed-off-by: Lubomir Rintel <lkundrak@v3.sk> Reviewed-by: Jiri Pirko <jiri@resnulli.us> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv6')
-rw-r--r--net/ipv6/route.c16
1 files changed, 15 insertions, 1 deletions
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 06fa819c43c9..58c0e6a4d15d 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -2398,6 +2398,7 @@ static const struct nla_policy rtm_ipv6_policy[RTA_MAX+1] = {
2398 [RTA_PRIORITY] = { .type = NLA_U32 }, 2398 [RTA_PRIORITY] = { .type = NLA_U32 },
2399 [RTA_METRICS] = { .type = NLA_NESTED }, 2399 [RTA_METRICS] = { .type = NLA_NESTED },
2400 [RTA_MULTIPATH] = { .len = sizeof(struct rtnexthop) }, 2400 [RTA_MULTIPATH] = { .len = sizeof(struct rtnexthop) },
2401 [RTA_PREF] = { .type = NLA_U8 },
2401}; 2402};
2402 2403
2403static int rtm_to_fib6_config(struct sk_buff *skb, struct nlmsghdr *nlh, 2404static int rtm_to_fib6_config(struct sk_buff *skb, struct nlmsghdr *nlh,
@@ -2405,6 +2406,7 @@ static int rtm_to_fib6_config(struct sk_buff *skb, struct nlmsghdr *nlh,
2405{ 2406{
2406 struct rtmsg *rtm; 2407 struct rtmsg *rtm;
2407 struct nlattr *tb[RTA_MAX+1]; 2408 struct nlattr *tb[RTA_MAX+1];
2409 unsigned int pref;
2408 int err; 2410 int err;
2409 2411
2410 err = nlmsg_parse(nlh, sizeof(*rtm), tb, RTA_MAX, rtm_ipv6_policy); 2412 err = nlmsg_parse(nlh, sizeof(*rtm), tb, RTA_MAX, rtm_ipv6_policy);
@@ -2480,6 +2482,14 @@ static int rtm_to_fib6_config(struct sk_buff *skb, struct nlmsghdr *nlh,
2480 cfg->fc_mp_len = nla_len(tb[RTA_MULTIPATH]); 2482 cfg->fc_mp_len = nla_len(tb[RTA_MULTIPATH]);
2481 } 2483 }
2482 2484
2485 if (tb[RTA_PREF]) {
2486 pref = nla_get_u8(tb[RTA_PREF]);
2487 if (pref != ICMPV6_ROUTER_PREF_LOW &&
2488 pref != ICMPV6_ROUTER_PREF_HIGH)
2489 pref = ICMPV6_ROUTER_PREF_MEDIUM;
2490 cfg->fc_flags |= RTF_PREF(pref);
2491 }
2492
2483 err = 0; 2493 err = 0;
2484errout: 2494errout:
2485 return err; 2495 return err;
@@ -2583,7 +2593,8 @@ static inline size_t rt6_nlmsg_size(void)
2583 + nla_total_size(4) /* RTA_PRIORITY */ 2593 + nla_total_size(4) /* RTA_PRIORITY */
2584 + RTAX_MAX * nla_total_size(4) /* RTA_METRICS */ 2594 + RTAX_MAX * nla_total_size(4) /* RTA_METRICS */
2585 + nla_total_size(sizeof(struct rta_cacheinfo)) 2595 + nla_total_size(sizeof(struct rta_cacheinfo))
2586 + nla_total_size(TCP_CA_NAME_MAX); /* RTAX_CC_ALGO */ 2596 + nla_total_size(TCP_CA_NAME_MAX) /* RTAX_CC_ALGO */
2597 + nla_total_size(1); /* RTA_PREF */
2587} 2598}
2588 2599
2589static int rt6_fill_node(struct net *net, 2600static int rt6_fill_node(struct net *net,
@@ -2724,6 +2735,9 @@ static int rt6_fill_node(struct net *net,
2724 if (rtnl_put_cacheinfo(skb, &rt->dst, 0, expires, rt->dst.error) < 0) 2735 if (rtnl_put_cacheinfo(skb, &rt->dst, 0, expires, rt->dst.error) < 0)
2725 goto nla_put_failure; 2736 goto nla_put_failure;
2726 2737
2738 if (nla_put_u8(skb, RTA_PREF, IPV6_EXTRACT_PREF(rt->rt6i_flags)))
2739 goto nla_put_failure;
2740
2727 nlmsg_end(skb, nlh); 2741 nlmsg_end(skb, nlh);
2728 return 0; 2742 return 0;
2729 2743