From 2b1bf3b96f26537148e0ae91cebf260fdbff920f Mon Sep 17 00:00:00 2001 From: Orne Brocaar Date: Tue, 9 Aug 2022 15:29:22 +0100 Subject: [PATCH] Only decode mac-commands for logging if in plaintext. Please note that for LoRaWAN 1.1.x, mac-commands in the f_opts field are encrypted. Within the context of the device we can decrypt these, but within the context of a gateway we can only show these as raw bytes. --- chirpstack/src/downlink/tx_ack.rs | 2 + chirpstack/src/framelog.rs | 132 +++++++++++++++++------------- chirpstack/src/uplink/data.rs | 1 + chirpstack/src/uplink/mod.rs | 1 + 4 files changed, 80 insertions(+), 56 deletions(-) diff --git a/chirpstack/src/downlink/tx_ack.rs b/chirpstack/src/downlink/tx_ack.rs index a4bda42d..946d846d 100644 --- a/chirpstack/src/downlink/tx_ack.rs +++ b/chirpstack/src/downlink/tx_ack.rs @@ -415,6 +415,7 @@ impl TxAck { "".to_string() } }, + plaintext_mac_commands: false, }; // Log for gateway (with potentially encrypted mac-commands). @@ -451,6 +452,7 @@ impl TxAck { m_type: dfl.m_type, dev_addr: dfl.dev_addr.clone(), dev_eui: dfl.dev_eui.clone(), + plaintext_mac_commands: true, }; // Log for device. diff --git a/chirpstack/src/framelog.rs b/chirpstack/src/framelog.rs index 678ecfd5..3fbbc0ab 100644 --- a/chirpstack/src/framelog.rs +++ b/chirpstack/src/framelog.rs @@ -40,6 +40,7 @@ pub async fn log_uplink_for_gateways(ufl: &api::UplinkFrameLog) -> Result<()> { dev_addr: ufl.dev_addr.clone(), dev_eui: ufl.dev_eui.clone(), time: ufl.time.clone(), + plaintext_mac_commands: ufl.plaintext_mac_commands, }; let b = ufl_copy.encode_to_vec(); @@ -268,71 +269,90 @@ pub async fn get_frame_logs( for stream_id in &stream_key.ids { last_id = stream_id.id.clone(); for (k, v) in &stream_id.map { - match k.as_ref() { - "up" => { - trace!(key = %k, id = %last_id, "Frame-log received from stream"); - if let redis::Value::Data(b) = v { - let pl = api::UplinkFrameLog::decode(&mut Cursor::new(b))?; - let mut phy = lrwn::PhyPayload::from_slice(&pl.phy_payload)?; - phy.decode_f_opts_to_mac_commands()?; + let res = || -> Result<()> { + match k.as_ref() { + "up" => { + trace!(key = %k, id = %last_id, "Frame-log received from stream"); + if let redis::Value::Data(b) = v { + let pl = api::UplinkFrameLog::decode(&mut Cursor::new(b))?; + let mut phy = lrwn::PhyPayload::from_slice(&pl.phy_payload)?; + if pl.plaintext_mac_commands { + phy.decode_f_opts_to_mac_commands()?; + } - let pl = api::LogItem { - id: stream_id.id.clone(), - time: pl.time.clone(), - description: pl.m_type().into(), - body: json!({ - "phy_payload": phy, - "tx_info": pl.tx_info, - "rx_info": pl.rx_info, - }) - .to_string(), - properties: [ - ("DevAddr".to_string(), pl.dev_addr), - ("DevEUI".to_string(), pl.dev_eui), - ] - .iter() - .cloned() - .collect(), - }; - if channel.blocking_send(pl).is_err() { - return Err(anyhow!("Channel send error")); + let pl = api::LogItem { + id: stream_id.id.clone(), + time: pl.time.clone(), + description: pl.m_type().into(), + body: json!({ + "phy_payload": phy, + "tx_info": pl.tx_info, + "rx_info": pl.rx_info, + }) + .to_string(), + properties: [ + ("DevAddr".to_string(), pl.dev_addr), + ("DevEUI".to_string(), pl.dev_eui), + ] + .iter() + .cloned() + .collect(), + }; + + if let Err(e) = channel.blocking_send(pl) { + return Err(anyhow::Error::new(e)); + } } } - } - "down" => { - trace!(key = %k, id = %last_id, "frame-log received from stream"); - if let redis::Value::Data(b) = v { - let pl = api::DownlinkFrameLog::decode(&mut Cursor::new(b))?; - let mut phy = lrwn::PhyPayload::from_slice(&pl.phy_payload)?; - phy.decode_f_opts_to_mac_commands()?; + "down" => { + trace!(key = %k, id = %last_id, "frame-log received from stream"); + if let redis::Value::Data(b) = v { + let pl = api::DownlinkFrameLog::decode(&mut Cursor::new(b))?; + let mut phy = lrwn::PhyPayload::from_slice(&pl.phy_payload)?; + if pl.plaintext_mac_commands { + phy.decode_f_opts_to_mac_commands()?; + } - let pl = api::LogItem { - id: stream_id.id.clone(), - time: pl.time.clone(), - description: pl.m_type().into(), - body: json!({ - "phy_payload": phy, - "tx_info": pl.tx_info, - }) - .to_string(), - properties: [ - ("DevAddr".to_string(), pl.dev_addr), - ("DevEUI".to_string(), pl.dev_eui), - ("Gateway ID".to_string(), pl.gateway_id), - ] - .iter() - .cloned() - .collect(), - }; + let pl = api::LogItem { + id: stream_id.id.clone(), + time: pl.time.clone(), + description: pl.m_type().into(), + body: json!({ + "phy_payload": phy, + "tx_info": pl.tx_info, + }) + .to_string(), + properties: [ + ("DevAddr".to_string(), pl.dev_addr), + ("DevEUI".to_string(), pl.dev_eui), + ("Gateway ID".to_string(), pl.gateway_id), + ] + .iter() + .cloned() + .collect(), + }; - if channel.blocking_send(pl).is_err() { - return Err(anyhow!("Channel send error")); + if let Err(e) = channel.blocking_send(pl) { + return Err(anyhow::Error::new(e)); + } } } + _ => { + error!(key = %k, "Unexpected key in frame-log stream"); + } } - _ => { - error!(key = %k, "Unexpected key in frame-log stream"); + + Ok(()) + }(); + + if let Err(e) = res { + // Return in case of channel error, in any other case we just log + // the error. + if let Some(_) = e.downcast_ref::>() { + return Err(e); } + + error!(key = %k, error = %e, "Parsing frame-log error"); } } } diff --git a/chirpstack/src/uplink/data.rs b/chirpstack/src/uplink/data.rs index 4e5fc782..1700b61e 100644 --- a/chirpstack/src/uplink/data.rs +++ b/chirpstack/src/uplink/data.rs @@ -442,6 +442,7 @@ impl Data { trace!("Logging uplink frame-set"); let mut ufl: api::UplinkFrameLog = (&self.uplink_frame_set).try_into()?; ufl.dev_eui = self.device.as_ref().unwrap().dev_eui.to_string(); + ufl.plaintext_mac_commands = true; framelog::log_uplink_for_device(&ufl).await?; Ok(()) } diff --git a/chirpstack/src/uplink/mod.rs b/chirpstack/src/uplink/mod.rs index a3db4e77..a5464759 100644 --- a/chirpstack/src/uplink/mod.rs +++ b/chirpstack/src/uplink/mod.rs @@ -74,6 +74,7 @@ impl TryFrom<&UplinkFrameSet> for api::UplinkFrameLog { _ => "".to_string(), }, time: None, // is set below + plaintext_mac_commands: false, }; for rx_info in &ufl.rx_info {