mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-06-23 07:01:23 +00:00
[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:
parent
80a9492a33
commit
7bc570c8b4
13 changed files with 1751 additions and 27 deletions
|
@ -29,6 +29,7 @@
|
|||
#include <linux/netdevice.h>
|
||||
#include <linux/in6.h>
|
||||
#include <linux/icmpv6.h>
|
||||
#include <linux/mroute6.h>
|
||||
|
||||
#include <linux/netfilter.h>
|
||||
#include <linux/netfilter_ipv6.h>
|
||||
|
@ -236,36 +237,84 @@ int ip6_mc_input(struct sk_buff *skb)
|
|||
hdr = ipv6_hdr(skb);
|
||||
deliver = ipv6_chk_mcast_addr(skb->dev, &hdr->daddr, NULL);
|
||||
|
||||
#ifdef CONFIG_IPV6_MROUTE
|
||||
/*
|
||||
* IPv6 multicast router mode isnt currently supported.
|
||||
* IPv6 multicast router mode is now supported ;)
|
||||
*/
|
||||
#if 0
|
||||
if (ipv6_config.multicast_route) {
|
||||
int addr_type;
|
||||
if (ipv6_devconf.mc_forwarding &&
|
||||
likely(!(IP6CB(skb)->flags & IP6SKB_FORWARDED))) {
|
||||
/*
|
||||
* Okay, we try to forward - split and duplicate
|
||||
* packets.
|
||||
*/
|
||||
struct sk_buff *skb2;
|
||||
struct inet6_skb_parm *opt = IP6CB(skb);
|
||||
|
||||
addr_type = ipv6_addr_type(&hdr->daddr);
|
||||
/* Check for MLD */
|
||||
if (unlikely(opt->ra)) {
|
||||
/* Check if this is a mld message */
|
||||
u8 *ptr = skb_network_header(skb) + opt->ra;
|
||||
struct icmp6hdr *icmp6;
|
||||
u8 nexthdr = hdr->nexthdr;
|
||||
int offset;
|
||||
|
||||
if (!(addr_type & (IPV6_ADDR_LOOPBACK | IPV6_ADDR_LINKLOCAL))) {
|
||||
struct sk_buff *skb2;
|
||||
struct dst_entry *dst;
|
||||
/* Check if the value of Router Alert
|
||||
* is for MLD (0x0000).
|
||||
*/
|
||||
if ((ptr[2] | ptr[3]) == 0) {
|
||||
if (!ipv6_ext_hdr(nexthdr)) {
|
||||
/* BUG */
|
||||
goto discard;
|
||||
}
|
||||
offset = ipv6_skip_exthdr(skb, sizeof(*hdr),
|
||||
&nexthdr);
|
||||
if (offset < 0)
|
||||
goto discard;
|
||||
|
||||
dst = skb->dst;
|
||||
if (nexthdr != IPPROTO_ICMPV6)
|
||||
goto discard;
|
||||
|
||||
if (deliver) {
|
||||
skb2 = skb_clone(skb, GFP_ATOMIC);
|
||||
dst_output(skb2);
|
||||
} else {
|
||||
dst_output(skb);
|
||||
return 0;
|
||||
if (!pskb_may_pull(skb, (skb_network_header(skb) +
|
||||
offset + 1 - skb->data)))
|
||||
goto discard;
|
||||
|
||||
icmp6 = (struct icmp6hdr *)(skb_network_header(skb) + offset);
|
||||
|
||||
switch (icmp6->icmp6_type) {
|
||||
case ICMPV6_MGM_QUERY:
|
||||
case ICMPV6_MGM_REPORT:
|
||||
case ICMPV6_MGM_REDUCTION:
|
||||
case ICMPV6_MLD2_REPORT:
|
||||
break;
|
||||
default:
|
||||
/* Bogus */
|
||||
goto discard;
|
||||
}
|
||||
deliver = 1;
|
||||
goto out;
|
||||
}
|
||||
/* unknown RA - process it normally */
|
||||
}
|
||||
|
||||
if (deliver)
|
||||
skb2 = skb_clone(skb, GFP_ATOMIC);
|
||||
else {
|
||||
skb2 = skb;
|
||||
skb = NULL;
|
||||
}
|
||||
|
||||
if (skb2) {
|
||||
skb2->dev = skb2->dst->dev;
|
||||
ip6_mr_input(skb2);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
out:
|
||||
if (likely(deliver)) {
|
||||
ip6_input(skb);
|
||||
return 0;
|
||||
}
|
||||
discard:
|
||||
/* discard */
|
||||
kfree_skb(skb);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue