From a186383f2aefc203cd77aaeee99e72b0b3c101b9 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Thu, 17 May 2018 07:46:09 -0600 Subject: [PATCH] Recent changes to UDP in order to correct problems with UDP connection mode introduced a new bug: The 'to' address passed to sendto() must now be NULL in connection mode. But there are errors because there was one place where the 'to' address was still being used. This commit adds logic to first check for UDP connection mode. If the UDP socket is connected, then the NULL 'to' address is ignored and saved connection address is used instead. --- net/inet/inet_recvfrom.c | 1 - net/udp/udp_psock_sendto_buffered.c | 62 +++++++++++++++++++++-- net/udp/udp_psock_sendto_unbuffered.c | 72 +++++++++++++++++++++++---- 3 files changed, 120 insertions(+), 15 deletions(-) diff --git a/net/inet/inet_recvfrom.c b/net/inet/inet_recvfrom.c index e35fefe602b..805acb44ef2 100644 --- a/net/inet/inet_recvfrom.c +++ b/net/inet/inet_recvfrom.c @@ -1292,7 +1292,6 @@ static ssize_t inet_udp_recvfrom(FAR struct socket *psock, FAR void *buf, size_t } } -errout_with_state: net_unlock(); inet_recvfrom_uninitialize(&state); return ret; diff --git a/net/udp/udp_psock_sendto_buffered.c b/net/udp/udp_psock_sendto_buffered.c index cca6f89b6ba..8d5608ab9a8 100644 --- a/net/udp/udp_psock_sendto_buffered.c +++ b/net/udp/udp_psock_sendto_buffered.c @@ -647,31 +647,87 @@ ssize_t psock_udp_sendto(FAR struct socket *psock, FAR const void *buf, return -EDESTADDRREQ; } - /* Make sure that we have the IP address mapping */ + /* Get the underlying the UDP connection structure. */ conn = (FAR struct udp_conn_s *)psock->s_conn; DEBUGASSERT(conn); #if defined(CONFIG_NET_ARP_SEND) || defined(CONFIG_NET_ICMPv6_NEIGHBOR) #ifdef CONFIG_NET_ARP_SEND + /* Assure the the IPv4 destination address maps to a valid MAC address in + * the ARP table. + */ + #ifdef CONFIG_NET_ICMPv6_NEIGHBOR if (psock->s_domain == PF_INET) #endif { + in_addr_t destipaddr; + + /* Check if the socket is connection mode */ + + if (_SS_ISCONNECTED(psock->s_flags)) + { + /* Yes.. use the connected remote address (the 'to' address is + * null). + */ + + destipaddr = conn->u.ipv4.raddr; + } + else + { + FAR const struct sockaddr_in *into; + + /* No.. use the destination address provided by the non-NULL 'to' + * argument. + */ + + into = (FAR const struct sockaddr_in *)to; + destipaddr = into->sin_addr.s_addr; + } + /* Make sure that the IP address mapping is in the ARP table */ - ret = arp_send(conn->u.ipv4.raddr); + ret = arp_send(destipaddr); } #endif /* CONFIG_NET_ARP_SEND */ #ifdef CONFIG_NET_ICMPv6_NEIGHBOR + /* Assure the the IPv6 destination address maps to a valid MAC address in + * the neighbor table. + */ + #ifdef CONFIG_NET_ARP_SEND else #endif { + FAR const uint16_t *destipaddr; + + /* Check if the socket is connection mode */ + + if (_SS_ISCONNECTED(psock->s_flags)) + { + /* Yes.. use the connected remote address (the 'to' address is + * null). + */ + + destipaddr = conn->u.ipv6.raddr; + } + else + { + FAR const struct sockaddr_in6 *into; + + /* No.. use the destination address provided by the non-NULL 'to' + * argument. + */ + + into = (FAR const struct sockaddr_in6 *)to; + destipaddr = into->sin6_addr.s6_addr16; + } + /* Make sure that the IP address mapping is in the Neighbor Table */ - ret = icmpv6_neighbor(conn->u.ipv6.raddr); + ret = icmpv6_neighbor(destipaddr); } #endif /* CONFIG_NET_ICMPv6_NEIGHBOR */ diff --git a/net/udp/udp_psock_sendto_unbuffered.c b/net/udp/udp_psock_sendto_unbuffered.c index e0c8d516cf1..cbb41d24543 100644 --- a/net/udp/udp_psock_sendto_unbuffered.c +++ b/net/udp/udp_psock_sendto_unbuffered.c @@ -352,32 +352,87 @@ ssize_t psock_udp_sendto(FAR struct socket *psock, FAR const void *buf, return -EDESTADDRREQ; } + /* Get the underlying the UDP connection structure. */ + + conn = (FAR struct udp_conn_s *)psock->s_conn; + DEBUGASSERT(conn); + #if defined(CONFIG_NET_ARP_SEND) || defined(CONFIG_NET_ICMPv6_NEIGHBOR) #ifdef CONFIG_NET_ARP_SEND + /* Assure the the IPv4 destination address maps to a valid MAC address in + * the ARP table. + */ + #ifdef CONFIG_NET_ICMPv6_NEIGHBOR if (psock->s_domain == PF_INET) #endif { - FAR const struct sockaddr_in *into; + in_addr_t destipaddr; + + /* Check if the socket is connection mode */ + + if (_SS_ISCONNECTED(psock->s_flags)) + { + /* Yes.. use the connected remote address (the 'to' address is + * null). + */ + + destipaddr = conn->u.ipv4.raddr; + } + else + { + FAR const struct sockaddr_in *into; + + /* No.. use the destination address provided by the non-NULL 'to' + * argument. + */ + + into = (FAR const struct sockaddr_in *)to; + destipaddr = into->sin_addr.s_addr; + } /* Make sure that the IP address mapping is in the ARP table */ - into = (FAR const struct sockaddr_in *)to; - ret = arp_send(into->sin_addr.s_addr); + ret = arp_send(destipaddr); } #endif /* CONFIG_NET_ARP_SEND */ #ifdef CONFIG_NET_ICMPv6_NEIGHBOR + /* Assure the the IPv6 destination address maps to a valid MAC address in + * the neighbor table. + */ + #ifdef CONFIG_NET_ARP_SEND else #endif { - FAR const struct sockaddr_in6 *into; + FAR const uint16_t *destipaddr; + + /* Check if the socket is connection mode */ + + if (_SS_ISCONNECTED(psock->s_flags)) + { + /* Yes.. use the connected remote address (the 'to' address is + * null). + */ + + destipaddr = conn->u.ipv6.raddr; + } + else + { + FAR const struct sockaddr_in6 *into; + + /* No.. use the destination address provided by the non-NULL 'to' + * argument. + */ + + into = (FAR const struct sockaddr_in6 *)to; + destipaddr = into->sin6_addr.s6_addr16; + } /* Make sure that the IP address mapping is in the Neighbor Table */ - into = (FAR const struct sockaddr_in6 *)to; - ret = icmpv6_neighbor(into->sin6_addr.s6_addr16); + ret = icmpv6_neighbor(destipaddr); } #endif /* CONFIG_NET_ICMPv6_NEIGHBOR */ @@ -426,11 +481,6 @@ ssize_t psock_udp_sendto(FAR struct socket *psock, FAR const void *buf, state.st_time = clock_systimer(); #endif - /* Setup the UDP socket. */ - - conn = (FAR struct udp_conn_s *)psock->s_conn; - DEBUGASSERT(conn); - /* Check if the socket is connected */ if (!_SS_ISCONNECTED(psock->s_flags))