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

[IPV6]: Add notification for MIB:ipv6Prefix events.

parent 3c1ea2a5
...@@ -44,7 +44,10 @@ ...@@ -44,7 +44,10 @@
#define RTM_DELTFILTER (RTM_BASE+29) #define RTM_DELTFILTER (RTM_BASE+29)
#define RTM_GETTFILTER (RTM_BASE+30) #define RTM_GETTFILTER (RTM_BASE+30)
#define RTM_MAX (RTM_BASE+31) #define RTM_NEWPREFIX (RTM_BASE+36)
#define RTM_GETPREFIX (RTM_BASE+38)
#define RTM_MAX (RTM_BASE+39)
/* /*
Generic structure for encapsulation of optional route information. Generic structure for encapsulation of optional route information.
...@@ -459,6 +462,34 @@ struct ifinfomsg ...@@ -459,6 +462,34 @@ struct ifinfomsg
unsigned ifi_change; /* IFF_* change mask */ unsigned ifi_change; /* IFF_* change mask */
}; };
/********************************************************************
* prefix information
****/
struct prefixmsg
{
unsigned char prefix_family;
int prefix_ifindex;
unsigned char prefix_type;
unsigned char prefix_len;
unsigned char prefix_flags;
};
enum
{
PREFIX_UNSPEC,
PREFIX_ADDRESS,
PREFIX_CACHEINFO,
};
#define PREFIX_MAX PREFIX_CACHEINFO
struct prefix_cacheinfo
{
__u32 preferred_time;
__u32 valid_time;
};
/* The struct should be in sync with struct net_device_stats */ /* The struct should be in sync with struct net_device_stats */
struct rtnl_link_stats struct rtnl_link_stats
{ {
...@@ -625,6 +656,8 @@ enum ...@@ -625,6 +656,8 @@ enum
#define RTMGRP_DECnet_IFADDR 0x1000 #define RTMGRP_DECnet_IFADDR 0x1000
#define RTMGRP_DECnet_ROUTE 0x4000 #define RTMGRP_DECnet_ROUTE 0x4000
#define RTMGRP_IPV6_PREFIX 0x20000
/* End of information exported to user level */ /* End of information exported to user level */
#ifdef __KERNEL__ #ifdef __KERNEL__
......
...@@ -25,6 +25,10 @@ ...@@ -25,6 +25,10 @@
#define IF_RA_RCVD 0x20 #define IF_RA_RCVD 0x20
#define IF_RS_SENT 0x10 #define IF_RS_SENT 0x10
/* prefix flags */
#define IF_PREFIX_ONLINK 0x01
#define IF_PREFIX_AUTOCONF 0x02
#ifdef __KERNEL__ #ifdef __KERNEL__
struct inet6_ifaddr struct inet6_ifaddr
......
...@@ -138,6 +138,8 @@ static void addrconf_dad_completed(struct inet6_ifaddr *ifp); ...@@ -138,6 +138,8 @@ 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);
static void ipv6_ifa_notify(int event, struct inet6_ifaddr *ifa); static void ipv6_ifa_notify(int event, struct inet6_ifaddr *ifa);
static void inet6_prefix_notify(int event, struct inet6_dev *idev,
struct prefix_info *pinfo);
static int ipv6_chk_same_addr(const struct in6_addr *addr, struct net_device *dev); static int ipv6_chk_same_addr(const struct in6_addr *addr, struct net_device *dev);
static struct notifier_block *inet6addr_chain; static struct notifier_block *inet6addr_chain;
...@@ -1492,6 +1494,7 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len) ...@@ -1492,6 +1494,7 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len)
addrconf_verify(0); addrconf_verify(0);
} }
} }
inet6_prefix_notify(RTM_NEWPREFIX, in6_dev, pinfo);
in6_dev_put(in6_dev); in6_dev_put(in6_dev);
} }
...@@ -2854,6 +2857,66 @@ void inet6_ifinfo_notify(int event, struct inet6_dev *idev) ...@@ -2854,6 +2857,66 @@ void inet6_ifinfo_notify(int event, struct inet6_dev *idev)
netlink_broadcast(rtnl, skb, 0, RTMGRP_IPV6_IFINFO, GFP_ATOMIC); netlink_broadcast(rtnl, skb, 0, RTMGRP_IPV6_IFINFO, GFP_ATOMIC);
} }
static int inet6_fill_prefix(struct sk_buff *skb, struct inet6_dev *idev,
struct prefix_info *pinfo, u32 pid, u32 seq, int event)
{
struct prefixmsg *pmsg;
struct nlmsghdr *nlh;
unsigned char *b = skb->tail;
struct prefix_cacheinfo ci;
nlh = NLMSG_PUT(skb, pid, seq, event, sizeof(*pmsg));
if (pid)
nlh->nlmsg_flags |= NLM_F_MULTI;
pmsg = NLMSG_DATA(nlh);
pmsg->prefix_family = AF_INET6;
pmsg->prefix_ifindex = idev->dev->ifindex;
pmsg->prefix_len = pinfo->prefix_len;
pmsg->prefix_type = pinfo->type;
pmsg->prefix_flags = 0;
if (pinfo->onlink)
pmsg->prefix_flags |= IF_PREFIX_ONLINK;
if (pinfo->autoconf)
pmsg->prefix_flags |= IF_PREFIX_AUTOCONF;
RTA_PUT(skb, PREFIX_ADDRESS, sizeof(pinfo->prefix), &pinfo->prefix);
ci.preferred_time = ntohl(pinfo->prefered);
ci.valid_time = ntohl(pinfo->valid);
RTA_PUT(skb, PREFIX_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;
}
static void inet6_prefix_notify(int event, struct inet6_dev *idev,
struct prefix_info *pinfo)
{
struct sk_buff *skb;
int size = NLMSG_SPACE(sizeof(struct prefixmsg)+128);
skb = alloc_skb(size, GFP_ATOMIC);
if (!skb) {
netlink_set_err(rtnl, 0, RTMGRP_IPV6_PREFIX, ENOBUFS);
return;
}
if (inet6_fill_prefix(skb, idev, pinfo, 0, 0, event) < 0) {
kfree_skb(skb);
netlink_set_err(rtnl, 0, RTMGRP_IPV6_PREFIX, EINVAL);
return;
}
NETLINK_CB(skb).dst_groups = RTMGRP_IPV6_PREFIX;
netlink_broadcast(rtnl, skb, 0, RTMGRP_IPV6_PREFIX, GFP_ATOMIC);
}
static struct rtnetlink_link inet6_rtnetlink_table[RTM_MAX - RTM_BASE + 1] = { static struct rtnetlink_link inet6_rtnetlink_table[RTM_MAX - RTM_BASE + 1] = {
[RTM_GETLINK - RTM_BASE] = { .dumpit = inet6_dump_ifinfo, }, [RTM_GETLINK - RTM_BASE] = { .dumpit = inet6_dump_ifinfo, },
[RTM_NEWADDR - RTM_BASE] = { .doit = inet6_rtm_newaddr, }, [RTM_NEWADDR - RTM_BASE] = { .doit = inet6_rtm_newaddr, },
......
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