Socket interface: Added getsockname[C() interfaces.
This commit is contained in:
parent
ac72978072
commit
ac543648b8
@ -116,6 +116,8 @@ struct sock_intf_s
|
|||||||
CODE void (*si_addref)(FAR struct socket *psock);
|
CODE void (*si_addref)(FAR struct socket *psock);
|
||||||
CODE int (*si_bind)(FAR struct socket *psock,
|
CODE int (*si_bind)(FAR struct socket *psock,
|
||||||
FAR const struct sockaddr *addr, socklen_t addrlen);
|
FAR const struct sockaddr *addr, socklen_t addrlen);
|
||||||
|
CODE int (*si_getsockname)(FAR struct socket *psock,
|
||||||
|
FAR struct sockaddr *addr, FAR socklen_t *addrlen);
|
||||||
CODE int (*si_listen)(FAR struct socket *psock, int backlog);
|
CODE int (*si_listen)(FAR struct socket *psock, int backlog);
|
||||||
CODE int (*si_connect)(FAR struct socket *psock,
|
CODE int (*si_connect)(FAR struct socket *psock,
|
||||||
FAR const struct sockaddr *addr, socklen_t addrlen);
|
FAR const struct sockaddr *addr, socklen_t addrlen);
|
||||||
|
@ -69,8 +69,8 @@ int psock_local_bind(FAR struct socket *psock,
|
|||||||
(FAR const struct sockaddr_un *)addr;
|
(FAR const struct sockaddr_un *)addr;
|
||||||
int namelen;
|
int namelen;
|
||||||
|
|
||||||
DEBUGASSERT(psock && psock->s_conn && unaddr &&
|
DEBUGASSERT(psock != NULL && psock->s_conn != NULL &&
|
||||||
unaddr->sun_family == AF_LOCAL &&
|
unaddr != NULL && unaddr->sun_family == AF_LOCAL &&
|
||||||
addrlen >= sizeof(sa_family_t));
|
addrlen >= sizeof(sa_family_t));
|
||||||
|
|
||||||
conn = (FAR struct local_conn_s *)psock->s_conn;
|
conn = (FAR struct local_conn_s *)psock->s_conn;
|
||||||
@ -79,7 +79,7 @@ int psock_local_bind(FAR struct socket *psock,
|
|||||||
|
|
||||||
conn->lc_proto = psock->s_type;
|
conn->lc_proto = psock->s_type;
|
||||||
|
|
||||||
/* No determine the type of the Unix domain socket by comparing the size
|
/* Now determine the type of the Unix domain socket by comparing the size
|
||||||
* of the address description.
|
* of the address description.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -63,6 +63,8 @@ static sockcaps_t local_sockcaps(FAR struct socket *psock);
|
|||||||
static void local_addref(FAR struct socket *psock);
|
static void local_addref(FAR struct socket *psock);
|
||||||
static int local_bind(FAR struct socket *psock,
|
static int local_bind(FAR struct socket *psock,
|
||||||
FAR const struct sockaddr *addr, socklen_t addrlen);
|
FAR const struct sockaddr *addr, socklen_t addrlen);
|
||||||
|
static int local_getsockname(FAR struct socket *psock,
|
||||||
|
FAR struct sockaddr *addr, FAR socklen_t *addrlen);
|
||||||
static int local_connect(FAR struct socket *psock,
|
static int local_connect(FAR struct socket *psock,
|
||||||
FAR const struct sockaddr *addr, socklen_t addrlen);
|
FAR const struct sockaddr *addr, socklen_t addrlen);
|
||||||
static ssize_t local_send(FAR struct socket *psock, FAR const void *buf,
|
static ssize_t local_send(FAR struct socket *psock, FAR const void *buf,
|
||||||
@ -82,6 +84,7 @@ const struct sock_intf_s g_local_sockif =
|
|||||||
local_sockcaps, /* si_sockcaps */
|
local_sockcaps, /* si_sockcaps */
|
||||||
local_addref, /* si_addref */
|
local_addref, /* si_addref */
|
||||||
local_bind, /* si_bind */
|
local_bind, /* si_bind */
|
||||||
|
local_getsockname, /* si_getsockname */
|
||||||
local_listen, /* si_listen */
|
local_listen, /* si_listen */
|
||||||
local_connect, /* si_connect */
|
local_connect, /* si_connect */
|
||||||
local_accept, /* si_accept */
|
local_accept, /* si_accept */
|
||||||
@ -303,6 +306,87 @@ static int local_bind(FAR struct socket *psock,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: local_getsockname
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* The local_getsockname() function retrieves the locally-bound name of
|
||||||
|
* the specified local socket, stores this address in the sockaddr
|
||||||
|
* structure pointed to by the 'addr' argument, and stores the length of
|
||||||
|
* this address in the object pointed to by the 'addrlen' argument.
|
||||||
|
*
|
||||||
|
* If the actual length of the address is greater than the length of the
|
||||||
|
* supplied sockaddr structure, the stored address will be truncated.
|
||||||
|
*
|
||||||
|
* If the socket has not been bound to a local name, the value stored in
|
||||||
|
* the object pointed to by address is unspecified.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* psock Socket structure of the socket to be queried
|
||||||
|
* addr sockaddr structure to receive data [out]
|
||||||
|
* addrlen Length of sockaddr structure [in/out]
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* On success, 0 is returned, the 'addr' argument points to the address
|
||||||
|
* of the socket, and the 'addrlen' argument points to the length of the
|
||||||
|
* address. Otherwise, a negated errno value is returned. See
|
||||||
|
* getsockname() for the list of appropriate error numbers.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static int local_getsockname(FAR struct socket *psock,
|
||||||
|
FAR struct sockaddr *addr,
|
||||||
|
FAR socklen_t *addrlen)
|
||||||
|
{
|
||||||
|
FAR const struct sockaddr_un *unaddr =
|
||||||
|
(FAR const struct sockaddr_un *)addr;
|
||||||
|
FAR struct local_conn_s *conn;
|
||||||
|
|
||||||
|
DEBUGASSERT(psock != NULL && psock->s_conn != NULL &&
|
||||||
|
unaddr != NULL && addrlen != NULL &&
|
||||||
|
*addrlen >= sizeof(sa_family_t));
|
||||||
|
|
||||||
|
if (*addrlen < sizeof(sa_family_t))
|
||||||
|
{
|
||||||
|
/* This is apparently not an error */
|
||||||
|
|
||||||
|
*addrlen = 0;
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
conn = (FAR struct local_conn_s *)psock->s_conn;
|
||||||
|
|
||||||
|
/* Save the address family */
|
||||||
|
|
||||||
|
unaddr->sun_family = AF_LOCAL;
|
||||||
|
if (*addrlen > sizeof(sa_family_t))
|
||||||
|
{
|
||||||
|
/* Now copy the address description. */
|
||||||
|
|
||||||
|
if (conn->lc_type == LOCAL_TYPE_UNNAMED)
|
||||||
|
{
|
||||||
|
/* Zero-length sun_path... This is an abstract Unix domain socket */
|
||||||
|
|
||||||
|
*addrlen = sizeof(sa_family_t);
|
||||||
|
}
|
||||||
|
else /* conn->lctype = LOCAL_TYPE_PATHNAME */
|
||||||
|
{
|
||||||
|
/* Get the available length in the user-provided buffer. */
|
||||||
|
|
||||||
|
int pathlen = *addrlen - sizeof(sa_family_t);
|
||||||
|
|
||||||
|
/* Copy the path into the user address structure */
|
||||||
|
|
||||||
|
(void)strncpy(unaddr->sun_path, conn->lc_path, pathlen);
|
||||||
|
unaddr->sun_path[pathlen - 1] = '\0';
|
||||||
|
|
||||||
|
*addrlen = sizeof(sa_family_t) + namelen;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: local_connect
|
* Name: local_connect
|
||||||
*
|
*
|
||||||
|
@ -63,6 +63,8 @@ static sockcaps_t pkt_sockcaps(FAR struct socket *psock);
|
|||||||
static void pkt_addref(FAR struct socket *psock);
|
static void pkt_addref(FAR struct socket *psock);
|
||||||
static int pkt_bind(FAR struct socket *psock,
|
static int pkt_bind(FAR struct socket *psock,
|
||||||
FAR const struct sockaddr *addr, socklen_t addrlen);
|
FAR const struct sockaddr *addr, socklen_t addrlen);
|
||||||
|
static int pkt_getsockname(FAR struct socket *psock,
|
||||||
|
FAR struct sockaddr *addr, FAR socklen_t *addrlen);
|
||||||
static int pkt_listen(FAR struct socket *psock, int backlog);
|
static int pkt_listen(FAR struct socket *psock, int backlog);
|
||||||
static int pkt_connect(FAR struct socket *psock,
|
static int pkt_connect(FAR struct socket *psock,
|
||||||
FAR const struct sockaddr *addr, socklen_t addrlen);
|
FAR const struct sockaddr *addr, socklen_t addrlen);
|
||||||
@ -85,6 +87,7 @@ const struct sock_intf_s g_pkt_sockif =
|
|||||||
pkt_sockcaps, /* si_sockcaps */
|
pkt_sockcaps, /* si_sockcaps */
|
||||||
pkt_addref, /* si_addref */
|
pkt_addref, /* si_addref */
|
||||||
pkt_bind, /* si_bind */
|
pkt_bind, /* si_bind */
|
||||||
|
pkt_getsockname, /* si_getsockname */
|
||||||
pkt_listen, /* si_listen */
|
pkt_listen, /* si_listen */
|
||||||
pkt_connect, /* si_connect */
|
pkt_connect, /* si_connect */
|
||||||
pkt_accept, /* si_accept */
|
pkt_accept, /* si_accept */
|
||||||
@ -378,6 +381,40 @@ static int pkt_bind(FAR struct socket *psock, FAR const struct sockaddr *addr,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: pkt_getsockname
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* The pkt_getsockname() function retrieves the locally-bound name of the
|
||||||
|
* specified packet socket, stores this address in the sockaddr structure
|
||||||
|
* pointed to by the 'addr' argument, and stores the length of this
|
||||||
|
* address in the object pointed to by the 'addrlen' argument.
|
||||||
|
*
|
||||||
|
* If the actual length of the address is greater than the length of the
|
||||||
|
* supplied sockaddr structure, the stored address will be truncated.
|
||||||
|
*
|
||||||
|
* If the socket has not been bound to a local name, the value stored in
|
||||||
|
* the object pointed to by address is unspecified.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* psock Socket structure of the socket to be queried
|
||||||
|
* addr sockaddr structure to receive data [out]
|
||||||
|
* addrlen Length of sockaddr structure [in/out]
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* On success, 0 is returned, the 'addr' argument points to the address
|
||||||
|
* of the socket, and the 'addrlen' argument points to the length of the
|
||||||
|
* address. Otherwise, a negated errno value is returned. See
|
||||||
|
* getsockname() for the list of appropriate error numbers.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static int pkt_getsockname(FAR struct socket *psock,
|
||||||
|
FAR struct sockaddr *addr, FAR socklen_t *addrlen)
|
||||||
|
{
|
||||||
|
return -EAFNOSUPPORT;
|
||||||
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: pkt_listen
|
* Name: pkt_listen
|
||||||
*
|
*
|
||||||
|
@ -49,6 +49,14 @@ else ifeq ($(CONFIG_NET_IPv6),y)
|
|||||||
SOCK_CSRCS += inet_sockif.c inet_recvfrom.c inet_connect.c inet_close.c
|
SOCK_CSRCS += inet_sockif.c inet_recvfrom.c inet_connect.c inet_close.c
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifeq ($(CONFIG_NET_IPv4),y)
|
||||||
|
SOCK_CSRCS += ipv4_getsockname.c
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(CONFIG_NET_IPv6),y)
|
||||||
|
SOCK_CSRCS += ipv6_getsockname.c
|
||||||
|
endif
|
||||||
|
|
||||||
# TCP/IP support
|
# TCP/IP support
|
||||||
|
|
||||||
ifeq ($(CONFIG_NET_TCP),y)
|
ifeq ($(CONFIG_NET_TCP),y)
|
||||||
|
@ -47,308 +47,11 @@
|
|||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
#include <nuttx/net/net.h>
|
#include <nuttx/net/net.h>
|
||||||
#include <nuttx/net/netdev.h>
|
|
||||||
#include <nuttx/net/udp.h>
|
|
||||||
|
|
||||||
#include "utils/utils.h"
|
|
||||||
#include "netdev/netdev.h"
|
|
||||||
#include "tcp/tcp.h"
|
|
||||||
#include "udp/udp.h"
|
|
||||||
#include "socket/socket.h"
|
#include "socket/socket.h"
|
||||||
#include "usrsock/usrsock.h"
|
|
||||||
|
|
||||||
#ifdef CONFIG_NET
|
#ifdef CONFIG_NET
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* Private Functions
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* Name: get_ipv4_sockname
|
|
||||||
*
|
|
||||||
* Description:
|
|
||||||
* The getsockname() function retrieves the locally-bound name of the
|
|
||||||
* specified PF_NET socket.
|
|
||||||
*
|
|
||||||
* Parameters:
|
|
||||||
* psock Point to the socket structure instance [in]
|
|
||||||
* addr sockaddr structure to receive data [out]
|
|
||||||
* addrlen Length of sockaddr structure [in/out]
|
|
||||||
*
|
|
||||||
* Returned Value:
|
|
||||||
* On success, 0 is returned, the 'addr' argument points to the address
|
|
||||||
* of the socket, and the 'addrlen' argument points to the length of the
|
|
||||||
* address. Otherwise, -1 is returned and errno is set to indicate the error.
|
|
||||||
* Possible errno values that may be returned include:
|
|
||||||
*
|
|
||||||
* EBADF - The socket argument is not a valid file descriptor.
|
|
||||||
* EOPNOTSUPP - The operation is not supported for this socket's protocol.
|
|
||||||
* EINVAL - The socket has been shut down.
|
|
||||||
*
|
|
||||||
* Assumptions:
|
|
||||||
*
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
#ifdef CONFIG_NET_IPv4
|
|
||||||
int ipv4_getsockname(FAR struct socket *psock, FAR struct sockaddr *addr,
|
|
||||||
FAR socklen_t *addrlen)
|
|
||||||
{
|
|
||||||
FAR struct net_driver_s *dev;
|
|
||||||
#if defined(NET_TCP_HAVE_STACK) || defined(NET_UDP_HAVE_STACK)
|
|
||||||
FAR struct sockaddr_in *outaddr = (FAR struct sockaddr_in *)addr;
|
|
||||||
#endif
|
|
||||||
#ifdef CONFIG_NETDEV_MULTINIC
|
|
||||||
in_addr_t lipaddr;
|
|
||||||
in_addr_t ripaddr;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Check if enough space has been provided for the full address */
|
|
||||||
|
|
||||||
if (*addrlen < sizeof(struct sockaddr_in))
|
|
||||||
{
|
|
||||||
/* This function is supposed to return the partial address if
|
|
||||||
* a smaller buffer has been provided. This support has not
|
|
||||||
* been implemented.
|
|
||||||
*/
|
|
||||||
|
|
||||||
return -ENOSYS;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set the port number */
|
|
||||||
|
|
||||||
switch (psock->s_type)
|
|
||||||
{
|
|
||||||
#ifdef NET_TCP_HAVE_STACK
|
|
||||||
case SOCK_STREAM:
|
|
||||||
{
|
|
||||||
FAR struct tcp_conn_s *tcp_conn = (FAR struct tcp_conn_s *)psock->s_conn;
|
|
||||||
outaddr->sin_port = tcp_conn->lport; /* Already in network byte order */
|
|
||||||
#ifdef CONFIG_NETDEV_MULTINIC
|
|
||||||
lipaddr = tcp_conn->u.ipv4.laddr;
|
|
||||||
ripaddr = tcp_conn->u.ipv4.raddr;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef NET_UDP_HAVE_STACK
|
|
||||||
case SOCK_DGRAM:
|
|
||||||
{
|
|
||||||
FAR struct udp_conn_s *udp_conn = (FAR struct udp_conn_s *)psock->s_conn;
|
|
||||||
outaddr->sin_port = udp_conn->lport; /* Already in network byte order */
|
|
||||||
#ifdef CONFIG_NETDEV_MULTINIC
|
|
||||||
lipaddr = udp_conn->u.ipv4.laddr;
|
|
||||||
ripaddr = udp_conn->u.ipv4.raddr;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
default:
|
|
||||||
return -EOPNOTSUPP;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef CONFIG_NETDEV_MULTINIC
|
|
||||||
/* The socket/connection does not know its IP address unless
|
|
||||||
* CONFIG_NETDEV_MULTINIC is selected. Otherwise the design supports only
|
|
||||||
* a single network device and only the network device knows the IP address.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (lipaddr == 0)
|
|
||||||
{
|
|
||||||
#if defined(CONFIG_NET_TCP) || defined(CONFIG_NET_UDP)
|
|
||||||
outaddr->sin_family = AF_INET;
|
|
||||||
outaddr->sin_addr.s_addr = 0;
|
|
||||||
*addrlen = sizeof(struct sockaddr_in);
|
|
||||||
#endif
|
|
||||||
return OK;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
net_lock();
|
|
||||||
|
|
||||||
#ifdef CONFIG_NETDEV_MULTINIC
|
|
||||||
/* Find the device matching the IPv4 address in the connection structure.
|
|
||||||
* NOTE: listening sockets have no ripaddr. Work around is to use the
|
|
||||||
* lipaddr when ripaddr is not available.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (ripaddr == 0)
|
|
||||||
{
|
|
||||||
ripaddr = lipaddr;
|
|
||||||
}
|
|
||||||
|
|
||||||
dev = netdev_findby_ipv4addr(lipaddr, ripaddr);
|
|
||||||
#else
|
|
||||||
/* There is only one, the first network device in the list. */
|
|
||||||
|
|
||||||
dev = g_netdevices;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (!dev)
|
|
||||||
{
|
|
||||||
net_unlock();
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set the address family and the IP address */
|
|
||||||
|
|
||||||
#if defined(NET_TCP_HAVE_STACK) || defined(NET_UDP_HAVE_STACK)
|
|
||||||
outaddr->sin_family = AF_INET;
|
|
||||||
outaddr->sin_addr.s_addr = dev->d_ipaddr;
|
|
||||||
*addrlen = sizeof(struct sockaddr_in);
|
|
||||||
#endif
|
|
||||||
net_unlock();
|
|
||||||
|
|
||||||
/* Return success */
|
|
||||||
|
|
||||||
return OK;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* Name: ipv6_getsockname
|
|
||||||
*
|
|
||||||
* Description:
|
|
||||||
* The getsockname() function retrieves the locally-bound name of the
|
|
||||||
* specified PF_NET6 socket.
|
|
||||||
*
|
|
||||||
* Parameters:
|
|
||||||
* psock Point to the socket structure instance [in]
|
|
||||||
* addr sockaddr structure to receive data [out]
|
|
||||||
* addrlen Length of sockaddr structure [in/out]
|
|
||||||
*
|
|
||||||
* Returned Value:
|
|
||||||
* On success, 0 is returned, the 'addr' argument points to the address
|
|
||||||
* of the socket, and the 'addrlen' argument points to the length of the
|
|
||||||
* address. Otherwise, -1 is returned and errno is set to indicate the error.
|
|
||||||
* Possible errno values that may be returned include:
|
|
||||||
*
|
|
||||||
* EBADF - The socket argument is not a valid file descriptor.
|
|
||||||
* EOPNOTSUPP - The operation is not supported for this socket's protocol.
|
|
||||||
* EINVAL - The socket has been shut down.
|
|
||||||
*
|
|
||||||
* Assumptions:
|
|
||||||
*
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
#ifdef CONFIG_NET_IPv6
|
|
||||||
int ipv6_getsockname(FAR struct socket *psock, FAR struct sockaddr *addr,
|
|
||||||
FAR socklen_t *addrlen)
|
|
||||||
{
|
|
||||||
FAR struct net_driver_s *dev;
|
|
||||||
#if defined(NET_TCP_HAVE_STACK) || defined(NET_UDP_HAVE_STACK)
|
|
||||||
FAR struct sockaddr_in6 *outaddr = (FAR struct sockaddr_in6 *)addr;
|
|
||||||
#endif
|
|
||||||
#ifdef CONFIG_NETDEV_MULTINIC
|
|
||||||
net_ipv6addr_t *lipaddr;
|
|
||||||
net_ipv6addr_t *ripaddr;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Check if enough space has been provided for the full address */
|
|
||||||
|
|
||||||
if (*addrlen < sizeof(struct sockaddr_in6))
|
|
||||||
{
|
|
||||||
/* This function is supposed to return the partial address if
|
|
||||||
* a smaller buffer has been provided. This support has not
|
|
||||||
* been implemented.
|
|
||||||
*/
|
|
||||||
|
|
||||||
return -ENOSYS;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set the port number */
|
|
||||||
|
|
||||||
switch (psock->s_type)
|
|
||||||
{
|
|
||||||
#ifdef NET_TCP_HAVE_STACK
|
|
||||||
case SOCK_STREAM:
|
|
||||||
{
|
|
||||||
FAR struct tcp_conn_s *tcp_conn = (FAR struct tcp_conn_s *)psock->s_conn;
|
|
||||||
outaddr->sin6_port = tcp_conn->lport; /* Already in network byte order */
|
|
||||||
#ifdef CONFIG_NETDEV_MULTINIC
|
|
||||||
lipaddr = &tcp_conn->u.ipv6.laddr;
|
|
||||||
ripaddr = &tcp_conn->u.ipv6.raddr;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef NET_UDP_HAVE_STACK
|
|
||||||
case SOCK_DGRAM:
|
|
||||||
{
|
|
||||||
FAR struct udp_conn_s *udp_conn = (FAR struct udp_conn_s *)psock->s_conn;
|
|
||||||
outaddr->sin6_port = udp_conn->lport; /* Already in network byte order */
|
|
||||||
#ifdef CONFIG_NETDEV_MULTINIC
|
|
||||||
lipaddr = &udp_conn->u.ipv6.laddr;
|
|
||||||
ripaddr = &udp_conn->u.ipv6.raddr;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
default:
|
|
||||||
return -EOPNOTSUPP;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef CONFIG_NETDEV_MULTINIC
|
|
||||||
/* The socket/connection does not know its IP address unless
|
|
||||||
* CONFIG_NETDEV_MULTINIC is selected. Otherwise the design supports only
|
|
||||||
* a single network device and only the network device knows the IP address.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (net_ipv6addr_cmp(lipaddr, g_ipv6_allzeroaddr))
|
|
||||||
{
|
|
||||||
#if defined(NET_TCP_HAVE_STACK) || defined(NET_UDP_HAVE_STACK)
|
|
||||||
outaddr->sin6_family = AF_INET6;
|
|
||||||
memcpy(outaddr->sin6_addr.in6_u.u6_addr8, g_ipv6_allzeroaddr, 16);
|
|
||||||
*addrlen = sizeof(struct sockaddr_in6);
|
|
||||||
#endif
|
|
||||||
return OK;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
net_lock();
|
|
||||||
|
|
||||||
#ifdef CONFIG_NETDEV_MULTINIC
|
|
||||||
/* Find the device matching the IPv6 address in the connection structure.
|
|
||||||
* NOTE: listening sockets have no ripaddr. Work around is to use the
|
|
||||||
* lipaddr when ripaddr is not available.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (net_ipv6addr_cmp(ripaddr, g_ipv6_allzeroaddr))
|
|
||||||
{
|
|
||||||
ripaddr = lipaddr;
|
|
||||||
}
|
|
||||||
|
|
||||||
dev = netdev_findby_ipv6addr(*lipaddr, *ripaddr);
|
|
||||||
#else
|
|
||||||
/* There is only one, the first network device in the list. */
|
|
||||||
|
|
||||||
dev = g_netdevices;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (!dev)
|
|
||||||
{
|
|
||||||
net_unlock();
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set the address family and the IP address */
|
|
||||||
|
|
||||||
#if defined(NET_TCP_HAVE_STACK) || defined(NET_UDP_HAVE_STACK)
|
|
||||||
outaddr->sin6_family = AF_INET6;
|
|
||||||
memcpy(outaddr->sin6_addr.in6_u.u6_addr8, dev->d_ipv6addr, 16);
|
|
||||||
*addrlen = sizeof(struct sockaddr_in6);
|
|
||||||
#endif
|
|
||||||
net_unlock();
|
|
||||||
|
|
||||||
/* Return success */
|
|
||||||
|
|
||||||
return OK;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Public Functions
|
* Public Functions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
@ -380,10 +83,11 @@ int ipv6_getsockname(FAR struct socket *psock, FAR struct sockaddr *addr,
|
|||||||
* Possible errno values that may be returned include:
|
* Possible errno values that may be returned include:
|
||||||
*
|
*
|
||||||
* EBADF - The socket argument is not a valid file descriptor.
|
* EBADF - The socket argument is not a valid file descriptor.
|
||||||
|
* ENOTSOCK - The socket argument does not refer to a socket.
|
||||||
* EOPNOTSUPP - The operation is not supported for this socket's protocol.
|
* EOPNOTSUPP - The operation is not supported for this socket's protocol.
|
||||||
* EINVAL - The socket has been shut down.
|
* EINVAL - The socket has been shut down.
|
||||||
*
|
* ENOBUFS - Insufficient resources were available in the system to
|
||||||
* Assumptions:
|
* complete the function.
|
||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
@ -395,7 +99,7 @@ int getsockname(int sockfd, FAR struct sockaddr *addr, FAR socklen_t *addrlen)
|
|||||||
|
|
||||||
/* Verify that the sockfd corresponds to valid, allocated socket */
|
/* Verify that the sockfd corresponds to valid, allocated socket */
|
||||||
|
|
||||||
if (!psock || psock->s_crefs <= 0)
|
if (psock == NULL || psock->s_crefs <= 0)
|
||||||
{
|
{
|
||||||
errcode = EBADF;
|
errcode = EBADF;
|
||||||
goto errout;
|
goto errout;
|
||||||
@ -406,54 +110,19 @@ int getsockname(int sockfd, FAR struct sockaddr *addr, FAR socklen_t *addrlen)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef CONFIG_DEBUG_FEATURES
|
#ifdef CONFIG_DEBUG_FEATURES
|
||||||
if (!addr || !addrlen)
|
if (addr == NULL || addrlen <= 0)
|
||||||
{
|
{
|
||||||
errcode = EINVAL;
|
errcode = EINVAL;
|
||||||
goto errout;
|
goto errout;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_NET_USRSOCK
|
/* Let the address family's send() method handle the operation */
|
||||||
if (psock->s_type == SOCK_USRSOCK_TYPE)
|
|
||||||
{
|
|
||||||
FAR struct usrsock_conn_s *conn = psock->s_conn;
|
|
||||||
|
|
||||||
DEBUGASSERT(conn);
|
DEBUGASSERT(psock->s_sockif != NULL &&
|
||||||
|
psock->s_sockif->si_getsockname != NULL);
|
||||||
|
|
||||||
/* Handle usrsock getsockname */
|
ret = psock->s_sockif->si_getsockname(psock, addr, addrlen);
|
||||||
|
|
||||||
ret = usrsock_getsockname(conn, addr, addrlen);
|
|
||||||
if (ret < 0)
|
|
||||||
{
|
|
||||||
errcode = -ret;
|
|
||||||
goto errout;
|
|
||||||
}
|
|
||||||
|
|
||||||
return OK;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Handle by address domain */
|
|
||||||
|
|
||||||
switch (psock->s_domain)
|
|
||||||
{
|
|
||||||
#ifdef CONFIG_NET_IPv4
|
|
||||||
case PF_INET:
|
|
||||||
ret = ipv4_getsockname(psock, addr, addrlen);
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef CONFIG_NET_IPv6
|
|
||||||
case PF_INET6:
|
|
||||||
ret = ipv6_getsockname(psock, addr, addrlen);
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
case PF_PACKET:
|
|
||||||
default:
|
|
||||||
errcode = EAFNOSUPPORT;
|
|
||||||
goto errout;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check for failure */
|
/* Check for failure */
|
||||||
|
|
||||||
|
@ -63,6 +63,8 @@ static sockcaps_t inet_sockcaps(FAR struct socket *psock);
|
|||||||
static void inet_addref(FAR struct socket *psock);
|
static void inet_addref(FAR struct socket *psock);
|
||||||
static int inet_bind(FAR struct socket *psock,
|
static int inet_bind(FAR struct socket *psock,
|
||||||
FAR const struct sockaddr *addr, socklen_t addrlen);
|
FAR const struct sockaddr *addr, socklen_t addrlen);
|
||||||
|
static int inet_getsockname(FAR struct socket *psock,
|
||||||
|
FAR struct sockaddr *addr, FAR socklen_t *addrlen);
|
||||||
static int inet_listen(FAR struct socket *psock, int backlog);
|
static int inet_listen(FAR struct socket *psock, int backlog);
|
||||||
static int inet_accept(FAR struct socket *psock,
|
static int inet_accept(FAR struct socket *psock,
|
||||||
FAR struct sockaddr *addr, FAR socklen_t *addrlen,
|
FAR struct sockaddr *addr, FAR socklen_t *addrlen,
|
||||||
@ -83,6 +85,7 @@ const struct sock_intf_s g_inet_sockif =
|
|||||||
inet_sockcaps, /* si_sockcaps */
|
inet_sockcaps, /* si_sockcaps */
|
||||||
inet_addref, /* si_addref */
|
inet_addref, /* si_addref */
|
||||||
inet_bind, /* si_bind */
|
inet_bind, /* si_bind */
|
||||||
|
inet_getsockname, /* si_getsockname */
|
||||||
inet_listen, /* si_listen */
|
inet_listen, /* si_listen */
|
||||||
inet_connect, /* si_connect */
|
inet_connect, /* si_connect */
|
||||||
inet_accept, /* si_accept */
|
inet_accept, /* si_accept */
|
||||||
@ -544,6 +547,72 @@ static int inet_bind(FAR struct socket *psock,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: inet_getsockname
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* The inet_getsockname() function retrieves the locally-bound name of
|
||||||
|
* the specified INET socket, stores this address in the sockaddr
|
||||||
|
* structure pointed to by the 'addr' argument, and stores the length of
|
||||||
|
* this address in the object pointed to by the 'addrlen' argument.
|
||||||
|
*
|
||||||
|
* If the actual length of the address is greater than the length of the
|
||||||
|
* supplied sockaddr structure, the stored address will be truncated.
|
||||||
|
*
|
||||||
|
* If the socket has not been bound to a local name, the value stored in
|
||||||
|
* the object pointed to by address is unspecified.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* psock Socket structure of the socket to be queried
|
||||||
|
* addr sockaddr structure to receive data [out]
|
||||||
|
* addrlen Length of sockaddr structure [in/out]
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* On success, 0 is returned, the 'addr' argument points to the address
|
||||||
|
* of the socket, and the 'addrlen' argument points to the length of the
|
||||||
|
* address. Otherwise, a negated errno value is returned. See
|
||||||
|
* getsockname() for the list of appropriate error numbers.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static int inet_getsockname(FAR struct socket *psock,
|
||||||
|
FAR struct sockaddr *addr,
|
||||||
|
FAR socklen_t *addrlen)
|
||||||
|
{
|
||||||
|
#ifdef CONFIG_NET_USRSOCK
|
||||||
|
if (psock->s_type == SOCK_USRSOCK_TYPE)
|
||||||
|
{
|
||||||
|
FAR struct usrsock_conn_s *conn = psock->s_conn;
|
||||||
|
|
||||||
|
DEBUGASSERT(conn != NULL);
|
||||||
|
|
||||||
|
/* Handle usrsock getsockname */
|
||||||
|
|
||||||
|
return usrsock_getsockname(conn, addr, addrlen);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Handle by address domain */
|
||||||
|
|
||||||
|
switch (psock->s_domain)
|
||||||
|
{
|
||||||
|
#ifdef CONFIG_NET_IPv4
|
||||||
|
case PF_INET:
|
||||||
|
return ipv4_getsockname(psock, addr, addrlen);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_NET_IPv6
|
||||||
|
case PF_INET6:
|
||||||
|
return ipv6_getsockname(psock, addr, addrlen);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
default:
|
||||||
|
return -EAFNOSUPPORT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: inet_listen
|
* Name: inet_listen
|
||||||
*
|
*
|
||||||
|
@ -436,6 +436,35 @@ int net_timeo(systime_t start_time, socktimeo_t timeo);
|
|||||||
ssize_t psock_send(FAR struct socket *psock, FAR const void *buf, size_t len,
|
ssize_t psock_send(FAR struct socket *psock, FAR const void *buf, size_t len,
|
||||||
int flags);
|
int flags);
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: ipv4_getsockname and ipv6_sockname
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* The ipv4_getsockname() and ipv6_getsocknam() function retrieve the
|
||||||
|
* locally-bound name of the specified INET socket.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* psock Point to the socket structure instance [in]
|
||||||
|
* addr sockaddr structure to receive data [out]
|
||||||
|
* addrlen Length of sockaddr structure [in/out]
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* On success, 0 is returned, the 'addr' argument points to the address
|
||||||
|
* of the socket, and the 'addrlen' argument points to the length of the
|
||||||
|
* address. Otherwise, a negated errno value is returned. See
|
||||||
|
* getsockname() for the list of returned error values.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifdef CONFIG_NET_IPv4
|
||||||
|
int ipv4_getsockname(FAR struct socket *psock, FAR struct sockaddr *addr,
|
||||||
|
FAR socklen_t *addrlen);
|
||||||
|
#endif
|
||||||
|
#ifdef CONFIG_NET_IPv6
|
||||||
|
int ipv6_getsockname(FAR struct socket *psock, FAR struct sockaddr *addr,
|
||||||
|
FAR socklen_t *addrlen);
|
||||||
|
#endif
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: inet_connect
|
* Name: inet_connect
|
||||||
*
|
*
|
||||||
|
Loading…
x
Reference in New Issue
Block a user