Exemplo n.º 1
0
FAR struct igmp_group_s *igmp_grpallocfind(FAR struct net_driver_s *dev,
                                           FAR const in_addr_t *addr)
{
  FAR struct igmp_group_s *group = igmp_grpfind(dev, addr);

  grplldbg("group: %p addr: %08x\n", group, (int)*addr);
  if (!group)
    {
      group = igmp_grpalloc(dev, addr);
    }

  grplldbg("group: %p\n", group);
  return group;
}
Exemplo n.º 2
0
int ipv4_input(FAR struct net_driver_s *dev)
{
  FAR struct ipv4_hdr_s *pbuf = BUF;
  uint16_t iplen;

  /* This is where the input processing starts. */

#ifdef CONFIG_NET_STATISTICS
  g_netstats.ipv4.recv++;
#endif

  /* Start of IP input header processing code. */
  /* Check validity of the IP header. */

  if (pbuf->vhl != 0x45)
    {
      /* IP version and header length. */

#ifdef CONFIG_NET_STATISTICS
      g_netstats.ipv4.drop++;
      g_netstats.ipv4.vhlerr++;
#endif
      nlldbg("Invalid IP version or header length: %02x\n", pbuf->vhl);
      goto drop;
    }

  /* Check the size of the packet. If the size reported to us in d_len is
   * smaller the size reported in the IP header, we assume that the packet
   * has been corrupted in transit. If the size of d_len is larger than the
   * size reported in the IP packet header, the packet has been padded and
   * we set d_len to the correct value.
   */

  iplen = (pbuf->len[0] << 8) + pbuf->len[1];
  if (iplen <= dev->d_len)
    {
      dev->d_len = iplen;
    }
  else
    {
      nlldbg("IP packet shorter than length in IP header\n");
      goto drop;
    }

  /* Check the fragment flag. */

  if ((pbuf->ipoffset[0] & 0x3f) != 0 || pbuf->ipoffset[1] != 0)
    {
#if defined(CONFIG_NET_TCP_REASSEMBLY)
      dev->d_len = devif_reassembly();
      if (dev->d_len == 0)
        {
          goto drop;
        }
#else /* CONFIG_NET_TCP_REASSEMBLY */
#ifdef CONFIG_NET_STATISTICS
      g_netstats.ipv4.drop++;
      g_netstats.ipv4.fragerr++;
#endif
      nlldbg("IP fragment dropped\n");
      goto drop;
#endif /* CONFIG_NET_TCP_REASSEMBLY */
    }

   /* If IP broadcast support is configured, we check for a broadcast
    * UDP packet, which may be destined to us (even if there is no IP
    * address yet assigned to the device as is the case when we are
    * negotiating over DHCP for an address).
    */

#if defined(CONFIG_NET_BROADCAST) && defined(CONFIG_NET_UDP_STACK)
  if (pbuf->proto == IP_PROTO_UDP &&
      net_ipv4addr_cmp(net_ip4addr_conv32(pbuf->destipaddr),
                       g_ipv4_alloneaddr))
    {
      return udp_ipv4_input(dev);
    }

  /* In most other cases, the device must be assigned a non-zero IP
   * address.  Another exception is when CONFIG_NET_PINGADDRCONF is
   * enabled...
   */

  else
#endif
#ifdef CONFIG_NET_ICMP
  if (net_ipv4addr_cmp(dev->d_ipaddr, g_ipv4_allzeroaddr))
    {
      /* If we are configured to use ping IP address configuration and
       * hasn't been assigned an IP address yet, we accept all ICMP
       * packets.
       */

#ifdef CONFIG_NET_PINGADDRCONF
      if (pbuf->proto == IP_PROTO_ICMP)
        {
          nlldbg("Possible ping config packet received\n");
          icmp_input(dev);
          goto drop;
        }
      else
#endif
        {
          nlldbg("No IP address assigned\n");
          goto drop;
        }
    }

  /* Check if the packet is destined for out IP address */
  else
#endif
    {
      /* Check if the packet is destined for our IP address. */

      if (!net_ipv4addr_cmp(net_ip4addr_conv32(pbuf->destipaddr), dev->d_ipaddr))
        {
#ifdef CONFIG_NET_IGMP
          in_addr_t destip = net_ip4addr_conv32(pbuf->destipaddr);
          if (igmp_grpfind(dev, &destip) == NULL)
#endif
            {
#ifdef CONFIG_NET_STATISTICS
              g_netstats.ipv4.drop++;
#endif
              goto drop;
            }
        }
    }

  if (ipv4_chksum(dev) != 0xffff)
    {
      /* Compute and check the IP header checksum. */

#ifdef CONFIG_NET_STATISTICS
      g_netstats.ipv4.drop++;
      g_netstats.ipv4.chkerr++;
#endif
      nlldbg("Bad IP checksum\n");
      goto drop;
    }

  /* Make sure that all packet processing logic knows that there is an IPv4
   * packet in the device buffer.
   */

  IFF_SET_IPv4(dev->d_flags);

  /* Now process the incoming packet according to the protocol. */

  switch (pbuf->proto)
    {
#ifdef CONFIG_NET_TCP_STACK
      case IP_PROTO_TCP:   /* TCP input */
        tcp_ipv4_input(dev);
        break;
#endif

#ifdef CONFIG_NET_UDP_STACK
      case IP_PROTO_UDP:   /* UDP input */
        udp_ipv4_input(dev);
        break;
#endif

  /* Check for ICMP input */

#ifdef CONFIG_NET_ICMP
      case IP_PROTO_ICMP:  /* ICMP input */
        icmp_input(dev);
        break;
#endif

  /* Check for IGMP input */

#ifdef CONFIG_NET_IGMP
      case IP_PROTO_IGMP:  /* IGMP input */
        igmp_input(dev);
        break;
#endif

      default:              /* Unrecognized/unsupported protocol */
#ifdef CONFIG_NET_STATISTICS
        g_netstats.ipv4.drop++;
        g_netstats.ipv4.protoerr++;
#endif

        nlldbg("Unrecognized IP protocol\n");
        goto drop;
    }

  /* Return and let the caller do any pending transmission. */

  return OK;

  /* Drop the packet.  NOTE that OK is returned meaning that the
   * packet has been processed (although processed unsuccessfully).
   */

drop:
  dev->d_len = 0;
  return OK;
}