//! The term "information element" is used by 3GPP to describe "structural //! elements containing single or multiple fields" in 2G/3G/4G/5G. We use //! the term to refer to a structured, fully parsed message in any telcom //! standard. use crate::gsmtap::{GsmtapMessage, GsmtapType, LteNasSubtype, LteRrcSubtype}; use pycrate_rs::nas::NASMessage; use telcom_parser::{decode, lte_rrc}; use thiserror::Error; #[derive(Error, Debug)] pub enum InformationElementError { #[error("Failed decoding RRC message")] RRCDecodingError(#[from] telcom_parser::ParsingError), #[error("Failed decoding NAS message")] NASDecodingError(#[from] pycrate_rs::nas::ParseError), #[error("Unsupported LTE RRC subtype {0:?}")] UnsupportedGsmtapType(GsmtapType), } #[derive(Debug)] pub enum InformationElement { GSM, UMTS, // 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), FiveG, } #[derive(Debug)] pub enum LteInformationElement { DlCcch(lte_rrc::DL_CCCH_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), UlCcch(lte_rrc::UL_CCCH_Message), UlDcch(lte_rrc::UL_DCCH_Message), BcchBch(lte_rrc::BCCH_BCH_Message), BcchDlSch(lte_rrc::BCCH_DL_SCH_Message), PCCH(lte_rrc::PCCH_Message), MCCH(lte_rrc::MCCH_Message), ScMcch(lte_rrc::SC_MCCH_Message_r13), BcchBchMbms(lte_rrc::BCCH_BCH_Message_MBMS), BcchDlSchBr(lte_rrc::BCCH_DL_SCH_Message_BR), BcchDlSchMbms(lte_rrc::BCCH_DL_SCH_Message_MBMS), SbcchSlBch(lte_rrc::SBCCH_SL_BCH_Message), SbcchSlBchV2x(lte_rrc::SBCCH_SL_BCH_Message_V2X_r14), NAS(NASMessage), // FIXME: unclear which message these "NB" types map to //DlCcchNb(), //DlDcchNb(), //UlCcchNb(), //UlDcchNb(), //BcchBchNb(), //BcchBchTddNb(), //BcchDlSchNb(), //PcchNb(), //ScMcchNb(), } impl TryFrom<&GsmtapMessage> for InformationElement { type Error = InformationElementError; fn try_from(gsmtap_msg: &GsmtapMessage) -> Result { match gsmtap_msg.header.gsmtap_type { GsmtapType::LteRrc(lte_rrc_subtype) => { use LteInformationElement as R; use LteRrcSubtype as L; let lte = match lte_rrc_subtype { L::DlCcch => R::DlCcch(decode(&gsmtap_msg.payload)?), L::DlDcch => R::DlDcch(Box::new(decode(&gsmtap_msg.payload)?)), L::UlCcch => R::UlCcch(decode(&gsmtap_msg.payload)?), L::UlDcch => R::UlDcch(decode(&gsmtap_msg.payload)?), L::BcchBch => R::BcchBch(decode(&gsmtap_msg.payload)?), L::BcchDlSch => R::BcchDlSch(decode(&gsmtap_msg.payload)?), L::PCCH => R::PCCH(decode(&gsmtap_msg.payload)?), L::MCCH => R::MCCH(decode(&gsmtap_msg.payload)?), L::ScMcch => R::ScMcch(decode(&gsmtap_msg.payload)?), L::BcchBchMbms => R::BcchBchMbms(decode(&gsmtap_msg.payload)?), L::BcchDlSchBr => R::BcchDlSchBr(decode(&gsmtap_msg.payload)?), L::BcchDlSchMbms => R::BcchDlSchMbms(decode(&gsmtap_msg.payload)?), L::SbcchSlBch => R::SbcchSlBch(decode(&gsmtap_msg.payload)?), L::SbcchSlBchV2x => R::SbcchSlBchV2x(decode(&gsmtap_msg.payload)?), _ => { return Err(InformationElementError::UnsupportedGsmtapType( gsmtap_msg.header.gsmtap_type, )); } }; Ok(InformationElement::LTE(Box::new(lte))) } GsmtapType::LteNas(LteNasSubtype::Plain) => { let msg = NASMessage::parse(&gsmtap_msg.payload)?; Ok(InformationElement::LTE(Box::new( LteInformationElement::NAS(msg), ))) } _ => Err(InformationElementError::UnsupportedGsmtapType( gsmtap_msg.header.gsmtap_type, )), } } }