net/tcp: The logic that binds a specific networkd device to a connection was faulty for the case of multiple network devices. On bind(), the local address should be used to associate a device with the connection (if the local address is not INADDR_ANY); On connect(), the remote address should be used (in case the local address is INADDR_ANY). On accept(), it does not matter but the remote address is the one guarenteed to be available.
This commit is contained in:
parent
f44320d2a6
commit
0e2986f131
5 changed files with 212 additions and 43 deletions
|
@ -10933,3 +10933,11 @@
|
|||
Averyanov (2015-09-02).
|
||||
* arch/arm/src/lpc43xx/lpc43_ethernet.c: Add Ethernet support. From
|
||||
Ilya Averyanov (2015-09-02).
|
||||
* net/tcp: The logic that binds a specific networkd device to
|
||||
a connection was faulty for the case of multiple network
|
||||
devices. On bind(), the local address should be used to associate
|
||||
a device with the connection (if the local address is not INADDR_ANY);
|
||||
On connect(), the remote address should be used (in case the local
|
||||
address is INADDR_ANY). On accept(), it does not matter but the
|
||||
remote address is the one guarenteed to be availalbe (2015-09-02).
|
||||
|
||||
|
|
|
@ -407,10 +407,11 @@ FAR struct tcp_conn_s *tcp_active(FAR struct net_driver_s *dev,
|
|||
FAR struct tcp_conn_s *tcp_nextconn(FAR struct tcp_conn_s *conn);
|
||||
|
||||
/****************************************************************************
|
||||
* Function: tcp_find_ipv4_device
|
||||
* Function: tcp_local_ipv4_device
|
||||
*
|
||||
* Description:
|
||||
* Select the network driver to use with the IPv4 TCP transaction.
|
||||
* Select the network driver to use with the IPv4 TCP transaction based
|
||||
* on the locally bound IPv4 address
|
||||
*
|
||||
* Input Parameters:
|
||||
* conn - TCP connection structure. The locally bound address, laddr,
|
||||
|
@ -423,14 +424,36 @@ FAR struct tcp_conn_s *tcp_nextconn(FAR struct tcp_conn_s *conn);
|
|||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_NET_IPv4
|
||||
int tcp_find_ipv4_device(FAR struct tcp_conn_s *conn);
|
||||
int tcp_local_ipv4_device(FAR struct tcp_conn_s *conn);
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Function: tcp_find_ipv6_device
|
||||
* Function: tcp_remote_ipv4_device
|
||||
*
|
||||
* Description:
|
||||
* Select the network driver to use with the IPv6 TCP transaction.
|
||||
* Select the network driver to use with the IPv4 TCP transaction based
|
||||
* on the remotely connected IPv4 address
|
||||
*
|
||||
* Input Parameters:
|
||||
* conn - TCP connection structure. The remotely conected address, raddr,
|
||||
* should be set to a non-zero value in this structure.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) is returned on success. A negated errno value is returned
|
||||
* on failure. -ENODEV is the only expected error value.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_NET_IPv4
|
||||
int tcp_remote_ipv4_device(FAR struct tcp_conn_s *conn);
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Function: tcp_local_ipv6_device
|
||||
*
|
||||
* Description:
|
||||
* Select the network driver to use with the IPv6 TCP transaction based
|
||||
* on the locally bound IPv6 address
|
||||
*
|
||||
* Input Parameters:
|
||||
* conn - TCP connection structure. The locally bound address, laddr,
|
||||
|
@ -443,7 +466,28 @@ int tcp_find_ipv4_device(FAR struct tcp_conn_s *conn);
|
|||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_NET_IPv6
|
||||
int tcp_find_ipv6_device(FAR struct tcp_conn_s *conn);
|
||||
int tcp_local_ipv6_device(FAR struct tcp_conn_s *conn);
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Function: tcp_remote_ipv6_device
|
||||
*
|
||||
* Description:
|
||||
* Select the network driver to use with the IPv6 TCP transaction based
|
||||
* on the remotely conected IPv6 address
|
||||
*
|
||||
* Input Parameters:
|
||||
* conn - TCP connection structure. The remotely connected address, raddr,
|
||||
* should be set to a non-zero value in this structure.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) is returned on success. A negated errno value is returned
|
||||
* on failure. -EHOSTUNREACH is the only expected error value.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_NET_IPv6
|
||||
int tcp_remote_ipv6_device(FAR struct tcp_conn_s *conn);
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
|
|
|
@ -543,16 +543,16 @@ static inline int tcp_ipv4_bind(FAR struct tcp_conn_s *conn,
|
|||
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.
|
||||
/* Find the device that can receive packets on the network associated with
|
||||
* this local address.
|
||||
*/
|
||||
|
||||
ret = tcp_find_ipv4_device(conn);
|
||||
ret = tcp_local_ipv4_device(conn);
|
||||
if (ret < 0)
|
||||
{
|
||||
/* If no device is found, then the address is not reachable */
|
||||
|
||||
ndbg("tcp_find_ipv4_device failed: %d\n", ret);
|
||||
ndbg("tcp_local_ipv4_device failed: %d\n", ret);
|
||||
|
||||
/* Back out the local address setting */
|
||||
|
||||
|
@ -628,12 +628,12 @@ static inline int tcp_ipv6_bind(FAR struct tcp_conn_s *conn,
|
|||
* associated with this local address.
|
||||
*/
|
||||
|
||||
ret = tcp_find_ipv6_device(conn);
|
||||
ret = tcp_local_ipv6_device(conn);
|
||||
if (ret < 0)
|
||||
{
|
||||
/* If no device is found, then the address is not reachable */
|
||||
|
||||
ndbg("tcp_find_ipv6_device failed: %d\n", ret);
|
||||
ndbg("tcp_local_ipv6_device failed: %d\n", ret);
|
||||
|
||||
/* Back out the local address setting */
|
||||
|
||||
|
@ -1016,7 +1016,7 @@ FAR struct tcp_conn_s *tcp_alloc_accept(FAR struct net_driver_s *dev,
|
|||
* associated with this local address.
|
||||
*/
|
||||
|
||||
ret = tcp_find_ipv6_device(conn);
|
||||
ret = tcp_remote_ipv6_device(conn);
|
||||
}
|
||||
#endif /* CONFIG_NET_IPv6 */
|
||||
|
||||
|
@ -1027,12 +1027,15 @@ FAR struct tcp_conn_s *tcp_alloc_accept(FAR struct net_driver_s *dev,
|
|||
{
|
||||
FAR struct ipv4_hdr_s *ip = IPv4BUF;
|
||||
|
||||
/* Set the IPv6 specific MSS and the IPv4 locally bound address. */
|
||||
/* Set the IPv6 specific MSS and the IPv4 bound remote address. */
|
||||
|
||||
conn->mss = TCP_IPv4_INITIAL_MSS(dev);
|
||||
net_ipv4addr_copy(conn->u.ipv4.raddr,
|
||||
net_ip4addr_conv32(ip->srcipaddr));
|
||||
|
||||
#ifdef CONFIG_NETDEV_MULTINIC
|
||||
/* Set the local address as well */
|
||||
|
||||
net_ipv4addr_copy(conn->u.ipv4.laddr,
|
||||
net_ip4addr_conv32(ip->destipaddr));
|
||||
|
||||
|
@ -1048,7 +1051,7 @@ FAR struct tcp_conn_s *tcp_alloc_accept(FAR struct net_driver_s *dev,
|
|||
* associated with this local address.
|
||||
*/
|
||||
|
||||
ret = tcp_find_ipv4_device(conn);
|
||||
ret = tcp_remote_ipv4_device(conn);
|
||||
}
|
||||
#endif /* CONFIG_NET_IPv4 */
|
||||
|
||||
|
@ -1274,10 +1277,10 @@ int tcp_connect(FAR struct tcp_conn_s *conn, FAR const struct sockaddr *addr)
|
|||
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 local address.
|
||||
* with this remote address.
|
||||
*/
|
||||
|
||||
ret = tcp_find_ipv4_device(conn);
|
||||
ret = tcp_remote_ipv4_device(conn);
|
||||
}
|
||||
#endif /* CONFIG_NET_IPv4 */
|
||||
|
||||
|
@ -1302,7 +1305,7 @@ int tcp_connect(FAR struct tcp_conn_s *conn, FAR const struct sockaddr *addr)
|
|||
* with this local address.
|
||||
*/
|
||||
|
||||
ret = tcp_find_ipv6_device(conn);
|
||||
ret = tcp_remote_ipv6_device(conn);
|
||||
}
|
||||
#endif /* CONFIG_NET_IPv6 */
|
||||
|
||||
|
|
|
@ -57,39 +57,41 @@
|
|||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Function: tcp_find_ipv4_device
|
||||
*
|
||||
* Description:
|
||||
* Select the network driver to use with the IPv4 TCP transaction.
|
||||
* Select the network driver to use with the IPv4 TCP connection.
|
||||
*
|
||||
* Input Parameters:
|
||||
* conn - TCP connection structure. The locally bound address, laddr,
|
||||
* should be set to a non-zero value in this structure.
|
||||
* conn - TCP connection structure.
|
||||
* addr - The IPv4 address to use
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) is returned on success. A negated errno value is returned
|
||||
* on failure. -ENETUNREACH is the only expected error value.
|
||||
* on failure. -ENODEV is the only expected error value.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_NET_IPv4
|
||||
int tcp_find_ipv4_device(FAR struct tcp_conn_s *conn)
|
||||
static int tcp_find_ipv4_device(FAR struct tcp_conn_s *conn, in_addr_t addr)
|
||||
{
|
||||
#ifdef CONFIG_NETDEV_MULTINIC
|
||||
/* Do nothing if a device is already bound to the connection */
|
||||
|
||||
if (conn->dev != NULL)
|
||||
{
|
||||
return OK;
|
||||
}
|
||||
|
||||
/* Return success without using device notification if the locally bound
|
||||
* address is INADDR_ANY. In this case, there may be multiple devices
|
||||
* that can provide data so the exceptional events from any particular
|
||||
* device are not important.
|
||||
*/
|
||||
|
||||
if (net_ipv4addr_cmp(conn->u.ipv4.laddr, INADDR_ANY))
|
||||
if (net_ipv4addr_cmp(addr, INADDR_ANY))
|
||||
{
|
||||
conn->dev = NULL;
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
@ -97,8 +99,7 @@ int tcp_find_ipv4_device(FAR struct tcp_conn_s *conn)
|
|||
* is going to route the TCP packet based on the provided IP address.
|
||||
*/
|
||||
|
||||
conn->dev = netdev_findby_ipv4addr(conn->u.ipv4.laddr,
|
||||
conn->u.ipv4.laddr);
|
||||
conn->dev = netdev_findby_ipv4addr(addr, addr);
|
||||
|
||||
/* Return success if we found the device */
|
||||
|
||||
|
@ -121,8 +122,8 @@ int tcp_find_ipv4_device(FAR struct tcp_conn_s *conn)
|
|||
* Select the network driver to use with the IPv6 TCP transaction.
|
||||
*
|
||||
* Input Parameters:
|
||||
* conn - TCP connection structure. The locally bound address, laddr,
|
||||
* should be set to a non-zero value in this structure.
|
||||
* conn - TCP connection structure.
|
||||
* addr - The IPv6 address to use
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) is returned on success. A negated errno value is returned
|
||||
|
@ -131,18 +132,24 @@ int tcp_find_ipv4_device(FAR struct tcp_conn_s *conn)
|
|||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_NET_IPv6
|
||||
int tcp_find_ipv6_device(FAR struct tcp_conn_s *conn)
|
||||
static int tcp_find_ipv6_device(FAR struct tcp_conn_s *conn, const net_ipv6addr_t addr)
|
||||
{
|
||||
#ifdef CONFIG_NETDEV_MULTINIC
|
||||
/* Do nothing if a device is already bound to the connection */
|
||||
|
||||
if (conn->dev != NULL)
|
||||
{
|
||||
return OK;
|
||||
}
|
||||
|
||||
/* Return success without using device notification if the locally bound
|
||||
* address is IN6ADDR_ANY. In this case, there may be multiple devices
|
||||
* that can provide data so the exceptional events from any particular
|
||||
* device are not important.
|
||||
*/
|
||||
|
||||
if (net_ipv6addr_cmp(conn->u.ipv6.laddr, g_ipv6_allzeroaddr))
|
||||
if (net_ipv6addr_cmp(addr, g_ipv6_allzeroaddr))
|
||||
{
|
||||
conn->dev = NULL;
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
@ -150,8 +157,7 @@ int tcp_find_ipv6_device(FAR struct tcp_conn_s *conn)
|
|||
* is going to route the TCP packet based on the provided IP address.
|
||||
*/
|
||||
|
||||
conn->dev = netdev_findby_ipv6addr(conn->u.ipv6.laddr,
|
||||
conn->u.ipv6.laddr);
|
||||
conn->dev = netdev_findby_ipv6addr(addr, addr);
|
||||
|
||||
/* Return success if we found the device */
|
||||
|
||||
|
@ -167,4 +173,112 @@ int tcp_find_ipv6_device(FAR struct tcp_conn_s *conn)
|
|||
}
|
||||
#endif /* CONFIG_NET_IPv6 */
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Function: tcp_local_ipv4_device
|
||||
*
|
||||
* Description:
|
||||
* Select the network driver to use with the IPv4 TCP transaction based
|
||||
* on the locally bound IPv4 address
|
||||
*
|
||||
* Input Parameters:
|
||||
* conn - TCP connection structure. The locally bound address, laddr,
|
||||
* should be set to a non-zero value in this structure.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) is returned on success. A negated errno value is returned
|
||||
* on failure. -ENODEV is the only expected error value.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_NET_IPv4
|
||||
int tcp_local_ipv4_device(FAR struct tcp_conn_s *conn)
|
||||
{
|
||||
#ifdef CONFIG_NETDEV_MULTINIC
|
||||
return tcp_find_ipv4_device(conn, conn->u.ipv4.laddr);
|
||||
#else
|
||||
return tcp_find_ipv4_device(conn, 0);
|
||||
#endif
|
||||
}
|
||||
#endif /* CONFIG_NET_IPv4 */
|
||||
|
||||
/****************************************************************************
|
||||
* Function: tcp_remote_ipv4_device
|
||||
*
|
||||
* Description:
|
||||
* Select the network driver to use with the IPv4 TCP transaction based
|
||||
* on the remotely connected IPv4 address
|
||||
*
|
||||
* Input Parameters:
|
||||
* conn - TCP connection structure. The remotely conected address, raddr,
|
||||
* should be set to a non-zero value in this structure.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) is returned on success. A negated errno value is returned
|
||||
* on failure. -ENODEV is the only expected error value.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_NET_IPv4
|
||||
int tcp_remote_ipv4_device(FAR struct tcp_conn_s *conn)
|
||||
{
|
||||
return tcp_find_ipv4_device(conn, conn->u.ipv4.raddr);
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Function: tcp_local_ipv6_device
|
||||
*
|
||||
* Description:
|
||||
* Select the network driver to use with the IPv6 TCP transaction.
|
||||
*
|
||||
* Input Parameters:
|
||||
* conn - TCP connection structure. The locally bound address, laddr,
|
||||
* should be set to a non-zero value in this structure.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) is returned on success. A negated errno value is returned
|
||||
* on failure. -ENETUNREACH is the only expected error value.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_NET_IPv6
|
||||
int tcp_local_ipv6_device(FAR struct tcp_conn_s *conn)
|
||||
{
|
||||
#ifdef CONFIG_NETDEV_MULTINIC
|
||||
return tcp_find_ipv6_device(conn, conn->u.ipv6.laddr);
|
||||
#else
|
||||
return tcp_find_ipv6_device(conn, NULL);
|
||||
#endif
|
||||
|
||||
}
|
||||
#endif /* CONFIG_NET_IPv6 */
|
||||
|
||||
/****************************************************************************
|
||||
* Function: tcp_remote_ipv6_device
|
||||
*
|
||||
* Description:
|
||||
* Select the network driver to use with the IPv6 TCP transaction based
|
||||
* on the remotely conected IPv6 address
|
||||
*
|
||||
* Input Parameters:
|
||||
* conn - TCP connection structure. The remotely connected address, raddr,
|
||||
* should be set to a non-zero value in this structure.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) is returned on success. A negated errno value is returned
|
||||
* on failure. -EHOSTUNREACH is the only expected error value.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_NET_IPv6
|
||||
int tcp_remote_ipv6_device(FAR struct tcp_conn_s *conn)
|
||||
{
|
||||
return int tcp_find_ipv6_device(conn, conn->u.ipv6.raddr);
|
||||
}
|
||||
#endif /* CONFIG_NET_IPv6 */
|
||||
|
||||
#endif /* CONFIG_NET && CONFIG_NET_TCP */
|
||||
|
|
|
@ -71,7 +71,7 @@
|
|||
* Name: chksum
|
||||
****************************************************************************/
|
||||
|
||||
#if !CONFIG_NET_ARCH_CHKSUM
|
||||
#ifndef CONFIG_NET_ARCH_CHKSUM
|
||||
static uint16_t chksum(uint16_t sum, FAR const uint8_t *data, uint16_t len)
|
||||
{
|
||||
FAR const uint8_t *dataptr;
|
||||
|
@ -204,7 +204,7 @@ static uint16_t ipv6_upperlayer_chksum(FAR struct net_driver_s *dev,
|
|||
*
|
||||
****************************************************************************/
|
||||
|
||||
#if !CONFIG_NET_ARCH_INCR32
|
||||
#ifndef CONFIG_NET_ARCH_INCR32
|
||||
static inline void net_carry32(FAR uint8_t *sum, uint16_t op16)
|
||||
{
|
||||
if (sum[2] < (op16 >> 8))
|
||||
|
@ -254,7 +254,7 @@ static inline void net_carry32(FAR uint8_t *sum, uint16_t op16)
|
|||
*
|
||||
****************************************************************************/
|
||||
|
||||
#if !CONFIG_NET_ARCH_INCR32
|
||||
#ifndef CONFIG_NET_ARCH_INCR32
|
||||
void net_incr32(FAR uint8_t *op32, uint16_t op16)
|
||||
{
|
||||
op32[3] += (op16 & 0xff);
|
||||
|
@ -288,7 +288,7 @@ void net_incr32(FAR uint8_t *op32, uint16_t op16)
|
|||
*
|
||||
****************************************************************************/
|
||||
|
||||
#if !CONFIG_NET_ARCH_CHKSUM
|
||||
#ifndef CONFIG_NET_ARCH_CHKSUM
|
||||
uint16_t net_chksum(FAR uint16_t *data, uint16_t len)
|
||||
{
|
||||
return htons(chksum(0, (uint8_t *)data, len));
|
||||
|
@ -341,7 +341,7 @@ uint16_t ipv4_chksum(FAR struct net_driver_s *dev)
|
|||
*
|
||||
****************************************************************************/
|
||||
|
||||
#if !CONFIG_NET_ARCH_CHKSUM
|
||||
#ifndef CONFIG_NET_ARCH_CHKSUM
|
||||
#ifdef CONFIG_NET_IPv4
|
||||
uint16_t tcp_ipv4_chksum(FAR struct net_driver_s *dev)
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue