diff --git a/epdg/EPDG_Tests.ttcn b/epdg/EPDG_Tests.ttcn index 9aaeb60ed..99e70b6e8 100644 --- a/epdg/EPDG_Tests.ttcn +++ b/epdg/EPDG_Tests.ttcn @@ -478,6 +478,7 @@ private function f_DIA_SWx_RT(template (value) CxDx_3GPP_Reason_Code reason_code var UINT32 hbh_id := f_rnd_octstring(4); var UINT32 ete_id := f_rnd_octstring(4); var octetstring reason_info := char2oct("test"); + var CxDx_3GPP_Reason_Code reason_code_permanent_termination := PERMANENT_TERMINATION; /* Unlike STR, STA contains no IMSI. Register ete_id in DIAMETER_Emulation, * so AIA is forwarded back to us in DIAMETER port instead of MTC_CT.DIAMETER_UNIT. @@ -488,6 +489,14 @@ private function f_DIA_SWx_RT(template (value) CxDx_3GPP_Reason_Code reason_code hbh_id := hbh_id, ete_id := ete_id)); + if (match(reason_code_permanent_termination, reason_code)) { + /* Expect Abort-Session procedure (ASR + ASA) in the S6b interface: */ + as_DIA_S6b_AS_success(); + /* Here AAA-Server starts an ASR + ASA procedure towards ePDG, which forwards it to strongswan: */ + as_GSUP_rx_CL_REQ(OSMO_GSUP_CANCEL_TYPE_WITHDRAW); + f_GSUP_tx_CL_RES(); + } + alt { [] SWx.receive(tr_DIA_SWx_RTA(exp_result_tmpl, hbh_id := hbh_id, ete_id := ete_id)) -> value rx_dia {} [] SWx.receive(PDU_DIAMETER:?) -> value rx_dia { @@ -549,6 +558,25 @@ private function f_S6b_ST_success() runs on EPDG_ConnHdlr { } } +/* Diameter S6b ASR + ASA, TS 29.273 9.1.2.3.4. */ +private altstep as_DIA_S6b_AS_success() runs on EPDG_ConnHdlr { + var PDU_DIAMETER rx_dia; + var template (omit) AVP avp; + var octetstring sess_id; + [] S6b.receive(tr_DIA_S6b_ASR(f_nai())) -> value rx_dia { + avp := f_DIAMETER_get_avp(rx_dia, c_AVP_Code_BASE_NONE_Session_Id); + sess_id := valueof(avp.avp_data.avp_BASE_NONE_Session_Id); + SWx.send(ts_DIA_S6b_ASA(DIAMETER_SUCCESS, + sess_id := sess_id, + hbh_id := rx_dia.hop_by_hop_id, + ete_id := rx_dia.end_to_end_id)); + setverdict(pass); + } + [] S6b.receive(PDU_DIAMETER:?) -> value rx_dia { + Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("Unexpected Diameter msg rx: ", rx_dia)); + } +} + private function f_exp_tr_GTP2C_APCO_in_CreateSessionReq() runs on EPDG_ConnHdlr return template (present) APCO { var template ProtocolIDs_and_ContainerIDs protos, protosV4, protosV6, protosV46; @@ -796,6 +824,10 @@ private altstep as_GTPU_rx_icmp4(template (present) PDU_ICMP expected := ?) runs } } +/************ + * GSUP CEAI + ************/ + private function f_GSUP_tx_SAI_REQ(boolean req_resync := false) runs on EPDG_ConnHdlr { var GSUP_PDU rx_gsup; var template (value) GSUP_IEs pdp_info; @@ -811,7 +843,6 @@ private function f_GSUP_tx_SAI_REQ(boolean req_resync := false) runs on EPDG_Con } } - private altstep as_GSUP_rx_SAI_RES() runs on EPDG_ConnHdlr { var GSUP_PDU rx_gsup; var template (present) GSUP_IE auth_tuple_ie := tr_GSUP_IE_AuthTuple3G( @@ -838,6 +869,20 @@ private altstep as_GSUP_rx_SAI_ERR(template (present) integer cause := ?) runs o } } +private altstep as_GSUP_rx_CL_REQ(template GSUP_CancelType ctype := omit) runs on EPDG_ConnHdlr { + var GSUP_PDU rx_gsup; + + [] GSUP.receive(tr_GSUP_CL_REQ(g_pars.imsi, dom := *, ctype := ctype)) -> value rx_gsup { + } + [] GSUP.receive(GSUP_PDU:?) -> value rx_gsup { + Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("Unexpected GSUP msg rx: ", rx_gsup)); + } +} + +private function f_GSUP_tx_CL_RES() runs on EPDG_ConnHdlr { + GSUP.send(ts_GSUP_CL_RES(g_pars.imsi)); +} + /* GSUP AuthInfo Req + Resp, triggers SWx MAR + MAA. */ private function f_GSUP_AI_success(boolean req_resync := false) runs on EPDG_ConnHdlr { f_GSUP_tx_SAI_REQ(req_resync); @@ -1071,6 +1116,24 @@ testcase TC_hss_initiated_deregister_new_server_assigned() runs on MTC_CT { setverdict(pass); } +private function f_TC_hss_initiated_deregister_permanent_termination(charstring id) runs on EPDG_ConnHdlr { + f_initial_attach(); + /* Procedure should be performed properly: */ + f_DIA_SWx_RT(PERMANENT_TERMINATION, tr_AVP_ResultCode(DIAMETER_SUCCESS)); + /* Subscriber was already removed, it should fail if requested again: */ + var DIAMETER_ts29_229_ExperimentalResultcode erc := DIAMETER_ERROR_USER_UNKNOWN; + f_DIA_SWx_RT(PERMANENT_TERMINATION, tr_AVP_ExperimentalResult(vendor_id_3GPP, int2oct(enum2int(erc), 4))); + f_sleep(3.0); +} +testcase TC_hss_initiated_deregister_permanent_termination() runs on MTC_CT { + var EPDG_ConnHdlrPars pars := f_init_pars(); + var EPDG_ConnHdlr vc_conn; + f_init(); + vc_conn := f_start_handler(refers(f_TC_hss_initiated_deregister_permanent_termination), pars); + vc_conn.done; + setverdict(pass); +} + private function f_TC_concurrent_ues(charstring id) runs on EPDG_ConnHdlr { COORD.send(COORD_CMD_READY); COORD.receive(COORD_CMD_START); @@ -1168,6 +1231,7 @@ control { execute ( TC_ho_wifi_to_lte() ); execute ( TC_s2b_CreateSession_rejected() ); execute ( TC_hss_initiated_deregister_new_server_assigned() ); + execute ( TC_hss_initiated_deregister_permanent_termination() ); execute ( TC_concurrent_ues2() ); execute ( TC_concurrent_ues100() ); execute ( TC_upf_echo_req() ); diff --git a/epdg/expected-results.xml b/epdg/expected-results.xml index bb288119d..ccc69cb3b 100644 --- a/epdg/expected-results.xml +++ b/epdg/expected-results.xml @@ -8,6 +8,7 @@ + diff --git a/library/DIAMETER_Templates.ttcn b/library/DIAMETER_Templates.ttcn index 31ea8216f..933c97b4a 100644 --- a/library/DIAMETER_Templates.ttcn +++ b/library/DIAMETER_Templates.ttcn @@ -569,11 +569,11 @@ template (value) GenericAVP ts_AVP_SuppVendorIdRaw(uint32_t vendor_id) := { template (value) GenericAVP ts_AVP_SuppVendorId(Vendor_Id vendor_id) := ts_AVP_SuppVendorIdRaw(enum2int(vendor_id)); -template (value) GenericAVP ts_AVP_ResultCode(DIAMETER_Resultcode res_code) := { +template (value) GenericAVP ts_AVP_ResultCode(template (value) DIAMETER_Resultcode res_code) := { avp := { avp_header := ts_DIA_Hdr(c_AVP_Code_BASE_NONE_Result_Code), avp_data := { - avp_BASE_NONE_Result_Code := int2oct(enum2int(res_code), 4) + avp_BASE_NONE_Result_Code := int2oct(enum2int(valueof(res_code)), 4) } } } diff --git a/library/DIAMETER_ts29_273_Templates.ttcn b/library/DIAMETER_ts29_273_Templates.ttcn index 0a42d6a62..e1a070061 100644 --- a/library/DIAMETER_ts29_273_Templates.ttcn +++ b/library/DIAMETER_ts29_273_Templates.ttcn @@ -486,4 +486,73 @@ tr_DIA_S6b_STA(template (present) DIAMETER_Resultcode res_code := ?, /* Lots other Optional */ )); + +/* TS 29.273 9.2.2.4.1 Abort-Session-Request (ASR) */ +template (present) PDU_DIAMETER +tr_DIA_S6b_ASR(template (present) charstring username_nai := ?, + template (present) octetstring sess_id := ?, + template (present) charstring orig_host := ?, + template (present) charstring orig_realm := ?, + template (present) charstring dest_realm := ?, + template (present) charstring dest_host := ?, + template (present) UINT32 hbh_id := ?, + template (present) UINT32 ete_id := ?) := + tr_DIAMETER(flags := '1???????'B, + cmd_code := Abort_Session, + 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_OriginHost(orig_host), + tr_AVP_OriginRealm(orig_realm), + tr_AVP_DestinationRealm(dest_realm), + tr_AVP_DestinationHost(dest_host), + tr_AVP_AuthAppId(int2oct(c_DIAMETER_3GPP_S6b_AID, 4)), + tr_AVP_UserName(char2oct_tmpl_present(username_nai)), + tr_AVP_AuthSessionState(NO_STATE_MAINTAINED) + )); + +/* TS 29.273 9.2.2.4.2 Abort-Session-Answer (ASA) */ +template (present) PDU_DIAMETER +tr_DIA_S6b_ASA(template (present) DIAMETER_Resultcode res_code := ?, + 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 := '0???????'B, + cmd_code := Abort_Session, + 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_ResultCode(res_code), + tr_AVP_OriginHost(orig_host), + tr_AVP_OriginRealm(orig_realm) + )); + +template (value) PDU_DIAMETER +ts_DIA_S6b_ASA(template (value) DIAMETER_Resultcode res_code := DIAMETER_SUCCESS, + 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 := Abort_Session, + 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_ResultCode(res_code), + ts_AVP_OriginHost(orig_host), + ts_AVP_OriginRealm(orig_realm) + }); + }