From 65792ab40882dda6a4db8a6a71ca1694ff21c917 Mon Sep 17 00:00:00 2001 From: Steve Karg Date: Wed, 3 May 2023 23:33:06 -0500 Subject: [PATCH] Update address in VMAC table for IPv6 (#429) * Update address in VMAC table for IPv6 * fix compile warnings in IPv6 handler * cleanup BIP6 PRINTF * enable unit test for BBMD6 hander * keylist should only return FALSE when growing fails --------- Co-authored-by: Steve Karg --- src/bacnet/basic/bbmd6/h_bbmd6.c | 107 +++++++++++++------- src/bacnet/basic/sys/keylist.c | 2 - test/CMakeLists.txt | 2 +- test/bacnet/basic/bbmd6/CMakeLists.txt | 48 +++++++++ test/bacnet/basic/bbmd6/Makefile | 52 ---------- test/bacnet/basic/bbmd6/{ => src}/main.c | 123 ++++++++++++----------- 6 files changed, 182 insertions(+), 152 deletions(-) create mode 100644 test/bacnet/basic/bbmd6/CMakeLists.txt delete mode 100644 test/bacnet/basic/bbmd6/Makefile rename test/bacnet/basic/bbmd6/{ => src}/main.c (74%) diff --git a/src/bacnet/basic/bbmd6/h_bbmd6.c b/src/bacnet/basic/bbmd6/h_bbmd6.c index c9159248..8e981305 100644 --- a/src/bacnet/basic/bbmd6/h_bbmd6.c +++ b/src/bacnet/basic/bbmd6/h_bbmd6.c @@ -48,15 +48,27 @@ static bool BVLC6_Debug; #if PRINT_ENABLED #include #include -#define PRINTF(...) \ - if (BVLC6_Debug) { \ - fprintf(stderr, __VA_ARGS__); \ - fflush(stderr); \ - } -#else -#define PRINTF(...) -#endif +static int printf_stderr(const char *format, ...) +{ + int length = 0; + va_list ap; + if (BVLC6_Debug) { + va_start(ap, format); + length = vfprintf(stderr, format, ap); + va_end(ap); + fflush(stderr); + } + + return length; +} +#else +static int printf_stderr(const char *format, ...) { + (void)format; + return 0; +} +#endif +#define PRINTF printf_stderr /** result from a client request */ static uint16_t BVLC6_Result_Code = BVLC6_RESULT_SUCCESSFUL_COMPLETION; /** incoming function */ @@ -115,6 +127,8 @@ void bvlc6_maintenance_timer(uint16_t seconds) } } } +#else + (void)seconds; #endif } @@ -174,39 +188,60 @@ static bool bbmd6_address_to_vmac( * * @param device_id - device ID used as the key-pair * @param addr - IPv6 source address - * - * @return true if the VMAC address was added */ -static bool bbmd6_add_vmac(uint32_t device_id, BACNET_IP6_ADDRESS *addr) +static void bbmd6_add_vmac(uint32_t device_id, BACNET_IP6_ADDRESS *addr) { - bool status = false; + bool found = false; + uint32_t list_device_id = 0; struct vmac_data *vmac; struct vmac_data new_vmac; unsigned i = 0; - if (addr) { - vmac = VMAC_Find_By_Key(device_id); - if (vmac) { - /* already exists - replace? */ - PRINTF("VMAC existing %u [", (unsigned int)device_id); - for (i = 0; i < vmac->mac_len; i++) { - PRINTF("%02X", vmac->mac[i]); + if (bbmd6_address_to_vmac(&new_vmac, addr)) { + if (VMAC_Find_By_Data(&new_vmac, &list_device_id)) { + if (list_device_id == device_id) { + /* valid VMAC entry exists. */ + found = true; + } else { + /* VMAC exists, but device ID changed */ + VMAC_Delete(list_device_id); + PRINTF("BVLC6: VMAC existed for %u [", + (unsigned int)list_device_id); + for (i = 0; i < new_vmac.mac_len; i++) { + PRINTF("%02X", new_vmac.mac[i]); + } + PRINTF("]\n"); + PRINTF("BVLC6: Removed VMAC for %lu.\n", + (unsigned long)list_device_id); } - PRINTF("]\n"); - PRINTF("VMAC ignoring %u [", (unsigned int)device_id); - for (i = 0; i < IP6_ADDRESS_MAX; i++) { - PRINTF("%02X", addr->address[i]); + } + if (!found) { + vmac = VMAC_Find_By_Key(device_id); + if (vmac) { + /* device ID already exists. Update MAC. */ + memmove(vmac, &new_vmac, sizeof(struct vmac_data)); + PRINTF("BVLC6: VMAC for %u [", + (unsigned int)device_id); + for (i = 0; i < new_vmac.mac_len; i++) { + PRINTF("%02X", new_vmac.mac[i]); + } + PRINTF("]\n"); + PRINTF("BVLC6: Updated VMAC for %lu.\n", + (unsigned long)device_id); + } else { + /* new entry - add it! */ + VMAC_Add(device_id, &new_vmac); + PRINTF("BVLC6: VMAC for %u [", + (unsigned int)device_id); + for (i = 0; i < new_vmac.mac_len; i++) { + PRINTF("%02X", new_vmac.mac[i]); + } + PRINTF("]\n"); + PRINTF("BVLC6: Added VMAC for %lu.\n", + (unsigned long)device_id); } - PRINTF("%04X", addr->port); - PRINTF("]\n"); - } else if (bbmd6_address_to_vmac(&new_vmac, addr)) { - /* new entry - add it! */ - status = VMAC_Add(device_id, &new_vmac); - PRINTF("BVLC6: Adding VMAC %lu.\n", (unsigned long)device_id); } } - - return status; } /** @@ -218,7 +253,7 @@ static bool bbmd6_add_vmac(uint32_t device_id, BACNET_IP6_ADDRESS *addr) */ static bool bbmd6_address_match_self(BACNET_IP6_ADDRESS *addr) { - BACNET_IP6_ADDRESS my_addr = { { 0 } }; + BACNET_IP6_ADDRESS my_addr = { 0 }; bool status = false; if (bip6_get_addr(&my_addr)) { @@ -282,7 +317,7 @@ int bvlc6_send_pdu(BACNET_ADDRESS *dest, uint8_t *pdu, unsigned pdu_len) { - BACNET_IP6_ADDRESS bvlc_dest = { { 0 } }; + BACNET_IP6_ADDRESS bvlc_dest = { 0 }; uint8_t mtu[BIP6_MPDU_MAX] = { 0 }; uint16_t mtu_len = 0; uint32_t vmac_src = 0; @@ -348,7 +383,7 @@ int bvlc6_send_pdu(BACNET_ADDRESS *dest, */ static void bbmd6_send_pdu_bdt(uint8_t *mtu, unsigned int mtu_len) { - BACNET_IP6_ADDRESS my_addr = { { 0 } }; + BACNET_IP6_ADDRESS my_addr = { 0 }; unsigned i = 0; /* loop counter */ if (mtu) { @@ -375,7 +410,7 @@ static void bbmd6_send_pdu_bdt(uint8_t *mtu, unsigned int mtu_len) */ static void bbmd6_send_pdu_fdt(uint8_t *mtu, unsigned int mtu_len) { - BACNET_IP6_ADDRESS my_addr = { { 0 } }; + BACNET_IP6_ADDRESS my_addr = { 0 }; unsigned i = 0; /* loop counter */ if (mtu) { @@ -655,7 +690,7 @@ int bvlc6_bbmd_disabled_handler(BACNET_IP6_ADDRESS *addr, uint16_t npdu_len = 0; bool send_result = false; uint16_t offset = 0; - BACNET_IP6_ADDRESS fwd_address = { { 0 } }; + BACNET_IP6_ADDRESS fwd_address = { 0 }; header_len = bvlc6_decode_header(mtu, mtu_len, &message_type, &message_length); diff --git a/src/bacnet/basic/sys/keylist.c b/src/bacnet/basic/sys/keylist.c index 5df6c2fc..e56cb58a 100644 --- a/src/bacnet/basic/sys/keylist.c +++ b/src/bacnet/basic/sys/keylist.c @@ -119,8 +119,6 @@ static int CheckArraySize(OS_Keylist list) } list->array = new_array; list->size = new_size; - } else if (new_size < 0) { - return FALSE; } return TRUE; diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 96ed7efd..f7ec5ff0 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -81,8 +81,8 @@ list(APPEND testdirs # bacnet/basic/* list(APPEND testdirs - # basic/object/binding bacnet/basic/binding/address + bacnet/basic/bbmd6 # basic/object bacnet/basic/object/acc bacnet/basic/object/access_credential diff --git a/test/bacnet/basic/bbmd6/CMakeLists.txt b/test/bacnet/basic/bbmd6/CMakeLists.txt new file mode 100644 index 00000000..812352bc --- /dev/null +++ b/test/bacnet/basic/bbmd6/CMakeLists.txt @@ -0,0 +1,48 @@ +# SPDX-License-Identifier: MIT + +cmake_minimum_required(VERSION 3.10 FATAL_ERROR) + +get_filename_component(basename ${CMAKE_CURRENT_SOURCE_DIR} NAME) +project(test_${basename} + VERSION 1.0.0 + LANGUAGES C) + + +string(REGEX REPLACE + "/test/bacnet/[a-zA-Z0-9_/-]*$" + "/src" + SRC_DIR + ${CMAKE_CURRENT_SOURCE_DIR}) +string(REGEX REPLACE + "/test/bacnet/[a-zA-Z0-9_/-]*$" + "/test" + TST_DIR + ${CMAKE_CURRENT_SOURCE_DIR}) + +add_compile_definitions( + BIG_ENDIAN=0 + ) + +include_directories( + ${SRC_DIR} + ) + +add_executable(${PROJECT_NAME} + # File(s) under test + ${SRC_DIR}/bacnet/basic/bbmd6/h_bbmd6.c + ${SRC_DIR}/bacnet/basic/bbmd6/vmac.c + # Support files and stubs (pathname alphabetical) + ${SRC_DIR}/bacnet/bacdcode.c + ${SRC_DIR}/bacnet/bacint.c + ${SRC_DIR}/bacnet/bacstr.c + ${SRC_DIR}/bacnet/bacreal.c + ${SRC_DIR}/bacnet/iam.c + ${SRC_DIR}/bacnet/npdu.c + ${SRC_DIR}/bacnet/basic/sys/bigend.c + ${SRC_DIR}/bacnet/basic/sys/keylist.c + ${SRC_DIR}/bacnet/basic/bbmd6/h_bbmd6.c + ${SRC_DIR}/bacnet/basic/bbmd6/vmac.c + ${SRC_DIR}/bacnet/datalink/bvlc6.c + # Test and test library files + ./src/main.c + ) diff --git a/test/bacnet/basic/bbmd6/Makefile b/test/bacnet/basic/bbmd6/Makefile deleted file mode 100644 index dd8a3d3d..00000000 --- a/test/bacnet/basic/bbmd6/Makefile +++ /dev/null @@ -1,52 +0,0 @@ -#Makefile to build test case -CC = gcc -SRC_DIR = ../../../../src -TEST_DIR = ../../.. -INCLUDES = -I$(SRC_DIR) -I$(TEST_DIR) -DEFINES = -DBIG_ENDIAN=0 -DDEBUG_ENABLED=0 - -CFLAGS = -Wall $(INCLUDES) $(DEFINES) -g - -SRCS = main.c \ - $(SRC_DIR)/bacnet/bacdcode.c \ - $(SRC_DIR)/bacnet/bacint.c \ - $(SRC_DIR)/bacnet/bacstr.c \ - $(SRC_DIR)/bacnet/bacreal.c \ - $(SRC_DIR)/bacnet/iam.c \ - $(SRC_DIR)/bacnet/npdu.c \ - $(SRC_DIR)/bacnet/basic/sys/keylist.c \ - $(SRC_DIR)/bacnet/basic/bbmd6/h_bbmd6.c \ - $(SRC_DIR)/bacnet/basic/bbmd6/vmac.c \ - $(SRC_DIR)/bacnet/datalink/bvlc6.c \ - $(SRC_DIR)/bacnet/basic/sys/debug.c \ - $(TEST_DIR)/ctest.c - -TARGET_NAME = unittest -ifeq ($(OS),Windows_NT) -TARGET_EXT = .exe -else -TARGET_EXT = -endif -TARGET = $(TARGET_NAME)$(TARGET_EXT) - -all: ${TARGET} - -OBJS = ${SRCS:.c=.o} - -${TARGET}: ${OBJS} - ${CC} -o $@ ${OBJS} - -.c.o: - ${CC} -c ${CFLAGS} $*.c -o $@ - -depend: - rm -f .depend - ${CC} -MM ${CFLAGS} *.c >> .depend - -clean: - rm -rf ${TARGET} $(OBJS) - -test: ${TARGET} - ./${TARGET} - -include: .depend diff --git a/test/bacnet/basic/bbmd6/main.c b/test/bacnet/basic/bbmd6/src/main.c similarity index 74% rename from test/bacnet/basic/bbmd6/main.c rename to test/bacnet/basic/bbmd6/src/main.c index 3b4d6e6a..eceb886e 100644 --- a/test/bacnet/basic/bbmd6/main.c +++ b/test/bacnet/basic/bbmd6/src/main.c @@ -4,26 +4,7 @@ * @date April 2020 * @brief Test file for a basic BBMD for BVLC IPv6 handler * - * @section LICENSE - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * SPDX-License-Identifier: MIT */ #include /* for standard i/o, like printing */ #include /* for standard integer types uint8_t etc. */ @@ -40,7 +21,6 @@ #include "bacnet/basic/object/device.h" #include "bacnet/basic/bbmd6/h_bbmd6.h" #include "bacnet/basic/bbmd6/vmac.h" -#include "ctest.h" struct device_info_t { uint32_t Device_ID; @@ -51,6 +31,10 @@ struct device_info_t { static struct device_info_t TD; static struct device_info_t IUT; +#ifndef MAX_MPDU +#define MAX_MPDU 1497 +#endif + /* for the reply sent from the handler */ static uint8_t Test_Sent_Message_Type; static uint8_t Test_Sent_Message_Length; @@ -171,7 +155,7 @@ static void test_cleanup(void) /** * @brief Test 15.2.1.1 Initiate Original-Broadcast-NPDU */ -static void test_Initiate_Original_Broadcast_NPDU(Test *pTest) +static void test_Initiate_Original_Broadcast_NPDU(void) { uint8_t pdu[MAX_MPDU] = {0}; int npdu_len = 0; @@ -194,22 +178,22 @@ static void test_Initiate_Original_Broadcast_NPDU(Test *pTest) pdu_len = npdu_len + apdu_len; bvlc6_send_pdu(&dest, &npdu_data, pdu, pdu_len); /* DA=Link Local Multicast Address */ - ct_test(pTest, !bvlc6_address_different(&TD.BIP6_Broadcast_Addr, + assert(!bvlc6_address_different(&TD.BIP6_Broadcast_Addr, &Test_Sent_Message_Dest)); /* SA = IUT - done in port layer */ /* Original-Broadcast-NPDU */ - ct_test(pTest, Test_Sent_Message_Type == + assert(Test_Sent_Message_Type == BVLC6_ORIGINAL_BROADCAST_NPDU); if (Test_Sent_Message_Type == BVLC6_ORIGINAL_BROADCAST_NPDU) { function_len = bvlc6_decode_original_broadcast( Test_Sent_Message_Buffer, Test_Sent_Message_Buffer_Length, &test_vmac_src, test_pdu, sizeof(test_pdu), &test_pdu_len); - ct_test(pTest, function_len > 0); + assert(function_len > 0); /* Source-Virtual-Address = IUT */ - ct_test(pTest, test_vmac_src == IUT.Device_ID); + assert(test_vmac_src == IUT.Device_ID); /* (any valid BACnet-Unconfirmed-Request-PDU, with any valid broadcast network options */ - ct_test(pTest, test_pdu_len == pdu_len); + assert(test_pdu_len == pdu_len); } test_cleanup(); } @@ -217,12 +201,13 @@ static void test_Initiate_Original_Broadcast_NPDU(Test *pTest) /** * @brief Test 15.1.2 Execute Virtual-Address-Resolution */ -static void test_Execute_Virtual_Address_Resolution(Test *pTest) +static void test_Execute_Virtual_Address_Resolution(void) { uint8_t mtu[MAX_MPDU] = {0}; uint16_t mtu_len = 0; uint32_t test_vmac_src = 0; uint32_t test_vmac_dst = 0; + uint32_t old_device_id = 0; int result = 0; int function_len = 0; @@ -231,24 +216,59 @@ static void test_Execute_Virtual_Address_Resolution(Test *pTest) &mtu[0], sizeof(mtu), TD.Device_ID); result = bvlc6_bbmd_disabled_handler(&TD.BIP6_Addr, &TD.BACnet_Address, &mtu[0], mtu_len); - ct_test(pTest, result == 0); - ct_test(pTest, bvlc6_get_function_code() == + assert(result == 0); + assert(bvlc6_get_function_code() == BVLC6_VIRTUAL_ADDRESS_RESOLUTION); - ct_test(pTest, Test_Sent_Message_Type == + assert(Test_Sent_Message_Type == BVLC6_VIRTUAL_ADDRESS_RESOLUTION_ACK); - ct_test(pTest, VMAC_Find_By_Key(TD.Device_ID) != NULL); + assert(VMAC_Find_By_Key(TD.Device_ID) != NULL); if (Test_Sent_Message_Type == BVLC6_VIRTUAL_ADDRESS_RESOLUTION_ACK) { function_len = bvlc6_decode_virtual_address_resolution_ack( Test_Sent_Message_Buffer, Test_Sent_Message_Buffer_Length, &test_vmac_src, &test_vmac_dst); - ct_test(pTest, function_len > 0); - ct_test(pTest, test_vmac_src == IUT.Device_ID); - ct_test(pTest, test_vmac_dst == TD.Device_ID); + assert(function_len > 0); + assert(test_vmac_src == IUT.Device_ID); + assert(test_vmac_dst == TD.Device_ID); } + /* change Device ID */ + old_device_id = TD.Device_ID; + TD.Device_ID += 42; + mtu_len = bvlc6_encode_virtual_address_resolution( + &mtu[0], sizeof(mtu), TD.Device_ID); + result = bvlc6_bbmd_disabled_handler(&TD.BIP6_Addr, &TD.BACnet_Address, + &mtu[0], mtu_len); + assert(result == 0); + assert(bvlc6_get_function_code() == + BVLC6_VIRTUAL_ADDRESS_RESOLUTION); + assert(VMAC_Find_By_Key(TD.Device_ID) != NULL); + assert(VMAC_Find_By_Key(old_device_id) == NULL); + /* change IPv6 address */ + mtu_len = bvlc6_encode_virtual_address_resolution( + &mtu[0], sizeof(mtu), TD.Device_ID); + bvlc6_address_set(&TD.BIP6_Addr, + 0x2001, 0x0DBB, 0xAC10, 0xFE01, 0, 0, 42, + BIP6_MULTICAST_GROUP_ID); + result = bvlc6_bbmd_disabled_handler(&TD.BIP6_Addr, &TD.BACnet_Address, + &mtu[0], mtu_len); + assert(result == 0); + assert(bvlc6_get_function_code() == + BVLC6_VIRTUAL_ADDRESS_RESOLUTION); + assert(VMAC_Find_By_Key(TD.Device_ID) != NULL); + /* repeat with same device ID and address */ + /* change IPv6 address */ + mtu_len = bvlc6_encode_virtual_address_resolution( + &mtu[0], sizeof(mtu), TD.Device_ID); + result = bvlc6_bbmd_disabled_handler(&TD.BIP6_Addr, &TD.BACnet_Address, + &mtu[0], mtu_len); + assert(result == 0); + assert(bvlc6_get_function_code() == + BVLC6_VIRTUAL_ADDRESS_RESOLUTION); + assert(VMAC_Find_By_Key(TD.Device_ID) != NULL); + test_cleanup(); } -static void test_BBMD_Result(Test *pTest) +static void test_BBMD_Result(void) { int result = 0; uint32_t vmac_src = 0x1234; @@ -275,38 +295,19 @@ static void test_BBMD_Result(Test *pTest) bvlc6_encode_result(&mtu[0], sizeof(mtu), vmac_src, result_code[i]); result = bvlc6_bbmd_disabled_handler(&addr, &src, &mtu[0], mtu_len); /* validate that the result is handled (0) */ - ct_test(pTest, result == 0); + assert(result == 0); test_result_code = bvlc6_get_last_result(); - ct_test(pTest, test_result_code == result_code[i]); + assert(test_result_code == result_code[i]); test_function_code = bvlc6_get_function_code(); - ct_test(pTest, test_function_code == BVLC6_RESULT); + assert(test_function_code == BVLC6_RESULT); } } -static void test_BBMD6(Test *pTest) -{ - bool rc; - - /* individual tests */ - rc = ct_addTestFunction(pTest, test_BBMD_Result); - assert(rc); - rc = ct_addTestFunction(pTest, test_Execute_Virtual_Address_Resolution); - assert(rc); - rc = ct_addTestFunction(pTest, test_Initiate_Original_Broadcast_NPDU); - assert(rc); -} - int main(void) { - Test *pTest; - - pTest = ct_create("BACnet Broadcast Management Device IP/v6", NULL); - test_BBMD6(pTest); - /* configure output */ - ct_setStream(pTest, stdout); - ct_run(pTest); - (void)ct_report(pTest); - ct_destroy(pTest); + test_BBMD_Result(); + test_Execute_Virtual_Address_Resolution(); + test_Initiate_Original_Broadcast_NPDU(); return 0; }