mirror of
https://github.com/alexhopeoconnor/firmware.git
synced 2026-10-14 15:31:31 +10:00
* Block coordinate traffic on configured event channels Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> * Suppress event coordinates in reliable relay paths Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> * Reject blocked phone coordinates before rate limiting Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> * Prevent event coordinates from reaching MQTT Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> * Add event coordinate policy preference Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> * Test event coordinate policy in native CI Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> * Make event policy test tolerate a full NodeDB Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> * Test Router event coordinate enforcement Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> * Test PhoneAPI event coordinate retry handling Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> * Test reliable event coordinate suppression Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> * Test MQTT event coordinate suppression Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> * Run event policy behavioral suites in native CI Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> * tests: address CodeRabbit review feedback - test_event_channel_phone_api: complete the setUp/tearDown save-restore pair. GlobalState now carries cryptLock and myNodeInfo; setUp() nulls cryptLock before constructing MockRouter (Router's ctor asserts it is unset), and tearDown() restores both so the suite leaves no global mutated. Not reachable today - the globals start null in this binary - but the pair was asymmetric. - Replace the strcpy calls this branch added on Channel.settings.name (char[12]) with the bounded form the rest of the test tree already uses, strncpy(dst, src, sizeof(dst) - 1). Covers the flagged site in test_nexthop_routing plus the six equivalents in test_event_channel_phone_api, test_mqtt and test_position_precision, which trip the same ast-grep dangerous-buffer-functions-cpp rule. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> --------- Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> Co-authored-by: Ben Meadors <benmmeadors@gmail.com> Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
99 lines
3.4 KiB
C++
99 lines
3.4 KiB
C++
#include "PositionPrecision.h"
|
|
#include "Channels.h"
|
|
#include "mesh-pb-constants.h"
|
|
|
|
#include <Arduino.h>
|
|
|
|
uint32_t getPositionPrecisionForChannel(const meshtastic_Channel &channel)
|
|
{
|
|
if (channel.settings.has_module_settings) {
|
|
return channel.settings.module_settings.position_precision;
|
|
}
|
|
// No module settings: fail closed. A PRIMARY channel used to default to 32
|
|
// here, leaking an exact position on a sharing-disabled channel. See #10509.
|
|
return 0;
|
|
}
|
|
|
|
uint32_t getPositionPrecisionForChannel(uint8_t channelIndex)
|
|
{
|
|
// Event-channel privacy takes precedence over every stored precision and key policy.
|
|
if (channels.isEventChannel(channelIndex))
|
|
return 0;
|
|
|
|
const meshtastic_Channel &ch = channels.getByIndex(channelIndex);
|
|
if (ch.role == meshtastic_Channel_Role_DISABLED)
|
|
return 0;
|
|
uint32_t precision = getPositionPrecisionForChannel(ch);
|
|
|
|
// Never send a precise position on a publicly-decryptable channel (key check is gated on > ceiling).
|
|
if (precision > MAX_POSITION_PRECISION_PUBLIC_KEY && channels.usesPublicKey(channelIndex)) {
|
|
precision = MAX_POSITION_PRECISION_PUBLIC_KEY;
|
|
}
|
|
return precision;
|
|
}
|
|
|
|
int32_t truncateCoordinate(int32_t coordinate, uint32_t precision)
|
|
{
|
|
if (precision == 0 || precision >= 32)
|
|
return coordinate;
|
|
|
|
uint32_t coordinateBits = static_cast<uint32_t>(coordinate);
|
|
uint32_t truncated = coordinateBits & (UINT32_MAX << (32 - precision));
|
|
|
|
// Use the middle of the possible location, not the low edge of the bucket.
|
|
truncated += (1UL << (31 - precision));
|
|
|
|
return static_cast<int32_t>(truncated);
|
|
}
|
|
|
|
int32_t truncateCoordinate(int32_t coordinate, uint8_t precision)
|
|
{
|
|
return truncateCoordinate(coordinate, static_cast<uint32_t>(precision));
|
|
}
|
|
|
|
void applyPositionPrecision(meshtastic_Position &position, uint32_t precision)
|
|
{
|
|
if (precision == 0) {
|
|
uint32_t time = position.time;
|
|
position = meshtastic_Position_init_default;
|
|
position.time = time;
|
|
return;
|
|
}
|
|
|
|
uint32_t effectivePrecision = precision > 32 ? 32 : precision;
|
|
position.precision_bits = effectivePrecision;
|
|
|
|
if (effectivePrecision < 32) {
|
|
position.latitude_i = truncateCoordinate(position.latitude_i, effectivePrecision);
|
|
position.longitude_i = truncateCoordinate(position.longitude_i, effectivePrecision);
|
|
}
|
|
}
|
|
|
|
bool applyPositionPrecision(meshtastic_MeshPacket &packet, uint32_t precision)
|
|
{
|
|
if (packet.which_payload_variant != meshtastic_MeshPacket_decoded_tag ||
|
|
packet.decoded.portnum != meshtastic_PortNum_POSITION_APP) {
|
|
return true;
|
|
}
|
|
|
|
meshtastic_Position position = meshtastic_Position_init_default;
|
|
if (!pb_decode_from_bytes(packet.decoded.payload.bytes, packet.decoded.payload.size, &meshtastic_Position_msg, &position)) {
|
|
return false;
|
|
}
|
|
|
|
applyPositionPrecision(position, precision);
|
|
packet.decoded.payload.size = pb_encode_to_bytes(packet.decoded.payload.bytes, sizeof(packet.decoded.payload.bytes),
|
|
&meshtastic_Position_msg, &position);
|
|
return true;
|
|
}
|
|
|
|
bool applyPositionPrecisionForChannel(meshtastic_MeshPacket &packet, uint8_t channelIndex)
|
|
{
|
|
if (packet.which_payload_variant != meshtastic_MeshPacket_decoded_tag ||
|
|
packet.decoded.portnum != meshtastic_PortNum_POSITION_APP) {
|
|
return true;
|
|
}
|
|
|
|
return applyPositionPrecision(packet, getPositionPrecisionForChannel(channelIndex));
|
|
}
|