Пример #1
0
static uint16_t arp_send_eventhandler(FAR struct net_driver_s *dev,
                                      FAR void *pvconn,
                                      FAR void *priv, uint16_t flags)
{
  FAR struct arp_send_s *state = (FAR struct arp_send_s *)priv;

  ninfo("flags: %04x sent: %d\n", flags, state->snd_sent);

  if (state)
    {
      /* Check if the network is still up */

      if ((flags & NETDEV_DOWN) != 0)
        {
          nerr("ERROR: Interface is down\n");
          arp_send_terminate(state, -ENETUNREACH);
          return flags;
        }

      /* Check if the outgoing packet is available. It may have been claimed
       * by a send event handler serving a different thread -OR- if the
       * output buffer currently contains unprocessed incoming data. In
       * these cases we will just have to wait for the next polling cycle.
       */

      if (dev->d_sndlen > 0 || (flags & PKT_NEWDATA) != 0)
        {
          /* Another thread has beat us sending data or the buffer is busy,
           * Check for a timeout. If not timed out, wait for the next
           * polling cycle and check again.
           */

          /* REVISIT: No timeout. Just wait for the next polling cycle */

          return flags;
        }

      /* It looks like we are good to send the data */
      /* Copy the packet data into the device packet buffer and send it */

      arp_format(dev, state->snd_ipaddr);

      /* Make sure no ARP request overwrites this ARP request.  This
       * flag will be cleared in arp_out().
       */

      IFF_SET_NOARP(dev->d_flags);

      /* Don't allow any further call backs. */

      arp_send_terminate(state, OK);
    }

  return flags;
}
Пример #2
0
void icmpv6_solicit(FAR struct net_driver_s *dev,
                    FAR const net_ipv6addr_t ipaddr)
{
    FAR struct icmpv6_iphdr_s *icmp;
    FAR struct icmpv6_neighbor_solicit_s *sol;
    FAR struct eth_hdr_s *eth;

    /* Set up the IPv6 header (most is probably already in place) */

    icmp          = ICMPv6BUF;
    icmp->vtc     = 0x60;                    /* Version/traffic class (MS) */
    icmp->tcf     = 0;                       /* Traffic class (LS)/Flow label (MS) */
    icmp->flow    = 0;                       /* Flow label (LS) */

    /* Length excludes the IPv6 header */

    icmp->len[0]  = (sizeof(struct icmpv6_neighbor_solicit_s) >> 8);
    icmp->len[1]  = (sizeof(struct icmpv6_neighbor_solicit_s) & 0xff);

    icmp->proto   = IP_PROTO_ICMP6;          /* Next header */
    icmp->ttl     = 255;                     /* Hop limit */

    /* Set the multicast destination IP address */

    memcpy(icmp->destipaddr, g_icmpv_mcastaddr, 6*sizeof(uint16_t));
    icmp->destipaddr[6] = ipaddr[6] | HTONS(0xff00);
    icmp->destipaddr[7] = ipaddr[7];

    /* Add out IPv6 address as the source address */

    net_ipv6addr_copy(icmp->srcipaddr, dev->d_ipv6addr);

    /* Set up the ICMPv6 Neighbor Solicitation message */

    sol           = ICMPv6SOLICIT;
    sol->type     = ICMPv6_NEIGHBOR_SOLICIT; /* Message type */
    sol->code     = 0;                       /* Message qualifier */
    sol->flags[0] = 0;                       /* flags */
    sol->flags[1] = 0;
    sol->flags[2] = 0;
    sol->flags[3] = 0;

    /* Copy the target address into the Neighbor Solicitation message */

    net_ipv6addr_copy(sol->tgtaddr, ipaddr);

    /* Set up the options */

    sol->opttype  = ICMPv6_OPT_SRCLLADDR;    /* Option type */
    sol->optlen   = 1;                       /* Option length = 1 octet */

    /* Copy our link layer address into the message
     * REVISIT:  What if the link layer is not Ethernet?
     */

    memcpy(sol->srclladdr, &dev->d_mac, IFHWADDRLEN);

    /* Calculate the checksum over both the ICMP header and payload */

    icmp->chksum  = 0;
    icmp->chksum  = ~icmpv6_chksum(dev);

    /* Set the size to the size of the IPv6 header and the payload size */

    dev->d_len    = IPv6_HDRLEN + sizeof(struct icmpv6_neighbor_solicit_s);

#ifdef CONFIG_NET_ETHERNET
#ifdef CONFIG_NET_MULTILINK
    if (dev->d_lltype == NET_LL_ETHERNET)
#endif
    {
        /* Set the destination IPv6 multicast Ethernet address:
         *
         * For IPv6 multicast addresses, the Ethernet MAC is derived by
         * the four low-order octets OR'ed with the MAC 33:33:00:00:00:00,
         * so for example the IPv6 address FF02:DEAD:BEEF::1:3 would map
         * to the Ethernet MAC address 33:33:00:01:00:03.
         *
         * NOTES:  This appears correct for the ICMPv6 Router Solicitation
         * Message, but the ICMPv6 Neighbor Solicitation message seems to
         * use 33:33:ff:01:00:03.
         */

        eth          = ETHBUF;
        eth->dest[0] = 0x33;
        eth->dest[1] = 0x33;
        eth->dest[2] = 0xff;
        eth->dest[3] = ipaddr[6] >> 8;
        eth->dest[4] = ipaddr[7] & 0xff;
        eth->dest[5] = ipaddr[7] >> 8;

        /* Move our source Ethernet addresses into the Ethernet header */

        memcpy(eth->src, dev->d_mac.ether_addr_octet, ETHER_ADDR_LEN);

        /* Set the IPv6 Ethernet type */

        eth->type  = HTONS(ETHTYPE_IP6);
#if 0
        /* No additional neighbor lookup is required on this packet.
         * REVISIT:  It is inappropriate to set this bit if we get here
         * via neighbor_out(); It is no necessary to set this bit if we
         * get here via icmpv6_input().  Is it ever necessary?
         */

        IFF_SET_NOARP(dev->d_flags);
#endif
    }
Пример #3
0
static uint16_t icmpv6_neighbor_interrupt(FAR struct net_driver_s *dev,
                                          FAR void *pvconn,
                                          FAR void *priv, uint16_t flags)
{
  FAR struct icmpv6_neighbor_s *state = (FAR struct icmpv6_neighbor_s *)priv;

  nllvdbg("flags: %04x sent: %d\n", flags, state->snd_sent);

  if (state)
    {
#ifdef CONFIG_NETDEV_MULTINIC
      /* Is this the device that we need to route this request? */

      if (strncmp((FAR const char *)dev->d_ifname,
                  (FAR const char *)state->snd_ifname, IFNAMSIZ) != 0)
        {
          /* No... pass on this one and wait for the device that we want */

          return flags;
        }

#endif

      /* Check if the outgoing packet is available. It may have been claimed
       * by a send interrupt serving a different thread -OR- if the output
       * buffer currently contains unprocessed incoming data. In these cases
       * we will just have to wait for the next polling cycle.
       */

      if (dev->d_sndlen > 0 || (flags & ICMPv6_NEWDATA) != 0)
        {
          /* Another thread has beat us sending data or the buffer is busy,
           * Check for a timeout. If not timed out, wait for the next
           * polling cycle and check again.
           */

          /* REVISIT: No timeout. Just wait for the next polling cycle */

          return flags;
        }

      /* It looks like we are good to send the data */
      /* Copy the packet data into the device packet buffer and send it */

      icmpv6_solicit(dev, state->snd_ipaddr);

      /* Make sure no additional Neighbor Solicitation overwrites this one.
       * This flag will be cleared in icmpv6_out().
       */

      IFF_SET_NOARP(dev->d_flags);

      /* Don't allow any further call backs. */

      state->snd_sent         = true;
      state->snd_cb->flags    = 0;
      state->snd_cb->priv     = NULL;
      state->snd_cb->event    = NULL;

      /* Wake up the waiting thread */

      sem_post(&state->snd_sem);
    }

  return flags;
}
Пример #4
0
static uint16_t icmpv6_router_interrupt(FAR struct net_driver_s *dev,
                                        FAR void *pvconn,
                                        FAR void *priv, uint16_t flags)
{
  FAR struct icmpv6_router_s *state = (FAR struct icmpv6_router_s *)priv;

  ninfo("flags: %04x sent: %d\n", flags, state->snd_sent);

  if (state)
    {
      /* Check if the network is still up */

      if ((flags & NETDEV_DOWN) != 0)
        {
          nerr("ERROR: Interface is down\n");
          icmpv6_router_terminate(state, -ENETUNREACH);
          return flags;
        }

      /* Check if the outgoing packet is available. It may have been claimed
       * by a send interrupt serving a different thread -OR- if the output
       * buffer currently contains unprocessed incoming data. In these cases
       * we will just have to wait for the next polling cycle.
       */

      else if (dev->d_sndlen > 0 || (flags & ICMPv6_NEWDATA) != 0)
        {
          /* Another thread has beat us sending data or the buffer is busy,
           * Check for a timeout. If not timed out, wait for the next
           * polling cycle and check again.
           */

          /* REVISIT: No timeout. Just wait for the next polling cycle */

          return flags;
        }

      /* It looks like we are good to send the data */
      /* Copy the packet data into the device packet buffer and send it */

      if (state->snd_advertise)
        {
          /* Send the ICMPv6 Neighbor Advertisement message */

          icmpv6_advertise(dev, g_ipv6_allnodes);
        }
      else
        {
          /* Send the ICMPv6 Router Solicitation message */

          icmpv6_rsolicit(dev);
        }

      /* Make sure no additional Router Solicitation overwrites this one.
       * This flag will be cleared in icmpv6_out().
       */

      IFF_SET_NOARP(dev->d_flags);

      /* Don't allow any further call backs. */

      icmpv6_router_terminate(state, OK);
    }

  return flags;
}