From 091e3f732e08dfd54359371150185cecbc1ca0e9 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Wed, 25 Apr 2018 08:43:38 -0600 Subject: [PATCH] =?UTF-8?q?net/udp:=20=20Fix=20several=20issues=20using=20?= =?UTF-8?q?connected=20UDP=20sockets:=20=20sendto()=20should=20not=20accep?= =?UTF-8?q?t=20and=20address.=20=20Normally=20send()=20should=20be=20used?= =?UTF-8?q?=20instead.=20=20recvfrom()=20is=20no=20longer=20necessary.=20?= =?UTF-8?q?=20recvfrom()=20and=20poll()=20should=20not=20reset=20to=20acce?= =?UTF-8?q?pt=20any=20addresses=20but=20should,=20instead,=20only=20accept?= =?UTF-8?q?=20inputs=20and=20events=20from=20the=20connected=20remore=20pe?= =?UTF-8?q?er.=20=20On=20of=20these=20issues=20was=20noted=20by=20?= =?UTF-8?q?=E6=9D=8E=E6=A1=82=E4=B8=81=20.=20=20Ch?= =?UTF-8?q?anges=20were=20made=20as=20summarized=20here:=20http://www.mast?= =?UTF-8?q?erraghu.com/subjects/np/introduction/unix=5Fnetwork=5Fprogrammi?= =?UTF-8?q?ng=5Fv1.3/ch08lev1sec11.html?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- configs/stm32f746g-disco/scripts/Make.defs | 1 - .../wireless/ieee802154/ieee802154_mac.h | 2 +- net/inet/inet_recvfrom.c | 20 ++++++++++++--- net/inet/inet_sockif.c | 16 +++++++++++- net/socket/socket.h | 2 +- net/udp/udp.h | 25 ++++++++++++------- net/udp/udp_conn.c | 10 +++++--- net/udp/udp_netpoll.c | 22 ++++++++++++---- net/udp/udp_psock_sendto_buffered.c | 11 ++++++++ net/udp/udp_psock_sendto_unbuffered.c | 11 ++++++++ 10 files changed, 94 insertions(+), 26 deletions(-) diff --git a/configs/stm32f746g-disco/scripts/Make.defs b/configs/stm32f746g-disco/scripts/Make.defs index 354180c1c4..17b575d7e3 100644 --- a/configs/stm32f746g-disco/scripts/Make.defs +++ b/configs/stm32f746g-disco/scripts/Make.defs @@ -92,7 +92,6 @@ else endif endif - ifeq ($(CONFIG_DEBUG_SYMBOLS),y) ARCHOPTIMIZATION = -g endif diff --git a/include/nuttx/wireless/ieee802154/ieee802154_mac.h b/include/nuttx/wireless/ieee802154/ieee802154_mac.h index 398134b696..74855ed0d6 100644 --- a/include/nuttx/wireless/ieee802154/ieee802154_mac.h +++ b/include/nuttx/wireless/ieee802154/ieee802154_mac.h @@ -595,7 +595,7 @@ struct ieee802154_pandesc_s struct ieee802154_superframespec_s sfspec; - uint8_t gtspermit; /* 0=No GTS requests allowed + uint8_t gtspermit; /* 0=No GTS requests allowed * 1=GTS request allowed */ uint8_t lqi; /* Link Quality Indication of the beacon */ uint32_t timestamp; /* Time at which the beacon frame was received diff --git a/net/inet/inet_recvfrom.c b/net/inet/inet_recvfrom.c index ea1da4b12a..5940ca2deb 100644 --- a/net/inet/inet_recvfrom.c +++ b/net/inet/inet_recvfrom.c @@ -1206,12 +1206,24 @@ static ssize_t inet_udp_recvfrom(FAR struct socket *psock, FAR void *buf, size_t net_lock(); inet_recvfrom_initialize(psock, buf, len, from, fromlen, &state); - /* Setup the UDP remote connection */ + /* If the UDP socket was previously assigned a remote peer address via + * connect(), then it is not necessary to use recvfrom() to obtain the + * address of the remote peer: UDP messages will be received only from + * the connected peer. Normally recv() would be used with such connected + * UDP sockets. + */ - ret = udp_connect(conn, NULL); - if (ret < 0) + if (!_SS_ISCONNECTED(psock->s_flags)) { - goto errout_with_state; + /* Setup the UDP remote connection to accept packets from any remote + * address. + */ + + ret = udp_connect(conn, NULL); + if (ret < 0) + { + goto errout_with_state; + } } #ifdef CONFIG_NET_UDP_READAHEAD diff --git a/net/inet/inet_sockif.c b/net/inet/inet_sockif.c index 5c81866972..b2479d6274 100644 --- a/net/inet/inet_sockif.c +++ b/net/inet/inet_sockif.c @@ -695,7 +695,21 @@ static int inet_connect(FAR struct socket *psock, #if defined(CONFIG_NET_UDP) && defined(NET_UDP_HAVE_STACK) case SOCK_DGRAM: { - int ret = udp_connect(psock->s_conn, addr); + int ret; + + /* We will accept connecting to a addr == NULL for disconnection. + * However, the correct way is to disconnect is to provide an + * address with sa_family == AF_UNSPEC. + */ + + if (addr != NULL && addr->sa_family == AF_UNSPEC) + { + addr = NULL; + } + + /* Peform the connect/disconnect operation */ + + ret = udp_connect(psock->s_conn, addr); if (ret < 0) { psock->s_flags &= ~_SF_CONNECTED; diff --git a/net/socket/socket.h b/net/socket/socket.h index 6ab75853d2..a546660dd3 100644 --- a/net/socket/socket.h +++ b/net/socket/socket.h @@ -67,7 +67,7 @@ #define _SF_LISTENING 0x10 /* Bit 4: SOCK_STREAM is listening */ #define _SF_BOUND 0x20 /* Bit 5: SOCK_STREAM is bound to an address */ /* Bits 6-7: Connection state */ -#define _SF_CONNECTED 0x40 /* Bit 6: SOCK_STREAM is connected */ +#define _SF_CONNECTED 0x40 /* Bit 6: SOCK_STREAM/SOCK_DGRAM is connected */ #define _SF_CLOSED 0x80 /* Bit 7: SOCK_STREAM was gracefully disconnected */ /* Connection state encoding: diff --git a/net/udp/udp.h b/net/udp/udp.h index 3a1b731de7..8e317ec820 100644 --- a/net/udp/udp.h +++ b/net/udp/udp.h @@ -247,21 +247,28 @@ int udp_bind(FAR struct udp_conn_s *conn, FAR const struct sockaddr *addr); * Name: udp_connect * * Description: - * This function sets up a new UDP connection. The function will - * automatically allocate an unused local port for the new - * connection. However, another port can be chosen by using the - * udp_bind() call, after the udp_connect() function has been - * called. + * This function simply assigns a remote address to UDP "connection" + * structure. This function is called as part of the implementation of: * - * This function is called as part of the implementation of sendto - * and recvfrom. + * - connect(). If connect() is called for a SOCK_DGRAM socket, then + * this logic performs the moral equivalent of connect() operation + * for the UDP socket. + * - recvfrom() and sendto(). This function is called to set the + * remote address of the peer. + * + * The function will automatically allocate an unused local port for the + * new connection if the socket is not yet bound to a local address. + * However, another port can be chosen by using the udp_bind() call, + * after the udp_connect() function has been called. * * Input Parameters: - * conn - A reference to UDP connection structure + * conn - A reference to UDP connection structure. A value of NULL will + * disconnect from any previously connected address. * addr - The address of the remote host. * * Assumptions: - * This function is called user code. Interrupts may be enabled. + * This function is called (indirectly) from user code. Interrupts may + * be enabled. * ****************************************************************************/ diff --git a/net/udp/udp_conn.c b/net/udp/udp_conn.c index 243d3afed3..2ea1c4e7a5 100644 --- a/net/udp/udp_conn.c +++ b/net/udp/udp_conn.c @@ -706,7 +706,7 @@ int udp_bind(FAR struct udp_conn_s *conn, FAR const struct sockaddr *addr) * structure. This function is called as part of the implementation of: * * - connect(). If connect() is called for a SOCK_DGRAM socket, then - * this logic performs the moral equivalent of connec() operation + * this logic performs the moral equivalent of connect() operation * for the UDP socket. * - recvfrom() and sendto(). This function is called to set the * remote address of the peer. @@ -717,11 +717,13 @@ int udp_bind(FAR struct udp_conn_s *conn, FAR const struct sockaddr *addr) * after the udp_connect() function has been called. * * Input Parameters: - * conn - A reference to UDP connection structure + * conn - A reference to UDP connection structure. A value of NULL will + * disconnect from any previously connected address. * addr - The address of the remote host. * * Assumptions: - * This function is called user code. Interrupts may be enabled. + * This function is called (indirectly) from user code. Interrupts may + * be enabled. * ****************************************************************************/ @@ -740,7 +742,7 @@ int udp_connect(FAR struct udp_conn_s *conn, FAR const struct sockaddr *addr) /* Is there a remote port (rport)? */ - if (addr) + if (addr != NULL) { #ifdef CONFIG_NET_IPv4 #ifdef CONFIG_NET_IPv6 diff --git a/net/udp/udp_netpoll.c b/net/udp/udp_netpoll.c index 70f46141a0..332de04aeb 100644 --- a/net/udp/udp_netpoll.c +++ b/net/udp/udp_netpoll.c @@ -1,7 +1,8 @@ /**************************************************************************** * net/udp/udp_netpoll.c * - * Copyright (C) 2008-2009, 2011-2015 Gregory Nutt. All rights reserved. + * Copyright (C) 2008-2009, 2011-2015, 2018 Gregory Nutt. All rights + * reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -47,6 +48,7 @@ #include #include +#include #include "udp/udp.h" #ifdef HAVE_UDP_POLL @@ -196,12 +198,22 @@ int udp_pollsetup(FAR struct socket *psock, FAR struct pollfd *fds) info->dev = udp_find_laddr_device(conn); - /* Setup the UDP remote connection */ + /* Check if the UDP socket was previously assigned a remote peer address + * via connect(). In that case, we will only be interested in poll + * related events associated with that address. + */ - ret = udp_connect(conn, NULL); - if (ret) + if (!_SS_ISCONNECTED(psock->s_flags)) { - goto errout_with_lock; + /* Setup the UDP remote connection to accept packets from any remote + * address. + */ + + ret = udp_connect(conn, NULL); + if (ret) + { + goto errout_with_lock; + } } /* Allocate a UDP callback structure */ diff --git a/net/udp/udp_psock_sendto_buffered.c b/net/udp/udp_psock_sendto_buffered.c index 82fba1c200..141fbd62ce 100644 --- a/net/udp/udp_psock_sendto_buffered.c +++ b/net/udp/udp_psock_sendto_buffered.c @@ -619,6 +619,17 @@ ssize_t psock_udp_sendto(FAR struct socket *psock, FAR const void *buf, FAR struct udp_wrbuffer_s *wrb; int ret = OK; + /* If the UDP socket was previously assigned a remote peer address via + * connect(), then as with connection-mode socket, sendto() may not be + * used with a non-NULL destination address. Normally send() would be + * used with such connected UDP sockets. + */ + + if (to != NULL && _SS_ISCONNECTED(psock->s_flags)) + { + return -EISCONN; + } + /* Make sure that we have the IP address mapping */ conn = (FAR struct udp_conn_s *)psock->s_conn; diff --git a/net/udp/udp_psock_sendto_unbuffered.c b/net/udp/udp_psock_sendto_unbuffered.c index 707e00ce3e..8ac9a22450 100644 --- a/net/udp/udp_psock_sendto_unbuffered.c +++ b/net/udp/udp_psock_sendto_unbuffered.c @@ -324,6 +324,17 @@ ssize_t psock_udp_sendto(FAR struct socket *psock, FAR const void *buf, struct sendto_s state; int ret; + /* If the UDP socket was previously assigned a remote peer address via + * connect(), then as with connection-mode socket, sendto() may not be + * used with a non-NULL destination address. Normally send() would be + * used with such connected UDP sockets. + */ + + if (to != NULL && _SS_ISCONNECTED(psock->s_flags)) + { + return -EISCONN; + } + #if defined(CONFIG_NET_ARP_SEND) || defined(CONFIG_NET_ICMPv6_NEIGHBOR) #ifdef CONFIG_NET_ARP_SEND #ifdef CONFIG_NET_ICMPv6_NEIGHBOR