From 18bda345325b2cdcbda10b378ce56ebf671fc9e9 Mon Sep 17 00:00:00 2001 From: Lukas Karel Date: Sat, 9 Oct 2021 14:56:02 +0200 Subject: [PATCH] build cleaner interface dtls --- CMakeLists.txt | 8 +- examples/CMakeLists.txt | 14 +- examples/bootstrap_server/bootstrap_server.c | 30 +- examples/client/lwm2mclient.c | 141 +---- examples/client/lwm2mclient.h | 10 +- examples/lightclient/lightclient.c | 45 +- examples/server/lwm2mserver.c | 18 +- examples/shared/commandline.h | 1 + examples/shared/connection.c | 289 +++++++--- examples/shared/connection.h | 43 +- examples/shared/dtls/tinydtls.cmake | 8 +- examples/shared/dtlsconnection.h | 13 + examples/shared/mbedtlsconnection.c | 402 +++++-------- examples/shared/mbedtlsconnection.h | 12 - examples/shared/object_utils.c | 96 ++++ examples/shared/object_utils.h | 20 + examples/shared/shared.cmake | 16 +- examples/shared/tinydtlsconnection.c | 563 ++++--------------- examples/shared/tinydtlsconnection.h | 74 --- tests/CMakeLists.txt | 4 + 20 files changed, 693 insertions(+), 1114 deletions(-) create mode 100644 examples/shared/dtlsconnection.h delete mode 100644 examples/shared/mbedtlsconnection.h create mode 100644 examples/shared/object_utils.c create mode 100644 examples/shared/object_utils.h delete mode 100644 examples/shared/tinydtlsconnection.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 9b8b9be39..116938454 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,11 +7,5 @@ if (CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME) enable_testing() endif() -if(DTLS_MBEDTLS) - message("Skipping tests") -else() - message("Adding tests") - add_subdirectory(tests) -endif() - +add_subdirectory(tests) add_subdirectory(examples) diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 199d53651..195ece550 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -6,16 +6,12 @@ add_compile_options(-pedantic) if(DTLS_MBEDTLS) option(ENABLE_PROGRAMS "Build mbed TLS programs." OFF) option(ENABLE_TESTING "Build mbed TLS tests." OFF) - include_directories(${CMAKE_CURRENT_LIST_DIR}/shared/dtls/mbedtls/include) - # Use custom config file for Mbed TLS - add_definitions(-DMBEDTLS_CONFIG_FILE="${CMAKE_CURRENT_LIST_DIR}/shared/dtls/config-ccm-psk-tls1_2.h") add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/shared/dtls/mbedtls) - - include_directories(${CMAKE_CURRENT_LIST_DIR}/client) - add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/client) else() - add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/bootstrap_server) - add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/client) add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/lightclient) - add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/server) endif() + +add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/bootstrap_server) +add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/client) +add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/server) + diff --git a/examples/bootstrap_server/bootstrap_server.c b/examples/bootstrap_server/bootstrap_server.c index 2995c75bb..a6dbfc870 100644 --- a/examples/bootstrap_server/bootstrap_server.c +++ b/examples/bootstrap_server/bootstrap_server.c @@ -57,11 +57,11 @@ typedef struct _endpoint_ typedef struct { - int sock; - connection_t * connList; - bs_info_t * bsInfo; - endpoint_t * endpointList; - int addressFamily; + int sock; + lwm2m_connection_layer_t * connLayer; + bs_info_t * bsInfo; + endpoint_t * endpointList; + int addressFamily; } internal_data_t; #define MAX_PACKET_SIZE 2048 @@ -536,12 +536,11 @@ static void prv_bootstrap_client(lwm2m_context_t *lwm2mH, port++; fprintf(stderr, "Trying to connect to LWM2M CLient at %s:%s\r\n", host, port); - newConnP = connection_create(dataP->connList, dataP->sock, host, port, dataP->addressFamily); + newConnP = connection_create(dataP->connLayer, dataP->sock, host, port, dataP->addressFamily); if (newConnP == NULL) { fprintf(stderr, "Connection creation failed.\r\n"); return; } - dataP->connList = newConnP; // simulate a client bootstrap request. // Only LWM2M 1.0 clients support this method of bootstrap. For them, TLV @@ -654,6 +653,8 @@ int main(int argc, char *argv[]) return -1; } + data.connLayer = connectionlayer_create(lwm2mH); + signal(SIGINT, handle_sigint); fd = fopen(filename, "r"); @@ -749,19 +750,12 @@ int main(int argc, char *argv[]) output_buffer(stderr, buffer, numBytes, 0); - connP = connection_find(data.connList, &addr, addrLen); + connP = connectionlayer_find_connection(data.connLayer, &addr, addrLen); if (connP == NULL) { - connP = connection_new_incoming(data.connList, data.sock, (struct sockaddr *)&addr, addrLen); - if (connP != NULL) - { - data.connList = connP; - } - } - if (connP != NULL) - { - lwm2m_handle_packet(lwm2mH, buffer, numBytes, connP); + connP = connection_new_incoming(data.connLayer, data.sock, &addr, addrLen); } + connectionlayer_handle_packet(data.connLayer, &addr, addrLen, buffer, numBytes); } } // command line input @@ -834,7 +828,7 @@ int main(int argc, char *argv[]) prv_endpoint_free(endP); } close(data.sock); - connection_free(data.connList); + connectionlayer_free(data.connLayer); return 0; } diff --git a/examples/client/lwm2mclient.c b/examples/client/lwm2mclient.c index 279b1f01f..ad950477c 100644 --- a/examples/client/lwm2mclient.c +++ b/examples/client/lwm2mclient.c @@ -59,13 +59,11 @@ #include "lwm2mclient.h" #include "liblwm2m.h" #include "commandline.h" -#ifdef WITH_TINYDTLS -#include "tinydtlsconnection.h" -#elif defined(WITH_MBEDTLS) -#include "mbedtlsconnection.h" -#include "connection.h" +#if defined(WITH_TINYDTLS) || defined(WITH_MBEDTLS) +#include "dtlsconnection.h" #endif - +#include "connection.h" +#include "object_utils.h" #include #include #include @@ -191,35 +189,12 @@ void handle_value_changed(lwm2m_context_t * lwm2mH, fprintf(stderr, "Object not found !\n"); } } -#ifndef WITH_MBEDTLS -#ifdef WITH_TINYDTLS -void * lwm2m_connect_server(uint16_t secObjInstID, - void * userData) -{ - client_data_t * dataP; - lwm2m_list_t * instance; - dtls_connection_t * newConnP = NULL; - dataP = (client_data_t *)userData; - lwm2m_object_t * securityObj = dataP->securityObjP; - instance = LWM2M_LIST_FIND(dataP->securityObjP->instanceList, secObjInstID); - if (instance == NULL) return NULL; - - - newConnP = connection_create(dataP->connList, dataP->sock, securityObj, instance->id, dataP->lwm2mH, dataP->addressFamily); - if (newConnP == NULL) - { - fprintf(stderr, "Connection creation failed.\n"); - return NULL; - } - - dataP->connList = newConnP; - return (void *)newConnP; -} -#else void * lwm2m_connect_server(uint16_t secObjInstID, void * userData) { + int securityMode = 0; + int ret = 0; client_data_t * dataP; char * uri; char * host; @@ -259,63 +234,38 @@ void * lwm2m_connect_server(uint16_t secObjInstID, port++; fprintf(stderr, "Opening connection to server at %s:%s\r\n", host, port); - newConnP = connection_create(dataP->connList, dataP->sock, host, port, dataP->addressFamily); + ret = security_get_security_mode(dataP->ctx, secObjInstID, &securityMode); + if(ret <= 0){ + goto exit; + } + if(securityMode == LWM2M_SECURITY_MODE_PRE_SHARED_KEY) { + #if defined(WITH_TINYDTLS) || defined(WITH_MBEDTLS) + newConnP = (connection_t*)dtlsconnection_create(dataP->connLayer, secObjInstID, dataP->sock, host, port, dataP->addressFamily); + #endif + } + else if(securityMode == LWM2M_SECURITY_MODE_NONE) { + newConnP = connection_create(dataP->connLayer, dataP->sock, host, port, dataP->addressFamily); + } + if (newConnP == NULL) { fprintf(stderr, "Connection creation failed.\r\n"); } - else { - dataP->connList = newConnP; - } exit: lwm2m_free(uri); return (void *)newConnP; } -#endif void lwm2m_close_connection(void * sessionH, void * userData) { client_data_t * app_data; -#ifdef WITH_TINYDTLS - dtls_connection_t * targetP; -#else connection_t * targetP; -#endif app_data = (client_data_t *)userData; -#ifdef WITH_TINYDTLS - targetP = (dtls_connection_t *)sessionH; -#else targetP = (connection_t *)sessionH; -#endif - - if (targetP == app_data->connList) - { - app_data->connList = targetP->next; - lwm2m_free(targetP); - } - else - { -#ifdef WITH_TINYDTLS - dtls_connection_t * parentP; -#else - connection_t * parentP; -#endif - - parentP = app_data->connList; - while (parentP != NULL && parentP->next != targetP) - { - parentP = parentP->next; - } - if (parentP != NULL) - { - parentP->next = targetP->next; - lwm2m_free(targetP); - } - } + connectionlayer_free_connection(app_data->connLayer, targetP); } -#endif static void prv_output_servers(lwm2m_context_t * lwm2mH, char * buffer, @@ -1031,7 +981,6 @@ int main(int argc, char *argv[]) server = (AF_INET == data.addressFamily ? DEFAULT_SERVER_IPV4 : DEFAULT_SERVER_IPV6); } -#ifndef WITH_MBEDTLS /* *This call an internal function that create an IPV6 socket on the port 5683. */ @@ -1042,7 +991,6 @@ int main(int argc, char *argv[]) fprintf(stderr, "Failed to open socket: %d %s\r\n", errno, strerror(errno)); return -1; } -#endif /* * Now the main function fill an array with each object, this list will be later passed to liblwm2m. @@ -1181,7 +1129,7 @@ int main(int argc, char *argv[]) return -1; } data.ctx = lwm2mH; - + data.connLayer = connectionlayer_create(lwm2mH); /* * We configure the liblwm2m library with the name of the client - which shall be unique for each client - * the number of objects we will be passing through and the objects array @@ -1220,7 +1168,7 @@ int main(int argc, char *argv[]) { reboot_time = tv_sec + 5; } - if (reboot_time < tv_sec) + if (reboot_time <= tv_sec) { /* * Message should normally be lost with reboot ... @@ -1245,17 +1193,7 @@ int main(int argc, char *argv[]) tv.tv_usec = 0; FD_ZERO(&readfds); -#ifndef WITH_MBEDTLS FD_SET(data.sock, &readfds); -#else - int sockSize = 0; - int * socks = mbedtls_get_sockets(lwm2mH, &sockSize); - if(socks != NULL) { - for(int i = 0; i < sockSize; i++) { - FD_SET(socks[i], &readfds); - } - } -#endif FD_SET(STDIN_FILENO, &readfds); /* @@ -1328,7 +1266,6 @@ int main(int argc, char *argv[]) { uint8_t buffer[MAX_PACKET_SIZE]; int numBytes; -#ifndef WITH_MBEDTLS /* * If an event happens on the socket */ @@ -1356,12 +1293,7 @@ int main(int argc, char *argv[]) { char s[INET6_ADDRSTRLEN]; in_port_t port; - -#ifdef WITH_TINYDTLS - dtls_connection_t * connP; -#else connection_t * connP; -#endif if (AF_INET == addr.ss_family) { struct sockaddr_in *saddr = (struct sockaddr_in *)&addr; @@ -1381,21 +1313,13 @@ int main(int argc, char *argv[]) */ output_buffer(stderr, buffer, numBytes, 0); - connP = connection_find(data.connList, &addr, addrLen); + connP = connectionlayer_find_connection(data.connLayer, &addr, addrLen); if (connP != NULL) { /* * Let liblwm2m respond to the query depending on the context */ -#ifdef WITH_TINYDTLS - int result = connection_handle_packet(connP, buffer, numBytes); - if (0 != result) - { - printf("error handling message %d\n",result); - } -#else - lwm2m_handle_packet(lwm2mH, buffer, numBytes, connP); -#endif + connectionlayer_handle_packet(data.connLayer, &addr, addrLen, buffer, numBytes); conn_s_updateRxStatistic(objArray[7], numBytes, false); } else @@ -1409,19 +1333,6 @@ int main(int argc, char *argv[]) * If the event happened on the SDTIN */ else if (FD_ISSET(STDIN_FILENO, &readfds)) - #else - for(int i = 0; i < sockSize; i++) { - if(FD_ISSET(socks[i], &readfds)) { - void * connection = NULL; - numBytes = mbedtls_receive(lwm2mH, socks[i], buffer, MAX_PACKET_SIZE, &connection); - if(numBytes > 0) { - lwm2m_handle_packet(lwm2mH, buffer, numBytes, connection); - } - } - lwm2m_free(socks); - } - if (FD_ISSET(STDIN_FILENO, &readfds)) - #endif { numBytes = read(STDIN_FILENO, buffer, MAX_PACKET_SIZE - 1); @@ -1460,10 +1371,8 @@ int main(int argc, char *argv[]) #endif lwm2m_close(lwm2mH); } -#ifndef WITH_MBEDTLS close(data.sock); - connection_free(data.connList); -#endif + connectionlayer_free(data.connLayer); clean_security_object(objArray[0]); lwm2m_free(objArray[0]); diff --git a/examples/client/lwm2mclient.h b/examples/client/lwm2mclient.h index a5268637a..3242de662 100644 --- a/examples/client/lwm2mclient.h +++ b/examples/client/lwm2mclient.h @@ -28,6 +28,7 @@ #define LWM2MCLIENT_H_ #include "liblwm2m.h" +#include "connection.h" extern int g_reboot; @@ -113,15 +114,8 @@ typedef struct lwm2m_object_t * securityObjP; lwm2m_object_t * serverObject; lwm2m_context_t * ctx; -#ifndef WITH_MBEDTLS int sock; -#ifdef WITH_TINYDTLS - dtls_connection_t * connList; - lwm2m_context_t * lwm2mH; -#else - connection_t * connList; -#endif -#endif + lwm2m_connection_layer_t * connLayer; int addressFamily; } client_data_t; diff --git a/examples/lightclient/lightclient.c b/examples/lightclient/lightclient.c index dcb943ba8..a92c36dbd 100644 --- a/examples/lightclient/lightclient.c +++ b/examples/lightclient/lightclient.c @@ -93,7 +93,7 @@ typedef struct { lwm2m_object_t * securityObjP; int sock; - connection_t * connList; + lwm2m_connection_layer_t * connLayer; int addressFamily; } client_data_t; @@ -149,13 +149,10 @@ void * lwm2m_connect_server(uint16_t secObjInstID, *port = 0; port++; - newConnP = connection_create(dataP->connList, dataP->sock, host, port, dataP->addressFamily); + newConnP = connection_create(dataP->connLayer, dataP->sock, host, port, dataP->addressFamily); if (newConnP == NULL) { fprintf(stderr, "Connection creation failed.\r\n"); } - else { - dataP->connList = newConnP; - } exit: lwm2m_free(uri); @@ -171,26 +168,7 @@ void lwm2m_close_connection(void * sessionH, app_data = (client_data_t *)userData; targetP = (connection_t *)sessionH; - if (targetP == app_data->connList) - { - app_data->connList = targetP->next; - lwm2m_free(targetP); - } - else - { - connection_t * parentP; - - parentP = app_data->connList; - while (parentP != NULL && parentP->next != targetP) - { - parentP = parentP->next; - } - if (parentP != NULL) - { - parentP->next = targetP->next; - lwm2m_free(targetP); - } - } + connectionlayer_free_connection(app_data->connLayer, targetP); } void print_usage(void) @@ -447,6 +425,8 @@ int main(int argc, char *argv[]) return -1; } + data.connLayer = connectionlayer_create(lwm2mH); + /* * We configure the liblwm2m library with the name of the client - which shall be unique for each client - * the number of objects we will be passing through and the objects array @@ -537,18 +517,7 @@ int main(int argc, char *argv[]) } else if (0 < numBytes) { - connection_t * connP; - - connP = connection_find(data.connList, &addr, addrLen); - if (connP != NULL) - { - /* - * Let liblwm2m respond to the query depending on the context - */ - lwm2m_handle_packet(lwm2mH, buffer, numBytes, connP); - } - else - { + if (-1 == connectionlayer_handle_packet(data.connLayer, &addr, addrLen, buffer, numBytes)) { /* * This packet comes from an unknown peer */ @@ -564,7 +533,7 @@ int main(int argc, char *argv[]) */ lwm2m_close(lwm2mH); close(data.sock); - connection_free(data.connList); + connectionlayer_free(data.connLayer); free_security_object(objArray[0]); free_server_object(objArray[1]); diff --git a/examples/server/lwm2mserver.c b/examples/server/lwm2mserver.c index 75d537a33..a48be31c2 100644 --- a/examples/server/lwm2mserver.c +++ b/examples/server/lwm2mserver.c @@ -1046,7 +1046,7 @@ int main(int argc, char *argv[]) struct timeval tv; int result; lwm2m_context_t * lwm2mH = NULL; - connection_t * connList = NULL; + lwm2m_connection_layer_t * connLayer = NULL; int addressFamily = AF_INET6; int opt; const char * localPort = LWM2M_STANDARD_PORT_STR; @@ -1174,6 +1174,7 @@ int main(int argc, char *argv[]) fprintf(stderr, "lwm2m_init() failed\r\n"); return -1; } + connLayer = connectionlayer_create(lwm2mH); signal(SIGINT, handle_sigint); @@ -1250,19 +1251,12 @@ int main(int argc, char *argv[]) fprintf(stderr, "%d bytes received from [%s]:%hu\r\n", numBytes, s, ntohs(port)); output_buffer(stderr, buffer, numBytes, 0); - connP = connection_find(connList, &addr, addrLen); + connP = connectionlayer_find_connection(connLayer, &addr, addrLen); if (connP == NULL) { - connP = connection_new_incoming(connList, sock, (struct sockaddr *)&addr, addrLen); - if (connP != NULL) - { - connList = connP; - } - } - if (connP != NULL) - { - lwm2m_handle_packet(lwm2mH, buffer, numBytes, connP); + connection_new_incoming(connLayer, sock, &addr, addrLen); } + connectionlayer_handle_packet(connLayer, &addr, addrLen, buffer, numBytes); } } else if (FD_ISSET(STDIN_FILENO, &readfds)) @@ -1290,7 +1284,7 @@ int main(int argc, char *argv[]) lwm2m_close(lwm2mH); close(sock); - connection_free(connList); + connectionlayer_free(connLayer); #ifdef MEMORY_TRACE if (g_quit == 1) diff --git a/examples/shared/commandline.h b/examples/shared/commandline.h index fdb5a51f1..c984f7633 100644 --- a/examples/shared/commandline.h +++ b/examples/shared/commandline.h @@ -16,6 +16,7 @@ *******************************************************************************/ #include +#include "liblwm2m.h" #define COMMAND_END_LIST {NULL, NULL, NULL, NULL, NULL} diff --git a/examples/shared/connection.c b/examples/shared/connection.c index 39b305458..7f6e6f76d 100644 --- a/examples/shared/connection.c +++ b/examples/shared/connection.c @@ -26,6 +26,117 @@ #include #include +static int connection_send(uint8_t const * buffer, + size_t length, + void* userData) +{ + int nbSent; + size_t offset; + connection_t *connP = (connection_t*)userData; + offset = 0; + while (offset != length) + { + nbSent = sendto(connP->sock, buffer + offset, length - offset, 0, (struct sockaddr *)&(connP->addr), connP->addrLen); + if (nbSent == -1) return -1; + offset += nbSent; + } + return 0; +} + +static int connection_recv(lwm2m_context_t * ctx, uint8_t * buffer, size_t length, void* userData) +{ + lwm2m_handle_packet(ctx, buffer, length, userData); + return 0; +} + +static connection_t * connection_find(connection_t * connList, + struct sockaddr_storage const * addr, + size_t addrLen) +{ + connection_t * connP; + + connP = connList; + while (connP != NULL) + { + if ((connP->addrLen == addrLen) + && (memcmp(&(connP->addr), addr, addrLen) == 0)) + { + return connP; + } + connP = connP->next; + } + + return connP; +} + +static void connection_free(connection_t * conn) +{ + if(conn->deinitFunc) { + conn->deinitFunc(conn); + } + lwm2m_free(conn); +} + +static void connectionlayer_free_connlist(connection_t * connList) { + while (connList != NULL) + { + connection_t * nextP; + + nextP = connList->next; + connection_free(connList); + + connList = nextP; + } +} + +lwm2m_connection_layer_t * connectionlayer_create(lwm2m_context_t * context) +{ + lwm2m_connection_layer_t * layerCtx = (lwm2m_connection_layer_t *)lwm2m_malloc(sizeof(lwm2m_connection_layer_t)); + if (layerCtx == NULL) { + return NULL; + } + layerCtx->ctx = context; + layerCtx->connList = NULL; + return layerCtx; +} + +int connectionlayer_handle_packet(lwm2m_connection_layer_t * connLayerP, struct sockaddr_storage * addr, size_t addrLen, uint8_t * buffer, size_t length) { + connection_t * connP = connection_find(connLayerP->connList, addr, addrLen); + if(connP == NULL) { + return -1; + } + return connP->recvFunc(connLayerP->ctx, buffer, length, connP); +} + +connection_t * connectionlayer_find_connection(lwm2m_connection_layer_t * connLayerP, struct sockaddr_storage const * addr, size_t addrLen) { + return connection_find(connLayerP->connList, addr, addrLen); +} + +void connectionlayer_free(lwm2m_connection_layer_t * connLayerP) { + if(connLayerP == NULL) { + return; + } + connectionlayer_free_connlist(connLayerP->connList); + lwm2m_free(connLayerP); +} + +void connectionlayer_free_connection(lwm2m_connection_layer_t * connLayerP, connection_t * conn) { + connection_t * connItor = connLayerP->connList; + if(connLayerP->connList == conn) { + connLayerP->connList = conn->next; + connection_free(conn); + } + else { + while(connItor != NULL && connItor->next != conn) { + connItor = connItor->next; + } + if(connItor != NULL) { + connItor->next = conn->next; + connection_free(conn); + } + } +} + int create_socket(const char * portStr, int addressFamily) { int s = -1; @@ -61,64 +172,60 @@ int create_socket(const char * portStr, int addressFamily) return s; } -connection_t * connection_find(connection_t * connList, - struct sockaddr_storage * addr, - size_t addrLen) -{ - connection_t * connP; - - connP = connList; - while (connP != NULL) - { - if ((connP->addrLen == addrLen) - && (memcmp(&(connP->addr), addr, addrLen) == 0)) - { - return connP; - } - connP = connP->next; - } +void connectionlayer_add_connection(lwm2m_connection_layer_t * connLayer, connection_t * conn) { + conn->next = connLayer->connList; + connLayer->connList = conn; +} - return connP; +static void connection_new_incoming_internal(connection_t * conn, int sock, struct sockaddr_storage * addr, size_t addrLen) { + conn->sock = sock; + memcpy(&(conn->addr), addr, addrLen); + conn->addrLen = addrLen; + conn->sendFunc = connection_send; + conn->recvFunc = connection_recv; } -connection_t * connection_new_incoming(connection_t * connList, - int sock, - struct sockaddr * addr, - size_t addrLen) +connection_t * connection_new_incoming(lwm2m_connection_layer_t * connLayerP, int sock, struct sockaddr_storage * addr, size_t addrLen) { - connection_t * connP; - - connP = (connection_t *)lwm2m_malloc(sizeof(connection_t)); + connection_t * connP = (connection_t *)lwm2m_malloc(sizeof(connection_t)); if (connP != NULL) { - connP->sock = sock; - memcpy(&(connP->addr), addr, addrLen); - connP->addrLen = addrLen; - connP->next = connList; + connection_new_incoming_internal(connP, sock, addr, addrLen); + connectionlayer_add_connection(connLayerP, connP); } return connP; } -connection_t * connection_create(connection_t * connList, - int sock, - char * host, - char * port, - int addressFamily) +connection_t * connection_create(lwm2m_connection_layer_t * connLayerP, int sock, char * host, char * port, int addressFamily) { + connection_t * conn = (connection_t *)lwm2m_malloc(sizeof(connection_t)); + if(conn == NULL) { + return NULL; + } + if(connection_create_inplace(conn, sock, host, port, addressFamily) > 0) { + connectionlayer_add_connection(connLayerP, conn); + } + else { + lwm2m_free(conn); + conn = NULL; + } + return conn; +} + +int connection_create_inplace(connection_t * conn, int sock, char * host, char * port, int addressFamily) { struct addrinfo hints; struct addrinfo *servinfo = NULL; struct addrinfo *p; int s; struct sockaddr *sa; socklen_t sl; - connection_t * connP = NULL; memset(&hints, 0, sizeof(hints)); hints.ai_family = addressFamily; hints.ai_socktype = SOCK_DGRAM; - if (0 != getaddrinfo(host, port, &hints, &servinfo) || servinfo == NULL) return NULL; + if (0 != getaddrinfo(host, port, &hints, &servinfo) || servinfo == NULL) return -1; // we test the various addresses s = -1; @@ -138,35 +245,31 @@ connection_t * connection_create(connection_t * connList, } if (s >= 0) { - connP = connection_new_incoming(connList, sock, sa, sl); + connection_new_incoming_internal(conn, sock, (struct sockaddr_storage*)sa, sl); close(s); + return 1; } if (NULL != servinfo) { freeaddrinfo(servinfo); } - return connP; + return 0; } -void connection_free(connection_t * connList) +uint8_t lwm2m_buffer_send(void * sessionH, + uint8_t * buffer, + size_t length, + void * userdata) { - while (connList != NULL) - { - connection_t * nextP; + connection_t * connP = (connection_t*) sessionH; - nextP = connList->next; - lwm2m_free(connList); + (void)userdata; /* unused */ - connList = nextP; + if (connP == NULL) + { + fprintf(stderr, "#> failed sending %lu bytes, missing connection\r\n", length); + return COAP_500_INTERNAL_SERVER_ERROR ; } -} - -int connection_send(connection_t *connP, - uint8_t * buffer, - size_t length) -{ - int nbSent; - size_t offset; #ifdef LWM2M_WITH_LOGS char s[INET6_ADDRSTRLEN]; @@ -192,32 +295,7 @@ int connection_send(connection_t *connP, output_buffer(stderr, buffer, length, 0); #endif - offset = 0; - while (offset != length) - { - nbSent = sendto(connP->sock, buffer + offset, length - offset, 0, (struct sockaddr *)&(connP->addr), connP->addrLen); - if (nbSent == -1) return -1; - offset += nbSent; - } - return 0; -} - -uint8_t lwm2m_buffer_send(void * sessionH, - uint8_t * buffer, - size_t length, - void * userdata) -{ - connection_t * connP = (connection_t*) sessionH; - - (void)userdata; /* unused */ - - if (connP == NULL) - { - fprintf(stderr, "#> failed sending %lu bytes, missing connection\r\n", length); - return COAP_500_INTERNAL_SERVER_ERROR ; - } - - if (-1 == connection_send(connP, buffer, length)) + if (-1 == connP->sendFunc(buffer, length, connP)) { fprintf(stderr, "#> failed sending %lu bytes\r\n", length); return COAP_500_INTERNAL_SERVER_ERROR ; @@ -234,3 +312,58 @@ bool lwm2m_session_is_equal(void * session1, return (session1 == session2); } + + +/* + +int get_port(struct sockaddr *x) +{ + if (x->sa_family == AF_INET) + { + return ((struct sockaddr_in *)x)->sin_port; + } else if (x->sa_family == AF_INET6) { + return ((struct sockaddr_in6 *)x)->sin6_port; + } else { + printf("non IPV4 or IPV6 address\n"); + return -1; + } +} + +int sockaddr_cmp(struct sockaddr *x, struct sockaddr *y) +{ + int portX = get_port(x); + int portY = get_port(y); + + // if the port is invalid of different + if (portX == -1 || portX != portY) + { + return 0; + } + + // IPV4? + if (x->sa_family == AF_INET) + { + // is V4? + if (y->sa_family == AF_INET) + { + // compare V4 with V4 + return ((struct sockaddr_in *)x)->sin_addr.s_addr == ((struct sockaddr_in *)y)->sin_addr.s_addr; + // is V6 mapped V4? + } else if (IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)y)->sin6_addr)) { + struct in6_addr* addr6 = &((struct sockaddr_in6 *)y)->sin6_addr; + uint32_t y6to4 = addr6->s6_addr[15] << 24 | addr6->s6_addr[14] << 16 | addr6->s6_addr[13] << 8 | addr6->s6_addr[12]; + return y6to4 == ((struct sockaddr_in *)x)->sin_addr.s_addr; + } else { + return 0; + } + } else if (x->sa_family == AF_INET6 && y->sa_family == AF_INET6) { + // IPV6 with IPV6 compare + return memcmp(((struct sockaddr_in6 *)x)->sin6_addr.s6_addr, ((struct sockaddr_in6 *)y)->sin6_addr.s6_addr, 16) == 0; + } else { + // unknown address type + printf("non IPV4 or IPV6 address\n"); + return 0; + } +} + +*/ \ No newline at end of file diff --git a/examples/shared/connection.h b/examples/shared/connection.h index 6e8d02f75..45e39fc48 100644 --- a/examples/shared/connection.h +++ b/examples/shared/connection.h @@ -34,22 +34,47 @@ #define LWM2M_BSSERVER_PORT_STR "5685" #define LWM2M_BSSERVER_PORT 5685 +typedef int (*connection_send_func_t)(uint8_t const *, size_t, void*); +typedef int (*connection_recv_func_t)(lwm2m_context_t *, uint8_t *, size_t, void*); +typedef void (*connection_deinit_func_t)(void*); + typedef struct _connection_t { - struct _connection_t * next; - int sock; - struct sockaddr_in6 addr; - size_t addrLen; + struct _connection_t * next; + int sock; + struct sockaddr_in6 addr; + size_t addrLen; + connection_send_func_t sendFunc; + connection_recv_func_t recvFunc; + connection_deinit_func_t deinitFunc; } connection_t; +typedef struct _lwm2m_connection_layer_t { + lwm2m_context_t * ctx; + connection_t * connList; +} lwm2m_connection_layer_t; + +lwm2m_connection_layer_t * connectionlayer_create(lwm2m_context_t * context); +int connectionlayer_handle_packet(lwm2m_connection_layer_t * connLayerP, struct sockaddr_storage * addr, size_t addrLen, uint8_t * buffer, size_t length); +void connectionlayer_free(lwm2m_connection_layer_t * connLayerP); +void connectionlayer_free_connection(lwm2m_connection_layer_t * connLayerP, connection_t * conn); +connection_t * connectionlayer_find_connection(lwm2m_connection_layer_t * connLayerP, struct sockaddr_storage const * addr, size_t addrLen); +void connectionlayer_add_connection(lwm2m_connection_layer_t * connLayer, connection_t * conn); + int create_socket(const char * portStr, int ai_family); -connection_t * connection_find(connection_t * connList, struct sockaddr_storage * addr, size_t addrLen); -connection_t * connection_new_incoming(connection_t * connList, int sock, struct sockaddr * addr, size_t addrLen); -connection_t * connection_create(connection_t * connList, int sock, char * host, char * port, int addressFamily); -void connection_free(connection_t * connList); +connection_t * connection_new_incoming(lwm2m_connection_layer_t * connLayerP, int sock, struct sockaddr_storage * addr, size_t addrLen); +connection_t * connection_create(lwm2m_connection_layer_t * connLayerP, int sock, char * host, char * port, int addressFamily); +int connection_create_inplace(connection_t * conn, int sock, char * host, char * port, int addressFamily); +// todo +/* +- +- mbedtls: + - dtlsconnection mbedtls: add pointer to recv buffer and buffer length in mbedtlsconnection + -> mbedtls_receive checks only if data is available in buffer (or return MBEDTLS_ERR_SSL_WANT_READ) + -> no while loop in receive on WANT_READ/WANT_WRITE -int connection_send(connection_t *connP, uint8_t * buffer, size_t length); +*/ #endif diff --git a/examples/shared/dtls/tinydtls.cmake b/examples/shared/dtls/tinydtls.cmake index a625d2b14..850f453c6 100644 --- a/examples/shared/dtls/tinydtls.cmake +++ b/examples/shared/dtls/tinydtls.cmake @@ -21,9 +21,9 @@ set(TINYDTLS_SOURCES_GENERATED # source files are only available after tinydtls submodule have been checked out. # Create a target "submodule_update" for that purpose. -find_package(Git REQUIRED) -add_custom_command(OUTPUT ${TINYDTLS_SOURCES} COMMAND ${GIT_EXECUTABLE} submodule update) -add_custom_target(submodule_update SOURCES ${TINYDTLS_SOURCES}) +#find_package(Git REQUIRED) +#add_custom_command(OUTPUT ${TINYDTLS_SOURCES} COMMAND ${GIT_EXECUTABLE} submodule update) +#add_custom_target(submodule_update SOURCES ${TINYDTLS_SOURCES}) get_filename_component( COMPILER_FILENAME "${CMAKE_C_COMPILER}" NAME ) string( REGEX REPLACE "-[^-]+$" "" @@ -44,7 +44,7 @@ if (NOT EXISTS ${TINYDTLS_SOURCES_GENERATED}) LOG_DOWNLOAD 1 LOG_CONFIGURE 1 # Make the submodule_update target a dependency. - DEPENDS submodule_update + # DEPENDS submodule_update ) ExternalProject_Add_Step(external_tinydtls autoheader diff --git a/examples/shared/dtlsconnection.h b/examples/shared/dtlsconnection.h new file mode 100644 index 000000000..683be5044 --- /dev/null +++ b/examples/shared/dtlsconnection.h @@ -0,0 +1,13 @@ +#ifndef MBEDTLSCONNECTION_H_ +#define MBEDTLSCONNECTION_H_ + +#include "liblwm2m.h" +#include "connection.h" + +/*int * mbedtls_get_sockets(lwm2m_context_t const * ctx, int * sz); + +int mbedtls_receive(lwm2m_context_t const * ctx, int sock, uint8_t * buffer, int sz, void ** connection);*/ + +connection_t * dtlsconnection_create(lwm2m_connection_layer_t * connLayerP, uint16_t securityInstance, int sock, char * host, char * port, int addressFamily); + +#endif \ No newline at end of file diff --git a/examples/shared/mbedtlsconnection.c b/examples/shared/mbedtlsconnection.c index 59afd5786..04ca56219 100644 --- a/examples/shared/mbedtlsconnection.c +++ b/examples/shared/mbedtlsconnection.c @@ -1,217 +1,170 @@ -#ifdef LWM2M_CLIENT_MODE -#define MBEDTLS_ALLOW_PRIVATE_ACCESS +#include "dtlsconnection.h" +#if defined LWM2M_CLIENT_MODE && defined WITH_MBEDTLS #include #include #include "liblwm2m.h" -#include "mbedtls/net_sockets.h" +#include "object_utils.h" #include "mbedtls/ssl.h" #include "mbedtls/entropy.h" #include "mbedtls/ctr_drbg.h" #include "mbedtls/debug.h" #include "mbedtls/timing.h" #include "mbedtls/error.h" -#include "lwm2mclient.h" -#include "mbedtlsconnection.h" #include -#define COAP_PORT "5683" -#define COAPS_PORT "5684" -typedef struct { - mbedtls_net_context server_fd; +#define MIN(a,b) (((a)<(b))?(a):(b)) + +typedef struct _dtlsconnection_t { + connection_t conn; mbedtls_entropy_context entropy; mbedtls_ctr_drbg_context ctr_drbg; mbedtls_ssl_context ssl; mbedtls_ssl_config conf; mbedtls_timing_delay_context timer; -}dtlsconnection_t; - -static char * lwm2m_get_psk_identity(lwm2m_context_t * lwm2mH, lwm2m_object_t * obj, int instanceId, int * len) { - int numData = 1; - lwm2m_data_t * dataP = lwm2m_data_new(1); - if(dataP == NULL) return NULL; - dataP->id = LWM2M_SECURITY_PUBLIC_KEY_ID; - uint8_t ret = obj->readFunc(lwm2mH, instanceId, &numData, &dataP, obj); - char * identity = NULL; - if(ret != COAP_205_CONTENT || dataP->type != LWM2M_TYPE_OPAQUE) - { - lwm2m_data_free(1, dataP); - return NULL; - } - else { - identity = (char*)lwm2m_malloc(dataP->value.asBuffer.length); - if(identity != NULL) { - memcpy(identity, dataP->value.asBuffer.buffer, dataP->value.asBuffer.length); - *len = dataP->value.asBuffer.length; - } - - } - lwm2m_data_free(numData, dataP); - return identity; + uint8_t * recvBuffer; + size_t len; +} dtlsconnection_t; + +static void dtlsconnection_deinit(void * conn) { + dtlsconnection_t * dtlsConn = (dtlsconnection_t *)conn; + mbedtls_ssl_config_free(&dtlsConn->conf); + mbedtls_ctr_drbg_free(&dtlsConn->ctr_drbg); + mbedtls_entropy_free(&dtlsConn->entropy); + mbedtls_ssl_free(&dtlsConn->ssl); } -char * lwm2m_get_secret_key(lwm2m_context_t * lwm2mH, lwm2m_object_t * obj, int instanceId, int * length){ - int numData = 1; - lwm2m_data_t * dataP = lwm2m_data_new(numData); - if(dataP == NULL) return NULL; - dataP->id = LWM2M_SECURITY_SECRET_KEY_ID; // secret key +static int dtlsconnection_recv(lwm2m_context_t * context, uint8_t * buffer, size_t len, void* conn) { + dtlsconnection_t * dtlsConn = (dtlsconnection_t *)conn; + int ret = 0; + dtlsConn->recvBuffer = buffer; + dtlsConn->len = len; + + do { + ret = mbedtls_ssl_read(&dtlsConn->ssl, buffer, len); + } while(ret == MBEDTLS_ERR_SSL_WANT_WRITE); - uint8_t ret = obj->readFunc(lwm2mH, instanceId, &numData, &dataP, obj); - char * buf = NULL; - if (ret == COAP_205_CONTENT && dataP->type == LWM2M_TYPE_OPAQUE) - { + if(ret != MBEDTLS_ERR_SSL_WANT_READ && ret < 0) { +#if defined(MBEDTLS_ERROR_C) + char error_buf[200]; + mbedtls_strerror( ret, error_buf, 200 ); + printf("Last error was: -0x%04x - %s\n\n", (unsigned int) -ret, error_buf ); +#else + printf("Last error was: -0x%04x\n\n", (unsigned int) -ret ); +#endif /* MBEDTLS_ERROR_C */ + } - buf = (char*)lwm2m_malloc(dataP->value.asBuffer.length); - if (buf != 0) - { - memcpy(buf, dataP->value.asBuffer.buffer, dataP->value.asBuffer.length); - *length = dataP->value.asBuffer.length; - } + if(ret > 0) { + lwm2m_handle_packet(context, buffer, ret, dtlsConn); + return ret; } - lwm2m_data_free(numData, dataP); - return buf; + return 0; } -char * lwm2m_get_uri(lwm2m_context_t * lwm2mH, lwm2m_object_t * obj, int instanceId){ - int size = 1; - lwm2m_data_t * dataP = lwm2m_data_new(size); - if(dataP == NULL) return NULL; - dataP->id = LWM2M_SECURITY_URI_ID; // security server uri +static int dtlsconnection_send(uint8_t const * buffer, size_t len, void* conn) { + dtlsconnection_t * dtlsConn = (dtlsconnection_t *)conn; + int ret = 0; + do { + ret = mbedtls_ssl_write(&dtlsConn->ssl, buffer, len); + } while(ret == MBEDTLS_ERR_SSL_WANT_WRITE); - uint8_t ret = obj->readFunc(lwm2mH, instanceId, &size, &dataP, obj); - char * uri = NULL; - if (ret == COAP_205_CONTENT && dataP->type == LWM2M_TYPE_STRING && dataP->value.asBuffer.length > 0) - { - uri = (char*)lwm2m_malloc(dataP->value.asBuffer.length + 1); - if(uri != NULL) { - memset(uri,0,dataP->value.asBuffer.length+1); - memcpy(uri,dataP->value.asBuffer.buffer, dataP->value.asBuffer.length); - } + if(ret != MBEDTLS_ERR_SSL_WANT_READ && ret < 0) { +#if defined(MBEDTLS_ERROR_C) + char error_buf[200]; + mbedtls_strerror( ret, error_buf, 200 ); + printf("Last error was: -0x%04x - %s\n\n", (unsigned int) -ret, error_buf ); +#else + printf("Last error was: -0x%04x\n\n", (unsigned int) -ret ); +#endif /* MBEDTLS_ERROR_C */ } - lwm2m_data_free(size, dataP); - return uri; + return ret; } - -void * lwm2m_connect_server(uint16_t secObjInstID, void * userData) -{ - client_data_t * client_data = (client_data_t*)userData; - - char * host; - char * port; - char * uri = lwm2m_get_uri(client_data->ctx, client_data->securityObjP, secObjInstID); - if(uri == NULL) return NULL; - - char * defaultport; - if (0 == strncmp(uri, "coaps://", strlen("coaps://"))) +static int dtlsconnection_mbedtls_send(void * ctx, uint8_t const * buffer, size_t length) { + dtlsconnection_t * connP = (dtlsconnection_t*)ctx; + int nbSent; + size_t offset; + offset = 0; + while (offset != length) { - host = uri+strlen("coaps://"); - defaultport = COAPS_PORT; + nbSent = sendto(connP->conn.sock, buffer + offset, length - offset, 0, (struct sockaddr *)&(connP->conn.addr), connP->conn.addrLen); + if (nbSent == -1) return -1; + offset += nbSent; } - else if (0 == strncmp(uri, "coap://", strlen("coap://"))) - { - host = uri+strlen("coap://"); - defaultport = COAP_PORT; - } - else - { - lwm2m_free(uri); - return NULL; - } - port = strrchr(host, ':'); - if (port == NULL) - { - port = defaultport; - } - else - { - // remove brackets - if (host[0] == '[') - { - host++; - if (*(port - 1) == ']') - { - *(port - 1) = 0; - } - else - { - lwm2m_free(uri); - return NULL; - } + return length; +} + +static int dtlsconnection_mbedtls_recv(void * ctx, uint8_t * buf, size_t len) { + dtlsconnection_t * conn = (dtlsconnection_t*)ctx; + size_t minLen = MIN(len, conn->len); + if(conn->recvBuffer != NULL) { + memcpy(buf, conn->recvBuffer, minLen); + if(minLen < conn->len) { + conn->recvBuffer = conn->recvBuffer + minLen; + conn->len = conn->len - minLen; + } + else { + conn->recvBuffer = NULL; + conn->len = 0; } - // split strings - *port = 0; - port++; + + return minLen; } + return MBEDTLS_ERR_SSL_WANT_READ; +} + +connection_t * dtlsconnection_create(lwm2m_connection_layer_t * connLayerP, uint16_t securityInstance, int sock, char * host, char * port, int addressFamily) { + size_t identityLen = 0; + uint8_t * identity = NULL; + size_t pskLen = 0; + uint8_t * psk = NULL; + dtlsconnection_t * dtlsConn = NULL; - int identityLen = 0; - char * identity = lwm2m_get_psk_identity(client_data->ctx, client_data->securityObjP, secObjInstID, &identityLen); - if(identity == NULL) { - lwm2m_free(uri); + int ret = security_get_psk_identity(connLayerP->ctx, securityInstance, &identity, &identityLen); + if(ret <= 0) { return NULL; } - int pskLen = 0; - char * psk = lwm2m_get_secret_key(client_data->ctx, client_data->securityObjP, secObjInstID, &pskLen); - if(psk == NULL) { - lwm2m_free(uri); + ret = security_get_psk(connLayerP->ctx, securityInstance, &psk, &pskLen); + if(ret <= 0) { lwm2m_free(identity); return NULL; } - - dtlsconnection_t * conn = (dtlsconnection_t*)lwm2m_malloc(sizeof(dtlsconnection_t)); - int ret = 0; - if (conn == NULL) { - lwm2m_free(uri); + dtlsConn = (dtlsconnection_t*)lwm2m_malloc(sizeof(dtlsconnection_t)); + memset(dtlsConn, 0, sizeof(dtlsconnection_t)); + if(dtlsConn == NULL) { lwm2m_free(identity); lwm2m_free(psk); return NULL; } - mbedtls_net_init(&conn->server_fd ); - mbedtls_ssl_init(&conn->ssl); - mbedtls_ssl_config_init(&conn->conf); - mbedtls_ctr_drbg_init(&conn->ctr_drbg); - mbedtls_entropy_init(&conn->entropy); - if((ret = mbedtls_ctr_drbg_seed(&conn->ctr_drbg, mbedtls_entropy_func, &conn->entropy, - (const unsigned char *)identity, - strlen(identity))) != 0) { - //printf( " failed\n ! mbedtls_ctr_drbg_seed returned %d\n", ret ); - mbedtls_net_free(&conn->server_fd); - mbedtls_ssl_config_free(&conn->conf); - mbedtls_ctr_drbg_free(&conn->ctr_drbg); - mbedtls_entropy_free(&conn->entropy); - mbedtls_ssl_free(&conn->ssl); - lwm2m_free(uri); + if(connection_create_inplace(&dtlsConn->conn, sock, host, port, addressFamily) <= 0) { lwm2m_free(identity); lwm2m_free(psk); - lwm2m_free(conn); + lwm2m_free(dtlsConn); return NULL; } + dtlsConn->conn.sendFunc = dtlsconnection_send; + dtlsConn->conn.recvFunc = dtlsconnection_recv; + dtlsConn->conn.deinitFunc = dtlsconnection_deinit; - if((ret = mbedtls_net_connect(&conn->server_fd, host, port, MBEDTLS_NET_PROTO_UDP)) != 0) - { - //printf( " failed\n ! mbedtls_net_connect returned %d\n\n", ret ); - mbedtls_net_free(&conn->server_fd); - mbedtls_ssl_config_free(&conn->conf); - mbedtls_ctr_drbg_free(&conn->ctr_drbg); - mbedtls_entropy_free(&conn->entropy); - mbedtls_ssl_free(&conn->ssl); - lwm2m_free(uri); + mbedtls_ssl_init(&dtlsConn->ssl); + mbedtls_ssl_config_init(&dtlsConn->conf); + mbedtls_ctr_drbg_init(&dtlsConn->ctr_drbg); + mbedtls_entropy_init(&dtlsConn->entropy); + if((ret = mbedtls_ctr_drbg_seed(&dtlsConn->ctr_drbg, mbedtls_entropy_func, &dtlsConn->entropy, + (const unsigned char *)identity, + identityLen)) != 0) { + dtlsconnection_deinit(dtlsConn); lwm2m_free(identity); lwm2m_free(psk); - lwm2m_free(conn); + lwm2m_free(dtlsConn); return NULL; } - lwm2m_free(uri); - if((ret = mbedtls_ssl_config_defaults(&conn->conf, MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_DATAGRAM, MBEDTLS_SSL_PRESET_DEFAULT)) != 0) { - //mbedtls_printf( " failed\n ! mbedtls_ssl_config_defaults returned %d\n\n", ret ); - mbedtls_net_free(&conn->server_fd); - mbedtls_ssl_config_free(&conn->conf); - mbedtls_ctr_drbg_free(&conn->ctr_drbg); - mbedtls_entropy_free(&conn->entropy); - mbedtls_ssl_free(&conn->ssl); + + if((ret = mbedtls_ssl_config_defaults(&dtlsConn->conf, MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_DATAGRAM, MBEDTLS_SSL_PRESET_DEFAULT)) != 0) { + dtlsconnection_deinit(dtlsConn); lwm2m_free(identity); lwm2m_free(psk); - lwm2m_free(conn); + lwm2m_free(dtlsConn); return NULL; } static int ciphersuites[] = { @@ -219,130 +172,37 @@ void * lwm2m_connect_server(uint16_t secObjInstID, void * userData) 0 }; - mbedtls_ssl_conf_ciphersuites(&conn->conf, ciphersuites); + mbedtls_ssl_conf_ciphersuites(&dtlsConn->conf, ciphersuites); - if((ret = mbedtls_ssl_conf_psk(&conn->conf, (uint8_t*)psk, pskLen, (uint8_t*)identity, identityLen)) != 0) { - mbedtls_net_free(&conn->server_fd); - mbedtls_ssl_config_free(&conn->conf); - mbedtls_ctr_drbg_free(&conn->ctr_drbg); - mbedtls_entropy_free(&conn->entropy); - mbedtls_ssl_free(&conn->ssl); + if((ret = mbedtls_ssl_conf_psk(&dtlsConn->conf, (uint8_t*)psk, pskLen, (uint8_t*)identity, identityLen)) != 0) { + dtlsconnection_deinit(dtlsConn); lwm2m_free(identity); lwm2m_free(psk); - lwm2m_free(conn); + lwm2m_free(dtlsConn); return NULL; } + lwm2m_free(identity); + lwm2m_free(psk); - mbedtls_ssl_conf_rng(&conn->conf, mbedtls_ctr_drbg_random, &conn->ctr_drbg); - mbedtls_ssl_set_bio(&conn->ssl, &conn->server_fd, mbedtls_net_send, mbedtls_net_recv, mbedtls_net_recv_timeout); - // void mbedtls_ssl_conf_read_timeout( mbedtls_ssl_config *conf, uint32_t timeout ); //timeout millseconds + mbedtls_ssl_conf_rng(&dtlsConn->conf, mbedtls_ctr_drbg_random, &dtlsConn->ctr_drbg); + mbedtls_ssl_set_bio(&dtlsConn->ssl, dtlsConn, dtlsconnection_mbedtls_send, dtlsconnection_mbedtls_recv, NULL); - mbedtls_ssl_set_timer_cb(&conn->ssl, &conn->timer, mbedtls_timing_set_delay, mbedtls_timing_get_delay); + mbedtls_ssl_set_timer_cb(&dtlsConn->ssl, &dtlsConn->timer, mbedtls_timing_set_delay, mbedtls_timing_get_delay); - if((ret = mbedtls_ssl_setup(&conn->ssl, &conn->conf)) != 0) + if((ret = mbedtls_ssl_setup(&dtlsConn->ssl, &dtlsConn->conf)) != 0) { - //mbedtls_printf( " failed\n ! mbedtls_ssl_setup returned %d\n\n", ret ); - mbedtls_net_free(&conn->server_fd); - mbedtls_ssl_config_free(&conn->conf); - mbedtls_ctr_drbg_free(&conn->ctr_drbg); - mbedtls_entropy_free(&conn->entropy); - mbedtls_ssl_free(&conn->ssl); - lwm2m_free(identity); - lwm2m_free(psk); - lwm2m_free(conn); + dtlsconnection_deinit(dtlsConn); + lwm2m_free(dtlsConn); return NULL; } - return conn; -} - -void lwm2m_close_connection(void * sessionH, void * userData) -{ - dtlsconnection_t * conn = (dtlsconnection_t*)sessionH; - mbedtls_net_free(&conn->server_fd); - mbedtls_ssl_config_free(&conn->conf); - mbedtls_ctr_drbg_free(&conn->ctr_drbg); - mbedtls_entropy_free(&conn->entropy); - mbedtls_ssl_free(&conn->ssl); -} - -uint8_t lwm2m_buffer_send(void * sessionH, - uint8_t * buffer, - size_t length, - void * userdata) -{ - int ret = 0; - dtlsconnection_t * conn = (dtlsconnection_t*)sessionH; - do { - ret = mbedtls_ssl_write(&conn->ssl, buffer, length); - }while(ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE); - - if(ret < 0) { -#if defined(MBEDTLS_ERROR_C) - char error_buf[200]; - mbedtls_strerror( ret, error_buf, 200 ); - printf("Last error was: -0x%04x - %s\n\n", (unsigned int) -ret, error_buf ); -#else - printf("Last error was: -0x%04x\n\n", (unsigned int) -ret ); -#endif /* MBEDTLS_ERROR_C */ - - } - - return COAP_NO_ERROR; -} - -bool lwm2m_session_is_equal(void * session1, - void * session2, - void * userdata) -{ - (void)userdata; - return (session1 == session2); -} -int * mbedtls_get_sockets(lwm2m_context_t const * ctx, int * cnt) { - int * socks = NULL; - *cnt = 0; - lwm2m_server_t * serv = ctx->serverList; - while(serv != NULL) { - if(serv->sessionH != NULL) { - dtlsconnection_t * conn = (dtlsconnection_t *)serv->sessionH; - if(conn->server_fd.fd > 0) { - int * newSocks = lwm2m_malloc(sizeof(int)*((*cnt) + 1)); - memcpy(newSocks, socks, *cnt); - newSocks[*cnt] = conn->server_fd.fd; - lwm2m_free(socks); - socks = newSocks; - (*cnt)++; - } - } - - serv = serv->next; - } - return socks; + connectionlayer_add_connection(connLayerP, (connection_t*)dtlsConn); + return (connection_t*)dtlsConn; } -int mbedtls_receive(lwm2m_context_t const * ctx, int sock, uint8_t * buffer, int sz, void ** connection) { - lwm2m_server_t * serv = ctx->serverList; - dtlsconnection_t * conn = NULL; - while(serv != NULL && conn == NULL) { - if(serv->sessionH != NULL) { - conn = (dtlsconnection_t *)serv->sessionH; - if(conn->server_fd.fd != sock) { - conn == NULL; - } - } - serv = serv->next; - } - if(conn == NULL) { - return 0; - } - int ret = 0; - do { - ret = mbedtls_ssl_read(&conn->ssl, buffer, sz); - } while(ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE); - *connection = conn; - return ret; +#else +connection_t * dtlsconnection_create(lwm2m_connection_layer_t * connLayerP, uint16_t securityInstance, int sock, char * host, char * port, int addressFamily) { + return NULL; } - - #endif \ No newline at end of file diff --git a/examples/shared/mbedtlsconnection.h b/examples/shared/mbedtlsconnection.h deleted file mode 100644 index ef98c0476..000000000 --- a/examples/shared/mbedtlsconnection.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef MBEDTLSCONNECTION_H_ -#define MBEDTLSCONNECTION_H_ - -#include "liblwm2m.h" - -int * mbedtls_get_sockets(lwm2m_context_t const * ctx, int * sz); - -int mbedtls_receive(lwm2m_context_t const * ctx, int sock, uint8_t * buffer, int sz, void ** connection); - - - -#endif \ No newline at end of file diff --git a/examples/shared/object_utils.c b/examples/shared/object_utils.c new file mode 100644 index 000000000..95f8b10df --- /dev/null +++ b/examples/shared/object_utils.c @@ -0,0 +1,96 @@ +#include "object_utils.h" +#include + +#ifdef LWM2M_CLIENT_MODE + +int object_get_int(lwm2m_context_t * clientCtx, uint16_t objId, uint16_t instanceId, uint16_t resourceId, int * value) { + lwm2m_object_t * obj = (lwm2m_object_t*)LWM2M_LIST_FIND(clientCtx->objectList, objId); + int64_t i64 = 0; + int ret = 0; + if(obj == NULL) { + return 0; + } + int numData = 1; + lwm2m_data_t * data = lwm2m_data_new(1); + if(data == NULL) { + return 0; + } + data->id = resourceId; + uint8_t coapRet = obj->readFunc(clientCtx, instanceId, &numData, &data, obj); + if(coapRet == COAP_205_CONTENT) { + if(lwm2m_data_decode_int(data, &i64) == 1) { + *value = (int)i64; + ret = 1; + } + } + lwm2m_data_free(1, data); + return ret; +} + +int object_get_str(lwm2m_context_t * clientCtx, uint16_t objId, uint16_t instanceId, uint16_t resourceId, char ** value) { + lwm2m_object_t * obj = (lwm2m_object_t*)LWM2M_LIST_FIND(clientCtx->objectList, objId); + int ret = 0; + if(obj == NULL) { + return 0; + } + int numData = 1; + lwm2m_data_t * data = lwm2m_data_new(1); + if(data == NULL) { + return 0; + } + data->id = resourceId; + uint8_t coapRet = obj->readFunc(clientCtx, instanceId, &numData, &data, obj); + if(coapRet == COAP_205_CONTENT) { + if(data->type == LWM2M_TYPE_STRING) { + *value = lwm2m_malloc(data->value.asBuffer.length + 1); + if(*value != NULL) { + memset(*value, 0, data->value.asBuffer.length + 1); + memcpy(*value, data->value.asBuffer.buffer, data->value.asBuffer.length); + ret = 1; + } + + } + } + lwm2m_data_free(1, data); + return ret; +} + +int object_get_opaque(lwm2m_context_t * clientCtx, uint16_t objId, uint16_t instanceId, uint16_t resourceId, uint8_t ** value, size_t * len) { + lwm2m_object_t * obj = (lwm2m_object_t*)LWM2M_LIST_FIND(clientCtx->objectList, objId); + int ret = 0; + if(obj == NULL) { + return 0; + } + int numData = 1; + lwm2m_data_t * data = lwm2m_data_new(1); + if(data == NULL) { + return 0; + } + data->id = resourceId; + uint8_t coapRet = obj->readFunc(clientCtx, instanceId, &numData, &data, obj); + if(coapRet == COAP_205_CONTENT) { + if(data->type == LWM2M_TYPE_OPAQUE || data->type == LWM2M_TYPE_STRING) { + *value = data->value.asBuffer.buffer; + *len = data->value.asBuffer.length; + data->value.asBuffer.buffer = NULL; + data->value.asBuffer.length = 0; + ret = 1; + } + } + lwm2m_data_free(1, data); + return ret; +} + +int security_get_psk(lwm2m_context_t * clientCtx, uint16_t securityInstanceId, uint8_t ** psk, size_t * len) { + return object_get_opaque(clientCtx, LWM2M_SECURITY_OBJECT_ID, securityInstanceId, LWM2M_SECURITY_SECRET_KEY_ID, psk, len); +} + +int security_get_psk_identity(lwm2m_context_t * clientCtx, uint16_t securityInstanceId, uint8_t ** pskId, size_t * len) { + return object_get_opaque(clientCtx, LWM2M_SECURITY_OBJECT_ID, securityInstanceId, LWM2M_SECURITY_PUBLIC_KEY_ID, pskId, len); +} + +int security_get_security_mode(lwm2m_context_t * clientCtx, uint16_t securityInstanceId, int * mode) { + return object_get_int(clientCtx, LWM2M_SECURITY_OBJECT_ID, securityInstanceId, LWM2M_SECURITY_SECURITY_ID, mode); +} + +#endif \ No newline at end of file diff --git a/examples/shared/object_utils.h b/examples/shared/object_utils.h new file mode 100644 index 000000000..fbbbcf399 --- /dev/null +++ b/examples/shared/object_utils.h @@ -0,0 +1,20 @@ +#ifndef OBJECT_UTILS_H_ +#define OBJECT_UTILS_H_ + +#include "liblwm2m.h" + +#ifdef LWM2M_CLIENT_MODE + +// generic helper functions +int object_get_int(lwm2m_context_t * clientCtx, uint16_t objId, uint16_t instanceId, uint16_t resourceId, int * value); +int object_get_str(lwm2m_context_t * clientCtx, uint16_t objId, uint16_t instanceId, uint16_t resourceId, char ** value); +int object_get_opaque(lwm2m_context_t * clientCtx, uint16_t objId, uint16_t instanceId, uint16_t resourceId, uint8_t ** value, size_t * len); + +int security_get_psk_identity(lwm2m_context_t * clientCtx, uint16_t securityInstanceId, uint8_t ** pskId, size_t * len); +int security_get_psk(lwm2m_context_t * clientCtx, uint16_t securityInstanceId, uint8_t ** psk, size_t * len); +int security_get_security_mode(lwm2m_context_t * clientCtx, uint16_t securityInstanceId, int * mode); + +#endif + + +#endif \ No newline at end of file diff --git a/examples/shared/shared.cmake b/examples/shared/shared.cmake index 16f3646bd..6e3efab3f 100644 --- a/examples/shared/shared.cmake +++ b/examples/shared/shared.cmake @@ -25,6 +25,10 @@ if(DTLS_TINYDTLS) add_compile_definitions(WITH_TINYDTLS) elseif(DTLS_MBEDTLS) + include_directories(${CMAKE_CURRENT_LIST_DIR}/dtls/mbedtls/include) + # Use custom config file for Mbed TLS + add_definitions(-DMBEDTLS_CONFIG_FILE="${CMAKE_CURRENT_LIST_DIR}/dtls/config-ccm-psk-tls1_2.h") + set(SHARED_INCLUDE_DIRS ${SHARED_SOURCES_DIR}) set(SHARED_SOURCES ${SHARED_SOURCES} @@ -32,10 +36,12 @@ elseif(DTLS_MBEDTLS) ) add_compile_definitions(WITH_MBEDTLS) else() - set(SHARED_SOURCES - ${SHARED_SOURCES} - ${SHARED_SOURCES_DIR}/connection.c - ) - set(SHARED_INCLUDE_DIRS ${SHARED_SOURCES_DIR}) endif() + + +set(SHARED_SOURCES + ${SHARED_SOURCES} + ${SHARED_SOURCES_DIR}/connection.c + ${SHARED_SOURCES_DIR}/object_utils.c +) diff --git a/examples/shared/tinydtlsconnection.c b/examples/shared/tinydtlsconnection.c index 56f2566b0..421d6895b 100644 --- a/examples/shared/tinydtlsconnection.c +++ b/examples/shared/tinydtlsconnection.c @@ -16,122 +16,37 @@ * *******************************************************************************/ +#include "dtlsconnection.h" +#ifdef LWM2M_CLIENT_MODE + #include #include #include -#include "tinydtlsconnection.h" +#include "object_utils.h" #include "commandline.h" +#include "tinydtls.h" +#include "dtls.h" #define COAP_PORT "5683" #define COAPS_PORT "5684" #define URI_LENGTH 256 -dtls_context_t * dtlsContext; +#define DTLS_NAT_TIMEOUT 40 -typedef struct _dtls_app_context_ +typedef struct _dtls_connection_t { - lwm2m_context_t * lwm2mH; - dtls_connection_t * connList; -} dtls_app_context_t; - -dtls_app_context_t appContext; - -/********************* Security Obj Helpers **********************/ -char * security_get_uri(lwm2m_context_t * lwm2mH, lwm2m_object_t * obj, int instanceId, char * uriBuffer, int bufferSize){ - int size = 1; - lwm2m_data_t * dataP = lwm2m_data_new(size); - dataP->id = 0; // security server uri - - obj->readFunc(lwm2mH, instanceId, &size, &dataP, obj); - if (dataP != NULL && - dataP->type == LWM2M_TYPE_STRING && - dataP->value.asBuffer.length > 0) - { - if (bufferSize > dataP->value.asBuffer.length){ - memset(uriBuffer,0,dataP->value.asBuffer.length+1); - strncpy(uriBuffer,(const char *)dataP->value.asBuffer.buffer,dataP->value.asBuffer.length); - lwm2m_data_free(size, dataP); - return uriBuffer; - } - } - lwm2m_data_free(size, dataP); - return NULL; -} - -int64_t security_get_mode(lwm2m_context_t * lwm2mH, lwm2m_object_t * obj, int instanceId){ - int64_t mode; - int size = 1; - lwm2m_data_t * dataP = lwm2m_data_new(size); - dataP->id = 2; // security mode - - obj->readFunc(lwm2mH, instanceId, &size, &dataP, obj); - if (0 != lwm2m_data_decode_int(dataP,&mode)) - { - lwm2m_data_free(size, dataP); - return mode; - } + connection_t conn; + session_t * dtlsSession; + int securityInstId; + dtls_context_t * dtlsContext; + time_t lastSend; // last time a data was sent to the server (used for NAT timeouts) +} dtlsconnection_t; - lwm2m_data_free(size, dataP); - fprintf(stderr, "Unable to get security mode : use not secure mode"); - return LWM2M_SECURITY_MODE_NONE; -} - -char * security_get_public_id(lwm2m_context_t * lwm2mH, lwm2m_object_t * obj, int instanceId, int * length){ - int size = 1; - lwm2m_data_t * dataP = lwm2m_data_new(size); - dataP->id = 3; // public key or id - - obj->readFunc(lwm2mH, instanceId, &size, &dataP, obj); - if (dataP != NULL && - dataP->type == LWM2M_TYPE_OPAQUE) - { - char * buff; - - buff = (char*)lwm2m_malloc(dataP->value.asBuffer.length); - if (buff != 0) - { - memcpy(buff, dataP->value.asBuffer.buffer, dataP->value.asBuffer.length); - *length = dataP->value.asBuffer.length; - } - lwm2m_data_free(size, dataP); - - return buff; - } else { - return NULL; - } -} - - -char * security_get_secret_key(lwm2m_context_t * lwm2mH, lwm2m_object_t * obj, int instanceId, int * length){ - int size = 1; - lwm2m_data_t * dataP = lwm2m_data_new(size); - dataP->id = 5; // secret key - - obj->readFunc(lwm2mH, instanceId, &size, &dataP, obj); - if (dataP != NULL && - dataP->type == LWM2M_TYPE_OPAQUE) - { - char * buff; - - buff = (char*)lwm2m_malloc(dataP->value.asBuffer.length); - if (buff != 0) - { - memcpy(buff, dataP->value.asBuffer.buffer, dataP->value.asBuffer.length); - *length = dataP->value.asBuffer.length; - } - lwm2m_data_free(size, dataP); - - return buff; - } else { - return NULL; - } -} - -/********************* Security Obj Helpers Ends **********************/ +dtls_context_t * dtlsContext; /* Returns the number sent, or -1 for errors */ -int send_data(dtls_connection_t *connP, - uint8_t * buffer, +static int send_data(dtlsconnection_t *connP, + uint8_t const * buffer, size_t length) { int nbSent; @@ -143,15 +58,15 @@ int send_data(dtls_connection_t *connP, s[0] = 0; - if (AF_INET == connP->addr.sin6_family) + if (AF_INET == connP->conn.addr.sin6_family) { - struct sockaddr_in *saddr = (struct sockaddr_in *)&connP->addr; + struct sockaddr_in *saddr = (struct sockaddr_in *)&connP->conn.addr; inet_ntop(saddr->sin_family, &saddr->sin_addr, s, INET6_ADDRSTRLEN); port = saddr->sin_port; } - else if (AF_INET6 == connP->addr.sin6_family) + else if (AF_INET6 == connP->conn.addr.sin6_family) { - struct sockaddr_in6 *saddr = (struct sockaddr_in6 *)&connP->addr; + struct sockaddr_in6 *saddr = (struct sockaddr_in6 *)&connP->conn.addr; inet_ntop(saddr->sin6_family, &saddr->sin6_addr, s, INET6_ADDRSTRLEN); port = saddr->sin6_port; } @@ -164,7 +79,7 @@ int send_data(dtls_connection_t *connP, offset = 0; while (offset != length) { - nbSent = sendto(connP->sock, buffer + offset, length - offset, 0, (struct sockaddr *)&(connP->addr), connP->addrLen); + nbSent = sendto(connP->conn.sock, buffer + offset, length - offset, 0, (struct sockaddr *)&(connP->conn.addr), connP->conn.addrLen); if (nbSent == -1) return -1; offset += nbSent; } @@ -183,10 +98,10 @@ static int get_psk_info(struct dtls_context_t *ctx, const unsigned char *id, size_t id_len, unsigned char *result, size_t result_length) { - dtls_app_context_t *appContext = (dtls_app_context_t *)ctx->app; + lwm2m_connection_layer_t * connLayer = (lwm2m_connection_layer_t *)ctx->app; // find connection - dtls_connection_t* cnx = connection_find(appContext->connList, &(session->addr.st),session->size); + dtlsconnection_t* cnx = (dtlsconnection_t*)connectionlayer_find_connection(connLayer, &(session->addr.st), session->size); if (cnx == NULL) { printf("GET PSK session not found\n"); @@ -196,32 +111,39 @@ static int get_psk_info(struct dtls_context_t *ctx, switch (type) { case DTLS_PSK_IDENTITY: { - int idLen; - char * id; - id = security_get_public_id(appContext->lwm2mH, cnx->securityObj, cnx->securityInstId, &idLen); + size_t idLen; + uint8_t * id; + int ret = security_get_psk_identity(connLayer->ctx, cnx->securityInstId, &id, &idLen); + if(ret <= 0) { + printf("cannot read psk identity from security object\n"); + return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR); + } if (result_length < idLen) { printf("cannot set psk_identity -- buffer too small\n"); return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR); } - memcpy(result, id,idLen); + memcpy(result, id, idLen); lwm2m_free(id); return idLen; } case DTLS_PSK_KEY: { - int keyLen; - char * key; - key = security_get_secret_key(appContext->lwm2mH, cnx->securityObj, cnx->securityInstId, &keyLen); - + size_t keyLen; + uint8_t * key; + int ret = security_get_psk(connLayer->ctx, cnx->securityInstId, &key, &keyLen); + if (ret <= 0) { + printf("cannot read psk from security object\n"); + return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR); + } if (result_length < keyLen) { printf("cannot set psk -- buffer too small\n"); return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR); } - memcpy(result, key,keyLen); + memcpy(result, key, keyLen); lwm2m_free(key); return keyLen; } @@ -243,10 +165,10 @@ static int get_psk_info(struct dtls_context_t *ctx, static int send_to_peer(struct dtls_context_t *ctx, session_t *session, uint8 *data, size_t len) { - dtls_app_context_t *appContext = (dtls_app_context_t *)ctx->app; + lwm2m_connection_layer_t * connLayer = (lwm2m_connection_layer_t *)ctx->app; // find connection - dtls_connection_t* cnx = connection_find(appContext->connList, &(session->addr.st),session->size); + dtlsconnection_t* cnx = (dtlsconnection_t*)connectionlayer_find_connection(connLayer, &(session->addr.st), session->size); if (cnx != NULL) { // send data to peer @@ -265,13 +187,13 @@ static int send_to_peer(struct dtls_context_t *ctx, static int read_from_peer(struct dtls_context_t *ctx, session_t *session, uint8 *data, size_t len) { - dtls_app_context_t *appContext = (dtls_app_context_t *)ctx->app; + lwm2m_connection_layer_t * connLayer = (lwm2m_connection_layer_t *)ctx->app; // find connection - dtls_connection_t* cnx = connection_find(appContext->connList, &(session->addr.st),session->size); + dtlsconnection_t* cnx = (dtlsconnection_t*)connectionlayer_find_connection(connLayer, &(session->addr.st), session->size); if (cnx != NULL) { - lwm2m_handle_packet(appContext->lwm2mH, (uint8_t*)data, len, (void*)cnx); + lwm2m_handle_packet(connLayer->ctx, (uint8_t*)data, len, (void*)cnx); return 0; } return -1; @@ -291,12 +213,10 @@ static dtls_handler_t cb = { //#endif /* DTLS_ECC */ }; -dtls_context_t * get_dtls_context(lwm2m_context_t * lwm2mH, dtls_connection_t * connList) { - appContext.lwm2mH = lwm2mH; - appContext.connList = connList; +static dtls_context_t * get_dtls_context(lwm2m_connection_layer_t * layer) { if (dtlsContext == NULL) { dtls_init(); - dtlsContext = dtls_new_context(&appContext); + dtlsContext = dtls_new_context(layer); if (dtlsContext == NULL) fprintf(stderr, "Failed to create the DTLS context\r\n"); dtls_set_handler(dtlsContext, &cb); @@ -304,359 +224,96 @@ dtls_context_t * get_dtls_context(lwm2m_context_t * lwm2mH, dtls_connection_t * return dtlsContext; } -int get_port(struct sockaddr *x) -{ - if (x->sa_family == AF_INET) - { - return ((struct sockaddr_in *)x)->sin_port; - } else if (x->sa_family == AF_INET6) { - return ((struct sockaddr_in6 *)x)->sin6_port; - } else { - printf("non IPV4 or IPV6 address\n"); - return -1; - } -} - -int sockaddr_cmp(struct sockaddr *x, struct sockaddr *y) -{ - int portX = get_port(x); - int portY = get_port(y); - - // if the port is invalid of different - if (portX == -1 || portX != portY) - { - return 0; - } - - // IPV4? - if (x->sa_family == AF_INET) - { - // is V4? - if (y->sa_family == AF_INET) - { - // compare V4 with V4 - return ((struct sockaddr_in *)x)->sin_addr.s_addr == ((struct sockaddr_in *)y)->sin_addr.s_addr; - // is V6 mapped V4? - } else if (IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)y)->sin6_addr)) { - struct in6_addr* addr6 = &((struct sockaddr_in6 *)y)->sin6_addr; - uint32_t y6to4 = addr6->s6_addr[15] << 24 | addr6->s6_addr[14] << 16 | addr6->s6_addr[13] << 8 | addr6->s6_addr[12]; - return y6to4 == ((struct sockaddr_in *)x)->sin_addr.s_addr; - } else { - return 0; - } - } else if (x->sa_family == AF_INET6 && y->sa_family == AF_INET6) { - // IPV6 with IPV6 compare - return memcmp(((struct sockaddr_in6 *)x)->sin6_addr.s6_addr, ((struct sockaddr_in6 *)y)->sin6_addr.s6_addr, 16) == 0; - } else { - // unknown address type - printf("non IPV4 or IPV6 address\n"); - return 0; - } -} - -int create_socket(const char * portStr, int ai_family) -{ - int s = -1; - struct addrinfo hints; - struct addrinfo *res; - struct addrinfo *p; - - memset(&hints, 0, sizeof hints); - hints.ai_family = ai_family; - hints.ai_socktype = SOCK_DGRAM; - hints.ai_flags = AI_PASSIVE; +static int connection_rehandshake(dtlsconnection_t * dtlsConn, bool sendCloseNotify) { - if (0 != getaddrinfo(NULL, portStr, &hints, &res)) - { - return -1; - } - - for(p = res ; p != NULL && s == -1 ; p = p->ai_next) + // reset current session + dtls_peer_t * peer = dtls_get_peer(dtlsConn->dtlsContext, dtlsConn->dtlsSession); + if (peer != NULL) { - s = socket(p->ai_family, p->ai_socktype, p->ai_protocol); - if (s >= 0) + if (!sendCloseNotify) { - if (-1 == bind(s, p->ai_addr, p->ai_addrlen)) - { - close(s); - s = -1; - } + peer->state = DTLS_STATE_CLOSED; } + dtls_reset_peer(dtlsConn->dtlsContext, peer); } - freeaddrinfo(res); - - return s; -} - -dtls_connection_t * connection_find(dtls_connection_t * connList, - const struct sockaddr_storage * addr, - size_t addrLen) -{ - dtls_connection_t * connP; - - connP = connList; - while (connP != NULL) - { - - if (sockaddr_cmp((struct sockaddr*) (&connP->addr),(struct sockaddr*) addr)) { - return connP; - } - - connP = connP->next; - } - - return connP; -} - -dtls_connection_t * connection_new_incoming(dtls_connection_t * connList, - int sock, - const struct sockaddr * addr, - size_t addrLen) -{ - dtls_connection_t * connP; - - connP = (dtls_connection_t *)malloc(sizeof(dtls_connection_t)); - if (connP != NULL) - { - memset(connP, 0, sizeof(dtls_connection_t)); - connP->sock = sock; - memcpy(&(connP->addr), addr, addrLen); - connP->addrLen = addrLen; - connP->next = connList; - - connP->dtlsSession = (session_t *)malloc(sizeof(session_t)); - memset(connP->dtlsSession, 0, sizeof(session_t)); - connP->dtlsSession->addr.sin6 = connP->addr; - connP->dtlsSession->size = connP->addrLen; - connP->lastSend = lwm2m_gettime(); + // start a fresh handshake + int result = dtls_connect(dtlsConn->dtlsContext, dtlsConn->dtlsSession); + if (result != 0) { + printf("error dtls reconnection %d\n",result); } - - return connP; + return result; } -dtls_connection_t * connection_create(dtls_connection_t * connList, - int sock, - lwm2m_object_t * securityObj, - int instanceId, - lwm2m_context_t * lwm2mH, - int addressFamily) -{ - struct addrinfo hints; - struct addrinfo *servinfo = NULL; - struct addrinfo *p; - int s; - struct sockaddr *sa; - socklen_t sl; - dtls_connection_t * connP = NULL; - char uriBuf[URI_LENGTH]; - char * uri; - char * host; - char * port; - - memset(&hints, 0, sizeof(hints)); - hints.ai_family = addressFamily; - hints.ai_socktype = SOCK_DGRAM; - - uri = security_get_uri(lwm2mH, securityObj, instanceId, uriBuf, URI_LENGTH); - if (uri == NULL) return NULL; - - // parse uri in the form "coaps://[host]:[port]" - char * defaultport; - if (0 == strncmp(uri, "coaps://", strlen("coaps://"))) - { - host = uri+strlen("coaps://"); - defaultport = COAPS_PORT; - } - else if (0 == strncmp(uri, "coap://", strlen("coap://"))) - { - host = uri+strlen("coap://"); - defaultport = COAP_PORT; - } - else - { - return NULL; - } - port = strrchr(host, ':'); - if (port == NULL) - { - port = defaultport; - } - else - { - // remove brackets - if (host[0] == '[') - { - host++; - if (*(port - 1) == ']') - { - *(port - 1) = 0; - } - else - { - return NULL; - } - } - // split strings - *port = 0; - port++; - } - - if (0 != getaddrinfo(host, port, &hints, &servinfo) || servinfo == NULL) return NULL; +static int dtlsconnection_send(uint8_t const * buffer, size_t len, void * userdata) { + dtlsconnection_t * dtlsConn = (dtlsconnection_t*)userdata; - // we test the various addresses - s = -1; - for(p = servinfo ; p != NULL && s == -1 ; p = p->ai_next) + if (DTLS_NAT_TIMEOUT > 0 && (lwm2m_gettime() - dtlsConn->lastSend) > DTLS_NAT_TIMEOUT) { - s = socket(p->ai_family, p->ai_socktype, p->ai_protocol); - if (s >= 0) + // we need to rehandhake because our source IP/port probably changed for the server + if ( connection_rehandshake(dtlsConn, false) != 0 ) { - sa = p->ai_addr; - sl = p->ai_addrlen; - if (-1 == connect(s, p->ai_addr, p->ai_addrlen)) - { - close(s); - s = -1; - } - } - } - if (s >= 0) - { - connP = connection_new_incoming(connList, sock, sa, sl); - close(s); - - // do we need to start tinydtls? - if (connP != NULL) - { - connP->securityObj = securityObj; - connP->securityInstId = instanceId; - connP->lwm2mH = lwm2mH; - - if (security_get_mode(lwm2mH, connP->securityObj,connP->securityInstId) - != LWM2M_SECURITY_MODE_NONE) - { - connP->dtlsContext = get_dtls_context(lwm2mH, connP); - } - else - { - // no dtls session - connP->dtlsSession = NULL; - } - } - } - - if (NULL != servinfo) free(servinfo); - - return connP; -} - -void connection_free(dtls_connection_t * connList) -{ - dtls_free_context(dtlsContext); - dtlsContext = NULL; - while (connList != NULL) - { - dtls_connection_t * nextP; - - nextP = connList->next; - free(connList); - - connList = nextP; - } -} - -int connection_send(dtls_connection_t *connP, uint8_t * buffer, size_t length){ - if (connP->dtlsSession == NULL) { - // no security - if (0 >= send_data(connP, buffer, length)) { - return -1 ; - } - } else { - if (DTLS_NAT_TIMEOUT > 0 && (lwm2m_gettime() - connP->lastSend) > DTLS_NAT_TIMEOUT) - { - // we need to rehandhake because our source IP/port probably changed for the server - if ( connection_rehandshake(connP, false) != 0 ) - { - printf("can't send due to rehandshake error\n"); - return -1; - } - } - if (-1 == dtls_write(connP->dtlsContext, connP->dtlsSession, buffer, length)) { + printf("can't send due to rehandshake error\n"); return -1; } } - - return 0; -} - -int connection_handle_packet(dtls_connection_t *connP, uint8_t * buffer, size_t numBytes){ - - if (connP->dtlsSession != NULL) - { - // Let liblwm2m respond to the query depending on the context - int result = dtls_handle_message(connP->dtlsContext, connP->dtlsSession, buffer, numBytes); - if (result !=0) { - printf("error dtls handling message %d\n",result); - } - return result; - } else { - // no security, just give the plaintext buffer to liblwm2m - lwm2m_handle_packet(connP->lwm2mH, buffer, numBytes, (void*)connP); - return 0; + if (-1 == dtls_write(dtlsConn->dtlsContext, dtlsConn->dtlsSession, (uint8_t*)buffer, len)) { + return -1; } + return 1; } -int connection_rehandshake(dtls_connection_t *connP, bool sendCloseNotify) { - - // if not a dtls connection we do nothing - if (connP->dtlsSession == NULL) { - return 0; - } - - // reset current session - dtls_peer_t * peer = dtls_get_peer(connP->dtlsContext, connP->dtlsSession); - if (peer != NULL) - { - if (!sendCloseNotify) - { - peer->state = DTLS_STATE_CLOSED; - } - dtls_reset_peer(connP->dtlsContext, peer); - } - - // start a fresh handshake - int result = dtls_connect(connP->dtlsContext, connP->dtlsSession); +static int dtlsconnection_recv(lwm2m_context_t * ctx, uint8_t * buffer, size_t len, void * userdata) { + (void)ctx; + dtlsconnection_t * dtlsConn = (dtlsconnection_t*)userdata; + int result = dtls_handle_message(dtlsConn->dtlsContext, dtlsConn->dtlsSession, buffer, len); if (result !=0) { - printf("error dtls reconnection %d\n",result); + printf("error dtls handling message %d\n",result); } return result; } -uint8_t lwm2m_buffer_send(void * sessionH, - uint8_t * buffer, - size_t length, - void * userdata) -{ - dtls_connection_t * connP = (dtls_connection_t*) sessionH; +static void dtlsconnection_deinit(void * userdata) { + dtlsconnection_t * dtlsConn = (dtlsconnection_t*)userdata; + dtls_close(dtlsConn->dtlsContext, dtlsConn->dtlsSession); + lwm2m_free(dtlsConn->dtlsSession); +} - if (connP == NULL) - { - fprintf(stderr, "#> failed sending %lu bytes, missing connection\r\n", length); - return COAP_500_INTERNAL_SERVER_ERROR ; +connection_t * dtlsconnection_create(lwm2m_connection_layer_t * connLayerP, uint16_t securityInstance, int sock, char * host, char * port, int addressFamily) { + dtlsconnection_t * dtlsConn = (dtlsconnection_t*)lwm2m_malloc(sizeof(dtlsconnection_t)); + if(dtlsConn == NULL) { + return NULL; } - - if (-1 == connection_send(connP, buffer, length)) - { - fprintf(stderr, "#> failed sending %lu bytes\r\n", length); - return COAP_500_INTERNAL_SERVER_ERROR ; + if(connection_create_inplace(&dtlsConn->conn, sock, host, port, addressFamily) <= 0) { + lwm2m_free(dtlsConn); + return NULL; + } + dtlsConn->dtlsSession = (session_t *)lwm2m_malloc(sizeof(session_t)); + if(dtlsConn->dtlsSession == NULL) { + lwm2m_free(dtlsConn); + } + memset(dtlsConn->dtlsSession, 0, sizeof(session_t)); + dtlsConn->dtlsSession->addr.sin6 = dtlsConn->conn.addr; + dtlsConn->dtlsSession->size = dtlsConn->conn.addrLen; + dtlsConn->lastSend = lwm2m_gettime(); + dtlsConn->securityInstId = securityInstance; + dtlsConn->dtlsContext = get_dtls_context(connLayerP); + if(dtlsConn->dtlsContext == NULL) { + lwm2m_free(dtlsConn->dtlsSession); + lwm2m_free(dtlsConn); + return NULL; } + dtlsConn->conn.sendFunc = dtlsconnection_send; + dtlsConn->conn.recvFunc = dtlsconnection_recv; + dtlsConn->conn.deinitFunc = dtlsconnection_deinit; + dtlsConn->lastSend = lwm2m_gettime(); - return COAP_NO_ERROR; + connectionlayer_add_connection(connLayerP, (connection_t*)dtlsConn); + return (connection_t*)dtlsConn; } -bool lwm2m_session_is_equal(void * session1, - void * session2, - void * userData) -{ - return (session1 == session2); +#else +connection_t * dtlsconnection_create(lwm2m_connection_layer_t * connLayerP, uint16_t securityInstance, int sock, char * host, char * port, int addressFamily) { + return NULL; } +#endif \ No newline at end of file diff --git a/examples/shared/tinydtlsconnection.h b/examples/shared/tinydtlsconnection.h deleted file mode 100644 index 7b7289d04..000000000 --- a/examples/shared/tinydtlsconnection.h +++ /dev/null @@ -1,74 +0,0 @@ -/******************************************************************************* - * - * Copyright (c) 2015 Intel Corporation and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v2.0 - * and Eclipse Distribution License v1.0 which accompany this distribution. - * - * The Eclipse Public License is available at - * http://www.eclipse.org/legal/epl-v20.html - * The Eclipse Distribution License is available at - * http://www.eclipse.org/org/documents/edl-v10.php. - * - * Contributors: - * Simon Bernard - initial API and implementation - * Christian Renz - Please refer to git log - * - *******************************************************************************/ - -#ifndef DTLS_CONNECTION_H_ -#define DTLS_CONNECTION_H_ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "tinydtls/tinydtls.h" -#include "tinydtls/dtls.h" -#include "liblwm2m.h" - -#define LWM2M_STANDARD_PORT_STR "5683" -#define LWM2M_STANDARD_PORT 5683 -#define LWM2M_DTLS_PORT_STR "5684" -#define LWM2M_DTLS_PORT 5684 -#define LWM2M_BSSERVER_PORT_STR "5685" -#define LWM2M_BSSERVER_PORT 5685 - -// after 40sec of inactivity we rehandshake -#define DTLS_NAT_TIMEOUT 40 - -typedef struct _dtls_connection_t -{ - struct _dtls_connection_t * next; - int sock; - struct sockaddr_in6 addr; - size_t addrLen; - session_t * dtlsSession; - lwm2m_object_t * securityObj; - int securityInstId; - lwm2m_context_t * lwm2mH; - dtls_context_t * dtlsContext; - time_t lastSend; // last time a data was sent to the server (used for NAT timeouts) -} dtls_connection_t; - -int create_socket(const char * portStr, int ai_family); - -dtls_connection_t * connection_find(dtls_connection_t * connList, const struct sockaddr_storage * addr, size_t addrLen); -dtls_connection_t * connection_new_incoming(dtls_connection_t * connList, int sock, const struct sockaddr * addr, size_t addrLen); -dtls_connection_t * connection_create(dtls_connection_t * connList, int sock, lwm2m_object_t * securityObj, int instanceId, lwm2m_context_t * lwm2mH, int addressFamily); - -void connection_free(dtls_connection_t * connList); - -int connection_send(dtls_connection_t *connP, uint8_t * buffer, size_t length); -int connection_handle_packet(dtls_connection_t *connP, uint8_t * buffer, size_t length); - -// rehandshake a connection, useful when your NAT timed out and your client has a new IP/PORT -int connection_rehandshake(dtls_connection_t *connP, bool sendCloseNotify); - -#endif diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 44c6e1dd4..c4903377c 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -28,6 +28,10 @@ file(GLOB SOURCES "*.c") add_executable(${PROJECT_NAME} ${SOURCES} ${WAKAAMA_SOURCES} ${COAP_SOURCES} ${DATA_SOURCES} ${SHARED_SOURCES}) target_link_libraries(${PROJECT_NAME} cunit) +if (DTLS_MBEDTLS) + target_link_libraries(${PROJECT_NAME} mbedtls) +endif() + if(SANITIZER) target_compile_options(${PROJECT_NAME} PRIVATE -fsanitize=${SANITIZER} -fno-sanitize-recover=all) target_link_options(${PROJECT_NAME} PRIVATE -fsanitize=${SANITIZER} -fno-sanitize-recover=all)