diff --git a/.ci_scripts/full-test/run_cppcheck.sh b/.ci_scripts/full-test/run_cppcheck.sh
index 7ee9ee4e1d111e53eee6d91c038178e9cc89c1d3..fde11aadc5a26417254c6167b3a2ea4542421cb2 100755
--- a/.ci_scripts/full-test/run_cppcheck.sh
+++ b/.ci_scripts/full-test/run_cppcheck.sh
@@ -1,7 +1,8 @@
 EXITCODE=0
+PARSERS_DIR="$GITHUB_WORKSPACE/src/parsers"
 
 # Pattern matching on all source files
-for file in $(find $GITHUB_WORKSPACE/include $GITHUB_WORKSPACE/src $GITHUB_WORKSPACE/devices $GITHUB_WORKSPACE/test -name *.h -o -name *.c)
+for file in $(find "$GITHUB_WORKSPACE"/include "$GITHUB_WORKSPACE"/src "$GITHUB_WORKSPACE"/devices "$GITHUB_WORKSPACE"/test "$PARSERS_DIR"/include "$PARSERS_DIR"/src "$PARSERS_DIR"/test -name *.h -o -name *.c)
 do
     if [[ "$file" != *"/hashmap.c" ]]
     then
diff --git a/.ci_scripts/full-test/run_tests.sh b/.ci_scripts/full-test/run_tests.sh
index 044ad75f4589541b2a99a4c6f16456ddb837026e..efd030301eafcf21142824897978c67512622551 100755
--- a/.ci_scripts/full-test/run_tests.sh
+++ b/.ci_scripts/full-test/run_tests.sh
@@ -1,8 +1,9 @@
 EXITCODE=0
+PARSERS_DIR="$GITHUB_WORKSPACE/src/parsers"
 VALGRIND_SUPP="$GITHUB_WORKSPACE/.ci_scripts/full-test/valgrind.supp"
 
 PREFIX=""
-for file in $GITHUB_WORKSPACE/bin/test/*
+for file in "$GITHUB_WORKSPACE"/bin/test/* "$PARSERS_DIR"/bin/test/*
 do
     if [[ "$file" == *"rule_utils-test" ]]
     then
diff --git a/CMakeLists.txt b/CMakeLists.txt
index e806ffb84fc4b9f9565f60ea5b297635bcd45bc1..58e261ff80c80677a49ac338977a9779f5981832 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -15,6 +15,7 @@ ENDIF()
 link_directories($ENV{LD_LIBRARY_PATH})
 set(CMAKE_INSTALL_PREFIX ${PROJECT_SOURCE_DIR})
 set(INCLUDE_DIR ${PROJECT_SOURCE_DIR}/include)
+set(INCLUDE_PARSERS_DIR ${PROJECT_SOURCE_DIR}/src/parsers/include)
 set(BIN_DIR ${PROJECT_SOURCE_DIR}/bin)
 set(LIB_DIR ${PROJECT_SOURCE_DIR}/lib)
 set(EXECUTABLE_OUTPUT_PATH ${BIN_DIR})
@@ -39,4 +40,4 @@ add_subdirectory(src)
 IF( NOT OPENWRT_CROSSCOMPILING )
     add_subdirectory(test)
 ENDIF()
-add_subdirectory(devices)
+#add_subdirectory(devices)
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index b709a9596d296bf58019e84c263a63e1b38f3a8f..2f006b86cced382323c4adfec2cdfca878246025 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -1,49 +1,27 @@
 # Minimum required CMake version
 cmake_minimum_required(VERSION 3.20)
 
-# Build libraries
+## Build instructions
 
-# hashmap
-add_library(hashmap STATIC ${HASHMAP_DIR}/hashmap.h ${HASHMAP_DIR}/hashmap.c)
-target_include_directories(hashmap PRIVATE ${HASHMAP_DIR})
-install(TARGETS hashmap DESTINATION ${LIB_DIR})
-
-# SHA256
-add_library(sha256 STATIC ${INCLUDE_DIR}/sha256.h sha256.c)
-target_include_directories(sha256 PRIVATE ${INCLUDE_DIR})
-install(TARGETS sha256 DESTINATION ${LIB_DIR})
-
-# packet_utils
-add_library(packet_utils STATIC ${INCLUDE_DIR}/packet_utils.h packet_utils.c)
-target_link_libraries(packet_utils sha256)
-target_include_directories(packet_utils PRIVATE ${INCLUDE_DIR})
-install(TARGETS packet_utils DESTINATION ${LIB_DIR})
-
-# dns_map
-add_library(dns_map STATIC ${INCLUDE_DIR}/dns_map.h dns_map.c)
-target_link_libraries(dns_map hashmap)
-target_include_directories(dns_map PRIVATE ${INCLUDE_DIR})
-install(TARGETS dns_map DESTINATION ${LIB_DIR})
+# Protocol parsers libs
+add_subdirectory(parsers)
 
-# rule_utils
+# rule_utils lib
 add_library(rule_utils STATIC ${INCLUDE_DIR}/rule_utils.h rule_utils.c)
 target_link_libraries(rule_utils nftables nftnl nfnetlink mnl jansson)
 target_include_directories(rule_utils PRIVATE ${INCLUDE_DIR})
 install(TARGETS rule_utils DESTINATION ${LIB_DIR})
 
-# nfqueue
+# nfqueue lib
 add_library(nfqueue STATIC ${INCLUDE_DIR}/nfqueue.h nfqueue.c)
 target_link_libraries(nfqueue netfilter_queue)
 target_link_libraries(nfqueue packet_utils)
-target_include_directories(nfqueue PRIVATE ${INCLUDE_DIR})
+target_include_directories(nfqueue PRIVATE ${INCLUDE_DIR} ${INCLUDE_PARSERS_DIR})
 install(TARGETS nfqueue DESTINATION ${LIB_DIR})
 
 # nflog executable
 add_executable(nflog nflog.c)
 target_link_libraries(nflog nfnetlink mnl netfilter_log pthread)
 target_link_libraries(nflog packet_utils)
-target_include_directories(nflog PRIVATE ${INCLUDE_DIR})
+target_include_directories(nflog PRIVATE ${INCLUDE_DIR} ${INCLUDE_PARSERS_DIR})
 install(TARGETS nflog DESTINATION ${BIN_DIR})
-
-# Build parsers
-add_subdirectory(parsers)
diff --git a/src/parsers b/src/parsers
index 3e063aee14cbb8dd4317872a70cd865f3732f737..82189ca816108a170ab1641f24d272e108b51e3d 160000
--- a/src/parsers
+++ b/src/parsers
@@ -1 +1 @@
-Subproject commit 3e063aee14cbb8dd4317872a70cd865f3732f737
+Subproject commit 82189ca816108a170ab1641f24d272e108b51e3d
diff --git a/src/translator/protocols b/src/translator/protocols
index c8a7af9717f4e5696db65eecf02f999e723e1c25..d1b4408fbb16d88b7ddfbd48d336f56a2b403cc7 160000
--- a/src/translator/protocols
+++ b/src/translator/protocols
@@ -1 +1 @@
-Subproject commit c8a7af9717f4e5696db65eecf02f999e723e1c25
+Subproject commit d1b4408fbb16d88b7ddfbd48d336f56a2b403cc7
diff --git a/src/translator/templates/CMakeLists.txt.j2 b/src/translator/templates/CMakeLists.txt.j2
index d39af2a7b8e7502b257e460efc59415027f4da0c..b29d1b4d718b3e51ad058d8a091b7e38e5048ad6 100644
--- a/src/translator/templates/CMakeLists.txt.j2
+++ b/src/translator/templates/CMakeLists.txt.j2
@@ -11,5 +11,5 @@ target_link_libraries({{device}} jansson mnl nfnetlink nftnl nftables netfilter_
 ENDIF()
 target_link_libraries({{device}} nfqueue packet_utils rule_utils)
 target_link_libraries({{device}} ${PARSERS})
-target_include_directories({{device}} PRIVATE ${INCLUDE_DIR})
+target_include_directories({{device}} PRIVATE ${INCLUDE_DIR} ${INCLUDE_PARSERS_DIR})
 install(TARGETS {{device}} DESTINATION ${EXECUTABLE_OUTPUT_PATH})
diff --git a/src/translator/templates/header.c.j2 b/src/translator/templates/header.c.j2
index 299a66ba506188ce239bd27ff2f5960ffef5b2cc..a4afe5f00ea7298bc89a4152e726a6e0c6ed93cb 100644
--- a/src/translator/templates/header.c.j2
+++ b/src/translator/templates/header.c.j2
@@ -19,12 +19,12 @@
 #include "packet_utils.h"
 #include "rule_utils.h"
 // Parsers
-#include "parsers/header.h"
+#include "header.h"
 {% for parser in custom_parsers %}
 {% if "dns" in parser %}
-#include "parsers/dns.h"
+#include "dns.h"
 {% else %}
-#include "parsers/{{parser}}.h"
+#include "{{parser}}.h"
 {% endif %}
 {% endfor %}
 
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 1519dfe5ab35dcf4e4d0195e6fd54085a7a3ac1d..7d83dfd9ac0abd23bafabbe6565d7fabf7a510ea 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -5,21 +5,7 @@ cmake_minimum_required(VERSION 3.20)
 set(TEST_BIN_DIR ${BIN_DIR}/test)
 set(EXECUTABLE_OUTPUT_PATH ${TEST_BIN_DIR})
 
-# Packet utils test
-add_executable(packet_utils-test packet_utils.c)
-target_include_directories(packet_utils-test PRIVATE ${INCLUDE_DIR})
-target_link_libraries(packet_utils-test cunit)
-target_link_libraries(packet_utils-test packet_utils)
-install(TARGETS packet_utils-test DESTINATION ${TEST_BIN_DIR})
-
-# Domain - IP mapping test
-add_executable(dns_map-test dns_map.c)
-target_include_directories(dns_map-test PRIVATE ${INCLUDE_DIR})
-target_link_libraries(dns_map-test cunit)
-target_link_libraries(dns_map-test hashmap)
-target_link_libraries(dns_map-test packet_utils)
-target_link_libraries(dns_map-test dns_map)
-install(TARGETS dns_map-test DESTINATION ${TEST_BIN_DIR})
+## Build unit tests
 
 # Rule utilitairies test
 add_executable(rule_utils-test rule_utils.c)
@@ -27,6 +13,3 @@ target_include_directories(rule_utils-test PRIVATE ${INCLUDE_DIR})
 target_link_libraries(rule_utils-test cunit)
 target_link_libraries(rule_utils-test rule_utils)
 install(TARGETS rule_utils-test DESTINATION ${TEST_BIN_DIR})
-
-# Test subdirectories
-add_subdirectory(parsers)
diff --git a/test/dns_map.c b/test/dns_map.c
deleted file mode 100644
index 2c367738dde37899de4e1d803d915edb2f32e6f3..0000000000000000000000000000000000000000
--- a/test/dns_map.c
+++ /dev/null
@@ -1,244 +0,0 @@
-/**
- * @file test/dns_map.c
- * @brief Unit tests for the mapping structure from DNS domain names to IP addresses
- * @date 2022-09-06
- * 
- * @copyright Copyright (c) 2022
- * 
- */
-
-#include <string.h>
-// Custom libraries
-#include "hashmap.h"
-#include "packet_utils.h"
-#include "dns_map.h"
-// CUnit
-#include <CUnit/CUnit.h>
-#include <CUnit/Basic.h>
-
-/**
- * Test the creation of a DNS table.
- */
-void test_dns_map_create() {
-    printf("test_dns_map_create\n");
-    dns_map_t *table = dns_map_create();
-    CU_ASSERT_PTR_NOT_NULL(table);
-    CU_ASSERT_EQUAL(hashmap_count(table), 0);
-    dns_map_free(table);
-}
-
-/**
- * Test operations on an empty DNS table.
- */
-void test_dns_map_empty() {
-    printf("test_dns_map_empty\n");
-    dns_map_t *table = dns_map_create();
-    dns_entry_t* entry = dns_map_get(table, "www.google.com");
-    CU_ASSERT_PTR_NULL(entry);
-    entry = dns_map_pop(table, "www.google.com");
-    CU_ASSERT_PTR_NULL(entry);
-    dns_map_remove(table, "www.google.com");  // Does nothing, but should not crash
-    dns_map_free(table);
-}
-
-/**
- * Test adding and removing entries in a DNS table.
- */
-void test_dns_map_add_remove() {
-    printf("test_dns_map_add_remove\n");
-    dns_map_t *table = dns_map_create();
-
-    // Add IP addresses for www.google.com
-    ip_addr_t *google_ips = (ip_addr_t *) malloc(2 * sizeof(ip_addr_t));
-    *google_ips = (ip_addr_t) {.version = 4, .value.ipv4 = ipv4_str_to_net("192.168.1.1")};
-    *(google_ips + 1) = (ip_addr_t) {.version = 4, .value.ipv4 = ipv4_str_to_net("192.168.1.2")};
-    ip_list_t ip_list_google = { .ip_count = 2, .ip_addresses = google_ips };
-    dns_map_add(table, "www.google.com", ip_list_google);
-    CU_ASSERT_EQUAL(hashmap_count(table), 1);
-
-    // Add IP addresses for www.example.com
-    ip_addr_t *example_ips = (ip_addr_t *) malloc(2 * sizeof(ip_addr_t));
-    *example_ips = (ip_addr_t) {.version = 4, .value.ipv4 = ipv4_str_to_net("192.168.1.3")};
-    *(example_ips + 1) = (ip_addr_t) {.version = 4, .value.ipv4 = ipv4_str_to_net("192.168.1.4")};
-    ip_list_t ip_list_example = {.ip_count = 2, .ip_addresses = example_ips};
-    dns_map_add(table, "www.example.com", ip_list_example);
-    CU_ASSERT_EQUAL(hashmap_count(table), 2);
-
-    // Add a new IP address for www.google.com
-    ip_addr_t *google_ips_new = (ip_addr_t *) malloc(sizeof(ip_addr_t));
-    *google_ips_new = (ip_addr_t) {.version = 4, .value.ipv4 = ipv4_str_to_net("192.168.1.5")};
-    ip_list_t ip_list_google_new = { .ip_count = 1, .ip_addresses = google_ips_new };
-    dns_map_add(table, "www.google.com", ip_list_google_new);
-    CU_ASSERT_EQUAL(hashmap_count(table), 2);
-
-    // Remove all IP addresses
-    dns_map_remove(table, "www.google.com");
-    CU_ASSERT_EQUAL(hashmap_count(table), 1);
-    dns_map_remove(table, "www.example.com");
-    CU_ASSERT_EQUAL(hashmap_count(table), 0);
-    dns_map_free(table);
-}
-
-/**
- * Test retrieving entries from a DNS table.
- */
-void test_dns_map_get() {
-    printf("test_dns_map_get\n");
-    dns_map_t *table = dns_map_create();
-    
-    // Add IP addresses for www.google.com
-    ip_addr_t *google_ips = (ip_addr_t *)malloc(2 * sizeof(ip_addr_t));
-    *google_ips = (ip_addr_t){.version = 4, .value.ipv4 = ipv4_str_to_net("192.168.1.1")};
-    *(google_ips + 1) = (ip_addr_t){.version = 4, .value.ipv4 = ipv4_str_to_net("192.168.1.2")};
-    ip_list_t ip_list_google = {.ip_count = 2, .ip_addresses = google_ips};
-    dns_map_add(table, "www.google.com", ip_list_google);
-
-    // Verify getting IP addresses for www.google.com
-    dns_entry_t *actual = dns_map_get(table, "www.google.com");
-    CU_ASSERT_PTR_NOT_NULL(actual);
-    CU_ASSERT_EQUAL(actual->ip_list.ip_count, 2);
-    for (int i = 0; i < actual->ip_list.ip_count; i++) {
-        CU_ASSERT_TRUE(compare_ip(*(actual->ip_list.ip_addresses + i), *(google_ips + i)));
-    }
-
-    // Add IP addresses for www.example.com
-    ip_addr_t *example_ips = (ip_addr_t *)malloc(2 * sizeof(ip_addr_t));
-    *example_ips = (ip_addr_t){.version = 4, .value.ipv4 = ipv4_str_to_net("192.168.1.3")};
-    *(example_ips + 1) = (ip_addr_t){.version = 4, .value.ipv4 = ipv4_str_to_net("192.168.1.4")};
-    ip_list_t ip_list_example = {.ip_count = 2, .ip_addresses = example_ips};
-    dns_map_add(table, "www.example.com", ip_list_example);
-
-    // Verify getting IP addresses for www.example.com
-    actual = dns_map_get(table, "www.example.com");
-    CU_ASSERT_PTR_NOT_NULL(actual);
-    CU_ASSERT_EQUAL(actual->ip_list.ip_count, 2);
-    for (int i = 0; i < actual->ip_list.ip_count; i++) {
-        CU_ASSERT_TRUE(compare_ip(*(actual->ip_list.ip_addresses + i), *(example_ips + i)));
-    }
-
-    // Add a new IP address for www.google.com
-    ip_addr_t *google_ips_new = (ip_addr_t *)malloc(sizeof(ip_addr_t));
-    *google_ips_new = (ip_addr_t){.version = 4, .value.ipv4 = ipv4_str_to_net("192.168.1.5")};
-    ip_list_t ip_list_google_new = {.ip_count = 1, .ip_addresses = google_ips_new};
-    dns_map_add(table, "www.google.com", ip_list_google_new);
-
-    // Verify getting IP addresses for www.google.com
-    actual = dns_map_get(table, "www.google.com");
-    CU_ASSERT_PTR_NOT_NULL(actual);
-    CU_ASSERT_EQUAL(actual->ip_list.ip_count, 3);
-    ip_addr_t *google_all_ips = (ip_addr_t *)malloc(3 * sizeof(ip_addr_t));
-    *google_all_ips = (ip_addr_t){.version = 4, .value.ipv4 = ipv4_str_to_net("192.168.1.1")};
-    *(google_all_ips + 1) = (ip_addr_t){.version = 4, .value.ipv4 = ipv4_str_to_net("192.168.1.2")};
-    *(google_all_ips + 2) = (ip_addr_t){.version = 4, .value.ipv4 = ipv4_str_to_net("192.168.1.5")};
-    for (int i = 0; i < actual->ip_list.ip_count; i++)
-    {
-        CU_ASSERT_TRUE(compare_ip(*(actual->ip_list.ip_addresses + i), *(google_all_ips + i)));
-    }
-
-    free(google_all_ips);
-    dns_map_free(table);
-}
-
-/**
- * Test popping entries from a DNS table.
- */
-void test_dns_map_pop() {
-    printf("test_dns_map_pop\n");
-    dns_map_t *table = dns_map_create();
-
-    // Add IP addresses for www.google.com
-    ip_addr_t *google_ips = (ip_addr_t *)malloc(2 * sizeof(ip_addr_t));
-    *google_ips = (ip_addr_t){.version = 4, .value.ipv4 = ipv4_str_to_net("192.168.1.1")};
-    *(google_ips + 1) = (ip_addr_t){.version = 4, .value.ipv4 = ipv4_str_to_net("192.168.1.2")};
-    ip_list_t ip_list_google = {.ip_count = 2, .ip_addresses = google_ips};
-    dns_map_add(table, "www.google.com", ip_list_google);
-
-    // Add IP addresses for www.example.com
-    ip_addr_t *example_ips = (ip_addr_t *)malloc(2 * sizeof(ip_addr_t));
-    *example_ips = (ip_addr_t){.version = 4, .value.ipv4 = ipv4_str_to_net("192.168.1.3")};
-    *(example_ips + 1) = (ip_addr_t){.version = 4, .value.ipv4 = ipv4_str_to_net("192.168.1.4")};
-    ip_list_t ip_list_example = {.ip_count = 2, .ip_addresses = example_ips};
-    dns_map_add(table, "www.example.com", ip_list_example);
-
-    // Verify popping IP addresses for www.google.com
-    dns_entry_t *actual = dns_map_pop(table, "www.google.com");
-    CU_ASSERT_PTR_NOT_NULL(actual);
-    CU_ASSERT_EQUAL(actual->ip_list.ip_count, 2);
-    for (int i = 0; i < actual->ip_list.ip_count; i++)
-    {
-        CU_ASSERT_TRUE(compare_ip(*(actual->ip_list.ip_addresses + i), *(google_ips + i)));
-    }
-    free(actual->ip_list.ip_addresses);
-    CU_ASSERT_EQUAL(hashmap_count(table), 1);
-    actual = dns_map_pop(table, "www.google.com");
-    CU_ASSERT_PTR_NULL(actual);
-
-    // Verify popping IP addresses for www.example.com
-    actual = dns_map_pop(table, "www.example.com");
-    CU_ASSERT_PTR_NOT_NULL(actual);
-    CU_ASSERT_EQUAL(actual->ip_list.ip_count, 2);
-    for (int i = 0; i < actual->ip_list.ip_count; i++)
-    {
-        CU_ASSERT_TRUE(compare_ip(*(actual->ip_list.ip_addresses + i), *(example_ips + i)));
-    }
-    free(actual->ip_list.ip_addresses);
-    CU_ASSERT_EQUAL(hashmap_count(table), 0);
-    actual = dns_map_pop(table, "www.example.com");
-    CU_ASSERT_PTR_NULL(actual);
-    
-    dns_map_free(table);
-}
-
-/**
- * Test printing entries from a DNS table.
- */
-void test_dns_entry_print() {
-    printf("test_dns_entry_print\n");
-    dns_map_t *table = dns_map_create();
-
-    // Add IP addresses for www.google.com
-    ip_addr_t *google_ips = (ip_addr_t *)malloc(2 * sizeof(ip_addr_t));
-    *google_ips = (ip_addr_t){.version = 4, .value.ipv4 = ipv4_str_to_net("192.168.1.1")};
-    *(google_ips + 1) = (ip_addr_t){.version = 4, .value.ipv4 = ipv4_str_to_net("192.168.1.2")};
-    ip_list_t ip_list_google = {.ip_count = 2, .ip_addresses = google_ips};
-    dns_map_add(table, "www.google.com", ip_list_google);
-
-    // Add IP addresses for www.example.com
-    ip_addr_t *example_ips = (ip_addr_t *)malloc(2 * sizeof(ip_addr_t));
-    *example_ips = (ip_addr_t){.version = 4, .value.ipv4 = ipv4_str_to_net("192.168.1.3")};
-    *(example_ips + 1) = (ip_addr_t){.version = 4, .value.ipv4 = ipv4_str_to_net("192.168.1.4")};
-    ip_list_t ip_list_example = {.ip_count = 2, .ip_addresses = example_ips};
-    dns_map_add(table, "www.example.com", ip_list_example);
-
-    // Print entries
-    dns_entry_t *dns_entry = dns_map_get(table, "www.google.com");
-    dns_entry_print(dns_entry);
-    dns_entry = dns_map_get(table, "www.example.com");
-    dns_entry_print(dns_entry);
-
-    // Destroy DNS table
-    dns_map_free(table);
-}
-
-
-/**
- * Test suite entry point.
- */
-int main(int argc, char const *argv[])
-{
-    // Initialize the CUnit test registry and suite
-    printf("Test suite: dns_map\n");
-    if (CU_initialize_registry() != CUE_SUCCESS)
-        return CU_get_error();
-    CU_pSuite suite = CU_add_suite("dns_map", NULL, NULL);
-    // Add and run tests
-    CU_add_test(suite, "dns_map_create", test_dns_map_create);
-    CU_add_test(suite, "dns_map_empty", test_dns_map_empty);
-    CU_add_test(suite, "dns_map_add_remove", test_dns_map_add_remove);
-    CU_add_test(suite, "dns_map_get", test_dns_map_get);
-    CU_add_test(suite, "dns_map_pop", test_dns_map_pop);
-    CU_add_test(suite, "dns_entry_print", test_dns_entry_print);
-    CU_basic_run_tests();
-    CU_cleanup_registry();
-    return 0;
-}
diff --git a/test/packet_utils.c b/test/packet_utils.c
deleted file mode 100644
index 673dbb55254ad4c959d8457f9745394522202bce..0000000000000000000000000000000000000000
--- a/test/packet_utils.c
+++ /dev/null
@@ -1,263 +0,0 @@
-/**
- * @file test/packet_utils.c
- * @brief Unit tests for the packet utilities
- * @date 2022-09-13
- * 
- * @copyright Copyright (c) 2022
- * 
- */
-
-// Standard libraries
-#include <stdlib.h>
-#include <string.h>
-// Custom libraries
-#include "packet_utils.h"
-// CUnit
-#include <CUnit/CUnit.h>
-#include <CUnit/Basic.h>
-
-
-/**
- * @brief Unit test for the function hexstr_to_payload.
- */
-void test_hexstr_to_payload() {
-    char *hexstr = "48656c6c6f20576f726c6421";
-    uint8_t expected[] = {0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x57, 0x6f, 0x72, 0x6c, 0x64, 0x21};
-    uint8_t *actual;
-    size_t length = hexstr_to_payload(hexstr, &actual);
-    CU_ASSERT_EQUAL(length, strlen(hexstr) / 2);  // Verify payload length
-    // Verify payload byte by byte
-    for (uint8_t i = 0; i < length; i++) {
-        CU_ASSERT_EQUAL(*(actual + i), expected[i]);
-    }
-    free(actual);
-}
-
-/**
- * @brief Unit test for the function mac_hex_to_str.
- */
-void test_mac_hex_to_str()
-{
-    uint8_t mac_hex[] = {0x00, 0x0c, 0x29, 0x6b, 0x9f, 0x5a};
-    char *expected = "00:0c:29:6b:9f:5a";
-    char *actual = mac_hex_to_str(mac_hex);
-    CU_ASSERT_STRING_EQUAL(actual, expected);
-    free(actual);
-}
-
-/**
- * @brief Unit test for the function mac_str_to_hex.
- */
-void test_mac_str_to_hex()
-{
-    char *mac_str = "00:0c:29:6b:9f:5a";
-    uint8_t *expected = (uint8_t *) malloc(sizeof(uint8_t) * 6);
-    memcpy(expected, "\x00\x0c\x29\x6b\x9f\x5a", 6);
-    uint8_t *actual = mac_str_to_hex(mac_str);
-    for (uint8_t i = 0; i < 6; i++)
-    {
-        CU_ASSERT_EQUAL(*(actual + i), *(expected + i))
-    }
-    free(actual);
-    free(expected);
-}
-
-/**
- * @brief Unit test for the function ipv4_net_to_str.
- */
-void test_ipv4_net_to_str() {
-    uint32_t ipv4_net = 0xa101a8c0;
-    char *expected = "192.168.1.161";
-    char *actual = ipv4_net_to_str(ipv4_net);
-    CU_ASSERT_STRING_EQUAL(actual, expected);
-}
-
-/**
- * @brief Unit test for the function ipv4_str_to_net.
- */
-void test_ipv4_str_to_net() {
-    char *ipv4_str = "192.168.1.161";
-    uint32_t expected = 0xa101a8c0;
-    uint32_t actual = ipv4_str_to_net(ipv4_str);
-    CU_ASSERT_EQUAL(actual, expected);
-}
-
-/**
- * @brief Unit test for the function ipv4_hex_to_str.
- */
-void test_ipv4_hex_to_str() {
-    char *ipv4_hex = "\xc0\xa8\x01\xa1";
-    char *expected = "192.168.1.161";
-    char *actual = ipv4_hex_to_str(ipv4_hex);
-    CU_ASSERT_STRING_EQUAL(actual, expected);
-    free(actual);
-}
-
-/**
- * @brief Unit test for the function ipv4_str_to_hex.
- */
-void test_ipv4_str_to_hex() {
-    char *ipv4_str = "192.168.1.161";
-    char *expected = "\xc0\xa8\x01\xa1";
-    char *actual = ipv4_str_to_hex(ipv4_str);
-    for (uint8_t i = 0; i < 4; i++) {
-        CU_ASSERT_EQUAL(*(actual + i), *(expected + i))
-    }
-    free(actual);
-}
-
-/**
- * @brief Unit test for the function ipv6_net_to_str.
- */
-void test_ipv6_net_to_str() {
-    // Full textual representation
-    uint8_t ipv6_1[] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x11};
-    char *actual = ipv6_net_to_str(ipv6_1);
-    char *expected = "1122:3344:5566:7788:99aa:bbcc:ddee:ff11";
-    CU_ASSERT_STRING_EQUAL(actual, expected);
-    free(actual);
-
-    // Compressed textual representation
-    uint8_t ipv6_2[] = {0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01};
-    actual = ipv6_net_to_str(ipv6_2);
-    expected = "1::1";
-    CU_ASSERT_STRING_EQUAL(actual, expected);
-    free(actual);
-}
-
-/**
- * @brief Unit test for the function ipv6_str_to_net.
- * 
- */
-void test_ipv6_str_to_net() {
-    // Full textual representation
-    char *ipv6_1 = "1122:3344:5566:7788:99aa:bbcc:ddee:ff11";
-    uint8_t *expected = (uint8_t *) malloc(IPV6_ADDR_LENGTH * sizeof(uint8_t));
-    memcpy(expected, "\x11\x22\x33\x44\x55\x66\x77\x88\x99\xaa\xbb\xcc\xdd\xee\xff\x11", IPV6_ADDR_LENGTH);
-    uint8_t *actual = ipv6_str_to_net(ipv6_1);
-    for (uint8_t i = 0; i < IPV6_ADDR_LENGTH; i++) {
-        CU_ASSERT_EQUAL(*(actual + i), *(expected + i))
-    }
-    free(actual);
-
-    // Compressed textual representation
-    char *ipv6_2 = "1::1";
-    memcpy(expected, "\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01", IPV6_ADDR_LENGTH);
-    actual = ipv6_str_to_net(ipv6_2);
-    for (uint8_t i = 0; i < IPV6_ADDR_LENGTH; i++) {
-        CU_ASSERT_EQUAL(*(actual + i), *(expected + i))
-    }
-    free(actual);
-    free(expected);
-}
-
-/**
- * @brief Unit test for the function ip_net_to_str.
- */
-void test_ip_net_to_str() {
-    // IPv4
-    ip_addr_t ipv4 = {.version = 4, .value.ipv4 = 0x0101a8c0};
-    char *actual = ip_net_to_str(ipv4);
-    char *expected = "192.168.1.1";
-    CU_ASSERT_STRING_EQUAL(actual, expected);
-
-    // IPv6
-    ip_addr_t ipv6 = {.version = 6, .value.ipv6 = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x11}};
-    actual = ip_net_to_str(ipv6);
-    expected = "1122:3344:5566:7788:99aa:bbcc:ddee:ff11";
-    CU_ASSERT_STRING_EQUAL(actual, expected);
-    free(actual);
-}
-
-/**
- * @brief Unit test for the function ip_str_to_net.
- *
- */
-void test_ip_str_to_net()
-{
-    // IPv4
-    char *ipv4_str = "192.168.1.161";
-    ip_addr_t actual = ip_str_to_net(ipv4_str, 4);
-    ip_addr_t expected = (ip_addr_t) {.version = 4, .value.ipv4 = 0xa101a8c0};
-    CU_ASSERT_EQUAL(actual.version, expected.version);
-    CU_ASSERT_EQUAL(actual.value.ipv4, expected.value.ipv4);
-
-    // IPv6
-    char *ipv6_str = "1122:3344:5566:7788:99aa:bbcc:ddee:ff11";
-    actual = ip_str_to_net(ipv6_str, 6);
-    expected.version = 6;
-    memcpy(expected.value.ipv6, "\x11\x22\x33\x44\x55\x66\x77\x88\x99\xaa\xbb\xcc\xdd\xee\xff\x11", IPV6_ADDR_LENGTH);
-    CU_ASSERT_EQUAL(actual.version, expected.version);
-    for (uint8_t i = 0; i < IPV6_ADDR_LENGTH; i++) {
-        CU_ASSERT_EQUAL(actual.value.ipv6[i], expected.value.ipv6[i]);
-    }
-}
-
-/**
- * @brief Unit test for the function compare_ipv6.
- */
-void test_compare_ipv6() {
-    uint8_t ipv6_1[] = {0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01};
-    uint8_t ipv6_2[] = {0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01};
-    uint8_t ipv6_3[] = {0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02};
-    CU_ASSERT_TRUE(compare_ipv6(ipv6_1, ipv6_2));
-    CU_ASSERT_TRUE(compare_ipv6(ipv6_2, ipv6_1));
-    CU_ASSERT_FALSE(compare_ipv6(ipv6_1, ipv6_3));
-    CU_ASSERT_FALSE(compare_ipv6(ipv6_3, ipv6_1));
-}
-
-/**
- * @brief Unit test for the function compare_ip.
- */
-void test_compare_ip() {
-    // Compare IPv4
-    ip_addr_t ipv4_1 = { .version = 4, .value.ipv4 = 0xa101a8c0 };
-    ip_addr_t ipv4_2 = {.version = 4, .value.ipv4 = 0xa101a8c0};
-    ip_addr_t ipv4_3 = {.version = 4, .value.ipv4 = 0xa201a8c0};
-    CU_ASSERT_TRUE(compare_ip(ipv4_1, ipv4_2));
-    CU_ASSERT_TRUE(compare_ip(ipv4_2, ipv4_1));
-    CU_ASSERT_FALSE(compare_ip(ipv4_1, ipv4_3));
-    CU_ASSERT_FALSE(compare_ip(ipv4_3, ipv4_1));
-
-    // Compare IPv6
-    ip_addr_t ipv6_1 = {.version = 6, .value.ipv6 = {0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}};
-    ip_addr_t ipv6_2 = {.version = 6, .value.ipv6 = {0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}};
-    ip_addr_t ipv6_3 = {.version = 6, .value.ipv6 = {0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02}};
-    CU_ASSERT_TRUE(compare_ip(ipv6_1, ipv6_2));
-    CU_ASSERT_TRUE(compare_ip(ipv6_2, ipv6_1));
-    CU_ASSERT_FALSE(compare_ip(ipv6_1, ipv6_3));
-    CU_ASSERT_FALSE(compare_ip(ipv6_3, ipv6_1));
-
-    // Compare IPv4 and IPv6
-    CU_ASSERT_FALSE(compare_ip(ipv4_1, ipv6_1));
-    CU_ASSERT_FALSE(compare_ip(ipv6_1, ipv4_1));
-}
-
-/**
- * Test suite entry point.
- */
-int main(int argc, char const *argv[])
-{
-    // Initialize the CUnit test registry and suite
-    printf("Test suite: packet_utils\n");
-    if (CU_initialize_registry() != CUE_SUCCESS)
-        return CU_get_error();
-    CU_pSuite suite = CU_add_suite("packet_utils", NULL, NULL);
-    // Add and run tests
-    CU_add_test(suite, "hexstr_to_payload", test_hexstr_to_payload);
-    CU_add_test(suite, "mac_hex_to_str", test_mac_hex_to_str);
-    CU_add_test(suite, "mac_str_to_hex", test_mac_str_to_hex);
-    CU_add_test(suite, "ipv4_net_to_str", test_ipv4_net_to_str);
-    CU_add_test(suite, "ipv4_str_to_net", test_ipv4_str_to_net);
-    CU_add_test(suite, "ipv4_hex_to_str", test_ipv4_hex_to_str);
-    CU_add_test(suite, "ipv4_str_to_hex", test_ipv4_str_to_hex);
-    CU_add_test(suite, "ipv6_net_to_str", test_ipv6_net_to_str);
-    CU_add_test(suite, "ipv6_str_to_net", test_ipv6_str_to_net);
-    CU_add_test(suite, "ip_net_to_str", test_ip_net_to_str);
-    CU_add_test(suite, "ip_str_to_net", test_ip_str_to_net);
-    CU_add_test(suite, "compare_ipv6", test_compare_ipv6);
-    CU_add_test(suite, "compare_ip", test_compare_ip);
-    CU_basic_run_tests();
-    CU_cleanup_registry();
-    return 0;
-}
diff --git a/test/parsers/CMakeLists.txt b/test/parsers/CMakeLists.txt
deleted file mode 100644
index 1f80bed51662087171583bf2f6190f9d7edbfb31..0000000000000000000000000000000000000000
--- a/test/parsers/CMakeLists.txt
+++ /dev/null
@@ -1,58 +0,0 @@
-# Minimum required CMake version
-cmake_minimum_required(VERSION 3.20)
-
-# Header
-add_executable(header-test header.c)
-target_include_directories(header-test PRIVATE ${INCLUDE_DIR})
-target_link_libraries(header-test cunit)
-target_link_libraries(header-test packet_utils)
-target_link_libraries(header-test header)
-install(TARGETS header-test DESTINATION ${TEST_BIN_DIR})
-
-# DNS
-add_executable(dns-test dns.c)
-target_include_directories(dns-test PRIVATE ${INCLUDE_DIR})
-target_link_libraries(dns-test cunit)
-target_link_libraries(dns-test packet_utils)
-target_link_libraries(dns-test header dns)
-install(TARGETS dns-test DESTINATION ${TEST_BIN_DIR})
-
-# DHCP
-add_executable(dhcp-test dhcp.c)
-target_include_directories(dhcp-test PRIVATE ${INCLUDE_DIR})
-target_link_libraries(dhcp-test cunit)
-target_link_libraries(dhcp-test packet_utils)
-target_link_libraries(dhcp-test header dhcp)
-install(TARGETS dhcp-test DESTINATION ${TEST_BIN_DIR})
-
-# HTTP
-add_executable(http-test http.c)
-target_include_directories(http-test PRIVATE ${INCLUDE_DIR})
-target_link_libraries(http-test cunit)
-target_link_libraries(http-test packet_utils)
-target_link_libraries(http-test header http)
-install(TARGETS http-test DESTINATION ${TEST_BIN_DIR})
-
-# IGMP
-add_executable(igmp-test igmp.c)
-target_include_directories(igmp-test PRIVATE ${INCLUDE_DIR})
-target_link_libraries(igmp-test cunit)
-target_link_libraries(igmp-test packet_utils)
-target_link_libraries(igmp-test header igmp)
-install(TARGETS igmp-test DESTINATION ${TEST_BIN_DIR})
-
-# SSDP
-add_executable(ssdp-test ssdp.c)
-target_include_directories(ssdp-test PRIVATE ${INCLUDE_DIR})
-target_link_libraries(ssdp-test cunit)
-target_link_libraries(ssdp-test packet_utils)
-target_link_libraries(ssdp-test header ssdp)
-install(TARGETS ssdp-test DESTINATION ${TEST_BIN_DIR})
-
-# CoAP
-add_executable(coap-test coap.c)
-target_include_directories(coap-test PRIVATE ${INCLUDE_DIR})
-target_link_libraries(coap-test cunit)
-target_link_libraries(coap-test packet_utils)
-target_link_libraries(coap-test header coap)
-install(TARGETS coap-test DESTINATION ${TEST_BIN_DIR})
diff --git a/test/parsers/coap.c b/test/parsers/coap.c
deleted file mode 100644
index f961870f9954ca7fa016df515d59e5c0ecd46165..0000000000000000000000000000000000000000
--- a/test/parsers/coap.c
+++ /dev/null
@@ -1,71 +0,0 @@
-/**
- * @file test/parsers/coap.c
- * @brief Unit tests for the CoAP parser
- * @date 2022-11-30
- * 
- * @copyright Copyright (c) 2022
- * 
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-// Custom libraries
-#include "packet_utils.h"
-#include "parsers/header.h"
-#include "parsers/coap.h"
-// CUnit
-#include <CUnit/CUnit.h>
-#include <CUnit/Basic.h>
-
-
-/**
- * @brief Unit test for the CoAP parser, using a Non-Confirmable GET message.
- */
-void test_coap_non_get() {
-
-    char *hexstring = "60017a1800451102fe80000000000000db22fbeca6b444feff0200000000000000000000000001588b5316330045c374580175f2d55892c87b38f0fbb36f6963037265734d1472743d782e636f6d2e73616d73756e672e70726f766973696f6e696e67696e666f213ce1fed6c0";
-
-    uint8_t *payload;
-    size_t length = hexstr_to_payload(hexstring, &payload);
-    CU_ASSERT_EQUAL(length, strlen(hexstring) / 2);  // Verify message length
-
-    // Actual message
-    size_t skipped = get_ipv6_header_length(payload);
-    uint16_t coap_length = get_udp_payload_length(payload + skipped);
-    skipped += get_udp_header_length(payload + skipped);
-    coap_message_t actual = coap_parse_message(payload + skipped, coap_length);
-    free(payload);
-    //coap_print_message(actual);
-
-    // Expected message
-    coap_message_t expected;
-    expected.type = COAP_NON;
-    expected.method = HTTP_GET;
-    expected.uri = "/oic/res?rt=x.com.samsung.provisioninginfo";
-
-    // Compare messages
-    CU_ASSERT_EQUAL(actual.type, expected.type);
-    CU_ASSERT_EQUAL(actual.method, expected.method);
-    CU_ASSERT_STRING_EQUAL(actual.uri, expected.uri);
-
-    coap_free_message(actual);
-
-}
-
-
-/**
- * Main function for the unit tests.
- */
-int main(int argc, char const *argv[])
-{
-    // Initialize registry and suite
-    if (CU_initialize_registry() != CUE_SUCCESS)
-        return CU_get_error();
-    CU_pSuite suite = CU_add_suite("coap", NULL, NULL);
-    // Run tests
-    CU_add_test(suite, "coap-non-get", test_coap_non_get);
-    CU_basic_run_tests();
-    CU_cleanup_registry();
-    return 0;
-}
diff --git a/test/parsers/dhcp.c b/test/parsers/dhcp.c
deleted file mode 100644
index 254b75890dd1dabb9b65ef4a09be13d0ab8bb961..0000000000000000000000000000000000000000
--- a/test/parsers/dhcp.c
+++ /dev/null
@@ -1,254 +0,0 @@
-/**
- * @file test/parsers/dhcp.c
- * @brief Unit tests for the DHCP parser
- * @date 2022-09-12
- * 
- * @copyright Copyright (c) 2022
- * 
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-// Custom libraries
-#include "packet_utils.h"
-#include "parsers/header.h"
-#include "parsers/dhcp.h"
-// CUnit
-#include <CUnit/CUnit.h>
-#include <CUnit/Basic.h>
-
-
-/**
- * @brief Compare the headers of two DHCP messages.
- * 
- * @param actual actual DHCP message
- * @param expected expected DHCP message
- */
-void compare_headers(dhcp_message_t actual, dhcp_message_t expected) {
-    CU_ASSERT_EQUAL(actual.op, expected.op);
-    CU_ASSERT_EQUAL(actual.htype, expected.htype);
-    CU_ASSERT_EQUAL(actual.hlen, expected.hlen);
-    CU_ASSERT_EQUAL(actual.hops, expected.hops);
-    CU_ASSERT_EQUAL(actual.xid, expected.xid);
-    CU_ASSERT_EQUAL(actual.secs, expected.secs);
-    CU_ASSERT_EQUAL(actual.flags, expected.flags);
-    CU_ASSERT_EQUAL(actual.ciaddr, expected.ciaddr);
-    CU_ASSERT_EQUAL(actual.yiaddr, expected.yiaddr);
-    CU_ASSERT_EQUAL(actual.siaddr, expected.siaddr);
-    CU_ASSERT_EQUAL(actual.giaddr, expected.giaddr);
-    for (uint8_t i = 0; i < MAX_HW_LEN; i++) {
-        CU_ASSERT_EQUAL(actual.chaddr[i], expected.chaddr[i]);
-    }
-}
-
-/**
- * @brief Compare two DHCP options lists.
- * 
- * @param actual actual DHCP options list
- * @param expected expected DHCP options list
- */
-void compare_options(dhcp_options_t actual, dhcp_options_t expected) {
-    for (uint8_t i = 0; i < expected.count; i++) {
-        CU_ASSERT_EQUAL((actual.options + i)->code, (expected.options + i)->code);
-        CU_ASSERT_EQUAL((actual.options + i)->length, (expected.options + i)->length);
-        for (uint8_t j = 0; j < (actual.options + i)->length; j++) {
-            CU_ASSERT_EQUAL(*(((actual.options + i)->value) + j), *(((expected.options + i)->value) + j));
-        }
-    }
-}
-
-/**
- * DHCP Unit test, with a DHCP Discover message.
- */
-void test_dhcp_discover() {
-    char *hexstring = "4500014c00000000401179a200000000ffffffff004400430138dc40010106006617ca540000000000000000000000000000000000000000788b2ab220ea00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000638253633501013d0701788b2ab220ea3902024037070103060c0f1c2a3c0c756468637020312e32382e310c16636875616e676d695f63616d6572615f697063303139ff";
-
-    uint8_t *payload;
-    size_t length = hexstr_to_payload(hexstring, &payload);
-    CU_ASSERT_EQUAL(length, strlen(hexstring) / 2);  // Verify message length
-
-    size_t skipped = get_headers_length(payload);
-    dhcp_message_t message = dhcp_parse_message(payload + skipped);
-    free(payload);
-    //dhcp_print_message(message);
-
-    // Test different sections of the DHCP message
-
-    // Header
-    dhcp_message_t expected;
-    expected.op = DHCP_BOOTREQUEST;
-    expected.htype = 1;
-    expected.hlen = 6;
-    expected.hops = 0;
-    expected.xid = 0x6617ca54;
-    expected.secs = 0;
-    expected.flags = 0x0000;
-    expected.ciaddr = ipv4_str_to_net("0.0.0.0");
-    expected.yiaddr = ipv4_str_to_net("0.0.0.0");
-    expected.siaddr = ipv4_str_to_net("0.0.0.0");
-    expected.giaddr = ipv4_str_to_net("0.0.0.0");
-    memcpy(expected.chaddr, "\x78\x8b\x2a\xb2\x20\xea\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", MAX_HW_LEN);
-    compare_headers(message, expected);
-
-    // Options
-    expected.options.count = 7;
-    expected.options.options = (dhcp_option_t *) malloc(sizeof(dhcp_option_t) * expected.options.count);
-    // Option 53: DHCP Message Type
-    expected.options.options->code = 53;
-    expected.options.options->length = 1;
-    expected.options.options->value = (uint8_t *) malloc(sizeof(uint8_t) * expected.options.options->length);
-    *(expected.options.options->value) = DHCP_DISCOVER;
-    CU_ASSERT_EQUAL(message.options.message_type, DHCP_DISCOVER);
-    // Option 61: Client Identifier
-    (expected.options.options + 1)->code = 61;
-    (expected.options.options + 1)->length = 7;
-    (expected.options.options + 1)->value = (uint8_t *) malloc(sizeof(uint8_t) * (expected.options.options + 1)->length);
-    memcpy((expected.options.options + 1)->value, "\x01\x78\x8b\x2a\xb2\x20\xea", (expected.options.options + 1)->length);
-    // Option 57: Maximum DHCP Message Size
-    (expected.options.options + 2)->code = 57;
-    (expected.options.options + 2)->length = 2;
-    (expected.options.options + 2)->value = (uint8_t *) malloc(sizeof(uint8_t) * (expected.options.options + 2)->length);
-    memcpy((expected.options.options + 2)->value, "\x02\x40", (expected.options.options + 2)->length);
-    // Option 55: Parameter Request List
-    (expected.options.options + 3)->code = 55;
-    (expected.options.options + 3)->length = 7;
-    (expected.options.options + 3)->value = (uint8_t *) malloc(sizeof(uint8_t) * (expected.options.options + 3)->length);
-    memcpy((expected.options.options + 3)->value, "\x01\x03\x06\x0c\x0f\x1c\x2a", (expected.options.options + 3)->length);
-    // Option 60: Vendor Class Identifier
-    (expected.options.options + 4)->code = 60;
-    (expected.options.options + 4)->length = 12;
-    (expected.options.options + 4)->value = (uint8_t *) malloc(sizeof(uint8_t) * (expected.options.options + 4)->length);
-    memcpy((expected.options.options + 4)->value, "\x75\x64\x68\x63\x70\x20\x31\x2e\x32\x38\x2e\x31", (expected.options.options + 4)->length);
-    // Option 12: Host Name
-    (expected.options.options + 5)->code = 12;
-    (expected.options.options + 5)->length = 22;
-    (expected.options.options + 5)->value = (uint8_t *) malloc(sizeof(uint8_t) * (expected.options.options + 5)->length);
-    memcpy((expected.options.options + 5)->value, "\x63\x68\x75\x61\x6e\x67\x6d\x69\x5f\x63\x61\x6d\x65\x72\x61\x5f\x69\x70\x63\x30\x31\x39", (expected.options.options + 5)->length);
-    // Option 255: End
-    (expected.options.options + 6)->code = 255;
-    (expected.options.options + 6)->length = 0;
-    (expected.options.options + 6)->value = NULL;
-    // Compare and free options
-    compare_options(message.options, expected.options);
-
-    // Free messages
-    dhcp_free_message(message);
-    dhcp_free_message(expected);
-}
-
-/**
- * DHCP Unit test, with a DHCP Offer message.
- */
-void test_dhcp_offer() {
-    char *hexstring = "45c0014820a000004011d452c0a80101c0a801a10043004401341617020106006617ca540000000000000000c0a801a1c0a8010100000000788b2ab220ea00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000638253633501023604c0a8010133040000a8c03a04000054603b04000093a80104ffffff001c04c0a801ff0304c0a801010604c0a801010f036c616eff000000";
-
-    uint8_t *payload;
-    size_t length = hexstr_to_payload(hexstring, &payload);
-    CU_ASSERT_EQUAL(length, strlen(hexstring) / 2);  // Verify message length
-
-    size_t skipped = get_headers_length(payload);
-    dhcp_message_t message = dhcp_parse_message(payload + skipped);
-    free(payload);
-    //dhcp_print_message(message);
-
-    // Test different sections of the DHCP message
-
-    // Header
-    dhcp_message_t expected;
-    expected.op = DHCP_BOOTREPLY;
-    expected.htype = 1;
-    expected.hlen = 6;
-    expected.hops = 0;
-    expected.xid = 0x6617ca54;
-    expected.secs = 0;
-    expected.flags = 0x0000;
-    expected.ciaddr = ipv4_str_to_net("0.0.0.0");
-    expected.yiaddr = ipv4_str_to_net("192.168.1.161");
-    expected.siaddr = ipv4_str_to_net("192.168.1.1");
-    expected.giaddr = ipv4_str_to_net("0.0.0.0");
-    memcpy(expected.chaddr, "\x78\x8b\x2a\xb2\x20\xea\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", MAX_HW_LEN);
-    compare_headers(message, expected);
-
-    // Options
-    expected.options.count = 11;
-    expected.options.options = (dhcp_option_t *) malloc(sizeof(dhcp_option_t) * expected.options.count);
-    // Option 53: DHCP Message Type
-    expected.options.options->code = 53;
-    expected.options.options->length = 1;
-    expected.options.options->value = (uint8_t *) malloc(sizeof(uint8_t) * expected.options.options->length);
-    *(expected.options.options->value) = DHCP_OFFER;
-    CU_ASSERT_EQUAL(message.options.message_type, DHCP_OFFER);
-    // Option 54: Server Identifier
-    (expected.options.options + 1)->code = 54;
-    (expected.options.options + 1)->length = 4;
-    (expected.options.options + 1)->value = (uint8_t *) malloc(sizeof(uint8_t) * (expected.options.options + 1)->length);
-    memcpy((expected.options.options + 1)->value, "\xc0\xa8\x01\x01", (expected.options.options + 1)->length);
-    // Option 51: IP Address Lease Time
-    (expected.options.options + 2)->code = 51;
-    (expected.options.options + 2)->length = 4;
-    (expected.options.options + 2)->value = (uint8_t *) malloc(sizeof(uint8_t) * (expected.options.options + 2)->length);
-    memcpy((expected.options.options + 2)->value, "\x00\x00\xa8\xc0", (expected.options.options + 2)->length);
-    // Option 58: Renewal Time Value
-    (expected.options.options + 3)->code = 58;
-    (expected.options.options + 3)->length = 4;
-    (expected.options.options + 3)->value = (uint8_t *) malloc(sizeof(uint8_t) * (expected.options.options + 3)->length);
-    memcpy((expected.options.options + 3)->value, "\x00\x00\x54\x60", (expected.options.options + 3)->length);
-    // Option 59: Rebinding Time Value
-    (expected.options.options + 4)->code = 59;
-    (expected.options.options + 4)->length = 4;
-    (expected.options.options + 4)->value = (uint8_t *) malloc(sizeof(uint8_t) * (expected.options.options + 4)->length);
-    memcpy((expected.options.options + 4)->value, "\x00\x00\x93\xa8", (expected.options.options + 4)->length);
-    // Option 1: Subnet Mask
-    (expected.options.options + 5)->code = 1;
-    (expected.options.options + 5)->length = 4;
-    (expected.options.options + 5)->value = (uint8_t *) malloc(sizeof(uint8_t) * (expected.options.options + 5)->length);
-    memcpy((expected.options.options + 5)->value, "\xff\xff\xff\x00", (expected.options.options + 5)->length);
-    // Option 28: Broadcast Address
-    (expected.options.options + 6)->code = 28;
-    (expected.options.options + 6)->length = 4;
-    (expected.options.options + 6)->value = (uint8_t *) malloc(sizeof(uint8_t) * (expected.options.options + 6)->length);
-    memcpy((expected.options.options + 6)->value, "\xc0\xa8\x01\xff", (expected.options.options + 6)->length);
-    // Option 3: Router
-    (expected.options.options + 7)->code = 3;
-    (expected.options.options + 7)->length = 4;
-    (expected.options.options + 7)->value = (uint8_t *) malloc(sizeof(uint8_t) * (expected.options.options + 7)->length);
-    memcpy((expected.options.options + 7)->value, "\xc0\xa8\x01\x01", (expected.options.options + 7)->length);
-    // Option 6: Domain Name Server
-    (expected.options.options + 8)->code = 6;
-    (expected.options.options + 8)->length = 4;
-    (expected.options.options + 8)->value = (uint8_t *) malloc(sizeof(uint8_t) * (expected.options.options + 8)->length);
-    memcpy((expected.options.options + 8)->value, "\xc0\xa8\x01\x01", (expected.options.options + 8)->length);
-    // Option 15: Domain Name
-    (expected.options.options + 9)->code = 15;
-    (expected.options.options + 9)->length = 3;
-    (expected.options.options + 9)->value = (uint8_t *) malloc(sizeof(uint8_t) * (expected.options.options + 9)->length);
-    memcpy((expected.options.options + 9)->value, "\x6c\x61\x6e", (expected.options.options + 9)->length);
-    // Option 255: End
-    (expected.options.options + 10)->code = 255;
-    (expected.options.options + 10)->length = 0;
-    (expected.options.options + 10)->value = NULL;
-    // Compare and free options
-    compare_options(message.options, expected.options);
-
-    // Free messages
-    dhcp_free_message(message);
-    dhcp_free_message(expected);
-}
-
-/**
- * Main function for the unit tests.
- */
-int main(int argc, char const *argv[])
-{
-    // Initialize registry and suite
-    if (CU_initialize_registry() != CUE_SUCCESS)
-        return CU_get_error();
-    CU_pSuite suite = CU_add_suite("dhcp", NULL, NULL);
-    // Run tests
-    CU_add_test(suite, "dhcp-discover", test_dhcp_discover);
-    CU_add_test(suite, "dhcp-offer", test_dhcp_offer);
-    CU_basic_run_tests();
-    CU_cleanup_registry();
-    return 0;
-}
diff --git a/test/parsers/dns.c b/test/parsers/dns.c
deleted file mode 100644
index f75e3db8059dacd2a4a81cf17123a6623bd43c6f..0000000000000000000000000000000000000000
--- a/test/parsers/dns.c
+++ /dev/null
@@ -1,333 +0,0 @@
-/**
- * @file test/parsers/dns.c
- * @brief Unit tests for the DNS parser
- * @date 2022-09-09
- * 
- * @copyright Copyright (c) 2022
- * 
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-// Custom libraries
-#include "packet_utils.h"
-#include "parsers/header.h"
-#include "parsers/dns.h"
-// CUnit
-#include <CUnit/CUnit.h>
-#include <CUnit/Basic.h>
-
-
-/**
- * Unit test for the header section of a DNS message.
- * Verify that each header field is as expected.
- */
-void compare_headers(dns_header_t actual, dns_header_t expected) {
-    CU_ASSERT_EQUAL(actual.id, expected.id);
-    CU_ASSERT_EQUAL(actual.flags, expected.flags);
-    CU_ASSERT_EQUAL(actual.qr, expected.qr);
-    CU_ASSERT_EQUAL(actual.qdcount, expected.qdcount);
-    CU_ASSERT_EQUAL(actual.ancount, expected.ancount);
-    CU_ASSERT_EQUAL(actual.nscount, expected.nscount);
-    CU_ASSERT_EQUAL(actual.arcount, expected.arcount);
-}
-
-/**
- * Unit test for the questions section
- * of a DNS message.
- */
-void compare_questions(uint16_t qdcount, dns_question_t *actual, dns_question_t *expected) {
-    for (int i = 0; i < qdcount; i++) {
-        CU_ASSERT_STRING_EQUAL((actual + i)->qname, (expected + i)->qname);
-        CU_ASSERT_EQUAL((actual + i)->qtype, (expected + i)->qtype);
-        CU_ASSERT_EQUAL((actual + i)->qclass, (expected + i)->qclass);
-    }
-}
-
-/**
- * Unit test for a resource records section
- * of a DNS message.
- */
-void compare_rrs(uint16_t count, dns_resource_record_t *actual, dns_resource_record_t *expected) {
-    for (int i = 0; i < count; i++) {
-        CU_ASSERT_STRING_EQUAL((actual + i)->name, (expected + i)->name);
-        CU_ASSERT_EQUAL((actual + i)->rtype, (expected + i)->rtype);
-        CU_ASSERT_EQUAL((actual + i)->rclass, (expected + i)->rclass);
-        CU_ASSERT_EQUAL((actual + i)->ttl, (expected + i)->ttl);
-        CU_ASSERT_EQUAL((actual + i)->rdlength, (expected + i)->rdlength);
-        CU_ASSERT_STRING_EQUAL(
-            dns_rdata_to_str((actual + i)->rtype, (actual + i)->rdlength, (actual + i)->rdata),
-            dns_rdata_to_str((expected + i)->rtype, (expected + i)->rdlength, (expected + i)->rdata)
-        );
-    }
-}
-
-/**
- * Unit test for the DNS parser.
- */
-void test_dns_xiaomi() {
-
-    char *hexstring = "450000912ecc40004011879dc0a80101c0a801a10035a6b5007d76b46dca8180000100020000000008627573696e6573730b736d61727463616d6572610361706902696f026d6903636f6d0000010001c00c0005000100000258002516636e616d652d6170702d636f6d2d616d7370726f78790177066d692d64756e03636f6d00c04000010001000000930004142f61e7";
-    
-    uint8_t *payload;
-    size_t length = hexstr_to_payload(hexstring, &payload);
-    CU_ASSERT_EQUAL(length, strlen(hexstring) / 2);  // Verify message length
-
-    size_t skipped = get_headers_length(payload);
-    dns_message_t message = dns_parse_message(payload + skipped);
-    free(payload);
-    //dns_print_message(message);
-
-    // Test different sections of the DNS message
-
-    // Header
-    dns_header_t expected_header;
-    expected_header.id = 0x6dca;
-    expected_header.flags = 0x8180;
-    expected_header.qr = 1;
-    expected_header.qdcount = 1;
-    expected_header.ancount = 2;
-    expected_header.nscount = 0;
-    expected_header.arcount = 0;
-    compare_headers(message.header, expected_header);
-    
-    // Questions
-    dns_question_t *expected_question;
-    expected_question = malloc(sizeof(dns_question_t) * message.header.qdcount);
-    expected_question->qname = "business.smartcamera.api.io.mi.com";
-    expected_question->qtype = 1;
-    expected_question->qclass = 1;
-    compare_questions(message.header.qdcount, message.questions, expected_question);
-    free(expected_question);
-    
-    // Answer resource records
-    dns_resource_record_t *expected_answer;
-    expected_answer = malloc(sizeof(dns_resource_record_t) * message.header.ancount);
-    // Answer n°0
-    expected_answer->name = "business.smartcamera.api.io.mi.com";
-    expected_answer->rtype = 5;
-    expected_answer->rclass = 1;
-    expected_answer->ttl = 600;
-    expected_answer->rdlength = 37;
-    expected_answer->rdata.domain_name = "cname-app-com-amsproxy.w.mi-dun.com";
-    // Answer n°1
-    (expected_answer + 1)->name = "cname-app-com-amsproxy.w.mi-dun.com";
-    (expected_answer + 1)->rtype = 1;
-    (expected_answer + 1)->rclass = 1;
-    (expected_answer + 1)->ttl = 147;
-    (expected_answer + 1)->rdlength = 4;
-    (expected_answer + 1)->rdata.ip.version = 4;
-    (expected_answer + 1)->rdata.ip.value.ipv4 = ipv4_str_to_net("20.47.97.231");
-    compare_rrs(message.header.ancount, message.answers, expected_answer);
-    free(expected_answer);
-
-
-    // Lookup functions
-
-    // Search for domain name
-    char *domain_name = "business.smartcamera.api.io.mi.com";
-    CU_ASSERT_TRUE(dns_contains_full_domain_name(message.questions, message.header.qdcount, domain_name));
-    char *suffix = "api.io.mi.com";
-    CU_ASSERT_TRUE(dns_contains_suffix_domain_name(message.questions, message.header.qdcount, suffix, strlen(suffix)));
-    domain_name = "www.example.org";
-    CU_ASSERT_FALSE(dns_contains_full_domain_name(message.questions, message.header.qdcount, domain_name));
-    suffix = "example.org";
-    CU_ASSERT_FALSE(dns_contains_suffix_domain_name(message.questions, message.header.qdcount, suffix, strlen(suffix)));
-
-    // Get question from domain name
-    domain_name = "business.smartcamera.api.io.mi.com";
-    dns_question_t *question_lookup = dns_get_question(message.questions, message.header.qdcount, domain_name);
-    CU_ASSERT_PTR_NOT_NULL(question_lookup);
-    domain_name = "www.example.org";
-    question_lookup = dns_get_question(message.questions, message.header.qdcount, domain_name);
-    CU_ASSERT_PTR_NULL(question_lookup);
-
-    // Get IP addresses from domain name
-    domain_name = "business.smartcamera.api.io.mi.com";
-    ip_list_t ip_list = dns_get_ip_from_name(message.answers, message.header.ancount, domain_name);
-    char *ip_address = "20.47.97.231";
-    CU_ASSERT_EQUAL(ip_list.ip_count, 1);
-    CU_ASSERT_STRING_EQUAL(ipv4_net_to_str(ip_list.ip_addresses->value.ipv4), ip_address);
-    free(ip_list.ip_addresses);
-    domain_name = "www.example.org";
-    ip_list = dns_get_ip_from_name(message.answers, message.header.ancount, domain_name);
-    CU_ASSERT_EQUAL(ip_list.ip_count, 0);
-    CU_ASSERT_PTR_NULL(ip_list.ip_addresses);
-
-    // Free memory
-    dns_free_message(message);
-}
-
-/**
- * Unit test for the DNS parser.
- */
-void test_dns_office() {
-    char *hexstring = "4500012a4aa900003e114737826801018268e4110035d7550116a82b3ebf81800001000900000001076f75746c6f6f6b066f666669636503636f6d0000010001c00c0005000100000007000c09737562737472617465c014c03000050001000000500017076f75746c6f6f6b096f666669636533363503636f6d00c0480005000100000093001a076f75746c6f6f6b026861096f666669636533363503636f6d00c06b000500010000000b001c076f75746c6f6f6b076d732d61636463066f666669636503636f6d00c091000500010000001b000a07414d532d65667ac099c0b90001000100000004000434619ea2c0b90001000100000004000428650c62c0b9000100010000000400042863cc22c0b9000100010000000400042865791200002904d0000000000000";
-
-    // Create payload from hexstring
-    uint8_t *payload;
-    size_t length = hexstr_to_payload(hexstring, &payload);
-    CU_ASSERT_EQUAL(length, strlen(hexstring) / 2);  // Verify message length
-    size_t skipped = get_headers_length(payload);
-    dns_message_t message = dns_parse_message(payload + skipped);
-    free(payload);
-    //dns_print_message(message);
-
-    // Test different sections of the DNS message
-
-    // Header
-    dns_header_t expected_header;
-    expected_header.id = 0x3ebf;
-    expected_header.flags = 0x8180;
-    expected_header.qr = 1;
-    expected_header.qdcount = 1;
-    expected_header.ancount = 9;
-    expected_header.nscount = 0;
-    expected_header.arcount = 1;
-    compare_headers(message.header, expected_header);
-
-    // Questions
-    dns_question_t *expected_question;
-    expected_question = malloc(sizeof(dns_question_t) * message.header.qdcount);
-    expected_question->qname = "outlook.office.com";
-    expected_question->qtype = 1;
-    expected_question->qclass = 1;
-    compare_questions(message.header.qdcount, message.questions, expected_question);
-    free(expected_question);
-
-    // Answer resource records
-    dns_resource_record_t *expected_answer;
-    expected_answer = malloc(sizeof(dns_resource_record_t) * message.header.ancount);
-    // Answer n°0
-    expected_answer->name = "outlook.office.com";
-    expected_answer->rtype = 5;
-    expected_answer->rclass = 1;
-    expected_answer->ttl = 7;
-    expected_answer->rdlength = 12;
-    expected_answer->rdata.domain_name = "substrate.office.com";
-    // Answer n°1
-    (expected_answer + 1)->name = "substrate.office.com";
-    (expected_answer + 1)->rtype = 5;
-    (expected_answer + 1)->rclass = 1;
-    (expected_answer + 1)->ttl = 80;
-    (expected_answer + 1)->rdlength = 23;
-    (expected_answer + 1)->rdata.domain_name = "outlook.office365.com";
-    // Answer n°2
-    (expected_answer + 2)->name = "outlook.office365.com";
-    (expected_answer + 2)->rtype = 5;
-    (expected_answer + 2)->rclass = 1;
-    (expected_answer + 2)->ttl = 147;
-    (expected_answer + 2)->rdlength = 26;
-    (expected_answer + 2)->rdata.domain_name = "outlook.ha.office365.com";
-    // Answer n°3
-    (expected_answer + 3)->name = "outlook.ha.office365.com";
-    (expected_answer + 3)->rtype = 5;
-    (expected_answer + 3)->rclass = 1;
-    (expected_answer + 3)->ttl = 11;
-    (expected_answer + 3)->rdlength = 28;
-    (expected_answer + 3)->rdata.domain_name = "outlook.ms-acdc.office.com";
-    // Answer n°4
-    (expected_answer + 4)->name = "outlook.ms-acdc.office.com";
-    (expected_answer + 4)->rtype = CNAME;
-    (expected_answer + 4)->rclass = 1;
-    (expected_answer + 4)->ttl = 27;
-    (expected_answer + 4)->rdlength = 10;
-    (expected_answer + 4)->rdata.domain_name = "AMS-efz.ms-acdc.office.com";
-    // Answer n°5
-    (expected_answer + 5)->name = "AMS-efz.ms-acdc.office.com";
-    (expected_answer + 5)->rtype = A;
-    (expected_answer + 5)->rclass = 1;
-    (expected_answer + 5)->ttl = 4;
-    (expected_answer + 5)->rdlength = 4;
-    (expected_answer + 5)->rdata.ip.version = 4;
-    (expected_answer + 5)->rdata.ip.value.ipv4 = ipv4_str_to_net("52.97.158.162");
-    // Answer n°6
-    (expected_answer + 6)->name = "AMS-efz.ms-acdc.office.com";
-    (expected_answer + 6)->rtype = A;
-    (expected_answer + 6)->rclass = 1;
-    (expected_answer + 6)->ttl = 4;
-    (expected_answer + 6)->rdlength = 4;
-    (expected_answer + 6)->rdata.ip.version = 4;
-    (expected_answer + 6)->rdata.ip.value.ipv4 = ipv4_str_to_net("40.101.12.98");
-    // Answer n°7
-    (expected_answer + 7)->name = "AMS-efz.ms-acdc.office.com";
-    (expected_answer + 7)->rtype = A;
-    (expected_answer + 7)->rclass = 1;
-    (expected_answer + 7)->ttl = 4;
-    (expected_answer + 7)->rdlength = 4;
-    (expected_answer + 7)->rdata.ip.version = 4;
-    (expected_answer + 7)->rdata.ip.value.ipv4 = ipv4_str_to_net("40.99.204.34");
-    // Answer n°8
-    (expected_answer + 8)->name = "AMS-efz.ms-acdc.office.com";
-    (expected_answer + 8)->rtype = A;
-    (expected_answer + 8)->rclass = 1;
-    (expected_answer + 8)->ttl = 4;
-    (expected_answer + 8)->rdlength = 4;
-    (expected_answer + 8)->rdata.ip.version = 4;
-    (expected_answer + 8)->rdata.ip.value.ipv4 = ipv4_str_to_net("40.101.121.18");
-    // Compare and free answer
-    compare_rrs(message.header.ancount, message.answers, expected_answer);
-    free(expected_answer);
-
-
-    // Lookup functions
-
-    // Search for domain name
-    char *domain_name = "outlook.office.com";
-    CU_ASSERT_TRUE(dns_contains_full_domain_name(message.questions, message.header.qdcount, domain_name));
-    char* suffix = "office.com";
-    CU_ASSERT_TRUE(dns_contains_suffix_domain_name(message.questions, message.header.qdcount, suffix, strlen(suffix)));
-    domain_name = "www.example.org";
-    CU_ASSERT_FALSE(dns_contains_full_domain_name(message.questions, message.header.qdcount, domain_name));
-    suffix = "example.org";
-    CU_ASSERT_FALSE(dns_contains_suffix_domain_name(message.questions, message.header.qdcount, suffix, strlen(suffix)));
-
-    // Get question from domain name
-    domain_name = "outlook.office.com";
-    dns_question_t *question_lookup = dns_get_question(message.questions, message.header.qdcount, domain_name);
-    CU_ASSERT_PTR_NOT_NULL(question_lookup);
-    domain_name = "www.example.org";
-    question_lookup = dns_get_question(message.questions, message.header.qdcount, domain_name);
-    CU_ASSERT_PTR_NULL(question_lookup);
-
-    // Get IP addresses from domain name
-    domain_name = "outlook.office.com";
-    ip_list_t ip_list = dns_get_ip_from_name(message.answers, message.header.ancount, domain_name);
-    char* ip_addresses[] = {
-        "52.97.158.162",
-        "40.101.12.98",
-        "40.99.204.34",
-        "40.101.121.18"
-    };
-    CU_ASSERT_EQUAL(ip_list.ip_count, 4);
-    for (uint8_t i = 0; i < 4; i++) {
-        CU_ASSERT_STRING_EQUAL(ipv4_net_to_str((ip_list.ip_addresses + i)->value.ipv4), ip_addresses[i]);
-    }
-    free(ip_list.ip_addresses);
-    domain_name = "www.example.org";
-    ip_list = dns_get_ip_from_name(message.answers, message.header.ancount, domain_name);
-    CU_ASSERT_EQUAL(ip_list.ip_count, 0);
-    CU_ASSERT_PTR_NULL(ip_list.ip_addresses);
-
-    // Free memory
-    dns_free_message(message);
-}
-
-/**
- * Main function for the unit tests.
- */
-int main(int argc, char const *argv[])
-{
-    // Initialize registry and suite
-    if (CU_initialize_registry() != CUE_SUCCESS)
-        return CU_get_error();
-    printf("Test suite: dns\n");
-    CU_pSuite suite = CU_add_suite("dns", NULL, NULL);
-    // Run tests
-    CU_add_test(suite, "dns-xiaomi", test_dns_xiaomi);
-    CU_add_test(suite, "dns-office", test_dns_office);
-    CU_basic_run_tests();
-    CU_cleanup_registry();
-    return 0;
-}
diff --git a/test/parsers/header.c b/test/parsers/header.c
deleted file mode 100644
index 2a9a945de3080a34d9d3c82134329d136fdb5bbd..0000000000000000000000000000000000000000
--- a/test/parsers/header.c
+++ /dev/null
@@ -1,165 +0,0 @@
-/**
- * @file test/parsers/header.c
- * @brief Unit test for the header parser (OSI layers 3 and 4)
- * @date 2022-12-01
- * 
- * @copyright Copyright (c) 2022
- * 
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-// Custom libraries
-#include "packet_utils.h"
-#include "parsers/header.h"
-// CUnit
-#include <CUnit/CUnit.h>
-#include <CUnit/Basic.h>
-
-
-/**
- * @brief Unit test using a TCP SYN packet.
- */
-void test_tcp_syn() {
-
-    char *hexstring = "4500003cbcd2400040066e0fc0a801966c8ae111c67f005004f77abb00000000a002ffff2b380000020405b40402080a0003c6690000000001030306";
-
-    uint8_t *payload;
-    size_t length = hexstr_to_payload(hexstring, &payload);
-    CU_ASSERT_EQUAL(length, strlen(hexstring) / 2);  // Verify packet length
-
-    // Layer-3 header length
-    uint16_t l3_header_length = get_l3_header_length(payload);
-    CU_ASSERT_EQUAL(l3_header_length, 20);
-
-    // IPv4 destination address
-    uint32_t ipv4_src_addr = get_ipv4_src_addr(payload);
-    CU_ASSERT_STRING_EQUAL(ipv4_net_to_str(ipv4_src_addr), "192.168.1.150");
-
-    // IPv4 destination address
-    uint32_t ipv4_dst_addr = get_ipv4_dst_addr(payload);
-    CU_ASSERT_STRING_EQUAL(ipv4_net_to_str(ipv4_dst_addr), "108.138.225.17");
-
-    // TCP header length
-    uint16_t tcp_header_length = get_tcp_header_length(payload + l3_header_length);
-    CU_ASSERT_EQUAL(tcp_header_length, 40);
-
-    // Layers 3 and 4 headers length
-    uint16_t headers_length = get_headers_length(payload);
-    CU_ASSERT_EQUAL(headers_length, 20 + 40);
-
-    // Destination port
-    uint16_t dst_port = get_dst_port(payload + l3_header_length);
-    CU_ASSERT_EQUAL(dst_port, 80);
-
-    // Contains payload ?
-    CU_ASSERT_FALSE(length - headers_length > 0);
-
-    free(payload);
-}
-
-/**
- * @brief Unit test using an HTTPS data packet.
- */
-void test_https_data() {
-
-    char *hexstring = "450001613b64400040067977c0a801dec0a8018d8da801bbec035d653f25b250501808065ff2000017030301340000000000000087884ca5c237291279d20249e09c2848a56615a0fda66e788fdc5a04cb96d7be52b00302e4956118ec87e74ad1e3e20192689876cc821e6c95087fbc160163edd6a48b5f1f06752e3b0b0ee4c9c1f208508ba36fd57499c3a1d95805f33a5e5b89edb06e8b70615eb3f531a375537674e298b7692d78bd5e407738597097285a1205a2d3f4ba183bbd7f609ec1a9464934dd9999b8955c6a537a28a03118ac8a3391fdc378413bfcacba2a3995f54b45ea05126f1d906bbad2629a8d16e88b531f2d047a7f8b5199c5db819f76eac6d83e1e428b97b71721f3280e4eab6fb1c10dd58dfad004d11061aff1ee559c4704930a4dac9e33f32707f80823438990457dafdd5d325dda22f2fab0863cbbb45cafc11c5209370e23d5bc779506f5621d75afa003932c8bdb72ff5f9a2f";
-
-    uint8_t *payload;
-    size_t length = hexstr_to_payload(hexstring, &payload);
-    CU_ASSERT_EQUAL(length, strlen(hexstring) / 2); // Verify packet length
-
-    // Layer-3 header length
-    uint16_t l3_header_length = get_l3_header_length(payload);
-    CU_ASSERT_EQUAL(l3_header_length, 20);
-
-    // IPv4 destination address
-    uint32_t ipv4_src_addr = get_ipv4_src_addr(payload);
-    CU_ASSERT_STRING_EQUAL(ipv4_net_to_str(ipv4_src_addr), "192.168.1.222");
-
-    // IPv4 destination address
-    uint32_t ipv4_dst_addr = get_ipv4_dst_addr(payload);
-    CU_ASSERT_STRING_EQUAL(ipv4_net_to_str(ipv4_dst_addr), "192.168.1.141");
-
-    // TCP header length
-    uint16_t tcp_header_length = get_tcp_header_length(payload + l3_header_length);
-    CU_ASSERT_EQUAL(tcp_header_length, 20);
-
-    // Layers 3 and 4 headers length
-    uint16_t headers_length = get_headers_length(payload);
-    CU_ASSERT_EQUAL(headers_length, 20 + 20);
-
-    // Destination port
-    uint16_t dst_port = get_dst_port(payload + l3_header_length);
-    CU_ASSERT_EQUAL(dst_port, 443);
-
-    // Contains payload ?
-    CU_ASSERT_TRUE(length - headers_length > 0);
-
-    free(payload);
-}
-
-/**
- * @brief Unit test using a DNS message over IPv6.
- */
-void test_dns_ipv6() {
-
-    char *hexstring = "6002ec1b002d1140fddded18f05b0000d8a3adc0f68fe5cffddded18f05b00000000000000000001b0f20035002d5388ac4a01000001000000000000036170690b736d6172747468696e677303636f6d00001c0001";
-
-    uint8_t *payload;
-    size_t length = hexstr_to_payload(hexstring, &payload);
-    CU_ASSERT_EQUAL(length, strlen(hexstring) / 2); // Verify packet length
-
-    // Layer-3 header length
-    uint16_t l3_header_length = get_l3_header_length(payload);
-    CU_ASSERT_EQUAL(l3_header_length, IPV6_HEADER_LENGTH);
-
-    // IPv6 source address
-    uint8_t *ipv6_src_addr = get_ipv6_src_addr(payload);
-    uint8_t expected_src[IPV6_ADDR_LENGTH] = {0xfd, 0xdd, 0xed, 0x18, 0xf0, 0x5b, 0x00, 0x00, 0xd8, 0xa3, 0xad, 0xc0, 0xf6, 0x8f, 0xe5, 0xcf};
-    CU_ASSERT_TRUE(compare_ipv6(ipv6_src_addr, expected_src));
-    free(ipv6_src_addr);
-
-    // IPv6 destination address
-    uint8_t *ipv6_dst_addr = get_ipv6_dst_addr(payload);
-    uint8_t expected_dst[IPV6_ADDR_LENGTH] = {0xfd, 0xdd, 0xed, 0x18, 0xf0, 0x5b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01};
-    CU_ASSERT_TRUE(compare_ipv6(ipv6_dst_addr, expected_dst));
-    free(ipv6_dst_addr);
-
-    // UDP header length
-    uint16_t udp_header_length = get_udp_header_length(payload + l3_header_length);
-    CU_ASSERT_EQUAL(udp_header_length, UDP_HEADER_LENGTH);
-
-    // Layers 3 and 4 headers length
-    uint16_t headers_length = get_headers_length(payload);
-    CU_ASSERT_EQUAL(headers_length, IPV6_HEADER_LENGTH + UDP_HEADER_LENGTH);
-
-    // Destination port
-    uint16_t dst_port = get_dst_port(payload + l3_header_length);
-    CU_ASSERT_EQUAL(dst_port, 53);
-
-    // UDP payload length
-    uint16_t udp_payload_length = get_udp_payload_length(payload + l3_header_length);
-    CU_ASSERT_EQUAL(udp_payload_length, 45 - UDP_HEADER_LENGTH);
-
-    free(payload);
-}
-
-/**
- * Driver function for the unit tests.
- */
-int main(int argc, char const *argv[])
-{
-    // Initialize registry and suite
-    if (CU_initialize_registry() != CUE_SUCCESS)
-        return CU_get_error();
-    CU_pSuite suite = CU_add_suite("header", NULL, NULL);
-    // Run tests
-    CU_add_test(suite, "tcp-syn", test_tcp_syn);
-    CU_add_test(suite, "https-data", test_https_data);
-    CU_add_test(suite, "dns-ipv6", test_dns_ipv6);
-    CU_basic_run_tests();
-    CU_cleanup_registry();
-    return 0;
-}
diff --git a/test/parsers/http.c b/test/parsers/http.c
deleted file mode 100644
index 3554d43c85eb972b916cd8c6f255b92d38bd3faa..0000000000000000000000000000000000000000
--- a/test/parsers/http.c
+++ /dev/null
@@ -1,92 +0,0 @@
-/**
- * @file test/parsers/http.c
- * @brief Unit tests for the HTTP parser
- * @date 2022-20-09
- * 
- * @copyright Copyright (c) 2022
- * 
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-// Custom libraries
-#include "packet_utils.h"
-#include "parsers/header.h"
-#include "parsers/http.h"
-// CUnit
-#include <CUnit/CUnit.h>
-#include <CUnit/Basic.h>
-
-
-/**
- * @brief Unit test for the HTTP parser.
- */
-void test_http_request() {
-
-    char *hexstring = "450000ccb11f400040065845c0a801a16e2b005387b8005023882026a6ab695450180e4278860000474554202f67736c623f747665723d322669643d33363932313536313726646d3d6f74732e696f2e6d692e636f6d2674696d657374616d703d38267369676e3d6a327a743325324270624177637872786f765155467443795a3644556d47706c584e4b723169386a746552623425334420485454502f312e310d0a486f73743a20646e732e696f2e6d692e636f6d0d0a557365722d4167656e743a204d496f540d0a0d0a";
-
-    uint8_t *payload;
-    size_t length = hexstr_to_payload(hexstring, &payload);
-    CU_ASSERT_EQUAL(length, strlen(hexstring) / 2);  // Verify message length
-
-    size_t l3_header_length = get_l3_header_length(payload);
-    uint16_t dst_port = get_dst_port(payload + l3_header_length);
-    size_t skipped = get_headers_length(payload);
-    http_message_t actual = http_parse_message(payload + skipped, dst_port);
-    free(payload);
-    //http_print_message(actual);
-
-    // Test if HTTP message has been correctly parsed
-    http_message_t expected;
-    expected.is_request = true;
-    expected.method = HTTP_GET;
-    expected.uri = "/gslb?tver=2&id=369215617&dm=ots.io.mi.com&timestamp=8&sign=j2zt3%2BpbAwcxrxovQUFtCyZ6DUmGplXNKr1i8jteRb4%3D";
-    CU_ASSERT_EQUAL(actual.is_request, expected.is_request);
-    CU_ASSERT_EQUAL(actual.method, expected.method);
-    CU_ASSERT_STRING_EQUAL(actual.uri, expected.uri);
-
-    http_free_message(actual);
-
-}
-
-void test_http_response() {
-
-    char *hexstring = "450001a42fc540002f06e9c76e2b0053c0a801a1005087b8a6ab6954238820ca501803b8e92e0000485454502f312e3120323030204f4b0d0a5365727665723a2054656e67696e650d0a446174653a205765642c203330204d617220323032322031323a30353a323420474d540d0a436f6e74656e742d547970653a206170706c69636174696f6e2f6a736f6e3b20636861727365743d7574662d380d0a436f6e74656e742d4c656e6774683a203231350d0a436f6e6e656374696f6e3a206b6565702d616c6976650d0a0d0a7b22696e666f223a7b22656e61626c65223a312c22686f73745f6c697374223a5b7b226970223a223132302e39322e39362e313535222c22706f7274223a3434337d2c7b226970223a223132302e39322e3134352e313430222c22706f7274223a3434337d2c7b226970223a223132302e39322e36352e323431222c22706f7274223a3434337d5d7d2c227369676e223a225a757856496a2b337858303362654a4b5936684e385668454f7a65485630446a6753654471656d2b7032413d222c2274696d657374616d70223a313634383634313932347d";
-
-    uint8_t *payload;
-    size_t length = hexstr_to_payload(hexstring, &payload);
-    CU_ASSERT_EQUAL(length, strlen(hexstring) / 2); // Verify message length
-
-    size_t skipped = get_ipv4_header_length(payload);
-    uint16_t dst_port = get_dst_port(payload + skipped);
-    skipped += get_tcp_header_length(payload + skipped);
-    http_message_t actual = http_parse_message(payload + skipped, dst_port);
-    free(payload);
-    //http_print_message(actual);
-
-    // Test if HTTP message has been correctly parsed
-    http_message_t expected;
-    expected.is_request = false;
-    CU_ASSERT_EQUAL(actual.is_request, expected.is_request);
-
-    http_free_message(actual);
-
-}
-
-/**
- * Driver function for the unit tests.
- */
-int main(int argc, char const *argv[])
-{
-    // Initialize registry and suite
-    if (CU_initialize_registry() != CUE_SUCCESS)
-        return CU_get_error();
-    CU_pSuite suite = CU_add_suite("http", NULL, NULL);
-    // Run tests
-    CU_add_test(suite, "http-request", test_http_request);
-    CU_add_test(suite, "http-response", test_http_response);
-    CU_basic_run_tests();
-    CU_cleanup_registry();
-    return 0;
-}
diff --git a/test/parsers/igmp.c b/test/parsers/igmp.c
deleted file mode 100644
index d67b19a932f7cbcbe7ade8bfce156edc773e5a3e..0000000000000000000000000000000000000000
--- a/test/parsers/igmp.c
+++ /dev/null
@@ -1,195 +0,0 @@
-/**
- * @file test/parsers/igmp.c
- * @brief Unit tests for the IGMP parser
- * @date 2022-10-05
- * 
- * @copyright Copyright (c) 2022
- * 
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-// Custom libraries
-#include "packet_utils.h"
-#include "parsers/header.h"
-#include "parsers/igmp.h"
-// CUnit
-#include <CUnit/CUnit.h>
-#include <CUnit/Basic.h>
-
-
-/**
- * @brief Compare two IGMPv2 messages.
- * 
- * @param actual actual IGMPv2 message
- * @param expected expected IGMPv2 message
- */
-void compare_igmp_v2_messages(igmp_v2_message_t actual, igmp_v2_message_t expected) {
-    CU_ASSERT_EQUAL(actual.max_resp_time, expected.max_resp_time);
-    CU_ASSERT_EQUAL(actual.checksum, expected.checksum);
-    CU_ASSERT_EQUAL(actual.group_address, expected.group_address);
-}
-
-/**
- * @brief Compare two IGMPv3 Membership Report messages.
- *
- * @param actual actual IGMPv3 Membership Report message
- * @param expected expected IGMPv3 Membership Report message
- */
-void compare_igmp_v3_messages(igmp_v3_membership_report_t actual, igmp_v3_membership_report_t expected) {
-    CU_ASSERT_EQUAL(actual.checksum, expected.checksum);
-    CU_ASSERT_EQUAL(actual.num_groups, expected.num_groups);
-    for (uint16_t i = 0; i < actual.num_groups; i++) {
-        igmp_v3_group_record_t actual_group = *(actual.groups + i);
-        igmp_v3_group_record_t expected_group = *(expected.groups + i);
-        CU_ASSERT_EQUAL(actual_group.type, expected_group.type);
-        CU_ASSERT_EQUAL(actual_group.aux_data_len, expected_group.aux_data_len);
-        CU_ASSERT_EQUAL(actual_group.num_sources, expected_group.num_sources);
-        CU_ASSERT_EQUAL(actual_group.group_address, expected_group.group_address);
-        for (uint16_t j = 0; j < actual_group.num_sources; j++) {
-            CU_ASSERT_EQUAL(*(actual_group.sources + j), *(expected_group.sources + j));
-        }
-    }
-}
-
-/**
- * @brief Compare two IGMP messages.
- *
- * @param actual actual IGMP message
- * @param expected expected IGMP message
- */
-void compare_igmp_messages(igmp_message_t actual, igmp_message_t expected)
-{
-    CU_ASSERT_EQUAL(actual.version, expected.version);
-    if (actual.version != expected.version)
-        return;
-    
-    CU_ASSERT_EQUAL(actual.type, expected.type);
-    if (actual.type != expected.type)
-        return;
-
-    switch (actual.version)
-    {
-    case 2:
-        compare_igmp_v2_messages(actual.body.v2_message, expected.body.v2_message);
-        break;
-    case 3:
-        compare_igmp_v3_messages(actual.body.v3_membership_report, expected.body.v3_membership_report);
-        break;
-    default:
-        CU_FAIL("Unknown IGMP version");
-    }
-}
-
-/**
- * @brief Unit test with an IGMPv2 Membership Report message.
- */
-void test_igmp_v2_membership_report() {
-
-    char *hexstring = "46c000200000400001024096c0a801dee00000fb9404000016000904e00000fb";
-
-    uint8_t *payload;
-    size_t length = hexstr_to_payload(hexstring, &payload);
-    CU_ASSERT_EQUAL(length, strlen(hexstring) / 2);  // Verify message length
-
-    size_t skipped = get_headers_length(payload);
-    igmp_message_t actual = igmp_parse_message(payload + skipped);
-    free(payload);
-    //igmp_print_message(actual);
-
-    // Expected message
-    igmp_message_t expected;
-    expected.version = 2;
-    expected.type = V2_MEMBERSHIP_REPORT;
-    expected.body.v2_message.max_resp_time = 0;
-    expected.body.v2_message.checksum = 0x0904;
-    expected.body.v2_message.group_address = ipv4_str_to_net("224.0.0.251");
-
-    // Compare messages
-    compare_igmp_messages(actual, expected);
-
-}
-
-/**
- * @brief Unit test with an IGMPv2 Leave Group message.
- */
-void test_igmp_v2_leave_group() {
-
-    char *hexstring = "46c00020000040000102418fc0a801dee00000029404000017000804e00000fb";
-
-    uint8_t *payload;
-    size_t length = hexstr_to_payload(hexstring, &payload);
-    CU_ASSERT_EQUAL(length, strlen(hexstring) / 2);  // Verify message length
-
-    size_t skipped = get_headers_length(payload);
-    igmp_message_t actual = igmp_parse_message(payload + skipped);
-    free(payload);
-    //igmp_print_message(actual);
-
-    // Expected message
-    igmp_message_t expected;
-    expected.version = 2;
-    expected.type = LEAVE_GROUP;
-    expected.body.v2_message.max_resp_time = 0;
-    expected.body.v2_message.checksum = 0x0804;
-    expected.body.v2_message.group_address = ipv4_str_to_net("224.0.0.251");
-
-    // Compare messages
-    compare_igmp_messages(actual, expected);
-
-}
-
-/**
- * @brief Unit test with an IGMPv3 Membership Report message.
- */
-void test_igmp_v3_membership_report() {
-
-    char *hexstring = "46c0002800004000010241dec0a80173e0000016940400002200f9020000000104000000e00000fb";
-
-    uint8_t *payload;
-    size_t length = hexstr_to_payload(hexstring, &payload);
-    CU_ASSERT_EQUAL(length, strlen(hexstring) / 2);  // Verify message length
-
-    size_t skipped = get_headers_length(payload);
-    igmp_message_t actual = igmp_parse_message(payload + skipped);
-    free(payload);
-    //igmp_print_message(actual);
-
-    // Expected message
-    igmp_message_t expected;
-    expected.version = 3;
-    expected.type = V3_MEMBERSHIP_REPORT;
-    expected.body.v3_membership_report.checksum = 0xf902;
-    expected.body.v3_membership_report.num_groups = 1;
-    expected.body.v3_membership_report.groups = malloc(sizeof(igmp_v3_group_record_t));
-    expected.body.v3_membership_report.groups->type = 4;
-    expected.body.v3_membership_report.groups->aux_data_len = 0;
-    expected.body.v3_membership_report.groups->num_sources = 0;
-    expected.body.v3_membership_report.groups->group_address = ipv4_str_to_net("224.0.0.251");
-
-    // Compare messages
-    compare_igmp_messages(actual, expected);
-    
-    // Free messages
-    igmp_free_message(actual);
-    igmp_free_message(expected);
-}
-
-/**
- * Main function for the unit tests.
- */
-int main(int argc, char const *argv[])
-{
-    // Initialize registry and suite
-    if (CU_initialize_registry() != CUE_SUCCESS)
-        return CU_get_error();
-    CU_pSuite suite = CU_add_suite("igmp", NULL, NULL);
-    // Run tests
-    CU_add_test(suite, "igmp-v2-membership-report", test_igmp_v2_membership_report);
-    CU_add_test(suite, "igmp-leave-group", test_igmp_v2_leave_group);
-    CU_add_test(suite, "igmp-v3-membership-report", test_igmp_v3_membership_report);
-    CU_basic_run_tests();
-    CU_cleanup_registry();
-    return 0;
-}
diff --git a/test/parsers/ssdp.c b/test/parsers/ssdp.c
deleted file mode 100644
index 6d71041706f694f63ea7dc38ae8cc9b0ac9071de..0000000000000000000000000000000000000000
--- a/test/parsers/ssdp.c
+++ /dev/null
@@ -1,117 +0,0 @@
-/**
- * @file test/parsers/ssdp.c
- * @brief Unit tests for the SSDP parser
- * @date 2022-11-24
- *
- * @copyright Copyright (c) 2022
- *
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-// Custom libraries
-#include "packet_utils.h"
-#include "parsers/header.h"
-#include "parsers/ssdp.h"
-// CUnit
-#include <CUnit/CUnit.h>
-#include <CUnit/Basic.h>
-
-
-/**
- * @brief Unit test for an SSDP M-SEARCH message.
- */
-void test_ssdp_msearch() {
-
-    char *hexstring = "45000095dba640000111eb7bc0a80193effffffad741076c008163124d2d534541524348202a20485454502f312e310d0a4d583a20340d0a4d414e3a2022737364703a646973636f766572220d0a484f53543a203233392e3235352e3235352e3235303a313930300d0a53543a2075726e3a736368656d61732d75706e702d6f72673a6465766963653a62617369633a310d0a0d0a";
-
-    uint8_t *payload;
-    size_t length = hexstr_to_payload(hexstring, &payload);
-    CU_ASSERT_EQUAL(length, strlen(hexstring) / 2);  // Verify message length
-
-    uint32_t dst_addr = get_ipv4_dst_addr(payload); // IPv4 destination address, in network byte order
-    size_t skipped = get_ipv4_header_length(payload);
-    skipped += get_udp_header_length(payload + skipped);
-    ssdp_message_t actual = ssdp_parse_message(payload + skipped, dst_addr);
-    free(payload);
-    //ssdp_print_message(actual);
-
-    // Test if SSDP message has been correctly parsed
-    ssdp_message_t expected;
-    expected.is_request = true;
-    expected.method = SSDP_M_SEARCH;
-    CU_ASSERT_EQUAL(actual.is_request, expected.is_request);
-    CU_ASSERT_EQUAL(actual.method, expected.method);
-
-}
-
-/**
- * @brief Unit test for an SSDP NOTIFY message.
- */
-void test_ssdp_notify() {
-
-    char *hexstring = "4500014db3ea4000ff111485c0a8018deffffffa076c076c01399a564e4f54494659202a20485454502f312e310d0a484f53543a203233392e3235352e3235352e3235303a313930300d0a43414348452d434f4e54524f4c3a206d61782d6167653d3130300d0a4c4f434154494f4e3a20687474703a2f2f3139322e3136382e312e3134313a38302f6465736372697074696f6e2e786d6c0d0a5345525645523a204875652f312e302055506e502f312e3020332e31342e302f49704272696467650d0a4e54533a20737364703a616c6976650d0a6875652d62726964676569643a20303031373838464646453734433244430d0a4e543a2075706e703a726f6f746465766963650d0a55534e3a20757569643a32663430326638302d646135302d313165312d396232332d3030313738383734633264633a3a75706e703a726f6f746465766963650d0a0d0a";
-
-    uint8_t *payload;
-    size_t length = hexstr_to_payload(hexstring, &payload);
-    CU_ASSERT_EQUAL(length, strlen(hexstring) / 2);  // Verify message length
-
-    uint32_t dst_addr = get_ipv4_dst_addr(payload);  // IPv4 destination address, in network byte order
-    size_t skipped = get_ipv4_header_length(payload);
-    skipped += get_udp_header_length(payload + skipped);
-    ssdp_message_t actual = ssdp_parse_message(payload + skipped, dst_addr);
-    free(payload);
-    //ssdp_print_message(actual);
-
-    // Test if SSDP message has been correctly parsed
-    ssdp_message_t expected;
-    expected.is_request = true;
-    expected.method = SSDP_NOTIFY;
-    CU_ASSERT_EQUAL(actual.is_request, expected.is_request);
-    CU_ASSERT_EQUAL(actual.method, expected.method);
-}
-
-/**
- * @brief Unit test for an SSDP response.
- */
-void test_ssdp_response() {
-
-    char *hexstring = "45000140456c400040116f85c0a8018dc0a801de076c0f66012cdcc8485454502f312e3120323030204f4b0d0a484f53543a203233392e3235352e3235352e3235303a313930300d0a4558543a0d0a43414348452d434f4e54524f4c3a206d61782d6167653d3130300d0a4c4f434154494f4e3a20687474703a2f2f3139322e3136382e312e3134313a38302f6465736372697074696f6e2e786d6c0d0a5345525645523a204875652f312e302055506e502f312e302049704272696467652f312e34382e300d0a6875652d62726964676569643a20303031373838464646453734433244430d0a53543a2075706e703a726f6f746465766963650d0a55534e3a20757569643a32663430326638302d646135302d313165312d396232332d3030313738383734633264633a3a75706e703a726f6f746465766963650d0a0d0a";
-
-    uint8_t *payload;
-    size_t length = hexstr_to_payload(hexstring, &payload);
-    CU_ASSERT_EQUAL(length, strlen(hexstring) / 2);  // Verify message length
-
-    uint32_t dst_addr = get_ipv4_dst_addr(payload);  // IPv4 destination address, in network byte order
-    size_t skipped = get_ipv4_header_length(payload);
-    skipped += get_udp_header_length(payload + skipped);
-    ssdp_message_t actual = ssdp_parse_message(payload + skipped, dst_addr);
-    free(payload);
-    //ssdp_print_message(actual);
-
-    // Test if SSDP message has been correctly parsed
-    ssdp_message_t expected;
-    expected.is_request = false;
-    expected.method = SSDP_UNKNOWN;
-    CU_ASSERT_EQUAL(actual.is_request, expected.is_request);
-    CU_ASSERT_EQUAL(actual.method, expected.method);
-
-}
-
-/**
- * Main function for the unit tests.
- */
-int main(int argc, char const *argv[]) {
-    // Initialize registry and suite
-    if (CU_initialize_registry() != CUE_SUCCESS)
-        return CU_get_error();
-    CU_pSuite suite = CU_add_suite("ssdp", NULL, NULL);
-    // Run tests
-    CU_add_test(suite, "ssdp-msearch", test_ssdp_msearch);
-    CU_add_test(suite, "ssdp-notify", test_ssdp_notify);
-    CU_add_test(suite, "ssdp-response", test_ssdp_response);
-    CU_basic_run_tests();
-    CU_cleanup_registry();
-    return 0;
-}