mirror of
https://github.com/EFForg/rayhunter.git
synced 2026-07-09 10:08:10 -07:00
Flattens analysis structure a bit
Instead of mirroring the QMDL container format exactly, let our analysis files just be flat lists of packet analysis. Also removes the dummy analyzer and adds version numbers to analysis reports and Analyzers
This commit is contained in:
committed by
Cooper Quintin
parent
da18a1f9da
commit
0915103ede
+12
-15
@@ -18,7 +18,6 @@ use tokio::sync::mpsc::Receiver;
|
||||
use tokio::sync::{RwLock, RwLockWriteGuard};
|
||||
use tokio_util::task::TaskTracker;
|
||||
|
||||
use crate::dummy_analyzer::TestAnalyzer;
|
||||
use crate::qmdl_store::RecordingStore;
|
||||
use crate::server::ServerState;
|
||||
|
||||
@@ -37,13 +36,10 @@ pub struct AnalysisWriter {
|
||||
impl AnalysisWriter {
|
||||
pub async fn new(
|
||||
file: File,
|
||||
enable_dummy_analyzer: bool,
|
||||
analyzer_config: &AnalyzerConfig,
|
||||
) -> Result<Self, std::io::Error> {
|
||||
let mut harness = Harness::new_with_config(analyzer_config);
|
||||
if enable_dummy_analyzer {
|
||||
harness.add_analyzer(Box::new(TestAnalyzer { count: 0 }));
|
||||
}
|
||||
let harness = Harness::new_with_config(analyzer_config);
|
||||
|
||||
|
||||
let mut result = Self {
|
||||
writer: BufWriter::new(file),
|
||||
@@ -56,16 +52,20 @@ impl AnalysisWriter {
|
||||
}
|
||||
|
||||
// Runs the analysis harness on the given container, serializing the results
|
||||
// to the analysis file and returning the file's new length.
|
||||
// to the analysis file, returning the file's new length, and whether any
|
||||
// warnings were detected
|
||||
pub async fn analyze(
|
||||
&mut self,
|
||||
container: MessagesContainer,
|
||||
) -> Result<(usize, bool), std::io::Error> {
|
||||
let row = self.harness.analyze_qmdl_messages(container);
|
||||
if !row.is_empty() {
|
||||
self.write(&row).await?;
|
||||
let mut warning_detected = false;
|
||||
for row in self.harness.analyze_qmdl_messages(container) {
|
||||
if !row.is_empty() {
|
||||
self.write(&row).await?;
|
||||
}
|
||||
warning_detected |= row.contains_warnings();
|
||||
}
|
||||
Ok((self.bytes_written, row.contains_warnings()))
|
||||
Ok((self.bytes_written, warning_detected))
|
||||
}
|
||||
|
||||
async fn write<T: Serialize>(&mut self, value: &T) -> Result<(), std::io::Error> {
|
||||
@@ -134,7 +134,6 @@ async fn finish_running_analysis(analysis_status_lock: Arc<RwLock<AnalysisStatus
|
||||
async fn perform_analysis(
|
||||
name: &str,
|
||||
qmdl_store_lock: Arc<RwLock<RecordingStore>>,
|
||||
enable_dummy_analyzer: bool,
|
||||
analyzer_config: &AnalyzerConfig,
|
||||
) -> Result<(), String> {
|
||||
info!("Opening QMDL and analysis file for {name}...");
|
||||
@@ -156,7 +155,7 @@ async fn perform_analysis(
|
||||
};
|
||||
|
||||
let mut analysis_writer =
|
||||
AnalysisWriter::new(analysis_file, enable_dummy_analyzer, analyzer_config)
|
||||
AnalysisWriter::new(analysis_file, analyzer_config)
|
||||
.await
|
||||
.map_err(|e| format!("{e:?}"))?;
|
||||
let file_size = qmdl_file
|
||||
@@ -203,7 +202,6 @@ pub fn run_analysis_thread(
|
||||
mut analysis_rx: Receiver<AnalysisCtrlMessage>,
|
||||
qmdl_store_lock: Arc<RwLock<RecordingStore>>,
|
||||
analysis_status_lock: Arc<RwLock<AnalysisStatus>>,
|
||||
enable_dummy_analyzer: bool,
|
||||
analyzer_config: AnalyzerConfig,
|
||||
) {
|
||||
task_tracker.spawn(async move {
|
||||
@@ -216,7 +214,6 @@ pub fn run_analysis_thread(
|
||||
if let Err(err) = perform_analysis(
|
||||
&name,
|
||||
qmdl_store_lock.clone(),
|
||||
enable_dummy_analyzer,
|
||||
&analyzer_config,
|
||||
)
|
||||
.await
|
||||
|
||||
@@ -11,10 +11,12 @@ pub struct Config {
|
||||
pub port: u16,
|
||||
pub debug_mode: bool,
|
||||
pub ui_level: u8,
|
||||
pub enable_dummy_analyzer: bool,
|
||||
pub colorblind_mode: bool,
|
||||
pub key_input_mode: u8,
|
||||
pub analyzers: AnalyzerConfig,
|
||||
|
||||
// deprecated
|
||||
pub enable_dummy_analyzer: bool,
|
||||
}
|
||||
|
||||
impl Default for Config {
|
||||
@@ -24,10 +26,12 @@ impl Default for Config {
|
||||
port: 8080,
|
||||
debug_mode: false,
|
||||
ui_level: 1,
|
||||
enable_dummy_analyzer: false,
|
||||
colorblind_mode: false,
|
||||
key_input_mode: 0,
|
||||
analyzers: AnalyzerConfig::default(),
|
||||
|
||||
// deprecated
|
||||
enable_dummy_analyzer: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-3
@@ -37,14 +37,13 @@ pub fn run_diag_read_thread(
|
||||
ui_update_sender: Sender<display::DisplayState>,
|
||||
qmdl_store_lock: Arc<RwLock<RecordingStore>>,
|
||||
analysis_sender: Sender<AnalysisCtrlMessage>,
|
||||
enable_dummy_analyzer: bool,
|
||||
analyzer_config: AnalyzerConfig,
|
||||
) {
|
||||
task_tracker.spawn(async move {
|
||||
let (initial_qmdl_file, initial_analysis_file) = qmdl_store_lock.write().await.new_entry().await.expect("failed creating QMDL file entry");
|
||||
let mut maybe_qmdl_writer: Option<QmdlWriter<File>> = Some(QmdlWriter::new(initial_qmdl_file));
|
||||
let mut diag_stream = pin!(dev.as_stream().into_stream());
|
||||
let mut maybe_analysis_writer = Some(AnalysisWriter::new(initial_analysis_file, enable_dummy_analyzer, &analyzer_config).await
|
||||
let mut maybe_analysis_writer = Some(AnalysisWriter::new(initial_analysis_file, &analyzer_config).await
|
||||
.expect("failed to create analysis writer"));
|
||||
loop {
|
||||
tokio::select! {
|
||||
@@ -66,7 +65,7 @@ pub fn run_diag_read_thread(
|
||||
analysis_writer.close().await.expect("failed to close analysis writer");
|
||||
}
|
||||
|
||||
maybe_analysis_writer = Some(AnalysisWriter::new(new_analysis_file, enable_dummy_analyzer, &analyzer_config).await
|
||||
maybe_analysis_writer = Some(AnalysisWriter::new(new_analysis_file, &analyzer_config).await
|
||||
.expect("failed to write to analysis file"));
|
||||
|
||||
if let Err(e) = ui_update_sender.send(display::DisplayState::Recording).await {
|
||||
|
||||
@@ -1,53 +0,0 @@
|
||||
use std::borrow::Cow;
|
||||
|
||||
use rayhunter::telcom_parser::lte_rrc::{PCCH_MessageType, PCCH_MessageType_c1, PagingUE_Identity};
|
||||
|
||||
use rayhunter::analysis::analyzer::{Analyzer, Event, EventType, Severity};
|
||||
use rayhunter::analysis::information_element::{InformationElement, LteInformationElement};
|
||||
|
||||
pub struct TestAnalyzer {
|
||||
pub count: i32,
|
||||
}
|
||||
|
||||
impl Analyzer for TestAnalyzer {
|
||||
fn get_name(&self) -> Cow<str> {
|
||||
Cow::from("Example Analyzer")
|
||||
}
|
||||
|
||||
fn get_description(&self) -> Cow<str> {
|
||||
Cow::from(
|
||||
"Always returns true, if you are seeing this you are either a developer or you are about to have problems.",
|
||||
)
|
||||
}
|
||||
|
||||
fn analyze_information_element(&mut self, ie: &InformationElement) -> Option<Event> {
|
||||
self.count += 1;
|
||||
if self.count % 100 == 0 {
|
||||
return Some(Event {
|
||||
event_type: EventType::Informational,
|
||||
message: "multiple of 100 events processed".to_string(),
|
||||
});
|
||||
}
|
||||
let pcch_msg = match ie {
|
||||
InformationElement::LTE(lte_ie) => match &**lte_ie {
|
||||
LteInformationElement::PCCH(pcch_msg) => pcch_msg,
|
||||
_ => return None,
|
||||
},
|
||||
_ => return None,
|
||||
};
|
||||
let PCCH_MessageType::C1(PCCH_MessageType_c1::Paging(paging)) = &pcch_msg.message else {
|
||||
return None;
|
||||
};
|
||||
for record in &paging.paging_record_list.as_ref()?.0 {
|
||||
if let PagingUE_Identity::S_TMSI(_) = record.ue_identity {
|
||||
return Some(Event {
|
||||
event_type: EventType::QualitativeWarning {
|
||||
severity: Severity::Low,
|
||||
},
|
||||
message: "TMSI was provided to cell".to_string(),
|
||||
});
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,6 @@ mod analysis;
|
||||
mod config;
|
||||
mod diag;
|
||||
mod display;
|
||||
mod dummy_analyzer;
|
||||
mod error;
|
||||
mod key_input;
|
||||
mod pcap;
|
||||
@@ -231,7 +230,6 @@ async fn run_with_config(
|
||||
ui_update_tx.clone(),
|
||||
qmdl_store_lock.clone(),
|
||||
analysis_tx.clone(),
|
||||
config.enable_dummy_analyzer,
|
||||
config.analyzers.clone(),
|
||||
);
|
||||
info!("Starting UI");
|
||||
@@ -256,7 +254,6 @@ async fn run_with_config(
|
||||
analysis_rx,
|
||||
qmdl_store_lock.clone(),
|
||||
analysis_status_lock.clone(),
|
||||
config.enable_dummy_analyzer,
|
||||
config.analyzers.clone(),
|
||||
);
|
||||
let should_restart_flag = Arc::new(AtomicBool::new(false));
|
||||
|
||||
Reference in New Issue
Block a user