diff --git a/Makefile.dep b/Makefile.dep
index 3f6ef658a..e0f3d7892 100644
--- a/Makefile.dep
+++ b/Makefile.dep
@@ -1,9 +1,5 @@
ifneq (,$(filter libcoap,$(USEPKG)))
- USEMODULE += pnet
-endif
-
-ifneq (,$(filter pnet,$(USEMODULE)))
- USEMODULE += vtimer
+ USEMODULE += posix_sockets
endif
ifneq (,$(filter gnrc_%,$(filter-out gnrc_netapi gnrc_netreg gnrc_netif% gnrc_pktbuf,$(USEMODULE))))
@@ -276,6 +272,11 @@ ifneq (,$(filter newlib,$(USEMODULE)))
USEMODULE += uart_stdio
endif
+ifneq (,$(filter posix_sockets,$(USEMODULE)))
+ USEMODULE += posix
+ USEMODULE += random
+endif
+
ifneq (,$(filter posix,$(USEMODULE)))
USEMODULE += timex
USEMODULE += vtimer
diff --git a/sys/Makefile b/sys/Makefile
index 2d4a65930..efb6384da 100644
--- a/sys/Makefile
+++ b/sys/Makefile
@@ -1,5 +1,5 @@
-ifneq (,$(filter pnet,$(USEMODULE)))
- DIRS += posix/pnet
+ifneq (,$(filter posix_sockets,$(USEMODULE)))
+ DIRS += posix/sockets
endif
ifneq (,$(filter pthread,$(USEMODULE)))
DIRS += posix/pthread
diff --git a/sys/Makefile.include b/sys/Makefile.include
index 91ebcbdda..1c4d405de 100644
--- a/sys/Makefile.include
+++ b/sys/Makefile.include
@@ -18,7 +18,7 @@ ifneq (,$(filter posix,$(USEMODULE)))
USEMODULE_INCLUDES += $(RIOTBASE)/sys/posix/include
USEMODULE_INCLUDES += $(RIOTBASE)/sys/net/include
endif
-ifneq (,$(filter pnet,$(USEMODULE)))
+ifneq (,$(filter posix_sockets,$(USEMODULE)))
USEMODULE_INCLUDES += $(RIOTBASE)/sys/posix/include
endif
ifneq (,$(filter pthread,$(USEMODULE)))
diff --git a/sys/posix/include/arpa/inet.h b/sys/posix/include/arpa/inet.h
index 1b2d5f51c..98646b9f0 100644
--- a/sys/posix/include/arpa/inet.h
+++ b/sys/posix/include/arpa/inet.h
@@ -31,29 +31,13 @@
#include "net/af.h"
#include "net/ipv4/addr.h"
#include "net/ipv6/addr.h"
-#include "socket_base/socket.h"
+#include "sys/bytes.h"
+#include "netinet/in.h"
#ifdef __cplusplus
extern "C" {
#endif
-typedef uint16_t in_port_t; /**< Internet port type */
-typedef uint32_t in_addr_t; /**< IPv4 address type */
-
-/**
- * @brief Alias to @ref IPV4_ADDR_MAX_STR_LEN
- */
-#ifndef INET_ADDRSTRLEN
-#define INET_ADDRSTRLEN (IPV4_ADDR_MAX_STR_LEN)
-#endif
-
-/**
- * @brief Alias to @ref IPV6_ADDR_MAX_STR_LEN
- */
-#ifndef INET6_ADDRSTRLEN
-#define INET6_ADDRSTRLEN (IPV6_ADDR_MAX_STR_LEN)
-#endif
-
/**
* @brief Size in byte of an IPv4 address
*/
@@ -68,66 +52,6 @@ typedef uint32_t in_addr_t; /**< IPv4 address type */
#define IN6ADDRSZ (sizeof(ipv6_addr_t))
#endif
-
-/**
- * @brief IPv4 address structure type.
- */
-struct in_addr {
- in_addr_t s_addr; ///< an IPv4 address
-};
-
-/**
- * @brief Convert values between host and network byte order.
- *
- * @see
- * The Open Group Base Specification Issue 7, htonl
- *
- *
- * @param[in] hostlong A 32 bit number.
- * @return The argument value converted from host to network byte
- * order.
- */
-#define htonl(hostlong) HTONL(hostlong)
-
-/**
- * @brief Convert values between host and network byte order.
- *
- * @see
- * The Open Group Base Specification Issue 7, htons
- *
- *
- * @param[in] hostshort A 16 bit number.
- * @return The argument value converted from host to network byte
- * order.
- */
-#define htons(hostshort) HTONS(hostshort)
-
-/**
- * @brief Convert values between host and network byte order.
- *
- * @see
- * The Open Group Base Specification Issue 7, ntohl
- *
- *
- * @param[in] netlong A 32-bit integer number.
- * @return The argument value converted from network to host byte
- * order.
- */
-#define ntohl(netlong) NTOHL(netlong)
-
-/**
- * @brief Convert values between host and network byte order.
- *
- * @see
- * The Open Group Base Specification Issue 7, ntohs
- *
- *
- * @param[in] netshort A 16-bit integer number.
- * @return The argument value converted from network to host byte
- * order.
- */
-#define ntohs(netshort) NTOHS(netshort)
-
/**
* @brief Converts an IP address to its string representation
*
diff --git a/sys/posix/include/netinet/in.h b/sys/posix/include/netinet/in.h
index 4767182d1..5d3ccb014 100644
--- a/sys/posix/include/netinet/in.h
+++ b/sys/posix/include/netinet/in.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 Freie Universität Berlin
+ * Copyright (C) 2013-15 Freie Universität Berlin
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
@@ -7,7 +7,7 @@
*/
/**
- * @addtogroup pnet
+ * @addtogroup posix_sockets
* @{
*/
@@ -25,135 +25,244 @@
#include
#include
-#include
-#include "net/gnrc/ipv6.h"
-#include "socket_base/socket.h"
+
+#include "net/protnum.h"
+#include "net/ipv6/addr.h"
+#include "sys/bytes.h"
#ifdef __cplusplus
extern "C" {
#endif
+#define INET_ADDRSTRLEN (16) /**< Length of the string form for IPv4. */
+#define INET6_ADDRSTRLEN (46) /**< Length of the string form for IPv6. */
+
/**
- * IPv4 socket address type.
+ * IPv4 local host address.
*/
-struct sockaddr_in {
- sa_family_t sin_family; ///< Protocol family, always AF_INET.
- in_port_t sin_port; ///< Port number
- struct in_addr sin_addr; ///< IPv4 address
-};
+#define INADDR_ANY ((in_addr_t)0x00000000)
/**
- * IPv6 address structure type.
+ * IPv4 broadcast address.
*/
-struct in6_addr {
- /**
- * Private RIOT-internal data, needs not to be touched by the user.
- */
- ipv6_addr_t __in6_u;
+#define INADDR_BROADCAST ((in_addr_t)0xffffffff)
- /**
- * IPv6 Address represented as sequence of 8-bit numbers. Member of
- * struct in6_addr.
- */
-#define s6_addr __in6_u.uint8
+/**
+ * IPv6 wildcard address.
+ */
+#define IN6ADDR_ANY_INIT IPV6_ADDR_UNSPECIFIED
- /**
- * IPv6 Address represented as sequence of 16-bit numbers. Member of
- * struct in6_addr.
- */
-#define s6_addr16 __in6_u.uint16
+/**
+ * IPv6 loopback address.
+ */
+#define IN6ADDR_LOOPBACK_INIT IPV6_ADDR_LOOPBACK
- /**
- * IPv6 Address represented as sequence of 32-bit numbers. Member of
- * struct in6_addr.
- */
-#define s6_addr32 __in6_u.uint32
-};
+/**
+ * @name IPv6 address macros
+ * @{
+ */
+/**
+ * @brief Check if address is the unspecified address (`::`).
+ *
+ * @param[in] addr address of type `const struct in6_addr *`
+ *
+ * @return 0, when an address is not the unspecified address.
+ * @return any other value otherwise.
+ */
+#define IN6_IS_ADDR_UNSPECIFIED(addr) ((int)(ipv6_addr_is_unspecified((const ipv6_addr_t *)(addr))))
/**
- * IPv6 socket address type.
+ * @brief Check if address is the loopback address (`::1`).
+ *
+ * @param[in] addr address of type `const struct in6_addr *`
+ *
+ * @return 0, when an address is not the loopback address.
+ * @return any other value otherwise.
*/
-struct sockaddr_in6 {
- /**
- * Private RIOT-internal data, needs not to be touched by the user.
- */
- sockaddr6_t __in6_a;
+#define IN6_IS_ADDR_LOOPBACK(addr) ((int)(ipv6_addr_is_loopback((const ipv6_addr_t *)(addr))))
- /**
- * Protocol family, always AF_INET6. Member of struct sockaddr_in6
- */
-#define sin6_family __in6_a.sin6_family
+/**
+ * @brief Check if address is a multicast address.
+ *
+ * @param[in] addr address of type `const struct in6_addr *`
+ *
+ * @return 0, when an address is not a multicast address.
+ * @return any other value otherwise.
+ */
+#define IN6_IS_ADDR_MULTICAST(addr) ((int)(ipv6_addr_is_multicast((const ipv6_addr_t *)(addr))))
- /**
- * Port number. Member of struct sockaddr_in6
- */
-#define sin6_port __in6_a.sin6_port
+/**
+ * @brief Check if address is a link-local address.
+ *
+ * @param[in] addr address of type `const struct in6_addr *`
+ *
+ * @return 0, when an address is not a link-local address.
+ * @return any other value otherwise.
+ */
+#define IN6_IS_ADDR_LINKLOCAL(addr) ((int)(ipv6_addr_is_link_local((const ipv6_addr_t *)addr)))
- /**
- * IPv6 traffic class and flow information. Member of struct sockaddr_in6
- */
-#define sin6_flowinfo __in6_a.sin6_flowinfo
+/**
+ * @brief Check if address is a site-local address.
+ *
+ * @param[in] addr address of type `const struct in6_addr *`
+ *
+ * @return 0, when an address is not a site-local address.
+ * @return any other value otherwise.
+ */
+#define IN6_IS_ADDR_SITELOCAL(addr) ((int)(ipv6_addr_is_site_local((const ipv6_addr_t *)addr)))
- /**
- * IPv6 address. Member of struct sockaddr_in6
- */
-#define sin6_addr __in6_a.sin6_addr
+/**
+ * @brief Check if address is an IPv4 mapped address.
+ *
+ * @param[in] addr address of type `const struct in6_addr *`
+ *
+ * @return 0, when an address is not an IPv4 mapped address.
+ * @return any other value otherwise.
+ */
+#define IN6_IS_ADDR_V4MAPPED(addr) ((int)(ipv6_addr_is_ipv4_mapped((const ipv6_addr_t *)addr)))
- /**
- * Set of interfaces for a scope.
- */
- uint32_t sin6_scope_id;
-};
+/**
+ * @brief Check if address is an IPv4-compatible address.
+ *
+ * @param[in] addr address of type `const struct in6_addr *`
+ *
+ * @return 0, when an address is not an IPv4-compatible address.
+ * @return any other value otherwise.
+ */
+#define IN6_IS_ADDR_V4COMPAT(addr) ((int)(ipv6_addr_is_ipv4_compat((const ipv6_addr_t *)addr)))
/**
- * IPv6 wildcard address.
+ * @brief Check if address is a multicast node-local address.
+ *
+ * @param[in] addr address of type `const struct in6_addr *`
+ *
+ * @return 0, when an address is not a multicast node-local address.
+ * @return any other value otherwise.
*/
-#define IN6ADDR_ANY_INIT {{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}}
+#define IN6_IS_ADDR_MC_NODELOCAL(addr) (IN6_IS_ADDR_MULTICAST(addr) && \
+ (int)((addr->s6_addr[1] & 0x0f) == IPV6_ADDR_MCAST_SCP_IF_LOCAL))
/**
- * IPv6 loopback address.
+ * @brief Check if address is a multicast link-local address.
+ *
+ * @param[in] addr address of type `const struct in6_addr *`
+ *
+ * @return 0, when an address is not a multicast link-local address.
+ * @return any other value otherwise.
*/
-#define IN6ADDR_LOOPBACK_INIT {{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}}
+#define IN6_IS_ADDR_MC_LINKLOCAL(addr) (IN6_IS_ADDR_MULTICAST(addr) && \
+ (int)((addr->s6_addr[1] & 0x0f) == IPV6_ADDR_MCAST_SCP_LINK_LOCAL))
/**
- * IPv6 socket address for the wildcard address.
+ * @brief Check if address is a multicast site-local address.
+ *
+ * @param[in] addr address of type `const struct in6_addr *`
+ *
+ * @return 0, when an address is not a multicast site-local address.
+ * @return any other value otherwise.
*/
-extern const struct sockaddr_in6 in6addr_any;
+#define IN6_IS_ADDR_MC_SITELOCAL(addr) (IN6_IS_ADDR_MULTICAST(addr) && \
+ (int)((addr->s6_addr[1] & 0x0f) == IPV6_ADDR_MCAST_SCP_SITE_LOCAL))
/**
- * IPv6 socket address for the loopback address.
+ * @brief Check if address is a multicast organization-local address.
+ *
+ * @param[in] addr address of type `const struct in6_addr *`
+ *
+ * @return 0, when an address is not a multicast organization-local address.
+ * @return any other value otherwise.
*/
-extern const struct sockaddr_in6 in6addr_loopback;
+#define IN6_IS_ADDR_MC_ORGLOCAL(addr) (IN6_IS_ADDR_MULTICAST(addr) && \
+ (int)((addr->s6_addr[1] & 0x0f) == IPV6_ADDR_MCAST_SCP_ORG_LOCAL))
/**
- * IPv4 local host address.
+ * @brief Check if address is a multicast global address.
+ *
+ * @param[in] addr address of type `const struct in6_addr *`
+ *
+ * @return 0, when an address is not a multicast global address.
+ * @return any other value otherwise.
*/
-#define INADDR_ANY ((in_addr_t)0x00000000)
+#define IN6_IS_ADDR_MC_GLOBAL(addr) (IN6_IS_ADDR_MULTICAST(addr) && \
+ (int)((addr->s6_addr[1] & 0x0f) == IPV6_ADDR_MCAST_SCP_GLOBAL))
+/** @} */
/**
- * IPv4 broadcast address.
+ * @name Protocol numbers for option
+ * @{
*/
-#define INADDR_BROADCAST ((in_addr_t)0xffffffff)
+#define IPPROTO_IP (PROTNUM_IPV4) /**< Internet Protocol version 4 */
+#define IPPROTO_IPV6 (PROTNUM_IPV6) /**< Internet Protocol version 6 */
+#define IPPROTO_ICMP (PROTNUM_ICMP) /**< Internet Control Message Protocol */
+#define IPPROTO_ICMPV6 (PROTNUM_ICMPV6) /**< ICMP for IPv6 */
+#define IPPROTO_RAW (PROTNUM_RESERVED) /**< Raw IP packets protocol */
+#define IPPROTO_TCP (PROTNUM_TCP) /**< Transmission control protocol */
+#define IPPROTO_UDP (PROTNUM_UDP) /**< User datagram protocol */
+/** @} */
/**
- * Multicast hop limit option name for getsockopt() or setsockopt()
- *
- * @see
- * The Open Group Base Specification Issue 7, getsockopt
- *
- * @see
- * The Open Group Base Specification Issue 7, setsockopt
- *
+ * @todo IPv6 option names
*/
-#define IPV6_MULTICAST_HOPS 0x12
+
+typedef uint16_t in_port_t; /**< Internet port type */
+typedef uint32_t in_addr_t; /**< IPv4 address type */
/**
- * Test for IPv6 multicast address.
- *
- * @param[in] a An IPv6 address.
- * @return 1 if *a* is an multicast address, 0 if not.
+ * IPv4 address structure type.
*/
-#define IN6_IS_ADDR_MULTICAST(a) (((const uint8_t *) (a))[0] == 0xff)
+struct in_addr {
+ in_addr_t s_addr; /**< an IPv4 address */
+};
+
+/**
+ * @brief IPv6 address structure type.
+ */
+struct in6_addr {
+ uint8_t s6_addr[16]; /**< unsigned 8-bit integer array */
+};
+
+/**
+ * @brief IPv4 socket address type.
+ * @extends struct sockaddr
+ */
+struct sockaddr_in {
+ sa_family_t sin_family; /**< Protocol family, always AF_INET */
+ in_port_t sin_port; /**< Port number */
+ struct in_addr sin_addr; /**< IPv4 address */
+};
+
+/**
+ * IPv6 socket address type.
+ * @extends struct sockaddr
+ */
+struct sockaddr_in6 {
+ /**
+ * Protocol family, always AF_INET6. Member of struct sockaddr_in6
+ */
+ int sin6_family; /**< Protocol family, always AF_INET6 */
+ in_port_t sin6_port; /**< Port number */
+ uint32_t sin6_flowinfo; /**< IPv6 traffic class and flow information */
+ struct in6_addr sin6_addr; /**< IPv6 address */
+ uint32_t sin6_scope_id; /**< Set of interfaces for a scope */
+};
+
+/**
+ * @brief IPv6 multicast request.
+ */
+struct ipv6_mreq {
+ struct in6_addr ipv6mr_multiaddr; /**< an IPv6 multicast address */
+ unsigned ipv6mr_interface; /**< interface index, leave 0 for default */
+};
+
+/**
+ * IPv6 socket address for the wildcard address.
+ */
+extern const struct sockaddr_in6 in6addr_any;
+
+/**
+ * IPv6 socket address for the loopback address.
+ */
+extern const struct sockaddr_in6 in6addr_loopback;
#ifdef __cplusplus
}
diff --git a/sys/posix/include/sys/bytes.h b/sys/posix/include/sys/bytes.h
new file mode 100644
index 000000000..86d4872f6
--- /dev/null
+++ b/sys/posix/include/sys/bytes.h
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2015 Martine Lenders
+ *
+ * This file is subject to the terms and conditions of the GNU Lesser
+ * General Public License v2.1. See the file LICENSE in the top level
+ * directory for more details.
+ */
+
+/**
+ * @addtogroup posix_sockets
+ */
+/**
+ * @{
+ *
+ * @file
+ * @brief System-internal byte operations.
+ *
+ * @author Martine Lenders
+ */
+#ifndef BYTES_H_
+#define BYTES_H_
+
+#include "byteorder.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Convert values between host and network byte order.
+ *
+ * @see
+ * The Open Group Base Specification Issue 7, htonl
+ *
+ *
+ * @param[in] hostlong A 32 bit number.
+ * @return The argument value converted from host to network byte
+ * order.
+ */
+#ifndef htonl
+#define htonl(hostlong) HTONL(hostlong)
+#endif
+
+/**
+ * @brief Convert values between host and network byte order.
+ *
+ * @see
+ * The Open Group Base Specification Issue 7, htons
+ *
+ *
+ * @param[in] hostshort A 16 bit number.
+ * @return The argument value converted from host to network byte
+ * order.
+ */
+#ifndef htons
+#define htons(hostshort) HTONS(hostshort)
+#endif
+
+/**
+ * @brief Convert values between host and network byte order.
+ *
+ * @see
+ * The Open Group Base Specification Issue 7, ntohl
+ *
+ *
+ * @param[in] netlong A 32-bit integer number.
+ * @return The argument value converted from network to host byte
+ * order.
+ */
+#ifndef ntohl
+#define ntohl(netlong) NTOHL(netlong)
+#endif
+
+/**
+ * @brief Convert values between host and network byte order.
+ *
+ * @see
+ * The Open Group Base Specification Issue 7, ntohs
+ *
+ *
+ * @param[in] netshort A 16-bit integer number.
+ * @return The argument value converted from network to host byte
+ * order.
+ */
+#ifndef ntohs
+#define ntohs(netshort) NTOHS(netshort)
+#endif
+
+typedef size_t socklen_t; /**< socket address length */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BYTES_H_ */
+/** @} */
diff --git a/sys/posix/include/sys/socket.h b/sys/posix/include/sys/socket.h
index e0db357b1..52fcd6d4b 100644
--- a/sys/posix/include/sys/socket.h
+++ b/sys/posix/include/sys/socket.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 Freie Universität Berlin
+ * Copyright (C) 2013-15 Freie Universität Berlin
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
@@ -7,7 +7,7 @@
*/
/**
- * @addtogroup pnet
+ * @addtogroup posix_sockets
* @{
*/
@@ -18,6 +18,12 @@
* The Open Group Base Specifications Issue 7,
*
*
+ * @todo Omitted from original specification for now:
+ * * struct msghdr, struct cmesghdr, and struct linger and all related defines
+ * * getsockopt()/setsockopt() and all related defines.
+ * * shutdown() and all related defines.
+ * * sockatmark()
+ *
* @author Martine Lenders
*/
#ifndef _SYS_SOCKET_H
@@ -32,135 +38,81 @@
#define __SOCKADDR_COMMON_SIZE (sizeof (unsigned short int))
#endif
+#include
#include
+#include
-#include "cpu.h"
+#include "kernel_types.h"
#include "net/af.h"
-
-#include "socket_base/socket.h"
+#include "sys/bytes.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
- * @brief Used to define the socket address.
- */
-struct __attribute__((packed)) sockaddr {
- sa_family_t sa_family; ///< Address family
- char sa_data[14]; ///< Socket address (variable length data)
-};
-
-/**
- * @brief Implementation based socket address table.
- */
-struct __attribute__((packed)) sockaddr_storage {
- sa_family_t ss_family; ///< Address family
- char ss_data[14]; ///< address data
-};
-
-/*
- * Omitted from original specification for now are struct msghdr,
- * struct cmesghdr, and struct linger and all related defines
- */
-
-/**
- * @brief *level* value for getsockopt() or setsockopt().
- */
-#define SOL_SOCKET 1 ///< Options to be accessed at socket level, not
- ///< protocol level.
-
-/**
- * @brief *option_name* value for getsockopt() or setsockopt()
- */
-#define SO_ACCEPTCONN 1 ///< Socket is accepting connections.
-
-/**
- * @brief *option_name* value for getsockopt() or setsockopt()
- */
-#define SO_BROADCAST 2 ///< Transmission of broadcast messages is supported.
-
-/**
- * @brief *option_name* value for getsockopt() or setsockopt()
- */
-#define SO_DEBUG 3 ///< Debugging information is being recorded.
-
-/**
- * @brief *option_name* value for getsockopt() or setsockopt()
- */
-#define SO_DONTROUTE 4 ///< Bypass normal routing.
-
-/**
- * @brief *option_name* value for getsockopt() or setsockopt()
- */
-#define SO_ERROR 5 ///< Socket error status.
-
-/**
- * @brief *option_name* value for getsockopt() or setsockopt()
- */
-#define SO_KEEPALIVE 6 ///< Connections are kept alive with periodic messages.
-
-/**
- * @brief *option_name* value for getsockopt() or setsockopt()
- */
-#define SO_OOBINLINE 7 ///< Out-of-band data is transmitted in line.
-
-/**
- * @brief *option_name* value for getsockopt() or setsockopt()
- */
-#define SO_RCVBUF 8 ///< Receive buffer size.
-
-/**
- * @brief *option_name* value for getsockopt() or setsockopt()
- */
-#define SO_RCVLOWAT 9 ///< Receive "low water mark".
-
-/**
- * @brief *option_name* value for getsockopt() or setsockopt()
- */
-#define SO_RCVTIMEO 10 ///< Receive timeout.
-
-/**
- * @brief *option_name* value for getsockopt() or setsockopt()
- */
-#define SO_REUSEADDR 11 ///< Reuse of local addresses is supported.
-
-/**
- * @brief *option_name* value for getsockopt() or setsockopt()
+ * @brief Maximum data length for a socket address.
+ *
+ * It is assumed that struct sockaddr_in6 is currently the longest socket address struct.
+ * As such it's data length is taken consisting of the IPv6 address (16 byte), the port (2 byte),
+ * the flow information (4 byte) and the scope ID (4 byte)
*/
-#define SO_SNDBUF 12 ///< Send buffer size.
+#define SOCKADDR_MAX_DATA_LEN (26)
/**
- * @brief *option_name* value for getsockopt() or setsockopt()
+ * @name Socket types
+ * @{
*/
-#define SO_SNDLOWAT 13 ///< Send "low water mark".
+#define SOCK_DGRAM (1) /**< Datagram socket */
+#define SOCK_RAW (2) /**< Raw socket */
+#define SOCK_SEQPACKET (3) /**< Sequenced-packet socket */
+#define SOCK_STREAM (4) /**< Stream socket */
+/** @} */
-/**
- * @brief *option_name* value for getsockopt() or setsockopt()
- */
-#define SO_SNDTIMEO 14 ///< Send timeout.
+#define SOL_SOCKET (-1) /**< Options to be accessed at socket level, not protocol level */
/**
- * @brief *option_name* value for getsockopt() or setsockopt()
+ * @name Option names
+ * @brief Option names for getsockopt() and setsockopt()
+ * @{
*/
-#define SO_TYPE 15 ///< Socket type.
-
-#define SOMAXCONN 16 ///< Maximum *backlog* size for listen()
+#define SO_ACCEPTCONN (0) /**< Socket is accepting connections. */
+#define SO_BROADCAST (1) /**< Transmission of broadcast messages is supported. */
+#define SO_DEBUG (2) /**< Debugging information is being recorded. */
+#define SO_DONTROUTE (3) /**< Bypass normal routing. */
+#define SO_ERROR (4) /**< Socket error status. */
+#define SO_KEEPALIVE (5) /**< Connections are kept alive with periodic messages. */
+#define SO_LINGER (6) /**< Socket lingers on close. */
+#define SO_OOBINLINE (7) /**< Out-of-band data is transmitted in line. */
+#define SO_RCVBUF (8) /**< Receive buffer size. */
+#define SO_RCVLOWAT (9) /**< Receive "low water mark". */
+#define SO_RCVTIMEO (10) /**< Receive timeout. */
+#define SO_REUSEADDR (11) /**< Reuse of local addresses is supported. */
+#define SO_SNDBUF (12) /**< Send buffer size. */
+#define SO_SNDLOWAT (13) /**< Send "low water mark". */
+#define SO_SNDTIMEO (14) /**< Send timeout. */
+#define SO_TYPE (15) /**< Socket type. */
+/** @} */
+
+typedef unsigned int sa_family_t; /**< address family type */
/**
- * @brief *how* value for shutdown()
+ * @brief Used to define the socket address.
*/
-#define SHUT_WR 1 ///< Disables further send operations.
+struct sockaddr {
+ sa_family_t sa_family; /**< Address family */
+ char sa_data[SOCKADDR_MAX_DATA_LEN]; /**< Socket address (variable length data) */
+};
/**
- * @brief *how* value for shutdown()
+ * @brief Implementation based socket address table.
+ * @extends struct sockaddr
*/
-#define SHUT_RD 2 ///< Disables further receive operations.
+struct sockaddr_storage {
+ sa_family_t ss_family; /**< Address family */
+ uint8_t ss_data[SOCKADDR_MAX_DATA_LEN]; /**< Socket address */
+};
-/**
- * @brief *how* value for shutdown()
- */
-#define SHUT_RDWR 3 ///< Disables further send and receive operations.
/**
* @brief Accept a new connection on a socket
@@ -260,27 +212,56 @@ int bind(int socket, const struct sockaddr *address,
int connect(int socket, const struct sockaddr *address, socklen_t address_len);
/**
- * @brief Get the socket options.
+ * @brief Get the name of the peer socket.
+ * @details The getpeername() function shall retrieve the peer address of the specified socket,
+ * store this address in the sockaddr structure pointed to by the @p address argument,
+ * and store the length of this address in the object pointed to by the @p address_len
+ * argument.
*
- * @see
- * The Open Group Base Specification Issue 7, getsockopt
+ * @see
+ * The Open Group Base Specification Issue 7, getpeername
*
*
- * @param[in] socket Specifies the file descriptor associated with the socket.
- * @param[in] level Protocol level this option applies to. Valid values
- * are defined in , prefixed with
- * ``SOL_``.
- * @param[in] option_name Defines the option to get. Valid values are defined
- * in , prefixed with ``SO_``.
- * @param[out] option_value Buffer to write the current value of the socket
- * option into.
- * @param[out] option_len Length of the option value in byte.
+ * @param[in] socket Specifies the file descriptor associated with the
+ * socket.
+ * @param[out] address Points to a sockaddr structure containing the peer
+ * address. The length and format of the address depend
+ * on the address family of the socket.
+ * @param[in,out] address_len Specifies the length of the sockaddr structure on input and the
+ * length of the stored address on output. If the address is greater
+ * than the length of the supplied sockaddr structure, the stored
+ * address shal be truncated.
+ * @return Upon successful completion, getpeername() shall return 0; otherwise,
+ * -1 shall be returned and errno set to indicate the error.
+ */
+int getpeername(int socket, struct sockaddr *__restrict address,
+ socklen_t *__restrict address_len);
+
+/**
+ * @brief Get the socket name.
+ * @details The getsockname() function shall retrieve the locally-bound name of the specified
+ * socket, store this address in the sockaddr structure pointed to by the @p address
+ * argument, and store the length of this address in the object pointed to by the
+ * @p address_len argument.
*
- * @return Upon successful completion, getsockopt() shall return 0; otherwise,
+ * @see
+ * The Open Group Base Specification Issue 7, getsockname
+ *
+ *
+ * @param[in] socket Specifies the file descriptor associated with the
+ * socket.
+ * @param[out] address Points to a sockaddr structure containing the peer
+ * address. The length and format of the address depend
+ * on the address family of the socket.
+ * @param[in,out] address_len Specifies the length of the sockaddr structure on input and the
+ * length of the stored address on output. If the address is greater
+ * than the length of the supplied sockaddr structure, the stored
+ * address shal be truncated.
+ * @return Upon successful completion, getsockname() shall return 0; otherwise,
* -1 shall be returned and errno set to indicate the error.
*/
-int getsockopt(int socket, int level, int option_name,
- void *__restrict option_value, socklen_t *__restrict option_len);
+int getsockname(int socket, struct sockaddr *__restrict address,
+ socklen_t *__restrict address_len);
/**
* @brief Listen for socket connections and limit the queue of incoming
@@ -396,9 +377,9 @@ ssize_t send(int socket, const void *buffer, size_t length, int flags);
* @details Shall send a message through a connection-mode or
* connectionless-mode socket. If the socket is a connectionless-mode
* socket, the message shall be sent to the address specified by
- * *dest_addr* if no pre-specified peer address has been set. If a
+ * @p address if no pre-specified peer address has been set. If a
* peer address has been pre-specified, either the message shall be
- * sent to the address specified by *dest_addr* (overriding the
+ * sent to the address specified by @p address (overriding the
* pre-specified peer address), or the function shall return -1 and
* set errno to EISCONN.
*
@@ -406,45 +387,23 @@ ssize_t send(int socket, const void *buffer, size_t length, int flags);
* The Open Group Base Specification Issue 7, sendto
*
*
- * @param[in] socket Specifies the socket file descriptor.
- * @param[in] message Points to the buffer containing the message to send.
- * @param[in] length Specifies the length of the message in bytes.
- * @param[in] flags Specifies the type of message reception. Support
- * for values other than 0 is not implemented yet.
- * @param[in] dest_addr Points to a sockaddr structure containing the
- * destination address. The length and format of the
- * address depend on the address family of the socket.
- * @param[in] dest_len Specifies the length of the sockaddr structure pointed
- * to by the *dest_addr* argument.
+ * @param[in] socket Specifies the socket file descriptor.
+ * @param[in] buffer Points to the buffer containing the message to send.
+ * @param[in] length Specifies the length of the message in bytes.
+ * @param[in] flags Specifies the type of message reception. Support
+ * for values other than 0 is not implemented yet.
+ * @param[in] address Points to a sockaddr structure containing the
+ * destination address. The length and format of the
+ * address depend on the address family of the socket.
+ * @param[in] address_len Specifies the length of the sockaddr structure pointed
+ * to by the @p address argument.
*
* @return Upon successful completion, send() shall return the number of bytes
* sent. Otherwise, -1 shall be returned and errno set to indicate the
* error.
*/
-ssize_t sendto(int socket, const void *message, size_t length, int flags,
- const struct sockaddr *dest_addr, socklen_t dest_len);
-
-/**
- * @brief Set the socket options.
- *
- * @see
- * The Open Group Base Specification Issue 7, setsockopt
- *
- *
- * @param[in] socket Specifies the file descriptor associated with the socket.
- * @param[in] level Protocol level this option applies to. Valid values
- * are defined in , prefixed with
- * ``SOL_``.
- * @param[in] option_name Defines the option to set. Valid values are defined
- * in , prefixed with ``SO_``.
- * @param[in] option_value Value for the option to set.
- * @param[in] option_len Length of the option value in byte.
- *
- * @return Upon successful completion, setsockopt() shall return 0; otherwise,
- * -1 shall be returned and errno set to indicate the error.
- */
-int setsockopt(int socket, int level, int option_name, const void *option_value,
- socklen_t option_len);
+ssize_t sendto(int socket, const void *buffer, size_t length, int flags,
+ const struct sockaddr *address, socklen_t address_len);
/**
* @brief Create an endpoint for communication.
@@ -469,6 +428,34 @@ int setsockopt(int socket, int level, int option_name, const void *option_value,
*/
int socket(int domain, int type, int protocol);
+/**
+ * @todo implement out these functions
+ * @{
+ */
+static inline int getsockopt(int socket, int level, int option_name, void *option_value,
+ socklen_t *option_len)
+{
+ (void)socket;
+ (void)level;
+ (void)option_name;
+ (void)option_value;
+ (void)option_len;
+ return -1;
+}
+
+static inline int setsockopt(int socket, int level, int option_name, const void *option_value,
+ socklen_t option_len)
+{
+ (void)socket;
+ (void)level;
+ (void)option_name;
+ (void)option_value;
+ (void)option_len;
+ return -1;
+}
+
+/** @} */
+
#ifdef __cplusplus
}
#endif
diff --git a/sys/posix/pnet/netinet_in.c b/sys/posix/pnet/netinet_in.c
deleted file mode 100644
index 7ef06230c..000000000
--- a/sys/posix/pnet/netinet_in.c
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (C) 2013 Freie Universität Berlin
- *
- * This file is subject to the terms and conditions of the GNU Lesser
- * General Public License v2.1. See the file LICENSE in the top level
- * directory for more details.
- */
-
-/**
- * @{
- * @file
- * @brief Providing values for in6addr_any and in6addr_loopback.
- * @author Martine Lenders
- */
-#include
-
-const struct sockaddr_in6 in6addr_any = {{AF_INET6, 0, 0, IN6ADDR_ANY_INIT}, 0};
-const struct sockaddr_in6 in6addr_loopback = {{
- AF_INET6, 0, 0, IN6ADDR_LOOPBACK_INIT
- }, 0
-};
-
-/**
- * @}
- */
diff --git a/sys/posix/pnet/sys_socket.c b/sys/posix/pnet/sys_socket.c
deleted file mode 100644
index bc870a9f6..000000000
--- a/sys/posix/pnet/sys_socket.c
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * Copyright (C) 2013 Freie Universität Berlin
- *
- * This file is subject to the terms and conditions of the GNU Lesser
- * General Public License v2.1. See the file LICENSE in the top level
- * directory for more details.
- */
-
-/**
- * @{
- * @file
- * @brief Providing implementation for POSIX socket wrapper.
- * @author Martine Lenders
- * @todo
- */
-
-#include "sys/socket.h"
-
-int flagless_send(int fd, const void *buf, size_t len)
-{
- (void)fd;
- (void)buf;
- (void)len;
-
- return -1;
-}
-
-int flagless_recv(int fd, void *buf, size_t len)
-{
- return (int)socket_base_recv(fd, buf, (uint32_t)len, 0);
-}
-
-int socket(int domain, int type, int protocol)
-{
- (void)domain;
- (void)type;
- (void)protocol;
-
- return -1;
-}
-
-
-int accept(int socket, struct sockaddr *restrict address,
- socklen_t *restrict address_len)
-{
- (void)socket;
- (void)address;
- (void)address_len;
-
- return -1;
-}
-
-int bind(int socket, const struct sockaddr *address, socklen_t address_len)
-{
- (void)socket;
- (void)address;
- (void)address_len;
-
- return -1;
-}
-
-int connect(int socket, const struct sockaddr *address, socklen_t address_len)
-{
- (void)socket;
- (void)address;
- (void)address_len;
-
- return -1;
-}
-
-int getsockopt(int socket, int level, int option_name,
- void *restrict option_value, socklen_t *restrict option_len)
-{
- // TODO
- (void) socket;
- (void) level;
- (void) option_name;
- (void) option_value;
- (void) option_len;
-
- return -1;
-}
-
-int listen(int socket, int backlog)
-{
- (void)socket;
- (void)backlog;
-
- return -1;
-}
-
-ssize_t recv(int socket, void *buffer, size_t length, int flags)
-{
- (void)socket;
- (void)buffer;
- (void)length;
- (void)flags;
-
- return -1;
-}
-
-ssize_t recvfrom(int socket, void *restrict buffer, size_t length, int flags,
- struct sockaddr *restrict address,
- socklen_t *restrict address_len)
-{
- (void)socket;
- (void)buffer;
- (void)length;
- (void)flags;
- (void)address;
- (void)address_len;
-
- return -1;
-}
-
-ssize_t send(int socket, const void *buffer, size_t length, int flags)
-{
- (void)socket;
- (void)buffer;
- (void)length;
- (void)flags;
- return -1;
-}
-
-ssize_t sendto(int socket, const void *message, size_t length, int flags,
- const struct sockaddr *dest_addr, socklen_t dest_len)
-{
- // TODO
- (void)socket;
- (void)message;
- (void)length;
- (void)flags;
- (void)dest_addr;
- (void)dest_len;
-
- return -1;
-}
-
-int setsockopt(int socket, int level, int option_name, const void *option_value,
- socklen_t option_len)
-{
- // TODO
- (void) socket;
- (void) level;
- (void) option_name;
- (void) option_value;
- (void) option_len;
-
- return -1;
-}
-
-/**
- * @}
- */
diff --git a/sys/posix/pnet/Makefile b/sys/posix/sockets/Makefile
similarity index 58%
rename from sys/posix/pnet/Makefile
rename to sys/posix/sockets/Makefile
index 48422e909..7f84cdea3 100644
--- a/sys/posix/pnet/Makefile
+++ b/sys/posix/sockets/Makefile
@@ -1 +1,3 @@
+MODULE = posix_sockets
+
include $(RIOTBASE)/Makefile.base
diff --git a/sys/posix/pnet/doc.txt b/sys/posix/sockets/doc.txt
similarity index 78%
rename from sys/posix/pnet/doc.txt
rename to sys/posix/sockets/doc.txt
index cb5bdbaa2..c02bd2f6f 100644
--- a/sys/posix/pnet/doc.txt
+++ b/sys/posix/sockets/doc.txt
@@ -7,8 +7,8 @@
*/
/**
- * @defgroup pnet Network related POSIX wrapper of RIOT
- * @brief Network related POSIX header files
+ * @defgroup posix_sockets POSIX sockets
+ * @brief POSIX socket wrapper of RIOT's @ref net_conn
* @see
* The Open Group Specifications Issue 7
*
diff --git a/sys/posix/sockets/posix_sockets.c b/sys/posix/sockets/posix_sockets.c
new file mode 100644
index 000000000..e1c201598
--- /dev/null
+++ b/sys/posix/sockets/posix_sockets.c
@@ -0,0 +1,890 @@
+/*
+ * Copyright (C) 2015 Freie Universität Berlin
+ *
+ * This file is subject to the terms and conditions of the GNU Lesser
+ * General Public License v2.1. See the file LICENSE in the top level
+ * directory for more details.
+ */
+
+/**
+ * @{
+ * @file
+ * @brief Providing implementation for POSIX socket wrapper.
+ * @author Martine Lenders
+ * @todo
+ */
+
+#include
+#include
+#include
+#include
+
+#include "fd.h"
+#include "mutex.h"
+#include "net/conn.h"
+#include "net/ipv4/addr.h"
+#include "net/ipv6/addr.h"
+#include "random.h"
+
+#include "sys/socket.h"
+#include "netinet/in.h"
+
+#define SOCKET_POOL_SIZE (4)
+
+/**
+ * @brief Unitfied connection type.
+ */
+typedef union {
+ /* is not supposed to be used */
+ /* cppcheck-suppress unusedStructMember */
+ int undef; /**< for case that no connection module is present */
+#ifdef MODULE_CONN_IP
+ conn_ip_t raw; /**< raw IP connection */
+#endif /* MODULE_CONN_IP */
+#ifdef MODULE_CONN_TCP
+ conn_tcp_t tcp; /**< TCP connection */
+#endif /* MODULE_CONN_TCP */
+#ifdef MODULE_CONN_UDP
+ conn_udp_t udp; /**< UDP connection */
+#endif /* MODULE_CONN_UDP */
+} socket_conn_t;
+
+typedef struct {
+ int fd;
+ sa_family_t domain;
+ int type;
+ int protocol;
+ bool bound;
+ socket_conn_t conn;
+} socket_t;
+
+socket_t _pool[SOCKET_POOL_SIZE];
+mutex_t _pool_mutex = MUTEX_INIT;
+
+const struct sockaddr_in6 in6addr_any = {AF_INET6, 0, 0, IN6ADDR_ANY_INIT, 0};
+const struct sockaddr_in6 in6addr_loopback = {
+ AF_INET6, 0, 0, IN6ADDR_LOOPBACK_INIT, 0
+};
+
+static socket_t *_get_free_socket(void)
+{
+ for (int i = 0; i < SOCKET_POOL_SIZE; i++) {
+ if (_pool[i].domain == AF_UNSPEC) {
+ return &_pool[i];
+ }
+ }
+ return NULL;
+}
+
+static socket_t *_get_socket(int fd)
+{
+ for (int i = 0; i < SOCKET_POOL_SIZE; i++) {
+ if (_pool[i].fd == fd) {
+ return &_pool[i];
+ }
+ }
+ return NULL;
+}
+
+static inline int _choose_ipproto(int type, int protocol)
+{
+ switch (type) {
+#ifdef MODULE_CONN_TCP
+ case SOCK_STREAM:
+ if ((protocol == 0) || (protocol == IPPROTO_TCP)) {
+ return protocol;
+ }
+ else {
+ errno = EPROTOTYPE;
+ }
+ break;
+#endif
+#ifdef MODULE_CONN_UDP
+ case SOCK_DGRAM:
+ if ((protocol == 0) || (protocol == IPPROTO_UDP)) {
+ return protocol;
+ }
+ else {
+ errno = EPROTOTYPE;
+ }
+ break;
+#endif
+#ifdef MODULE_CONN_IP
+ case SOCK_RAW:
+ return protocol;
+#endif
+ default:
+ (void)protocol;
+ break;
+ }
+ errno = EPROTONOSUPPORT;
+ return -1;
+}
+
+static inline void _htons_port(uint16_t *port)
+{
+ *port = htons(*port);
+}
+
+static inline ipv4_addr_t *_in_addr_ptr(struct sockaddr_storage *addr)
+{
+ return (ipv4_addr_t *)(&((struct sockaddr_in *)addr)->sin_addr);
+}
+
+static inline uint16_t *_in_port_ptr(struct sockaddr_storage *addr)
+{
+ return &((struct sockaddr_in *)addr)->sin_port;
+}
+
+static inline ipv6_addr_t *_in6_addr_ptr(struct sockaddr_storage *addr)
+{
+ return (ipv6_addr_t *)(&((struct sockaddr_in6 *)addr)->sin6_addr);
+}
+
+static inline uint16_t *_in6_port_ptr(struct sockaddr_storage *addr)
+{
+ return &((struct sockaddr_in6 *)addr)->sin6_port;
+}
+
+static inline socklen_t _addr_truncate(struct sockaddr *out, socklen_t out_len,
+ struct sockaddr_storage *in, socklen_t target_size)
+{
+ out_len = (out_len < target_size) ? out_len : target_size;
+ memcpy(out, in, out_len);
+ return out_len;
+}
+
+static inline int _get_data_from_sockaddr(const struct sockaddr *address, size_t address_len,
+ void **addr, size_t *addr_len, uint16_t *port)
+{
+ switch (address->sa_family) {
+ case AF_INET:
+ if (address_len < sizeof(struct sockaddr_in)) {
+ errno = EINVAL;
+ return -1;
+ }
+ struct sockaddr_in *in_addr = (struct sockaddr_in *)address;
+ *addr = &in_addr->sin_addr;
+ *addr_len = sizeof(ipv4_addr_t);
+ /* XXX sin_port is in network byteorder */
+ *port = ntohs(in_addr->sin_port);
+ break;
+ case AF_INET6:
+ if (address_len < sizeof(struct sockaddr_in6)) {
+ errno = EINVAL;
+ return -1;
+ }
+ struct sockaddr_in6 *in6_addr = (struct sockaddr_in6 *)address;
+ *addr = &in6_addr->sin6_addr;
+ *addr_len = sizeof(ipv6_addr_t);
+ /* XXX sin6_port is in network byteorder */
+ *port = ntohs(in6_addr->sin6_port);
+ break;
+ default:
+ errno = EAFNOSUPPORT;
+ return -1;
+ }
+ return 0;
+}
+
+static int socket_close(int socket)
+{
+ socket_t *s;
+ int res = 0;
+ if ((unsigned)(socket - 1) > (SOCKET_POOL_SIZE - 1)) {
+ return -1;
+ }
+ mutex_lock(&_pool_mutex);
+ s = &_pool[socket];
+ if (s->bound) {
+ switch (s->domain) {
+ case AF_INET:
+ case AF_INET6:
+ switch (s->type) {
+#ifdef MODULE_CONN_UDP
+ case SOCK_DGRAM:
+ conn_udp_close(&s->conn.udp);
+ break;
+#endif
+#ifdef MODULE_CONN_IP
+ case SOCK_RAW:
+ conn_ip_close(&s->conn.raw);
+ break;
+#endif
+#ifdef MODULE_CONN_TCP
+ case SOCK_STREAM:
+ conn_tcp_close(&s->conn.tcp);
+ break;
+#endif
+ default:
+ errno = EOPNOTSUPP;
+ res = -1;
+ break;
+ }
+ default:
+ res = -1;
+ break;
+ }
+ }
+ s->domain = AF_UNSPEC;
+ mutex_unlock(&_pool_mutex);
+ return res;
+}
+
+static ssize_t socket_read(int socket, void *buf, size_t n)
+{
+ return recv(socket, buf, n, 0);
+}
+
+static ssize_t socket_write(int socket, const void *buf, size_t n)
+{
+ return send(socket, buf, n, 0);
+}
+
+int socket(int domain, int type, int protocol)
+{
+ int res = 0;
+ socket_t *s;
+ mutex_lock(&_pool_mutex);
+ s = _get_free_socket();
+ if (s == NULL) {
+ errno = ENFILE;
+ mutex_unlock(&_pool_mutex);
+ return -1;
+ }
+ switch (domain) {
+ case AF_INET:
+ case AF_INET6:
+ s->domain = domain;
+ s->type = type;
+ if ((s->protocol = _choose_ipproto(type, protocol)) < 0) {
+ res = -1;
+ }
+ break;
+
+ default:
+ (void)type;
+ (void)protocol;
+ errno = EAFNOSUPPORT;
+ res = -1;
+ }
+ if (res == 0) {
+ /* TODO: add read and write */
+ int fd = fd_new(s - _pool, socket_read, socket_write, socket_close);
+ if (fd < 0) {
+ errno = ENFILE;
+ res = -1;
+ }
+ else {
+ s->fd = res = fd;
+ }
+ }
+ s->bound = false;
+ mutex_unlock(&_pool_mutex);
+ return res;
+}
+
+
+int accept(int socket, struct sockaddr *restrict address,
+ socklen_t *restrict address_len)
+{
+ socket_t *s, *new_s = NULL;
+ int res = 0;
+ /* May be kept unassigned if no conn module is available */
+ /* cppcheck-suppress unassignedVariable */
+ struct sockaddr_storage tmp;
+ void *addr;
+ uint16_t *port;
+ socklen_t tmp_len;
+ mutex_lock(&_pool_mutex);
+ s = _get_socket(socket);
+ if (s == NULL) {
+ mutex_unlock(&_pool_mutex);
+ errno = ENOTSOCK;
+ return -1;
+ }
+ if (!s->bound) {
+ mutex_unlock(&_pool_mutex);
+ errno = EINVAL;
+ return -1;
+ }
+ switch (s->domain) {
+ case AF_INET:
+ addr = _in_addr_ptr(&tmp);
+ port = _in_port_ptr(&tmp);
+ tmp_len = sizeof(struct sockaddr_in);
+ break;
+ case AF_INET6:
+ addr = _in6_addr_ptr(&tmp);
+ port = _in6_port_ptr(&tmp);
+ tmp_len = sizeof(struct sockaddr_in6);
+ break;
+ default:
+ (void)address;
+ (void)address_len;
+ (void)new_s;
+ (void)tmp;
+ (void)addr;
+ (void)port;
+ (void)tmp_len;
+ errno = EPROTO;
+ res = -1;
+ break;
+ }
+ switch (s->type) {
+#ifdef MODULE_CONN_TCP
+ case SOCK_STREAM:
+ new_s = _get_free_socket();
+ if (new_s == NULL) {
+ errno = ENFILE;
+ res = -1;
+ break;
+ }
+ if ((res = conn_tcp_accept(&s->conn.tcp, &new_s->conn.tcp)) < 0) {
+ errno = -res;
+ res = -1;
+ break;
+ }
+ else if ((address != NULL) && (address_len != NULL)) {
+ /* TODO: add read and write */
+ int fd = fd_new(new_s - _pool, NULL, NULL, socket_close);
+ if (fd < 0) {
+ errno = ENFILE;
+ res = -1;
+ break;
+ }
+ else {
+ new_s->fd = res = fd;
+ }
+ new_s->domain = s->domain;
+ new_s->type = s->type;
+ new_s->protocol = s->protocol;
+ tmp.ss_family = s->domain;
+ if ((res = conn_tcp_getpeeraddr(&s->conn.tcp, addr, port)) < 0) {
+ errno = -res;
+ res = -1;
+ break;
+ }
+ _htons_port(port); /* XXX: sin(6)_port is supposed to be network byte
+ * order */
+ *address_len = _addr_truncate(address, *address_len, &tmp, tmp_len);
+ }
+ break;
+#endif
+ default:
+ errno = EOPNOTSUPP;
+ res = -1;
+ break;
+ }
+ mutex_unlock(&_pool_mutex);
+ return res;
+}
+
+int bind(int socket, const struct sockaddr *address, socklen_t address_len)
+{
+ socket_t *s;
+ int res = 0;
+ void *addr;
+ size_t addr_len;
+ uint16_t port;
+ mutex_lock(&_pool_mutex);
+ s = _get_socket(socket);
+ mutex_unlock(&_pool_mutex);
+ if (s == NULL) {
+ errno = ENOTSOCK;
+ return -1;
+ }
+ if (address->sa_family != s->domain) {
+ errno = EAFNOSUPPORT;
+ return -1;
+ }
+ if (_get_data_from_sockaddr(address, address_len, &addr, &addr_len, &port) < 0) {
+ return -1;
+ }
+ switch (s->type) {
+#ifdef MODULE_CONN_IP
+ case SOCK_RAW:
+ (void)port;
+ if ((res = conn_ip_create(&s->conn.raw, addr, addr_len, s->domain, s->protocol)) < 0) {
+ errno = -res;
+ return -1;
+ }
+ break;
+#endif
+#ifdef MODULE_CONN_TCP
+ case SOCK_STREAM:
+ if ((res = conn_tcp_create(&s->conn.tcp, addr, addr_len, s->domain, port)) < 0) {
+ errno = -res;
+ return -1;
+ }
+ break;
+#endif
+#ifdef MODULE_CONN_UDP
+ case SOCK_DGRAM:
+ if ((res = conn_udp_create(&s->conn.udp, addr, addr_len, s->domain, port)) < 0) {
+ errno = -res;
+ return -1;
+ }
+ break;
+#endif
+ default:
+ (void)addr;
+ (void)addr_len;
+ (void)port;
+ (void)res;
+ errno = EOPNOTSUPP;
+ return -1;
+ }
+ s->bound = true;
+ return 0;
+}
+
+int connect(int socket, const struct sockaddr *address, socklen_t address_len)
+{
+ socket_t *s;
+ int res = 0;
+ void *addr;
+ size_t addr_len;
+ uint16_t port;
+ mutex_lock(&_pool_mutex);
+ s = _get_socket(socket);
+ mutex_unlock(&_pool_mutex);
+ if (s == NULL) {
+ errno = ENOTSOCK;
+ return -1;
+ }
+ if (!s->bound) {
+ errno = EINVAL;
+ return -1;
+ }
+ if (address->sa_family != s->domain) {
+ errno = EAFNOSUPPORT;
+ return -1;
+ }
+ if (_get_data_from_sockaddr(address, address_len, &addr, &addr_len, &port) < 0) {
+ return -1;
+ }
+ switch (s->type) {
+#ifdef MODULE_CONN_TCP
+ case SOCK_STREAM:
+ /* XXX sin_port is in network byteorder */
+ if ((res = conn_tcp_connect(&s->conn.tcp, addr, addr_len, port)) < 0) {
+ errno = -res;
+ return -1;
+ }
+ break;
+#endif
+ default:
+ (void)res;
+ errno = EPROTOTYPE;
+ return -1;
+ }
+ return 0;
+}
+
+int getpeername(int socket, struct sockaddr *__restrict address,
+ socklen_t *__restrict address_len)
+{
+ socket_t *s;
+ int res = 0;
+ /* May be kept unassigned if no conn module is available */
+ /* cppcheck-suppress unassignedVariable */
+ struct sockaddr_storage tmp;
+ void *addr;
+ uint16_t *port;
+ socklen_t tmp_len;
+ mutex_lock(&_pool_mutex);
+ s = _get_socket(socket);
+ mutex_unlock(&_pool_mutex);
+ if (s == NULL) {
+ errno = ENOTSOCK;
+ return -1;
+ }
+ switch (s->domain) {
+ case AF_INET:
+ addr = _in_addr_ptr(&tmp);
+ port = _in_port_ptr(&tmp);
+ tmp_len = sizeof(struct sockaddr_in);
+ break;
+ case AF_INET6:
+ addr = _in6_addr_ptr(&tmp);
+ port = _in6_port_ptr(&tmp);
+ tmp_len = sizeof(struct sockaddr_in6);
+ break;
+ default:
+ (void)address;
+ (void)address_len;
+ (void)tmp;
+ (void)addr;
+ (void)port;
+ (void)tmp_len;
+ (void)res;
+ errno = EBADF;
+ return -1;
+ }
+ if (*address_len != tmp_len) {
+ errno = EINVAL;
+ return -1;
+ }
+ switch (s->type) {
+#ifdef MODULE_CONN_TCP
+ case SOCK_STREAM:
+ if ((res = conn_tcp_getpeeraddr(&s->conn.tcp, addr, port)) < 0) {
+ errno = -res;
+ return -1;
+ }
+ break;
+#endif
+ default:
+ errno = ENOTCONN;
+ return -1;
+ }
+ tmp.ss_family = s->domain;
+ _htons_port(port); /* XXX: sin(6)_port is supposed to be network byte
+ * order */
+ *address_len = _addr_truncate(address, *address_len, &tmp, tmp_len);
+ return 0;
+}
+
+int getsockname(int socket, struct sockaddr *__restrict address,
+ socklen_t *__restrict address_len)
+{
+ socket_t *s;
+ int res = 0;
+ /* May be kept unassigned if no conn module is available */
+ /* cppcheck-suppress unassignedVariable */
+ struct sockaddr_storage tmp;
+ void *addr;
+ uint16_t *port;
+ socklen_t tmp_len;
+ mutex_lock(&_pool_mutex);
+ s = _get_socket(socket);
+ mutex_unlock(&_pool_mutex);
+ if (s == NULL) {
+ errno = ENOTSOCK;
+ return -1;
+ }
+ if (!s->bound) {
+ memset(address, 0, *address_len);
+ return 0;
+ }
+ switch (s->domain) {
+ case AF_INET:
+ addr = _in_addr_ptr(&tmp);
+ port = _in_port_ptr(&tmp);
+ tmp_len = sizeof(struct sockaddr_in);
+ break;
+ case AF_INET6:
+ addr = _in6_addr_ptr(&tmp);
+ port = _in6_port_ptr(&tmp);
+ tmp_len = sizeof(struct sockaddr_in6);
+ break;
+ default:
+ (void)address;
+ (void)address_len;
+ (void)tmp;
+ (void)addr;
+ (void)port;
+ (void)tmp_len;
+ (void)res;
+ errno = EBADF;
+ return -1;
+ }
+ if (*address_len != tmp_len) {
+ errno = EINVAL;
+ return -1;
+ }
+ switch (s->type) {
+#ifdef MODULE_CONN_UDP
+ case SOCK_DGRAM:
+ if ((res = conn_udp_getlocaladdr(&s->conn.udp, addr, port)) < 0) {
+ errno = -res;
+ return -1;
+ }
+ break;
+#endif
+#ifdef MODULE_CONN_IP
+ case SOCK_RAW:
+ if ((res = conn_ip_getlocaladdr(&s->conn.raw, addr)) < 0) {
+ errno = -res;
+ return -1;
+ }
+ break;
+#endif
+#ifdef MODULE_CONN_TCP
+ case SOCK_STREAM:
+ if ((res = conn_tcp_getlocaladdr(&s->conn.tcp, addr, port)) < 0) {
+ errno = -res;
+ return -1;
+ }
+ break;
+#endif
+ default:
+ errno = EOPNOTSUPP;
+ return -1;
+ }
+ tmp.ss_family = AF_INET;
+ _htons_port(port); /* XXX: sin(6)_port is supposed to be network byte
+ * order */
+ *address_len = _addr_truncate(address, *address_len, &tmp, tmp_len);
+ return 0;
+}
+
+int listen(int socket, int backlog)
+{
+ socket_t *s;
+ int res = 0;
+ mutex_lock(&_pool_mutex);
+ s = _get_socket(socket);
+ mutex_unlock(&_pool_mutex);
+ if (!s->bound) {
+ errno = EINVAL;
+ return -1;
+ }
+ switch (s->domain) {
+ case AF_INET:
+ case AF_INET6:
+ switch (s->type) {
+#ifdef MODULE_CONN_TCP
+ case SOCK_STREAM:
+ if ((res = conn_tcp_listen(&s->conn.tcp, backlog)) < 0) {
+ errno = -res;
+ return -1;
+ }
+ break;
+#endif
+ default:
+ errno = EOPNOTSUPP;
+ return -1;
+ }
+ break;
+ default:
+ (void)backlog;
+ (void)res;
+ errno = EAFNOSUPPORT;
+ return -1;
+ }
+ return 0;
+}
+
+ssize_t recv(int socket, void *buffer, size_t length, int flags)
+{
+ return recvfrom(socket, buffer, length, flags, NULL, NULL);
+}
+
+ssize_t recvfrom(int socket, void *restrict buffer, size_t length, int flags,
+ struct sockaddr *restrict address,
+ socklen_t *restrict address_len)
+{
+ socket_t *s;
+ int res = 0;
+ /* May be kept unassigned if no conn module is available */
+ /* cppcheck-suppress unassignedVariable */
+ struct sockaddr_storage tmp;
+ void *addr;
+ size_t addr_len;
+ uint16_t *port;
+ socklen_t tmp_len;
+ (void)flags;
+ mutex_lock(&_pool_mutex);
+ s = _get_socket(socket);
+ mutex_unlock(&_pool_mutex);
+ if (s == NULL) {
+ errno = ENOTSOCK;
+ return -1;
+ }
+ if (!s->bound) {
+ errno = EINVAL;
+ return -1;
+ }
+ switch (s->domain) {
+ case AF_INET:
+ addr = _in_addr_ptr(&tmp);
+ port = _in_port_ptr(&tmp);
+ addr_len = sizeof(ipv4_addr_t);
+ tmp_len = sizeof(struct sockaddr_in);
+ break;
+ case AF_INET6:
+ addr = _in6_addr_ptr(&tmp);
+ port = _in6_port_ptr(&tmp);
+ addr_len = sizeof(ipv6_addr_t);
+ tmp_len = sizeof(struct sockaddr_in6);
+ break;
+ default:
+ (void)buffer;
+ (void)length;
+ (void)address;
+ (void)address_len;
+ (void)tmp;
+ (void)addr;
+ (void)port;
+ (void)tmp_len;
+ errno = EAFNOSUPPORT;
+ return -1;
+ }
+ switch (s->type) {
+#ifdef MODULE_CONN_UDP
+ case SOCK_DGRAM:
+ if ((res = conn_udp_recvfrom(&s->conn.udp, buffer, length, addr, &addr_len,
+ port)) < 0) {
+ errno = -res;
+ return -1;
+ }
+ break;
+#endif
+#ifdef MODULE_CONN_IP
+ case SOCK_RAW:
+ if ((res = conn_ip_recvfrom(&s->conn.raw, buffer, length, addr, &addr_len)) < 0) {
+ errno = -res;
+ return -1;
+ }
+ break;
+#endif
+#ifdef MODULE_CONN_TCP
+ case SOCK_STREAM:
+ if ((res = conn_tcp_recv(&s->conn.tcp, buffer, length)) < 0) {
+ errno = -res;
+ return -1;
+ }
+ if ((res = conn_tcp_getpeeraddr(&s->conn.tcp, addr, port)) < 0) {
+ errno = -res;
+ return -1;
+ }
+ break;
+#endif
+ default:
+ (void)addr_len;
+ errno = EOPNOTSUPP;
+ return -1;
+ }
+ if ((address != NULL) && (address_len != NULL)) {
+ tmp.ss_family = s->domain;
+ _htons_port(port); /* XXX: sin_port is supposed to be network byte
+ * order */
+ *address_len = _addr_truncate(address, *address_len, &tmp, tmp_len);
+ }
+ return res;
+}
+
+ssize_t send(int socket, const void *buffer, size_t length, int flags)
+{
+ return sendto(socket, buffer, length, flags, NULL, 0);
+}
+
+ssize_t sendto(int socket, const void *buffer, size_t length, int flags,
+ const struct sockaddr *address, socklen_t address_len)
+{
+ socket_t *s;
+ int res = 0;
+ void *addr = NULL;
+ size_t addr_len = 0;
+ uint16_t port = 0;
+ (void)flags;
+ mutex_lock(&_pool_mutex);
+ s = _get_socket(socket);
+ mutex_unlock(&_pool_mutex);
+ if (s == NULL) {
+ errno = ENOTSOCK;
+ return -1;
+ }
+ if (address != NULL) {
+ if (address->sa_family != s->domain) {
+ errno = EAFNOSUPPORT;
+ return -1;
+ }
+ if (_get_data_from_sockaddr(address, address_len, &addr, &addr_len, &port) < 0) {
+ return -1;
+ }
+ }
+ switch (s->type) {
+#ifdef MODULE_CONN_IP
+ case SOCK_RAW:
+ if ((address != NULL) && (s->bound)) {
+ uint8_t src_addr[sizeof(ipv6_addr_t)];
+ size_t src_len;
+ int res = conn_ip_getlocaladdr(&s->conn.raw, src_addr);
+ if (res < 0) {
+ errno = ENOTSOCK; /* Something seems to be wrong with the socket */
+ return -1;
+ }
+ src_len = (size_t)res;
+ /* cppcheck bug? res is read below in l824 */
+ /* cppcheck-suppress unreadVariable */
+ res = conn_ip_sendto(buffer, length, src_addr, src_len, addr, addr_len, s->domain,
+ s->protocol);
+ }
+ else if (address != NULL) {
+ res = conn_ip_sendto(buffer, length, NULL, 0, addr, addr_len, s->domain,
+ s->protocol);
+ }
+ else {
+ errno = ENOTCONN;
+ return -1;
+ }
+ if (res < 0) {
+ errno = -res;
+ return -1;
+ }
+ break;
+#endif
+#ifdef MODULE_CONN_TCP
+ case SOCK_STREAM:
+ if (!s->bound) {
+ errno = ENOTCONN;
+ return -1;
+ }
+ if (address != NULL) {
+ errno = EISCONN;
+ return -1;
+ }
+ if ((res = conn_tcp_send(&s->conn.tcp, buffer, length)) < 0) {
+ errno = -res;
+ return -1;
+ }
+ break;
+#endif
+#ifdef MODULE_CONN_UDP
+ case SOCK_DGRAM:
+ if ((address != NULL) && (s->bound)) {
+ uint8_t src_addr[sizeof(ipv6_addr_t)];
+ size_t src_len;
+ uint16_t sport;
+ int res = conn_udp_getlocaladdr(&s->conn.udp, src_addr, &sport);
+ if (res < 0) {
+ errno = ENOTSOCK; /* Something seems to be wrong with the socket */
+ return -1;
+ }
+ src_len = (size_t)res;
+ /* cppcheck bug? res is read below in l824 */
+ /* cppcheck-suppress unreadVariable */
+ res = conn_udp_sendto(buffer, length, src_addr, src_len, addr, addr_len, s->domain,
+ sport, port);
+ }
+ else if (address != NULL) {
+ uint16_t sport = (uint16_t)genrand_uint32_range(1LU << 10U, 1LU << 16U);
+ res = conn_udp_sendto(buffer, length, NULL, 0, addr, addr_len, s->domain,
+ sport, port);
+ }
+ else {
+ errno = ENOTCONN;
+ return -1;
+ }
+ if (res < 0) {
+ errno = -res;
+ return -1;
+ }
+ break;
+#endif
+ default:
+ (void)buffer;
+ (void)length;
+ errno = EOPNOTSUPP;
+ return -1;
+ }
+ return res;
+}
+
+
+/**
+ * @}
+ */