* When enabled, the starting time will be set by given frames in the future.
* If a starting time is given by the network, this time is ignored.
*/
-//#define TEST_STARTING_TIMER 40
+//#define TEST_STARTING_TIMER 140
/* Testing if frequency modification works correctly "after time".
*
return 0;
}
+int gsm48_encode_lai(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;
+}
+
static int gsm48_decode_chan_h0(struct gsm48_chan_desc *cd, uint8_t *tsc,
uint16_t *arfcn)
{
struct gsm_settings *set = &ms->settings;
struct msgb *nmsg;
struct gsm48_hdr *gh;
+ struct gsm48_rr_hdr *nrrh;
uint8_t buf[11], *tlv;
LOGP(DRR, LOGL_INFO, "CIPHERING MODE COMPLETE (cr %d)\n", cr);
/* MI */
if (cr) {
gsm48_generate_mid_from_imsi(buf, set->imeisv);
+ /* alter MI type */
+ buf[2] = (buf[2] & ~GSM_MI_TYPE_MASK) | GSM_MI_TYPE_IMEISV;
tlv = msgb_put(nmsg, 2 + buf[1]);
memcpy(tlv, buf, 2 + buf[1]);
}
- return gsm48_send_rsl(ms, RSL_MT_DATA_REQ, nmsg);
+ gsm48_send_rsl(ms, RSL_MT_DATA_REQ, nmsg);
+
+ /* send RR_SYNC_IND(ciphering) */
+ nmsg = gsm48_rr_msgb_alloc(GSM48_RR_SYNC_IND);
+ if (!nmsg)
+ return -ENOMEM;
+ nrrh = (struct gsm48_rr_hdr *)nmsg->data;
+ nrrh->cause = RR_SYNC_CAUSE_CIPHERING;
+ return gsm48_rr_upmsg(ms, nmsg);
}
/* receive ciphering mode command */
static int gsm48_rr_rx_cip_mode_cmd(struct osmocom_ms *ms, struct msgb *msg)
{
struct gsm48_rrlayer *rr = &ms->rrlayer;
+ struct gsm_subscriber *subscr = &ms->subscr;
struct gsm_support *sup = &ms->support;
struct gsm48_hdr *gh = msgb_l3(msg);
struct gsm48_cip_mode_cmd *cm = (struct gsm48_cip_mode_cmd *)gh->data;
/* cipher mode response */
cr = cm->cr;
- if (sc)
- LOGP(DRR, LOGL_INFO, "CIPHERING MODE COMMAND (sc=%u, cr=%u)",
+ if (!sc)
+ LOGP(DRR, LOGL_INFO, "CIPHERING MODE COMMAND (sc=%u, cr=%u)\n",
sc, cr);
else
LOGP(DRR, LOGL_INFO, "CIPHERING MODE COMMAND (sc=%u, "
- "algo=A5/%d cr=%u)", sc, alg_id + 1, cr);
+ "algo=A5/%d cr=%u)\n", sc, alg_id + 1, cr);
/* 3.4.7.2 */
if (rr->cipher_on && sc) {
- LOGP(DRR, LOGL_NOTICE, "chiphering already applied.\n");
+ LOGP(DRR, LOGL_NOTICE, "chiphering already applied\n");
return gsm48_rr_tx_rr_status(ms,
GSM48_RR_CAUSE_PROT_ERROR_UNSPC);
}
/* check if we actually support this cipher */
- if ((alg_id == GSM_CIPHER_A5_1 && !sup->a5_1)
- || (alg_id == GSM_CIPHER_A5_2 && !sup->a5_2)
- || (alg_id == GSM_CIPHER_A5_3 && !sup->a5_3)
- || (alg_id == GSM_CIPHER_A5_4 && !sup->a5_4)
- || (alg_id == GSM_CIPHER_A5_5 && !sup->a5_5)
- || (alg_id == GSM_CIPHER_A5_6 && !sup->a5_6)
- || (alg_id == GSM_CIPHER_A5_7 && !sup->a5_7))
+ if (sc && ((alg_id == GSM_CIPHER_A5_1 && !sup->a5_1)
+ || (alg_id == GSM_CIPHER_A5_2 && !sup->a5_2)
+ || (alg_id == GSM_CIPHER_A5_3 && !sup->a5_3)
+ || (alg_id == GSM_CIPHER_A5_4 && !sup->a5_4)
+ || (alg_id == GSM_CIPHER_A5_5 && !sup->a5_5)
+ || (alg_id == GSM_CIPHER_A5_6 && !sup->a5_6)
+ || (alg_id == GSM_CIPHER_A5_7 && !sup->a5_7))) {
+ LOGP(DRR, LOGL_NOTICE, "algo not supported\n");
return gsm48_rr_tx_rr_status(ms,
GSM48_RR_CAUSE_CHAN_MODE_UNACCT);
+ }
+
+ /* check if we have no key */
+ if (sc && subscr->key_seq == 7) {
+ LOGP(DRR, LOGL_NOTICE, "no key available\n");
+ return gsm48_rr_tx_rr_status(ms,
+ GSM48_RR_CAUSE_PROT_ERROR_UNSPC);
+ }
/* change to ciphering */
-#warning FIXME: cyphering command
rr->cipher_on = sc, rr->cipher_type = alg_id;
+ if (sc)
+ l1ctl_tx_crypto_req(ms, alg_id + 1, subscr->key, 8);
+ else
+ l1ctl_tx_crypto_req(ms, 0, NULL, 0);
- /* response */
+ /* response (using the new mode) */
return gsm48_rr_tx_cip_mode_cpl(ms, cr);
}
cm->pwr_lev = sup->pwr_lev_1800;
else
cm->pwr_lev = sup->pwr_lev_900;
- cm->a5_1 = sup->a5_1;
+ cm->a5_1 = !sup->a5_1;
cm->es_ind = sup->es_ind;
cm->rev_lev = sup->rev_lev;
cm->fc = (sup->r_gsm || sup->e_gsm);
/* given LV of mobile identity is checked agains ms */
static int gsm_match_mi(struct osmocom_ms *ms, uint8_t *mi)
{
+ struct gsm322_cellsel *cs = &ms->cellsel;
char imsi[16];
uint32_t tmsi;
uint8_t mi_type;
return 0;
memcpy(&tmsi, mi+2, 4);
if (ms->subscr.tmsi == ntohl(tmsi)
- && ms->subscr.tmsi_valid) {
+ && ms->subscr.mcc == cs->sel_mcc
+ && ms->subscr.mnc == cs->sel_mnc
+ && ms->subscr.lac == cs->sel_lac) {
LOGP(DPAG, LOGL_INFO, "TMSI %08x matches\n",
ntohl(tmsi));
chan_2 = pa->cneed2;
/* first MI */
if (ms->subscr.tmsi == ntohl(pa->tmsi1)
- && ms->subscr.tmsi_valid) {
+ && ms->subscr.mcc == cs->sel_mcc
+ && ms->subscr.mnc == cs->sel_mnc
+ && ms->subscr.lac == cs->sel_lac) {
LOGP(DPAG, LOGL_INFO, "TMSI %08x matches\n", ntohl(pa->tmsi1));
return gsm48_rr_chan_req(ms, gsm48_rr_chan2cause[chan_1], 1);
} else
ntohl(pa->tmsi1));
/* second MI */
if (ms->subscr.tmsi == ntohl(pa->tmsi2)
- && ms->subscr.tmsi_valid) {
+ && ms->subscr.mcc == cs->sel_mcc
+ && ms->subscr.mnc == cs->sel_mnc
+ && ms->subscr.lac == cs->sel_lac) {
LOGP(DPAG, LOGL_INFO, "TMSI %08x matches\n", ntohl(pa->tmsi2));
return gsm48_rr_chan_req(ms, gsm48_rr_chan2cause[chan_2], 1);
} else
chan_4 = pa->cneed4;
/* first MI */
if (ms->subscr.tmsi == ntohl(pa->tmsi1)
- && ms->subscr.tmsi_valid) {
+ && ms->subscr.mcc == cs->sel_mcc
+ && ms->subscr.mnc == cs->sel_mnc
+ && ms->subscr.lac == cs->sel_lac) {
LOGP(DPAG, LOGL_INFO, "TMSI %08x matches\n", ntohl(pa->tmsi1));
return gsm48_rr_chan_req(ms, gsm48_rr_chan2cause[chan_1], 1);
} else
ntohl(pa->tmsi1));
/* second MI */
if (ms->subscr.tmsi == ntohl(pa->tmsi2)
- && ms->subscr.tmsi_valid) {
+ && ms->subscr.mcc == cs->sel_mcc
+ && ms->subscr.mnc == cs->sel_mnc
+ && ms->subscr.lac == cs->sel_lac) {
LOGP(DPAG, LOGL_INFO, "TMSI %08x matches\n", ntohl(pa->tmsi2));
return gsm48_rr_chan_req(ms, gsm48_rr_chan2cause[chan_2], 1);
} else
ntohl(pa->tmsi2));
/* thrid MI */
if (ms->subscr.tmsi == ntohl(pa->tmsi3)
- && ms->subscr.tmsi_valid) {
+ && ms->subscr.mcc == cs->sel_mcc
+ && ms->subscr.mnc == cs->sel_mnc
+ && ms->subscr.lac == cs->sel_lac) {
LOGP(DPAG, LOGL_INFO, "TMSI %08x matches\n", ntohl(pa->tmsi3));
return gsm48_rr_chan_req(ms, gsm48_rr_chan2cause[chan_3], 1);
} else
ntohl(pa->tmsi3));
/* fourth MI */
if (ms->subscr.tmsi == ntohl(pa->tmsi4)
- && ms->subscr.tmsi_valid) {
+ && ms->subscr.mcc == cs->sel_mcc
+ && ms->subscr.mnc == cs->sel_mnc
+ && ms->subscr.lac == cs->sel_lac) {
LOGP(DPAG, LOGL_INFO, "TMSI %08x matches\n", ntohl(pa->tmsi4));
return gsm48_rr_chan_req(ms, gsm48_rr_chan2cause[chan_4], 1);
} else
static int gsm48_rr_dl_est(struct osmocom_ms *ms)
{
struct gsm48_rrlayer *rr = &ms->rrlayer;
+ struct gsm322_cellsel *cs = &ms->cellsel;
struct gsm_subscriber *subscr = &ms->subscr;
struct msgb *nmsg;
struct gsm48_hdr *gh;
pr->cm2_len = sizeof(pr->cm2);
gsm48_rr_enc_cm2(ms, &pr->cm2);
/* mobile identity */
- if (ms->subscr.tmsi_valid) {
+ if (ms->subscr.tmsi != 0xffffffff
+ && ms->subscr.mcc == cs->sel_mcc
+ && ms->subscr.mnc == cs->sel_mnc
+ && ms->subscr.lac == cs->sel_lac) {
gsm48_generate_mid_from_tmsi(mi, subscr->tmsi);
LOGP(DRR, LOGL_INFO, "sending paging response with "
"TMSI\n");
/* 9.1.13 FREQUENCY REDEFINITION is received */
static int gsm48_rr_rx_frq_redef(struct osmocom_ms *ms, struct msgb *msg)
{
+#warning disabled, until added to libosmocore
+#if 0
struct gsm48_rrlayer *rr = &ms->rrlayer;
struct gsm48_frq_redef *fr = msgb_l3(msg);
int mob_al_len = msgb_l3len(msg) - sizeof(*fr);
rr->cd_now.start = 0;
+#endif
return 0;
}
/* 9.1.16 sending HANDOVER COMPLETE */
static int gsm48_rr_tx_hando_cpl(struct osmocom_ms *ms, uint8_t cause)
{
+#warning disabled, until added to libosmocore
+#if 0
struct msgb *nmsg;
struct gsm48_hdr *gh;
struct gsm48_ho_cpl *hc;
// FIXME: mobile observed time
return gsm48_send_rsl(ms, RSL_MT_DATA_REQ, nmsg);
+#endif
}
/* 9.1.4 sending HANDOVER FAILURE */
static int gsm48_rr_tx_hando_fail(struct osmocom_ms *ms, uint8_t cause)
{
+#warning disabled, until added to libosmocore
+#if 0
struct msgb *nmsg;
struct gsm48_hdr *gh;
struct gsm48_ho_fail *hf;
hf->rr_cause = cause;
return gsm48_send_rsl(ms, RSL_MT_DATA_REQ, nmsg);
+#endif
}
/* receiving HANDOVER COMMAND message (9.1.15) */
uint16_t ma[64];
uint8_t ma_len;
- LOGP(DRR, LOGL_INFO, "suspend complete, request resume of "
- "data link\n");
-
/* deactivating dedicated mode */
- LOGP(DRR, LOGL_INFO, "leaving dedicated mode\n");
- l1ctl_tx_dm_rel_req(rr->ms);
+ LOGP(DRR, LOGL_INFO, "suspension coplete, leaving dedicated "
+ "mode\n");
+ l1ctl_tx_dm_rel_req(ms);
+ l1ctl_tx_reset_req(ms, L1CTL_RES_T_SCHED);
/* store current channel descriptions */
memcpy(&rr->cd_last, &rr->cd_now, sizeof(rr->cd_last));
gsm48_send_rsl_rel(ms, RSL_MT_REL_REQ, nmsg);
/* deactivate channel */
- l1ctl_tx_dm_rel_req(rr->ms);
+ l1ctl_tx_dm_rel_req(ms);
+ l1ctl_tx_reset_req(ms, L1CTL_RES_T_SCHED);
switch (rr->modify_state) {
case GSM48_RR_MOD_ASSIGN: