Box some of the larger information element enum variants

An enum is always the size needed to store its largest variant. Some of
the variants of the InformationElement and LteInformationElement are
substantially larger than the rest. Boxing the larger variants reduces
the size of the enum, in some cases by several kilobytes.

Since Rust does not currently support destructing a Box via pattern
matching, some code that destructures these enums had to be modified.
This commit is contained in:
Sashanoraa
2025-03-25 18:38:42 -04:00
committed by Will Greenberg
parent 4edf001ca4
commit 034e0632e4
7 changed files with 44 additions and 19 deletions
+6 -2
View File
@@ -26,8 +26,12 @@ impl Analyzer for TestAnalyzer{
message: "multiple of 100 events processed".to_string(), message: "multiple of 100 events processed".to_string(),
}) })
} }
let InformationElement::LTE(LteInformationElement::PCCH(pcch_msg)) = ie else { let pcch_msg = match ie {
return None; 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 { let PCCH_MessageType::C1(PCCH_MessageType_c1::Paging(paging)) = &pcch_msg.message else {
return None; return None;
@@ -2,7 +2,7 @@ use std::borrow::Cow;
use super::analyzer::{Analyzer, Event, EventType, Severity}; use super::analyzer::{Analyzer, Event, EventType, Severity};
use super::information_element::{InformationElement, LteInformationElement}; use super::information_element::{InformationElement, LteInformationElement};
use telcom_parser::lte_rrc::{DL_DCCH_Message, DL_DCCH_MessageType, DL_DCCH_MessageType_c1, RRCConnectionReleaseCriticalExtensions, RRCConnectionReleaseCriticalExtensions_c1, RedirectedCarrierInfo}; use telcom_parser::lte_rrc::{DL_DCCH_MessageType, DL_DCCH_MessageType_c1, RRCConnectionReleaseCriticalExtensions, RRCConnectionReleaseCriticalExtensions_c1, RedirectedCarrierInfo};
use super::util::unpack; use super::util::unpack;
// Based on HITBSecConf presentation "Forcing a targeted LTE cellphone into an // Based on HITBSecConf presentation "Forcing a targeted LTE cellphone into an
@@ -22,7 +22,10 @@ impl Analyzer for ConnectionRedirect2GDowngradeAnalyzer {
fn analyze_information_element(&mut self, ie: &InformationElement) -> Option<Event> { fn analyze_information_element(&mut self, ie: &InformationElement) -> Option<Event> {
unpack!(InformationElement::LTE(lte_ie) = ie); unpack!(InformationElement::LTE(lte_ie) = ie);
unpack!(LteInformationElement::DlDcch(DL_DCCH_Message { message }) = lte_ie); let message = match &**lte_ie {
LteInformationElement::DlDcch(msg_cont) => &msg_cont.message,
_ => return None,
};
unpack!(DL_DCCH_MessageType::C1(c1) = message); unpack!(DL_DCCH_MessageType::C1(c1) = message);
unpack!(DL_DCCH_MessageType_c1::RrcConnectionRelease(release) = c1); unpack!(DL_DCCH_MessageType_c1::RrcConnectionRelease(release) = c1);
unpack!(RRCConnectionReleaseCriticalExtensions::C1(c1) = &release.critical_extensions); unpack!(RRCConnectionReleaseCriticalExtensions::C1(c1) = &release.critical_extensions);
+6 -2
View File
@@ -18,8 +18,12 @@ impl Analyzer for ImsiProvidedAnalyzer {
} }
fn analyze_information_element(&mut self, ie: &InformationElement) -> Option<Event> { fn analyze_information_element(&mut self, ie: &InformationElement) -> Option<Event> {
let InformationElement::LTE(LteInformationElement::PCCH(pcch_msg)) = ie else { let pcch_msg = match ie {
return None; 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 { let PCCH_MessageType::C1(PCCH_MessageType_c1::Paging(paging)) = &pcch_msg.message else {
return None; return None;
+6 -2
View File
@@ -26,8 +26,12 @@ impl Analyzer for ImsiRequestedAnalyzer {
fn analyze_information_element(&mut self, ie: &InformationElement) -> Option<Event> { fn analyze_information_element(&mut self, ie: &InformationElement) -> Option<Event> {
self.packet_num += 1; self.packet_num += 1;
let InformationElement::LTE(LteInformationElement::NAS(payload)) = ie else { let payload = match ie {
return None; InformationElement::LTE(inner) => match &**inner {
LteInformationElement::NAS(payload) => payload,
_ => return None,
}
_ => return None,
}; };
// NAS identity request, ID type IMSI // NAS identity request, ID type IMSI
+9 -5
View File
@@ -19,14 +19,18 @@ pub enum InformationElementError {
pub enum InformationElement { pub enum InformationElement {
GSM, GSM,
UMTS, UMTS,
LTE(LteInformationElement), // This element of the enum is substantially larger than the others,
// so we box it to prevent the size of the enum (any variant) from blowing up.
LTE(Box<LteInformationElement>),
FiveG, FiveG,
} }
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
pub enum LteInformationElement { pub enum LteInformationElement {
DlCcch(lte_rrc::DL_CCCH_Message), DlCcch(lte_rrc::DL_CCCH_Message),
DlDcch(lte_rrc::DL_DCCH_Message), // This element of the enum is substantially larger than the others,
// so we box it to prevent the size of the enum (any variant) from blowing up.
DlDcch(Box<lte_rrc::DL_DCCH_Message>),
UlCcch(lte_rrc::UL_CCCH_Message), UlCcch(lte_rrc::UL_CCCH_Message),
UlDcch(lte_rrc::UL_DCCH_Message), UlDcch(lte_rrc::UL_DCCH_Message),
BcchBch(lte_rrc::BCCH_BCH_Message), BcchBch(lte_rrc::BCCH_BCH_Message),
@@ -65,7 +69,7 @@ impl TryFrom<&GsmtapMessage> for InformationElement {
use LteInformationElement as R; use LteInformationElement as R;
let lte = match lte_rrc_subtype { let lte = match lte_rrc_subtype {
L::DlCcch => R::DlCcch(decode(&gsmtap_msg.payload)?), L::DlCcch => R::DlCcch(decode(&gsmtap_msg.payload)?),
L::DlDcch => R::DlDcch(decode(&gsmtap_msg.payload)?), L::DlDcch => R::DlDcch(Box::new(decode(&gsmtap_msg.payload)?)),
L::UlCcch => R::UlCcch(decode(&gsmtap_msg.payload)?), L::UlCcch => R::UlCcch(decode(&gsmtap_msg.payload)?),
L::UlDcch => R::UlDcch(decode(&gsmtap_msg.payload)?), L::UlDcch => R::UlDcch(decode(&gsmtap_msg.payload)?),
L::BcchBch => R::BcchBch(decode(&gsmtap_msg.payload)?), L::BcchBch => R::BcchBch(decode(&gsmtap_msg.payload)?),
@@ -80,10 +84,10 @@ impl TryFrom<&GsmtapMessage> for InformationElement {
L::SbcchSlBchV2x => R::SbcchSlBchV2x(decode(&gsmtap_msg.payload)?), L::SbcchSlBchV2x => R::SbcchSlBchV2x(decode(&gsmtap_msg.payload)?),
_ => return Err(InformationElementError::UnsupportedGsmtapType(gsmtap_msg.header.gsmtap_type)), _ => return Err(InformationElementError::UnsupportedGsmtapType(gsmtap_msg.header.gsmtap_type)),
}; };
Ok(InformationElement::LTE(lte)) Ok(InformationElement::LTE(Box::new(lte)))
}, },
GsmtapType::LteNas(LteNasSubtype::Plain) => { GsmtapType::LteNas(LteNasSubtype::Plain) => {
Ok(InformationElement::LTE(LteInformationElement::NAS(gsmtap_msg.payload.clone()))) Ok(InformationElement::LTE(Box::new(LteInformationElement::NAS(gsmtap_msg.payload.clone()))))
}, },
_ => Err(InformationElementError::UnsupportedGsmtapType(gsmtap_msg.header.gsmtap_type)), _ => Err(InformationElementError::UnsupportedGsmtapType(gsmtap_msg.header.gsmtap_type)),
} }
+6 -2
View File
@@ -93,8 +93,12 @@ impl Analyzer for NullCipherAnalyzer {
} }
fn analyze_information_element(&mut self, ie: &InformationElement) -> Option<Event> { fn analyze_information_element(&mut self, ie: &InformationElement) -> Option<Event> {
let InformationElement::LTE(LteInformationElement::DlDcch(dcch_msg)) = ie else { let dcch_msg = match ie {
return None; InformationElement::LTE(lte_ie) => match &** lte_ie {
LteInformationElement::DlDcch(dcch_msg) => dcch_msg,
_ => return None,
}
_ => return None,
}; };
let DL_DCCH_MessageType::C1(c1) = &dcch_msg.message else { let DL_DCCH_MessageType::C1(c1) = &dcch_msg.message else {
return None; return None;
+6 -4
View File
@@ -10,10 +10,12 @@ pub struct LteSib6And7DowngradeAnalyzer {
impl LteSib6And7DowngradeAnalyzer { impl LteSib6And7DowngradeAnalyzer {
fn unpack_system_information<'a>(&self, ie: &'a InformationElement) -> Option<&'a SystemInformation_r8_IEsSib_TypeAndInfo> { 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 InformationElement::LTE(lte_ie) = ie {
if let BCCH_DL_SCH_MessageType::C1(BCCH_DL_SCH_MessageType_c1::SystemInformation(system_information)) = &bcch_dl_sch_message.message { if let LteInformationElement::BcchDlSch(bcch_dl_sch_message) = &**lte_ie {
if let SystemInformationCriticalExtensions::SystemInformation_r8(sib) = &system_information.critical_extensions { if let BCCH_DL_SCH_MessageType::C1(BCCH_DL_SCH_MessageType_c1::SystemInformation(system_information)) = &bcch_dl_sch_message.message {
return Some(&sib.sib_type_and_info); if let SystemInformationCriticalExtensions::SystemInformation_r8(sib) = &system_information.critical_extensions {
return Some(&sib.sib_type_and_info);
}
} }
} }
} }