summaryrefslogtreecommitdiff
path: root/nuttx/net/socket
diff options
context:
space:
mode:
Diffstat (limited to 'nuttx/net/socket')
-rw-r--r--nuttx/net/socket/getsockname.c295
-rw-r--r--nuttx/net/socket/socket.c131
2 files changed, 317 insertions, 109 deletions
diff --git a/nuttx/net/socket/getsockname.c b/nuttx/net/socket/getsockname.c
index 34fea0c12..04b96b01b 100644
--- a/nuttx/net/socket/getsockname.c
+++ b/nuttx/net/socket/getsockname.c
@@ -61,26 +61,14 @@
****************************************************************************/
/****************************************************************************
- * Public Functions
- ****************************************************************************/
-
-/****************************************************************************
- * Function: getsockname
+ * Function: get_ipv4_sockname
*
* Description:
* The getsockname() function retrieves the locally-bound name of the
- * specified 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.
+ * specified PF_NET socket.
*
* Parameters:
- * sockfd Socket descriptor of socket [in]
+ * psock Point to the socket structure instance [in]
* addr sockaddr structure to receive data [out]
* addrlen Length of sockaddr structure [in/out]
*
@@ -98,56 +86,152 @@
*
****************************************************************************/
-int getsockname(int sockfd, FAR struct sockaddr *addr, FAR socklen_t *addrlen)
+#ifdef CONFIG_NET_IPv4
+int ipv4_getsockname(FAR struct socket *psock, FAR struct sockaddr *addr,
+ FAR socklen_t *addrlen)
{
- FAR struct socket *psock = sockfd_socket(sockfd);
FAR struct net_driver_s *dev;
-
#if defined(CONFIG_NET_TCP) || defined(CONFIG_NET_UDP)
-#ifdef CONFIG_NET_IPv6
- FAR struct sockaddr_in6 *outaddr = (FAR struct sockaddr_in6 *)addr;
-#else
FAR struct sockaddr_in *outaddr = (FAR struct sockaddr_in *)addr;
#endif
+#ifdef CONFIG_NETDEV_MULTINIC
+ in_addr_t lipaddr;
+ in_addr_t ripaddr;
#endif
- int err;
+ /* Check if enough space has been provided for the full address */
- /* Verify that the sockfd corresponds to valid, allocated socket */
+ 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.
+ */
- if (!psock || psock->s_crefs <= 0)
+ return -ENOSYS;
+ }
+
+ /* Set the port number */
+
+ switch (psock->s_type)
{
- err = EBADF;
- goto errout;
+#ifdef CONFIG_NET_TCP
+ 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->lipaddr;
+ ripaddr = tcp_conn->ripaddr;
+#endif
+ }
+ break;
+#endif
+
+#ifdef CONFIG_NET_UDP
+ 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->lipaddr;
+ ripaddr = udp_conn->ripaddr;
+#endif
+ }
+ break;
+#endif
+
+ default:
+ return -EOPNOTSUPP;
}
- /* Some sanity checking... Shouldn't need this on a buckled up embedded
- * system (?)
+ /* 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.
*/
-#ifdef CONFIG_DEBUG
- if (!addr || !addrlen)
+ netdev_semtake();
+
+#ifdef CONFIG_NETDEV_MULTINIC
+ /* Find the device matching the IPv4 address in the connection structure */
+
+ dev = netdev_findby_ipv4addr(lipaddr, ripaddr);
+#else
+ /* There is only one, the first network device in the list. */
+
+ dev = g_netdevices;
+#endif
+
+ if (!dev)
{
- err = EINVAL;
- goto errout;
+ netdev_semgive();
+ return -EINVAL;
}
+
+ /* Set the address family and the IP address */
+
+#if defined(CONFIG_NET_TCP) || defined(CONFIG_NET_UDP)
+ outaddr->sin_family = AF_INET;
+ outaddr->sin_addr.s_addr = dev->d_ipaddr;
+ *addrlen = sizeof(struct sockaddr_in);
#endif
+ netdev_semgive();
- /* Check if enough space has been provided for the full address */
+ /* Return success */
+
+ return OK;
+}
+#endif
+
+/****************************************************************************
+ * Function: 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
- if (*addrlen < sizeof(struct sockaddr_in6))
-#else
- if (*addrlen < sizeof(struct sockaddr_in))
+int ipv6_getsockname(FAR struct socket *psock, FAR struct sockaddr *addr,
+ FAR socklen_t *addrlen)
+{
+ FAR struct net_driver_s *dev;
+#if defined(CONFIG_NET_TCP) || defined(CONFIG_NET_UDP)
+ 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.
*/
- err = ENOSYS;
- goto errout;
+ return -ENOSYS;
}
/* Set the port number */
@@ -159,6 +243,10 @@ int getsockname(int sockfd, FAR struct sockaddr *addr, FAR socklen_t *addrlen)
{
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->lipaddr;
+ ripaddr = tcp_conn->ripaddr;
+#endif
}
break;
#endif
@@ -168,6 +256,10 @@ int getsockname(int sockfd, FAR struct sockaddr *addr, FAR socklen_t *addrlen)
{
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->lipaddr;
+ ripaddr = &udp_conn->ripaddr;
+#endif
}
break;
#endif
@@ -177,42 +269,139 @@ int getsockname(int sockfd, FAR struct sockaddr *addr, FAR socklen_t *addrlen)
goto errout;
}
- /* ISSUE: As of this writing, the socket/connection does not know its IP
- * address. This is because the uIP design is only intended to support
- * a single network device and, therefore, only the network device knows
- * the IP address.
- *
- * Right now, we can just pick the first network device. But that may
- * not work in the future.
+ /* 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.
*/
netdev_semtake();
+
+#ifdef CONFIG_NETDEV_MULTINIC
+ /* Find the device matching the IPv6 address in the connection structure */
+
+ dev = netdev_findby_ipv6addr(*lipaddr, *ripaddr);
+#else
+ /* There is only one, the first network device in the list. */
+
dev = g_netdevices;
+#endif
+
if (!dev)
{
netdev_semgive();
- err = EINVAL;
- goto errout;
+ return -EINVAL;
}
/* Set the address family and the IP address */
#if defined(CONFIG_NET_TCP) || defined(CONFIG_NET_UDP)
-#ifdef CONFIG_NET_IPv6
outaddr->sin_family = AF_INET6;
memcpy(outaddr->sin6_addr.in6_u.u6_addr8, dev->d_ipaddr, 16);
*addrlen = sizeof(struct sockaddr_in6);
-#else
- outaddr->sin_family = AF_INET;
- outaddr->sin_addr.s_addr = dev->d_ipaddr;
- *addrlen = sizeof(struct sockaddr_in);
-#endif
#endif
netdev_semgive();
/* Return success */
return OK;
+}
+#endif
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Function: getsockname
+ *
+ * Description:
+ * The getsockname() function retrieves the locally-bound name of the
+ * specified 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:
+ * sockfd Socket descriptor of socket [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:
+ *
+ ****************************************************************************/
+
+int getsockname(int sockfd, FAR struct sockaddr *addr, FAR socklen_t *addrlen)
+{
+ FAR struct socket *psock = sockfd_socket(sockfd);
+ int ret;
+ int err;
+
+ /* Verify that the sockfd corresponds to valid, allocated socket */
+
+ if (!psock || psock->s_crefs <= 0)
+ {
+ err = EBADF;
+ goto errout;
+ }
+
+ /* Some sanity checking... Shouldn't need this on a buckled up embedded
+ * system (?)
+ */
+
+#ifdef CONFIG_DEBUG
+ if (!addr || !addrlen)
+ {
+ err = EINVAL;
+ goto errout;
+ }
+#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:
+ err = EAFNOSUPPORT;
+ goto errout;
+ }
+
+ /* Check for failure */
+
+ if (ret < 0)
+ {
+ err = -ret;
+ goto errout;
+ }
+
+ return OK;
errout:
set_errno(err);
diff --git a/nuttx/net/socket/socket.c b/nuttx/net/socket/socket.c
index 505dbfc0e..6dadf79d3 100644
--- a/nuttx/net/socket/socket.c
+++ b/nuttx/net/socket/socket.c
@@ -1,7 +1,7 @@
/****************************************************************************
* net/socket/socket.c
*
- * Copyright (C) 2007-2009, 2012, 2014 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007-2009, 2012, 2014-2015 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -96,66 +96,85 @@
int psock_socket(int domain, int type, int protocol, FAR struct socket *psock)
{
+ bool ipdomain = false;
int err;
/* Only PF_INET, PF_INET6 or PF_PACKET domains supported */
- if (
-#if defined(CONFIG_NET_IPv6)
- domain != PF_INET6
-#else
- domain != PF_INET
+ switch (domain)
+ {
+#ifdef CONFIG_NET_IPv4
+ case PF_INET:
+ ipdomain = true;
+ break;
#endif
-#if defined(CONFIG_NET_PKT)
- && domain != PF_PACKET
+
+#ifdef CONFIG_NET_IPv6
+ case PF_INET6:
+ ipdomain = true;
+ break;
#endif
- )
- {
+
+#ifdef CONFIG_NET_PKT
+ case PF_PACKET:
+ break;
+#endif
+
+ default:
err = EAFNOSUPPORT;
goto errout;
}
/* Only SOCK_STREAM, SOCK_DGRAM and possible SOCK_RAW are supported */
- if (
-#if defined(CONFIG_NET_TCP)
- (type == SOCK_STREAM && protocol != 0 && protocol != IPPROTO_TCP) ||
-#endif
-#if defined(CONFIG_NET_UDP)
- (type == SOCK_DGRAM && protocol != 0 && protocol != IPPROTO_UDP) ||
-#endif
- (
-#if defined(CONFIG_NET_TCP)
-#if defined(CONFIG_NET_UDP) || defined(CONFIG_NET_PKT)
- type != SOCK_STREAM &&
-#else
- type != SOCK_STREAM
-#endif
-#endif
-#if defined(CONFIG_NET_UDP)
-#if defined(CONFIG_NET_PKT)
- type != SOCK_DGRAM &&
-#else
- type != SOCK_DGRAM
+ switch (type)
+ {
+#ifdef CONFIG_NET_TCP
+ case SOCK_STREAM:
+ if ((protocol != 0 && protocol != IPPROTO_TCP) || !ipdomain)
+ {
+ err = EPROTONOSUPPORT;
+ goto errout;
+ }
+
+ break;
#endif
+
+#ifdef CONFIG_NET_UDP
+ case SOCK_DGRAM:
+ if ((protocol != 0 && protocol != IPPROTO_UDP) || !ipdomain)
+ {
+ err = EPROTONOSUPPORT;
+ goto errout;
+ }
+
+ break;
#endif
-#if defined(CONFIG_NET_PKT)
- type != SOCK_RAW
+
+#ifdef CONFIG_NET_PKT
+ case SOCK_RAW:
+ if (ipdomain)
+ {
+ err = EPROTONOSUPPORT;
+ goto errout;
+ }
+
+ break;
#endif
- )
- )
- {
- err = EPROTONOSUPPORT;
- goto errout;
+
+ default:
+ err = EPROTONOSUPPORT;
+ goto errout;
}
/* Everything looks good. Initialize the socket structure */
/* Save the protocol type */
- psock->s_type = type;
- psock->s_conn = NULL;
+ psock->s_domain = domain;
+ psock->s_type = type;
+ psock->s_conn = NULL;
#ifdef CONFIG_NET_TCP_WRITE_BUFFERS
- psock->s_sndcb = NULL;
+ psock->s_sndcb = NULL;
#endif
/* Allocate the appropriate connection structure. This reserves the
@@ -166,19 +185,19 @@ int psock_socket(int domain, int type, int protocol, FAR struct socket *psock)
err = ENOMEM; /* Assume failure to allocate connection instance */
switch (type)
{
-#ifdef CONFIG_NET_PKT
- case SOCK_RAW:
+#ifdef CONFIG_NET_TCP
+ case SOCK_STREAM:
{
- /* Allocate the packet socket connection structure and save
- * in the new socket instance.
+ /* Allocate the TCP connection structure and save in the new
+ * socket instance.
*/
- FAR struct pkt_conn_s *conn = pkt_alloc();
+ FAR struct tcp_conn_s *conn = tcp_alloc();
if (!conn)
{
/* Failed to reserve a connection structure */
- goto errout;
+ goto errout; /* With err == ENFILE or ENOMEM */
}
/* Set the reference count on the connection structure. This
@@ -193,14 +212,14 @@ int psock_socket(int domain, int type, int protocol, FAR struct socket *psock)
break;
#endif
-#ifdef CONFIG_NET_TCP
- case SOCK_STREAM:
+#ifdef CONFIG_NET_UDP
+ case SOCK_DGRAM:
{
- /* Allocate the TCP connection structure and save in the new
+ /* Allocate the UDP connection structure and save in the new
* socket instance.
*/
- FAR struct tcp_conn_s *conn = tcp_alloc();
+ FAR struct udp_conn_s *conn = udp_alloc();
if (!conn)
{
/* Failed to reserve a connection structure */
@@ -220,19 +239,19 @@ int psock_socket(int domain, int type, int protocol, FAR struct socket *psock)
break;
#endif
-#ifdef CONFIG_NET_UDP
- case SOCK_DGRAM:
+#ifdef CONFIG_NET_PKT
+ case SOCK_RAW:
{
- /* Allocate the UDP connection structure and save in the new
- * socket instance.
+ /* Allocate the packet socket connection structure and save
+ * in the new socket instance.
*/
- FAR struct udp_conn_s *conn = udp_alloc();
+ FAR struct pkt_conn_s *conn = pkt_alloc();
if (!conn)
{
/* Failed to reserve a connection structure */
- goto errout; /* With err == ENFILE or ENOMEM */
+ goto errout;
}
/* Set the reference count on the connection structure. This