Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
pespin committed Jan 2, 2024
1 parent 7d9f618 commit afc5508
Show file tree
Hide file tree
Showing 10 changed files with 145 additions and 3 deletions.
27 changes: 26 additions & 1 deletion src/mme/emm-handler.c
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ int emm_handle_attach_request(mme_ue_t *mme_ue,
OGS_NAS_SECURITY_ALGORITHMS_EIA0) {
ogs_warn("Encrypt[0x%x] can be skipped with EEA0, "
"but Integrity[0x%x] cannot be bypassed with EIA0",
mme_selected_enc_algorithm(mme_ue),
mme_selected_enc_algorithm(mme_ue),
mme_selected_int_algorithm(mme_ue));
r = nas_eps_send_attach_reject(mme_ue,
OGS_NAS_EMM_CAUSE_UE_SECURITY_CAPABILITIES_MISMATCH,
Expand Down Expand Up @@ -549,6 +549,27 @@ int emm_handle_service_request(
return OGS_OK;
}


bool emm_tau_request_guti_comes_from_sgsn(const ogs_nas_eps_tracking_area_update_request_t *tau_request)
{
if (tau_request->presencemask &
OGS_NAS_EPS_TRACKING_AREA_UPDATE_REQUEST_OLD_GUTI_TYPE_PRESENT) {
/* 0 = Native, 1 = Mapped */
return tau_request->old_guti_type.guti_type;
} else {
/* TS 23.003 2.8.2.2.2:
* "The most significant bit of the <LAC> shall be set to zero;
* and the most significant bit of <MME group id> shall be set to
* one. Based on this definition, the most significant bit of the
* <MME group id> can be used to distinguish the node type, i.e.
* whether it is an MME or SGSN */
const ogs_nas_eps_mobile_identity_t *eps_mobile_identity = &tau_request->old_guti;
if (eps_mobile_identity->imsi.type != OGS_NAS_EPS_MOBILE_IDENTITY_GUTI)
return false;
return !(eps_mobile_identity->guti.mme_gid & 0x8000);
}
}

int emm_handle_tau_request(mme_ue_t *mme_ue,
ogs_nas_eps_tracking_area_update_request_t *tau_request, ogs_pkbuf_t *pkbuf)
{
Expand Down Expand Up @@ -679,6 +700,10 @@ int emm_handle_tau_request(mme_ue_t *mme_ue,
nas_guti.m_tmsi,
MME_UE_HAVE_IMSI(mme_ue)
? mme_ue->imsi_bcd : "Unknown");

memcpy(&mme_ue->next.guti,
&nas_guti, sizeof(ogs_nas_eps_guti_t));

break;
default:
ogs_error("Not implemented[%d]", eps_mobile_identity->imsi.type);
Expand Down
3 changes: 3 additions & 0 deletions src/mme/emm-handler.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ int emm_handle_extended_service_request(mme_ue_t *mme_ue,
int emm_handle_security_mode_complete(mme_ue_t *mme_ue,
ogs_nas_eps_security_mode_complete_t *security_mode_complete);

bool emm_tau_request_guti_comes_from_sgsn(
const ogs_nas_eps_tracking_area_update_request_t *tau_request);

#ifdef __cplusplus
}
#endif
Expand Down
22 changes: 22 additions & 0 deletions src/mme/emm-sm.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include "mme-event.h"
#include "mme-timer.h"
#include "s1ap-handler.h"
#include "mme-gn-handler.h"
#include "mme-fd-path.h"
#include "emm-handler.h"
#include "emm-build.h"
Expand Down Expand Up @@ -285,7 +286,9 @@ static void common_register_state(ogs_fsm_t *s, mme_event_t *e,

mme_ue_t *mme_ue = NULL;
enb_ue_t *enb_ue = NULL;
mme_sgsn_t *sgsn = NULL;
ogs_nas_eps_message_t *message = NULL;
ogs_nas_rai_t rai;
ogs_nas_security_header_type_t h;

ogs_assert(e);
Expand Down Expand Up @@ -488,6 +491,25 @@ static void common_register_state(ogs_fsm_t *s, mme_event_t *e,
break;
}

if (emm_tau_request_guti_comes_from_sgsn(&message->emm.tracking_area_update_request)) {
ogs_info("TAU request : UE comes from SGSN, attempt retrieving context");
guti_to_rai_ptmsi(&mme_ue->next.guti, &rai, NULL, NULL);
sgsn = mme_sgsn_find_by_routing_address(&rai, 0xffff);
if (!sgsn) {
ogs_plmn_id_t plmn_id;
ogs_nas_from_plmn_id(&rai.lai.nas_plmn_id, &plmn_id);
ogs_warn("No SGSN route matching RAI[MCC:%u MNC:%u LAC:%u RAC:%u]",
ogs_plmn_id_mcc(&plmn_id), ogs_plmn_id_mnc(&plmn_id),
rai.lai.lac, rai.rac);
r = nas_eps_send_tau_reject(mme_ue,
OGS_NAS_EMM_CAUSE_UE_IDENTITY_CANNOT_BE_DERIVED_BY_THE_NETWORK);
OGS_FSM_TRAN(s, &emm_state_exception);
}
mme_gtp1_send_sgsn_context_request(sgsn, mme_ue);
OGS_FSM_TRAN(s, &emm_state_registered); /* FIXME: use a specific FSM state here? */
break;
}

if (!MME_UE_HAVE_IMSI(mme_ue)) {
ogs_info("TAU request : Unknown UE");
r = nas_eps_send_tau_reject(mme_ue,
Expand Down
9 changes: 9 additions & 0 deletions src/mme/mme-context.c
Original file line number Diff line number Diff line change
Expand Up @@ -2488,6 +2488,15 @@ mme_sgsn_t *mme_sgsn_find_by_routing_address(const ogs_nas_rai_t *rai, uint16_t
}
}

/* If no exact match found, try using any with same RAI: */
ogs_list_for_each(&self.sgsn_list, sgsn) {
mme_sgsn_route_t *rt = NULL;
ogs_list_for_each(&sgsn->route_list, rt) {
if (memcmp(&rt->rai, rai, sizeof(ogs_nas_rai_t)) == 0)
return sgsn;
}
}

/* No route found, return default route if available: */
return mme_sgsn_find_by_default_routing_address();
}
Expand Down
20 changes: 20 additions & 0 deletions src/mme/mme-gn-build.c
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,26 @@ static int sess_fill_pdp_context_decoded(mme_sess_t *sess, ogs_gtp1_pdp_context_
return OGS_OK;
}

/* 3GPP TS 29.060 7.5.3 SGSN Context Request */
ogs_pkbuf_t *mme_gn_build_sgsn_context_request(
mme_ue_t *mme_ue)
{
ogs_gtp1_message_t gtp1_message;
ogs_gtp1_sgsn_context_request_t *req = NULL;

ogs_debug("[Gn] build SGSN Context Request");

ogs_assert(mme_ue);

req = &gtp1_message.sgsn_context_request;
memset(&gtp1_message, 0, sizeof(ogs_gtp1_message_t));

(void)req;

gtp1_message.h.type = OGS_GTP1_SGSN_CONTEXT_REQUEST_TYPE;
return ogs_gtp1_build_msg(&gtp1_message);
}

/* 3GPP TS 29.060 7.5.4 SGSN Context Response */
ogs_pkbuf_t *mme_gn_build_sgsn_context_response(
mme_ue_t *mme_ue, uint8_t cause)
Expand Down
3 changes: 3 additions & 0 deletions src/mme/mme-gn-build.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ extern "C" {
ogs_pkbuf_t *mme_gn_build_sgsn_context_response(
mme_ue_t *mme_ue, uint8_t cause);

ogs_pkbuf_t *mme_gn_build_sgsn_context_request(
mme_ue_t *mme_ue);

ogs_pkbuf_t *mme_gn_build_ran_information_relay(
uint8_t type, const uint8_t *buf, size_t len,
const ogs_nas_rai_t *rai, uint16_t cell_id);
Expand Down
19 changes: 17 additions & 2 deletions src/mme/mme-gn-handler.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,10 +68,25 @@ static int decode_global_enb_id(S1AP_Global_ENB_ID_t *glob_enb_id, const uint8_t
return OGS_OK;
}

/* 3GPP TS 23.003 2.8.2.2 Mapping from RAI and P-TMSI to GUT */
/* 3GPP TS 23.003 2.8.2.1 Mapping from GUTI to RAI, P-TMSI and P-TMSI signature */
void guti_to_rai_ptmsi(const ogs_nas_eps_guti_t *nas_guti, ogs_nas_rai_t *rai, mme_p_tmsi_t *ptmsi, uint32_t *ptmsi_sig)
{
rai->lai.nas_plmn_id = nas_guti->nas_plmn_id;
rai->lai.lac = htobe16(nas_guti->mme_gid);
rai->rac = nas_guti->mme_code;
if (ptmsi)
*ptmsi = 0xC0000000 |
(nas_guti->m_tmsi & 0x3f000000) |
(nas_guti->mme_code & 0x0ff) << 16 |
(nas_guti->m_tmsi & 0x0000ffff);
if (ptmsi_sig)
*ptmsi_sig = (nas_guti->m_tmsi & 0x00ff0000);
}

/* 3GPP TS 23.003 2.8.2.2 Mapping from RAI and P-TMSI to GUTI */
static void rai_ptmsi_to_guti(const ogs_nas_rai_t *rai, mme_p_tmsi_t ptmsi, uint32_t ptmsi_sig, ogs_nas_eps_guti_t *nas_guti)
{
uint16_t lac = be16toh(rai->lai.lac);;
uint16_t lac = be16toh(rai->lai.lac);
nas_guti->nas_plmn_id =rai->lai.nas_plmn_id;
nas_guti->mme_gid = lac;
nas_guti->mme_code = rai->rac;
Expand Down
3 changes: 3 additions & 0 deletions src/mme/mme-gn-handler.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ void mme_gn_handle_sgsn_context_acknowledge(
void mme_gn_handle_ran_information_relay(
ogs_gtp_xact_t *xact, ogs_gtp1_ran_information_relay_t *req);

void guti_to_rai_ptmsi(const ogs_nas_eps_guti_t *nas_guti, ogs_nas_rai_t *rai,
mme_p_tmsi_t *ptmsi, uint32_t *ptmsi_sig);

#ifdef __cplusplus
}
#endif
Expand Down
39 changes: 39 additions & 0 deletions src/mme/mme-gtp-path.c
Original file line number Diff line number Diff line change
Expand Up @@ -758,6 +758,45 @@ int mme_gtp_send_bearer_resource_command(
return rv;
}

/*************************
* GTPv1C (Gn interface):
*************************/

int mme_gtp1_send_sgsn_context_request(
mme_sgsn_t *sgsn, mme_ue_t *mme_ue)
{
int rv;
ogs_gtp1_header_t h;
ogs_pkbuf_t *pkbuf = NULL;
ogs_gtp_xact_t *xact = NULL;

ogs_assert(sgsn);

memset(&h, 0, sizeof(ogs_gtp1_header_t));
h.type = OGS_GTP1_SGSN_CONTEXT_REQUEST_TYPE;
h.teid = 0;

pkbuf = mme_gn_build_sgsn_context_request(mme_ue);
if (!pkbuf) {
ogs_error("mme_gn_build_ran_information_relay() failed");
return OGS_ERROR;
}

xact = ogs_gtp1_xact_local_create(&sgsn->gnode, &h, pkbuf, NULL, NULL);
if (!xact) {
ogs_error("ogs_gtp1_xact_local_create() failed");
return OGS_ERROR;
}
/* TS 29.060 8.2: "The SGSN Context Request message, where the Tunnel
* Endpoint Identifier shall be set to all zeroes." */
xact->local_teid = 0;

rv = ogs_gtp_xact_commit(xact);
ogs_expect(rv == OGS_OK);

return rv;
}

int mme_gtp1_send_sgsn_context_response(
mme_ue_t *mme_ue, uint8_t cause, ogs_gtp_xact_t *xact)
{
Expand Down
3 changes: 3 additions & 0 deletions src/mme/mme-gtp-path.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@ int mme_gtp_send_delete_indirect_data_forwarding_tunnel_request(
int mme_gtp_send_bearer_resource_command(
mme_bearer_t *bearer, ogs_nas_eps_message_t *nas_message);

int mme_gtp1_send_sgsn_context_request(
mme_sgsn_t *sgsn, mme_ue_t *mme_ue);

int mme_gtp1_send_sgsn_context_response(
mme_ue_t *mme_ue, uint8_t cause, ogs_gtp_xact_t *xact);

Expand Down

0 comments on commit afc5508

Please sign in to comment.