static FAR struct uip_driver_s *netdev_finddevice(const uip_ipaddr_t addr)
{
  struct uip_driver_s *dev;

  netdev_semtake();
  for (dev = g_netdevices; dev; dev = dev->flink)
    {
      if (uip_ipaddr_maskcmp(dev->d_ipaddr, addr, dev->d_netmask))
        {
          netdev_semgive();
          return dev;
        }
    }

  netdev_semgive();
  return NULL;
}
Пример #2
0
FAR struct uip_driver_s *netdev_findbyaddr(const uip_ipaddr_t *raddr)
{
  struct uip_driver_s *dev;

  if (raddr)
    {
      netdev_semtake();
      for (dev = g_netdevices; dev; dev = dev->flink)
        {
          if (netdev_maskcmp(&dev->d_ipaddr, raddr, &dev->d_netmask))
            {
              netdev_semgive();
              return dev;
            }
        }
      netdev_semgive();
    }
  return NULL;
}
Пример #3
0
int netdev_count(void)
{
  struct uip_driver_s *dev;
  int ndev;

  netdev_semtake();
  for (dev = g_netdevices, ndev = 0; dev; dev = dev->flink, ndev++);
  netdev_semgive();
  return ndev;
}
Пример #4
0
int netdev_unregister(FAR struct uip_driver_s *dev)
{
  struct uip_driver_s *prev;
  struct uip_driver_s *curr;

  if (dev)
    {
      netdev_semtake();

      /* Find the device in the list of known network devices */

      for (prev = NULL, curr = g_netdevices;
           curr && curr != dev;
           prev = curr, curr = curr->flink);

      /* Remove the device to the list of known network devices */

      if (curr)
        {
          /* Where was the entry */

          if (prev)
            {
              /* The entry was in the middle or at the end of the list */

              prev->flink = curr->flink;
            }
          else
            {
               /* The entry was at the beginning of the list */

               g_netdevices = curr;
            }

          curr->flink = NULL;
        }

      netdev_semgive();

#ifdef CONFIG_NET_ETHERNET
      nlldbg("Unregistered MAC: %02x:%02x:%02x:%02x:%02x:%02x as dev: %s\n",
             dev->d_mac.ether_addr_octet[0], dev->d_mac.ether_addr_octet[1],
             dev->d_mac.ether_addr_octet[2], dev->d_mac.ether_addr_octet[3],
             dev->d_mac.ether_addr_octet[4], dev->d_mac.ether_addr_octet[5],
             dev->d_ifname);
#else
      nlldbg("Registered dev: %s\n", dev->d_ifname);
#endif
      return OK;
    }

  return -EINVAL;
}
Пример #5
0
int netdev_foreach(netdev_callback_t callback, void *arg)
{
    struct uip_driver_s *dev;
    int ret = 0;

    if (callback)
    {
        netdev_semtake();
        for (dev = g_netdevices; dev; dev = dev->flink)
        {
            if (callback(dev, arg) != 0)
            {
                ret = 1;
                break;
            }
        }
        netdev_semgive();
    }
    return ret;
}
Пример #6
0
int ipv4_getsockname(FAR struct socket *psock, FAR struct sockaddr *addr,
                     FAR socklen_t *addrlen)
{
  FAR struct net_driver_s *dev;
#if defined(CONFIG_NET_TCP) || defined(CONFIG_NET_UDP)
  FAR struct sockaddr_in *outaddr = (FAR struct sockaddr_in *)addr;
#endif
#ifdef CONFIG_NETDEV_MULTINIC
  in_addr_t lipaddr;
  in_addr_t ripaddr;
#endif

  /* Check if enough space has been provided for the full address */

  if (*addrlen < sizeof(struct sockaddr_in))
    {
      /* This function is supposed to return the partial address if
       * a smaller buffer has been provided.  This support has not
       * been implemented.
       */

      return -ENOSYS;
    }

  /* Set the port number */

  switch (psock->s_type)
    {
#ifdef CONFIG_NET_TCP
      case SOCK_STREAM:
        {
          FAR struct tcp_conn_s *tcp_conn = (FAR struct tcp_conn_s *)psock->s_conn;
          outaddr->sin_port = tcp_conn->lport; /* Already in network byte order */
#ifdef CONFIG_NETDEV_MULTINIC
          lipaddr = tcp_conn->u.ipv4.laddr;
          ripaddr = tcp_conn->u.ipv4.raddr;
#endif
        }
        break;
#endif

#ifdef CONFIG_NET_UDP
      case SOCK_DGRAM:
        {
          FAR struct udp_conn_s *udp_conn = (FAR struct udp_conn_s *)psock->s_conn;
          outaddr->sin_port = udp_conn->lport; /* Already in network byte order */
#ifdef CONFIG_NETDEV_MULTINIC
          lipaddr = udp_conn->u.ipv4.laddr;
          ripaddr = udp_conn->u.ipv4.raddr;
#endif
        }
        break;
#endif

      default:
        return -EOPNOTSUPP;
    }

  /* The socket/connection does not know its IP address unless
   * CONFIG_NETDEV_MULTINIC is selected.  Otherwise the design supports only
   * a single network device and only the network device knows the IP address.
   */

  netdev_semtake();

#ifdef CONFIG_NETDEV_MULTINIC
  /* Find the device matching the IPv4 address in the connection structure */

  dev = netdev_findby_ipv4addr(lipaddr, ripaddr);
#else
  /* There is only one, the first network device in the list. */

  dev = g_netdevices;
#endif

  if (!dev)
    {
      netdev_semgive();
      return -EINVAL;
    }

  /* Set the address family and the IP address */

#if defined(CONFIG_NET_TCP) || defined(CONFIG_NET_UDP)
  outaddr->sin_family = AF_INET;
  outaddr->sin_addr.s_addr = dev->d_ipaddr;
  *addrlen = sizeof(struct sockaddr_in);
#endif
  netdev_semgive();

  /* Return success */

  return OK;
}
Пример #7
0
int getsockname(int sockfd, FAR struct sockaddr *addr, FAR socklen_t *addrlen)
{
  FAR struct socket *psock = sockfd_socket(sockfd);
  FAR struct uip_driver_s *dev;

#if defined(CONFIG_NET_TCP) || defined(CONFIG_NET_UDP)
#ifdef CONFIG_NET_IPv6
  FAR struct sockaddr_in6 *outaddr = (FAR struct sockaddr_in6 *)addr;
#else
  FAR struct sockaddr_in *outaddr = (FAR struct sockaddr_in *)addr;
#endif
#endif

  int err;

  /* Verify that the sockfd corresponds to valid, allocated socket */

  if (!psock || psock->s_crefs <= 0)
    {
      err = EBADF;
      goto errout;
    }

  /* Some sanity checking... Shouldn't need this on a buckled up embedded
   * system (?)
   */

#ifdef CONFIG_DEBUG
  if (!addr || !addrlen)
    {
      err = EINVAL;
      goto errout;
    }
#endif

  /* Check if enough space has been provided for the full address */

#ifdef CONFIG_NET_IPv6
  if (*addrlen < sizeof(struct sockaddr_in6))
#else
  if (*addrlen < sizeof(struct sockaddr_in))
#endif
  {
    /* This function is supposed to return the partial address if
     * a smaller buffer has been provided.  This support has not
     * been implemented.
     */

    err = ENOSYS;
    goto errout;
  }

  /* Set the port number */

  switch (psock->s_type)
    {
#ifdef CONFIG_NET_TCP
      case SOCK_STREAM:
        {
          struct uip_conn *tcp_conn = (struct uip_conn *)psock->s_conn;
          outaddr->sin_port = tcp_conn->lport; /* Already in network byte order */
        }
        break;
#endif

#ifdef CONFIG_NET_UDP
      case SOCK_DGRAM:
        {
          struct uip_udp_conn *udp_conn = (struct uip_udp_conn *)psock->s_conn;
          outaddr->sin_port = udp_conn->lport; /* Already in network byte order */
        }
        break;
#endif

      default:
        err = EOPNOTSUPP;
        goto errout;
    }

  /* ISSUE: As of this writing, the socket/connection does not know its IP
   * address.  This is because the uIP design is only intended to support
   * a single network device and, therefore, only the network device knows
   * the IP address.
   *
   * Right now, we can just pick the first network device.  But that may
   * not work in the future.
   */

  netdev_semtake();
  dev = g_netdevices;
  if (!dev)
    {
      netdev_semgive();
      err = EINVAL;
      goto errout;
    }

  /* Set the address family and the IP address */

#if defined(CONFIG_NET_TCP) || defined(CONFIG_NET_UDP)
#ifdef CONFIG_NET_IPv6
#error "Not big enough for IPv6 address"
  outaddr->sin_family = AF_INET6;
  memcpy(outaddr->sin6_addr.in6_u.u6_addr8, dev->d_ipaddr, 16);
  *addrlen = sizeof(struct sockaddr_in6);
#else
  outaddr->sin_family = AF_INET;
  outaddr->sin_addr.s_addr = dev->d_ipaddr;
  *addrlen = sizeof(struct sockaddr_in);
#endif
#endif
  netdev_semgive();

  /* Return success */

  return OK;

errout:
  set_errno(err);
  return ERROR;
}
Пример #8
0
int netdev_register(FAR struct net_driver_s *dev, enum net_lltype_e lltype)
{
  FAR const char *devfmt;
#ifdef CONFIG_NET_USER_DEVFMT
  FAR const char devfmt_str[IFNAMSIZ];
#endif
  int devnum;

  if (dev)
    {
#ifdef CONFIG_NET_MULTILINK
      /* We are supporting multiple network devices and using different link
       * level protocols.  Set the protocol usd by the device and the size
       * level protocols.  Set the protocol used by the device and the size
       * of the link header used by this protocol.
       */

      switch (lltype)
        {
#ifdef CONFIG_NET_ETHERNET
          case NET_LL_ETHERNET:  /* Ethernet */
            dev->d_llhdrlen = ETH_HDRLEN;
            dev->d_mtu      = CONFIG_NET_ETH_MTU;
#ifdef CONFIG_NET_TCP_STACK
            dev->d_recvwndo = CONFIG_NET_ETH_TCP_RECVWNDO;
#endif
            devfmt          = NETDEV_ETH_FORMAT;
            break;
#endif

#ifdef CONFIG_NET_SLIP
          case NET_LL_SLIP:      /* Serial Line Internet Protocol (SLIP) */
            dev->d_llhdrlen = 0;
            dev->d_mtu      = CONFIG_NET_SLIP_MTU;
#ifdef CONFIG_NET_TCP_STACK
            dev->d_recvwndo = CONFIG_NET_SLIP_TCP_RECVWNDO;
#endif
            devfmt          = NETDEV_SLIP_FORMAT;
            break;
#endif

#ifdef CONFIG_NET_TUN
          case NET_LL_TUN:       /* Virtual Network Device (TUN) */
            dev->d_llhdrlen = 0;
            dev->d_mtu      = CONFIG_NET_TUN_MTU;
#ifdef CONFIG_NET_TCP
            dev->d_recvwndo = CONFIG_NET_TUN_TCP_RECVWNDO;
#endif
            devfmt          = NETDEV_TUN_FORMAT;
            break;
#endif

#if 0                            /* REVISIT: Not yet supported */
          case NET_LL_PPP:       /* Point-to-Point Protocol (PPP) */
            dev->d_llhdrlen = 0;
            dev->d_mtu      = CONFIG_NET_PPP_MTU;
#ifdef CONFIG_NET_TCP_STACK
            dev->d_recvwndo = CONFIG_NET_PPP_TCP_RECVWNDO;
#endif
            devfmt          = NETDEV_PPP_FORMAT;
            break;
#endif

          default:
            nlldbg("ERROR: Unrecognized link type: %d\n", lltype);
            return -EINVAL;
        }

      /* Remember the verified link type */

      dev->d_lltype = (uint8_t)lltype;

#else
     /* Use the default device name */

     devfmt = NETDEV_DEFAULT_FORMAT;
#endif

      /* Get the next available device number and sssign a device name to
       * the interface
       */

      netdev_semtake();
#ifdef CONFIG_NET_MULTILINK
      devnum = find_devnum(devfmt);
#else
      devnum = g_next_devnum++;
#endif
#ifdef CONFIG_NET_USER_DEVFMT
      if (*dev->d_ifname)
        {
          strncpy(devfmt_str, dev->d_ifname, IFNAMSIZ);
          devfmt = devfmt_str;
        }
#endif

      snprintf(dev->d_ifname, IFNAMSIZ, devfmt, devnum );

      /* Add the device to the list of known network devices */

      dev->flink  = g_netdevices;
      g_netdevices = dev;

      /* Configure the device for IGMP support */

#ifdef CONFIG_NET_IGMP
      igmp_devinit(dev);
#endif
      netdev_semgive();

#ifdef CONFIG_NET_ETHERNET
      nlldbg("Registered MAC: %02x:%02x:%02x:%02x:%02x:%02x as dev: %s\n",
             dev->d_mac.ether_addr_octet[0], dev->d_mac.ether_addr_octet[1],
             dev->d_mac.ether_addr_octet[2], dev->d_mac.ether_addr_octet[3],
             dev->d_mac.ether_addr_octet[4], dev->d_mac.ether_addr_octet[5],
             dev->d_ifname);
#else
      nlldbg("Registered dev: %s\n", dev->d_ifname);
#endif
      return OK;
    }

  return -EINVAL;
}
FAR struct uip_driver_s *netdev_findbyaddr(const uip_ipaddr_t addr)
{
  struct uip_driver_s *dev;
#ifdef CONFIG_NET_ROUTE
  uip_ipaddr_t router;
  int ret;
#endif

  /* First, see if the address maps to the a local network */

  dev = netdev_finddevice(addr);
  if (dev)
    {
      return dev;
    }

  /* No.. The address lies on an external network */

#ifdef CONFIG_NET_ROUTE
  /* If we have a routing table, then perhaps we can find the the local
   * address of a router that can forward packets to the external network.
   */

#ifdef CONFIG_NET_IPv6
  ret = net_router(addr, router);
#else
  ret = net_router(addr, &router);
#endif
  if (ret >= 0)
    {
      /* Success... try to find the network device associated with the local
       * router address
       */

      dev = netdev_finddevice(router);
      if (dev)
        {
          return dev;
        }
    }
#endif /* CONFIG_NET_ROUTE */

  /* The above lookup will fail if the packet is being sent out of our
   * out subnet to a router and there is no routing information.
   *
   * However, if there is only a single, registered network interface, then
   * the decision is pretty easy.  Use that device and its default router
   * address.
   */

  netdev_semtake();
  if (g_netdevices && !g_netdevices->flink)
    {
      dev = g_netdevices;
    }
  netdev_semgive();

  /* If we will did not find the network device, then we might as well fail
   * because we are not configured properly to determine the route to the
   * target.
   */

  return dev;
}