Merge branch 'develop' into XEdDSA

This commit is contained in:
Jonathan Bennett
2025-12-01 15:07:32 -06:00
committed by GitHub
499 changed files with 49852 additions and 14356 deletions

View File

@@ -104,6 +104,19 @@ bool AdminModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshta
(config.security.admin_key[2].size == 32 &&
memcmp(mp.public_key.bytes, config.security.admin_key[2].bytes, 32) == 0)) {
LOG_INFO("PKC admin payload with authorized sender key");
// Automatically favorite the node that is using the admin key
auto remoteNode = nodeDB->getMeshNode(mp.from);
if (remoteNode && !remoteNode->is_favorite) {
if (config.device.role == meshtastic_Config_DeviceConfig_Role_CLIENT_BASE) {
// Special case for CLIENT_BASE: is_favorite has special meaning, and we don't want to automatically set it
// without the user doing so deliberately.
LOG_INFO("PKC admin valid, but not auto-favoriting node %x because role==CLIENT_BASE", mp.from);
} else {
LOG_INFO("PKC admin valid. Auto-favoriting node %x", mp.from);
remoteNode->is_favorite = true;
}
}
} else {
myReply = allocErrorResponse(meshtastic_Routing_Error_ADMIN_PUBLIC_KEY_UNAUTHORIZED, &mp);
LOG_INFO("Received PKC admin payload, but the sender public key does not match the admin authorized key!");
@@ -276,7 +289,12 @@ bool AdminModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshta
case meshtastic_AdminMessage_nodedb_reset_tag: {
disableBluetooth();
LOG_INFO("Initiate node-db reset");
nodeDB->resetNodes();
// CLIENT_BASE, ROUTER and ROUTER_LATE are able to preserve the remaining hop count when relaying a packet via a
// favorited node, so ensure that their favorites are kept on reset
bool rolePreference =
isOneOf(config.device.role, meshtastic_Config_DeviceConfig_Role_CLIENT_BASE,
meshtastic_Config_DeviceConfig_Role_ROUTER, meshtastic_Config_DeviceConfig_Role_ROUTER_LATE);
nodeDB->resetNodes(rolePreference ? rolePreference : r->nodedb_reset);
reboot(DEFAULT_REBOOT_SECONDS);
break;
}
@@ -505,7 +523,7 @@ bool AdminModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshta
if (mp.decoded.want_response && !myReply) {
myReply = allocErrorResponse(meshtastic_Routing_Error_NONE, &mp);
}
if (mp.pki_encrypted) {
if (mp.pki_encrypted && myReply) {
myReply->pki_encrypted = true;
}
return handled;
@@ -550,10 +568,8 @@ void AdminModule::handleSetOwner(const meshtastic_User &o)
changed |= strcmp(owner.short_name, o.short_name);
strncpy(owner.short_name, o.short_name, sizeof(owner.short_name));
}
if (*o.id) {
changed |= strcmp(owner.id, o.id);
strncpy(owner.id, o.id, sizeof(owner.id));
}
snprintf(owner.id, sizeof(owner.id), "!%08x", nodeDB->getNodeNum());
if (owner.is_licensed != o.is_licensed) {
changed = 1;
owner.is_licensed = o.is_licensed;
@@ -607,10 +623,9 @@ void AdminModule::handleSetConfig(const meshtastic_Config &c)
}
config.device = c.payload_variant.device;
if (config.device.rebroadcast_mode == meshtastic_Config_DeviceConfig_RebroadcastMode_NONE &&
IS_ONE_OF(config.device.role, meshtastic_Config_DeviceConfig_Role_ROUTER,
meshtastic_Config_DeviceConfig_Role_REPEATER)) {
config.device.role == meshtastic_Config_DeviceConfig_Role_ROUTER) {
config.device.rebroadcast_mode = meshtastic_Config_DeviceConfig_RebroadcastMode_ALL;
const char *warning = "Rebroadcast mode can't be set to NONE for a router or repeater";
const char *warning = "Rebroadcast mode can't be set to NONE for a router";
LOG_WARN(warning);
sendWarning(warning);
}
@@ -623,8 +638,9 @@ void AdminModule::handleSetConfig(const meshtastic_Config &c)
LOG_DEBUG("Tried to set node_info_broadcast_secs too low, setting to %d", min_node_info_broadcast_secs);
config.device.node_info_broadcast_secs = min_node_info_broadcast_secs;
}
// Router Client is deprecated; Set it to client
if (c.payload_variant.device.role == meshtastic_Config_DeviceConfig_Role_ROUTER_CLIENT) {
// Router Client and Repeater deprecated; Set it to client
if (IS_ONE_OF(c.payload_variant.device.role, meshtastic_Config_DeviceConfig_Role_ROUTER_CLIENT,
meshtastic_Config_DeviceConfig_Role_REPEATER)) {
config.device.role = meshtastic_Config_DeviceConfig_Role_CLIENT;
if (moduleConfig.store_forward.enabled && !moduleConfig.store_forward.is_server) {
moduleConfig.store_forward.is_server = true;
@@ -633,10 +649,9 @@ void AdminModule::handleSetConfig(const meshtastic_Config &c)
}
}
#if USERPREFS_EVENT_MODE
// If we're in event mode, nobody is a Router or Repeater
// If we're in event mode, nobody is a Router or Router Late
if (config.device.role == meshtastic_Config_DeviceConfig_Role_ROUTER ||
config.device.role == meshtastic_Config_DeviceConfig_Role_ROUTER_LATE ||
config.device.role == meshtastic_Config_DeviceConfig_Role_REPEATER) {
config.device.role == meshtastic_Config_DeviceConfig_Role_ROUTER_LATE) {
config.device.role = meshtastic_Config_DeviceConfig_Role_CLIENT;
}
#endif
@@ -703,20 +718,40 @@ void AdminModule::handleSetConfig(const meshtastic_Config &c)
#endif
config.display = c.payload_variant.display;
break;
case meshtastic_Config_lora_tag:
case meshtastic_Config_lora_tag: {
// Wrap the entire case in a block to scope variables and avoid crossing initialization
auto oldLoraConfig = config.lora;
auto validatedLora = c.payload_variant.lora;
LOG_INFO("Set config: LoRa");
config.has_lora = true;
if (validatedLora.coding_rate < 4 || validatedLora.coding_rate > 8) {
LOG_WARN("Invalid coding_rate %d, setting to 5", validatedLora.coding_rate);
validatedLora.coding_rate = 5;
}
if (validatedLora.spread_factor < 7 || validatedLora.spread_factor > 12) {
LOG_WARN("Invalid spread_factor %d, setting to 11", validatedLora.spread_factor);
validatedLora.spread_factor = 11;
}
if (validatedLora.bandwidth == 0) {
int originalBandwidth = validatedLora.bandwidth;
validatedLora.bandwidth = myRegion->wideLora ? 800 : 250;
LOG_WARN("Invalid bandwidth %d, setting to default", originalBandwidth);
}
// If no lora radio parameters change, don't need to reboot
if (config.lora.use_preset == c.payload_variant.lora.use_preset && config.lora.region == c.payload_variant.lora.region &&
config.lora.modem_preset == c.payload_variant.lora.modem_preset &&
config.lora.bandwidth == c.payload_variant.lora.bandwidth &&
config.lora.spread_factor == c.payload_variant.lora.spread_factor &&
config.lora.coding_rate == c.payload_variant.lora.coding_rate &&
config.lora.tx_power == c.payload_variant.lora.tx_power &&
config.lora.frequency_offset == c.payload_variant.lora.frequency_offset &&
config.lora.override_frequency == c.payload_variant.lora.override_frequency &&
config.lora.channel_num == c.payload_variant.lora.channel_num &&
config.lora.sx126x_rx_boosted_gain == c.payload_variant.lora.sx126x_rx_boosted_gain) {
if (oldLoraConfig.use_preset == validatedLora.use_preset && oldLoraConfig.region == validatedLora.region &&
oldLoraConfig.modem_preset == validatedLora.modem_preset && oldLoraConfig.bandwidth == validatedLora.bandwidth &&
oldLoraConfig.spread_factor == validatedLora.spread_factor &&
oldLoraConfig.coding_rate == validatedLora.coding_rate && oldLoraConfig.tx_power == validatedLora.tx_power &&
oldLoraConfig.frequency_offset == validatedLora.frequency_offset &&
oldLoraConfig.override_frequency == validatedLora.override_frequency &&
oldLoraConfig.channel_num == validatedLora.channel_num &&
oldLoraConfig.sx126x_rx_boosted_gain == validatedLora.sx126x_rx_boosted_gain) {
requiresReboot = false;
}
@@ -735,7 +770,7 @@ void AdminModule::handleSetConfig(const meshtastic_Config &c)
digitalWrite(RF95_FAN_EN, HIGH ^ 0);
}
#endif
config.lora = c.payload_variant.lora;
config.lora = validatedLora;
// If we're setting region for the first time, init the region and regenerate the keys
if (isRegionUnset && config.lora.region > meshtastic_Config_LoRaConfig_RegionCode_UNSET) {
// Use consolidated key generation function
@@ -745,12 +780,26 @@ void AdminModule::handleSetConfig(const meshtastic_Config &c)
if (myRegion->dutyCycle < 100) {
config.lora.ignore_mqtt = true; // Ignore MQTT by default if region has a duty cycle limit
}
// Compare the entire string, we are sure of the length as a topic has never been set
if (strcmp(moduleConfig.mqtt.root, default_mqtt_root) == 0) {
sprintf(moduleConfig.mqtt.root, "%s/%s", default_mqtt_root, myRegion->name);
changes = SEGMENT_CONFIG | SEGMENT_MODULECONFIG | SEGMENT_NODEDATABASE | SEGMENT_DEVICESTATE;
}
}
if (config.lora.region != myRegion->code) {
// Region has changed so check whether there is a regulatory one we should be using instead.
// Additionally as a side-effect, assume a new value under myRegion
initRegion();
if (strncmp(moduleConfig.mqtt.root, default_mqtt_root, strlen(default_mqtt_root)) == 0) {
// Default root is in use, so subscribe to the appropriate MQTT topic for this region
sprintf(moduleConfig.mqtt.root, "%s/%s", default_mqtt_root, myRegion->name);
}
changes = SEGMENT_CONFIG | SEGMENT_MODULECONFIG;
}
break;
}
case meshtastic_Config_bluetooth_tag:
LOG_INFO("Set config: Bluetooth");
config.has_bluetooth = true;