Example #1
0
int dup2(int sockfd1, int sockfd2)
#endif
{
  FAR struct socket *psock1;
  FAR struct socket *psock2;
  int err;
  int ret;

  /* Lock the scheduler throughout the following */

  sched_lock();

  /* Get the socket structures underly both descriptors */

  psock1 = sockfd_socket(sockfd1);
  psock2 = sockfd_socket(sockfd2);

  /* Verify that the sockfd1 and sockfd2 both refer to valid socket
   * descriptors and that sockfd2 corresponds to allocated socket
   */

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

  /* If sockfd2 also valid, allocated socket, then we will have to
   * close it!
   */

  if (psock2->s_crefs > 0)
    {
      net_close(sockfd2);
    }

  /* Duplicate the socket state */

  ret = net_clone(psock1, psock2);
  if (ret < 0)
    {
      err = -ret;
      goto errout;
    }

  sched_unlock();
  return OK;

errout:
  sched_unlock();
  errno = err;
  return ERROR;
}
Example #2
0
File: sendto.c Project: dagar/NuttX
ssize_t sendto(int sockfd, FAR const void *buf, size_t len, int flags,
               FAR const struct sockaddr *to, socklen_t tolen)
{
  FAR struct socket *psock;
  ssize_t ret;

  /* sendto() is a cancellation point */

  (void)enter_cancellation_point();

  /* Get the underlying socket structure */

  psock = sockfd_socket(sockfd);

  /* And let psock_sendto do all of the work */

  ret = psock_sendto(psock, buf, len, flags, to, tolen);
  if (ret < 0)
    {
      set_errno((int)-ret);
      ret = ERROR;
    }

  leave_cancellation_point();
  return ret;
}
Example #3
0
int connect(int sockfd, FAR const struct sockaddr *addr, socklen_t addrlen)
{
  /* Get the underlying socket structure */

  FAR struct socket *psock = sockfd_socket(sockfd);

  /* Then let psock_connect() do all of the work */

  return psock_connect(psock, addr, addrlen);
}
Example #4
0
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
{
  /* Make the socket descriptor to the underlying socket structure */

  FAR struct socket *psock = sockfd_socket(sockfd);

  /* Then let psock_bind do all of the work */

  return psock_bind(psock, addr, addrlen);
}
Example #5
0
int netdev_ioctl(int sockfd, int cmd, unsigned long arg)
{
  FAR struct socket *psock = sockfd_socket(sockfd);
  int ret;

  /* Check if this is a valid command.  In all cases, arg is a pointer that has
   * been cast to unsigned long.  Verify that the value of the to-be-pointer is
   * non-NULL.
   */

  if (!_SIOCVALID(cmd))
    {
      ret = -ENOTTY;
      goto errout;
    }

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

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

  /* Execute the command */

  ret = netdev_ifrioctl(psock, cmd, (FAR struct ifreq*)((uintptr_t)arg));
#ifdef CONFIG_NET_IGMP
  if (ret == -ENOTTY)
    {

      ret = netdev_imsfioctl(psock, cmd, (FAR struct ip_msfilter*)((uintptr_t)arg));
    }
#endif
#ifdef CONFIG_NET_ROUTE
  if (ret == -ENOTTY)
    {
      ret = netdev_rtioctl(psock, cmd, (FAR struct rtentry*)((uintptr_t)arg));
    }
#endif

  /* Check for success or failure */

  if (ret >= 0)
    {
      return ret;
    }

/* On failure, set the errno and return -1 */

errout:
  errno = -ret;
  return ERROR;
}
Example #6
0
void sockfd_release(int sockfd)
{
  /* Get the socket structure for this sockfd */

  FAR struct socket *psock = sockfd_socket(sockfd);

  /* Get the socket structure for this sockfd */

  if (psock)
    {
      sock_release(psock);
    }
}
Example #7
0
ssize_t recvfrom(int sockfd, FAR void *buf, size_t len, int flags,
                 FAR struct sockaddr *from, FAR socklen_t *fromlen)
{
  FAR struct socket *psock;

  /* Get the underlying socket structure */

  psock = sockfd_socket(sockfd);

  /* Then let psock_recvfrom() do all of the work */

  return psock_recvfrom(psock, buf, len, flags, from, fromlen);
}
ssize_t sendto(int sockfd, FAR const void *buf, size_t len, int flags,
               FAR const struct sockaddr *to, socklen_t tolen)
{
  FAR struct socket *psock;

  /* Get the underlying socket structure */

  psock = sockfd_socket(sockfd);

  /* And let psock_sendto do all of the work */

  return psock_sendto(psock, buf, len, flags, to, tolen);
}
Example #9
0
int net_poll(int sockfd, struct pollfd *fds, bool setup)
{
#ifndef HAVE_NETPOLL
  return -ENOSYS;
#else
  FAR struct socket *psock;
  int ret;

  /* Get the underlying socket structure and verify that the sockfd
   * corresponds to valid, allocated socket
   */

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

#ifdef CONFIG_NET_UDP
  /* poll() not supported for UDP */

  if (psock->s_type != SOCK_STREAM)
    {
      ret = -ENOSYS;
      goto errout;
    }
#endif

  /* Check if we are setting up or tearing down the poll */
 
  if (setup)
    {
      /* Perform the TCP/IP poll() setup */

      ret = net_pollsetup(psock, fds);
    }
  else
    {
      /* Perform the TCP/IP poll() teardown */

      ret = net_pollteardown(psock, fds);
    }

errout:
  return ret;
#endif /* HAVE_NETPOLL */
}
Example #10
0
int setsockopt(int sockfd, int level, int option, const void *value, socklen_t value_len)
{
  FAR struct socket *psock;

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

  psock = sockfd_socket(sockfd);
  if (!psock || psock->s_crefs <= 0)
    {
      set_errno(EBADF);
      return ERROR;
    }

  /* Then let psock_setockopt() do all of the work */

  return psock_setsockopt(psock, level, option, value, value_len);
}
Example #11
0
File: send.c Project: a1ien/nuttx
ssize_t send(int sockfd, FAR const void *buf, size_t len, int flags)
{
  FAR struct socket *psock;
  ssize_t ret;

  /* send() is a cancellation point */

  (void)enter_cancellation_point();

  /* Get the underlying socket structure */

  psock = sockfd_socket(sockfd);

  /* And let psock_send do all of the work */

  ret = psock_send(psock, buf, len, flags);
  leave_cancellation_point();
  return ret;
}
Example #12
0
int socket(int domain, int type, int protocol)
{
  FAR struct socket *psock;
  int sockfd;
  int ret;

  /* Allocate a socket descriptor */

  sockfd = sockfd_allocate(0);
  if (sockfd < 0)
    {
      set_errno(ENFILE);
      return ERROR;
    }

  /* Get the underlying socket structure */

  psock = sockfd_socket(sockfd);
  if (!psock)
    {
      set_errno(ENOSYS); /* should not happen */
      goto errout;
    }

  /* Initialize the socket structure */

  ret = psock_socket(domain, type, protocol, psock);
  if (ret < 0)
    {
      /* Error already set by psock_socket() */

      goto errout;
    }

  return sockfd;

errout:
  sockfd_release(sockfd);
  return ERROR;
}
Example #13
0
int net_poll(int sockfd, struct pollfd *fds, bool setup)
{
#ifndef HAVE_NETPOLL
  return -ENOSYS;
#else
  FAR struct socket *psock;

  /* Get the underlying socket structure and verify that the sockfd
   * corresponds to valid, allocated socket
   */

  psock = sockfd_socket(sockfd);
  if (!psock || psock->s_crefs <= 0)
    {
      return -EBADF;
    }

  /* Then let psock_poll() do the heavy lifting */

  return psock_poll(psock, fds, setup);
#endif /* HAVE_NETPOLL */
}
Example #14
0
FAR char *telnetd_driver(int sd, FAR struct telnetd_s *daemon)
{
  FAR struct telnetd_dev_s *priv;
  FAR struct socket *psock;
  FAR char *devpath = NULL;
  int ret;

  /* Allocate instance data for this driver */

  priv = (FAR struct telnetd_dev_s*)malloc(sizeof(struct telnetd_dev_s));
  if (!priv)
    {
      nlldbg("Failed to allocate the driver data structure\n");
      return NULL;
    }

  /* Initialize the allocated driver instance */

  sem_init(&priv->td_exclsem, 0, 1);

  priv->td_state   = STATE_NORMAL;
  priv->td_crefs   = 0;
  priv->td_pending = 0;
  priv->td_offset  = 0;

  /* Clone the internal socket structure.  We do this so that it will be
   * independent of threads and of socket descriptors (the original socket
   * instance resided in the daemon's socket array).
   */

  psock = sockfd_socket(sd);
  if (!psock)
    {
      nlldbg("Failed to convert sd=%d to a socket structure\n", sd);
      goto errout_with_dev;
    }

  ret = net_clone(psock, &priv->td_psock);
  if (ret < 0)
    {
      nlldbg("net_clone failed: %d\n", ret);
      goto errout_with_dev;
    }

  /* And close the original */

  psock_close(psock);

  /* Allocation a unique minor device number of the telnet drvier */

  do
    {
      ret = sem_wait(&g_telnetdcommon.exclsem);
      if (ret < 0 && errno != -EINTR)
        {
          goto errout_with_dev;
        }
    }
  while (ret < 0);

  priv->td_minor = g_telnetdcommon.minor;
  g_telnetdcommon.minor++;
  sem_post(&g_telnetdcommon.exclsem);

  /* Create a path and name for the driver. */

  ret = asprintf(&devpath, TELNETD_DEVFMT, priv->td_minor);
  if (ret < 0)
    {
      nlldbg("Failed to allocate the driver path\n");
      goto errout_with_dev;
    }

  /* Register the driver */

  ret = register_driver(devpath, &g_telnetdfops, 0666, priv);
  if (ret < 0)
    {
      nlldbg("Failed to register the driver %s: %d\n", devpath, ret);
      goto errout_with_devpath;
    }

  /* Return the path to the new telnet driver */

  return devpath;

errout_with_devpath:
  free(devpath);
errout_with_dev:
  free(priv);
  return NULL;
}
Example #15
0
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
{
  FAR struct socket *psock = sockfd_socket(sockfd);
  FAR struct socket *pnewsock;
  FAR struct uip_conn *conn;
  struct accept_s state;
#ifdef CONFIG_NET_IPv6
  FAR struct sockaddr_in6 *inaddr = (struct sockaddr_in6 *)addr;
#else
  FAR struct sockaddr_in *inaddr = (struct sockaddr_in *)addr;
#endif
  uip_lock_t save;
  int newfd;
  int err;
  int ret;

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

  if (!psock || psock->s_crefs <= 0)
    {
      /* It is not a valid socket description.  Distinguish between the cases
       * where sockfd is a just valid and when it is a valid file descriptor used
       * in the wrong context.
       */

#if CONFIG_NFILE_DESCRIPTORS > 0
      if ((unsigned int)sockfd < CONFIG_NFILE_DESCRIPTORS)
        {
          err = ENOTSOCK;
        }
      else
#endif
        {
          err = EBADF;
        }
      goto errout;
    }

  /* We have a socket descriptor, but it is a stream? */

  if (psock->s_type != SOCK_STREAM)
    {
      err = EOPNOTSUPP;
      goto errout;
    }

  /* Is the socket listening for a connection? */

  if (!_SS_ISLISTENING(psock->s_flags))
    {
      err = EINVAL;
      goto errout;
    }

  /* Verify that a valid memory block has been provided to receive the
   * address
   */

  if (addr)
    {
#ifdef CONFIG_NET_IPv6
      if (*addrlen < sizeof(struct sockaddr_in6))
#else
      if (*addrlen < sizeof(struct sockaddr_in))
#endif
        {
          err = EBADF;
          goto errout;
        }
    }

  /* Allocate a socket descriptor for the new connection now (so that it
   * cannot fail later)
   */

  newfd = sockfd_allocate(0);
  if (newfd < 0)
    {
      err = ENFILE;
      goto errout;
    }

  pnewsock = sockfd_socket(newfd);
  if (!pnewsock)
    {
      err = ENFILE;
      goto errout_with_socket;
    }

  /* Check the backlog to see if there is a connection already pending for
   * this listener.
   */

  save = uip_lock();
  conn = (struct uip_conn *)psock->s_conn;

#ifdef CONFIG_NET_TCPBACKLOG
  state.acpt_newconn = uip_backlogremove(conn);
  if (state.acpt_newconn)
    {
      /* Yes... get the address of the connected client */

      nvdbg("Pending conn=%p\n", state.acpt_newconn);
      accept_tcpsender(state.acpt_newconn, inaddr);
    }

  /* In general, this uIP-based implementation will not support non-blocking
   * socket operations... except in a few cases:  Here for TCP accept with backlog
   * enabled.  If this socket is configured as non-blocking then return EAGAIN
   * if there is no pending connection in the backlog.
   */

  else if (_SS_ISNONBLOCK(psock->s_flags))
    {
      err = EAGAIN;
      goto errout_with_lock;
    }
  else
#endif
    {
      /* Set the socket state to accepting */

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

      /* Perform the TCP accept operation */

      /* Initialize the state structure.  This is done with interrupts
       * disabled because we don't want anything to happen until we
       * are ready.
       */

      state.acpt_addr       = inaddr;
      state.acpt_newconn    = NULL;
      state.acpt_result     = OK;
      sem_init(&state.acpt_sem, 0, 0);

      /* Set up the callback in the connection */

      conn->accept_private  = (void*)&state;
      conn->accept          = accept_interrupt;

      /* Wait for the send to complete or an error to occur:  NOTES: (1)
       * uip_lockedwait will also terminate if a signal is received, (2) interrupts
       * may be disabled!  They will be re-enabled while the task sleeps and
       * automatically re-enabled when the task restarts.
       */

      ret = uip_lockedwait(&state.acpt_sem);

      /* Make sure that no further interrupts are processed */

      conn->accept_private = NULL;
      conn->accept         = NULL;

      sem_destroy(&state. acpt_sem);

      /* Set the socket state to idle */

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

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

      if (state.acpt_result != 0)
        {
          err = state.acpt_result;
          goto errout_with_lock;
        }

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

      if (ret < 0)
        {
          err = -ret;
          goto errout_with_lock;
        }
    }

  /* Initialize the socket structure and mark the socket as connected.
   * (The reference count on the new connection structure was set in the
   * interrupt handler).
   */

  pnewsock->s_type   = SOCK_STREAM;
  pnewsock->s_conn   = state.acpt_newconn;
  pnewsock->s_flags |= _SF_CONNECTED;
  pnewsock->s_flags &= ~_SF_CLOSED;

  /* Begin monitoring for TCP connection events on the newly connected socket */

  net_startmonitor(pnewsock);
  uip_unlock(save);
  return newfd;

errout_with_lock:
  uip_unlock(save);

errout_with_socket:
  sockfd_release(newfd);

errout:
  errno = err;
  return ERROR;
}
Example #16
0
int getsockname(int sockfd, FAR struct sockaddr *addr, FAR socklen_t *addrlen)
{
  FAR struct socket *psock = sockfd_socket(sockfd);
  int ret;
  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

  /* Handle by address domain */

  switch (psock->s_domain)
    {
#ifdef CONFIG_NET_IPv4
    case PF_INET:
      ret = ipv4_getsockname(psock, addr, addrlen);
      break;
#endif

#ifdef CONFIG_NET_IPv6
    case PF_INET6:
      ret = ipv6_getsockname(psock, addr, addrlen);
      break;
#endif

    case PF_PACKET:
    default:
      err = EAFNOSUPPORT;
      goto errout;
    }

  /* Check for failure */

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

  return OK;

errout:
  set_errno(err);
  return ERROR;
}
Example #17
0
FAR struct aio_container_s *aio_contain(FAR struct aiocb *aiocbp)
{
  FAR struct aio_container_s *aioc;
  union
  {
#ifdef AIO_HAVE_FILEP
    FAR struct file *filep;
#endif
#ifdef AIO_HAVE_FILEP
    FAR struct socket *psock;
#endif
    FAR void *ptr;
  } u;
#ifdef CONFIG_PRIORITY_INHERITANCE
  struct sched_param param;
#endif

#if defined(AIO_HAVE_FILEP) && defined(AIO_HAVE_PSOCK)
  if (aiocbp->aio_fildes  >= CONFIG_NFILE_DESCRIPTORS)
#endif
#ifdef AIO_HAVE_FILEP
    {
      /* Get the file structure corresponding to the file descriptor. */

      u.filep = fs_getfilep(aiocbp->aio_fildes);
      if (!u.filep)
        {
          /* The errno value has already been set */

          return NULL;
        }
    }
#endif
#if defined(AIO_HAVE_FILEP) && defined(AIO_HAVE_PSOCK)
  else
#endif
#ifdef AIO_HAVE_PSOCK
    {
      /* Get the socket structure corresponding to the socket descriptor */

      u.psock = sockfd_socket(aiocbp->aio_fildes);
      if (!u.psock)
        {
          /* Does not set the errno.  EBADF is the most likely explanation. */

          set_errno(EBADF);
          return NULL;
        }
    }
#endif

  /* Allocate the AIO control block container, waiting for one to become
   * available if necessary.  This should never fail.
   */

  aioc = aioc_alloc();
  DEBUGASSERT(aioc);

  /* Initialize the container */

  memset(aioc, 0, sizeof(struct aio_container_s));
  aioc->aioc_aiocbp = aiocbp;
  aioc->u.aioc_filep = u.ptr;
  aioc->aioc_pid = getpid();

#ifdef CONFIG_PRIORITY_INHERITANCE
  DEBUGVERIFY(sched_getparam (aioc->aioc_pid, &param));
  aioc->aioc_prio = param.sched_priority;
#endif

  /* Add the container to the pending transfer list. */

  aio_lock();
  dq_addlast(&aioc->aioc_link, &g_aio_pending);
  aio_unlock();
  return aioc;
}
Example #18
0
ssize_t send(int sockfd, const void *buf, size_t len, int flags)
{
  FAR struct socket *psock = sockfd_socket(sockfd);
  struct send_s state;
  uip_lock_t save;
  int err;
  int ret = OK;

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

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

  /* If this is an un-connected socket, then return ENOTCONN */

  if (psock->s_type != SOCK_STREAM || !_SS_ISCONNECTED(psock->s_flags))
    {
      err = ENOTCONN;
      goto errout;
    }

  /* Set the socket state to sending */

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

  /* Perform the TCP send operation */

  /* Initialize the state structure.  This is done with interrupts
   * disabled because we don't want anything to happen until we
   * are ready.
   */

  save                = uip_lock();
  memset(&state, 0, sizeof(struct send_s));
  (void)sem_init(&state. snd_sem, 0, 0); /* Doesn't really fail */
  state.snd_sock      = psock;             /* Socket descriptor to use */
  state.snd_buflen    = len;               /* Number of bytes to send */
  state.snd_buffer    = buf;               /* Buffer to send from */

  if (len > 0)
    {
      struct uip_conn *conn = (struct uip_conn*)psock->s_conn;

      /* Allocate resources to receive a callback */

      state.snd_cb = uip_tcpcallbackalloc(conn);
      if (state.snd_cb)
        {
          /* Get the initial sequence number that will be used */

          state.snd_isn         = uip_tcpgetsequence(conn->sndseq);

          /* There is no outstanding, unacknowledged data after this
           * initial sequence number.
           */

          conn->unacked         = 0;

          /* Update the initial time for calculating timeouts */

#if defined(CONFIG_NET_SOCKOPTS) && !defined(CONFIG_DISABLE_CLOCK)
          state.snd_time        = clock_systimer();
#endif
          /* Set up the callback in the connection */

          state.snd_cb->flags   = UIP_ACKDATA|UIP_REXMIT|UIP_POLL|UIP_CLOSE|UIP_ABORT|UIP_TIMEDOUT;
          state.snd_cb->priv    = (void*)&state;
          state.snd_cb->event   = send_interrupt;

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

          netdev_txnotify(&conn->ripaddr);

          /* Wait for the send to complete or an error to occur:  NOTES: (1)
           * uip_lockedwait will also terminate if a signal is received, (2) interrupts
           * may be disabled!  They will be re-enabled while the task sleeps and
           * automatically re-enabled when the task restarts.
           */

          ret = uip_lockedwait(&state. snd_sem);

          /* Make sure that no further interrupts are processed */

          uip_tcpcallbackfree(conn, state.snd_cb);
        }
    }

  sem_destroy(&state. snd_sem);
  uip_unlock(save);

  /* Set the socket state to idle */

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

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

  if (state.snd_sent < 0)
    {
      err = state.snd_sent;
      goto errout;
    }

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

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

  /* Return the number of bytes actually sent */

  return state.snd_sent;

errout:
  *get_errno_ptr() = err;
  return ERROR;
}
Example #19
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;
}
Example #20
0
int netdev_ioctl(int sockfd, int cmd, unsigned long arg)
{
  FAR struct socket *psock = sockfd_socket(sockfd);

  return psock_ioctl(psock, cmd, arg);
}
Example #21
0
ssize_t net_sendfile(int outfd, struct file *infile, off_t *offset,
                     size_t count)
{
  FAR struct socket *psock = sockfd_socket(outfd);
  FAR struct tcp_conn_s *conn;
  struct sendfile_s state;
  net_lock_t save;
  int err;

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

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

  /* If this is an un-connected socket, then return ENOTCONN */

  if (psock->s_type != SOCK_STREAM || !_SS_ISCONNECTED(psock->s_flags))
    {
      ndbg("ERROR: Not connected\n");
      err = 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)
    {
      ndbg("ERROR: Not reachable\n");
      err = ENETUNREACH;
      goto errout;
    }
#endif /* CONFIG_NET_ARP_SEND || CONFIG_NET_ICMPv6_NEIGHBOR */

  /* Set the socket state to sending */

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

  /* Initialize the state structure.  This is done with interrupts
   * disabled because we don't want anything to happen until we
   * are ready.
   */

  save  = net_lock();

  memset(&state, 0, sizeof(struct sendfile_s));
  sem_init(&state. snd_sem, 0, 0);          /* Doesn't really fail */
  state.snd_sock    = psock;                /* Socket descriptor to use */
  state.snd_foffset = offset ? *offset : 0; /* Input file offset */
  state.snd_flen    = count;                /* Number of bytes to send */
  state.snd_file    = infile;               /* File to read from */

  /* Allocate resources to receive a callback */

  state.snd_datacb = tcp_callback_alloc(conn);

  if (state.snd_datacb == NULL)
    {
      nlldbg("Failed to allocate data callback\n");
      err = ENOMEM;
      goto errout_locked;
    }

  state.snd_ackcb = tcp_callback_alloc(conn);

  if (state.snd_ackcb == NULL)
    {
      nlldbg("Failed to allocate ack callback\n");
      err = ENOMEM;
      goto errout_datacb;
    }

  /* Get the initial sequence number that will be used */

  state.snd_isn          = tcp_getsequence(conn->sndseq);

  /* There is no outstanding, unacknowledged data after this
   * initial sequence number.
   */

  conn->unacked          = 0;

#ifdef CONFIG_NET_SOCKOPTS
  /* Set the initial time for calculating timeouts */

  state.snd_time         = clock_systimer();
#endif

  /* Set up the ACK callback in the connection */

  state.snd_ackcb->flags = (TCP_ACKDATA | TCP_REXMIT | TCP_DISCONN_EVENTS);
  state.snd_ackcb->priv  = (FAR void *)&state;
  state.snd_ackcb->event = ack_interrupt;

  /* Perform the TCP send operation */

  do
    {
      state.snd_datacb->flags = TCP_POLL;
      state.snd_datacb->priv  = (FAR void *)&state;
      state.snd_datacb->event = sendfile_interrupt;

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

      sendfile_txnotify(psock, conn);
      net_lockedwait(&state.snd_sem);
    }
  while (state.snd_sent >= 0 && state.snd_acked < state.snd_flen);

  /* Set the socket state to idle */

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

  tcp_callback_free(conn, state.snd_ackcb);

errout_datacb:
  tcp_callback_free(conn, state.snd_datacb);

errout_locked:

  sem_destroy(&state. snd_sem);
  net_unlock(save);

errout:

  if (err)
    {
      set_errno(err);
      return ERROR;
    }
  else if (state.snd_sent < 0)
    {
      set_errno(-state.snd_sent);
      return ERROR;
    }
  else
    {
      return state.snd_sent;
    }
}
Example #22
0
ssize_t send(int sockfd, const void *buf, size_t len, int flags)
{
  return psock_send(sockfd_socket(sockfd), buf, len, flags);
}
Example #23
0
int net_vfcntl(int sockfd, int cmd, va_list ap)
{
  FAR struct socket *psock = sockfd_socket(sockfd);
  net_lock_t flags;
  int err = 0;
  int ret = 0;

  nvdbg("sockfd=%d cmd=%d\n", sockfd, cmd);

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

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

  /* Interrupts must be disabled in order to perform operations on socket structures */

  flags = net_lock();
  switch (cmd)
    {
      case F_DUPFD:
        /* Return a new file descriptor which shall be the lowest numbered
         * available (that is, not already open) file descriptor greater than
         * or equal to the third argument, arg, taken as an integer of type
         * int. The new file descriptor shall refer to the same open file
         * description as the original file descriptor, and shall share any
         * locks.  The FD_CLOEXEC flag associated  with the new file descriptor
         * shall be cleared to keep the file open across calls to one of the
         * exec functions.
         */

        {
          ret = net_dupsd(sockfd, va_arg(ap, int));
        }
        break;

      case F_GETFD:
        /* Get the file descriptor flags defined in <fcntl.h> that are associated
         * with the file descriptor fd.  File descriptor flags are associated
         * with a single file descriptor and do not affect other file descriptors
         * that refer to the same file.
         */

      case F_SETFD:
        /* Set the file descriptor flags defined in <fcntl.h>, that are associated
         * with fd, to the third argument, arg, taken as type int. If the
         * FD_CLOEXEC flag in the third argument is 0, the file shall remain open
         * across the exec functions; otherwise, the file shall be closed upon
         * successful execution of one  of  the  exec  functions.
         */

         err = ENOSYS; /* F_GETFD and F_SETFD not implemented */
         break;

      case F_GETFL:
        /* Get the file status flags and file access modes, defined in
         * <fcntl.h>, for the file description associated with fd. The file
         * access modes can be extracted from the return value using the
         * mask O_ACCMODE, which is defined  in <fcntl.h>. File status flags
         * and file access modes are associated with the file description
         * and do not affect other file descriptors that refer to the same
         * file with different open file descriptions.
         */

        {
          /* This summarizes the behavior of all NuttX sockets */

          ret = O_RDWR | O_SYNC | O_RSYNC;

#if defined(CONFIG_NET_LOCAL) || defined(CONFIG_NET_TCP_READAHEAD) || \
    defined(CONFIG_NET_UDP_READAHEAD)
          /* Unix domain sockets may be non-blocking.  TCP/IP and UDP/IP
           * sockets may also be non-blocking if read-ahead is enabled
           */

          if ((0
#ifdef CONFIG_NET_LOCAL
              || psock->s_domain == PF_LOCAL  /* Unix domain stream or datagram */
#endif
#ifdef CONFIG_NET_TCP_READAHEAD
              || psock->s_type == SOCK_STREAM /* IP or Unix domain stream */
#endif
#ifdef CONFIG_NET_UDP_READAHEAD
              || psock->s_type == SOCK_DGRAM  /* IP or Unix domain datagram */
#endif
              ) && _SS_ISNONBLOCK(psock->s_flags))
            {
              ret |= O_NONBLOCK;
            }
#endif /* CONFIG_NET_LOCAL || CONFIG_NET_TCP_READAHEAD || CONFIG_NET_UDP_READAHEAD */
        }
        break;

      case F_SETFL:
        /* Set the file status flags, defined in <fcntl.h>, for the file description
         * associated with fd from the corresponding  bits in the third argument,
         * arg, taken as type int. Bits corresponding to the file access mode and
         * the file creation flags, as defined in <fcntl.h>, that are set in arg shall
         * be ignored. If any bits in arg other than those mentioned here are changed
         * by the application, the result is unspecified.
         */

        {
#if defined(CONFIG_NET_LOCAL) || defined(CONFIG_NET_TCP_READAHEAD) || \
    defined(CONFIG_NET_UDP_READAHEAD)
           /* Non-blocking is the only configurable option.  And it applies
            * only Unix domain sockets and to read operations on TCP/IP
            * and UDP/IP sockets when read-ahead is enabled.
            */

          int mode =  va_arg(ap, int);
#if defined(CONFIG_NET_LOCAL_STREAM) || defined(CONFIG_NET_TCP_READAHEAD)
          if (psock->s_type == SOCK_STREAM) /* IP or Unix domain stream */
            {
               if ((mode & O_NONBLOCK) != 0)
                 {
                   psock->s_flags |= _SF_NONBLOCK;
                 }
               else
                 {
                   psock->s_flags &= ~_SF_NONBLOCK;
                 }
            }
          else
#endif
#if defined(CONFIG_NET_LOCAL_DGRAM) || defined(CONFIG_NET_UDP_READAHEAD)
          if (psock->s_type == SOCK_DGRAM)  /* IP or Unix domain datagram */
            {
               if ((mode & O_NONBLOCK) != 0)
                 {
                   psock->s_flags |= _SF_NONBLOCK;
                 }
               else
                 {
                   psock->s_flags &= ~_SF_NONBLOCK;
                 }
            }
          else
#endif
#endif /* CONFIG_NET_LOCAL || CONFIG_NET_TCP_READAHEAD || CONFIG_NET_UDP_READAHEAD */
            {
              ndbg("ERROR: Non-blocking not supported for this socket\n");
            }
        }
        break;

      case F_GETOWN:
        /* If fd refers to a socket, get the process or process group ID specified
         * to receive SIGURG signals when out-of-band data is available. Positive values
         * indicate a process ID; negative values, other than -1, indicate a process group
         * ID. If fd does not refer to a socket, the results are unspecified.
         */

      case F_SETOWN:
        /* If fd refers to a socket, set the process or process group ID specified
         * to receive SIGURG signals when out-of-band data is available, using the value
         * of the third argument, arg, taken as type int. Positive values indicate a
         * process ID; negative values, other than -1, indicate a process group ID. If
         * fd does not refer to a socket, the results are unspecified.
         */

      case F_GETLK:
        /* Get the first lock which blocks the lock description pointed to by the third
         * argument, arg, taken as a pointer to type struct flock, defined in <fcntl.h>.
         * The information retrieved shall overwrite the information passed to fcntl() in
         * the structure flock. If no lock is found that would prevent this lock from being
         * created, then the structure shall be left unchanged except for the lock type
         * which shall be set to F_UNLCK.
         */

      case F_SETLK:
        /* Set or clear a file segment lock according to the lock description pointed to
         * by the third argument, arg, taken as a pointer to type struct flock, defined in
         * <fcntl.h>. F_SETLK can establish shared (or read) locks (F_RDLCK) or exclusive
         * (or write) locks (F_WRLCK), as well  as  to  remove  either  type  of  lock  (F_UNLCK).
         * F_RDLCK, F_WRLCK, and F_UNLCK are defined in <fcntl.h>. If a shared or exclusive
         * lock cannot be set, fcntl() shall return immediately with a return value of -1.
         */

      case F_SETLKW:
        /* This command shall be equivalent to F_SETLK except that if a shared or exclusive
         * lock is blocked by other locks, the thread shall wait until the request can be
         * satisfied. If a signal that is to be caught is received while fcntl() is waiting
         * for a region, fcntl() shall be interrupted. Upon return from the signal handler,
         * fcntl() shall return -1 with errno set to [EINTR], and the lock operation shall
         * not be done.
         */

         err = ENOSYS; /* F_GETOWN, F_SETOWN, F_GETLK, F_SETLK, F_SETLKW */
         break;

      default:
         err = EINVAL;
         break;
  }

  net_unlock(flags);

errout:
  if (err != 0)
    {
      set_errno(err);
      return ERROR;
    }

  return ret;
}
Example #24
0
int net_close(int sockfd)
{
  return psock_close(sockfd_socket(sockfd));
}
Example #25
0
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
{
  FAR struct socket *psock = sockfd_socket(sockfd);

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

  int err;

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

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

  /* Verify that a valid address has been provided */

#ifdef CONFIG_NET_IPv6
  if (addr->sa_family != AF_INET6 || addrlen < sizeof(struct sockaddr_in6))
#else
  if (addr->sa_family != AF_INET || addrlen < sizeof(struct sockaddr_in))
#endif
  {
      err = EBADF;
      goto errout;
  }

  /* Perform the connection depending on the protocol type */

  switch (psock->s_type)
    {
#ifdef CONFIG_NET_TCP
      case SOCK_STREAM:
        {
          /* Verify that the socket is not already connected */

          if (_SS_ISCONNECTED(psock->s_flags))
            {
              err = EISCONN;
              goto errout;
            }

          /* Its not ... connect it */

          ret = tcp_connect(psock, inaddr);
          if (ret < 0)
            {
              err = -ret;
              goto errout;
            }
        }
        break;
#endif

#ifdef CONFIG_NET_UDP
      case SOCK_DGRAM:
        {
          ret = uip_udpconnect(psock->s_conn, inaddr);
          if (ret < 0)
            {
              err = -ret;
              goto errout;
            }
        }
        break;
#endif

      default:
        err = EBADF;
        goto errout;
    }

  return OK;

errout:
   errno = err;
  return ERROR;
}
Example #26
0
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
{
  FAR struct socket *psock = sockfd_socket(sockfd);

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

  int err;
  int ret;

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

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

  /* Verify that a valid address has been provided */

#ifdef CONFIG_NET_IPv6
  if (addr->sa_family != AF_INET6 || addrlen < sizeof(struct sockaddr_in6))
#else
  if (addr->sa_family != AF_INET || addrlen < sizeof(struct sockaddr_in))
#endif
  {
      err = EBADF;
      goto errout;
  }

  /* Perform the binding depending on the protocol type */

  switch (psock->s_type)
    {
#ifdef CONFIG_NET_TCP
      case SOCK_STREAM:
        ret = uip_tcpbind(psock->s_conn, inaddr);
        psock->s_flags |= _SF_BOUND;
        break;
#endif

#ifdef CONFIG_NET_UDP
      case SOCK_DGRAM:
        ret = uip_udpbind(psock->s_conn, inaddr);
        break;
#endif

      default:
        err = EBADF;
        goto errout;
    }

  /* Was the bind successful */

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

  return OK;

errout:
  *get_errno_ptr() = err;
  return ERROR;
}