diff options
author | Lubomir Rintel <lkundrak@v3.sk> | 2015-03-11 10:39:21 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2015-03-11 23:28:09 -0400 |
commit | c78ba6d64c78634a875d1e316676667cabfea256 (patch) | |
tree | 500e33f08cc707c80967c4ae74c49a2d8c8198eb /net/ipv6 | |
parent | ac70c05b6f2b228f778cbde94f64e5df8a2c4d55 (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.c | 16 |
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 | ||
2403 | static int rtm_to_fib6_config(struct sk_buff *skb, struct nlmsghdr *nlh, | 2404 | static 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; |
2484 | errout: | 2494 | errout: |
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 | ||
2589 | static int rt6_fill_node(struct net *net, | 2600 | static 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 | ||