Exemple #1
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;
}
Exemple #2
0
int tcp_bind(FAR struct tcp_conn_s *conn,
             FAR const struct sockaddr_in *addr)
#endif
{
  net_lock_t flags;
  int port;

  /* Verify or select a local port */

  flags = net_lock();
  port = tcp_selectport(ntohs(addr->sin_port));
  net_unlock(flags);

  if (port < 0)
    {
      return port;
    }

  /* Save the local address in the connection structure.  Note that the requested
   * local IP address is saved but not used.  At present, only a single network
   * interface is supported, the IP address is not of importance.
   */

  conn->lport = addr->sin_port;

#if 0 /* Not used */
#ifdef CONFIG_NET_IPv6
  net_ipaddr_copy(conn->lipaddr, addr->sin6_addr.in6_u.u6_addr16);
#else
  net_ipaddr_copy(conn->lipaddr, addr->sin_addr.s_addr);
#endif
#endif

  return OK;
}
Exemple #3
0
int tcp_connect(FAR struct tcp_conn_s *conn,
                FAR const struct sockaddr_in *addr)
#endif
{
  net_lock_t flags;
  int port;

  /* The connection is expected to be in the TCP_ALLOCATED state.. i.e.,
   * allocated via up_tcpalloc(), but not yet put into the active connections
   * list.
   */

  if (!conn || conn->tcpstateflags != TCP_ALLOCATED)
    {
      return -EISCONN;
    }

  /* If the TCP port has not already been bound to a local port, then select
   * one now.
   */

  flags = net_lock();
  port = tcp_selectport(ntohs(conn->lport));
  net_unlock(flags);

  if (port < 0)
    {
      return port;
    }

  /* Initialize and return the connection structure, bind it to the port number */

  conn->tcpstateflags = TCP_SYN_SENT;
  tcp_initsequence(conn->sndseq);

  conn->mss        = TCP_INITIAL_MSS;
  conn->unacked    = 1;    /* TCP length of the SYN is one. */
  conn->nrtx       = 0;
  conn->timer      = 1;    /* Send the SYN next time around. */
  conn->rto        = TCP_RTO;
  conn->sa         = 0;
  conn->sv         = 16;   /* Initial value of the RTT variance. */
  conn->lport      = htons((uint16_t)port);
#ifdef CONFIG_NET_TCP_WRITE_BUFFERS
  conn->expired    = 0;
  conn->isn        = 0;
  conn->sent       = 0;
#endif

  /* The sockaddr port is 16 bits and already in network order */

  conn->rport = addr->sin_port;

  /* The sockaddr address is 32-bits in network order. */

  net_ipaddr_copy(conn->ripaddr, addr->sin_addr.s_addr);

#ifdef CONFIG_NET_TCP_READAHEAD
  /* Initialize the list of TCP read-ahead buffers */

  IOB_QINIT(&conn->readahead);
#endif

#ifdef CONFIG_NET_TCP_WRITE_BUFFERS
  /* Initialize the TCP write buffer lists */

  sq_init(&conn->write_q);
  sq_init(&conn->unacked_q);
#endif

  /* And, finally, put the connection structure into the active
   * list. Because g_active_tcp_connections is accessed from user level and
   * interrupt level, code, it is necessary to keep interrupts disabled during
   * this operation.
   */

  flags = net_lock();
  dq_addlast(&conn->node, &g_active_tcp_connections);
  net_unlock(flags);

  return OK;
}
Exemple #4
0
static inline int tcp_ipv6_bind(FAR struct tcp_conn_s *conn,
                                FAR const struct sockaddr_in6 *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
  /* The port number must be unique for this address binding */

  port = tcp_selectport(PF_INET6,
                        (FAR const union ip_addr_u *)addr->sin6_addr.in6_u.u6_addr16,
                        ntohs(addr->sin6_port));
#else
  /* There is only one network device; the port number can be globally
   * unique.
   */

  port = tcp_selectport(ntohs(addr->sin6_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_ipv6addr_copy(conn->u.ipv6.laddr, addr->sin6_addr.in6_u.u6_addr16);
#endif

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

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

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

      /* Back out the local address setting */

      conn->lport = 0;
#ifdef CONFIG_NETDEV_MULTINIC
      net_ipv6addr_copy(conn->u.ipv6.laddr, g_ipv6_allzeroaddr);
#endif
      return ret;
    }

  net_unlock();
  return OK;
}
Exemple #5
0
int tcp_connect(FAR struct tcp_conn_s *conn, FAR const struct sockaddr *addr)
{
  int port;
  int ret;

  /* The connection is expected to be in the TCP_ALLOCATED state.. i.e.,
   * allocated via up_tcpalloc(), but not yet put into the active connections
   * list.
   */

  if (!conn || conn->tcpstateflags != TCP_ALLOCATED)
    {
      return -EISCONN;
    }

  /* If the TCP port has not already been bound to a local port, then select
   * one now.  We assume that the IP address has been bound to a local device,
   * but the port may still be INPORT_ANY.
   */

  net_lock();

#ifdef CONFIG_NETDEV_MULTINIC
  /* If there are multiple network devices, then we need to pass the local,
   * bound address.  This is needed because port unique-ness is only for a
   * given network.
   *
   * This is complicated by the fact that the local address may be either an
   * IPv4 or an IPv6 address.
   */

#ifdef CONFIG_NET_IPv4
#ifdef CONFIG_NET_IPv6
  if (conn->domain == PF_INET)
#endif
    {
      /* Select a port that is unique for this IPv4 local address (host
       * order).
       */

      port = tcp_selectport(PF_INET,
                            (FAR const union ip_addr_u *)&conn->u.ipv4.laddr,
                            ntohs(conn->lport));
    }
#endif /* CONFIG_NET_IPv4 */

#ifdef CONFIG_NET_IPv6
#ifdef CONFIG_NET_IPv4
  else
#endif
    {
      /* Select a port that is unique for this IPv6 local address (host
       * order).
       */

      port = tcp_selectport(PF_INET6,
                            (FAR const union ip_addr_u *)conn->u.ipv6.laddr,
                            ntohs(conn->lport));
    }
#endif /* CONFIG_NET_IPv6 */

#else /* CONFIG_NETDEV_MULTINIC */
  /* Select the next available port number.  This is only one network device
   * so we do not have to bother with all of the IPv4/IPv6 local address
   * silliness.
   */

  port = tcp_selectport(ntohs(conn->lport));

#endif /* CONFIG_NETDEV_MULTINIC */

  /* Did we have a port assignment? */

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

  /* Set up the local address (laddr) and the remote address (raddr) that
   * describes the TCP connection.
   */

#ifdef CONFIG_NET_IPv4
#ifdef CONFIG_NET_IPv6
  if (conn->domain == PF_INET)
#endif
    {
      FAR const struct sockaddr_in *inaddr =
        (FAR const struct sockaddr_in *)addr;

      /* Save MSS and the port from the sockaddr (already in network order) */

      conn->mss    = MIN_IPv4_TCP_INITIAL_MSS;
      conn->rport  = inaddr->sin_port;

      /* The sockaddr address is 32-bits in network order. */

      net_ipv4addr_copy(conn->u.ipv4.raddr, inaddr->sin_addr.s_addr);

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

      ret = tcp_remote_ipv4_device(conn);
    }
#endif /* CONFIG_NET_IPv4 */

#ifdef CONFIG_NET_IPv6
#ifdef CONFIG_NET_IPv4
  else
#endif
    {
      FAR const struct sockaddr_in6 *inaddr =
        (FAR const struct sockaddr_in6 *)addr;

      /* Save MSS and the port from the sockaddr (already in network order) */

      conn->mss     = MIN_IPv6_TCP_INITIAL_MSS;
      conn->rport   = inaddr->sin6_port;

      /* The sockaddr address is 128-bits in network order. */

      net_ipv6addr_copy(conn->u.ipv6.raddr, inaddr->sin6_addr.s6_addr16);

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

      ret = tcp_remote_ipv6_device(conn);
    }
#endif /* CONFIG_NET_IPv6 */

  /* Verify that a network device that can provide packets to this local
   * address was found.
   */

  if (ret < 0)
    {
      /* If no device is found, then the address is not reachable.  That
       * should be impossible in this context and we should probably really
       * just assert here.
       */

      nerr("ERROR: Failed to find network device: %d\n", ret);
      goto errout_with_lock;
    }

  /* Initialize and return the connection structure, bind it to the port
   * number.  At this point, we do not know the size of the initial MSS We
   * know the total size of the packet buffer, but we don't yet know the
   * size of link layer header.
   */

  conn->tcpstateflags = TCP_SYN_SENT;
  tcp_initsequence(conn->sndseq);

  conn->unacked    = 1;    /* TCP length of the SYN is one. */
  conn->nrtx       = 0;
  conn->timer      = 1;    /* Send the SYN next time around. */
  conn->rto        = TCP_RTO;
  conn->sa         = 0;
  conn->sv         = 16;   /* Initial value of the RTT variance. */
  conn->lport      = htons((uint16_t)port);
#ifdef CONFIG_NET_TCP_WRITE_BUFFERS
  conn->expired    = 0;
  conn->isn        = 0;
  conn->sent       = 0;
  conn->sndseq_max = 0;
#endif

#ifdef CONFIG_NET_TCP_READAHEAD
  /* Initialize the list of TCP read-ahead buffers */

  IOB_QINIT(&conn->readahead);
#endif

#ifdef CONFIG_NET_TCP_WRITE_BUFFERS
  /* Initialize the TCP write buffer lists */

  sq_init(&conn->write_q);
  sq_init(&conn->unacked_q);
#endif

  /* And, finally, put the connection structure into the active list. */

  dq_addlast(&conn->node, &g_active_tcp_connections);
  ret = OK;

errout_with_lock:
  net_unlock();
  return ret;
}