Esempio n. 1
0
static void idle(ClientData client_data, struct timeval *nowP)
{
  int cnum;
  struct connect_s *conn;

  for (cnum = 0; cnum < AVAILABLE_FDS; ++cnum)
    {
      conn = &connects[cnum];
      switch (conn->conn_state)
        {
        case CNST_READING:
          if (nowP->tv_sec - conn->active_at >= CONFIG_THTTPD_IDLE_READ_LIMIT_SEC)
            {
              nerr("ERROR: %s connection timed out reading\n",
                   httpd_ntoa(&conn->hc->client_addr));
              httpd_send_err(conn->hc, 408, httpd_err408title, "",
                             httpd_err408form, "");
              finish_connection(conn, nowP);
            }
          break;

        case CNST_SENDING:
          if (nowP->tv_sec - conn->active_at >= CONFIG_THTTPD_IDLE_SEND_LIMIT_SEC)
            {
              nerr("ERROR: %s connection timed out sending\n",
                   httpd_ntoa(&conn->hc->client_addr));
              clear_connection(conn, nowP);
            }
          break;
        }
    }
}
Esempio n. 2
0
static inline int tcp_ipv4_bind(FAR struct tcp_conn_s *conn,
                                FAR const struct sockaddr_in *addr)
{
  int port;
  int ret;

  /* Verify or select a local port and address */

  net_lock();

  /* Verify or select a local port (host byte order) */

#ifdef CONFIG_NETDEV_MULTINIC
  port = tcp_selectport(PF_INET,
                       (FAR const union ip_addr_u *)&addr->sin_addr.s_addr,
                        ntohs(addr->sin_port));
#else
  port = tcp_selectport(ntohs(addr->sin_port));
#endif

  if (port < 0)
    {
      nerr("ERROR: tcp_selectport failed: %d\n", port);
      return port;
    }

  /* Save the local address in the connection structure (network byte order). */

  conn->lport = htons(port);
#ifdef CONFIG_NETDEV_MULTINIC
  net_ipv4addr_copy(conn->u.ipv4.laddr, addr->sin_addr.s_addr);
#endif

  /* Find the device that can receive packets on the network associated with
   * this local address.
   */

  ret = tcp_local_ipv4_device(conn);
  if (ret < 0)
    {
      /* If no device is found, then the address is not reachable */

      nerr("ERROR: tcp_local_ipv4_device failed: %d\n", ret);

      /* Back out the local address setting */

      conn->lport = 0;
#ifdef CONFIG_NETDEV_MULTINIC
      net_ipv4addr_copy(conn->u.ipv4.laddr, INADDR_ANY);
#endif
      return ret;
    }

  net_unlock();
  return OK;
}
Esempio n. 3
0
int ftpc_login(SESSION handle, FAR struct ftpc_login_s *login)
{
  FAR struct ftpc_session_s *session = (FAR struct ftpc_session_s *)handle;
  int errcode;
  int ret;

  /* Verify that we are connected to a server */

  if (!ftpc_connected(session))
    {
      nerr("ERROR: Not connected\n");
      errcode = ENOTCONN;
      goto errout_with_err;
    }

  /* Verify that we are not already logged in to the server */

  if (ftpc_loggedin(session))
    {
      nerr("ERROR: Already logged in\n");
      errcode = EINVAL;
      goto errout_with_err;
    }

  /* Save the login parameter */

  session->uname    = ftpc_dequote(login->uname);
  session->pwd      = ftpc_dequote(login->pwd);
  session->initrdir = ftpc_dequote(login->rdir);

  /* Is passive mode requested? */

  FTPC_CLR_PASSIVE(session);
  if (login->pasv)
    {
      ninfo("Setting passive mode\n");
      FTPC_SET_PASSIVE(session);
    }

  /* The (Re-)login to the server */

  ret = ftpc_relogin(session);
  if (ret != OK)
    {
      nerr("ERROR: login failed: %d\n", errno);
      goto errout;
    }

  return OK;

errout_with_err:
  set_errno(errcode);
errout:
  return ERROR;
}
Esempio n. 4
0
File: sendto.c Progetto: dagar/NuttX
ssize_t psock_sendto(FAR struct socket *psock, FAR const void *buf,
                     size_t len, int flags, FAR const struct sockaddr *to,
                     socklen_t tolen)
{
  ssize_t nsent;

  /* Verify that non-NULL pointers were passed */

#ifdef CONFIG_DEBUG_FEATURES
  if (buf == NULL)
    {
      return -EINVAL;
    }
#endif

  /* If to is NULL or tolen is zero, then this function is same as send (for
   * connected socket types)
   */

  if (to == NULL || tolen <= 0)
    {
#if defined(CONFIG_NET_TCP) || defined(CONFIG_NET_LOCAL_STREAM) || \
    defined(CONFIG_NET_USRSOCK)
      return psock_send(psock, buf, len, flags);
#else
      nerr("ERROR: No 'to' address\n");
      return -EINVAL;
#endif
    }

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

  if (psock == NULL || psock->s_crefs <= 0)
    {
      nerr("ERROR: Invalid socket\n");
      return -EBADF;
    }

  /* Let the address family's sendto() method handle the operation */

  DEBUGASSERT(psock->s_sockif != NULL && psock->s_sockif->si_sendto != NULL);
  nsent = psock->s_sockif->si_sendto(psock, buf, len, flags, to, tolen);

  /* Check if the domain-specific sendto() logic failed */

  if (nsent < 0)
    {
      nerr("ERROR:  Family-specific send failed: %ld\n", (long)nsent);
      return nsent;
    }

  return nsent;
}
Esempio n. 5
0
static int local_tx_open(FAR struct local_conn_s *conn, FAR const char *path,
                         bool nonblock)
{
  int oflags = nonblock ? O_WRONLY | O_NONBLOCK : O_WRONLY;

  conn->lc_outfd = open(path, oflags);
  if (conn->lc_outfd < 0)
    {
      int errcode = get_errno();
      DEBUGASSERT(errcode > 0);

      nerr("ERROR: Failed on open %s for writing: %d\n",
           path, errcode);

      /* Map the errcode to something consistent with the return
       * error codes from connect():
       *
       * If errcode is ENOENT, meaning that the FIFO does exist,
       * return EFAULT meaning that the socket structure address is
       * outside the user's address space.
       */

      return errcode == ENOENT ? -EFAULT : -errcode;
    }

  return OK;
}
Esempio n. 6
0
/****************************************************************************
 * Name: local_release_fifo
 *
 * Description:
 *   Release a reference from one of the FIFOs used in a connection.
 *
 ****************************************************************************/

#ifdef CONFIG_NET_LOCAL_STREAM /* Currently not used by datagram code */
static int local_release_fifo(FAR const char *path)
{
  int ret;

  /* Unlink the client-to-server FIFO if it exists. */

  if (local_fifo_exists(path))
    {
      /* Un-linking the FIFO removes the FIFO from the namespace.  It will
       * also mark the FIFO device "unlinked".  When all of the open
       * references to the FIFO device are closed, the resources consumed
       * by the device instance will also be freed.
       */

      ret = unlink(path);
      if (ret < 0)
        {
          int errcode = get_errno();
          DEBUGASSERT(errcode > 0);

          nerr("ERROR: Failed to unlink FIFO %s: %d\n", path, errcode);
          return -errcode;
        }
    }

  /* The FIFO does not exist or we successfully unlinked it. */

  return OK;
}
Esempio n. 7
0
static int local_create_fifo(FAR const char *path)
{
  int ret;

  /* Create the client-to-server FIFO if it does not already exist. */

  if (!local_fifo_exists(path))
    {
      ret = mkfifo(path, 0644);
      if (ret < 0)
        {
          int errcode = get_errno();
          DEBUGASSERT(errcode > 0);

          nerr("ERROR: Failed to create FIFO %s: %d\n", path, errcode);
          return -errcode;
        }
    }

  /* The FIFO (or some character driver) exists at PATH or we successfully
   * created the FIFO at that location.
   */

  return OK;
}
Esempio n. 8
0
ssize_t psock_local_send(FAR struct socket *psock, FAR const void *buf,
                         size_t len, int flags)
{
  FAR struct local_conn_s *peer;
  int ret;

  DEBUGASSERT(psock && psock->s_conn && buf);
  peer = (FAR struct local_conn_s *)psock->s_conn;

  /* Verify that this is a connected peer socket and that it has opened the
   * outgoing FIFO for write-only access.
   */

  if (peer->lc_state != LOCAL_STATE_CONNECTED ||
      peer->lc_outfd < 0)
    {
      nerr("ERROR: not connected\n");
      return -ENOTCONN;
    }

  /* Send the packet */

  ret = local_send_packet(peer->lc_outfd, (FAR uint8_t *)buf, len);

  /* If the send was successful, then the full packet will have been sent */

  return ret < 0 ? ret : len;
}
Esempio n. 9
0
FAR const struct sock_intf_s *
  net_sockif(sa_family_t family, int type, int protocol)
{
  FAR const struct sock_intf_s *sockif = NULL;

  /* Get the socket interface.
   *
   * REVISIT:  Should also support PF_UNSPEC which would permit the socket
   * to be used for anything.
   */

  switch (family)
    {
#ifdef HAVE_INET_SOCKETS
#ifdef HAVE_PFINET_SOCKETS
    case PF_INET:
#endif
#ifdef HAVE_PFINET6_SOCKETS
    case PF_INET6:
#endif
      sockif = inet_sockif(family, type, protocol);
      break;
#endif

#ifdef CONFIG_NET_LOCAL
    case PF_LOCAL:
      sockif = &g_local_sockif;
      break;
#endif

#ifdef CONFIG_NET_NETLINK
    case PF_NETLINK:
      sockif = &g_netlink_sockif;
      break;
#endif

#ifdef CONFIG_NET_PKT
    case PF_PACKET:
      sockif = &g_pkt_sockif;
      break;
#endif

#ifdef CONFIG_NET_BLUETOOTH
    case PF_BLUETOOTH:
      sockif = &g_bluetooth_sockif;
      break;
#endif

#ifdef CONFIG_NET_IEEE802154
    case PF_IEEE802154:
      sockif = &g_ieee802154_sockif;
      break;
#endif

    default:
      nerr("ERROR: Address family unsupported: %d\n", family);
    }

  return sockif;
}
Esempio n. 10
0
int bluetooth_input(FAR struct radio_driver_s *radio,
                     FAR struct iob_s *framelist,
                     FAR struct bluetooth_frame_meta_s *meta)
{
  FAR struct bluetooth_conn_s *conn;
  FAR struct iob_s *frame;
  FAR struct iob_s *next;
  int ret = OK;

  /* Check if there is a connection that will accept this packet */

  conn = bluetooth_conn_active(meta);
  if (conn != NULL)
    {
      /* Setup for the application callback (NOTE:  These should not be
       * used by PF_BLUETOOTH sockets).
       */

      radio->r_dev.d_appdata = radio->r_dev.d_buf;
      radio->r_dev.d_len     = 0;
      radio->r_dev.d_sndlen  = 0;

      /* The framelist probably contains only a single frame, but we will
       * process it as a list of frames.
       */

      for (frame = framelist; frame != NULL; frame = next)
        {
          /* Remove the frame from the list */

          next            = frame->io_flink;
          frame->io_flink = NULL;

          /* Add the frame to the RX queue */

          ret = bluetooth_queue_frame(conn, frame, meta);
          if (ret < 0)
            {
              nerr("ERROR: Failed to queue frame: %d\n", ret);
              iob_free(frame);
            }
        }

      /* Perform the application callback.  The frame may be processed now
       * if there is a user wait for an incoming frame.  Or it may pend in
       * the RX queue until some user process reads the frame.  NOTE:  The
       * return value from bluetooth_callback would distinguish these
       * cases:  BLUETOOTH_NEWDATA will still be processed if the frame
       * was not consumed.
       */

      (void)bluetooth_callback(radio, conn, BLUETOOTH_NEWDATA);
    }
  else
    {
      nwarn("WARNING: No listener\n");
    }

  return ret;
}
Esempio n. 11
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;
}
Esempio n. 12
0
int psock_tcp_cansend(FAR struct socket *psock)
{
  if (!psock || psock->s_crefs <= 0)
    {
      nerr("ERROR: Invalid socket\n");
      return -EBADF;
    }

  if (psock->s_type != SOCK_STREAM || !_SS_ISCONNECTED(psock->s_flags))
    {
      nerr("ERROR: Not connected\n");
      return -ENOTCONN;
    }

  if (tcp_wrbuffer_test())
    {
      return -EWOULDBLOCK;
    }

  return OK;
}
Esempio n. 13
0
static void clear_connection(struct connect_s *conn, struct timeval *tv)
{
  ClientData client_data;

  if (conn->wakeup_timer != NULL)
    {
      tmr_cancel(conn->wakeup_timer);
      conn->wakeup_timer = 0;
    }

  /* This is our version of Apache's lingering_close() routine, which is
   * their version of the often-broken SO_LINGER socket option.  For why
   * this is necessary, see http://www.apache.org/docs/misc/fin_wait_2.html
   * What we do is delay the actual closing for a few seconds, while reading
   * any bytes that come over the connection.  However, we don't want to do
   * this unless it's necessary, because it ties up a connection slot and
   * file descriptor which means our maximum connection-handling rateis
   * lower.  So, elsewhere we set a flag when we detect the few
   * circumstances that make a lingering close necessary.  If the flag isn't
   * set we do the real close now.
   */

  if (conn->conn_state == CNST_LINGERING)
    {
      /* If we were already lingering, shut down for real */

      tmr_cancel(conn->linger_timer);
      conn->linger_timer      = NULL;
      conn->hc->should_linger = false;
    }
  else if (conn->hc->should_linger)
    {
      fdwatch_del_fd(fw, conn->hc->conn_fd);
      conn->conn_state = CNST_LINGERING;
      fdwatch_add_fd(fw, conn->hc->conn_fd, conn);
      client_data.p = conn;

      conn->linger_timer = tmr_create(tv, linger_clear_connection, client_data,
                                      CONFIG_THTTPD_LINGER_MSEC, 0);
      if (conn->linger_timer != NULL)
        {
          return;
        }

      nerr("ERROR: tmr_create(linger_clear_connection) failed\n");
    }

  /* Either we are done lingering, we shouldn't linger, or we failed to setup the linger */

  really_clear_connection(conn);
}
Esempio n. 14
0
static int local_set_policy(int fd, unsigned long policy)
{
  int ret;

  /* Set the buffer policy */

  ret = ioctl(fd, PIPEIOC_POLICY, policy);
  if (ret < 0)
    {
      int errcode = get_errno();
      DEBUGASSERT(errcode > 0);

      nerr("ERROR: Failed to set FIFO buffer policty: %d\n", errcode);
      return -errcode;
    }

  return OK;
}
Esempio n. 15
0
int dns_foreach_nameserver(dns_callback_t callback, FAR void *arg)
{
  int ret = OK;

  if (g_dns_address)
    {
#ifdef CONFIG_NET_IPv4
      /* Check for an IPv4 address */

      if (g_dns_server.addr.sa_family == AF_INET)
        {
          /* Perform the callback */

          ret = callback(arg, (FAR struct sockaddr *)&g_dns_server.ipv4,
                         sizeof(struct sockaddr_in));
        }
      else
#endif

#ifdef CONFIG_NET_IPv6
      /* Check for an IPv6 address */

      if (g_dns_server.addr.sa_family == AF_INET6)
        {
          /* Perform the callback */

          ret = callback(arg, (FAR struct sockaddr *)&g_dns_server.ipv6,
                         sizeof(struct sockaddr_in6));
        }
      else
#endif
        {
          nerr("ERROR: Unsupported family: %d\n",
                g_dns_server.addr.sa_family);
          ret = -ENOSYS;
        }
    }

  return ret;
}
Esempio n. 16
0
static int slip_rxtask(int argc, FAR char *argv[])
{
  FAR struct slip_driver_s *priv;
  unsigned int index = *(argv[1]) - '0';
  net_lock_t flags;
  int ch;

  nerr("index: %d\n", index);
  DEBUGASSERT(index < CONFIG_NET_SLIP_NINTERFACES);

  /* Get our private data structure instance and wake up the waiting
   * initialization logic.
   */

  priv = &g_slip[index];
  slip_semgive(priv);

  /* Loop forever */

  for (; ; )
    {
      /* Wait for the next character to be available on the input stream. */

      ninfo("Waiting...\n");
      ch = slip_getc(priv);

      /* Ignore any input that we receive before the interface is up. */

      if (!priv->bifup)
        {
          continue;
        }

      /* We have something...
       *
       * END characters may appear at packet boundaries BEFORE as well as
       * after the beginning of the packet.  This is normal and expected.
       */

      if (ch == SLIP_END)
        {
          priv->rxlen = 0;
        }

      /* Otherwise, we are in danger of being out-of-sync.  Apparently the
       * leading END character is optional.  Let's try to continue.
       */

      else
        {
          priv->rxbuf[0] = (uint8_t)ch;
          priv->rxlen    = 1;
        }

      /* Copy the data data from the hardware to priv->rxbuf until we put
       * together a whole packet.
       */

      slip_receive(priv);
      NETDEV_RXPACKETS(&priv->dev);

      /* All packets are assumed to be IP packets (we don't have a choice..
       * there is no Ethernet header containing the EtherType).  So pass the
       * received packet on for IP processing -- but only if it is big
       * enough to hold an IP header.
       */

      if (priv->rxlen >= IPv4_HDRLEN)
        {
          NETDEV_RXIPV4(&priv->dev);

          /* Handle the IP input.  Get exclusive access to the network. */

          slip_semtake(priv);
          priv->dev.d_buf = priv->rxbuf;
          priv->dev.d_len = priv->rxlen;

          flags = net_lock();
          ipv4_input(&priv->dev);

          /* If the above function invocation resulted in data that should
           * be sent out on the network, the field  d_len will set to a
           * value > 0.  NOTE that we are transmitting using the RX buffer!
           */

          if (priv->dev.d_len > 0)
            {
              slip_transmit(priv);
              kill(priv->txpid, SIGALRM);
            }
          net_unlock(flags);
          slip_semgive(priv);
        }
      else
        {
          NETDEV_RXERRORS(&priv->dev);
        }
    }

  /* We won't get here */

  return OK;
}
Esempio n. 17
0
static int bluetooth_queue_frame(FAR struct bluetooth_conn_s *conn,
                                  FAR struct iob_s *frame,
                                  FAR struct bluetooth_frame_meta_s *meta)
{
  FAR struct bluetooth_container_s *container;

  /* Allocate a container for the frame */

  container = bluetooth_container_allocate();
  if (container == NULL)
    {
      nerr("ERROR: Failed to allocate a container\n");
      return -ENOMEM;
    }

  /* Initialize the container */

  memset(&container->bn_raddr, 0, sizeof(bt_addr_t));
  container->bn_channel = meta->bm_channel;
  BLUETOOTH_ADDRCOPY(&container->bn_raddr, &meta->bm_raddr);

  DEBUGASSERT(frame != NULL);
  container->bn_iob = frame;

  /* Add the container to the tail of the list of incoming frames */

  container->bn_flink = NULL;
  if (conn->bc_rxtail == NULL)
    {
      conn->bc_rxhead = container;
    }
  else
    {
      conn->bc_rxtail->bn_flink = container;
    }

#if CONFIG_NET_BLUETOOTH_BACKLOG > 0
   /* If incrementing the count would exceed the maximum bc_backlog value, then
    * delete the oldest frame from the head of the RX queue.
    */

   if (conn->bc_backlog >= CONFIG_NET_BLUETOOTH_BACKLOG)
     {
      DEBUGASSERT(conn->bc_backlog == CONFIG_NET_BLUETOOTH_BACKLOG);

      /* Remove the container from the tail RX input queue. */

      container           = conn->bc_rxhead;
      DEBUGASSERT(container != NULL);
      conn->bc_rxhead     = container->bn_flink;
      container->bn_flink = NULL;

      /* Did the RX queue become empty? */

      if (conn->bc_rxhead == NULL)
        {
          conn->bc_rxtail = NULL;
        }

      DEBUGASSERT(container != NULL && container->bn_iob != NULL);

      /* Free both the IOB and the container */

      iob_free(container->bn_iob);
      bluetooth_container_free(container);
     }
   else
     {
       /* Increment the count of frames in the queue. */

       conn->bc_backlog++;
     }

   DEBUGASSERT((int)conn->bc_backlog == bluetooth_count_frames(conn));
#endif

  return OK;
}
Esempio n. 18
0
int tcp_getsockopt(FAR struct socket *psock, int option,
                   FAR void *value, FAR socklen_t *value_len)
{
#ifdef CONFIG_NET_TCP_KEEPALIVE
  /* Keep alive options are the only TCP protocol socket option currently
   * supported.
   */

  FAR struct tcp_conn_s *conn;
  int ret;

  DEBUGASSERT(psock != NULL && value != NULL && value_len != NULL &&
              psock->s_conn != NULL);
  conn = (FAR struct tcp_conn_s *)psock->s_conn;

  /* All of the TCP protocol options apply only TCP sockets.  The sockets
   * do not have to be connected.. that might occur later with the KeepAlive
   * already configured.
   */

  if (psock->s_type != SOCK_STREAM)
    {
      nerr("ERROR:  Not a TCP socket\n");
      return -ENOTCONN;
    }

  /* Handle the Keep-Alive option */

  switch (option)
    {
      /* Handle the SO_KEEPALIVE socket-level option.
       *
       * NOTE: SO_KEEPALIVE is not really a socket-level option; it is a
       * protocol-level option.  A given TCP connection may service multiple
       * sockets (via dup'ing of the socket).  There is, however, still only
       * one connection to be monitored and that is a global attribute across
       * all of the clones that may use the underlying connection.
       */

      case SO_KEEPALIVE:  /* Verifies TCP connections active by enabling the
                           * periodic transmission of probes */
        if (*value_len < sizeof(int))
          {
            /* REVISIT: POSIX says that we should truncate the value if it
             * is larger than value_len.   That just doesn't make sense
             * to me in this case.
             */

            ret                = -EINVAL;
          }
        else
          {
            FAR int *keepalive = (FAR int *)value;
            *keepalive         = (int)conn->keepalive;
            *value_len         = sizeof(int);
            ret                = OK;
          }
        break;

      case TCP_NODELAY:  /* Avoid coalescing of small segments. */
        nerr("ERROR: TCP_NODELAY not supported\n");
        ret = -ENOSYS;
        break;

      case TCP_KEEPIDLE:  /* Start keepalives after this IDLE period */
        if (*value_len < sizeof(struct timeval))
          {
            /* REVISIT: POSIX says that we should truncate the value if it
             * is larger than value_len.   That just doesn't make sense
             * to me in this case.
             */

            ret = -EINVAL;
          }
        else
          {
            FAR struct timeval *tv = (FAR struct timeval *)value;

            if (tv == NULL)
              {
                ret        = -EINVAL;
              }
            else
              {
                /* Convert the KeepIdle time from deciseconds to struct
                 * timeval.
                 */

                net_dsec2timeval(conn->keepidle, tv);
                *value_len = sizeof(struct timeval);
                ret        = OK;
              }
          }
        break;

      case TCP_KEEPINTVL: /* Interval between keepalives */
        if (*value_len < sizeof(struct timeval))
          {
            /* REVISIT: POSIX says that we should truncate the value if it
             * is larger than value_len.   That just doesn't make sense
             * to me in this case.
             */

            ret = -EINVAL;
          }
        else
          {
            FAR struct timeval *tv = (FAR struct timeval *)value;

            if (tv == NULL)
              {
                ret        = -EINVAL;
              }
            else
              {
                /* Convert the KeepIdle time from deciseconds to struct
                 * timeval.
                 */

                net_dsec2timeval(conn->keepintvl, tv);
                *value_len = sizeof(struct timeval);
                ret        = OK;
              }
          }
        break;

      case TCP_KEEPCNT:   /* Number of keepalives before death */
        if (*value_len < sizeof(int))
          {
            /* REVISIT: POSIX says that we should truncate the value if it
             * is larger than value_len.   That just doesn't make sense
             * to me in this case.
             */

            ret              = -EINVAL;
          }
        else
          {
            FAR int *keepcnt = (FAR int *)value;
            *keepcnt         = (int)conn->keepcnt;
            *value_len       = sizeof(int);
            ret              = OK;
          }
        break;

      default:
        nerr("ERROR: Unrecognized TCP option: %d\n", option);
        ret = -ENOPROTOOPT;
        break;
    }

  return ret;
#else
  return -ENOPROTOOPT;
#endif /* CONFIG_NET_TCP_KEEPALIVE */
}
Esempio n. 19
0
int arp_send(in_addr_t ipaddr)
{
  FAR struct net_driver_s *dev;
  struct arp_notify_s notify;
  struct timespec delay;
  struct arp_send_s state;
  int ret;

  /* First check if destination is a local broadcast. */

  if (ipaddr == INADDR_BROADCAST)
    {
      /* We don't need to send the ARP request */

      return OK;
    }

#ifdef CONFIG_NET_IGMP
  /* Check if the destination address is a multicast address
   *
   * - IPv4: multicast addresses lie in the class D group -- The address range
   *   224.0.0.0 to 239.255.255.255 (224.0.0.0/4)
   *
   * - IPv6 multicast addresses are have the high-order octet of the
   *   addresses=0xff (ff00::/8.)
   */

  if (NTOHL(ipaddr) >= 0xe0000000 && NTOHL(ipaddr) <= 0xefffffff)
    {
      /* We don't need to send the ARP request */

      return OK;
    }
#endif

  /* Get the device that can route this request */

  dev = netdev_findby_ipv4addr(INADDR_ANY, ipaddr);
  if (!dev)
    {
      nerr("ERROR: Unreachable: %08lx\n", (unsigned long)ipaddr);
      ret = -EHOSTUNREACH;
      goto errout;
    }

  /* ARP support is only built if the Ethernet data link is supported.
   * Continue and send the ARP request only if this device uses the
   * Ethernet data link protocol.
   */

  if (dev->d_lltype != NET_LL_ETHERNET)
    {
      return OK;
    }

  /* Check if the destination address is on the local network. */

  if (!net_ipv4addr_maskcmp(ipaddr, dev->d_ipaddr, dev->d_netmask))
    {
      in_addr_t dripaddr;

      /* Destination address is not on the local network */

#ifdef CONFIG_NET_ROUTE
      /* We have a routing table.. find the correct router to use in
       * this case (or, as a fall-back, use the device's default router
       * address).  We will use the router IP address instead of the
       * destination address when determining the MAC address.
       */

      netdev_ipv4_router(dev, ipaddr, &dripaddr);
#else
      /* Use the device's default router IP address instead of the
       * destination address when determining the MAC address.
       */

      net_ipv4addr_copy(dripaddr, dev->d_draddr);
#endif
      ipaddr = dripaddr;
    }

  /* The destination address is on the local network.  Check if it is
   * the sub-net broadcast address.
   */

  else if (net_ipv4addr_broadcast(ipaddr, dev->d_netmask))
    {
      /* Yes.. We don't need to send the ARP request */

      return OK;
    }

  /* Allocate resources to receive a callback.  This and the following
   * initialization is performed with the network lock because we don't
   * want anything to happen until we are ready.
   */

  net_lock();
  state.snd_cb = arp_callback_alloc(dev);
  if (!state.snd_cb)
    {
      nerr("ERROR: Failed to allocate a callback\n");
      ret = -ENOMEM;
      goto errout_with_lock;
    }

  /* This semaphore is used for signaling and, hence, should not have
   * priority inheritance enabled.
   */

  (void)nxsem_init(&state.snd_sem, 0, 0); /* Doesn't really fail */
  nxsem_setprotocol(&state.snd_sem, SEM_PRIO_NONE);

  state.snd_retries   = 0;              /* No retries yet */
  state.snd_ipaddr    = ipaddr;         /* IP address to query */

  /* Remember the routing device name */

  strncpy((FAR char *)state.snd_ifname, (FAR const char *)dev->d_ifname,
          IFNAMSIZ);

  /* Now loop, testing if the address mapping is in the ARP table and re-
   * sending the ARP request if it is not.
   */

  ret = -ETIMEDOUT; /* Assume a timeout failure */

  while (state.snd_retries < CONFIG_ARP_SEND_MAXTRIES)
    {
      /* Check if the address mapping is present in the ARP table.  This
       * is only really meaningful on the first time through the loop.
       *
       * NOTE: If the ARP table is large than this could be a performance
       * issue.
       */

      if (arp_find(ipaddr, NULL) >= 0)
        {
          /* We have it!  Break out with success */

          ret = OK;
          break;
        }

      /* Set up the ARP response wait BEFORE we send the ARP request */

      arp_wait_setup(ipaddr, &notify);

      /* Arm/re-arm the callback */

      state.snd_sent      = false;
      state.snd_result    = -EBUSY;
      state.snd_cb->flags = (ARP_POLL | NETDEV_DOWN);
      state.snd_cb->priv  = (FAR void *)&state;
      state.snd_cb->event = arp_send_eventhandler;

      /* Notify the device driver that new TX data is available.
       * NOTES: This is in essence what netdev_ipv4_txnotify() does, which
       * is not possible to call since it expects a in_addr_t as
       * its single argument to lookup the network interface.
       */

      if (dev->d_txavail)
        {
          dev->d_txavail(dev);
        }

      /* Wait for the send to complete or an error to occur.
       * net_lockedwait will also terminate if a signal is received.
       */

      do
        {
          (void)net_lockedwait(&state.snd_sem);
        }
      while (!state.snd_sent);

      /* Check the result of the send operation */

      ret = state.snd_result;
      if (ret < 0)
        {
          /* Break out on a send failure */

          nerr("ERROR: Send failed: %d\n", ret);
          break;
        }

      /* Now wait for response to the ARP response to be received.  The
       * optimal delay would be the work case round trip time.
       * NOTE: The network is locked.
       */

      delay.tv_sec  = CONFIG_ARP_SEND_DELAYSEC;
      delay.tv_nsec = CONFIG_ARP_SEND_DELAYNSEC;

      ret = arp_wait(&notify, &delay);

      /* arp_wait will return OK if and only if the matching ARP response
       * is received.  Otherwise, it will return -ETIMEDOUT.
       */

      if (ret >= OK)
        {
          /* Break out if arp_wait() fails */

          break;
        }

      /* Increment the retry count */

      state.snd_retries++;
      nerr("ERROR: arp_wait failed: %d\n", ret);
    }

  nxsem_destroy(&state.snd_sem);
  arp_callback_free(dev, state.snd_cb);
errout_with_lock:
  net_unlock();
errout:
  return ret;
}
Esempio n. 20
0
int net_delroute_ipv6(net_ipv6addr_t target, net_ipv6addr_t netmask)
{
  struct route_match_ipv6_s match;
  struct net_route_ipv6_s route;
  struct file fshandle;
  off_t filesize;
  ssize_t nwritten;
  ssize_t nread;
  off_t pos;
  int nentries;
  int index;
  int ret;

  /* We must lock out other accesses to the routing table while we remove
   * entry
   */

  ret = net_lockroute_ipv6();
  if (ret < 0)
    {
       nerr("ERROR: net_lockroute_ipv6 failed: %d\n", ret);
       return ret;
    }

  /* Get the size of the routing table (in entries) */

  nentries = net_routesize_ipv6();
  if (nentries < 0)
    {
      ret = nentries;
      goto errout_with_lock;
    }
  else if (nentries == 0)
    {
      ret = -ENOENT;
      goto errout_with_lock;
    }

  /* Set up the comparison structure */

  net_ipv6addr_copy(match.target, target);
  net_ipv6addr_copy(match.netmask, netmask);
  match.index = 0;

  /* Then find the index into the routing table where the match can be found */

  ret = net_foreachroute_ipv6(net_match_ipv6, &match);
  if (ret < 0)
    {
      /* And error occurred */

      ret = ret;
      goto errout_with_lock;
    }
  else if (ret == 0)
    {
      /* No match found */

      ret = -ENOENT;
      goto errout_with_lock;
    }

  /* Open the routing table for read/write access */

  ret = net_openroute_ipv6(O_RDWR, &fshandle);
  if (ret < 0)
    {
      nerr("ERROR: Could not open IPv6 routing table: %d\n", ret);
      goto errout_with_lock;
    }

#ifdef CONFIG_ROUTE_IPv6_CACHEROUTE
  /* We are committed to modifying the routing table.  Flush the in-memory
   * routing table cache.
   */

  net_flushcache_ipv6();
#endif

  /* Loop, copying each entry, to the previous entry thus removing the entry
   * to be deleted.
   */

  for (index = match.index + 1; index < nentries; index++)
    {
      /* Seek to the current entry to be moved */

      pos = net_seekroute_ipv6(&fshandle, index);
      if (pos < 0)
        {
          nerr("ERROR: net_readroute_ipv6 failed: %ld\n", (long)pos);
          ret =(int)pos;
          goto errout_with_fshandle;
        }

      /* Read the routing table entry at this position */

      nread = net_readroute_ipv6(&fshandle, &route);
      if (nread < 0)
        {
          nerr("ERROR: net_readroute_ipv6 failed: %ld\n", (long)nread);
          ret = (int)nread;
          goto errout_with_fshandle;
        }
      else if (nread == 0)
        {
          nerr("ERROR: Unexpected end of file\n");
          ret = -EINVAL;
          goto errout_with_fshandle;
        }

      /* Seek to the previous entry to be replaced */

      pos = net_seekroute_ipv6(&fshandle, index - 1);
      if (pos < 0)
        {
          nerr("ERROR: net_readroute_ipv6 failed: %ld\n", (long)pos);
          ret =(int)pos;
          goto errout_with_fshandle;
        }

      /* Now write the record to its new location */

      nwritten = net_writeroute_ipv6(&fshandle, &route);
      if (nwritten < 0)
        {
          nerr("ERROR: net_readroute_ipv6 failed: %ld\n", (long)nwritten);
          ret = (int)nwritten;
          goto errout_with_fshandle;
        }
    }

  /* Now truncate the one duplicate entry at the end of the file.  This may
   * result in a zero length file.
   */

  filesize = (nentries - 1) * sizeof(struct net_route_ipv6_s);
  ret = file_truncate(&fshandle, filesize);

errout_with_fshandle:
  (void)net_closeroute_ipv6(&fshandle);

errout_with_lock:
  (void)net_unlockroute_ipv6();
  return ret;
}
Esempio n. 21
0
static uint16_t udp_datahandler(FAR struct net_driver_s *dev, FAR struct udp_conn_s *conn,
                                FAR uint8_t *buffer, uint16_t buflen)
{
  FAR struct iob_s *iob;
  int ret;
#ifdef CONFIG_NET_IPv6
  FAR struct sockaddr_in6 src_addr6;
#endif
#ifdef CONFIG_NET_IPv4
  FAR struct sockaddr_in src_addr4;
#endif
  FAR void  *src_addr;
  uint8_t src_addr_size;

  /* Allocate on I/O buffer to start the chain (throttling as necessary).
   * We will not wait for an I/O buffer to become available in this context.
   */

  iob = iob_tryalloc(true);
  if (iob == NULL)
    {
      nerr("ERROR: Failed to create new I/O buffer chain\n");
      return 0;
    }

#ifdef CONFIG_NET_IPv6
#ifdef CONFIG_NET_IPv4
  if (IFF_IS_IPv6(dev->d_flags))
#endif
    {
      FAR struct udp_hdr_s *udp   = UDPIPv6BUF;
      FAR struct ipv6_hdr_s *ipv6 = IPv6BUF;

      src_addr6.sin6_family = AF_INET6;
      src_addr6.sin6_port   = udp->srcport;

      net_ipv6addr_copy(src_addr6.sin6_addr.s6_addr, ipv6->srcipaddr);

      src_addr_size = sizeof(src_addr6);
      src_addr = &src_addr6;
    }
#endif /* CONFIG_NET_IPv6 */

#ifdef CONFIG_NET_IPv4
#ifdef CONFIG_NET_IPv6
  else
#endif
    {
#ifdef CONFIG_NET_IPv6
      /* Hybrid dual-stack IPv6/IPv4 implementations recognize a special
       * class of addresses, the IPv4-mapped IPv6 addresses.
       */

      if (conn->domain == PF_INET6)
        {
          FAR struct udp_hdr_s *udp   = UDPIPv6BUF;
          FAR struct ipv6_hdr_s *ipv6 = IPv6BUF;
          in_addr_t ipv4addr;

          /* Encode the IPv4 address as an IPv-mapped IPv6 address */

          src_addr6.sin6_family = AF_INET6;
          src_addr6.sin6_port = udp->srcport;

          ipv4addr = net_ip4addr_conv32(ipv6->srcipaddr);
          ip6_map_ipv4addr(ipv4addr, src_addr6.sin6_addr.s6_addr16);

          src_addr_size = sizeof(src_addr6);
          src_addr = &src_addr6;
        }
      else
#endif
        {
          FAR struct udp_hdr_s *udp   = UDPIPv4BUF;
          FAR struct ipv4_hdr_s *ipv4 = IPv4BUF;

          src_addr4.sin_family = AF_INET;
          src_addr4.sin_port   = udp->srcport;

          net_ipv4addr_copy(src_addr4.sin_addr.s_addr,
                            net_ip4addr_conv32(ipv4->srcipaddr));

          src_addr_size = sizeof(src_addr4);
          src_addr = &src_addr4;
        }
    }
#endif /* CONFIG_NET_IPv4 */

  /* Copy the src address info into the I/O buffer chain.  We will not wait
   * for an I/O buffer to become available in this context.  It there is
   * any failure to allocated, the entire I/O buffer chain will be discarded.
   */

  ret = iob_trycopyin(iob, (FAR const uint8_t *)&src_addr_size,
                      sizeof(uint8_t), 0, true);
  if (ret < 0)
    {
      /* On a failure, iob_trycopyin return a negated error value but does
       * not free any I/O buffers.
       */

      nerr("ERROR: Failed to add data to the I/O buffer chain: %d\n", ret);
      (void)iob_free_chain(iob);
      return 0;
    }

  ret = iob_trycopyin(iob, (FAR const uint8_t *)src_addr, src_addr_size,
                      sizeof(uint8_t), true);
  if (ret < 0)
    {
      /* On a failure, iob_trycopyin return a negated error value but does
       * not free any I/O buffers.
       */

      nerr("ERROR: Failed to add data to the I/O buffer chain: %d\n", ret);
      (void)iob_free_chain(iob);
      return 0;
    }

  if (buflen > 0)
    {
      /* Copy the new appdata into the I/O buffer chain */

      ret = iob_trycopyin(iob, buffer, buflen,
                          src_addr_size + sizeof(uint8_t), true);
      if (ret < 0)
        {
          /* On a failure, iob_trycopyin return a negated error value but
           * does not free any I/O buffers.
           */

          nerr("ERROR: Failed to add data to the I/O buffer chain: %d\n",
               ret);
          (void)iob_free_chain(iob);
          return 0;
        }
    }

  /* Add the new I/O buffer chain to the tail of the read-ahead queue */

  ret = iob_tryadd_queue(iob, &conn->readahead);
  if (ret < 0)
    {
      nerr("ERROR: Failed to queue the I/O buffer chain: %d\n", ret);
      (void)iob_free_chain(iob);
      return 0;
    }

#ifdef CONFIG_UDP_READAHEAD_NOTIFIER
  /* Provided notification(s) that additional UDP read-ahead data is
   * available.
   */

  udp_notifier_signal(conn);
#endif

  ninfo("Buffered %d bytes\n", buflen);
  return buflen;
}
Esempio n. 22
0
static int bcmf_ioctl(FAR struct net_driver_s *dev, int cmd,
                      unsigned long arg)
{
  int ret;
  FAR struct bcmf_dev_s *priv = (FAR struct bcmf_dev_s *)dev->d_private;

  /* Decode and dispatch the driver-specific IOCTL command */

  switch (cmd)
    {
      case SIOCSIWSCAN:
        ret = bcmf_wl_start_scan(priv, (struct iwreq *)arg);
        break;

      case SIOCGIWSCAN:
        ret = bcmf_wl_get_scan_results(priv, (struct iwreq *)arg);
        break;

      case SIOCSIFHWADDR:    /* Set device MAC address */
        ret = bcmf_wl_set_mac_address(priv, (struct ifreq *)arg);
        break;

      case SIOCSIWAUTH:
        ret = bcmf_wl_set_auth_param(priv, (struct iwreq *)arg);
        break;

      case SIOCSIWENCODEEXT:
        ret = bcmf_wl_set_encode_ext(priv, (struct iwreq *)arg);
        break;

      case SIOCSIWFREQ:     /* Set channel/frequency (Hz) */
        wlwarn("WARNING: SIOCSIWFREQ not implemented\n");
        ret = -ENOSYS;
        break;

      case SIOCGIWFREQ:     /* Get channel/frequency (Hz) */
        wlwarn("WARNING: SIOCGIWFREQ not implemented\n");
        ret = -ENOSYS;
        break;

      case SIOCSIWMODE:     /* Set operation mode */
        ret = bcmf_wl_set_mode(priv, (struct iwreq *)arg);
        break;

      case SIOCGIWMODE:     /* Get operation mode */
        wlwarn("WARNING: SIOCGIWMODE not implemented\n");
        ret = -ENOSYS;
        break;

      case SIOCSIWAP:       /* Set access point MAC addresses */
        wlwarn("WARNING: SIOCSIWAP not implemented\n");
        ret = -ENOSYS;
        break;

      case SIOCGIWAP:       /* Get access point MAC addresses */
        wlwarn("WARNING: SIOCGIWAP not implemented\n");
        ret = -ENOSYS;
        break;

      case SIOCSIWESSID:    /* Set ESSID (network name) */
        ret = bcmf_wl_set_ssid(priv, (struct iwreq *)arg);
        break;

      case SIOCGIWESSID:    /* Get ESSID */
        wlwarn("WARNING: SIOCGIWESSID not implemented\n");
        ret = -ENOSYS;
        break;

      case SIOCSIWRATE:     /* Set default bit rate (bps) */
        wlwarn("WARNING: SIOCSIWRATE not implemented\n");
        ret = -ENOSYS;
        break;

      case SIOCGIWRATE:     /* Get default bit rate (bps) */
        wlwarn("WARNING: SIOCGIWRATE not implemented\n");
        ret = -ENOSYS;
        break;

      case SIOCSIWTXPOW:    /* Set transmit power (dBm) */
        wlwarn("WARNING: SIOCSIWTXPOW not implemented\n");
        ret = -ENOSYS;
        break;

      case SIOCGIWTXPOW:    /* Get transmit power (dBm) */
        wlwarn("WARNING: SIOCGIWTXPOW not implemented\n");
        ret = -ENOSYS;
        break;

      default:
        nerr("ERROR: Unrecognized IOCTL command: %d\n", cmd);
        ret = -ENOTTY;  /* Special return value for this case */
        break;
    }

  return ret;
}
Esempio n. 23
0
xcpt_t arch_phy_irq(FAR const char *intf, xcpt_t handler, phy_enable_t *enable)
{
  irqstate_t flags;
  xcpt_t *phandler;
  xcpt_t oldhandler;
  gpio_pinset_t pinset;
  phy_enable_t enabler;
  int irq;

  DEBUGASSERT(intf);

  ninfo("%s: handler=%p\n", intf, handler);
  phyinfo("EMAC0: devname=%s\n", SAMV7_EMAC0_DEVNAME);

  if (strcmp(intf, SAMV7_EMAC0_DEVNAME) == 0)
    {
      phyinfo("Select EMAC0\n");

      phandler = &g_emac0_handler;
      pinset   = GPIO_EMAC0_INT;
      irq      = IRQ_EMAC0_INT;
      enabler  = sam_emac0_phy_enable;
    }
  else
    {
      nerr("ERROR: Unsupported interface: %s\n", intf);
      return NULL;
    }

  /* Disable interrupts until we are done.  This guarantees that the
   * following operations are atomic.
   */

  flags = enter_critical_section();

  /* Get the old interrupt handler and save the new one */

  oldhandler = *phandler;
  *phandler  = handler;

  /* Configure the interrupt */

  if (handler)
    {
      phyinfo("Configure pin: %08x\n", pinset);
      sam_gpioirq(pinset);

      phyinfo("Attach IRQ%d\n", irq);
      (void)irq_attach(irq, handler);
    }
  else
    {
      phyinfo("Detach IRQ%d\n", irq);
      (void)irq_detach(irq);
      enabler = NULL;
    }

  /* Return with the interrupt disabled in either case */

  sam_gpioirqdisable(irq);

  /* Return the enabling function pointer */

  if (enable)
    {
      *enable = enabler;
    }

  /* Return the old handler (so that it can be restored) */

  leave_critical_section(flags);
  return oldhandler;
}
Esempio n. 24
0
int sam_emac0_setmac(void)
{
  struct i2c_master_s *i2c;
  struct mtd_dev_s *at24;
  uint8_t mac[6];
  ssize_t nread;
  int ret;

  /* Get an instance of the TWI0 interface */

  i2c = sam_i2cbus_initialize(0);
  if (!i2c)
    {
      nerr("ERROR: Failed to initialize TWI0\n");
      return -ENODEV;
    }

  /* Initialize the AT24 driver */

  at24 = at24c_initialize(i2c);
  if (!at24)
    {
      nerr("ERROR: Failed to initialize the AT24 driver\n");
      (void)sam_i2cbus_uninitialize(i2c);
      return -ENODEV;
    }

  /* Configure the AT24 to access the extended memory region */

  ret = at24->ioctl(at24, MTDIOC_EXTENDED, 1);
  if (ret < 0)
    {
      nerr("ERROR: AT24 ioctl(MTDIOC_EXTENDED) failed: %d\n", ret);
      (void)sam_i2cbus_uninitialize(i2c);
      return ret;
    }

  /* Read the MAC address */

  nread = at24->read(at24, AT24XX_MACADDR_OFFSET, 6, mac);
  if (nread < 6)
    {
      nerr("ERROR: AT24 read(AT24XX_MACADDR_OFFSET) failed: ld\n", (long)nread);
      (void)sam_i2cbus_uninitialize(i2c);
      return (int)nread;
    }

  /* Put the AT24 back in normal memory access mode */

  ret = at24->ioctl(at24, MTDIOC_EXTENDED, 0);
  if (ret < 0)
    {
      nerr("ERROR: AT24 ioctl(MTDIOC_EXTENDED) failed: %d\n", ret);
    }

  /* Release the I2C instance.
   * REVISIT:  Need an interface to release the AT24 instance too
   */

  ret = sam_i2cbus_uninitialize(i2c);
  if (ret < 0)
    {
      nerr("ERROR: Failed to release the I2C interface: %d\n", ret);
    }

  ninfo("MAC: %02x:%02x:%02x:%02x:%02x:%02x\n",
        mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);

  /* Now configure the EMAC driver to use this MAC address */

  ret = sam_emac_setmacaddr(EMAC0_INTF, mac);
  if (ret < 0)
    {
      nerr("ERROR: Failed to set MAC address: %d\n", ret);
    }

  return ret;
}
Esempio n. 25
0
ssize_t psock_tcp_send(FAR struct socket *psock, FAR const void *buf,
                       size_t len)
{
  FAR struct tcp_conn_s *conn;
  FAR struct tcp_wrbuffer_s *wrb;
  net_lock_t save;
  ssize_t    result = 0;
  int        errcode;
  int        ret = OK;

  if (!psock || psock->s_crefs <= 0)
    {
      nerr("ERROR: Invalid socket\n");
      errcode = EBADF;
      goto errout;
    }

  if (psock->s_type != SOCK_STREAM || !_SS_ISCONNECTED(psock->s_flags))
    {
      nerr("ERROR: Not connected\n");
      errcode = ENOTCONN;
      goto errout;
    }

  /* Make sure that we have the IP address mapping */

  conn = (FAR struct tcp_conn_s *)psock->s_conn;
  DEBUGASSERT(conn);

#if defined(CONFIG_NET_ARP_SEND) || defined(CONFIG_NET_ICMPv6_NEIGHBOR)
#ifdef CONFIG_NET_ARP_SEND
#ifdef CONFIG_NET_ICMPv6_NEIGHBOR
  if (psock->s_domain == PF_INET)
#endif
    {
      /* Make sure that the IP address mapping is in the ARP table */

      ret = arp_send(conn->u.ipv4.raddr);
    }
#endif /* CONFIG_NET_ARP_SEND */

#ifdef CONFIG_NET_ICMPv6_NEIGHBOR
#ifdef CONFIG_NET_ARP_SEND
  else
#endif
    {
      /* Make sure that the IP address mapping is in the Neighbor Table */

      ret = icmpv6_neighbor(conn->u.ipv6.raddr);
    }
#endif /* CONFIG_NET_ICMPv6_NEIGHBOR */

  /* Did we successfully get the address mapping? */

  if (ret < 0)
    {
      nerr("ERROR: Not reachable\n");
      errcode = ENETUNREACH;
      goto errout;
    }
#endif /* CONFIG_NET_ARP_SEND || CONFIG_NET_ICMPv6_NEIGHBOR */

  /* Dump the incoming buffer */

  BUF_DUMP("psock_tcp_send", buf, len);

  /* Set the socket state to sending */

  psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_SEND);

  if (len > 0)
    {
      /* Allocate a write buffer.  Careful, the network will be momentarily
       * unlocked here.
       */

      save = net_lock();
      wrb = tcp_wrbuffer_alloc();
      if (!wrb)
        {
          /* A buffer allocation error occurred */

          nerr("ERROR: Failed to allocate write buffer\n");
          errcode = ENOMEM;
          goto errout_with_lock;
        }

      /* Allocate resources to receive a callback */

      if (!psock->s_sndcb)
        {
          psock->s_sndcb = tcp_callback_alloc(conn);
        }

      /* Test if the callback has been allocated */

      if (!psock->s_sndcb)
        {
          /* A buffer allocation error occurred */

          nerr("ERROR: Failed to allocate callback\n");
          errcode = ENOMEM;
          goto errout_with_wrb;
        }

      /* Set up the callback in the connection */

      psock->s_sndcb->flags = (TCP_ACKDATA | TCP_REXMIT | TCP_POLL |
                               TCP_DISCONN_EVENTS);
      psock->s_sndcb->priv  = (FAR void *)psock;
      psock->s_sndcb->event = psock_send_interrupt;

      /* Initialize the write buffer */

      WRB_SEQNO(wrb) = (unsigned)-1;
      WRB_NRTX(wrb)  = 0;
      result = WRB_COPYIN(wrb, (FAR uint8_t *)buf, len);

      /* Dump I/O buffer chain */

      WRB_DUMP("I/O buffer chain", wrb, WRB_PKTLEN(wrb), 0);

      /* psock_send_interrupt() will send data in FIFO order from the
       * conn->write_q
       */

      sq_addlast(&wrb->wb_node, &conn->write_q);
      ninfo("Queued WRB=%p pktlen=%u write_q(%p,%p)\n",
            wrb, WRB_PKTLEN(wrb),
            conn->write_q.head, conn->write_q.tail);

      /* Notify the device driver of the availability of TX data */

      send_txnotify(psock, conn);
      net_unlock(save);
    }

  /* Set the socket state to idle */

  psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_IDLE);

  /* Check for errors.  Errors are signalled by negative errno values
   * for the send length
   */

  if (result < 0)
    {
      errcode = result;
      goto errout;
    }

  /* If net_lockedwait failed, then we were probably reawakened by a signal.
   * In this case, net_lockedwait will have set errno appropriately.
   */

  if (ret < 0)
    {
      errcode = -ret;
      goto errout;
    }

  /* Return the number of bytes actually sent */

  return result;

errout_with_wrb:
  tcp_wrbuffer_release(wrb);

errout_with_lock:
  net_unlock(save);

errout:
  set_errno(errcode);
  return ERROR;
}
Esempio n. 26
0
static void slip_txtask(int argc, FAR char *argv[])
{
  FAR struct slip_driver_s *priv;
  unsigned int index = *(argv[1]) - '0';
  net_lock_t flags;
  systime_t msec_start;
  systime_t msec_now;
  unsigned int hsec;

  nerr("index: %d\n", index);
  DEBUGASSERT(index < CONFIG_NET_SLIP_NINTERFACES);

  /* Get our private data structure instance and wake up the waiting
   * initialization logic.
   */

  priv = &g_slip[index];
  slip_semgive(priv);

  /* Loop forever */

  msec_start = clock_systimer() * MSEC_PER_TICK;
  for (;  ; )
    {
      /* Wait for the timeout to expire (or until we are signaled by by  */

      slip_semtake(priv);
      if (!priv->txnodelay)
        {
          slip_semgive(priv);
          usleep(SLIP_WDDELAY);
        }
      else
        {
          priv->txnodelay = false;
          slip_semgive(priv);
        }

      /* Is the interface up? */

      if (priv->bifup)
        {
          /* Get exclusive access to the network (if it it is already being used
           * slip_rxtask, then we have to wait).
           */

          slip_semtake(priv);

          /* Poll the networking layer for new XMIT data. */

          flags = net_lock();
          priv->dev.d_buf = priv->txbuf;

          /* Has a half second elapsed since the last timer poll? */

          msec_now = clock_systimer() * MSEC_PER_TICK;
          hsec = (unsigned int)(msec_now - msec_start) / (MSEC_PER_SEC / 2);
          if (hsec)
            {
              /* Yes, perform the timer poll */

              (void)devif_timer(&priv->dev, slip_txpoll);
              msec_start += hsec * (MSEC_PER_SEC / 2);
            }
          else
            {
              /* No, perform the normal TX poll */

              (void)devif_poll(&priv->dev, slip_txpoll);
            }

          net_unlock(flags);
          slip_semgive(priv);
        }
    }
}
Esempio n. 27
0
int net_foreachroute_ipv4(route_handler_ipv4_t handler, FAR void *arg)
{
  struct net_route_ipv4_s route;
  struct file fshandle;
  ssize_t nread;
  int ret = 0;

  /* Open the IPv4 routing table for read-only access */

  ret = net_openroute_ipv4(O_RDONLY, &fshandle);
  if (ret < 0)
    {
      /* Special case:  the routing table has not yet been created.  This is
       * not an error.  We will just want to return successful completion of
       * the traversal.
       */

       if (ret == -ENOENT)
         {
           /* The routing table does not exit.. return successful completion */

           ninfo("The IPv4 routing table file does not exist\n");
           return OK;
         }

       /* Some other error occurred. */

       nerr("ERROR: Could not open IPv4 routing table: %d\n", ret);
       return ret;
    }

  /* Read each entry from the routing table */

  for (; ; )
    {
      nread = net_readroute_ipv4(&fshandle, &route);
      if (nread < 0)
        {
          /* File read error */

          nerr("ERROR: net_readroute_ipv4() failed: %ld\n", (long)nread);
          ret = (int)nread;
          break;
        }
      else if (nread == 0)
        {
          /* End of file */

          ret = OK;
          break;
        }

      /* Call the handler. */

      ret = handler(&route, arg);
      if (ret != OK)
        {
          /* Terminate early if the handler returns any non-zero value. */

          break;
        }
    }

  (void)net_closeroute_ipv4(&fshandle);
  return ret;
}
Esempio n. 28
0
static inline void slip_receive(FAR struct slip_driver_s *priv)
{
  uint8_t ch;

  /* Copy the data data from the hardware to to the RX buffer until we
   * put together a whole packet. Make sure not to copy them into the
   * packet if we run out of room.
   */

  ninfo("Receiving packet\n");
  for (; ; )
    {
      /* Get the next character in the stream. */

      ch = slip_getc(priv);

      /* Handle bytestuffing if necessary */

      switch (ch)
        {
        /* If it's an END character then we're done with the packet.
         * (OR we are just starting a packet)
         */

        case SLIP_END:
          {
            ninfo("END\n");

            /* A minor optimization: if there is no data in the packet,
             * ignore it. This is meant to avoid bothering IP with all the
             * empty packets generated by the duplicate END characters which
             * are in turn sent to try to detect line noise.
             */

            if (priv->rxlen > 0)
              {
                ninfo("Received packet size %d\n", priv->rxlen);
                return;
              }
          }
          break;

        /* if it's the same code as an ESC character, wait and get another
         * character and then figure out what to store in the packet based
         * on that.
         */

        case SLIP_ESC:
          {
            ninfo("ESC\n");
            ch = slip_getc(priv);

            /* if "ch" is not one of these two, then we have a protocol
             * violation.  The best bet seems to be to leave the byte alone
             * and just stuff it into the packet
             */

            switch (ch)
              {
              case SLIP_ESC_END:
                ninfo("ESC-END\n");
                ch = SLIP_END;
                break;

               case SLIP_ESC_ESC:
                ninfo("ESC-ESC\n");
                ch = SLIP_ESC;
                break;

              default:
                nerr("ERROR: Protocol violation: %02x\n", ch);
                break;
              }

            /* Here we fall into the default handler and let it store the
             * character for us
             */
          }

        default:
          {
            if (priv->rxlen < CONFIG_NET_SLIP_MTU+2)
              {
                priv->rxbuf[priv->rxlen++] = ch;
              }
          }
          break;
        }
    }
}
Esempio n. 29
0
static int iob_copyin_internal(FAR struct iob_s *iob, FAR const uint8_t *src,
                               unsigned int len, unsigned int offset,
                               bool throttled, bool can_block)
{
  FAR struct iob_s *head = iob;
  FAR struct iob_s *next;
  FAR uint8_t *dest;
  unsigned int ncopy;
  unsigned int avail;
  unsigned int total = len;

  ninfo("iob=%p len=%u offset=%u\n", iob, len, offset);
  DEBUGASSERT(iob && src);

  /* The offset must applied to data that is already in the I/O buffer chain */

  if (offset > iob->io_pktlen)
    {
      nerr("ERROR: offset is past the end of data: %u > %u\n",
           offset, iob->io_pktlen);
      return -ESPIPE;
    }

  /* Skip to the I/O buffer containing the data offset */

  while (offset > iob->io_len)
    {
      offset -= iob->io_len;
      iob     = iob->io_flink;
    }

  /* Then loop until all of the I/O data is copied from the user buffer */

  while (len > 0)
    {
      next = iob->io_flink;

      /* Get the destination I/O buffer address and the amount of data
       * available from that address.
       */

      dest  = &iob->io_data[iob->io_offset + offset];
      avail = iob->io_len - offset;

      ninfo("iob=%p avail=%u len=%u next=%p\n", iob, avail, len, next);

      /* Will the rest of the copy fit into this buffer, overwriting
       * existing data.
       */

      if (len > avail)
        {
          /* No.. Is this the last buffer in the chain? */

          if (next)
            {
              /* No.. clip to size that will overwrite.  We cannot
               * extend the length of an I/O block in mid-chain.
               */

              ncopy = avail;
            }
          else
            {
              unsigned int maxlen;
              unsigned int newlen;

              /* Yes.. We can extend this buffer to the up to the very end. */

              maxlen = CONFIG_IOB_BUFSIZE - iob->io_offset;

              /* This is the new buffer length that we need.  Of course,
               * clipped to the maximum possible size in this buffer.
               */

              newlen = len + offset;
              if (newlen > maxlen)
                {
                  newlen = maxlen;
                }

              /* Set the new length and increment the packet length */

              head->io_pktlen += (newlen - iob->io_len);
              iob->io_len      = newlen;

              /* Set the new number of bytes to copy */

              ncopy = newlen - offset;
            }
        }
      else
        {
          /* Yes.. Copy all of the remaining bytes */

          ncopy = len;
        }

      /* Copy from the user buffer to the I/O buffer.  */

      memcpy(dest, src, ncopy);
      ninfo("iob=%p Copy %u bytes new len=%u\n",
            iob, ncopy, iob->io_len);

      /* Adjust the total length of the copy and the destination address in
       * the user buffer.
       */

      len -= ncopy;
      src += ncopy;

      /* Skip to the next I/O buffer in the chain.  First, check if we
       * are at the end of the buffer chain.
       */

      if (len > 0 && !next)
        {
          /* Yes.. allocate a new buffer.
           *
           * Copy as many bytes as possible.  If we have successfully copied
           * any already don't block, otherwise block if we're allowed.
           */

          if (!can_block || len < total)
            {
              next = iob_tryalloc(throttled);
            }
          else
            {
              next = iob_alloc(throttled);
            }

          if (next == NULL)
            {
              nerr("ERROR: Failed to allocate I/O buffer\n");
              return len;
            }

          /* Add the new, empty I/O buffer to the end of the buffer chain. */

          iob->io_flink = next;
          ninfo("iob=%p added to the chain\n", iob);
        }

      iob = next;
      offset = 0;
    }

  return 0;
}
Esempio n. 30
0
int slip_initialize(int intf, FAR const char *devname)
{
  FAR struct slip_driver_s *priv;
  char buffer[8];
  FAR char *argv[2];

  /* Get the interface structure associated with this interface number. */

  DEBUGASSERT(intf < CONFIG_NET_SLIP_NINTERFACES);
  priv = &g_slip[intf];

  /* Initialize the driver structure */

  memset(priv, 0, sizeof(struct slip_driver_s));
  priv->dev.d_ifup    = slip_ifup;     /* I/F up (new IP address) callback */
  priv->dev.d_ifdown  = slip_ifdown;   /* I/F down callback */
  priv->dev.d_txavail = slip_txavail;  /* New TX data callback */
#ifdef CONFIG_NET_IGMP
  priv->dev.d_addmac  = slip_addmac;   /* Add multicast MAC address */
  priv->dev.d_rmmac   = slip_rmmac;    /* Remove multicast MAC address */
#endif
  priv->dev.d_private = priv;          /* Used to recover private state from dev */

  /* Open the device */

  priv->fd            = open(devname, O_RDWR, 0666);
  if (priv->fd < 0)
    {
      nerr("ERROR: Failed to open %s: %d\n", devname, errno);
      return -errno;
    }

  /* Initialize the wait semaphore */

  sem_init(&priv->waitsem, 0, 0);

  /* Put the interface in the down state.  This usually amounts to resetting
   * the device and/or calling slip_ifdown().
   */

  slip_ifdown(&priv->dev);

  /* Start the SLIP receiver task */

  snprintf(buffer, 8, "%d", intf);
  argv[0] = buffer;
  argv[1] = NULL;

  priv->rxpid = task_create("rxslip", CONFIG_NET_SLIP_DEFPRIO,
                            CONFIG_NET_SLIP_STACKSIZE, (main_t)slip_rxtask,
                            (FAR char * const *)argv);
  if (priv->rxpid < 0)
    {
      nerr("ERROR: Failed to start receiver task\n");
      return -errno;
    }

  /* Wait and make sure that the receive task is started. */

  slip_semtake(priv);

  /* Start the SLIP transmitter task */

  priv->txpid = task_create("txslip", CONFIG_NET_SLIP_DEFPRIO,
                            CONFIG_NET_SLIP_STACKSIZE, (main_t)slip_txtask,
                            (FAR char * const *)argv);
  if (priv->txpid < 0)
    {
      nerr("ERROR: Failed to start receiver task\n");
      return -errno;
    }

  /* Wait and make sure that the transmit task is started. */

  slip_semtake(priv);

  /* Bump the semaphore count so that it can now be used as a mutex */

  slip_semgive(priv);

  /* Register the device with the OS so that socket IOCTLs can be performed */

  (void)netdev_register(&priv->dev, NET_LL_SLIP);

  /* When the RX and TX tasks were created, the TTY file descriptor was
   * dup'ed for each task.  This task no longer needs the file descriptor
   * and we can safely close it.
   */

  close(priv->fd);
  return OK;
}