net/udp: Fix several issues using connected UDP sockets: sendto() should not accept and address. Normally send() should be used instead. recvfrom() is no longer necessary. recvfrom() and poll() should not reset to accept any addresses but should, instead, only accept inputs and events from the connected remore peer. On of these issues was noted by 李桂丁 <liguiding@pinecone.net>. Changes were made as summarized here: http://www.masterraghu.com/subjects/np/introduction/unix_network_programming_v1.3/ch08lev1sec11.html

This commit is contained in:
Gregory Nutt 2018-04-25 08:43:38 -06:00
parent 31e3f208b2
commit 091e3f732e
10 changed files with 94 additions and 26 deletions

View File

@ -92,7 +92,6 @@ else
endif
endif
ifeq ($(CONFIG_DEBUG_SYMBOLS),y)
ARCHOPTIMIZATION = -g
endif

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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:

View File

@ -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.
*
****************************************************************************/

View File

@ -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

View File

@ -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 <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@ -47,6 +48,7 @@
#include <nuttx/net/net.h>
#include <devif/devif.h>
#include <socket/socket.h>
#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 */

View File

@ -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;

View File

@ -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