Migrate network identifier fields to modern osmocom structures

This allows using well tested standarized API to print, compare, etc. usual
identifiers like PLMN, LAI, etc.
It also simplifies code by avoiding passing lots of parameters and
making it easier to identify which fields go packed together.
This is specially important since in the future more of those
identifiers will be added for GPRS.

Change-Id: I07a9289825c09ed748e53d36a746ea164c8a5d7f
This commit is contained in:
Pau Espin 2023-05-18 18:51:03 +02:00
parent 554e7cfb56
commit 3348f49179
19 changed files with 600 additions and 766 deletions

View File

@ -1,24 +1,27 @@
#ifndef _NETWORKS_H
#define _NETWORKS_H
#include <osmocom/gsm/gsm23003.h>
#define GSM_INPUT_INVALID 0xffff
/* Instead of handling numerical MCC and MNC, they stored and handled
* hexadecimal. This makes it possible
* to correctly handle 2 and 3 digits MNC. Internally 2 digit MNCs are stored
* as 0xXXf, and 3 digits MNC are stored as 0xXXX, where X is the digit 0..9.
*/
struct gsm_networks {
uint16_t mcc;
int16_t mnc;
uint16_t mcc_hex;
int16_t mnc_hex;
const char *name;
};
int gsm_match_mcc(uint16_t mcc, char *imsi);
int gsm_match_mnc(uint16_t mcc, uint16_t mnc, char *imsi);
const char *gsm_print_mcc(uint16_t mcc);
const char *gsm_print_mnc(uint16_t mcc);
int gsm_match_mnc(uint16_t mcc, uint16_t mnc, bool mnc_3_digits, char *imsi);
const char *gsm_get_mcc(uint16_t mcc);
const char *gsm_get_mnc(uint16_t mcc, uint16_t mnc);
const char *gsm_get_mnc(const struct osmo_plmn_id *plmn);
const char *gsm_imsi_mcc(char *imsi);
const char *gsm_imsi_mnc(char *imsi);
const uint16_t gsm_input_mcc(char *string);
const uint16_t gsm_input_mnc(char *string);
uint16_t gsm_mcc_to_hex(uint16_t mcc);
uint16_t gsm_mnc_to_hex(uint16_t mnc, bool mnc_3_digits);
#endif /* _NETWORKS_H */

View File

@ -4,6 +4,7 @@
#include <osmocom/core/utils.h>
#include <osmocom/core/linuxlist.h>
#include <osmocom/gsm/protocol/gsm_23_003.h>
#include <osmocom/gsm/gsm23003.h>
struct osmocom_ms;
struct osmobb_apn;
@ -64,7 +65,7 @@ struct test_sim_settings {
uint8_t ki[16]; /* 128 bit max */
uint8_t barr;
uint8_t rplmn_valid;
uint16_t rplmn_mcc, rplmn_mnc;
struct osmo_plmn_id rplmn;
uint16_t lac;
uint8_t imsi_attached;
uint8_t always; /* ...search hplmn... */

View File

@ -5,6 +5,7 @@
#include <osmocom/core/utils.h>
#include <osmocom/gsm/protocol/gsm_23_003.h>
#include <osmocom/gsm/gsm23003.h>
/* GSM 04.08 4.1.2.2 SIM update status */
enum gsm_sub_sim_ustate {
@ -22,12 +23,12 @@ static inline const char *gsm_sub_sim_ustate_name(enum gsm_sub_sim_ustate val)
struct gsm_sub_plmn_list {
struct llist_head entry;
uint16_t mcc, mnc;
struct osmo_plmn_id plmn;
};
struct gsm_sub_plmn_na {
struct llist_head entry;
uint16_t mcc, mnc;
struct osmo_plmn_id plmn;
uint8_t cause;
};
@ -58,7 +59,7 @@ struct gsm_subscriber {
/* TMSI / LAI */
uint32_t tmsi; /* invalid tmsi: GSM_RESERVED_TMSI */
uint32_t ptmsi; /* invalid tmsi: GSM_RESERVED_TMSI */
uint16_t mcc, mnc, lac; /* invalid lac: 0x0000 */
struct osmo_location_area_id lai; /* invalid lac: 0x0000 */
/* key */
@ -80,7 +81,7 @@ struct gsm_subscriber {
/* PLMN last registered */
uint8_t plmn_valid;
uint16_t plmn_mcc, plmn_mnc;
struct osmo_plmn_id plmn;
/* our access */
uint8_t acc_barr; /* if we may access, if cell barred */
@ -111,12 +112,9 @@ int gsm_subscr_write_loci(struct osmocom_ms *ms);
int gsm_subscr_generate_kc(struct osmocom_ms *ms, uint8_t key_seq, const uint8_t *rand,
bool no_sim);
void new_sim_ustate(struct gsm_subscriber *subscr, int state);
int gsm_subscr_del_forbidden_plmn(struct gsm_subscriber *subscr, uint16_t mcc,
uint16_t mnc);
int gsm_subscr_add_forbidden_plmn(struct gsm_subscriber *subscr, uint16_t mcc,
uint16_t mnc, uint8_t cause);
int gsm_subscr_is_forbidden_plmn(struct gsm_subscriber *subscr, uint16_t mcc,
uint16_t mnc);
int gsm_subscr_del_forbidden_plmn(struct gsm_subscriber *subscr, const struct osmo_plmn_id *plmn);
int gsm_subscr_add_forbidden_plmn(struct gsm_subscriber *subscr, const struct osmo_plmn_id *plmn, uint8_t cause);
int gsm_subscr_is_forbidden_plmn(struct gsm_subscriber *subscr, const struct osmo_plmn_id *plmn);
int gsm_subscr_dump_forbidden_plmn(struct osmocom_ms *ms,
void (*print)(void *, const char *, ...), void *priv);
void gsm_subscr_dump(struct gsm_subscriber *subscr,

View File

@ -2,6 +2,7 @@
#define _SYSINFO_H
#include <osmocom/gsm/gsm48_ie.h>
#include <osmocom/gsm/gsm23003.h>
/* collection of system information of the current cell */
@ -44,7 +45,7 @@ struct gsm48_sysinfo {
/* serving cell */
uint8_t bsic;
uint16_t cell_id;
uint16_t mcc, mnc, lac; /* LAI */
struct osmo_location_area_id lai;
uint8_t max_retrans; /* decoded */
uint8_t tx_integer; /* decoded */
uint8_t reest_denied; /* 1 = denied */
@ -195,9 +196,5 @@ int gsm48_decode_sysinfo13(struct gsm48_sysinfo *s,
int gsm48_decode_mobile_alloc(struct gsm_sysinfo_freq *freq,
const uint8_t *ma, uint8_t len,
uint16_t *hopping, uint8_t *hopp_len, int si4);
int gsm48_encode_lai_hex(struct gsm48_loc_area_id *lai,
uint16_t mcc, uint16_t mnc, uint16_t lac);
int gsm48_decode_lai_hex(const struct gsm48_loc_area_id *lai,
uint16_t *mcc, uint16_t *mnc, uint16_t *lac);
#endif /* _SYSINFO_H */

View File

@ -29,6 +29,7 @@ struct node_mcc {
struct node_mnc {
struct node_mnc *next;
uint16_t mnc;
bool mnc_3_digits;
struct node_lac *lac;
};
@ -75,7 +76,7 @@ struct node_meas {
};
struct node_mcc *get_node_mcc(uint16_t mcc);
struct node_mnc *get_node_mnc(struct node_mcc *mcc, uint16_t mnc);
struct node_mnc *get_node_mnc(struct node_mcc *mcc, uint16_t mnc, bool mnc_3_digits);
struct node_lac *get_node_lac(struct node_mnc *mnc, uint16_t lac);
struct node_cell *get_node_cell(struct node_lac *lac, uint16_t cellid);
struct node_meas *add_node_meas(struct node_cell *cell);

View File

@ -1,10 +1,11 @@
#ifndef _GSM322_H
#define _GSM322_H
#include <osmocom/bb/common/sysinfo.h>
#include <osmocom/core/linuxlist.h>
#include <osmocom/core/timer.h>
#include <osmocom/gsm/gsm23003.h>
#include <osmocom/bb/common/sysinfo.h>
/* 4.3.1.1 List of states for PLMN selection process (automatic mode) */
#define GSM322_A0_NULL 0
@ -74,7 +75,7 @@ enum {
/* node for each PLMN */
struct gsm322_plmn_list {
struct llist_head entry;
uint16_t mcc, mnc;
struct osmo_plmn_id plmn;
uint8_t rxlev; /* rx level in range format */
uint8_t cause; /* cause value, if PLMN is not allowed */
};
@ -82,14 +83,14 @@ struct gsm322_plmn_list {
/* node for each forbidden LA */
struct gsm322_la_list {
struct llist_head entry;
uint16_t mcc, mnc, lac;
struct osmo_location_area_id lai;
uint8_t cause;
};
/* node for each BA-List */
struct gsm322_ba_list {
struct llist_head entry;
uint16_t mcc, mnc;
struct osmo_plmn_id plmn;
/* Band allocation for 1024+299 frequencies.
* First bit of first index is frequency 0.
*/
@ -124,7 +125,7 @@ struct gsm322_plmn {
struct osmo_timer_list timer;
int plmn_curr; /* current index in sorted_plmn */
uint16_t mcc, mnc; /* current network selected */
struct osmo_plmn_id plmn; /* current network selected */
};
/* state of CCCH activation */
@ -171,7 +172,7 @@ struct gsm322_cellsel {
/* cell selection list per frequency. */
/* scan and tune state */
struct osmo_timer_list timer; /* cell selection timer */
uint16_t mcc, mnc; /* current network to search for */
struct osmo_plmn_id plmn; /* current network to search for */
uint8_t powerscan; /* currently scanning for power */
uint8_t ccch_state; /* special state of current ccch */
uint32_t scan_state; /* special state of current scan */
@ -188,7 +189,7 @@ struct gsm322_cellsel {
uint8_t selected; /* if a cell is selected */
uint16_t sel_arfcn; /* current selected serving cell! */
struct gsm48_sysinfo sel_si; /* copy of selected cell, will update */
uint16_t sel_mcc, sel_mnc, sel_lac, sel_id;
struct osmo_cell_global_id sel_cgi;
/* cell re-selection */
struct llist_head nb_list; /* list of neighbour cells */
@ -209,7 +210,7 @@ struct gsm322_cellsel {
/* GSM 03.22 message */
struct gsm322_msg {
int msg_type;
uint16_t mcc, mnc;
struct osmo_plmn_id plmn;
uint8_t sysinfo; /* system information type */
uint8_t same_cell; /* select same cell when RET_IDLE */
uint8_t reject; /* location update reject cause */
@ -229,18 +230,15 @@ int gsm322_cs_sendmsg(struct osmocom_ms *ms, struct msgb *msg);
int gsm322_c_event(struct osmocom_ms *ms, struct msgb *msg);
int gsm322_plmn_dequeue(struct osmocom_ms *ms);
int gsm322_cs_dequeue(struct osmocom_ms *ms);
int gsm322_add_forbidden_la(struct osmocom_ms *ms, uint16_t mcc,
uint16_t mnc, uint16_t lac, uint8_t cause);
int gsm322_del_forbidden_la(struct osmocom_ms *ms, uint16_t mcc,
uint16_t mnc, uint16_t lac);
int gsm322_is_forbidden_la(struct osmocom_ms *ms, uint16_t mcc, uint16_t mnc,
uint16_t lac);
int gsm322_add_forbidden_la(struct osmocom_ms *ms, const struct osmo_location_area_id *lai, uint8_t cause);
int gsm322_del_forbidden_la(struct osmocom_ms *ms, const struct osmo_location_area_id *lai);
int gsm322_is_forbidden_la(struct osmocom_ms *ms, const struct osmo_location_area_id *lai);
int gsm322_dump_sorted_plmn(struct osmocom_ms *ms);
int gsm322_dump_cs_list(struct gsm322_cellsel *cs, uint8_t flags,
void (*print)(void *, const char *, ...), void *priv);
int gsm322_dump_forbidden_la(struct osmocom_ms *ms,
void (*print)(void *, const char *, ...), void *priv);
int gsm322_dump_ba_list(struct gsm322_cellsel *cs, uint16_t mcc, uint16_t mnc,
int gsm322_dump_ba_list(struct gsm322_cellsel *cs, const struct osmo_plmn_id *plmn,
void (*print)(void *, const char *, ...), void *priv);
int gsm322_dump_nb_list(struct gsm322_cellsel *cs,
void (*print)(void *, const char *, ...), void *priv);

View File

@ -186,7 +186,7 @@ struct gsm48_mmlayer {
uint8_t lupd_rej_cause; /* cause of last reject */
uint8_t lupd_periodic; /* periodic update pending */
uint8_t lupd_retry; /* pending T3211/T3213 to */
uint16_t lupd_mcc, lupd_mnc, lupd_lac;
struct osmo_location_area_id lupd_lai;
/* imsi detach */
uint8_t delay_detach; /* do detach when possible */

View File

@ -2,6 +2,8 @@
#include <stdint.h>
#include <stdio.h>
#include <osmocom/gsm/gsm23003.h>
#include <osmocom/bb/common/networks.h>
/* list of networks */
@ -1774,6 +1776,43 @@ static struct gsm_networks gsm_networks[] = {
{ 0, 0, NULL }
};
/* param: numerically stored mcc as per osmo_plmn_id. */
uint16_t gsm_mcc_to_hex(uint16_t mcc)
{
uint8_t buf[3];
uint16_t in = mcc;
buf[2] = in % 10;
in = in / 10;
buf[1] = in % 10;
in = in / 10;
buf[0] = in % 10;
return ((buf[0] << 8) +
(buf[1] << 4) +
buf[2]);
}
/* param: numerically stored mnc as per osmo_plmn_id. */
uint16_t gsm_mnc_to_hex(uint16_t mnc, bool mnc_3_digits)
{
uint8_t buf[3];
uint16_t in = mnc;
if (mnc_3_digits) {
buf[2] = in % 10;
in = in / 10;
} else {
buf[2] = 0x0f;
}
buf[1] = in % 10;
in = in / 10;
buf[0] = in % 10;
return ((buf[0] << 8) +
(buf[1] << 4) +
buf[2]);
}
/* GSM 03.22 Annex A */
int gsm_match_mcc(uint16_t mcc, char *imsi)
{
@ -1783,30 +1822,33 @@ int gsm_match_mcc(uint16_t mcc, char *imsi)
+ ((imsi[1] - '0') << 4)
+ imsi[2] - '0';
return (mcc == sim_mcc);
return (gsm_mcc_to_hex(mcc) == sim_mcc);
}
/* GSM 03.22 Annex A */
int gsm_match_mnc(uint16_t mcc, uint16_t mnc, char *imsi)
int gsm_match_mnc(uint16_t mcc, uint16_t mnc, bool mnc_3_digits, char *imsi)
{
uint16_t sim_mnc;
uint16_t mnc_hex;
/* 1. SIM-MCC = BCCH-MCC */
if (!gsm_match_mcc(mcc, imsi))
return 0;
mnc_hex = gsm_mnc_to_hex(mnc, mnc_3_digits);
/* 2. 3rd digit of BCCH-MNC is not 0xf */
if ((mnc & 0x00f) != 0x00f) {
if ((mnc_hex & 0x00f) != 0x00f) {
/* 3. 3 digit SIM-MNC = BCCH-MNC */
sim_mnc = ((imsi[3] - '0') << 8)
+ ((imsi[4] - '0') << 4)
+ imsi[5] - '0';
return (mnc == sim_mnc);
return (mnc_hex == sim_mnc);
}
/* 4. BCCH-MCC in the range 310-316 */
if (mcc >= 310 && mcc <= 316) {
if (gsm_mcc_to_hex(mcc) >= 310 && mnc_hex <= 316) {
/* 5. 3rd diit of SIM-MNC is 0 */
if (imsi[5] != 0)
return 0;
@ -1817,123 +1859,47 @@ int gsm_match_mnc(uint16_t mcc, uint16_t mnc, char *imsi)
+ ((imsi[4] - '0') << 4)
+ 0x00f;
return (mnc == sim_mnc);
}
const char *gsm_print_mcc(uint16_t mcc)
{
static char string[6] = "000";
snprintf(string, 5, "%03x", mcc);
return string;
}
const char *gsm_print_mnc(uint16_t mnc)
{
static char string[8];
/* invalid format: return hex value */
if ((mnc & 0xf000)
|| (mnc & 0x0f00) > 0x0900
|| (mnc & 0x00f0) > 0x0090
|| ((mnc & 0x000f) > 0x0009 && (mnc & 0x000f) < 0x000f)) {
snprintf(string, 7, "0x%03x", mnc);
return string;
}
/* two digits */
if ((mnc & 0x000f) == 0x000f) {
snprintf(string, 7, "%02x", mnc >> 4);
return string;
}
/* three digits */
snprintf(string, 7, "%03x", mnc);
return string;
}
const uint16_t gsm_input_mcc(char *string)
{
uint16_t mcc;
if (strlen(string) != 3)
return GSM_INPUT_INVALID;
if (string[0] < '0' || string [0] > '9'
|| string[1] < '0' || string [1] > '9'
|| string[2] < '0' || string [2] > '9')
return GSM_INPUT_INVALID;
mcc = ((string[0] - '0') << 8)
| ((string[1] - '0') << 4)
| ((string[2] - '0'));
if (mcc == 0x000)
return GSM_INPUT_INVALID;
return mcc;
}
const uint16_t gsm_input_mnc(char *string)
{
uint16_t mnc = 0;
if (strlen(string) == 2) {
if (string[0] < '0' || string [0] > '9'
|| string[1] < '0' || string [1] > '9')
return GSM_INPUT_INVALID;
mnc = ((string[0] - '0') << 8)
| ((string[1] - '0') << 4)
| 0x00f;
} else
if (strlen(string) == 3) {
if (string[0] < '0' || string [0] > '9'
|| string[1] < '0' || string [1] > '9'
|| string[2] < '0' || string [2] > '9')
return GSM_INPUT_INVALID;
mnc = ((string[0] - '0') << 8)
| ((string[1] - '0') << 4)
| ((string[2] - '0'));
}
return mnc;
return (mnc_hex == sim_mnc);
}
const char *gsm_get_mcc(uint16_t mcc)
{
int i;
uint16_t mcc_hex = gsm_mcc_to_hex(mcc);
for (i = 0; gsm_networks[i].name; i++)
if (gsm_networks[i].mnc < 0 && gsm_networks[i].mcc == mcc)
if (gsm_networks[i].mnc_hex < 0 && gsm_networks[i].mcc_hex == mcc_hex)
return gsm_networks[i].name;
return gsm_print_mcc(mcc);
return osmo_mcc_name(mcc);
}
const char *gsm_get_mnc(uint16_t mcc, uint16_t mnc)
const char *gsm_get_mnc(const struct osmo_plmn_id *plmn)
{
int i;
uint16_t mcc_hex = gsm_mcc_to_hex(plmn->mcc);
uint16_t mnc_hex = gsm_mnc_to_hex(plmn->mnc, plmn->mnc_3_digits);
for (i = 0; gsm_networks[i].name; i++)
if (gsm_networks[i].mcc == mcc && gsm_networks[i].mnc == mnc)
if (gsm_networks[i].mcc_hex == mcc_hex &&
gsm_networks[i].mnc_hex == mnc_hex)
return gsm_networks[i].name;
return gsm_print_mnc(mnc);
return osmo_mnc_name(plmn->mnc, plmn->mnc_3_digits);
}
/* get MCC from IMSI */
const char *gsm_imsi_mcc(char *imsi)
{
int i, found = 0;
uint16_t mcc;
uint16_t mcc_hex;
mcc = ((imsi[0] - '0') << 8)
mcc_hex = ((imsi[0] - '0') << 8)
| ((imsi[1] - '0') << 4)
| ((imsi[2] - '0'));
for (i = 0; gsm_networks[i].name; i++) {
if (gsm_networks[i].mcc == mcc) {
if (gsm_networks[i].mcc_hex == mcc_hex) {
found = 1;
break;
}
@ -1961,15 +1927,15 @@ const char *gsm_imsi_mnc(char *imsi)
+ imsi[5] - '0';
for (i = 0; gsm_networks[i].name; i++) {
if (gsm_networks[i].mcc != mcc)
if (gsm_networks[i].mcc_hex != mcc)
continue;
if ((gsm_networks[i].mnc & 0x00f) == 0x00f) {
if (mnc2 == gsm_networks[i].mnc) {
if ((gsm_networks[i].mnc_hex & 0x00f) == 0x00f) {
if (mnc2 == gsm_networks[i].mnc_hex) {
found++;
position = i;
}
} else {
if (mnc3 == gsm_networks[i].mnc) {
if (mnc3 == gsm_networks[i].mnc_hex) {
found++;
position = i;
}

View File

@ -68,7 +68,9 @@ int gsm_settings_init(struct osmocom_ms *ms)
/* test SIM */
OSMO_STRLCPY_ARRAY(set->test_sim.imsi, "001010000000000");
set->test_sim.rplmn_mcc = set->test_sim.rplmn_mnc = 1;
set->test_sim.rplmn.mcc = 1;
set->test_sim.rplmn.mnc = 1;
set->test_sim.rplmn.mnc_3_digits = false;
set->test_sim.lac = 0x0000;
set->test_sim.tmsi = GSM_RESERVED_TMSI;

View File

@ -106,7 +106,7 @@ int gsm_subscr_init(struct osmocom_ms *ms)
/* set TMSI / LAC invalid */
subscr->tmsi = GSM_RESERVED_TMSI;
subscr->ptmsi = GSM_RESERVED_TMSI;
subscr->lac = 0x0000;
subscr->lai.lac = 0x0000;
/* set key invalid */
subscr->key_seq = 7;
@ -328,22 +328,20 @@ static int subscr_write_plmn_na(struct osmocom_ms *ms)
}
}
/* del forbidden PLMN. if MCC==0, flush complete list */
int gsm_subscr_del_forbidden_plmn(struct gsm_subscriber *subscr, uint16_t mcc,
uint16_t mnc)
/* del forbidden PLMN. if PLMN is NULL, flush complete list */
int gsm_subscr_del_forbidden_plmn(struct gsm_subscriber *subscr, const struct osmo_plmn_id *plmn)
{
struct gsm_sub_plmn_na *na, *na2;
int deleted = 0;
llist_for_each_entry_safe(na, na2, &subscr->plmn_na, entry) {
if (!mcc || (na->mcc == mcc && na->mnc == mnc)) {
LOGP(DPLMN, LOGL_INFO, "Delete from list of forbidden "
"PLMNs (mcc=%s, mnc=%s)\n",
gsm_print_mcc(mcc), gsm_print_mnc(mnc));
if (!plmn || (osmo_plmn_cmp(&na->plmn, plmn) == 0)) {
LOGP(DPLMN, LOGL_INFO, "Delete from list of forbidden PLMNs (mcc-mnc=%s)\n",
osmo_plmn_name(&na->plmn));
llist_del(&na->entry);
talloc_free(na);
deleted = 1;
if (mcc)
if (plmn)
break;
}
}
@ -357,26 +355,24 @@ int gsm_subscr_del_forbidden_plmn(struct gsm_subscriber *subscr, uint16_t mcc,
}
/* add forbidden PLMN */
int gsm_subscr_add_forbidden_plmn(struct gsm_subscriber *subscr, uint16_t mcc,
uint16_t mnc, uint8_t cause)
int gsm_subscr_add_forbidden_plmn(struct gsm_subscriber *subscr, const struct osmo_plmn_id *plmn, uint8_t cause)
{
struct gsm_sub_plmn_na *na;
/* if already in the list, remove and add to tail */
gsm_subscr_del_forbidden_plmn(subscr, mcc, mnc);
gsm_subscr_del_forbidden_plmn(subscr, plmn);
LOGP(DPLMN, LOGL_INFO, "Add to list of forbidden PLMNs "
"(mcc=%s, mnc=%s)\n", gsm_print_mcc(mcc), gsm_print_mnc(mnc));
"(mcc-mnc=%s)\n", osmo_plmn_name(plmn));
na = talloc_zero(subscr->ms, struct gsm_sub_plmn_na);
if (!na)
return -ENOMEM;
na->mcc = mcc;
na->mnc = mnc;
memcpy(&na->plmn, plmn, sizeof(struct osmo_plmn_id));
na->cause = cause ? : -1; /* cause 0 is not allowed */
llist_add_tail(&na->entry, &subscr->plmn_na);
/* don't add Home PLMN to SIM */
if (subscr->sim_valid && gsm_match_mnc(mcc, mnc, subscr->imsi))
if (subscr->sim_valid && gsm_match_mnc(plmn->mcc, plmn->mnc, plmn->mnc_3_digits, subscr->imsi))
return -EINVAL;
/* update plmn not allowed list on SIM */
@ -386,13 +382,12 @@ int gsm_subscr_add_forbidden_plmn(struct gsm_subscriber *subscr, uint16_t mcc,
}
/* search forbidden PLMN */
int gsm_subscr_is_forbidden_plmn(struct gsm_subscriber *subscr, uint16_t mcc,
uint16_t mnc)
int gsm_subscr_is_forbidden_plmn(struct gsm_subscriber *subscr, const struct osmo_plmn_id *plmn)
{
struct gsm_sub_plmn_na *na;
llist_for_each_entry(na, &subscr->plmn_na, entry) {
if (na->mcc == mcc && na->mnc == mnc)
if (osmo_plmn_cmp(&na->plmn, plmn) == 0)
return 1;
}
@ -416,9 +411,10 @@ int gsm_subscr_dump_forbidden_plmn(struct osmocom_ms *ms,
print(priv, "MCC |MNC |cause\n");
print(priv, "-------+-------+-------\n");
llist_for_each_entry(temp, &subscr->plmn_na, entry)
print(priv, "%s |%s%s |#%d\n",
gsm_print_mcc(temp->mcc), gsm_print_mnc(temp->mnc),
((temp->mnc & 0x00f) == 0x00f) ? " ":"", temp->cause);
print(priv, "%s |%-3s |#%d\n",
osmo_mcc_name(temp->plmn.mcc),
osmo_mnc_name(temp->plmn.mnc, temp->plmn.mnc_3_digits),
temp->cause);
return 0;
}
@ -454,13 +450,12 @@ void gsm_subscr_dump(struct gsm_subscriber *subscr,
print(priv, " TMSI 0x%08x", subscr->tmsi);
if (subscr->ptmsi != GSM_RESERVED_TMSI)
print(priv, " P-TMSI 0x%08x", subscr->ptmsi);
if (subscr->lac > 0x0000 && subscr->lac < 0xfffe) {
if (subscr->lai.lac > 0x0000 && subscr->lai.lac < 0xfffe) {
print(priv, "\n");
print(priv, " LAI: MCC %s MNC %s LAC 0x%04x "
"(%s, %s)\n", gsm_print_mcc(subscr->mcc),
gsm_print_mnc(subscr->mnc), subscr->lac,
gsm_get_mcc(subscr->mcc),
gsm_get_mnc(subscr->mcc, subscr->mnc));
print(priv, " LAI: %s (%s, %s)\n",
osmo_lai_name(&subscr->lai),
gsm_get_mcc(subscr->lai.plmn.mcc),
gsm_get_mnc(&subscr->lai.plmn));
} else
print(priv, " LAI: invalid\n");
if (subscr->key_seq != 7) {
@ -470,11 +465,10 @@ void gsm_subscr_dump(struct gsm_subscriber *subscr,
print(priv, "\n");
}
if (subscr->plmn_valid)
print(priv, " Registered PLMN: MCC %s MNC %s (%s, %s)\n",
gsm_print_mcc(subscr->plmn_mcc),
gsm_print_mnc(subscr->plmn_mnc),
gsm_get_mcc(subscr->plmn_mcc),
gsm_get_mnc(subscr->plmn_mcc, subscr->plmn_mnc));
print(priv, " Registered PLMN: MCC-MNC %s (%s, %s)\n",
osmo_plmn_name(&subscr->plmn),
gsm_get_mcc(subscr->plmn.mcc),
gsm_get_mnc(&subscr->plmn));
print(priv, " Access barred cells: %s\n",
(subscr->acc_barr) ? "yes" : "no");
print(priv, " Access classes:");
@ -488,22 +482,21 @@ void gsm_subscr_dump(struct gsm_subscriber *subscr,
print(priv, " -------+-------\n");
llist_for_each_entry(plmn_list, &subscr->plmn_list, entry)
print(priv, " %s |%s (%s, %s)\n",
gsm_print_mcc(plmn_list->mcc),
gsm_print_mnc(plmn_list->mnc),
gsm_get_mcc(plmn_list->mcc),
gsm_get_mnc(plmn_list->mcc, plmn_list->mnc));
osmo_mcc_name(plmn_list->plmn.mcc),
osmo_mnc_name(plmn_list->plmn.mnc, plmn_list->plmn.mnc_3_digits),
gsm_get_mcc(plmn_list->plmn.mcc),
gsm_get_mnc(&plmn_list->plmn));
}
if (!llist_empty(&subscr->plmn_na)) {
print(priv, " List of forbidden PLMNs:\n");
print(priv, " MCC |MNC |cause\n");
print(priv, " -------+-------+-------\n");
llist_for_each_entry(plmn_na, &subscr->plmn_na, entry)
print(priv, " %s |%s%s |#%d "
"(%s, %s)\n", gsm_print_mcc(plmn_na->mcc),
gsm_print_mnc(plmn_na->mnc),
((plmn_na->mnc & 0x00f) == 0x00f) ? " ":"",
plmn_na->cause, gsm_get_mcc(plmn_na->mcc),
gsm_get_mnc(plmn_na->mcc, plmn_na->mnc));
print(priv, " %s |%-3s |#%d (%s, %s)\n",
osmo_mcc_name(plmn_na->plmn.mcc),
osmo_mnc_name(plmn_na->plmn.mnc, plmn_na->plmn.mnc_3_digits),
plmn_na->cause, gsm_get_mcc(plmn_na->plmn.mcc),
gsm_get_mnc(&plmn_na->plmn));
}
}
@ -528,11 +521,9 @@ int gsm_subscr_insert_testcard(struct osmocom_ms *ms)
subscr->acc_barr = set->test_sim.barr; /* we may access barred cell */
subscr->acc_class = 0xffff; /* we have any access class */
subscr->plmn_valid = set->test_sim.rplmn_valid;
subscr->plmn_mcc = set->test_sim.rplmn_mcc;
subscr->plmn_mnc = set->test_sim.rplmn_mnc;
subscr->mcc = set->test_sim.rplmn_mcc;
subscr->mnc = set->test_sim.rplmn_mnc;
subscr->lac = set->test_sim.lac;
memcpy(&subscr->plmn, &set->test_sim.rplmn, sizeof(struct osmo_plmn_id));
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->ptmsi = GSM_RESERVED_TMSI;
subscr->always_search_hplmn = set->test_sim.always;
@ -549,10 +540,10 @@ int gsm_subscr_insert_testcard(struct osmocom_ms *ms)
gsm_imsi_mnc(subscr->imsi));
if (subscr->plmn_valid)
LOGP(DMM, LOGL_INFO, "-> Test card registered to %s %s 0x%04x"
"(%s, %s)\n", gsm_print_mcc(subscr->mcc),
gsm_print_mnc(subscr->mnc), subscr->lac, gsm_get_mcc(subscr->mcc),
gsm_get_mnc(subscr->mcc, subscr->mnc));
LOGP(DMM, LOGL_INFO, "-> Test card registered to %s"
"(%s, %s)\n", osmo_lai_name(&subscr->lai),
gsm_get_mcc(subscr->lai.plmn.mcc),
gsm_get_mnc(&subscr->lai.plmn));
else
LOGP(DMM, LOGL_INFO, "-> Test card not registered\n");
if (subscr->imsi_attached)
@ -654,8 +645,7 @@ static int subscr_sim_loci(struct osmocom_ms *ms, uint8_t *data,
subscr->tmsi = ntohl(loci->tmsi);
/* LAI */
gsm48_decode_lai_hex(&loci->lai, &subscr->mcc, &subscr->mnc,
&subscr->lac);
gsm48_decode_lai2(&loci->lai, &subscr->lai);
/* location update status */
switch (loci->lupd_status & 0x07) {
@ -670,9 +660,8 @@ static int subscr_sim_loci(struct osmocom_ms *ms, uint8_t *data,
subscr->ustate = GSM_SIM_U2_NOT_UPDATED;
}
LOGP(DMM, LOGL_INFO, "received LOCI from SIM (mcc=%s mnc=%s lac=0x%04x "
"U%d)\n", gsm_print_mcc(subscr->mcc),
gsm_print_mnc(subscr->mnc), subscr->lac, subscr->ustate);
LOGP(DMM, LOGL_INFO, "received LOCI from SIM (lai=%s U%d)\n",
osmo_lai_name(&subscr->lai), subscr->ustate);
return 0;
}
@ -760,8 +749,6 @@ static int subscr_sim_plmnsel(struct osmocom_ms *ms, uint8_t *data,
struct gsm_subscriber *subscr = &ms->subscr;
struct gsm_sub_plmn_list *plmn;
struct llist_head *lh, *lh2;
uint8_t lai[5];
uint16_t dummy_lac;
/* flush list */
llist_for_each_safe(lh, lh2, &subscr->plmn_list) {
@ -778,16 +765,11 @@ static int subscr_sim_plmnsel(struct osmocom_ms *ms, uint8_t *data,
plmn = talloc_zero(ms, struct gsm_sub_plmn_list);
if (!plmn)
return -ENOMEM;
lai[0] = data[0];
lai[1] = data[1];
lai[2] = data[2];
gsm48_decode_lai_hex((struct gsm48_loc_area_id *)lai,
&plmn->mcc, &plmn->mnc, &dummy_lac);
osmo_plmn_to_bcd(&data[0], &plmn->plmn);
llist_add_tail(&plmn->entry, &subscr->plmn_list);
LOGP(DMM, LOGL_INFO, "received PLMN selector (mcc=%s mnc=%s) "
"from SIM\n",
gsm_print_mcc(plmn->mcc), gsm_print_mnc(plmn->mnc));
LOGP(DMM, LOGL_INFO, "received PLMN selector (mcc-mnc=%s) from SIM\n",
osmo_plmn_name(&plmn->plmn));
data += 3;
length -= 3;
@ -860,8 +842,6 @@ static int subscr_sim_fplmn(struct osmocom_ms *ms, uint8_t *data,
struct gsm_subscriber *subscr = &ms->subscr;
struct gsm_sub_plmn_na *na;
struct llist_head *lh, *lh2;
uint8_t lai[5];
uint16_t dummy_lac;
#ifdef TEST_EMPTY_FPLMN
return 0;
@ -882,13 +862,9 @@ static int subscr_sim_fplmn(struct osmocom_ms *ms, uint8_t *data,
na = talloc_zero(ms, struct gsm_sub_plmn_na);
if (!na)
return -ENOMEM;
lai[0] = data[0];
lai[1] = data[1];
lai[2] = data[2];
gsm48_decode_lai_hex((struct gsm48_loc_area_id *)lai, &na->mcc,
&na->mnc, &dummy_lac);
LOGP(DMM, LOGL_INFO, "received Forbidden PLMN %s %s from SIM\n",
gsm_print_mcc(na->mcc), gsm_print_mnc(na->mnc));
osmo_plmn_to_bcd(&data[0], &na->plmn);
LOGP(DMM, LOGL_INFO, "received Forbidden PLMN %s from SIM\n",
osmo_plmn_name(&na->plmn));
na->cause = -1; /* must have a value, but SIM stores no cause */
llist_add_tail(&na->entry, &subscr->plmn_na);
@ -936,16 +912,13 @@ static int subscr_sim_request(struct osmocom_ms *ms)
gsm_imsi_mcc(subscr->imsi), gsm_imsi_mnc(subscr->imsi));
/* if LAI is valid, set RPLMN */
if (subscr->lac > 0x0000 && subscr->lac < 0xfffe) {
if (subscr->lai.lac > 0x0000 && subscr->lai.lac < 0xfffe) {
subscr->plmn_valid = 1;
subscr->plmn_mcc = subscr->mcc;
subscr->plmn_mnc = subscr->mnc;
LOGP(DMM, LOGL_INFO, "-> SIM card registered to %s %s "
"(%s, %s)\n", gsm_print_mcc(subscr->plmn_mcc),
gsm_print_mnc(subscr->plmn_mnc),
gsm_get_mcc(subscr->plmn_mcc),
gsm_get_mnc(subscr->plmn_mcc,
subscr->plmn_mnc));
memcpy(&subscr->plmn, &subscr->lai.plmn, sizeof(struct osmo_plmn_id));
LOGP(DMM, LOGL_INFO, "-> SIM card registered to %s (%s, %s)\n",
osmo_plmn_name(&subscr->plmn),
gsm_get_mcc(subscr->plmn.mcc),
gsm_get_mnc(&subscr->plmn));
} else
LOGP(DMM, LOGL_INFO, "-> SIM card not registered\n");
@ -1138,7 +1111,6 @@ static int subscr_write_plmn_na_simcard(struct osmocom_ms *ms)
struct gsm_sub_plmn_na *na, *nas[4] = { NULL, NULL, NULL, NULL };
int count = 0, i;
uint8_t *data;
uint8_t lai[5];
#ifdef TEST_EMPTY_FPLMN
return 0;
@ -1170,11 +1142,8 @@ static int subscr_write_plmn_na_simcard(struct osmocom_ms *ms)
nsh->file = 0x6f7b;
for (i = 0; i < 4; i++) {
if (nas[i]) {
gsm48_encode_lai_hex((struct gsm48_loc_area_id *)lai,
nas[i]->mcc, nas[i]->mnc, 0);
*data++ = lai[0];
*data++ = lai[1];
*data++ = lai[2];
osmo_plmn_to_bcd(data, &nas[i]->plmn);
data += 3;
} else {
*data++ = 0xff;
*data++ = 0xff;
@ -1209,7 +1178,7 @@ static int gsm_subscr_write_loci_simcard(struct osmocom_ms *ms)
loci->tmsi = htonl(subscr->tmsi);
/* LAI */
gsm48_encode_lai_hex(&loci->lai, subscr->mcc, subscr->mnc, subscr->lac);
gsm48_generate_lai2(&loci->lai, &subscr->lai);
/* TMSI time */
loci->tmsi_time = 0xff;

View File

@ -22,6 +22,7 @@
#include <osmocom/core/utils.h>
#include <osmocom/core/bitvec.h>
#include <osmocom/gsm/gsm48.h>
#include <osmocom/gprs/rlcmac/csn1_defs.h>
@ -203,12 +204,10 @@ int gsm48_sysinfo_dump(const struct gsm48_sysinfo *s, uint16_t arfcn,
/* serving cell */
print(priv, "Serving Cell:\n");
print(priv, " BSIC = %d,%d MCC = %s MNC = %s LAC = 0x%04x Cell ID "
"= 0x%04x\n", s->bsic >> 3, s->bsic & 0x7,
gsm_print_mcc(s->mcc), gsm_print_mnc(s->mnc), s->lac,
s->cell_id);
print(priv, " Country = %s Network Name = %s\n", gsm_get_mcc(s->mcc),
gsm_get_mnc(s->mcc, s->mnc));
print(priv, " BSIC = %d,%d LAI = %s Cell ID = 0x%04x\n",
s->bsic >> 3, s->bsic & 0x7, osmo_lai_name(&s->lai), s->cell_id);
print(priv, " Country = %s Network Name = %s\n",
gsm_get_mcc(s->lai.plmn.mcc), gsm_get_mnc(&s->lai.plmn));
print(priv, " MAX_RETRANS = %d TX_INTEGER = %d re-establish = %s\n",
s->max_retrans, s->tx_integer,
(s->reest_denied) ? "denied" : "allowed");
@ -685,7 +684,7 @@ int gsm48_decode_sysinfo3(struct gsm48_sysinfo *s,
/* Cell Identity */
s->cell_id = ntohs(si->cell_identity);
/* LAI */
gsm48_decode_lai_hex(&si->lai, &s->mcc, &s->mnc, &s->lac);
gsm48_decode_lai2(&si->lai, &s->lai);
/* Control Channel Description */
gsm48_decode_ccd(s, &si->control_channel_desc);
/* Cell Options (BCCH) */
@ -699,8 +698,7 @@ int gsm48_decode_sysinfo3(struct gsm48_sysinfo *s,
gsm48_decode_si3_rest(s, si->rest_octets, payload_len);
LOGP(DRR, LOGL_INFO,
"New SYSTEM INFORMATION 3 (mcc %s mnc %s lac 0x%04x)\n",
gsm_print_mcc(s->mcc), gsm_print_mnc(s->mnc), s->lac);
"New SYSTEM INFORMATION 3 (lai=%s)\n", osmo_lai_name(&s->lai));
s->si3 = 1;
@ -718,7 +716,7 @@ int gsm48_decode_sysinfo4(struct gsm48_sysinfo *s,
memcpy(s->si4_msg, si, OSMO_MIN(len, sizeof(s->si4_msg)));
/* LAI */
gsm48_decode_lai_hex(&si->lai, &s->mcc, &s->mnc, &s->lac);
gsm48_decode_lai2(&si->lai, &s->lai);
/* Cell Selection Parameters */
gsm48_decode_cell_sel_param(s, &si->cell_sel_par);
/* RACH Control Parameter */
@ -828,7 +826,7 @@ int gsm48_decode_sysinfo6(struct gsm48_sysinfo *s,
"read.\n");
s->cell_id = ntohs(si->cell_identity);
/* LAI */
gsm48_decode_lai_hex(&si->lai, &s->mcc, &s->mnc, &s->lac);
gsm48_decode_lai2(&si->lai, &s->lai);
/* Cell Options (SACCH) */
gsm48_decode_cellopt_sacch(s, &si->cell_options);
/* NCC Permitted */
@ -923,29 +921,3 @@ int gsm48_decode_sysinfo13(struct gsm48_sysinfo *s,
return 0;
}
int gsm48_encode_lai_hex(struct gsm48_loc_area_id *lai,
uint16_t mcc, uint16_t mnc, uint16_t lac)
{
lai->digits[0] = (mcc >> 8) | (mcc & 0xf0);
lai->digits[1] = (mcc & 0x0f) | (mnc << 4);
lai->digits[2] = (mnc >> 8) | (mnc & 0xf0);
lai->lac = htons(lac);
return 0;
}
int gsm48_decode_lai_hex(const struct gsm48_loc_area_id *lai,
uint16_t *mcc, uint16_t *mnc, uint16_t *lac)
{
*mcc = ((lai->digits[0] & 0x0f) << 8)
| (lai->digits[0] & 0xf0)
| (lai->digits[1] & 0x0f);
*mnc = ((lai->digits[2] & 0x0f) << 8)
| (lai->digits[2] & 0xf0)
| ((lai->digits[1] & 0xf0) >> 4);
*lac = ntohs(lai->lac);
return 0;
}

View File

@ -503,18 +503,16 @@ static int _sim_test_cmd(struct vty *vty, int argc, const char *argv[],
return CMD_WARNING;
}
if (argc >= 3) {
uint16_t mcc = gsm_input_mcc((char *)argv[1]);
uint16_t mnc = gsm_input_mnc((char *)argv[2]);
if (mcc == GSM_INPUT_INVALID) {
struct osmo_plmn_id plmn;
if (osmo_mcc_from_str(argv[1], &plmn.mcc) < 0) {
vty_out(vty, "Given MCC invalid%s", VTY_NEWLINE);
return CMD_WARNING;
}
if (mnc == GSM_INPUT_INVALID) {
if (osmo_mnc_from_str(argv[2], &plmn.mnc, &plmn.mnc_3_digits) < 0) {
vty_out(vty, "Given MNC invalid%s", VTY_NEWLINE);
return CMD_WARNING;
}
set->test_sim.rplmn_mcc = mcc;
set->test_sim.rplmn_mnc = mnc;
memcpy(&set->test_sim.rplmn, &plmn, sizeof(plmn));
set->test_sim.rplmn_valid = 1;
} else {
set->test_sim.rplmn_valid = 0;
@ -743,26 +741,26 @@ DEFUN(sim_lai, sim_lai_cmd, "sim lai MS_NAME MCC MNC LAC",
" (use 0000 to remove LAI)")
{
struct osmocom_ms *ms;
uint16_t mcc = gsm_input_mcc((char *)argv[1]),
mnc = gsm_input_mnc((char *)argv[2]),
lac = strtoul(argv[3], NULL, 16);
struct osmo_plmn_id plmn;
uint16_t lac;
ms = l23_vty_get_ms(argv[0], vty);
if (!ms)
return CMD_WARNING;
if (mcc == GSM_INPUT_INVALID) {
if (osmo_mcc_from_str(argv[1], &plmn.mcc) < 0) {
vty_out(vty, "Given MCC invalid%s", VTY_NEWLINE);
return CMD_WARNING;
}
if (mnc == GSM_INPUT_INVALID) {
if (osmo_mnc_from_str(argv[2], &plmn.mnc, &plmn.mnc_3_digits) < 0) {
vty_out(vty, "Given MNC invalid%s", VTY_NEWLINE);
return CMD_WARNING;
}
ms->subscr.mcc = mcc;
ms->subscr.mnc = mnc;
ms->subscr.lac = lac;
lac = strtoul(argv[3], NULL, 0);
memcpy(&ms->subscr.lai.plmn, &plmn, sizeof(plmn));
ms->subscr.lai.lac = lac;
ms->subscr.tmsi = GSM_RESERVED_TMSI;
gsm_subscr_write_loci(ms);
@ -1044,7 +1042,9 @@ DEFUN(cfg_test_no_rplmn, cfg_test_no_rplmn_cmd, "no rplmn",
struct gsm_settings *set = &ms->settings;
set->test_sim.rplmn_valid = 0;
set->test_sim.rplmn_mcc = set->test_sim.rplmn_mnc = 1;
set->test_sim.rplmn.mcc = 1;
set->test_sim.rplmn.mnc = 1;
set->test_sim.rplmn.mnc_3_digits = false;
set->test_sim.lac = 0x0000;
set->test_sim.tmsi = GSM_RESERVED_TMSI;
@ -1058,20 +1058,18 @@ static int _test_rplmn_cmd(struct vty *vty, int argc, const char *argv[],
{
struct osmocom_ms *ms = vty->index;
struct gsm_settings *set = &ms->settings;
uint16_t mcc = gsm_input_mcc((char *)argv[0]),
mnc = gsm_input_mnc((char *)argv[1]);
struct osmo_plmn_id plmn;
if (mcc == GSM_INPUT_INVALID) {
if (osmo_mcc_from_str(argv[0], &plmn.mcc) < 0) {
vty_out(vty, "Given MCC invalid%s", VTY_NEWLINE);
return CMD_WARNING;
}
if (mnc == GSM_INPUT_INVALID) {
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.rplmn_valid = 1;
set->test_sim.rplmn_mcc = mcc;
set->test_sim.rplmn_mnc = mnc;
memcpy(&set->test_sim.rplmn, &plmn, sizeof(plmn));
if (argc >= 3)
set->test_sim.lac = strtoul(argv[2], NULL, 16);
@ -1205,8 +1203,8 @@ static int l23_vty_config_write_testsim_node(struct vty *vty, const struct osmoc
(set->test_sim.barr) ? "" : "no ", VTY_NEWLINE);
if (set->test_sim.rplmn_valid) {
vty_out(vty, "%s rplmn %s %s", prefix,
gsm_print_mcc(set->test_sim.rplmn_mcc),
gsm_print_mnc(set->test_sim.rplmn_mnc));
osmo_mcc_name(set->test_sim.rplmn.mcc),
osmo_mnc_name(set->test_sim.rplmn.mnc, set->test_sim.rplmn.mnc_3_digits));
if (set->test_sim.lac > 0x0000 && set->test_sim.lac < 0xfffe) {
vty_out(vty, " 0x%04x", set->test_sim.lac);
if (set->test_sim.tmsi != GSM_RESERVED_TMSI) {

View File

@ -98,7 +98,7 @@ static struct log_si {
uint16_t flags;
uint8_t bsic;
int8_t rxlev_dbm;
uint16_t mcc, mnc, lac, cellid;
struct osmo_cell_global_id cgi;
uint8_t ta;
double latitude, longitude;
} log_si;
@ -187,9 +187,10 @@ static void log_sysinfo(void)
if (log_si.ta != 0xff)
sprintf(ta_str, " TA=%d", log_si.ta);
LOGP(DSUM, LOGL_INFO, "Cell: ARFCN=%d MCC=%s MNC=%s (%s, %s)%s\n",
arfcn, gsm_print_mcc(s->mcc), gsm_print_mnc(s->mnc),
gsm_get_mcc(s->mcc), gsm_get_mnc(s->mcc, s->mnc), ta_str);
LOGP(DSUM, LOGL_INFO, "Cell: ARFCN=%d MCC-MNC=%s (%s, %s)%s\n",
arfcn, osmo_plmn_name(&s->lai.plmn),
gsm_get_mcc(s->lai.plmn.mcc),
gsm_get_mnc(&s->lai.plmn), ta_str);
LOGFILE("[sysinfo]\n");
LOGFILE("arfcn %d\n", s->arfcn);

View File

@ -121,13 +121,13 @@ static void add_sysinfo(void)
23);
printf("--------------------------------------------------------------------------\n");
gsm48_sysinfo_dump(&s, sysinfo.arfcn, print_si, stdout, NULL);
mcc = get_node_mcc(s.mcc);
mcc = get_node_mcc(s.lai.plmn.mcc);
if (!mcc)
nomem();
mnc = get_node_mnc(mcc, s.mnc);
mnc = get_node_mnc(mcc, s.lai.plmn.mnc, s.lai.plmn.mnc_3_digits);
if (!mnc)
nomem();
lac = get_node_lac(mnc, s.lac);
lac = get_node_lac(mnc, s.lai.lac);
if (!lac)
nomem();
cell = get_node_cell(lac, s.cell_id);
@ -296,8 +296,7 @@ void kml_footer(FILE *outfp)
}
void kml_meas(FILE *outfp, struct node_meas *meas, int n, uint16_t mcc,
uint16_t mnc, uint16_t lac, uint16_t cellid)
static void kml_meas(FILE *outfp, struct node_meas *meas, int n, const struct osmo_cell_global_id *cgi)
{
struct tm *tm = localtime(&meas->gmt);
@ -305,8 +304,11 @@ void kml_meas(FILE *outfp, struct node_meas *meas, int n, uint16_t mcc,
fprintf(outfp, "\t\t\t\t\t\t<name>%d: %d</name>\n", n, meas->rxlev);
fprintf(outfp, "\t\t\t\t\t\t<description>\n");
fprintf(outfp, "MCC=%s MNC=%s\nLAC=%04x CELL-ID=%04x\n(%s %s)\n",
gsm_print_mcc(mcc), gsm_print_mnc(mnc), lac, cellid,
gsm_get_mcc(mcc), gsm_get_mnc(mcc, mnc));
osmo_mcc_name(cgi->lai.plmn.mcc),
osmo_mnc_name(cgi->lai.plmn.mnc, cgi->lai.plmn.mnc_3_digits),
cgi->lai.lac, cgi->cell_identity,
gsm_get_mcc(cgi->lai.plmn.mcc),
gsm_get_mnc(&cgi->lai.plmn));
fprintf(outfp, "\n%s", asctime(tm));
fprintf(outfp, "RX-LEV %d dBm\n", meas->rxlev);
if (meas->ta_valid)
@ -423,11 +425,11 @@ void kml_cell(FILE *outfp, struct node_cell *cell)
return;
fprintf(outfp, "\t\t\t\t\t<Placemark>\n");
fprintf(outfp, "\t\t\t\t\t\t<name>MCC=%s MNC=%s\nLAC=%04x "
"CELL-ID=%04x\n(%s %s)</name>\n", gsm_print_mcc(cell->s.mcc),
gsm_print_mnc(cell->s.mnc), cell->s.lac, cell->s.cell_id,
gsm_get_mcc(cell->s.mcc),
gsm_get_mnc(cell->s.mcc, cell->s.mnc));
fprintf(outfp, "\t\t\t\t\t\t<name>LAI=%s "
"CELL-ID=%04x\n(%s %s)</name>\n",
osmo_lai_name(&cell->s.lai), cell->s.cell_id,
gsm_get_mcc(cell->s.lai.plmn.mcc),
gsm_get_mnc(&cell->s.lai.plmn));
fprintf(outfp, "\t\t\t\t\t\t<description>\n");
gsm48_sysinfo_dump(&cell->s, cell->sysinfo.arfcn, print_si, outfp,
NULL);
@ -576,15 +578,20 @@ usage:
/* folder open */
fprintf(outfp, "\t<Folder>\n");
fprintf(outfp, "\t\t<name>MCC %s (%s)</name>\n",
gsm_print_mcc(mcc->mcc), gsm_get_mcc(mcc->mcc));
osmo_mcc_name(mcc->mcc), gsm_get_mcc(mcc->mcc));
fprintf(outfp, "\t\t<open>0</open>\n");
mnc = mcc->mnc;
while (mnc) {
struct osmo_plmn_id plmn = {
.mcc = mcc->mcc,
.mnc = mnc->mnc,
.mnc_3_digits = mnc->mnc_3_digits,
};
printf(" MNC: %02x\n", mnc->mnc);
/* folder open */
fprintf(outfp, "\t\t<Folder>\n");
fprintf(outfp, "\t\t\t<name>MNC %s (%s)</name>\n",
gsm_print_mnc(mnc->mnc), gsm_get_mnc(mcc->mcc, mnc->mnc));
osmo_mnc_name(mnc->mnc, mnc->mnc_3_digits), gsm_get_mnc(&plmn));
fprintf(outfp, "\t\t\t<open>0</open>\n");
lac = mnc->lac;
while (lac) {
@ -604,9 +611,20 @@ usage:
while (meas) {
if (meas->ta_valid)
printf(" TA: %d\n", meas->ta);
if (meas->gps_valid)
kml_meas(outfp, meas, ++n, mcc->mcc, mnc->mnc,
lac->lac, cell->cellid);
if (meas->gps_valid) {
struct osmo_cell_global_id cgi = {
.lai = {
.plmn = {
.mcc = mcc->mcc,
.mnc = mnc->mnc,
.mnc_3_digits = mnc->mnc_3_digits,
},
.lac = lac->lac,
},
.cell_identity = cell->cellid,
};
kml_meas(outfp, meas, ++n, &cgi);
}
meas = meas->next;
}
kml_cell(outfp, cell);

View File

@ -55,18 +55,22 @@ struct node_mcc *get_node_mcc(uint16_t mcc)
return node_mcc;
}
struct node_mnc *get_node_mnc(struct node_mcc *mcc, uint16_t mnc)
struct node_mnc *get_node_mnc(struct node_mcc *mcc, uint16_t mnc, bool mnc_3_digits)
{
struct node_mnc *node_mnc;
struct node_mnc **node_mnc_p = &mcc->mnc;
while (*node_mnc_p) {
/* found in list */
if ((*node_mnc_p)->mnc == mnc)
if ((*node_mnc_p)->mnc == mnc &&
(*node_mnc_p)->mnc_3_digits == mnc_3_digits)
return *node_mnc_p;
/* insert into list */
if ((*node_mnc_p)->mnc > mnc)
if (((*node_mnc_p)->mnc > mnc) ||
((*node_mnc_p)->mnc == mnc &&
(*node_mnc_p)->mnc_3_digits > mnc_3_digits)) {
break;
}
node_mnc_p = &((*node_mnc_p)->next);
}
@ -75,6 +79,7 @@ struct node_mnc *get_node_mnc(struct node_mcc *mcc, uint16_t mnc)
if (!node_mnc)
return NULL;
node_mnc->mnc = mnc;
node_mnc->mnc_3_digits = mnc_3_digits;
node_mnc->next = *node_mnc_p;
*node_mnc_p = node_mnc;
return node_mnc;

File diff suppressed because it is too large Load Diff

View File

@ -928,8 +928,8 @@ static void new_mm_state(struct gsm48_mmlayer *mm, int state, int substate)
case GSM48_MM_SST_NORMAL_SERVICE:
l23_vty_ms_notify(ms, NULL);
l23_vty_ms_notify(ms, "On Network, normal service: %s, %s\n",
gsm_get_mcc(plmn->mcc),
gsm_get_mnc(plmn->mcc, plmn->mnc));
gsm_get_mcc(plmn->plmn.mcc),
gsm_get_mnc(&plmn->plmn));
break;
case GSM48_MM_SST_LIMITED_SERVICE:
l23_vty_ms_notify(ms, NULL);
@ -953,7 +953,7 @@ static void new_mm_state(struct gsm48_mmlayer *mm, int state, int substate)
case GSM48_MM_SST_ATTEMPT_UPDATE:
l23_vty_ms_notify(ms, NULL);
l23_vty_ms_notify(ms, "Trying to register with network %s, %s...\n",
gsm_get_mcc(plmn->mcc), gsm_get_mnc(plmn->mcc, plmn->mnc));
gsm_get_mcc(plmn->plmn.mcc), gsm_get_mnc(&plmn->plmn));
break;
}
}
@ -1043,7 +1043,7 @@ static int gsm48_mm_set_plmn_search(struct osmocom_ms *ms)
"SIM not updated.\n");
return GSM48_MM_SST_PLMN_SEARCH;
}
if (subscr->lac == 0x0000 || subscr->lac >= 0xfffe) {
if (subscr->lai.lac == 0x0000 || subscr->lai.lac >= 0xfffe) {
LOGP(DMM, LOGL_INFO, "Selecting PLMN SEARCH state, because "
"LAI in SIM not valid.\n");
return GSM48_MM_SST_PLMN_SEARCH;
@ -1057,15 +1057,12 @@ static int gsm48_mm_set_plmn_search(struct osmocom_ms *ms)
}
/* selected cell's LAI not equal to LAI stored on the sim */
if (cs->sel_mcc != subscr->mcc
|| cs->sel_mnc != subscr->mnc
|| cs->sel_lac != subscr->lac) {
if (osmo_lai_cmp(&cs->sel_cgi.lai, &subscr->lai) != 0) {
LOGP(DMM, LOGL_INFO, "Selecting PLMN SEARCH state, because "
"LAI of selected cell (MCC %s MNC %s LAC 0x%04x) "
"!= LAI in SIM (MCC %s MNC %s LAC 0x%04x).\n",
gsm_print_mcc(cs->sel_mcc), gsm_print_mnc(cs->sel_mnc),
cs->sel_lac, gsm_print_mcc(subscr->mcc),
gsm_print_mnc(subscr->mnc), subscr->lac);
"LAI of selected cell (MCC-MNC %s LAC 0x%04x) "
"!= LAI in SIM (MCC-MNC %s LAC 0x%04x).\n",
osmo_plmn_name(&cs->sel_cgi.lai.plmn), cs->sel_cgi.lai.lac,
osmo_plmn_name2(&subscr->lai.plmn), subscr->lai.lac);
return GSM48_MM_SST_PLMN_SEARCH;
}
@ -1121,10 +1118,8 @@ static int gsm48_mm_return_idle(struct osmocom_ms *ms, struct msgb *msg)
/* if we are attached and selected cell equals the registered LAI */
if (subscr->imsi_attached
&& subscr->lac /* valid */
&& cs->sel_mcc == subscr->mcc
&& cs->sel_mnc == subscr->mnc
&& cs->sel_lac == subscr->lac) {
&& subscr->lai.lac /* valid */
&& (osmo_lai_cmp(&cs->sel_cgi.lai, &subscr->lai) == 0)) {
LOGP(DMM, LOGL_INFO, "We are in registered LAI as returning "
"to MM IDLE\n");
/* if SIM not updated (abnormal case as described in 4.4.4.9) */
@ -1141,15 +1136,13 @@ static int gsm48_mm_return_idle(struct osmocom_ms *ms, struct msgb *msg)
if (cs->state == GSM322_C3_CAMPED_NORMALLY) {
LOGP(DMM, LOGL_INFO, "We are camping normally as returning to "
"MM IDLE\n");
if (gsm_subscr_is_forbidden_plmn(subscr, cs->sel_mcc,
cs->sel_mnc)) {
if (gsm_subscr_is_forbidden_plmn(subscr, &cs->sel_cgi.lai.plmn)) {
/* location update not allowed */
LOGP(DMM, LOGL_INFO, "Loc. upd. not allowed PLMN.\n");
new_mm_state(mm, GSM48_MM_ST_MM_IDLE,
GSM48_MM_SST_LIMITED_SERVICE);
} else
if (gsm322_is_forbidden_la(ms, cs->sel_mcc, cs->sel_mnc,
cs->sel_lac)) {
if (gsm322_is_forbidden_la(ms, &cs->sel_cgi.lai)) {
/* location update not allowed */
LOGP(DMM, LOGL_INFO, "Loc. upd. not allowed LA.\n");
new_mm_state(mm, GSM48_MM_ST_MM_IDLE,
@ -1211,10 +1204,8 @@ static int gsm48_mm_cell_selected(struct osmocom_ms *ms, struct msgb *msg)
/* SIM not updated in this LA */
if (subscr->ustate == GSM_SIM_U1_UPDATED
&& subscr->lac /* valid */
&& cs->sel_mcc == subscr->mcc
&& cs->sel_mnc == subscr->mnc
&& cs->sel_lac == subscr->lac
&& subscr->lai.lac /* valid */
&& (osmo_lai_cmp(&cs->sel_cgi.lai, &subscr->lai) == 0)
&& !mm->lupd_periodic) {
if (subscr->imsi_attached) {
struct msgb *nmsg;
@ -1252,9 +1243,8 @@ static int gsm48_mm_cell_selected(struct osmocom_ms *ms, struct msgb *msg)
/* PLMN mode auto and selected cell is forbidden */
if (set->plmn_mode == PLMN_MODE_AUTO
&& (!cs->selected
|| gsm_subscr_is_forbidden_plmn(subscr, cs->sel_mcc, cs->sel_mnc)
|| gsm322_is_forbidden_la(ms, cs->sel_mcc, cs->sel_mnc,
cs->sel_lac))) {
|| gsm_subscr_is_forbidden_plmn(subscr, &cs->sel_cgi.lai.plmn)
|| gsm322_is_forbidden_la(ms, &cs->sel_cgi.lai))) {
struct msgb *nmsg;
LOGP(DMM, LOGL_INFO, "Selected cell is forbidden.\n");
@ -1274,8 +1264,7 @@ static int gsm48_mm_cell_selected(struct osmocom_ms *ms, struct msgb *msg)
* in M3 state the PLMN is not selected for registration. */
if (set->plmn_mode == PLMN_MODE_MANUAL
&& (!cs->selected
|| plmn->mcc != cs->sel_mcc
|| plmn->mnc != cs->sel_mnc
|| (osmo_plmn_cmp(&plmn->plmn, &cs->sel_cgi.lai.plmn) != 0)
|| plmn->state == GSM322_M3_NOT_ON_PLMN)) {
struct msgb *nmsg;
@ -1585,7 +1574,7 @@ static int gsm48_mm_rx_tmsi_realloc_cmd(struct osmocom_ms *ms, struct msgb *msg)
return -EINVAL;
}
/* LAI */
gsm48_decode_lai_hex(lai, &subscr->mcc, &subscr->mnc, &subscr->lac);
gsm48_decode_lai2(lai, &subscr->lai);
/* MI */
mi = gh->data + sizeof(struct gsm48_loc_area_id);
mi_type = mi[1] & GSM_MI_TYPE_MASK;
@ -1699,7 +1688,7 @@ static int gsm48_mm_rx_auth_rej(struct osmocom_ms *ms, struct msgb *msg)
/* TMSI and LAI invalid */
subscr->tmsi = GSM_RESERVED_TMSI;
subscr->lac = 0x0000;
subscr->lai.lac = 0x0000;
/* key is invalid */
subscr->key_seq = 7;
@ -2018,7 +2007,7 @@ static int gsm48_mm_rx_abort(struct osmocom_ms *ms, struct msgb *msg)
/* TMSI and LAI invalid */
subscr->tmsi = GSM_RESERVED_TMSI;
subscr->lac = 0x0000;
subscr->lai.lac = 0x0000;
/* key is invalid */
subscr->key_seq = 7;
@ -2170,20 +2159,18 @@ static int gsm48_mm_loc_upd(struct osmocom_ms *ms, struct msgb *msg)
"forbidden PLMN.\n");
LOGP(DSUM, LOGL_INFO, "Location updating is disabled by "
"configuration\n");
gsm_subscr_add_forbidden_plmn(subscr, cs->sel_mcc,
cs->sel_mnc, GSM48_REJECT_PLMN_NOT_ALLOWED);
gsm_subscr_add_forbidden_plmn(subscr, &cs->sel_cgi.lai.plmn, GSM48_REJECT_PLMN_NOT_ALLOWED);
msg_type = GSM322_EVENT_REG_FAILED;
goto _stop;
}
/* if LAI is forbidden, don't start */
if (gsm_subscr_is_forbidden_plmn(subscr, cs->sel_mcc, cs->sel_mnc)) {
if (gsm_subscr_is_forbidden_plmn(subscr, &cs->sel_cgi.lai.plmn)) {
LOGP(DMM, LOGL_INFO, "Loc. upd. not allowed PLMN.\n");
msg_type = GSM322_EVENT_REG_FAILED;
goto stop;
}
if (gsm322_is_forbidden_la(ms, cs->sel_mcc,
cs->sel_mnc, cs->sel_lac)) {
if (gsm322_is_forbidden_la(ms, &cs->sel_cgi.lai)) {
LOGP(DMM, LOGL_INFO, "Loc. upd. not allowed LA.\n");
msg_type = GSM322_EVENT_REG_FAILED;
goto stop;
@ -2198,13 +2185,9 @@ static int gsm48_mm_loc_upd(struct osmocom_ms *ms, struct msgb *msg)
goto stop;
}
mm->lupd_mcc = cs->sel_mcc;
mm->lupd_mnc = cs->sel_mnc;
mm->lupd_lac = cs->sel_lac;
memcpy(&mm->lupd_lai, &cs->sel_cgi.lai, sizeof(mm->lupd_lai));
LOGP(DSUM, LOGL_INFO, "Perform location update (MCC %s, MNC %s "
"LAC 0x%04x)\n", gsm_print_mcc(mm->lupd_mcc),
gsm_print_mnc(mm->lupd_mnc), mm->lupd_lac);
LOGP(DSUM, LOGL_INFO, "Perform location update (LAI=%s)\n", osmo_lai_name(&mm->lupd_lai));
return gsm48_mm_tx_loc_upd_req(ms);
}
@ -2247,9 +2230,7 @@ static int gsm48_mm_loc_upd_normal(struct osmocom_ms *ms, struct msgb *msg)
/* if location update is not required */
if (subscr->ustate == GSM_SIM_U1_UPDATED
&& cs->selected
&& cs->sel_mcc == subscr->mcc
&& cs->sel_mnc == subscr->mnc
&& cs->sel_lac == subscr->lac
&& (osmo_lai_cmp(&cs->sel_cgi.lai, &subscr->lai) == 0)
&& (subscr->imsi_attached
|| !s->att_allowed)) {
LOGP(DMM, LOGL_INFO, "Loc. upd. not required.\n");
@ -2277,9 +2258,7 @@ static int gsm48_mm_loc_upd_normal(struct osmocom_ms *ms, struct msgb *msg)
/* 4.4.3 is attachment required? */
if (subscr->ustate == GSM_SIM_U1_UPDATED
&& cs->selected
&& cs->sel_mcc == subscr->mcc
&& cs->sel_mnc == subscr->mnc
&& cs->sel_lac == subscr->lac
&& (osmo_lai_cmp(&cs->sel_cgi.lai, &subscr->lai) == 0)
&& !subscr->imsi_attached
&& s->att_allowed) {
/* do location update for IMSI attach */
@ -2357,10 +2336,8 @@ static int gsm48_mm_tx_loc_upd_req(struct osmocom_ms *ms)
*
* NOTE: The TMSI is only valid within a LAI!
*/
gsm48_encode_lai_hex(&nlu->lai, subscr->mcc, subscr->mnc, subscr->lac);
LOGP(DMM, LOGL_INFO, " using LAI (mcc %s mnc %s " "lac 0x%04x)\n",
gsm_print_mcc(subscr->mcc),
gsm_print_mnc(subscr->mnc), subscr->lac);
gsm48_generate_lai2(&nlu->lai, &subscr->lai);
LOGP(DMM, LOGL_INFO, " using LAI=%s\n", osmo_lai_name(&subscr->lai));
/* classmark 1 */
pwr_lev = gsm48_current_pwr_lev(set, cs->sel_arfcn);
gsm48_encode_classmark1(&nlu->classmark1, sup->rev_lev, sup->es_ind,
@ -2427,7 +2404,7 @@ static int gsm48_mm_rx_loc_upd_acc(struct osmocom_ms *ms, struct msgb *msg)
stop_mm_t3212(mm); /* 4.4.2 */
/* LAI */
gsm48_decode_lai_hex(lai, &subscr->mcc, &subscr->mnc, &subscr->lac);
gsm48_decode_lai2(lai, &subscr->lai);
/* stop location update timer */
stop_mm_t3210(mm);
@ -2445,19 +2422,17 @@ static int gsm48_mm_rx_loc_upd_acc(struct osmocom_ms *ms, struct msgb *msg)
gsm_subscr_write_loci(ms);
/* set last registered PLMN */
if (subscr->lac > 0x0000 && subscr->lac < 0xfffe) {
if (subscr->lai.lac > 0x0000 && subscr->lai.lac < 0xfffe) {
subscr->plmn_valid = 1;
subscr->plmn_mcc = subscr->mcc;
subscr->plmn_mnc = subscr->mnc;
memcpy(&subscr->plmn, &subscr->lai.plmn, sizeof(struct osmo_plmn_id));
}
LOGP(DSUM, LOGL_INFO, "Location update accepted\n");
LOGP(DMM, LOGL_INFO, "LOCATION UPDATING ACCEPT (mcc %s mnc %s "
"lac 0x%04x)\n", gsm_print_mcc(subscr->mcc),
gsm_print_mnc(subscr->mnc), subscr->lac);
LOGP(DMM, LOGL_INFO, "LOCATION UPDATING ACCEPT (lai=%s)\n",
osmo_lai_name(&subscr->lai));
/* remove LA from forbidden list */
gsm322_del_forbidden_la(ms, subscr->mcc, subscr->mnc, subscr->lac);
gsm322_del_forbidden_la(ms, &subscr->lai);
/* MI */
if (TLVP_PRESENT(&tp, GSM48_IE_MOBILE_ID)) {
@ -2583,7 +2558,7 @@ static int gsm48_mm_rel_loc_upd_rej(struct osmocom_ms *ms, struct msgb *msg)
case GSM48_REJECT_ROAMING_NOT_ALLOWED:
/* TMSI and LAI invalid */
subscr->tmsi = GSM_RESERVED_TMSI;
subscr->lac = 0x0000;
subscr->lai.lac = 0x0000;
/* key is invalid */
subscr->key_seq = 7;
@ -2632,15 +2607,13 @@ static int gsm48_mm_rel_loc_upd_rej(struct osmocom_ms *ms, struct msgb *msg)
LOGP(DSUM, LOGL_INFO, "Location update failed (Illegal ME)\n");
break;
case GSM48_REJECT_PLMN_NOT_ALLOWED:
gsm_subscr_add_forbidden_plmn(subscr, mm->lupd_mcc,
mm->lupd_mnc, mm->lupd_rej_cause);
gsm_subscr_add_forbidden_plmn(subscr, &mm->lupd_lai.plmn, mm->lupd_rej_cause);
LOGP(DSUM, LOGL_INFO, "Location update failed (PLMN not "
"allowed)\n");
break;
case GSM48_REJECT_LOC_NOT_ALLOWED:
case GSM48_REJECT_ROAMING_NOT_ALLOWED:
gsm322_add_forbidden_la(ms, mm->lupd_mcc, mm->lupd_mnc,
mm->lupd_lac, mm->lupd_rej_cause);
gsm322_add_forbidden_la(ms, &mm->lupd_lai, mm->lupd_rej_cause);
LOGP(DSUM, LOGL_INFO, "Location update failed (LAI not "
"allowed)\n");
break;
@ -2687,9 +2660,7 @@ static int gsm48_mm_loc_upd_failed(struct osmocom_ms *ms, struct msgb *msg)
stop_mm_t3210(mm);
if (subscr->ustate == GSM_SIM_U1_UPDATED
&& mm->lupd_mcc == subscr->mcc
&& mm->lupd_mnc == subscr->mnc
&& mm->lupd_lac == subscr->lac) {
&& (osmo_lai_cmp(&mm->lupd_lai, &subscr->lai) == 0)) {
if (mm->lupd_attempt < 4) {
LOGP(DSUM, LOGL_INFO, "Try location update later\n");
LOGP(DMM, LOGL_INFO, "Loc. upd. failed, retry #%d\n",
@ -2706,7 +2677,7 @@ static int gsm48_mm_loc_upd_failed(struct osmocom_ms *ms, struct msgb *msg)
/* TMSI and LAI invalid */
subscr->tmsi = GSM_RESERVED_TMSI;
subscr->lac = 0x0000;
subscr->lai.lac = 0x0000;
/* key is invalid */
subscr->key_seq = 7;
@ -2914,7 +2885,7 @@ static int gsm48_mm_rx_cm_service_rej(struct osmocom_ms *ms, struct msgb *msg)
/* TMSI and LAI invalid */
subscr->tmsi = GSM_RESERVED_TMSI;
subscr->lac = 0x0000;
subscr->lai.lac = 0x0000;
/* key is invalid */
subscr->key_seq = 7;

View File

@ -658,10 +658,9 @@ static void timeout_rr_meas(void *arg)
berr = (meas->berr + meas->frames / 2) / meas->frames;
snr = (meas->snr + meas->frames / 2) / meas->frames;
OSMO_STRBUF_PRINTF(sb, "MON: f=%d lev=%s snr=%2d ber=%3d "
"LAI=%s %s %04x ID=%04x", cs->sel_arfcn,
"CGI=%s", cs->sel_arfcn,
gsm_print_rxlev(rxlev), snr, berr,
gsm_print_mcc(cs->sel_mcc),
gsm_print_mnc(cs->sel_mnc), cs->sel_lac, cs->sel_id);
osmo_cgi_name(&cs->sel_cgi));
if (rr->state == GSM48_RR_ST_DEDICATED) {
OSMO_STRBUF_PRINTF(sb, " TA=%d pwr=%d",
rr->cd_now.ind_ta - set->alter_delay,
@ -1952,9 +1951,7 @@ static int gsm48_rr_rx_sysinfo4(struct osmocom_ms *ms, struct msgb *msg)
gsm48_decode_sysinfo4(s, si, msgb_l3len(msg));
LOGP(DRR, LOGL_INFO, "New SYSTEM INFORMATION 4 (mcc %s mnc %s "
"lac 0x%04x)\n", gsm_print_mcc(s->mcc),
gsm_print_mnc(s->mnc), s->lac);
LOGP(DRR, LOGL_INFO, "New SYSTEM INFORMATION 4 (lai=%s)\n", osmo_lai_name(&s->lai));
return gsm48_new_sysinfo(ms, si->header.system_information);
}
@ -2077,9 +2074,8 @@ static int gsm48_rr_rx_sysinfo6(struct osmocom_ms *ms, struct msgb *msg)
gsm48_decode_sysinfo6(s, si, msgb_l3len(msg));
LOGP(DRR, LOGL_INFO, "New SYSTEM INFORMATION 6 (mcc %s mnc %s "
"lac 0x%04x SACCH-timeout %d)\n", gsm_print_mcc(s->mcc),
gsm_print_mnc(s->mnc), s->lac, s->sacch_radio_link_timeout);
LOGP(DRR, LOGL_INFO, "New SYSTEM INFORMATION 6 (lai=%s SACCH-timeout %d)\n",
osmo_lai_name(&s->lai), s->sacch_radio_link_timeout);
meas->rl_fail = meas->s = s->sacch_radio_link_timeout;
LOGP(DRR, LOGL_INFO, "using (new) SACCH timeout %d\n", meas->rl_fail);
@ -2148,9 +2144,7 @@ static uint8_t gsm_match_mi(struct osmocom_ms *ms, uint8_t *mi)
return 0;
memcpy(&tmsi, mi+2, 4);
if (ms->subscr.tmsi == ntohl(tmsi)
&& ms->subscr.mcc == cs->sel_mcc
&& ms->subscr.mnc == cs->sel_mnc
&& ms->subscr.lac == cs->sel_lac) {
&& (osmo_lai_cmp(&ms->subscr.lai, &cs->sel_cgi.lai) == 0)) {
LOGP(DPAG, LOGL_INFO, " TMSI %08x matches\n",
ntohl(tmsi));
@ -2269,9 +2263,7 @@ static int gsm48_rr_rx_pag_req_2(struct osmocom_ms *ms, struct msgb *msg)
chan_2 = pa->cneed2;
/* first MI */
if (ms->subscr.tmsi == ntohl(pa->tmsi1)
&& ms->subscr.mcc == cs->sel_mcc
&& ms->subscr.mnc == cs->sel_mnc
&& ms->subscr.lac == cs->sel_lac) {
&& (osmo_lai_cmp(&ms->subscr.lai, &cs->sel_cgi.lai) == 0)) {
LOGP(DPAG, LOGL_INFO, " TMSI %08x matches\n", ntohl(pa->tmsi1));
return gsm48_rr_chan_req(ms, gsm48_rr_chan2cause[chan_1], 1,
GSM_MI_TYPE_TMSI);
@ -2280,9 +2272,7 @@ static int gsm48_rr_rx_pag_req_2(struct osmocom_ms *ms, struct msgb *msg)
ntohl(pa->tmsi1));
/* second MI */
if (ms->subscr.tmsi == ntohl(pa->tmsi2)
&& ms->subscr.mcc == cs->sel_mcc
&& ms->subscr.mnc == cs->sel_mnc
&& ms->subscr.lac == cs->sel_lac) {
&& (osmo_lai_cmp(&ms->subscr.lai, &cs->sel_cgi.lai) == 0)) {
LOGP(DPAG, LOGL_INFO, " TMSI %08x matches\n", ntohl(pa->tmsi2));
return gsm48_rr_chan_req(ms, gsm48_rr_chan2cause[chan_2], 1,
GSM_MI_TYPE_TMSI);
@ -2339,9 +2329,7 @@ static int gsm48_rr_rx_pag_req_3(struct osmocom_ms *ms, struct msgb *msg)
chan_4 = pa->cneed4;
/* first MI */
if (ms->subscr.tmsi == ntohl(pa->tmsi1)
&& ms->subscr.mcc == cs->sel_mcc
&& ms->subscr.mnc == cs->sel_mnc
&& ms->subscr.lac == cs->sel_lac) {
&& (osmo_lai_cmp(&ms->subscr.lai, &cs->sel_cgi.lai) == 0)) {
LOGP(DPAG, LOGL_INFO, " TMSI %08x matches\n", ntohl(pa->tmsi1));
return gsm48_rr_chan_req(ms, gsm48_rr_chan2cause[chan_1], 1,
GSM_MI_TYPE_TMSI);
@ -2350,9 +2338,7 @@ static int gsm48_rr_rx_pag_req_3(struct osmocom_ms *ms, struct msgb *msg)
ntohl(pa->tmsi1));
/* second MI */
if (ms->subscr.tmsi == ntohl(pa->tmsi2)
&& ms->subscr.mcc == cs->sel_mcc
&& ms->subscr.mnc == cs->sel_mnc
&& ms->subscr.lac == cs->sel_lac) {
&& (osmo_lai_cmp(&ms->subscr.lai, &cs->sel_cgi.lai) == 0)) {
LOGP(DPAG, LOGL_INFO, " TMSI %08x matches\n", ntohl(pa->tmsi2));
return gsm48_rr_chan_req(ms, gsm48_rr_chan2cause[chan_2], 1,
GSM_MI_TYPE_TMSI);
@ -2361,9 +2347,7 @@ static int gsm48_rr_rx_pag_req_3(struct osmocom_ms *ms, struct msgb *msg)
ntohl(pa->tmsi2));
/* third MI */
if (ms->subscr.tmsi == ntohl(pa->tmsi3)
&& ms->subscr.mcc == cs->sel_mcc
&& ms->subscr.mnc == cs->sel_mnc
&& ms->subscr.lac == cs->sel_lac) {
&& (osmo_lai_cmp(&ms->subscr.lai, &cs->sel_cgi.lai) == 0)) {
LOGP(DPAG, LOGL_INFO, " TMSI %08x matches\n", ntohl(pa->tmsi3));
return gsm48_rr_chan_req(ms, gsm48_rr_chan2cause[chan_3], 1,
GSM_MI_TYPE_TMSI);
@ -2372,9 +2356,7 @@ static int gsm48_rr_rx_pag_req_3(struct osmocom_ms *ms, struct msgb *msg)
ntohl(pa->tmsi3));
/* fourth MI */
if (ms->subscr.tmsi == ntohl(pa->tmsi4)
&& ms->subscr.mcc == cs->sel_mcc
&& ms->subscr.mnc == cs->sel_mnc
&& ms->subscr.lac == cs->sel_lac) {
&& (osmo_lai_cmp(&ms->subscr.lai, &cs->sel_cgi.lai) == 0)) {
LOGP(DPAG, LOGL_INFO, " TMSI %08x matches\n", ntohl(pa->tmsi4));
return gsm48_rr_chan_req(ms, gsm48_rr_chan2cause[chan_4], 1,
GSM_MI_TYPE_TMSI);
@ -3310,9 +3292,7 @@ static int gsm48_rr_dl_est(struct osmocom_ms *ms)
gsm48_rr_enc_cm2(ms, &pr->cm2, rr->cd_now.arfcn);
/* mobile identity */
if (ms->subscr.tmsi != GSM_RESERVED_TMSI
&& ms->subscr.mcc == cs->sel_mcc
&& ms->subscr.mnc == cs->sel_mnc
&& ms->subscr.lac == cs->sel_lac
&& (osmo_lai_cmp(&ms->subscr.lai, &cs->sel_cgi.lai) == 0)
&& rr->paging_mi_type == GSM_MI_TYPE_TMSI) {
gsm48_generate_mid_from_tmsi(mi, subscr->tmsi);
LOGP(DRR, LOGL_INFO, "sending paging response with "

View File

@ -151,23 +151,21 @@ static void gsm_ms_dump(struct osmocom_ms *ms, struct vty *vty)
else
vty_out(vty, " manual network selection state : %s%s",
get_m_state_name(ms->plmn.state), VTY_NEWLINE);
if (ms->plmn.mcc)
if (ms->plmn.plmn.mcc)
vty_out(vty, " MCC=%s "
"MNC=%s (%s, %s)%s", gsm_print_mcc(ms->plmn.mcc),
gsm_print_mnc(ms->plmn.mnc), gsm_get_mcc(ms->plmn.mcc),
gsm_get_mnc(ms->plmn.mcc, ms->plmn.mnc), VTY_NEWLINE);
"MNC=%s (%s, %s)%s", osmo_mcc_name(ms->plmn.plmn.mcc),
osmo_mnc_name(ms->plmn.plmn.mnc, ms->plmn.plmn.mnc_3_digits),
gsm_get_mcc(ms->plmn.plmn.mcc),
gsm_get_mnc(&ms->plmn.plmn), VTY_NEWLINE);
vty_out(vty, " cell selection state: %s%s",
get_cs_state_name(ms->cellsel.state), VTY_NEWLINE);
if (ms->cellsel.sel_mcc) {
vty_out(vty, " ARFCN=%s MCC=%s MNC=%s "
"LAC=0x%04x CELLID=0x%04x%s",
if (ms->cellsel.sel_cgi.lai.plmn.mcc) {
vty_out(vty, " ARFCN=%s CGI=%s%s",
gsm_print_arfcn(ms->cellsel.sel_arfcn),
gsm_print_mcc(ms->cellsel.sel_mcc),
gsm_print_mnc(ms->cellsel.sel_mnc),
ms->cellsel.sel_lac, ms->cellsel.sel_id, VTY_NEWLINE);
osmo_cgi_name(&ms->cellsel.sel_cgi), VTY_NEWLINE);
vty_out(vty, " (%s, %s)%s",
gsm_get_mcc(ms->cellsel.sel_mcc),
gsm_get_mnc(ms->cellsel.sel_mcc, ms->cellsel.sel_mnc),
gsm_get_mcc(ms->cellsel.sel_cgi.lai.plmn.mcc),
gsm_get_mnc(&ms->cellsel.sel_cgi.lai.plmn),
VTY_NEWLINE);
}
vty_out(vty, " radio resource layer state: %s%s",
@ -282,26 +280,26 @@ DEFUN(show_ba, show_ba_cmd, "show ba MS_NAME [MCC] [MNC]",
"Mobile Network Code")
{
struct osmocom_ms *ms;
uint16_t mcc = 0, mnc = 0;
struct osmo_plmn_id plmn;
struct osmo_plmn_id *plmn_ptr = NULL;
ms = l23_vty_get_ms(argv[0], vty);
if (!ms)
return CMD_WARNING;
if (argc >= 3) {
mcc = gsm_input_mcc((char *)argv[1]);
mnc = gsm_input_mnc((char *)argv[2]);
if (mcc == GSM_INPUT_INVALID) {
if (osmo_mcc_from_str(argv[1], &plmn.mcc) < 0) {
vty_out(vty, "Given MCC invalid%s", VTY_NEWLINE);
return CMD_WARNING;
}
if (mnc == GSM_INPUT_INVALID) {
if (osmo_mnc_from_str(argv[2], &plmn.mnc, &plmn.mnc_3_digits) < 0) {
vty_out(vty, "Given MNC invalid%s", VTY_NEWLINE);
return CMD_WARNING;
}
plmn_ptr = &plmn;
}
gsm322_dump_ba_list(&ms->cellsel, mcc, mnc, l23_vty_printf, vty);
gsm322_dump_ba_list(&ms->cellsel, plmn_ptr, l23_vty_printf, vty);
return CMD_SUCCESS;
}
@ -372,18 +370,17 @@ DEFUN(network_select, network_select_cmd,
"Force selecting a network that is not in the list")
{
struct osmocom_ms *ms;
struct gsm322_plmn *plmn;
struct gsm322_plmn *plmn322;
struct msgb *nmsg;
struct gsm322_msg *ngm;
struct gsm322_plmn_list *temp;
uint16_t mcc = gsm_input_mcc((char *)argv[1]),
mnc = gsm_input_mnc((char *)argv[2]);
struct osmo_plmn_id plmn;
int found = 0;
ms = l23_vty_get_ms(argv[0], vty);
if (!ms)
return CMD_WARNING;
plmn = &ms->plmn;
plmn322 = &ms->plmn;
if (ms->settings.plmn_mode != PLMN_MODE_MANUAL) {
vty_out(vty, "Not in manual network selection mode%s",
@ -391,18 +388,18 @@ DEFUN(network_select, network_select_cmd,
return CMD_WARNING;
}
if (mcc == GSM_INPUT_INVALID) {
if (osmo_mcc_from_str(argv[1], &plmn.mcc) < 0) {
vty_out(vty, "Given MCC invalid%s", VTY_NEWLINE);
return CMD_WARNING;
}
if (mnc == GSM_INPUT_INVALID) {
if (osmo_mnc_from_str(argv[2], &plmn.mnc, &plmn.mnc_3_digits) < 0) {
vty_out(vty, "Given MNC invalid%s", VTY_NEWLINE);
return CMD_WARNING;
}
if (argc < 4) {
llist_for_each_entry(temp, &plmn->sorted_plmn, entry)
if (temp->mcc == mcc && temp->mnc == mnc)
llist_for_each_entry(temp, &plmn322->sorted_plmn, entry)
if (osmo_plmn_cmp(&temp->plmn, &plmn) == 0)
found = 1;
if (!found) {
vty_out(vty, "Network not in list!%s", VTY_NEWLINE);
@ -416,8 +413,7 @@ DEFUN(network_select, network_select_cmd,
if (!nmsg)
return CMD_WARNING;
ngm = (struct gsm322_msg *) nmsg->data;
ngm->mcc = mcc;
ngm->mnc = mnc;
memcpy(&ngm->plmn, &plmn, sizeof(struct osmo_plmn_id));
gsm322_plmn_sendmsg(ms, nmsg);
return CMD_SUCCESS;
@ -623,23 +619,22 @@ DEFUN(delete_forbidden_plmn, delete_forbidden_plmn_cmd,
"Mobile Country Code\nMobile Network Code")
{
struct osmocom_ms *ms;
uint16_t mcc = gsm_input_mcc((char *)argv[1]),
mnc = gsm_input_mnc((char *)argv[2]);
struct osmo_plmn_id plmn;
ms = l23_vty_get_ms(argv[0], vty);
if (!ms)
return CMD_WARNING;
if (mcc == GSM_INPUT_INVALID) {
if (osmo_mcc_from_str(argv[1], &plmn.mcc) < 0) {
vty_out(vty, "Given MCC invalid%s", VTY_NEWLINE);
return CMD_WARNING;
}
if (mnc == GSM_INPUT_INVALID) {
if (osmo_mnc_from_str(argv[2], &plmn.mnc, &plmn.mnc_3_digits) < 0) {
vty_out(vty, "Given MNC invalid%s", VTY_NEWLINE);
return CMD_WARNING;
}
gsm_subscr_del_forbidden_plmn(&ms->subscr, mcc, mnc);
gsm_subscr_del_forbidden_plmn(&ms->subscr, &plmn);
return CMD_SUCCESS;
}
@ -667,9 +662,10 @@ DEFUN(network_show, network_show_cmd, "network show MS_NAME",
llist_for_each_entry(temp, &plmn->sorted_plmn, entry)
vty_out(vty, " Network %s, %s (%s, %s)%s",
gsm_print_mcc(temp->mcc), gsm_print_mnc(temp->mnc),
gsm_get_mcc(temp->mcc),
gsm_get_mnc(temp->mcc, temp->mnc), VTY_NEWLINE);
osmo_mcc_name(temp->plmn.mcc),
osmo_mnc_name(temp->plmn.mnc, temp->plmn.mnc_3_digits),
gsm_get_mcc(temp->plmn.mcc),
gsm_get_mnc(&temp->plmn), VTY_NEWLINE);
return CMD_SUCCESS;
}