Keep old 2G downgrade analyzer

This commit is contained in:
Will Greenberg
2025-01-17 13:31:50 -08:00
committed by Cooper Quintin
parent 28b0f409db
commit 30323b8329
5 changed files with 114 additions and 3 deletions

View File

@@ -7,7 +7,8 @@ use crate::{diag::MessagesContainer, gsmtap_parser};
use super::{
imsi_requested::ImsiRequestedAnalyzer,
information_element::InformationElement,
lte_downgrade::ConnectionRedirect2GDowngradeAnalyzer,
connection_redirect_downgrade::ConnectionRedirect2GDowngradeAnalyzer,
priority_2g_downgrade::LteSib6And7DowngradeAnalyzer,
null_cipher::NullCipherAnalyzer,
};
@@ -117,8 +118,9 @@ impl Harness {
pub fn new_with_all_analyzers() -> Self {
let mut harness = Harness::new();
harness.add_analyzer(Box::new(ConnectionRedirect2GDowngradeAnalyzer{}));
harness.add_analyzer(Box::new(ImsiRequestedAnalyzer::new()));
harness.add_analyzer(Box::new(ConnectionRedirect2GDowngradeAnalyzer{}));
harness.add_analyzer(Box::new(LteSib6And7DowngradeAnalyzer{}));
harness.add_analyzer(Box::new(NullCipherAnalyzer{}));
harness

View File

@@ -1,6 +1,7 @@
pub mod analyzer;
pub mod information_element;
pub mod lte_downgrade;
pub mod priority_2g_downgrade;
pub mod connection_redirect_downgrade;
pub mod imsi_provided;
pub mod imsi_requested;
pub mod null_cipher;

View File

@@ -0,0 +1,81 @@
use std::borrow::Cow;
use super::analyzer::{Analyzer, Event, EventType, Severity};
use super::information_element::{InformationElement, LteInformationElement};
use telcom_parser::lte_rrc::{BCCH_DL_SCH_MessageType, BCCH_DL_SCH_MessageType_c1, CellReselectionPriority, SystemInformationBlockType7, SystemInformationCriticalExtensions, SystemInformation_r8_IEsSib_TypeAndInfo, SystemInformation_r8_IEsSib_TypeAndInfo_Entry};
/// Based on heuristic T7 from Shinjo Park's "Why We Cannot Win".
pub struct LteSib6And7DowngradeAnalyzer {
}
impl LteSib6And7DowngradeAnalyzer {
fn unpack_system_information<'a>(&self, ie: &'a InformationElement) -> Option<&'a SystemInformation_r8_IEsSib_TypeAndInfo> {
if let InformationElement::LTE(LteInformationElement::BcchDlSch(bcch_dl_sch_message)) = ie {
if let BCCH_DL_SCH_MessageType::C1(BCCH_DL_SCH_MessageType_c1::SystemInformation(system_information)) = &bcch_dl_sch_message.message {
if let SystemInformationCriticalExtensions::SystemInformation_r8(sib) = &system_information.critical_extensions {
return Some(&sib.sib_type_and_info);
}
}
}
None
}
}
// TODO: keep track of SIB state to compare LTE reselection blocks w/ 2g/3g ones
impl Analyzer for LteSib6And7DowngradeAnalyzer {
fn get_name(&self) -> Cow<str> {
Cow::from("LTE SIB 6/7 Downgrade")
}
fn get_description(&self) -> Cow<str> {
Cow::from("Tests for LTE cells broadcasting a SIB type 6 and 7 which include 2G/3G frequencies with higher priorities.")
}
fn analyze_information_element(&mut self, ie: &InformationElement) -> Option<super::analyzer::Event> {
let sibs = &self.unpack_system_information(ie)?.0;
for sib in sibs {
match sib {
SystemInformation_r8_IEsSib_TypeAndInfo_Entry::Sib6(sib6) => {
if let Some(carrier_info_list) = sib6.carrier_freq_list_utra_fdd.as_ref() {
for carrier_info in &carrier_info_list.0 {
if let Some(CellReselectionPriority(p)) = carrier_info.cell_reselection_priority {
if p == 0 {
return Some(Event {
event_type: EventType::QualitativeWarning { severity: Severity::High },
message: "LTE cell advertised a 3G cell for priority 0 reselection".to_string(),
});
}
}
}
}
if let Some(carrier_info_list) = sib6.carrier_freq_list_utra_tdd.as_ref() {
for carrier_info in &carrier_info_list.0 {
if let Some(CellReselectionPriority(p)) = carrier_info.cell_reselection_priority {
if p == 0 {
return Some(Event {
event_type: EventType::QualitativeWarning { severity: Severity::High },
message: "LTE cell advertised a 3G cell for priority 0 reselection".to_string(),
});
}
}
}
}
},
SystemInformation_r8_IEsSib_TypeAndInfo_Entry::Sib7(SystemInformationBlockType7 { carrier_freqs_info_list: Some(carrier_info_list), .. }) => {
for carrier_info in &carrier_info_list.0 {
if let Some(CellReselectionPriority(p)) = carrier_info.common_info.cell_reselection_priority {
if p == 0 {
return Some(Event {
event_type: EventType::QualitativeWarning { severity: Severity::High },
message: "LTE cell advertised a 2G cell for priority 0 reselection".to_string(),
});
}
}
}
},
_ => {},
}
}
None
}
}

View File

@@ -1,7 +1,34 @@
/// Unpacks a pattern, or returns None.
///
/// # Examples
/// Suppose you've got some highly nested enum:
/// ```
/// enum Foo {
/// A(Bar),
/// B,
/// }
///
/// enum Baz {
/// C(Bang)
/// }
///
/// struct Bang;
/// ```
///
/// You can use `unpack!` to unroll it like this:
/// ```
/// fn get_bang(foo: Foo) -> Option<Bang> {
/// unpack!(Foo::A(bar) = foo);
/// unpack!(Baz::C(bang) = bar);
/// bang
/// }
/// ```
macro_rules! unpack {
($pat:pat = $val:expr) => {
let $pat = $val else { return None; };
};
}
// this is apparently how you make a macro publicly usable from this module
pub(crate) use unpack;