Skip to content
Extraits de code Groupes Projets
Valider 967c07f3 rédigé par François De Keersmaeker's avatar François De Keersmaeker
Parcourir les fichiers

Configured submodule protocol-parsers

parent b20e5ee4
Aucune branche associée trouvée
Aucune étiquette associée trouvée
Aucune requête de fusion associée trouvée
Affichage de
avec 20 ajouts et 1848 suppressions
EXITCODE=0 EXITCODE=0
PARSERS_DIR="$GITHUB_WORKSPACE/src/parsers"
# Pattern matching on all source files # 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 do
if [[ "$file" != *"/hashmap.c" ]] if [[ "$file" != *"/hashmap.c" ]]
then then
......
EXITCODE=0 EXITCODE=0
PARSERS_DIR="$GITHUB_WORKSPACE/src/parsers"
VALGRIND_SUPP="$GITHUB_WORKSPACE/.ci_scripts/full-test/valgrind.supp" VALGRIND_SUPP="$GITHUB_WORKSPACE/.ci_scripts/full-test/valgrind.supp"
PREFIX="" PREFIX=""
for file in $GITHUB_WORKSPACE/bin/test/* for file in "$GITHUB_WORKSPACE"/bin/test/* "$PARSERS_DIR"/bin/test/*
do do
if [[ "$file" == *"rule_utils-test" ]] if [[ "$file" == *"rule_utils-test" ]]
then then
......
...@@ -15,6 +15,7 @@ ENDIF() ...@@ -15,6 +15,7 @@ ENDIF()
link_directories($ENV{LD_LIBRARY_PATH}) link_directories($ENV{LD_LIBRARY_PATH})
set(CMAKE_INSTALL_PREFIX ${PROJECT_SOURCE_DIR}) set(CMAKE_INSTALL_PREFIX ${PROJECT_SOURCE_DIR})
set(INCLUDE_DIR ${PROJECT_SOURCE_DIR}/include) 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(BIN_DIR ${PROJECT_SOURCE_DIR}/bin)
set(LIB_DIR ${PROJECT_SOURCE_DIR}/lib) set(LIB_DIR ${PROJECT_SOURCE_DIR}/lib)
set(EXECUTABLE_OUTPUT_PATH ${BIN_DIR}) set(EXECUTABLE_OUTPUT_PATH ${BIN_DIR})
...@@ -39,4 +40,4 @@ add_subdirectory(src) ...@@ -39,4 +40,4 @@ add_subdirectory(src)
IF( NOT OPENWRT_CROSSCOMPILING ) IF( NOT OPENWRT_CROSSCOMPILING )
add_subdirectory(test) add_subdirectory(test)
ENDIF() ENDIF()
add_subdirectory(devices) #add_subdirectory(devices)
# Minimum required CMake version # Minimum required CMake version
cmake_minimum_required(VERSION 3.20) cmake_minimum_required(VERSION 3.20)
# Build libraries ## Build instructions
# hashmap # Protocol parsers libs
add_library(hashmap STATIC ${HASHMAP_DIR}/hashmap.h ${HASHMAP_DIR}/hashmap.c) add_subdirectory(parsers)
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})
# rule_utils # rule_utils lib
add_library(rule_utils STATIC ${INCLUDE_DIR}/rule_utils.h rule_utils.c) add_library(rule_utils STATIC ${INCLUDE_DIR}/rule_utils.h rule_utils.c)
target_link_libraries(rule_utils nftables nftnl nfnetlink mnl jansson) target_link_libraries(rule_utils nftables nftnl nfnetlink mnl jansson)
target_include_directories(rule_utils PRIVATE ${INCLUDE_DIR}) target_include_directories(rule_utils PRIVATE ${INCLUDE_DIR})
install(TARGETS rule_utils DESTINATION ${LIB_DIR}) install(TARGETS rule_utils DESTINATION ${LIB_DIR})
# nfqueue # nfqueue lib
add_library(nfqueue STATIC ${INCLUDE_DIR}/nfqueue.h nfqueue.c) add_library(nfqueue STATIC ${INCLUDE_DIR}/nfqueue.h nfqueue.c)
target_link_libraries(nfqueue netfilter_queue) target_link_libraries(nfqueue netfilter_queue)
target_link_libraries(nfqueue packet_utils) 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}) install(TARGETS nfqueue DESTINATION ${LIB_DIR})
# nflog executable # nflog executable
add_executable(nflog nflog.c) add_executable(nflog nflog.c)
target_link_libraries(nflog nfnetlink mnl netfilter_log pthread) target_link_libraries(nflog nfnetlink mnl netfilter_log pthread)
target_link_libraries(nflog packet_utils) 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}) install(TARGETS nflog DESTINATION ${BIN_DIR})
# Build parsers
add_subdirectory(parsers)
Subproject commit 3e063aee14cbb8dd4317872a70cd865f3732f737 Subproject commit 82189ca816108a170ab1641f24d272e108b51e3d
Subproject commit c8a7af9717f4e5696db65eecf02f999e723e1c25 Subproject commit d1b4408fbb16d88b7ddfbd48d336f56a2b403cc7
...@@ -11,5 +11,5 @@ target_link_libraries({{device}} jansson mnl nfnetlink nftnl nftables netfilter_ ...@@ -11,5 +11,5 @@ target_link_libraries({{device}} jansson mnl nfnetlink nftnl nftables netfilter_
ENDIF() ENDIF()
target_link_libraries({{device}} nfqueue packet_utils rule_utils) target_link_libraries({{device}} nfqueue packet_utils rule_utils)
target_link_libraries({{device}} ${PARSERS}) 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}) install(TARGETS {{device}} DESTINATION ${EXECUTABLE_OUTPUT_PATH})
...@@ -19,12 +19,12 @@ ...@@ -19,12 +19,12 @@
#include "packet_utils.h" #include "packet_utils.h"
#include "rule_utils.h" #include "rule_utils.h"
// Parsers // Parsers
#include "parsers/header.h" #include "header.h"
{% for parser in custom_parsers %} {% for parser in custom_parsers %}
{% if "dns" in parser %} {% if "dns" in parser %}
#include "parsers/dns.h" #include "dns.h"
{% else %} {% else %}
#include "parsers/{{parser}}.h" #include "{{parser}}.h"
{% endif %} {% endif %}
{% endfor %} {% endfor %}
......
...@@ -5,21 +5,7 @@ cmake_minimum_required(VERSION 3.20) ...@@ -5,21 +5,7 @@ cmake_minimum_required(VERSION 3.20)
set(TEST_BIN_DIR ${BIN_DIR}/test) set(TEST_BIN_DIR ${BIN_DIR}/test)
set(EXECUTABLE_OUTPUT_PATH ${TEST_BIN_DIR}) set(EXECUTABLE_OUTPUT_PATH ${TEST_BIN_DIR})
# Packet utils test ## Build unit tests
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})
# Rule utilitairies test # Rule utilitairies test
add_executable(rule_utils-test rule_utils.c) add_executable(rule_utils-test rule_utils.c)
...@@ -27,6 +13,3 @@ target_include_directories(rule_utils-test PRIVATE ${INCLUDE_DIR}) ...@@ -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 cunit)
target_link_libraries(rule_utils-test rule_utils) target_link_libraries(rule_utils-test rule_utils)
install(TARGETS rule_utils-test DESTINATION ${TEST_BIN_DIR}) install(TARGETS rule_utils-test DESTINATION ${TEST_BIN_DIR})
# Test subdirectories
add_subdirectory(parsers)
/**
* @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;
}
/**
* @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;
}
# 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})
/**
* @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;
}
/**
* @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;
}
/**
* @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;
}
/**
* @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;
}
/**
* @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;
}
/**
* @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;
}
/**
* @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;
}
0% Chargement en cours ou .
You are about to add 0 people to the discussion. Proceed with caution.
Terminez d'abord l'édition de ce message.
Veuillez vous inscrire ou vous pour commenter