Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e9823185 authored by Patrick McHardy's avatar Patrick McHardy Committed by David S. Miller
Browse files

[NETFILTER]: Restore netfilter assumptions in IPv6 multicast



Netfilter assumes that skb->data == skb->nh.ipv6h

Signed-off-by: default avatarPatrick McHardy <kaber@trash.net>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 18b8afc7
Loading
Loading
Loading
Loading
+26 −21
Original line number Original line Diff line number Diff line
@@ -1301,15 +1301,6 @@ static struct sk_buff *mld_newpack(struct net_device *dev, int size)
		return NULL;
		return NULL;


	skb_reserve(skb, LL_RESERVED_SPACE(dev));
	skb_reserve(skb, LL_RESERVED_SPACE(dev));
	if (dev->hard_header) {
		unsigned char ha[MAX_ADDR_LEN];

		ndisc_mc_map(&mld2_all_mcr, ha, dev, 1);
		if (dev->hard_header(skb, dev, ETH_P_IPV6,ha,NULL,size) < 0) {
			kfree_skb(skb);
			return NULL;
		}
	}


	if (ipv6_get_lladdr(dev, &addr_buf)) {
	if (ipv6_get_lladdr(dev, &addr_buf)) {
		/* <draft-ietf-magma-mld-source-05.txt>:
		/* <draft-ietf-magma-mld-source-05.txt>:
@@ -1333,6 +1324,30 @@ static struct sk_buff *mld_newpack(struct net_device *dev, int size)
	return skb;
	return skb;
}
}


static inline int mld_dev_queue_xmit2(struct sk_buff *skb)
{
	struct net_device *dev = skb->dev;

	if (dev->hard_header) {
		unsigned char ha[MAX_ADDR_LEN];
		int err;

		ndisc_mc_map(&skb->nh.ipv6h->daddr, ha, dev, 1);
		err = dev->hard_header(skb, dev, ETH_P_IPV6, ha, NULL, skb->len);
		if (err < 0) {
			kfree_skb(skb);
			return err;
		}
	}
	return dev_queue_xmit(skb);
}

static inline int mld_dev_queue_xmit(struct sk_buff *skb)
{
	return NF_HOOK(PF_INET6, NF_IP6_POST_ROUTING, skb, NULL, skb->dev,
	               mld_dev_queue_xmit2);
}

static void mld_sendpack(struct sk_buff *skb)
static void mld_sendpack(struct sk_buff *skb)
{
{
	struct ipv6hdr *pip6 = skb->nh.ipv6h;
	struct ipv6hdr *pip6 = skb->nh.ipv6h;
@@ -1350,7 +1365,7 @@ static void mld_sendpack(struct sk_buff *skb)
	pmr->csum = csum_ipv6_magic(&pip6->saddr, &pip6->daddr, mldlen,
	pmr->csum = csum_ipv6_magic(&pip6->saddr, &pip6->daddr, mldlen,
		IPPROTO_ICMPV6, csum_partial(skb->h.raw, mldlen, 0));
		IPPROTO_ICMPV6, csum_partial(skb->h.raw, mldlen, 0));
	err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, skb->dev,
	err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, skb->dev,
		dev_queue_xmit);
		mld_dev_queue_xmit);
	if (!err) {
	if (!err) {
		ICMP6_INC_STATS(idev,ICMP6_MIB_OUTMSGS);
		ICMP6_INC_STATS(idev,ICMP6_MIB_OUTMSGS);
		IP6_INC_STATS(IPSTATS_MIB_OUTMCASTPKTS);
		IP6_INC_STATS(IPSTATS_MIB_OUTMCASTPKTS);
@@ -1656,12 +1671,6 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type)
	}
	}


	skb_reserve(skb, LL_RESERVED_SPACE(dev));
	skb_reserve(skb, LL_RESERVED_SPACE(dev));
	if (dev->hard_header) {
		unsigned char ha[MAX_ADDR_LEN];
		ndisc_mc_map(snd_addr, ha, dev, 1);
		if (dev->hard_header(skb, dev, ETH_P_IPV6, ha, NULL, full_len) < 0)
			goto out;
	}


	if (ipv6_get_lladdr(dev, &addr_buf)) {
	if (ipv6_get_lladdr(dev, &addr_buf)) {
		/* <draft-ietf-magma-mld-source-05.txt>:
		/* <draft-ietf-magma-mld-source-05.txt>:
@@ -1689,7 +1698,7 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type)
	idev = in6_dev_get(skb->dev);
	idev = in6_dev_get(skb->dev);


	err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, skb->dev,
	err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, skb->dev,
		dev_queue_xmit);
		mld_dev_queue_xmit);
	if (!err) {
	if (!err) {
		if (type == ICMPV6_MGM_REDUCTION)
		if (type == ICMPV6_MGM_REDUCTION)
			ICMP6_INC_STATS(idev, ICMP6_MIB_OUTGROUPMEMBREDUCTIONS);
			ICMP6_INC_STATS(idev, ICMP6_MIB_OUTGROUPMEMBREDUCTIONS);
@@ -1703,10 +1712,6 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type)
	if (likely(idev != NULL))
	if (likely(idev != NULL))
		in6_dev_put(idev);
		in6_dev_put(idev);
	return;
	return;

out:
	IP6_INC_STATS(IPSTATS_MIB_OUTDISCARDS);
	kfree_skb(skb);
}
}


static int ip6_mc_del1_src(struct ifmcaddr6 *pmc, int sfmode,
static int ip6_mc_del1_src(struct ifmcaddr6 *pmc, int sfmode,