diff --git a/sys/Makefile b/sys/Makefile index c95de75d951a6..d1ce84a3e9d14 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 49ff4789e87d5..3313688cac9e0 100644 --- a/sys/Makefile.include +++ b/sys/Makefile.include @@ -13,7 +13,7 @@ endif ifneq (,$(filter posix,$(USEMODULE))) USEMODULE_INCLUDES += $(RIOTBASE)/sys/posix/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 91841ea5c1a3e..8bb06d74e2de3 100644 --- a/sys/posix/include/arpa/inet.h +++ b/sys/posix/include/arpa/inet.h @@ -7,7 +7,7 @@ */ /** - * @addtogroup pnet + * @addtogroup posix_sockets * @{ */ @@ -24,80 +24,16 @@ #define ARPA_INET_H #include +#include -#include "net_help.h" #include "inet_ntop.h" #include "inet_pton.h" +#include "sys/bytes.h" #ifdef __cplusplus extern "C" { #endif -typedef uint16_t in_port_t; ///< Internet port type -typedef uint32_t in_addr_t; ///< IPv4 address type - -#define INET_ADDRSTRLEN 16 ///< Length of the string form for IPv4. -#define INET6_ADDRSTRLEN 46 ///< Length of the string form for IPv6. - -/** - * 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) - #ifdef __cplusplus } #endif diff --git a/sys/posix/include/netinet/in.h b/sys/posix/include/netinet/in.h index 1530fc7173bc6..54b8e55f848d1 100644 --- a/sys/posix/include/netinet/in.h +++ b/sys/posix/include/netinet/in.h @@ -7,7 +7,7 @@ */ /** - * @addtogroup pnet + * @addtogroup posix_sockets * @{ */ @@ -25,135 +25,243 @@ #include #include -#include -#include "net/ng_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 {{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}} - /** - * 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 {{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}} - /** - * 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 Protocol version 6 */ +#define IPPROTO_RAW (PROTNUM_IPV6_NONXT) /**< 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 0000000000000..48899abd4906f --- /dev/null +++ b/sys/posix/include/sys/bytes.h @@ -0,0 +1,87 @@ +/* + * 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. + */ +#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) + + +#ifdef __cplusplus +} +#endif + +#endif /* BYTES_H_ */ +/** @} */ diff --git a/sys/posix/include/sys/socket.h b/sys/posix/include/sys/socket.h index 925ab2cddf67d..730f093c9edff 100644 --- a/sys/posix/include/sys/socket.h +++ b/sys/posix/include/sys/socket.h @@ -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,134 +38,54 @@ #define __SOCKADDR_COMMON_SIZE (sizeof (unsigned short int)) #endif +#include #include - -#include "cpu.h" - -#include "socket_base/socket.h" +#include #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() - */ -#define SO_SNDBUF 12 ///< Send buffer size. - -/** - * @brief *option_name* value for getsockopt() or setsockopt() - */ -#define SO_SNDLOWAT 13 ///< Send "low water mark". - -/** - * @brief *option_name* value for getsockopt() or setsockopt() + * @name Adress domains + * @{ */ -#define SO_SNDTIMEO 14 ///< Send timeout. +#define AF_UNSPEC (0) /**< Unspecified */ +#define AF_INET (1) /**< Internet domain socket for use with IPv4 addresses */ +#define AF_INET6 (2) /**< Internet domain socket for use with IPv6 addresses */ +#define AF_UNIX (3) /**< Unix domain socket */ +/** @} */ /** - * @brief *option_name* value for getsockopt() or setsockopt() + * @name Socket types + * @{ */ -#define SO_TYPE 15 ///< Socket type. +#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 */ +/** @} */ -#define SOMAXCONN 16 ///< Maximum *backlog* size for listen() +typedef size_t socklen_t; /**< socket address length */ +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[14]; /**< 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 */ + char ss_data[14]; /**< address data */ +}; -/** - * @brief *how* value for shutdown() - */ -#define SHUT_RDWR 3 ///< Disables further send and receive operations. /** * @brief Accept a new connection on a socket @@ -259,27 +185,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. + * + * @see + * The Open Group Base Specification Issue 7, getsockname + * * - * @return Upon successful completion, getsockopt() shall return 0; otherwise, + * @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 @@ -423,28 +378,6 @@ ssize_t send(int socket, const void *buffer, size_t length, int flags); 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); - /** * @brief Create an endpoint for communication. * @details Shall create an unbound socket in a communications domain, and diff --git a/sys/posix/pnet/netinet_in.c b/sys/posix/pnet/netinet_in.c deleted file mode 100644 index 7ef06230c3cec..0000000000000 --- 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 bc870a9f69de9..0000000000000 --- 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 48422e909a47d..7f84cdea31b2f 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 cb5bdbaa22db3..c02bd2f6fbff0 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 0000000000000..ccd7fa94c93e2 --- /dev/null +++ b/sys/posix/sockets/posix_sockets.c @@ -0,0 +1,624 @@ +/* + * 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 + +#include "fd.h" +#include "mutex.h" +#include "net/conn.h" +#include "sys/socket.h" +#include "netinet/in.h" + +#define SOCKET_POOL_SIZE (4) +#define CONN_IPV4 defined(MODULE_CONN_IP4) || defined(MODULE_CONN_UDP4) || \ + defined(MODULE_CONN_TCP4) +#define CONN_IPV6 defined(MODULE_CONN_IP6) || defined(MODULE_CONN_UDP6) || \ + defined(MODULE_CONN_TCP6) + +/** + * @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_IP4 + conn_ip4_t raw4; /**< raw IPv4 connection */ +#endif /* MODULE_CONN_IP4 */ +#ifdef MODULE_CONN_IP6 + conn_ip6_t raw6; /**< raw IPv6 connection */ +#endif /* MODULE_CONN_IP6 */ +#ifdef MODULE_CONN_TCP4 + conn_tcp4_t tcp4; /**< TCP over IPv4 connection */ +#endif /* MODULE_CONN_TCP4 */ +#ifdef MODULE_CONN_TCP6 + conn_tcp6_t tcp6; /**< TCP over IPv6 connection */ +#endif /* MODULE_CONN_TCP6 */ +#ifdef MODULE_CONN_UDP4 + conn_udp4_t udp4; /**< UDP over IPv4 connection */ +#endif /* MODULE_CONN_UDP4 */ +#ifdef MODULE_CONN_UDP6 + conn_udp6_t udp6; /**< UDP over IPv6 connection */ +#endif /* MODULE_CONN_UDP6 */ +} socket_conn_t; + +typedef struct { + int fd; + int domain; + int type; + int protocol; + 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) { +#if defined(MODULE_CONN_TCP4) || defined(MODULE_CONN_TCP6) + case SOCK_STREAM: + if ((protocol == 0) || (protocol == IPPROTO_TCP)) { + return protocol; + } + else { + errno = EPROTOTYPE; + } + break; +#endif +#if defined(MODULE_CONN_UDP4) || defined(MODULE_CONN_UDP6) + case SOCK_DGRAM: + if ((protocol == 0) || (protocol == IPPROTO_UDP)) { + return protocol; + } + else { + errno = EPROTOTYPE; + } + break; +#endif +#if defined(MODULE_CONN_IP4) || defined(MODULE_CONN_IP6) + case SOCK_RAW: + return protocol; +#endif + default: + break; + } + errno = EPROTONOSUPPORT; + return -1; +} + +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]; + s->domain = AF_INET; + switch (s->domain) { +#if CONN_IPV4 + case AF_INET: + switch (s->type) { +#ifdef MODULE_CONN_UDP4 + case SOCK_DGRAM: + conn_udp4_close(&s->conn.udp4); + break; +#endif +#ifdef MODULE_CONN_IP4 + case SOCK_RAW: + conn_ip4_close(&s->conn.raw4); + break; +#endif +#ifdef MODULE_CONN_TCP4 + case SOCK_STREAM: + conn_tcp4_close(&s->conn.tcp4); + break; +#endif + default: + res = -1; + break; + } +#endif +#if CONN_IPV6 + case AF_INET6: + switch (s->type) { +#ifdef MODULE_CONN_UDP6 + case SOCK_DGRAM: + conn_udp6_close(&s->conn.udp6); + break; +#endif +#ifdef MODULE_CONN_IP6 + case SOCK_RAW: + conn_ip6_close(&s->conn.raw6); + break; +#endif +#ifdef MODULE_CONN_TCP6 + case SOCK_STREAM: + conn_tcp6_close(&s->conn.tcp6); + break; +#endif + default: + res = -1; + break; + } +#endif + default: + res = -1; + break; + } + mutex_unlock(&_pool_mutex); + return res; +} + +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) { +#if CONN_IPV4 + case AF_INET: +#endif +#if CONN_IPV6 + case AF_INET6: +#endif +#if CONN_IPV4 || CONN_IPV6 + s->domain = domain; + s->type = type; + if ((s->protocol = _choose_ipproto(type, protocol)) < 0) { + res = -1; + } + break; +#endif + default: + errno = EAFNOSUPPORT; + res = -1; + } + if (res == 0) { + /* TODO: add read and write */ + int fd = fd_new(s - _pool, NULL, NULL, socket_close); + if (fd < 0) { + errno = ENFILE; + res = -1; + } + else { + s->fd = res = fd; + } + } + 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; + mutex_lock(&_pool_mutex); + s = _get_socket(socket); + switch (s->domain) { +#if CONN_IPV4 + case AF_INET: + if ((address_len != NULL) && (*address_len < sizeof(struct sockaddr_in))) { + errno = ENOMEM; + res = -1; + break; + } + switch (s->type) { +#ifdef MODULE_CONN_TCP4 + case SOCK_STREAM: + new_s = _get_free_socket(); + if (new_s == NULL) { + errno = ENFILE; + res = -1; + break; + } + if ((res = conn_tcp4_accept(&s->conn.tcp4, &new_s->conn.tcp4)) < 0) { + errno = -res; + res = -1; + break; + } + else if ((address != NULL) && (address_len != NULL)) { + struct sockaddr_in *addr = (struct sockaddr_in *)address; + /* 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; + *address_len = sizeof(struct sockaddr_in); + addr->sin_family = AF_INET; + conn_tcp4_getpeeraddr(&s->conn.tcp4, (ipv4_addr_t *)&addr->sin_addr, + &addr->sin_port); + addr->sin_port = htons(addr->sin_port); /* XXX: sin_port is supposed to be + * network byte order */ + } + break; +#endif + default: + errno = EOPNOTSUPP; + res = -1; + break; + } + break; +#endif +#if CONN_IPV6 + case AF_INET6: + if ((address_len != NULL) && (*address_len < sizeof(struct sockaddr_in6))) { + errno = ENOMEM; + res = -1; + break; + } + switch (s->type) { +#ifdef MODULE_CONN_TCP6 + case SOCK_STREAM: + new_s = _get_free_socket(); + if (new_s == NULL) { + errno = ENFILE; + res = -1; + break; + } + if ((res = conn_tcp6_accept(&s->conn.tcp6, &new_s->conn.tcp6)) < 0) { + errno = -res; + res = -1; + break; + } + else if ((address != NULL) && (address_len != NULL)) { + struct sockaddr_in6 *addr = (struct sockaddr_in6 *)address; + /* 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; + *address_len = sizeof(struct sockaddr_in6); + addr->sin6_family = AF_INET; + addr->sin6_flowinfo = 0; /* TODO */ + conn_tcp6_getpeeraddr(&s->conn.tcp6, (ipv6_addr_t *)&addr->sin6_addr, + &addr->sin6_port); + addr->sin6_port = htons(addr->sin6_port); /* XXX: sin6_port is supposed to + * be network byte order */ + addr->sin6_scope_id = 0; /* TODO */ + } + break; +#endif + default: + errno = EOPNOTSUPP; + res = -1; + break; + } + break; +#endif + default: + (void)address; + (void)address_len; + (void)new_s; + errno = EPROTO; + 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; + mutex_lock(&_pool_mutex); + s = _get_socket(socket); + mutex_unlock(&_pool_mutex); + switch (s->domain) { +#if CONN_IPV4 + case AF_INET: + if ((address_len != sizeof(struct sockaddr_in)) && (address->sa_family != AF_INET)) { + errno = EAFNOSUPPORT; + res = -1; + break; + } + struct sockaddr_in *in_addr = (struct sockaddr_in *)address; + switch (s->type) { +#ifdef MODULE_CONN_IP4 + case SOCK_RAW: + if ((res = conn_ip4_create(&s->conn.raw4, (ipv4_addr_t *)&in_addr->sin_addr, + s->protocol)) < 0) { + errno = -res; + res = -1; + } + break; +#endif +#ifdef MODULE_CONN_TCP4 + case SOCK_STREAM: + /* XXX sin_port is in network byteorder */ + if ((res = conn_tcp4_create(&s->conn.tcp4, (ipv4_addr_t *)&in_addr->sin_addr, + ntohs(in_addr->sin_port))) < 0) { + errno = -res; + res = -1; + } + break; +#endif +#ifdef MODULE_CONN_UDP4 + case SOCK_DGRAM: + /* XXX sin_port is in network byteorder */ + if ((res = conn_udp4_create(&s->conn.udp4, (ipv4_addr_t *)&in_addr->sin_addr, + ntohs(in_addr->sin_port))) < 0) { + errno = -res; + res = -1; + } + break; +#endif + default: + (void)in_addr; + errno = EOPNOTSUPP; + res = -1; + break; + } + break; +#endif +#if CONN_IPV6 + case AF_INET6: + if ((address_len != sizeof(struct sockaddr_in6)) && (address->sa_family != AF_INET6)) { + errno = EAFNOSUPPORT; + res = -1; + break; + } + struct sockaddr_in6 *in6_addr = (struct sockaddr_in6 *)address; + switch (s->type) { +#ifdef MODULE_CONN_IP6 + case SOCK_RAW: + if ((res = conn_ip6_create(&s->conn.raw6, (ipv6_addr_t *)&in6_addr->sin6_addr, + s->protocol)) < 0) { + errno = -res; + res = -1; + } + break; +#endif +#ifdef MODULE_CONN_TCP6 + case SOCK_STREAM: + /* XXX sin6_port is in network byteorder */ + if ((res = conn_tcp6_create(&s->conn.tcp6, (ipv6_addr_t *)&in6_addr->sin6_addr, + ntohs(in6_addr->sin6_port))) < 0) { + errno = -res; + res = -1; + } + break; +#endif +#ifdef MODULE_CONN_UDP6 + case SOCK_DGRAM: + /* XXX sin6_port is in network byteorder */ + if ((res = conn_udp6_create(&s->conn.udp6, (ipv6_addr_t *)&in6_addr->sin6_addr, + ntohs(in6_addr->sin6_port))) < 0) { + errno = -res; + res = -1; + } + break; +#endif + default: + (void)in6_addr; + errno = EOPNOTSUPP; + res = -1; + break; + } + break; +#endif + default: + (void)address; + (void)address_len; + errno = EAFNOSUPPORT; + res = -1; + break; + } + return res; +} + +int connect(int socket, const struct sockaddr *address, socklen_t address_len) +{ + socket_t *s; + int res = 0; + mutex_lock(&_pool_mutex); + s = _get_socket(socket); + mutex_unlock(&_pool_mutex); + switch (s->domain) { +#if CONN_IPV4 + case AF_INET: + if ((address_len != sizeof(struct sockaddr_in)) && (address->sa_family != AF_INET)) { + errno = EINVAL; + res = -1; + break; + } + struct sockaddr_in *in_addr = (struct sockaddr_in *)address; + switch (s->type) { +#ifdef MODULE_CONN_TCP4 + case SOCK_STREAM: + /* XXX sin_port is in network byteorder */ + if ((res = conn_tcp4_connect(&s->conn.tcp4, (ipv4_addr_t *)&in_addr->sin_addr, + ntohs(in_addr->sin_port))) < 0) { + errno = -res; + res = -1; + } + break; +#endif + default: + (void)in_addr; + errno = EPROTOTYPE; + res = -1; + break; + } + break; +#endif +#if CONN_IPV6 + case AF_INET6: + if ((address_len != sizeof(struct sockaddr_in6)) && (address->sa_family != AF_INET6)) { + errno = EINVAL; + res = -1; + break; + } + struct sockaddr_in6 *in6_addr = (struct sockaddr_in6 *)address; + switch (s->type) { +#ifdef MODULE_CONN_TCP6 + case SOCK_STREAM: + /* XXX sin6_port is in network byteorder */ + if ((res = conn_tcp6_connect(&s->conn.tcp6, (ipv6_addr_t *)&in6_addr->sin6_addr, + ntohs(in6_addr->sin6_port))) < 0) { + errno = -res; + res = -1; + } + break; +#endif + default: + (void)in6_addr; + errno = EPROTOTYPE; + res = -1; + break; + } + break; +#endif + default: + (void)address; + (void)address_len; + errno = EAFNOSUPPORT; + res = -1; + break; + } + return res; +} + +int getpeername(int socket, struct sockaddr *__restrict address, + socklen_t *__restrict address_len) +{ + (void)socket; + (void)address; + (void)address_len; + + return -1; +} + +int getsockname(int socket, struct sockaddr *__restrict address, + socklen_t *__restrict address_len) +{ + (void)socket; + (void)address; + (void)address_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; +} + +/** + * @} + */