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

Commit 41927178 authored by YOSHIFUJI Hideaki's avatar YOSHIFUJI Hideaki
Browse files

[IPV6] MCAST: Use standard path for sending MLD/MLDv2 messages.



This is changing the paths for sending MLD/MLDv2 messages
from dev_queue_xmit() to standard dst_output().

Signed-off-by: default avatarYOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
parent 3b00944c
Loading
Loading
Loading
Loading
+45 −21
Original line number Diff line number Diff line
@@ -1433,25 +1433,6 @@ static struct sk_buff *mld_newpack(struct net_device *dev, int size)
	return skb;
}

static inline int mld_dev_queue_xmit2(struct sk_buff *skb)
{
	struct net_device *dev = skb->dev;
	unsigned char ha[MAX_ADDR_LEN];

	ndisc_mc_map(&ipv6_hdr(skb)->daddr, ha, dev, 1);
	if (dev_hard_header(skb, dev, ETH_P_IPV6, ha, NULL, skb->len) < 0) {
		kfree_skb(skb);
		return -EINVAL;
	}
	return dev_queue_xmit(skb);
}

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

static void mld_sendpack(struct sk_buff *skb)
{
	struct ipv6hdr *pip6 = ipv6_hdr(skb);
@@ -1460,6 +1441,7 @@ static void mld_sendpack(struct sk_buff *skb)
	int payload_len, mldlen;
	struct inet6_dev *idev = in6_dev_get(skb->dev);
	int err;
	struct flowi fl;

	IP6_INC_STATS(idev, IPSTATS_MIB_OUTREQUESTS);
	payload_len = (skb->tail - skb->network_header) - sizeof(*pip6);
@@ -1469,8 +1451,25 @@ static void mld_sendpack(struct sk_buff *skb)
	pmr->csum = csum_ipv6_magic(&pip6->saddr, &pip6->daddr, mldlen,
		IPPROTO_ICMPV6, csum_partial(skb_transport_header(skb),
					     mldlen, 0));

	skb->dst = icmp6_dst_alloc(skb->dev, NULL, &ipv6_hdr(skb)->daddr);

	if (!skb->dst) {
		err = -ENOMEM;
		goto err_out;
	}

	icmpv6_flow_init(igmp6_socket->sk, &fl, ICMPV6_MLD2_REPORT,
			 &ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr,
			 skb->dev->ifindex);

	err = xfrm_lookup(&skb->dst, &fl, NULL, 0);
	if (err)
		goto err_out;

	err = NF_HOOK(PF_INET6, NF_INET_LOCAL_OUT, skb, NULL, skb->dev,
		mld_dev_queue_xmit);
		      dst_output);
out:
	if (!err) {
		ICMP6MSGOUT_INC_STATS_BH(idev, ICMPV6_MLD2_REPORT);
		ICMP6_INC_STATS_BH(idev, ICMP6_MIB_OUTMSGS);
@@ -1480,6 +1479,11 @@ static void mld_sendpack(struct sk_buff *skb)

	if (likely(idev != NULL))
		in6_dev_put(idev);
	return;

err_out:
	kfree_skb(skb);
	goto out;
}

static int grec_size(struct ifmcaddr6 *pmc, int type, int gdel, int sdel)
@@ -1761,6 +1765,7 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type)
	u8 ra[8] = { IPPROTO_ICMPV6, 0,
		     IPV6_TLV_ROUTERALERT, 2, 0, 0,
		     IPV6_TLV_PADN, 0 };
	struct flowi fl;

	rcu_read_lock();
	IP6_INC_STATS(__in6_dev_get(dev),
@@ -1813,8 +1818,23 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type)

	idev = in6_dev_get(skb->dev);

	skb->dst = icmp6_dst_alloc(skb->dev, NULL, &ipv6_hdr(skb)->daddr);
	if (!skb->dst) {
		err = -ENOMEM;
		goto err_out;
	}

	icmpv6_flow_init(igmp6_socket->sk, &fl, type,
			 &ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr,
			 skb->dev->ifindex);

	err = xfrm_lookup(&skb->dst, &fl, NULL, 0);
	if (err)
		goto err_out;

	err = NF_HOOK(PF_INET6, NF_INET_LOCAL_OUT, skb, NULL, skb->dev,
		mld_dev_queue_xmit);
		      dst_output);
out:
	if (!err) {
		ICMP6MSGOUT_INC_STATS(idev, type);
		ICMP6_INC_STATS(idev, ICMP6_MIB_OUTMSGS);
@@ -1825,6 +1845,10 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type)
	if (likely(idev != NULL))
		in6_dev_put(idev);
	return;

err_out:
	kfree_skb(skb);
	goto out;
}

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