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/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)" }