layer23: subscriber: Implement LOCIGPRS read/write for testcard backend

Change-Id: Ibcaaf430587a3a270398e9a9eeab6ee98514c3c8
This commit is contained in:
Pau Espin 2023-05-19 14:55:24 +02:00
parent 9be9a2ef7f
commit 8bd2e644b5
5 changed files with 207 additions and 5 deletions

View File

@ -5,6 +5,9 @@
#include <osmocom/core/linuxlist.h>
#include <osmocom/gsm/protocol/gsm_23_003.h>
#include <osmocom/gsm/gsm23003.h>
#include <osmocom/gsm/gsm48.h>
#include <osmocom/bb/common/sim.h>
struct osmocom_ms;
struct osmobb_apn;
@ -69,6 +72,14 @@ struct test_sim_settings {
uint16_t lac;
bool imsi_attached;
bool always_search_hplmn;
struct {
bool valid;
uint32_t ptmsi; /* invalid tmsi: GSM_RESERVED_TMSI */
uint32_t ptmsi_sig; /* P-TMSI signature, 3 bytes */
struct gprs_ra_id rai;
enum gsm1111_ef_locigprs_rau_status gu_state; /* GU, TS 24.008 */
bool imsi_attached;
} locigprs;
};
struct gsm_settings {

View File

@ -20,6 +20,8 @@
#include <osmocom/gsm/protocol/gsm_04_08.h>
#include <osmocom/core/endian.h>
struct osmocom_ms;
/* 9.2 commands */
#define GSM1111_CLASS_GSM 0xa0
#define GSM1111_INST_SELECT 0xa4

View File

@ -112,6 +112,7 @@ struct gsm_subscriber {
struct {
uint8_t gu_state; /* GU, TS 24.008 */
bool rai_valid;
struct gprs_ra_id rai;
uint32_t ptmsi; /* invalid tmsi: GSM_RESERVED_TMSI */
uint32_t ptmsi_sig; /* P-TMSI signature, 3 bytes */

View File

@ -67,6 +67,7 @@ static int gsm_subscr_generate_kc_testcard(struct osmocom_ms *ms, uint8_t key_se
static int gsm_subscr_write_loci_simcard(struct osmocom_ms *ms);
static int gsm_subscr_write_locigprs_simcard(struct osmocom_ms *ms);
static int gsm_subscr_write_locigprs_testcard(struct osmocom_ms *ms);
static int gsm_subscr_sim_pin_simcard(struct osmocom_ms *ms, const char *pin1, const char *pin2,
int8_t mode);
@ -331,8 +332,7 @@ int gsm_subscr_write_locigprs(struct osmocom_ms *ms)
case GSM_SIM_TYPE_SAP:
return gsm_subscr_write_locigprs_simcard(ms);
case GSM_SIM_TYPE_TEST:
LOGP(DMM, LOGL_NOTICE, "Updating LOCIGPRS on test SIM: not implemented!\n");
return 0; /* TODO */
return gsm_subscr_write_locigprs_testcard(ms);
default:
OSMO_ASSERT(0);
}
@ -582,7 +582,6 @@ int gsm_subscr_insert_testcard(struct osmocom_ms *ms)
memcpy(&subscr->lai.plmn, &set->test_sim.rplmn, sizeof(struct osmo_plmn_id));
subscr->lai.lac = set->test_sim.lac;
subscr->tmsi = set->test_sim.tmsi;
subscr->gprs.ptmsi = GSM_RESERVED_TMSI;
subscr->always_search_hplmn = set->test_sim.always_search_hplmn;
subscr->t6m_hplmn = 1; /* try to find home network every 6 min */
OSMO_STRLCPY_ARRAY(subscr->imsi, set->test_sim.imsi);
@ -592,13 +591,25 @@ int gsm_subscr_insert_testcard(struct osmocom_ms *ms)
else
subscr->ustate = GSM_SIM_U2_NOT_UPDATED;
LOGP(DMM, LOGL_INFO, "(ms %s) Inserting test card (IMSI=%s %s, %s)\n",
/* GPRS related: */
subscr->gprs.ptmsi = set->test_sim.locigprs.ptmsi;
subscr->gprs.ptmsi_sig = set->test_sim.locigprs.ptmsi_sig;
subscr->gprs.imsi_attached = set->test_sim.locigprs.imsi_attached;
subscr->gprs.rai_valid = set->test_sim.locigprs.valid;
memcpy(&subscr->gprs.rai, &set->test_sim.locigprs.rai, sizeof(subscr->gprs.rai));
if (subscr->gprs.imsi_attached && subscr->gprs.rai_valid)
subscr->ustate = GSM_SIM_U1_UPDATED;
else
subscr->ustate = GSM_SIM_U2_NOT_UPDATED;
LOGP(DMM, LOGL_INFO, "(ms %s) Inserting test card (IMSI=%s, %s, %s)\n",
ms->name, subscr->imsi, gsm_imsi_mcc(subscr->imsi),
gsm_imsi_mnc(subscr->imsi));
if (subscr->plmn_valid)
LOGP(DMM, LOGL_INFO, "-> Test card registered to %s"
"(%s, %s)\n", osmo_lai_name(&subscr->lai),
" (%s, %s)\n", osmo_lai_name(&subscr->lai),
gsm_get_mcc(subscr->lai.plmn.mcc),
gsm_get_mnc(&subscr->lai.plmn));
else
@ -606,6 +617,16 @@ int gsm_subscr_insert_testcard(struct osmocom_ms *ms)
if (subscr->imsi_attached)
LOGP(DMM, LOGL_INFO, "-> Test card attached\n");
/* GPRS:*/
if (subscr->gprs.rai_valid)
LOGP(DMM, LOGL_INFO, "-> Test card GPRS registered to %s\n",
osmo_rai_name(&subscr->gprs.rai));
else
LOGP(DMM, LOGL_INFO, "-> Test card not GPRS registered\n");
if (subscr->gprs.imsi_attached)
LOGP(DMM, LOGL_INFO, "-> Test card GPRS attached\n");
/* insert card */
osmo_signal_dispatch(SS_L23_SUBSCR, S_L23_SUBSCR_SIM_ATTACHED, ms);
return 0;
@ -642,6 +663,56 @@ static int gsm_subscr_generate_kc_testcard(struct osmocom_ms *ms, uint8_t key_se
return 0;
}
/* update LOCIGPRS on test SIM */
int gsm_subscr_write_locigprs_testcard(struct osmocom_ms *ms)
{
struct gsm_subscriber *subscr = &ms->subscr;
struct msgb *nmsg;
struct sim_hdr *nsh;
struct gsm1111_ef_locigprs *locigprs;
/* skip, if no real valid SIM */
if (!GSM_SIM_IS_READER(subscr->sim_type) || !subscr->sim_valid)
return 0;
LOGP(DMM, LOGL_INFO, "Updating LOCI on SIM\n");
/* write to SIM */
nmsg = gsm_sim_msgb_alloc(subscr->sim_handle_update,
SIM_JOB_UPDATE_BINARY);
if (!nmsg)
return -ENOMEM;
nsh = (struct sim_hdr *) nmsg->data;
nsh->path[0] = 0x7f20;
nsh->path[1] = 0;
nsh->file = 0x6f53;
locigprs = (struct gsm1111_ef_locigprs *)msgb_put(nmsg, sizeof(*locigprs));
/* P-TMSI, P-TMSI signature */
locigprs->ptmsi = htonl(subscr->gprs.ptmsi);
locigprs->ptmsi_sig_hi = htonl(subscr->gprs.ptmsi) >> 8;
locigprs->ptmsi_sig_lo = htonl(subscr->gprs.ptmsi) & 0xff;
/* RAI */
gsm48_encode_ra(&locigprs->rai, &subscr->gprs.rai);
/* location update status */
switch (subscr->gprs.gu_state) {
case GSM_SIM_GU1_UPDATED:
locigprs->rau_status = GSM1111_EF_LOCIGPRS_RAU_ST_UPDATED;
break;
case GSM_SIM_GU3_ROAMING_NA:
locigprs->rau_status = GSM1111_EF_LOCIGPRS_RAU_ST_RA_NOT_ALLOWED;
break;
default:
locigprs->rau_status = GSM1111_EF_LOCIGPRS_RAU_ST_NOT_UPDATED;
}
sim_job(ms, nmsg);
return 0;
}
/********************
* simcard backend
********************/
@ -738,6 +809,7 @@ static int subscr_sim_locigprs(struct osmocom_ms *ms, uint8_t *data,
subscr->gprs.ptmsi_sig = (((uint32_t)locigprs->ptmsi_sig_hi) << 8) | locigprs->ptmsi_sig_lo;
/* RAI */
subscr->gprs.rai_valid = true;
gsm48_parse_ra(&subscr->gprs.rai, (uint8_t *)&locigprs->rai);
/* routing area update status */

View File

@ -1127,6 +1127,95 @@ DEFUN(cfg_testsim_hplmn, cfg_testsim_hplmn_cmd, "hplmn-search (everywhere|foreig
return CMD_SUCCESS;
}
static int _testsim_locigprs_cmd(struct vty *vty, int argc, const char *argv[], bool attached)
{
struct osmocom_ms *ms = vty->index;
struct gsm_settings *set = &ms->settings;
struct osmo_plmn_id plmn;
if (osmo_mcc_from_str(argv[0], &plmn.mcc) < 0) {
vty_out(vty, "Given MCC invalid%s", VTY_NEWLINE);
return CMD_WARNING;
}
if (osmo_mnc_from_str(argv[1], &plmn.mnc, &plmn.mnc_3_digits) < 0) {
vty_out(vty, "Given MNC invalid%s", VTY_NEWLINE);
return CMD_WARNING;
}
set->test_sim.locigprs.valid = true;
set->test_sim.locigprs.rai.mcc = plmn.mcc;
set->test_sim.locigprs.rai.mnc = plmn.mnc;
set->test_sim.locigprs.rai.mnc_3_digits = plmn.mnc_3_digits;
if (argc >= 3)
set->test_sim.locigprs.rai.lac = strtoul(argv[2], NULL, 16);
else
set->test_sim.locigprs.rai.lac = 0xfffe;
if (argc >= 4)
set->test_sim.locigprs.rai.rac = strtoul(argv[3], NULL, 16);
else
set->test_sim.locigprs.rai.rac = 0xff;
if (argc >= 5)
set->test_sim.locigprs.ptmsi = strtoul(argv[4], NULL, 16);
else
set->test_sim.locigprs.ptmsi = GSM_RESERVED_TMSI;
if (argc >= 6)
set->test_sim.locigprs.ptmsi_sig = strtoul(argv[5], NULL, 16);
else
set->test_sim.locigprs.ptmsi_sig = GSM_RESERVED_TMSI;
set->test_sim.locigprs.imsi_attached = attached;
l23_vty_restart_required_warn(vty, ms);
return CMD_SUCCESS;
}
DEFUN(cfg_testsim_no_locigprs, cfg_testsim_no_locigprs_cmd, "no locigprs",
NO_STR "Unset EF LOCIgprs\n")
{
struct osmocom_ms *ms = vty->index;
struct gsm_settings *set = &ms->settings;
set->test_sim.locigprs.valid = false;
set->test_sim.locigprs.ptmsi = GSM_RESERVED_TMSI;
set->test_sim.locigprs.ptmsi_sig = GSM_RESERVED_TMSI;
set->test_sim.locigprs.rai.mcc = 1;
set->test_sim.locigprs.rai.mnc = 1;
set->test_sim.locigprs.rai.mnc_3_digits = false;
set->test_sim.locigprs.rai.lac = 0x0000;
set->test_sim.locigprs.rai.rac = 0x0000;
l23_vty_restart_required_warn(vty, ms);
return CMD_SUCCESS;
}
DEFUN(cfg_testsim_locigprs, cfg_testsim_locigprs_cmd,
"locigprs MCC MNC [LAC] [RAC] [PTMSI] [PTMSISIG]",
"Set EF LOCIgprs\nMobile Country Code\nMobile Network Code\n"
"Optionally set location area code\n"
"Optionally set routing area code\n"
"Optionally set current assigned P-TMSI\n"
"Optionally set current assigned P-TMSI signature\n")
{
return _testsim_locigprs_cmd(vty, argc, argv, false);
}
DEFUN(cfg_testsim_locigprs_att, cfg_testsim_locigprs_att_cmd,
"locigprs MCC MNC LAC RAC PTMSI PTMSISIG attached",
"Set EF LOCIgprs\nMobile Country Code\nMobile Network Code\n"
"Set location area code\n"
"Set routing area code\n"
"Set current assigned P-TMSI\n"
"Set current assigned P-TMSI signature\n"
"Indicate to MM that card is already attached\n")
{
return _testsim_locigprs_cmd(vty, argc, argv, true);
}
static int l23_vty_config_write_gsmtap_node(struct vty *vty)
{
const char *chan_buf;
@ -1213,10 +1302,34 @@ static int l23_vty_config_write_testsim_node(struct vty *vty, const struct osmoc
} else
if (!l23_vty_hide_default)
vty_out(vty, "%s no rplmn%s", prefix, VTY_NEWLINE);
if (!l23_vty_hide_default || set->test_sim.always_search_hplmn)
vty_out(vty, "%s hplmn-search %s%s", prefix,
set->test_sim.always_search_hplmn ? "everywhere" : "foreign-country",
VTY_NEWLINE);
if (set->test_sim.locigprs.valid) {
vty_out(vty, "%s locigprs %s %s", prefix,
osmo_mcc_name(set->test_sim.locigprs.rai.mcc),
osmo_mnc_name(set->test_sim.locigprs.rai.mnc,
set->test_sim.locigprs.rai.mnc_3_digits));
if (set->test_sim.locigprs.rai.lac > 0x0000 && set->test_sim.locigprs.rai.lac < 0xfffe) {
vty_out(vty, " 0x%04x", set->test_sim.locigprs.rai.lac);
if (set->test_sim.locigprs.rai.rac < 0xff) {
vty_out(vty, " 0x%02x", set->test_sim.locigprs.rai.rac);
if (set->test_sim.locigprs.ptmsi != GSM_RESERVED_TMSI) {
vty_out(vty, " 0x%08x 0x%06x",
set->test_sim.locigprs.ptmsi,
set->test_sim.locigprs.ptmsi_sig);
if (set->test_sim.locigprs.imsi_attached)
vty_out(vty, " attached");
}
}
}
vty_out(vty, "%s", VTY_NEWLINE);
} else
if (!l23_vty_hide_default)
vty_out(vty, "%s no locigprs%s", prefix, VTY_NEWLINE);
return CMD_SUCCESS;
}
@ -1368,6 +1481,9 @@ int l23_vty_init(int (*config_write_ms_node_cb)(struct vty *), osmo_signal_cbfn
install_element(TESTSIM_NODE, &cfg_testsim_rplmn_cmd);
install_element(TESTSIM_NODE, &cfg_testsim_rplmn_att_cmd);
install_element(TESTSIM_NODE, &cfg_testsim_hplmn_cmd);
install_element(TESTSIM_NODE, &cfg_testsim_no_locigprs_cmd);
install_element(TESTSIM_NODE, &cfg_testsim_locigprs_cmd);
install_element(TESTSIM_NODE, &cfg_testsim_locigprs_att_cmd);
install_element(MS_NODE, &cfg_ms_shutdown_cmd);
install_element(MS_NODE, &cfg_ms_shutdown_force_cmd);
install_element(MS_NODE, &cfg_ms_no_shutdown_cmd);