Commit 4aec72b9 authored by Krishna Kumar's avatar Krishna Kumar Committed by David S. Miller

[IPV6]: Reporting of prefix routes via rtnetlink.

parent 3c881eb0
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#define RTF_DEFAULT 0x00010000 /* default - learned via ND */ #define RTF_DEFAULT 0x00010000 /* default - learned via ND */
#define RTF_ALLONLINK 0x00020000 /* fallback, no routers on link */ #define RTF_ALLONLINK 0x00020000 /* fallback, no routers on link */
#define RTF_ADDRCONF 0x00040000 /* addrconf route - RA */ #define RTF_ADDRCONF 0x00040000 /* addrconf route - RA */
#define RTF_PREFIX_RT 0x00080000 /* A prefix only route - RA */
#define RTF_NONEXTHOP 0x00200000 /* route with no nexthop */ #define RTF_NONEXTHOP 0x00200000 /* route with no nexthop */
#define RTF_EXPIRES 0x00400000 #define RTF_EXPIRES 0x00400000
......
...@@ -168,6 +168,7 @@ enum rt_scope_t ...@@ -168,6 +168,7 @@ enum rt_scope_t
#define RTM_F_NOTIFY 0x100 /* Notify user of route change */ #define RTM_F_NOTIFY 0x100 /* Notify user of route change */
#define RTM_F_CLONED 0x200 /* This route is cloned */ #define RTM_F_CLONED 0x200 /* This route is cloned */
#define RTM_F_EQUALIZE 0x400 /* Multipath equalizer: NI */ #define RTM_F_EQUALIZE 0x400 /* Multipath equalizer: NI */
#define RTM_F_PREFIX 0x800 /* Prefix addresses */
/* Reserved table identifiers */ /* Reserved table identifiers */
......
...@@ -130,7 +130,7 @@ static spinlock_t addrconf_verify_lock = SPIN_LOCK_UNLOCKED; ...@@ -130,7 +130,7 @@ static spinlock_t addrconf_verify_lock = SPIN_LOCK_UNLOCKED;
static int addrconf_ifdown(struct net_device *dev, int how); static int addrconf_ifdown(struct net_device *dev, int how);
static void addrconf_dad_start(struct inet6_ifaddr *ifp); static void addrconf_dad_start(struct inet6_ifaddr *ifp, int flags);
static void addrconf_dad_timer(unsigned long data); static void addrconf_dad_timer(unsigned long data);
static void addrconf_dad_completed(struct inet6_ifaddr *ifp); static void addrconf_dad_completed(struct inet6_ifaddr *ifp);
static void addrconf_rs_timer(unsigned long data); static void addrconf_rs_timer(unsigned long data);
...@@ -710,7 +710,7 @@ static int ipv6_create_tempaddr(struct inet6_ifaddr *ifp, struct inet6_ifaddr *i ...@@ -710,7 +710,7 @@ static int ipv6_create_tempaddr(struct inet6_ifaddr *ifp, struct inet6_ifaddr *i
ift->prefered_lft = tmp_prefered_lft; ift->prefered_lft = tmp_prefered_lft;
ift->tstamp = ifp->tstamp; ift->tstamp = ifp->tstamp;
spin_unlock_bh(&ift->lock); spin_unlock_bh(&ift->lock);
addrconf_dad_start(ift); addrconf_dad_start(ift, 0);
in6_ifa_put(ift); in6_ifa_put(ift);
in6_dev_put(idev); in6_dev_put(idev);
out: out:
...@@ -1247,7 +1247,7 @@ static void addrconf_add_mroute(struct net_device *dev) ...@@ -1247,7 +1247,7 @@ static void addrconf_add_mroute(struct net_device *dev)
rtmsg.rtmsg_dst_len = 8; rtmsg.rtmsg_dst_len = 8;
rtmsg.rtmsg_metric = IP6_RT_PRIO_ADDRCONF; rtmsg.rtmsg_metric = IP6_RT_PRIO_ADDRCONF;
rtmsg.rtmsg_ifindex = dev->ifindex; rtmsg.rtmsg_ifindex = dev->ifindex;
rtmsg.rtmsg_flags = RTF_UP|RTF_ADDRCONF; rtmsg.rtmsg_flags = RTF_UP;
rtmsg.rtmsg_type = RTMSG_NEWROUTE; rtmsg.rtmsg_type = RTMSG_NEWROUTE;
ip6_route_add(&rtmsg, NULL, NULL); ip6_route_add(&rtmsg, NULL, NULL);
} }
...@@ -1274,7 +1274,7 @@ static void addrconf_add_lroute(struct net_device *dev) ...@@ -1274,7 +1274,7 @@ static void addrconf_add_lroute(struct net_device *dev)
struct in6_addr addr; struct in6_addr addr;
ipv6_addr_set(&addr, htonl(0xFE800000), 0, 0, 0); ipv6_addr_set(&addr, htonl(0xFE800000), 0, 0, 0);
addrconf_prefix_route(&addr, 64, dev, 0, RTF_ADDRCONF); addrconf_prefix_route(&addr, 64, dev, 0, 0);
} }
static struct inet6_dev *addrconf_add_dev(struct net_device *dev) static struct inet6_dev *addrconf_add_dev(struct net_device *dev)
...@@ -1367,7 +1367,7 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len) ...@@ -1367,7 +1367,7 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len)
} }
} else if (valid_lft) { } else if (valid_lft) {
addrconf_prefix_route(&pinfo->prefix, pinfo->prefix_len, addrconf_prefix_route(&pinfo->prefix, pinfo->prefix_len,
dev, rt_expires, RTF_ADDRCONF|RTF_EXPIRES); dev, rt_expires, RTF_ADDRCONF|RTF_EXPIRES|RTF_PREFIX_RT);
} }
if (rt) if (rt)
dst_release(&rt->u.dst); dst_release(&rt->u.dst);
...@@ -1413,7 +1413,7 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len) ...@@ -1413,7 +1413,7 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len)
} }
update_lft = create = 1; update_lft = create = 1;
addrconf_dad_start(ifp); addrconf_dad_start(ifp, RTF_ADDRCONF|RTF_PREFIX_RT);
} }
if (ifp) { if (ifp) {
...@@ -1586,7 +1586,7 @@ static int inet6_addr_add(int ifindex, struct in6_addr *pfx, int plen) ...@@ -1586,7 +1586,7 @@ static int inet6_addr_add(int ifindex, struct in6_addr *pfx, int plen)
ifp = ipv6_add_addr(idev, pfx, plen, scope, IFA_F_PERMANENT); ifp = ipv6_add_addr(idev, pfx, plen, scope, IFA_F_PERMANENT);
if (!IS_ERR(ifp)) { if (!IS_ERR(ifp)) {
addrconf_dad_start(ifp); addrconf_dad_start(ifp, 0);
in6_ifa_put(ifp); in6_ifa_put(ifp);
return 0; return 0;
} }
...@@ -1761,7 +1761,7 @@ static void addrconf_add_linklocal(struct inet6_dev *idev, struct in6_addr *addr ...@@ -1761,7 +1761,7 @@ static void addrconf_add_linklocal(struct inet6_dev *idev, struct in6_addr *addr
ifp = ipv6_add_addr(idev, addr, 64, IFA_LINK, IFA_F_PERMANENT); ifp = ipv6_add_addr(idev, addr, 64, IFA_LINK, IFA_F_PERMANENT);
if (!IS_ERR(ifp)) { if (!IS_ERR(ifp)) {
addrconf_dad_start(ifp); addrconf_dad_start(ifp, 0);
in6_ifa_put(ifp); in6_ifa_put(ifp);
} }
} }
...@@ -2021,8 +2021,7 @@ static void addrconf_rs_timer(unsigned long data) ...@@ -2021,8 +2021,7 @@ static void addrconf_rs_timer(unsigned long data)
memset(&rtmsg, 0, sizeof(struct in6_rtmsg)); memset(&rtmsg, 0, sizeof(struct in6_rtmsg));
rtmsg.rtmsg_type = RTMSG_NEWROUTE; rtmsg.rtmsg_type = RTMSG_NEWROUTE;
rtmsg.rtmsg_metric = IP6_RT_PRIO_ADDRCONF; rtmsg.rtmsg_metric = IP6_RT_PRIO_ADDRCONF;
rtmsg.rtmsg_flags = (RTF_ALLONLINK | RTF_ADDRCONF | rtmsg.rtmsg_flags = (RTF_ALLONLINK | RTF_DEFAULT | RTF_UP);
RTF_DEFAULT | RTF_UP);
rtmsg.rtmsg_ifindex = ifp->idev->dev->ifindex; rtmsg.rtmsg_ifindex = ifp->idev->dev->ifindex;
...@@ -2036,7 +2035,7 @@ static void addrconf_rs_timer(unsigned long data) ...@@ -2036,7 +2035,7 @@ static void addrconf_rs_timer(unsigned long data)
/* /*
* Duplicate Address Detection * Duplicate Address Detection
*/ */
static void addrconf_dad_start(struct inet6_ifaddr *ifp) static void addrconf_dad_start(struct inet6_ifaddr *ifp, int flags)
{ {
struct net_device *dev; struct net_device *dev;
unsigned long rand_num; unsigned long rand_num;
...@@ -2046,7 +2045,8 @@ static void addrconf_dad_start(struct inet6_ifaddr *ifp) ...@@ -2046,7 +2045,8 @@ static void addrconf_dad_start(struct inet6_ifaddr *ifp)
addrconf_join_solict(dev, &ifp->addr); addrconf_join_solict(dev, &ifp->addr);
if (ifp->prefix_len != 128 && (ifp->flags&IFA_F_PERMANENT)) if (ifp->prefix_len != 128 && (ifp->flags&IFA_F_PERMANENT))
addrconf_prefix_route(&ifp->addr, ifp->prefix_len, dev, 0, RTF_ADDRCONF); addrconf_prefix_route(&ifp->addr, ifp->prefix_len, dev, 0,
flags);
net_srandom(ifp->addr.s6_addr32[3]); net_srandom(ifp->addr.s6_addr32[3]);
rand_num = net_random() % (ifp->idev->cnf.rtr_solicit_delay ? : 1); rand_num = net_random() % (ifp->idev->cnf.rtr_solicit_delay ? : 1);
......
...@@ -1459,13 +1459,20 @@ static int rt6_fill_node(struct sk_buff *skb, struct rt6_info *rt, ...@@ -1459,13 +1459,20 @@ static int rt6_fill_node(struct sk_buff *skb, struct rt6_info *rt,
struct in6_addr *src, struct in6_addr *src,
int iif, int iif,
int type, u32 pid, u32 seq, int type, u32 pid, u32 seq,
struct nlmsghdr *in_nlh) struct nlmsghdr *in_nlh, int prefix)
{ {
struct rtmsg *rtm; struct rtmsg *rtm;
struct nlmsghdr *nlh; struct nlmsghdr *nlh;
unsigned char *b = skb->tail; unsigned char *b = skb->tail;
struct rta_cacheinfo ci; struct rta_cacheinfo ci;
if (prefix) { /* user wants prefix routes only */
if (!(rt->rt6i_flags & RTF_PREFIX_RT)) {
/* success since this is not a prefix route */
return 1;
}
}
if (!pid && in_nlh) { if (!pid && in_nlh) {
pid = in_nlh->nlmsg_pid; pid = in_nlh->nlmsg_pid;
} }
...@@ -1546,10 +1553,17 @@ static int rt6_fill_node(struct sk_buff *skb, struct rt6_info *rt, ...@@ -1546,10 +1553,17 @@ static int rt6_fill_node(struct sk_buff *skb, struct rt6_info *rt,
static int rt6_dump_route(struct rt6_info *rt, void *p_arg) static int rt6_dump_route(struct rt6_info *rt, void *p_arg)
{ {
struct rt6_rtnl_dump_arg *arg = (struct rt6_rtnl_dump_arg *) p_arg; struct rt6_rtnl_dump_arg *arg = (struct rt6_rtnl_dump_arg *) p_arg;
struct rtmsg *rtm;
int prefix;
rtm = NLMSG_DATA(arg->cb->nlh);
if (rtm)
prefix = (rtm->rtm_flags & RTM_F_PREFIX) != 0;
else prefix = 0;
return rt6_fill_node(arg->skb, rt, NULL, NULL, 0, RTM_NEWROUTE, return rt6_fill_node(arg->skb, rt, NULL, NULL, 0, RTM_NEWROUTE,
NETLINK_CB(arg->cb->skb).pid, arg->cb->nlh->nlmsg_seq, NETLINK_CB(arg->cb->skb).pid, arg->cb->nlh->nlmsg_seq,
NULL); NULL, prefix);
} }
static int fib6_dump_node(struct fib6_walker_t *w) static int fib6_dump_node(struct fib6_walker_t *w)
...@@ -1697,7 +1711,7 @@ int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void *arg) ...@@ -1697,7 +1711,7 @@ int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void *arg)
&fl.fl6_dst, &fl.fl6_src, &fl.fl6_dst, &fl.fl6_src,
iif, iif,
RTM_NEWROUTE, NETLINK_CB(in_skb).pid, RTM_NEWROUTE, NETLINK_CB(in_skb).pid,
nlh->nlmsg_seq, nlh); nlh->nlmsg_seq, nlh, 0);
if (err < 0) { if (err < 0) {
err = -EMSGSIZE; err = -EMSGSIZE;
goto out_free; goto out_free;
...@@ -1723,7 +1737,7 @@ void inet6_rt_notify(int event, struct rt6_info *rt, struct nlmsghdr *nlh) ...@@ -1723,7 +1737,7 @@ void inet6_rt_notify(int event, struct rt6_info *rt, struct nlmsghdr *nlh)
netlink_set_err(rtnl, 0, RTMGRP_IPV6_ROUTE, ENOBUFS); netlink_set_err(rtnl, 0, RTMGRP_IPV6_ROUTE, ENOBUFS);
return; return;
} }
if (rt6_fill_node(skb, rt, NULL, NULL, 0, event, 0, 0, nlh) < 0) { if (rt6_fill_node(skb, rt, NULL, NULL, 0, event, 0, 0, nlh, 0) < 0) {
kfree_skb(skb); kfree_skb(skb);
netlink_set_err(rtnl, 0, RTMGRP_IPV6_ROUTE, EINVAL); netlink_set_err(rtnl, 0, RTMGRP_IPV6_ROUTE, EINVAL);
return; return;
......
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