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);
 
                        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) &&
                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;
                                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;
+                               deliver = true;
                        }
                        /* unknown RA - process it normally */
                }
 
        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
  */