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.
This commit is contained in:
Orne Brocaar 2022-08-09 15:29:22 +01:00
parent fd62076e02
commit 2b1bf3b96f
4 changed files with 80 additions and 56 deletions

View File

@ -415,6 +415,7 @@ impl TxAck {
"".to_string() "".to_string()
} }
}, },
plaintext_mac_commands: false,
}; };
// Log for gateway (with potentially encrypted mac-commands). // Log for gateway (with potentially encrypted mac-commands).
@ -451,6 +452,7 @@ impl TxAck {
m_type: dfl.m_type, m_type: dfl.m_type,
dev_addr: dfl.dev_addr.clone(), dev_addr: dfl.dev_addr.clone(),
dev_eui: dfl.dev_eui.clone(), dev_eui: dfl.dev_eui.clone(),
plaintext_mac_commands: true,
}; };
// Log for device. // Log for device.

View File

@ -40,6 +40,7 @@ pub async fn log_uplink_for_gateways(ufl: &api::UplinkFrameLog) -> Result<()> {
dev_addr: ufl.dev_addr.clone(), dev_addr: ufl.dev_addr.clone(),
dev_eui: ufl.dev_eui.clone(), dev_eui: ufl.dev_eui.clone(),
time: ufl.time.clone(), time: ufl.time.clone(),
plaintext_mac_commands: ufl.plaintext_mac_commands,
}; };
let b = ufl_copy.encode_to_vec(); let b = ufl_copy.encode_to_vec();
@ -268,71 +269,90 @@ pub async fn get_frame_logs(
for stream_id in &stream_key.ids { for stream_id in &stream_key.ids {
last_id = stream_id.id.clone(); last_id = stream_id.id.clone();
for (k, v) in &stream_id.map { for (k, v) in &stream_id.map {
match k.as_ref() { let res = || -> Result<()> {
"up" => { match k.as_ref() {
trace!(key = %k, id = %last_id, "Frame-log received from stream"); "up" => {
if let redis::Value::Data(b) = v { trace!(key = %k, id = %last_id, "Frame-log received from stream");
let pl = api::UplinkFrameLog::decode(&mut Cursor::new(b))?; if let redis::Value::Data(b) = v {
let mut phy = lrwn::PhyPayload::from_slice(&pl.phy_payload)?; let pl = api::UplinkFrameLog::decode(&mut Cursor::new(b))?;
phy.decode_f_opts_to_mac_commands()?; 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 { let pl = api::LogItem {
id: stream_id.id.clone(), id: stream_id.id.clone(),
time: pl.time.clone(), time: pl.time.clone(),
description: pl.m_type().into(), description: pl.m_type().into(),
body: json!({ body: json!({
"phy_payload": phy, "phy_payload": phy,
"tx_info": pl.tx_info, "tx_info": pl.tx_info,
"rx_info": pl.rx_info, "rx_info": pl.rx_info,
}) })
.to_string(), .to_string(),
properties: [ properties: [
("DevAddr".to_string(), pl.dev_addr), ("DevAddr".to_string(), pl.dev_addr),
("DevEUI".to_string(), pl.dev_eui), ("DevEUI".to_string(), pl.dev_eui),
] ]
.iter() .iter()
.cloned() .cloned()
.collect(), .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));
}
} }
} }
} "down" => {
"down" => { trace!(key = %k, id = %last_id, "frame-log received from stream");
trace!(key = %k, id = %last_id, "frame-log received from stream"); if let redis::Value::Data(b) = v {
if let redis::Value::Data(b) = v { let pl = api::DownlinkFrameLog::decode(&mut Cursor::new(b))?;
let pl = api::DownlinkFrameLog::decode(&mut Cursor::new(b))?; let mut phy = lrwn::PhyPayload::from_slice(&pl.phy_payload)?;
let mut phy = lrwn::PhyPayload::from_slice(&pl.phy_payload)?; if pl.plaintext_mac_commands {
phy.decode_f_opts_to_mac_commands()?; phy.decode_f_opts_to_mac_commands()?;
}
let pl = api::LogItem { let pl = api::LogItem {
id: stream_id.id.clone(), id: stream_id.id.clone(),
time: pl.time.clone(), time: pl.time.clone(),
description: pl.m_type().into(), description: pl.m_type().into(),
body: json!({ body: json!({
"phy_payload": phy, "phy_payload": phy,
"tx_info": pl.tx_info, "tx_info": pl.tx_info,
}) })
.to_string(), .to_string(),
properties: [ properties: [
("DevAddr".to_string(), pl.dev_addr), ("DevAddr".to_string(), pl.dev_addr),
("DevEUI".to_string(), pl.dev_eui), ("DevEUI".to_string(), pl.dev_eui),
("Gateway ID".to_string(), pl.gateway_id), ("Gateway ID".to_string(), pl.gateway_id),
] ]
.iter() .iter()
.cloned() .cloned()
.collect(), .collect(),
}; };
if channel.blocking_send(pl).is_err() { if let Err(e) = channel.blocking_send(pl) {
return Err(anyhow!("Channel send error")); 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::<mpsc::error::SendError<api::LogItem>>() {
return Err(e);
} }
error!(key = %k, error = %e, "Parsing frame-log error");
} }
} }
} }

View File

@ -442,6 +442,7 @@ impl Data {
trace!("Logging uplink frame-set"); trace!("Logging uplink frame-set");
let mut ufl: api::UplinkFrameLog = (&self.uplink_frame_set).try_into()?; let mut ufl: api::UplinkFrameLog = (&self.uplink_frame_set).try_into()?;
ufl.dev_eui = self.device.as_ref().unwrap().dev_eui.to_string(); ufl.dev_eui = self.device.as_ref().unwrap().dev_eui.to_string();
ufl.plaintext_mac_commands = true;
framelog::log_uplink_for_device(&ufl).await?; framelog::log_uplink_for_device(&ufl).await?;
Ok(()) Ok(())
} }

View File

@ -74,6 +74,7 @@ impl TryFrom<&UplinkFrameSet> for api::UplinkFrameLog {
_ => "".to_string(), _ => "".to_string(),
}, },
time: None, // is set below time: None, // is set below
plaintext_mac_commands: false,
}; };
for rx_info in &ufl.rx_info { for rx_info in &ufl.rx_info {