コード例 #1
0
ファイル: icmpv6_rnotify.c プロジェクト: dagar/NuttX
static void icmpv6_setaddresses(FAR struct net_driver_s *dev,
                                const net_ipv6addr_t draddr,
                                const net_ipv6addr_t prefix,
                                unsigned int preflen)
{
  unsigned int i;

  /* Make sure that the network is down before changing any addresses */

  netdev_ifdown(dev);

  /* Create an address mask from the prefix */

  if (preflen > 128)
    {
      preflen = 128;
    }

  net_ipv6_pref2mask(preflen, dev->d_ipv6netmask);

  ninfo("preflen=%d netmask=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
        preflen, dev->d_ipv6netmask[0], dev->d_ipv6netmask[1],
        dev->d_ipv6netmask[2], dev->d_ipv6netmask[3], dev->d_ipv6netmask[4],
        dev->d_ipv6netmask[5], dev->d_ipv6netmask[6], dev->d_ipv6netmask[7]);

  /* Copy prefix to the current IPv6 address, applying the mask */

  for (i = 0; i < 7; i++)
    {
      dev->d_ipv6addr[i] = (dev->d_ipv6addr[i] & ~dev->d_ipv6netmask[i]) |
                           (prefix[i] & dev->d_ipv6netmask[i]);
    }

  ninfo("prefix=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
        prefix[0], prefix[1], prefix[2], prefix[3],
        prefix[4], prefix[6], prefix[6], prefix[7]);
  ninfo("IP address=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
        dev->d_ipv6addr[0], dev->d_ipv6addr[1], dev->d_ipv6addr[2],
        dev->d_ipv6addr[3], dev->d_ipv6addr[4], dev->d_ipv6addr[6],
        dev->d_ipv6addr[6], dev->d_ipv6addr[7]);

  /* Finally, copy the router address */

  net_ipv6addr_copy(dev->d_ipv6draddr, draddr);

  ninfo("DR address=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
        dev->d_ipv6draddr[0], dev->d_ipv6draddr[1], dev->d_ipv6draddr[2],
        dev->d_ipv6draddr[3], dev->d_ipv6draddr[4], dev->d_ipv6draddr[6],
        dev->d_ipv6draddr[6], dev->d_ipv6draddr[7]);
}
コード例 #2
0
ファイル: up_netdriver.c プロジェクト: AlexShiLucky/NuttX
int netdriver_ifdown(struct net_driver_s *dev)
{
  netdev_ifdown();
  return OK;
}
コード例 #3
0
static int netdev_ifrioctl(FAR struct socket *psock, int cmd,
                           FAR struct ifreq *req)
{
  FAR struct net_driver_s *dev;
  int ret = -EINVAL;

  nvdbg("cmd: %d\n", cmd);

  /* Execute the command */

  switch (cmd)
    {
#ifdef CONFIG_NET_IPv4
      case SIOCGIFADDR:  /* Get IP address */
        {
          dev = netdev_ifrdev(req);
          if (dev)
            {
              ioctl_getipv4addr(&req->ifr_addr, dev->d_ipaddr);
              ret = OK;
            }
        }
        break;
#endif


#ifdef CONFIG_NET_IPv4
      case SIOCSIFADDR:  /* Set IP address */
        {
          dev = netdev_ifrdev(req);
          if (dev)
            {
              netdev_ifdown(dev);
              ioctl_setipv4addr(&dev->d_ipaddr, &req->ifr_addr);
              netdev_ifup(dev);
              ret = OK;
            }
        }
        break;
#endif

#ifdef CONFIG_NET_IPv4
      case SIOCGIFDSTADDR:  /* Get P-to-P address */
        {
          dev = netdev_ifrdev(req);
          if (dev)
            {
              ioctl_getipv4addr(&req->ifr_dstaddr, dev->d_draddr);
              ret = OK;
            }
        }
        break;
#endif

#ifdef CONFIG_NET_IPv4
      case SIOCSIFDSTADDR:  /* Set P-to-P address */
        {
          dev = netdev_ifrdev(req);
          if (dev)
            {
              ioctl_setipv4addr(&dev->d_draddr, &req->ifr_dstaddr);
              ret = OK;
            }
        }
        break;
#endif

#ifdef CONFIG_NET_IPv4
      case SIOCGIFBRDADDR:  /* Get broadcast IP address */
      case SIOCSIFBRDADDR:  /* Set broadcast IP address */
        {
          ret = -ENOSYS;
        }
        break;
#endif

#ifdef CONFIG_NET_IPv4
      case SIOCGIFNETMASK:  /* Get network mask */
        {
          dev = netdev_ifrdev(req);
          if (dev)
            {
              ioctl_getipv4addr(&req->ifr_addr, dev->d_netmask);
              ret = OK;
            }
        }
        break;
#endif

#ifdef CONFIG_NET_IPv4
      case SIOCSIFNETMASK:  /* Set network mask */
        {
          dev = netdev_ifrdev(req);
          if (dev)
            {
              ioctl_setipv4addr(&dev->d_netmask, &req->ifr_addr);
              ret = OK;
            }
        }
        break;
#endif

#ifdef CONFIG_NET_IPv6
      case SIOCGLIFADDR:  /* Get IP address */
        {
          dev = netdev_ifrdev(req);
          if (dev)
            {
              FAR struct lifreq *lreq = (FAR struct lifreq *)req;

              ioctl_getipv6addr(&lreq->lifr_addr, dev->d_ipv6addr);
              ret = OK;
            }
        }
        break;
#endif

#ifdef CONFIG_NET_IPv6
      case SIOCSLIFADDR:  /* Set IP address */
        {
          dev = netdev_ifrdev(req);
          if (dev)
            {
              FAR struct lifreq *lreq = (FAR struct lifreq *)req;

              netdev_ifdown(dev);
              ioctl_setipv6addr(dev->d_ipv6addr, &lreq->lifr_addr);
              netdev_ifup(dev);
              ret = OK;
            }
        }
        break;
#endif

#ifdef CONFIG_NET_IPv6
      case SIOCGLIFDSTADDR:  /* Get P-to-P address */
        {
          dev = netdev_ifrdev(req);
          if (dev)
            {
              FAR struct lifreq *lreq = (FAR struct lifreq *)req;

              ioctl_getipv6addr(&lreq->lifr_dstaddr, dev->d_ipv6draddr);
              ret = OK;
            }
        }
        break;
#endif

#ifdef CONFIG_NET_IPv6
      case SIOCSLIFDSTADDR:  /* Set P-to-P address */
        {
          dev = netdev_ifrdev(req);
          if (dev)
            {
              FAR struct lifreq *lreq = (FAR struct lifreq *)req;

              ioctl_setipv6addr(dev->d_ipv6draddr, &lreq->lifr_dstaddr);
              ret = OK;
            }
        }
        break;
#endif

#ifdef CONFIG_NET_IPv6
      case SIOCGLIFBRDADDR:  /* Get broadcast IP address */
      case SIOCSLIFBRDADDR:  /* Set broadcast IP address */
        {
          ret = -ENOSYS;
        }
        break;
#endif

#ifdef CONFIG_NET_IPv6
      case SIOCGLIFNETMASK:  /* Get network mask */
        {
          dev = netdev_ifrdev(req);
          if (dev)
            {
              FAR struct lifreq *lreq = (FAR struct lifreq *)req;

              ioctl_getipv6addr(&lreq->lifr_addr, dev->d_ipv6netmask);
              ret = OK;
            }
        }
        break;
#endif

#ifdef CONFIG_NET_IPv6
      case SIOCSLIFNETMASK:  /* Set network mask */
        {
          dev = netdev_ifrdev(req);
          if (dev)
            {
              FAR struct lifreq *lreq = (FAR struct lifreq *)req;
              ioctl_setipv6addr(dev->d_ipv6netmask, &lreq->lifr_addr);
              ret = OK;
            }
        }
        break;
#endif

      case SIOCGLIFMTU:  /* Get MTU size */
      case SIOCGIFMTU:   /* Get MTU size */
        {
          dev = netdev_ifrdev(req);
          if (dev)
            {
              req->ifr_mtu = NET_DEV_MTU(dev);
              ret = OK;
            }
        }
        break;

#ifdef CONFIG_NET_ICMPv6_AUTOCONF
      case SIOCIFAUTOCONF:  /* Perform ICMPv6 auto-configuration */
        {
          dev = netdev_ifrdev(req);
          if (dev)
            {
              ret = icmpv6_autoconfig(dev);
            }
        }
        break;
#endif

      case SIOCSIFFLAGS:  /* Sets the interface flags */
        {
          /* Is this a request to bring the interface up? */

          dev = netdev_ifrdev(req);
          if (dev)
            {
              if (req->ifr_flags & IFF_UP)
                {
                  /* Yes.. bring the interface up */

                  netdev_ifup(dev);
                }

              /* Is this a request to take the interface down? */

              else if (req->ifr_flags & IFF_DOWN)
                {
                  /* Yes.. take the interface down */

                  netdev_ifdown(dev);
                }
            }

          ret = OK;
        }
        break;

      case SIOCGIFFLAGS:  /* Gets the interface flags */
        {
          dev = netdev_ifrdev(req);
          if (dev)
            {
              req->ifr_flags = dev->d_flags;
            }

          ret = OK;
        }
        break;

      /* MAC address operations only make sense if Ethernet is supported */

#ifdef CONFIG_NET_ETHERNET
      case SIOCGIFHWADDR:  /* Get hardware address */
        {
          dev = netdev_ifrdev(req);
          if (dev)
            {
              req->ifr_hwaddr.sa_family = AF_INETX;
              memcpy(req->ifr_hwaddr.sa_data,
                     dev->d_mac.ether_addr_octet, IFHWADDRLEN);
              ret = OK;
            }
        }
        break;

      case SIOCSIFHWADDR:  /* Set hardware address -- will not take effect until ifup */
        {
          dev = netdev_ifrdev(req);
          if (dev)
            {
              memcpy(dev->d_mac.ether_addr_octet,
                     req->ifr_hwaddr.sa_data, IFHWADDRLEN);
              ret = OK;
            }
        }
        break;
#endif

      case SIOCDIFADDR:  /* Delete IP address */
        {
          dev = netdev_ifrdev(req);
          if (dev)
            {
              netdev_ifdown(dev);
#ifdef CONFIG_NET_IPv4
              dev->d_ipaddr = 0;
#endif
#ifdef CONFIG_NET_IPv6
              memset(&dev->d_ipv6addr, 0, sizeof(net_ipv6addr_t));
#endif
              ret = OK;
            }
        }
        break;

      case SIOCGIFCOUNT:  /* Get number of devices */
        {
          req->ifr_count = netdev_count();
          ret = -ENOSYS;
        }
        break;

#ifdef CONFIG_NET_ARPIOCTLS
      case SIOCSARP:  /* Set a ARP mapping */
      case SIOCDARP:  /* Delete an ARP mapping */
      case SIOCGARP:  /* Get an ARP mapping */
# error "IOCTL Commands not implemented"
#endif

#ifdef CONFIG_NETDEV_PHY_IOCTL
#ifdef CONFIG_ARCH_PHY_INTERRUPT
      case SIOCMIINOTIFY: /* Set up for PHY event notifications */
        {
          dev = netdev_ifrdev(req);
          if (dev && dev->d_ioctl)
            {
              struct mii_iotcl_notify_s *notify = &req->ifr_ifru.ifru_mii_notify;
              ret = dev->d_ioctl(dev, cmd, ((long)(uintptr_t)notify));
            }
        }
        break;
#endif

      case SIOCGMIIPHY: /* Get address of MII PHY in use */
      case SIOCGMIIREG: /* Get MII register via MDIO */
      case SIOCSMIIREG: /* Set MII register via MDIO */
        {
          dev = netdev_ifrdev(req);
          if (dev && dev->d_ioctl)
            {
              struct mii_ioctl_data_s *mii_data = &req->ifr_ifru.ifru_mii_data;
              ret = dev->d_ioctl(dev, cmd, ((long)(uintptr_t)mii_data));
            }
        }
        break;
#endif

      default:
        {
          ret = -ENOTTY;
        }
        break;;
    }

  return ret;
}
コード例 #4
0
ファイル: icmpv6_autoconfig.c プロジェクト: a1ien/nuttx
int icmpv6_autoconfig(FAR struct net_driver_s *dev)
{
#ifndef CONFIG_NET_ETHERNET
  /* Only Ethernet supported for now */

  nerr("ERROR: Only Ethernet is supported\n");
  return -ENOSYS;

#else /* CONFIG_NET_ETHERNET */
  struct icmpv6_rnotify_s notify;
  net_ipv6addr_t lladdr;
  int retries;
  int ret;

  /* Sanity checks */

  DEBUGASSERT(dev);
  ninfo("Auto-configuring %s\n", dev->d_ifname);

#ifdef CONFIG_NET_MULTILINK
  /* Only Ethernet devices are supported for now */

  if (dev->d_lltype != NET_LL_ETHERNET)
    {
      nerr("ERROR: Only Ethernet is supported\n");
      return -ENOSYS;
    }
#endif

  /* The interface should be in the down state */

  net_lock();
  netdev_ifdown(dev);
  net_unlock();

  /* IPv6 Stateless Autoconfiguration
   * Reference: http://www.tcpipguide.com/free/t_IPv6AutoconfigurationandRenumbering.htm
   *
   * The following is a summary of the steps a device takes when using
   * stateless auto-configuration:
   *
   * 1. Link-Local Address Generation: The device generates a link-local
   *    address. Recall that this is one of the two types of local-use IPv6
   *    addresses. Link-local addresses have "1111 1110 10" for the first
   *    ten bits. The generated address uses those ten bits followed by 54
   *    zeroes and then the 64 bit interface identifier. Typically this
   *    will be derived from the data link layer (MAC) address.
   *
   *    IEEE 802 MAC addresses, used by Ethernet and other IEEE 802 Project
   *    networking technologies, have 48 bits.  The IEEE has also defined a
   *    format called the 64-bit extended unique identifier, abbreviated
   *    EUI-64.  To get the modified EUI-64 interface ID for a device, you
   *    simply take the EUI-64 address and change the 7th bit from the left
   *    (the"universal/local" or "U/L" bit) from a zero to a one.
   *
   *    128  112  96   80    64   48   32   16
   *    ---- ---- ---- ----  ---- ---- ---- ----
   *    fe80 0000 0000 0000  0000 xxxx xxxx xxxx
   */

  lladdr[0] = HTONS(0xfe80);                        /* 10-bit address + 6 zeroes */
  memset(&lladdr[1], 0, 4 * sizeof(uint16_t));      /* 64 more zeroes */
  memcpy(&lladdr[5], dev->d_mac.ether_addr_octet,
        sizeof(struct ether_addr));                 /* 48-bit Ethernet address */

  ninfo("lladdr=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
        lladdr[0], lladdr[1], lladdr[2], lladdr[3],
        lladdr[4], lladdr[6], lladdr[6], lladdr[7]);

#ifdef CONFIG_NET_ICMPv6_NEIGHBOR
  /* Bring the interface up with no IP address */

  net_lock();
  netdev_ifup(dev);
  net_unlock();

  /* 2. Link-Local Address Uniqueness Test: The node tests to ensure that
   *    the address it generated isn't for some reason already in use on the
   *    local network. (This is very unlikely to be an issue if the link-local
   *    address came from a MAC address but more likely if it was based on a
   *    generated token.) It sends a Neighbor Solicitation message using the
   *    Neighbor Discovery (ND) protocol. It then listens for a Neighbor
   *    Advertisement in response that indicates that another device is
   *    already using its link-local address; if so, either a new address
   *    must be generated, or auto-configuration fails and another method
   *    must be employed.
   */

  ret = icmpv6_neighbor(lladdr);

  /* Take the interface back down */

  net_lock();
  netdev_ifdown(dev);
  net_unlock();

  if (ret == OK)
    {
      /* Hmmm... someone else responded to our Neighbor Solicitation.  We
       * have not back-up plan in place.  Just bail.
       */

      nerr("ERROR: IP conflict\n");
      return -EEXIST;
    }
#endif

  /* 3. Link-Local Address Assignment: Assuming the uniqueness test passes,
   *    the device assigns the link-local address to its IP interface. This
   *    address can be used for communication on the local network, but not
   *    on the wider Internet (since link-local addresses are not routed).
   */

  net_lock();
  net_ipv6addr_copy(dev->d_ipv6addr, lladdr);

  /* Bring the interface up with the new, temporary IP address */

  netdev_ifup(dev);

  /* 4. Router Contact: The node next attempts to contact a local router for
   *    more information on continuing the configuration. This is done either
   *    by listening for Router Advertisement messages sent periodically by
   *    routers, or by sending a specific Router Solicitation to ask a router
   *    for information on what to do next.
   */

  for (retries = 0; retries < CONFIG_ICMPv6_AUTOCONF_MAXTRIES; retries++)
    {
      /* Set up the Router Advertisement BEFORE we send the Router
       * Solicitation.
       */

      icmpv6_rwait_setup(dev, &notify);

      /* Send the ICMPv6 Router solicitation message */

      ret = icmpv6_send_message(dev, false);
      if (ret < 0)
        {
          nerr("ERROR: Failed send router solicitation: %d\n", ret);
          break;
        }

      /* Wait to receive the Router Advertisement message */

      ret = icmpv6_wait_radvertise(dev, &notify);
      if (ret != -ETIMEDOUT)
        {
          /* ETIMEDOUT is the only expected failure.  We will retry on that
           * case only.
           */

          break;
        }

      ninfo("Timed out... retrying %d\n", retries + 1);
    }

  /* Check for failures.  Note:  On successful return, the network will be 
   * in the down state, but not in the event of failures.
   */

  if (ret < 0)
    {
      nerr("ERROR: Failed to get the router advertisement: %d (retries=%d)\n",
           ret, retries);

      /* Claim the link local address as ours by sending the ICMPv6 Neighbor
       * Advertisement message.
       */

      ret = icmpv6_send_message(dev, true);
      if (ret < 0)
        {
          nerr("ERROR: Failed send neighbor advertisement: %d\n", ret);
          netdev_ifdown(dev);
        }

      /* No off-link communications; No router address. */

      net_ipv6addr_copy(dev->d_ipv6draddr, g_ipv6_allzeroaddr);

      /* Set a netmask for the local link address */

      net_ipv6addr_copy(dev->d_ipv6netmask, g_ipv6_llnetmask);

      /* Leave the network up and return success (even though things did not
       * work out quite the way we wanted).
       */

      net_unlock();
      return ret;
    }

  /* 5. Router Direction: The router provides direction to the node on how to
   *    proceed with the auto-configuration. It may tell the node that on this
   *    network "stateful" auto-configuration is in use, and tell it the
   *    address of a DHCP server to use. Alternately, it will tell the host
   *    how to determine its global Internet address.
   *
   * 6. Global Address Configuration: Assuming that stateless auto-
   *    configuration is in use on the network, the host will configure
   *    itself with its globally-unique Internet address. This address is
   *    generally formed from a network prefix provided to the host by the
   *    router, combined with the device's identifier as generated in the
   *    first step.
   */

  /* On success, the new address was already set (in icmpv_rnotify()).  We
   * need only to bring the network back to the up state and return success.
   */

  netdev_ifup(dev);
  net_unlock();
  return OK;
#endif /* CONFIG_NET_ETHERNET */
}
コード例 #5
0
ファイル: netdev_ioctl.c プロジェクト: dagar/NuttX
static int netdev_ifr_ioctl(FAR struct socket *psock, int cmd,
                            FAR struct ifreq *req)
{
  FAR struct net_driver_s *dev;
  int ret = -EINVAL;

  ninfo("cmd: %d\n", cmd);

  /* Execute the command */

  switch (cmd)
    {
#ifdef CONFIG_NET_IPv4
      case SIOCGIFADDR:  /* Get IP address */
        {
          dev = netdev_ifr_dev(req);
          if (dev)
            {
              ioctl_get_ipv4addr(&req->ifr_addr, dev->d_ipaddr);
              ret = OK;
            }
        }
        break;
#endif


#ifdef CONFIG_NET_IPv4
      case SIOCSIFADDR:  /* Set IP address */
        {
          dev = netdev_ifr_dev(req);
          if (dev)
            {
              ioctl_set_ipv4addr(&dev->d_ipaddr, &req->ifr_addr);
              ret = OK;
            }
        }
        break;
#endif

#ifdef CONFIG_NET_IPv4
      case SIOCGIFDSTADDR:  /* Get P-to-P address */
        {
          dev = netdev_ifr_dev(req);
          if (dev)
            {
              ioctl_get_ipv4addr(&req->ifr_dstaddr, dev->d_draddr);
              ret = OK;
            }
        }
        break;
#endif

#ifdef CONFIG_NET_IPv4
      case SIOCSIFDSTADDR:  /* Set P-to-P address */
        {
          dev = netdev_ifr_dev(req);
          if (dev)
            {
              ioctl_set_ipv4addr(&dev->d_draddr, &req->ifr_dstaddr);
              ret = OK;
            }
        }
        break;
#endif

#ifdef CONFIG_NET_IPv4
      case SIOCGIFBRDADDR:  /* Get broadcast IP address */
        {
          dev = netdev_ifr_dev(req);
          if (dev)
            {
              ioctl_get_ipv4broadcast(&req->ifr_broadaddr, dev->d_ipaddr,
                                      dev->d_netmask);
              ret = OK;
            }
        }
        break;
#endif

#ifdef CONFIG_NET_IPv4
      case SIOCSIFBRDADDR:  /* Set broadcast IP address */
        {
          ret = -ENOSYS;
        }
        break;
#endif

#ifdef CONFIG_NET_IPv4
      case SIOCGIFNETMASK:  /* Get network mask */
        {
          dev = netdev_ifr_dev(req);
          if (dev)
            {
              ioctl_get_ipv4addr(&req->ifr_addr, dev->d_netmask);
              ret = OK;
            }
        }
        break;
#endif

#ifdef CONFIG_NET_IPv4
      case SIOCSIFNETMASK:  /* Set network mask */
        {
          dev = netdev_ifr_dev(req);
          if (dev)
            {
              ioctl_set_ipv4addr(&dev->d_netmask, &req->ifr_addr);
              ret = OK;
            }
        }
        break;
#endif

#ifdef CONFIG_NET_IPv6
      case SIOCGLIFADDR:  /* Get IP address */
        {
          dev = netdev_ifr_dev(req);
          if (dev)
            {
              FAR struct lifreq *lreq = (FAR struct lifreq *)req;

              ioctl_get_ipv6addr(&lreq->lifr_addr, dev->d_ipv6addr);
              ret = OK;
            }
        }
        break;
#endif

#ifdef CONFIG_NET_IPv6
      case SIOCSLIFADDR:  /* Set IP address */
        {
          dev = netdev_ifr_dev(req);
          if (dev)
            {
              FAR struct lifreq *lreq = (FAR struct lifreq *)req;

              ioctl_set_ipv6addr(dev->d_ipv6addr, &lreq->lifr_addr);
              ret = OK;
            }
        }
        break;
#endif

#ifdef CONFIG_NET_IPv6
      case SIOCGLIFDSTADDR:  /* Get P-to-P address */
        {
          dev = netdev_ifr_dev(req);
          if (dev)
            {
              FAR struct lifreq *lreq = (FAR struct lifreq *)req;

              ioctl_get_ipv6addr(&lreq->lifr_dstaddr, dev->d_ipv6draddr);
              ret = OK;
            }
        }
        break;
#endif

#ifdef CONFIG_NET_IPv6
      case SIOCSLIFDSTADDR:  /* Set P-to-P address */
        {
          dev = netdev_ifr_dev(req);
          if (dev)
            {
              FAR struct lifreq *lreq = (FAR struct lifreq *)req;

              ioctl_set_ipv6addr(dev->d_ipv6draddr, &lreq->lifr_dstaddr);
              ret = OK;
            }
        }
        break;
#endif

#ifdef CONFIG_NET_IPv6
      case SIOCGLIFBRDADDR:  /* Get broadcast IP address */
      case SIOCSLIFBRDADDR:  /* Set broadcast IP address */
        {
          ret = -ENOSYS;
        }
        break;
#endif

#ifdef CONFIG_NET_IPv6
      case SIOCGLIFNETMASK:  /* Get network mask */
        {
          dev = netdev_ifr_dev(req);
          if (dev)
            {
              FAR struct lifreq *lreq = (FAR struct lifreq *)req;

              ioctl_get_ipv6addr(&lreq->lifr_addr, dev->d_ipv6netmask);
              ret = OK;
            }
        }
        break;
#endif

#ifdef CONFIG_NET_IPv6
      case SIOCSLIFNETMASK:  /* Set network mask */
        {
          dev = netdev_ifr_dev(req);
          if (dev)
            {
              FAR struct lifreq *lreq = (FAR struct lifreq *)req;
              ioctl_set_ipv6addr(dev->d_ipv6netmask, &lreq->lifr_addr);
              ret = OK;
            }
        }
        break;
#endif

      case SIOCGLIFMTU:  /* Get MTU size */
      case SIOCGIFMTU:   /* Get MTU size */
        {
          dev = netdev_ifr_dev(req);
          if (dev)
            {
              req->ifr_mtu = NETDEV_PKTSIZE(dev);
              ret = OK;
            }
        }
        break;

#ifdef CONFIG_NET_ICMPv6_AUTOCONF
      case SIOCIFAUTOCONF:  /* Perform ICMPv6 auto-configuration */
        {
          dev = netdev_ifr_dev(req);
          if (dev)
            {
              ret = icmpv6_autoconfig(dev);
            }
        }
        break;
#endif

      case SIOCSIFFLAGS:  /* Sets the interface flags */
        {
          /* Is this a request to bring the interface up? */

          dev = netdev_ifr_dev(req);
          if (dev)
            {
              if ((req->ifr_flags & IFF_UP) != 0)
                {
                  /* Yes.. bring the interface up */

                  netdev_ifup(dev);
                }

              /* Is this a request to take the interface down? */

              else if ((req->ifr_flags & IFF_DOWN) != 0)
                {
                  /* Yes.. take the interface down */

                  netdev_ifdown(dev);
                }
            }

          ret = OK;
        }
        break;

      case SIOCGIFFLAGS:  /* Gets the interface flags */
        {
          dev = netdev_ifr_dev(req);
          if (dev)
            {
              req->ifr_flags = dev->d_flags;
            }

          ret = OK;
        }
        break;

      /* MAC address operations only make sense if Ethernet or 6LoWPAN are
       * supported.
       */

#if defined(CONFIG_NET_ETHERNET) || defined(CONFIG_NET_6LOWPAN)
      case SIOCGIFHWADDR:  /* Get hardware address */
        {
          dev = netdev_ifr_dev(req);
          if (dev)
            {
#ifdef CONFIG_NET_ETHERNET
              if (dev->d_lltype == NET_LL_ETHERNET ||
                  dev->d_lltype == NET_LL_IEEE80211)
                {
                  req->ifr_hwaddr.sa_family = AF_INETX;
                  memcpy(req->ifr_hwaddr.sa_data,
                         dev->d_mac.ether.ether_addr_octet, IFHWADDRLEN);
                  ret = OK;
                }
              else
#endif

#ifdef CONFIG_NET_6LOWPAN
              if (dev->d_lltype == NET_LL_IEEE802154 ||
                  dev->d_lltype == NET_LL_PKTRADIO)
                {
                  req->ifr_hwaddr.sa_family = AF_INETX;
                  memcpy(req->ifr_hwaddr.sa_data,
                         dev->d_mac.radio.nv_addr,
                         dev->d_mac.radio.nv_addrlen);
                  ret = OK;
                }
               else
#endif
                {
                  nerr("Unsupported link layer\n");
                }
            }
        }
        break;

      case SIOCSIFHWADDR:  /* Set hardware address -- will not take effect until ifup */
        {
          dev = netdev_ifr_dev(req);
          if (dev)
            {
#ifdef CONFIG_NET_ETHERNET
              if (dev->d_lltype == NET_LL_ETHERNET)
                {
                  memcpy(dev->d_mac.ether.ether_addr_octet,
                         req->ifr_hwaddr.sa_data, IFHWADDRLEN);
                  ret = OK;
                }
              else
#endif

#ifdef CONFIG_NET_6LOWPAN
              if (dev->d_lltype == NET_LL_IEEE802154 ||
                  dev->d_lltype == NET_LL_PKTRADIO)
                {
                  FAR struct radio_driver_s *radio;
                  struct radiodev_properties_s properties;

                  /* Get the radio properties */

                  radio = (FAR struct radio_driver_s *)dev;
                  DEBUGASSERT(radio->r_properties != NULL);

                  ret = radio->r_properties(radio, &properties);
                  if (ret >= 0)
                    {
                      dev->d_mac.radio.nv_addrlen = properties.sp_addrlen;
                      memcpy(dev->d_mac.radio.nv_addr,
                             req->ifr_hwaddr.sa_data, NET_6LOWPAN_ADDRSIZE);
                    }
                }
              else
#endif
                {
                  nerr("Unsupported link layer\n");
                }
            }
        }
        break;
#endif

      case SIOCDIFADDR:  /* Delete IP address */
        {
          dev = netdev_ifr_dev(req);
          if (dev)
            {
#ifdef CONFIG_NET_IPv4
              dev->d_ipaddr = 0;
#endif
#ifdef CONFIG_NET_IPv6
              memset(&dev->d_ipv6addr, 0, sizeof(net_ipv6addr_t));
#endif
              ret = OK;
            }
        }
        break;

      case SIOCGIFCOUNT:  /* Get number of devices */
        {
          req->ifr_count = netdev_count();
          ret = -ENOSYS;
        }
        break;

#ifdef CONFIG_NET_IPv4
      case SIOCGIFCONF:  /* Return an interface list (IPv4) */
        {
          ret = netdev_ipv4_ifconf((FAR struct ifconf *)req);
        }
        break;
#endif

#ifdef CONFIG_NET_IPv6
      case SIOCGLIFCONF:  /* Return an interface list (IPv6) */
        {
          ret = netdev_ipv6_ifconf((FAR struct lifconf *)req);
        }
        break;
#endif

#if defined(CONFIG_NETDEV_IOCTL) && defined(CONFIG_NETDEV_PHY_IOCTL)
#ifdef CONFIG_ARCH_PHY_INTERRUPT
      case SIOCMIINOTIFY: /* Set up for PHY event notifications */
        {
          dev = netdev_ifr_dev(req);
          if (dev && dev->d_ioctl)
            {
              struct mii_iotcl_notify_s *notify = &req->ifr_ifru.ifru_mii_notify;
              ret = dev->d_ioctl(dev, cmd, ((unsigned long)(uintptr_t)notify));
            }
        }
        break;
#endif

      case SIOCGMIIPHY: /* Get address of MII PHY in use */
      case SIOCGMIIREG: /* Get MII register via MDIO */
      case SIOCSMIIREG: /* Set MII register via MDIO */
        {
          dev = netdev_ifr_dev(req);
          if (dev && dev->d_ioctl)
            {
              struct mii_ioctl_data_s *mii_data = &req->ifr_ifru.ifru_mii_data;
              ret = dev->d_ioctl(dev, cmd, ((unsigned long)(uintptr_t)mii_data));
            }
        }
        break;
#endif

      default:
        {
          ret = -ENOTTY;
        }
        break;
    }

  return ret;
}