Commit c272dd46 authored by Shirley Ma's avatar Shirley Ma Committed by David S. Miller

[IPV6]: Add MIB:ipv6RouterAdvert netlink notification.

parent 4ab58d18
......@@ -44,6 +44,8 @@
#define RTM_DELTFILTER (RTM_BASE+29)
#define RTM_GETTFILTER (RTM_BASE+30)
#define RTM_NEWRA (RTM_BASE+32)
#define RTM_NEWPREFIX (RTM_BASE+36)
#define RTM_GETPREFIX (RTM_BASE+38)
......@@ -443,6 +445,38 @@ struct rtgenmsg
unsigned char rtgen_family;
};
/*****************************************************************
* Route Advertisement specific messages.
* ******/
/* struct iframsg
* passes router advertisement specific information
*/
struct iframsg
{
unsigned char ifra_family;
unsigned ifra_flags;
int ifra_index;
};
enum
{
IFRA_UNSPEC,
IFRA_LMTU,
IFRA_CACHEINFO
};
/* max_adver_interval, min_adver_interval should be gotten from user level */
struct ifra_cacheinfo {
__u32 hop_limit;
__u32 lifetime;
__u32 reachable_time;
__u32 retrans_time;
};
#define IFRA_MAX IFRA_CACHEINFO
/*****************************************************************
* Link layer specific messages.
****/
......@@ -658,6 +692,8 @@ enum
#define RTMGRP_IPV6_PREFIX 0x20000
#define RTMGRP_IPV6_IFRA 0x10000
/* End of information exported to user level */
#ifdef __KERNEL__
......
......@@ -109,6 +109,10 @@ extern int ndisc_ifinfo_sysctl_change(ctl_table *ctl,
extern void inet6_ifinfo_notify(int event,
struct inet6_dev *idev);
extern void inet6_ifra_notify(int event,
struct inet6_dev *idev,
struct ra_msg *ra_msg);
static inline struct neighbour * ndisc_get_neigh(struct net_device *dev, struct in6_addr *addr)
{
......
......@@ -2924,6 +2924,62 @@ static void inet6_prefix_notify(int event, struct inet6_dev *idev,
netlink_broadcast(rtnl, skb, 0, RTMGRP_IPV6_PREFIX, GFP_ATOMIC);
}
static int inet6_fill_ifra(struct sk_buff *skb, struct inet6_dev *idev,
struct ra_msg *ra_msg, u32 pid, u32 seq, int event)
{
struct iframsg *ifra;
struct nlmsghdr *nlh;
unsigned char *b = skb->tail;
__u32 mtu = idev->dev->mtu;
struct ifra_cacheinfo ci;
nlh = NLMSG_PUT(skb, pid, seq, event, sizeof(*ifra));
if (pid)
nlh->nlmsg_flags |= NLM_F_MULTI;
ifra = NLMSG_DATA(nlh);
ifra->ifra_family = AF_INET6;
ifra->ifra_index = idev->dev->ifindex;
ifra->ifra_flags = idev->if_flags;
RTA_PUT(skb, IFRA_LMTU, sizeof(mtu), &mtu);
ci.hop_limit = ra_msg->icmph.icmp6_hop_limit;
ci.lifetime = ntohs(ra_msg->icmph.icmp6_rt_lifetime);
ci.reachable_time = ntohl(ra_msg->reachable_time);
ci.retrans_time = ntohl(ra_msg->retrans_timer);
RTA_PUT(skb, IFRA_CACHEINFO, sizeof(ci), &ci);
nlh->nlmsg_len = skb->tail - b;
return skb->len;
nlmsg_failure:
rtattr_failure:
skb_trim(skb, b - skb->data);
return -1;
}
void inet6_ifra_notify(int event, struct inet6_dev *idev,
struct ra_msg *ra_msg)
{
struct sk_buff *skb;
int size = NLMSG_SPACE(sizeof(struct iframsg)+128);
skb = alloc_skb(size, GFP_ATOMIC);
if (!skb) {
netlink_set_err(rtnl, 0, RTMGRP_IPV6_IFRA, ENOBUFS);
return;
}
if (inet6_fill_ifra(skb, idev, ra_msg, 0, 0, event) < 0) {
kfree_skb(skb);
netlink_set_err(rtnl, 0, RTMGRP_IPV6_IFRA, EINVAL);
return;
}
NETLINK_CB(skb).dst_groups = RTMGRP_IPV6_IFRA;
netlink_broadcast(rtnl, skb, 0, RTMGRP_IPV6_IFRA, GFP_ATOMIC);
}
static struct rtnetlink_link inet6_rtnetlink_table[RTM_MAX - RTM_BASE + 1] = {
[RTM_GETLINK - RTM_BASE] = { .dumpit = inet6_dump_ifinfo, },
[RTM_NEWADDR - RTM_BASE] = { .doit = inet6_rtm_newaddr, },
......
......@@ -1194,6 +1194,7 @@ static void ndisc_router_discovery(struct sk_buff *skb)
out:
if (rt)
dst_release(&rt->u.dst);
inet6_ifra_notify(RTM_NEWRA, in6_dev, ra_msg);
in6_dev_put(in6_dev);
}
......
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