forked from nuttx/nuttx-update
Networking: Straighten up use if IPv6/IPv4 in TCP connection logic
This commit is contained in:
parent
b187b4f381
commit
86f617cc88
4 changed files with 476 additions and 151 deletions
|
@ -74,11 +74,11 @@
|
|||
#define IFF_CLR_IPv6(f) do { (f) &= ~IFF_IPv6; } while (0)
|
||||
#define IFF_CLR_NOARP(f) do { (f) &= ~IFF_NOARP; } while (0)
|
||||
|
||||
#define IFF_IS_DOWN(f) ((f) & IFF_DOWN) != 0)
|
||||
#define IFF_IS_UP(f) ((f) & IFF_UP) != 0)
|
||||
#define IFF_IS_RUNNING(f) ((f) & IFF_RUNNING) != 0)
|
||||
#define IFF_IS_IPv6(f) ((f) & IFF_IPv6) != 0)
|
||||
#define IFF_IS_NOARP(f) ((f) & IFF_NOARP) != 0)
|
||||
#define IFF_IS_DOWN(f) (((f) & IFF_DOWN) != 0)
|
||||
#define IFF_IS_UP(f) (((f) & IFF_UP) != 0)
|
||||
#define IFF_IS_RUNNING(f) (((f) & IFF_RUNNING) != 0)
|
||||
#define IFF_IS_IPv6(f) (((f) & IFF_IPv6) != 0)
|
||||
#define IFF_IS_NOARP(f) (((f) & IFF_NOARP) != 0)
|
||||
|
||||
#define IFF_SET_IPv4(f) IFF_CLR_IPv6(f)
|
||||
#define IFF_CLR_IPv4(f) IFF_SET_IPv6(f)
|
||||
|
|
|
@ -146,14 +146,6 @@ int psock_bind(FAR struct socket *psock, const struct sockaddr *addr,
|
|||
#ifdef CONFIG_NET_PKT
|
||||
FAR const struct sockaddr_ll *lladdr = (const struct sockaddr_ll *)addr;
|
||||
#endif
|
||||
#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 = OK;
|
||||
|
||||
|
@ -204,7 +196,7 @@ int psock_bind(FAR struct socket *psock, const struct sockaddr *addr,
|
|||
|
||||
#ifdef CONFIG_NET_TCP
|
||||
case SOCK_STREAM:
|
||||
ret = tcp_bind(psock->s_conn, inaddr);
|
||||
ret = tcp_bind(psock->s_conn, addr);
|
||||
psock->s_flags |= _SF_BOUND;
|
||||
break;
|
||||
#endif
|
||||
|
|
|
@ -269,7 +269,7 @@ extern "C"
|
|||
|
||||
/* Defined in tcp_conn.c ****************************************************/
|
||||
|
||||
struct sockaddr; /* Forward reference */
|
||||
struct sockaddr; /* Forward reference */
|
||||
struct tcp_iphdr_s; /* Forward reference */
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -366,13 +366,7 @@ FAR struct tcp_conn_s *tcp_alloc_accept(FAR struct net_driver_s *dev,
|
|||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_NET_IPv6
|
||||
int tcp_bind(FAR struct tcp_conn_s *conn,
|
||||
FAR const struct sockaddr_in6 *addr);
|
||||
#else
|
||||
int tcp_bind(FAR struct tcp_conn_s *conn,
|
||||
FAR const struct sockaddr_in *addr);
|
||||
#endif
|
||||
int tcp_bind(FAR struct tcp_conn_s *conn, FAR const struct sockaddr *addr);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: tcp_connect
|
||||
|
|
|
@ -64,8 +64,8 @@
|
|||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#define IPv4 ((struct net_iphdr_s *)&dev->d_buf[NET_LL_HDRLEN(dev)])
|
||||
#define IPv6 ((struct net_ipv6hdr_s *)&dev->d_buf[NET_LL_HDRLEN(dev)])
|
||||
#define IPv4BUF ((struct net_iphdr_s *)&dev->d_buf[NET_LL_HDRLEN(dev)])
|
||||
#define IPv6BUF ((struct net_ipv6hdr_s *)&dev->d_buf[NET_LL_HDRLEN(dev)])
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
|
@ -92,7 +92,7 @@ static uint16_t g_last_tcp_port;
|
|||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: tcp_listener
|
||||
* Name: tcp_ipv4_listener
|
||||
*
|
||||
* Description:
|
||||
* Given a local port number (in network byte order), find the TCP
|
||||
|
@ -103,11 +103,9 @@ static uint16_t g_last_tcp_port;
|
|||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_NETDEV_MULTINIC
|
||||
static FAR struct tcp_conn_s *tcp_listener(in_addr_t ipaddr, uint16_t portno)
|
||||
#else
|
||||
static FAR struct tcp_conn_s *tcp_listener(uint16_t portno)
|
||||
#endif
|
||||
#if defined(CONFIG_NET_IPv4) && defined(CONFIG_NETDEV_MULTINIC)
|
||||
static inline FAR struct tcp_conn_s *tcp_ipv4_listener(inaddr_t ipaddr,
|
||||
uint16_t portno)
|
||||
{
|
||||
FAR struct tcp_conn_s *conn;
|
||||
int i;
|
||||
|
@ -124,7 +122,6 @@ static FAR struct tcp_conn_s *tcp_listener(uint16_t portno)
|
|||
|
||||
if (conn->tcpstateflags != TCP_CLOSED && conn->lport == portno)
|
||||
{
|
||||
#ifdef CONFIG_NETDEV_MULTINIC
|
||||
/* If there are multiple interface devices, then the local IP
|
||||
* address of the connection must also match. INADDR_ANY is a
|
||||
* special case: There can only be instance of a port number
|
||||
|
@ -132,12 +129,7 @@ static FAR struct tcp_conn_s *tcp_listener(uint16_t portno)
|
|||
*/
|
||||
|
||||
if (net_ipv4addr_cmp(conn->u.ipv4.laddr, ipaddr) ||
|
||||
#ifdef CONFIG_NET_IPv6
|
||||
net_ipv4addr_cmp(conn->u.ipv4.laddr, g_ipv4_allzeroaddr))
|
||||
#else
|
||||
net_ipv4addr_cmp(conn->u.ipv4.laddr, INADDR_ANY))
|
||||
#endif
|
||||
#endif
|
||||
{
|
||||
/* The port number is in use, return the connection */
|
||||
|
||||
|
@ -148,6 +140,123 @@ static FAR struct tcp_conn_s *tcp_listener(uint16_t portno)
|
|||
|
||||
return NULL;
|
||||
}
|
||||
#endif /* CONFIG_NET_IPv4 && CONFIG_NETDEV_MULTINIC */
|
||||
|
||||
/****************************************************************************
|
||||
* Name: tcp_ipv6_listener
|
||||
*
|
||||
* Description:
|
||||
* Given a local port number (in network byte order), find the TCP
|
||||
* connection that listens on this this port.
|
||||
*
|
||||
* Primary uses: (1) to determine if a port number is available, (2) to
|
||||
* To identify the socket that will accept new connections on a local port.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#if defined(CONFIG_NET_IPv6) && defined(CONFIG_NETDEV_MULTINIC)
|
||||
static inline FAR struct tcp_conn_s *tcp_ipv6_ listener(net_ipv6addr_t ipaddr,
|
||||
uint16_t portno)
|
||||
{
|
||||
FAR struct tcp_conn_s *conn;
|
||||
int i;
|
||||
|
||||
/* Check if this port number is in use by any active UIP TCP connection */
|
||||
|
||||
for (i = 0; i < CONFIG_NET_TCP_CONNS; i++)
|
||||
{
|
||||
conn = &g_tcp_connections[i];
|
||||
|
||||
/* Check if this connection is open and the local port assignment
|
||||
* matches the requested port number.
|
||||
*/
|
||||
|
||||
if (conn->tcpstateflags != TCP_CLOSED && conn->lport == portno)
|
||||
{
|
||||
/* If there are multiple interface devices, then the local IP
|
||||
* address of the connection must also match. INADDR_ANY is a
|
||||
* special case: There can only be instance of a port number
|
||||
* with INADDR_ANY.
|
||||
*/
|
||||
|
||||
if (net_ipv6addr_cmp(conn->u.ipv6.laddr, ipaddr) ||
|
||||
net_ipv6addr_cmp(conn->u.ipv6.laddr, g_ipv6_allzeroaddr))
|
||||
{
|
||||
/* The port number is in use, return the connection */
|
||||
|
||||
return conn;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
#endif /* CONFIG_NET_IPv6 && CONFIG_NETDEV_MULTINIC */
|
||||
|
||||
/****************************************************************************
|
||||
* Name: tcp_listener
|
||||
*
|
||||
* Description:
|
||||
* Given a local port number (in network byte order), find the TCP
|
||||
* connection that listens on this this port.
|
||||
*
|
||||
* Primary uses: (1) to determine if a port number is available, (2) to
|
||||
* To identify the socket that will accept new connections on a local port.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_NETDEV_MULTINIC
|
||||
static FAR struct tcp_conn_s *
|
||||
tcp_listener(uint8_t domain, FAR const union ip_binding_u *ipaddr,
|
||||
uint16_t portno)
|
||||
{
|
||||
#ifdef CONFIG_NET_IPv4
|
||||
#ifdef CONFIG_NET_IPv6
|
||||
if (domain == PF_INET)
|
||||
#endif
|
||||
{
|
||||
return tcp_ipv4_listener(ipaddr->ipv4, portno);
|
||||
}
|
||||
#endif /* CONFIG_NET_IPv4 */
|
||||
|
||||
#ifdef CONFIG_NET_IPv6
|
||||
#ifdef CONFIG_NET_IPv4
|
||||
else
|
||||
#endif
|
||||
{
|
||||
return tcp_ipv6_listener(ipaddr->ipv6, portno);
|
||||
}
|
||||
#endif /* CONFIG_NET_IPv6 */
|
||||
}
|
||||
|
||||
#else /* CONFIG_NETDEV_MULTINIC */
|
||||
|
||||
static FAR struct tcp_conn_s *tcp_listener(uint16_t portno)
|
||||
{
|
||||
FAR struct tcp_conn_s *conn;
|
||||
int i;
|
||||
|
||||
/* Check if this port number is in use by any active UIP TCP connection */
|
||||
|
||||
for (i = 0; i < CONFIG_NET_TCP_CONNS; i++)
|
||||
{
|
||||
conn = &g_tcp_connections[i];
|
||||
|
||||
/* Check if this connection is open and the local port assignment
|
||||
* matches the requested port number.
|
||||
*/
|
||||
|
||||
if (conn->tcpstateflags != TCP_CLOSED && conn->lport == portno)
|
||||
{
|
||||
/* The port number is in use, return the connection */
|
||||
|
||||
return conn;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
#endif /* CONFIG_NETDEV_MULTINIC */
|
||||
|
||||
/****************************************************************************
|
||||
* Name: tcp_selectport
|
||||
|
@ -175,7 +284,8 @@ static FAR struct tcp_conn_s *tcp_listener(uint16_t portno)
|
|||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_NETDEV_MULTINIC
|
||||
static int tcp_selectport(in_addr_t ipaddr, uint16_t portno)
|
||||
static int tcp_selectport(uint8_t domain, FAR const union ip_addr_u *ipaddr,
|
||||
uint16_t portno)
|
||||
#else
|
||||
static int tcp_selectport(uint16_t portno)
|
||||
#endif
|
||||
|
@ -203,7 +313,7 @@ static int tcp_selectport(uint16_t portno)
|
|||
}
|
||||
}
|
||||
#ifdef CONFIG_NETDEV_MULTINIC
|
||||
while (tcp_listener(ipaddr, htons(g_last_tcp_port)));
|
||||
while (tcp_listener(domain, ipaddr, htons(g_last_tcp_port)));
|
||||
#else
|
||||
while (tcp_listener(htons(g_last_tcp_port)));
|
||||
#endif
|
||||
|
@ -215,7 +325,7 @@ static int tcp_selectport(uint16_t portno)
|
|||
*/
|
||||
|
||||
#ifdef CONFIG_NETDEV_MULTINIC
|
||||
if (tcp_listener(ipaddr, portno))
|
||||
if (tcp_listener(domain, ipaddr, portno))
|
||||
#else
|
||||
if (tcp_listener(portno))
|
||||
#endif
|
||||
|
@ -231,6 +341,266 @@ static int tcp_selectport(uint16_t portno)
|
|||
return portno;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: tcp_ipv4_active
|
||||
*
|
||||
* Description:
|
||||
* Find a connection structure that is the appropriate
|
||||
* connection to be used with the provided TCP/IP header
|
||||
*
|
||||
* Assumptions:
|
||||
* This function is called from UIP logic at interrupt level
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_NET_IPv4
|
||||
static inline FAR struct tcp_conn_s *
|
||||
tcp_ipv4_active(FAR struct net_driver_s *dev, FAR struct tcp_hdr_s *tcp)
|
||||
{
|
||||
FAR struct net_iphdr_s *ip = IPv4BUF;
|
||||
FAR struct tcp_conn_s *conn;
|
||||
in_addr_t srcipaddr;
|
||||
#ifdef CONFIG_NETDEV_MULTINIC
|
||||
in_addr_t destipaddr;
|
||||
#endif
|
||||
|
||||
conn = (FAR struct tcp_conn_s *)g_active_tcp_connections.head;
|
||||
srcipaddr = net_ip4addr_conv32(ip->srcipaddr);
|
||||
#ifdef CONFIG_NETDEV_MULTINIC
|
||||
destipaddr = net_ip4addr_conv32(ip->destipaddr);
|
||||
#endif
|
||||
|
||||
while (conn)
|
||||
{
|
||||
/* Find an open connection matching the TCP input. The following
|
||||
* checks are performed:
|
||||
*
|
||||
* - The local port number is checked against the destination port
|
||||
* number in the received packet.
|
||||
* - The remote port number is checked if the connection is bound
|
||||
* to a remote port.
|
||||
* - If multiple network interfaces are supported, then the local
|
||||
* IP address is available and we will insist that the
|
||||
* destination IP matches the bound address. If a socket is
|
||||
* bound to INADDRY_ANY, then it should receive all packets
|
||||
* directed to the port.
|
||||
* - Finally, if the connection is bound to a remote IP address,
|
||||
* the source IP address of the packet is checked.
|
||||
*
|
||||
* If all of the above are true then the newly received TCP packet
|
||||
* is destined for this TCP connection.
|
||||
*/
|
||||
|
||||
if (conn->tcpstateflags != TCP_CLOSED &&
|
||||
tcp->destport == conn->lport &&
|
||||
tcp->srcport == conn->rport &&
|
||||
#ifdef CONFIG_NETDEV_MULTINIC
|
||||
(net_ipv4addr_cmp(conn->u.ipv4.laddr, g_ipv4_allzeroaddr) ||
|
||||
net_ipv4addr_cmp(destipaddr, conn->u.ipv4.laddr)) &&
|
||||
#endif
|
||||
net_ipv4addr_cmp(srcipaddr, conn->u.ipv4.raddr))
|
||||
{
|
||||
/* Matching connection found.. break out of the loop and return a
|
||||
* reference to it.
|
||||
*/
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
/* Look at the next active connection */
|
||||
|
||||
conn = (FAR struct tcp_conn_s *)conn->node.flink;
|
||||
}
|
||||
|
||||
return conn;
|
||||
}
|
||||
#endif /* CONFIG_NET_IPv4 */
|
||||
|
||||
/****************************************************************************
|
||||
* Name: tcp_ipv6_active
|
||||
*
|
||||
* Description:
|
||||
* Find a connection structure that is the appropriate
|
||||
* connection to be used with the provided TCP/IP header
|
||||
*
|
||||
* Assumptions:
|
||||
* This function is called from UIP logic at interrupt level
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_NET_IPv6
|
||||
static inline FAR struct tcp_conn_s *
|
||||
tcp_ipv6_active(FAR struct net_driver_s *dev, FAR struct tcp_hdr_s *tcp)
|
||||
{
|
||||
FAR struct net_ipv6hdr_s *ip = IPv6BUF;
|
||||
FAR struct tcp_conn_s *conn;
|
||||
net_ipv6addr_t *srcipaddr;
|
||||
#ifdef CONFIG_NETDEV_MULTINIC
|
||||
net_ipv6addr_t destipaddr;
|
||||
#endif
|
||||
|
||||
conn = (FAR struct tcp_conn_s *)g_active_tcp_connections.head;
|
||||
srcipaddr = (net_ipv6addr_t *)ip->srcipaddr;
|
||||
#ifdef CONFIG_NETDEV_MULTINIC
|
||||
destipaddr = (net_ipv6addr_t *)ip->destipaddr;
|
||||
#endif
|
||||
|
||||
while (conn)
|
||||
{
|
||||
/* Find an open connection matching the TCP input. The following
|
||||
* checks are performed:
|
||||
*
|
||||
* - The local port number is checked against the destination port
|
||||
* number in the received packet.
|
||||
* - The remote port number is checked if the connection is bound
|
||||
* to a remote port.
|
||||
* - If multiple network interfaces are supported, then the local
|
||||
* IP address is available and we will insist that the
|
||||
* destination IP matches the bound address. If a socket is
|
||||
* bound to INADDRY_ANY, then it should receive all packets
|
||||
* directed to the port.
|
||||
* - Finally, if the connection is bound to a remote IP address,
|
||||
* the source IP address of the packet is checked.
|
||||
*
|
||||
* If all of the above are true then the newly received TCP packet
|
||||
* is destined for this TCP connection.
|
||||
*/
|
||||
|
||||
if (conn->tcpstateflags != TCP_CLOSED &&
|
||||
tcp->destport == conn->lport &&
|
||||
tcp->srcport == conn->rport &&
|
||||
#ifdef CONFIG_NETDEV_MULTINIC
|
||||
(net_ipv6addr_cmp(conn->u.ipv6.laddr, g_ipv6_allzeroaddr) ||
|
||||
net_ipv6addr_cmp(*destipaddr, conn->u.ipv6.laddr)) &&
|
||||
#endif
|
||||
net_ipv6addr_cmp(*srcipaddr, conn->u.ipv6.raddr))
|
||||
{
|
||||
/* Matching connection found.. break out of the loop and return a
|
||||
* reference to it.
|
||||
*/
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
/* Look at the next active connection */
|
||||
|
||||
conn = (FAR struct tcp_conn_s *)conn->node.flink;
|
||||
}
|
||||
|
||||
return conn;
|
||||
}
|
||||
#endif /* CONFIG_NET_IPv6 */
|
||||
|
||||
/****************************************************************************
|
||||
* Name: tcp_ipv4_bind
|
||||
*
|
||||
* Description:
|
||||
* This function implements the lower level parts of the standard TCP
|
||||
* bind() operation.
|
||||
*
|
||||
* Return:
|
||||
* 0 on success or -EADDRINUSE on failure
|
||||
*
|
||||
* Assumptions:
|
||||
* This function is called from normal user level code.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_NET_IPv4
|
||||
static inline int tcp_ipv4_bind(FAR struct tcp_conn_s *conn,
|
||||
FAR const struct sockaddr_in *addr)
|
||||
{
|
||||
net_lock_t flags;
|
||||
int port;
|
||||
|
||||
/* Verify or select a local port and address */
|
||||
|
||||
flags = net_lock();
|
||||
|
||||
/* Verify or select a local port */
|
||||
|
||||
#ifdef CONFIG_NETDEV_MULTINIC
|
||||
port = tcp_selectport(PF_INET,
|
||||
(FAR const union ip_addr_u ipaddr *)&addr->sin_addr.s_addr,
|
||||
ntohs(addr->sin_port));
|
||||
#else
|
||||
port = tcp_selectport(ntohs(addr->sin_port));
|
||||
#endif
|
||||
|
||||
net_unlock(flags);
|
||||
|
||||
if (port < 0)
|
||||
{
|
||||
return port;
|
||||
}
|
||||
|
||||
/* Save the local address in the connection structure. */
|
||||
|
||||
conn->lport = addr->sin_port;
|
||||
|
||||
#ifdef CONFIG_NETDEV_MULTINIC
|
||||
net_ipv4addr_copy(conn->u.ipv4.laddr, ipaddr);
|
||||
#endif
|
||||
|
||||
return OK;
|
||||
}
|
||||
#endif /* CONFIG_NET_IPv4 */
|
||||
|
||||
/****************************************************************************
|
||||
* Name: tcp_ipv6_bind
|
||||
*
|
||||
* Description:
|
||||
* This function implements the lower level parts of the standard TCP
|
||||
* bind() operation.
|
||||
*
|
||||
* Return:
|
||||
* 0 on success or -EADDRINUSE on failure
|
||||
*
|
||||
* Assumptions:
|
||||
* This function is called from normal user level code.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_NET_IPv6
|
||||
static inline int tcp_ipv6_bind(FAR struct tcp_conn_s *conn,
|
||||
FAR const struct sockaddr_in6 *addr)
|
||||
{
|
||||
net_lock_t flags;
|
||||
int port;
|
||||
|
||||
/* Verify or select a local port and address */
|
||||
|
||||
flags = net_lock();
|
||||
|
||||
/* Verify or select a local port */
|
||||
|
||||
#ifdef CONFIG_NETDEV_MULTINIC
|
||||
port = tcp_selectport(PF_INET6,
|
||||
(FAR const union ip_addr_u ipaddr *)addr->sin6_addr.in6_u.u6_addr16,
|
||||
ntohs(addr->sin_port));
|
||||
#else
|
||||
port = tcp_selectport(ntohs(addr->sin_port));
|
||||
#endif
|
||||
|
||||
net_unlock(flags);
|
||||
|
||||
if (port < 0)
|
||||
{
|
||||
return port;
|
||||
}
|
||||
|
||||
/* Save the local address in the connection structure. */
|
||||
|
||||
conn->lport = addr->sin_port;
|
||||
|
||||
#ifdef CONFIG_NETDEV_MULTINIC
|
||||
net_ipv6addr_copy(conn->u.ipv6.laddr, addr->sin6_addr.in6_u.u6_addr16);
|
||||
#endif
|
||||
|
||||
return OK;
|
||||
}
|
||||
#endif /* CONFIG_NET_IPv6 */
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
@ -489,62 +859,23 @@ void tcp_free(FAR struct tcp_conn_s *conn)
|
|||
FAR struct tcp_conn_s *tcp_active(FAR struct net_driver_s *dev,
|
||||
FAR struct tcp_hdr_s *tcp)
|
||||
{
|
||||
FAR struct net_iphdr_s *ip = IPv4;
|
||||
FAR struct tcp_conn_s *conn;
|
||||
in_addr_t srcipaddr;
|
||||
#ifdef CONFIG_NETDEV_MULTINIC
|
||||
in_addr_t destipaddr;
|
||||
#ifdef CONFIG_NET_IPv6
|
||||
#ifdef CONFIG_NET_IPv4
|
||||
if (IFF_IS_IPv6(dev->d_flags))
|
||||
#endif
|
||||
|
||||
conn = (FAR struct tcp_conn_s *)g_active_tcp_connections.head;
|
||||
srcipaddr = net_ip4addr_conv32(ip->srcipaddr);
|
||||
#ifdef CONFIG_NETDEV_MULTINIC
|
||||
destipaddr = net_ip4addr_conv32(ip->destipaddr);
|
||||
#endif
|
||||
|
||||
while (conn)
|
||||
{
|
||||
/* Find an open connection matching the TCP input. The following
|
||||
* checks are performed:
|
||||
*
|
||||
* - The local port number is checked against the destination port
|
||||
* number in the received packet.
|
||||
* - The remote port number is checked if the connection is bound
|
||||
* to a remote port.
|
||||
* - If multiple network interfaces are supported, then the local
|
||||
* IP address is available and we will insist that the
|
||||
* destination IP matches the bound address. If a socket is
|
||||
* bound to INADDRY_ANY, then it should receive all packets
|
||||
* directed to the port.
|
||||
* - Finally, if the connection is bound to a remote IP address,
|
||||
* the source IP address of the packet is checked.
|
||||
*
|
||||
* If all of the above are true then the newly received TCP packet
|
||||
* is destined for this TCP connection.
|
||||
*/
|
||||
|
||||
if (conn->tcpstateflags != TCP_CLOSED &&
|
||||
tcp->destport == conn->lport &&
|
||||
tcp->srcport == conn->rport &&
|
||||
#ifdef CONFIG_NETDEV_MULTINIC
|
||||
(net_ipv4addr_cmp(conn->u.ipv4.laddr, g_ipv4_allzeroaddr) ||
|
||||
net_ipv4addr_cmp(destipaddr, conn->u.ipv4.laddr)) &&
|
||||
#endif
|
||||
net_ipv4addr_cmp(srcipaddr, conn->u.ipv4.raddr))
|
||||
{
|
||||
/* Matching connection found.. break out of the loop and return a
|
||||
* reference to it.
|
||||
*/
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
/* Look at the next active connection */
|
||||
|
||||
conn = (FAR struct tcp_conn_s *)conn->node.flink;
|
||||
return tcp_ipv6_active(dev, tcp);
|
||||
}
|
||||
#endif /* CONFIG_NET_IPv6 */
|
||||
|
||||
return conn;
|
||||
#ifdef CONFIG_NET_IPv4
|
||||
#ifdef CONFIG_NET_IPv6
|
||||
else
|
||||
#endif
|
||||
{
|
||||
return tcp_ipv4_active(dev, tcp);
|
||||
}
|
||||
#endif /* CONFIG_NET_IPv4 */
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -587,14 +918,23 @@ FAR struct tcp_conn_s *tcp_nextconn(FAR struct tcp_conn_s *conn)
|
|||
FAR struct tcp_conn_s *tcp_alloc_accept(FAR struct net_driver_s *dev,
|
||||
FAR struct tcp_hdr_s *tcp)
|
||||
{
|
||||
FAR struct net_iphdr_s *ip = IPv4;
|
||||
FAR struct tcp_conn_s *conn;
|
||||
uint8_t domain;
|
||||
|
||||
#ifdef CONFIG_NET_IPv4
|
||||
conn = tcp_alloc(PF_INET);
|
||||
#else
|
||||
conn = tcp_alloc(PF_INET6);
|
||||
/* Get the appropriate IP domain */
|
||||
|
||||
#if defined(CONFIG_NET_IPv4) && defined(CONFIG_NET_IPv4)
|
||||
bool ipv6 = IFF_IS_IPv6(dev->d_flags);
|
||||
domain = ipv6 ? PF_INET6 : PF_INET;
|
||||
#elif defined(CONFIG_NET_IPv4)
|
||||
domain = PF_INET;
|
||||
#else /* defined(CONFIG_NET_IPv6) */
|
||||
domain = PF_INET6;
|
||||
#endif
|
||||
|
||||
/* Allocate the connection structure */
|
||||
|
||||
conn = tcp_alloc(domain);
|
||||
if (conn)
|
||||
{
|
||||
/* Fill in the necessary fields for the new connection. */
|
||||
|
@ -606,19 +946,47 @@ FAR struct tcp_conn_s *tcp_alloc_accept(FAR struct net_driver_s *dev,
|
|||
conn->nrtx = 0;
|
||||
conn->lport = tcp->destport;
|
||||
conn->rport = tcp->srcport;
|
||||
conn->mss = TCP_IPv4_INITIAL_MSS(dev);
|
||||
net_ipv4addr_copy(conn->u.ipv4.raddr, net_ip4addr_conv32(ip->srcipaddr));
|
||||
#ifdef CONFIG_NETDEV_MULTINIC
|
||||
net_ipv4addr_copy(conn->u.ipv4.laddr, net_ip4addr_conv32(ip->destipaddr));
|
||||
|
||||
#ifdef CONFIG_NET_IPv6
|
||||
#ifdef CONFIG_NET_IPv4
|
||||
if (ipv6)
|
||||
#endif
|
||||
{
|
||||
FAR struct net_ipv6hdr_s *ip = IPv6BUF;
|
||||
|
||||
conn->mss = TCP_IPv6_INITIAL_MSS(dev);
|
||||
net_ipv6addr_copy(conn->u.ipv6.raddr, ip->srcipaddr);
|
||||
#ifdef CONFIG_NETDEV_MULTINIC
|
||||
net_ipv6addr_copy(conn->u.ipv6.laddr, ip->destipaddr);
|
||||
#endif
|
||||
}
|
||||
#endif /* CONFIG_NET_IPv6 */
|
||||
|
||||
#ifdef CONFIG_NET_IPv4
|
||||
#ifdef CONFIG_NET_IPv6
|
||||
else
|
||||
#endif
|
||||
{
|
||||
FAR struct net_iphdr_s *ip = IPv4BUF;
|
||||
|
||||
conn->mss = TCP_IPv4_INITIAL_MSS(dev);
|
||||
net_ipv4addr_copy(conn->u.ipv4.raddr,
|
||||
net_ip4addr_conv32(ip->srcipaddr));
|
||||
#ifdef CONFIG_NETDEV_MULTINIC
|
||||
net_ipv4addr_copy(conn->u.ipv4.laddr,
|
||||
net_ip4addr_conv32(ip->destipaddr));
|
||||
#endif
|
||||
}
|
||||
#endif /* CONFIG_NET_IPv4 */
|
||||
|
||||
conn->tcpstateflags = TCP_SYN_RCVD;
|
||||
|
||||
tcp_initsequence(conn->sndseq);
|
||||
conn->unacked = 1;
|
||||
conn->unacked = 1;
|
||||
#ifdef CONFIG_NET_TCP_WRITE_BUFFERS
|
||||
conn->expired = 0;
|
||||
conn->isn = 0;
|
||||
conn->sent = 0;
|
||||
conn->expired = 0;
|
||||
conn->isn = 0;
|
||||
conn->sent = 0;
|
||||
#endif
|
||||
|
||||
/* rcvseq should be the seqno from the incoming packet + 1. */
|
||||
|
@ -663,60 +1031,31 @@ FAR struct tcp_conn_s *tcp_alloc_accept(FAR struct net_driver_s *dev,
|
|||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_NET_IPv6
|
||||
int tcp_bind(FAR struct tcp_conn_s *conn,
|
||||
FAR const struct sockaddr_in6 *addr)
|
||||
#else
|
||||
int tcp_bind(FAR struct tcp_conn_s *conn,
|
||||
FAR const struct sockaddr_in *addr)
|
||||
#endif
|
||||
int tcp_bind(FAR struct tcp_conn_s *conn, FAR const struct sockaddr *addr)
|
||||
{
|
||||
net_lock_t flags;
|
||||
int port;
|
||||
#ifdef CONFIG_NETDEV_MULTINIC
|
||||
in_addr_t ipaddr;
|
||||
#endif
|
||||
|
||||
/* Verify or select a local port and address */
|
||||
|
||||
flags = net_lock();
|
||||
|
||||
#ifdef CONFIG_NETDEV_MULTINIC
|
||||
#ifdef CONFIG_NET_IPv4
|
||||
#ifdef CONFIG_NET_IPv6
|
||||
/* Get the IPv6 address that we are binding to */
|
||||
|
||||
ipaddr = addr->sin6_addr.in6_u.u6_addr16;
|
||||
|
||||
#else
|
||||
/* Get the IPv4 address that we are binding to */
|
||||
|
||||
ipaddr = addr->sin_addr.s_addr;
|
||||
|
||||
if (conn->domain == PF_INET)
|
||||
#endif
|
||||
|
||||
port = tcp_selectport(ipaddr, ntohs(addr->sin_port));
|
||||
#else
|
||||
/* Verify or select a local port */
|
||||
|
||||
port = tcp_selectport(ntohs(addr->sin_port));
|
||||
#endif
|
||||
|
||||
net_unlock(flags);
|
||||
|
||||
if (port < 0)
|
||||
{
|
||||
return port;
|
||||
FAR const struct sockaddr_in *inaddr =
|
||||
(FAR const struct sockaddr_in *)addr;
|
||||
|
||||
return tcp_ipv4_bind(conn, inaddr);
|
||||
}
|
||||
#endif /* CONFIG_NET_IPv4 */
|
||||
|
||||
/* Save the local address in the connection structure. */
|
||||
|
||||
conn->lport = addr->sin_port;
|
||||
|
||||
#ifdef CONFIG_NETDEV_MULTINIC
|
||||
net_ipv4addr_copy(conn->u.ipv4.laddr, ipaddr);
|
||||
#ifdef CONFIG_NET_IPv6
|
||||
#ifdef CONFIG_NET_IPv4
|
||||
else
|
||||
#endif
|
||||
{
|
||||
FAR const struct sockaddr_in6 *inaddr =
|
||||
(FAR const struct sockaddr_in6 *)addr;
|
||||
|
||||
return OK;
|
||||
return tcp_ipv6_bind(conn, inaddr);
|
||||
}
|
||||
#endif /* CONFIG_NET_IPv6 */
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -761,7 +1100,7 @@ int tcp_connect(FAR struct tcp_conn_s *conn, FAR const struct sockaddr *addr)
|
|||
|
||||
flags = net_lock();
|
||||
#ifdef CONFIG_NETDEV_MULTINIC
|
||||
port = tcp_selectport(conn->u.ipv4.laddr, ntohs(conn->lport));
|
||||
port = tcp_selectport(conn->domain, &conn->u, ntohs(conn->lport));
|
||||
#else
|
||||
port = tcp_selectport(ntohs(conn->lport));
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue