net/udp: Correct an error introduce in recent fixes for UDP connected sockets. The interaction between psock_udp_send() and psock_udp_sendto() was perverse: It should always pass a NULL destinatino address.
This commit is contained in:
parent
77d7856642
commit
434da18cd7
@ -1,7 +1,7 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* net/udp/udp_psock_send.c
|
* net/udp/udp_psock_send.c
|
||||||
*
|
*
|
||||||
* Copyright (C) 2015 Gregory Nutt. All rights reserved.
|
* Copyright (C) 2015, 2018 Gregory Nutt. All rights reserved.
|
||||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -65,17 +65,6 @@ ssize_t psock_udp_send(FAR struct socket *psock, FAR const void *buf,
|
|||||||
size_t len)
|
size_t len)
|
||||||
{
|
{
|
||||||
FAR struct udp_conn_s *conn;
|
FAR struct udp_conn_s *conn;
|
||||||
union
|
|
||||||
{
|
|
||||||
struct sockaddr addr;
|
|
||||||
#ifdef CONFIG_NET_IPv4
|
|
||||||
struct sockaddr_in addr4;
|
|
||||||
#endif
|
|
||||||
#ifdef CONFIG_NET_IPv6
|
|
||||||
struct sockaddr_in6 addr6;
|
|
||||||
#endif
|
|
||||||
} to;
|
|
||||||
socklen_t tolen;
|
|
||||||
|
|
||||||
DEBUGASSERT(psock != NULL && psock->s_crefs > 0);
|
DEBUGASSERT(psock != NULL && psock->s_crefs > 0);
|
||||||
DEBUGASSERT(psock->s_type == SOCK_DGRAM);
|
DEBUGASSERT(psock->s_type == SOCK_DGRAM);
|
||||||
@ -94,29 +83,5 @@ ssize_t psock_udp_send(FAR struct socket *psock, FAR const void *buf,
|
|||||||
|
|
||||||
/* Yes, then let psock_sendto to the work */
|
/* Yes, then let psock_sendto to the work */
|
||||||
|
|
||||||
#ifdef CONFIG_NET_IPv4
|
return psock_udp_sendto(psock, buf, len, 0, NULL, 0);
|
||||||
#ifdef CONFIG_NET_IPv6
|
|
||||||
if (conn->domain == PF_INET)
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
tolen = sizeof(struct sockaddr_in);
|
|
||||||
to.addr4.sin_family = AF_INET;
|
|
||||||
to.addr4.sin_port = conn->rport;
|
|
||||||
net_ipv4addr_copy(to.addr4.sin_addr.s_addr, conn->u.ipv4.raddr);
|
|
||||||
}
|
|
||||||
#endif /* CONFIG_NET_IPv4 */
|
|
||||||
|
|
||||||
#ifdef CONFIG_NET_IPv6
|
|
||||||
#ifdef CONFIG_NET_IPv4
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
tolen = sizeof(struct sockaddr_in6);
|
|
||||||
to.addr6.sin6_family = AF_INET6;
|
|
||||||
to.addr6.sin6_port = conn->rport;
|
|
||||||
net_ipv6addr_copy(to.addr6.sin6_addr.s6_addr, conn->u.ipv6.raddr);
|
|
||||||
}
|
|
||||||
#endif /* CONFIG_NET_IPv6 */
|
|
||||||
|
|
||||||
return psock_udp_sendto(psock, buf, len, 0, &to.addr, tolen);
|
|
||||||
}
|
}
|
||||||
|
@ -630,6 +630,15 @@ ssize_t psock_udp_sendto(FAR struct socket *psock, FAR const void *buf,
|
|||||||
return -EISCONN;
|
return -EISCONN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Otherwise, if the socket is not connected, then a destination address
|
||||||
|
* must be provided.
|
||||||
|
*/
|
||||||
|
|
||||||
|
else if (to == NULL && !_SS_ISCONNECTED(psock->s_flags))
|
||||||
|
{
|
||||||
|
return -EDESTADDRREQ;
|
||||||
|
}
|
||||||
|
|
||||||
/* Make sure that we have the IP address mapping */
|
/* Make sure that we have the IP address mapping */
|
||||||
|
|
||||||
conn = (FAR struct udp_conn_s *)psock->s_conn;
|
conn = (FAR struct udp_conn_s *)psock->s_conn;
|
||||||
@ -693,8 +702,48 @@ ssize_t psock_udp_sendto(FAR struct socket *psock, FAR const void *buf,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Initialize the write buffer */
|
/* Initialize the write buffer */
|
||||||
|
/* Check if the socket is connected */
|
||||||
|
|
||||||
|
if (!_SS_ISCONNECTED(psock->s_flags))
|
||||||
|
{
|
||||||
|
/* Yes.. get the connection address from the connection structure */
|
||||||
|
|
||||||
|
#ifdef CONFIG_NET_IPv4
|
||||||
|
#ifdef CONFIG_NET_IPv6
|
||||||
|
if (conn->domain == PF_INET)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
FAR struct sockaddr_in *addr4 =
|
||||||
|
(FAR struct sockaddr_in *)&wrb->wb_dest;
|
||||||
|
|
||||||
|
addr4->sin_family = AF_INET;
|
||||||
|
addr4->sin_port = conn->rport;
|
||||||
|
net_ipv4addr_copy(addr4->sin_addr.s_addr, conn->u.ipv4.raddr);
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_NET_IPv4 */
|
||||||
|
|
||||||
|
#ifdef CONFIG_NET_IPv6
|
||||||
|
#ifdef CONFIG_NET_IPv4
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
FAR struct sockaddr_in6 *addr6 =
|
||||||
|
(FAR struct sockaddr_in6 *)&wrb->wb_dest;
|
||||||
|
|
||||||
|
addr6->sin6_family = AF_INET6;
|
||||||
|
addr6->sin6_port = conn->rport;
|
||||||
|
net_ipv6addr_copy(addr6->sin6_addr.s6_addr, conn->u.ipv6.raddr);
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_NET_IPv6 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Not connected. Use the provided destination address */
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
memcpy(&wrb->wb_dest, to, tolen);
|
||||||
|
}
|
||||||
|
|
||||||
memcpy(&wrb->wb_dest, to, tolen);
|
|
||||||
#ifdef CONFIG_NET_SOCKOPTS
|
#ifdef CONFIG_NET_SOCKOPTS
|
||||||
wrb->wb_start = clock_systimer();
|
wrb->wb_start = clock_systimer();
|
||||||
#endif
|
#endif
|
||||||
|
@ -335,6 +335,15 @@ ssize_t psock_udp_sendto(FAR struct socket *psock, FAR const void *buf,
|
|||||||
return -EISCONN;
|
return -EISCONN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Otherwise, if the socket is not connected, then a destination address
|
||||||
|
* must be provided.
|
||||||
|
*/
|
||||||
|
|
||||||
|
else if (to == NULL && !_SS_ISCONNECTED(psock->s_flags))
|
||||||
|
{
|
||||||
|
return -EDESTADDRREQ;
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(CONFIG_NET_ARP_SEND) || defined(CONFIG_NET_ICMPv6_NEIGHBOR)
|
#if defined(CONFIG_NET_ARP_SEND) || defined(CONFIG_NET_ICMPv6_NEIGHBOR)
|
||||||
#ifdef CONFIG_NET_ARP_SEND
|
#ifdef CONFIG_NET_ARP_SEND
|
||||||
#ifdef CONFIG_NET_ICMPv6_NEIGHBOR
|
#ifdef CONFIG_NET_ICMPv6_NEIGHBOR
|
||||||
@ -409,18 +418,25 @@ ssize_t psock_udp_sendto(FAR struct socket *psock, FAR const void *buf,
|
|||||||
state.st_time = clock_systimer();
|
state.st_time = clock_systimer();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Setup the UDP socket. udp_connect will set the remote address in the
|
/* Setup the UDP socket. */
|
||||||
* connection structure.
|
|
||||||
*/
|
|
||||||
|
|
||||||
conn = (FAR struct udp_conn_s *)psock->s_conn;
|
conn = (FAR struct udp_conn_s *)psock->s_conn;
|
||||||
DEBUGASSERT(conn);
|
DEBUGASSERT(conn);
|
||||||
|
|
||||||
ret = udp_connect(conn, to);
|
/* Check if the socket is connected */
|
||||||
if (ret < 0)
|
|
||||||
|
if (!_SS_ISCONNECTED(psock->s_flags))
|
||||||
{
|
{
|
||||||
nerr("ERROR: udp_connect failed: %d\n", ret);
|
/* No.. Call udp_connect() to set the remote address in the connection
|
||||||
goto errout_with_lock;
|
* structure to the sendto() destination address.
|
||||||
|
*/
|
||||||
|
|
||||||
|
ret = udp_connect(conn, to);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
nerr("ERROR: udp_connect failed: %d\n", ret);
|
||||||
|
goto errout_with_lock;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get the device that will handle the remote packet transfers. This
|
/* Get the device that will handle the remote packet transfers. This
|
||||||
|
Loading…
Reference in New Issue
Block a user