Additions are highlighted in red


int igmp_rcv(struct sk_buff *skb)
{
 /* This basically follows the spec line by line -- see RFC1112 */
 struct igmphdr *ih = skb->h.igmph;
 struct in_device *in_dev = in_dev_get(skb->dev);
 int len = skb->len;

 if (in_dev==NULL) {
  kfree_skb(skb);
  return 0;
 }

 if (skb_is_nonlinear(skb)) {
  if (skb_linearize(skb, GFP_ATOMIC) != 0) {
   kfree_skb(skb);
   return -ENOMEM;
  }
  ih = skb->h.igmph;
 }

 if (len < sizeof(struct igmphdr) || ip_compute_csum((void *)ih, len)) {
  in_dev_put(in_dev);
  kfree_skb(skb);
  return 0;
 }

 /*
  Checks if packet's ethernet address is a Multicast
 ethernet address. If not, packet is dropped
  */
if (skb->pkt_type!=PACKET_MULTICAST) {
                in_dev_put(in_dev);
                kfree_skb(skb);
                return 0;
        }
 

 switch (ih->type) {
 case IGMP_HOST_MEMBERSHIP_QUERY:
  igmp_heard_query(in_dev, ih->code, ih->group);
  break;
 case IGMP_HOST_MEMBERSHIP_REPORT:
 case IGMP_HOST_NEW_MEMBERSHIP_REPORT:
  /* Is it our report looped back? */
  if (((struct rtable*)skb->dst)->key.iif == 0)
   break;
  igmp_heard_report(in_dev, ih->group);
  break;
 case IGMP_PIM:
#ifdef CONFIG_IP_PIMSM_V1
  in_dev_put(in_dev);
  return pim_rcv_v1(skb);
#endif
 case IGMP_DVMRP:
 case IGMP_TRACE:
 case IGMP_HOST_LEAVE_MESSAGE:
 case IGMP_MTRACE:
 case IGMP_MTRACE_RESP:
  break;
 default:
  NETDEBUG(printk(KERN_DEBUG "New IGMP type=%d, why we do not know about it?\n", ih->type));
 }
 in_dev_put(in_dev);
 kfree_skb(skb);
 return 0;
}