Networking: Fix accept() so that it returns the correct IP address for the selected socket IP domain.

This commit is contained in:
Gregory Nutt 2015-01-17 09:27:05 -06:00
parent a90ccb0c1c
commit 820509eadc
9 changed files with 111 additions and 78 deletions

View File

@ -90,7 +90,7 @@
#include <nuttx/net/netstats.h> #include <nuttx/net/netstats.h>
#include <nuttx/net/ip.h> #include <nuttx/net/ip.h>
#include "ipv6/ipv6.h" #include "neighbor/neighbor.h"
#include "tcp/tcp.h" #include "tcp/tcp.h"
#include "udp/udp.h" #include "udp/udp.h"
#include "pkt/pkt.h" #include "pkt/pkt.h"

View File

@ -59,7 +59,7 @@
#include "devif/devif.h" #include "devif/devif.h"
#include "utils/utils.h" #include "utils/utils.h"
#include "ipv6/ipv6.h" #include "neighbor/neighbor.h"
#include "icmpv6/icmpv6.h" #include "icmpv6/icmpv6.h"
#ifdef CONFIG_NET_ICMPv6 #ifdef CONFIG_NET_ICMPv6

View File

@ -58,7 +58,7 @@
#include "socket/socket.h" #include "socket/socket.h"
/**************************************************************************** /****************************************************************************
* Definitions * Pre-processor Definitions
****************************************************************************/ ****************************************************************************/
/**************************************************************************** /****************************************************************************
@ -67,14 +67,11 @@
struct accept_s struct accept_s
{ {
sem_t acpt_sem; /* Wait for interrupt event */ FAR struct socket *acpt_sock; /* The accepting socket */
#ifdef CONFIG_NET_IPv6 sem_t acpt_sem; /* Wait for interrupt event */
FAR struct sockaddr_in6 *acpt_addr; /* Return connection adress */ FAR struct sockaddr *acpt_addr; /* Return connection address */
#else FAR struct tcp_conn_s *acpt_newconn; /* The accepted connection */
FAR struct sockaddr_in *acpt_addr; /* Return connection adress */ int acpt_result; /* The result of the wait */
#endif
FAR struct tcp_conn_s *acpt_newconn; /* The accepted connection */
int acpt_result; /* The result of the wait */
}; };
/**************************************************************************** /****************************************************************************
@ -89,9 +86,10 @@ struct accept_s
* Function: accept_tcpsender * Function: accept_tcpsender
* *
* Description: * Description:
* Getting the sender's address from the UDP packet * Get the sender's address from the UDP packet
* *
* Parameters: * Parameters:
* psock - The state structure of the accepting socket
* conn - The newly accepted TCP connection * conn - The newly accepted TCP connection
* pstate - the recvfrom state structure * pstate - the recvfrom state structure
* *
@ -100,33 +98,50 @@ struct accept_s
* *
* Assumptions: * Assumptions:
* Running at the interrupt level * Running at the interrupt level
* *
****************************************************************************/ ****************************************************************************/
#ifdef CONFIG_NET_TCP #ifdef CONFIG_NET_TCP
static inline void accept_tcpsender(FAR struct socket *psock,
FAR struct tcp_conn_s *conn,
FAR struct sockaddr *addr)
{
if (addr)
{
#ifdef CONFIG_NET_IPv4 #ifdef CONFIG_NET_IPv4
static inline void accept_tcpsender(FAR struct tcp_conn_s *conn, #ifdef CONFIG_NET_IPv6
FAR struct sockaddr_in *addr) /* If both IPv4 and IPv6 support are enabled, then we will need to
{ * select which one to use when obtaining the sender's IP address.
if (addr) */
{
addr->sin_family = AF_INET; if (psock->s_domain == PF_INET)
addr->sin_port = conn->rport; #endif /* CONFIG_NET_IPv6 */
net_ipv4addr_copy(addr->sin_addr.s_addr, conn->u.ipv4.raddr); {
} FAR struct sockaddr_in *inaddr = (FAR struct sockaddr_in *)addr;
}
#else inaddr->sin_family = AF_INET;
static inline void accept_tcpsender(FAR struct tcp_conn_s *conn, inaddr->sin_port = conn->rport;
FAR struct sockaddr_in6 *addr) net_ipv4addr_copy(inaddr->sin_addr.s_addr, conn->u.ipv4.raddr);
{ }
if (addr)
{
addr->sin_family = AF_INET6;
addr->sin_port = conn->rport;
net_ipv6addr_copy(addr->sin6_addr.s6_addr, conn->u.ipv4.raddr);
}
}
#endif /* CONFIG_NET_IPv4 */ #endif /* CONFIG_NET_IPv4 */
#ifdef CONFIG_NET_IPv6
#ifdef CONFIG_NET_IPv4
/* Otherwise, this the IPv6 address is needed */
else
#endif /* CONFIG_NET_IPv4 */
{
FAR struct sockaddr_in6 *inaddr = (FAR struct sockaddr_in6 *)addr;
DEBUGASSERT(psock->s_domain == PF_INET6);
inaddr->sin_family = AF_INET6;
inaddr->sin_port = conn->rport;
net_ipv6addr_copy(inaddr->sin6_addr.s6_addr, conn->u.ipv6.raddr);
}
#endif /* CONFIG_NET_IPv6 */
}
}
#endif /* CONFIG_NET_TCP */ #endif /* CONFIG_NET_TCP */
/**************************************************************************** /****************************************************************************
@ -157,7 +172,7 @@ static int accept_interrupt(FAR struct tcp_conn_s *listener,
{ {
/* Get the connection address */ /* Get the connection address */
accept_tcpsender(conn, pstate->acpt_addr); accept_tcpsender(pstate->acpt_sock, conn, pstate->acpt_addr);
/* Save the connection structure */ /* Save the connection structure */
@ -256,17 +271,12 @@ static int accept_interrupt(FAR struct tcp_conn_s *listener,
* *
****************************************************************************/ ****************************************************************************/
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen) int accept(int sockfd, FAR struct sockaddr *addr, FAR socklen_t *addrlen)
{ {
FAR struct socket *psock = sockfd_socket(sockfd); FAR struct socket *psock = sockfd_socket(sockfd);
FAR struct socket *pnewsock; FAR struct socket *pnewsock;
FAR struct tcp_conn_s *conn; FAR struct tcp_conn_s *conn;
struct accept_s state; struct accept_s state;
#ifdef CONFIG_NET_IPv6
FAR struct sockaddr_in6 *inaddr = (struct sockaddr_in6 *)addr;
#else
FAR struct sockaddr_in *inaddr = (struct sockaddr_in *)addr;
#endif
net_lock_t save; net_lock_t save;
int newfd; int newfd;
int err; int err;
@ -316,13 +326,35 @@ int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
if (addr) if (addr)
{ {
#ifdef CONFIG_NET_IPv6 switch (psock->s_domain)
if (*addrlen < sizeof(struct sockaddr_in6))
#else
if (*addrlen < sizeof(struct sockaddr_in))
#endif
{ {
err = EBADF; #ifdef CONFIG_NET_IPv4
case PF_INET:
{
if (*addrlen < sizeof(struct sockaddr_in))
{
err = EBADF;
goto errout;
}
}
break;
#endif /* CONFIG_NET_IPv4 */
#ifdef CONFIG_NET_IPv6
case PF_INET:
{
if (*addrlen < sizeof(struct sockaddr_in6))
{
err = EBADF;
goto errout;
}
}
break;
#endif /* CONFIG_NET_IPv6 */
default:
DEBUGPANIC();
err = EINVAL;
goto errout; goto errout;
} }
} }
@ -359,7 +391,7 @@ int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
/* Yes... get the address of the connected client */ /* Yes... get the address of the connected client */
nvdbg("Pending conn=%p\n", state.acpt_newconn); nvdbg("Pending conn=%p\n", state.acpt_newconn);
accept_tcpsender(state.acpt_newconn, inaddr); accept_tcpsender(psock, state.acpt_newconn, addr);
} }
/* In general, this uIP-based implementation will not support non-blocking /* In general, this uIP-based implementation will not support non-blocking
@ -387,7 +419,8 @@ int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
* are ready. * are ready.
*/ */
state.acpt_addr = inaddr; state.acpt_sock = psock;
state.acpt_addr = addr;
state.acpt_newconn = NULL; state.acpt_newconn = NULL;
state.acpt_result = OK; state.acpt_result = OK;
sem_init(&state.acpt_sem, 0, 0); sem_init(&state.acpt_sem, 0, 0);

View File

@ -282,7 +282,7 @@ static inline void netclose_txnotify(FAR struct socket *psock,
* the device driver using the appropriate IP domain. * the device driver using the appropriate IP domain.
*/ */
if (psock->domain == PF_INET) if (psock->s_domain == PF_INET)
#endif #endif
{ {
/* Notify the device driver that send data is available */ /* Notify the device driver that send data is available */
@ -297,12 +297,12 @@ static inline void netclose_txnotify(FAR struct socket *psock,
#ifdef CONFIG_NET_IPv6 #ifdef CONFIG_NET_IPv6
#ifdef CONFIG_NET_IPv4 #ifdef CONFIG_NET_IPv4
else /* if (psock->domain == PF_INET6) */ else /* if (psock->s_domain == PF_INET6) */
#endif /* CONFIG_NET_IPv4 */ #endif /* CONFIG_NET_IPv4 */
{ {
/* Notify the device driver that send data is available */ /* Notify the device driver that send data is available */
DEBUGASSERT(psock->domain == PF_INET6); DEBUGASSERT(psock->s_domain == PF_INET6);
#ifdef CONFIG_NET_MULTILINK #ifdef CONFIG_NET_MULTILINK
netdev_ipv6_txnotify(conn->u.ipv6.laddr, conn->u.ipv6.raddr); netdev_ipv6_txnotify(conn->u.ipv6.laddr, conn->u.ipv6.raddr);
#else #else

View File

@ -411,7 +411,7 @@ static inline void sendfile_txnotify(FAR struct socket *psock,
* the device driver using the appropriate IP domain. * the device driver using the appropriate IP domain.
*/ */
if (psock->domain == PF_INET) if (psock->s_domain == PF_INET)
#endif #endif
{ {
/* Notify the device driver that send data is available */ /* Notify the device driver that send data is available */
@ -426,12 +426,12 @@ static inline void sendfile_txnotify(FAR struct socket *psock,
#ifdef CONFIG_NET_IPv6 #ifdef CONFIG_NET_IPv6
#ifdef CONFIG_NET_IPv4 #ifdef CONFIG_NET_IPv4
else /* if (psock->domain == PF_INET6) */ else /* if (psock->s_domain == PF_INET6) */
#endif /* CONFIG_NET_IPv4 */ #endif /* CONFIG_NET_IPv4 */
{ {
/* Notify the device driver that send data is available */ /* Notify the device driver that send data is available */
DEBUGASSERT(psock->domain == PF_INET6); DEBUGASSERT(psock->s_domain == PF_INET6);
#ifdef CONFIG_NET_MULTILINK #ifdef CONFIG_NET_MULTILINK
netdev_ipv6_txnotify(conn->u.ipv6.laddr, conn->u.ipv6.raddr); netdev_ipv6_txnotify(conn->u.ipv6.laddr, conn->u.ipv6.raddr);
#else #else

View File

@ -1086,7 +1086,7 @@ static inline void recvfrom_udp_rxnotify(FAR struct socket *psock,
* the device driver using the appropriate IP domain. * the device driver using the appropriate IP domain.
*/ */
if (psock->domain == PF_INET) if (psock->s_domain == PF_INET)
#endif #endif
{ {
/* Notify the device driver of the receive ready */ /* Notify the device driver of the receive ready */
@ -1101,12 +1101,12 @@ static inline void recvfrom_udp_rxnotify(FAR struct socket *psock,
#ifdef CONFIG_NET_IPv6 #ifdef CONFIG_NET_IPv6
#ifdef CONFIG_NET_IPv4 #ifdef CONFIG_NET_IPv4
else /* if (psock->domain == PF_INET6) */ else /* if (psock->s_domain == PF_INET6) */
#endif /* CONFIG_NET_IPv4 */ #endif /* CONFIG_NET_IPv4 */
{ {
/* Notify the device driver of the receive ready */ /* Notify the device driver of the receive ready */
DEBUGASSERT(psock->domain == PF_INET6); DEBUGASSERT(psock->s_domain == PF_INET6);
#ifdef CONFIG_NET_MULTILINK #ifdef CONFIG_NET_MULTILINK
netdev_ipv6_rxnotify(conn->u.ipv6.laddr, conn->u.ipv6.raddr); netdev_ipv6_rxnotify(conn->u.ipv6.laddr, conn->u.ipv6.raddr);
#else #else
@ -1226,10 +1226,10 @@ errout_with_state:
#ifdef CONFIG_NET_UDP #ifdef CONFIG_NET_UDP
#ifdef CONFIG_NET_IPv6 #ifdef CONFIG_NET_IPv6
static ssize_t udp_recvfrom(FAR struct socket *psock, FAR void *buf, size_t len, static ssize_t udp_recvfrom(FAR struct socket *psock, FAR void *buf, size_t len,
FAR struct sockaddr_in6 *infrom ) FAR struct sockaddr_in6 *infrom)
#else #else
static ssize_t udp_recvfrom(FAR struct socket *psock, FAR void *buf, size_t len, static ssize_t udp_recvfrom(FAR struct socket *psock, FAR void *buf, size_t len,
FAR struct sockaddr_in *infrom ) FAR struct sockaddr_in *infrom)
#endif #endif
{ {
FAR struct udp_conn_s *conn = (FAR struct udp_conn_s *)psock->s_conn; FAR struct udp_conn_s *conn = (FAR struct udp_conn_s *)psock->s_conn;

View File

@ -183,17 +183,17 @@ static inline void sendto_ipselect(FAR struct net_driver_s *dev,
/* Which domain the the socket support */ /* Which domain the the socket support */
if (psock->domain == PF_INET) if (psock->s_domain == PF_INET)
{ {
/* Select the IPv4 domain */ /* Select the IPv4 domain */
udp_ipv4_select(dev); udp_ipv4_select(dev);
} }
else /* if (psock->domain == PF_INET6) */ else /* if (psock->s_domain == PF_INET6) */
{ {
/* Select the IPv6 domain */ /* Select the IPv6 domain */
DEBUGASSERT(psock->domain == PF_INET6); DEBUGASSERT(psock->s_domain == PF_INET6);
udp_ipv4_select(dev); udp_ipv4_select(dev);
} }
} }
@ -319,7 +319,7 @@ static inline void sendto_txnotify(FAR struct socket *psock,
* the device driver using the appropriate IP domain. * the device driver using the appropriate IP domain.
*/ */
if (psock->domain == PF_INET) if (psock->s_domain == PF_INET)
#endif #endif
{ {
/* Notify the device driver that send data is available */ /* Notify the device driver that send data is available */
@ -334,12 +334,12 @@ static inline void sendto_txnotify(FAR struct socket *psock,
#ifdef CONFIG_NET_IPv6 #ifdef CONFIG_NET_IPv6
#ifdef CONFIG_NET_IPv4 #ifdef CONFIG_NET_IPv4
else /* if (psock->domain == PF_INET6) */ else /* if (psock->s_domain == PF_INET6) */
#endif /* CONFIG_NET_IPv4 */ #endif /* CONFIG_NET_IPv4 */
{ {
/* Notify the device driver that send data is available */ /* Notify the device driver that send data is available */
DEBUGASSERT(psock->domain == PF_INET6); DEBUGASSERT(psock->s_domain == PF_INET6);
#ifdef CONFIG_NET_MULTILINK #ifdef CONFIG_NET_MULTILINK
netdev_ipv6_txnotify(conn->u.ipv6.laddr, conn->u.ipv6.raddr); netdev_ipv6_txnotify(conn->u.ipv6.laddr, conn->u.ipv6.raddr);
#else #else

View File

@ -233,17 +233,17 @@ static inline void send_ipselect(FAR struct net_driver_s *dev,
{ {
/* Which domain the the socket support */ /* Which domain the the socket support */
if (psock->domain == PF_INET) if (psock->s_domain == PF_INET)
{ {
/* Select the IPv4 domain */ /* Select the IPv4 domain */
tcp_ipv4_select(dev); tcp_ipv4_select(dev);
} }
else /* if (psock->domain == PF_INET6) */ else /* if (psock->s_domain == PF_INET6) */
{ {
/* Select the IPv6 domain */ /* Select the IPv6 domain */
DEBUGASSERT(psock->domain == PF_INET6); DEBUGASSERT(psock->s_domain == PF_INET6);
tcp_ipv4_select(dev); tcp_ipv4_select(dev);
} }
} }
@ -750,7 +750,7 @@ static inline void send_txnotify(FAR struct socket *psock,
* the device driver using the appropriate IP domain. * the device driver using the appropriate IP domain.
*/ */
if (psock->domain == PF_INET) if (psock->s_domain == PF_INET)
#endif #endif
{ {
/* Notify the device driver that send data is available */ /* Notify the device driver that send data is available */
@ -765,12 +765,12 @@ static inline void send_txnotify(FAR struct socket *psock,
#ifdef CONFIG_NET_IPv6 #ifdef CONFIG_NET_IPv6
#ifdef CONFIG_NET_IPv4 #ifdef CONFIG_NET_IPv4
else /* if (psock->domain == PF_INET6) */ else /* if (psock->s_domain == PF_INET6) */
#endif /* CONFIG_NET_IPv4 */ #endif /* CONFIG_NET_IPv4 */
{ {
/* Notify the device driver that send data is available */ /* Notify the device driver that send data is available */
DEBUGASSERT(psock->domain == PF_INET6); DEBUGASSERT(psock->s_domain == PF_INET6);
#ifdef CONFIG_NET_MULTILINK #ifdef CONFIG_NET_MULTILINK
netdev_ipv6_txnotify(conn->u.ipv6.laddr, conn->u.ipv6.raddr); netdev_ipv6_txnotify(conn->u.ipv6.laddr, conn->u.ipv6.raddr);
#else #else

View File

@ -180,17 +180,17 @@ static inline void tcpsend_ipselect(FAR struct net_driver_s *dev,
/* Which domain the the socket support */ /* Which domain the the socket support */
if (psock->domain == PF_INET) if (psock->s_domain == PF_INET)
{ {
/* Select the IPv4 domain */ /* Select the IPv4 domain */
tcp_ipv4_select(dev); tcp_ipv4_select(dev);
} }
else /* if (psock->domain == PF_INET6) */ else /* if (psock->s_domain == PF_INET6) */
{ {
/* Select the IPv6 domain */ /* Select the IPv6 domain */
DEBUGASSERT(psock->domain == PF_INET6); DEBUGASSERT(psock->s_domain == PF_INET6);
tcp_ipv4_select(dev); tcp_ipv4_select(dev);
} }
} }
@ -533,7 +533,7 @@ static inline void send_txnotify(FAR struct socket *psock,
* the device driver using the appropriate IP domain. * the device driver using the appropriate IP domain.
*/ */
if (psock->domain == PF_INET) if (psock->s_domain == PF_INET)
#endif #endif
{ {
/* Notify the device driver that send data is available */ /* Notify the device driver that send data is available */
@ -548,12 +548,12 @@ static inline void send_txnotify(FAR struct socket *psock,
#ifdef CONFIG_NET_IPv6 #ifdef CONFIG_NET_IPv6
#ifdef CONFIG_NET_IPv4 #ifdef CONFIG_NET_IPv4
else /* if (psock->domain == PF_INET6) */ else /* if (psock->s_domain == PF_INET6) */
#endif /* CONFIG_NET_IPv4 */ #endif /* CONFIG_NET_IPv4 */
{ {
/* Notify the device driver that send data is available */ /* Notify the device driver that send data is available */
DEBUGASSERT(psock->domain == PF_INET6); DEBUGASSERT(psock->s_domain == PF_INET6);
#ifdef CONFIG_NET_MULTILINK #ifdef CONFIG_NET_MULTILINK
netdev_ipv6_txnotify(conn->u.ipv6.laddr, conn->u.ipv6.raddr); netdev_ipv6_txnotify(conn->u.ipv6.laddr, conn->u.ipv6.raddr);
#else #else