library/GSM_SystemInformation: add dec_SystemInformationSafe()
Some types of System Information (mostly the Rest Octets) are not
fully implemented, so calling the generic dec_SystemInformation()
may result in a DTE. Let's add dec_SystemInformationSafeBT() with
"prototype(backtrack)", so it would return a non-zero integer if
decoding fails. Let's add a wrapper dec_SystemInformationSafe()
that would additionally check the RR Protocol Discriminator.
Change-Id: Id4d73e0f3347e1d4c4c77aec75b767311d662292
Related: OS#4662
diff --git a/bts/BTS_Tests.ttcn b/bts/BTS_Tests.ttcn
index 587e14a..47f8a29 100644
--- a/bts/BTS_Tests.ttcn
+++ b/bts/BTS_Tests.ttcn
@@ -3534,7 +3534,6 @@
repeat;
}
[] L1CTL.receive(tr_L1CTL_DATA_IND(t_RslChanNr_PCH_AGCH(0), ?)) -> value l1_dl {
- /* somehow dec_SystemInformation will try to decode even non-RR as SI */
var GsmRrMessage rr := dec_GsmRrMessage(l1_dl.payload.data_ind.payload);
if (not match(rr, tr_IMM_ASS(42, ?, 5, ?, ?))) {
/* FIXME: Why are we seeing paging requests on PCH/AGCH? */
@@ -3936,15 +3935,12 @@
T.start;
alt {
[] pt.receive(tr_L1CTL_DATA_IND(t_RslChanNr_BCCH(0), ?)) -> value l1_dl {
- /* somehow dec_SystemInformation will try to decode even non-RR as SI */
- if (not (l1_dl.payload.data_ind.payload[1] == '06'O)) {
- log("Ignoring non-RR SI ", l1_dl);
+ var SystemInformationFn sig := { frame_number := l1_dl.dl_info.frame_nr };
+ if (dec_SystemInformationSafe(l1_dl.payload.data_ind.payload, sig.si) != 0) {
+ log("Ignoring non-RR or invalid SI ", l1_dl);
repeat;
}
- var SystemInformationFn sig := {
- frame_number := l1_dl.dl_info.frame_nr,
- si := dec_SystemInformation(l1_dl.payload.data_ind.payload)
- }
+
var integer tc := f_gsm_compute_tc(sig.frame_number);
log("SI received at TC=", tc, ": ", sig.si);
/* append to the per-TC bucket */
@@ -5227,17 +5223,13 @@
runs on test_CT return SystemInformation {
var L1ctlDlMessage l1_dl;
var SystemInformation si;
+ var integer rc;
timer T := 5.0;
T.start;
alt {
[] pt.receive(tr_L1CTL_DATA_IND(t_RslChanNr_BCCH(0), ?)) -> value l1_dl {
- /* somehow dec_SystemInformation will try to decode even non-RR as SI */
- if (not (l1_dl.payload.data_ind.payload[1] == '06'O)) {
- log("Ignoring non-RR SI ", l1_dl);
- repeat;
- }
- si := dec_SystemInformation(l1_dl.payload.data_ind.payload)
- if (si.header.message_type != si_type) {
+ rc := dec_SystemInformationSafe(l1_dl.payload.data_ind.payload, si);
+ if (rc != 0 or si.header.message_type != si_type) {
repeat;
}
}
diff --git a/library/GSM_SystemInformation.ttcn b/library/GSM_SystemInformation.ttcn
index 3c3d96c..9113583 100644
--- a/library/GSM_SystemInformation.ttcn
+++ b/library/GSM_SystemInformation.ttcn
@@ -264,4 +264,29 @@
}
}
+ external function dec_SystemInformationSafeBT(in octetstring stream, out SystemInformation si)
+ return integer /* Decoding result: successful (0) or unsuccessful (1) */
+ with { extension "prototype(backtrack) decode(RAW)" };
+
+ /* Some types of System Information (mostly the Rest Octets) are not fully implemented,
+ * so calling the generic dec_SystemInformation() may result in a DTE. This function
+ * additionally checks RR Protocol Discriminator, and should be used in the most cases. */
+ function dec_SystemInformationSafe(in octetstring stream, out SystemInformation si)
+ return integer {
+ /* Try to decode a given octetstring as System Information */
+ if (dec_SystemInformationSafeBT(stream, si) != 0) {
+ log("Failed to decode (RR) System Information: ", stream);
+ return 1;
+ }
+
+ /* Check the protocol discriminator (we expect RR messages) */
+ if (si.header.rr_protocol_discriminator != bit2int('0110'B)) {
+ log("Protocol discriminator is not RR (!= '0110'B): ",
+ si.header.rr_protocol_discriminator);
+ return 1;
+ }
+
+ return 0;
+ }
+
} with { encode "RAW"; variant "FIELDORDER(msb)" }