diff --git a/net/udp/udp_psock_send.c b/net/udp/udp_psock_send.c index 4c5ee0cf859..a89153aaddd 100644 --- a/net/udp/udp_psock_send.c +++ b/net/udp/udp_psock_send.c @@ -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 * * 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); } diff --git a/net/udp/udp_psock_sendto_buffered.c b/net/udp/udp_psock_sendto_buffered.c index 141fbd62ce6..5e7ef7054cf 100644 --- a/net/udp/udp_psock_sendto_buffered.c +++ b/net/udp/udp_psock_sendto_buffered.c @@ -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 diff --git a/net/udp/udp_psock_sendto_unbuffered.c b/net/udp/udp_psock_sendto_unbuffered.c index 8ac9a224505..d9cccbc1fed 100644 --- a/net/udp/udp_psock_sendto_unbuffered.c +++ b/net/udp/udp_psock_sendto_unbuffered.c @@ -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