int cmd_ifconfig()

in nshlib/nsh_netcmds.c [548:1042]


int cmd_ifconfig(FAR struct nsh_vtbl_s *vtbl, int argc, FAR char **argv)
{
#ifdef CONFIG_NET_IPv4
  struct in_addr addr;
  in_addr_t gip = INADDR_ANY;
#endif
#ifdef CONFIG_NET_IPv6
  struct in6_addr addr6;
  struct in6_addr gip6 = IN6ADDR_ANY_INIT;
  FAR char *preflen = NULL;
#endif
  int i;
  FAR char *ifname = NULL;
  FAR char *hostip = NULL;
  FAR char *gwip = NULL;
  FAR char *mask = NULL;
  FAR char *tmp = NULL;
#ifdef HAVE_HWADDR
  FAR char *hw = NULL;
#endif
#if defined(CONFIG_NETINIT_DHCPC) || defined(CONFIG_NETINIT_DNS)
  FAR char *dns = NULL;
#endif
#if defined(CONFIG_NET_IPv4) && defined(CONFIG_NET_IPv6)
  bool inet6 = false;
#endif
  bool missingarg = true;
  bool badarg = false;
#ifdef HAVE_HWADDR
  mac_addr_t macaddr;
#endif
#if defined(CONFIG_NETINIT_DHCPC)
  FAR void *handle;
#endif
  int ret;
  int mtu = 0;

  /* With one or no arguments, ifconfig simply shows the status of the
   * network device:
   *
   *   ifconfig
   *   ifconfig [interface]
   */

  if (argc <= 2)
    {
      if (argc == 2)
        {
          return ifconfig_callback(vtbl, argv[1]);
        }

      ret = nsh_foreach_netdev(ifconfig_callback, vtbl, "ifconfig");
      if (ret < 0)
        {
          return ERROR;
        }

      net_statistics(vtbl);
      return OK;
    }

  /* If both the network interface name and an IP address are supplied as
   * arguments, then ifconfig will set the address of the Ethernet device:
   *
   *    ifconfig ifname [ip_address] [named options]
   */

  if (argc > 2)
    {
      for (i = 1; i < argc; i++)
        {
          if (i == 1)
            {
              ifname = argv[i];
              missingarg = false;
            }
          else
            {
              tmp = argv[i];

              if (!strcmp(tmp, "dr") || !strcmp(tmp, "gw") ||
                  !strcmp(tmp, "gateway"))
                {
                  if (argc - 1 >= i + 1)
                    {
                      gwip = argv[i + 1];
                      i++;
                    }
                  else
                    {
                      badarg = true;
                    }
                }
              else if (!strcmp(tmp, "netmask"))
                {
                  if (argc - 1 >= i + 1)
                    {
                      mask = argv[i + 1];
                      i++;
                    }
                  else
                    {
                      badarg = true;
                    }
                }
              else if (!strcmp(tmp, "inet"))
                {
#if defined(CONFIG_NET_IPv4) && defined(CONFIG_NET_IPv6)
                  inet6 = false;
#elif !defined(CONFIG_NET_IPv4)
                  badarg = true;
#endif
                }
              else if (!strcmp(tmp, "inet6"))
                {
#if defined(CONFIG_NET_IPv4) && defined(CONFIG_NET_IPv6)
                  inet6 = true;
#elif !defined(CONFIG_NET_IPv6)
                  badarg = true;
#endif
                }

#ifdef CONFIG_NET_IPv6
              else if (!strcmp(tmp, "prefixlen"))
                {
                  if (argc - 1 >= i + 1)
                    {
                      preflen = argv[i + 1];
                      i++;
                    }
                  else
                    {
                      badarg = true;
                    }
                }
#endif

#ifdef HAVE_HWADDR
              /* REVISIT: How will we handle Ethernet and SLIP together? */

              else if (!strcmp(tmp, "hw"))
                {
                  if (argc - 1 >= i + 1)
                    {
                      hw = argv[i + 1];
                      i++;

                      badarg = nsh_addrconv(hw, &macaddr);
                    }
                  else
                    {
                      badarg = true;
                    }
                }
#endif

#if defined(CONFIG_NETINIT_DHCPC) || defined(CONFIG_NETINIT_DNS)
              else if (!strcmp(tmp, "dns"))
                {
                  if (argc - 1 >= i + 1)
                    {
                      dns = argv[i + 1];
                      i++;
                    }
                  else
                    {
                      badarg = true;
                    }
                }
#endif
              else if (!strcmp(tmp, "add"))
                {
                  /* Compatible with linux IPv6 command, do nothing. */

                  continue;
                }
              else if (!strcmp(tmp, "mtu"))
                {
                  if (argc - 1 >= i + 1)
                    {
                      mtu = atoi(argv[i + 1]);
                      i++;
                      if (mtu < 1280)
                        {
                          mtu = 1280;
                        }
                    }
                  else
                    {
                      badarg = true;
                    }
                }
              else if (hostip == NULL && i <= 4)
                {
                  /* Let first non-option be host ip, to support inet/inet6
                   * options before address.
                   */

                  hostip = tmp;
                }
              else
                {
                  badarg = true;
                }
            }
        }
    }

  if (missingarg)
    {
      nsh_error(vtbl, g_fmtargrequired, argv[0]);
      return ERROR;
    }

  if (badarg)
    {
      nsh_error(vtbl, g_fmtarginvalid, argv[0]);
      return ERROR;
    }

#ifdef HAVE_HWADDR
  /* Set Hardware Ethernet MAC address */

  if (hw != NULL)
    {
      ninfo("HW MAC: %s\n", hw);
      nsh_sethwaddr(ifname, &macaddr);
    }
#endif

  if (mtu != 0)
    {
      netlib_set_mtu(ifname, mtu);
      return OK;
    }

  /* Set IP address */

#ifdef CONFIG_NET_IPv6
#ifdef CONFIG_NET_IPv4
  if (inet6)
#endif
    {
      if (hostip != NULL)
        {
          /* REVISIT: Should DHCPC check be used here too? */

          if ((tmp = strchr(hostip, '/')) != NULL)
            {
              *tmp = 0;
              if (preflen == NULL)
                {
                  preflen = tmp + 1;
                }
            }

          ninfo("Host IP: %s\n", hostip);
          inet_pton(AF_INET6, hostip, &addr6);
        }

      netlib_set_ipv6addr(ifname, &addr6);
    }
#endif /* CONFIG_NET_IPv6 */

#ifdef CONFIG_NET_IPv4
#ifdef CONFIG_NET_IPv6
  else
#endif
    {
      if (hostip != NULL)
        {
#if defined(CONFIG_NETINIT_DHCPC)
          if (strcmp(hostip, "dhcp") == 0)
            {
              /* Set DHCP addr */

              ninfo("DHCPC Mode\n");
              addr.s_addr = 0;
              gip         = 0;
            }
          else
#endif
            {
              /* Set host IP address */

              ninfo("Host IP: %s\n", hostip);
              addr.s_addr = inet_addr(hostip);
              gip         = addr.s_addr;
            }
        }
      else
        {
          addr.s_addr = 0;
        }

      netlib_set_ipv4addr(ifname, &addr);
    }
#endif /* CONFIG_NET_IPv4 */

  /* Set gateway */

#ifdef CONFIG_NET_IPv6
#ifdef CONFIG_NET_IPv4
  if (inet6)
#endif
    {
      /* Only set the gateway address if it was explicitly provided. */

      if (gwip != NULL)
        {
          ninfo("Gateway: %s\n", gwip);
          inet_pton(AF_INET6, gwip, &addr6);

          netlib_set_dripv6addr(ifname, &addr6);
          gip6 = addr6;
        }
    }
#endif /* CONFIG_NET_IPv6 */

#ifdef CONFIG_NET_IPv4
#ifdef CONFIG_NET_IPv6
  else
#endif
    {
      if (gwip != NULL)
        {
          ninfo("Gateway: %s\n", gwip);
          gip = addr.s_addr = inet_addr(gwip);
        }
      else
        {
          if (gip != 0)
            {
              ninfo("Gateway: default\n");
              gip  = NTOHL(gip);
              gip &= ~0x000000ff;
              gip |= 0x00000001;
              gip  = HTONL(gip);
            }

          addr.s_addr = gip;
        }

      netlib_set_dripv4addr(ifname, &addr);
    }
#endif /* CONFIG_NET_IPv4 */

  /* Set network mask */

#ifdef CONFIG_NET_IPv6
#ifdef CONFIG_NET_IPv4
  if (inet6)
#endif
    {
      if (mask != NULL)
        {
          ninfo("Netmask: %s\n", mask);
          inet_pton(AF_INET6, mask, &addr6);
        }
      else if (preflen != NULL)
        {
          ninfo("Prefixlen: %s\n", preflen);
          netlib_prefix2ipv6netmask(atoi(preflen), &addr6);
        }
      else
        {
          ninfo("Netmask: Default\n");
          inet_pton(AF_INET6, "ffff:ffff:ffff:ffff::", &addr6);
        }

      netlib_set_ipv6netmask(ifname, &addr6);
    }
#endif /* CONFIG_NET_IPv6 */

#ifdef CONFIG_NET_IPv4
#ifdef CONFIG_NET_IPv6
  else
#endif
    {
      if (mask != NULL)
        {
          ninfo("Netmask: %s\n", mask);
          addr.s_addr = inet_addr(mask);
        }
      else
        {
          ninfo("Netmask: Default\n");
          addr.s_addr = inet_addr("255.255.255.0");
        }

      netlib_set_ipv4netmask(ifname, &addr);
    }
#endif /* CONFIG_NET_IPv4 */

  UNUSED(ifname); /* Not used in all configurations */

#if defined(CONFIG_NETINIT_DHCPC) || defined(CONFIG_NETINIT_DNS)
#ifdef CONFIG_NET_IPv6
#ifdef CONFIG_NET_IPv4
  if (inet6)
#endif
    {
      if (dns != NULL)
        {
          ninfo("DNS: %s\n", dns);
          inet_pton(AF_INET6, dns, &addr6);
        }
      else
        {
          ninfo("DNS: Default\n");
          addr6 = gip6;
        }

      netlib_set_ipv6dnsaddr(&addr6);
    }
#endif /* CONFIG_NET_IPv6 */

#ifdef CONFIG_NET_IPv4
#ifdef CONFIG_NET_IPv6
  else
#endif
    {
      if (dns != NULL)
        {
          ninfo("DNS: %s\n", dns);
          addr.s_addr = inet_addr(dns);
        }
      else
        {
          ninfo("DNS: Default\n");
          addr.s_addr = gip;
        }

      netlib_set_ipv4dnsaddr(&addr);
    }
#endif /* CONFIG_NET_IPv4 */
#endif /* CONFIG_NETINIT_DHCPC || CONFIG_NETINIT_DNS */

#if defined(CONFIG_NETINIT_DHCPC)
  /* Get the MAC address of the NIC */

  if (!gip)
    {
      netlib_getmacaddr("eth0", macaddr);

      /* Set up the DHCPC modules */

      handle = dhcpc_open("eth0", &macaddr, IFHWADDRLEN);

      /* Get an IP address.  Note that there is no logic for renewing the IP
       * address in this example.  The address should be renewed in
       * ds.lease_time/2 seconds.
       */

      if (handle != NULL)
        {
          struct dhcpc_state ds;

          dhcpc_request(handle, &ds);
          netlib_set_ipv4addr("eth0", &ds.ipaddr);

          if (ds.netmask.s_addr != 0)
            {
              netlib_set_ipv4netmask("eth0", &ds.netmask);
            }

          if (ds.default_router.s_addr != 0)
            {
              netlib_set_dripv4addr("eth0", &ds.default_router);
            }

          if (ds.dnsaddr.s_addr != 0)
            {
              netlib_set_ipv4dnsaddr(&ds.dnsaddr);
            }

          dhcpc_close(handle);
        }
    }
#endif

#if !defined(CONFIG_NET_IPv4) && !defined(CONFIG_NET_IPv6)
  UNUSED(hostip);
  UNUSED(mask);
  UNUSED(gwip);
#endif
#ifdef CONFIG_NET_IPv4
  UNUSED(gip);
#endif
#ifdef CONFIG_NET_IPv6
  UNUSED(gip6);
#endif

  return OK;
}