diff --git a/.github/workflows/build_tests.sh b/.github/workflows/build_tests.sh index a8df126..6c3171d 100755 --- a/.github/workflows/build_tests.sh +++ b/.github/workflows/build_tests.sh @@ -36,35 +36,43 @@ cmake .. -G "Unix Makefiles" -DCONFIG_MENDER_PLATFORM_FLASH_TYPE="generic/weak" make -j$(nproc) cmake .. -G "Unix Makefiles" -DCONFIG_MENDER_PLATFORM_FLASH_TYPE="generic/weak" -DCONFIG_MENDER_PLATFORM_LOG_TYPE="generic/weak" -DCONFIG_MENDER_PLATFORM_NET_TYPE="generic/weak" -DCONFIG_MENDER_PLATFORM_SCHEDULER_TYPE="generic/weak" -DCONFIG_MENDER_PLATFORM_STORAGE_TYPE="generic/weak" -DCONFIG_MENDER_PLATFORM_TLS_TYPE="generic/weak" -DCONFIG_MENDER_CLIENT_ADD_ON_CONFIGURE=OFF -DCONFIG_MENDER_CLIENT_ADD_ON_INVENTORY=ON -DCONFIG_MENDER_CLIENT_ADD_ON_TROUBLESHOOT=OFF make -j$(nproc) -cmake .. -G "Unix Makefiles" -DCONFIG_MENDER_PLATFORM_FLASH_TYPE="generic/weak" -DCONFIG_MENDER_PLATFORM_LOG_TYPE="generic/weak" -DCONFIG_MENDER_PLATFORM_NET_TYPE="generic/weak" -DCONFIG_MENDER_PLATFORM_SCHEDULER_TYPE="generic/weak" -DCONFIG_MENDER_PLATFORM_STORAGE_TYPE="generic/weak" -DCONFIG_MENDER_PLATFORM_TLS_TYPE="generic/weak" -DCONFIG_MENDER_CLIENT_ADD_ON_CONFIGURE=OFF -DCONFIG_MENDER_CLIENT_ADD_ON_INVENTORY=OFF -DCONFIG_MENDER_CLIENT_ADD_ON_TROUBLESHOOT=ON -DCONFIG_MENDER_CLIENT_TROUBLESHOOT_SHELL=OFF -DCONFIG_MENDER_CLIENT_TROUBLESHOOT_FILE_TRANSFER=OFF +cmake .. -G "Unix Makefiles" -DCONFIG_MENDER_PLATFORM_FLASH_TYPE="generic/weak" -DCONFIG_MENDER_PLATFORM_LOG_TYPE="generic/weak" -DCONFIG_MENDER_PLATFORM_NET_TYPE="generic/weak" -DCONFIG_MENDER_PLATFORM_SCHEDULER_TYPE="generic/weak" -DCONFIG_MENDER_PLATFORM_STORAGE_TYPE="generic/weak" -DCONFIG_MENDER_PLATFORM_TLS_TYPE="generic/weak" -DCONFIG_MENDER_CLIENT_ADD_ON_CONFIGURE=OFF -DCONFIG_MENDER_CLIENT_ADD_ON_INVENTORY=OFF -DCONFIG_MENDER_CLIENT_ADD_ON_TROUBLESHOOT=ON -DCONFIG_MENDER_CLIENT_TROUBLESHOOT_SHELL=OFF -DCONFIG_MENDER_CLIENT_TROUBLESHOOT_FILE_TRANSFER=OFF -DCONFIG_MENDER_CLIENT_TROUBLESHOOT_PORT_FORWARDING=OFF make -j$(nproc) -cmake .. -G "Unix Makefiles" -DCONFIG_MENDER_PLATFORM_FLASH_TYPE="generic/weak" -DCONFIG_MENDER_PLATFORM_LOG_TYPE="generic/weak" -DCONFIG_MENDER_PLATFORM_NET_TYPE="generic/weak" -DCONFIG_MENDER_PLATFORM_SCHEDULER_TYPE="generic/weak" -DCONFIG_MENDER_PLATFORM_STORAGE_TYPE="generic/weak" -DCONFIG_MENDER_PLATFORM_TLS_TYPE="generic/weak" -DCONFIG_MENDER_CLIENT_ADD_ON_CONFIGURE=OFF -DCONFIG_MENDER_CLIENT_ADD_ON_INVENTORY=OFF -DCONFIG_MENDER_CLIENT_ADD_ON_TROUBLESHOOT=ON -DCONFIG_MENDER_CLIENT_TROUBLESHOOT_SHELL=ON -DCONFIG_MENDER_CLIENT_TROUBLESHOOT_FILE_TRANSFER=OFF +cmake .. -G "Unix Makefiles" -DCONFIG_MENDER_PLATFORM_FLASH_TYPE="generic/weak" -DCONFIG_MENDER_PLATFORM_LOG_TYPE="generic/weak" -DCONFIG_MENDER_PLATFORM_NET_TYPE="generic/weak" -DCONFIG_MENDER_PLATFORM_SCHEDULER_TYPE="generic/weak" -DCONFIG_MENDER_PLATFORM_STORAGE_TYPE="generic/weak" -DCONFIG_MENDER_PLATFORM_TLS_TYPE="generic/weak" -DCONFIG_MENDER_CLIENT_ADD_ON_CONFIGURE=OFF -DCONFIG_MENDER_CLIENT_ADD_ON_INVENTORY=OFF -DCONFIG_MENDER_CLIENT_ADD_ON_TROUBLESHOOT=ON -DCONFIG_MENDER_CLIENT_TROUBLESHOOT_SHELL=ON -DCONFIG_MENDER_CLIENT_TROUBLESHOOT_FILE_TRANSFER=OFF -DCONFIG_MENDER_CLIENT_TROUBLESHOOT_PORT_FORWARDING=OFF make -j$(nproc) -cmake .. -G "Unix Makefiles" -DCONFIG_MENDER_PLATFORM_FLASH_TYPE="generic/weak" -DCONFIG_MENDER_PLATFORM_LOG_TYPE="generic/weak" -DCONFIG_MENDER_PLATFORM_NET_TYPE="generic/weak" -DCONFIG_MENDER_PLATFORM_SCHEDULER_TYPE="generic/weak" -DCONFIG_MENDER_PLATFORM_STORAGE_TYPE="generic/weak" -DCONFIG_MENDER_PLATFORM_TLS_TYPE="generic/weak" -DCONFIG_MENDER_CLIENT_ADD_ON_CONFIGURE=OFF -DCONFIG_MENDER_CLIENT_ADD_ON_INVENTORY=OFF -DCONFIG_MENDER_CLIENT_ADD_ON_TROUBLESHOOT=ON -DCONFIG_MENDER_CLIENT_TROUBLESHOOT_SHELL=OFF -DCONFIG_MENDER_CLIENT_TROUBLESHOOT_FILE_TRANSFER=ON +cmake .. -G "Unix Makefiles" -DCONFIG_MENDER_PLATFORM_FLASH_TYPE="generic/weak" -DCONFIG_MENDER_PLATFORM_LOG_TYPE="generic/weak" -DCONFIG_MENDER_PLATFORM_NET_TYPE="generic/weak" -DCONFIG_MENDER_PLATFORM_SCHEDULER_TYPE="generic/weak" -DCONFIG_MENDER_PLATFORM_STORAGE_TYPE="generic/weak" -DCONFIG_MENDER_PLATFORM_TLS_TYPE="generic/weak" -DCONFIG_MENDER_CLIENT_ADD_ON_CONFIGURE=OFF -DCONFIG_MENDER_CLIENT_ADD_ON_INVENTORY=OFF -DCONFIG_MENDER_CLIENT_ADD_ON_TROUBLESHOOT=ON -DCONFIG_MENDER_CLIENT_TROUBLESHOOT_SHELL=OFF -DCONFIG_MENDER_CLIENT_TROUBLESHOOT_FILE_TRANSFER=ON -DCONFIG_MENDER_CLIENT_TROUBLESHOOT_PORT_FORWARDING=OFF make -j$(nproc) -cmake .. -G "Unix Makefiles" -DCONFIG_MENDER_PLATFORM_FLASH_TYPE="generic/weak" -DCONFIG_MENDER_PLATFORM_LOG_TYPE="generic/weak" -DCONFIG_MENDER_PLATFORM_NET_TYPE="generic/weak" -DCONFIG_MENDER_PLATFORM_SCHEDULER_TYPE="generic/weak" -DCONFIG_MENDER_PLATFORM_STORAGE_TYPE="generic/weak" -DCONFIG_MENDER_PLATFORM_TLS_TYPE="generic/weak" -DCONFIG_MENDER_CLIENT_ADD_ON_CONFIGURE=OFF -DCONFIG_MENDER_CLIENT_ADD_ON_INVENTORY=OFF -DCONFIG_MENDER_CLIENT_ADD_ON_TROUBLESHOOT=ON -DCONFIG_MENDER_CLIENT_TROUBLESHOOT_SHELL=ON -DCONFIG_MENDER_CLIENT_TROUBLESHOOT_FILE_TRANSFER=ON +cmake .. -G "Unix Makefiles" -DCONFIG_MENDER_PLATFORM_FLASH_TYPE="generic/weak" -DCONFIG_MENDER_PLATFORM_LOG_TYPE="generic/weak" -DCONFIG_MENDER_PLATFORM_NET_TYPE="generic/weak" -DCONFIG_MENDER_PLATFORM_SCHEDULER_TYPE="generic/weak" -DCONFIG_MENDER_PLATFORM_STORAGE_TYPE="generic/weak" -DCONFIG_MENDER_PLATFORM_TLS_TYPE="generic/weak" -DCONFIG_MENDER_CLIENT_ADD_ON_CONFIGURE=OFF -DCONFIG_MENDER_CLIENT_ADD_ON_INVENTORY=OFF -DCONFIG_MENDER_CLIENT_ADD_ON_TROUBLESHOOT=ON -DCONFIG_MENDER_CLIENT_TROUBLESHOOT_SHELL=ON -DCONFIG_MENDER_CLIENT_TROUBLESHOOT_FILE_TRANSFER=ON -DCONFIG_MENDER_CLIENT_TROUBLESHOOT_PORT_FORWARDING=OFF make -j$(nproc) -cmake .. -G "Unix Makefiles" -DCONFIG_MENDER_PLATFORM_FLASH_TYPE="generic/weak" -DCONFIG_MENDER_PLATFORM_LOG_TYPE="generic/weak" -DCONFIG_MENDER_PLATFORM_NET_TYPE="generic/weak" -DCONFIG_MENDER_PLATFORM_SCHEDULER_TYPE="generic/weak" -DCONFIG_MENDER_PLATFORM_STORAGE_TYPE="generic/weak" -DCONFIG_MENDER_PLATFORM_TLS_TYPE="generic/weak" -DCONFIG_MENDER_CLIENT_ADD_ON_CONFIGURE=ON -DCONFIG_MENDER_CLIENT_ADD_ON_INVENTORY=ON -DCONFIG_MENDER_CLIENT_ADD_ON_TROUBLESHOOT=ON -DCONFIG_MENDER_CLIENT_TROUBLESHOOT_SHELL=ON -DCONFIG_MENDER_CLIENT_TROUBLESHOOT_FILE_TRANSFER=ON +cmake .. -G "Unix Makefiles" -DCONFIG_MENDER_PLATFORM_FLASH_TYPE="generic/weak" -DCONFIG_MENDER_PLATFORM_LOG_TYPE="generic/weak" -DCONFIG_MENDER_PLATFORM_NET_TYPE="generic/weak" -DCONFIG_MENDER_PLATFORM_SCHEDULER_TYPE="generic/weak" -DCONFIG_MENDER_PLATFORM_STORAGE_TYPE="generic/weak" -DCONFIG_MENDER_PLATFORM_TLS_TYPE="generic/weak" -DCONFIG_MENDER_CLIENT_ADD_ON_CONFIGURE=OFF -DCONFIG_MENDER_CLIENT_ADD_ON_INVENTORY=OFF -DCONFIG_MENDER_CLIENT_ADD_ON_TROUBLESHOOT=ON -DCONFIG_MENDER_CLIENT_TROUBLESHOOT_SHELL=OFF -DCONFIG_MENDER_CLIENT_TROUBLESHOOT_FILE_TRANSFER=OFF -DCONFIG_MENDER_CLIENT_TROUBLESHOOT_PORT_FORWARDING=ON +make -j$(nproc) +cmake .. -G "Unix Makefiles" -DCONFIG_MENDER_PLATFORM_FLASH_TYPE="generic/weak" -DCONFIG_MENDER_PLATFORM_LOG_TYPE="generic/weak" -DCONFIG_MENDER_PLATFORM_NET_TYPE="generic/weak" -DCONFIG_MENDER_PLATFORM_SCHEDULER_TYPE="generic/weak" -DCONFIG_MENDER_PLATFORM_STORAGE_TYPE="generic/weak" -DCONFIG_MENDER_PLATFORM_TLS_TYPE="generic/weak" -DCONFIG_MENDER_CLIENT_ADD_ON_CONFIGURE=OFF -DCONFIG_MENDER_CLIENT_ADD_ON_INVENTORY=OFF -DCONFIG_MENDER_CLIENT_ADD_ON_TROUBLESHOOT=ON -DCONFIG_MENDER_CLIENT_TROUBLESHOOT_SHELL=ON -DCONFIG_MENDER_CLIENT_TROUBLESHOOT_FILE_TRANSFER=OFF -DCONFIG_MENDER_CLIENT_TROUBLESHOOT_PORT_FORWARDING=ON +make -j$(nproc) +cmake .. -G "Unix Makefiles" -DCONFIG_MENDER_PLATFORM_FLASH_TYPE="generic/weak" -DCONFIG_MENDER_PLATFORM_LOG_TYPE="generic/weak" -DCONFIG_MENDER_PLATFORM_NET_TYPE="generic/weak" -DCONFIG_MENDER_PLATFORM_SCHEDULER_TYPE="generic/weak" -DCONFIG_MENDER_PLATFORM_STORAGE_TYPE="generic/weak" -DCONFIG_MENDER_PLATFORM_TLS_TYPE="generic/weak" -DCONFIG_MENDER_CLIENT_ADD_ON_CONFIGURE=OFF -DCONFIG_MENDER_CLIENT_ADD_ON_INVENTORY=OFF -DCONFIG_MENDER_CLIENT_ADD_ON_TROUBLESHOOT=ON -DCONFIG_MENDER_CLIENT_TROUBLESHOOT_SHELL=OFF -DCONFIG_MENDER_CLIENT_TROUBLESHOOT_FILE_TRANSFER=ON -DCONFIG_MENDER_CLIENT_TROUBLESHOOT_PORT_FORWARDING=ON +make -j$(nproc) +cmake .. -G "Unix Makefiles" -DCONFIG_MENDER_PLATFORM_FLASH_TYPE="generic/weak" -DCONFIG_MENDER_PLATFORM_LOG_TYPE="generic/weak" -DCONFIG_MENDER_PLATFORM_NET_TYPE="generic/weak" -DCONFIG_MENDER_PLATFORM_SCHEDULER_TYPE="generic/weak" -DCONFIG_MENDER_PLATFORM_STORAGE_TYPE="generic/weak" -DCONFIG_MENDER_PLATFORM_TLS_TYPE="generic/weak" -DCONFIG_MENDER_CLIENT_ADD_ON_CONFIGURE=OFF -DCONFIG_MENDER_CLIENT_ADD_ON_INVENTORY=OFF -DCONFIG_MENDER_CLIENT_ADD_ON_TROUBLESHOOT=ON -DCONFIG_MENDER_CLIENT_TROUBLESHOOT_SHELL=ON -DCONFIG_MENDER_CLIENT_TROUBLESHOOT_FILE_TRANSFER=ON -DCONFIG_MENDER_CLIENT_TROUBLESHOOT_PORT_FORWARDING=ON +make -j$(nproc) +cmake .. -G "Unix Makefiles" -DCONFIG_MENDER_PLATFORM_FLASH_TYPE="generic/weak" -DCONFIG_MENDER_PLATFORM_LOG_TYPE="generic/weak" -DCONFIG_MENDER_PLATFORM_NET_TYPE="generic/weak" -DCONFIG_MENDER_PLATFORM_SCHEDULER_TYPE="generic/weak" -DCONFIG_MENDER_PLATFORM_STORAGE_TYPE="generic/weak" -DCONFIG_MENDER_PLATFORM_TLS_TYPE="generic/weak" -DCONFIG_MENDER_CLIENT_ADD_ON_CONFIGURE=ON -DCONFIG_MENDER_CLIENT_ADD_ON_INVENTORY=ON -DCONFIG_MENDER_CLIENT_ADD_ON_TROUBLESHOOT=ON -DCONFIG_MENDER_CLIENT_TROUBLESHOOT_SHELL=ON -DCONFIG_MENDER_CLIENT_TROUBLESHOOT_FILE_TRANSFER=ON -DCONFIG_MENDER_CLIENT_TROUBLESHOOT_PORT_FORWARDING=ON make -j$(nproc) # Build ESP-IDF use cases: # - NVS storage option # - mbedtls/cryptoauthlib TLS options -cmake .. -G "Unix Makefiles" -DCONFIG_MENDER_PLATFORM_FLASH_TYPE="esp-idf" -DCONFIG_MENDER_PLATFORM_LOG_TYPE="esp-idf" -DCONFIG_MENDER_PLATFORM_NET_TYPE="esp-idf" -DCONFIG_MENDER_PLATFORM_SCHEDULER_TYPE="freertos" -DCONFIG_MENDER_PLATFORM_STORAGE_TYPE="esp-idf/nvs" -DCONFIG_MENDER_PLATFORM_TLS_TYPE="generic/mbedtls" -DCONFIG_MENDER_CLIENT_ADD_ON_CONFIGURE=ON -DCONFIG_MENDER_CLIENT_CONFIGURE_STORAGE=ON -DCONFIG_MENDER_CLIENT_ADD_ON_INVENTORY=ON -DCONFIG_MENDER_CLIENT_ADD_ON_TROUBLESHOOT=ON -DCONFIG_MENDER_CLIENT_TROUBLESHOOT_SHELL=ON -DCONFIG_MENDER_CLIENT_TROUBLESHOOT_FILE_TRANSFER=ON +cmake .. -G "Unix Makefiles" -DCONFIG_MENDER_PLATFORM_FLASH_TYPE="esp-idf" -DCONFIG_MENDER_PLATFORM_LOG_TYPE="esp-idf" -DCONFIG_MENDER_PLATFORM_NET_TYPE="esp-idf" -DCONFIG_MENDER_PLATFORM_SCHEDULER_TYPE="freertos" -DCONFIG_MENDER_PLATFORM_STORAGE_TYPE="esp-idf/nvs" -DCONFIG_MENDER_PLATFORM_TLS_TYPE="generic/mbedtls" -DCONFIG_MENDER_CLIENT_ADD_ON_CONFIGURE=ON -DCONFIG_MENDER_CLIENT_CONFIGURE_STORAGE=ON -DCONFIG_MENDER_CLIENT_ADD_ON_INVENTORY=ON -DCONFIG_MENDER_CLIENT_ADD_ON_TROUBLESHOOT=ON -DCONFIG_MENDER_CLIENT_TROUBLESHOOT_SHELL=ON -DCONFIG_MENDER_CLIENT_TROUBLESHOOT_FILE_TRANSFER=ON -DCONFIG_MENDER_CLIENT_TROUBLESHOOT_PORT_FORWARDING=ON make -j$(nproc) -cmake .. -G "Unix Makefiles" -DCONFIG_MENDER_PLATFORM_FLASH_TYPE="esp-idf" -DCONFIG_MENDER_PLATFORM_LOG_TYPE="esp-idf" -DCONFIG_MENDER_PLATFORM_NET_TYPE="esp-idf" -DCONFIG_MENDER_PLATFORM_SCHEDULER_TYPE="freertos" -DCONFIG_MENDER_PLATFORM_STORAGE_TYPE="esp-idf/nvs" -DCONFIG_MENDER_PLATFORM_TLS_TYPE="generic/cryptoauthlib" -DCONFIG_MENDER_CLIENT_ADD_ON_CONFIGURE=ON -DCONFIG_MENDER_CLIENT_CONFIGURE_STORAGE=ON -DCONFIG_MENDER_CLIENT_ADD_ON_INVENTORY=ON -DCONFIG_MENDER_CLIENT_ADD_ON_TROUBLESHOOT=ON -DCONFIG_MENDER_CLIENT_TROUBLESHOOT_SHELL=ON -DCONFIG_MENDER_CLIENT_TROUBLESHOOT_FILE_TRANSFER=ON +cmake .. -G "Unix Makefiles" -DCONFIG_MENDER_PLATFORM_FLASH_TYPE="esp-idf" -DCONFIG_MENDER_PLATFORM_LOG_TYPE="esp-idf" -DCONFIG_MENDER_PLATFORM_NET_TYPE="esp-idf" -DCONFIG_MENDER_PLATFORM_SCHEDULER_TYPE="freertos" -DCONFIG_MENDER_PLATFORM_STORAGE_TYPE="esp-idf/nvs" -DCONFIG_MENDER_PLATFORM_TLS_TYPE="generic/cryptoauthlib" -DCONFIG_MENDER_CLIENT_ADD_ON_CONFIGURE=ON -DCONFIG_MENDER_CLIENT_CONFIGURE_STORAGE=ON -DCONFIG_MENDER_CLIENT_ADD_ON_INVENTORY=ON -DCONFIG_MENDER_CLIENT_ADD_ON_TROUBLESHOOT=ON -DCONFIG_MENDER_CLIENT_TROUBLESHOOT_SHELL=ON -DCONFIG_MENDER_CLIENT_TROUBLESHOOT_FILE_TRANSFER=ON -DCONFIG_MENDER_CLIENT_TROUBLESHOOT_PORT_FORWARDING=ON make -j$(nproc) # Build Zephyr use cases: # - NVS storage option # - mbedtls/cryptoauthlib TLS options -cmake .. -G "Unix Makefiles" -DCONFIG_MENDER_PLATFORM_FLASH_TYPE="zephyr" -DCONFIG_MENDER_PLATFORM_LOG_TYPE="zephyr" -DCONFIG_MENDER_PLATFORM_NET_TYPE="zephyr" -DCONFIG_MENDER_PLATFORM_SCHEDULER_TYPE="zephyr" -DCONFIG_MENDER_PLATFORM_STORAGE_TYPE="zephyr/nvs" -DCONFIG_MENDER_PLATFORM_TLS_TYPE="generic/mbedtls" -DCONFIG_MENDER_CLIENT_ADD_ON_CONFIGURE=ON -DCONFIG_MENDER_CLIENT_CONFIGURE_STORAGE=ON -DCONFIG_MENDER_CLIENT_ADD_ON_INVENTORY=ON -DCONFIG_MENDER_CLIENT_ADD_ON_TROUBLESHOOT=ON -DCONFIG_MENDER_CLIENT_TROUBLESHOOT_SHELL=ON -DCONFIG_MENDER_CLIENT_TROUBLESHOOT_FILE_TRANSFER=ON +cmake .. -G "Unix Makefiles" -DCONFIG_MENDER_PLATFORM_FLASH_TYPE="zephyr" -DCONFIG_MENDER_PLATFORM_LOG_TYPE="zephyr" -DCONFIG_MENDER_PLATFORM_NET_TYPE="zephyr" -DCONFIG_MENDER_PLATFORM_SCHEDULER_TYPE="zephyr" -DCONFIG_MENDER_PLATFORM_STORAGE_TYPE="zephyr/nvs" -DCONFIG_MENDER_PLATFORM_TLS_TYPE="generic/mbedtls" -DCONFIG_MENDER_CLIENT_ADD_ON_CONFIGURE=ON -DCONFIG_MENDER_CLIENT_CONFIGURE_STORAGE=ON -DCONFIG_MENDER_CLIENT_ADD_ON_INVENTORY=ON -DCONFIG_MENDER_CLIENT_ADD_ON_TROUBLESHOOT=ON -DCONFIG_MENDER_CLIENT_TROUBLESHOOT_SHELL=ON -DCONFIG_MENDER_CLIENT_TROUBLESHOOT_FILE_TRANSFER=ON -DCONFIG_MENDER_CLIENT_TROUBLESHOOT_PORT_FORWARDING=ON make -j$(nproc) -cmake .. -G "Unix Makefiles" -DCONFIG_MENDER_PLATFORM_FLASH_TYPE="zephyr" -DCONFIG_MENDER_PLATFORM_LOG_TYPE="zephyr" -DCONFIG_MENDER_PLATFORM_NET_TYPE="zephyr" -DCONFIG_MENDER_PLATFORM_SCHEDULER_TYPE="zephyr" -DCONFIG_MENDER_PLATFORM_STORAGE_TYPE="zephyr/nvs" -DCONFIG_MENDER_PLATFORM_TLS_TYPE="generic/cryptoauthlib" -DCONFIG_MENDER_CLIENT_ADD_ON_CONFIGURE=ON -DCONFIG_MENDER_CLIENT_CONFIGURE_STORAGE=ON -DCONFIG_MENDER_CLIENT_ADD_ON_INVENTORY=ON -DCONFIG_MENDER_CLIENT_ADD_ON_TROUBLESHOOT=ON -DCONFIG_MENDER_CLIENT_TROUBLESHOOT_SHELL=ON -DCONFIG_MENDER_CLIENT_TROUBLESHOOT_FILE_TRANSFER=ON +cmake .. -G "Unix Makefiles" -DCONFIG_MENDER_PLATFORM_FLASH_TYPE="zephyr" -DCONFIG_MENDER_PLATFORM_LOG_TYPE="zephyr" -DCONFIG_MENDER_PLATFORM_NET_TYPE="zephyr" -DCONFIG_MENDER_PLATFORM_SCHEDULER_TYPE="zephyr" -DCONFIG_MENDER_PLATFORM_STORAGE_TYPE="zephyr/nvs" -DCONFIG_MENDER_PLATFORM_TLS_TYPE="generic/cryptoauthlib" -DCONFIG_MENDER_CLIENT_ADD_ON_CONFIGURE=ON -DCONFIG_MENDER_CLIENT_CONFIGURE_STORAGE=ON -DCONFIG_MENDER_CLIENT_ADD_ON_INVENTORY=ON -DCONFIG_MENDER_CLIENT_ADD_ON_TROUBLESHOOT=ON -DCONFIG_MENDER_CLIENT_TROUBLESHOOT_SHELL=ON -DCONFIG_MENDER_CLIENT_TROUBLESHOOT_FILE_TRANSFER=ON -DCONFIG_MENDER_CLIENT_TROUBLESHOOT_PORT_FORWARDING=ON make -j$(nproc) # Build Posix use cases: # - curl network option # - mbedtls TLS option -cmake .. -G "Unix Makefiles" -DCONFIG_MENDER_PLATFORM_FLASH_TYPE="posix" -DCONFIG_MENDER_PLATFORM_LOG_TYPE="posix" -DCONFIG_MENDER_PLATFORM_NET_TYPE="generic/curl" -DCONFIG_MENDER_PLATFORM_SCHEDULER_TYPE="posix" -DCONFIG_MENDER_PLATFORM_STORAGE_TYPE="posix" -DCONFIG_MENDER_PLATFORM_TLS_TYPE="generic/mbedtls" -DCONFIG_MENDER_CLIENT_ADD_ON_CONFIGURE=ON -DCONFIG_MENDER_CLIENT_CONFIGURE_STORAGE=ON -DCONFIG_MENDER_CLIENT_ADD_ON_INVENTORY=ON -DCONFIG_MENDER_CLIENT_ADD_ON_TROUBLESHOOT=ON -DCONFIG_MENDER_CLIENT_TROUBLESHOOT_SHELL=ON -DCONFIG_MENDER_CLIENT_TROUBLESHOOT_FILE_TRANSFER=ON +cmake .. -G "Unix Makefiles" -DCONFIG_MENDER_PLATFORM_FLASH_TYPE="posix" -DCONFIG_MENDER_PLATFORM_LOG_TYPE="posix" -DCONFIG_MENDER_PLATFORM_NET_TYPE="generic/curl" -DCONFIG_MENDER_PLATFORM_SCHEDULER_TYPE="posix" -DCONFIG_MENDER_PLATFORM_STORAGE_TYPE="posix" -DCONFIG_MENDER_PLATFORM_TLS_TYPE="generic/mbedtls" -DCONFIG_MENDER_CLIENT_ADD_ON_CONFIGURE=ON -DCONFIG_MENDER_CLIENT_CONFIGURE_STORAGE=ON -DCONFIG_MENDER_CLIENT_ADD_ON_INVENTORY=ON -DCONFIG_MENDER_CLIENT_ADD_ON_TROUBLESHOOT=ON -DCONFIG_MENDER_CLIENT_TROUBLESHOOT_SHELL=ON -DCONFIG_MENDER_CLIENT_TROUBLESHOOT_FILE_TRANSFER=ON -DCONFIG_MENDER_CLIENT_TROUBLESHOOT_PORT_FORWARDING=ON make -j$(nproc) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4a21d02..75807b0 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -82,6 +82,10 @@ if (CONFIG_MENDER_CLIENT_ADD_ON_TROUBLESHOOT) if (CONFIG_MENDER_CLIENT_TROUBLESHOOT_FILE_TRANSFER) message(STATUS "Using mender-troubleshoot add-on file transfer feature") endif() + option(CONFIG_MENDER_CLIENT_TROUBLESHOOT_PORT_FORWARDING "Mender client Troubleshoot Port Forwarding Transfer" OFF) + if (CONFIG_MENDER_CLIENT_TROUBLESHOOT_PORT_FORWARDING) + message(STATUS "Using mender-troubleshoot add-on port forwarding feature") + endif() endif() if (NOT CONFIG_MENDER_LOG_LEVEL) message(STATUS "Using default log level") @@ -179,6 +183,9 @@ if (CONFIG_MENDER_CLIENT_ADD_ON_TROUBLESHOOT) if (CONFIG_MENDER_CLIENT_TROUBLESHOOT_FILE_TRANSFER) target_compile_definitions(mender-mcu-client PUBLIC CONFIG_MENDER_CLIENT_TROUBLESHOOT_FILE_TRANSFER) endif() + if (CONFIG_MENDER_CLIENT_TROUBLESHOOT_PORT_FORWARDING) + target_compile_definitions(mender-mcu-client PUBLIC CONFIG_MENDER_CLIENT_TROUBLESHOOT_PORT_FORWARDING) + endif() endif() if (CONFIG_MENDER_LOG_LEVEL) target_compile_definitions(mender-mcu-client PUBLIC CONFIG_MENDER_LOG_LEVEL=${CONFIG_MENDER_LOG_LEVEL}) @@ -234,6 +241,11 @@ if (CONFIG_MENDER_CLIENT_ADD_ON_TROUBLESHOOT) "${CMAKE_CURRENT_LIST_DIR}/add-ons/troubleshoot/src/mender-troubleshoot-file-transfer.c" ) endif() + if (CONFIG_MENDER_CLIENT_TROUBLESHOOT_PORT_FORWARDING) + list(APPEND SOURCES_TEMP + "${CMAKE_CURRENT_LIST_DIR}/add-ons/troubleshoot/src/mender-troubleshoot-port-forwarding.c" + ) + endif() endif() target_sources(mender-mcu-client PRIVATE ${SOURCES_TEMP}) diff --git a/add-ons/troubleshoot/include/mender-troubleshoot-port-forwarding.h b/add-ons/troubleshoot/include/mender-troubleshoot-port-forwarding.h new file mode 100644 index 0000000..8d8a703 --- /dev/null +++ b/add-ons/troubleshoot/include/mender-troubleshoot-port-forwarding.h @@ -0,0 +1,84 @@ +/** + * @file mender-troubleshoot-port-forwarding.h + * @brief Mender MCU Troubleshoot add-on port forwarding messages handler implementation + * + * Copyright joelguittet and mender-mcu-client contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __MENDER_TROUBLESHOOT_PORT_FORWARDING_H__ +#define __MENDER_TROUBLESHOOT_PORT_FORWARDING_H__ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#include "mender-troubleshoot-protomsg.h" +#include + +#ifdef CONFIG_MENDER_CLIENT_ADD_ON_TROUBLESHOOT +#ifdef CONFIG_MENDER_CLIENT_TROUBLESHOOT_PORT_FORWARDING + +/** + * @brief Mender troubleshoot port forwarding callbacks + */ +typedef struct { + mender_err_t (*connect)(char *, uint16_t, char *, void **); /**< Open connection to remote host */ + mender_err_t (*send)(void *, void *, size_t); /**< Send data to remote host */ + mender_err_t (*close)(void *); /**< Close connection to remote host */ +} mender_troubleshoot_port_forwarding_callbacks_t; + +/** + * @brief Initialize mender troubleshoot add-on port forwarding handler + * @param callbacks Mender troubleshoot port forwarding callbacks + * @return MENDER_OK if the function succeeds, error code otherwise + */ +mender_err_t mender_troubleshoot_port_forwarding_init(mender_troubleshoot_port_forwarding_callbacks_t *callbacks); + +/** + * @brief Function called to perform the treatment of the port forwarding messages + * @param protomsg Received proto message + * @param response Response to be sent back to the server, NULL if no response to send + * @return MENDER_OK if the function succeeds, error code if an error occured + */ +mender_err_t mender_troubleshoot_port_forwarding_message_handler(mender_troubleshoot_protomsg_t *protomsg, mender_troubleshoot_protomsg_t **response); + +/** + * @brief Send port forwarding data to the server + * @param data Data to send to the server + * @param length Length of the data to send to the server + * @return MENDER_OK if the function succeeds, error code if an error occured + */ +mender_err_t mender_troubleshoot_port_forwarding_forward(void *data, size_t length); + +/** + * @brief Close mender troubleshoot add-on port forwarding connection + * @return MENDER_OK if the function succeeds, error code if an error occured + */ +mender_err_t mender_troubleshoot_port_forwarding_close(void); + +/** + * @brief Release mender troubleshoot add-on port forwarding handler + * @return MENDER_OK if the function succeeds, error code otherwise + */ +mender_err_t mender_troubleshoot_port_forwarding_exit(void); + +#endif /* CONFIG_MENDER_CLIENT_TROUBLESHOOT_PORT_FORWARDING */ +#endif /* CONFIG_MENDER_CLIENT_ADD_ON_TROUBLESHOOT */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __MENDER_TROUBLESHOOT_PORT_FORWARDING_H__ */ diff --git a/add-ons/troubleshoot/src/mender-troubleshoot-control.c b/add-ons/troubleshoot/src/mender-troubleshoot-control.c index 62f484c..8dfae46 100644 --- a/add-ons/troubleshoot/src/mender-troubleshoot-control.c +++ b/add-ons/troubleshoot/src/mender-troubleshoot-control.c @@ -350,6 +350,9 @@ mender_troubleshoot_control_encode_accept_data(msgpack_object *object) { #ifdef CONFIG_MENDER_CLIENT_TROUBLESHOOT_FILE_TRANSFER 1 + #endif /* CONFIG_MENDER_CLIENT_TROUBLESHOOT_FILE_TRANSFER */ +#ifdef CONFIG_MENDER_CLIENT_TROUBLESHOOT_PORT_FORWARDING + 1 + +#endif /* CONFIG_MENDER_CLIENT_TROUBLESHOOT_PORT_FORWARDING */ #if CONFIG_MENDER_CLIENT_TROUBLESHOOT_SHELL 1 + #endif /* CONFIG_MENDER_CLIENT_TROUBLESHOOT_SHELL */ @@ -364,6 +367,11 @@ mender_troubleshoot_control_encode_accept_data(msgpack_object *object) { p->val.via.array.ptr[proto_index].via.u64 = MENDER_TROUBLESHOOT_PROTOMSG_HDR_PROTO_FILE_TRANSFER; proto_index++; #endif /* CONFIG_MENDER_CLIENT_TROUBLESHOOT_FILE_TRANSFER */ +#ifdef CONFIG_MENDER_CLIENT_TROUBLESHOOT_PORT_FORWARDING + p->val.via.array.ptr[proto_index].type = MSGPACK_OBJECT_POSITIVE_INTEGER; + p->val.via.array.ptr[proto_index].via.u64 = MENDER_TROUBLESHOOT_PROTOMSG_HDR_PROTO_PORT_FORWARD; + proto_index++; +#endif /* CONFIG_MENDER_CLIENT_TROUBLESHOOT_PORT_FORWARDING */ #if CONFIG_MENDER_CLIENT_TROUBLESHOOT_SHELL p->val.via.array.ptr[proto_index].type = MSGPACK_OBJECT_POSITIVE_INTEGER; p->val.via.array.ptr[proto_index].via.u64 = MENDER_TROUBLESHOOT_PROTOMSG_HDR_PROTO_SHELL; diff --git a/add-ons/troubleshoot/src/mender-troubleshoot-port-forwarding.c b/add-ons/troubleshoot/src/mender-troubleshoot-port-forwarding.c new file mode 100644 index 0000000..ec6fb9d --- /dev/null +++ b/add-ons/troubleshoot/src/mender-troubleshoot-port-forwarding.c @@ -0,0 +1,1132 @@ +/** + * @file mender-troubleshoot-port-forwarding.c + * @brief Mender MCU Troubleshoot add-on port forwarding message handler implementation + * + * Copyright joelguittet and mender-mcu-client contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "mender-log.h" +#include "mender-troubleshoot-api.h" +#include "mender-troubleshoot-port-forwarding.h" +#include "mender-troubleshoot-msgpack.h" + +#ifdef CONFIG_MENDER_CLIENT_ADD_ON_TROUBLESHOOT +#ifdef CONFIG_MENDER_CLIENT_TROUBLESHOOT_PORT_FORWARDING + +/** + * @brief Message type + */ +#define MENDER_TROUBLESHOOT_PORT_FORWARD_MESSAGE_TYPE_NEW "new" +#define MENDER_TROUBLESHOOT_PORT_FORWARD_MESSAGE_TYPE_STOP "stop" +#define MENDER_TROUBLESHOOT_PORT_FORWARD_MESSAGE_TYPE_FORWARD "forward" +#define MENDER_TROUBLESHOOT_PORT_FORWARD_MESSAGE_TYPE_ACK "ack" +#define MENDER_TROUBLESHOOT_PORT_FORWARD_MESSAGE_TYPE_ERROR "error" + +/** + * @brief Connect request + */ +typedef struct { + char *remote_host; /**< Remote host */ + uint16_t remote_port; /**< Remote port */ + char *protocol; /**< Protocol */ +} mender_troubleshoot_port_forwarding_connect_t; + +/** + * @brief Error + */ +typedef struct { + char *description; /**< Description */ + char *type; /**< Type */ +} mender_troubleshoot_port_forwarding_error_t; + +/** + * @brief State machine used for sending files to the server + */ +enum { + MENDER_TROUBLESHOOT_FILE_TRANSFER_IDLE, /**< Idle */ + MENDER_TROUBLESHOOT_FILE_TRANSFER_READING, /**< Reading file and sending chunks to the server */ + MENDER_TROUBLESHOOT_FILE_TRANSFER_EOF /**< Waiting for the latest ack to close the handle */ +} mender_troubleshoot_port_forwarding_state_machine + = MENDER_TROUBLESHOOT_FILE_TRANSFER_IDLE; + +/** + * @brief Mender troubleshoot port forwarding callbacks + */ +static mender_troubleshoot_port_forwarding_callbacks_t mender_troubleshoot_port_forwarding_callbacks; + +/** + * @brief Mender troubleshoot port forwarding session ID + */ +static char *mender_troubleshoot_port_forwarding_sid = NULL; + +/** + * @brief Mender troubleshoot port forwarding connection ID + */ +static char *mender_troubleshoot_port_forwarding_connection_id = NULL; + +/** + * @brief Connection handle used to store temporary connection reference + */ +static void *mender_troubleshoot_port_forwarding_handle = NULL; + +/** + * @brief Function called to perform the treatment of the port forwarding new messages + * @param protomsg Received proto message + * @param response Response to be sent back to the server, NULL if no response to send + * @return MENDER_OK if the function succeeds, error code if an error occured + */ +static mender_err_t mender_troubleshoot_port_forwarding_connect_message_handler(mender_troubleshoot_protomsg_t *protomsg, + mender_troubleshoot_protomsg_t **response); + +/** + * @brief Function called to perform the treatment of the port forwarding stop messages + * @param protomsg Received proto message + * @param response Response to be sent back to the server, NULL if no response to send + * @return MENDER_OK if the function succeeds, error code if an error occured + */ +static mender_err_t mender_troubleshoot_port_forwarding_close_message_handler(mender_troubleshoot_protomsg_t *protomsg, + mender_troubleshoot_protomsg_t **response); + +/** + * @brief Function called to perform the treatment of the port forwarding forward messages + * @param protomsg Received proto message + * @param response Response to be sent back to the server, NULL if no response to send + * @return MENDER_OK if the function succeeds, error code if an error occured + */ +static mender_err_t mender_troubleshoot_port_forwarding_forward_message_handler(mender_troubleshoot_protomsg_t *protomsg, + mender_troubleshoot_protomsg_t **response); + +/** + * @brief Unpack and decode connect request + * @param data Packed data to be decoded + * @param length Length of the data to be decoded + * @return Connect if the function succeeds, NULL otherwise + */ +static mender_troubleshoot_port_forwarding_connect_t *mender_troubleshoot_port_forwarding_connect_unpack(void *data, size_t length); + +/** + * @brief Decode connect object + * @param object Connect object + * @return Connect if the function succeeds, NULL otherwise + */ +static mender_troubleshoot_port_forwarding_connect_t *mender_troubleshoot_port_forwarding_connect_decode(msgpack_object *object); + +/** + * @brief Release connect + * @param connect Connect + */ +static void mender_troubleshoot_port_forwarding_connect_release(mender_troubleshoot_port_forwarding_connect_t *connect); + +/** + * @brief Function used to format port forwarding ack message + * @param protomsg Received proto message + * @param response Response to be sent back to the server, NULL if no response to send + * @return MENDER_OK if the function succeeds, error code if an error occured + */ +static mender_err_t mender_troubleshoot_port_forwarding_format_ack(mender_troubleshoot_protomsg_t *protomsg, mender_troubleshoot_protomsg_t **response); + +/** + * @brief Function used to format port forwarding error message + * @param protomsg Received proto message + * @param error Error + * @param response Response to be sent back to the server, NULL if no response to send + * @return MENDER_OK if the function succeeds, error code if an error occured + */ +static mender_err_t mender_troubleshoot_port_forwarding_format_error(mender_troubleshoot_protomsg_t *protomsg, + mender_troubleshoot_port_forwarding_error_t *error, + mender_troubleshoot_protomsg_t **response); + +/** + * @brief Encode and pack error message + * @param error Error + * @param data Packed data encoded + * @param length Length of the data encoded + * @return MENDER_OK if the function succeeds, error code otherwise + */ +static mender_err_t mender_troubleshoot_port_forwarding_error_message_pack(mender_troubleshoot_port_forwarding_error_t *error, void **data, size_t *length); + +/** + * @brief Encode error message + * @param error Error + * @param data Packed data encoded + * @param length Length of the data encoded + * @return MENDER_OK if the function succeeds, error code otherwise + */ +static mender_err_t mender_troubleshoot_port_forwarding_error_message_encode(mender_troubleshoot_port_forwarding_error_t *error, msgpack_object *object); + +/** + * @brief Function called to send port forwarding stop protomsg + * @return MENDER_OK if the function succeeds, error code if an error occured + */ +static mender_err_t mender_troubleshoot_port_forwarding_send_stop(void); + +mender_err_t +mender_troubleshoot_port_forwarding_init(mender_troubleshoot_port_forwarding_callbacks_t *callbacks) { + + /* Save callbacks */ + if (NULL != callbacks) { + memcpy(&mender_troubleshoot_port_forwarding_callbacks, callbacks, sizeof(mender_troubleshoot_port_forwarding_callbacks_t)); + } + + return MENDER_OK; +} + +mender_err_t +mender_troubleshoot_port_forwarding_message_handler(mender_troubleshoot_protomsg_t *protomsg, mender_troubleshoot_protomsg_t **response) { + + assert(NULL != protomsg); + assert(NULL != protomsg->hdr); + mender_err_t ret = MENDER_OK; + + /* Verify integrity of the message */ + if (NULL == protomsg->hdr->typ) { + mender_log_error("Invalid message received"); + ret = MENDER_FAIL; + goto FAIL; + } + + /* Treatment of the message depending of the message type */ + if (!strcmp(protomsg->hdr->typ, MENDER_TROUBLESHOOT_PORT_FORWARD_MESSAGE_TYPE_NEW)) { + /* Connect to the remote host */ + ret = mender_troubleshoot_port_forwarding_connect_message_handler(protomsg, response); + } else if (!strcmp(protomsg->hdr->typ, MENDER_TROUBLESHOOT_PORT_FORWARD_MESSAGE_TYPE_STOP)) { + /* Close connection to the remote host */ + ret = mender_troubleshoot_port_forwarding_close_message_handler(protomsg, response); + } else if (!strcmp(protomsg->hdr->typ, MENDER_TROUBLESHOOT_PORT_FORWARD_MESSAGE_TYPE_FORWARD)) { + /* Send data to the remote host */ + ret = mender_troubleshoot_port_forwarding_forward_message_handler(protomsg, response); + } else if (!strcmp(protomsg->hdr->typ, MENDER_TROUBLESHOOT_PORT_FORWARD_MESSAGE_TYPE_ACK)) { + /* Nothing to do */ + } else if (!strcmp(protomsg->hdr->typ, MENDER_TROUBLESHOOT_PORT_FORWARD_MESSAGE_TYPE_ERROR)) { + /* Nothing to do */ + } else { + /* Not supported */ + mender_log_error("Unsupported message received with message type '%s'", protomsg->hdr->typ); + ret = MENDER_FAIL; + goto FAIL; + } + +FAIL: + + return ret; +} + +mender_err_t +mender_troubleshoot_port_forwarding_forward(void *data, size_t length) { + + mender_troubleshoot_protomsg_t *protomsg = NULL; + mender_err_t ret = MENDER_OK; + void *payload = NULL; + + /* Check if a session is already opened */ + if (NULL == mender_troubleshoot_port_forwarding_sid) { + mender_log_error("No port forwarding session opened"); + ret = MENDER_FAIL; + goto FAIL; + } + + /* Check if a connection is already opened */ + if (NULL == mender_troubleshoot_port_forwarding_connection_id) { + mender_log_error("No port forwarding connection opened"); + ret = MENDER_FAIL; + goto FAIL; + } + + /* Send port forwarding forward message */ + if (NULL == (protomsg = (mender_troubleshoot_protomsg_t *)malloc(sizeof(mender_troubleshoot_protomsg_t)))) { + mender_log_error("Unable to allocate memory"); + ret = MENDER_FAIL; + goto FAIL; + } + memset(protomsg, 0, sizeof(mender_troubleshoot_protomsg_t)); + if (NULL == (protomsg->hdr = (mender_troubleshoot_protomsg_hdr_t *)malloc(sizeof(mender_troubleshoot_protomsg_hdr_t)))) { + mender_log_error("Unable to allocate memory"); + ret = MENDER_FAIL; + goto FAIL; + } + memset(protomsg->hdr, 0, sizeof(mender_troubleshoot_protomsg_hdr_t)); + protomsg->hdr->proto = MENDER_TROUBLESHOOT_PROTOMSG_HDR_PROTO_PORT_FORWARD; + if (NULL == (protomsg->hdr->typ = strdup(MENDER_TROUBLESHOOT_PORT_FORWARD_MESSAGE_TYPE_FORWARD))) { + mender_log_error("Unable to allocate memory"); + ret = MENDER_FAIL; + goto FAIL; + } + if (NULL == (protomsg->hdr->sid = strdup(mender_troubleshoot_port_forwarding_sid))) { + mender_log_error("Unable to allocate memory"); + ret = MENDER_FAIL; + goto FAIL; + } + if (NULL == (protomsg->hdr->properties = (mender_troubleshoot_protomsg_hdr_properties_t *)malloc(sizeof(mender_troubleshoot_protomsg_hdr_properties_t)))) { + mender_log_error("Unable to allocate memory"); + ret = MENDER_FAIL; + goto FAIL; + } + memset(protomsg->hdr->properties, 0, sizeof(mender_troubleshoot_protomsg_hdr_properties_t)); + if (NULL == (protomsg->hdr->properties->connection_id = strdup(mender_troubleshoot_port_forwarding_connection_id))) { + mender_log_error("Unable to allocate memory"); + ret = MENDER_FAIL; + goto FAIL; + } + if ((NULL != data) && (0 != length)) { + if (NULL == (protomsg->body = (mender_troubleshoot_protomsg_body_t *)malloc(sizeof(mender_troubleshoot_protomsg_body_t)))) { + mender_log_error("Unable to allocate memory"); + ret = MENDER_FAIL; + goto FAIL; + } + memset(protomsg->body, 0, sizeof(mender_troubleshoot_protomsg_body_t)); + if (NULL == (protomsg->body->data = malloc(length))) { + mender_log_error("Unable to allocate memory"); + ret = MENDER_FAIL; + goto FAIL; + } + memcpy(protomsg->body->data, data, length); + protomsg->body->length = length; + } + + /* Encode and pack the message */ + if (MENDER_OK != (ret = mender_troubleshoot_protomsg_pack(protomsg, &payload, &length))) { + mender_log_error("Unable to encode message"); + goto FAIL; + } + + /* Send message */ + if (MENDER_OK != (ret = mender_troubleshoot_api_send(payload, length))) { + mender_log_error("Unable to send message"); + goto FAIL; + } + +FAIL: + + /* Release memory */ + mender_troubleshoot_protomsg_release(protomsg); + if (NULL != payload) { + free(payload); + } + + return ret; +} + +mender_err_t +mender_troubleshoot_port_forwarding_close(void) { + + mender_err_t ret = MENDER_OK; + + /* Check if a session is already opened */ + if (NULL != mender_troubleshoot_port_forwarding_sid) { + + /* Check if a connection is already opened */ + if (NULL != mender_troubleshoot_port_forwarding_connection_id) { + + /* Invoke port forwarding close callback */ + if (NULL != mender_troubleshoot_port_forwarding_callbacks.close) { + if (MENDER_OK != mender_troubleshoot_port_forwarding_callbacks.close(mender_troubleshoot_port_forwarding_handle)) { + mender_log_error("An error occured"); + } + } + + /* Send stop message to the server */ + if (MENDER_OK != (ret = mender_troubleshoot_port_forwarding_send_stop())) { + mender_log_error("Unable to send stop message to the server"); + } + + /* Release connection ID */ + free(mender_troubleshoot_port_forwarding_connection_id); + mender_troubleshoot_port_forwarding_connection_id = NULL; + } + + /* Release session ID */ + free(mender_troubleshoot_port_forwarding_sid); + mender_troubleshoot_port_forwarding_sid = NULL; + } + + return ret; +} + +mender_err_t +mender_troubleshoot_port_forwarding_exit(void) { + + mender_err_t ret; + + /* Close connection if it is opened */ + if (MENDER_OK != (ret = mender_troubleshoot_port_forwarding_close())) { + mender_log_error("Unable to close connection"); + } + + return ret; +} + +static mender_err_t +mender_troubleshoot_port_forwarding_connect_message_handler(mender_troubleshoot_protomsg_t *protomsg, mender_troubleshoot_protomsg_t **response) { + + assert(NULL != protomsg); + mender_troubleshoot_port_forwarding_error_t error; + mender_troubleshoot_port_forwarding_connect_t *connect = NULL; + mender_err_t ret = MENDER_OK; + + /* Initialize error message */ + memset(&error, 0, sizeof(mender_troubleshoot_port_forwarding_error_t)); + + /* Verify integrity of the message */ + if (NULL == protomsg->hdr) { + mender_log_error("Invalid message received"); + error.description = "Invalid message received"; + ret = MENDER_FAIL; + goto FAIL; + } + if (NULL == protomsg->hdr->sid) { + mender_log_error("Invalid message received"); + error.description = "Invalid message received"; + ret = MENDER_FAIL; + goto FAIL; + } + if (NULL == protomsg->hdr->properties) { + mender_log_error("Invalid message received"); + error.description = "Invalid message received"; + ret = MENDER_FAIL; + goto FAIL; + } + if (NULL == protomsg->hdr->properties->connection_id) { + mender_log_error("Invalid message received"); + error.description = "Invalid message received"; + ret = MENDER_FAIL; + goto FAIL; + } + if (NULL == protomsg->hdr->properties->user_id) { + mender_log_error("Invalid message received"); + error.description = "Invalid message received"; + ret = MENDER_FAIL; + goto FAIL; + } + if (NULL == protomsg->body) { + mender_log_error("Invalid message received"); + error.description = "Invalid message received"; + ret = MENDER_FAIL; + goto FAIL; + } + if (NULL == protomsg->body->data) { + mender_log_error("Invalid message received"); + error.description = "Invalid message received"; + ret = MENDER_FAIL; + goto FAIL; + } + + /* Check is a session is already opened */ + if ((NULL != mender_troubleshoot_port_forwarding_sid) || (NULL != mender_troubleshoot_port_forwarding_connection_id)) { + mender_log_warning("A port forwarding session is already opened"); + error.description = "A port forwarding session is already opened"; + ret = MENDER_FAIL; + goto FAIL; + } + + /* Start port forwarding session */ + mender_log_info("Starting a new port forwarding session"); + + /* Save the session ID and connection ID */ + if (NULL == (mender_troubleshoot_port_forwarding_sid = strdup(protomsg->hdr->sid))) { + mender_log_error("Unable to allocate memory"); + error.description = "Internal error"; + ret = MENDER_FAIL; + goto FAIL; + } + if (NULL == (mender_troubleshoot_port_forwarding_connection_id = strdup(protomsg->hdr->properties->connection_id))) { + mender_log_error("Unable to allocate memory"); + error.description = "Internal error"; + ret = MENDER_FAIL; + goto FAIL; + } + + /* Unpack and decode data */ + if (NULL == (connect = mender_troubleshoot_port_forwarding_connect_unpack(protomsg->body->data, protomsg->body->length))) { + mender_log_error("Unable to decode connect request"); + error.description = "Unable to decode connect request"; + ret = MENDER_FAIL; + goto FAIL; + } + + /* Verify integrity of the connect request */ + if ((NULL == connect->remote_host) || (0 == connect->remote_port) || (NULL == connect->protocol)) { + mender_log_error("Invalid message received"); + error.description = "Invalid message received"; + ret = MENDER_FAIL; + goto FAIL; + } + + /* Connect to the remote host */ + if (NULL != mender_troubleshoot_port_forwarding_callbacks.connect) { + if (MENDER_OK + != (ret = mender_troubleshoot_port_forwarding_callbacks.connect( + connect->remote_host, connect->remote_port, connect->protocol, &mender_troubleshoot_port_forwarding_handle))) { + mender_log_error("Unable to connect to '%s:%d' with protocol '%s'", connect->remote_host, connect->remote_port, connect->protocol); + error.description = "Unable to connect to remote host"; + goto FAIL; + } + } + + /* Format ack */ + if (MENDER_OK != (ret = mender_troubleshoot_port_forwarding_format_ack(protomsg, response))) { + mender_log_error("Unable to format response"); + error.description = "Unable to format response"; + goto FAIL; + } + + /* Release memory */ + mender_troubleshoot_port_forwarding_connect_release(connect); + + return ret; + +FAIL: + + /* Format error */ + if (MENDER_OK != mender_troubleshoot_port_forwarding_format_error(protomsg, &error, response)) { + mender_log_error("Unable to format response"); + } + + /* Release memory */ + mender_troubleshoot_port_forwarding_connect_release(connect); + + /* Release connection ID */ + if (NULL != mender_troubleshoot_port_forwarding_connection_id) { + free(mender_troubleshoot_port_forwarding_connection_id); + mender_troubleshoot_port_forwarding_connection_id = NULL; + } + + /* Release session ID */ + if (NULL != mender_troubleshoot_port_forwarding_sid) { + free(mender_troubleshoot_port_forwarding_sid); + mender_troubleshoot_port_forwarding_sid = NULL; + } + + return ret; +} + +static mender_err_t +mender_troubleshoot_port_forwarding_close_message_handler(mender_troubleshoot_protomsg_t *protomsg, mender_troubleshoot_protomsg_t **response) { + + assert(NULL != protomsg); + mender_troubleshoot_port_forwarding_error_t error; + mender_err_t ret = MENDER_OK; + + /* Initialize error message */ + memset(&error, 0, sizeof(mender_troubleshoot_port_forwarding_error_t)); + + /* Check if a session is already opened */ + if (NULL == mender_troubleshoot_port_forwarding_sid) { + mender_log_error("No port forwarding session opened"); + error.description = "No port forwarding session opened"; + ret = MENDER_FAIL; + goto FAIL; + } + + /* Check if a connection is already opened */ + if (NULL == mender_troubleshoot_port_forwarding_connection_id) { + mender_log_error("No port forwarding connection opened"); + error.description = "No port forwarding connection opened"; + ret = MENDER_FAIL; + goto FAIL; + } + + /* Verify integrity of the message */ + if (NULL == protomsg->hdr) { + mender_log_error("Invalid message received"); + error.description = "Invalid message received"; + ret = MENDER_FAIL; + goto FAIL; + } + if (NULL == protomsg->hdr->sid) { + mender_log_error("Invalid message received"); + error.description = "Invalid message received"; + ret = MENDER_FAIL; + goto FAIL; + } + if (NULL == protomsg->hdr->properties) { + mender_log_error("Invalid message received"); + error.description = "Invalid message received"; + ret = MENDER_FAIL; + goto FAIL; + } + if (NULL == protomsg->hdr->properties->connection_id) { + mender_log_error("Invalid message received"); + error.description = "Invalid message received"; + ret = MENDER_FAIL; + goto FAIL; + } + if (NULL == protomsg->hdr->properties->user_id) { + mender_log_error("Invalid message received"); + error.description = "Invalid message received"; + ret = MENDER_FAIL; + goto FAIL; + } + + /* Close connection to the remote host */ + if (NULL != mender_troubleshoot_port_forwarding_callbacks.close) { + if (MENDER_OK != (ret = mender_troubleshoot_port_forwarding_callbacks.close(mender_troubleshoot_port_forwarding_handle))) { + mender_log_error("Unable to close connection"); + error.description = "Unable to close connection"; + goto FAIL; + } + } + + /* Format ack */ + if (MENDER_OK != (ret = mender_troubleshoot_port_forwarding_format_ack(protomsg, response))) { + mender_log_error("Unable to format response"); + error.description = "Unable to format response"; + goto FAIL; + } + + /* Release connection ID */ + if (NULL != mender_troubleshoot_port_forwarding_connection_id) { + free(mender_troubleshoot_port_forwarding_connection_id); + mender_troubleshoot_port_forwarding_connection_id = NULL; + } + + /* Release session ID */ + if (NULL != mender_troubleshoot_port_forwarding_sid) { + free(mender_troubleshoot_port_forwarding_sid); + mender_troubleshoot_port_forwarding_sid = NULL; + } + + return ret; + +FAIL: + + /* Format error */ + if (MENDER_OK != mender_troubleshoot_port_forwarding_format_error(protomsg, &error, response)) { + mender_log_error("Unable to format response"); + } + + return ret; +} + +static mender_err_t +mender_troubleshoot_port_forwarding_forward_message_handler(mender_troubleshoot_protomsg_t *protomsg, mender_troubleshoot_protomsg_t **response) { + + assert(NULL != protomsg); + mender_troubleshoot_port_forwarding_error_t error; + mender_err_t ret = MENDER_OK; + + /* Initialize error message */ + memset(&error, 0, sizeof(mender_troubleshoot_port_forwarding_error_t)); + + /* Check if a session is already opened */ + if (NULL == mender_troubleshoot_port_forwarding_sid) { + mender_log_error("No port forwarding session opened"); + error.description = "No port forwarding session opened"; + ret = MENDER_FAIL; + goto FAIL; + } + + /* Check if a connection is already opened */ + if (NULL == mender_troubleshoot_port_forwarding_connection_id) { + mender_log_error("No port forwarding connection opened"); + error.description = "No port forwarding connection opened"; + ret = MENDER_FAIL; + goto FAIL; + } + + /* Verify integrity of the message */ + if (NULL == protomsg->hdr) { + mender_log_error("Invalid message received"); + error.description = "Invalid message received"; + ret = MENDER_FAIL; + goto FAIL; + } + if (NULL == protomsg->hdr->sid) { + mender_log_error("Invalid message received"); + error.description = "Invalid message received"; + ret = MENDER_FAIL; + goto FAIL; + } + if (NULL == protomsg->hdr->properties) { + mender_log_error("Invalid message received"); + error.description = "Invalid message received"; + ret = MENDER_FAIL; + goto FAIL; + } + if (NULL == protomsg->hdr->properties->connection_id) { + mender_log_error("Invalid message received"); + error.description = "Invalid message received"; + ret = MENDER_FAIL; + goto FAIL; + } + if (NULL == protomsg->hdr->properties->user_id) { + mender_log_error("Invalid message received"); + error.description = "Invalid message received"; + ret = MENDER_FAIL; + goto FAIL; + } + if (NULL == protomsg->body) { + mender_log_error("Invalid message received"); + error.description = "Invalid message received"; + ret = MENDER_FAIL; + goto FAIL; + } + if (NULL == protomsg->body->data) { + mender_log_error("Invalid message received"); + error.description = "Invalid message received"; + ret = MENDER_FAIL; + goto FAIL; + } + + /* Send data to the remote host */ + if (NULL != mender_troubleshoot_port_forwarding_callbacks.send) { + if (MENDER_OK + != (ret = mender_troubleshoot_port_forwarding_callbacks.send( + mender_troubleshoot_port_forwarding_handle, protomsg->body->data, protomsg->body->length))) { + mender_log_error("Unable to send data to remote host"); + error.description = "Unable to send data to remote host"; + goto FAIL; + } + } + + /* Format ack */ + if (MENDER_OK != (ret = mender_troubleshoot_port_forwarding_format_ack(protomsg, response))) { + mender_log_error("Unable to format response"); + error.description = "Unable to format response"; + goto FAIL; + } + + return ret; + +FAIL: + + /* Format error */ + if (MENDER_OK != mender_troubleshoot_port_forwarding_format_error(protomsg, &error, response)) { + mender_log_error("Unable to format response"); + } + + return ret; +} + +static mender_troubleshoot_port_forwarding_connect_t * +mender_troubleshoot_port_forwarding_connect_unpack(void *data, size_t length) { + + assert(NULL != data); + msgpack_zone zone; + msgpack_object object; + mender_troubleshoot_port_forwarding_connect_t *connect = NULL; + + /* Unpack the message */ + if (MENDER_OK != mender_troubleshoot_msgpack_unpack_object(data, length, &zone, &object)) { + mender_log_error("Unable to unpack the data"); + goto END; + } + + /* Check object type */ + if ((MSGPACK_OBJECT_MAP != object.type) || (0 == object.via.map.size)) { + mender_log_error("Invalid upload request object"); + goto END; + } + + /* Decode connect */ + if (NULL == (connect = mender_troubleshoot_port_forwarding_connect_decode(&object))) { + mender_log_error("Invalid connect object"); + goto END; + } + +END: + + /* Release memory */ + msgpack_zone_destroy(&zone); + + return connect; +} + +static mender_troubleshoot_port_forwarding_connect_t * +mender_troubleshoot_port_forwarding_connect_decode(msgpack_object *object) { + + assert(NULL != object); + mender_troubleshoot_port_forwarding_connect_t *connect; + + /* Create connect */ + if (NULL == (connect = (mender_troubleshoot_port_forwarding_connect_t *)malloc(sizeof(mender_troubleshoot_port_forwarding_connect_t)))) { + mender_log_error("Unable to allocate memory"); + return NULL; + } + memset(connect, 0, sizeof(mender_troubleshoot_port_forwarding_connect_t)); + + /* Parse upload request */ + msgpack_object_kv *p = object->via.map.ptr; + do { + if ((MSGPACK_OBJECT_STR == p->key.type) && (!strncmp(p->key.via.str.ptr, "remote_host", p->key.via.str.size)) && (MSGPACK_OBJECT_STR == p->val.type)) { + if (NULL == (connect->remote_host = (char *)malloc(p->val.via.str.size + 1))) { + mender_log_error("Unable to allocate memory"); + goto FAIL; + } + memcpy(connect->remote_host, p->val.via.str.ptr, p->val.via.str.size); + connect->remote_host[p->val.via.str.size] = '\0'; + } else if ((MSGPACK_OBJECT_STR == p->key.type) && (!strncmp(p->key.via.str.ptr, "remote_port", p->key.via.str.size)) + && (MSGPACK_OBJECT_POSITIVE_INTEGER == p->val.type)) { + connect->remote_port = (uint16_t)p->val.via.u64; + } else if ((MSGPACK_OBJECT_STR == p->key.type) && (!strncmp(p->key.via.str.ptr, "protocol", p->key.via.str.size)) + && (MSGPACK_OBJECT_STR == p->val.type)) { + if (NULL == (connect->protocol = (char *)malloc(p->val.via.str.size + 1))) { + mender_log_error("Unable to allocate memory"); + goto FAIL; + } + memcpy(connect->protocol, p->val.via.str.ptr, p->val.via.str.size); + connect->protocol[p->val.via.str.size] = '\0'; + } + ++p; + } while (p < object->via.map.ptr + object->via.map.size); + + return connect; + +FAIL: + + /* Release memory */ + mender_troubleshoot_port_forwarding_connect_release(connect); + + return NULL; +} + +static void +mender_troubleshoot_port_forwarding_connect_release(mender_troubleshoot_port_forwarding_connect_t *connect) { + + /* Release memory */ + if (NULL != connect) { + if (NULL != connect->remote_host) { + free(connect->remote_host); + } + if (NULL != connect->protocol) { + free(connect->protocol); + } + free(connect); + } +} + +static mender_err_t +mender_troubleshoot_port_forwarding_format_ack(mender_troubleshoot_protomsg_t *protomsg, mender_troubleshoot_protomsg_t **response) { + + assert(NULL != protomsg); + assert(NULL != protomsg->hdr); + mender_err_t ret = MENDER_OK; + + /* Format port forwarding ack message */ + if (NULL == (*response = (mender_troubleshoot_protomsg_t *)malloc(sizeof(mender_troubleshoot_protomsg_t)))) { + mender_log_error("Unable to allocate memory"); + ret = MENDER_FAIL; + goto FAIL; + } + memset(*response, 0, sizeof(mender_troubleshoot_protomsg_t)); + if (NULL == ((*response)->hdr = (mender_troubleshoot_protomsg_hdr_t *)malloc(sizeof(mender_troubleshoot_protomsg_hdr_t)))) { + mender_log_error("Unable to allocate memory"); + ret = MENDER_FAIL; + goto FAIL; + } + memset((*response)->hdr, 0, sizeof(mender_troubleshoot_protomsg_hdr_t)); + (*response)->hdr->proto = protomsg->hdr->proto; + if (!strcmp(protomsg->hdr->typ, MENDER_TROUBLESHOOT_PORT_FORWARD_MESSAGE_TYPE_FORWARD)) { + if (NULL == ((*response)->hdr->typ = strdup(MENDER_TROUBLESHOOT_PORT_FORWARD_MESSAGE_TYPE_ACK))) { + mender_log_error("Unable to allocate memory"); + ret = MENDER_FAIL; + goto FAIL; + } + } else { + if (NULL == ((*response)->hdr->typ = strdup(protomsg->hdr->typ))) { + mender_log_error("Unable to allocate memory"); + ret = MENDER_FAIL; + goto FAIL; + } + } + if (NULL != protomsg->hdr->sid) { + if (NULL == ((*response)->hdr->sid = strdup(protomsg->hdr->sid))) { + mender_log_error("Unable to allocate memory"); + ret = MENDER_FAIL; + goto FAIL; + } + } + if (NULL != protomsg->hdr->properties) { + if (NULL + == ((*response)->hdr->properties + = (mender_troubleshoot_protomsg_hdr_properties_t *)malloc(sizeof(mender_troubleshoot_protomsg_hdr_properties_t)))) { + mender_log_error("Unable to allocate memory"); + ret = MENDER_FAIL; + goto FAIL; + } + memset((*response)->hdr->properties, 0, sizeof(mender_troubleshoot_protomsg_hdr_properties_t)); + if (NULL != protomsg->hdr->properties->connection_id) { + if (NULL == ((*response)->hdr->properties->connection_id = strdup(protomsg->hdr->properties->connection_id))) { + mender_log_error("Unable to allocate memory"); + ret = MENDER_FAIL; + goto FAIL; + } + } + } + + return ret; + +FAIL: + + /* Release memory */ + mender_troubleshoot_protomsg_release(*response); + *response = NULL; + + return ret; +} + +static mender_err_t +mender_troubleshoot_port_forwarding_format_error(mender_troubleshoot_protomsg_t *protomsg, + mender_troubleshoot_port_forwarding_error_t *error, + mender_troubleshoot_protomsg_t **response) { + + assert(NULL != protomsg); + assert(NULL != protomsg->hdr); + mender_err_t ret = MENDER_OK; + + /* Format port forwarding error message */ + if (NULL == (*response = (mender_troubleshoot_protomsg_t *)malloc(sizeof(mender_troubleshoot_protomsg_t)))) { + mender_log_error("Unable to allocate memory"); + ret = MENDER_FAIL; + goto FAIL; + } + memset(*response, 0, sizeof(mender_troubleshoot_protomsg_t)); + if (NULL == ((*response)->hdr = (mender_troubleshoot_protomsg_hdr_t *)malloc(sizeof(mender_troubleshoot_protomsg_hdr_t)))) { + mender_log_error("Unable to allocate memory"); + ret = MENDER_FAIL; + goto FAIL; + } + memset((*response)->hdr, 0, sizeof(mender_troubleshoot_protomsg_hdr_t)); + (*response)->hdr->proto = protomsg->hdr->proto; + if (NULL == ((*response)->hdr->typ = strdup(MENDER_TROUBLESHOOT_PORT_FORWARD_MESSAGE_TYPE_ERROR))) { + mender_log_error("Unable to allocate memory"); + ret = MENDER_FAIL; + goto FAIL; + } + if (NULL != protomsg->hdr->sid) { + if (NULL == ((*response)->hdr->sid = strdup(protomsg->hdr->sid))) { + mender_log_error("Unable to allocate memory"); + ret = MENDER_FAIL; + goto FAIL; + } + } + if (NULL != protomsg->hdr->properties) { + if (NULL + == ((*response)->hdr->properties + = (mender_troubleshoot_protomsg_hdr_properties_t *)malloc(sizeof(mender_troubleshoot_protomsg_hdr_properties_t)))) { + mender_log_error("Unable to allocate memory"); + ret = MENDER_FAIL; + goto FAIL; + } + memset((*response)->hdr->properties, 0, sizeof(mender_troubleshoot_protomsg_hdr_properties_t)); + if (NULL != protomsg->hdr->properties->user_id) { + if (NULL == ((*response)->hdr->properties->user_id = strdup(protomsg->hdr->properties->user_id))) { + mender_log_error("Unable to allocate memory"); + ret = MENDER_FAIL; + goto FAIL; + } + } + } + if (NULL == ((*response)->body = (mender_troubleshoot_protomsg_body_t *)malloc(sizeof(mender_troubleshoot_protomsg_body_t)))) { + mender_log_error("Unable to allocate memory"); + ret = MENDER_FAIL; + goto FAIL; + } + memset((*response)->body, 0, sizeof(mender_troubleshoot_protomsg_body_t)); + + /* Encode and pack error message */ + if (MENDER_OK != (ret = mender_troubleshoot_port_forwarding_error_message_pack(error, &((*response)->body->data), &((*response)->body->length)))) { + mender_log_error("Unable to encode message"); + goto FAIL; + } + + return ret; + +FAIL: + + /* Release memory */ + mender_troubleshoot_protomsg_release(*response); + *response = NULL; + + return ret; +} + +/** + * @brief Encode and pack error message + * @param error Error + * @param data Packed data encoded + * @param length Length of the data encoded + * @return MENDER_OK if the function succeeds, error code otherwise + */ +static mender_err_t +mender_troubleshoot_port_forwarding_error_message_pack(mender_troubleshoot_port_forwarding_error_t *error, void **data, size_t *length) { + + assert(NULL != error); + assert(NULL != data); + assert(NULL != length); + mender_err_t ret = MENDER_OK; + msgpack_object object; + + /* Encode error message */ + if (MENDER_OK != (ret = mender_troubleshoot_port_forwarding_error_message_encode(error, &object))) { + mender_log_error("Invalid error message object"); + goto FAIL; + } + + /* Pack error message */ + if (MENDER_OK != (ret = mender_troubleshoot_msgpack_pack_object(&object, data, length))) { + mender_log_error("Unable to pack error message object"); + goto FAIL; + } + + /* Release memory */ + mender_troubleshoot_msgpack_release_object(&object); + + return ret; + +FAIL: + + /* Release memory */ + mender_troubleshoot_msgpack_release_object(&object); + + return ret; +} + +static mender_err_t +mender_troubleshoot_port_forwarding_error_message_encode(mender_troubleshoot_port_forwarding_error_t *error, msgpack_object *object) { + + assert(NULL != error); + assert(NULL != object); + mender_err_t ret = MENDER_OK; + msgpack_object_kv *p; + + /* Create error */ + object->type = MSGPACK_OBJECT_MAP; + if (0 == (object->via.map.size = ((NULL != error->description) ? 1 : 0) + ((NULL != error->type) ? 1 : 0))) { + goto END; + } + if (NULL == (object->via.map.ptr = (msgpack_object_kv *)malloc(object->via.map.size * sizeof(struct msgpack_object_kv)))) { + mender_log_error("Unable to allocate memory"); + ret = MENDER_FAIL; + goto FAIL; + } + + /* Parse error */ + p = object->via.map.ptr; + if (NULL != error->description) { + p->key.type = MSGPACK_OBJECT_STR; + if (NULL == (p->key.via.str.ptr = strdup("err"))) { + mender_log_error("Unable to allocate memory"); + ret = MENDER_FAIL; + goto FAIL; + } + p->key.via.str.size = (uint32_t)strlen("err"); + p->val.type = MSGPACK_OBJECT_STR; + p->val.via.str.size = (uint32_t)strlen(error->description); + if (NULL == (p->val.via.str.ptr = (char *)malloc(p->val.via.str.size))) { + mender_log_error("Unable to allocate memory"); + ret = MENDER_FAIL; + goto FAIL; + } + memcpy((void *)p->val.via.str.ptr, error->description, p->val.via.str.size); + ++p; + } + if (NULL != error->type) { + p->key.type = MSGPACK_OBJECT_STR; + if (NULL == (p->key.via.str.ptr = strdup("msgtype"))) { + mender_log_error("Unable to allocate memory"); + ret = MENDER_FAIL; + goto FAIL; + } + p->key.via.str.size = (uint32_t)strlen("msgtype"); + p->val.type = MSGPACK_OBJECT_STR; + p->val.via.str.size = (uint32_t)strlen(error->type); + if (NULL == (p->val.via.str.ptr = (char *)malloc(p->val.via.str.size))) { + mender_log_error("Unable to allocate memory"); + ret = MENDER_FAIL; + goto FAIL; + } + memcpy((void *)p->val.via.str.ptr, error->type, p->val.via.str.size); + ++p; + } + +END: +FAIL: + + return ret; +} + +static mender_err_t +mender_troubleshoot_port_forwarding_send_stop(void) { + + mender_troubleshoot_protomsg_t *protomsg = NULL; + mender_err_t ret = MENDER_OK; + void *payload = NULL; + size_t length = 0; + + /* Send port forwarding close message */ + if (NULL == (protomsg = (mender_troubleshoot_protomsg_t *)malloc(sizeof(mender_troubleshoot_protomsg_t)))) { + mender_log_error("Unable to allocate memory"); + ret = MENDER_FAIL; + goto FAIL; + } + memset(protomsg, 0, sizeof(mender_troubleshoot_protomsg_t)); + if (NULL == (protomsg->hdr = (mender_troubleshoot_protomsg_hdr_t *)malloc(sizeof(mender_troubleshoot_protomsg_hdr_t)))) { + mender_log_error("Unable to allocate memory"); + ret = MENDER_FAIL; + goto FAIL; + } + memset(protomsg->hdr, 0, sizeof(mender_troubleshoot_protomsg_hdr_t)); + protomsg->hdr->proto = MENDER_TROUBLESHOOT_PROTOMSG_HDR_PROTO_PORT_FORWARD; + if (NULL == (protomsg->hdr->typ = strdup(MENDER_TROUBLESHOOT_PORT_FORWARD_MESSAGE_TYPE_STOP))) { + mender_log_error("Unable to allocate memory"); + ret = MENDER_FAIL; + goto FAIL; + } + if (NULL != mender_troubleshoot_port_forwarding_sid) { + if (NULL == (protomsg->hdr->sid = strdup(mender_troubleshoot_port_forwarding_sid))) { + mender_log_error("Unable to allocate memory"); + ret = MENDER_FAIL; + goto FAIL; + } + } + if (NULL == (protomsg->hdr->properties = (mender_troubleshoot_protomsg_hdr_properties_t *)malloc(sizeof(mender_troubleshoot_protomsg_hdr_properties_t)))) { + mender_log_error("Unable to allocate memory"); + ret = MENDER_FAIL; + goto FAIL; + } + memset(protomsg->hdr->properties, 0, sizeof(mender_troubleshoot_protomsg_hdr_properties_t)); + if (NULL != mender_troubleshoot_port_forwarding_connection_id) { + if (NULL == (protomsg->hdr->properties->connection_id = strdup(mender_troubleshoot_port_forwarding_connection_id))) { + mender_log_error("Unable to allocate memory"); + ret = MENDER_FAIL; + goto FAIL; + } + } + + /* Encode and pack the message */ + if (MENDER_OK != (ret = mender_troubleshoot_protomsg_pack(protomsg, &payload, &length))) { + mender_log_error("Unable to encode message"); + goto FAIL; + } + + /* Send message */ + if (MENDER_OK != (ret = mender_troubleshoot_api_send(payload, length))) { + mender_log_error("Unable to send message"); + goto FAIL; + } + +FAIL: + + /* Release memory */ + mender_troubleshoot_protomsg_release(protomsg); + if (NULL != payload) { + free(payload); + } + + return ret; +} + +#endif /* CONFIG_MENDER_CLIENT_TROUBLESHOOT_PORT_FORWARDING */ +#endif /* CONFIG_MENDER_CLIENT_ADD_ON_TROUBLESHOOT */ diff --git a/add-ons/troubleshoot/src/mender-troubleshoot.c b/add-ons/troubleshoot/src/mender-troubleshoot.c index e90d728..c9ad6ce 100644 --- a/add-ons/troubleshoot/src/mender-troubleshoot.c +++ b/add-ons/troubleshoot/src/mender-troubleshoot.c @@ -25,6 +25,7 @@ #include "mender-troubleshoot-control.h" #include "mender-troubleshoot-file-transfer.h" #include "mender-troubleshoot-mender-client.h" +#include "mender-troubleshoot-port-forwarding.h" #include "mender-troubleshoot-protomsg.h" #include "mender-troubleshoot-shell.h" @@ -112,6 +113,12 @@ mender_troubleshoot_init(void *config, void *callbacks) { mender_log_error("Unable to initialize mender client handler"); goto END; } +#ifdef CONFIG_MENDER_CLIENT_TROUBLESHOOT_PORT_FORWARDING + if (MENDER_OK != (ret = mender_troubleshoot_port_forwarding_init(&((mender_troubleshoot_callbacks_t *)callbacks)->port_forwarding))) { + mender_log_error("Unable to initialize port forwarding handler"); + goto END; + } +#endif /* CONFIG_MENDER_CLIENT_TROUBLESHOOT_PORT_FORWARDING */ #ifdef CONFIG_MENDER_CLIENT_TROUBLESHOOT_SHELL mender_troubleshoot_shell_config_t mender_troubleshoot_shell_config = { .healthcheck_interval = mender_troubleshoot_config.healthcheck_interval }; if (MENDER_OK != (ret = mender_troubleshoot_shell_init(&mender_troubleshoot_shell_config, &((mender_troubleshoot_callbacks_t *)callbacks)->shell))) { @@ -192,6 +199,9 @@ mender_troubleshoot_exit(void) { #ifdef CONFIG_MENDER_CLIENT_TROUBLESHOOT_SHELL mender_troubleshoot_shell_exit(); #endif /* CONFIG_MENDER_CLIENT_TROUBLESHOOT_SHELL */ +#ifdef CONFIG_MENDER_CLIENT_TROUBLESHOOT_PORT_FORWARDING + mender_troubleshoot_port_forwarding_exit(); +#endif /* CONFIG_MENDER_CLIENT_TROUBLESHOOT_PORT_FORWARDING */ mender_troubleshoot_mender_client_exit(); #ifdef CONFIG_MENDER_CLIENT_TROUBLESHOOT_FILE_TRANSFER mender_troubleshoot_file_transfer_exit(); @@ -319,10 +329,11 @@ mender_troubleshoot_data_received_callback(void *data, size_t length) { ret = mender_troubleshoot_file_transfer_message_handler(protomsg, &response); break; #endif /* CONFIG_MENDER_CLIENT_TROUBLESHOOT_FILE_TRANSFER */ +#ifdef CONFIG_MENDER_CLIENT_TROUBLESHOOT_PORT_FORWARDING case MENDER_TROUBLESHOOT_PROTOMSG_HDR_PROTO_PORT_FORWARD: - mender_log_error("Port Forwarding is not supported"); - ret = MENDER_FAIL; + ret = mender_troubleshoot_port_forwarding_message_handler(protomsg, &response); break; +#endif /* CONFIG_MENDER_CLIENT_TROUBLESHOOT_PORT_FORWARDING */ default: mender_log_error("Unsupported message received with proto type 0x%04x", protomsg->hdr->proto); ret = MENDER_FAIL; diff --git a/esp-idf/CMakeLists.txt b/esp-idf/CMakeLists.txt index e4795a3..3a10bb9 100755 --- a/esp-idf/CMakeLists.txt +++ b/esp-idf/CMakeLists.txt @@ -60,6 +60,11 @@ if(CONFIG_MENDER_CLIENT_ADD_ON_TROUBLESHOOT) "${CMAKE_CURRENT_LIST_DIR}/../add-ons/troubleshoot/src/mender-troubleshoot-file-transfer.c" ) endif() + if(CONFIG_MENDER_CLIENT_TROUBLESHOOT_PORT_FORWARDING) + list(APPEND srcs + "${CMAKE_CURRENT_LIST_DIR}/../add-ons/troubleshoot/src/mender-troubleshoot-port-forwarding.c" + ) + endif() endif() # List of includes diff --git a/esp-idf/Kconfig b/esp-idf/Kconfig index e74c564..8fd7b86 100755 --- a/esp-idf/Kconfig +++ b/esp-idf/Kconfig @@ -157,6 +157,12 @@ menu "Mender Firmware Over-the-Air support" help Troubleshoot file transfer permits to upload/download files to/from the device on the Mender server. + config MENDER_CLIENT_TROUBLESHOOT_PORT_FORWARDING + bool "Mender client Troubleshoot Port Forwarding" + default n + help + Troubleshoot port forwarding permits to remotly connect to a local service from the Mender server. + endif endmenu diff --git a/include/mender-troubleshoot.h b/include/mender-troubleshoot.h index 1be4387..e5348f3 100644 --- a/include/mender-troubleshoot.h +++ b/include/mender-troubleshoot.h @@ -30,6 +30,7 @@ extern "C" { #ifdef CONFIG_MENDER_CLIENT_ADD_ON_TROUBLESHOOT #include "mender-troubleshoot-file-transfer.h" +#include "mender-troubleshoot-port-forwarding.h" #include "mender-troubleshoot-shell.h" /** @@ -52,6 +53,9 @@ typedef struct { #ifdef CONFIG_MENDER_CLIENT_TROUBLESHOOT_FILE_TRANSFER mender_troubleshoot_file_transfer_callbacks_t file_transfer; /**< File transfer callbacks */ #endif /* CONFIG_MENDER_CLIENT_TROUBLESHOOT_FILE_TRANSFER */ +#ifdef CONFIG_MENDER_CLIENT_TROUBLESHOOT_PORT_FORWARDING + mender_troubleshoot_port_forwarding_callbacks_t port_forwarding; /**< Port forwarding callbacks */ +#endif /* CONFIG_MENDER_CLIENT_TROUBLESHOOT_PORT_FORWARDING */ #ifdef CONFIG_MENDER_CLIENT_TROUBLESHOOT_SHELL mender_troubleshoot_shell_callbacks_t shell; /**< Shell callbacks */ #endif /* CONFIG_MENDER_CLIENT_TROUBLESHOOT_SHELL */ diff --git a/tests/src/main.c b/tests/src/main.c index 53c6820..b455083 100644 --- a/tests/src/main.c +++ b/tests/src/main.c @@ -17,12 +17,16 @@ * limitations under the License. */ +#include +#include #include #include #include #include #include +#include #include +#include #include "mender-client.h" #include "mender-configure.h" #include "mender-flash.h" @@ -306,6 +310,117 @@ file_transfer_close_cb(void *handle) { } #endif /* CONFIG_MENDER_CLIENT_TROUBLESHOOT_FILE_TRANSFER */ +#ifdef CONFIG_MENDER_CLIENT_TROUBLESHOOT_PORT_FORWARDING + +/** + * Port forwarding handle + */ +typedef struct { + int socket; /**< Socket */ + pthread_t thread_handle; /**< Read thread */ +} port_forwarding_handle_t; + +static void * +port_forwarding_client_thread(void *arg) { + + assert(NULL != arg); + port_forwarding_handle_t *handle = (port_forwarding_handle_t *)arg; + uint8_t data[64]; + ssize_t ret; + + /* Read data from remote host */ + while ((ret = read(handle->socket, data, sizeof(data))) > 0) { + mender_troubleshoot_port_forwarding_forward(data, ret); + } + + return NULL; +} + +static mender_err_t +port_forwarding_connect_cb(char *remote_host, uint16_t remote_port, char *protocol, void **handle) { + + assert(NULL != remote_host); + assert(0 != remote_port); + assert(NULL != protocol); + assert(NULL != handle); + + /* Allocate handle */ + if (NULL == (*handle = malloc(sizeof(port_forwarding_handle_t)))) { + mender_log_error("Unable to allocate memory"); + return MENDER_FAIL; + } + memset(*handle, 0, sizeof(port_forwarding_handle_t)); + + /* Create socket */ + ((port_forwarding_handle_t *)(*handle))->socket = socket(AF_INET, (!strcmp(protocol, "tcp")) ? SOCK_STREAM : SOCK_DGRAM, 0); + if (((port_forwarding_handle_t *)(*handle))->socket < 0) { + mender_log_error("Unable to create socket (errno=%d)", errno); + free(*handle); + *handle = NULL; + return MENDER_FAIL; + } + + /* Connect */ + struct sockaddr_in serv_addr; + memset(&serv_addr, 0, sizeof(serv_addr)); + serv_addr.sin_family = AF_INET; + serv_addr.sin_addr.s_addr = inet_addr(remote_host); + serv_addr.sin_port = htons(remote_port); + if (connect(((port_forwarding_handle_t *)(*handle))->socket, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) { + mender_log_error("Unable to connect to '%s:%d' (errno=%d)", remote_host, remote_port, errno); + close(((port_forwarding_handle_t *)(*handle))->socket); + free(*handle); + *handle = NULL; + return MENDER_FAIL; + } + mender_log_info("Connection to remote host '%s:%d' with protocol '%s' opened", remote_host, remote_port, protocol); + + /* Create client thread to read data from the remote host */ + if (0 != pthread_create(&((port_forwarding_handle_t *)(*handle))->thread_handle, NULL, &port_forwarding_client_thread, *handle)) { + mender_log_error("Unable to create read thread"); + close(((port_forwarding_handle_t *)(*handle))->socket); + free(*handle); + *handle = NULL; + return MENDER_FAIL; + } + + return MENDER_OK; +} + +static mender_err_t +port_forwarding_send_cb(void *handle, void *data, size_t length) { + + assert(NULL != handle); + assert(NULL != data); + + /* Send data */ + if (send(((port_forwarding_handle_t *)handle)->socket, data, length, 0) < 0) { + mender_log_error("Unable to send data"); + return MENDER_FAIL; + } + + return MENDER_OK; +} + +static mender_err_t +port_forwarding_close_cb(void *handle) { + + assert(NULL != handle); + + /* Close socket */ + close(((port_forwarding_handle_t *)handle)->socket); + mender_log_info("Connection to remote host closed"); + + /* Wait end of execution of the client thread */ + pthread_join(((port_forwarding_handle_t *)handle)->thread_handle, NULL); + + /* Release memory */ + free(handle); + + return MENDER_OK; +} + +#endif /* CONFIG_MENDER_CLIENT_TROUBLESHOOT_PORT_FORWARDING */ #ifdef CONFIG_MENDER_CLIENT_TROUBLESHOOT_SHELL /** @@ -655,6 +770,9 @@ main(int argc, char **argv) { .write = file_transfer_write_cb, .close = file_transfer_close_cb }, #endif /* CONFIG_MENDER_CLIENT_TROUBLESHOOT_FILE_TRANSFER */ +#ifdef CONFIG_MENDER_CLIENT_TROUBLESHOOT_PORT_FORWARDING + .port_forwarding = { .connect = port_forwarding_connect_cb, .send = port_forwarding_send_cb, .close = port_forwarding_close_cb }, +#endif /* CONFIG_MENDER_CLIENT_TROUBLESHOOT_PORT_FORWARDING */ #ifdef CONFIG_MENDER_CLIENT_TROUBLESHOOT_SHELL .shell = { .open = shell_open_cb, .resize = shell_resize_cb, .write = shell_write_cb, .close = shell_close_cb } #endif /* CONFIG_MENDER_CLIENT_TROUBLESHOOT_SHELL */ diff --git a/zephyr/CMakeLists.txt b/zephyr/CMakeLists.txt index 9e1528d..cff1f93 100755 --- a/zephyr/CMakeLists.txt +++ b/zephyr/CMakeLists.txt @@ -54,6 +54,9 @@ if(CONFIG_MENDER_MCU_CLIENT) zephyr_library_sources_ifdef(CONFIG_MENDER_CLIENT_TROUBLESHOOT_FILE_TRANSFER "${CMAKE_CURRENT_LIST_DIR}/../add-ons/troubleshoot/src/mender-troubleshoot-file-transfer.c" ) + zephyr_library_sources_ifdef(CONFIG_MENDER_CLIENT_TROUBLESHOOT_PORT_FORWARDING + "${CMAKE_CURRENT_LIST_DIR}/../add-ons/troubleshoot/src/mender-troubleshoot-port-forwarding.c" + ) zephyr_include_directories("${CMAKE_CURRENT_LIST_DIR}/../include") zephyr_include_directories("${CMAKE_CURRENT_LIST_DIR}/../platform/net/${CONFIG_MENDER_PLATFORM_NET_TYPE}/include") zephyr_include_directories_ifdef(CONFIG_MENDER_CLIENT_ADD_ON_CONFIGURE diff --git a/zephyr/Kconfig b/zephyr/Kconfig index 0515c0b..2f497e1 100755 --- a/zephyr/Kconfig +++ b/zephyr/Kconfig @@ -158,6 +158,12 @@ if MENDER_MCU_CLIENT help Troubleshoot file transfer permits to upload/download files to/from the device on the Mender server. + config MENDER_CLIENT_TROUBLESHOOT_PORT_FORWARDING + bool "Mender client Troubleshoot Port Forwarding" + default n + help + Troubleshoot port forwarding permits to remotly connect to a local service from the Mender server. + endif endmenu