Compare commits

...

7 Commits

Author SHA1 Message Date
Thomas Göttgens
c157839e2b Merge branch 'master' into dont-process-mac-mismatch 2025-08-11 10:48:16 +02:00
Ben Meadors
7505fe7a7c Update device-ui deps 2025-08-09 10:38:09 -05:00
Ben Meadors
f6857f1bcb Heartbeat has a nonce now 2025-08-09 10:17:08 -05:00
github-actions[bot]
7fe2c74139 Update protobufs (#7588)
Co-authored-by: jp-bennett <5630967+jp-bennett@users.noreply.github.com>
2025-08-09 09:14:22 -05:00
github-actions[bot]
be60f9612e Update protobufs (#7587)
Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com>
2025-08-09 08:14:04 -05:00
github-actions[bot]
2de9f015b1 Automated version bumps (#7586)
Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com>
2025-08-09 08:12:24 -05:00
Ben Meadors
960d98484b Ignore NodeInfos from Users with forged MAC addresses 2025-07-14 16:10:55 +02:00
11 changed files with 94 additions and 15 deletions

View File

@@ -87,6 +87,9 @@
</screenshots> </screenshots>
<releases> <releases>
<release version="2.7.5" date="2025-08-09">
<url type="details">https://github.com/meshtastic/firmware/releases?q=tag%3Av2.7.5</url>
</release>
<release version="2.7.4" date="2025-07-19"> <release version="2.7.4" date="2025-07-19">
<url type="details">https://github.com/meshtastic/firmware/releases?q=tag%3Av2.7.4</url> <url type="details">https://github.com/meshtastic/firmware/releases?q=tag%3Av2.7.4</url>
</release> </release>

7
debian/changelog vendored
View File

@@ -1,4 +1,4 @@
meshtasticd (2.7.4.0) UNRELEASED; urgency=medium meshtasticd (2.7.5.0) UNRELEASED; urgency=medium
[ Austin Lane ] [ Austin Lane ]
* Initial packaging * Initial packaging
@@ -34,4 +34,7 @@ meshtasticd (2.7.4.0) UNRELEASED; urgency=medium
[ ] [ ]
* GitHub Actions Automatic version bump * GitHub Actions Automatic version bump
-- <github-actions[bot]@users.noreply.github.com> Sat, 19 Jul 2025 11:36:55 +0000 [ ]
* GitHub Actions Automatic version bump
-- <github-actions[bot]@users.noreply.github.com> Sat, 09 Aug 2025 12:46:53 +0000

View File

@@ -110,7 +110,7 @@ lib_deps =
[device-ui_base] [device-ui_base]
lib_deps = lib_deps =
# renovate: datasource=git-refs depName=meshtastic/device-ui packageName=https://github.com/meshtastic/device-ui gitBranch=master # renovate: datasource=git-refs depName=meshtastic/device-ui packageName=https://github.com/meshtastic/device-ui gitBranch=master
https://github.com/meshtastic/device-ui/archive/d044c01e87583867011991a96f926e4e929d8a93.zip https://github.com/meshtastic/device-ui/archive/0cd108ff783539e41ef38258ba2784ab3b1bdc97.zip
; Common libs for environmental measurements in telemetry module ; Common libs for environmental measurements in telemetry module
[environmental_base] [environmental_base]

View File

@@ -70,7 +70,7 @@ bool PacketAPI::receivePacket(void)
break; break;
} }
case meshtastic_ToRadio_heartbeat_tag: case meshtastic_ToRadio_heartbeat_tag:
if (mr->heartbeat.dummy_field == 1) { if (mr->heartbeat.nonce == 1) {
if (nodeInfoModule) { if (nodeInfoModule) {
LOG_INFO("Broadcasting nodeinfo ping"); LOG_INFO("Broadcasting nodeinfo ping");
nodeInfoModule->sendOurNodeInfo(NODENUM_BROADCAST, true, 0, true); nodeInfoModule->sendOurNodeInfo(NODENUM_BROADCAST, true, 0, true);

View File

@@ -362,7 +362,7 @@ extern const pb_msgdesc_t meshtastic_BackupPreferences_msg;
#define MESHTASTIC_MESHTASTIC_DEVICEONLY_PB_H_MAX_SIZE meshtastic_BackupPreferences_size #define MESHTASTIC_MESHTASTIC_DEVICEONLY_PB_H_MAX_SIZE meshtastic_BackupPreferences_size
#define meshtastic_BackupPreferences_size 2271 #define meshtastic_BackupPreferences_size 2271
#define meshtastic_ChannelFile_size 718 #define meshtastic_ChannelFile_size 718
#define meshtastic_DeviceState_size 1728 #define meshtastic_DeviceState_size 1737
#define meshtastic_NodeInfoLite_size 196 #define meshtastic_NodeInfoLite_size 196
#define meshtastic_PositionLite_size 28 #define meshtastic_PositionLite_size 28
#define meshtastic_UserLite_size 98 #define meshtastic_UserLite_size 98

View File

@@ -119,6 +119,8 @@ PB_BIND(meshtastic_ChunkedPayloadResponse, meshtastic_ChunkedPayloadResponse, AU

View File

@@ -509,6 +509,26 @@ typedef enum _meshtastic_MeshPacket_Delayed {
meshtastic_MeshPacket_Delayed_DELAYED_DIRECT = 2 meshtastic_MeshPacket_Delayed_DELAYED_DIRECT = 2
} meshtastic_MeshPacket_Delayed; } meshtastic_MeshPacket_Delayed;
/* Enum to identify which transport mechanism this packet arrived over */
typedef enum _meshtastic_MeshPacket_TransportMechanism {
/* The default case is that the node generated a packet itself */
meshtastic_MeshPacket_TransportMechanism_TRANSPORT_INTERNAL = 0,
/* Arrived via the primary LoRa radio */
meshtastic_MeshPacket_TransportMechanism_TRANSPORT_LORA = 1,
/* Arrived via a secondary LoRa radio */
meshtastic_MeshPacket_TransportMechanism_TRANSPORT_LORA_ALT1 = 2,
/* Arrived via a tertiary LoRa radio */
meshtastic_MeshPacket_TransportMechanism_TRANSPORT_LORA_ALT2 = 3,
/* Arrived via a quaternary LoRa radio */
meshtastic_MeshPacket_TransportMechanism_TRANSPORT_LORA_ALT3 = 4,
/* Arrived via an MQTT connection */
meshtastic_MeshPacket_TransportMechanism_TRANSPORT_MQTT = 5,
/* Arrived via Multicast UDP */
meshtastic_MeshPacket_TransportMechanism_TRANSPORT_MULTICAST_UDP = 6,
/* Arrived via API connection */
meshtastic_MeshPacket_TransportMechanism_TRANSPORT_API = 7
} meshtastic_MeshPacket_TransportMechanism;
/* Log levels, chosen to match python logging conventions. */ /* Log levels, chosen to match python logging conventions. */
typedef enum _meshtastic_LogRecord_Level { typedef enum _meshtastic_LogRecord_Level {
/* Log levels, chosen to match python logging conventions. */ /* Log levels, chosen to match python logging conventions. */
@@ -863,6 +883,8 @@ typedef struct _meshtastic_MeshPacket {
Timestamp after which this packet may be sent. Timestamp after which this packet may be sent.
Set by the firmware internally, clients are not supposed to set this. */ Set by the firmware internally, clients are not supposed to set this. */
uint32_t tx_after; uint32_t tx_after;
/* Indicates which transport mechanism this packet arrived over */
meshtastic_MeshPacket_TransportMechanism transport_mechanism;
} meshtastic_MeshPacket; } meshtastic_MeshPacket;
/* The bluetooth to device link: /* The bluetooth to device link:
@@ -1149,7 +1171,8 @@ typedef struct _meshtastic_FromRadio {
/* A heartbeat message is sent to the node from the client to keep the connection alive. /* A heartbeat message is sent to the node from the client to keep the connection alive.
This is currently only needed to keep serial connections alive, but can be used by any PhoneAPI. */ This is currently only needed to keep serial connections alive, but can be used by any PhoneAPI. */
typedef struct _meshtastic_Heartbeat { typedef struct _meshtastic_Heartbeat {
char dummy_field; /* The nonce of the heartbeat message */
uint32_t nonce;
} meshtastic_Heartbeat; } meshtastic_Heartbeat;
/* Packets/commands to the radio will be written (reliably) to the toRadio characteristic. /* Packets/commands to the radio will be written (reliably) to the toRadio characteristic.
@@ -1267,6 +1290,10 @@ extern "C" {
#define _meshtastic_MeshPacket_Delayed_MAX meshtastic_MeshPacket_Delayed_DELAYED_DIRECT #define _meshtastic_MeshPacket_Delayed_MAX meshtastic_MeshPacket_Delayed_DELAYED_DIRECT
#define _meshtastic_MeshPacket_Delayed_ARRAYSIZE ((meshtastic_MeshPacket_Delayed)(meshtastic_MeshPacket_Delayed_DELAYED_DIRECT+1)) #define _meshtastic_MeshPacket_Delayed_ARRAYSIZE ((meshtastic_MeshPacket_Delayed)(meshtastic_MeshPacket_Delayed_DELAYED_DIRECT+1))
#define _meshtastic_MeshPacket_TransportMechanism_MIN meshtastic_MeshPacket_TransportMechanism_TRANSPORT_INTERNAL
#define _meshtastic_MeshPacket_TransportMechanism_MAX meshtastic_MeshPacket_TransportMechanism_TRANSPORT_API
#define _meshtastic_MeshPacket_TransportMechanism_ARRAYSIZE ((meshtastic_MeshPacket_TransportMechanism)(meshtastic_MeshPacket_TransportMechanism_TRANSPORT_API+1))
#define _meshtastic_LogRecord_Level_MIN meshtastic_LogRecord_Level_UNSET #define _meshtastic_LogRecord_Level_MIN meshtastic_LogRecord_Level_UNSET
#define _meshtastic_LogRecord_Level_MAX meshtastic_LogRecord_Level_CRITICAL #define _meshtastic_LogRecord_Level_MAX meshtastic_LogRecord_Level_CRITICAL
#define _meshtastic_LogRecord_Level_ARRAYSIZE ((meshtastic_LogRecord_Level)(meshtastic_LogRecord_Level_CRITICAL+1)) #define _meshtastic_LogRecord_Level_ARRAYSIZE ((meshtastic_LogRecord_Level)(meshtastic_LogRecord_Level_CRITICAL+1))
@@ -1287,6 +1314,7 @@ extern "C" {
#define meshtastic_MeshPacket_priority_ENUMTYPE meshtastic_MeshPacket_Priority #define meshtastic_MeshPacket_priority_ENUMTYPE meshtastic_MeshPacket_Priority
#define meshtastic_MeshPacket_delayed_ENUMTYPE meshtastic_MeshPacket_Delayed #define meshtastic_MeshPacket_delayed_ENUMTYPE meshtastic_MeshPacket_Delayed
#define meshtastic_MeshPacket_transport_mechanism_ENUMTYPE meshtastic_MeshPacket_TransportMechanism
#define meshtastic_MyNodeInfo_firmware_edition_ENUMTYPE meshtastic_FirmwareEdition #define meshtastic_MyNodeInfo_firmware_edition_ENUMTYPE meshtastic_FirmwareEdition
@@ -1326,7 +1354,7 @@ extern "C" {
#define meshtastic_KeyVerification_init_default {0, {0, {0}}, {0, {0}}} #define meshtastic_KeyVerification_init_default {0, {0, {0}}, {0, {0}}}
#define meshtastic_Waypoint_init_default {0, false, 0, false, 0, 0, 0, "", "", 0} #define meshtastic_Waypoint_init_default {0, false, 0, false, 0, 0, 0, "", "", 0}
#define meshtastic_MqttClientProxyMessage_init_default {"", 0, {{0, {0}}}, 0} #define meshtastic_MqttClientProxyMessage_init_default {"", 0, {{0, {0}}}, 0}
#define meshtastic_MeshPacket_init_default {0, 0, 0, 0, {meshtastic_Data_init_default}, 0, 0, 0, 0, 0, _meshtastic_MeshPacket_Priority_MIN, 0, _meshtastic_MeshPacket_Delayed_MIN, 0, 0, {0, {0}}, 0, 0, 0, 0} #define meshtastic_MeshPacket_init_default {0, 0, 0, 0, {meshtastic_Data_init_default}, 0, 0, 0, 0, 0, _meshtastic_MeshPacket_Priority_MIN, 0, _meshtastic_MeshPacket_Delayed_MIN, 0, 0, {0, {0}}, 0, 0, 0, 0, _meshtastic_MeshPacket_TransportMechanism_MIN}
#define meshtastic_NodeInfo_init_default {0, false, meshtastic_User_init_default, false, meshtastic_Position_init_default, 0, 0, false, meshtastic_DeviceMetrics_init_default, 0, 0, false, 0, 0, 0, 0} #define meshtastic_NodeInfo_init_default {0, false, meshtastic_User_init_default, false, meshtastic_Position_init_default, 0, 0, false, meshtastic_DeviceMetrics_init_default, 0, 0, false, 0, 0, 0, 0}
#define meshtastic_MyNodeInfo_init_default {0, 0, 0, {0, {0}}, "", _meshtastic_FirmwareEdition_MIN, 0} #define meshtastic_MyNodeInfo_init_default {0, 0, 0, {0, {0}}, "", _meshtastic_FirmwareEdition_MIN, 0}
#define meshtastic_LogRecord_init_default {"", 0, "", _meshtastic_LogRecord_Level_MIN} #define meshtastic_LogRecord_init_default {"", 0, "", _meshtastic_LogRecord_Level_MIN}
@@ -1357,7 +1385,7 @@ extern "C" {
#define meshtastic_KeyVerification_init_zero {0, {0, {0}}, {0, {0}}} #define meshtastic_KeyVerification_init_zero {0, {0, {0}}, {0, {0}}}
#define meshtastic_Waypoint_init_zero {0, false, 0, false, 0, 0, 0, "", "", 0} #define meshtastic_Waypoint_init_zero {0, false, 0, false, 0, 0, 0, "", "", 0}
#define meshtastic_MqttClientProxyMessage_init_zero {"", 0, {{0, {0}}}, 0} #define meshtastic_MqttClientProxyMessage_init_zero {"", 0, {{0, {0}}}, 0}
#define meshtastic_MeshPacket_init_zero {0, 0, 0, 0, {meshtastic_Data_init_zero}, 0, 0, 0, 0, 0, _meshtastic_MeshPacket_Priority_MIN, 0, _meshtastic_MeshPacket_Delayed_MIN, 0, 0, {0, {0}}, 0, 0, 0, 0} #define meshtastic_MeshPacket_init_zero {0, 0, 0, 0, {meshtastic_Data_init_zero}, 0, 0, 0, 0, 0, _meshtastic_MeshPacket_Priority_MIN, 0, _meshtastic_MeshPacket_Delayed_MIN, 0, 0, {0, {0}}, 0, 0, 0, 0, _meshtastic_MeshPacket_TransportMechanism_MIN}
#define meshtastic_NodeInfo_init_zero {0, false, meshtastic_User_init_zero, false, meshtastic_Position_init_zero, 0, 0, false, meshtastic_DeviceMetrics_init_zero, 0, 0, false, 0, 0, 0, 0} #define meshtastic_NodeInfo_init_zero {0, false, meshtastic_User_init_zero, false, meshtastic_Position_init_zero, 0, 0, false, meshtastic_DeviceMetrics_init_zero, 0, 0, false, 0, 0, 0, 0}
#define meshtastic_MyNodeInfo_init_zero {0, 0, 0, {0, {0}}, "", _meshtastic_FirmwareEdition_MIN, 0} #define meshtastic_MyNodeInfo_init_zero {0, 0, 0, {0, {0}}, "", _meshtastic_FirmwareEdition_MIN, 0}
#define meshtastic_LogRecord_init_zero {"", 0, "", _meshtastic_LogRecord_Level_MIN} #define meshtastic_LogRecord_init_zero {"", 0, "", _meshtastic_LogRecord_Level_MIN}
@@ -1465,6 +1493,7 @@ extern "C" {
#define meshtastic_MeshPacket_next_hop_tag 18 #define meshtastic_MeshPacket_next_hop_tag 18
#define meshtastic_MeshPacket_relay_node_tag 19 #define meshtastic_MeshPacket_relay_node_tag 19
#define meshtastic_MeshPacket_tx_after_tag 20 #define meshtastic_MeshPacket_tx_after_tag 20
#define meshtastic_MeshPacket_transport_mechanism_tag 21
#define meshtastic_NodeInfo_num_tag 1 #define meshtastic_NodeInfo_num_tag 1
#define meshtastic_NodeInfo_user_tag 2 #define meshtastic_NodeInfo_user_tag 2
#define meshtastic_NodeInfo_position_tag 3 #define meshtastic_NodeInfo_position_tag 3
@@ -1551,6 +1580,7 @@ extern "C" {
#define meshtastic_FromRadio_fileInfo_tag 15 #define meshtastic_FromRadio_fileInfo_tag 15
#define meshtastic_FromRadio_clientNotification_tag 16 #define meshtastic_FromRadio_clientNotification_tag 16
#define meshtastic_FromRadio_deviceuiConfig_tag 17 #define meshtastic_FromRadio_deviceuiConfig_tag 17
#define meshtastic_Heartbeat_nonce_tag 1
#define meshtastic_ToRadio_packet_tag 1 #define meshtastic_ToRadio_packet_tag 1
#define meshtastic_ToRadio_want_config_id_tag 3 #define meshtastic_ToRadio_want_config_id_tag 3
#define meshtastic_ToRadio_disconnect_tag 4 #define meshtastic_ToRadio_disconnect_tag 4
@@ -1687,7 +1717,8 @@ X(a, STATIC, SINGULAR, BYTES, public_key, 16) \
X(a, STATIC, SINGULAR, BOOL, pki_encrypted, 17) \ X(a, STATIC, SINGULAR, BOOL, pki_encrypted, 17) \
X(a, STATIC, SINGULAR, UINT32, next_hop, 18) \ X(a, STATIC, SINGULAR, UINT32, next_hop, 18) \
X(a, STATIC, SINGULAR, UINT32, relay_node, 19) \ X(a, STATIC, SINGULAR, UINT32, relay_node, 19) \
X(a, STATIC, SINGULAR, UINT32, tx_after, 20) X(a, STATIC, SINGULAR, UINT32, tx_after, 20) \
X(a, STATIC, SINGULAR, UENUM, transport_mechanism, 21)
#define meshtastic_MeshPacket_CALLBACK NULL #define meshtastic_MeshPacket_CALLBACK NULL
#define meshtastic_MeshPacket_DEFAULT NULL #define meshtastic_MeshPacket_DEFAULT NULL
#define meshtastic_MeshPacket_payload_variant_decoded_MSGTYPE meshtastic_Data #define meshtastic_MeshPacket_payload_variant_decoded_MSGTYPE meshtastic_Data
@@ -1882,7 +1913,7 @@ X(a, STATIC, SINGULAR, UINT32, excluded_modules, 12)
#define meshtastic_DeviceMetadata_DEFAULT NULL #define meshtastic_DeviceMetadata_DEFAULT NULL
#define meshtastic_Heartbeat_FIELDLIST(X, a) \ #define meshtastic_Heartbeat_FIELDLIST(X, a) \
X(a, STATIC, SINGULAR, UINT32, nonce, 1)
#define meshtastic_Heartbeat_CALLBACK NULL #define meshtastic_Heartbeat_CALLBACK NULL
#define meshtastic_Heartbeat_DEFAULT NULL #define meshtastic_Heartbeat_DEFAULT NULL
@@ -1992,14 +2023,14 @@ extern const pb_msgdesc_t meshtastic_ChunkedPayloadResponse_msg;
#define meshtastic_DuplicatedPublicKey_size 0 #define meshtastic_DuplicatedPublicKey_size 0
#define meshtastic_FileInfo_size 236 #define meshtastic_FileInfo_size 236
#define meshtastic_FromRadio_size 510 #define meshtastic_FromRadio_size 510
#define meshtastic_Heartbeat_size 0 #define meshtastic_Heartbeat_size 6
#define meshtastic_KeyVerificationFinal_size 65 #define meshtastic_KeyVerificationFinal_size 65
#define meshtastic_KeyVerificationNumberInform_size 58 #define meshtastic_KeyVerificationNumberInform_size 58
#define meshtastic_KeyVerificationNumberRequest_size 52 #define meshtastic_KeyVerificationNumberRequest_size 52
#define meshtastic_KeyVerification_size 79 #define meshtastic_KeyVerification_size 79
#define meshtastic_LogRecord_size 426 #define meshtastic_LogRecord_size 426
#define meshtastic_LowEntropyKey_size 0 #define meshtastic_LowEntropyKey_size 0
#define meshtastic_MeshPacket_size 378 #define meshtastic_MeshPacket_size 381
#define meshtastic_MqttClientProxyMessage_size 501 #define meshtastic_MqttClientProxyMessage_size 501
#define meshtastic_MyNodeInfo_size 83 #define meshtastic_MyNodeInfo_size 83
#define meshtastic_NeighborInfo_size 258 #define meshtastic_NeighborInfo_size 258

View File

@@ -6,10 +6,45 @@
#include "Router.h" #include "Router.h"
#include "configuration.h" #include "configuration.h"
#include "main.h" #include "main.h"
#include "mesh/mesh-pb-constants.h"
#include <Throttle.h> #include <Throttle.h>
NodeInfoModule *nodeInfoModule; NodeInfoModule *nodeInfoModule;
ProcessMessage NodeInfoModule::handleReceived(const meshtastic_MeshPacket &mp)
{
if (mp.which_payload_variant != meshtastic_MeshPacket_decoded_tag || mp.decoded.portnum != ourPortNum) {
// Not for us, or not decoded, so skip
return ProcessMessage::CONTINUE;
}
// Decode the protobuf payload into a meshtastic_User
meshtastic_User p = meshtastic_User_init_default;
if (!pb_decode_from_bytes(mp.decoded.payload.bytes, mp.decoded.payload.size, &meshtastic_User_msg, &p)) {
LOG_ERROR("Failed to decode NodeInfo protobuf. Ignoring packet.");
return ProcessMessage::STOP;
}
// Validate that the nodenum matches the user's macaddr
NodeNum senderNodeNum = getFrom(&mp);
if (senderNodeNum != nodeDB->getNodeNum()) {
// Calculate expected nodenum from macaddr (same logic as pickNewNodeNum)
NodeNum expectedNodeNum = (p.macaddr[2] << 24) | (p.macaddr[3] << 16) | (p.macaddr[4] << 8) | p.macaddr[5];
if (senderNodeNum != expectedNodeNum) {
LOG_WARN(
"Dropping NodeInfo packet: nodenum 0x%08x doesn't match expected 0x%08x from MAC %02x:%02x:%02x:%02x:%02x:%02x",
senderNodeNum, expectedNodeNum, p.macaddr[0], p.macaddr[1], p.macaddr[2], p.macaddr[3], p.macaddr[4],
p.macaddr[5]);
// Cancel the sending of this packet and stop processing it
if (router)
router->cancelSending(mp.from, mp.id);
return ProcessMessage::STOP;
}
}
return ProcessMessage::CONTINUE;
}
bool NodeInfoModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshtastic_User *pptr) bool NodeInfoModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshtastic_User *pptr)
{ {
auto p = *pptr; auto p = *pptr;

View File

@@ -25,11 +25,16 @@ class NodeInfoModule : public ProtobufModule<meshtastic_User>, private concurren
protected: protected:
/** Called to handle a particular incoming message /** Called to handle a particular incoming message
@return true if you've guaranteed you've handled this message and no other handlers should be considered for it @return true if you've guaranteed you've handled this message and no other handlers should be considered for it
*/ */
virtual bool handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshtastic_User *p) override; virtual bool handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshtastic_User *p) override;
/** Called to handle a particular incoming message and continue or stop processing
* @return ProcessMessage::STOP if you've guaranteed you've handled this message and no other handlers should be considered
* for it
*/
virtual ProcessMessage handleReceived(const meshtastic_MeshPacket &mp) override;
/** Messages can be received that have the want_response bit set. If set, this callback will be invoked /** Messages can be received that have the want_response bit set. If set, this callback will be invoked
* so that subclasses can (optionally) send a response back to the original sender. */ * so that subclasses can (optionally) send a response back to the original sender. */
virtual meshtastic_MeshPacket *allocReply() override; virtual meshtastic_MeshPacket *allocReply() override;

View File

@@ -1,4 +1,4 @@
[VERSION] [VERSION]
major = 2 major = 2
minor = 7 minor = 7
build = 4 build = 5