ip6mr: add netlink notifications on mrt6msg cache reports
Add Netlink notifications on cache reports in ip6mr, in addition to the existing mrt6msg sent to mroute6_sk. Send RTM_NEWCACHEREPORT notifications to RTNLGRP_IPV6_MROUTE_R. MSGTYPE, MIF_ID, SRC_ADDR and DST_ADDR Netlink attributes contain the same data as their equivalent fields in the mrt6msg header. PKT attribute is the packet sent to mroute6_sk, without the added mrt6msg header. Suggested-by: Ryan Halbrook <halbrook@arista.com> Signed-off-by: Julien Gomes <julien@arista.com> Reviewed-by: Nikolay Aleksandrov <nikolay@cumulusnetworks.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
5a645dd86c
commit
dd12d15c9a
|
@ -133,4 +133,16 @@ struct mrt6msg {
|
|||
struct in6_addr im6_src, im6_dst;
|
||||
};
|
||||
|
||||
/* ip6mr netlink cache report attributes */
|
||||
enum {
|
||||
IP6MRA_CREPORT_UNSPEC,
|
||||
IP6MRA_CREPORT_MSGTYPE,
|
||||
IP6MRA_CREPORT_MIF_ID,
|
||||
IP6MRA_CREPORT_SRC_ADDR,
|
||||
IP6MRA_CREPORT_DST_ADDR,
|
||||
IP6MRA_CREPORT_PKT,
|
||||
__IP6MRA_CREPORT_MAX
|
||||
};
|
||||
#define IP6MRA_CREPORT_MAX (__IP6MRA_CREPORT_MAX - 1)
|
||||
|
||||
#endif /* _UAPI__LINUX_MROUTE6_H */
|
||||
|
|
|
@ -116,6 +116,7 @@ static int __ip6mr_fill_mroute(struct mr6_table *mrt, struct sk_buff *skb,
|
|||
struct mfc6_cache *c, struct rtmsg *rtm);
|
||||
static void mr6_netlink_event(struct mr6_table *mrt, struct mfc6_cache *mfc,
|
||||
int cmd);
|
||||
static void mrt6msg_netlink_event(struct mr6_table *mrt, struct sk_buff *pkt);
|
||||
static int ip6mr_rtm_dumproute(struct sk_buff *skb,
|
||||
struct netlink_callback *cb);
|
||||
static void mroute_clean_tables(struct mr6_table *mrt, bool all);
|
||||
|
@ -1125,8 +1126,7 @@ static void ip6mr_cache_resolve(struct net *net, struct mr6_table *mrt,
|
|||
}
|
||||
|
||||
/*
|
||||
* Bounce a cache query up to pim6sd. We could use netlink for this but pim6sd
|
||||
* expects the following bizarre scheme.
|
||||
* Bounce a cache query up to pim6sd and netlink.
|
||||
*
|
||||
* Called under mrt_lock.
|
||||
*/
|
||||
|
@ -1208,6 +1208,8 @@ static int ip6mr_cache_report(struct mr6_table *mrt, struct sk_buff *pkt,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
mrt6msg_netlink_event(mrt, skb);
|
||||
|
||||
/*
|
||||
* Deliver to user space multicast routing algorithms
|
||||
*/
|
||||
|
@ -2457,6 +2459,71 @@ errout:
|
|||
rtnl_set_sk_err(net, RTNLGRP_IPV6_MROUTE, err);
|
||||
}
|
||||
|
||||
static size_t mrt6msg_netlink_msgsize(size_t payloadlen)
|
||||
{
|
||||
size_t len =
|
||||
NLMSG_ALIGN(sizeof(struct rtgenmsg))
|
||||
+ nla_total_size(1) /* IP6MRA_CREPORT_MSGTYPE */
|
||||
+ nla_total_size(4) /* IP6MRA_CREPORT_MIF_ID */
|
||||
/* IP6MRA_CREPORT_SRC_ADDR */
|
||||
+ nla_total_size(sizeof(struct in6_addr))
|
||||
/* IP6MRA_CREPORT_DST_ADDR */
|
||||
+ nla_total_size(sizeof(struct in6_addr))
|
||||
/* IP6MRA_CREPORT_PKT */
|
||||
+ nla_total_size(payloadlen)
|
||||
;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static void mrt6msg_netlink_event(struct mr6_table *mrt, struct sk_buff *pkt)
|
||||
{
|
||||
struct net *net = read_pnet(&mrt->net);
|
||||
struct nlmsghdr *nlh;
|
||||
struct rtgenmsg *rtgenm;
|
||||
struct mrt6msg *msg;
|
||||
struct sk_buff *skb;
|
||||
struct nlattr *nla;
|
||||
int payloadlen;
|
||||
|
||||
payloadlen = pkt->len - sizeof(struct mrt6msg);
|
||||
msg = (struct mrt6msg *)skb_transport_header(pkt);
|
||||
|
||||
skb = nlmsg_new(mrt6msg_netlink_msgsize(payloadlen), GFP_ATOMIC);
|
||||
if (!skb)
|
||||
goto errout;
|
||||
|
||||
nlh = nlmsg_put(skb, 0, 0, RTM_NEWCACHEREPORT,
|
||||
sizeof(struct rtgenmsg), 0);
|
||||
if (!nlh)
|
||||
goto errout;
|
||||
rtgenm = nlmsg_data(nlh);
|
||||
rtgenm->rtgen_family = RTNL_FAMILY_IP6MR;
|
||||
if (nla_put_u8(skb, IP6MRA_CREPORT_MSGTYPE, msg->im6_msgtype) ||
|
||||
nla_put_u32(skb, IP6MRA_CREPORT_MIF_ID, msg->im6_mif) ||
|
||||
nla_put_in6_addr(skb, IP6MRA_CREPORT_SRC_ADDR,
|
||||
&msg->im6_src) ||
|
||||
nla_put_in6_addr(skb, IP6MRA_CREPORT_DST_ADDR,
|
||||
&msg->im6_dst))
|
||||
goto nla_put_failure;
|
||||
|
||||
nla = nla_reserve(skb, IP6MRA_CREPORT_PKT, payloadlen);
|
||||
if (!nla || skb_copy_bits(pkt, sizeof(struct mrt6msg),
|
||||
nla_data(nla), payloadlen))
|
||||
goto nla_put_failure;
|
||||
|
||||
nlmsg_end(skb, nlh);
|
||||
|
||||
rtnl_notify(skb, net, 0, RTNLGRP_IPV6_MROUTE_R, NULL, GFP_ATOMIC);
|
||||
return;
|
||||
|
||||
nla_put_failure:
|
||||
nlmsg_cancel(skb, nlh);
|
||||
errout:
|
||||
kfree_skb(skb);
|
||||
rtnl_set_sk_err(net, RTNLGRP_IPV6_MROUTE_R, -ENOBUFS);
|
||||
}
|
||||
|
||||
static int ip6mr_rtm_dumproute(struct sk_buff *skb, struct netlink_callback *cb)
|
||||
{
|
||||
struct net *net = sock_net(skb->sk);
|
||||
|
|
Loading…
Reference in New Issue