From 7340b5e0713a6f3ea9bc83b64ebf76ea57aee96e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Leroy?= <frederic.leroy@b-com.com>
Date: Tue, 12 Jul 2016 17:45:16 +0200
Subject: [PATCH] UE/EMM: move _plmn_list to nas_user_t

---
 openair3/NAS/UE/EMM/IdleMode.c      | 313 ++++++++++++----------------
 openair3/NAS/UE/EMM/IdleMode.h      |  22 +-
 openair3/NAS/UE/EMM/IdleMode_defs.h |  52 +++++
 openair3/NAS/UE/EMM/emm_main.c      |  44 ++--
 openair3/NAS/UE/EMM/emm_main.h      |   8 +-
 openair3/NAS/UE/EMM/emm_proc.h      |   2 +-
 openair3/NAS/UE/nas_proc.c          |   6 +-
 openair3/NAS/UE/user_defs.h         |   2 +
 8 files changed, 232 insertions(+), 217 deletions(-)
 create mode 100644 openair3/NAS/UE/EMM/IdleMode_defs.h

diff --git a/openair3/NAS/UE/EMM/IdleMode.c b/openair3/NAS/UE/EMM/IdleMode.c
index c9ebc40b7a..efecf7d321 100644
--- a/openair3/NAS/UE/EMM/IdleMode.c
+++ b/openair3/NAS/UE/EMM/IdleMode.c
@@ -78,57 +78,9 @@ Description Defines EMM procedures executed by the Non-Access Stratum
 /****************************************************************************/
 
 static int _IdleMode_plmn_str(char *plmn_str, const plmn_t *plmn);
-static int _IldlMode_get_opnn_id(nas_user_t *user, const plmn_t *plmn);
+static int _IldlMode_get_opnn_id(emm_data_t *emm_data, const plmn_t *plmn);
 static int _IdleMode_get_suitable_cell(nas_user_t *user, int index);
 
-/*
- * A list of PLMN identities in priority order is maintained locally
- * to perform the PLMN selection procedure.
- *
- * In automatic mode of operation, this list is used for PLMN selection when
- * the UE is switched on, or upon recovery from lack of coverage, or when the
- * user requests the UE to initiate PLMN reselection, and registration.
- * In manual mode of operation, this list is displayed to the user that may
- * select an available PLMN and initiate registration.
- *
- * The list may contain PLMN identifiers in the following order:
- * - The last registered PLMN or each equivalent PLMN present in the list of
- *   "equivalent PLMNs" (EPLMN_MAX), when UE is switched on or following
- *   recovery from lack of coverage;
- * - The highest priority PLMN in the list of "equivalent HPLMNs" or the
- *   HPLMN derived from the IMSI (1)
- * - Each PLMN/access technology combination in the "User Controlled PLMN
- *   Selector with Access Technology" (PLMN_MAX)
- * - Each PLMN/access technology combination in the "Operator Controlled PLMN
- *   Selector with Access Technology" (OPLMN_MAX)
- * - Other PLMN/access technology combinations with received high quality
- *   signal in random order (TODO)
- * - Other PLMN/access technology combinations in order of decreasing signal
- *   quality (TODO)
- * - The last selected PLMN again (1)
- */
-static struct {
-  int n_plmns;
-#define EMM_PLMN_LIST_SIZE (EMM_DATA_EPLMN_MAX + EMM_DATA_PLMN_MAX +    \
-                            EMM_DATA_OPLMN_MAX + 2)
-  plmn_t *plmn[EMM_PLMN_LIST_SIZE];
-  int index;    /* Index of the PLMN for which selection is ongoing        */
-  int hplmn;    /* Index of the home PLMN or the highest priority
-           * equivalent home PLMN                    */
-  int fplmn;    /* Index of the first forbidden PLMN               */
-  int splmn;    /* Index of the currently selected PLMN            */
-  int rplmn;    /* Index of the currently registered PLMN          */
-  struct plmn_param_t {
-    char fullname[NET_FORMAT_LONG_SIZE+1];   /* PLMN full identifier     */
-    char shortname[NET_FORMAT_SHORT_SIZE+1]; /* PLMN short identifier    */
-    char num[NET_FORMAT_NUM_SIZE+1];     /* PLMN numeric identifier  */
-    int stat; /* Indication of the PLMN availability             */
-    int tac;  /* Location/Tracking Area Code                 */
-    int ci;   /* Serving cell identifier                     */
-    int rat;  /* Radio Access Technology supported by the serving cell   */
-  } param[EMM_PLMN_LIST_SIZE];
-} _emm_plmn_list;
-
 /* Callback executed whenever a network indication is received */
 static IdleMode_callback_t _emm_indication_notify;
 
@@ -154,13 +106,19 @@ static IdleMode_callback_t _emm_indication_notify;
  ***************************************************************************/
 void IdleMode_initialize(nas_user_t *user, IdleMode_callback_t cb)
 {
+  emm_plmn_list_t *emm_plmn_list = calloc(1, sizeof(emm_plmn_list_t));
+  if ( emm_plmn_list == NULL ) {
+    LOG_TRACE(ERROR, "EMM  - Can't alloc emm_plmn_list");
+    // FIXME stop here
+  }
+  user->emm_plmn_list = emm_plmn_list;
   /* Initialize the list of available PLMNs */
-  _emm_plmn_list.n_plmns = 0;
-  _emm_plmn_list.index = 0;
-  _emm_plmn_list.hplmn = -1;
-  _emm_plmn_list.fplmn = -1;
-  _emm_plmn_list.splmn = -1;
-  _emm_plmn_list.rplmn = -1;
+  emm_plmn_list->n_plmns = 0;
+  emm_plmn_list->index = 0;
+  emm_plmn_list->hplmn = -1;
+  emm_plmn_list->fplmn = -1;
+  emm_plmn_list->splmn = -1;
+  emm_plmn_list->rplmn = -1;
 
   /* Initialize the network notification handler */
   _emm_indication_notify = *cb;
@@ -190,9 +148,9 @@ void IdleMode_initialize(nas_user_t *user, IdleMode_callback_t cb)
  **      Others:    None                                       **
  **                                                                        **
  ***************************************************************************/
-int IdleMode_get_nb_plmns(void)
+int IdleMode_get_nb_plmns(emm_plmn_list_t *emm_plmn_list)
 {
-  return _emm_plmn_list.n_plmns;
+  return emm_plmn_list->n_plmns;
 }
 
 /****************************************************************************
@@ -211,9 +169,9 @@ int IdleMode_get_nb_plmns(void)
  **      Others:    None                                       **
  **                                                                        **
  ***************************************************************************/
-int IdleMode_get_hplmn_index(void)
+int IdleMode_get_hplmn_index(emm_plmn_list_t *emm_plmn_list)
 {
-  return _emm_plmn_list.hplmn;
+  return emm_plmn_list->hplmn;
 }
 
 /****************************************************************************
@@ -232,9 +190,9 @@ int IdleMode_get_hplmn_index(void)
  **      Others:    None                                       **
  **                                                                        **
  ***************************************************************************/
-int IdleMode_get_rplmn_index(void)
+int IdleMode_get_rplmn_index(emm_plmn_list_t *emm_plmn_list)
 {
-  return _emm_plmn_list.rplmn;
+  return emm_plmn_list->rplmn;
 }
 
 /****************************************************************************
@@ -245,16 +203,15 @@ int IdleMode_get_rplmn_index(void)
  **      available PLMNs.                                          **
  **                                                                        **
  ** Inputs:  None                                                      **
- **      Others:    _emm_plmn_list                             **
  **                                                                        **
  ** Outputs:     None                                                      **
  **      Return:    The index of the selected PLMN in the list **
  **      Others:    None                                       **
  **                                                                        **
  ***************************************************************************/
-int IdleMode_get_splmn_index(void)
+int IdleMode_get_splmn_index(emm_plmn_list_t *emm_plmn_list)
 {
-  return _emm_plmn_list.splmn;
+  return emm_plmn_list->splmn;
 }
 
 /****************************************************************************
@@ -265,19 +222,18 @@ int IdleMode_get_splmn_index(void)
  **      tors present in the network                               **
  **                                                                        **
  ** Inputs:  i:     Index of the first operator to update      **
- **          Others:    _emm_plmn_list                             **
  **                                                                        **
  ** Outputs:     None                                                      **
  **      Return:    The size of the list in bytes              **
  **                                                                        **
  ***************************************************************************/
-int IdleMode_update_plmn_list(emm_data_t *emm_data, int i)
+int IdleMode_update_plmn_list(emm_plmn_list_t *emm_plmn_list, emm_data_t *emm_data, int i)
 {
   int offset = 0;
   int n = 1;
 
-  while ( (i < _emm_plmn_list.n_plmns) && (offset < EMM_DATA_BUFFER_SIZE) ) {
-    struct plmn_param_t *plmn = &(_emm_plmn_list.param[i++]);
+  while ( (i < emm_plmn_list->n_plmns) && (offset < EMM_DATA_BUFFER_SIZE) ) {
+    struct plmn_param_t *plmn = &(emm_plmn_list->param[i++]);
 
     if (n++ > 1) {
       offset += snprintf(emm_data->plist.buffer + offset,
@@ -319,13 +275,13 @@ int IdleMode_update_plmn_list(emm_data_t *emm_data, int i)
  **      Others:    None                                       **
  **                                                                        **
  ***************************************************************************/
-const char *IdleMode_get_plmn_fullname(const plmn_t *plmn, int index,
+const char *IdleMode_get_plmn_fullname(emm_plmn_list_t *emm_plmn_list, const plmn_t *plmn, int index,
                                        size_t *len)
 {
-  if (index < _emm_plmn_list.n_plmns) {
-    assert( PLMNS_ARE_EQUAL(*plmn, *_emm_plmn_list.plmn[index]) );
-    *len = strlen(_emm_plmn_list.param[index].fullname);
-    return _emm_plmn_list.param[index].fullname;
+  if (index < emm_plmn_list->n_plmns) {
+    assert( PLMNS_ARE_EQUAL(*plmn, *emm_plmn_list->plmn[index]) );
+    *len = strlen(emm_plmn_list->param[index].fullname);
+    return emm_plmn_list->param[index].fullname;
   }
 
   return NULL;
@@ -348,13 +304,13 @@ const char *IdleMode_get_plmn_fullname(const plmn_t *plmn, int index,
  **      Others:    None                                       **
  **                                                                        **
  ***************************************************************************/
-const char *IdleMode_get_plmn_shortname(const plmn_t *plmn, int index,
+const char *IdleMode_get_plmn_shortname(emm_plmn_list_t *emm_plmn_list, const plmn_t *plmn, int index,
                                         size_t *len)
 {
-  if (index < _emm_plmn_list.n_plmns) {
-    assert( PLMNS_ARE_EQUAL(*plmn, *_emm_plmn_list.plmn[index]) );
-    *len = strlen(_emm_plmn_list.param[index].shortname);
-    return _emm_plmn_list.param[index].shortname;
+  if (index < emm_plmn_list->n_plmns) {
+    assert( PLMNS_ARE_EQUAL(*plmn, *emm_plmn_list->plmn[index]) );
+    *len = strlen(emm_plmn_list->param[index].shortname);
+    return emm_plmn_list->param[index].shortname;
   }
 
   return NULL;
@@ -378,12 +334,12 @@ const char *IdleMode_get_plmn_shortname(const plmn_t *plmn, int index,
  **      Others:    None                                       **
  **                                                                        **
  ***************************************************************************/
-const char *IdleMode_get_plmn_id(const plmn_t *plmn, int index, size_t *len)
+const char *IdleMode_get_plmn_id(emm_plmn_list_t *emm_plmn_list, const plmn_t *plmn, int index, size_t *len)
 {
-  if (index < _emm_plmn_list.n_plmns) {
-    assert( PLMNS_ARE_EQUAL(*plmn, *_emm_plmn_list.plmn[index]) );
-    *len = strlen(_emm_plmn_list.param[index].num);
-    return _emm_plmn_list.param[index].num;
+  if (index < emm_plmn_list->n_plmns) {
+    assert( PLMNS_ARE_EQUAL(*plmn, *emm_plmn_list->plmn[index]) );
+    *len = strlen(emm_plmn_list->param[index].num);
+    return emm_plmn_list->param[index].num;
   }
 
   return NULL;
@@ -405,13 +361,13 @@ const char *IdleMode_get_plmn_id(const plmn_t *plmn, int index, size_t *len)
  **      Others:    None                                       **
  **                                                                        **
  ***************************************************************************/
-int IdleMode_get_plmn_fullname_index(const char *plmn)
+int IdleMode_get_plmn_fullname_index(emm_plmn_list_t *emm_plmn_list, const char *plmn)
 {
   int index;
 
   /* Get the index of the PLMN identifier with specified full name */
-  for (index = 0; index < _emm_plmn_list.n_plmns; index++) {
-    if ( strncmp(plmn, _emm_plmn_list.param[index].fullname,
+  for (index = 0; index < emm_plmn_list->n_plmns; index++) {
+    if ( strncmp(plmn, emm_plmn_list->param[index].fullname,
                  NET_FORMAT_LONG_SIZE) != 0 ) {
       continue;
     }
@@ -438,13 +394,13 @@ int IdleMode_get_plmn_fullname_index(const char *plmn)
  **      Others:    None                                       **
  **                                                                        **
  ***************************************************************************/
-int IdleMode_get_plmn_shortname_index(const char *plmn)
+int IdleMode_get_plmn_shortname_index(emm_plmn_list_t *emm_plmn_list, const char *plmn)
 {
   int index;
 
   /* Get the index of the PLMN identifier with specified short name */
-  for (index = 0; index < _emm_plmn_list.n_plmns; index++) {
-    if ( !strncmp(plmn, _emm_plmn_list.param[index].shortname,
+  for (index = 0; index < emm_plmn_list->n_plmns; index++) {
+    if ( !strncmp(plmn, emm_plmn_list->param[index].shortname,
                   NET_FORMAT_SHORT_SIZE) ) {
       continue;
     }
@@ -471,13 +427,13 @@ int IdleMode_get_plmn_shortname_index(const char *plmn)
  **      Others:    None                                       **
  **                                                                        **
  ***************************************************************************/
-int IdleMode_get_plmn_id_index(const char *plmn)
+int IdleMode_get_plmn_id_index(emm_plmn_list_t *emm_plmn_list, const char *plmn)
 {
   int index;
 
   /* Get the index of the PLMN identifier with specified numeric identifier */
-  for (index = 0; index < _emm_plmn_list.n_plmns; index++) {
-    if ( !strncmp(plmn, _emm_plmn_list.param[index].num,
+  for (index = 0; index < emm_plmn_list->n_plmns; index++) {
+    if ( !strncmp(plmn, emm_plmn_list->param[index].num,
                   NET_FORMAT_LONG_SIZE) ) {
       continue;
     }
@@ -516,6 +472,7 @@ int emm_proc_initialize(nas_user_t *user)
   emm_sap_t emm_sap;
   int rc;
   int i;
+  emm_plmn_list_t *emm_plmn_list = user->emm_plmn_list;
 
   if (!user->emm_data->usim_is_valid) {
     /* The USIM application is not present or not valid */
@@ -526,11 +483,11 @@ int emm_proc_initialize(nas_user_t *user)
      * if available, or the last registered PLMN */
     if (user->emm_data->nvdata.eplmn.n_plmns > 0) {
       for (i=0; i < user->emm_data->nvdata.eplmn.n_plmns; i++) {
-        _emm_plmn_list.plmn[_emm_plmn_list.n_plmns++] =
+        emm_plmn_list->plmn[emm_plmn_list->n_plmns++] =
           &user->emm_data->nvdata.eplmn.plmn[i];
       }
     } else if ( PLMN_IS_VALID(user->emm_data->nvdata.rplmn) ) {
-      _emm_plmn_list.plmn[_emm_plmn_list.n_plmns++] =
+      emm_plmn_list->plmn[emm_plmn_list->n_plmns++] =
         &user->emm_data->nvdata.rplmn;
     }
 
@@ -538,29 +495,29 @@ int emm_proc_initialize(nas_user_t *user)
      * When switched on, the UE will try to automatically register
      * to each previous PLMN within the ordered list of available
      * PLMNs regardless of the network selection mode of operation */
-    _emm_plmn_list.hplmn = _emm_plmn_list.n_plmns - 1;
-    // LG_emm_plmn_list.hplmn = _emm_plmn_list.n_plmns;
+    emm_plmn_list->hplmn = emm_plmn_list->n_plmns - 1;
+    // LGemm_plmn_list->hplmn = emm_plmn_list->n_plmns;
 
     /* Add the highest priority PLMN in the list of "equivalent HPLMNs"
        if present and not empty, or the HPLMN derived from the IMSI */
     if (user->emm_data->ehplmn.n_plmns > 0) {
-      _emm_plmn_list.plmn[_emm_plmn_list.n_plmns++] =
+      emm_plmn_list->plmn[emm_plmn_list->n_plmns++] =
         &user->emm_data->ehplmn.plmn[0];
     } else {
-      _emm_plmn_list.plmn[_emm_plmn_list.n_plmns++] = &user->emm_data->hplmn;
+      emm_plmn_list->plmn[emm_plmn_list->n_plmns++] = &user->emm_data->hplmn;
     }
 
     /* Each PLMN/access technology combination in the "User
      * Controlled PLMN Selector with Access Technology" */
     for (i=0; i < user->emm_data->plmn.n_plmns; i++) {
-      _emm_plmn_list.plmn[_emm_plmn_list.n_plmns++] =
+      emm_plmn_list->plmn[emm_plmn_list->n_plmns++] =
         &user->emm_data->plmn.plmn[i];
     }
 
     /* Each PLMN/access technology combination in the "Operator
      * Controlled PLMN Selector with Access Technology" */
     for (i=0; i < user->emm_data->oplmn.n_plmns; i++) {
-      _emm_plmn_list.plmn[_emm_plmn_list.n_plmns++] =
+      emm_plmn_list->plmn[emm_plmn_list->n_plmns++] =
         &user->emm_data->oplmn.plmn[i];
     }
 
@@ -573,9 +530,9 @@ int emm_proc_initialize(nas_user_t *user)
     /* TODO: Schedule periodic network selection attemps (hpplmn timer) */
 
     /* Initialize the PLMNs' parameters */
-    for (i=0; i < _emm_plmn_list.n_plmns; i++) {
-      struct plmn_param_t *plmn = &(_emm_plmn_list.param[i]);
-      int id = _IldlMode_get_opnn_id(user, _emm_plmn_list.plmn[i]);
+    for (i=0; i < emm_plmn_list->n_plmns; i++) {
+      struct plmn_param_t *plmn = &(emm_plmn_list->param[i]);
+      int id = _IldlMode_get_opnn_id(user->emm_data, emm_plmn_list->plmn[i]);
 
       if (id < 0) {
         plmn->fullname[0] = '\0';
@@ -587,7 +544,7 @@ int emm_proc_initialize(nas_user_t *user)
                 NET_FORMAT_SHORT_SIZE);
       }
 
-      (void)_IdleMode_plmn_str(plmn->num, _emm_plmn_list.plmn[i]);
+      (void)_IdleMode_plmn_str(plmn->num, emm_plmn_list->plmn[i]);
       plmn->stat = NET_OPER_UNKNOWN;
       plmn->tac = 0;
       plmn->ci = 0;
@@ -595,7 +552,7 @@ int emm_proc_initialize(nas_user_t *user)
     }
 
     LOG_TRACE(INFO, "EMM-IDLE  - %d PLMNs available for network selection",
-              _emm_plmn_list.n_plmns);
+              emm_plmn_list->n_plmns);
 
     /* Notify EMM that PLMN selection procedure has to be executed */
     emm_sap.primitive = EMMREG_REGISTER_REQ;
@@ -630,31 +587,33 @@ int emm_proc_initialize(nas_user_t *user)
  **                                                                        **
  ** Outputs:     None                                                      **
  **      Return:    None                                       **
- **      Others:    _emm_plmn_list.index                       **
+ **      Others:    emm_plmn_list->index                       **
  **                                                                        **
  ***************************************************************************/
 int emm_proc_plmn_selection(nas_user_t *user, int index)
 {
   LOG_FUNC_IN;
+  emm_data_t *emm_data = user->emm_data;
+  emm_plmn_list_t *emm_plmn_list = user->emm_plmn_list;
 
   int rc = RETURNok;
 
-  if (user->emm_data->plmn_mode != EMM_DATA_PLMN_AUTO) {
+  if (emm_data->plmn_mode != EMM_DATA_PLMN_AUTO) {
     /*
      * Manual or manual/automatic mode of operation
      * --------------------------------------------
      */
-    if (index >= _emm_plmn_list.hplmn) {
+    if (index >= emm_plmn_list->hplmn) {
       /*
        * Selection of the last registered or equivalent PLMNs failed
        */
-      if (user->emm_data->plmn_index < 0) {
+      if (emm_data->plmn_index < 0) {
         /*
          * The user did not select any PLMN yet; display the ordered
          * list of available PLMNs to the user
          */
         index = -1;
-        rc = emm_proc_network_notify(user->emm_data, _emm_plmn_list.hplmn);
+        rc = emm_proc_network_notify(emm_plmn_list, emm_data, emm_plmn_list->hplmn);
 
         if (rc != RETURNok) {
           LOG_TRACE(WARNING, "EMM-IDLE  - Failed to notify "
@@ -664,7 +623,7 @@ int emm_proc_plmn_selection(nas_user_t *user, int index)
         /*
          * Try to register to the PLMN manually selected by the user
          */
-        index = user->emm_data->plmn_index;
+        index = emm_data->plmn_index;
       }
     }
   }
@@ -677,7 +636,7 @@ int emm_proc_plmn_selection(nas_user_t *user, int index)
      * or any other PLMN in the ordered list of available PLMNs in
      * automatic mode.
      */
-    _emm_plmn_list.index = index;
+    emm_plmn_list->index = index;
     rc = _IdleMode_get_suitable_cell(user, index);
   }
 
@@ -713,11 +672,9 @@ int emm_proc_plmn_selection(nas_user_t *user, int index)
  **      ci:        The identifier of the cell                 **
  **      rat:       The radio access technology supported by   **
  **             the cell                                   **
- **      Others:    _emm_plmn_list, user->emm_data->                 **
  **                                                                        **
  ** Outputs:     None                                                      **
  **      Return:    None                                       **
- **      Others:    _emm_plmn_list, user->emm_data->                 **
  **                                                                        **
  ***************************************************************************/
 int emm_proc_plmn_selection_end(nas_user_t *user, int found, tac_t tac, ci_t ci, AcT_t rat)
@@ -726,34 +683,36 @@ int emm_proc_plmn_selection_end(nas_user_t *user, int found, tac_t tac, ci_t ci,
 
   emm_sap_t emm_sap;
   int rc = RETURNerror;
-  int index = _emm_plmn_list.index;
+  emm_data_t *emm_data = user->emm_data;
+  emm_plmn_list_t *emm_plmn_list = user->emm_plmn_list;
+  int index = emm_plmn_list->index;
   int select_next_plmn = FALSE;
 
   LOG_TRACE(INFO, "EMM-IDLE  - %s cell found for PLMN %d in %s mode",
             (found)? "One" : "No", index,
-            (user->emm_data->plmn_mode == EMM_DATA_PLMN_AUTO)? "Automatic" :
-            (user->emm_data->plmn_mode == EMM_DATA_PLMN_MANUAL)? "Manual" :
+            (emm_data->plmn_mode == EMM_DATA_PLMN_AUTO)? "Automatic" :
+            (emm_data->plmn_mode == EMM_DATA_PLMN_MANUAL)? "Manual" :
             "Automatic/manual");
 
   if (found) {
     int is_forbidden = FALSE;
 
     /* Select the PLMN of which a suitable cell has been found */
-    user->emm_data->splmn = *_emm_plmn_list.plmn[index];
+    emm_data->splmn = *emm_plmn_list->plmn[index];
 
     /* Update the selected PLMN's parameters */
-    _emm_plmn_list.param[index].tac = tac;
-    _emm_plmn_list.param[index].ci = ci;
-    _emm_plmn_list.param[index].rat = rat;
+    emm_plmn_list->param[index].tac = tac;
+    emm_plmn_list->param[index].ci = ci;
+    emm_plmn_list->param[index].rat = rat;
 
     /* Update the location data and notify EMM that data have changed */
-    rc = emm_proc_location_notify(user->emm_data, tac, ci , rat);
+    rc = emm_proc_location_notify(emm_data, tac, ci , rat);
 
     if (rc != RETURNok) {
       LOG_TRACE(WARNING, "EMM-IDLE  - Failed to notify location update");
     }
 
-    if (user->emm_data->plmn_mode == EMM_DATA_PLMN_AUTO) {
+    if (emm_data->plmn_mode == EMM_DATA_PLMN_AUTO) {
       /*
        * Automatic mode of operation
        * ---------------------------
@@ -761,17 +720,17 @@ int emm_proc_plmn_selection_end(nas_user_t *user, int found, tac_t tac, ci_t ci,
       int i;
 
       /* Check if the selected PLMN is in the forbidden list */
-      for (i = 0; i < user->emm_data->fplmn.n_plmns; i++) {
-        if (PLMNS_ARE_EQUAL(user->emm_data->splmn, user->emm_data->fplmn.plmn[i])) {
+      for (i = 0; i < emm_data->fplmn.n_plmns; i++) {
+        if (PLMNS_ARE_EQUAL(emm_data->splmn, emm_data->fplmn.plmn[i])) {
           is_forbidden = TRUE;
           break;
         }
       }
 
       if (!is_forbidden) {
-        for (i = 0; i < user->emm_data->fplmn_gprs.n_plmns; i++) {
-          if (PLMNS_ARE_EQUAL(user->emm_data->splmn,
-                              user->emm_data->fplmn_gprs.plmn[i])) {
+        for (i = 0; i < emm_data->fplmn_gprs.n_plmns; i++) {
+          if (PLMNS_ARE_EQUAL(emm_data->splmn,
+                              emm_data->fplmn_gprs.plmn[i])) {
             is_forbidden = TRUE;
             break;
           }
@@ -781,12 +740,12 @@ int emm_proc_plmn_selection_end(nas_user_t *user, int found, tac_t tac, ci_t ci,
       /* Check if the selected PLMN belongs to a forbidden
        * tracking area */
       tai_t tai;
-      tai.plmn = user->emm_data->splmn;
+      tai.plmn = emm_data->splmn;
       tai.tac = tac;
 
       if (!is_forbidden) {
-        for (i = 0; i < user->emm_data->ftai.n_tais; i++) {
-          if (TAIS_ARE_EQUAL(tai, user->emm_data->ftai.tai[i])) {
+        for (i = 0; i < emm_data->ftai.n_tais; i++) {
+          if (TAIS_ARE_EQUAL(tai, emm_data->ftai.tai[i])) {
             is_forbidden = TRUE;
             break;
           }
@@ -794,8 +753,8 @@ int emm_proc_plmn_selection_end(nas_user_t *user, int found, tac_t tac, ci_t ci,
       }
 
       if (!is_forbidden) {
-        for (i = 0; i < user->emm_data->ftai_roaming.n_tais; i++) {
-          if (TAIS_ARE_EQUAL(tai, user->emm_data->ftai_roaming.tai[i])) {
+        for (i = 0; i < emm_data->ftai_roaming.n_tais; i++) {
+          if (TAIS_ARE_EQUAL(tai, emm_data->ftai_roaming.tai[i])) {
             is_forbidden = TRUE;
             break;
           }
@@ -809,25 +768,25 @@ int emm_proc_plmn_selection_end(nas_user_t *user, int found, tac_t tac, ci_t ci,
       LOG_TRACE(INFO, "EMM-IDLE  - UE may camp on this acceptable cell for limited services");
 
       /* Save the index of the first forbidden PLMN */
-      if (_emm_plmn_list.fplmn < 0) {
-        _emm_plmn_list.fplmn = index;
+      if (emm_plmn_list->fplmn < 0) {
+        emm_plmn_list->fplmn = index;
       }
 
-      _emm_plmn_list.param[index].stat = NET_OPER_FORBIDDEN;
+      emm_plmn_list->param[index].stat = NET_OPER_FORBIDDEN;
     } else {
       /* A suitable cell has been found and the PLMN or tracking area
        * is not in the forbidden list */
       LOG_TRACE(INFO, "EMM-IDLE  - UE may camp on this suitable cell for normal services");
-      _emm_plmn_list.fplmn = -1;
-      _emm_plmn_list.param[index].stat = NET_OPER_CURRENT;
+      emm_plmn_list->fplmn = -1;
+      emm_plmn_list->param[index].stat = NET_OPER_CURRENT;
       emm_sap.primitive = EMMREG_REGISTER_CNF;
     }
 
     /* Duplicate the new selected PLMN at the end of the ordered list */
-    _emm_plmn_list.plmn[_emm_plmn_list.n_plmns] = &user->emm_data->splmn;
+    emm_plmn_list->plmn[emm_plmn_list->n_plmns] = &emm_data->splmn;
   }
 
-  else if (user->emm_data->plmn_mode == EMM_DATA_PLMN_AUTO) {
+  else if (emm_data->plmn_mode == EMM_DATA_PLMN_AUTO) {
     /*
      * Automatic mode of operation
      * ---------------------------
@@ -838,12 +797,12 @@ int emm_proc_plmn_selection_end(nas_user_t *user, int found, tac_t tac, ci_t ci,
     select_next_plmn = TRUE;
 
     /* Bypass the previously selected PLMN */
-    if (index == _emm_plmn_list.splmn) {
+    if (index == emm_plmn_list->splmn) {
       index += 1;
     }
   }
 
-  else if (user->emm_data->plmn_index < 0) {
+  else if (emm_data->plmn_index < 0) {
     /*
      * Manual or manual/automatic mode of operation
      * --------------------------------------------
@@ -854,7 +813,7 @@ int emm_proc_plmn_selection_end(nas_user_t *user, int found, tac_t tac, ci_t ci,
     select_next_plmn = TRUE;
   }
 
-  else if (user->emm_data->plmn_mode == EMM_DATA_PLMN_MANUAL) {
+  else if (emm_data->plmn_mode == EMM_DATA_PLMN_MANUAL) {
     /*
      * Manual mode of operation
      * ------------------------
@@ -870,8 +829,8 @@ int emm_proc_plmn_selection_end(nas_user_t *user, int found, tac_t tac, ci_t ci,
      * Attempt to find a suitable cell of the PLMN selected by the user
      * failed; Try to automatically select another PLMN
      */
-    user->emm_data->plmn_mode = EMM_DATA_PLMN_AUTO;
-    index = _emm_plmn_list.hplmn;
+    emm_data->plmn_mode = EMM_DATA_PLMN_AUTO;
+    index = emm_plmn_list->hplmn;
     select_next_plmn = TRUE;
   }
 
@@ -879,16 +838,16 @@ int emm_proc_plmn_selection_end(nas_user_t *user, int found, tac_t tac, ci_t ci,
    * Force an attempt to register to the next PLMN
    */
   if (select_next_plmn) {
-    int last_plmn_index = _emm_plmn_list.n_plmns;
+    int last_plmn_index = emm_plmn_list->n_plmns;
 
-    if (_emm_plmn_list.splmn != -1) {
+    if (emm_plmn_list->splmn != -1) {
       /* The last attempt was to register the previously selected PLMN */
       last_plmn_index += 1;
     }
 
     if (index < last_plmn_index) {
       /* Try to select the next PLMN in the list of available PLMNs */
-      _emm_plmn_list.index = index;
+      emm_plmn_list->index = index;
       rc = emm_proc_plmn_selection(user, index);
     } else {
       /* No suitable cell of any PLMN within the ordered list
@@ -902,27 +861,27 @@ int emm_proc_plmn_selection_end(nas_user_t *user, int found, tac_t tac, ci_t ci,
    * Or terminate the PLMN selection procedure
    */
   if (!select_next_plmn) {
-    if (_emm_plmn_list.fplmn >= 0) {
+    if (emm_plmn_list->fplmn >= 0) {
       /* There were one or more PLMNs which were available and allowable,
        * but an LR failure made registration on those PLMNs unsuccessful
        * or an entry in any of the forbidden area lists prevented a
        * registration attempt; select the first such PLMN and enters a
        * limited service state. */
-      index = _emm_plmn_list.fplmn;
-      _emm_plmn_list.fplmn = -1;
+      index = emm_plmn_list->fplmn;
+      emm_plmn_list->fplmn = -1;
       emm_sap.primitive = EMMREG_REGISTER_REJ;
     }
 
     /* Update the availability indicator of the previously selected PLMN */
-    if (_emm_plmn_list.splmn != -1) {
-      _emm_plmn_list.param[_emm_plmn_list.splmn].stat = NET_OPER_UNKNOWN;
+    if (emm_plmn_list->splmn != -1) {
+      emm_plmn_list->param[emm_plmn_list->splmn].stat = NET_OPER_UNKNOWN;
     }
 
     /* Update the index of the new selected PLMN */
     if (emm_sap.primitive != EMMREG_NO_CELL) {
-      _emm_plmn_list.splmn = index;
+      emm_plmn_list->splmn = index;
     } else {
-      _emm_plmn_list.splmn = -1;
+      emm_plmn_list->splmn = -1;
     }
 
     /*
@@ -930,15 +889,15 @@ int emm_proc_plmn_selection_end(nas_user_t *user, int found, tac_t tac, ci_t ci,
      */
     rc = emm_sap_send(user, &emm_sap);
 
-    if (_emm_plmn_list.splmn != -1) {
-      if (_emm_plmn_list.splmn == _emm_plmn_list.rplmn) {
+    if (emm_plmn_list->splmn != -1) {
+      if (emm_plmn_list->splmn == emm_plmn_list->rplmn) {
         /* The selected PLMN is the registered PLMN */
         LOG_TRACE(INFO, "EMM-IDLE  - The selected PLMN is the registered PLMN");
-        user->emm_data->is_rplmn = TRUE;
-      } else if (_emm_plmn_list.splmn < _emm_plmn_list.hplmn) {
+        emm_data->is_rplmn = TRUE;
+      } else if (emm_plmn_list->splmn < emm_plmn_list->hplmn) {
         /* The selected PLMN is in the list of equivalent PLMNs */
         LOG_TRACE(INFO, "EMM-IDLE  - The selected PLMN is in the list of equivalent PLMNs");
-        user->emm_data->is_eplmn = TRUE;
+        emm_data->is_eplmn = TRUE;
       }
 
       /*
@@ -1046,12 +1005,12 @@ int emm_proc_location_notify(emm_data_t *emm_data, tac_t tac, ci_t ci, AcT_t rat
  **          Others:    user->emm_data->                                 **
  **                                                                        **
  ***************************************************************************/
-int emm_proc_network_notify(emm_data_t *emm_data, int index)
+int emm_proc_network_notify(emm_plmn_list_t *emm_plmn_list, emm_data_t *emm_data, int index)
 {
   LOG_FUNC_IN;
 
   /* Update the list of operators present in the network */
-  int size = IdleMode_update_plmn_list(emm_data, index);
+  int size = IdleMode_update_plmn_list(emm_plmn_list, emm_data, index);
   /* Notify EMM that data has changed */
   int rc = (*_emm_indication_notify)(emm_data, size);
 
@@ -1122,7 +1081,6 @@ static int _IdleMode_plmn_str(char *plmn_str, const plmn_t *plmn)
  **      tor network name records                                  **
  **                                                                        **
  ** Inputs:  plmn:      The PLMN identifier                        **
- **      Others:    user->emm_data->                                 **
  **                                                                        **
  ** Outputs:     None                                                      **
  **      Return:    The index of the PLMN if found in the list **
@@ -1131,32 +1089,32 @@ static int _IdleMode_plmn_str(char *plmn_str, const plmn_t *plmn)
  **      Others:    None                                       **
  **                                                                        **
  ***************************************************************************/
-static int _IldlMode_get_opnn_id(nas_user_t *user, const plmn_t *plmn)
+static int _IldlMode_get_opnn_id(emm_data_t *emm_data, const plmn_t *plmn)
 {
   int i;
 
-  for (i = 0; i < user->emm_data->n_opnns; i++) {
-    if (plmn->MCCdigit1 != user->emm_data->opnn[i].plmn->MCCdigit1) {
+  for (i = 0; i < emm_data->n_opnns; i++) {
+    if (plmn->MCCdigit1 != emm_data->opnn[i].plmn->MCCdigit1) {
       continue;
     }
 
-    if (plmn->MCCdigit2 != user->emm_data->opnn[i].plmn->MCCdigit2) {
+    if (plmn->MCCdigit2 != emm_data->opnn[i].plmn->MCCdigit2) {
       continue;
     }
 
-    if (plmn->MCCdigit3 != user->emm_data->opnn[i].plmn->MCCdigit3) {
+    if (plmn->MCCdigit3 != emm_data->opnn[i].plmn->MCCdigit3) {
       continue;
     }
 
-    if (plmn->MNCdigit1 != user->emm_data->opnn[i].plmn->MNCdigit1) {
+    if (plmn->MNCdigit1 != emm_data->opnn[i].plmn->MNCdigit1) {
       continue;
     }
 
-    if (plmn->MNCdigit2 != user->emm_data->opnn[i].plmn->MNCdigit2) {
+    if (plmn->MNCdigit2 != emm_data->opnn[i].plmn->MNCdigit2) {
       continue;
     }
 
-    if (plmn->MNCdigit3 != user->emm_data->opnn[i].plmn->MNCdigit3) {
+    if (plmn->MNCdigit3 != emm_data->opnn[i].plmn->MNCdigit3) {
       continue;
     }
 
@@ -1177,7 +1135,6 @@ static int _IldlMode_get_opnn_id(nas_user_t *user, const plmn_t *plmn)
  **                                                                        **
  ** Inputs:  index:     Index of the selected PLMN in the ordered  **
  **             list of available PLMNs                    **
- **      Others:    _emm_plmn_list.plmn                        **
  **                                                                        **
  ** Outputs:     None                                                      **
  **      Return:    RETURNok, RETURNerror                      **
@@ -1187,12 +1144,14 @@ static int _IldlMode_get_opnn_id(nas_user_t *user, const plmn_t *plmn)
 static int _IdleMode_get_suitable_cell(nas_user_t *user, int index)
 {
   emm_sap_t emm_sap;
-  const plmn_t *plmn = _emm_plmn_list.plmn[index];
+  emm_data_t *emm_data = user->emm_data;
+  emm_plmn_list_t *emm_plmn_list = user->emm_plmn_list;
+  const plmn_t *plmn = emm_plmn_list->plmn[index];
 
   LOG_TRACE(INFO, "EMM-IDLE  - Trying to search a suitable cell "
             "of PLMN %d in %s mode", index,
-            (user->emm_data->plmn_mode == EMM_DATA_PLMN_AUTO)? "Automatic" :
-            (user->emm_data->plmn_mode == EMM_DATA_PLMN_MANUAL)? "Manual" :
+            (emm_data->plmn_mode == EMM_DATA_PLMN_AUTO)? "Automatic" :
+            (emm_data->plmn_mode == EMM_DATA_PLMN_MANUAL)? "Manual" :
             "Automatic/manual");
   /*
    * Notify EMM-AS SAP that cell information related to the given
@@ -1202,8 +1161,8 @@ static int _IdleMode_get_suitable_cell(nas_user_t *user, int index)
   emm_sap.u.emm_as.u.cell_info.plmnIDs.n_plmns = 1;
   emm_sap.u.emm_as.u.cell_info.plmnIDs.plmn[0] = *plmn;
 
-  if (user->emm_data->plmn_rat != NET_ACCESS_UNAVAILABLE) {
-    emm_sap.u.emm_as.u.cell_info.rat = (1 << user->emm_data->plmn_rat);
+  if (emm_data->plmn_rat != NET_ACCESS_UNAVAILABLE) {
+    emm_sap.u.emm_as.u.cell_info.rat = (1 << emm_data->plmn_rat);
   } else {
     emm_sap.u.emm_as.u.cell_info.rat = NET_ACCESS_UNAVAILABLE;
   }
diff --git a/openair3/NAS/UE/EMM/IdleMode.h b/openair3/NAS/UE/EMM/IdleMode.h
index 17b0eabee5..e92e14f5cb 100644
--- a/openair3/NAS/UE/EMM/IdleMode.h
+++ b/openair3/NAS/UE/EMM/IdleMode.h
@@ -63,21 +63,21 @@ typedef int (*IdleMode_callback_t) (emm_data_t *emm_data, int);
 
 void IdleMode_initialize(nas_user_t *user, IdleMode_callback_t cb);
 
-int IdleMode_get_nb_plmns(void);
-int IdleMode_get_hplmn_index(void);
-int IdleMode_get_rplmn_index(void);
-int IdleMode_get_splmn_index(void);
+int IdleMode_get_nb_plmns(emm_plmn_list_t *emm_plmn_list);
+int IdleMode_get_hplmn_index(emm_plmn_list_t *emm_plmn_list);
+int IdleMode_get_rplmn_index(emm_plmn_list_t *emm_plmn_list);
+int IdleMode_get_splmn_index(emm_plmn_list_t *emm_plmn_list);
 
-int IdleMode_update_plmn_list(emm_data_t *emm_data, int i);
+int IdleMode_update_plmn_list(emm_plmn_list_t *emm_plmn_list, emm_data_t *emm_data, int i);
 
-const char *IdleMode_get_plmn_fullname(const plmn_t *plmn, int index,
+const char *IdleMode_get_plmn_fullname(emm_plmn_list_t *emm_plmn_list, const plmn_t *plmn, int index,
                                        size_t *len);
-const char *IdleMode_get_plmn_shortname(const plmn_t *plmn, int index,
+const char *IdleMode_get_plmn_shortname(emm_plmn_list_t *emm_plmn_list, const plmn_t *plmn, int index,
                                         size_t *len);
-const char *IdleMode_get_plmn_id(const plmn_t *plmn, int index, size_t *len);
+const char *IdleMode_get_plmn_id(emm_plmn_list_t *emm_plmn_list, const plmn_t *plmn, int index, size_t *len);
 
-int IdleMode_get_plmn_fullname_index(const char *plmn);
-int IdleMode_get_plmn_shortname_index(const char *plmn);
-int IdleMode_get_plmn_id_index(const char *plmn);
+int IdleMode_get_plmn_fullname_index(emm_plmn_list_t *emm_plmn_list, const char *plmn);
+int IdleMode_get_plmn_shortname_index(emm_plmn_list_t *emm_plmn_list, const char *plmn);
+int IdleMode_get_plmn_id_index(emm_plmn_list_t *emm_plmn_list, const char *plmn);
 
 #endif /* __IDLEMODE_H__*/
diff --git a/openair3/NAS/UE/EMM/IdleMode_defs.h b/openair3/NAS/UE/EMM/IdleMode_defs.h
new file mode 100644
index 0000000000..8ef6c8e86d
--- /dev/null
+++ b/openair3/NAS/UE/EMM/IdleMode_defs.h
@@ -0,0 +1,52 @@
+#ifndef _IDLEMODE_DEFS_H
+#define _IDLEMODE_DEFS_H
+
+/*
+ * A list of PLMN identities in priority order is maintained locally
+ * to perform the PLMN selection procedure.
+ *
+ * In automatic mode of operation, this list is used for PLMN selection when
+ * the UE is switched on, or upon recovery from lack of coverage, or when the
+ * user requests the UE to initiate PLMN reselection, and registration.
+ * In manual mode of operation, this list is displayed to the user that may
+ * select an available PLMN and initiate registration.
+ *
+ * The list may contain PLMN identifiers in the following order:
+ * - The last registered PLMN or each equivalent PLMN present in the list of
+ *   "equivalent PLMNs" (EPLMN_MAX), when UE is switched on or following
+ *   recovery from lack of coverage;
+ * - The highest priority PLMN in the list of "equivalent HPLMNs" or the
+ *   HPLMN derived from the IMSI (1)
+ * - Each PLMN/access technology combination in the "User Controlled PLMN
+ *   Selector with Access Technology" (PLMN_MAX)
+ * - Each PLMN/access technology combination in the "Operator Controlled PLMN
+ *   Selector with Access Technology" (OPLMN_MAX)
+ * - Other PLMN/access technology combinations with received high quality
+ *   signal in random order (TODO)
+ * - Other PLMN/access technology combinations in order of decreasing signal
+ *   quality (TODO)
+ * - The last selected PLMN again (1)
+ */
+typedef struct {
+  int n_plmns;
+#define EMM_PLMN_LIST_SIZE (EMM_DATA_EPLMN_MAX + EMM_DATA_PLMN_MAX +    \
+                            EMM_DATA_OPLMN_MAX + 2)
+  plmn_t *plmn[EMM_PLMN_LIST_SIZE];
+  int index;    /* Index of the PLMN for which selection is ongoing        */
+  int hplmn;    /* Index of the home PLMN or the highest priority
+           * equivalent home PLMN                    */
+  int fplmn;    /* Index of the first forbidden PLMN               */
+  int splmn;    /* Index of the currently selected PLMN            */
+  int rplmn;    /* Index of the currently registered PLMN          */
+  struct plmn_param_t {
+    char fullname[NET_FORMAT_LONG_SIZE+1];   /* PLMN full identifier     */
+    char shortname[NET_FORMAT_SHORT_SIZE+1]; /* PLMN short identifier    */
+    char num[NET_FORMAT_NUM_SIZE+1];     /* PLMN numeric identifier  */
+    int stat; /* Indication of the PLMN availability             */
+    int tac;  /* Location/Tracking Area Code                 */
+    int ci;   /* Serving cell identifier                     */
+    int rat;  /* Radio Access Technology supported by the serving cell   */
+  } param[EMM_PLMN_LIST_SIZE];
+} emm_plmn_list_t;
+
+#endif
diff --git a/openair3/NAS/UE/EMM/emm_main.c b/openair3/NAS/UE/EMM/emm_main.c
index 591c9e6b0f..a1d4260923 100644
--- a/openair3/NAS/UE/EMM/emm_main.c
+++ b/openair3/NAS/UE/EMM/emm_main.c
@@ -63,10 +63,10 @@ static int _emm_main_get_imei(imei_t *imei, const char *imei_str);
 
 static int _emm_main_imsi_cmp(imsi_t *imsi1, imsi_t *imsi2);
 
-static const char *_emm_main_get_plmn(const plmn_t *plmn, int index,
+static const char *_emm_main_get_plmn(emm_plmn_list_t *emm_plmn_list, const plmn_t *plmn, int index,
                                       int format, size_t *size);
 
-static int _emm_main_get_plmn_index(const char *plmn, int format);
+static int _emm_main_get_plmn_index(emm_plmn_list_t *emm_plmn_list, const char *plmn, int format);
 
 /*
  * USIM application data
@@ -538,12 +538,14 @@ const msisdn_t *emm_main_get_msisdn(void)
  **      Others:    user->emm_data->                                 **
  **                                                                        **
  ***************************************************************************/
-int emm_main_set_plmn_selection_mode(emm_data_t *emm_data, int mode, int format,
+int emm_main_set_plmn_selection_mode(nas_user_t *user, int mode, int format,
                                      const network_plmn_t *plmn, int rat)
 {
   LOG_FUNC_IN;
 
   int index;
+  emm_data_t *emm_data = user->emm_data;
+  emm_plmn_list_t *emm_plmn_list = user->emm_plmn_list;
 
   LOG_TRACE(INFO, "EMM-MAIN  - PLMN selection: mode=%d, format=%d, plmn=%s, "
             "rat=%d", mode, format, (const char *)&plmn->id, rat);
@@ -552,7 +554,7 @@ int emm_main_set_plmn_selection_mode(emm_data_t *emm_data, int mode, int format,
 
   if (mode != EMM_DATA_PLMN_AUTO) {
     /* Get the index of the PLMN in the list of available PLMNs */
-    index = _emm_main_get_plmn_index((const char *)&plmn->id, format);
+    index = _emm_main_get_plmn_index(emm_plmn_list, (const char *)&plmn->id, format);
 
     if (index < 0) {
       LOG_TRACE(WARNING, "EMM-MAIN  - PLMN %s not available",
@@ -568,7 +570,7 @@ int emm_main_set_plmn_selection_mode(emm_data_t *emm_data, int mode, int format,
      * register to when switched on; the equivalent PLMNs list shall not be
      * applied to the user reselection in Automatic Network Selection Mode.
      */
-    index = IdleMode_get_hplmn_index();
+    index = IdleMode_get_hplmn_index(emm_plmn_list);
   }
 
   LOG_FUNC_RETURN (index);
@@ -609,11 +611,11 @@ int emm_main_get_plmn_selection_mode(emm_data_t *emm_data)
  **      Others:    None                                       **
  **                                                                        **
  ***************************************************************************/
-int emm_main_get_plmn_list(emm_data_t *emm_data, const char **plist)
+int emm_main_get_plmn_list(emm_plmn_list_t *emm_plmn_list, emm_data_t *emm_data, const char **plist)
 {
   LOG_FUNC_IN;
 
-  int size = IdleMode_update_plmn_list(emm_data, 0);
+  int size = IdleMode_update_plmn_list(emm_plmn_list, emm_data, 0);
   *plist = emm_data->plist.buffer;
 
   LOG_FUNC_RETURN (size);
@@ -635,7 +637,7 @@ int emm_main_get_plmn_list(emm_data_t *emm_data, const char **plist)
  **      Others:    None                                       **
  **                                                                        **
  ***************************************************************************/
-const char *emm_main_get_selected_plmn(emm_data_t *emm_data, network_plmn_t *plmn, int format)
+const char *emm_main_get_selected_plmn(emm_plmn_list_t *emm_plmn_list, emm_data_t *emm_data, network_plmn_t *plmn, int format)
 {
   LOG_FUNC_IN;
 
@@ -643,10 +645,10 @@ const char *emm_main_get_selected_plmn(emm_data_t *emm_data, network_plmn_t *plm
   /*
    * Get the identifier of the selected PLMN in the list of available PLMNs
    */
-  int index = IdleMode_get_splmn_index();
+  int index = IdleMode_get_splmn_index(emm_plmn_list);
 
   if ( !(index < 0) ) {
-    const char *name = _emm_main_get_plmn(&emm_data->splmn, index,
+    const char *name = _emm_main_get_plmn(emm_plmn_list, &emm_data->splmn, index,
                                           format, &size);
 
     if (size > 0) {
@@ -673,7 +675,7 @@ const char *emm_main_get_selected_plmn(emm_data_t *emm_data, network_plmn_t *plm
  **      Others:    None                                       **
  **                                                                        **
  ***************************************************************************/
-const char *emm_main_get_registered_plmn(emm_data_t *emm_data, network_plmn_t *plmn, int format)
+const char *emm_main_get_registered_plmn(emm_plmn_list_t *emm_plmn_list, emm_data_t *emm_data, network_plmn_t *plmn, int format)
 {
   LOG_FUNC_IN;
 
@@ -682,10 +684,10 @@ const char *emm_main_get_registered_plmn(emm_data_t *emm_data, network_plmn_t *p
   /*
    * Get the identifier of the registered PLMN in the list of available PLMNs
    */
-  int index = IdleMode_get_rplmn_index();
+  int index = IdleMode_get_rplmn_index(emm_plmn_list);
 
   if ( !(index < 0) ) {
-    const char *name = _emm_main_get_plmn(&emm_data->nvdata.rplmn,
+    const char *name = _emm_main_get_plmn(emm_plmn_list, &emm_data->nvdata.rplmn,
                                           index, format, &size);
 
     if (size > 0) {
@@ -952,24 +954,24 @@ static int _emm_main_imsi_cmp(imsi_t *imsi1, imsi_t *imsi2)
  **      Others:    None                                       **
  **                                                                        **
  ***************************************************************************/
-static const char *_emm_main_get_plmn(const plmn_t *plmn, int index,
+static const char *_emm_main_get_plmn(emm_plmn_list_t *emm_plmn_list, const plmn_t *plmn, int index,
                                       int format, size_t *size)
 {
   if ( PLMN_IS_VALID(*plmn) ) {
     switch (format) {
     case NET_FORMAT_LONG:
       /* Get the long alpha-numeric representation of the PLMN */
-      return IdleMode_get_plmn_fullname(plmn, index, size);
+      return IdleMode_get_plmn_fullname(emm_plmn_list, plmn, index, size);
       break;
 
     case NET_FORMAT_SHORT:
       /* Get the short alpha-numeric representation of the PLMN */
-      return IdleMode_get_plmn_shortname(plmn, index, size);
+      return IdleMode_get_plmn_shortname(emm_plmn_list, plmn, index, size);
       break;
 
     case NET_FORMAT_NUM:
       /* Get the numeric representation of the PLMN */
-      return IdleMode_get_plmn_id(plmn, index, size);
+      return IdleMode_get_plmn_id(emm_plmn_list, plmn, index, size);
       break;
 
     default:
@@ -1002,24 +1004,24 @@ static const char *_emm_main_get_plmn(const plmn_t *plmn, int index,
  **      Others:    None                                       **
  **                                                                        **
  ***************************************************************************/
-static int _emm_main_get_plmn_index(const char *plmn, int format)
+static int _emm_main_get_plmn_index(emm_plmn_list_t *emm_plmn_list, const char *plmn, int format)
 {
   int index = -1;
 
   switch (format) {
   case NET_FORMAT_LONG:
     /* Get the index of the long alpha-numeric PLMN identifier */
-    index = IdleMode_get_plmn_fullname_index(plmn);
+    index = IdleMode_get_plmn_fullname_index(emm_plmn_list, plmn);
     break;
 
   case NET_FORMAT_SHORT:
     /* Get the index of the short alpha-numeric PLMN identifier */
-    index = IdleMode_get_plmn_shortname_index(plmn);
+    index = IdleMode_get_plmn_shortname_index(emm_plmn_list, plmn);
     break;
 
   case NET_FORMAT_NUM:
     /* Get the index of the numeric PLMN identifier */
-    index = IdleMode_get_plmn_id_index(plmn);
+    index = IdleMode_get_plmn_id_index(emm_plmn_list, plmn);
     break;
 
   default:
diff --git a/openair3/NAS/UE/EMM/emm_main.h b/openair3/NAS/UE/EMM/emm_main.h
index dfb8049f07..90b5be0b8c 100644
--- a/openair3/NAS/UE/EMM/emm_main.h
+++ b/openair3/NAS/UE/EMM/emm_main.h
@@ -80,18 +80,18 @@ const imsi_t *emm_main_get_imsi(emm_data_t *emm_data);
 const msisdn_t *emm_main_get_msisdn(void);
 
 /* User's getter/setter for network selection */
-int emm_main_set_plmn_selection_mode(emm_data_t *emm_data, int mode, int format,
+int emm_main_set_plmn_selection_mode(nas_user_t *user, int mode, int format,
                                      const network_plmn_t *plmn, int rat);
 int emm_main_get_plmn_selection_mode(emm_data_t *emm_data);
-int emm_main_get_plmn_list(emm_data_t *emm_data, const char **plist);
-const char *emm_main_get_selected_plmn(emm_data_t *emm_data, network_plmn_t *plmn, int format);
+int emm_main_get_plmn_list(emm_plmn_list_t *emm_plmn_list, emm_data_t *emm_data, const char **plist);
+const char *emm_main_get_selected_plmn(emm_plmn_list_t *emm_plmn_list, emm_data_t *emm_data, network_plmn_t *plmn, int format);
 
 /* User's getter for network registration */
 Stat_t emm_main_get_plmn_status(emm_data_t *emm_data);
 tac_t emm_main_get_plmn_tac(emm_data_t *emm_data);
 ci_t emm_main_get_plmn_ci(emm_data_t *emm_data);
 AcT_t emm_main_get_plmn_rat(emm_data_t *emm_data);
-const char *emm_main_get_registered_plmn(emm_data_t *emm_data, network_plmn_t *plmn, int format);
+const char *emm_main_get_registered_plmn(emm_plmn_list_t *emm_plmn_list, emm_data_t *emm_data, network_plmn_t *plmn, int format);
 
 /* User's getter for network attachment */
 int emm_main_is_attached(emm_data_t *emm_data);
diff --git a/openair3/NAS/UE/EMM/emm_proc.h b/openair3/NAS/UE/EMM/emm_proc.h
index 0aaf76dfa0..0a58270216 100644
--- a/openair3/NAS/UE/EMM/emm_proc.h
+++ b/openair3/NAS/UE/EMM/emm_proc.h
@@ -185,6 +185,6 @@ int emm_proc_security_mode_command(nas_user_t *user, int native_ksi, int ksi, in
  */
 int emm_proc_registration_notify(emm_data_t *emm_data, Stat_t status);
 int emm_proc_location_notify(emm_data_t *emm_data, tac_t tac, ci_t ci, AcT_t rat);
-int emm_proc_network_notify(emm_data_t *emm_data, int index);
+int emm_proc_network_notify(emm_plmn_list_t *emm_plmn_list, emm_data_t *emm_data, int index);
 
 #endif /* __EMM_PROC_H__*/
diff --git a/openair3/NAS/UE/nas_proc.c b/openair3/NAS/UE/nas_proc.c
index ee7b4f52c0..f707c983d2 100644
--- a/openair3/NAS/UE/nas_proc.c
+++ b/openair3/NAS/UE/nas_proc.c
@@ -386,7 +386,7 @@ int nas_proc_register(nas_user_t *user, int mode, int format, const network_plmn
   /*
    * Set the PLMN selection mode of operation
    */
-  int index = emm_main_set_plmn_selection_mode(user->emm_data, mode, format, oper, AcT);
+  int index = emm_main_set_plmn_selection_mode(user, mode, format, oper, AcT);
 
   if ( !(index < 0) ) {
     /*
@@ -455,7 +455,7 @@ int nas_proc_get_reg_data(nas_user_t *user, int *mode, int *selected, int format
   *mode = emm_main_get_plmn_selection_mode(user->emm_data);
 
   /* Get the currently selected operator */
-  const char *oper_name = emm_main_get_selected_plmn(user->emm_data, oper, format);
+  const char *oper_name = emm_main_get_selected_plmn(user->emm_plmn_list, user->emm_data, oper, format);
 
   if (oper_name != NULL) {
     /* An operator is currently selected */
@@ -489,7 +489,7 @@ int nas_proc_get_oper_list(nas_user_t *user, const char **oper_list)
 {
   LOG_FUNC_IN;
 
-  int size = emm_main_get_plmn_list(user->emm_data, oper_list);
+  int size = emm_main_get_plmn_list(user->emm_plmn_list, user->emm_data, oper_list);
 
   LOG_FUNC_RETURN (size);
 }
diff --git a/openair3/NAS/UE/user_defs.h b/openair3/NAS/UE/user_defs.h
index 05ce952f22..7a2851ae5e 100644
--- a/openair3/NAS/UE/user_defs.h
+++ b/openair3/NAS/UE/user_defs.h
@@ -50,6 +50,7 @@ Description NAS type definition to manage a user equipment
 #include "esm_pt_defs.h"
 #include "EMM/emm_fsm_defs.h"
 #include "EMM/emmData.h"
+#include "EMM/IdleMode_defs.h"
 
 typedef struct {
   int fd;
@@ -59,6 +60,7 @@ typedef struct {
   esm_ebr_data_t *esm_ebr_data;  // EPS bearer contexts
   emm_fsm_state_t emm_fsm_status; // Current EPS Mobility Management status
   emm_data_t *emm_data; // EPS mobility management data
+  emm_plmn_list_t *emm_plmn_list; // list of PLMN identities
 } nas_user_t;
 
 #endif
-- 
GitLab