Skip to content

Commit d4c8130

Browse files
committed
Improve debug logging for mesh packets.
Closes #99. Signed-off-by: Christian Müller <christian.muller@wifx.net>
1 parent 9d327c2 commit d4c8130

3 files changed

Lines changed: 79 additions & 23 deletions

File tree

src/backend.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ type CommandChannel = mpsc::UnboundedSender<Command>;
2121

2222
pub async fn setup(conf: &Configuration) -> Result<()> {
2323
setup_concentratord(conf).await?;
24-
setup_mesh_conncentratord(conf).await?;
24+
setup_mesh_concentratord(conf).await?;
2525
Ok(())
2626
}
2727

@@ -128,7 +128,7 @@ async fn setup_concentratord(conf: &Configuration) -> Result<()> {
128128
Ok(())
129129
}
130130

131-
async fn setup_mesh_conncentratord(conf: &Configuration) -> Result<()> {
131+
async fn setup_mesh_concentratord(conf: &Configuration) -> Result<()> {
132132
info!(
133133
"Setting up Mesh Concentratord backend, event_url: {}, command_url: {}",
134134
conf.backend.mesh_concentratord.event_url, conf.backend.mesh_concentratord.command_url
@@ -339,7 +339,6 @@ async fn handle_mesh_event_msg(border_gateway: bool, event: gw::Event) -> Result
339339

340340
// The mesh event msg must always be a proprietary payload.
341341
if v.phy_payload.first().cloned().unwrap_or_default() & 0xe0 == 0xe0 {
342-
info!("Mesh frame received - {}", helpers::format_uplink(v)?);
343342
mesh::handle_mesh(border_gateway, v).await?;
344343
}
345344
}

src/mesh.rs

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use std::time::SystemTime;
44

55
use anyhow::Result;
66
use chirpstack_api::{gw, prost_types};
7-
use log::{info, trace, warn};
7+
use log::{debug, info, trace, warn};
88

99
use crate::{
1010
aes128::{Aes128Key, get_encryption_key, get_signing_key},
@@ -39,13 +39,23 @@ pub async fn handle_uplink(border_gateway: bool, pl: &gw::UplinkFrame) -> Result
3939
// Handle Proprietary LoRaWAN payload (mesh encapsulated).
4040
pub async fn handle_mesh(border_gateway: bool, pl: &gw::UplinkFrame) -> Result<()> {
4141
let conf = config::get();
42-
let mut packet = MeshPacket::from_slice(&pl.phy_payload)?;
42+
let mut packet = match MeshPacket::from_slice(&pl.phy_payload) {
43+
Ok(v) => v,
44+
Err(e) => {
45+
debug!(
46+
"Discarding proprietary uplink, not a valid mesh packet, error: {}, uplink_id: {}",
47+
e,
48+
pl.rx_info.as_ref().map(|v| v.uplink_id).unwrap_or_default()
49+
);
50+
return Ok(());
51+
}
52+
};
4353
if !packet.validate_mic(if conf.mesh.signing_key != Aes128Key::null() {
4454
conf.mesh.signing_key
4555
} else {
4656
get_signing_key(conf.mesh.root_key)
4757
})? {
48-
warn!("Dropping packet, invalid MIC, mesh_packet: {}", packet);
58+
debug!("Dropping packet, invalid MIC, mesh_packet: {}", packet);
4959
return Ok(());
5060
}
5161

@@ -62,6 +72,12 @@ pub async fn handle_mesh(border_gateway: bool, pl: &gw::UplinkFrame) -> Result<(
6272
// Decrypt the packet (in case it contains an encrypted payload).
6373
packet.decrypt(get_encryption_key(conf.mesh.root_key))?;
6474

75+
debug!(
76+
"Mesh frame received - {}, mesh_packet: {}",
77+
helpers::format_uplink(pl)?,
78+
packet
79+
);
80+
6581
match border_gateway {
6682
// Proxy relayed uplink
6783
true => match packet.mhdr.payload_type {

src/packets.rs

Lines changed: 58 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,8 @@ use std::fmt;
22
use std::io::{Cursor, Read};
33
use std::time::{Duration, SystemTime, UNIX_EPOCH};
44

5-
use aes::{
6-
cipher::BlockEncrypt,
7-
Aes128, Block,
8-
};
9-
use anyhow::Result;
5+
use aes::{Aes128, Block, cipher::BlockEncrypt};
6+
use anyhow::{Context, Result};
107
use cmac::{Cmac, Mac};
118
use log::warn;
129

@@ -276,7 +273,10 @@ pub struct UplinkPayload {
276273
impl UplinkPayload {
277274
pub fn from_slice(b: &[u8]) -> Result<UplinkPayload> {
278275
if b.len() < 9 {
279-
return Err(anyhow!("At least 9 bytes are expected"));
276+
return Err(anyhow!(
277+
"This is not a mesh uplink packet. At least 9 bytes of payload are expected, got: {}. ",
278+
b.len()
279+
));
280280
}
281281

282282
let mut md = [0; 5];
@@ -376,7 +376,7 @@ pub struct DownlinkPayload {
376376
impl DownlinkPayload {
377377
pub fn from_slice(b: &[u8]) -> Result<Self> {
378378
if b.len() < 10 {
379-
return Err(anyhow!("At least 10 bytes are expected"));
379+
return Err(anyhow!("At least 10 bytes are expected, got: {}", b.len()));
380380
}
381381

382382
let mut md = [0; 6];
@@ -463,18 +463,24 @@ pub struct EventPayload {
463463

464464
impl EventPayload {
465465
pub fn from_slice(b: &[u8]) -> Result<EventPayload> {
466+
if b.len() < 8 {
467+
return Err(anyhow!(
468+
"This is not a mesh event packet. At least 8 bytes of payload are expected, got: {}",
469+
b.len()
470+
));
471+
}
466472
let b_len = b.len() as u64;
467473
let mut cur = Cursor::new(b);
468474
let mut ts_b: [u8; 4] = [0; 4];
469475

470-
cur.read_exact(&mut ts_b)?;
476+
cur.read_exact(&mut ts_b).context("Read timestamp")?;
471477
let timestamp = u32::from_be_bytes(ts_b);
472478
let timestamp = UNIX_EPOCH
473479
.checked_add(Duration::from_secs(timestamp.into()))
474480
.ok_or_else(|| anyhow!("Invalid timestamp"))?;
475481

476482
let mut relay_id: [u8; 4] = [0; 4];
477-
cur.read_exact(&mut relay_id)?;
483+
cur.read_exact(&mut relay_id).context("Read relay_id")?;
478484

479485
let mut events = Vec::new();
480486

@@ -591,10 +597,10 @@ pub enum Event {
591597
impl Event {
592598
pub fn decode(cur: &mut Cursor<&[u8]>) -> Result<Self> {
593599
let mut tag_length: [u8; 2] = [0; 2];
594-
cur.read_exact(&mut tag_length)?;
600+
cur.read_exact(&mut tag_length).context("Read tag_length")?;
595601

596602
let mut value = vec![0; tag_length[1] as usize];
597-
cur.read_exact(&mut value)?;
603+
cur.read_exact(&mut value).context("Read value")?;
598604

599605
Ok(match tag_length[0] {
600606
0x00 => Event::Heartbeat(HeartbeatPayload::from_slice(&value)?),
@@ -714,18 +720,24 @@ pub struct CommandPayload {
714720

715721
impl CommandPayload {
716722
pub fn from_slice(b: &[u8]) -> Result<CommandPayload> {
723+
if b.len() < 8 {
724+
return Err(anyhow!(
725+
"This is not a mesh command packet : at least 8 bytes of payload are expected, got: {}",
726+
b.len()
727+
));
728+
}
717729
let b_len = b.len() as u64;
718730
let mut cur = Cursor::new(b);
719731
let mut ts_b: [u8; 4] = [0; 4];
720732

721-
cur.read_exact(&mut ts_b)?;
733+
cur.read_exact(&mut ts_b).context("Read timestamp")?;
722734
let timestamp = u32::from_be_bytes(ts_b);
723735
let timestamp = UNIX_EPOCH
724736
.checked_add(Duration::from_secs(timestamp.into()))
725737
.ok_or_else(|| anyhow!("Invalid timestamp"))?;
726738

727739
let mut relay_id: [u8; 4] = [0; 4];
728-
cur.read_exact(&mut relay_id)?;
740+
cur.read_exact(&mut relay_id).context("Read relay_id")?;
729741

730742
let mut commands = Vec::new();
731743

@@ -841,10 +853,10 @@ pub enum Command {
841853
impl Command {
842854
pub fn decode(cur: &mut Cursor<&[u8]>) -> Result<Self> {
843855
let mut tag_length: [u8; 2] = [0; 2];
844-
cur.read_exact(&mut tag_length)?;
856+
cur.read_exact(&mut tag_length).context("Read tag_length")?;
845857

846858
let mut value = vec![0; tag_length[1] as usize];
847-
cur.read_exact(&mut value)?;
859+
cur.read_exact(&mut value).context("Read value")?;
848860

849861
Ok(Command::Proprietary((tag_length[0], value)))
850862
}
@@ -1406,7 +1418,9 @@ mod test {
14061418
};
14071419
let b = dn_pl.to_vec().unwrap();
14081420
assert_eq!(
1409-
vec![0x40, 0x03, 0x84, 0x76, 0x28, 0xff, 0x01, 0x02, 0x03, 0x04, 0x05,],
1421+
vec![
1422+
0x40, 0x03, 0x84, 0x76, 0x28, 0xff, 0x01, 0x02, 0x03, 0x04, 0x05,
1423+
],
14101424
b
14111425
);
14121426
}
@@ -1468,7 +1482,9 @@ mod test {
14681482
};
14691483
let b = event_pl.to_vec().unwrap();
14701484
assert_eq!(
1471-
vec![59, 154, 202, 0, 1, 2, 3, 4, 0, 12, 5, 6, 7, 8, 120, 52, 9, 10, 11, 12, 120, 52],
1485+
vec![
1486+
59, 154, 202, 0, 1, 2, 3, 4, 0, 12, 5, 6, 7, 8, 120, 52, 9, 10, 11, 12, 120, 52
1487+
],
14721488
b
14731489
);
14741490
}
@@ -1735,4 +1751,29 @@ mod test {
17351751
assert_eq!(tst.expected_bytes, b);
17361752
}
17371753
}
1754+
1755+
#[test]
1756+
fn test_mesh_packet_from_slice_too_short() {
1757+
// PayloadType::Event, but only 1 byte of payload (MHDR(1) + EventPayload(1) + MIC(4) = 6 bytes)
1758+
// EventPayload needs at least 8 bytes (4 for timestamp, 4 for relay_id)
1759+
let b = vec![
1760+
MHDR {
1761+
payload_type: PayloadType::Event,
1762+
hop_count: 1,
1763+
}
1764+
.to_byte()
1765+
.unwrap(),
1766+
0x00, // 1 byte of payload (not enough for EventPayload)
1767+
0x00,
1768+
0x00,
1769+
0x00,
1770+
0x00, // MIC
1771+
];
1772+
let res = MeshPacket::from_slice(&b);
1773+
assert!(res.is_err());
1774+
assert_eq!(
1775+
res.unwrap_err().to_string(),
1776+
"This is not a mesh event packet. At least 8 bytes of payload are expected, got: 1"
1777+
);
1778+
}
17381779
}

0 commit comments

Comments
 (0)