pespin has uploaded this change for review. ( https://gerrit.osmocom.org/c/osmo-ttcn3-hacks/+/40408?usp=email )
Change subject: 5gc: Initial NAS receiving support ......................................................................
5gc: Initial NAS receiving support
With this patch it is already possible to receive the NAS Auth Request in the test ConnHdlr.
nas.git dep needs updating to include a new patch fixing decoding of NG_AUTHENTICATION_REQUEST.
Change-Id: I6697f30f95777fc9aed16a529a669d10f42c57be --- M 5gc/C5G_Tests.ttcn M 5gc/create_test_subscribers.sh M 5gc/gen_links.sh M deps/Makefile M library/NGAP_Emulation.ttcn M library/NGAP_Functions.ttcn A library/NG_NAS_Osmo_Templates.ttcn M library/Osmocom_Types.ttcn 8 files changed, 273 insertions(+), 96 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/osmo-ttcn3-hacks refs/changes/08/40408/1
diff --git a/5gc/C5G_Tests.ttcn b/5gc/C5G_Tests.ttcn index 62553fc..320d61f 100644 --- a/5gc/C5G_Tests.ttcn +++ b/5gc/C5G_Tests.ttcn @@ -17,6 +17,7 @@ import from Misc_Helpers all;
import from Osmocom_Types all; +import from GSM_Types all;
import from NGAP_PDU_Descriptions all; import from NGAP_IEs all; @@ -29,10 +30,14 @@ import from NGAP_Functions all; import from NGAP_Emulation all;
+import from NAS_CommonTypeDefs all; + import from NG_NAS_Common all; import from NG_NAS_MsgContainers all; import from NAS_CommonTemplates all; import from NG_NAS_Templates all; + +import from NG_NAS_Osmo_Templates all; import from NG_NAS_Functions all;
/* (maximum) number of emulated eNBs */ @@ -48,7 +53,9 @@ integer mp_5gc_ngap_port := 38412; charstring mp_local_ngap_ip := "127.0.0.1"; integer mp_local_ngap_port := 50000; - PLMNIdentity mp_plmn_id := '99f907'O; + GsmMcc mp_mcc := '999'H; + GsmMnc mp_mnc := '70'H; + hexstring mp_imsi := '999700000000000'H; uint24_t mp_tac := 1; }
@@ -86,9 +93,9 @@ /* copied over from MTC_CT on start of component */ UeParams ue_pars, /* currently used 5GC (index into ngran_pars, NGAP, ...) */ - integer c5g_idx//, + integer c5g_idx, /* Currently set KSI */ - //NAS_KeySetIdentifierV kset_id + NAS_KeySetIdentifier kset_id }
/* send incoming unit data messages (like reset) to global NGAP_UNIT port */ @@ -108,17 +115,18 @@ remote_ip := mp_5gc_ngap_ip, remote_sctp_port := mp_5gc_ngap_port, local_ip := mp_local_ngap_ip, - local_sctp_port := mp_local_ngap_port + num //, - //role := NAS_ROLE_UE + local_sctp_port := mp_local_ngap_port + num, + role := NGAP_NAS_ROLE_UE }; + var PLMNIdentity plmn_id := f_enc_mcc_mnc(mp_mcc, mp_mnc); var NGRANParams ngran_pars := { - global_ngran_id := valueof(m_globalRANNodeID_globalGNB_ID(m_ie_globalGnbId(mp_plmn_id, int2bit(num, 22)))), - cell_identity := { nR_CGI := valueof(m_nR_CGI(mp_plmn_id, int2bit(num, 36))) }, + global_ngran_id := valueof(m_globalRANNodeID_globalGNB_ID(m_ie_globalGnbId(plmn_id, int2bit(num, 22)))), + cell_identity := { nR_CGI := valueof(m_nR_CGI(plmn_id, int2bit(num, 36))) }, supported_ta_list := { { tAC := int2oct(mp_tac, 3), broadcastPLMNList := { - valueof(m_ie_broadcastPLMNItem(mp_plmn_id, { m_sliceSupportItem(m_s_NSSAI('01'O)) })) + valueof(m_ie_broadcastPLMNItem(plmn_id, { m_sliceSupportItem(m_s_NSSAI('01'O)) })) }, iE_Extensions := omit } @@ -136,17 +144,17 @@ friend function f_init_one_ue(inout UeParams uep, integer imsi_suffix) {
uep := { - imsi := f_gen_imsi(imsi_suffix), + imsi := f_concat_pad(lengthof(mp_imsi), substr(mp_imsi, 0, lengthof(mp_imsi) - 6), imsi_suffix), ue_ip := "192.168.123.50" } } -friend function f_init_ngap(integer imsi_suffix) runs on MTC_CT { +friend function f_init_ngap(integer imsi_suffix := 0) runs on MTC_CT { var integer i; for (i := 0; i < NUM_NGRAN; i := i+1) { f_init_one_ngran(i); } for (i := 0; i < NUM_UE; i := i+1) { - f_init_one_ue(g_ue_pars[i], i*1000 + imsi_suffix); + f_init_one_ue(g_ue_pars[i], 1000*imsi_suffix + i); } }
@@ -156,8 +164,8 @@ var ConnHdlrPars pars := { ngran_pars := g_ngran_pars, ue_pars := g_ue_pars[ue_idx], - c5g_idx := 0//, - //kset_id := valueof(ts_NAS_KeySetIdentifierV('000'B, c_NAS_TSC_NATIVE_SEC_CTX)) + c5g_idx := 0, + kset_id := valueof(cs_NAS_KeySetIdentifier_lv(tsc_NasKsi_NoKey, '0'B)) }; return pars; } @@ -203,6 +211,14 @@ iE_Extensions := omit }
+private function f_SUCI_IMSI() runs on ConnHdlr return octetstring { + var hexstring imsi := g_pars.ue_pars.imsi; + var GsmMcc mcc := substr(imsi, 0, 3); + var GsmMnc mnc := substr(imsi, 3, 2); + var octetstring imsi_suffix := imsi_hex2oct(substr(imsi, lengthof(imsi)-10, 10)); + return f_enc_mcc_mnc(mcc, mnc) & '21430001'O & imsi_suffix; +} + friend function f_ngap_setup(integer idx := 0, template (omit) NGAP_IEs.Cause cause := omit) runs on MTC_CT { var template (present) NGAP_IEs.Cause exp_cause := ?; var boolean exp_fail := false; @@ -243,6 +259,25 @@ } }
+private function f_tr_ConnHdlr_kset_id() runs on ConnHdlr return template (present) NAS_KeySetIdentifier { + /* KSI not yet set, expect whatever assignment from network: */ + if (g_pars.kset_id.nasKeySetId == tsc_NasKsi_NoKey) { + return cr_NAS_KeySetIdentifier(?, ?); + } else { + /* Expect specific kset_id. Upon transmitting it UE->Network, f_attach() + * has updated it to the expected value. */ + return g_pars.kset_id; + } +} + +private altstep as_ngap_handle_auth() runs on ConnHdlr { + var NG_NAS_DL_Message_Type rx_nas; + var template (present) NAS_KeySetIdentifier kset_id := f_tr_ConnHdlr_kset_id(); + [] NGAP.receive(cr_NG_AUTHENTICATION_REQUEST) -> value rx_nas { + log("Rx NAS message: ", rx_nas); + } +} + private function f_register() runs on ConnHdlr { var template (value) UserLocationInformation p_ueLocInf; var template (value) NGAP_PDU tx_pdu; @@ -258,10 +293,11 @@ ));
nas_ul_msg := cs_NG_REGISTRATION_REQUEST(cs_RegistrationType(tsc_NG_RegistrationInitial, '1'B), - tsc_NasKsi_NoKey, - '0'B, + g_pars.kset_id.nasKeySetId, + g_pars.kset_id.tsc, cs_NG_MobileIdentitySUCI('0000'B /* Type IMSI */, - '00f110214300014444330302'O)); + f_SUCI_IMSI()), + p_UESecurityCap := cs_NG_UE_SecurityCapability); nas_pdu := enc_NG_NAS_UL_Message_Type(valueof(nas_ul_msg));
@@ -271,7 +307,7 @@ mo_Signalling));
NGAP.send(tx_pdu); - f_sleep(5.0); + as_ngap_handle_auth();
/* TODO: handle Auth, SecurityModeCommand, InitialContextSetup, PDUSessionresource, */ } @@ -279,21 +315,21 @@ /* NG Setup procedure to 5GC using a Global gNB ID containing unknown/foreign PLMN. * Related: https://github.com/open5gs/open5gs/issues/3544 */ testcase TC_ng_setup_unknown_global_gnb_id_plmn() runs on MTC_CT { - f_init_ngap(1); + f_init_ngap(); g_ngran_pars[0].global_ngran_id.globalGNB_ID.pLMNIdentity := '62F224'O; f_ngap_setup(0); }
/* Unsuccessful NG Setup procedure to AMF (wrong PLMN) */ testcase TC_ng_setup_wrong_tac() runs on MTC_CT { - f_init_ngap(2); + f_init_ngap(); g_ngran_pars[0].supported_ta_list[0].broadcastPLMNList[0].pLMNIdentity := '62F224'O; f_ngap_setup(0, {misc:=unknown_PLMN_or_SNPN}); }
/* NG Setup procedure to 5GC using a correct Global gNB ID. */ testcase TC_ng_setup() runs on MTC_CT { - f_init_ngap(3); + f_init_ngap(); f_ngap_setup(0); }
@@ -302,7 +338,7 @@ f_register(); } testcase TC_ng_register() runs on MTC_CT { - f_init_ngap(4); + f_init_ngap(); f_ngap_setup(0);
var ConnHdlrPars pars := f_init_pars(ue_idx := 0); diff --git a/5gc/create_test_subscribers.sh b/5gc/create_test_subscribers.sh index f5b6c5b..a400e0f 100755 --- a/5gc/create_test_subscribers.sh +++ b/5gc/create_test_subscribers.sh @@ -18,10 +18,10 @@ done
# Create a test subscriber with IMSI=001010000000000 -$DBCTL_CMD add 001010000000000 3c6e0b8a9c15224a8228b9a98ca1531d 762a2206fe0b4151ace403c86a11e479 +$DBCTL_CMD add 999700000000000 3c6e0b8a9c15224a8228b9a98ca1531d 762a2206fe0b4151ace403c86a11e479
# Mark test subscriber with IMSI=001010000000001 as: # Subscriber-Status=OPERATOR_DETERMINED_BARRING (1) # Operator-Determined-Barring="Barring of all outgoing inter-zonal calls except those directed to the home PLMN country" (7) -$DBCTL_CMD add 001010000000001 3c6e0b8a9c15224a8228b9a98ca1531d 762a2206fe0b4151ace403c86a11e479 -$DBCTL_CMD subscriber_status 001010000000001 1 7 +$DBCTL_CMD add 999700000000001 3c6e0b8a9c15224a8228b9a98ca1531d 762a2206fe0b4151ace403c86a11e479 +$DBCTL_CMD subscriber_status 999700000000001 1 7 diff --git a/5gc/gen_links.sh b/5gc/gen_links.sh index 2cab445..295ca24 100755 --- a/5gc/gen_links.sh +++ b/5gc/gen_links.sh @@ -66,7 +66,7 @@ FILES+="SCTP_Templates.ttcn " FILES+="DNS_Helpers.ttcn " FILES+="NGAP_CodecPort.ttcn NGAP_CodecPort_CtrlFunctDef.cc NGAP_CodecPort_CtrlFunct.ttcn NGAP_Functions.ttcn NGAP_Emulation.ttcn " -FILES+="NG_NAS_Functions.ttcn " +FILES+="NG_NAS_Osmo_Templates.ttcn NG_NAS_Functions.ttcn " gen_links $DIR $FILES
gen_links_finish diff --git a/deps/Makefile b/deps/Makefile index b4a411a..a97b0a9 100644 --- a/deps/Makefile +++ b/deps/Makefile @@ -85,7 +85,7 @@ # Do not put references to branches here, except for local testing: this breaks the caching # logic of docker containers, which only invalidate their cached ttcn3 dependencies if this # file changed. -nas_commit= 205e24167517500ba2d49322dfa1754ab8a0fc43 +nas_commit= a82a1ce22ea056971f47a7d02389f989e2f4183b titan.Libraries.TCCUsefulFunctions_commit= R.35.B-6-gb3687da titan.ProtocolEmulations.M3UA_commit= b58f92046e48a7b1ed531e243a2319ebca53bf4c titan.ProtocolEmulations.SCCP_commit= 750a3e836831e58eae59d4757ef5d0c759f9ca5d diff --git a/library/NGAP_Emulation.ttcn b/library/NGAP_Emulation.ttcn index e885a4d..46f1d63 100644 --- a/library/NGAP_Emulation.ttcn +++ b/library/NGAP_Emulation.ttcn @@ -33,8 +33,16 @@ * SPDX-License-Identifier: GPL-2.0-or-later */
+import from General_Types all; +import from Osmocom_Types all; +import from IPL4asp_Types all; +import from DNS_Helpers all; + +import from SCTP_Templates all; + import from NGAP_CodecPort all; import from NGAP_CodecPort_CtrlFunct all; +import from NGAP_CommonDataTypes all; import from NGAP_Types all; import from NGAP_Constants all; import from NGAP_PDU_Contents all; @@ -42,13 +50,14 @@ import from NGAP_IEs all; import from NGAP_Templates all; import from NGAP_Functions all; -import from SCTP_Templates all;
-import from General_Types all; -import from Osmocom_Types all; -import from IPL4asp_Types all; -import from DNS_Helpers all; +import from NG_NAS_MsgContainers all; +import from NG_NAS_Functions all;
+type enumerated NGAP_NAS_Role { + NGAP_NAS_ROLE_UE, /* ATS implements/emulates UE */ + NGAP_NAS_ROLE_AMF /* ATS implements/emulates AMF */ +};
type component NGAP_ConnHdlr { port NGAP_Conn_PT NGAP; @@ -58,7 +67,7 @@
/* port between individual per-connection components and this dispatcher */ type port NGAP_Conn_PT message { - inout NGAP_PDU; + inout NGAP_PDU, NG_NAS_UL_Message_Type, NG_NAS_DL_Message_Type; } with { extension "internal" };
@@ -135,7 +144,7 @@ type record AssociationData { NGAP_ConnHdlr comp_ref, /* component handling this UE connection */ uint32_t ran_ue_ngap_id optional, /* eNB side NGAP ID */ - uint40_t amf_ue_ngap_id optional//, /* MME side NGAP ID */ + uint40_t amf_ue_ngap_id optional//, /* AMF side NGAP ID */ //EUTRAN_CGI cgi optional, //TAI tai optional, //NAS_UE_State nus @@ -182,8 +191,8 @@ HostName remote_ip, IPL4asp_Types.PortNumber remote_sctp_port, HostName local_ip, - IPL4asp_Types.PortNumber local_sctp_port//, - //NAS_Role role + IPL4asp_Types.PortNumber local_sctp_port, + NGAP_NAS_Role role }
function tr_NGAP_RecvFrom_R(template NGAP_PDU msg) @@ -205,8 +214,8 @@ var integer i; log("f_ngap_ids_known(",amf_id,", ",ran_id,")"); for (i := 0; i < sizeof(NGapAssociationTable); i := i+1) { - log("tbl[",i,"]: mme=", NGapAssociationTable[i].amf_ue_ngap_id, - ", enb=", NGapAssociationTable[i].ran_ue_ngap_id); + log("tbl[",i,"]: amf=", NGapAssociationTable[i].amf_ue_ngap_id, + ", ran=", NGapAssociationTable[i].ran_ue_ngap_id); /* skip empty records */ if (NGapAssociationTable[i].amf_ue_ngap_id == omit and NGapAssociationTable[i].ran_ue_ngap_id == omit) { @@ -214,11 +223,11 @@ continue; } if (NGapAssociationTable[i].amf_ue_ngap_id == omit) { - log("entry ", i, " has no MME ID yet (enb=", NGapAssociationTable[i].ran_ue_ngap_id); - /* Table doesn't yet know the MME side ID, let's look-up only + log("entry ", i, " has no AMF ID yet (ran=", NGapAssociationTable[i].ran_ue_ngap_id); + /* Table doesn't yet know the AMF side ID, let's look-up only * based on the eNB side ID */ if (match(NGapAssociationTable[i].ran_ue_ngap_id, ran_id)) { - /* update table with MME side ID */ + /* update table with AMF side ID */ NGapAssociationTable[i].amf_ue_ngap_id := valueof(amf_id); return true; } @@ -256,7 +265,7 @@ } } } - setverdict(fail, "NGAP Association Table not found by ENB-ID=", ran_id, " MME-ID=", amf_id); + setverdict(fail, "NGAP Association Table not found by RAN-ID=", ran_id, " AMF-ID=", amf_id); mtc.stop; }
@@ -346,20 +355,20 @@ return mrf.msg; }
-//function handle_NGAP_UeContextReleaseCmd(template (present) NGAP_PDU rel_cmd) runs on NGAP_Emulation_CT { +function handle_NGAP_UeContextReleaseCmd(template (present) NGAP_PDU rel_cmd) runs on NGAP_Emulation_CT { // if (ispresent(rel_cmd.initiatingMessage.value_.uEContextReleaseCommand.protocolIEs[0].value_.uE_NGAP_IDs.uE_NGAP_ID_pair)) { -// var template AMF_UE_NGAP_ID mme_ue_id; -// var template RAN_UE_NGAP_ID enb_ue_id; +// var template AMF_UE_NGAP_ID amf_ue_id; +// var template RAN_UE_NGAP_ID ran_ue_id; // var integer assoc_id; // var NGAP_ConnHdlr vc_conn // -// mme_ue_id := rel_cmd.initiatingMessage.value_.uEContextReleaseCommand.protocolIEs[0].value_.uE_NGAP_IDs.uE_NGAP_ID_pair.mME_UE_NGAP_ID; -// enb_ue_id := rel_cmd.initiatingMessage.value_.uEContextReleaseCommand.protocolIEs[0].value_.uE_NGAP_IDs.uE_NGAP_ID_pair.eNB_UE_NGAP_ID; +// amf_ue_id := rel_cmd.initiatingMessage.value_.uEContextReleaseCommand.protocolIEs[0].value_.uE_NGAP_IDs.uE_NGAP_ID_pair.mME_UE_NGAP_ID; +// ran_ue_id := rel_cmd.initiatingMessage.value_.uEContextReleaseCommand.protocolIEs[0].value_.uE_NGAP_IDs.uE_NGAP_ID_pair.eNB_UE_NGAP_ID; // -// assoc_id := f_assoc_id_by_ngap_ids(mme_ue_id, enb_ue_id); +// assoc_id := f_assoc_id_by_ngap_ids(amf_ue_id, ran_ue_id); // vc_conn := NGapAssociationTable[assoc_id].comp_ref; // -// f_ngap_id_table_del(vc_conn, valueof(enb_ue_id)); +// f_ngap_id_table_del(vc_conn, valueof(ran_ue_id)); // } else { // /* TODO: The UE CONTEXT RELEASE COMMAND (see also: 3GPP TS 36.413, section 9.1.4.6), may identify the // * context by either an uE_NGAP_ID_pair (AMF_UE_NGAP_ID and RAN_UE_NGAP_ID) or an AMF_UE_NGAP_ID alone. @@ -367,7 +376,7 @@ // setverdict(fail, "complete implementation of UeContextReleaseCmd handling"); // mtc.stop; // } -//} +}
private function SendToNGapExpectTableProc(NGAP_PDU msg) runs on NGAP_Emulation_CT { var integer procedureCode; @@ -395,6 +404,19 @@ return; }
+template ProcedureCode tr_NGAP_ProcedureCode_non_UErelated := +(id_NGSetup, id_RANConfigurationUpdate, id_AMFStatusIndication, id_NGReset, id_ErrorIndication, id_OverloadStart, id_OverloadStop); +template (present) NGAP_PDU +tr_NGAP_nonUErelated := (mw_ngap_initMsg({procedureCode := tr_NGAP_ProcedureCode_non_UErelated, + criticality := ?, + value_ := ?}), + mw_ngap_succMsg({procedureCode := tr_NGAP_ProcedureCode_non_UErelated, + criticality := ?, + value_ := ?}), + mw_ngap_unsuccMsg({procedureCode := tr_NGAP_ProcedureCode_non_UErelated, + criticality := ?, + value_ := ?})); + function main(NGAPOps ops, NGAP_conn_parameters p, charstring id) runs on NGAP_Emulation_CT { var Result res; g_pars := p; @@ -430,7 +452,7 @@ var integer procedureCode; var NGAP_RecvFrom mrf; var NGAP_PDU msg; - var charstring vlr_name, mme_name; + var charstring vlr_name, amf_name; var integer ai; var octetstring kasme;
@@ -458,54 +480,59 @@ NGAP.send(t_NGAP_Send(g_ngap_conn_id, msg)); }
- /* NGAP received from peer (MME) */ + /* NGAP received from peer (AMF) */ [] NGAP.receive(tr_NGAP_RecvFrom_R(?)) -> value mrf { -// if (match(mrf.msg, tr_NGAP_nonUErelated)) { + if (match(mrf.msg, tr_NGAP_nonUErelated)) { /* non-UE-related NGAP message */ SendToNGapExpectTableProc(mrf.msg); var template NGAP_PDU resp := ops.unitdata_cb.apply(mrf.msg); if (isvalue(resp)) { NGAP.send(t_NGAP_Send(g_ngap_conn_id, valueof(resp))); } -// } else { -// /* Ue-related NGAP message */ -// /* obtain MME + ENB UE NGAP ID */ -// var template (omit) AMF_UE_NGAP_ID mme_ue_id := f_NGAP_get_AMF_UE_NGAP_ID(mrf.msg); -// var template (omit) RAN_UE_NGAP_ID enb_ue_id := f_NGAP_get_RAN_UE_NGAP_ID(mrf.msg); -// /* check if those IDs are known in our table */ -// if (f_ngap_ids_known(mme_ue_id, enb_ue_id)) { -// /* if yes, dispatch to the ConnHdlr for this Ue-Connection */ -// var template (omit) octetstring nas_enc; -// var integer assoc_id := f_assoc_id_by_ngap_ids(mme_ue_id, enb_ue_id); -// vc_conn := NGapAssociationTable[assoc_id].comp_ref; -// nas_enc := f_NGAP_get_NAS_PDU(mrf.msg); -// if (isvalue(nas_enc)) { -// nas := dec_PDU_NAS_EPS(valueof(nas_enc)); -// if (match(nas, tr_NAS_EMM_SecurityProtected)) { -// nas := f_nas_try_decaps(NGapAssociationTable[assoc_id].nus, nas); -// } -// /* DL/UlNasTransport are not interesting, don't send them */ -// if (not match(mrf.msg, (tr_NGAP_DlNasTransport, tr_NGAP_UlNasTransport))) { -// /* send raw NGAP */ -// NGAP_CLIENT.send(mrf.msg) to vc_conn; -// } -// /* send decoded NAS */ -// NGAP_CLIENT.send(nas) to vc_conn; -// } else { -// /* send raw NGAP */ -// NGAP_CLIENT.send(mrf.msg) to vc_conn; -// } -// } else { -// /* if not, call create_cb so it can create new ConnHdlr */ -// vc_conn := ops.create_cb.apply(mrf.msg, mme_ue_id, enb_ue_id, id); -// f_ngap_id_table_add(vc_conn, mme_ue_id, valueof(enb_ue_id)); -// NGAP_CLIENT.send(mrf.msg) to vc_conn; -// } -// if (match(mrf.msg, tr_NGAP_UeContextReleaseCmd)) { -// handle_NGAP_UeContextReleaseCmd(mrf.msg); -// } -// } + } else { + /* Ue-related NGAP message */ + /* obtain AMF + NGRAN UE NGAP ID */ + var template (omit) AMF_UE_NGAP_ID amf_ue_id := f_NGAP_get_AMF_UE_NGAP_ID(mrf.msg); + var template (omit) RAN_UE_NGAP_ID ran_ue_id := f_NGAP_get_RAN_UE_NGAP_ID(mrf.msg); + /* check if those IDs are known in our table */ + if (f_ngap_ids_known(amf_ue_id, ran_ue_id)) { + /* if yes, dispatch to the ConnHdlr for this Ue-Connection */ + var template (omit) octetstring nas_enc; + var integer assoc_id := f_assoc_id_by_ngap_ids(amf_ue_id, ran_ue_id); + vc_conn := NGapAssociationTable[assoc_id].comp_ref; + nas_enc := f_NGAP_get_NAS_PDU(mrf.msg); + if (isvalue(nas_enc)) { + if (g_pars.role == NGAP_NAS_ROLE_UE) { + var NG_NAS_DL_Message_Type dl_nas := dec_NG_NAS_DL_Message_Type(valueof(nas_enc)); +// if (match(dl_nas, tr_NAS_EMM_SecurityProtected)) { +// dl_nas := f_nas_try_decaps(NGapAssociationTable[assoc_id].nus, dl_nas); +// } + /* DL/UlNasTransport are not interesting, don't send them */ + if (not match(mrf.msg, mw_ngap_initMsg(mw_n2_DownlinkNASTransport))) { + /* send raw NGAP */ + NGAP_CLIENT.send(mrf.msg) to vc_conn; + } + /* send decoded NAS */ + NGAP_CLIENT.send(dl_nas) to vc_conn; + } else { + log("Incoming NAS HANDLING in AMF role not supported!"); + var NG_NAS_UL_Message_Type ul_nas := dec_NG_NAS_UL_Message_Type(valueof(nas_enc)); + } + } else { + /* send raw NGAP */ + NGAP_CLIENT.send(mrf.msg) to vc_conn; + } + } else { + /* if not, call create_cb so it can create new ConnHdlr */ + vc_conn := ops.create_cb.apply(mrf.msg, amf_ue_id, ran_ue_id, id); + f_ngap_id_table_add(vc_conn, amf_ue_id, valueof(ran_ue_id)); + NGAP_CLIENT.send(mrf.msg) to vc_conn; + } + if (match(mrf.msg, mw_ngap_initMsg(mw_n2_UEContextReleaseCommand))) { + handle_NGAP_UeContextReleaseCmd(mrf.msg); + } } + } [] NGAP.receive(tr_SctpAssocChange) { } [] NGAP.receive(tr_SctpPeerAddrChange) { } [] NGAP_PROC.getcall(NGAPEM_register:{?,?,?}) -> param(amf_id, ran_id, vc_conn) { diff --git a/library/NGAP_Functions.ttcn b/library/NGAP_Functions.ttcn index 7ab2f5a..1323ab9 100644 --- a/library/NGAP_Functions.ttcn +++ b/library/NGAP_Functions.ttcn @@ -21,7 +21,10 @@ { if (ischosen(ngap.initiatingMessage)) { var InitiatingMessage im := ngap.initiatingMessage; - select (ngap) { + select (im) { + case (mw_n2_DownlinkNASTransport) { + return im.value_.downlinkNASTransport.protocolIEs[0].value_.aMF_UE_NGAP_ID; + } case (?) { return omit; /* TODO */ @@ -31,7 +34,7 @@ } } else if (ischosen(ngap.successfulOutcome)) { var SuccessfulOutcome so := ngap.successfulOutcome; - select (ngap) { + select (so) { case (?) { return omit; /* TODO */ @@ -41,7 +44,7 @@ } } else if (ischosen(ngap.unsuccessfulOutcome)) { var UnsuccessfulOutcome uo := ngap.unsuccessfulOutcome; - select (ngap) { + select (uo) { case (?) { return omit; /* TODO */ @@ -61,11 +64,14 @@ case (mw_n2_initialUeMessage) { return im.value_.InitialUEMessage.protocolIEs[0].value_.RAN_UE_NGAP_ID; } + case (mw_n2_DownlinkNASTransport) { + return im.value_.downlinkNASTransport.protocolIEs[1].value_.RAN_UE_NGAP_ID; + } /* TODO */ } } else if (ischosen(ngap.successfulOutcome)) { var SuccessfulOutcome so := ngap.successfulOutcome; - select (ngap) { + select (so) { case (?) { return omit; /* TODO */ @@ -75,7 +81,7 @@ } } else if (ischosen(ngap.unsuccessfulOutcome)) { var UnsuccessfulOutcome uo := ngap.unsuccessfulOutcome; - select (ngap) { + select (uo) { case (?) { return omit; /* TODO */ @@ -87,4 +93,41 @@ return omit; }
+function f_NGAP_get_NAS_PDU(NGAP_PDU ngap) return template (omit) NAS_PDU +{ + var integer i, j; + + if (ischosen(ngap.initiatingMessage)) { + var InitiatingMessage im := ngap.initiatingMessage; + select (im) { + case (mw_n2_DownlinkNASTransport) { + var DownlinkNASTransport msg := im.value_.DownlinkNASTransport; + for (i := 0; i < lengthof(msg.protocolIEs); i := i+1) { + if (msg.protocolIEs[i].id == id_NAS_PDU) { + return msg.protocolIEs[i].value_.NAS_PDU; + } + } + } + case (mw_n2_UplinkNASTransport) { + var UplinkNASTransport msg := im.value_.UplinkNASTransport; + for (i := 0; i < lengthof(msg.protocolIEs); i := i+1) { + if (msg.protocolIEs[i].id == id_NAS_PDU) { + return msg.protocolIEs[i].value_.NAS_PDU; + } + } + } + case (mw_n2_initialUeMessage) { + var InitialUEMessage msg := im.value_.InitialUEMessage; + for (i := 0; i < lengthof(msg.protocolIEs); i := i+1) { + if (msg.protocolIEs[i].id == id_NAS_PDU) { + return msg.protocolIEs[i].value_.NAS_PDU; + } + } + return omit; + } + } + } + return omit; +} + } diff --git a/library/NG_NAS_Osmo_Templates.ttcn b/library/NG_NAS_Osmo_Templates.ttcn new file mode 100644 index 0000000..a22c542 --- /dev/null +++ b/library/NG_NAS_Osmo_Templates.ttcn @@ -0,0 +1,71 @@ +/* Our own NG NAS templates on top of deps/nas/ttcn/Lib3GPP/NG_NAS/NG_NAS_Templates.ttcn. */ +module NG_NAS_Osmo_Templates { + +/* (C) 2025 by sysmocom - s.f.m.c. GmbH info@sysmocom.de + * All rights reserved. + * + * Released under the terms of GNU General Public License, Version 2 or + * (at your option) any later version. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +import from CommonDefs all; +import from NAS_CommonTypeDefs all; +import from NAS_CommonTemplates all; +import from NG_NAS_Common all; +import from NG_NAS_TypeDefs all; +import from NG_NAS_Templates all; +import from NG_NAS_MsgContainers all; + +/* 24.501 cl. 9.11.3.54 */ +private function f_cs_NG_UE_SecurityCapability_length(template (omit) O1_Type eeaCap := omit, + template (omit) O1_Type eiaCap := omit) +return integer { + var integer len := 2; + if (isvalue(eeaCap)) { + len := len + 1; + } + if (isvalue(eiaCap)) { + len := len + 1; + } + return len; +} +template (value) NG_UE_SecurityCapability cs_NG_UE_SecurityCapability(template (value) O1_Type ngeaCap := 'f0'O, + template (value) O1_Type ngiaCap := '70'O, + template (omit) O1_Type eeaCap := omit, + template (omit) O1_Type eiaCap := omit) := +{ + iei := '2E'O, + iel := int2oct(f_cs_NG_UE_SecurityCapability_length(eeaCap, eiaCap), 1), + ngeaCap := ngeaCap, + ngiaCap := ngiaCap, + eeaCap := eeaCap, + eiaCap := eiaCap, + spare := omit +}; + + +/* 24.501 cl. 8.2.1 */ +template (present) NG_NAS_DL_Message_Type cr_NG_AUTHENTICATION_REQUEST(template (present) NAS_KsiValue p_KeySetId := ?, + template (present) ABBA p_ABBA := ?, + template RAND p_RAND := *, + template AUTN p_AUTN := *, + template EAP_Message p_EAP := * + ) := +{ /* 24.501 cl. 8.2.1 */ + authentication_Request := { + protocolDiscriminator := tsc_EPD_GMM, /* cl. 9.2 M V 1 */ + spareHalfOctet := tsc_SpareHalfOctet, /* cl. 9.3 M V 1/2 */ + securityHeaderType := tsc_SHT_NoSecurityProtection, + messageType := tsc_MT_NG_AuthenticationRequest, /* cl. 9.7 M V 1 */ + spareHalfOctet2 := tsc_SpareHalfOctet, /* cl. 9.5 M V 1/2 */ + ngNasKeySetId := cr_NAS_KeySetIdentifier(p_KeySetId, tsc_NasKsi_NativeSecurityContext), /* cl. 9.11.3.32 M V 1/2 */ + abba := p_ABBA, /* cl. 9.11.3.10 M LV 3-n */ + rand := p_RAND, /* cl. 9.11.3.16 O TV 17 IEI=21 */ + autn := p_AUTN, /* cl. 9.11.3.15 O TLV 18 IEI=20 */ + eapMessage := p_EAP /* cl. 9.11.2.2 O TLV-E 7-1503 IEI=78 */ + } +} + +} diff --git a/library/Osmocom_Types.ttcn b/library/Osmocom_Types.ttcn index 995342a..21d7abf 100644 --- a/library/Osmocom_Types.ttcn +++ b/library/Osmocom_Types.ttcn @@ -343,7 +343,7 @@ }
-private function f_concat_pad(integer tot_len, hexstring prefix, integer suffix) return hexstring { +function f_concat_pad(integer tot_len, hexstring prefix, integer suffix) return hexstring { var integer suffix_len := tot_len - lengthof(prefix); var charstring suffix_ch := int2str(suffix); var integer pad_len := suffix_len - lengthof(suffix_ch);