|
|
|
|
@ -10,17 +10,49 @@
|
|
|
|
|
#include "host/Defines.h"
|
|
|
|
|
#include "common/p25/P25Defines.h"
|
|
|
|
|
#include "common/p25/kmm/KMMFactory.h"
|
|
|
|
|
#include "common/p25/kmm/KMMDeregistrationCommand.h"
|
|
|
|
|
#include "common/p25/kmm/KMMDeregistrationResponse.h"
|
|
|
|
|
#include "common/p25/kmm/KMMHello.h"
|
|
|
|
|
#include "common/p25/kmm/KMMNoService.h"
|
|
|
|
|
#include "fne/FNETestHooks.h"
|
|
|
|
|
#include "fne/HostFNE.h"
|
|
|
|
|
|
|
|
|
|
#include <catch2/catch_test_macros.hpp>
|
|
|
|
|
|
|
|
|
|
#include <cstring>
|
|
|
|
|
#include <vector>
|
|
|
|
|
|
|
|
|
|
using namespace p25;
|
|
|
|
|
using namespace p25::defines;
|
|
|
|
|
using namespace p25::kmm;
|
|
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
|
|
|
|
|
class KMMFNEHarness {
|
|
|
|
|
public:
|
|
|
|
|
KMMFNEHarness() :
|
|
|
|
|
host("fne-kmm-test.yml"),
|
|
|
|
|
traffic(&host, "127.0.0.1", 62031U, 999999U, "test-password", "test-fne",
|
|
|
|
|
false, false, false, false, true, true, true, true, true,
|
|
|
|
|
0U, false, true, true, 5U, 10U, 2U)
|
|
|
|
|
{
|
|
|
|
|
/* stub */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
HostFNE host;
|
|
|
|
|
network::TrafficNetwork traffic;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
|
std::vector<uint8_t> encodeKMM(T& frame)
|
|
|
|
|
{
|
|
|
|
|
std::vector<uint8_t> bytes(frame.fullLength(), 0U);
|
|
|
|
|
frame.encode(bytes.data());
|
|
|
|
|
return bytes;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} // namespace
|
|
|
|
|
|
|
|
|
|
TEST_CASE("KMM factory decodes encoded HELLO and NO_SERVICE frames", "[p25][kmm][factory]")
|
|
|
|
|
{
|
|
|
|
|
SECTION("HELLO frame round-trips with message number") {
|
|
|
|
|
@ -74,3 +106,83 @@ TEST_CASE("KMM factory decodes encoded HELLO and NO_SERVICE frames", "[p25][kmm]
|
|
|
|
|
REQUIRE(frame == nullptr);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_CASE("FNE OTAR dispatcher follows AACA response-kind procedures", "[p25][kmm][otar]")
|
|
|
|
|
{
|
|
|
|
|
KMMFNEHarness harness;
|
|
|
|
|
constexpr uint32_t SU_RSI = 0x654321U;
|
|
|
|
|
constexpr uint32_t KMF_RSI = 0x123456U;
|
|
|
|
|
|
|
|
|
|
SECTION("Response Kind 1 Hello produces no OTAR response") {
|
|
|
|
|
KMMHello request;
|
|
|
|
|
request.setDstLLId(KMF_RSI);
|
|
|
|
|
request.setSrcLLId(SU_RSI);
|
|
|
|
|
request.setResponseKind(KMM_ResponseKind::NONE);
|
|
|
|
|
|
|
|
|
|
uint32_t payloadSize = 99U;
|
|
|
|
|
UInt8Array response = FNETestHooks::processOTARKMM(harness.traffic,
|
|
|
|
|
encodeKMM(request), SU_RSI, payloadSize);
|
|
|
|
|
|
|
|
|
|
REQUIRE(response == nullptr);
|
|
|
|
|
REQUIRE(payloadSize == 0U);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SECTION("SU-originated Response Kind 2 Hello is discarded") {
|
|
|
|
|
KMMHello request;
|
|
|
|
|
request.setDstLLId(KMF_RSI);
|
|
|
|
|
request.setSrcLLId(SU_RSI);
|
|
|
|
|
request.setResponseKind(KMM_ResponseKind::DELAYED);
|
|
|
|
|
|
|
|
|
|
uint32_t payloadSize = 99U;
|
|
|
|
|
UInt8Array response = FNETestHooks::processOTARKMM(harness.traffic,
|
|
|
|
|
encodeKMM(request), SU_RSI, payloadSize);
|
|
|
|
|
|
|
|
|
|
REQUIRE(response == nullptr);
|
|
|
|
|
REQUIRE(payloadSize == 0U);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SECTION("Response Kind 3 Hello receives No-Service when KMF service is disabled") {
|
|
|
|
|
KMMHello request;
|
|
|
|
|
request.setDstLLId(KMF_RSI);
|
|
|
|
|
request.setSrcLLId(SU_RSI);
|
|
|
|
|
request.setResponseKind(KMM_ResponseKind::IMMEDIATE);
|
|
|
|
|
request.setFlag(KMM_HelloFlag::REKEY_REQUEST_UKEK);
|
|
|
|
|
|
|
|
|
|
uint32_t payloadSize = 0U;
|
|
|
|
|
UInt8Array response = FNETestHooks::processOTARKMM(harness.traffic,
|
|
|
|
|
encodeKMM(request), SU_RSI, payloadSize);
|
|
|
|
|
|
|
|
|
|
REQUIRE(response != nullptr);
|
|
|
|
|
REQUIRE(payloadSize == KMMNoService().fullLength());
|
|
|
|
|
std::unique_ptr<KMMFrame> decoded = KMMFactory::create(response.get());
|
|
|
|
|
REQUIRE(decoded != nullptr);
|
|
|
|
|
REQUIRE(decoded->getMessageId() == KMM_MessageType::NO_SERVICE);
|
|
|
|
|
REQUIRE(decoded->getResponseKind() == KMM_ResponseKind::NONE);
|
|
|
|
|
REQUIRE(decoded->getDstLLId() == SU_RSI);
|
|
|
|
|
REQUIRE(decoded->getSrcLLId() == WUID_FNE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SECTION("Response Kind 3 Deregistration receives Deregistration-Response") {
|
|
|
|
|
FNETestHooks::setKMFServicesEnabled(harness.traffic, true);
|
|
|
|
|
|
|
|
|
|
KMMDeregistrationCommand request;
|
|
|
|
|
request.setDstLLId(KMF_RSI);
|
|
|
|
|
request.setSrcLLId(SU_RSI);
|
|
|
|
|
request.setResponseKind(KMM_ResponseKind::IMMEDIATE);
|
|
|
|
|
request.setKMFRSI(KMF_RSI);
|
|
|
|
|
|
|
|
|
|
uint32_t payloadSize = 0U;
|
|
|
|
|
UInt8Array response = FNETestHooks::processOTARKMM(harness.traffic,
|
|
|
|
|
encodeKMM(request), SU_RSI, payloadSize);
|
|
|
|
|
|
|
|
|
|
REQUIRE(response != nullptr);
|
|
|
|
|
KMMDeregistrationResponse expected;
|
|
|
|
|
REQUIRE(payloadSize == expected.fullLength());
|
|
|
|
|
std::unique_ptr<KMMFrame> decoded = KMMFactory::create(response.get());
|
|
|
|
|
REQUIRE(decoded != nullptr);
|
|
|
|
|
REQUIRE(decoded->getMessageId() == KMM_MessageType::DEREG_RSP);
|
|
|
|
|
REQUIRE(decoded->getResponseKind() == KMM_ResponseKind::NONE);
|
|
|
|
|
REQUIRE(decoded->getDstLLId() == SU_RSI);
|
|
|
|
|
REQUIRE(decoded->getSrcLLId() == WUID_FNE);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|