pgw: Introduce test TC_s2b_createSession_v4_no_apco

This test allows initial testing of a session creation through the S2b
interface (emulating an ePDG).

A follow-up test will be added to test the APCO IE (feature which
open5gs-smfd still doesn't support).

Change-Id: I38e469edf0e00feca5a648035b64645e2c905937
diff --git a/library/DIAMETER_Emulation.ttcn b/library/DIAMETER_Emulation.ttcn
index e7481ca..69107d4 100644
--- a/library/DIAMETER_Emulation.ttcn
+++ b/library/DIAMETER_Emulation.ttcn
@@ -37,6 +37,7 @@
 import from DIAMETER_Templates all;
 import from Osmocom_Types all;
 import from IPL4asp_Types all;
+import from TCCConversion_Functions all;
 import from Native_Functions all;
 
 type hexstring IMSI;
@@ -297,7 +298,13 @@
 		return str2hex(oct2char(grp[1].avp.avp_data.avp_DCC_NONE_Subscription_Id_Data));
 	} else {
 		var octetstring imsi_oct := valueof(imsi_avp.avp_data.avp_BASE_NONE_User_Name);
-		return str2hex(oct2char(imsi_oct));
+		var charstring imsi_str := oct2char(imsi_oct);
+		/* Username may be a NAI instead of IMSI: "<IMSI>@nai.epc.mnc<MNC>.mcc<MCC>.3gppnetwork.org" */
+		var integer pos := f_strstr(imsi_str, "@");
+		if (pos != -1) {
+			imsi_str := substr(imsi_str, 0, pos);
+		}
+		return str2hex(imsi_str);
 	}
 }
 
diff --git a/library/DIAMETER_ts29_273_Templates.ttcn b/library/DIAMETER_ts29_273_Templates.ttcn
index e3a6c2f..87d1601 100644
--- a/library/DIAMETER_ts29_273_Templates.ttcn
+++ b/library/DIAMETER_ts29_273_Templates.ttcn
@@ -204,6 +204,35 @@
  *******************************/
 
  /* TS 29.273 9.2.2.5.1 AA-Request (AAR) */
+template (present) PDU_DIAMETER
+tr_DIA_S6b_AAR(template (present) charstring username_nai := ?,
+	       template (present) MIPv6_NONE_MIP6_Feature_Vector mip6_feat_vec := ?,
+	       template (present) charstring apn := ?,
+	       template (present) octetstring sess_id := ?,
+	       template (present) charstring orig_host := ?,
+	       template (present) charstring orig_realm := ?,
+	       template (present) charstring dest_realm := ?,
+	       template (present) UINT32 hbh_id := ?,
+	       template (present) UINT32 ete_id := ?) :=
+	tr_DIAMETER(flags := '1???????'B,
+		    cmd_code := Authorize_Authenticate,
+		    app_id := int2oct(c_DIAMETER_3GPP_S6b_AID, 4),
+		    hbh_id := hbh_id,
+		    ete_id := ete_id,
+		    avps := superset(
+			tr_AVP_SessionId(sess_id),
+			/* Optional: DRMP, */
+			tr_AVP_AuthAppId(int2oct(c_DIAMETER_3GPP_S6b_AID, 4)),
+			tr_AVP_OriginHost(orig_host),
+			tr_AVP_OriginRealm(orig_realm),
+			tr_AVP_DestinationRealm(dest_realm),
+			tr_AVP_AuthRequestType(AUTHORIZE_ONLY),
+			tr_AVP_UserName(char2oct_tmpl_present(username_nai)),
+			tr_AVP_MIP6FeatureVector(mip6_feat_vec),
+			tr_AVP_ServiceSelection(apn)
+			/* TODO: Lots other optional */
+	));
+
 template (value) PDU_DIAMETER
 ts_DIA_S6b_AAR(template (value) charstring username_nai,
 	       template (value) MIPv6_NONE_MIP6_Feature_Vector mip6_feat_vec,
@@ -257,6 +286,27 @@
 			tr_AVP_OriginRealm(orig_realm)
 	));
 
+template (value) PDU_DIAMETER
+ts_DIA_S6b_AAA(template (value) octetstring sess_id := c_def_sess_id,
+	       template (value) charstring orig_host := "aaa.localdomain",
+	       template (value) charstring orig_realm := "localdomain",
+	       template (value) charstring dest_realm := "localdomain",
+	       template (value) UINT32 hbh_id := '00000000'O,
+	       template (value) UINT32 ete_id := '00000000'O) :=
+	ts_DIAMETER(flags := '01000000'B,
+		    cmd_code := Authorize_Authenticate,
+		    app_id := int2oct(c_DIAMETER_3GPP_S6b_AID, 4),
+		    hbh_id := hbh_id, ete_id := ete_id,
+		    avps := {
+			ts_AVP_SessionId(sess_id),
+			/* Optional: DRMP, */
+			ts_AVP_AuthAppId(int2oct(c_DIAMETER_3GPP_S6b_AID, 4)),
+			ts_AVP_AuthRequestType(AUTHORIZE_ONLY),
+			ts_AVP_ResultCode(DIAMETER_SUCCESS),
+			ts_AVP_OriginHost(orig_host),
+			ts_AVP_OriginRealm(orig_realm)
+	});
+
  /* TS 29.273 9.2.2.3.1 Session-Termination-Request (STR) Command,
   * Table 9.1.2.3.1/1: S6b Session Termination Request (STR), based on RFC 6733 8.4.1 */
 template (value) PDU_DIAMETER
diff --git a/library/GTPv2_Templates.ttcn b/library/GTPv2_Templates.ttcn
index 431415a..c842230 100644
--- a/library/GTPv2_Templates.ttcn
+++ b/library/GTPv2_Templates.ttcn
@@ -407,6 +407,20 @@
 }
 
 /* 8.17 */
+type enumerated GTP2C_RAT_Type {
+	GTP2C_RAT_reserved		('00'O),
+	GTP2C_RAT_UTRAN 		('01'O),
+	GTP2C_RAT_GERAN			('02'O),
+	GTP2C_RAT_WLAN			('03'O),
+	GTP2C_RAT_GAN 			('04'O),
+	GTP2C_RAT_HSPA_EVOLUTION	('05'O),
+	GTP2C_RAT_EUTRAN		('06'O),
+	GTP2C_RAT_Virtual		('07'O),
+	GTP2C_RAT_EUTRAN_NB_IoT		('08'O),
+	GTP2C_RAT_LTE_M			('09'O),
+	GTP2C_RAT_NR			('0A'O)
+} with { variant "FIELDLENGTH(8)" encode "RAW" };
+
 template (value) RAT_Type ts_GTP2C_RatType(template (value) integer rat) := {
 	elementIdentifier := '52'O,
 	lengthIndicator := 0, /* overwritten */
@@ -1046,6 +1060,7 @@
 			   template (present) GTP2C_Cause cause := ?,
 			   template FullyQualifiedTEID_List fteids := *,
 			   template PDN_AddressAllocation addr := *,
+			   template APN_Restriction apn_restriction := *,
 			   template BearerContextGrouped_List bctxg := *) :=
 tr_PDU_GTP2C(d_teid, seq, {
 	createSessionResponse := {
@@ -1055,7 +1070,7 @@
 		heNBInformationReporting := *,
 		fullyQualifiedTEID := fteids,
 		pDN_AddressAllocation := addr,
-		aPN_Restriction := ?,
+		aPN_Restriction := apn_restriction,
 		ambr := *,
 		linkedEPS_Bearer_ID := *,
 		protocolConfigOptions := *,
diff --git a/library/Osmocom_Types.ttcn b/library/Osmocom_Types.ttcn
index d034a74..6653408 100644
--- a/library/Osmocom_Types.ttcn
+++ b/library/Osmocom_Types.ttcn
@@ -179,6 +179,15 @@
 	}
 }
 
+function char2oct_tmpl_present(template (present) charstring inp) return template (present) octetstring
+{
+	if (istemplatekind(inp, "?")) {
+		return ?;
+	} else {
+		return char2oct(valueof(inp));
+	}
+}
+
 function hex2str_tmpl(template hexstring inp) return template charstring
 {
 	if (istemplatekind(inp, "omit")) {