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

Commit daad1512 authored by YOSHIFUJI Hideaki / 吉藤英明's avatar YOSHIFUJI Hideaki / 吉藤英明 Committed by David S. Miller
Browse files

ipv6: Make ipv6_is_mld() inline and use it from ip6_mc_input().



Move generalized version of ipv6_is_mld() to header,
and use it from ip6_mc_input().

Signed-off-by: default avatarYOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent e7219858
Loading
Loading
Loading
Loading
+25 −1
Original line number Diff line number Diff line
@@ -150,7 +150,31 @@ extern void addrconf_dad_failure(struct inet6_ifaddr *ifp);
extern bool ipv6_chk_mcast_addr(struct net_device *dev,
				const struct in6_addr *group,
				const struct in6_addr *src_addr);
extern bool ipv6_is_mld(struct sk_buff *skb, int nexthdr);

/*
 * identify MLD packets for MLD filter exceptions
 */
static inline bool ipv6_is_mld(struct sk_buff *skb, int nexthdr, int offset)
{
	struct icmp6hdr *hdr;

	if (nexthdr != IPPROTO_ICMPV6 ||
	    !pskb_network_may_pull(skb, offset + sizeof(struct icmp6hdr)))
		return false;

	hdr = (struct icmp6hdr *)(skb_network_header(skb) + offset);

	switch (hdr->icmp6_type) {
	case ICMPV6_MGM_QUERY:
	case ICMPV6_MGM_REPORT:
	case ICMPV6_MGM_REDUCTION:
	case ICMPV6_MLD2_REPORT:
		return true;
	default:
		break;
	}
	return false;
}

extern void addrconf_prefix_rcv(struct net_device *dev,
				u8 *opt, int len, bool sllao);
+3 −18
Original line number Diff line number Diff line
@@ -212,7 +212,7 @@ static int ip6_input_finish(struct sk_buff *skb)
			if (ipv6_addr_is_multicast(&hdr->daddr) &&
			    !ipv6_chk_mcast_addr(skb->dev, &hdr->daddr,
			    &hdr->saddr) &&
			    !ipv6_is_mld(skb, nexthdr))
			    !ipv6_is_mld(skb, nexthdr, skb_network_header_len(skb)))
				goto discard;
		}
		if (!(ipprot->flags & INET6_PROTO_NOPOLICY) &&
@@ -283,7 +283,6 @@ int ip6_mc_input(struct sk_buff *skb)
		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;
			__be16 frag_off;
			int offset;
@@ -303,24 +302,10 @@ int ip6_mc_input(struct sk_buff *skb)
				if (offset < 0)
					goto out;

				if (nexthdr != IPPROTO_ICMPV6)
				if (!ipv6_is_mld(skb, nexthdr, offset))
					goto out;

				if (!pskb_may_pull(skb, (skb_network_header(skb) +
						   offset + 1 - skb->data)))
					goto out;

				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:
				deliver = true;
					break;
				}
				goto out;
			}
			/* unknown RA - process it normally */
		}
+0 −27
Original line number Diff line number Diff line
@@ -934,33 +934,6 @@ int ipv6_dev_mc_dec(struct net_device *dev, const struct in6_addr *addr)
	return err;
}

/*
 * identify MLD packets for MLD filter exceptions
 */
bool ipv6_is_mld(struct sk_buff *skb, int nexthdr)
{
	struct icmp6hdr *pic;

	if (nexthdr != IPPROTO_ICMPV6)
		return false;

	if (!pskb_may_pull(skb, sizeof(struct icmp6hdr)))
		return false;

	pic = icmp6_hdr(skb);

	switch (pic->icmp6_type) {
	case ICMPV6_MGM_QUERY:
	case ICMPV6_MGM_REPORT:
	case ICMPV6_MGM_REDUCTION:
	case ICMPV6_MLD2_REPORT:
		return true;
	default:
		break;
	}
	return false;
}

/*
 *	check if the interface/address pair is valid
 */