diff --git a/simplelink/CMakeLists.txt b/simplelink/CMakeLists.txt index 6dc39c1..5e16af5 100644 --- a/simplelink/CMakeLists.txt +++ b/simplelink/CMakeLists.txt @@ -37,6 +37,10 @@ if(CONFIG_HAS_CC3220SDK) source/ti/drivers/net/wifi/porting/cc_pal.c source/ti/drivers/net/wifi/eventreg.c source/ti/drivers/net/wifi/source/sl_socket.c + source/ti/drivers/net/wifi/slnetif/slnetifwifi.c + source/ti/net/slnetif.c + source/ti/net/slnetsock.c + source/ti/net/slnetutils.c source/ti/devices/cc32xx/driverlib/timer.c source/ti/devices/cc32xx/driverlib/udma.c diff --git a/simplelink/source/ti/net/slnet.h b/simplelink/source/ti/net/slnet.h new file mode 100644 index 0000000..7ae0a19 --- /dev/null +++ b/simplelink/source/ti/net/slnet.h @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2019, Texas Instruments Incorporated + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of Texas Instruments Incorporated nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __SL_NET_H__ +#define __SL_NET_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/*! + \defgroup SlNet SlNet group + + \short Interface for general SlNet services. + +*/ +/*! + \addtogroup SlNet + @{ +*/ + +/*****************************************************************************/ +/* Function prototypes */ +/*****************************************************************************/ + +/*! + + \brief Prototype for SysConfig generated initialization function that + initializes various parts of the NS stack based on the user's SysConfig + script. This function should be called after the lower network stacks + initialize. Non-SysConfig users can provide their own implementation of + this function in their application's source code. + + \return Zero on success, or negative error code on failure +*/ +int32_t ti_net_SlNet_initConfig(); + +/*! + + Close the Doxygen group. + @} + +*/ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __SL_NET_H__ */ diff --git a/simplelink/source/ti/net/slneterr.h b/simplelink/source/ti/net/slneterr.h new file mode 100644 index 0000000..1f3ce2c --- /dev/null +++ b/simplelink/source/ti/net/slneterr.h @@ -0,0 +1,700 @@ +/* + * Copyright (c) 2017-2019, Texas Instruments Incorporated + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of Texas Instruments Incorporated nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +/*****************************************************************************/ +/* Include files */ +/*****************************************************************************/ + +#ifndef __SL_NET_ERR_H__ +#define __SL_NET_ERR_H__ + + +#ifdef __cplusplus +extern "C" { +#endif + +/*! + \defgroup SlNetErr SlNetErr group + + \short Provide BSD and proprietary errors + +*/ +/*! + + \addtogroup SlNetErr + @{ + +*/ + +/*****************************************************************************/ +/* Macro declarations */ +/*****************************************************************************/ + +#define SLNETERR_RET_CODE_OK (0L) /**< Success */ + +#define SLNETERR_GENERAL_DEVICE (-6L) /**< General device error */ + +/* BSD SOCKET ERRORS CODES */ + +#define SLNETERR_BSD_SOC_ERROR (-1L) /**< Failure */ +#define SLNETERR_BSD_ENXIO (-6L) /**< No such device or address */ +#define SLNETERR_BSD_INEXE (-8L) /**< socket command in execution */ +#define SLNETERR_BSD_EBADF (-9L) /**< Bad file number */ +#define SLNETERR_BSD_ENSOCK (-10L) /**< The system limit on the total number of open sockets, has been reached */ +#define SLNETERR_BSD_EAGAIN (-11L) /**< Try again */ +#define SLNETERR_BSD_EWOULDBLOCK SLNETERR_BSD_EAGAIN +#define SLNETERR_BSD_ENOMEM (-12L) /**< Out of memory */ +#define SLNETERR_BSD_EACCES (-13L) /**< Permission denied */ +#define SLNETERR_BSD_EFAULT (-14L) /**< Bad address */ +#define SLNETERR_BSD_ECLOSE (-15L) /**< close socket operation failed to transmit all queued packets */ +#define SLNETERR_BSD_EALREADY_ENABLED (-21L) /**< Transceiver - Transceiver already ON. there could be only one */ +#define SLNETERR_BSD_EINVAL (-22L) /**< Invalid argument */ +#define SLNETERR_BSD_EAUTO_CONNECT_OR_CONNECTING (-69L) /**< Transceiver - During connection, connected or auto mode started */ +#define SLNETERR_BSD_CONNECTION_PENDING (-72L) /**< Transceiver - Device is connected, disconnect first to open transceiver */ +#define SLNETERR_BSD_EUNSUPPORTED_ROLE (-86L) /**< Transceiver - Trying to start when WLAN role is AP or P2P GO */ +#define SLNETERR_BSD_ENOTSOCK (-88L) /**< Socket operation on non-socket */ +#define SLNETERR_BSD_EDESTADDRREQ (-89L) /**< Destination address required */ +#define SLNETERR_BSD_EMSGSIZE (-90L) /**< Message too long */ +#define SLNETERR_BSD_EPROTOTYPE (-91L) /**< Protocol wrong type for socket */ +#define SLNETERR_BSD_ENOPROTOOPT (-92L) /**< Protocol not available */ +#define SLNETERR_BSD_EPROTONOSUPPORT (-93L) /**< Protocol not supported */ +#define SLNETERR_BSD_ESOCKTNOSUPPORT (-94L) /**< Socket type not supported */ +#define SLNETERR_BSD_EOPNOTSUPP (-95L) /**< Operation not supported on transport endpoint */ +#define SLNETERR_BSD_EAFNOSUPPORT (-97L) /**< Address family not supported by protocol */ +#define SLNETERR_BSD_EADDRINUSE (-98L) /**< Address already in use */ +#define SLNETERR_BSD_EADDRNOTAVAIL (-99L) /**< Cannot assign requested address */ +#define SLNETERR_BSD_ENETDOWN (-100L) /**< Network is down */ +#define SLNETERR_BSD_ENETUNREACH (-101L) /**< Network is unreachable */ +#define SLNETERR_BSD_ECONNABORTED (-103L) /**< Software caused connection abort */ +#define SLNETERR_BSD_ECONNRESET (-104L) /**< Connection reset by peer */ +#define SLNETERR_BSD_ENOBUFS (-105L) /**< No buffer space available */ +#define SLNETERR_BSD_EOBUFF SLNETERR_BSD_ENOBUFS +#define SLNETERR_BSD_EISCONN (-106L) /**< Transport endpoint is already connected */ +#define SLNETERR_BSD_ENOTCONN (-107L) /**< Transport endpoint is not connected */ +#define SLNETERR_BSD_ESHUTDOWN (-108L) /**< Cannot send after transport endpoint shutdown */ +#define SLNETERR_BSD_ETIMEDOUT (-110L) /**< Connection timed out */ +#define SLNETERR_BSD_ECONNREFUSED (-111L) /**< Connection refused */ +#define SLNETERR_BSD_EHOSTDOWN (-112L) /**< Host is down */ +#define SLNETERR_BSD_EHOSTUNREACH (-113L) /**< No route to host */ +#define SLNETERR_BSD_EALREADY (-114L) /**< Non blocking connect in progress, try again */ +#define SLNETERR_BSD_EDOM (-115L) /**< Mathematics argument out of domain of function. */ +#define SLNETERR_BSD_ENOSPC (-116L) /**< No space left on device. */ + +/* ssl tls security start with -300 offset */ +#define SLNETERR_ESEC_CLOSE_NOTIFY (-300L) /**< ssl/tls alerts */ +#define SLNETERR_ESEC_UNEXPECTED_MESSAGE (-310L) /**< ssl/tls alerts */ +#define SLNETERR_ESEC_BAD_RECORD_MAC (-320L) /**< ssl/tls alerts */ +#define SLNETERR_ESEC_DECRYPTION_FAILED (-321L) /**< ssl/tls alerts */ +#define SLNETERR_ESEC_RECORD_OVERFLOW (-322L) /**< ssl/tls alerts */ +#define SLNETERR_ESEC_DECOMPRESSION_FAILURE (-330L) /**< ssl/tls alerts */ +#define SLNETERR_ESEC_HANDSHAKE_FAILURE (-340L) /**< ssl/tls alerts */ +#define SLNETERR_ESEC_NO_CERTIFICATE (-341L) /**< ssl/tls alerts */ +#define SLNETERR_ESEC_BAD_CERTIFICATE (-342L) /**< ssl/tls alerts */ +#define SLNETERR_ESEC_UNSUPPORTED_CERTIFICATE (-343L) /**< ssl/tls alerts */ +#define SLNETERR_ESEC_ILLEGAL_PARAMETER (-347L) /**< ssl/tls alerts */ +#define SLNETERR_ESEC_ACCESS_DENIED (-349L) /**< ssl/tls alerts */ +#define SLNETERR_ESEC_DECODE_ERROR (-350L) /**< ssl/tls alerts */ +#define SLNETERR_ESEC_DECRYPT_ERROR1 (-351L) /**< ssl/tls alerts */ +#define SLNETERR_ESEC_EXPORT_RESTRICTION (-360L) /**< ssl/tls alerts */ +#define SLNETERR_ESEC_PROTOCOL_VERSION (-370L) /**< ssl/tls alerts */ +#define SLNETERR_ESEC_INSUFFICIENT_SECURITY (-371L) /**< ssl/tls alerts */ +#define SLNETERR_ESEC_INTERNAL_ERROR (-380L) /**< ssl/tls alerts */ +#define SLNETERR_ESEC_USER_CANCELLED (-390L) /**< ssl/tls alerts */ +#define SLNETERR_ESEC_NO_RENEGOTIATION (-400L) /**< ssl/tls alerts */ +#define SLNETERR_ESEC_UNSUPPORTED_EXTENSION (-410L) /**< ssl/tls alerts */ +#define SLNETERR_ESEC_CERTIFICATE_UNOBTAINABLE (-411L) /**< ssl/tls alerts */ +#define SLNETERR_ESEC_UNRECOGNIZED_NAME (-412L) /**< ssl/tls alerts */ +#define SLNETERR_ESEC_BAD_CERTIFICATE_STATUS_RESPONSE (-413L) /**< ssl/tls alerts */ +#define SLNETERR_ESEC_BAD_CERTIFICATE_HASH_VALUE (-414L) /**< ssl/tls alerts */ + + +/* proprietary secure */ +#define SLNETERR_ESEC_GENERAL (-450L) /**< error secure level general error */ +#define SLNETERR_ESEC_DECRYPT (-451L) /**< error secure level, decrypt recv packet fail */ +#define SLNETERR_ESEC_CLOSED (-452L) /**< secure layer is closed by other side, tcp is still connected */ +#define SLNETERR_ESEC_SNO_VERIFY (-453L) /**< Connected without server verification */ +#define SLNETERR_ESEC_NO_CA_FILE (-454L) /**< error secure level CA file not found */ +#define SLNETERR_ESEC_MEMORY (-455L) /**< error secure level No memory space available */ +#define SLNETERR_ESEC_BAD_CA_FILE (-456L) /**< error secure level bad CA file */ +#define SLNETERR_ESEC_BAD_CERT_FILE (-457L) /**< error secure level bad Certificate file */ +#define SLNETERR_ESEC_BAD_PRIVATE_FILE (-458L) /**< error secure level bad private file */ +#define SLNETERR_ESEC_BAD_DH_FILE (-459L) /**< error secure level bad DH file */ +#define SLNETERR_ESEC_T00_MANY_SSL_OPENED (-460L) /**< MAX SSL Sockets are opened */ +#define SLNETERR_ESEC_DATE_ERROR (-461L) /**< connected with certificate date verification error */ +#define SLNETERR_ESEC_HAND_SHAKE_TIMED_OUT (-462L) /**< connection timed out due to handshake time */ +#define SLNETERR_ESEC_TX_BUFFER_NOT_EMPTY (-463L) /**< cannot start ssl connection while send buffer is full */ +#define SLNETERR_ESEC_RX_BUFFER_NOT_EMPTY (-464L) /**< cannot start ssl connection while recv buffer is full */ +#define SLNETERR_ESEC_SSL_DURING_HAND_SHAKE (-465L) /**< cannot use while in handshaking */ +#define SLNETERR_ESEC_NOT_ALLOWED_WHEN_LISTENING (-466L) /**< the operation is not allowed when listening, do before listen */ +#define SLNETERR_ESEC_CERTIFICATE_REVOKED (-467L) /**< connected but one of the certificates in the chain is revoked */ +#define SLNETERR_ESEC_UNKNOWN_ROOT_CA (-468L) /**< connected but the root CA used to validate the peer is unknown */ +#define SLNETERR_ESEC_WRONG_PEER_CERT (-469L) /**< wrong peer cert (server cert) was received while trying to connect to server */ +#define SLNETERR_ESEC_TCP_DISCONNECTED_UNCOMPLETE_RECORD (-470L) /**< the other side disconnected the TCP layer and didn't send the whole ssl record */ +#define SLNETERR_ESEC_HELLO_VERIFY_ERROR (-471L) /**< Hello verification failed in DTLS */ + +#define SLNETERR_ESEC_BUFFER_E (-632L) /**< output buffer too small or input too large */ +#define SLNETERR_ESEC_ALGO_ID_E (-633L) /**< setting algo id error */ +#define SLNETERR_ESEC_PUBLIC_KEY_E (-634L) /**< setting public key error */ +#define SLNETERR_ESEC_DATE_E (-635L) /**< setting date validity error */ +#define SLNETERR_ESEC_SUBJECT_E (-636L) /**< setting subject name error */ +#define SLNETERR_ESEC_ISSUER_E (-637L) /**< setting issuer name error */ +#define SLNETERR_ESEC_CA_TRUE_E (-638L) /**< setting CA basic constraint true error */ +#define SLNETERR_ESEC_EXTENSIONS_E (-639L) /**< setting extensions error */ +#define SLNETERR_ESEC_ASN_PARSE_E (-640L) /**< ASN parsing error, invalid input */ +#define SLNETERR_ESEC_ASN_VERSION_E (-641L) /**< ASN version error, invalid number */ +#define SLNETERR_ESEC_ASN_GETINT_E (-642L) /**< ASN get big int error, invalid data */ +#define SLNETERR_ESEC_ASN_RSA_KEY_E (-643L) /**< ASN key init error, invalid input */ +#define SLNETERR_ESEC_ASN_OBJECT_ID_E (-644L) /**< ASN object id error, invalid id */ +#define SLNETERR_ESEC_ASN_TAG_NULL_E (-645L) /**< ASN tag error, not null */ +#define SLNETERR_ESEC_ASN_EXPECT_0_E (-646L) /**< ASN expect error, not zero */ +#define SLNETERR_ESEC_ASN_BITSTR_E (-647L) /**< ASN bit string error, wrong id */ +#define SLNETERR_ESEC_ASN_UNKNOWN_OID_E (-648L) /**< ASN oid error, unknown sum id */ +#define SLNETERR_ESEC_ASN_DATE_SZ_E (-649L) /**< ASN date error, bad size */ +#define SLNETERR_ESEC_ASN_BEFORE_DATE_E (-650L) /**< ASN date error, current date before */ +#define SLNETERR_ESEC_ASN_AFTER_DATE_E (-651L) /**< ASN date error, current date after */ +#define SLNETERR_ESEC_ASN_SIG_OID_E (-652L) /**< ASN signature error, mismatched oid */ +#define SLNETERR_ESEC_ASN_TIME_E (-653L) /**< ASN time error, unknown time type */ +#define SLNETERR_ESEC_ASN_INPUT_E (-654L) /**< ASN input error, not enough data */ +#define SLNETERR_ESEC_ASN_SIG_CONFIRM_E (-655L) /**< ASN sig error, confirm failure */ +#define SLNETERR_ESEC_ASN_SIG_HASH_E (-656L) /**< ASN sig error, unsupported hash type */ +#define SLNETERR_ESEC_ASN_SIG_KEY_E (-657L) /**< ASN sig error, unsupported key type */ +#define SLNETERR_ESEC_ASN_DH_KEY_E (-658L) /**< ASN key init error, invalid input */ +#define SLNETERR_ESEC_ASN_NTRU_KEY_E (-659L) /**< ASN ntru key decode error, invalid input */ +#define SLNETERR_ESEC_ASN_CRIT_EXT_E (-660L) /**< ASN unsupported critical extension */ +#define SLNETERR_ESEC_ECC_BAD_ARG_E (-670L) /**< ECC input argument of wrong type */ +#define SLNETERR_ESEC_ASN_ECC_KEY_E (-671L) /**< ASN ECC bad input */ +#define SLNETERR_ESEC_ECC_CURVE_OID_E (-672L) /**< Unsupported ECC OID curve type */ +#define SLNETERR_ESEC_BAD_FUNC_ARG (-673L) /**< Bad function argument provided */ +#define SLNETERR_ESEC_NOT_COMPILED_IN (-674L) /**< Feature not compiled in */ +#define SLNETERR_ESEC_UNICODE_SIZE_E (-675L) /**< Unicode password too big */ +#define SLNETERR_ESEC_NO_PASSWORD (-676L) /**< no password provided by user */ +#define SLNETERR_ESEC_ALT_NAME_E (-677L) /**< alt name size problem, too big */ +#define SLNETERR_ESEC_ASN_NO_SIGNER_E (-688L) /**< ASN no signer to confirm failure */ +#define SLNETERR_ESEC_ASN_CRL_CONFIRM_E (-689L) /**< ASN CRL signature confirm failure */ +#define SLNETERR_ESEC_ASN_CRL_NO_SIGNER_E (-690L) /**< ASN CRL no signer to confirm failure */ +#define SLNETERR_ESEC_ASN_OCSP_CONFIRM_E (-691L) /**< ASN OCSP signature confirm failure */ +#define SLNETERR_ESEC_VERIFY_FINISHED_ERROR (-704L) /**< verify problem on finished */ +#define SLNETERR_ESEC_VERIFY_MAC_ERROR (-705L) /**< verify mac problem */ +#define SLNETERR_ESEC_PARSE_ERROR (-706L) /**< parse error on header */ +#define SLNETERR_ESEC_UNKNOWN_HANDSHAKE_TYPE (-707L) /**< weird handshake type */ +#define SLNETERR_ESEC_SOCKET_ERROR_E (-708L) /**< error state on socket */ +#define SLNETERR_ESEC_SOCKET_NODATA (-709L) /**< expected data, not there */ +#define SLNETERR_ESEC_INCOMPLETE_DATA (-710L) /**< don't have enough data to complete task */ +#define SLNETERR_ESEC_UNKNOWN_RECORD_TYPE (-711L) /**< unknown type in record hdr */ +#define SLNETERR_ESEC_INNER_DECRYPT_ERROR (-712L) /**< error during decryption */ +#define SLNETERR_ESEC_FATAL_ERROR (-713L) /**< recvd alert fatal error */ +#define SLNETERR_ESEC_ENCRYPT_ERROR (-714L) /**< error during encryption */ +#define SLNETERR_ESEC_FREAD_ERROR (-715L) /**< fread problem */ +#define SLNETERR_ESEC_NO_PEER_KEY (-716L) /**< need peer's key */ +#define SLNETERR_ESEC_NO_PRIVATE_KEY (-717L) /**< need the private key */ +#define SLNETERR_ESEC_RSA_PRIVATE_ERROR (-718L) /**< error during rsa priv op */ +#define SLNETERR_ESEC_NO_DH_PARAMS (-719L) /**< server missing DH params */ +#define SLNETERR_ESEC_BUILD_MSG_ERROR (-720L) /**< build message failure */ +#define SLNETERR_ESEC_BAD_HELLO (-721L) /**< client hello malformed */ +#define SLNETERR_ESEC_DOMAIN_NAME_MISMATCH (-722L) /**< peer subject name mismatch */ +#define SLNETERR_ESEC_WANT_READ (-723L) /**< want read, call again */ +#define SLNETERR_ESEC_NOT_READY_ERROR (-724L) /**< handshake layer not ready */ +#define SLNETERR_ESEC_PMS_VERSION_ERROR (-725L) /**< pre m secret version error */ +#define SLNETERR_ESEC_WANT_WRITE (-727L) /**< want write, call again */ +#define SLNETERR_ESEC_BUFFER_ERROR (-728L) /**< malformed buffer input */ +#define SLNETERR_ESEC_VERIFY_CERT_ERROR (-729L) /**< verify cert error */ +#define SLNETERR_ESEC_VERIFY_SIGN_ERROR (-730L) /**< verify sign error */ +#define SLNETERR_ESEC_LENGTH_ERROR (-741L) /**< record layer length error */ +#define SLNETERR_ESEC_PEER_KEY_ERROR (-742L) /**< can't decode peer key */ +#define SLNETERR_ESEC_ZERO_RETURN (-743L) /**< peer sent close notify */ +#define SLNETERR_ESEC_SIDE_ERROR (-744L) /**< wrong client/server type */ +#define SLNETERR_ESEC_NO_PEER_CERT (-745L) /**< peer didn't send key */ +#define SLNETERR_ESEC_ECC_CURVETYPE_ERROR (-750L) /**< Bad ECC Curve Type */ +#define SLNETERR_ESEC_ECC_CURVE_ERROR (-751L) /**< Bad ECC Curve */ +#define SLNETERR_ESEC_ECC_PEERKEY_ERROR (-752L) /**< Bad Peer ECC Key */ +#define SLNETERR_ESEC_ECC_MAKEKEY_ERROR (-753L) /**< Bad Make ECC Key */ +#define SLNETERR_ESEC_ECC_EXPORT_ERROR (-754L) /**< Bad ECC Export Key */ +#define SLNETERR_ESEC_ECC_SHARED_ERROR (-755L) /**< Bad ECC Shared Secret */ +#define SLNETERR_ESEC_NOT_CA_ERROR (-757L) /**< Not a CA cert error */ +#define SLNETERR_ESEC_BAD_PATH_ERROR (-758L) /**< Bad path for opendir */ +#define SLNETERR_ESEC_BAD_CERT_MANAGER_ERROR (-759L) /**< Bad Cert Manager */ +#define SLNETERR_ESEC_OCSP_CERT_REVOKED (-760L) /**< OCSP Certificate revoked */ +#define SLNETERR_ESEC_CRL_CERT_REVOKED (-761L) /**< CRL Certificate revoked */ +#define SLNETERR_ESEC_CRL_MISSING (-762L) /**< CRL Not loaded */ +#define SLNETERR_ESEC_MONITOR_RUNNING_E (-763L) /**< CRL Monitor already running */ +#define SLNETERR_ESEC_THREAD_CREATE_E (-764L) /**< Thread Create Error */ +#define SLNETERR_ESEC_OCSP_NEED_URL (-765L) /**< OCSP need an URL for lookup */ +#define SLNETERR_ESEC_OCSP_CERT_UNKNOWN (-766L) /**< OCSP responder doesn't know */ +#define SLNETERR_ESEC_OCSP_LOOKUP_FAIL (-767L) /**< OCSP lookup not successful */ +#define SLNETERR_ESEC_MAX_CHAIN_ERROR (-768L) /**< max chain depth exceeded */ +#define SLNETERR_ESEC_NO_PEER_VERIFY (-778L) /**< Need peer cert verify Error */ +#define SLNETERR_ESEC_UNSUPPORTED_SUITE (-790L) /**< unsupported cipher suite */ +#define SLNETERR_ESEC_MATCH_SUITE_ERROR (-791L) /**< can't match cipher suite */ + + + +/* WLAN ERRORS CODES*/ + +#define SLNETERR_WLAN_KEY_ERROR (-2049L) +#define SLNETERR_WLAN_INVALID_ROLE (-2050L) +#define SLNETERR_WLAN_PREFERRED_NETWORKS_FILE_LOAD_FAILED (-2051L) +#define SLNETERR_WLAN_CANNOT_CONFIG_SCAN_DURING_PROVISIONING (-2052L) +#define SLNETERR_WLAN_INVALID_SECURITY_TYPE (-2054L) +#define SLNETERR_WLAN_PASSPHRASE_TOO_LONG (-2055L) +#define SLNETERR_WLAN_EAP_WRONG_METHOD (-2057L) +#define SLNETERR_WLAN_PASSWORD_ERROR (-2058L) +#define SLNETERR_WLAN_EAP_ANONYMOUS_LEN_ERROR (-2059L) +#define SLNETERR_WLAN_SSID_LEN_ERROR (-2060L) +#define SLNETERR_WLAN_USER_ID_LEN_ERROR (-2061L) +#define SLNETERR_WLAN_PREFERRED_NETWORK_LIST_FULL (-2062L) +#define SLNETERR_WLAN_PREFERRED_NETWORKS_FILE_WRITE_FAILED (-2063L) +#define SLNETERR_WLAN_ILLEGAL_WEP_KEY_INDEX (-2064L) +#define SLNETERR_WLAN_INVALID_DWELL_TIME_VALUES (-2065L) +#define SLNETERR_WLAN_INVALID_POLICY_TYPE (-2066L) +#define SLNETERR_WLAN_PM_POLICY_INVALID_OPTION (-2067L) +#define SLNETERR_WLAN_PM_POLICY_INVALID_PARAMS (-2068L) +#define SLNETERR_WLAN_WIFI_NOT_CONNECTED (-2069L) +#define SLNETERR_WLAN_ILLEGAL_CHANNEL (-2070L) +#define SLNETERR_WLAN_WIFI_ALREADY_DISCONNECTED (-2071L) +#define SLNETERR_WLAN_TRANSCEIVER_ENABLED (-2072L) +#define SLNETERR_WLAN_GET_NETWORK_LIST_EAGAIN (-2073L) +#define SLNETERR_WLAN_GET_PROFILE_INVALID_INDEX (-2074L) +#define SLNETERR_WLAN_FAST_CONN_DATA_INVALID (-2075L) +#define SLNETERR_WLAN_NO_FREE_PROFILE (-2076L) +#define SLNETERR_WLAN_AP_SCAN_INTERVAL_TOO_LOW (-2077L) +#define SLNETERR_WLAN_SCAN_POLICY_INVALID_PARAMS (-2078L) + +#define SLNETERR_RXFL_OK (0L) /**< O.K */ +#define SLNETERR_RXFL_RANGE_COMPARE_PARAMS_ARE_INVALID (-2079L) +#define SLNETERR_RXFL_RXFL_INVALID_PATTERN_LENGTH (-2080L) /**< requested length for L1/L4 payload matching must not exceed 16 bytes */ +#define SLNETERR_RXFL_ACTION_USER_EVENT_ID_TOO_BIG (-2081L) /**< user action id for host event must not exceed SLNETERR_WLAN_RX_FILTER_MAX_USER_EVENT_ID */ +#define SLNETERR_RXFL_OFFSET_TOO_BIG (-2082L) /**< requested offset for L1/L4 payload matching must not exceed 1535 bytes */ +#define SLNETERR_RXFL_STAT_UNSUPPORTED (-2083L) /**< get rx filters statistics not supported */ +#define SLNETERR_RXFL_INVALID_FILTER_ARG_UPDATE (-2084L) /**< invalid filter args request */ +#define SLNETERR_RXFL_INVALID_SYSTEM_STATE_TRIGGER_FOR_FILTER_TYPE (-2085L) /**< system state not supported for this filter type */ +#define SLNETERR_RXFL_INVALID_FUNC_ID_FOR_FILTER_TYPE (-2086L) /**< function id not supported for this filter type */ +#define SLNETERR_RXFL_DEPENDENT_FILTER_DO_NOT_EXIST_3 (-2087L) /**< filter parent doesn't exist */ +#define SLNETERR_RXFL_OUTPUT_OR_INPUT_BUFFER_LENGTH_TOO_SMALL (-2088L) /**< ! The output buffer length is smaller than required for that operation */ +#define SLNETERR_RXFL_DEPENDENT_FILTER_SOFTWARE_FILTER_NOT_FIT (-2089L) /**< Node filter can't be child of software filter and vice_versa */ +#define SLNETERR_RXFL_DEPENDENCY_IS_NOT_PERSISTENT (-2090L) /**< Dependency filter is not persistent */ +#define SLNETERR_RXFL_RXFL_ALLOCATION_PROBLEM (-2091L) +#define SLNETERR_RXFL_SYSTEM_STATE_NOT_SUPPORTED_FOR_THIS_FILTER (-2092L) /**< System state is not supported */ +#define SLNETERR_RXFL_TRIGGER_USE_REG5_TO_REG8 (-2093L) /**< Only counters 5 - 8 are allowed, for trigger */ +#define SLNETERR_RXFL_TRIGGER_USE_REG1_TO_REG4 (-2094L) /**< Only counters 1 - 4 are allowed, for trigger */ +#define SLNETERR_RXFL_ACTION_USE_REG5_TO_REG8 (-2095L) /**< Only counters 5 - 8 are allowed, for action */ +#define SLNETERR_RXFL_ACTION_USE_REG1_TO_REG4 (-2096L) /**< Only counters 1 - 4 are allowed, for action */ +#define SLNETERR_RXFL_FIELD_SUPPORT_ONLY_EQUAL_AND_NOTEQUAL (-2097L) /**< Rule compare function Id is out of range */ +#define SLNETERR_RXFL_WRONG_MULTICAST_BROADCAST_ADDRESS (-2098L) /**< The address should be of type multicast or broadcast */ +#define SLNETERR_RXFL_THE_FILTER_IS_NOT_OF_HEADER_TYPE (-2099L) /**< The filter should be of header type */ +#define SLNETERR_RXFL_WRONG_COMPARE_FUNC_FOR_BROADCAST_ADDRESS (-2100L) /**< The compare function is not suitable for broadcast address */ +#define SLNETERR_RXFL_WRONG_MULTICAST_ADDRESS (-2101L) /**< The address should be of multicast type */ +#define SLNETERR_RXFL_DEPENDENT_FILTER_IS_NOT_PERSISTENT (-2102L) /**< The dependency filter is not persistent */ +#define SLNETERR_RXFL_DEPENDENT_FILTER_IS_NOT_ENABLED (-2103L) /**< The dependency filter is not enabled */ +#define SLNETERR_RXFL_FILTER_HAS_CHILDS (-2104L) /**< The filter has childs and can't be removed */ +#define SLNETERR_RXFL_CHILD_IS_ENABLED (-2105L) /**< Can't disable filter while the child is enabled */ +#define SLNETERR_RXFL_DEPENDENCY_IS_DISABLED (-2106L) /**< Can't enable filter in case its dependency filter is disabled */ +#define SLNETERR_RXFL_MAC_SEND_MATCHDB_FAILED (-2107L) +#define SLNETERR_RXFL_MAC_SEND_ARG_DB_FAILED (-2108L) +#define SLNETERR_RXFL_MAC_SEND_NODEDB_FAILED (-2109L) +#define SLNETERR_RXFL_MAC_OPERTATION_RESUME_FAILED (-2110L) +#define SLNETERR_RXFL_MAC_OPERTATION_HALT_FAILED (-2111L) +#define SLNETERR_RXFL_NUMBER_OF_CONNECTION_POINTS_EXCEEDED (-2112L) /**< Number of connection points exceeded */ +#define SLNETERR_RXFL_DEPENDENT_FILTER_DEPENDENCY_ACTION_IS_DROP (-2113L) /**< The dependent filter has Drop action, thus the filter can't be created */ +#define SLNETERR_RXFL_FILTER_DO_NOT_EXISTS (-2114L) /**< The filter doesn't exists */ +#define SLNETERR_RXFL_DEPEDENCY_NOT_ON_THE_SAME_LAYER (-2115L) /**< The filter and its dependency must be on the same layer */ +#define SLNETERR_RXFL_NUMBER_OF_ARGS_EXCEEDED (-2116L) /**< Number of arguments exceeded */ +#define SLNETERR_RXFL_ACTION_NO_REG_NUMBER (-2117L) /**< Action require counter number */ +#define SLNETERR_RXFL_DEPENDENT_FILTER_LAYER_DO_NOT_FIT (-2118L) /**< the filter and its dependency should be from the same layer */ +#define SLNETERR_RXFL_DEPENDENT_FILTER_SYSTEM_STATE_DO_NOT_FIT (-2119L) /**< The filter and its dependency system state don't fit */ +#define SLNETERR_RXFL_DEPENDENT_FILTER_DO_NOT_EXIST_2 (-2120L) /**< The parent filter don't exist */ +#define SLNETERR_RXFL_DEPENDENT_FILTER_DO_NOT_EXIST_1 (-2121L) /**< The parent filter is null */ +#define SLNETERR_RXFL_RULE_HEADER_ACTION_TYPE_NOT_SUPPORTED (-2122L) /**< The action type is not supported */ +#define SLNETERR_RXFL_RULE_HEADER_TRIGGER_COMPARE_FUNC_OUT_OF_RANGE (-2123L) /**< The Trigger comparison function is out of range */ +#define SLNETERR_RXFL_RULE_HEADER_TRIGGER_OUT_OF_RANGE (-2124L) /**< The Trigger is out of range */ +#define SLNETERR_RXFL_RULE_HEADER_COMPARE_FUNC_OUT_OF_RANGE (-2125L) /**< The rule compare function is out of range */ +#define SLNETERR_RXFL_FRAME_TYPE_NOT_SUPPORTED (-2126L) /**< ASCII frame type string is illegal */ +#define SLNETERR_RXFL_RULE_FIELD_ID_NOT_SUPPORTED (-2127L) /**< Rule field ID is out of range */ +#define SLNETERR_RXFL_RULE_HEADER_FIELD_ID_ASCII_NOT_SUPPORTED (-2128L) /**< This ASCII field ID is not supported */ +#define SLNETERR_RXFL_RULE_HEADER_NOT_SUPPORTED (-2129L) /**< The header rule is not supported on current release */ +#define SLNETERR_RXFL_RULE_HEADER_OUT_OF_RANGE (-2130L) /**< The header rule is out of range */ +#define SLNETERR_RXFL_RULE_HEADER_COMBINATION_OPERATOR_OUT_OF_RANGE (-2131L) /**< Combination function Id is out of range */ +#define SLNETERR_RXFL_RULE_HEADER_FIELD_ID_OUT_OF_RANGE (-2132L) /**< rule field Id is out of range */ +#define SLNETERR_RXFL_UPDATE_NOT_SUPPORTED (-2133L) /**< Update not supported */ +#define SLNETERR_RXFL_NO_FILTER_DATABASE_ALLOCATE (-2134L) +#define SLNETERR_RXFL_ALLOCATION_FOR_GLOBALS_STRUCTURE_FAILED (-2135L) +#define SLNETERR_RXFL_ALLOCATION_FOR_DB_NODE_FAILED (-2136L) +#define SLNETERR_RXFL_READ_FILE_FILTER_ID_ILLEGAL (-2137L) +#define SLNETERR_RXFL_READ_FILE_NUMBER_OF_FILTER_FAILED (-2138L) +#define SLNETERR_RXFL_READ_FILE_FAILED (-2139L) +#define SLNETERR_RXFL_NO_FILTERS_ARE_DEFINED (-2140L) /**< No filters are defined in the system */ +#define SLNETERR_RXFL_NUMBER_OF_FILTER_EXCEEDED (-2141L) /**< Number of max filters exceeded */ +#define SLNETERR_RXFL_BAD_FILE_MODE (-2142L) +#define SLNETERR_RXFL_FAILED_READ_NVFILE (-2143L) +#define SLNETERR_RXFL_FAILED_INIT_STORAGE (-2144L) +#define SLNETERR_RXFL_CONTINUE_WRITE_MUST_BE_MOD_4 (-2145L) +#define SLNETERR_RXFL_FAILED_LOAD_FILE (-2146L) +#define SLNETERR_RXFL_INVALID_HANDLE (-2147L) +#define SLNETERR_RXFL_FAILED_TO_WRITE (-2148L) +#define SLNETERR_RXFL_OFFSET_OUT_OF_RANGE (-2149L) +#define SLNETERR_RXFL_ALLOC (-2150L) +#define SLNETERR_RXFL_READ_DATA_LENGTH (-2151L) +#define SLNETERR_RXFL_INVALID_FILE_ID (-2152L) +#define SLNETERR_RXFL_FILE_FILTERS_NOT_EXISTS (-2153L) +#define SLNETERR_RXFL_FILE_ALREADY_IN_USE (-2154L) +#define SLNETERR_RXFL_INVALID_ARGS (-2155L) +#define SLNETERR_RXFL_FAILED_TO_CREATE_FILE (-2156L) +#define SLNETERR_RXFL_FS_ALREADY_LOADED (-2157L) +#define SLNETERR_RXFL_UNKNOWN (-2158L) +#define SLNETERR_RXFL_FAILED_TO_CREATE_LOCK_OBJ (-2159L) +#define SLNETERR_RXFL_DEVICE_NOT_LOADED (-2160L) +#define SLNETERR_RXFL_INVALID_MAGIC_NUM (-2161L) +#define SLNETERR_RXFL_FAILED_TO_READ (-2162L) +#define SLNETERR_RXFL_NOT_SUPPORTED (-2163L) +#define SLNETERR_WLAN_INVALID_COUNTRY_CODE (-2164L) +#define SLNETERR_WLAN_NVMEM_ACCESS_FAILED (-2165L) +#define SLNETERR_WLAN_OLD_FILE_VERSION (-2166L) +#define SLNETERR_WLAN_TX_POWER_OUT_OF_RANGE (-2167L) +#define SLNETERR_WLAN_INVALID_AP_PASSWORD_LENGTH (-2168L) +#define SLNETERR_WLAN_PROVISIONING_ABORT_PROVISIONING_ALREADY_STARTED (-2169L) +#define SLNETERR_WLAN_PROVISIONING_ABORT_HTTP_SERVER_DISABLED (-2170L) +#define SLNETERR_WLAN_PROVISIONING_ABORT_PROFILE_LIST_FULL (-2171L) +#define SLNETERR_WLAN_PROVISIONING_ABORT_INVALID_PARAM (-2172L) +#define SLNETERR_WLAN_PROVISIONING_ABORT_GENERAL_ERROR (-2173L) +#define SLNETERR_WLAN_MULTICAST_EXCEED_MAX_ADDR (-2174L) +#define SLNETERR_WLAN_MULTICAST_INVAL_ADDR (-2175L) +#define SLNETERR_WLAN_AP_SCAN_INTERVAL_TOO_SHORT (-2176L) +#define SLNETERR_WLAN_PROVISIONING_CMD_NOT_EXPECTED (-2177L) + + +#define SLNETERR_WLAN_AP_ACCESS_LIST_NO_ADDRESS_TO_DELETE (-2178L) /**< List is empty, no address to delete */ +#define SLNETERR_WLAN_AP_ACCESS_LIST_FULL (-2179L) /**< access list is full */ +#define SLNETERR_WLAN_AP_ACCESS_LIST_DISABLED (-2180L) /**< access list is disabled */ +#define SLNETERR_WLAN_AP_ACCESS_LIST_MODE_NOT_SUPPORTED (-2181L) /**< Trying to switch to unsupported mode */ +#define SLNETERR_WLAN_AP_STA_NOT_FOUND (-2182L) /**< trying to disconnect station which is not connected */ + + + +/* DEVICE ERRORS CODES*/ +#define SLNETERR_SUPPLICANT_ERROR (-4097L) +#define SLNETERR_HOSTAPD_INIT_FAIL (-4098L) +#define SLNETERR_HOSTAPD_INIT_IF_FAIL (-4099L) +#define SLNETERR_WLAN_DRV_INIT_FAIL (-4100L) +#define SLNETERR_MDNS_ENABLE_FAIL (-4103L) /**< mDNS enable failed */ +#define SLNETERR_ROLE_STA_ERR (-4107L) /**< Failure to load MAC/PHY in STA role */ +#define SLNETERR_ROLE_AP_ERR (-4108L) /**< Failure to load MAC/PHY in AP role */ +#define SLNETERR_ROLE_P2P_ERR (-4109L) /**< Failure to load MAC/PHY in P2P role */ +#define SLNETERR_CALIB_FAIL (-4110L) /**< Failure of calibration */ +#define SLNETERR_RESTORE_IMAGE_COMPLETE (-4113L) /**< Return to factory image completed, perform reset */ +#define SLNETERR_UNKNOWN_ERR (-4114L) +#define SLNETERR_GENERAL_ERR (-4115L) /**< General error during init */ +#define SLNETERR_WRONG_ROLE (-4116L) +#define SLNETERR_INCOMPLETE_PROGRAMMING (-4117L) /**< Error during programming, Program new image should be invoked (see sl_FsProgram) */ + + +#define SLNETERR_PENDING_TXRX_STOP_TIMEOUT_EXP (-4118L) /**< Timeout expired before completing all TX/RX */ +#define SLNETERR_PENDING_TXRX_NO_TIMEOUT (-4119L) /**< No Timeout, still have pending TX/RX */ +#define SLNETERR_INVALID_PERSISTENT_CONFIGURATION (-4120L) /**< persistent configuration can only be set to 0 (disabled) or 1 (enabled) */ + + + +/* NETAPP ERRORS CODES*/ +#define SLNETERR_MDNS_CREATE_FAIL (-6145L) /**< mDNS create failed */ +#define SLNETERR_DEVICE_NAME_LEN_ERR (-6146L) /**< Set Dev name error codes */ +#define SLNETERR_DEVICE_NAME_INVALID (-6147L) /**< Set Dev name error codes */ +#define SLNETERR_DOMAIN_NAME_LEN_ERR (-6148L) /**< Set domain name error codes */ +#define SLNETERR_DOMAIN_NAME_INVALID (-6149L) /**< Set domain name error codes */ +#define SLNETERR_NET_APP_DNS_QUERY_NO_RESPONSE (-6150L) /**< DNS query failed, no response */ +#define SLNETERR_NET_APP_DNS_ERROR (-6151L) /**< DNS internal error */ +#define SLNETERR_NET_APP_DNS_NO_SERVER (-6152L) /**< No DNS server was specified */ +#define SLNETERR_NET_APP_DNS_TIMEOUTR (-6153L) /**< mDNS parameters error */ +#define SLNETERR_NET_APP_DNS_QUERY_FAILED (-6154L) /**< DNS query failed; no DNS server sent an 'answer' */ +#define SLNETERR_NET_APP_DNS_BAD_ADDRESS_ERROR (-6155L) /**< Improperly formatted IPv4 or IPv6 address */ +#define SLNETERR_NET_APP_DNS_SIZE_ERROR (-6156L) /**< DNS destination size is too small */ +#define SLNETERR_NET_APP_DNS_MALFORMED_PACKET (-6157L) /**< Improperly formed or corrupted DNS packet received */ +#define SLNETERR_NET_APP_DNS_BAD_ID_ERROR (-6158L) /**< DNS packet from server does not match query ID */ +#define SLNETERR_NET_APP_DNS_PARAM_ERROR (-6159L) /**< Invalid params */ +#define SLNETERR_NET_APP_DNS_SERVER_NOT_FOUND (-6160L) /**< Server not found in Client list of DNS servers */ +#define SLNETERR_NET_APP_DNS_PACKET_CREATE_ERROR (-6161L) /**< Error creating DNS packet */ +#define SLNETERR_NET_APP_DNS_EMPTY_DNS_SERVER_LIST (-6162L) /**< DNS Client's list of DNS servers is empty */ +#define SLNETERR_NET_APP_DNS_SERVER_AUTH_ERROR (-6163L) /**< Server not able to authenticate answer/authority data*/ +#define SLNETERR_NET_APP_DNS_ZERO_GATEWAY_IP_ADDRESS (-6164L) /**< DNS Client IP instance has a zero gateway IP address */ +#define SLNETERR_NET_APP_DNS_MISMATCHED_RESPONSE (-6165L) /**< Server response type does not match the query request*/ +#define SLNETERR_NET_APP_DNS_DUPLICATE_ENTRY (-6166L) /**< Duplicate entry exists in DNS server table */ +#define SLNETERR_NET_APP_DNS_RETRY_A_QUERY (-6167L) /**< SOA status returned; web site only exists as IPv4 */ +#define SLNETERR_NET_APP_DNS_INVALID_ADDRESS_TYPE (-6168L) /**< IP address type (e.g. IPv6L) not supported */ +#define SLNETERR_NET_APP_DNS_IPV6_NOT_SUPPORTED (-6169L) /**< IPv6 disabled */ +#define SLNETERR_NET_APP_DNS_NEED_MORE_RECORD_BUFFER (-6170L) /**< The buffer size is not enough. */ +#define SLNETERR_NET_APP_MDNS_ERROR (-6171L) /**< MDNS internal error. */ +#define SLNETERR_NET_APP_MDNS_PARAM_ERROR (-6172L) /**< MDNS parameters error. */ +#define SLNETERR_NET_APP_MDNS_CACHE_ERROR (-6173L) /**< The Cache size is not enough. */ +#define SLNETERR_NET_APP_MDNS_UNSUPPORTED_TYPE (-6174L) /**< The unsupported resource record type. */ +#define SLNETERR_NET_APP_MDNS_DATA_SIZE_ERROR (-6175L) /**< The data size is too big. */ +#define SLNETERR_NET_APP_MDNS_AUTH_ERROR (-6176L) /**< Attempting to parse too large a data. */ +#define SLNETERR_NET_APP_MDNS_PACKET_ERROR (-6177L) /**< The packet can not add the resource record. */ +#define SLNETERR_NET_APP_MDNS_DEST_ADDRESS_ERROR (-6178L) /**< The destination address error. */ +#define SLNETERR_NET_APP_MDNS_UDP_PORT_ERROR (-6179L) /**< The udp port error. */ +#define SLNETERR_NET_APP_MDNS_NOT_LOCAL_LINK (-6180L) /**< The message that not originate from the local link. */ +#define SLNETERR_NET_APP_MDNS_EXCEED_MAX_LABEL (-6181L) /**< The data exceed the max label size. */ +#define SLNETERR_NET_APP_MDNS_EXIST_UNIQUE_RR (-6182L) /**< At least one unique record in the cache. */ +#define SLNETERR_NET_APP_MDNS_EXIST_ANSWER (-6183L) /**< At least one answer record in the cache. */ +#define SLNETERR_NET_APP_MDNS_EXIST_SAME_QUERY (-6184L) /**< Exist the same query. */ +#define SLNETERR_NET_APP_MDNS_DUPLICATE_SERVICE (-6185L) /**< Duplicate service. */ +#define SLNETERR_NET_APP_MDNS_NO_ANSWER (-6186L) /**< No response for one-shot query. */ +#define SLNETERR_NET_APP_MDNS_NO_KNOWN_ANSWER (-6187L) /**< No known answer for query. */ +#define SLNETERR_NET_APP_MDNS_NAME_MISMATCH (-6188L) /**< The name mismatch. */ +#define SLNETERR_NET_APP_MDNS_NOT_STARTED (-6189L) /**< MDNS does not start. */ +#define SLNETERR_NET_APP_MDNS_HOST_NAME_ERROR (-6190L) /**< MDNS host name error. */ +#define SLNETERR_NET_APP_MDNS_NO_MORE_ENTRIES (-6191L) /**< No more entries be found. */ +#define SLNETERR_NET_APP_MDNS_SERVICE_TYPE_MISMATCH (-6192L) /**< The service type mismatch */ +#define SLNETERR_NET_APP_MDNS_LOOKUP_INDEX_ERROR (-6193L) /**< Index is bigger than number of services. */ +#define SLNETERR_NET_APP_MDNS_MAX_SERVICES_ERROR (-6194L) +#define SLNETERR_NET_APP_MDNS_IDENTICAL_SERVICES_ERROR (-6195L) +#define SLNETERR_NET_APP_MDNS_EXISTED_SERVICE_ERROR (-6196L) +#define SLNETERR_NET_APP_MDNS_ERROR_SERVICE_NAME_ERROR (-6197L) +#define SLNETERR_NET_APP_MDNS_RX_PACKET_ALLOCATION_ERROR (-6198L) +#define SLNETERR_NET_APP_MDNS_BUFFER_SIZE_ERROR (-6199L) +#define SLNETERR_NET_APP_MDNS_NET_APP_SET_ERROR (-6200L) +#define SLNETERR_NET_APP_MDNS_GET_SERVICE_LIST_FLAG_ERROR (-6201L) +#define SLNETERR_NET_APP_MDNS_MDNS_NO_CONFIGURATION_ERROR (-6202L) +#define SLNETERR_NET_APP_MDNS_STATUS_ERROR (-6203L) +#define SLNETERR_NET_APP_ENOBUFS (-6204L) +#define SLNETERR_NET_APP_DNS_IPV6_REQ_BUT_IPV6_DISABLED (-6205L) /**< trying to issue ipv6 DNS request but ipv6 is disabled */ +#define SLNETERR_NET_APP_DNS_INVALID_FAMILY_TYPE (-6206L) /**< Family type is not ipv4 and not ipv6 */ +#define SLNETERR_NET_APP_DNS_REQ_TOO_BIG (-6207L) /**< DNS request size is too big */ +#define SLNETERR_NET_APP_DNS_ALLOC_ERROR (-6208L) /**< Allocation error */ +#define SLNETERR_NET_APP_DNS_EXECUTION_ERROR (-6209L) /**< Execution error */ +#define SLNETERR_NET_APP_P2P_ROLE_IS_NOT_CONFIGURED (-6210L) /**< role p2p is not configured yet, should be CL or GO in order to execute command */ +#define SLNETERR_NET_APP_INCORECT_ROLE_FOR_APP (-6211L) /**< incorrect role for specific application */ +#define SLNETERR_NET_APP_INCORECT_APP_MASK (-6212L) /**< mask does not match any app */ +#define SLNETERR_NET_APP_MDNS_ALREADY_STARTED (-6213L) /**< mdns application already started */ +#define SLNETERR_NET_APP_HTTP_SERVER_ALREADY_STARTED (-6214L) /**< http server application already started */ + +#define SLNETERR_NET_APP_HTTP_GENERAL_ERROR (-6216L) /**< New error - Http handle request failed */ +#define SLNETERR_NET_APP_HTTP_INVALID_TIMEOUT (-6217L) /**< New error - Http timeout invalid argument */ +#define SLNETERR_NET_APP_INVALID_URN_LENGTH (-6218L) /**< invalid URN length */ +#define SLNETERR_NET_APP_RX_BUFFER_LENGTH (-6219L) /**< size of the requested services is smaller than size of the user buffer */ + + + +/*< NETCFG ERRORS CODES*/ +#define SLNETERR_STATIC_ADDR_SUBNET_ERROR (-8193L) +#define SLNETERR_INCORRECT_IPV6_STATIC_LOCAL_ADDR (-8194L) /**< Ipv6 Local address prefix is wrong */ +#define SLNETERR_INCORRECT_IPV6_STATIC_GLOBAL_ADDR (-8195L) /**< Ipv6 Global address prefix is wrong */ +#define SLNETERR_IPV6_LOCAL_ADDR_SHOULD_BE_SET_FIRST (-8195L) /**< Attempt to set ipv6 global address before ipv6 local address is set */ + + + +/* NETUTIL ERRORS CODES */ +#define SLNETERR_NETUTIL_CRYPTO_GENERAL (-12289L) +#define SLNETERR_NETUTIL_CRYPTO_INVALID_INDEX (-12290L) +#define SLNETERR_NETUTIL_CRYPTO_INVALID_PARAM (-12291L) +#define SLNETERR_NETUTIL_CRYPTO_MEM_ALLOC (-12292L) +#define SLNETERR_NETUTIL_CRYPTO_INVALID_DB_VER (-12293L) +#define SLNETERR_NETUTIL_CRYPTO_UNSUPPORTED_OPTION (-12294L) +#define SLNETERR_NETUTIL_CRYPTO_BUFFER_TOO_SMALL (-12295L) +#define SLNETERR_NETUTIL_CRYPTO_EMPTY_DB_ENTRY (-12296L) +#define SLNETERR_NETUTIL_CRYPTO_NON_TEMPORARY_KEY (-12297L) +#define SLNETERR_NETUTIL_CRYPTO_DB_ENTRY_NOT_FREE (-12298L) +#define SLNETERR_NETUTIL_CRYPTO_CORRUPTED_DB_FILE (-12299L) + + + +/* GENERAL ERRORS CODES*/ +#define SLNETERR_INVALID_OPCODE (-14337L) +#define SLNETERR_INVALID_PARAM (-14338L) +#define SLNETERR_STATUS_ERROR (-14341L) +#define SLNETERR_NVMEM_ACCESS_FAILED (-14342L) +#define SLNETERR_NOT_ALLOWED_NWP_LOCKED (-14343L) /**< Device is locked, Return to Factory Image or Program new image should be invoked (see sl_FsCtl, sl_FsProgram) */ + +/* SECURITY ERRORS CODE */ +#define SLNETERR_LOADING_CERTIFICATE_STORE (-28673L) + +/* Device is Locked! Return to Factory Image or Program new + image should be invoked (see sl_FsCtl, sl_FsProgram) */ +#define SLNETERR_DEVICE_LOCKED_SECURITY_ALERT (-28674L) + + + +/* INTERNAL HOST ERRORS CODES*/ + +/* Receive this error in case there are no resources to issue the command + If possible, increase the number of MAX_CONCURRENT_ACTIONS (result in memory increase) + If not, try again later */ +#define SLNETERR_POOL_IS_EMPTY (-2000L) + +/* Receive this error in case a given length for RX buffer was too small. + Receive payload was bigger than the given buffer size. Therefore, payload is cut according to receive size + Recommend to increase buffer size */ +#define SLNETERR_ESMALLBUF (-2001L) + +/* Receive this error in case zero length is supplied to a "get" API + Recommend to supply length according to requested information (view options defines for help) */ +#define SLNETERR_EZEROLEN (-2002L) + +/* User supplied invalid parameter */ +#define SLNETERR_INVALPARAM (-2003L) + +/* Failed to open interface */ +#define SLNETERR_BAD_INTERFACE (-2004L) + +/* API has been aborted due to an error detected by host driver */ +#define SLNETERR_API_ABORTED (-2005L) + +/* Parameters are invalid */ +#define SLNETERR_RET_CODE_INVALID_INPUT (-2006L) + +/* Driver internal error */ +#define SLNETERR_RET_CODE_SELF_ERROR (-2007L) + +/* NWP internal error */ +#define SLNETERR_RET_CODE_NWP_IF_ERROR (-2008L) + +/* malloc error */ +#define SLNETERR_RET_CODE_MALLOC_ERROR (-2009L) + +/* protocol error */ +#define SLNETERR_RET_CODE_PROTOCOL_ERROR (-2010L) + +/* API has been aborted, command is not allowed in device lock state */ +#define SLNETERR_RET_CODE_DEV_LOCKED (-2011L) + +/* SlNetSock_Start cannot be invoked twice */ +#define SLNETERR_RET_CODE_DEV_ALREADY_STARTED (-2012L) + +/* SL Net API is in progress */ +#define SLNETERR_RET_CODE_API_COMMAND_IN_PROGRESS (-2013L) + +/* Provisioning is in progress - */ +#define SLNETERR_RET_CODE_PROVISIONING_IN_PROGRESS (-2014L) + +/* Wrong ping parameters - ping cannot be called with the following parameters: +1. infinite ping packet +2. report only when finished +3. no callback supplied */ +#define SLNETERR_RET_CODE_NET_APP_PING_INVALID_PARAMS (-2015L) + + +/* SlNetSock select already in progress. + this error will be returned if app will try to call + SlNetSock_select blocking when there is already select trigger in progress */ +#define SLNETERR_RET_CODE_SOCKET_SELECT_IN_PROGRESS_ERROR (-2016L) + +#define SLNETERR_RET_CODE_STOP_IN_PROGRESS (-2017L) + + +/* The device has not been started yet */ +#define SLNETERR_RET_CODE_DEV_NOT_STARTED (-2018L) + +/* The event link was not found in the list */ +#define SLNETERR_RET_CODE_EVENT_LINK_NOT_FOUND (-2019L) + +/* Function couldn't find any free space/location */ +#define SLNETERR_RET_CODE_NO_FREE_SPACE (-2020L) + +/* Function couldn't execute correctly */ +#define SLNETERR_RET_CODE_FUNCTION_FAILED (-2021L) + +/* Mutex creation failed */ +#define SLNETERR_RET_CODE_MUTEX_CREATION_FAILED (-2022L) + +/* Function couldn't find the requested resource */ +#define SLNETERR_RET_CODE_COULDNT_FIND_RESOURCE (-2023L) + +/* Interface doesn't support the non mandatory function */ +#define SLNETERR_RET_CODE_DOESNT_SUPPORT_NON_MANDATORY_FXN (-2024L) + +/* Socket creation in progress */ +#define SLNETERR_RET_CODE_SOCKET_CREATION_IN_PROGRESS (-2025L) + +/* Unsupported scenario, option or feature */ +#define SLNETERR_RET_CODE_UNSUPPORTED (-2026L) + + +/* sock related API's from SlNetIf_Config_t failed */ +#define SLNETSOCK_ERR_SOCKCREATE_FAILED (-3000L) +#define SLNETSOCK_ERR_SOCKCLOSE_FAILED (-3001L) +#define SLNETSOCK_ERR_SOCKSELECT_FAILED (-3002L) +#define SLNETSOCK_ERR_SOCKSETOPT_FAILED (-3003L) +#define SLNETSOCK_ERR_SOCKGETOPT_FAILED (-3004L) +#define SLNETSOCK_ERR_SOCKRECVFROM_FAILED (-3005L) +#define SLNETSOCK_ERR_SOCKSENDTO_FAILED (-3006L) +#define SLNETSOCK_ERR_SOCKSHUTDOWN_FAILED (-3007L) +#define SLNETSOCK_ERR_SOCKACCEPT_FAILED (-3008L) +#define SLNETSOCK_ERR_SOCKBIND_FAILED (-3009L) +#define SLNETSOCK_ERR_SOCKLISTEN_FAILED (-3000L) +#define SLNETSOCK_ERR_SOCKCONNECT_FAILED (-3001L) +#define SLNETSOCK_ERR_SOCKGETPEERNAME_FAILED (-3002L) +#define SLNETSOCK_ERR_SOCKGETLOCALNAME_FAILED (-3003L) +#define SLNETSOCK_ERR_SOCKRECV_FAILED (-3004L) +#define SLNETSOCK_ERR_SOCKSEND_FAILED (-3005L) +#define SLNETSOCK_ERR_SOCKSTARTSEC_FAILED (-3006L) + +/* util related API's from SlNetIf_Config_t failed */ +#define SLNETUTIL_ERR_UTILGETHOSTBYNAME_FAILED (-3100L) + +/* + * base for util error codes related to SlNetUtil_getAddrInfo and + * SlNetUtil_gaiStrErr + */ +#define SLNETUTIL_EAI_BASE (-3120L) + +/* + * util error codes related to SlNetUtil_getAddrInfo and SlNetUtil_gaiStrErr + * The numbering of these codes MUST match the order of the strErrorMsgs array + * in + */ +#define SLNETUTIL_EAI_AGAIN (-3121L) +#define SLNETUTIL_EAI_BADFLAGS (-3122L) +#define SLNETUTIL_EAI_FAIL (-3123L) +#define SLNETUTIL_EAI_FAMILY (-3124L) +#define SLNETUTIL_EAI_MEMORY (-3125L) +#define SLNETUTIL_EAI_NONAME (-3126L) +#define SLNETUTIL_EAI_SERVICE (-3127L) +#define SLNETUTIL_EAI_SOCKTYPE (-3128L) +#define SLNETUTIL_EAI_SYSTEM (-3129L) +#define SLNETUTIL_EAI_OVERFLOW (-3130L) +#define SLNETUTIL_EAI_ADDRFAMILY (-3131L) + +/* if related API's from SlNetIf_Config_t failed */ +#define SLNETIF_ERR_IFLOADSECOBJ_FAILED (-3200L) +#define SLNETIF_ERR_IFGETIPADDR_FAILED (-3201L) +#define SLNETIF_ERR_IFGETCONNECTIONSTATUS_FAILED (-3202L) +#define SLNETIF_ERR_IFCREATECONTEXT_FAILED (-3203L) + +/*! + + Close the Doxygen group. + @} + +*/ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __SL_NET_ERR_H__ */ diff --git a/simplelink/source/ti/net/slnetif.c b/simplelink/source/ti/net/slnetif.c new file mode 100644 index 0000000..96eadfe --- /dev/null +++ b/simplelink/source/ti/net/slnetif.c @@ -0,0 +1,862 @@ +/* + * Copyright (c) 2017-2020, Texas Instruments Incorporated + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of Texas Instruments Incorporated nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/*****************************************************************************/ +/* Include files */ +/*****************************************************************************/ + +/* Global includes */ +#include +#include +#include +#include + +#include +#include + +/*****************************************************************************/ +/* Macro declarations */ +/*****************************************************************************/ + +#define SLNETIF_NORMALIZE_NEEDED 0 +#if SLNETIF_NORMALIZE_NEEDED + #define SLNETIF_NORMALIZE_RET_VAL(retVal,err) ((retVal < 0)?(retVal = err):(retVal)) +#else + #define SLNETIF_NORMALIZE_RET_VAL(retVal,err) +#endif + +/* Interface maximum priority */ +#define SLNETIF_MAX_PRIORITY (15) + +/* The 32bit interface flags structure: + Bits 0-3 : interface priority + Bit 4 : Interface state + Bits 5-31 : Reserved +*/ +#define IF_PRIORITY_BITS (0x000f) +#define IF_STATE_BIT (0x0010) + +/* this macro returns the priority of the interface */ +#define GET_IF_PRIORITY(netIf) ((netIf).flags & IF_PRIORITY_BITS) + +/* this macro reset the priority of the interface */ +#define RESET_IF_PRIORITY(netIf) ((netIf).flags &= ~IF_PRIORITY_BITS) + +/* this macro set the priority of the interface */ +#define SET_IF_PRIORITY(netIf, priority) ((netIf).flags |= ((int32_t)priority)) + +/* this macro returns the state of the interface */ +#define GET_IF_STATE(netIf) (((netIf).flags & IF_STATE_BIT)?SLNETIF_STATE_ENABLE:SLNETIF_STATE_DISABLE) + +/* this macro set the interface to enable state */ +#define SET_IF_STATE_ENABLE(netIf) ((netIf).flags |= IF_STATE_BIT) + +/* this macro set the interface to disable state */ +#define SET_IF_STATE_DISABLE(netIf) ((netIf).flags &= ~IF_STATE_BIT) + +/* Check if the state bit is set */ +#define IS_STATE_BIT_SET(queryBitmap) (0 != (queryBitmap & SLNETIF_QUERY_IF_STATE_BIT)) + +/* Check if the connection status bit is set */ +#define IS_CONNECTION_STATUS_BIT_SET(queryBitmap) (0 != (queryBitmap & SLNETIF_QUERY_IF_CONNECTION_STATUS_BIT)) + +/* Return last found netIf, if none of the existing interfaces answers + the query */ +#define IS_ALLOW_PARTIAL_MATCH_BIT_SET(queryBitmap) (0 != (queryBitmap & SLNETIF_QUERY_IF_ALLOW_PARTIAL_MATCH_BIT)) + +/*****************************************************************************/ +/* Structure/Enum declarations */ +/*****************************************************************************/ + + +/* Interface Node */ +typedef struct SlNetIf_Node_t +{ + SlNetIf_t netIf; + struct SlNetIf_Node_t *next; +} SlNetIf_Node_t; + +/*****************************************************************************/ +/* Global declarations */ +/*****************************************************************************/ + +static SlNetIf_Node_t * SlNetIf_listHead = NULL; + +/*****************************************************************************/ +/* Function prototypes */ +/*****************************************************************************/ + +static int32_t SlNetIf_configCheck(const SlNetIf_Config_t *ifConf); + +//***************************************************************************** +// +// SlNetIf_configCheck - Checks that all mandatory configuration exists +// +//***************************************************************************** + +static int32_t SlNetIf_configCheck(const SlNetIf_Config_t *ifConf) +{ + /* Check if the mandatory configuration exists + This configuration needs to be updated when new mandatory is added */ + if ((NULL != ifConf) && + (NULL != ifConf->sockCreate) && + (NULL != ifConf->sockClose) && + (NULL != ifConf->sockSelect) && + (NULL != ifConf->sockSetOpt) && + (NULL != ifConf->sockGetOpt) && + (NULL != ifConf->sockRecvFrom) && + (NULL != ifConf->sockSendTo) && + (NULL != ifConf->ifGetIPAddr) && + (NULL != ifConf->ifGetConnectionStatus) ) + { + /* All mandatory configuration exists - return success */ + return SLNETERR_RET_CODE_OK; + } + else + { + /* Not all mandatory configuration exists - return error code */ + return SLNETERR_INVALPARAM; + } + +} + +//***************************************************************************** +// +// SlNetIf_init - Initialize the SlNetIf module +// +//***************************************************************************** +int32_t SlNetIf_init(int32_t flags) +{ + return SLNETERR_RET_CODE_OK; +} + + +//***************************************************************************** +// +// SlNetIf_add - Adding new interface +// +//***************************************************************************** +int32_t SlNetIf_add(uint16_t ifID, char *ifName, const SlNetIf_Config_t *ifConf, uint8_t priority) +{ + SlNetIf_Node_t *ifNode = SlNetIf_listHead; + SlNetIf_Node_t *prvNode = NULL; + char *allocName = NULL; + int16_t strLen; + int32_t retVal; + + /* Check if ifID is a valid input - Only one bit is set (Pow of 2) or if + the priority isn't a valid input */ + if ( (false == ONLY_ONE_BIT_IS_SET(ifID)) || (priority > SLNETIF_MAX_PRIORITY) ) + { + return SLNETERR_RET_CODE_INVALID_INPUT; + } + + /* Run over the interface list until finding the required ifID or Until + reaching the end of the list */ + while (NULL != ifNode) + { + /* Check if the identifier of the interface is equal to the input */ + if ((ifNode->netIf).ifID == ifID) + { + /* Required interface found, ifID cannot be used again */ + return SLNETERR_RET_CODE_INVALID_INPUT; + } + /* Check if the identifier of the interface is equal to the input */ + if ((GET_IF_PRIORITY(ifNode->netIf)) > priority) + { + /* Higher priority interface found, save location */ + prvNode = ifNode; + } + else + { + break; + } + ifNode = ifNode->next; + } + + + /* Check if all required configuration exists */ + retVal = SlNetIf_configCheck(ifConf); + + /* Check retVal in order to continue with adding the interface */ + if (SLNETERR_RET_CODE_OK == retVal) + { + /* Interface node memory allocation */ + /* Allocate memory for new interface node for the interface list */ + ifNode = malloc(sizeof(SlNetIf_Node_t)); + + /* Check if the memory allocated successfully */ + if (NULL == ifNode) + { + /* Allocation failed, return error code */ + return SLNETERR_RET_CODE_MALLOC_ERROR; + } + + /* Interface name memory allocation */ + /* Check if memory allocation for the name of the string is required */ + if (NULL != ifName) + { + /* Store the length of the interface name */ + strLen = strlen(ifName); + + /* Allocate memory that will store the name of the interface */ + allocName = malloc(strLen + 1); + + /* Check if the memory allocated successfully */ + if (NULL == allocName) + { + /* Allocation failed, free ifNode before returning from + function */ + free(ifNode); + return SLNETERR_RET_CODE_MALLOC_ERROR; + } + /* Copy the input name into the allocated memory. + * + * Note, using strcpy (not strncpy) to work around gcc warning + * https://gcc.gnu.org/bugzilla//show_bug.cgi?id=88059 + * ... and we know ifName will fit in allocName. + */ + strcpy(allocName, ifName); + } + + /* Fill the allocated interface node with the input parameters */ + + /* Copy the interface ID */ + (ifNode->netIf).ifID = ifID; + /* Connect the string allocated memory into the allocated interface */ + (ifNode->netIf).ifName = allocName; + /* Copy the interface configuration */ + (ifNode->netIf).ifConf = (SlNetIf_Config_t *)ifConf; + /* Reset the flags, set state to ENABLE and set the priority */ + (ifNode->netIf).flags = 0; + SET_IF_PRIORITY(ifNode->netIf, priority); + SET_IF_STATE_ENABLE(ifNode->netIf); + + /* Check if CreateContext function exists */ + if (NULL != ifConf->ifCreateContext) + { + /* Function exists, run it and fill the context */ + retVal = ifConf->ifCreateContext(ifID, allocName, &((ifNode->netIf).ifContext)); + } + + /* Check retVal before continuing */ + if (SLNETERR_RET_CODE_OK == retVal) + { + /* After creating and filling the interface, add it to the right + place in the list according to its priority */ + + /* Check if there isn't any higher priority node */ + if (NULL == prvNode) + { + /* there isn't any higher priority node so check if list is + empty */ + if (NULL != SlNetIf_listHead) + { + /* List isn't empty, so use the new allocated interface + as the new head and connect the old list head as the + following node */ + ifNode->next = SlNetIf_listHead; + } + else + { + /* List is empty, so the new allocated interface will be + the head list */ + ifNode->next = NULL; + } + SlNetIf_listHead = ifNode; + } + else + { + /* Higher priority exists, connect the allocated node after + the prvNode and the next node (if exists) of prvNode to + the next of the node */ + ifNode->next = prvNode->next; + prvNode->next = ifNode; + } + } + } + + return retVal; +} + + +//***************************************************************************** +// +// SlNetIf_getIfByID - Get interface configuration from interface ID +// +//***************************************************************************** +SlNetIf_t * SlNetIf_getIfByID(uint16_t ifID) +{ + SlNetIf_Node_t *ifNode = SlNetIf_listHead; + + /* Check if ifID is a valid input - Only one bit is set (Pow of 2) */ + if (false == ONLY_ONE_BIT_IS_SET(ifID)) + { + return NULL; + } + + /* Run over the interface list until finding the required ifID or Until + reaching the end of the list */ + while (NULL != ifNode) + { + /* Check if the identifier of the interface is equal to the input */ + if ((ifNode->netIf).ifID == ifID) + { + /* Required interface found, return the interface pointer */ + return &(ifNode->netIf); + } + ifNode = ifNode->next; + } + + /* Interface identifier was not found */ + return NULL; +} + +//***************************************************************************** +// +// SlNetIf_queryIf - Get interface configuration with the highest priority +// from the provided interface bitmap +// Note: ifBitmap - 0 is not a valid input +// +//***************************************************************************** +SlNetIf_t * SlNetIf_queryIf(uint32_t ifBitmap, uint32_t queryBitmap) +{ + SlNetIf_Node_t *ifNode = SlNetIf_listHead; + SlNetIf_t *bestPartialMatchIf = NULL; + + if (0 == ifBitmap) + { + return NULL; + } + + /* Run over the interface list until finding the first ifID that is + set in the ifBitmap or Until reaching the end of the list if no + ifID were found */ + while (NULL != ifNode) + { + /* Check if the identifier of the interface is equal to the input */ + if (((ifNode->netIf).ifID) & ifBitmap) + { + /* Save the netIf only at the first match */ + if (NULL == bestPartialMatchIf) + { + bestPartialMatchIf = &(ifNode->netIf); + } + /* Skip over Bitmap queries */ + if ( 0 != queryBitmap) + { + /* Check if the state bit needs to be set and if it is */ + if ( (true == IS_STATE_BIT_SET(queryBitmap)) && + (SLNETIF_STATE_DISABLE == (GET_IF_STATE(ifNode->netIf))) ) + { + /* State is disabled when needed to be set, continue + to the next interface */ + ifNode = ifNode->next; + continue; + } + /* Check if the connection status bit needs to be set + and if it is */ + if ( (true == IS_CONNECTION_STATUS_BIT_SET(queryBitmap)) && + (SLNETIF_STATUS_CONNECTED != SlNetIf_getConnectionStatus((ifNode->netIf).ifID)) ) + { + /* Connection status is not connected when it needed to + be - continue to the next interface */ + ifNode = ifNode->next; + continue; + } + } + /* Required interface found, return the interface pointer */ + return &(ifNode->netIf); + } + ifNode = ifNode->next; + } + + /* When bit is set, return the last interface found if there isn't + an existing interface that answers the query return the last + netIf that was found */ + if (true == IS_ALLOW_PARTIAL_MATCH_BIT_SET(queryBitmap)) + { + return bestPartialMatchIf; + } + else + { + return NULL; + } + +} + + +//***************************************************************************** +// +// SlNetIf_getNameByID - Get interface Name from interface ID +// +//***************************************************************************** +const char * SlNetIf_getNameByID(uint16_t ifID) +{ + SlNetIf_t *netIf; + + /* Run validity check and find the requested interface */ + netIf = SlNetIf_getIfByID(ifID); + + /* Check if the requested interface exists or the function returned NULL */ + if (NULL == netIf) + { + /* Interface doesn't exists or invalid input, return NULL */ + return NULL; + } + else + { + /* Interface exists, return the interface name */ + return netIf->ifName; + } +} + + +//***************************************************************************** +// +// SlNetIf_getIDByName - Get interface ID from interface name +// +//***************************************************************************** +int32_t SlNetIf_getIDByName(char *ifName) +{ + SlNetIf_Node_t *ifNode = SlNetIf_listHead; + + /* Check if ifName is a valid input */ + if (NULL == ifName) + { + return(SLNETERR_RET_CODE_INVALID_INPUT); + } + + /* Run over the interface list until finding the required ifID or Until + reaching the end of the list */ + while (NULL != ifNode) + { + /* Check if the identifier of the interface is equal to the input */ + if (strcmp((ifNode->netIf).ifName, ifName) == 0) + { + /* Required interface found, return the interface identifier */ + return ((ifNode->netIf).ifID); + } + ifNode = ifNode->next; + } + + /* Interface identifier was not found, return error code */ + return(SLNETERR_RET_CODE_INVALID_INPUT); +} + + +//***************************************************************************** +// +// SlNetIf_getPriority - Get interface priority +// +//***************************************************************************** +int32_t SlNetIf_getPriority(uint16_t ifID) +{ + SlNetIf_t *netIf; + + /* Run validity check and find the requested interface */ + netIf = SlNetIf_getIfByID(ifID); + + /* Check if the requested interface exists or the function returned NULL */ + if (NULL == netIf) + { + /* Interface doesn't exists or invalid input, return error code */ + return SLNETERR_RET_CODE_INVALID_INPUT; + } + else + { + /* Interface exists, return interface priority */ + return GET_IF_PRIORITY(*netIf); + } +} + + +//***************************************************************************** +// +// SlNetIf_setPriority - Set interface priority +// +//***************************************************************************** +int32_t SlNetIf_setPriority(uint16_t ifID, uint8_t priority) +{ + SlNetIf_Node_t *ifListNode = SlNetIf_listHead; + SlNetIf_Node_t *prvIfListNode = SlNetIf_listHead; + SlNetIf_Node_t *reqIfListNode = NULL; + bool connectAgain = false; + + if (priority > SLNETIF_MAX_PRIORITY) + { + /* Run validity check and find the requested interface */ + return SLNETERR_RET_CODE_INVALID_INPUT; + } + + /* Find the location of required interface */ + while (NULL != ifListNode) + { + /* If the location of the required interface found, store the + location */ + if ((ifListNode->netIf.ifID) == ifID) + { + reqIfListNode = ifListNode; + /* Check if the required interface is the last node and needs + lower priority than the previous node, only update of the + priority is required for this node */ + if (NULL == ifListNode->next) + { + if (GET_IF_PRIORITY(prvIfListNode->netIf) >= priority) + { + /* The required interface is the last node and needs + lower priority than the previous node, only update + of the priority is required for this node */ + break; + } + else + { + /* The required interface is the last node but has + higher priority than the previous node, disconnect + the interface from the list. connect the previous node + to the end of the list + If this is not the only node in the list, find where + it now belongs based on its new priority. */ + if (reqIfListNode != SlNetIf_listHead) + { + prvIfListNode->next = NULL; + connectAgain = true; + /* This is the end of the list, so stop looping */ + break; + } + } + } + /* Check if the required interface is the first node in the list */ + else if (SlNetIf_listHead == ifListNode) + { + if ( (NULL == ifListNode->next) || ((GET_IF_PRIORITY(ifListNode->next->netIf)) <= priority) ) + { + /* The required interface is the first node and needs + higher priority than the following node, only update + of the priority is required for this node */ + break; + } + /* The required interface is the first node but doesn't need + higher priority than the following node so the following + node will be the first node of the list */ + else + { + SlNetIf_listHead = ifListNode->next; + connectAgain = true; + } + } + /* The required interface isn't the first or last node and needs + priority change but is in the correct location, only update + of the priority is required for this node */ + else if ( (GET_IF_PRIORITY(prvIfListNode->netIf) >= priority) && ((GET_IF_PRIORITY(ifListNode->next->netIf)) <= priority) ) + { + break; + } + /* The required interface isn't the first or last node and needs + priority change, disconnect it from the list. connect the + previous node with the following node */ + else + { + prvIfListNode->next = prvIfListNode->next->next; + connectAgain = true; + } + } + else + { + prvIfListNode = ifListNode; + } + ifListNode = ifListNode->next; + } + + /* When connectAgain is set, there's a need to find where to add back + the required interface according to the priority */ + if (connectAgain == true) + { + ifListNode = SlNetIf_listHead; + while (NULL != ifListNode) + { + /* If the incoming priority is higher than any present */ + if (ifListNode == SlNetIf_listHead) + { + if ((GET_IF_PRIORITY(ifListNode->netIf)) <= priority) + { + reqIfListNode->next = ifListNode; + SlNetIf_listHead = reqIfListNode; + break; + } + } + + /* Check if the priority of the current interface is higher of + the required priority, if so, store it as the previous + interface and continue to search until finding interface with + lower priority and than connect the required interface to the + prior interface */ + if ((GET_IF_PRIORITY(ifListNode->netIf)) > priority) + { + prvIfListNode = ifListNode; + + } + else + { + reqIfListNode->next = prvIfListNode->next; + prvIfListNode->next = reqIfListNode; + break; + } + ifListNode = ifListNode->next; + + if (NULL == ifListNode) + { + /* All interfaces have higher priorities than reqIfListNode */ + prvIfListNode->next = reqIfListNode; + reqIfListNode->next = NULL; + break; + } + } + } + + if (NULL != reqIfListNode) + { + /* Interface exists, set the interface priority */ + RESET_IF_PRIORITY(reqIfListNode->netIf); + SET_IF_PRIORITY(reqIfListNode->netIf, priority); + } + + return SLNETERR_RET_CODE_OK; +} + + +//***************************************************************************** +// +// SlNetIf_setState - Set interface state +// +//***************************************************************************** +int32_t SlNetIf_setState(uint16_t ifID, SlNetIfState_e ifState) +{ + SlNetIf_t *netIf; + + /* Run validity check and find the requested interface */ + netIf = SlNetIf_getIfByID(ifID); + + /* Check if the requested interface exists or the function returned NULL */ + if (NULL == netIf) + { + /* Interface doesn't exists or invalid input, return error code */ + return SLNETERR_RET_CODE_INVALID_INPUT; + } + else + { + /* Interface exists, set the interface state */ + if (ifState == SLNETIF_STATE_DISABLE) + { + /* Interface state - Disable */ + SET_IF_STATE_DISABLE(*netIf); + } + else + { + /* Interface state - Enable */ + SET_IF_STATE_ENABLE(*netIf); + } + } + return SLNETERR_RET_CODE_OK; +} + + +//***************************************************************************** +// +// SlNetIf_getState - Get interface state +// +//***************************************************************************** +int32_t SlNetIf_getState(uint16_t ifID) +{ + SlNetIf_t *netIf; + + /* Run validity check and find the requested interface */ + netIf = SlNetIf_getIfByID(ifID); + + /* Check if the requested interface exists or the function returned NULL */ + if (NULL == netIf) + { + /* Interface doesn't exists or invalid input, return error code */ + return SLNETERR_RET_CODE_INVALID_INPUT; + } + else + { + /* Interface exists, return interface state */ + return GET_IF_STATE(*netIf); + } +} + + +//***************************************************************************** +// +// SlNetIf_getIPAddr - Get IP Address of specific interface +// +//***************************************************************************** +int32_t SlNetIf_getIPAddr(uint16_t ifID, SlNetIfAddressType_e addrType, uint16_t *addrConfig, uint32_t *ipAddr) +{ + SlNetIf_t *netIf; + int32_t retVal; + + /* Run validity check and find the requested interface */ + netIf = SlNetIf_getIfByID(ifID); + + /* Check if the requested interface exists or the function returned NULL */ + if (NULL == netIf) + { + /* Interface doesn't exists or invalid input, return NULL */ + return SLNETERR_RET_CODE_INVALID_INPUT; + } + else + { + /* Interface exists, return interface IP address */ + retVal = (netIf->ifConf)->ifGetIPAddr(netIf->ifContext, addrType, addrConfig, ipAddr); + SLNETIF_NORMALIZE_RET_VAL(retVal,SLNETIF_ERR_IFGETIPADDR_FAILED); + + /* Check retVal for error codes */ + if (retVal < SLNETERR_RET_CODE_OK) + { + /* Return retVal, function error */ + return retVal; + } + else + { + /* Return success */ + return SLNETERR_RET_CODE_OK; + } + } +} + + +//***************************************************************************** +// +// SlNetIf_getConnectionStatus - Get interface connection status +// +//***************************************************************************** +int32_t SlNetIf_getConnectionStatus(uint16_t ifID) +{ + SlNetIf_t *netIf; + int16_t connectionStatus; + + /* Run validity check and find the requested interface */ + netIf = SlNetIf_getIfByID(ifID); + + /* Check if the requested interface exists or the function returned NULL */ + if (NULL == netIf) + { + /* Interface doesn't exists or invalid input, return NULL */ + return SLNETERR_RET_CODE_INVALID_INPUT; + } + else + { + /* Interface exists, return interface connection status */ + connectionStatus = (netIf->ifConf)->ifGetConnectionStatus(netIf->ifContext); + + /* Interface exists, set the interface state */ + if (connectionStatus == SLNETIF_STATUS_DISCONNECTED) + { + /* Interface is disconnected */ + return SLNETIF_STATUS_DISCONNECTED; + } + else if (connectionStatus > SLNETIF_STATUS_DISCONNECTED) + { + SLNETIF_NORMALIZE_RET_VAL(connectionStatus,SLNETIF_STATUS_CONNECTED); + } + else + { + SLNETIF_NORMALIZE_RET_VAL(connectionStatus,SLNETIF_ERR_IFGETCONNECTIONSTATUS_FAILED); + } + return connectionStatus; + } +} + + +//***************************************************************************** +// +// SlNetIf_loadSecObj - Load secured buffer to the network stack +// +//***************************************************************************** +int32_t SlNetIf_loadSecObj(uint16_t objType, char *objName, int16_t objNameLen, uint8_t *objBuff, int16_t objBuffLen, uint32_t ifBitmap) +{ + SlNetIf_t *netIf; + int32_t retVal; + uint32_t ifIDIndex = 1; /* Set value to highest bit in uint32_t */ + uint32_t maxIDIndex = (uint32_t)1 << SLNETIF_MAX_IF; + + /* validate params */ + if ((objName == NULL) || (strlen(objName) != objNameLen) || + ((objType != SLNETIF_SEC_OBJ_TYPE_RSA_PRIVATE_KEY) && + (objType != SLNETIF_SEC_OBJ_TYPE_CERTIFICATE) && + (objType != SLNETIF_SEC_OBJ_TYPE_DH_KEY))) + { + return SLNETERR_RET_CODE_INVALID_INPUT; + } + + /* bitmap 0 entered, load sec obj to all available interfaces */ + if (0 == ifBitmap) + { + ifBitmap = ~ifBitmap; + } + + while ( ifIDIndex < maxIDIndex ) + { + /* Check if ifIDIndex is a required ifID from the ifBitmap */ + if ( ifIDIndex & ifBitmap ) + { + /* Run validity check and find the requested interface */ + netIf = SlNetIf_getIfByID(ifIDIndex & ifBitmap); + + /* Check if the requested interface exists or the function + returned NULL */ + if ( (NULL != netIf) && (NULL != (netIf->ifConf)->ifLoadSecObj) ) + { + /* Interface exists, return interface IP address */ + retVal = (netIf->ifConf)->ifLoadSecObj(netIf->ifContext, objType, objName, objNameLen, objBuff, objBuffLen); + SLNETIF_NORMALIZE_RET_VAL(retVal,SLNETIF_ERR_IFLOADSECOBJ_FAILED); + + /* Check retVal for error codes */ + if (retVal < SLNETERR_RET_CODE_OK) + { + /* Return retVal, function error */ + return retVal; + } + else + { + /* Return success */ + return SLNETERR_RET_CODE_OK; + } + } + } + ifIDIndex <<= 1; + } + /* Interface doesn't exists or invalid input, return error code */ + return SLNETERR_RET_CODE_INVALID_INPUT; +} diff --git a/simplelink/source/ti/net/slnetif.h b/simplelink/source/ti/net/slnetif.h new file mode 100644 index 0000000..f259f26 --- /dev/null +++ b/simplelink/source/ti/net/slnetif.h @@ -0,0 +1,630 @@ +/* + * Copyright (c) 2017-2019, Texas Instruments Incorporated + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of Texas Instruments Incorporated nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/*****************************************************************************/ +/* Include files */ +/*****************************************************************************/ + +#ifndef __SL_NET_IF_H__ +#define __SL_NET_IF_H__ + +#include +#include + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/*! + \defgroup SlNetIf SlNetIf group + + \short Controls standard stack/interface options and capabilities + +*/ +/*! + \addtogroup SlNetIf + @{ +*/ + +/*****************************************************************************/ +/* Macro declarations */ +/*****************************************************************************/ + +/* Interface ID bit pool to be used in interface add and in socket creation */ +#define SLNETIF_ID_1 (1 << 0) /**< Interface ID 1 */ +#define SLNETIF_ID_2 (1 << 1) /**< Interface ID 2 */ +#define SLNETIF_ID_3 (1 << 2) /**< Interface ID 3 */ +#define SLNETIF_ID_4 (1 << 3) /**< Interface ID 4 */ +#define SLNETIF_ID_5 (1 << 4) /**< Interface ID 5 */ +#define SLNETIF_ID_6 (1 << 5) /**< Interface ID 6 */ +#define SLNETIF_ID_7 (1 << 6) /**< Interface ID 7 */ +#define SLNETIF_ID_8 (1 << 7) /**< Interface ID 8 */ +#define SLNETIF_ID_9 (1 << 8) /**< Interface ID 9 */ +#define SLNETIF_ID_10 (1 << 9) /**< Interface ID 10 */ +#define SLNETIF_ID_11 (1 << 10) /**< Interface ID 11 */ +#define SLNETIF_ID_12 (1 << 11) /**< Interface ID 12 */ +#define SLNETIF_ID_13 (1 << 12) /**< Interface ID 13 */ +#define SLNETIF_ID_14 (1 << 13) /**< Interface ID 14 */ +#define SLNETIF_ID_15 (1 << 14) /**< Interface ID 15 */ +#define SLNETIF_ID_16 (1 << 15) /**< Interface ID 16 */ + +#define SLNETIF_MAX_IF (16) /**< Maximum interface */ + +/* this macro returns 0 when only one bit is set and a number when it isn't */ +#define ONLY_ONE_BIT_IS_SET(x) (((x > 0) && ((x & (x - 1)) == 0))?true:false) + + +/* Interface connection status bit pool to be used in set interface connection status function */ + +#define SLNETIF_STATUS_DISCONNECTED (0) +#define SLNETIF_STATUS_CONNECTED (1) + +/*! + \brief Interface state bit pool to be used in set interface state function +*/ +typedef enum +{ + SLNETIF_STATE_DISABLE = 0, + SLNETIF_STATE_ENABLE = 1 +} SlNetIfState_e; + +/*! + \brief Address type enum to be used in get ip address function +*/ +typedef enum +{ + SLNETIF_IPV4_ADDR = 0, + SLNETIF_IPV6_ADDR_LOCAL = 1, + SLNETIF_IPV6_ADDR_GLOBAL = 2 +} SlNetIfAddressType_e; + +/* Address config return values that can be retrieved in get ip address function */ +#define SLNETIF_ADDR_CFG_UNKNOWN (0) +#define SLNETIF_ADDR_CFG_DHCP (1) +#define SLNETIF_ADDR_CFG_DHCP_LLA (2) +#define SLNETIF_ADDR_CFG_STATIC (4) +#define SLNETIF_ADDR_CFG_STATELESS (5) +#define SLNETIF_ADDR_CFG_STATEFUL (6) + +/* Security object types for load Sec Obj function */ +#define SLNETIF_SEC_OBJ_TYPE_RSA_PRIVATE_KEY (1) +#define SLNETIF_SEC_OBJ_TYPE_CERTIFICATE (2) +#define SLNETIF_SEC_OBJ_TYPE_DH_KEY (3) + + +/*! + Check if interface state is enabled. + + \sa SlNetIf_queryIf() + */ +#define SLNETIF_QUERY_IF_STATE_BIT (1 << 0) +/*! + Check if interface connection status is connected. + + \sa SlNetIf_queryIf() + */ +#define SLNETIF_QUERY_IF_CONNECTION_STATUS_BIT (1 << 1) +/*! + Enable last partial match in an interface search, if no existing + interface matches the query completely. + + \sa SlNetIf_queryIf() + */ +#define SLNETIF_QUERY_IF_ALLOW_PARTIAL_MATCH_BIT (1 << 2) + +/*****************************************************************************/ +/* Structure/Enum declarations */ +/*****************************************************************************/ + +/*! + \brief SlNetIf_Config_t structure contains all the function callbacks that are expected to be filled by the relevant network stack interface \n + Each interface has different capabilities, so not all the API's must be supported therefore an API's can be defined as: + - Mandatory API's - must be supported by the interface in order to be part of SlNetSock layer + - Non-Mandatory API's - can be supported, but not mandatory for basic SlNetSock proper operation + + \note Interface that is not supporting a non-mandatory API should set it to \b NULL in its function list + + \sa SlNetIf_Config_t +*/ +typedef struct SlNetIf_Config_t +{ + /* socket related API's */ + int16_t (*sockCreate) (void *ifContext, int16_t domain, int16_t type, int16_t protocol, void **sdContext); /*!< \b Mandatory API \n The actual implementation of the interface for ::SlNetSock_create */ + int32_t (*sockClose) (int16_t sd, void *sdContext); /*!< \b Mandatory API \n The actual implementation of the interface for ::SlNetSock_close */ + int32_t (*sockShutdown) (int16_t sd, void *sdContext, int16_t how); /*!< \b Non-Mandatory API \n The actual implementation of the interface for ::SlNetSock_shutdown */ + int16_t (*sockAccept) (int16_t sd, void *sdContext, SlNetSock_Addr_t *addr, SlNetSocklen_t *addrlen, uint8_t flags, void **acceptedSdContext); /*!< \b Non-Mandatory API \n The actual implementation of the interface for ::SlNetSock_accept */ + int32_t (*sockBind) (int16_t sd, void *sdContext, const SlNetSock_Addr_t *addr, int16_t addrlen); /*!< \b Non-Mandatory API \n The actual implementation of the interface for ::SlNetSock_bind */ + int32_t (*sockListen) (int16_t sd, void *sdContext, int16_t backlog); /*!< \b Non-Mandatory API \n The actual implementation of the interface for ::SlNetSock_listen */ + int32_t (*sockConnect) (int16_t sd, void *sdContext, const SlNetSock_Addr_t *addr, SlNetSocklen_t addrlen, uint8_t flags); /*!< \b Non-Mandatory API \n The actual implementation of the interface for ::SlNetSock_connect */ + int32_t (*sockGetPeerName) (int16_t sd, void *sdContext, SlNetSock_Addr_t *addr, SlNetSocklen_t *addrlen); /*!< \b Non-Mandatory API \n The actual implementation of the interface for ::SlNetSock_getPeerName */ + int32_t (*sockGetLocalName) (int16_t sd, void *sdContext, SlNetSock_Addr_t *addr, SlNetSocklen_t *addrlen); /*!< \b Non-Mandatory API \n The actual implementation of the interface for ::SlNetSock_getSockName */ + int32_t (*sockSelect) (void *ifContext, int16_t nsds, SlNetSock_SdSet_t *readsds, SlNetSock_SdSet_t *writesds, SlNetSock_SdSet_t *exceptsds, SlNetSock_Timeval_t *timeout); /*!< \b Mandatory API \n The actual implementation of the interface for ::SlNetSock_select */ + int32_t (*sockSetOpt) (int16_t sd, void *sdContext, int16_t level, int16_t optname, void *optval, SlNetSocklen_t optlen); /*!< \b Mandatory API \n The actual implementation of the interface for ::SlNetSock_setOpt */ + int32_t (*sockGetOpt) (int16_t sd, void *sdContext, int16_t level, int16_t optname, void *optval, SlNetSocklen_t *optlen); /*!< \b Mandatory API \n The actual implementation of the interface for ::SlNetSock_getOpt */ + int32_t (*sockRecv) (int16_t sd, void *sdContext, void *buf, uint32_t len, uint32_t flags); /*!< \b Non-Mandatory API \n The actual implementation of the interface for ::SlNetSock_recv */ + int32_t (*sockRecvFrom) (int16_t sd, void *sdContext, void *buf, uint32_t len, uint32_t flags, SlNetSock_Addr_t *from, SlNetSocklen_t *fromlen); /*!< \b Mandatory API \n The actual implementation of the interface for ::SlNetSock_recvFrom */ + int32_t (*sockSend) (int16_t sd, void *sdContext, const void *buf, uint32_t len, uint32_t flags); /*!< \b Non-Mandatory API \n The actual implementation of the interface for ::SlNetSock_send */ + int32_t (*sockSendTo) (int16_t sd, void *sdContext, const void *buf, uint32_t len, uint32_t flags, const SlNetSock_Addr_t *to, SlNetSocklen_t tolen); /*!< \b Mandatory API \n The actual implementation of the interface for ::SlNetSock_sendTo */ + int32_t (*sockstartSec) (int16_t sd, void *sdContext, SlNetSockSecAttrib_t *secAttrib, uint8_t flags); /*!< \b Non-Mandatory API \n The actual implementation of the interface for ::SlNetSock_startSec */ + + /* util related API's */ + int32_t (*utilGetHostByName) (void *ifContext, char *name, const uint16_t nameLen, uint32_t *ipAddr, uint16_t *ipAddrLen, const uint8_t family); /*!< \b Non-Mandatory API \n The actual implementation of the interface for ::SlNetUtil_getHostByName */ + + /* if related API's */ + int32_t (*ifGetIPAddr) (void *ifContext, SlNetIfAddressType_e addrType, uint16_t *addrConfig, uint32_t *ipAddr); /*!< \b Mandatory API \n The actual implementation of the interface for ::SlNetIf_getIPAddr */ + int32_t (*ifGetConnectionStatus) (void *ifContext); /*!< \b Mandatory API \n The actual implementation of the interface for ::SlNetIf_getConnectionStatus */ + int32_t (*ifLoadSecObj) (void *ifContext, uint16_t objType, char *objName, int16_t objNameLen, uint8_t *objBuff, int16_t objBuffLen); /*!< \b Non-Mandatory API \n The actual implementation of the interface for ::SlNetIf_loadSecObj */ + int32_t (*ifCreateContext) (uint16_t ifID, const char *ifName, void **ifContext); /*!< \b Non-Mandatory API \n The actual implementation of the interface for ::SlNetIf_add */ + +} SlNetIf_Config_t; + + +/*! + \brief The SlNetIf_t structure holds the configuration of the interface + Its ID, name, flags and the configuration list - ::SlNetIf_Config_t. +*/ +typedef struct SlNetIf_t +{ + uint32_t ifID; + char *ifName; + int32_t flags; + SlNetIf_Config_t *ifConf; + void *ifContext; +} SlNetIf_t; + +/*****************************************************************************/ +/* Function prototypes */ +/*****************************************************************************/ + +/*! + + \brief Initialize the SlNetIf module + + \param[in] flags For future usage, + The value 0 may be used in order to run the + default flags + + \return Zero on success, or negative error code on failure + + \par Examples + \snippet ti/net/test/snippets/slnetif.c SlNetIf_init snippet +*/ +int32_t SlNetIf_init(int32_t flags); + +/*! + \brief Add a new SlNetIf-compatible interface to the system + + The SlNetIf_add function allows the application to add specific interfaces + with their priorities and function list.\n + This function gives full control to the application on the interfaces. + + \param[in] ifID Specifies the interface which needs + to be added.\n + The values of the interface identifier + is defined with the prefix SLNETIF_ID_ + which defined in slnetif.h + \param[in] ifName Specifies the name of the interface, + \b Note: Can be set to NULL, but when set to NULL + cannot be used with SlNetIf_getIDByName() + \param[in] ifConf Specifies the function list for the + interface + \param[in] priority Specifies the priority of the interface + (In ascending order). + Note: maximum priority is 15 + + \return Zero on success, or negative error code on failure + + \slnetif_not_threadsafe + + \par Examples + \snippet ti/net/test/snippets/slnetif.c SlNetIf_add wifi snippet + \snippet ti/net/test/snippets/slnetif.c SlNetIf_add NDK snippet + \snippet ti/net/test/snippets/slnetif.c SlNetIf_add NDKSec snippet +*/ +int32_t SlNetIf_add(uint16_t ifID, char *ifName, const SlNetIf_Config_t *ifConf, uint8_t priority); + + +/*! + \brief Get interface configuration from interface ID + + The SlNetIf_getIfByID function retrieves the configuration of the + requested interface. + + \param[in] ifID Specifies the interface which its configuration + needs to be retrieved.\n + The values of the interface identifier is + defined with the prefix SLNETIF_ID_ which + defined in slnetif.h + + \return A pointer to the configuration of the + interface on success, or NULL on failure + + \sa SlNetIf_add() + + \slnetif_not_threadsafe + + \par Examples + \snippet ti/net/test/snippets/slnetif.c SlNetIf_getIfByID snippet +*/ +SlNetIf_t * SlNetIf_getIfByID(uint16_t ifID); + + +/*! + \brief Query for the highest priority interface, given a list of + interfaces and properties. + + \param[in] ifBitmap The bit-wise OR of interfaces to be searched.\n + Note: Zero is currently not valid. + \param[in] queryBitmap The bit-wise OR of additional query criteria. + + \remarks @c queryBitmap can be set to : + - #SLNETIF_QUERY_IF_STATE_BIT + - #SLNETIF_QUERY_IF_CONNECTION_STATUS_BIT + - #SLNETIF_QUERY_IF_ALLOW_PARTIAL_MATCH_BIT + + \return A pointer to the configuration of a found + interface on success, or NULL on failure + + \sa SlNetIf_add() + \slnetif_not_threadsafe + + \par Examples + \snippet ti/net/test/snippets/slnetif.c SlNetIf_queryIf snippet +*/ +SlNetIf_t * SlNetIf_queryIf(uint32_t ifBitmap, uint32_t queryBitmap); + + +/*! + \brief Get interface Name from interface ID + + The SlNetIf_getNameByID function retrieves the name of the requested + interface. + + \param[in] ifID Specifies the interface which its name needs + to be retrieved.\n + The values of the interface identifier is + defined with the prefix SLNETIF_ID_ which + defined in slnetif.h + + \return A pointer to the name of the interface on + success, or NULL on failure + + \sa SlNetIf_add() + \sa SlNetIf_getIDByName() + + \slnetif_not_threadsafe + + \par Examples + \snippet ti/net/test/snippets/slnetif.c SlNetIf_getNameByID snippet +*/ +const char * SlNetIf_getNameByID(uint16_t ifID); + + +/*! + \brief Get interface ID from interface name + + The SlNetIf_getIDByName function retrieves the interface identifier of the + requested interface name. + + \param[in] ifName Specifies the interface which its interface + identifier needs to be retrieved.\n + + \return The interface identifier value of the interface + on success, or negative error code on failure + The values of the interface identifier is + defined with the prefix SLNETIF_ID_ which + defined in slnetif.h + + \sa SlNetIf_add() + \sa SlNetIf_getNameByID() + \sa SlNetSock_getIfID() + + \note - Input NULL as ifName will return error code. + - When using more than one interface with the same + name, the ID of the highest priority interface + will be returned + \slnetif_not_threadsafe + + \par Examples + \snippet ti/net/test/snippets/slnetif.c SlNetIf_getIDByName snippet +*/ +int32_t SlNetIf_getIDByName(char *ifName); + + +/*! + \brief Get interface priority + + The SlNetIf_getPriority function retrieves the priority of the + interface. + + \param[in] ifID Specifies the interface which its priority + needs to be retrieved.\n + The values of the interface identifier is + defined with the prefix SLNETIF_ID_ which + defined in slnetif.h + + \return The priority value of the interface on success, + or negative error code on failure + + \sa SlNetIf_add() + \sa SlNetIf_setPriority() + + \slnetif_not_threadsafe + + \par Examples + \snippet ti/net/test/snippets/slnetif.c SlNetIf_getPriority snippet +*/ +int32_t SlNetIf_getPriority(uint16_t ifID); + + +/*! + \brief Set interface priority + + The SlNetIf_setPriority function sets new priority to the requested interface. + + \param[in] ifID Specifies the interface which its priority + needs to be changed.\n + The values of the interface identifier is + defined with the prefix SLNETIF_ID_ which + defined in slnetif.h + \param[in] priority Specifies the priority needs to be set. + (In ascending order) + Note: maximum priority is 15 + + \return Zero on success, or negative error code on + failure + + \sa SlNetIf_add() + \sa SlNetIf_getPriority() + + \slnetif_not_threadsafe + + \par Examples + \snippet ti/net/test/snippets/slnetif.c SlNetIf_setPriority snippet +*/ +int32_t SlNetIf_setPriority(uint16_t ifID, uint8_t priority); + + +/*! + \brief Set interface state + + Enable or disable the interface. + + \param[in] ifID Specifies the interface which its state + needs to be changed.\n + The values of the interface identifier is + defined with the prefix SLNETIF_ID_ which + defined in slnetif.h + \param[in] ifState Specifies the interface state.\n + The values of the interface state are defined + with the prefix SLNETIF_INTERFACE_ which + defined in slnetif.h + + \return Zero on success, or negative error code on + failure + + \sa SlNetIf_add() + \sa SlNetIf_getState() + + \slnetif_not_threadsafe + + \par Examples + \snippet ti/net/test/snippets/slnetif.c SlNetIf_setState snippet +*/ +int32_t SlNetIf_setState(uint16_t ifID, SlNetIfState_e ifState); + + +/*! + \brief Get interface state + + Obtain the current state of the interface. + + \param[in] ifID Specifies the interface which its state needs + to be retrieved.\n + The values of the interface identifier is + defined with the prefix SLNETIF_ID_ which + defined in slnetif.h + + \return State of the interface on success, or negative + error code on failure + + \sa SlNetIf_add() + \sa SlNetIf_setState() + + \slnetif_not_threadsafe + + \par Examples + \snippet ti/net/test/snippets/slnetif.c SlNetIf_getState snippet +*/ +int32_t SlNetIf_getState(uint16_t ifID); + + +/*! + \brief Get the connection status of an interface + + \param[in] ifID Interface ID + + \return @c SLNETIF_STATUS_ value on success, + or negative error code on failure + + \remark @c ifID should be a value with the @c SLNETIF_ID_ + prefix + + \sa SlNetIf_add() + \sa SLNETIF_STATUS_CONNECTED + \sa SLNETIF_STATUS_DISCONNECTED + + \slnetif_not_threadsafe + + \par Examples + \snippet ti/net/test/snippets/slnetif.c SlNetIf_getConnectionStatus snippet +*/ +int32_t SlNetIf_getConnectionStatus(uint16_t ifID); + + +/*! + \brief Get IP Address of specific interface + + The SlNetIf_getIPAddr function retrieve the IP address of a specific + interface according to the Address Type, IPv4, IPv6 LOCAL + or IPv6 GLOBAL. + + \param[in] ifID Specifies the interface which its connection + state needs to be retrieved.\n + The values of the interface identifier is + defined with the prefix SLNETIF_ID_ which + defined in slnetif.h + \param[in] addrType Address type: + - #SLNETIF_IPV4_ADDR + - #SLNETIF_IPV6_ADDR_LOCAL + - #SLNETIF_IPV6_ADDR_GLOBAL + \param[out] addrConfig Address config: + - #SLNETIF_ADDR_CFG_UNKNOWN + - #SLNETIF_ADDR_CFG_DHCP + - #SLNETIF_ADDR_CFG_DHCP_LLA + - #SLNETIF_ADDR_CFG_STATIC + - #SLNETIF_ADDR_CFG_STATELESS + - #SLNETIF_ADDR_CFG_STATEFUL + \param[out] ipAddr IP Address according to the Address Type + + \return Zero on success, or negative error code on failure + + \sa SlNetIfAddressType_e + + \slnetif_not_threadsafe + + \par Examples + \snippet ti/net/test/snippets/slnetif.c SlNetIf_getIPAddr snippet +*/ +int32_t SlNetIf_getIPAddr(uint16_t ifID, SlNetIfAddressType_e addrType, uint16_t *addrConfig, uint32_t *ipAddr); + + +/*! + \brief Load/unload/replace a secure object into a network interface/stack + + SlNetIf_loadSecObj() loads a named secure object into specific + network stack for future use by secure sockets. To unload the + named secure object, pass a NULL object buffer with the + appropriate name. + + \param[in] objType The secure object type: + - #SLNETIF_SEC_OBJ_TYPE_RSA_PRIVATE_KEY + - #SLNETIF_SEC_OBJ_TYPE_CERTIFICATE + - #SLNETIF_SEC_OBJ_TYPE_DH_KEY + \param[in] objName The secure object name + \param[in] objNameLen The secure object name length + \param[in] objBuff The secure object buffer to be loaded, or + NULL if the named object is to be unloaded + \param[in] objBuffLen The secure object buffer length + \param[in] ifBitmap The interfaces which the secure + objects should be loaded to + + \remark Loaded secure objects are added to secure attributes using + the SlNetSock_secAttribCreate(), + SlNetSock_secAttribSet(), and + SlNetSock_secAttribDelete() lifecycle APIs. The + loading/unloading of secure objects (via + SlNetIf_loadSecObj()) must be done while the secure + object is not associated with any existing secure + attributes. Restating, you must delete any existing + secure attributes before changing any secure objects + associated with them. + + \remark The values of @c ifBitmap typically have the prefix + @c SLNETIF_ID_. + + \remark SlNetIf_loadSecObj() internally validates the @c objName, + @c objNameLen, and @c objType arguments, so the + underlying interface/stack functions do not need to + check them again. + + \remark For stacks that use file systems (e.g. CC3XXX), @c objName + will be the file name used on the file system. + + \remark Note that ownership of @c objBuff after returning from + SlNetIf_loadSecObj() varies by stack/interface, often + depending on how the underlying stack implements it's + TLS support. + - On CC3XXX-based stacks, the TLS support is managed + on a separate network processor, and loading a + secure object results in persisting the secure + object to a file system. As a result, after + successfully calling SlNetIf_loadSecObj(), the @c + objBuff is no longer needed, and can be considered + "owned" by the application. + + - On NDK-based stacks, the TLS support is typically + managed by a software library like mbedTLS. As a + result, only a reference to @c objBuff is made + within the SlNetIf_loadSecObj() call, and the + buffer must persist as long as the secure object + remains loaded. Ownership of the buffer returns + to the user only after unloading the secure + object (or resetting the device). + + \remark To replace an existing named secure object with another + secure object of the same name, call + SlNetIf_loadSecObj() with the same @c objName. + Resources associated with the previously loaded secure + object will be released and replaced by the new secure + object. + + \remark When unloading a named secure object, @c objBuffLen is + ignored. + + \return 0 on success, negative on failure. Common errors include: + - #SLNETERR_RET_CODE_INVALID_INPUT + - #SLNETERR_RET_CODE_NO_FREE_SPACE + - #SLNETERR_RET_CODE_MALLOC_ERROR + + \sa SlNetSock_setOpt() + \sa SlNetSock_secAttribSet() + + \slnetif_not_threadsafe + +*/ +int32_t SlNetIf_loadSecObj(uint16_t objType, char *objName, int16_t objNameLen, uint8_t *objBuff, int16_t objBuffLen, uint32_t ifBitmap); + +/*! + + Close the Doxygen group. + @} + +*/ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __SL_NET_IF_H__ */ diff --git a/simplelink/source/ti/net/slnetsock.c b/simplelink/source/ti/net/slnetsock.c new file mode 100644 index 0000000..d221966 --- /dev/null +++ b/simplelink/source/ti/net/slnetsock.c @@ -0,0 +1,1541 @@ +/* + * Copyright (c) 2017-2020, Texas Instruments Incorporated + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of Texas Instruments Incorporated nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/*****************************************************************************/ +/* Include files */ +/*****************************************************************************/ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +/* POSIX Header files */ +#include + +/*****************************************************************************/ +/* Macro declarations */ +/*****************************************************************************/ +#define SLNETSOCK_NORMALIZE_NEEDED 0 +#if SLNETSOCK_NORMALIZE_NEEDED + #define SLNETSOCK_NORMALIZE_RET_VAL(retVal,err) ((retVal < 0)?(retVal = err):(retVal)) +#else + #define SLNETSOCK_NORMALIZE_RET_VAL(retVal,err) +#endif + +#define SLNETSOCK_IPV4_ADDR_LEN (4) +#define SLNETSOCK_IPV6_ADDR_LEN (16) + +#define SLNETSOCK_SIZEOF_ONE_SDSETBITMAP_SLOT_IN_BITS (sizeof(uint32_t)*8) + +#define SLNETSOCK_LOCK() sem_wait(&VirtualSocketSem) +#define SLNETSOCK_UNLOCK() sem_post(&VirtualSocketSem) + +#define ENABLE_DEFAULT_QUERY_FLAGS() (SLNETSOCK_CREATE_IF_STATE_ENABLE | SLNETSOCK_CREATE_IF_STATUS_CONNECTED | SLNETSOCK_CREATE_ALLOW_PARTIAL_MATCH) +#define GET_QUERY_FLAGS(flags) (flags & (SLNETSOCK_CREATE_IF_STATE_ENABLE | SLNETSOCK_CREATE_IF_STATUS_CONNECTED | SLNETSOCK_CREATE_ALLOW_PARTIAL_MATCH)) + +/* Macro which merge the 8bit security flags to the upper bits of the 32 bit + input flags */ +#define MERGE_SEC_INTO_INPUT_FLAGS(inputFlags, secFlags) (inputFlags |= (secFlags << 24)) + + +/*****************************************************************************/ +/* Structure/Enum declarations */ +/*****************************************************************************/ + + +/* Socket Endpoint */ +typedef struct SlNetSock_VirtualSocket_t +{ + int16_t realSd; + uint8_t sdFlags; + void *sdContext; + SlNetIf_t *netIf; +} SlNetSock_VirtualSocket_t; + +/* Structure which holds the realSd and the virtualSd indexes */ +typedef struct SlNetSock_RealToVirtualIndexes_t +{ + int16_t realSd; + int16_t virtualSd; + struct SlNetSock_RealToVirtualIndexes_t *next; +} SlNetSock_RealToVirtualIndexes_t; + +/*****************************************************************************/ +/* Global declarations */ +/*****************************************************************************/ + +static SlNetSock_VirtualSocket_t *VirtualSockets[SLNETSOCK_MAX_CONCURRENT_SOCKETS]; +static uint8_t SlNetSock_Initialized = false; + +/* semaphore to protect VirtualSockets[] */ +static sem_t VirtualSocketSem; + + +/*****************************************************************************/ +/* Function prototypes */ +/*****************************************************************************/ + +static int32_t SlNetSock_getVirtualSdConf(int16_t virtualSdIndex, int16_t *realSd, uint8_t *sdFlags, void **sdContext, SlNetIf_t **netIf); +static int32_t SlNetSock_AllocVirtualSocket(int16_t *virtualSdIndex, SlNetSock_VirtualSocket_t **newSocketNode); +static int32_t SlNetSock_freeVirtualSocket(int16_t virtualSdIndex); + +//***************************************************************************** +// +// SlNetSock_getVirtualSdConf - This function search and returns the +// configuration of virtual socket. +// +//***************************************************************************** +static int32_t SlNetSock_getVirtualSdConf(int16_t virtualSdIndex, int16_t *realSd, uint8_t *sdFlags, void **sdContext, SlNetIf_t **netIf) +{ + int32_t retVal = SLNETERR_RET_CODE_OK; + + if (false == SlNetSock_Initialized) + { + return SLNETERR_RET_CODE_MUTEX_CREATION_FAILED; + } + + SLNETSOCK_LOCK(); + + /* Check if the input is valid and if real socket descriptor exists */ + if ( (virtualSdIndex >= SLNETSOCK_MAX_CONCURRENT_SOCKETS) || (virtualSdIndex < 0) || (NULL == netIf) ) + { + retVal = SLNETERR_RET_CODE_INVALID_INPUT; + } + else if (NULL == VirtualSockets[virtualSdIndex]) + { + /* Socket was not found, return error code */ + retVal = SLNETERR_RET_CODE_COULDNT_FIND_RESOURCE; + } + else + { + /* Socket found, copy and return its content */ + *netIf = VirtualSockets[virtualSdIndex]->netIf; + *realSd = VirtualSockets[virtualSdIndex]->realSd; + + /* If sdContext pointer supplied, copy into it the sdContext of the + socket */ + if ( NULL != sdContext ) + { + *sdContext = VirtualSockets[virtualSdIndex]->sdContext; + } + + /* If sdFlags pointer supplied, copy into it the sdFlags of the + socket */ + if ( NULL != sdFlags ) + { + *sdFlags = VirtualSockets[virtualSdIndex]->sdFlags; + } + + /* Check if the interface of the socket is declared */ + if ( (NULL == (*netIf)) || (NULL == (*netIf)->ifConf) ) + { + /* Interface was not found or config list is missing, + return error code */ + retVal = SLNETERR_RET_CODE_SOCKET_CREATION_IN_PROGRESS; + } + } + + SLNETSOCK_UNLOCK(); + + return retVal; +} + +//***************************************************************************** +// +// SlNetSock_AllocVirtualSocket - Search for free space in the VirtualSockets +// array and allocate a socket in this location +// +//***************************************************************************** +static int32_t SlNetSock_AllocVirtualSocket(int16_t *virtualSdIndex, SlNetSock_VirtualSocket_t **newSocketNode) +{ + uint16_t arrayIndex = 0; + int32_t retVal = SLNETERR_RET_CODE_NO_FREE_SPACE; + + if (false == SlNetSock_Initialized) + { + return SLNETERR_RET_CODE_MUTEX_CREATION_FAILED; + } + + SLNETSOCK_LOCK(); + + /* Search for free space in the VirtualSockets array */ + while ( arrayIndex < SLNETSOCK_MAX_CONCURRENT_SOCKETS ) + { + /* Check if the arrayIndex in VirtualSockets is free */ + if ( NULL == VirtualSockets[arrayIndex] ) + { + /* Allocate memory for new socket node for the socket list */ + *newSocketNode = (SlNetSock_VirtualSocket_t *)calloc(1, sizeof(SlNetSock_VirtualSocket_t)); + + /* Check if the memory allocated successfully */ + if (NULL == *newSocketNode) + { + /* Allocation failed, return error code */ + retVal = SLNETERR_RET_CODE_MALLOC_ERROR; + break; + } + else + { + /* Location free, return the Index and function success */ + *virtualSdIndex = arrayIndex; + + VirtualSockets[arrayIndex] = *newSocketNode; + + retVal = SLNETERR_RET_CODE_OK; + break; + } + } + else + { + /* Location isn't free, continue to next location */ + arrayIndex++; + } + } + + SLNETSOCK_UNLOCK(); + + return retVal; +} + +//***************************************************************************** +// +// SlNetSock_freeVirtualSocket - free allocated socket and initialize the array +// in the virtual socket location +// +//***************************************************************************** +static int32_t SlNetSock_freeVirtualSocket(int16_t virtualSdIndex) +{ + int32_t retVal = SLNETERR_RET_CODE_OK; + + if (false == SlNetSock_Initialized) + { + return SLNETERR_RET_CODE_MUTEX_CREATION_FAILED; + } + + SLNETSOCK_LOCK(); + + /* Check if the input is valid and if real socket descriptor exists */ + if ( (virtualSdIndex >= SLNETSOCK_MAX_CONCURRENT_SOCKETS) || (virtualSdIndex < 0) ) + { + retVal = SLNETERR_RET_CODE_INVALID_INPUT; + } + else if (NULL == VirtualSockets[virtualSdIndex]) + { + /* Socket was not found, return error code */ + retVal = SLNETERR_RET_CODE_COULDNT_FIND_RESOURCE; + } + else + { + /* Free Socket Context allocated memory */ + if (NULL != VirtualSockets[virtualSdIndex]->sdContext) + { + free((void *)VirtualSockets[virtualSdIndex]->sdContext); + } + + /* Free Socket Node allocated memory and delete it from the + VirtualSockets array */ + free((void *)VirtualSockets[virtualSdIndex]); + + VirtualSockets[virtualSdIndex] = NULL; + } + + SLNETSOCK_UNLOCK(); + + return retVal; +} + +//***************************************************************************** +// +// SlNetSock_init - init the SlNetSock module +// +//***************************************************************************** +int32_t SlNetSock_init(int32_t flags) +{ + int16_t Index = SLNETSOCK_MAX_CONCURRENT_SOCKETS; + int32_t retVal; + + /* If the SlNetSock layer isn't initialized, initialize it */ + if (false == SlNetSock_Initialized) + { + retVal = sem_init(&VirtualSocketSem, 0, 1); + if (0 != retVal) + { + return SLNETERR_RET_CODE_MUTEX_CREATION_FAILED; + } + else + { + /* Initialize the VirtualSockets array */ + while (Index--) + { + VirtualSockets[Index] = NULL; + } + SlNetSock_Initialized = true; + } + } + return SLNETERR_RET_CODE_OK; +} + + +//***************************************************************************** +// +// SlNetSock_create - Create an endpoint for communication +// +//***************************************************************************** +int16_t SlNetSock_create(int16_t domain, int16_t type, int16_t protocol, uint32_t ifBitmap, int16_t flags) +{ + SlNetIf_t *netIf; + SlNetSock_VirtualSocket_t *sdNode; + int16_t socketIndex; + int16_t createdSd; + int16_t queryFlags; + int32_t retVal; + + + /* if flags is zero, enable the default bits */ + if (0 == flags) + { + queryFlags = ENABLE_DEFAULT_QUERY_FLAGS(); + } + else + { + queryFlags = GET_QUERY_FLAGS(flags); + } + + /* Search for free place in the array */ + retVal = SlNetSock_AllocVirtualSocket(&socketIndex, &sdNode); + + /* Before creating a socket, check if there is a free place in the array */ + if ( retVal < SLNETERR_RET_CODE_OK ) + { + /* There isn't a free space in the array, return error code */ + return retVal; + } + + if (protocol == 0) { + switch (type) { + case SLNETSOCK_SOCK_STREAM: + protocol = SLNETSOCK_PROTO_TCP; + break; + case SLNETSOCK_SOCK_DGRAM: + protocol = SLNETSOCK_PROTO_UDP; + break; + case SLNETSOCK_SOCK_RAW: + default: + /* Keep protocol as is for other types */ + break; + } + } + + /* When ifBitmap is 0, that means automatic selection of all interfaces + is required, enable all bits in ifBitmap */ + if (0 == ifBitmap) + { + ifBitmap = ~ifBitmap; + } + + /* This loop tries to create a socket on the required interface with the + required queryFlags. + When multiple interfaces, in addition to the queryFlags it will try + to create the socket on the interface with the highest priority */ + while ( ifBitmap > 0 ) + { + /* Search for the highest priority interface according to the + ifBitmap and the queryFlags */ + netIf = SlNetIf_queryIf(ifBitmap, queryFlags); + + /* Check if the function returned NULL or the requested interface + exists */ + if (NULL == netIf) + { + /* Free the captured VirtualSockets location */ + SlNetSock_freeVirtualSocket(socketIndex); + + /* Interface doesn't exists, save error code */ + return retVal; + } + else + { + + /* Disable the ifID bit from the ifBitmap after finding the + netIf */ + ifBitmap &= ~(netIf->ifID); + + /* Interface exists, try to create new socket */ + createdSd = (netIf->ifConf)->sockCreate(netIf->ifContext, domain, type, protocol, &(sdNode->sdContext)); + + /* Check createdSd for error codes */ + if (createdSd < 0) + { + /* sockCreate failed, continue to the next ifID */ + retVal = createdSd; + } + else + { + /* Real socket created, fill the allocated socket node */ + sdNode->realSd = createdSd; + sdNode->netIf = netIf; + + /* Socket created, allocated and connected to the + VirtualSockets array, return VirtualSockets index */ + return socketIndex; + } + } + } + + /* Free the captured VirtualSockets location */ + SlNetSock_freeVirtualSocket(socketIndex); + + /* There isn't a free space in the array or socket couldn't be opened, + return error code */ + return retVal; +} + + +//***************************************************************************** +// +// SlNetSock_close - Gracefully close socket +// +//***************************************************************************** +int32_t SlNetSock_close(int16_t sd) +{ + int32_t retVal = SLNETERR_RET_CODE_OK; + int16_t realSd; + SlNetIf_t *netIf; + void *sdContext; + + /* Check if the sd input exists and return it */ + retVal = SlNetSock_getVirtualSdConf(sd, &realSd, NULL, &sdContext, &netIf); + + /* Check if sd found */ + if (SLNETERR_RET_CODE_OK != retVal) + { + /* Validation failed, return error code */ + return retVal; + } + + /* Function exists in the interface of the socket descriptor, dispatch + the Close command */ + retVal = (netIf->ifConf)->sockClose(realSd, sdContext); + SLNETSOCK_NORMALIZE_RET_VAL(retVal,SLNETSOCK_ERR_SOCKCLOSE_FAILED); + + /* When freeing the virtual socket, it will free allocated memory + of the sdContext and of the socket node, if other threads will + try to use this socket or the retrieved data of the socket the + stack needs to return an error. + + The virtual socket resources are freed after a call to close regardless + of the return from netIf->sockClose. Recovery of the socket handle is + not possible after this function exits. This was one suggestion derived + from NS-233. */ + SlNetSock_freeVirtualSocket(sd); + return retVal; +} + + +//***************************************************************************** +// +// SlNetSock_shutdown - Shutting down parts of a full-duplex connection +// +//***************************************************************************** +int32_t SlNetSock_shutdown(int16_t sd, int16_t how) +{ + int32_t retVal = SLNETERR_RET_CODE_OK; + int16_t realSd; + SlNetIf_t *netIf; + void *sdContext; + + /* Check if the sd input exists and return it */ + retVal = SlNetSock_getVirtualSdConf(sd, &realSd, NULL, &sdContext, &netIf); + + /* Check if sd found or if the non mandatory function exists */ + if (SLNETERR_RET_CODE_OK != retVal) + { + return retVal; + } + if (NULL == (netIf->ifConf)->sockShutdown) + { + /* Non mandatory function doesn't exists, return error code */ + return SLNETERR_RET_CODE_DOESNT_SUPPORT_NON_MANDATORY_FXN; + } + + /* Function exists in the interface of the socket descriptor, dispatch + the Shutdown command */ + retVal = (netIf->ifConf)->sockShutdown(realSd, sdContext, how); + SLNETSOCK_NORMALIZE_RET_VAL(retVal,SLNETSOCK_ERR_SOCKSHUTDOWN_FAILED); + + return retVal; +} + + +//***************************************************************************** +// +// SlNetSock_accept - Accept a connection on a socket +// +//***************************************************************************** +int16_t SlNetSock_accept(int16_t sd, SlNetSock_Addr_t *addr, SlNetSocklen_t *addrlen) +{ + SlNetSock_VirtualSocket_t *allocSdNode; + void *sdContext; + int16_t realSd; + int16_t socketIndex; + int32_t retVal = SLNETERR_RET_CODE_OK; + + /* Search for free place in the array */ + retVal = SlNetSock_AllocVirtualSocket(&socketIndex, &allocSdNode); + + /* Before creating a socket, check if there is a free place in the array */ + if ( retVal < SLNETERR_RET_CODE_OK ) + { + /* There isn't a free space in the array, return error code */ + return retVal; + } + + /* Check if the sd input exists and return it */ + retVal = SlNetSock_getVirtualSdConf(sd, &realSd, &(allocSdNode->sdFlags), &sdContext, &(allocSdNode->netIf)); + + /* Check if sd found or if the non mandatory function exists */ + if (SLNETERR_RET_CODE_OK != retVal) + { + return retVal; + } + if (NULL == ((allocSdNode->netIf)->ifConf)->sockAccept) + { + /* Free the captured VirtualSockets location */ + SlNetSock_freeVirtualSocket(socketIndex); + + /* Validation failed, return error code */ + return SLNETERR_RET_CODE_INVALID_INPUT; + } + + /* Function exists in the interface of the socket descriptor, dispatch + the Accept command */ + retVal = ((allocSdNode->netIf)->ifConf)->sockAccept(realSd, sdContext, addr, addrlen, allocSdNode->sdFlags, &(allocSdNode->sdContext)); + + /* Check retVal for error codes */ + if (retVal < SLNETERR_RET_CODE_OK) + { + /* Free the captured VirtualSockets location */ + SlNetSock_freeVirtualSocket(socketIndex); + + /* sockAccept failed, return error code */ + return retVal; + } + else + { + /* Real socket created, fill the allocated socket node */ + allocSdNode->realSd = retVal; + + /* Socket created, allocated and connected to the + VirtualSockets array, return VirtualSockets index */ + return socketIndex; + } + +} + + +//***************************************************************************** +// +// SlNetSock_bind - Assign a name to a socket +// +//***************************************************************************** +int32_t SlNetSock_bind(int16_t sd, const SlNetSock_Addr_t *addr, int16_t addrlen) +{ + int32_t retVal = SLNETERR_RET_CODE_OK; + int16_t realSd; + SlNetIf_t *netIf; + void *sdContext; + + /* Check if the sd input exists and return it */ + retVal = SlNetSock_getVirtualSdConf(sd, &realSd, NULL, &sdContext, &netIf); + + /* Check if sd found or if the non mandatory function exists */ + if (SLNETERR_RET_CODE_OK != retVal) + { + return retVal; + } + if (NULL == (netIf->ifConf)->sockBind) + { + /* Non mandatory function doesn't exists, return error code */ + return SLNETERR_RET_CODE_DOESNT_SUPPORT_NON_MANDATORY_FXN; + } + + /* Function exists in the interface of the socket descriptor, dispatch + the Bind command */ + retVal = (netIf->ifConf)->sockBind(realSd, sdContext, addr, addrlen); + SLNETSOCK_NORMALIZE_RET_VAL(retVal,SLNETSOCK_ERR_SOCKBIND_FAILED); + + return retVal; +} + + +//***************************************************************************** +// +// SlNetSock_listen - Listen for connections on a socket +// +//***************************************************************************** +int32_t SlNetSock_listen(int16_t sd, int16_t backlog) +{ + int32_t retVal = SLNETERR_RET_CODE_OK; + int16_t realSd; + SlNetIf_t *netIf; + void *sdContext; + + /* Check if the sd input exists and return it */ + retVal = SlNetSock_getVirtualSdConf(sd, &realSd, NULL, &sdContext, &netIf); + + /* Check if sd found or if the non mandatory function exists */ + if (SLNETERR_RET_CODE_OK != retVal) + { + return retVal; + } + if (NULL == (netIf->ifConf)->sockListen) + { + /* Non mandatory function doesn't exists, return error code */ + return SLNETERR_RET_CODE_DOESNT_SUPPORT_NON_MANDATORY_FXN; + } + + /* Function exists in the interface of the socket descriptor, dispatch + the Listen command */ + retVal = (netIf->ifConf)->sockListen(realSd, sdContext, backlog); + SLNETSOCK_NORMALIZE_RET_VAL(retVal,SLNETSOCK_ERR_SOCKLISTEN_FAILED); + + return retVal; +} + + +//***************************************************************************** +// +// SlNetSock_connect - Initiate a connection on a socket +// +//***************************************************************************** +int32_t SlNetSock_connect(int16_t sd, const SlNetSock_Addr_t *addr, SlNetSocklen_t addrlen) +{ + int32_t retVal = SLNETERR_RET_CODE_OK; + int16_t realSd; + uint8_t sdFlags; + SlNetIf_t *netIf; + void *sdContext; + + /* Check if the sd input exists and return it */ + retVal = SlNetSock_getVirtualSdConf(sd, &realSd, &sdFlags, &sdContext, &netIf); + + /* Check if sd found or if the non mandatory function exists */ + if (SLNETERR_RET_CODE_OK != retVal) + { + return retVal; + } + if (NULL == (netIf->ifConf)->sockConnect) + { + /* Non mandatory function doesn't exists, return error code */ + return SLNETERR_RET_CODE_DOESNT_SUPPORT_NON_MANDATORY_FXN; + } + + /* Function exists in the interface of the socket descriptor, dispatch + the Connect command */ + retVal = (netIf->ifConf)->sockConnect(realSd, sdContext, addr, addrlen, sdFlags); + SLNETSOCK_NORMALIZE_RET_VAL(retVal,SLNETSOCK_ERR_SOCKCONNECT_FAILED); + + return retVal; +} + + +//***************************************************************************** +// +// SlNetSock_connectUrl - Initiate a connection on a socket by URL +// +//***************************************************************************** +int32_t SlNetSock_connectUrl(int16_t sd, const char *url) +{ + uint32_t addr[4]; + uint16_t ipAddrLen; + SlNetSock_AddrIn_t localAddr; //address of the server to connect to + SlNetSocklen_t localAddrSize; + int16_t realSd; + uint8_t sdFlags; + SlNetIf_t *netIf; + void *sdContext; + int32_t retVal = SLNETERR_RET_CODE_OK; + + /* Check if the sd input exists and return it */ + retVal = SlNetSock_getVirtualSdConf(sd, &realSd, &sdFlags, &sdContext, &netIf); + + /* Check if sd found or if the non mandatory function exists */ + if (SLNETERR_RET_CODE_OK != retVal) + { + return retVal; + } + if ( (NULL == (netIf->ifConf)->sockConnect) || (NULL == (netIf->ifConf)->utilGetHostByName) ) + { + /* Non mandatory function doesn't exists, return error code */ + return SLNETERR_RET_CODE_DOESNT_SUPPORT_NON_MANDATORY_FXN; + } + + /* Query DNS for IPv4 address. */ + retVal = (netIf->ifConf)->utilGetHostByName(netIf->ifContext, (char *)url, strlen(url), addr, &ipAddrLen, SLNETSOCK_AF_INET); + SLNETSOCK_NORMALIZE_RET_VAL(retVal,SLNETUTIL_ERR_UTILGETHOSTBYNAME_FAILED); + if(retVal < 0) + { + /* If call fails, try again for IPv6. */ + retVal = (netIf->ifConf)->utilGetHostByName(netIf->ifContext, (char *)url, strlen(url), addr, &ipAddrLen, SLNETSOCK_AF_INET6); + SLNETSOCK_NORMALIZE_RET_VAL(retVal,SLNETUTIL_ERR_UTILGETHOSTBYNAME_FAILED); + if(retVal < 0) + { + /* if the request failed twice, return error code. */ + return retVal; + } + else + { + /* fill the answer fields with IPv6 parameters */ + localAddr.sin_family = SLNETSOCK_AF_INET6; + localAddrSize = sizeof(SlNetSock_AddrIn6_t); + } + } + else + { + /* fill the answer fields with IPv4 parameters */ + localAddr.sin_family = SLNETSOCK_AF_INET; + localAddrSize = sizeof(SlNetSock_AddrIn_t); + + /* convert the IPv4 address from host byte order to network byte + order */ + localAddr.sin_addr.s_addr = SlNetUtil_htonl(addr[0]); + } + + + /* Function exists in the interface of the socket descriptor, dispatch + the Connect command */ + retVal = (netIf->ifConf)->sockConnect(realSd, sdContext, (const SlNetSock_Addr_t *)&localAddr, localAddrSize, sdFlags); + SLNETSOCK_NORMALIZE_RET_VAL(retVal,SLNETSOCK_ERR_SOCKCONNECT_FAILED); + + return retVal; +} + + +//***************************************************************************** +// +// SlNetSock_getPeerName - Return address info about the remote side of the +// connection +// +//***************************************************************************** +int32_t SlNetSock_getPeerName(int16_t sd, SlNetSock_Addr_t *addr, SlNetSocklen_t *addrlen) +{ + int32_t retVal = SLNETERR_RET_CODE_OK; + int16_t realSd; + SlNetIf_t *netIf; + void *sdContext; + + /* Check if the sd input exists and return it */ + retVal = SlNetSock_getVirtualSdConf(sd, &realSd, NULL, &sdContext, &netIf); + + /* Check if sd found or if the non mandatory function exists */ + if (SLNETERR_RET_CODE_OK != retVal) + { + return retVal; + } + if (NULL == (netIf->ifConf)->sockGetPeerName) + { + /* Non mandatory function doesn't exists, return error code */ + return SLNETERR_RET_CODE_DOESNT_SUPPORT_NON_MANDATORY_FXN; + } + + /* Function exists in the interface of the socket descriptor, dispatch + the GetPeerName command */ + retVal = (netIf->ifConf)->sockGetPeerName(realSd, sdContext, addr, addrlen); + SLNETSOCK_NORMALIZE_RET_VAL(retVal,SLNETSOCK_ERR_SOCKGETPEERNAME_FAILED); + + return retVal; +} + + +//***************************************************************************** +// +// SlNetSock_getSockName - Returns the local address info of the socket +// descriptor +// +//***************************************************************************** +int32_t SlNetSock_getSockName(int16_t sd, SlNetSock_Addr_t *addr, SlNetSocklen_t *addrlen) +{ + int32_t retVal = SLNETERR_RET_CODE_OK; + int16_t realSd; + SlNetIf_t *netIf; + void *sdContext; + + /* Check if the sd input exists and return it */ + retVal = SlNetSock_getVirtualSdConf(sd, &realSd, NULL, &sdContext, &netIf); + + /* Check if sd found or if the non mandatory function exists */ + if (SLNETERR_RET_CODE_OK != retVal) + { + return retVal; + } + if (NULL == (netIf->ifConf)->sockGetLocalName) + { + /* Non mandatory function doesn't exists, return error code */ + return SLNETERR_RET_CODE_DOESNT_SUPPORT_NON_MANDATORY_FXN; + } + + /* Function exists in the interface of the socket descriptor, dispatch + the GetLocalName command */ + retVal = (netIf->ifConf)->sockGetLocalName(realSd, sdContext, addr, addrlen); + SLNETSOCK_NORMALIZE_RET_VAL(retVal,SLNETSOCK_ERR_SOCKGETLOCALNAME_FAILED); + + return retVal; +} + + +//***************************************************************************** +// +// SlNetSock_select - Monitor socket activity +// +//***************************************************************************** +int32_t SlNetSock_select(int16_t nsds, SlNetSock_SdSet_t *readsds, SlNetSock_SdSet_t *writesds, SlNetSock_SdSet_t *exceptsds, SlNetSock_Timeval_t *timeout) +{ + int32_t retVal = SLNETERR_RET_CODE_OK; + int32_t sdIndex = 0; + int16_t realSd; + int16_t ifNsds = 0; + bool skipToNext = true; + SlNetIf_t *firstIfID = NULL; + SlNetIf_t *netIf; + void *sdContext; + SlNetSock_SdSet_t ifReadsds; + SlNetSock_SdSet_t ifWritesds; + SlNetSock_SdSet_t ifExceptsds; + SlNetSock_RealToVirtualIndexes_t *tempNode = NULL; + SlNetSock_RealToVirtualIndexes_t *realSdToVirtual = NULL; + + /* Initialize sds parameters */ + SlNetSock_sdsClrAll(&ifReadsds); + SlNetSock_sdsClrAll(&ifWritesds); + SlNetSock_sdsClrAll(&ifExceptsds); + + /* Run over all possible sd indexes */ + while ( sdIndex < nsds ) + { + /* get interface ID from the socket identifier */ + retVal = SlNetSock_getVirtualSdConf(sdIndex, &realSd, NULL, &sdContext, &netIf); + + /* Check if sd found */ + if (SLNETERR_RET_CODE_OK == retVal) + { + /* Check if sdIndex is set in read/write/except virtual sd sets, + if so, set the real sd set and set skipToNext to false + for further use */ + if (SlNetSock_sdsIsSet(sdIndex, readsds) == 1) + { + SlNetSock_sdsSet(realSd, &ifReadsds); + skipToNext = false; + } + if (SlNetSock_sdsIsSet(sdIndex, writesds) == 1) + { + SlNetSock_sdsSet(realSd, &ifWritesds); + skipToNext = false; + } + if (SlNetSock_sdsIsSet(sdIndex, exceptsds) == 1) + { + SlNetSock_sdsSet(realSd, &ifExceptsds); + skipToNext = false; + } + + if (false == skipToNext) + { + + /* Create a node which stores the relation between the virtual + sd index and the real sd index and connect it to the list */ + tempNode = (SlNetSock_RealToVirtualIndexes_t *)malloc(sizeof(SlNetSock_RealToVirtualIndexes_t)); + + /* Check if the malloc function failed */ + if (NULL == tempNode) + { + firstIfID = NULL; + retVal = SLNETERR_RET_CODE_MALLOC_ERROR; + break; + } + + tempNode->realSd = realSd; + tempNode->virtualSd = sdIndex; + tempNode->next = realSdToVirtual; + realSdToVirtual = tempNode; + + /* Check if the stored interface ID is different from the + interface ID of the socket */ + if (netIf != firstIfID) + { + /* Check if the stored interface ID is still initialized */ + if (NULL == firstIfID) + { + /* Store the interface ID */ + firstIfID = netIf; + } + else + { + /* Different interface ID from the stored interface + ID, that means more than one interface supplied + in the read sd set */ + firstIfID = NULL; + break; + } + } + if (ifNsds <= realSd) + { + ifNsds = realSd + 1; + } + skipToNext = true; + } + } + + /* Continue to next sd index */ + sdIndex++; + } + + /* Check if non mandatory function exists */ + if ( (NULL != firstIfID) && (NULL != (firstIfID->ifConf)->sockSelect) ) + { + /* Function exists in the interface of the socket descriptor, + dispatch the Select command */ + retVal = (firstIfID->ifConf)->sockSelect(firstIfID->ifContext, ifNsds, &ifReadsds, &ifWritesds, &ifExceptsds, timeout); + SLNETSOCK_NORMALIZE_RET_VAL(retVal,SLNETSOCK_ERR_SOCKSELECT_FAILED); + + /* Clear all virtual sd sets before setting the sockets that are set */ + SlNetSock_sdsClrAll(readsds); + SlNetSock_sdsClrAll(writesds); + SlNetSock_sdsClrAll(exceptsds); + + /* check if the sockselect returned positive value, this value + represents how many socket descriptors are set */ + if (retVal > 0) + { + /* Run over all the socket descriptors in the list and check if + the sockSelect function set them, if so, set the virtual + socket descriptors sets */ + tempNode = realSdToVirtual; + while ( NULL != tempNode ) + { + if (SlNetSock_sdsIsSet(tempNode->realSd, &ifReadsds) == 1) + { + SlNetSock_sdsSet(tempNode->virtualSd, readsds); + } + if (SlNetSock_sdsIsSet(tempNode->realSd, &ifWritesds) == 1) + { + SlNetSock_sdsSet(tempNode->virtualSd, writesds); + } + if (SlNetSock_sdsIsSet(tempNode->realSd, &ifExceptsds) == 1) + { + SlNetSock_sdsSet(tempNode->virtualSd, exceptsds); + } + tempNode = tempNode->next; + } + } + } + else + { + if ( SLNETERR_RET_CODE_MALLOC_ERROR != retVal ) + { + /* Validation failed, return error code */ + retVal = SLNETERR_RET_CODE_INVALID_INPUT; + } + } + + /* List isn't needed anymore, free it from the head of the list */ + while (NULL != realSdToVirtual) + { + tempNode = realSdToVirtual->next; + free(realSdToVirtual); + realSdToVirtual = tempNode; + } + + return retVal; +} + + +//***************************************************************************** +// +// SlNetSock_sdsSet - SlNetSock_select's SlNetSock_SdSet_t SET function +// +//***************************************************************************** +int32_t SlNetSock_sdsSet(int16_t sd, SlNetSock_SdSet_t *sdset) +{ + int sdArrayIndex; + + /* Validation check */ + if ( (NULL == sdset) || (sd >= SLNETSOCK_MAX_CONCURRENT_SOCKETS) ) + { + /* Validation failed, return error code */ + return SLNETERR_RET_CODE_INVALID_INPUT; + } + + /* Check in which sdset index the input socket exists */ + sdArrayIndex = (sd / SLNETSOCK_SIZEOF_ONE_SDSETBITMAP_SLOT_IN_BITS); + + /* Set the socket in the sd set */ + sdset->sdSetBitmap[sdArrayIndex] |= ( 1 << (sd % SLNETSOCK_SIZEOF_ONE_SDSETBITMAP_SLOT_IN_BITS) ); + + return SLNETERR_RET_CODE_OK; + +} + + +//***************************************************************************** +// +// SlNetSock_sdsClr - SlNetSock_select's SlNetSock_SdSet_t CLR function +// +//***************************************************************************** +int32_t SlNetSock_sdsClr(int16_t sd, SlNetSock_SdSet_t *sdset) +{ + int sdArrayIndex; + + /* Validation check */ + if ( (NULL == sdset) || (sd >= SLNETSOCK_MAX_CONCURRENT_SOCKETS) ) + { + /* Validation failed, return error code */ + return SLNETERR_RET_CODE_INVALID_INPUT; + } + /* Check in which sdset index the input socket exists */ + sdArrayIndex = (sd / SLNETSOCK_SIZEOF_ONE_SDSETBITMAP_SLOT_IN_BITS); + + /* Set the socket in the sd set */ + sdset->sdSetBitmap[sdArrayIndex] &= ~( 1 << (sd % SLNETSOCK_SIZEOF_ONE_SDSETBITMAP_SLOT_IN_BITS) ); + + return SLNETERR_RET_CODE_OK; +} + + +//***************************************************************************** +// +// SlNetSock_sdsClrAll - SlNetSock_select's SlNetSock_SdSet_t ZERO function +// +//***************************************************************************** +int32_t SlNetSock_sdsClrAll(SlNetSock_SdSet_t *sdset) +{ + int sdArrayIndex; + + /* Validation check */ + if (NULL == sdset) + { + /* Validation failed, return error code */ + return SLNETERR_RET_CODE_INVALID_INPUT; + } + + /* Check the size of the sdArrayIndex */ + sdArrayIndex = (((sizeof(sdset)*8)-1) / SLNETSOCK_SIZEOF_ONE_SDSETBITMAP_SLOT_IN_BITS); + + while (sdArrayIndex >= 0) + { + /* Set to 0 the sd set */ + sdset->sdSetBitmap[sdArrayIndex] = 0; + sdArrayIndex --; + } + + return SLNETERR_RET_CODE_OK; +} + + + +//***************************************************************************** +// +// SlNetSock_sdsIsSet - SlNetSock_select's SlNetSock_SdSet_t ISSET function +// +//***************************************************************************** +int32_t SlNetSock_sdsIsSet(int16_t sd, SlNetSock_SdSet_t *sdset) +{ + int sdArrayIndex; + + /* Validation check */ + if ( (NULL == sdset) || (sd >= SLNETSOCK_MAX_CONCURRENT_SOCKETS) ) + { + /* Validation failed, return error code */ + return SLNETERR_RET_CODE_INVALID_INPUT; + } + + /* Check in which sdset index the input socket exists */ + sdArrayIndex = (sd / SLNETSOCK_SIZEOF_ONE_SDSETBITMAP_SLOT_IN_BITS); + + /* Check if the sd is set in the sdSetBitmap */ + if ( (sdset->sdSetBitmap[sdArrayIndex]) & (1 << (sd % SLNETSOCK_SIZEOF_ONE_SDSETBITMAP_SLOT_IN_BITS)) ) + { + /* Bit is set, return 1 */ + return 1; + } + else + { + /* Bit is not set, return 0 */ + return 0; + } +} + + +//***************************************************************************** +// +// SlNetSock_setOpt - Set socket options +// +//***************************************************************************** +int32_t SlNetSock_setOpt(int16_t sd, int16_t level, int16_t optname, void *optval, SlNetSocklen_t optlen) +{ + int32_t retVal = SLNETERR_RET_CODE_OK; + int16_t realSd; + SlNetIf_t *netIf; + void *sdContext; + + /* Check if the sd input exists and return it */ + retVal = SlNetSock_getVirtualSdConf(sd, &realSd, NULL, &sdContext, &netIf); + + /* Check if sd found or if the non mandatory function exists */ + if (SLNETERR_RET_CODE_OK != retVal) + { + return retVal; + } + if (NULL == (netIf->ifConf)->sockSetOpt) + { + /* Non mandatory function doesn't exists, return error code */ + return SLNETERR_RET_CODE_DOESNT_SUPPORT_NON_MANDATORY_FXN; + } + + /* Function exists in the interface of the socket descriptor, dispatch + the SetOpt command */ + retVal = (netIf->ifConf)->sockSetOpt(realSd, sdContext, level, optname, optval, optlen); + SLNETSOCK_NORMALIZE_RET_VAL(retVal,SLNETSOCK_ERR_SOCKSETOPT_FAILED); + + return retVal; +} + + +//***************************************************************************** +// +// SlNetSock_getOpt - Get socket options +// +//***************************************************************************** +int32_t SlNetSock_getOpt(int16_t sd, int16_t level, int16_t optname, void *optval, SlNetSocklen_t *optlen) +{ + int32_t retVal = SLNETERR_RET_CODE_OK; + int16_t realSd; + SlNetIf_t *netIf; + void *sdContext; + + /* Check if the sd input exists and return it */ + retVal = SlNetSock_getVirtualSdConf(sd, &realSd, NULL, &sdContext, &netIf); + + /* Check if sd found or if the non mandatory function exists */ + if (SLNETERR_RET_CODE_OK != retVal) + { + return retVal; + } + if (NULL == (netIf->ifConf)->sockGetOpt) + { + /* Non mandatory function doesn't exists, return error code */ + return SLNETERR_RET_CODE_DOESNT_SUPPORT_NON_MANDATORY_FXN; + } + + /* Function exists in the interface of the socket descriptor, dispatch + the GetOpt command */ + retVal = (netIf->ifConf)->sockGetOpt(realSd, sdContext, level, optname, optval, optlen); + SLNETSOCK_NORMALIZE_RET_VAL(retVal,SLNETSOCK_ERR_SOCKGETOPT_FAILED); + + return retVal; +} + + +//***************************************************************************** +// +// SlNetSock_recv - Read data from TCP socket +// +//***************************************************************************** +int32_t SlNetSock_recv(int16_t sd, void *buf, uint32_t len, uint32_t flags) +{ + int32_t retVal = SLNETERR_RET_CODE_OK; + int16_t realSd; + uint8_t sdFlags; + SlNetIf_t *netIf; + void *sdContext; + + /* Check if the sd input exists and return it */ + retVal = SlNetSock_getVirtualSdConf(sd, &realSd, &sdFlags, &sdContext, &netIf); + + /* Check if sd found or if the non mandatory function exists */ + if (SLNETERR_RET_CODE_OK != retVal) + { + return retVal; + } + if (NULL == (netIf->ifConf)->sockRecv) + { + /* Non mandatory function doesn't exists, return error code */ + return SLNETERR_RET_CODE_DOESNT_SUPPORT_NON_MANDATORY_FXN; + } + if ((flags & 0xff000000) != 0) + { + /* invalid user flags */ + return SLNETERR_BSD_EOPNOTSUPP; + } + + /* Macro which merge the 8bit security flags to the upper bits of the + 32bit input flags */ + MERGE_SEC_INTO_INPUT_FLAGS(flags, sdFlags); + + /* Function exists in the interface of the socket descriptor, dispatch + the Recv command */ + retVal = (netIf->ifConf)->sockRecv(realSd, sdContext, buf, len, flags); + SLNETSOCK_NORMALIZE_RET_VAL(retVal,SLNETSOCK_ERR_SOCKRECV_FAILED); + + return retVal; +} + + +//***************************************************************************** +// +// SlNetSock_recvFrom - Read data from socket +// +//***************************************************************************** +int32_t SlNetSock_recvFrom(int16_t sd, void *buf, uint32_t len, uint32_t flags, SlNetSock_Addr_t *from, SlNetSocklen_t *fromlen) +{ + int32_t retVal = SLNETERR_RET_CODE_OK; + int16_t realSd; + uint8_t sdFlags; + SlNetIf_t *netIf; + void *sdContext; + + /* Check if the sd input exists and return it */ + retVal = SlNetSock_getVirtualSdConf(sd, &realSd, &sdFlags, &sdContext, &netIf); + + /* Check if sd found */ + if (SLNETERR_RET_CODE_OK != retVal) + { + /* Validation failed, return error code */ + return SLNETERR_RET_CODE_INVALID_INPUT; + } + if ((flags & 0xff000000) != 0) + { + /* invalid user flags */ + return SLNETERR_BSD_EOPNOTSUPP; + } + + /* Macro which merge the 8bit security flags to the upper bits of the + 32bit input flags */ + MERGE_SEC_INTO_INPUT_FLAGS(flags, sdFlags); + + /* Function exists in the interface of the socket descriptor, dispatch + the RecvFrom command */ + retVal = (netIf->ifConf)->sockRecvFrom(realSd, sdContext, buf, len, flags, from, fromlen); + SLNETSOCK_NORMALIZE_RET_VAL(retVal,SLNETSOCK_ERR_SOCKRECVFROM_FAILED); + + return retVal; +} + + +//***************************************************************************** +// +// SlNetSock_send - Write data to TCP socket +// +//***************************************************************************** +int32_t SlNetSock_send(int16_t sd, const void *buf, uint32_t len, uint32_t flags) +{ + int32_t retVal = SLNETERR_RET_CODE_OK; + int16_t realSd; + uint8_t sdFlags; + SlNetIf_t *netIf; + void *sdContext; + + /* Check if the sd input exists and return it */ + retVal = SlNetSock_getVirtualSdConf(sd, &realSd, &sdFlags, &sdContext, &netIf); + + /* Check if sd found or if the non mandatory function exists */ + if (SLNETERR_RET_CODE_OK != retVal) + { + return retVal; + } + if (NULL == (netIf->ifConf)->sockSend) + { + /* Non mandatory function doesn't exists, return error code */ + return SLNETERR_RET_CODE_DOESNT_SUPPORT_NON_MANDATORY_FXN; + } + if ((flags & 0xff000000) != 0) + { + /* invalid user flags */ + return SLNETERR_BSD_EOPNOTSUPP; + } + + /* Macro which merge the 8bit security flags to the upper bits of the + 32bit input flags */ + MERGE_SEC_INTO_INPUT_FLAGS(flags, sdFlags); + + /* Function exists in the interface of the socket descriptor, dispatch + the Send command */ + retVal = (netIf->ifConf)->sockSend(realSd, sdContext, buf, len, flags); + SLNETSOCK_NORMALIZE_RET_VAL(retVal,SLNETSOCK_ERR_SOCKSEND_FAILED); + + return retVal; +} + + +//***************************************************************************** +// +// SlNetSock_sendTo - Write data to socket +// +//***************************************************************************** +int32_t SlNetSock_sendTo(int16_t sd, const void *buf, uint32_t len, uint32_t flags, const SlNetSock_Addr_t *to, SlNetSocklen_t tolen) +{ + int32_t retVal = SLNETERR_RET_CODE_OK; + int16_t realSd; + uint8_t sdFlags; + SlNetIf_t *netIf; + void *sdContext; + + /* Check if the sd input exists and return it */ + retVal = SlNetSock_getVirtualSdConf(sd, &realSd, &sdFlags, &sdContext, &netIf); + + /* Check if sd found */ + if (SLNETERR_RET_CODE_OK != retVal) + { + /* Validation failed, return error code */ + return SLNETERR_RET_CODE_INVALID_INPUT; + } + if ((flags & 0xff000000) != 0) + { + /* invalid user flags */ + return SLNETERR_BSD_EOPNOTSUPP; + } + + /* Macro which merge the 8bit security flags to the upper bits of the + 32bit input flags */ + MERGE_SEC_INTO_INPUT_FLAGS(flags, sdFlags); + + /* Function exists in the interface of the socket descriptor, dispatch + the SendTo command */ + retVal = (netIf->ifConf)->sockSendTo(realSd, sdContext, buf, len, flags, to, tolen); + SLNETSOCK_NORMALIZE_RET_VAL(retVal,SLNETSOCK_ERR_SOCKSENDTO_FAILED); + + return retVal; +} + + +//***************************************************************************** +// +// SlNetSock_getIfID - Get interface ID from socket descriptor (sd) +// +//***************************************************************************** +int32_t SlNetSock_getIfID(uint16_t sd) +{ + int32_t retVal = SLNETERR_RET_CODE_OK; + int16_t realSd; + SlNetIf_t *netIf; + + /* Check if the sd input exists and return it */ + retVal = SlNetSock_getVirtualSdConf(sd, &realSd, NULL, NULL, &netIf); + + /* Check if sd found */ + if (SLNETERR_RET_CODE_OK != retVal) + { + /* Validation failed, return error code */ + return SLNETERR_RET_CODE_INVALID_INPUT; + } + + /* Return interface identifier */ + return netIf->ifID; +} + + +//***************************************************************************** +// +// SlNetSock_secAttribCreate - Creates a security attributes object +// +//***************************************************************************** +SlNetSockSecAttrib_t *SlNetSock_secAttribCreate(void) +{ + SlNetSockSecAttrib_t *secAttribHandler; + + /* Allocate and initialize dynamic memory for security attribute handler */ + secAttribHandler = (SlNetSockSecAttrib_t *)calloc(1, sizeof(SlNetSockSecAttrib_t)); + + /* Check if the calloc function failed */ + if (NULL == secAttribHandler) + { + /* Function failed, return error code */ + return NULL; + } + + return (secAttribHandler); +} + + +//***************************************************************************** +// +// SlNetSock_secAttribDelete - Deletes a security attributes object +// +//***************************************************************************** +int32_t SlNetSock_secAttribDelete(SlNetSockSecAttrib_t *secAttrib) +{ + SlNetSock_SecAttribNode_t *nextSecAttrib; + SlNetSock_SecAttribNode_t *tempSecAttrib; + + /* Check if the input doesn't exist */ + if (NULL == secAttrib) + { + /* Function failed, return error code */ + return SLNETERR_RET_CODE_INVALID_INPUT; + } + else + { + nextSecAttrib = (SlNetSock_SecAttribNode_t *)*secAttrib; + tempSecAttrib = (SlNetSock_SecAttribNode_t *)*secAttrib; + } + + /* Free all SecAttrib list nodes */ + while (NULL != nextSecAttrib) + { + nextSecAttrib = tempSecAttrib->next; + free((void *)tempSecAttrib); + tempSecAttrib = nextSecAttrib; + } + + free(secAttrib); + + return SLNETERR_RET_CODE_OK; +} + + +//***************************************************************************** +// +// SlNetSock_secAttribSet - used to set a security attribute of a security +// attributes object +// +//***************************************************************************** +int32_t SlNetSock_secAttribSet(SlNetSockSecAttrib_t *secAttrib, SlNetSockSecAttrib_e attribName, void *val, uint16_t len) +{ + SlNetSock_SecAttribNode_t *secAttribObj; + + /* Check if the inputs doesn't exists or not valid */ + if ( (NULL == secAttrib) || (0 == len) || (NULL == val) ) + { + /* Function failed, return error code */ + return SLNETERR_RET_CODE_INVALID_INPUT; + } + + /* Ensure the len was set correctly for the given attribName */ + switch (attribName) + { + case SLNETSOCK_SEC_ATTRIB_PRIVATE_KEY: + case SLNETSOCK_SEC_ATTRIB_LOCAL_CERT: + case SLNETSOCK_SEC_ATTRIB_PEER_ROOT_CA: + case SLNETSOCK_SEC_ATTRIB_DH_KEY: + case SLNETSOCK_SEC_ATTRIB_DOMAIN_NAME: + if((strlen((char *)val) + 1) != len) + { + return SLNETERR_RET_CODE_INVALID_INPUT; + } + break; + case SLNETSOCK_SEC_ATTRIB_CIPHERS: + case SLNETSOCK_SEC_ATTRIB_ALPN: + case SLNETSOCK_SEC_ATTRIB_DISABLE_CERT_STORE: + if(sizeof(uint32_t) != len) + { + return SLNETERR_RET_CODE_INVALID_INPUT; + } + break; + case SLNETSOCK_SEC_ATTRIB_METHOD: + if(sizeof(uint8_t) != len) + { + return SLNETERR_RET_CODE_INVALID_INPUT; + } + break; + case SLNETSOCK_SEC_ATTRIB_EXT_CLIENT_CHLNG_RESP: + /* Format for this attrib is TBD */ + break; + default: + /* Reject attribNames we don't recognize */ + return SLNETERR_RET_CODE_INVALID_INPUT; + } + + /* Allocate dynamic memory for security attribute handler */ + secAttribObj = (SlNetSock_SecAttribNode_t *)malloc(sizeof(SlNetSock_SecAttribNode_t)); + + /* Check if the malloc function failed */ + if (NULL == secAttribObj) + { + /* Function failed, return error code */ + return SLNETERR_RET_CODE_MALLOC_ERROR; + } + + /* Set the inputs in the allocated security attribute handler */ + secAttribObj->attribName = attribName; + secAttribObj->attribBuff = val; + secAttribObj->attribBuffLen = len; + secAttribObj->next = *secAttrib; + + /* Connect the security attribute to the secAttrib list */ + *secAttrib = secAttribObj; + + + + return SLNETERR_RET_CODE_OK; +} + + +//***************************************************************************** +// +// SlNetSock_startSec - Start a security session on an opened socket +// +//***************************************************************************** +int32_t SlNetSock_startSec(int16_t sd, SlNetSockSecAttrib_t *secAttrib, uint8_t flags) +{ + int32_t retVal = SLNETERR_RET_CODE_OK; + int16_t realSd; + uint8_t sdFlags; + SlNetIf_t *netIf; + void *sdContext; + + /* Check if the sd input exists and return it */ + retVal = SlNetSock_getVirtualSdConf(sd, &realSd, &sdFlags, &sdContext, &netIf); + + /* Check if sd found or if the non mandatory function exists */ + if (SLNETERR_RET_CODE_OK != retVal) + { + return retVal; + } + if (NULL == (netIf->ifConf)->sockstartSec) + { + /* Non mandatory function doesn't exists, return error code */ + return SLNETERR_RET_CODE_DOESNT_SUPPORT_NON_MANDATORY_FXN; + } + /* StartSec function called, set bit */ + sdFlags |= flags; + /* Function exists in the interface of the socket descriptor, dispatch + the startSec command */ + retVal = (netIf->ifConf)->sockstartSec(realSd, sdContext, secAttrib, flags); + SLNETSOCK_NORMALIZE_RET_VAL(retVal,SLNETSOCK_ERR_SOCKSTARTSEC_FAILED); + + return retVal; +} diff --git a/simplelink/source/ti/net/slnetsock.h b/simplelink/source/ti/net/slnetsock.h new file mode 100644 index 0000000..0882b06 --- /dev/null +++ b/simplelink/source/ti/net/slnetsock.h @@ -0,0 +1,1866 @@ +/* + * Copyright (c) 2017-2019, Texas Instruments Incorporated + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of Texas Instruments Incorporated nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + /*! + + + \page SlNetSock_overview SlNetSock + + \section intro_sec Introduction + +SlNetSock provides a standard BSD API for TCP and UDP transport +layers, and a lower-level SlNetSock API for basic and extended +usage. Supported use cases include: + + - Support of multi interface (WiFi NS, Ethernet NDK) + - Selecting which interfaces the host will use, one or more. + - Support of different types of sockets (TCP, TLS, UDP, RAW, RF, etc.) + - BSD and proprietary errors + + The SlNetSock API's lead to easier portability to microcontrollers, + without compromising the capabilities and robustness of the final + application. + + + \section modules_sec Module Names + TI's SlNetSock layer is divided into the following software modules: + -# \ref SlNet - Interface for general SlNet services + -# \ref SlNetSock - Controls standard client/server sockets options and capabilities + -# \ref SlNetIf - Controls standard stack/interface options and capabilities + -# \ref SlNetUtils - Provides sockets related commands and configuration + -# \ref SlNetErr - Provide BSD and proprietary errors + +In addition, SlNetSock provides a standard BSD API, built atop the +SlNet* APIs. The BSD headers are placed in ti/net/bsd directory, +which users should place on their include path. + +Also, there is a light +\subpage porting_guide "SL Interface Porting Guide" +with information available for adding SlNetSock support for other stacks. + + \page porting_guide SL Interface Porting Guide + + \section Introduction + +The generic SlNetSock layer sits between the application/service and +the interface stack. This guide describes the details of adding a network stack into the SlNetSock environment. + +The porting steps for adding new interface: + -# Create slnetifxxx file for the new interface + -# Select the capabilities set + -# Adding the interface to your application/service + -# Add the relevant functions to your application/service + -# Test your code to validate the correctness of your porting + + \subsection porting_step1 Step 1 - slnetifxxx.c and slnetifxxx.h file for your interface + + - Create slnetifxxx file (replace xxx with your interface/stack + name). Likely you will copy from an existing port. + + - Implement the needed API's. + +Each interface needs to provide a set of API's to work with the +interface. Some are mandatory, others are optional (but recommended). + + - Mandatory API's: + - \ref SlNetIf_Config_t.sockCreate "sockCreate" + - \ref SlNetIf_Config_t.sockClose "sockClose" + - \ref SlNetIf_Config_t.sockSelect "sockSelect" + - \ref SlNetIf_Config_t.sockSetOpt "sockSetOpt" + - \ref SlNetIf_Config_t.sockGetOpt "sockGetOpt" + - \ref SlNetIf_Config_t.sockRecvFrom "sockRecvFrom" + - \ref SlNetIf_Config_t.sockSendTo "sockSendTo" + - \ref SlNetIf_Config_t.ifGetIPAddr "ifGetIPAddr" + - \ref SlNetIf_Config_t.ifGetConnectionStatus "ifGetConnectionStatus" + + - The non-mandatory API's set: + - \ref SlNetIf_Config_t.sockShutdown "sockShutdown" + - \ref SlNetIf_Config_t.sockAccept "sockAccept" + - \ref SlNetIf_Config_t.sockBind "sockBind" + - \ref SlNetIf_Config_t.sockListen "sockListen" + - \ref SlNetIf_Config_t.sockConnect "sockConnect" + - \ref SlNetIf_Config_t.sockGetPeerName "sockGetPeerName" + - \ref SlNetIf_Config_t.sockGetLocalName "sockGetLocalName" + - \ref SlNetIf_Config_t.sockRecv "sockRecv" + - \ref SlNetIf_Config_t.sockSend "sockSend" + - \ref SlNetIf_Config_t.sockstartSec "sockstartSec" + - \ref SlNetIf_Config_t.utilGetHostByName "utilGetHostByName" + - \ref SlNetIf_Config_t.ifLoadSecObj "ifLoadSecOjb" + - \ref SlNetIf_Config_t.ifCreateContext "ifCreateContext" + + + \note The list of API's and more data can be found in ::SlNetIf_Config_t structure in SlNetIf module \n \n + + \subsection porting_step2 Step 2 - Select the capabilities set + + The capabilities prototype should be declared in your slnetifxxx.h and implemented in your slnetifxxx.c + + Each mandatory API's must be set, additional API's can be set or must + be set to NULL. + + An example config declaration for TI's SimpleLink CC31XX/CC32xx + + \code + SlNetIfConfig SlNetIfConfigWiFi = + { + SlNetIfWifi_socket, // Callback function sockCreate in slnetif module + SlNetIfWifi_close, // Callback function sockClose in slnetif module + NULL, // Callback function sockShutdown in slnetif module + SlNetIfWifi_accept, // Callback function sockAccept in slnetif module + SlNetIfWifi_bind, // Callback function sockBind in slnetif module + SlNetIfWifi_listen, // Callback function sockListen in slnetif module + SlNetIfWifi_connect, // Callback function sockConnect in slnetif module + NULL, // Callback function sockGetPeerName in slnetif module + NULL, // Callback function sockGetLocalName in slnetif module + SlNetIfWifi_select, // Callback function sockSelect in slnetif module + SlNetIfWifi_setSockOpt, // Callback function sockSetOpt in slnetif module + SlNetIfWifi_getSockOpt, // Callback function sockGetOpt in slnetif module + SlNetIfWifi_recv, // Callback function sockRecv in slnetif module + SlNetIfWifi_recvFrom, // Callback function sockRecvFrom in slnetif module + SlNetIfWifi_send, // Callback function sockSend in slnetif module + SlNetIfWifi_sendTo, // Callback function sockSendTo in slnetif module + SlNetIfWifi_sockstartSec, // Callback function sockstartSec in slnetif module + SlNetIfWifi_getHostByName, // Callback function utilGetHostByName in slnetif module + SlNetIfWifi_getIPAddr, // Callback function ifGetIPAddr in slnetif module + SlNetIfWifi_getConnectionStatus, // Callback function ifGetConnectionStatus in slnetif module + SlNetIfWifi_loadSecObj, // Callback function ifLoadSecObj in slnetif module + NULL // Callback function ifCreateContext in slnetif module + }; + \endcode + + In the example above the following API's are not supported by the interface, + and are set to NULL: + - sockShutdown + - sockGetPeerName + - sockGetLocalName + - utilGetHostByName + - ifCreateContext + + \subsection porting_step3 Step 3 - Adding the interface to your application/service + + \b Include the new file in the board header file in the application. + + \subsection porting_step4 Step 4 - Add the relevant functions to your application/service + + After configuring the capabilities of the interface, Adding the interface to the SlNetSock + is required. + + Use ::SlNetIf_add in order to add the interface and set his ID, Name, function list and priority. + Later on you need to use the BSD API's or SlNetSock API's for socket handling. + + \subsection porting_step5 Step 5 - Test your code to validate the correctness of your porting + + After porting the layer into your setup, validate that your code work as expected + +*/ + +/*****************************************************************************/ +/* Include files */ +/*****************************************************************************/ + +#ifndef __SL_NET_SOCK_H__ +#define __SL_NET_SOCK_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +/*! + \defgroup SlNetSock SlNetSock group + + \short Controls standard client/server sockets options and capabilities + +*/ +/*! + + \addtogroup SlNetSock + @{ + +*/ + +/*****************************************************************************/ +/* Macro declarations */ +/*****************************************************************************/ + +#define SLNETSOCK_MAX_CONCURRENT_SOCKETS (32) /**< Declares the maximum sockets that can be opened */ + +/* Address families. */ +#define SLNETSOCK_AF_UNSPEC (0) /**< Unspecified address family */ +#define SLNETSOCK_AF_INET (2) /**< IPv4 socket (UDP, TCP, etc) */ +#define SLNETSOCK_AF_INET6 (3) /**< IPv6 socket (UDP, TCP, etc) */ +#define SLNETSOCK_AF_RF (6) /**< Data include RF parameter, All layer by user (Wifi could be disconnected) */ +#define SLNETSOCK_AF_PACKET (17) /**< Network bypass */ + +/* Protocol families, same as address families. */ +#define SLNETSOCK_PF_UNSPEC SLNETSOCK_AF_UNSPEC +#define SLNETSOCK_PF_INET SLNETSOCK_AF_INET +#define SLNETSOCK_PF_INET6 SLNETSOCK_AF_INET6 + +/* Define argument types specifies the socket type. */ +#define SLNETSOCK_SOCK_STREAM (1) /**< TCP Socket */ +#define SLNETSOCK_SOCK_DGRAM (2) /**< UDP Socket */ +#define SLNETSOCK_SOCK_RAW (3) /**< Raw socket */ +#define SLNETSOCK_SOCK_RX_MTR (4) /**< RX Metrics socket */ +#define SLNETSOCK_SOCK_MAC_WITH_CCA (5) +#define SLNETSOCK_SOCK_MAC_WITH_NO_CCA (6) +#define SLNETSOCK_SOCK_BRIDGE (7) +#define SLNETSOCK_SOCK_ROUTER (8) + +/* Define some BSD protocol constants. */ +#define SLNETSOCK_PROTO_TCP (6) /**< TCP Raw Socket */ +#define SLNETSOCK_PROTO_UDP (17) /**< UDP Raw Socket */ +#define SLNETSOCK_PROTO_RAW (255) /**< Raw Socket */ +#define SLNETSOCK_PROTO_SECURE (100) /**< Secured Socket Layer (SSL,TLS) */ + +/* bind any addresses */ +#define SLNETSOCK_INADDR_ANY (0) +#define SLNETSOCK_IN6ADDR_ANY (0) + + +/* socket options */ + +/* possible values for the level parameter in slNetSock_setOpt / slNetSock_getOpt */ +#define SLNETSOCK_LVL_SOCKET (1) /**< Define the socket option category. */ +#define SLNETSOCK_LVL_IP (2) /**< Define the IP option category. */ +#define SLNETSOCK_LVL_PHY (3) /**< Define the PHY option category. */ + +/* possible values for the option parameter in slNetSock_setOpt / slNetSock_getOpt */ + +/* socket level options (SLNETSOCK_LVL_SOCKET) */ +#define SLNETSOCK_OPSOCK_RCV_BUF (8) /**< Setting TCP receive buffer size (window size) - This options takes SlNetSock_Winsize_t struct as parameter */ +#define SLNETSOCK_OPSOCK_SND_BUF (202) /**< Sets or gets the maximum socket send buffer in bytes. - This option takes an int as a parameter */ +#define SLNETSOCK_OPSOCK_RCV_TIMEO (20) /**< Enable receive timeout - This options takes SlNetSock_Timeval_t struct as parameter */ +#define SLNETSOCK_OPSOCK_SND_TIMEO (21) /**< Enable send timeout - This options takes SlNetSock_Timeval_t struct as parameter */ +#define SLNETSOCK_OPSOCK_KEEPALIVE (9) /**< Connections are kept alive with periodic messages - This options takes SlNetSock_Keepalive_t struct as parameter */ +#define SLNETSOCK_OPSOCK_KEEPALIVE_TIME (37) /**< keepalive time out - This options takes uint32_t as parameter */ +#define SLNETSOCK_OPSOCK_LINGER (13) /**< Socket lingers on close pending remaining send/receive packets - This options takes SlNetSock_linger_t struct as parameter */ +#define SLNETSOCK_OPSOCK_NON_BLOCKING (24) /**< Enable/disable nonblocking mode - This options takes SlNetSock_Nonblocking_t struct as parameter */ +#define SLNETSOCK_OPSOCK_NON_IP_BOUNDARY (39) /**< connectionless socket disable rx boundary - This options takes SlNetSock_NonIpBoundary_t struct as parameter */ +#define SLNETSOCK_OPSOCK_ERROR (58) /**< Socket level error code */ +#define SLNETSOCK_OPSOCK_SLNETSOCKSD (59) /**< Used by the BSD layer in order to retrieve the slnetsock sd */ +#define SLNETSOCK_OPSOCK_BROADCAST (200) /**< Enable/disable broadcast signals - This option takes SlNetSock_Broadcast_t struct as parameters */ +#define SLNETSOCK_OPSOCK_REUSEADDR (201) /**< Enable/disable allowing reuse of local addresses for bind calls - This option takes an int as a parameter */ +#define SLNETSOCK_OPSOCK_REUSEPORT (203) /**< Enable/disable multiple sockets to be bound to an identical socket address. - This option takes an int as a parameter */ + +/* IP level options (SLNETSOCK_LVL_IP) */ +#define SLNETSOCK_OPIP_MULTICAST_TTL (61) /**< Specify the TTL value to use for outgoing multicast packet. - This options takes uint8_t as parameter */ +#define SLNETSOCK_OPIP_ADD_MEMBERSHIP (65) /**< Join IPv4 multicast membership - This options takes SlNetSock_IpMreq_t struct as parameter */ +#define SLNETSOCK_OPIP_DROP_MEMBERSHIP (66) /**< Leave IPv4 multicast membership - This options takes SlNetSock_IpMreq_t struct as parameter */ +#define SLNETSOCK_OPIP_HDRINCL (67) /**< Raw socket IPv4 header included - This options takes uint32_t as parameter */ +#define SLNETSOCK_OPIP_RAW_RX_NO_HEADER (68) /**< Proprietary socket option that does not includeIPv4/IPv6 header (and extension headers) on received raw sockets - This options takes uint32_t as parameter */ +#define SLNETSOCK_OPIP_RAW_IPV6_HDRINCL (69) /**< Transmitted buffer over IPv6 socket contains IPv6 header - This options takes uint32_t as parameter */ +#define SLNETSOCK_OPIPV6_ADD_MEMBERSHIP (70) /**< Join IPv6 multicast membership - This options takes SlNetSock_IpV6Mreq_t struct as parameter */ +#define SLNETSOCK_OPIPV6_DROP_MEMBERSHIP (71) /**< Leave IPv6 multicast membership - This options takes SlNetSock_IpV6Mreq_t struct as parameter */ +#define SLNETSOCK_OPIPV6_MULTICAST_HOPS (72) /**< Specify the hops value to use for outgoing multicast packet. */ + +/* PHY level options (SLNETSOCK_LVL_PHY) */ +#define SLNETSOCK_OPPHY_CHANNEL (28) /**< This option is available only when transceiver started - This options takes uint32_t as channel number parameter */ +#define SLNETSOCK_OPPHY_RATE (100) /**< WLAN Transmit rate - This options takes uint32_t as parameter based on SlWlanRateIndex_e */ +#define SLNETSOCK_OPPHY_TX_POWER (101) /**< TX Power level - This options takes uint32_t as parameter */ +#define SLNETSOCK_OPPHY_NUM_FRAMES_TO_TX (102) /**< Number of frames to transmit - This options takes uint32_t as parameter */ +#define SLNETSOCK_OPPHY_PREAMBLE (103) /**< Preamble for transmission - This options takes uint32_t as parameter */ +#define SLNETSOCK_OPPHY_TX_INHIBIT_THRESHOLD (104) /**< TX Inhibit Threshold (CCA) - This options takes uint32_t as parameter based on SlNetSockTxInhibitThreshold_e */ +#define SLNETSOCK_OPPHY_TX_TIMEOUT (105) /**< TX timeout for Transceiver frames (lifetime) in miliseconds (max value is 100ms) - This options takes uint32_t as parameter */ +#define SLNETSOCK_OPPHY_ALLOW_ACKS (106) /**< Enable sending ACKs in transceiver mode - This options takes uint32_t as parameter */ + +/* TCP level options (SLNETSOCK_PROTO_TCP) */ +#define SLNETSOCK_TCP_NODELAY (203) /**< Disables TCP send delay/coalesce algorithm - This option takes SLNetSock_NoDelay_t struct as a parameter */ +#define SLNETSOCK_TCP_MAXSEG (204) /**< Set the maximum TCP segment size - This option takes SLNetSock_MaxSeg_t struct as a parameter */ +#define SLNETSOCK_TCP_NOPUSH (205) /**< Do not send data just to finish a data block (attempt to coalesce). - This option takes SLNetSock_NoPush_t struct as a parameter */ +#define SLNETSOCK_TCP_NOOPT (206) /**< Do not use TCP options. - This option takes SLNetSock_NoOpt_t struct as a parameter */ +#define SLNETSOCK_TCP_SACKPERMITTED (207) /**< Permit RFC-2018 Selective Acknowledgment(SACK) conformant connection - This option takes SLNetSock_SackPermitted_t struct as a parameter */ +#define SLNETSOCK_TCP_MAXRTT (208) /**< The maximum TCP Round Trip Time value allowed in the determination of the estimated TCP RTT - This option takes SLNetSock_MaxRtt_t struct as a parameter */ + +/*! + \brief The SlNetSockTxInhibitThreshold_e enumerations is used in SLNETSOCK_OPPHY_TX_INHIBIT_THRESHOLD PHY level option +*/ +typedef enum +{ + SLNETSOCK_TX_INHIBIT_THRESHOLD_MIN = 1, + SLNETSOCK_TX_INHIBIT_THRESHOLD_LOW = 2, + SLNETSOCK_TX_INHIBIT_THRESHOLD_DEFAULT = 3, + SLNETSOCK_TX_INHIBIT_THRESHOLD_MED = 4, + SLNETSOCK_TX_INHIBIT_THRESHOLD_HIGH = 5, + SLNETSOCK_TX_INHIBIT_THRESHOLD_MAX = 6 +} SlNetSockTxInhibitThreshold_e; + +/*! + \brief The SlNetSockSecAttrib_e enumerations are used to declare security + attribute objects in SlNetSock_secAttribSet(). + + \sa SlNetSock_secAttribSet() +*/ +typedef enum +{ + SLNETSOCK_SEC_ATTRIB_PRIVATE_KEY = 0, + SLNETSOCK_SEC_ATTRIB_LOCAL_CERT = 1, + SLNETSOCK_SEC_ATTRIB_PEER_ROOT_CA = 2, + SLNETSOCK_SEC_ATTRIB_DH_KEY = 3, + SLNETSOCK_SEC_ATTRIB_METHOD = 4, + SLNETSOCK_SEC_ATTRIB_CIPHERS = 5, + SLNETSOCK_SEC_ATTRIB_ALPN = 6, + SLNETSOCK_SEC_ATTRIB_EXT_CLIENT_CHLNG_RESP = 7, + SLNETSOCK_SEC_ATTRIB_DOMAIN_NAME = 8, + + /*! + @c SLNETSOCK_SEC_ATTRIB_DISABLE_CERT_STORE is + currently only supported on CC3xxx devices. + + The certificate store is a file, provided by TI, + containing a list of known and trusted root CAs by TI. + For more information, see the CC3xxx documentation. + + The certificate store is used only in client mode. Servers + use a proprietary root CA to authenticate clients, and + therefore cannot use the certificate store. + + Using this attribute allows using root CA which isn't a + part of the provided certificate store. + */ + + SLNETSOCK_SEC_ATTRIB_DISABLE_CERT_STORE = 9 +} SlNetSockSecAttrib_e; + +/* available values for SLNETSOCK_SEC_ATTRIB_METHOD */ +#define SLNETSOCK_SEC_METHOD_SSLV3 (0) /**< security method SSL v3 */ +#define SLNETSOCK_SEC_METHOD_TLSV1 (1) /**< security method TLS v1 */ +#define SLNETSOCK_SEC_METHOD_TLSV1_1 (2) /**< security method TLS v1_1 */ +#define SLNETSOCK_SEC_METHOD_TLSV1_2 (3) /**< security method TLS v1_2 */ +#define SLNETSOCK_SEC_METHOD_SSLv3_TLSV1_2 (4) /**< use highest possible version from SSLv3 - TLS 1.2 */ +#define SLNETSOCK_SEC_METHOD_DLSV1 (5) /**< security method DTL v1 */ + +/* available values for SLNETSOCK_SEC_ATTRIB_CIPHERS. The value is bitmap! */ +#define SLNETSOCK_SEC_CIPHER_SSL_RSA_WITH_RC4_128_SHA (1 << 0) +#define SLNETSOCK_SEC_CIPHER_SSL_RSA_WITH_RC4_128_MD5 (1 << 1) +#define SLNETSOCK_SEC_CIPHER_TLS_RSA_WITH_AES_256_CBC_SHA (1 << 2) +#define SLNETSOCK_SEC_CIPHER_TLS_DHE_RSA_WITH_AES_256_CBC_SHA (1 << 3) +#define SLNETSOCK_SEC_CIPHER_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (1 << 4) +#define SLNETSOCK_SEC_CIPHER_TLS_ECDHE_RSA_WITH_RC4_128_SHA (1 << 5) +#define SLNETSOCK_SEC_CIPHER_TLS_RSA_WITH_AES_128_CBC_SHA256 (1 << 6) +#define SLNETSOCK_SEC_CIPHER_TLS_RSA_WITH_AES_256_CBC_SHA256 (1 << 7) +#define SLNETSOCK_SEC_CIPHER_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 (1 << 8) +#define SLNETSOCK_SEC_CIPHER_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 (1 << 9) +#define SLNETSOCK_SEC_CIPHER_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA (1 << 10) +#define SLNETSOCK_SEC_CIPHER_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA (1 << 11) +#define SLNETSOCK_SEC_CIPHER_TLS_RSA_WITH_AES_128_GCM_SHA256 (1 << 12) +#define SLNETSOCK_SEC_CIPHER_TLS_RSA_WITH_AES_256_GCM_SHA384 (1 << 13) +#define SLNETSOCK_SEC_CIPHER_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 (1 << 14) +#define SLNETSOCK_SEC_CIPHER_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 (1 << 15) +#define SLNETSOCK_SEC_CIPHER_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (1 << 16) +#define SLNETSOCK_SEC_CIPHER_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (1 << 17) +#define SLNETSOCK_SEC_CIPHER_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 (1 << 18) +#define SLNETSOCK_SEC_CIPHER_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 (1 << 19) +#define SLNETSOCK_SEC_CIPHER_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 (1 << 20) +#define SLNETSOCK_SEC_CIPHER_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 (1 << 21) +#define SLNETSOCK_SEC_CIPHER_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 (1 << 22) +#define SLNETSOCK_SEC_CIPHER_FULL_LIST (0xFFFFFFFF) + +/* available values for SLNETSOCK_SEC_ATTRIB_ALPN */ +#define SLNETSOCK_SEC_ALPN_H1 (1 << 0) +#define SLNETSOCK_SEC_ALPN_H2 (1 << 1) +#define SLNETSOCK_SEC_ALPN_H2C (1 << 2) +#define SLNETSOCK_SEC_ALPN_H2_14 (1 << 3) +#define SLNETSOCK_SEC_ALPN_H2_16 (1 << 4) +#define SLNETSOCK_SEC_ALPN_FULL_LIST ((SLNETSOCK_SEC_ALPN_H2_16 << 1 ) - 1) + +/* available values for the flags of the SlNetSock_startSec function */ +#define SLNETSOCK_SEC_START_SECURITY_SESSION_ONLY (1 << 0) /**< Sends the command that will start the security session for a specific socket descriptor */ +#define SLNETSOCK_SEC_BIND_CONTEXT_ONLY (1 << 1) /**< Binds the security context to a specific socket descriptor */ +#define SLNETSOCK_SEC_IS_SERVER (1 << 2) /**< Used to define if the socket is client/server socket */ + +/* available values for the flags of the SlNetSock_create function */ + +#define SLNETSOCK_CREATE_IF_STATE_ENABLE (1 << 0) /**< Creation of the socket will be on enabled state */ +#define SLNETSOCK_CREATE_IF_STATUS_CONNECTED (1 << 1) /**< Creation of the socket will be on status connected */ +#define SLNETSOCK_CREATE_ALLOW_PARTIAL_MATCH (1 << 2) /**< Creation of the socket will be on the interface with + the highest priority if the other flags will fail */ + +/* Definitions for shutting down some or all parts of a full duplex connection */ +#define SLNETSOCK_SHUT_RD (0) /**< Further receptions will be disallowed */ +#define SLNETSOCK_SHUT_WR (1) /**< Further transmissions will be disallowed */ +#define SLNETSOCK_SHUT_RDWR (2) /**< Further receptions and transmissions will be disallowed */ + +/* Length of address string representation */ +#define SLNETSOCK_INET6_ADDRSTRLEN (46) +#define SLNETSOCK_INET_ADDRSTRLEN (16) + +/* flags used in send/recv and friends. + * + * Note these flags must not exceed 24-bits. The implementation will + * OR the 8-bits of security flags into the remaining high 8 bits of + * 32-bit flag variables. + */ +#define SLNETSOCK_MSG_OOB (0x0001) +#define SLNETSOCK_MSG_PEEK (0x0002) +#define SLNETSOCK_MSG_WAITALL (0x0004) +#define SLNETSOCK_MSG_DONTWAIT (0x0008) +#define SLNETSOCK_MSG_DONTROUTE (0x0010) +#define SLNETSOCK_MSG_NOSIGNAL (0x0020) + + +/*****************************************************************************/ +/* Structure/Enum declarations */ +/*****************************************************************************/ + +/*! + \brief Internet address +*/ +typedef struct SlNetSock_InAddr_t +{ +#ifndef s_addr + uint32_t s_addr; /* Internet address 32 bits */ +#else +/*! + \brief Different representations for in addr for different hosts. +*/ + union S_un + { + uint32_t S_addr; + struct + { + uint8_t s_b1,s_b2,s_b3,s_b4; + } S_un_b; + struct + { + uint16_t s_w1,s_w2; + } S_un_w; + } S_un; +#endif +} SlNetSock_InAddr_t; + +/*! + \brief IpV6 or Ipv6 EUI64 +*/ +typedef struct SlNetSock_In6Addr_t +{ + union + { + uint8_t _S6_u8[16]; + uint16_t _S6_u16[8]; + uint32_t _S6_u32[4]; + } _S6_un; +} SlNetSock_In6Addr_t; + +/*! + \brief The SlNetSock_NoDelay_t structure is used in #SLNETSOCK_TCP_NODELAY TCP level option +*/ +typedef struct SlNetSock_NoDelay_t +{ + uint32_t noDelayEnabled; /**< 0 = disabled;1 = enabled; default = 0 */ +} SlNetSock_NoDelay_t; + +/*! + \brief The SlNetSock_MaxSeg_t structure is used in #SLNETSOCK_TCP_MAXSEG TCP level option +*/ +typedef struct SlNetSock_MaxSeg_t +{ + uint32_t maxSeg; /**< Maximum TCP segment size. Default = 536 */ +} SlNetSock_MaxSeg_t; + +/*! + \brief The SlNetSock_NoPush_t structure is used in #SLNETSOCK_TCP_NOPUSH TCP level option +*/ +typedef struct SlNetSock_NoPush_t +{ + uint32_t noPushEnabled; /**< 0 = disabled;1 = enabled; default = 0 */ +} SlNetSock_NoPush_t; + +/*! + \brief The SlNetSock_NoOpt_t structure is used in #SLNETSOCK_TCP_NOOPT TCP level option +*/ +typedef struct SlNetSock_NoOpt_t +{ + uint32_t noOptEnabled; /**< 0 = disabled;1 = enabled; default = 0 */ +} SlNetSock_NoOpt_t; + +/*! + \brief The SlNetSock_SackPermitted_t structure is used in #SLNETSOCK_TCP_NOPUSH TCP level option +*/ +typedef struct SlNetSock_SackPermitted_t +{ + uint32_t sackPermittedEnabled; /**< 0 = disabled;1 = enabled; default = 0 */ +} SlNetSock_SackPermitted_t; + +/*! + \brief The SlNetSock_MaxRtt_t structure is used in #SLNETSOCK_TCP_MAXRTT TCP level option +*/ +typedef struct SlNetSock_MaxRtt_t +{ + uint32_t maxRtt; /**< Maximum TCP Round Trip Time value allowed; Default = 360000000 */ +} SlNetSock_MaxRtt_t; + +/*! + \brief The SlNetSock_Keepalive_t structure is used in #SLNETSOCK_OPSOCK_KEEPALIVE socket level option +*/ +typedef struct SlNetSock_Keepalive_t +{ + uint32_t keepaliveEnabled; /**< 0 = disabled;1 = enabled; default = 1 */ +} SlNetSock_Keepalive_t; + +/*! + \brief The SlNetSock_NonIpBoundary_t structure is used in #SLNETSOCK_OPSOCK_NON_IP_BOUNDARY socket level option +*/ +typedef struct SlNetSock_NonIpBoundary_t +{ + int32_t nonIpBoundaryEnabled; /**< 0 = keep IP boundary; 1 = don`t keep ip boundary; default = 0; */ +} SlNetSock_NonIpBoundary_t; + +/*! + \brief The SlNetSock_Winsize_t structure is used in #SLNETSOCK_OPSOCK_RCV_BUF socket level option +*/ +typedef struct SlNetSock_Winsize_t +{ + uint32_t winSize; /**< receive window size for tcp sockets */ +} SlNetSock_Winsize_t; + +/*! + \brief The SlNetSock_Nonblocking_t structure is used in #SLNETSOCK_OPSOCK_NON_BLOCKING socket level option +*/ +typedef struct SlNetSock_Nonblocking_t +{ + uint32_t nonBlockingEnabled; /**< 0 = disabled, 1 = enabled, default = 1*/ +} SlNetSock_Nonblocking_t; + +/*! + \brief The SlNetSock_Broadcast_t structure is used in #SLNETSOCK_OPSOCK_BROADCAST socket level option +*/ +typedef struct SlNetSock_Broadcast_t +{ + uint32_t broadcastEnabled; /**< 0 = disabled, 1 = enabled, default = 0*/ +} SlNetSock_Broadcast_t; + +/*! + \brief Secure socket attribute context +*/ +typedef struct SlNetSock_SecAttribNode_t +{ + SlNetSockSecAttrib_e attribName; /**< Security attribute name */ + uint8_t *attribBuff; /**< Security attribute buffer */ + uint16_t attribBuffLen; /**< Security attribute buffer length */ + struct SlNetSock_SecAttribNode_t *next; +} SlNetSock_SecAttribNode_t; + +/*! + \brief Secure socket attribute handler +*/ +typedef SlNetSock_SecAttribNode_t * SlNetSockSecAttrib_t; + +/*! + \brief Secure ALPN structure +*/ +typedef struct SlNetSock_SecureALPN_t +{ + uint32_t secureALPN; +} SlNetSock_SecureALPN_t; + +/*! + \brief Secure Mask structure +*/ +typedef struct SlNetSock_SecureMask_t +{ + uint32_t secureMask; +} SlNetSock_SecureMask_t; + +/*! + \brief Secure Method structure +*/ +typedef struct SlNetSock_SecureMethod_t +{ + uint8_t secureMethod; +} SlNetSock_SecureMethod_t; + +/*! + \brief The SlNetSock_IpMreq_t structure is used in #SLNETSOCK_OPIP_ADD_MEMBERSHIP and #SLNETSOCK_OPIP_DROP_MEMBERSHIP IP level option +*/ +typedef struct SlNetSock_IpMreq_t +{ + SlNetSock_InAddr_t imr_multiaddr; /**< The IPv4 multicast address to join */ + uint32_t imr_interface; /**< The interface to use for this group */ +} SlNetSock_IpMreq_t; + +/*! + \brief The SlNetSock_IpV6Mreq_t structure is used in #SLNETSOCK_OPIPV6_ADD_MEMBERSHIP and #SLNETSOCK_OPIPV6_DROP_MEMBERSHIP IP level option +*/ +typedef struct SlNetSock_IpV6Mreq_t +{ + SlNetSock_In6Addr_t ipv6mr_multiaddr; /**< IPv6 multicast address of group */ + uint32_t ipv6mr_interface; /**< should be 0 to choose the default multicast interface */ +} SlNetSock_IpV6Mreq_t; + +/*! + \brief The SlNetSock_linger_t structure is used in #SLNETSOCK_OPSOCK_LINGER socket level option +*/ +typedef struct SlNetSock_linger_t +{ + uint32_t l_onoff; /**< 0 = disabled; 1 = enabled; default = 0; */ + uint32_t l_linger; /**< linger time in seconds; default = 0; */ +} SlNetSock_linger_t; + +/*! + \brief The @c SlNetSock_Timeval_t structure is used in the + #SLNETSOCK_OPSOCK_RCV_TIMEO and #SLNETSOCK_OPSOCK_SND_TIMEO + socket level options + + \remarks Note that @c SlNetSock_Timeval_t is intentionally defined + to be equivalent to the POSIX-defined struct + timeval data type. +*/ +typedef struct timeval SlNetSock_Timeval_t; + +/*! + \brief The SlNetSocklen_t is used for declaring the socket length parameter +*/ +typedef uint16_t SlNetSocklen_t; + +/*! + \brief IpV4 socket address +*/ +typedef struct SlNetSock_Addr_t +{ + uint16_t sa_family; /**< Address family (e.g. AF_INET) */ + uint8_t sa_data[14]; /**< Protocol- specific address information */ +} SlNetSock_Addr_t; + +/*! + \brief SlNetSock IPv6 address, Internet style +*/ +typedef struct SlNetSock_AddrIn6_t +{ + uint16_t sin6_family; /**< SLNETSOCK_AF_INET6 */ + uint16_t sin6_port; /**< Transport layer port. */ + uint32_t sin6_flowinfo; /**< IPv6 flow information. */ + SlNetSock_In6Addr_t sin6_addr; /**< IPv6 address. */ + uint32_t sin6_scope_id; /**< set of interfaces for a scope. */ +} SlNetSock_AddrIn6_t; + +/*! + \brief SlNetSock IPv4 address, Internet style +*/ +typedef struct SlNetSock_AddrIn_t +{ + uint16_t sin_family; /**< Internet Protocol (AF_INET). */ + uint16_t sin_port; /**< Address port (16 bits). */ + SlNetSock_InAddr_t sin_addr; /**< Internet address (32 bits). */ + int8_t sin_zero[8]; /**< Not used. */ +} SlNetSock_AddrIn_t; + +/* ss_family + pad must be large enough to hold max of + * _SlNetSock_AddrIn6_t or _SlNetSock_AddrIn_t + */ +/*! + \brief Generic socket address type to hold either IPv4 or IPv6 address +*/ +typedef struct SlNetSock_SockAddrStorage_t +{ + uint16_t ss_family; + uint8_t pad[26]; +} SlNetSock_SockAddrStorage_t; + +/*! + \brief The SlNetSock_SdSet_t structure holds the sd array for SlNetSock_select function +*/ +typedef struct SlNetSock_SdSet_t /**< The select socket array manager */ +{ + uint32_t sdSetBitmap[(SLNETSOCK_MAX_CONCURRENT_SOCKETS + (uint8_t)31)/(uint8_t)32]; /* Bitmap of SOCKET Descriptors */ +} SlNetSock_SdSet_t; + + +/*! + \brief The SlNetSock_TransceiverRxOverHead_t structure holds the data for Rx transceiver mode using a raw socket when using SlNetSock_recv function +*/ +typedef struct SlNetSock_TransceiverRxOverHead_t +{ + uint8_t rate; /**< Received Rate */ + uint8_t channel; /**< The received channel */ + int8_t rssi; /**< The computed RSSI value in db of current frame */ + uint8_t padding; /**< pad to align to 32 bits */ + uint32_t timestamp; /**< Timestamp in microseconds */ +} SlNetSock_TransceiverRxOverHead_t; + + +/*****************************************************************************/ +/* Function prototypes */ +/*****************************************************************************/ + +/*! + + \brief Initialize the SlNetSock module + + \param[in] flags Reserved + + \return Zero on success, or negative error code on failure + + \par Examples + \snippet ti/net/test/snippets/slnetif.c SlNetSock_init snippet + +*/ +int32_t SlNetSock_init(int32_t flags); + +/*! + + \brief Create an endpoint for communication + + SlNetSock_create() creates a new socket of a certain socket type, + identified by an integer number, and allocates system resources to it.\n + This function is called by the application layer to obtain a socket descriptor (handle). + + \param[in] domain Specifies the protocol family of the created socket. + For example: + - #SLNETSOCK_AF_INET for network protocol IPv4 + - #SLNETSOCK_AF_INET6 for network protocol IPv6 + - #SLNETSOCK_AF_RF for starting transceiver mode. + Notes: + - sending and receiving any packet overriding 802.11 header + - for optimized power consumption the socket will be started in TX + only mode until receive command is activated + \param[in] type Specifies the socket type, which determines the semantics of communication over + the socket. The socket types supported by the system are implementation-dependent. + Possible socket types include: + - #SLNETSOCK_SOCK_STREAM (reliable stream-oriented service or Stream Sockets) + - #SLNETSOCK_SOCK_DGRAM (datagram service or Datagram Sockets) + - #SLNETSOCK_SOCK_RAW (raw protocols atop the network layer) + - when used with AF_RF: + - #SLNETSOCK_SOCK_RX_MTR + - #SLNETSOCK_SOCK_MAC_WITH_CCA + - #SLNETSOCK_SOCK_MAC_WITH_NO_CCA + - #SLNETSOCK_SOCK_BRIDGE + - #SLNETSOCK_SOCK_ROUTER + \param[in] protocol Specifies a particular transport to be used with the socket.\n + The most common are + - #SLNETSOCK_PROTO_TCP + - #SLNETSOCK_PROTO_UDP + - #SLNETSOCK_PROTO_RAW + - #SLNETSOCK_PROTO_SECURE + \param[in] ifBitmap Specifies the interface(s) which the socket will be created on + according to priority until one of them will return an answer.\n + Value 0 is used in order to choose automatic interfaces selection + according to the priority interface list. + Value can be a combination of interfaces by OR'ing multiple interfaces bit identifiers + (SLNETIFC_IDENT_ defined in slnetif.h) + Note: interface identifier bit must be configured prior to this socket creation + using SlNetIf_add(). + \param[in] flags Specifies flags. + - #SLNETSOCK_CREATE_IF_STATE_ENABLE - Creation of the socket will be on enabled state + - #SLNETSOCK_CREATE_IF_STATUS_CONNECTED - Creation of the socket will be on status connected + - #SLNETSOCK_CREATE_ALLOW_PARTIAL_MATCH - Creation of the socket will be on the interface with + the highest priority if the other flags will fail + The value 0 may be used in order to run the default flags: + - #SLNETSOCK_CREATE_IF_STATE_ENABLE + - #SLNETSOCK_CREATE_IF_STATUS_CONNECTED + + \return On success, socket descriptor (handle) that is used for consequent socket operations. \n + A successful return code should be a positive number\n + On error, a negative value will be returned specifying the error code. + - #SLNETERR_BSD_EAFNOSUPPORT - illegal domain parameter + - #SLNETERR_BSD_EPROTOTYPE - illegal type parameter + - #SLNETERR_BSD_EACCES - permission denied + - #SLNETERR_BSD_ENSOCK - exceeded maximal number of socket + - #SLNETERR_BSD_ENOMEM - memory allocation error + - #SLNETERR_BSD_EINVAL - error in socket configuration + - #SLNETERR_BSD_EPROTONOSUPPORT - illegal protocol parameter + - #SLNETERR_BSD_EOPNOTSUPP - illegal combination of protocol and type parameters + + \slnetsock_init_precondition + + \remark Not all platforms support all options. + + \remark A @c protocol value of zero can be used to select the default protocol from the selected @c domain and @c type. + + \remark SlNetSock_create() uses the highest priority interface from the ifBitmap, subject to the constraints specified + in the flags parameter. An interface that does not satisfy the constraints is ignored, without regards to its + priority level. + + \par Examples + \snippet ti/net/test/snippets/slnetif.c SlNetSock_create TCP IPv4 snippet + \snippet ti/net/test/snippets/slnetif.c SlNetSock_create TCP IPv6 snippet + \snippet ti/net/test/snippets/slnetif.c SlNetSock_create UDP IPv4 snippet + + \sa SlNetSock_close() +*/ +int16_t SlNetSock_create(int16_t domain, int16_t type, int16_t protocol, uint32_t ifBitmap, int16_t flags); + + +/*! + \brief Gracefully close socket + + Release resources allocated to a socket. + + \param[in] sd Socket descriptor (handle), received in SlNetSock_create() + + \return Zero on success, or negative error code on failure + + \slnetsock_init_precondition + + \remark In the case of TCP, the connection is terminated. + + \remark After this function returns there is no way to access the socket + identified by @c sd. The SlNetSock socket is closed regardless + of the status of the underlying interface's socket. + + \par Examples + \snippet ti/net/test/snippets/slnetif.c SlNetSock_close snippet + + \sa SlNetSock_create() +*/ +int32_t SlNetSock_close(int16_t sd); + + +/*! + \brief Shutting down parts of a full-duplex connection + + Shuts down parts of a full-duplex connection according to how parameter.\n + + \param[in] sd Socket descriptor (handle), received in SlNetSock_create + \param[in] how Specifies which part of a full-duplex connection to shutdown. \n + The options are + - #SLNETSOCK_SHUT_RD - further receptions will be disallowed + - #SLNETSOCK_SHUT_WR - further transmissions will be disallowed + - #SLNETSOCK_SHUT_RDWR - further receptions and transmissions will be disallowed + + \return Zero on success, or negative error code on failure + + \slnetsock_init_precondition + + \sa SlNetSock_create() + \sa SlNetSock_connect() + \sa SlNetSock_accept() +*/ +int32_t SlNetSock_shutdown(int16_t sd, int16_t how); + + +/*! + \brief Accept a connection on a socket + + The SlNetSock_accept function is used with connection-based socket types (#SLNETSOCK_SOCK_STREAM). + + It extracts the first connection request on the queue of pending + connections, creates a new connected socket, and returns a new file + descriptor referring to that socket. + + The newly created socket is not in the listening state. The + original socket sd is unaffected by this call. + + The argument sd is a socket that has been created with + SlNetSock_create(), bound to a local address with + SlNetSock_bind(), and is listening for connections after a + SlNetSock_listen(). + + The argument \c addr is a pointer to a sockaddr structure. This + structure is filled in with the address of the peer socket, as + known to the communications layer. + + The exact format of the address returned \c addr is determined by the socket's address family. + + \c addrlen is a value-result argument: it should initially contain + the size of the structure pointed to by addr, on return it will + contain the actual length (in bytes) of the address returned. + + \param[in] sd Socket descriptor (handle) + \param[out] addr The argument addr is a pointer + to a sockaddr structure. This + structure is filled in with the + address of the peer socket, as + known to the communications + layer. The exact format of the + address returned addr is + determined by the socket's + address\n + sockaddr:\n - code for the + address format.\n - + socket address, the length + depends on the code format + \param[out] addrlen The addrlen argument is a value-result + argument: it should initially contain the + size of the structure pointed to by addr + + \return On success, a socket descriptor.\n + On a non-blocking accept a possible negative value is #SLNETERR_BSD_EAGAIN.\n + On failure, negative error code.\n + #SLNETERR_BSD_ENOMEM may be return in case there are no resources in the system + + \slnetsock_init_precondition + + \sa SlNetSock_create() + \sa SlNetSock_bind() + \sa SlNetSock_listen() +*/ +int16_t SlNetSock_accept(int16_t sd, SlNetSock_Addr_t *addr, SlNetSocklen_t *addrlen); + + +/*! + \brief Assign a name to a socket + + This SlNetSock_bind function gives the socket the local address + addr. addr is addrlen bytes long. + + Traditionally, this is called when a socket is created with + socket, it exists in a name space (address family) but has no name + assigned. + + It is necessary to assign a local address before a #SLNETSOCK_SOCK_STREAM + socket may receive connections. + + \param[in] sd Socket descriptor (handle) + \param[in] addr Specifies the destination + addrs\n sockaddr:\n - code for + the address format.\n - socket address, + the length depends on the code + format + \param[in] addrlen Contains the size of the structure pointed to by addr + + \return Zero on success, or negative error code on failure + + \slnetsock_init_precondition + + \sa SlNetSock_create() + \sa SlNetSock_accept() + \sa SlNetSock_listen() +*/ +int32_t SlNetSock_bind(int16_t sd, const SlNetSock_Addr_t *addr, int16_t addrlen); + + +/*! + \brief Listen for connections on a socket + + The willingness to accept incoming connections and a queue + limit for incoming connections are specified with SlNetSock_listen(), + and then the connections are accepted with SlNetSock_accept(). + + \param[in] sd Socket descriptor (handle) + \param[in] backlog Specifies the listen queue depth. + + \return Zero on success, or negative error code on failure + + \slnetsock_init_precondition + + \remark The SlNetSock_listen() call applies only to sockets of + type #SLNETSOCK_SOCK_STREAM. + + \remark The \c backlog parameter defines the maximum length the queue of + pending connections may grow to. + + \sa SlNetSock_create() + \sa SlNetSock_accept() + \sa SlNetSock_bind() +*/ +int32_t SlNetSock_listen(int16_t sd, int16_t backlog); + + +/*! + \brief Initiate a connection on a socket + + Function connects the socket referred to by the socket + descriptor sd, to the address specified by \c addr. + + The format of the address in addr is determined by the address + space of the socket. + + If it is of type #SLNETSOCK_SOCK_DGRAM, this call specifies the + peer with which the socket is to be associated; this address is + that to which datagrams are to be sent, and the only address from + which datagrams are to be received. + + If the socket is of type #SLNETSOCK_SOCK_STREAM, this call + attempts to make a connection to another socket. + + The other socket is specified by address, which is an address in + the communications space of the socket. + + \param[in] sd Socket descriptor (handle) + \param[in] addr Specifies the destination addr\n + sockaddr:\n - code for the + address format.\n - + socket address, the length + depends on the code format + \param[in] addrlen Contains the size of the structure pointed + to by addr + + \return On success, a socket descriptor (handle).\n + On failure, negative value.\n + On a non-blocking connect a possible negative value is #SLNETERR_BSD_EALREADY. + #SLNETERR_POOL_IS_EMPTY may be returned in case there are no resources in the system + + \slnetsock_init_precondition + + \sa SlNetSock_create() +*/ +int32_t SlNetSock_connect(int16_t sd, const SlNetSock_Addr_t *addr, SlNetSocklen_t addrlen); + +/*! + \brief Return address info about the remote side of the connection + + Returns a struct SlNetSock_AddrIn_t + filled with information about the peer device that is connected + on the other side of the socket descriptor. + + \param[in] sd Socket descriptor (handle) + \param[out] addr returns the struct addr\n + SlNetSockAddrIn filled with information + about the peer device:\n - code for the + address format.\n - + socket address, the length + depends on the code format + \param[out] addrlen Contains the size of the structure pointed + to by addr + + \return Zero on success, or negative error code on failure + + \slnetsock_init_precondition + + \sa SlNetSock_accept() + \sa SlNetSock_connect() +*/ +int32_t SlNetSock_getPeerName(int16_t sd, SlNetSock_Addr_t *addr, SlNetSocklen_t *addrlen); + + +/*! + \brief Get local address info by socket descriptor + + Returns the local address info of the socket descriptor. + + \param[in] sd Socket descriptor (handle) + \param[out] addr The argument addr is a pointer + to a SlNetSock_Addr_t structure. This + structure is filled in with the + address of the peer socket, as + known to the communications + layer. The exact format of the + address returned addr is + determined by the socket's + address\n + SlNetSock_Addr_t:\n - code for the + address format.\n - + socket address, the length + depends on the code format + \param[out] addrlen The addrlen argument is a value-result + argument: it should initially contain the + size of the structure pointed to by addr + + \return Zero on success, or negative on failure. + + \slnetsock_init_precondition + + \remark If the provided buffer is too small the returned address + will be truncated and \c addrlen will contain the + actual size of the socket address. + + \sa SlNetSock_create() + \sa SlNetSock_bind() +*/ +int32_t SlNetSock_getSockName(int16_t sd, SlNetSock_Addr_t *addr, SlNetSocklen_t *addrlen); + + +/*! + \brief Monitor socket activity + + SlNetSock_select() allow a program to monitor multiple file descriptors, + waiting until one or more of the file descriptors become + "ready" for some class of I/O operation. + + \param[in] nsds The highest-numbered file descriptor in any of the + three sets, plus 1. + \param[in,out] readsds Socket descriptors list for read monitoring and accept monitoring + \param[in,out] writesds Socket descriptors list for connect monitoring only, write monitoring is not supported + \param[in,out] exceptsds Socket descriptors list for exception monitoring, not supported. + \param[in] timeout Is an upper bound on the amount of time elapsed + before SlNetSock_select() returns. Null or above 0xffff seconds means + infinity timeout. The minimum timeout is 10 milliseconds, + less than 10 milliseconds will be set automatically to 10 milliseconds. + Max microseconds supported is 0xfffc00. + In trigger mode the timeout fields must be set to zero. + + \return On success, SlNetSock_select() returns the number of + file descriptors contained in the three returned + descriptor sets (that is, the total number of bits that + are set in readsds, writesds, exceptsds) which may be + zero if the timeout expires before anything interesting + happens.\n On error, a negative value is returned. + readsds - return the sockets on which Read request will + return without delay with valid data.\n + writesds - return the sockets on which Write request + will return without delay.\n + exceptsds - return the sockets closed recently. \n + #SLNETERR_BSD_ENOMEM may be return in case there are no resources in the system + + \slnetsock_init_precondition + + \remark If \c timeout is set to less than 10ms it will + automatically set to 10ms to prevent overload of the + system + + \sa SlNetSock_create() +*/ +int32_t SlNetSock_select(int16_t nsds, SlNetSock_SdSet_t *readsds, SlNetSock_SdSet_t *writesds, SlNetSock_SdSet_t *exceptsds, SlNetSock_Timeval_t *timeout); + + +/*! + \brief SlNetSock_select's SlNetSock_SdSet_t SET function + + Sets current socket descriptor on SlNetSock_SdSet_t container +*/ +int32_t SlNetSock_sdsSet(int16_t sd, SlNetSock_SdSet_t *sdset); + + +/*! + \brief SlNetSock_select's SlNetSock_SdSet_t CLR function + + Clears current socket descriptor on SlNetSock_SdSet_t container +*/ +int32_t SlNetSock_sdsClr(int16_t sd, SlNetSock_SdSet_t *sdset); + + +/*! + \brief SlNetSock_select's SlNetSock_SdSet_t ZERO function + + Clears all socket descriptors from SlNetSock_SdSet_t +*/ +int32_t SlNetSock_sdsClrAll(SlNetSock_SdSet_t *sdset); + + +/*! + \brief SlNetSock_select's SlNetSock_SdSet_t ISSET function + + Checks if current socket descriptor is set (true/false) + + \return Returns true if set, false if unset + +*/ +int32_t SlNetSock_sdsIsSet(int16_t sd, SlNetSock_SdSet_t *sdset); + + +/*! + \brief Set socket options + + SlNetSock_setOpt() manipulates the options associated with a socket. + + Options may exist at multiple protocol levels; they are always + present at the uppermost socket level. + + When manipulating socket options the level at which the option resides + and the name of the option must be specified. To manipulate options at + the socket level, level is specified as #SLNETSOCK_LVL_SOCKET. To manipulate + options at any other level the protocol number of the appropriate protocol + controlling the option is supplied. For example, to indicate that an + option is to be interpreted by the TCP protocol, level should be set to + the protocol number of TCP. + + \c optval and \c optlen are used to access opt_values + for SlNetSock_setOpt(). For SlNetSock_getOpt() they identify a + buffer in which the value for the requested option(s) are to + be returned. For SlNetSock_getOpt(), \c optlen is a value-result + parameter, initially containing the size of the buffer + pointed to by option_value, and modified on return to + indicate the actual size of the value returned. If no option + value is to be supplied or returned, \c optval may be \c NULL. + + \param[in] sd Socket descriptor (handle) + \param[in] level Defines the protocol level for this option + - #SLNETSOCK_LVL_SOCKET - Socket level configurations (L4, transport layer) + - #SLNETSOCK_LVL_IP - IP level configurations (L3, network layer) + - #SLNETSOCK_LVL_PHY - Link level configurations (L2, link layer) + \param[in] optname Defines the option name to interrogate + - #SLNETSOCK_LVL_SOCKET + - #SLNETSOCK_OPSOCK_RCV_BUF\n + Sets tcp max recv window size.\n + This options takes SlNetSock_Winsize_t struct as parameter + - #SLNETSOCK_OPSOCK_RCV_TIMEO\n + Sets the timeout value that specifies the maximum amount of time an input function waits until it completes.\n + Default: No timeout\n + This options takes SlNetSock_Timeval_t struct as parameter + - #SLNETSOCK_OPSOCK_KEEPALIVE\n + Enable or Disable periodic keep alive. + Keeps TCP connections active by enabling the periodic transmission of messages \n + Timeout is 5 minutes.\n + Default: Enabled \n + This options takes SlNetSock_Keepalive_t struct as parameter + - #SLNETSOCK_OPSOCK_KEEPALIVE_TIME\n + Set keep alive timeout. + Value is in seconds \n + Default: 5 minutes \n + - #SLNETSOCK_OPSOCK_LINGER\n + Socket lingers on close pending remaining send/receive packets\n + - #SLNETSOCK_OPSOCK_NON_BLOCKING\n + Sets socket to non-blocking operation Impacts: connect, accept, send, sendto, recv and recvfrom. \n + Default: Blocking. + This options takes SlNetSock_Nonblocking_t struct as parameter + - #SLNETSOCK_OPSOCK_NON_IP_BOUNDARY\n + Enable or Disable rx ip boundary. + In connectionless socket (udp/raw), unread data is dropped (when SlNetSock_recvFrom() len parameter < data size), Enable this option in order to read the left data on the next SlNetSock_recvFrom() iteration\n + Default: Disabled, IP boundary kept\n + This options takes SlNetSock_NonIpBoundary_t struct as parameter + - #SLNETSOCK_LVL_IP + - #SLNETSOCK_OPIP_MULTICAST_TTL\n + Set the time-to-live value of outgoing multicast packets for this socket. \n + This options takes uint8_t as parameter + - #SLNETSOCK_OPIP_ADD_MEMBERSHIP \n + UDP socket, Join a multicast group. \n + This options takes SlNetSock_IpMreq_t struct as parameter + - #SLNETSOCK_OPIP_DROP_MEMBERSHIP \n + UDP socket, Leave a multicast group \n + This options takes SlNetSock_IpMreq_t struct as parameter + - #SLNETSOCK_OPIP_HDRINCL \n + RAW socket only, the IPv4 layer generates an IP header when sending a packet unless \n + the IP_HDRINCL socket option is enabled on the socket. \n + When it is enabled, the packet must contain an IP header. \n + Default: disabled, IPv4 header generated by Network Stack \n + This options takes uint32_t as parameter + - #SLNETSOCK_OPIP_RAW_RX_NO_HEADER \n + Raw socket remove IP header from received data. \n + Default: data includes ip header \n + This options takes uint32_t as parameter + - #SLNETSOCK_OPIP_RAW_IPV6_HDRINCL (inactive) \n + RAW socket only, the IPv6 layer generates an IP header when sending a packet unless \n + the IP_HDRINCL socket option is enabled on the socket. When it is enabled, the packet must contain an IP header \n + Default: disabled, IPv4 header generated by Network Stack \n + This options takes uint32_t as parameter + - #SLNETSOCK_LVL_PHY + - #SLNETSOCK_OPPHY_CHANNEL \n + Sets channel in transceiver mode. + This options takes uint32_t as channel number parameter + - #SLNETSOCK_OPPHY_RATE \n + RAW socket, set WLAN PHY transmit rate \n + The values are based on SlWlanRateIndex_e \n + This options takes uint32_t as parameter + - #SLNETSOCK_OPPHY_TX_POWER \n + RAW socket, set WLAN PHY TX power \n + Valid rage is 1-15 \n + This options takes uint32_t as parameter + - #SLNETSOCK_OPPHY_NUM_FRAMES_TO_TX \n + RAW socket, set number of frames to transmit in transceiver mode. + Default: 1 packet + This options takes uint32_t as parameter + - #SLNETSOCK_OPPHY_PREAMBLE \n + RAW socket, set WLAN PHY preamble for Long/Short\n + This options takes uint32_t as parameter + - #SLNETSOCK_OPPHY_TX_INHIBIT_THRESHOLD \n + RAW socket, set WLAN Tx - Set CCA threshold. \n + The values are based on SlNetSockTxInhibitThreshold_e \n + This options takes uint32_t as parameter + - #SLNETSOCK_OPPHY_TX_TIMEOUT \n + RAW socket, set WLAN Tx - changes the TX timeout (lifetime) of transceiver frames. \n + Value in Ms, maximum value is 10ms \n + This options takes uint32_t as parameter + - #SLNETSOCK_OPPHY_ALLOW_ACKS \n + RAW socket, set WLAN Tx - Enable or Disable sending ACKs in transceiver mode \n + 0 = disabled / 1 = enabled \n + This options takes uint32_t as parameter + - #SLNETSOCK_PROTO_TCP + - #SLNETSOCK_TCP_NODELAY \n + Disables TCP send delay/coalesce algorithm. \n + This option takes SLNetSock_NoDelay_t struct as a parameter. + - #SLNETSOCK_TCP_MAXSEG \n + Set the maximum TCP segment size \n + This option takes SLNetSock_MaxSeg_t struct as a parameter. + - #SLNETSOCK_TCP_NOPUSH \n + Do not send data just to finish a data block (attempt to coalesce). \n + This option takes SLNetSock_NoPush_t struct as a parameter + - #SLNETSOCK_TCP_NOOPT \n + Do not use TCP options. \n + This option takes SLNetSock_NoOpt_t struct as a parameter. + - #SLNETSOCK_TCP_SACKPERMITTED \n + Permit RFC-2018 Selective Acknowledgment(SACK) conformant connection + This option takes SLNetSock_SackPermitted_t struct as a parameter + - #SLNETSOCK_TCP_MAXRTT \n + The maximum TCP Round Trip Time value allowed in the determination of the estimated TCP RTT. \n + This option takes SLNetSock_MaxRtt_t struct as a parameter + + \param[in] optval Specifies a value for the option + \param[in] optlen Specifies the length of the + option value + + \return Zero on success, or negative error code on failure + + \par Persistent + All params are Non- Persistent + + \slnetsock_init_precondition + + \par Examples + + - SLNETSOCK_OPSOCK_RCV_BUF: + \code + SlNetSock_Winsize_t size; + size.winsize = 3000; // bytes + SlNetSock_setOpt(SockID, SLNETSOCK_LVL_SOCKET, SLNETSOCK_OPSOCK_RCV_BUF, (uint8_t *)&size, sizeof(size)); + \endcode +
+ + - SLNETSOCK_OPSOCK_RCV_TIMEO: + \code + struct SlNetSock_Timeval_t timeVal; + timeVal.tv_sec = 1; // Seconds + timeVal.tv_usec = 0; // Microseconds. 10000 microseconds resolution + SlNetSock_setOpt(SockID, SLNETSOCK_LVL_SOCKET, SLNETSOCK_OPSOCK_RCV_TIMEO, (uint8_t *)&timeVal, sizeof(timeVal)); // Enable receive timeout + \endcode +
+ + - SLNETSOCK_OPSOCK_KEEPALIVE: //disable Keepalive + \code + SlNetSock_Keepalive_t enableOption; + enableOption.keepaliveEnabled = 0; + SlNetSock_setOpt(SockID, SLNETSOCK_LVL_SOCKET, SLNETSOCK_OPSOCK_KEEPALIVE, (uint8_t *)&enableOption, sizeof(enableOption)); + \endcode +
+ + - SLNETSOCK_OPSOCK_KEEPALIVE_TIME: //Set Keepalive timeout + \code + int16_t Status; + uint32_t TimeOut = 120; + SlNetSock_setOpt(Sd, SLNETSOCK_LVL_SOCKET, SLNETSOCK_OPSOCK_KEEPALIVE_TIME, (uint8_t *)&TimeOut, sizeof(TimeOut)); + \endcode +
+ + - SLNETSOCK_OPSOCK_NON_BLOCKING: //Enable or disable nonblocking mode + \code + SlNetSock_Nonblocking_t enableOption; + enableOption.nonBlockingEnabled = 1; + SlNetSock_setOpt(SockID, SLNETSOCK_LVL_SOCKET, SLNETSOCK_OPSOCK_NON_BLOCKING, (uint8_t *)&enableOption, sizeof(enableOption)); + \endcode +
+ + - SLNETSOCK_OPSOCK_NON_IP_BOUNDARY: //disable boundary + \code + SlNetSock_NonIpBoundary_t enableOption; + enableOption.nonIpBoundaryEnabled = 1; + SlNetSock_setOpt(SockID, SLNETSOCK_LVL_SOCKET, SLNETSOCK_OPSOCK_NON_IP_BOUNDARY, (uint8_t *)&enableOption, sizeof(enableOption)); + \endcode +
+ + - SLNETSOCK_OPSOCK_LINGER: + \code + SlNetSock_linger_t linger; + linger.l_onoff = 1; + linger.l_linger = 10; + SlNetSock_setOpt(SockID, SLNETSOCK_LVL_SOCKET, SLNETSOCK_OPSOCK_LINGER, &linger, sizeof(linger)); + \endcode +
+ + - SLNETSOCK_OPIP_MULTICAST_TTL: + \code + uint8_t ttl = 20; + SlNetSock_setOpt(SockID, SLNETSOCK_LVL_IP, SLNETSOCK_OPIP_MULTICAST_TTL, &ttl, sizeof(ttl)); + \endcode +
+ + - SLNETSOCK_OPIP_ADD_MEMBERSHIP: + \code + SlNetSock_IpMreq_t mreq; + SlNetSock_setOpt(SockID, SLNETSOCK_LVL_IP, SLNETSOCK_OPIP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)); + \endcode +
+ + - SLNETSOCK_OPIP_DROP_MEMBERSHIP: + \code + SlNetSock_IpMreq_t mreq; + SlNetSock_setOpt(SockID, SLNETSOCK_LVL_IP, SLNETSOCK_OPIP_DROP_MEMBERSHIP, &mreq, sizeof(mreq)); + \endcode +
+ + - SLNETSOCK_OPIP_RAW_RX_NO_HEADER: + \code + uint32_t header = 1; // remove ip header + SlNetSock_setOpt(SockID, SLNETSOCK_LVL_IP, SLNETSOCK_OPIP_RAW_RX_NO_HEADER, &header, sizeof(header)); + \endcode +
+ + - SLNETSOCK_OPIP_HDRINCL: + \code + uint32_t header = 1; + SlNetSock_setOpt(SockID, SLNETSOCK_LVL_IP, SLNETSOCK_OPIP_HDRINCL, &header, sizeof(header)); + \endcode +
+ + - SLNETSOCK_OPIP_RAW_IPV6_HDRINCL: + \code + uint32_t header = 1; + SlNetSock_setOpt(SockID, SLNETSOCK_LVL_IP, SLNETSOCK_OPIP_RAW_IPV6_HDRINCL, &header, sizeof(header)); + \endcode +
+ + - SLNETSOCK_OPPHY_CHANNEL: + \code + uint32_t newChannel = 6; // range is 1-13 + SlNetSock_setOpt(SockID, SLNETSOCK_LVL_SOCKET, SLNETSOCK_OPPHY_CHANNEL, &newChannel, sizeof(newChannel)); + \endcode +
+ + - SLNETSOCK_OPPHY_RATE: + \code + uint32_t rate = 6; // see wlan.h SlWlanRateIndex_e for values + SlNetSock_setOpt(SockID, SLNETSOCK_LVL_PHY, SLNETSOCK_OPPHY_RATE, &rate, sizeof(rate)); + \endcode +
+ + - SLNETSOCK_OPPHY_TX_POWER: + \code + uint32_t txpower = 1; // valid range is 1-15 + SlNetSock_setOpt(SockID, SLNETSOCK_LVL_PHY, SLNETSOCK_OPPHY_TX_POWER, &txpower, sizeof(txpower)); + \endcode +
+ + - SLNETSOCK_OPPHY_NUM_FRAMES_TO_TX: + \code + uint32_t numframes = 1; + SlNetSock_setOpt(SockID, SLNETSOCK_LVL_PHY, SLNETSOCK_OPPHY_NUM_FRAMES_TO_TX, &numframes, sizeof(numframes)); + \endcode +
+ + - SLNETSOCK_OPPHY_PREAMBLE: + \code + uint32_t preamble = 1; + SlNetSock_setOpt(SockID, SLNETSOCK_LVL_PHY, SLNETSOCK_OPPHY_PREAMBLE, &preamble, sizeof(preamble)); + \endcode +
+ + - SLNETSOCK_OPPHY_TX_INHIBIT_THRESHOLD: + \code + uint32_t thrshld = SLNETSOCK_TX_INHIBIT_THRESHOLD_MED; + SlNetSock_setOpt(SockID, SLNETSOCK_LVL_PHY, SLNETSOCK_OPPHY_TX_INHIBIT_THRESHOLD, &thrshld, sizeof(thrshld)); + \endcode +
+ + - SLNETSOCK_OPPHY_TX_TIMEOUT: + \code + uint32_t timeout = 50; + SlNetSock_setOpt(SockID, SLNETSOCK_LVL_PHY, SLNETSOCK_OPPHY_TX_TIMEOUT, &timeout, sizeof(timeout)); + \endcode +
+ + - SLNETSOCK_OPPHY_ALLOW_ACKS: + \code + uint32_t acks = 1; // 0 = disabled / 1 = enabled + SlNetSock_setOpt(SockID, SLNETSOCK_LVL_PHY, SLNETSOCK_OPPHY_ALLOW_ACKS, &acks, sizeof(acks)); + \endcode + + \sa slNetSock_create() + \sa SlNetSock_getOpt() +*/ +int32_t SlNetSock_setOpt(int16_t sd, int16_t level, int16_t optname, void *optval, SlNetSocklen_t optlen); + + +/*! + \brief Get socket options + + The SlNetSock_getOpt function gets the options associated with a socket. + Options may exist at multiple protocol levels; they are always + present at the uppermost socket level. + + The parameters optval and optlen identify a + buffer in which the value for the requested option(s) are to + be returned. \c optlen is a value-result + parameter, initially containing the size of the buffer + pointed to by option_value, and modified on return to + indicate the actual size of the value returned. If no option + value is to be supplied or returned, \c optval may be \c NULL. + + + \param[in] sd Socket descriptor (handle) + \param[in] level Defines the protocol level for this option + \param[in] optname defines the option name to interrogate + \param[out] optval Specifies a value for the option + \param[out] optlen Specifies the length of the + option value + + \return Zero on success, or negative error code on failure + + \slnetsock_init_precondition + + \sa SlNetSock_create() + \sa SlNetSock_setOpt() +*/ +int32_t SlNetSock_getOpt(int16_t sd, int16_t level, int16_t optname, void *optval, SlNetSocklen_t *optlen); + + +/*! + \brief Read data from TCP socket + + The SlNetSock_recv function receives a message from a connection-mode socket + + \param[in] sd Socket descriptor (handle) + \param[out] buf Points to the buffer where the + message should be stored. + \param[in] len Specifies the length in bytes of + the buffer pointed to by the buffer argument. + Range: 1-16000 bytes + \param[in] flags Specifies the type of message + reception. On this version, this parameter is not + supported. + + \return Return the number of bytes received, + or a negative value if an error occurred.\n + Using a non-blocking recv a possible negative value is #SLNETERR_BSD_EAGAIN.\n + #SLNETERR_BSD_ENOMEM may be return in case there are no resources in the system + + \slnetsock_init_precondition + + \par Examples + \snippet ti/net/test/snippets/slnetif.c SlNetSock_recv snippet + + \sa SlNetSock_create() + \sa SlNetSock_recvFrom() +*/ +int32_t SlNetSock_recv(int16_t sd, void *buf, uint32_t len, uint32_t flags); + + +/*! + \brief Read data from socket + + SlNetSock_recvFrom function receives a message from a connection-mode or + connectionless-mode socket + + \param[in] sd Socket descriptor (handle) + \param[out] buf Points to the buffer where the message should be stored. + \param[in] len Specifies the length in bytes of the buffer pointed to by the buffer argument. + Range: 1-16000 bytes + \param[in] flags Specifies the type of message + reception. On this version, this parameter is not + supported + \param[in] from Pointer to an address structure + indicating the source + address.\n sockaddr:\n - code + for the address format.\n - socket address, + the length depends on the code + format + \param[in] fromlen Source address structure + size. This parameter MUST be set to the size of the structure pointed to by addr. + + + \return Return the number of bytes received, + or a negative value if an error occurred.\n + Using a non-blocking recv a possible negative value is #SLNETERR_BSD_EAGAIN. + #SLNETERR_RET_CODE_INVALID_INPUT will be returned if fromlen has incorrect length.\n + #SLNETERR_BSD_ENOMEM may be return in case there are no resources in the system + + \slnetsock_init_precondition + + \par Example + \snippet ti/net/test/snippets/slnetif.c SlNetSock_recvFrom snippet + + \sa SlNetSock_create() + \sa SlNetSock_recv() +*/ +int32_t SlNetSock_recvFrom(int16_t sd, void *buf, uint32_t len, uint32_t flags, SlNetSock_Addr_t *from, SlNetSocklen_t *fromlen); + + +/*! + \brief Write data to TCP socket + + Transmits a message to another socket. + Returns immediately after sending data to device. + In case of a RAW socket (transceiver mode), extra 4 bytes should be reserved at the end of the + frame data buffer for WLAN FCS + + \param[in] sd Socket descriptor (handle) + \param[in] buf Points to a buffer containing + the message to be sent + \param[in] len Message size in bytes. + \param[in] flags Specifies the type of message + transmission. On this version, this parameter is not + supported for TCP. + + \return Return the number of bytes sent, + or a negative value if an error occurred. + + \slnetsock_init_precondition + + \par Example + \snippet ti/net/test/snippets/slnetif.c SlNetSock_send snippet + + \sa SlNetSock_create() + \sa SlNetSock_sendTo() +*/ +int32_t SlNetSock_send(int16_t sd, const void *buf, uint32_t len, uint32_t flags); + + +/*! + \brief Write data to socket + + The SlNetSock_sendTo function is used to transmit a message on a connectionless socket + (connection less socket #SLNETSOCK_SOCK_DGRAM, #SLNETSOCK_SOCK_RAW). + + Returns immediately after sending data to device. + + \param[in] sd Socket descriptor (handle) + \param[in] buf Points to a buffer containing + the message to be sent + \param[in] len message size in bytes. + \param[in] flags Specifies the type of message + transmission. On this version, this parameter is not + supported + \param[in] to Pointer to an address structure + indicating the destination + address.\n sockaddr:\n - code + for the address format.\n - socket address, + the length depends on the code + format + \param[in] tolen Destination address structure size + + \return Return the number of bytes sent, + or a negative value if an error occurred.\n + + \slnetsock_init_precondition + + \par Example + \snippet ti/net/test/snippets/slnetif.c SlNetSock_sendTo snippet + + \sa SlNetSock_create() + \sa SlNetSock_send() +*/ +int32_t SlNetSock_sendTo(int16_t sd, const void *buf, uint32_t len, uint32_t flags, const SlNetSock_Addr_t *to, SlNetSocklen_t tolen); + + +/*! + \brief Get interface ID from socket descriptor (sd) + + \param[in] sd Specifies the socket descriptor which its + interface identifier needs to be retrieved.\n + + \return The interface identifier value of the + interface on success, or negative error code + on failure. The values of the interface + identifier is defined with the prefix + @c SLNETIF_ID_ in slnetif.h. + + \slnetsock_init_precondition + + \par Examples + \snippet ti/net/test/snippets/slnetif.c SlNetSock_getIfID snippet + + \sa SlNetSock_create() + \sa SlNetIf_add() + \sa SlNetIf_getIDByName() +*/ +int32_t SlNetSock_getIfID(uint16_t sd); + + +/*! + \brief Creates a security attributes object + + Create a security attribute, which is required in order to start a secure session. + + \remark When the security attributes object is no longer needed, call + SlNetSock_secAttribDelete() to destroy it. + + \remark A single security object can be used to initiate several secure + sessions (provided they all have the same security attributes). + + \slnetsock_init_precondition + + \sa SlNetSock_startSec() + \sa SlNetSock_secAttribDelete() +*/ +SlNetSockSecAttrib_t *SlNetSock_secAttribCreate(void); + + +/*! + \brief Deletes a security attributes object + + \param[in] secAttrib Secure attribute handle + + \return Zero on success, or negative error code + on failure + + \slnetsock_init_precondition + + \remark \c secAttrib must be created using SlNetSock_secAttribCreate() + + \sa SlNetSock_secAttribCreate() + \sa SlNetSock_secAttribSet() + \sa SlNetSock_startSec() +*/ +int32_t SlNetSock_secAttribDelete(SlNetSockSecAttrib_t *secAttrib); + + +/*! + \brief set a security attribute + + The SlNetSock_secAttribSet function is used to set a security + attribute of a security attribute object. + + \param[in] secAttrib Secure attribute handle + \param[in] attribName Define the actual attribute to set. Applicable values: + - #SLNETSOCK_SEC_ATTRIB_PRIVATE_KEY \n + Sets the private key corresponding to the local certificate \n + This attribute takes the name of security object containing the private key and the name's length (including the NULL terminating character) as parameters \n + - #SLNETSOCK_SEC_ATTRIB_LOCAL_CERT \n + Sets the local certificate chain \n + This attribute takes the name of the security object containing the certificate and the name's length (including the NULL terminating character) as parameters \n + For certificate chains, each certificate in the chain can be added via a separate call to SlNetSock_secAttribSet, starting with the root certificate of the chain \n + - #SLNETSOCK_SEC_ATTRIB_PEER_ROOT_CA \n + Sets the root CA certificate \n + This attribute takes the name of the security object containing the certificate and the name's length (including the NULL terminating character) as parameters \n + - #SLNETSOCK_SEC_ATTRIB_DH_KEY \n + Sets the DH Key \n + This attribute takes the name of the security object containing the DH Key and the name's length (including the NULL terminating character) as parameters \n + - #SLNETSOCK_SEC_ATTRIB_METHOD \n + Sets the TLS protocol version \n + This attribute takes a SLNETSOCK_SEC_METHOD_* option and sizeof(uint8_t) as parameters \n + - #SLNETSOCK_SEC_ATTRIB_CIPHERS \n + Sets the ciphersuites to be used for the connection \n + This attribute takes a bit mask formed using SLNETSOCK_SEC_CIPHER_* options and sizeof(uint32_t) as parameters \n + - #SLNETSOCK_SEC_ATTRIB_ALPN \n + Sets the ALPN \n + This attribute takes a bit mask formed using SLNETSOCK_SEC_ALPN_* options and sizeof(uint32_t) as parameters \n + - #SLNETSOCK_SEC_ATTRIB_EXT_CLIENT_CHLNG_RESP \n + Sets the EXT CLIENT CHLNG RESP \n + Format TBD \n + - #SLNETSOCK_SEC_ATTRIB_DOMAIN_NAME \n + Sets the domain name for verification during connection \n + This attribute takes a string with the domain name and the string's length (including the NULL-terminating character) as parameters \n + - #SLNETSOCK_SEC_ATTRIB_DISABLE_CERT_STORE\n + Sets whether to disable the certificate store \n + This attribute takes 1 (disable) or 0 (enable) and sizeof(uint32_t) as parameters \n + + \param[in] val + \param[in] len + + \return Zero on success, or negative error code + on failure + + \slnetsock_init_precondition + + \note Once an attribute is set, it cannot be unset or set to something + different. Doing so may result in undefined behavior. + Instead, SlNetSock_secAttribDelete() should be called on the + existing object, and a new security object should be created with + the new attribute set. + + \note The #SLNETSOCK_SEC_ATTRIB_DISABLE_CERT_STORE value + is currently being evaluated, and may be removed in a + future release. It is currently only supported on CC3xxx + devices. + + \par Examples + + - SLNETSOCK_SEC_ATTRIB_PRIVATE_KEY: + \code + #define PRIVATE_KEY_FILE "DummyKey" + SlNetIf_loadSecObj(SLNETIF_SEC_OBJ_TYPE_RSA_PRIVATE_KEY, PRIVATE_KEY_FILE, strlen(PRIVATE_KEY_FILE), srvKeyPem, srvKeyPemLen, SLNETIF_ID_2); + SlNetSock_secAttribSet(secAttrib, SLNETSOCK_SEC_ATTRIB_PRIVATE_KEY, PRIVATE_KEY_FILE, sizeof(PRIVATE_KEY_FILE)); + \endcode +
+ + - SLNETSOCK_SEC_ATTRIB_LOCAL_CERT: + \code + #define ROOT_CA_CERT_FILE "DummyCA" + #define TRUSTED_CERT_FILE "DummyTrustedCert" + + // create a local certificate chain + SlNetIf_loadSecObj(SLNETIF_SEC_OBJ_TYPE_CERTIFICATE, ROOT_CA_CERT_FILE, strlen(ROOT_CA_CERT_FILE), srvCAPem, srvCAPemLen, SLNETIF_ID_2); + SlNetIf_loadSecObj(SLNETIF_SEC_OBJ_TYPE_CERTIFICATE, TRUSTED_CERT_FILE, strlen(TRUSTED_CERT_FILE), srvCertPem, srvCertPemLen, SLNETIF_ID_2); + SlNetSock_secAttribSet(secAttrib, SLNETSOCK_SEC_ATTRIB_LOCAL_CERT, ROOT_CA_CERT_FILE, sizeof(ROOT_CA_CERT_FILE)); + SlNetSock_secAttribSet(secAttrib, SLNETSOCK_SEC_ATTRIB_LOCAL_CERT, TRUSTED_CERT_FILE, sizeof(TRUSTED_CERT_FILE)); + \endcode +
+ + - SLNETSOCK_SEC_ATTRIB_PEER_ROOT_CA: + \code + #define ROOT_CA_CERT_FILE "DummyCA" + SlNetIf_loadSecObj(SLNETIF_SEC_OBJ_TYPE_CERTIFICATE, ROOT_CA_CERT_FILE, strlen(ROOT_CA_CERT_FILE), srvCAPem, srvCAPemLen, SLNETIF_ID_2); + SlNetSock_secAttribSet(secAttrib, SLNETSOCK_SEC_ATTRIB_PEER_ROOT_CA, ROOT_CA_CERT_FILE, sizeof(ROOT_CA_CERT_FILE)); + \endcode +
+ + - SLNETSOCK_SEC_ATTRIB_METHOD: + \code + uint8_t SecurityMethod = SLNETSOCK_SEC_METHOD_SSLV3; + SlNetSock_secAttribSet(secAttrib, SLNETSOCK_SEC_ATTRIB_METHOD, (void *)&(SecurityMethod), sizeof(SecurityMethod)); + \endcode +
+ + - SLNETSOCK_SEC_ATTRIB_CIPHERS: + \code + uint32_t SecurityCipher = SLNETSOCK_SEC_CIPHER_SSL_RSA_WITH_RC4_128_SHA | SLNETSOCK_SEC_CIPHER_TLS_RSA_WITH_AES_256_CBC_SHA; + SlNetSock_secAttribSet(secAttrib, SLNETSOCK_SEC_ATTRIB_METHOD, (void *)&(SecurityCipher), sizeof(SecurityCipher)); + \endcode +
+ + - SLNETSOCK_SEC_ATTRIB_DOMAIN_NAME: + \code + char addr[] = "www.ti.com"; + SlNetSock_secAttribSet(secAttrib, SLNETSOCK_SEC_ATTRIB_DOMAIN_NAME, (void *)addr, strlen(addr) + 1); + \endcode +
+ + + \sa SlNetSock_secAttribCreate() +*/ +int32_t SlNetSock_secAttribSet(SlNetSockSecAttrib_t *secAttrib, SlNetSockSecAttrib_e attribName, void *val, uint16_t len); + + +/*! + \brief Start a security session on an opened socket + + \param[in] sd Socket descriptor (handle) + \param[in] secAttrib Secure attribute handle. This can be NULL only + if the SLNETSOCK_SEC_BIND_CONTEXT_ONLY flag is + not thrown. + \param[in] flags Specifies flags. \n + The available flags are: + - #SLNETSOCK_SEC_START_SECURITY_SESSION_ONLY + - #SLNETSOCK_SEC_BIND_CONTEXT_ONLY + - #SLNETSOCK_SEC_IS_SERVER + + \return Zero on success, or negative error code + on failure + + \slnetsock_init_precondition + + \remark If the return value indicates failure, the socket should be + closed. + + \remark If \c secAttrib is \c NULL, the session will be started with + default security settings. + + \sa SlNetSock_create() + \sa SlNetSock_secAttribCreate() +*/ +int32_t SlNetSock_startSec(int16_t sd, SlNetSockSecAttrib_t *secAttrib, uint8_t flags); + + +/*! + + Close the Doxygen group. + @} + +*/ + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __NET_SOCK_H__ */ diff --git a/simplelink/source/ti/net/slnetutils.c b/simplelink/source/ti/net/slnetutils.c new file mode 100644 index 0000000..4a987fd --- /dev/null +++ b/simplelink/source/ti/net/slnetutils.c @@ -0,0 +1,1533 @@ +/* + * Copyright (c) 2017-2018, Texas Instruments Incorporated + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of Texas Instruments Incorporated nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/*****************************************************************************/ +/* Include files */ +/*****************************************************************************/ + +#include /* needed? */ +#include +#include + +#include +#include +#include + +/*****************************************************************************/ +/* Macro declarations */ +/*****************************************************************************/ + +#define SLNETUTIL_NORMALIZE_NEEDED 0 +#if SLNETUTIL_NORMALIZE_NEEDED + #define SLNETUTIL_NORMALIZE_RET_VAL(retVal,err) ((retVal < 0)?(retVal = err):(retVal)) +#else + #define SLNETUTIL_NORMALIZE_RET_VAL(retVal,err) +#endif + +/* Size needed for getaddrinfo mem allocation */ +#define SLNETUTIL_ADDRINFO_ALLOCSZ ((sizeof(SlNetUtil_addrInfo_t)) + \ + (sizeof(SlNetSock_AddrIn6_t))) + +/* Cap number of mem allocations in case of large number of results from DNS */ +#define SLNETUTIL_ADDRINFO_MAX_DNS_NODES 10 + +#define SLNETUTIL_DNSBUFSIZE ((SLNETUTIL_ADDRINFO_MAX_DNS_NODES) * \ + (sizeof(uint32_t))) + +#define LL_PREFIX 0xFE80 + +/*****************************************************************************/ +/* Structure/Enum declarations */ +/*****************************************************************************/ + + +/*****************************************************************************/ +/* Function prototypes */ +/*****************************************************************************/ + +static int32_t SlNetUtil_UTOA(uint16_t value, char * string, uint16_t base); +static int32_t SlNetUtil_bin2StrIpV4(SlNetSock_InAddr_t *binaryAddr, char *strAddr, uint16_t strAddrLen); +static int32_t SlNetUtil_bin2StrIpV6(SlNetSock_In6Addr_t *binaryAddr, char *strAddr, uint16_t strAddrLen); +static int32_t SlNetUtil_strTok(char **string, char *returnstring, int retstringlength, const char *delimiter); +static int32_t SlNetUtil_str2BinIpV4(char *strAddr, SlNetSock_InAddr_t *binaryAddr); +static int32_t SlNetUtil_str2BinIpV6(char *strAddr, SlNetSock_In6Addr_t *binaryAddr); + +/* Local SlNetUtil_getAddrInfo utility functions */ +static SlNetUtil_addrInfo_t *setAddrInfo(uint16_t ifID, SlNetSock_Addr_t *addr, + int family, const char *service, const SlNetUtil_addrInfo_t *hints); + +static SlNetUtil_addrInfo_t *createAddrInfo(uint16_t ifID, + SlNetSock_Addr_t *addr, int family, const char *service, int flags, + int socktype, int protocol); + +static int mergeLists(SlNetUtil_addrInfo_t **curList, + SlNetUtil_addrInfo_t **newList); + +//***************************************************************************** +// +// SlNetUtil_init - Initialize the slnetutil module +// +//***************************************************************************** +int32_t SlNetUtil_init(int32_t flags) +{ + return 0; +} + + +//***************************************************************************** +// SlNetUtil_gaiStrErr +//***************************************************************************** + +/* + * Error codes for gai_strerror + * The order of this array MUST match the numbering of the SLNETUTIL_EAI_CODE + * defines in + */ +static const char *strErrorMsgs[] = +{ + "Temporary failure in name resolution", /* SLNETUTIL_EAI_AGAIN */ + "Bad value for ai_flags", /* SLNETUTIL_EAI_BADFLAGS */ + "Non-recoverable failure in name resolution", /* SLNETUTIL_EAI_FAIL */ + "ai_family not supported", /* SLNETUTIL_EAI_FAMILY */ + "Memory allocation failure", /* SLNETUTIL_EAI_MEMORY */ + "Node or service not known, " /* SLNETUTIL_EAI_NONAME */ + "or both node and service are NULL", + "Service (port number) not supported " /* SLNETUTIL_EAI_SERVICE */ + "for ai_socktype", + "ai_socktype not supported", /* SLNETUTIL_EAI_SOCKTYPE */ + "System error", /* SLNETUTIL_EAI_SYSTEM */ + "An argument buffer overflowed", /* SLNETUTIL_EAI_OVERFLOW */ + "Address family for node not supported" /* SLNETUTIL_EAI_ADDRFAMILY */ +}; + +const char *SlNetUtil_gaiStrErr(int32_t errorCode) +{ + /* + * Error codes are negative starting with -3121 so + * ~(errorCode - SLNETUTIL_EAI_BASE) takes the one's compliment of the code + * minus the base of the error codes to convert the code into a positive + * value that matches the StrerrorMsgs array index. + */ + int msgsIndex = ~(errorCode - SLNETUTIL_EAI_BASE); + int msgsRange = sizeof(strErrorMsgs) / sizeof(strErrorMsgs[0]); + + if ((msgsIndex < msgsRange) && (msgsIndex >= 0)) + { + return strErrorMsgs[msgsIndex]; + } + else + { + return "Unknown error"; + } +} + +//***************************************************************************** +// +// SlNetUtil_getHostByName - Obtain the IP Address of machine on network, by +// machine name +// +//***************************************************************************** +int32_t SlNetUtil_getHostByName(uint32_t ifBitmap, char *name, const uint16_t nameLen, uint32_t *ipAddr, uint16_t *ipAddrLen, const uint8_t family) +{ + uint16_t origIpAddrLen; + SlNetIf_t *netIf; + int32_t retVal; + + /* When ifBitmap is 0, that means automatic selection of all interfaces + is required, enable all bits in ifBitmap */ + if (0 == ifBitmap) + { + ifBitmap = ~ifBitmap; + } + + /* + * Save original value of ipAddrLen. If DNS resolution fails, ipAddrLen + * will be overwritten with zero, which is problematic for next iteration + * of the while loop. + */ + origIpAddrLen = *ipAddrLen; + + /* This loop tries to run get host by name on the required interface + only if it in state enable and connected status + When multiple interfaces, in addition to the enable and connected it + will try to run the function on the interface from the highest + priority until an answer will return or until no interfaces left */ + do + { + /* Search for the highest priority interface according to the + ifBitmap and the queryFlags */ + netIf = SlNetIf_queryIf(ifBitmap, SLNETIF_QUERY_IF_STATE_BIT | SLNETIF_QUERY_IF_CONNECTION_STATUS_BIT); + + /* Check if the function returned NULL or the requested interface + exists */ + if ( (NULL == netIf) || ( NULL == (netIf->ifConf)->utilGetHostByName) ) + { + /* Interface doesn't exists, return error code */ + return SLNETERR_RET_CODE_INVALID_INPUT; + } + else + { + /* Disable the ifID bit from the ifBitmap after finding the netIf*/ + ifBitmap &= ~(netIf->ifID); + + /* Use SlNetUtil_inetPton to test if name is already an IP address. + If so, point ipAddr to the binary value of the IP and return */ + if (SlNetUtil_inetPton(family, name, ipAddr)) { + /* Convert ipAddr to host byte order as getHostByName requires + ipAddr to be in host byte order */ + *ipAddr = SlNetUtil_ntohl(*ipAddr); + + *ipAddrLen = 1; + return netIf->ifID; + } + + /* Interface exists, return interface IP address */ + retVal = (netIf->ifConf)->utilGetHostByName(netIf->ifContext, name, nameLen, ipAddr, ipAddrLen, family); + SLNETUTIL_NORMALIZE_RET_VAL(retVal, SLNETUTIL_ERR_UTILGETHOSTBYNAME_FAILED); + + /* Check retVal for error codes */ + if (retVal < SLNETERR_RET_CODE_OK) + { + /* + * utilGetHostByName failed. Restore the size of the ipAddr + * array and continue to the next ifID + */ + *ipAddrLen = origIpAddrLen; + continue; + } + else + { + /* Return success */ + return netIf->ifID; + } + } + }while ( ifBitmap > 0 ); + /* Interface doesn't exists, return error code */ + return SLNETERR_RET_CODE_INVALID_INPUT; +} + +//***************************************************************************** +// SlNetUtil_getAddrInfo +//***************************************************************************** +int32_t SlNetUtil_getAddrInfo(uint16_t ifID, const char *node, + const char *service, const struct SlNetUtil_addrInfo_t *hints, + struct SlNetUtil_addrInfo_t **res) +{ + int i; + int retval = 0; + int resolved = 0; + int numNodes = 0; + char *buffer = NULL; + char *currAddr = NULL; + uint16_t numIpAddrs; + int32_t selectedIfId; + int32_t ipv4DnsError = 0; + int32_t ipv6DnsError = 0; + + SlNetUtil_addrInfo_t *ai = NULL; + SlNetUtil_addrInfo_t *aiTmp = NULL; + SlNetSock_AddrIn_t sin; + SlNetSock_AddrIn6_t sin6; + + /* check args passed in for errors */ + if (!node && !service) { + /* Error: node and service args cannot both be NULL */ + return (SLNETUTIL_EAI_NONAME); + } + + if (!service) { + service = "0"; + } + + if (!res) { + /* Error: res cannot be NULL */ + return (SLNETUTIL_EAI_NONAME); + } + + if (!hints) { + /* User passed NULL hints. Create a hints for them with all 0 values */ + static const SlNetUtil_addrInfo_t defHints = { + 0, /* ai_flags */ + SLNETSOCK_AF_UNSPEC, /* ai_family */ + 0, /* ai_socktype */ + 0, /* ai_protocol */ + 0, /* ai_addrlen */ + NULL, /* ai_addr */ + NULL, /* ai_canonname */ + NULL /* ai_next */ + }; + hints = &defHints; + } + else { + /* Check the user's hints for invalid settings */ + if (hints->ai_socktype != SLNETSOCK_SOCK_STREAM && + hints->ai_socktype != SLNETSOCK_SOCK_DGRAM && + hints->ai_socktype != 0) { + /* Error: invalid or unknown socktype */ + return (SLNETUTIL_EAI_SOCKTYPE); + } + else if (hints->ai_protocol != SLNETSOCK_PROTO_TCP && + hints->ai_protocol != SLNETSOCK_PROTO_UDP && + hints->ai_protocol != 0) { + /* Error: invalid or unknown protocol */ + return (SLNETUTIL_EAI_SOCKTYPE); + } + else if ((hints->ai_family != SLNETSOCK_AF_INET) && + (hints->ai_family != SLNETSOCK_AF_INET6) && + (hints->ai_family != SLNETSOCK_AF_UNSPEC)) { + /* Error: invalid or unknown family */ + return (SLNETUTIL_EAI_FAMILY); + } + } + + if (node) { + /* + * Client case. User needs an address structure to call connect() with. + * + * Determine what caller has passed to us for 'node'. Should be either: + * - an IPv4 address + * - an IPv6 address + * - or a hostname + */ + + /* Test if 'node' is an IPv4 address */ + retval = SlNetUtil_inetAton(node, &(sin.sin_addr)); + if (retval) { + /* Ensure address family matches */ + if (hints->ai_family != SLNETSOCK_AF_INET && + hints->ai_family != SLNETSOCK_AF_UNSPEC) { + return (SLNETUTIL_EAI_ADDRFAMILY); + } + + /* + * Create addrinfo struct(s) containing this IPv4 address. If ai + * is NULL, this will be caught at end of getaddrinfo + * + * Pass zero for IF ID. This is a don't care for the case of node + * being set to an IPv4 address + */ + ai = setAddrInfo(0, (SlNetSock_Addr_t *)&sin, SLNETSOCK_AF_INET, + service, hints); + } + else { + /* 'node' is either an IPv6 address or a hostname (or invalid) */ + + /* Test if 'node' is an IPv6 address */ + retval = SlNetUtil_inetPton(SLNETSOCK_AF_INET6, node, + &(sin6.sin6_addr)); + if (retval > 0) { + /* Ensure address family matches */ + if (hints->ai_family != SLNETSOCK_AF_INET6 && + hints->ai_family != SLNETSOCK_AF_UNSPEC) { + return (SLNETUTIL_EAI_ADDRFAMILY); + } + + /* + * If we were given a link local address and corresponding IF, + * pass the IF number through. It must be used for the scope ID + */ + if ((SlNetUtil_ntohs(sin6.sin6_addr._S6_un._S6_u16[0]) == + LL_PREFIX) && ifID != 0) { + selectedIfId = ifID; + } + else { + /* + * Set scope ID to zero for these cases: + * - Link local addr and ifID == 0: + * (caller responsibe for setting scope ID) + * + * - Non-local addr with ifID == 0: + * - Non-local addr with ifID == 1: + * scope ID not used and should be set to 0 + */ + selectedIfId = 0; + } + + /* + * Create addrinfo struct(s) containing this IPv6 address. If + * ai is NULL, this will be caught at end of getaddrinfo + */ + ai = setAddrInfo(selectedIfId, (SlNetSock_Addr_t *)&sin6, + SLNETSOCK_AF_INET6, service, hints); + } + else { + /* Test if 'node' is a host name. Use DNS to resolve it. */ + + /* + * Per RFC 2553, if node is not a valid numeric address string + * and AI_NUMERICHOST is set, return error (and prevent call to + * DNS). + */ + if (hints->ai_flags & SLNETUTIL_AI_NUMERICHOST) { + return (SLNETUTIL_EAI_NONAME); + } + + buffer = malloc(SLNETUTIL_DNSBUFSIZE); + if (!buffer) { + /* Error: couldn't alloc DNS buffer */ + return (SLNETUTIL_EAI_MEMORY); + } + + /* IPv4 DNS lookup */ + if (hints->ai_family == SLNETSOCK_AF_INET || + hints->ai_family == SLNETSOCK_AF_UNSPEC) { + /* + * Set the size of the buffer to the number of 32-bit IPv4 + * addresses this buffer can hold + */ + numIpAddrs = SLNETUTIL_DNSBUFSIZE / sizeof(uint32_t); + + selectedIfId = SlNetUtil_getHostByName(ifID, (char *)node, + strlen(node), (uint32_t *)buffer, &numIpAddrs, + SLNETSOCK_AF_INET); + + if (selectedIfId > 0) { + + /* + * Process the results returned by DNS. Upon success, + * numIpAddrs contains the number of IP addresses stored + * into the buffer + */ + resolved = 1; + currAddr = buffer; + for (i = 0; i < numIpAddrs && + numNodes < SLNETUTIL_ADDRINFO_MAX_DNS_NODES; + i++) { + sin.sin_addr.s_addr = + SlNetUtil_htonl(*((uint32_t *)currAddr)); + /* + * Create addrinfo struct(s) containing this IPv4 + * address. This can return a list with multiple + * nodes, depending on hints provided. Empty lists + * are handled before returning. + * + * Pass zero for IF ID. This is a don't care for + * the case of node being set to an IPv4 address. + */ + aiTmp = setAddrInfo(0, (SlNetSock_Addr_t *)&sin, + SLNETSOCK_AF_INET, service, hints); + + if (aiTmp) { + /* + * Merge the results into the main list + * for each loop iteration: + */ + numNodes += mergeLists(&ai, &aiTmp); + } + + /* move to the next IPv4 address */ + currAddr += sizeof(uint32_t); + } + } + else { + /* save the IPv4 error code */ + ipv4DnsError = selectedIfId; + } + } + + /* IPv6 DNS lookup */ + if (hints->ai_family == SLNETSOCK_AF_INET6 || + hints->ai_family == SLNETSOCK_AF_UNSPEC) { + /* + * Set the size of the buffer to the number of 128-bit IPv6 + * addresses this buffer can hold + */ + numIpAddrs = + SLNETUTIL_DNSBUFSIZE / sizeof(SlNetSock_In6Addr_t); + + selectedIfId = SlNetUtil_getHostByName(ifID, (char *)node, + strlen(node), (uint32_t *)buffer, &numIpAddrs, + SLNETSOCK_AF_INET6); + + if (selectedIfId > 0) { + + /* + * Process the results returned by DNS. Upon success, + * numIpAddrs contains the number of IP addresses stored + * into the buffer + */ + resolved = 1; + currAddr = buffer; + for (i = 0; i < numIpAddrs && + numNodes < SLNETUTIL_ADDRINFO_MAX_DNS_NODES; + i++) { + + /* Copy the IPv6 address out of the buffer */ + memcpy(&(sin6.sin6_addr), currAddr, + sizeof(SlNetSock_In6Addr_t)); + + /* + * Is this address non-local? If so, IF ID is a + * don't care + */ + if (sin6.sin6_addr._S6_un._S6_u16[0] != LL_PREFIX) { + selectedIfId = 0; + } + + /* Change byte ordering to net byte order */ + sin6.sin6_addr._S6_un._S6_u16[0] = SlNetUtil_htons( + sin6.sin6_addr._S6_un._S6_u16[0]); + sin6.sin6_addr._S6_un._S6_u16[1] = SlNetUtil_htons( + sin6.sin6_addr._S6_un._S6_u16[1]); + sin6.sin6_addr._S6_un._S6_u16[2] = SlNetUtil_htons( + sin6.sin6_addr._S6_un._S6_u16[2]); + sin6.sin6_addr._S6_un._S6_u16[3] = SlNetUtil_htons( + sin6.sin6_addr._S6_un._S6_u16[3]); + sin6.sin6_addr._S6_un._S6_u16[4] = SlNetUtil_htons( + sin6.sin6_addr._S6_un._S6_u16[4]); + sin6.sin6_addr._S6_un._S6_u16[5] = SlNetUtil_htons( + sin6.sin6_addr._S6_un._S6_u16[5]); + sin6.sin6_addr._S6_un._S6_u16[6] = SlNetUtil_htons( + sin6.sin6_addr._S6_un._S6_u16[6]); + sin6.sin6_addr._S6_un._S6_u16[7] = SlNetUtil_htons( + sin6.sin6_addr._S6_un._S6_u16[7]); + + /* + * Create addrinfo struct(s) containing this IPv6 + * address. This can return a list with multiple + * nodes, depending on hints provided. Empty lists + * are handled before returning. + * + * Pass down the appropriate IF number or zero, + * depending on whether this address is + * local or not + */ + + aiTmp = setAddrInfo(selectedIfId, + (SlNetSock_Addr_t *)&sin6, + SLNETSOCK_AF_INET6, service, hints); + + if (aiTmp) { + /* + * Merge the results into the main list + * for each loop iteration: + */ + numNodes += mergeLists(&ai, &aiTmp); + } + + /* move to the next IPv6 address */ + currAddr += sizeof(SlNetSock_In6Addr_t); + } + } + else { + /* save the IPv6 error code */ + ipv6DnsError = selectedIfId; + } + } + + free(buffer); + + if (!resolved) { + /* + * Error: couldn't resolve host name + * Translate the SlNetSock error code to a GAI error code. + * Give the IPv4 error precedence: + */ + retval = (ipv4DnsError != 0) ? ipv4DnsError : ipv6DnsError; + + switch (retval) { + case SLNETERR_NET_APP_DNS_ALLOC_ERROR: + retval = SLNETUTIL_EAI_MEMORY; + break; + case SLNETERR_NET_APP_DNS_INVALID_FAMILY_TYPE: + retval = SLNETUTIL_EAI_FAMILY; + break; + case SLNETERR_NET_APP_DNS_IPV6_REQ_BUT_IPV6_DISABLED: + retval = SLNETUTIL_EAI_SERVICE; + break; + case SLNETERR_NET_APP_DNS_PARAM_ERROR: + case SLNETERR_NET_APP_DNS_QUERY_FAILED: + default: + retval = SLNETUTIL_EAI_FAIL; + break; + } + return (retval); + } + } + } + } + else { + /* Server case. User needs an address structure to call bind() with. */ + if (hints->ai_family == SLNETSOCK_AF_INET || + hints->ai_family == SLNETSOCK_AF_UNSPEC) { + if (hints->ai_flags & SLNETUTIL_AI_PASSIVE) { + /* Per RFC 2553, accept connections on any IF */ + sin.sin_addr.s_addr = SlNetUtil_htonl(SLNETSOCK_INADDR_ANY); + } + else { + /* Per RFC 2553, accept connections on loopback IF */ + retval = SlNetUtil_inetPton(SLNETSOCK_AF_INET, "127.0.0.1", + &(sin.sin_addr.s_addr)); + if (retval <= 0) { + return (SLNETUTIL_EAI_SYSTEM); + } + } + + /* + * Create addrinfo struct(s) containing this IPv4 address. If ai + * is NULL, this will be caught at end of getaddrinfo + * + * Pass zero for IF ID. This is a don't care for + * the case of setting up a server socket. + */ + ai = setAddrInfo(0, (SlNetSock_Addr_t *)&sin, + SLNETSOCK_AF_INET, service, hints); + } + + if (hints->ai_family == SLNETSOCK_AF_INET6 || + hints->ai_family == SLNETSOCK_AF_UNSPEC) { + if (hints->ai_flags & SLNETUTIL_AI_PASSIVE) { + /* + * Per RFC 2553, accept connections on any IF + * (The IPv6 unspecified address is all zeroes) + */ + /* TODO: use in6addr_any, once available (NS-84) */ + memset(&(sin6.sin6_addr), 0, sizeof(SlNetSock_In6Addr_t)); + } + else { + /* + * Per RFC 2553, accept connections on loopback IF + * (The IPv6 loopback address is a 1 preceded by all zeroes) + */ + /* TODO: use in6addr_loopback, once available (NS-84) */ + sin6.sin6_addr._S6_un._S6_u32[0] = 0; + sin6.sin6_addr._S6_un._S6_u32[1] = 0; + sin6.sin6_addr._S6_un._S6_u32[2] = 0; + sin6.sin6_addr._S6_un._S6_u32[3] = SlNetUtil_htonl(1); + } + + /* + * Create addrinfo struct(s) containing this IPv6 address. If ai + * is NULL, this will be caught at end of getaddrinfo + * + * Pass zero for IF ID. This is a don't care for + * the case of setting up a server socket. + */ + aiTmp = setAddrInfo(0, (SlNetSock_Addr_t *)&sin6, + SLNETSOCK_AF_INET6, service, hints); + + if (aiTmp) { + /* + * The current list (ai) may not be empty. Merge the new + * results (aiTmp) into the existing ai to handle this case. + */ + mergeLists(&ai, &aiTmp); + } + } + } + + /* Give user our allocated and initialized addrinfo struct(s) */ + *res = ai; + + if (!ai) { + /* Our list is empty - memory allocations failed */ + return (SLNETUTIL_EAI_MEMORY); + } + + return (0); +} + +//***************************************************************************** +// SlNetUtil_freeAddrInfo +//***************************************************************************** +void SlNetUtil_freeAddrInfo(struct SlNetUtil_addrInfo_t *res) +{ + SlNetUtil_addrInfo_t *aiTmp; + + /* Delete all nodes in linked list */ + while (res) { + aiTmp = res->ai_next; + free((void *)res); + res = aiTmp; + } +} + +//***************************************************************************** +// setAddrInfo +// Intermediate step to handle permutations of ai_socktype and ai_protocol +// hints fields, passed by the user. If both socktype and protocol are 0, must +// create a results struct for each socktype and protocol. +// Returns an empty list (NULL) or a list with one or more nodes. +//***************************************************************************** +static SlNetUtil_addrInfo_t *setAddrInfo(uint16_t ifID, SlNetSock_Addr_t *addr, + int family, const char *service, + const SlNetUtil_addrInfo_t *hints) +{ + SlNetUtil_addrInfo_t *ai = NULL; + SlNetUtil_addrInfo_t *aiTmp = NULL; + + if ((hints->ai_socktype == 0 && hints->ai_protocol == 0) || + (hints->ai_socktype == 0 && hints->ai_protocol == SLNETSOCK_PROTO_UDP) + || (hints->ai_socktype == SLNETSOCK_SOCK_DGRAM && + hints->ai_protocol == 0) || (hints->ai_socktype == SLNETSOCK_SOCK_DGRAM + && hints->ai_protocol == SLNETSOCK_PROTO_UDP)) { + + ai = createAddrInfo(ifID, addr, family, service, hints->ai_flags, + SLNETSOCK_SOCK_DGRAM, SLNETSOCK_PROTO_UDP); + } + + if ((hints->ai_socktype == 0 && hints->ai_protocol == 0) || + (hints->ai_socktype == 0 && hints->ai_protocol == SLNETSOCK_PROTO_TCP) + || (hints->ai_socktype == SLNETSOCK_SOCK_STREAM && + hints->ai_protocol == 0) || (hints->ai_socktype == SLNETSOCK_SOCK_STREAM + && hints->ai_protocol == SLNETSOCK_PROTO_TCP)) { + + aiTmp = createAddrInfo(ifID, addr, family, service, hints->ai_flags, + SLNETSOCK_SOCK_STREAM, SLNETSOCK_PROTO_TCP); + + if (aiTmp) { + /* Insert into front of list (assume UDP node was added above) */ + aiTmp->ai_next = ai; + ai = aiTmp; + } + } + + return (ai); +} + +//***************************************************************************** +// createAddrInfo +// Create new address info structure. Returns a single node. +//***************************************************************************** +static SlNetUtil_addrInfo_t *createAddrInfo(uint16_t ifID, + SlNetSock_Addr_t *addr, int family, const char *service, int flags, + int socktype, int protocol) +{ + SlNetUtil_addrInfo_t *ai = NULL; + + /* + * Allocate memory for the addrinfo struct, which we must fill out and + * return to the caller. This struct also has a pointer to a generic socket + * address struct, which will point to either struct sockaddr_in, or + * struct sockaddr_in6, depending. Need to allocate enough space to hold + * that struct, too. + */ + ai = (SlNetUtil_addrInfo_t *)calloc(1, SLNETUTIL_ADDRINFO_ALLOCSZ); + if (!ai) { + /* Error: memory allocation failed */ + return (NULL); + } + + ai->ai_flags = flags; + ai->ai_socktype = socktype; + ai->ai_protocol = protocol; + ai->ai_canonname = NULL; + ai->ai_next = NULL; + + /* Store socket addr struct after the addrinfo struct in our memory block */ + ai->ai_addr = (SlNetSock_Addr_t *)(ai + 1); + + if (family == SLNETSOCK_AF_INET) { + /* Fill in structure for IPv4 */ + ai->ai_family = SLNETSOCK_AF_INET; + ai->ai_addrlen = sizeof(SlNetSock_AddrIn_t); + + /* Write values to addrinfo's socket struct as an sockaddr_in struct */ + ((SlNetSock_AddrIn_t *)ai->ai_addr)->sin_family = SLNETSOCK_AF_INET; + + ((SlNetSock_AddrIn_t *)ai->ai_addr)->sin_port = + SlNetUtil_htons(atoi(service)); + + ((SlNetSock_AddrIn_t *)ai->ai_addr)->sin_addr = + ((SlNetSock_AddrIn_t *)addr)->sin_addr; + } + else { + /* Fill in structure for IPv6 */ + ai->ai_family = SLNETSOCK_AF_INET6; + ai->ai_addrlen = sizeof(SlNetSock_AddrIn6_t); + + /* Write values to addrinfo's socket struct as an sockaddr_in6 struct */ + ((SlNetSock_AddrIn6_t *)ai->ai_addr)->sin6_family = SLNETSOCK_AF_INET6; + + ((SlNetSock_AddrIn6_t *)ai->ai_addr)->sin6_port = + SlNetUtil_htons(atoi(service)); + + memcpy(&(((SlNetSock_AddrIn6_t *)ai->ai_addr)->sin6_addr), + &(((SlNetSock_AddrIn6_t *)addr)->sin6_addr), + sizeof(SlNetSock_In6Addr_t)); + + /* Scope ID should have been determined correctly by the caller */ + ((SlNetSock_AddrIn6_t *)ai->ai_addr)->sin6_scope_id = (uint32_t)ifID; + } + + return (ai); +} + +//***************************************************************************** +// mergeLists +// Combines an existing linked list of addrinfo structs (curList) and a newly +// obtained list (newList) into a single list. If the existing list is empty, +// it will be initialized to the new list. If both lists are empty, no action +// is taken. +//***************************************************************************** +static int mergeLists(SlNetUtil_addrInfo_t **curList, + SlNetUtil_addrInfo_t **newList) +{ + int numNodes = 0; + SlNetUtil_addrInfo_t *tail = NULL; + + /* Check params */ + if (!curList || !newList || !(*newList)) { + return (numNodes); + } + + /* Update node count & find end of new list */ + for (tail = *newList; tail != NULL;) { + numNodes++; + if (tail->ai_next != NULL) { + /* Not the tail, keep traversing */ + tail = tail->ai_next; + } + else { + /* Tail found, quit loop */ + break; + } + } + + /* Append current list to end of new list */ + tail->ai_next = *curList; + *curList = *newList; + + return (numNodes); +} + +//***************************************************************************** +// +// SlNetUtil_htonl - Reorder the bytes of a 32-bit unsigned value from host +// order to network order(Big endian) +// +//***************************************************************************** +uint32_t SlNetUtil_htonl(uint32_t val) +{ + uint32_t i = 1; + int8_t *p = (int8_t *)&i; + + /* When the LSB of i stored in the smallest address of *p */ + if (p[0] == 1) /* little endian */ + { + /* Swap the places of the value */ + p[0] = ((int8_t *)&val)[3]; + p[1] = ((int8_t *)&val)[2]; + p[2] = ((int8_t *)&val)[1]; + p[3] = ((int8_t *)&val)[0]; + + /* return the reordered bytes */ + return i; + } + else /* big endian */ + { + /* return the input without any changes */ + return val; + } +} + + +//***************************************************************************** +// +// SlNetUtil_ntohl - Reorder the bytes of a 32-bit unsigned value from network +// order(Big endian) to host order +// +//***************************************************************************** +uint32_t SlNetUtil_ntohl(uint32_t val) +{ + /* return the reordered bytes */ + return SlNetUtil_htonl(val); +} + + +//***************************************************************************** +// +// SlNetUtil_htons - Reorder the bytes of a 16-bit unsigned value from host +// order to network order(Big endian) +// +//***************************************************************************** +uint16_t SlNetUtil_htons(uint16_t val) +{ + int16_t i = 1; + int8_t *p = (int8_t *)&i; + + /* When the LSB of i stored in the smallest address of *p */ + if (p[0] == 1) /* little endian */ + { + /* Swap the places of the value */ + p[0] = ((int8_t *)&val)[1]; + p[1] = ((int8_t *)&val)[0]; + + /* return the reordered bytes */ + return (uint16_t)i; + } + else /* big endian */ + { + /* return the input without any changes */ + return val; + } +} + + +//***************************************************************************** +// +// SlNetUtil_ntohs - Reorder the bytes of a 16-bit unsigned value from network +// order(Big endian) to host order +// +//***************************************************************************** +uint16_t SlNetUtil_ntohs(uint16_t val) +{ + /* return the reordered bytes */ + return SlNetUtil_htons(val); +} + +//***************************************************************************** +// +// SlNetUtil_UTOA - converts unsigned 16 bits binary number to string with +// maximum of 4 characters + 1 NULL terminated +// +//***************************************************************************** +static int32_t SlNetUtil_UTOA(uint16_t value, char * string, uint16_t base) +{ + uint16_t Index = 4; + char tempString[5] = { 0 }; + char * ptempString = tempString; + char * pString = string; + + /* Check if the inputs valid */ + if ( (NULL == string) || ((base < 2 ) && (base > 16 )) ) + { + return SLNETERR_RET_CODE_INVALID_INPUT; + } + + /* If value is zero, that means that the returned string needs to be zero*/ + if (0 == value) + { + *ptempString = '0'; + ptempString++; + Index--; + } + + /* Run until all value digits are 0 or until Index get to 0 */ + for (; (value && (Index > 0)); Index--, value /= base) + { + *ptempString = "0123456789abcdef"[value % base]; + ptempString++; + } + /* Invalid value input */ + if (0 != value) + { + return SLNETERR_RET_CODE_INVALID_INPUT; + } + + /* Reverse the string and initialize temporary array */ + while (Index < 4) + { + *(pString++) = *(--ptempString); + *ptempString = '\0'; + *pString = '\0'; + Index++; + } + + return 0; +} + +//***************************************************************************** +// +// SlNetUtil_bin2StrIpV4 - converts IPv4 address in binary representation +// (network byte order) to IP address in string +// representation +// +//***************************************************************************** +static int32_t SlNetUtil_bin2StrIpV4(SlNetSock_InAddr_t *binaryAddr, char *strAddr, uint16_t strAddrLen) +{ + uint8_t tempOctet; + uint32_t tempBinAddr; + int32_t octetIndex = 0; + char tempStrOctet[4] = { 0 }; + + /* Check if the strAddr buffer is at least in the minimum required size */ + if (strAddrLen < SLNETSOCK_INET_ADDRSTRLEN) + { + /* Return error code */ + return SLNETERR_RET_CODE_INVALID_INPUT; + } + + /* initialize strAddr to an empty string (so we can strcat() later) */ + strAddr[0] = '\0'; + + /* Copy the address value for further use */ + memcpy(&tempBinAddr, binaryAddr, sizeof(SlNetSock_InAddr_t)); + + /* Run over all octets (in network byte order), starting with the + most significant octet and ending with the least significant octet */ + while ( octetIndex <= 3 ) + { + /* Save octet on tempOctet for further usage. + When converting from binary representation to string + representation, the MSO of the binary number is the first char + of the string, so it needs to copied to the first location of + the array */ + tempOctet = ((int8_t *)&tempBinAddr)[octetIndex]; + + /* Initialize the octet for validation after copying the value */ + ((int8_t *)&tempBinAddr)[octetIndex] = 0; + + /* Convert tempOctet to string */ + SlNetUtil_UTOA(tempOctet, tempStrOctet, 10); + + /* Appends the tempStrOctet to strAddr */ + strcat(strAddr, tempStrOctet); + + /* Appends the "." to strAddr for the first 3 octets */ + if ( octetIndex < 3) + { + strcat(strAddr, "."); + } + + /* Move to the next octet */ + octetIndex ++; + + } + + /* Check if the address had only 4 octets, this was done by initializing + each octet that was copied and than checking if the number equal to 0 */ + if ( 0 == tempBinAddr ) + { + /* Return success */ + return SLNETERR_RET_CODE_OK; + } + else + { + /* Return error code */ + return SLNETERR_RET_CODE_INVALID_INPUT; + } +} + + +//***************************************************************************** +// +// SlNetUtil_bin2StrIpV6 - converts IPv6 address in binary representation to +// IP address in string representation +// +//***************************************************************************** +static int32_t SlNetUtil_bin2StrIpV6(SlNetSock_In6Addr_t *binaryAddr, char *strAddr, uint16_t strAddrLen) +{ + uint16_t tempHextet; + int32_t hextetIndex = 0; + uint8_t tempBinAddr[16] = { 0 }; + char tempStrHextet[5] = { 0 }; + + /* Check if the strAddr buffer is at least in the minimum required size */ + if (strAddrLen < SLNETSOCK_INET6_ADDRSTRLEN) + { + /* Return error code */ + return SLNETERR_RET_CODE_INVALID_INPUT; + } + + /* initialize strAddr to an empty string (so we can strcat() later) */ + strAddr[0] = '\0'; + + /* Copy the address value for further use */ + memcpy(tempBinAddr, binaryAddr, sizeof(SlNetSock_In6Addr_t)); + + /* Run over all octets, from the latest hextet (the most significant + hextet) until the first one (the least significant hextet) */ + while (hextetIndex < 8) + { + /* Save hextet on tempHextet for further usage. + When converting from binary representation to string + representation, the most significant hextet of the binary number + is the first char of the string, so it needs to copied to the + first location of the array */ + tempHextet = (tempBinAddr[hextetIndex * 2] << 8) | + (tempBinAddr[(hextetIndex * 2) + 1]); + + /* Convert tempHextet to string */ + SlNetUtil_UTOA(tempHextet, tempStrHextet, 16); + + /* Appends the tempStrHextet to strAddr */ + strcat(strAddr, tempStrHextet); + + /* Appends the ":" after each hextet (without the last one) */ + if (hextetIndex < 7) + { + strcat(strAddr, ":"); + } + + /* Move to the next hextet */ + hextetIndex++; + + } + + /* Return success */ + return SLNETERR_RET_CODE_OK; +} + + +//***************************************************************************** +// +// SlNetUtil_inetNtop - converts IP address in binary representation to IP +// address in string representation +// +//***************************************************************************** +const char *SlNetUtil_inetNtop(int16_t addrFamily, const void *binaryAddr, char *strAddr, SlNetSocklen_t strAddrLen) +{ + int32_t retVal; + + /* Switch according to the address family */ + switch(addrFamily) + { + case SLNETSOCK_AF_INET: + /* Convert from IPv4 string to numeric/binary representation */ + retVal = SlNetUtil_bin2StrIpV4((SlNetSock_InAddr_t *)binaryAddr, strAddr, strAddrLen); + + break; + case SLNETSOCK_AF_INET6: + /* Convert from IPv6 string to numeric/binary representation */ + retVal = SlNetUtil_bin2StrIpV6((SlNetSock_In6Addr_t *)binaryAddr, strAddr, strAddrLen); + + break; + default: + /* wrong address family - function error, return NULL error */ + return NULL; + } + + /* Check if conversion was successful */ + if (retVal != SLNETERR_RET_CODE_OK) + { + /* Conversion failed, return NULL as error code */ + return NULL; + } + /* Conversion success - return strAddr for success */ + return strAddr; +} + +//***************************************************************************** +// +// SlNetUtil_strTok - Split a valid ipv4 string up into tokens +// +//***************************************************************************** +static int32_t SlNetUtil_strTok(char **string, char *returnstring, int retstringlength, const char *delimiter) +{ + char * retStr; + int count = 0; + + retStr = returnstring; + + while ( (**string !='\0') && (**string != *delimiter) && + (count != (retstringlength-1))) + { + *retStr = **string; + retStr++; + (*string)++; + count++; + } + /* string portion has to either end with delimiter or null char to be an + ipv4 string */ + if (**string !='\0' && **string != *delimiter) + { + return SLNETERR_RET_CODE_INVALID_INPUT; + } + /* skip delimiter chars */ + if (**string == *delimiter) + { + (*string)++; + } + *retStr = '\0'; + + return SLNETERR_RET_CODE_OK; +} + +//***************************************************************************** +// +// SlNetUtil_str2BinIpV4 - converts IPv4 address in string representation to +// IP address in binary representation +// +//***************************************************************************** +static int32_t SlNetUtil_str2BinIpV4(char *strAddr, SlNetSock_InAddr_t *binaryAddr) +{ + uint32_t decNumber; + char token[4]; + char *end; + int32_t retVal; + int32_t ipOctet = 0; + uint32_t ipv4Address = 0; + char *modifiedStr = strAddr; + + /* split strAddr into tokens separated by "." */ + retVal = SlNetUtil_strTok(&modifiedStr, token, 4, "."); + if (SLNETERR_RET_CODE_OK != retVal) + { + return retVal; + } + + /* run 4 times as IPv4 contain of four octets and separated by periods */ + while(ipOctet < 4) + { + /* Parses the token strAddr, interpreting its content as an integral + number of the specified base 10 */ + decNumber = (int)strtoul(token, &end, 10); + + /* Check if the octet holds valid number between the range 0-255. + end points the end of the numeric portion of the input string + for strtoul, so if end == token that means no conversion has + occured as there was no numeric portion detected */ + if (decNumber < 256 && end != token) + { + /* manually place each byte in network order */ + ((int8_t *)&ipv4Address)[ipOctet] = (uint8_t)decNumber; + + /* split strAddr into tokens separated by "." */ + SlNetUtil_strTok(&modifiedStr, token, 4, "."); + ipOctet++; + } + else + { + return SLNETERR_RET_CODE_INVALID_INPUT; + } + } + + /* Copy the temporary variable to the input variable */ + memcpy(binaryAddr, &ipv4Address, sizeof(SlNetSock_InAddr_t)); + + return SLNETERR_RET_CODE_OK; +} + + +//***************************************************************************** +// +// SlNetUtil_str2BinIpV6 - converts IPv6 address in string representation to +// IP address in binary representation +// +//***************************************************************************** +static int32_t SlNetUtil_str2BinIpV6(char *strAddr, SlNetSock_In6Addr_t *binaryAddr) +{ + + int32_t octetIndex = 0; + int32_t octetTailIndex; + uint8_t *pLocalStr; + uint8_t tmp[16]; + int32_t zeroCompressPos = -1; + uint16_t value = 0; + uint8_t asciiCharacter = 0; + + /* Copy the first address of the string */ + pLocalStr = (uint8_t *)strAddr; + + /* Initialize tmp parameter */ + memset(tmp, 0, sizeof(tmp)); + + /* Check if the IP starts with "::" */ + if(*pLocalStr==':') + { + /* If the IP starts with ":", check if it doesn't have the second ":" + If so, return an error */ + if(*++pLocalStr!=':') + { + return SLNETERR_RET_CODE_INVALID_INPUT; + } + } + + /* run over the remaining two octets */ + while(*pLocalStr && (octetIndex < 16)) + { + /* Check if the ASCII character is a number between "0" to "9" */ + if(*pLocalStr >= '0' && *pLocalStr <= '9') + { + /* Each ASCII character can be max 4 bits, shift the number + 4 bits and copy the new converted number */ + value = (value << 4) | (*pLocalStr - '0'); + + /* Set the flag for ASCII character */ + asciiCharacter = 1; + } + /* Check if the ASCII character is a hex character between "a" to "f"*/ + else if(*pLocalStr >= 'a' && *pLocalStr <= 'f') + { + /* Each ASCII character can be max 4 bits, shift the number + 4 bits and copy the new converted number */ + value = (value << 4) | ((*pLocalStr - 'a') + 10); + + /* Set the flag for ASCII character */ + asciiCharacter = 1; + } + /* Check if the ASCII character is a hex character between "A" to "F"*/ + else if(*pLocalStr >= 'A' && *pLocalStr <= 'F') + { + /* Each ASCII character can be max 4 bits, shift the number + 4 bits and copy the new converted number */ + value = (value << 4) | ((*pLocalStr - 'A') + 10); + + /* Set the flag for ASCII character */ + asciiCharacter = 1; + } + /* Check if the hextet (two octets) finished with ":" and still a + part of the IP */ + else if((*pLocalStr == ':') && (octetIndex < 14)) + { + /* Check if the hextet contain ASCII character */ + if(asciiCharacter) + { + /* ASCII character exists, store the converted number in tmp + and reset the value and ascii character parameters */ + tmp[octetIndex++] = (value >> 8) & 0xFF; + tmp[octetIndex++] = (value) & 0xFF; + asciiCharacter = 0; + value = 0; + } + else + { + /* ASCII character doesn't exists, compressed hextet found */ + if(zeroCompressPos < 0) + { + /* first compressed hextet found, sore the octet Index */ + zeroCompressPos = octetIndex; + } + else + { + /* Second compressed hextet found, return error code */ + return SLNETERR_RET_CODE_INVALID_INPUT; + } + } + } + /* None of the valid characters have matched so this is not an ipv6 + address */ + else + { + return SLNETERR_RET_CODE_INVALID_INPUT; + } + /* Continue to the next ASCII character */ + pLocalStr++; + } + + /* if more than 15 octets found, return error code */ + if(octetIndex > 15) + { + return SLNETERR_RET_CODE_INVALID_INPUT; + } + /* if less than 14 octets found, and without any compress hextet, + return error code */ + else if(asciiCharacter && (zeroCompressPos < 0) && (octetIndex < 14)) + { + return SLNETERR_RET_CODE_INVALID_INPUT; + } + /* if all octets found, but still found compressed hextet, + return error code */ + else if((zeroCompressPos >= 0) && octetIndex >= 14) + { + return SLNETERR_RET_CODE_INVALID_INPUT; + } + + /* copy the last available hextet to the tmp array */ + if((asciiCharacter) && (octetIndex <= 14)) + { + /* Store the converted number in tmp and reset the value and + ascii character parameters */ + tmp[octetIndex++] = (value >> 8) & 0xFF; + tmp[octetIndex++] = (value) & 0xFF; + asciiCharacter = 0; + value = 0; + } + + /* compressed position found, add zeros in the compressed sections */ + if(zeroCompressPos >= 0) + { + /* compressed position found, add zeros in the compressed sections */ + octetIndex--; + octetTailIndex = 15; + /* Move the converted octets from the position they are located on + to the end of the array and add zero instead */ + while(octetIndex >= zeroCompressPos) + { + /* Check if the indexes are still in range */ + if ((octetTailIndex >= 0) && (octetIndex >= 0)) + { + /* Move all the octets after the zero compress position to + the end of the array */ + tmp[octetTailIndex] = tmp[octetIndex]; + tmp[octetIndex] = 0; + octetTailIndex--; + octetIndex--; + } + } + } + + /* Copy the temporary variable to the input variable */ + memcpy(binaryAddr, tmp, sizeof(tmp)); + + return SLNETERR_RET_CODE_OK; + +} + +//***************************************************************************** +// +// SlNetUtil_inetAton - Converts a string to a network address structure +// +//***************************************************************************** +int SlNetUtil_inetAton(const char *str, SlNetSock_InAddr_t *addr) +{ + uint32_t val[4]; + uint32_t base; + int sect; + char c; + + sect = -1; + while (*str) { + /* New section */ + sect++; + + /* Get the base for this number */ + base = 10; + if (*str == '0') + { + if (*(str + 1) == 'x' || *(str + 1) == 'X') { + base = 16; + str += 2; + } + else { + base = 8; + str++; + } + } + + /* Now decode this number */ + val[sect] = 0; + for (;;) { + c = *str++; + + if ((c >= '0' && c <= '9')) { + val[sect] = (val[sect] * base) + (c - '0'); + } + else if (base == 16 && (c >= 'A' && c <= 'F')) { + val[sect] = (val[sect] * 16) + (c - 'A') + 10; + } + else if (base == 16 && (c >= 'a' && c <= 'f')) { + val[sect] = (val[sect] * 16) + (c - 'a') + 10; + } + else if (c == '.') { + /* validate value */ + if(val[sect] > 255) { + return (0); + } + + /* + * Once we have four sections, quit. + * We want to accept: "1.2.3.4.in-addr.arpa" + */ + if (sect == 3) { + goto done; + } + + /* Break this section */ + break; + } + else if (!c) { + goto done; + } + else if (c != ' ') { + return (0); + } + } + } + +done: + /* What we do changes based on the number of sections */ + switch (sect) { + case 0: + addr->s_addr = val[0]; + break; + case 1: + if (val[1] > 0xffffff) { + return (0); + } + addr->s_addr = val[0] << 24; + addr->s_addr += val[1]; + break; + case 2: + if (val[2] > 0xffff) { + return (0); + } + addr->s_addr = val[0] << 24; + addr->s_addr += (val[1] << 16); + addr->s_addr += val[2]; + break; + case 3: + if (val[3] > 0xff) { + return (0); + } + addr->s_addr = val[0] << 24; + addr->s_addr += (val[1] << 16); + addr->s_addr += (val[2] << 8); + addr->s_addr += val[3]; + break; + default: + return (0); + } + + addr->s_addr = SlNetUtil_htonl(addr->s_addr); + return (1); +} + +//***************************************************************************** +// +// SlNetUtil_inetPton - converts IP address in string representation to IP +// address in binary representation +// +//***************************************************************************** +int32_t SlNetUtil_inetPton(int16_t addrFamily, const char *strAddr, void *binaryAddr) +{ + int32_t retVal; + + /* Switch according to the address family */ + switch(addrFamily) + { + case SLNETSOCK_AF_INET: + /* Convert from IPv4 string to numeric/binary representation */ + retVal = SlNetUtil_str2BinIpV4((char *)strAddr, (SlNetSock_InAddr_t *)binaryAddr); + break; + + case SLNETSOCK_AF_INET6: + /* Convert from IPv6 string to numeric/binary representation */ + retVal = SlNetUtil_str2BinIpV6((char *)strAddr, (SlNetSock_In6Addr_t *)binaryAddr); + break; + + default: + /* wrong address family - function error, return -1 error */ + return -1; + } + + /* Check if conversion was successful */ + if (retVal != SLNETERR_RET_CODE_OK) + { + /* Conversion failed, that means the input wasn't a + valid IP address, return 0 as error code */ + return 0; + } + /* Conversion success - return 1 for success */ + return 1; +} diff --git a/simplelink/source/ti/net/slnetutils.h b/simplelink/source/ti/net/slnetutils.h new file mode 100644 index 0000000..5e3e29b --- /dev/null +++ b/simplelink/source/ti/net/slnetutils.h @@ -0,0 +1,428 @@ +/* + * Copyright (c) 2017-2019, Texas Instruments Incorporated + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of Texas Instruments Incorporated nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/*****************************************************************************/ +/* Include files */ +/*****************************************************************************/ + +#ifndef __SL_NET_UTILS_H__ +#define __SL_NET_UTILS_H__ + +#include + +#include "slnetsock.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/*! + \defgroup SlNetUtils SlNetUtils group + + \short Sockets related commands and configuration + +*/ +/*! + + \addtogroup SlNetUtils + @{ + +*/ + +/*****************************************************************************/ +/* Macro declarations */ +/*****************************************************************************/ +#define SLNETUTIL_AI_PASSIVE 0x00000001 +#define SLNETUTIL_AI_NUMERICHOST 0x00000004 + +/*****************************************************************************/ +/* Structure/Enum declarations */ +/*****************************************************************************/ + +typedef struct SlNetUtil_addrInfo_t { + int ai_flags; + int ai_family; + int ai_socktype; + int ai_protocol; + size_t ai_addrlen; + struct SlNetSock_Addr_t *ai_addr; + char *ai_canonname; + struct SlNetUtil_addrInfo_t *ai_next; +} SlNetUtil_addrInfo_t; + +/* Creating one address parameter from 4 separate address parameters */ +#define SLNETUTIL_IPV4_VAL(add_3,add_2,add_1,add_0) ((((uint32_t)add_3 << 24) & 0xFF000000) | (((uint32_t)add_2 << 16) & 0xFF0000) | (((uint32_t)add_1 << 8) & 0xFF00) | ((uint32_t)add_0 & 0xFF) ) + +/*****************************************************************************/ +/* Function prototypes */ +/*****************************************************************************/ + +/*! + + \brief Initialize the SlNetUtil module + + \param[in] flags Reserved + + \return Zero on success, or negative error code on failure +*/ +int32_t SlNetUtil_init(int32_t flags); + +/*! + \brief Return text descriptions of getAddrInfo error codes + + \param[in] errorCode A getAddrInfo error code + + \return Text description of the passed in getAddrInfo error code. + If the error code does not exist returns "Unknown Error" + */ +const char *SlNetUtil_gaiStrErr(int32_t errorCode); + +/*! + \brief Get host IP by name\n + Obtain the IP Address of machine on network, by machine name. + + \param[in] ifBitmap Specifies the interfaces which the host ip + needs to be retrieved from according to the + priority until one of them will return an answer.\n + Value 0 is used in order to choose automatic + interfaces selection according to the priority + interface list. + Value can be combination of interfaces by OR'ing + multiple interfaces bit identifiers (SLNETIFC_IDENT_ + defined in slnetif.h) + Note: interface identifier bit must be configured + prior to this socket creation using SlNetIf_add(). + \param[in] name Host name + \param[in] nameLen Name length + \param[out] ipAddr A buffer used to store the IP address(es) from + the resulting DNS resolution. The caller is + responsible for allocating this buffer. Upon + return, this buffer can be accessed as an array + of IPv4 or IPv6 addresses, depending on the + protocol passed in for the family parameter. + Addresses are stored in host byte order. + \param[in,out] ipAddrLen Initially holds the number of IP addresses + that the ipAddr buffer parameter is capable of + storing. Upon successful return, the ipAddrLen + parameter contains the number of IP addresses + that were actually written into the ipAddr + buffer, as a result of successful DNS + resolution, or zero if DNS resolution failed. + \param[in] family Protocol family + + \return The interface ID of the interface which was + able to successfully run the function, or + negative on failure.\n + #SLNETERR_POOL_IS_EMPTY may be return in case + there are no resources in the system\n + Possible DNS error codes: + - #SLNETERR_NET_APP_DNS_QUERY_NO_RESPONSE + - #SLNETERR_NET_APP_DNS_NO_SERVER + - #SLNETERR_NET_APP_DNS_QUERY_FAILED + - #SLNETERR_NET_APP_DNS_MALFORMED_PACKET + - #SLNETERR_NET_APP_DNS_MISMATCHED_RESPONSE + + \slnetutil_init_precondition + + \warning + In case an IP address in a string format is set as input, without + any prefix (e.g. "1.2.3.4") the device will not try to access the + DNS and it will return the input address in the \c ipAddr field + \par Example + - Getting IPv4 using get host by name: + \code + // A buffer capable of storing a single 32-bit IPv4 address + uint32_t DestIP[1]; + + // The number of IP addresses that DestIP can hold + uint16_t DestIPListSize = 1; + + int32_t ifID; + int16_t SockId; + SlNetSock_AddrIn_t LocalAddr; //address of the server to connect to + int32_t LocalAddrSize; + + ifID = SlNetUtil_getHostByName(0, "www.ti.com", strlen("www.ti.com"), DestIP, &DestIPListSize, SLNETSOCK_PF_INET); + + LocalAddr.sin_family = SLNETSOCK_AF_INET; + LocalAddr.sin_addr.s_addr = SlNetUtil_htonl(DestIP[0]); + LocalAddr.sin_port = SlNetUtil_htons(80); + LocalAddrSize = sizeof(SlNetSock_AddrIn_t); + + SockId = SlNetSock_create(SLNETSOCK_AF_INET, SLNETSOCK_SOCK_STREAM, ifID, 0); + + if (SockId >= 0) + { + status = SlNetSock_connect(SockId, (SlNetSock_Addr_t *)&LocalAddr, LocalAddrSize); + } + \endcode +*/ +int32_t SlNetUtil_getHostByName(uint32_t ifBitmap, char *name, const uint16_t nameLen, uint32_t *ipAddr, uint16_t *ipAddrLen, const uint8_t family); + + +/*! + \brief Network address and service translation + + Create an IPv4 or IPv6 socket address structure, to be used with bind() + and/or connect() to create a client or server socket + + This is a "minimal" version for support on embedded devices. Supports a + host name or an IPv4 or IPv6 address string passed in via the 'node' + parameter for creating a client socket. A value of NULL should be passed + for 'node' with AI_PASSIVE flag set to create a (non-loopback) server + socket. + + The caller is responsible for freeing the allocated results by calling + SlNetUtil_freeAddrInfo(). + + \param[in] ifID Specifies the interface which needs + to used for socket operations.\n + The values of the interface identifier + is defined with the prefix SLNETIF_ID_ + which defined in slnetif.h + + \param[in] node An IP address or a host name. + + \param[in] service The port number of the service to bind or connect to. + + \param[in] hints An SlNetUtil_addrInfo_t struct used to filter the + results returned. + + \param[out] res one or more SlNetUtil_addrInfo_t structs, each of which + can be used to bind or connect a socket. + + \return Returns 0 on success, or an error code on failure. + + \sa SlNetUtil_freeAddrInfo() +*/ +int32_t SlNetUtil_getAddrInfo(uint16_t ifID, const char *node, + const char *service, const struct SlNetUtil_addrInfo_t *hints, + struct SlNetUtil_addrInfo_t **res); + +/*! + \brief Free the results returned from SlNetUtil_getAddrInfo + + Free the chain of SlNetUtil_addrInfo_t structs allocated and returned by + SlNetUtil_getAddrInfo + + \param[in] res linked list of results returned from SlNetUtil_getAddrInfo + + \return None. + + \sa SlNetUtil_getAddrInfo() +*/ +void SlNetUtil_freeAddrInfo(struct SlNetUtil_addrInfo_t *res); + +/*! + \brief Reorder the bytes of a 32-bit unsigned value + + This function is used to reorder the bytes of a 32-bit unsigned value + from host order to network order. + + \param[in] val Variable in host order + + \return Return the variable in network order + + \slnetutil_init_precondition + + \sa SlNetSock_bind() + \sa SlNetSock_connect() + \sa SlNetSock_recvFrom() + \sa SlNetSock_accept() +*/ +uint32_t SlNetUtil_htonl(uint32_t val); + + +/*! + \brief Reorder the bytes of a 32-bit unsigned value + + This function is used to reorder the bytes of a 32-bit unsigned + value from network order to host order. + + \param[in] val Variable in network order + + \return Return the variable in host order + + \slnetutil_init_precondition + + \sa SlNetSock_bind() + \sa SlNetSock_connect() + \sa SlNetSock_recvFrom() + \sa SlNetSock_accept() +*/ +uint32_t SlNetUtil_ntohl(uint32_t val); + + +/*! + \brief Reorder the bytes of a 16-bit unsigned value + + This functions is used to reorder the bytes of a 16-bit unsigned + value from host order to network order. + + \param[in] val Variable in host order + + \return Return the variable in network order + + \slnetutil_init_precondition + + \sa SlNetSock_bind() + \sa SlNetSock_connect() + \sa SlNetSock_recvFrom() + \sa SlNetSock_accept() +*/ +uint16_t SlNetUtil_htons(uint16_t val); + + +/*! + \brief Reorder the bytes of a 16-bit unsigned value + + This functions is used to reorder the bytes of a 16-bit unsigned value + from network order to host order. + + \param[in] val Variable in network order + + \return Return the variable in host order + + \slnetutil_init_precondition + + \sa SlNetSock_bind() + \sa SlNetSock_connect() + \sa SlNetSock_recvFrom() + \sa SlNetSock_accept() +*/ +uint16_t SlNetUtil_ntohs(uint16_t val); + +/*! + \brief Convert an IPv4 address in string format to binary format + + This function converts an IPv4 address stored as a character string to a + 32-bit binary value in network byte order. Note that a leading zero or a + "0x" in the address string are interpreted as octal or hexadecimal, + respectively. The function stores the IPv4 address in the address structure + pointed to by the addr parameter. + + \param[in] str IPv4 address string in dotted decimal format + + \param[out] addr pointer to an IPv4 address structure. The converted binary + address is stored in this structure upon return (in network byte order) + + \return returns nonzero if the address string is valid, zero if not +*/ +int SlNetUtil_inetAton(const char *str, struct SlNetSock_InAddr_t *addr); + +/*! + \brief Converts IP address in binary representation to string representation + + This functions is used to converts IP address in binary representation + to IP address in string representation. + + \param[in] addrFamily Specifies the address family of the created + socket + For example: + - #SLNETSOCK_AF_INET for network address IPv4 + - #SLNETSOCK_AF_INET6 for network address IPv6 + \param[in] binaryAddr Pointer to an IP address structure indicating the + address in binary representation. The address + is assumed to be in network-byte order + \param[out] strAddr Pointer to the address string representation + for IPv4 or IPv6 according to the address + family + \param[in] strAddrLen Specifies the length of the StrAddress_dst, + the maximum length of the address in string + representation for IPv4 or IPv6 according to + the address family + + \return strAddr on success, or NULL on failure + + \slnetutil_init_precondition + + \par Example + - IPv4 demo of inet_ntop() + \code + SlNetSock_AddrIn_t sa; + char str[SLNETSOCK_INET_ADDRSTRLEN]; + + // store this IP address in sa: + SlNetUtil_inetPton(SLNETSOCK_AF_INET, "192.0.2.33", &(sa.sin_addr)); + // now get it back and print it + SlNetUtil_inetNtop(SLNETSOCK_AF_INET, &(sa.sin_addr), str, SLNETSOCK_INET_ADDRSTRLEN); + \endcode +*/ +const char *SlNetUtil_inetNtop(int16_t addrFamily, const void *binaryAddr, char *strAddr, SlNetSocklen_t strAddrLen); + + +/*! + \brief Converts IP address in string representation to binary representation + + This functions is used to converts IP address in string representation + to IP address in binary representation. + + \param[in] addrFamily Specifies the address family of the created + socket + For example: + - #SLNETSOCK_AF_INET for network address IPv4 + - #SLNETSOCK_AF_INET6 for network address IPv6 + \param[in] strAddr Specifies the IP address in string representation + for IPv4 or IPv6 according to the address family + \param[out] binaryAddr Pointer to an address structure that will be + filled by the IP address in Binary representation. + The address is returned in network-byte order + + \return 1 on success, -1 on failure, or 0 if the input + isn't a valid IP address + + \slnetutil_init_precondition + + \par Example + - IPv6 demo of inet_pton() + \code + SlNetSock_AddrIn6_t sa; + + // store this IP address in sa: + SlNetUtil_inetPton(SLNETSOCK_AF_INET6, "0:0:0:0:0:0:0:0", &(sa.sin6_addr)); + \endcode +*/ +int32_t SlNetUtil_inetPton(int16_t addrFamily, const char *strAddr, void *binaryAddr); + +/*! + + Close the Doxygen group. + @} + +*/ + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __SL_NET_UTILS_H__ */