[IPV6] MROUTE: Support multicast forwarding.
Based on ancient patch by Mickael Hoerdt <hoerdt@clarinet.u-strasbg.fr>, which is available at <http://www-r2.u-strasbg.fr/~hoerdt/dev/linux_ipv6_mforwarding/patch-linux-ipv6-mforwarding-0.1a>. Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
This commit is contained in:
@@ -36,6 +36,7 @@
|
||||
#include <linux/route.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/in6.h>
|
||||
#include <linux/mroute6.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/if_arp.h>
|
||||
#include <linux/proc_fs.h>
|
||||
@@ -2106,7 +2107,7 @@ static inline size_t rt6_nlmsg_size(void)
|
||||
static int rt6_fill_node(struct sk_buff *skb, struct rt6_info *rt,
|
||||
struct in6_addr *dst, struct in6_addr *src,
|
||||
int iif, int type, u32 pid, u32 seq,
|
||||
int prefix, unsigned int flags)
|
||||
int prefix, int nowait, unsigned int flags)
|
||||
{
|
||||
struct rtmsg *rtm;
|
||||
struct nlmsghdr *nlh;
|
||||
@@ -2166,9 +2167,24 @@ static int rt6_fill_node(struct sk_buff *skb, struct rt6_info *rt,
|
||||
} else if (rtm->rtm_src_len)
|
||||
NLA_PUT(skb, RTA_SRC, 16, &rt->rt6i_src.addr);
|
||||
#endif
|
||||
if (iif)
|
||||
NLA_PUT_U32(skb, RTA_IIF, iif);
|
||||
else if (dst) {
|
||||
if (iif) {
|
||||
#ifdef CONFIG_IPV6_MROUTE
|
||||
if (ipv6_addr_is_multicast(&rt->rt6i_dst.addr)) {
|
||||
int err = ip6mr_get_route(skb, rtm, nowait);
|
||||
if (err <= 0) {
|
||||
if (!nowait) {
|
||||
if (err == 0)
|
||||
return 0;
|
||||
goto nla_put_failure;
|
||||
} else {
|
||||
if (err == -EMSGSIZE)
|
||||
goto nla_put_failure;
|
||||
}
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
NLA_PUT_U32(skb, RTA_IIF, iif);
|
||||
} else if (dst) {
|
||||
struct in6_addr saddr_buf;
|
||||
if (ipv6_dev_get_saddr(ip6_dst_idev(&rt->u.dst)->dev,
|
||||
dst, 0, &saddr_buf) == 0)
|
||||
@@ -2211,7 +2227,7 @@ int rt6_dump_route(struct rt6_info *rt, void *p_arg)
|
||||
|
||||
return rt6_fill_node(arg->skb, rt, NULL, NULL, 0, RTM_NEWROUTE,
|
||||
NETLINK_CB(arg->cb->skb).pid, arg->cb->nlh->nlmsg_seq,
|
||||
prefix, NLM_F_MULTI);
|
||||
prefix, 0, NLM_F_MULTI);
|
||||
}
|
||||
|
||||
static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void *arg)
|
||||
@@ -2277,7 +2293,7 @@ static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void
|
||||
|
||||
err = rt6_fill_node(skb, rt, &fl.fl6_dst, &fl.fl6_src, iif,
|
||||
RTM_NEWROUTE, NETLINK_CB(in_skb).pid,
|
||||
nlh->nlmsg_seq, 0, 0);
|
||||
nlh->nlmsg_seq, 0, 0, 0);
|
||||
if (err < 0) {
|
||||
kfree_skb(skb);
|
||||
goto errout;
|
||||
@@ -2303,7 +2319,7 @@ void inet6_rt_notify(int event, struct rt6_info *rt, struct nl_info *info)
|
||||
goto errout;
|
||||
|
||||
err = rt6_fill_node(skb, rt, NULL, NULL, 0,
|
||||
event, info->pid, seq, 0, 0);
|
||||
event, info->pid, seq, 0, 0, 0);
|
||||
if (err < 0) {
|
||||
/* -EMSGSIZE implies BUG in rt6_nlmsg_size() */
|
||||
WARN_ON(err == -EMSGSIZE);
|
||||
|
||||
Reference in New Issue
Block a user