Skip to content

Commit

Permalink
[NOTICE: this commit is *EXPERIMENTAL* and implements *very* early da…
Browse files Browse the repository at this point in the history
…ta support, it is expected to be buggy, incomplete or broken] implement VTUN interface (fne0) on the dvmfne (this requires dvmfne to be run as root on Linux system [untested on non-Linux] to create the tun interface); implement VIFace random MAC generation; implement P25 TIA-102.BAEB SCEP ARP (SCEP is always used for conventional data) on dvmfne; refactor P25 packet status bits (this may break things else where, beware!); properly implement P25 status bit flipping on inbound channel activity; implement functionality in the P25 and DMR DataHeader classes to calculate the proper raw PDU frame length; implement dvmfne ARP table creation and maintainence (this is buggy and requires more implementation and test); implement dvmfne VTUN -> PDU and PDU -> VTUN IP traffic forwarding (this is incomplete and requires more implementation and test); correct several issues on dvmhost p25::packet::Data with overlapped buffers;
  • Loading branch information
gatekeep committed Jul 13, 2024
1 parent ac64946 commit da2f613
Show file tree
Hide file tree
Showing 24 changed files with 951 additions and 141 deletions.
21 changes: 20 additions & 1 deletion configs/fne-config.example.yml
Original file line number Diff line number Diff line change
Expand Up @@ -225,4 +225,23 @@ system:
# Full path to the white/blacklist file.
file: peer_list.dat
# Amount of time between updates of white/blacklist file. (minutes)
time: 2
time: 2

#
# Packet Data Virtual Network Tunnel Configuration
#
vtun:
# Flag indicating the virtual network tunnel is enabled.
# (If this is enabled, dvmfne must be run as root to create the TUN interface.)
enabled: false
# Operational mode for the network tunnel (dmr or p25).
digitalMode: p25

# Kernel Interface Name
interfaceName: fne0
# IP address of the tunnel network interface
address: 192.168.1.254
# Netmask of the tunnel network interface
netmask: 255.255.255.0
# Broadcast address of the tunnel network interface
broadcast: 192.168.1.255
16 changes: 16 additions & 0 deletions src/common/dmr/data/DataHeader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -418,6 +418,22 @@ uint32_t DataHeader::getPacketLength() const
}
}

/* Gets the total length in bytes of entire PDU. */

uint32_t DataHeader::getPDULength() const
{
if (m_DPF == DPF::RESPONSE) {
return 0U; // responses have no packet length as they are header only
}

if (m_DPF == DPF::CONFIRMED_DATA) {
return DMR_PDU_CONFIRMED_DATA_LENGTH_BYTES * m_blocksToFollow;
}
else {
return DMR_PDU_UNCONFIRMED_LENGTH_BYTES * m_blocksToFollow;
}
}

/* Gets the raw header data. */

uint32_t DataHeader::getData(uint8_t* buffer) const
Expand Down
5 changes: 5 additions & 0 deletions src/common/dmr/data/DataHeader.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,11 @@ namespace dmr
* @returns uint32_t Total length of packet in bytes.
*/
uint32_t getPacketLength() const;
/**
* @brief Gets the total length in bytes of entire PDU.
* @returns uint32_t Total length of PDU in bytes.
*/
uint32_t getPDULength() const;

/**
* @brief Gets the raw header data.
Expand Down
29 changes: 27 additions & 2 deletions src/common/network/viface/VIFace.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ using namespace network::viface;
#include <sstream>
#include <fstream>
#include <iomanip>
#include <random>

#include <cassert>
#include <cstring>
Expand Down Expand Up @@ -332,7 +333,7 @@ VIFace::VIFace(std::string name, bool tap, int id) :
throw std::runtime_error("Unable to create IPv4 socket channel to the NET kernel.");
}

// Set id
// set id
if (id < 0) {
m_id = m_idSeq;
m_idSeq++;
Expand Down Expand Up @@ -543,6 +544,30 @@ bool VIFace::write(const uint8_t* buffer, uint32_t length, ssize_t* lenWritten)
return result;
}

/* Set the MAC address of the virtual interface to a random value. */

void VIFace::setRandomMAC()
{
// generate random MAC
std::random_device rd;
std::mt19937 mt(rd());

std::ostringstream addr;
addr << std::hex << std::setfill('0');
for (int i = 0; i < 6; i++) {
uint8_t macByte = 0U;
std::uniform_int_distribution<uint8_t> dist(1U, 254U);
macByte = dist(mt);

addr << std::setw(2) << (uint8_t)(0xFFU & macByte);
if (i != 5) {
addr << ":";
}
}

m_mac = addr.str();
}

/* Set the MAC address of the virtual interface. */

void VIFace::setMAC(std::string mac)
Expand All @@ -567,7 +592,7 @@ std::string VIFace::getMAC() const
std::ostringstream addr;
addr << std::hex << std::setfill('0');
for (int i = 0; i < 6; i++) {
addr << std::setw(2) << (uint8_t)(0xFF & ifr.ifr_hwaddr.sa_data[i]);
addr << std::setw(2) << (uint8_t)(0xFFU & ifr.ifr_hwaddr.sa_data[i]);
if (i != 5) {
addr << ":";
}
Expand Down
4 changes: 4 additions & 0 deletions src/common/network/viface/VIFace.h
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,10 @@ namespace network
*/
bool write(const uint8_t* buffer, uint32_t length, ssize_t* lenWritten = nullptr);

/**
* @brief Set the MAC address of the virtual interface to a random value.
*/
void setRandomMAC();
/**
* @brief Set the MAC address of the virtual interface.
*
Expand Down
7 changes: 7 additions & 0 deletions src/common/p25/P25Defines.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,10 @@ namespace p25
const uint32_t P25_PDU_CONFIRMED_DATA_LENGTH_BYTES = 16U;
const uint32_t P25_PDU_UNCONFIRMED_LENGTH_BYTES = 12U;

const uint32_t P25_PDU_ARP_PCKT_LENGTH = 22U;
const uint8_t P25_PDU_ARP_HW_ADDR_LENGTH = 3U;
const uint8_t P25_PDU_ARP_PROTO_ADDR_LENGTH = 4U;

const uint32_t P25_PDU_FEC_LENGTH_BYTES = 25U;
const uint32_t P25_PDU_FEC_LENGTH_BITS = P25_PDU_FEC_LENGTH_BYTES * 8U - 4U; // Trellis is actually 196 bits

Expand Down Expand Up @@ -169,6 +173,9 @@ namespace p25
/** @brief All-call Talkgroup ID */
const uint32_t TGID_ALL = 0xFFFFU;

/** @brief ARP Hardware Type */
const uint16_t P25_PDU_ARP_CAI_TYPE = 0x21U;

/** @brief ARP Request */
const uint8_t P25_PDU_ARP_REQUEST = 0x01U;
/** @brief ARP Reply */
Expand Down
45 changes: 34 additions & 11 deletions src/common/p25/P25Utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,47 +21,70 @@ using namespace p25::defines;
// Static Class Members
// ---------------------------------------------------------------------------

/* Helper to set the busy status bits on P25 frame data. */
/* Helper to set the status bits on P25 frame data. */

void P25Utils::setBusyBits(uint8_t* data, uint32_t ssOffset, bool b1, bool b2)
void P25Utils::setStatusBits(uint8_t* data, uint32_t ssOffset, bool b1, bool b2)
{
assert(data != nullptr);

WRITE_BIT(data, ssOffset, b1);
WRITE_BIT(data, ssOffset + 1U, b2);
}

/* Helper to add the busy status bits on P25 frame data. */
/* Helper to add the status bits on P25 frame data. */

void P25Utils::addBusyBits(uint8_t* data, uint32_t length, bool b1, bool b2)
void P25Utils::addStatusBits(uint8_t* data, uint32_t length, bool inbound, bool control)
{
assert(data != nullptr);

// insert the "10" (Unknown, use for inbound or outbound) status bits
for (uint32_t ss0Pos = P25_SS0_START; ss0Pos < length; ss0Pos += P25_SS_INCREMENT) {
uint32_t ss1Pos = ss0Pos + 1U;
WRITE_BIT(data, ss0Pos, true); // 1
WRITE_BIT(data, ss1Pos, false); // 0
WRITE_BIT(data, ss0Pos, true); // 1
WRITE_BIT(data, ss1Pos, false); // 0
}

// interleave the requested status bits (every other)
for (uint32_t ss0Pos = P25_SS0_START; ss0Pos < length; ss0Pos += (P25_SS_INCREMENT * 2U)) {
uint32_t ss1Pos = ss0Pos + 1U;
WRITE_BIT(data, ss0Pos, b1);
WRITE_BIT(data, ss1Pos, b2);
if (inbound) {
WRITE_BIT(data, ss0Pos, false); // 0
WRITE_BIT(data, ss1Pos, true); // 1
} else {
if (control) {
WRITE_BIT(data, ss0Pos, true); // 1
WRITE_BIT(data, ss1Pos, false); // 0
} else {
WRITE_BIT(data, ss0Pos, true); // 1
WRITE_BIT(data, ss1Pos, true); // 1
}
}
}
}

/* Helper to add the idle status bits on P25 frame data. */

void P25Utils::addIdleBits(uint8_t* data, uint32_t length, bool b1, bool b2)
void P25Utils::addIdleStatusBits(uint8_t* data, uint32_t length)
{
assert(data != nullptr);

for (uint32_t ss0Pos = P25_SS0_START; ss0Pos < length; ss0Pos += (P25_SS_INCREMENT * 5U)) {
uint32_t ss1Pos = ss0Pos + 1U;
WRITE_BIT(data, ss0Pos, true); // 1
WRITE_BIT(data, ss1Pos, false); // 0
}
}

/* Helper to add the trunk start slot status bits on P25 frame data. */

void P25Utils::addTrunkSlotStatusBits(uint8_t* data, uint32_t length)
{
assert(data != nullptr);

for (uint32_t ss0Pos = P25_SS0_START; ss0Pos < length; ss0Pos += (P25_SS_INCREMENT * 5U)) {
uint32_t ss1Pos = ss0Pos + 1U;
WRITE_BIT(data, ss0Pos, b1);
WRITE_BIT(data, ss1Pos, b2);
WRITE_BIT(data, ss0Pos, true); // 1
WRITE_BIT(data, ss1Pos, true); // 1
}
}

Expand Down
26 changes: 17 additions & 9 deletions src/common/p25/P25Utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -118,29 +118,37 @@ namespace p25
}

/**
* @brief Helper to set the busy status bits on P25 frame data.
* @brief Helper to set the status bits on P25 frame data.
* @param data P25 frame data buffer.
* @param ssOffset
* @param b1 Status Bit 1
* @param b2 Status Bit 2
*/
static void setBusyBits(uint8_t* data, uint32_t ssOffset, bool b1, bool b2);
static void setStatusBits(uint8_t* data, uint32_t ssOffset, bool b1, bool b2);
/**
* @brief Helper to add the busy status bits on P25 frame data.
* @brief Helper to add the status bits on P25 frame data.
* This appropriately sets the status bits for the P25 frame, starting with 1,0 and then
* properly setting 0,1 for inbound traffic, or 1,1 for idle (or 1,0 for control channels).
* @param data P25 frame data buffer.
* @param length
* @param b1 Status Bit 1
* @param b2 Status Bit 2
* @param inbound Flag indicating inbound channel is busy.
* @param control Flag indicating the channel is a control channel.
*/
static void addBusyBits(uint8_t* data, uint32_t length, bool b1, bool b2);
static void addStatusBits(uint8_t *data, uint32_t length, bool inbound, bool control = false);
/**
* @brief Helper to add the idle status bits on P25 frame data.
* This sets the status bits to 1,0 interleaved every 5th status bit pair.
* @param data P25 frame data buffer.
* @param length
*/
static void addIdleStatusBits(uint8_t* data, uint32_t length);
/**
* @brief Helper to add the trunk start slot status bits on P25 frame data.
* This sets the status bits to 1,1 interleaved every 5th status bit pair.
* @param data P25 frame data buffer.
* @param length
* @param b1 Status Bit 1
* @param b2 Status Bit 2
*/
static void addIdleBits(uint8_t* data, uint32_t length, bool b1, bool b2);
static void addTrunkSlotStatusBits(uint8_t* data, uint32_t length);

/**
* @brief Decode bit interleaving.
Expand Down
24 changes: 24 additions & 0 deletions src/common/p25/data/DataHeader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -430,6 +430,22 @@ uint32_t DataHeader::getPacketLength() const
}
}

/* Gets the total length in bytes of entire PDU. */

uint32_t DataHeader::getPDULength() const
{
if (m_fmt == PDUFormatType::RSP) {
return 0U; // responses have no packet length as they are header only
}

if (m_fmt == PDUFormatType::CONFIRMED) {
return P25_PDU_CONFIRMED_DATA_LENGTH_BYTES * m_blocksToFollow;
}
else {
return P25_PDU_UNCONFIRMED_LENGTH_BYTES * m_blocksToFollow;
}
}

/* Gets the raw header data. */

uint32_t DataHeader::getData(uint8_t* buffer) const
Expand Down Expand Up @@ -457,6 +473,14 @@ uint32_t DataHeader::getExtAddrData(uint8_t* buffer) const
void DataHeader::calculateLength(uint32_t packetLength)
{
uint32_t len = packetLength + 4U; // packet length + CRC32
if (m_fmt == PDUFormatType::UNCONFIRMED && m_sap == PDUSAP::EXT_ADDR) {
len += P25_PDU_HEADER_LENGTH_BYTES;
}

if (m_fmt == PDUFormatType::CONFIRMED && m_sap == PDUSAP::EXT_ADDR) {
len += 4U;
}

uint32_t blockLen = (m_fmt == PDUFormatType::CONFIRMED) ? P25_PDU_CONFIRMED_DATA_LENGTH_BYTES : P25_PDU_UNCONFIRMED_LENGTH_BYTES;

if (len > blockLen) {
Expand Down
5 changes: 5 additions & 0 deletions src/common/p25/data/DataHeader.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,11 @@ namespace p25
* @returns uint32_t Total length of packet in bytes.
*/
uint32_t getPacketLength() const;
/**
* @brief Gets the total length in bytes of entire PDU.
* @returns uint32_t Total length of PDU in bytes.
*/
uint32_t getPDULength() const;

/**
* @brief Gets the raw header data.
Expand Down
Loading

0 comments on commit da2f613

Please sign in to comment.