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
|
||||
*
|
||||
* Copyright (C) 2015 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2015, 2018 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* 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)
|
||||
{
|
||||
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->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 */
|
||||
|
||||
#ifdef CONFIG_NET_IPv4
|
||||
#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);
|
||||
return psock_udp_sendto(psock, buf, len, 0, NULL, 0);
|
||||
}
|
||||
|
@ -630,6 +630,15 @@ ssize_t psock_udp_sendto(FAR struct socket *psock, FAR const void *buf,
|
||||
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 */
|
||||
|
||||
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 */
|
||||
/* 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
|
||||
wrb->wb_start = clock_systimer();
|
||||
#endif
|
||||
|
@ -335,6 +335,15 @@ ssize_t psock_udp_sendto(FAR struct socket *psock, FAR const void *buf,
|
||||
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)
|
||||
#ifdef CONFIG_NET_ARP_SEND
|
||||
#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();
|
||||
#endif
|
||||
|
||||
/* Setup the UDP socket. udp_connect will set the remote address in the
|
||||
* connection structure.
|
||||
*/
|
||||
/* Setup the UDP socket. */
|
||||
|
||||
conn = (FAR struct udp_conn_s *)psock->s_conn;
|
||||
DEBUGASSERT(conn);
|
||||
|
||||
ret = udp_connect(conn, to);
|
||||
if (ret < 0)
|
||||
/* Check if the socket is connected */
|
||||
|
||||
if (!_SS_ISCONNECTED(psock->s_flags))
|
||||
{
|
||||
nerr("ERROR: udp_connect failed: %d\n", ret);
|
||||
goto errout_with_lock;
|
||||
/* No.. Call udp_connect() to set the remote address in the connection
|
||||
* 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
|
||||
|
Loading…
Reference in New Issue
Block a user