layer23: Fixed issues about location update and it's result.
authorAndreas.Eversberg <jolly@eversberg.eu>
Sun, 13 Jun 2010 13:51:30 +0000 (13:51 +0000)
committerAndreas.Eversberg <jolly@eversberg.eu>
Sun, 13 Jun 2010 13:51:30 +0000 (13:51 +0000)
Now location update reject works. The rejected network/cell is stored in
an appropriate list. The lists can be dumped from the VTY.

A fake authentication response is generated until the SIM interface is
available. If the network rejects the test SIM, due to authentication
failure, it is removed and limited service state is entered. This currenlty
works on networks with SDCCH on the TS0 only.

src/host/layer23/include/osmocom/gsm322.h
src/host/layer23/include/osmocom/gsm48_mm.h
src/host/layer23/include/osmocom/subscriber.h
src/host/layer23/src/gsm322.c
src/host/layer23/src/gsm48_mm.c
src/host/layer23/src/gsm48_rr.c
src/host/layer23/src/subscriber.c
src/host/layer23/src/vty_interface.c

index bce9f3e..6cb1677 100755 (executable)
@@ -185,7 +185,8 @@ int gsm322_is_forbidden_la(struct osmocom_ms *ms, uint16_t mcc, uint16_t mnc,
 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);
+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,
                        void (*print)(void *, const char *, ...), void *priv);
 void start_cs_timer(struct gsm322_cellsel *cs, int sec, int micro);
index ece5484..ad71ce0 100644 (file)
@@ -183,6 +183,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;
 
        /* imsi detach */
        uint8_t                 delay_detach;   /* do detach when possible */
index 81cec30..40cf28a 100644 (file)
@@ -80,6 +80,8 @@ 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_dump_forbidden_plmn(struct osmocom_ms *ms,
+                       void (*print)(void *, const char *, ...), void *priv);
 void gsm_subscr_dump(struct gsm_subscriber *subscr,
                        void (*print)(void *, const char *, ...), void *priv);
 char *gsm_check_imsi(const char *imsi, uint16_t *mcc, uint16_t *mnc);
index 9a71092..a484bac 100644 (file)
@@ -1013,7 +1013,7 @@ static int gsm322_a_switch_on(struct osmocom_ms *ms, struct msgb *msg)
        struct msgb *nmsg;
 
        if (!subscr->sim_valid) {
-               LOGP(DSUM, LOGL_INFO, "No SIM inserted\n");
+               LOGP(DSUM, LOGL_INFO, "SIM is removed\n");
                LOGP(DPLMN, LOGL_INFO, "Switch on without SIM.\n");
                new_a_state(plmn, GSM322_A6_NO_SIM);
 
@@ -1214,7 +1214,7 @@ static int gsm322_m_switch_on(struct osmocom_ms *ms, struct msgb *msg)
        struct msgb *nmsg;
 
        if (!subscr->sim_valid) {
-               LOGP(DSUM, LOGL_INFO, "No SIM inserted\n");
+               LOGP(DSUM, LOGL_INFO, "SIM is removed\n");
                LOGP(DPLMN, LOGL_INFO, "Switch on without SIM.\n");
                new_m_state(plmn, GSM322_M5_NO_SIM);
 
@@ -2855,6 +2855,9 @@ static struct plmnastatelist {
        {SBIT(GSM322_A1_TRYING_RPLMN),
         GSM322_EVENT_REG_FAILED, gsm322_a_sel_first_plmn},
 
+       {SBIT(GSM322_A1_TRYING_RPLMN),
+        GSM322_EVENT_ROAMING_NA, gsm322_a_sel_first_plmn},
+
        {SBIT(GSM322_A1_TRYING_RPLMN),
         GSM322_EVENT_NO_CELL_FOUND, gsm322_a_sel_first_plmn},
 
@@ -2876,6 +2879,9 @@ static struct plmnastatelist {
        {SBIT(GSM322_A3_TRYING_PLMN),
         GSM322_EVENT_REG_FAILED, gsm322_a_sel_next_plmn},
 
+       {SBIT(GSM322_A3_TRYING_PLMN),
+        GSM322_EVENT_ROAMING_NA, gsm322_a_sel_next_plmn},
+
        {SBIT(GSM322_A3_TRYING_PLMN),
         GSM322_EVENT_NO_CELL_FOUND, gsm322_a_sel_next_plmn},
 
@@ -2952,6 +2958,9 @@ static struct plmnmstatelist {
        {SBIT(GSM322_M1_TRYING_RPLMN),
         GSM322_EVENT_REG_FAILED, gsm322_m_display_plmns},
 
+       {SBIT(GSM322_M1_TRYING_RPLMN),
+        GSM322_EVENT_ROAMING_NA, gsm322_m_display_plmns},
+
        {SBIT(GSM322_M1_TRYING_RPLMN),
         GSM322_EVENT_NO_CELL_FOUND, gsm322_m_display_plmns},
 
@@ -2980,6 +2989,9 @@ static struct plmnmstatelist {
        {SBIT(GSM322_M4_TRYING_PLMN),
         GSM322_EVENT_REG_FAILED, gsm322_m_go_not_on_plmn},
 
+       {SBIT(GSM322_M4_TRYING_PLMN),
+        GSM322_EVENT_ROAMING_NA, gsm322_m_go_not_on_plmn},
+
        {SBIT(GSM322_M4_TRYING_PLMN),
         GSM322_EVENT_NO_CELL_FOUND, gsm322_m_go_not_on_plmn},
 
@@ -3214,16 +3226,17 @@ int gsm322_dump_cs_list(struct gsm322_cellsel *cs, uint8_t flags,
        return 0;
 }
 
-int gsm322_dump_forbidden_la(struct osmocom_ms *ms)
+int gsm322_dump_forbidden_la(struct osmocom_ms *ms,
+                       void (*print)(void *, const char *, ...), void *priv)
 {
        struct gsm322_plmn *plmn = &ms->plmn;
        struct gsm322_la_list *temp;
 
-       printf("MCC    |MNC    |LAC    |cause\n");
-       printf("-------+-------+-------+-------\n");
+       print(priv, "MCC    |MNC    |LAC    |cause\n");
+       print(priv, "-------+-------+-------+-------\n");
        llist_for_each_entry(temp, &plmn->forbidden_la, entry)
-               printf("%03d    |%02d     |0x%04x |#%d\n", temp->mcc, temp->mnc,
-                       temp->lac, temp->cause);
+               print(priv, "%03d    |%02d     |0x%04x |#%d\n",
+                       temp->mcc, temp->mnc, temp->lac, temp->cause);
 
        return 0;
 }
index 54ac8f7..9fbc1f2 100644 (file)
@@ -1159,7 +1159,7 @@ static int gsm48_mm_cell_selected(struct osmocom_ms *ms, struct msgb *msg)
                        GSM48_MM_SST_LIMITED_SERVICE);
 
                /* send message to PLMN search process */
-               nmsg = gsm322_msgb_alloc(GSM322_EVENT_REG_FAILED);
+               nmsg = gsm322_msgb_alloc(GSM322_EVENT_ROAMING_NA);
                if (!nmsg)
                        return -ENOMEM;
                gsm322_plmn_sendmsg(ms, nmsg);
@@ -1508,6 +1508,10 @@ static int gsm48_mm_rx_tmsi_realloc_cmd(struct osmocom_ms *ms, struct msgb *msg)
        return 0;
 }
 
+#ifndef TODO
+static int gsm48_mm_tx_auth_rsp(struct osmocom_ms *ms, struct msgb *msg);
+#endif
+
 /* 4.3.2.2 AUTHENTICATION REQUEST is received */
 static int gsm48_mm_rx_auth_req(struct osmocom_ms *ms, struct msgb *msg)
 {
@@ -1535,6 +1539,17 @@ static int gsm48_mm_rx_auth_req(struct osmocom_ms *ms, struct msgb *msg)
 #ifdef TODO
        new key to sim:
        (..., ar->key_seq, ar->rand);
+#else
+       /* Fake response */
+       struct msgb *nmsg;
+       struct gsm48_mm_event *nmme;
+       nmsg = gsm48_l3_msgb_alloc();
+       if (!nmsg)
+               return -ENOMEM;
+       nmme = (struct gsm48_mm_event *)msgb_put(nmsg, sizeof(*nmme));
+       *((uint32_t *)nmme->sres) = 0x12345678;
+       gsm48_mm_tx_auth_rsp(ms, nmsg);
+       msgb_free(nmsg);
 #endif
 
        /* wait for auth response event from SIM */
@@ -1986,6 +2001,7 @@ static int gsm48_mm_loc_upd(struct osmocom_ms *ms, struct msgb *msg)
        struct gsm48_sysinfo *s = &cs->sel_si;
        struct gsm_subscriber *subscr = &ms->subscr;
        struct msgb *nmsg;
+       int msg_type;
        
        /* (re)start only if we still require location update */
        if (!mm->lupd_pending) {
@@ -1996,11 +2012,12 @@ static int gsm48_mm_loc_upd(struct osmocom_ms *ms, struct msgb *msg)
        /* must camp normally */
        if (cs->state != GSM322_C3_CAMPED_NORMALLY) {
                LOGP(DMM, LOGL_INFO, "Loc. upd. not camping normally.\n");
+               msg_type = GSM322_EVENT_REG_FAILED;
                stop:
                LOGP(DSUM, LOGL_INFO, "Location update not possible\n");
                mm->lupd_pending = 0;
                /* send message to PLMN search process */
-               nmsg = gsm322_msgb_alloc(GSM322_EVENT_REG_FAILED);
+               nmsg = gsm322_msgb_alloc(msg_type);
                if (!nmsg)
                        return -ENOMEM;
                gsm322_plmn_sendmsg(ms, nmsg);
@@ -2010,11 +2027,13 @@ static int gsm48_mm_loc_upd(struct osmocom_ms *ms, struct msgb *msg)
        /* if LAI is forbidden, don't start */
        if (gsm_subscr_is_forbidden_plmn(subscr, cs->sel_mcc, cs->sel_mnc)) {
                LOGP(DMM, LOGL_INFO, "Loc. upd. not allowed PLMN.\n");
+               msg_type = GSM322_EVENT_ROAMING_NA;
                goto stop;
        }
        if (gsm322_is_forbidden_la(ms, cs->sel_mcc,
                cs->sel_mnc, cs->sel_lac)) {
                LOGP(DMM, LOGL_INFO, "Loc. upd. not allowed LA.\n");
+               msg_type = GSM322_EVENT_ROAMING_NA;
                goto stop;
        }
 
@@ -2023,10 +2042,16 @@ static int gsm48_mm_loc_upd(struct osmocom_ms *ms, struct msgb *msg)
         || (!subscr->acc_barr && !((subscr->acc_class & 0xfbff) &
                                        (s->class_barr ^ 0xffff)))) {
                LOGP(DMM, LOGL_INFO, "Loc. upd. no access.\n");
+               msg_type = GSM322_EVENT_ROAMING_NA;
                goto stop;
        }
 
-       LOGP(DSUM, LOGL_INFO, "Perform location update\n");
+       mm->lupd_mcc = cs->sel_mcc;
+       mm->lupd_mnc = cs->sel_mnc;
+       mm->lupd_lac = cs->sel_lac;
+
+       LOGP(DSUM, LOGL_INFO, "Perform location update (MCC %03d, MNC %02d "
+               "LAC 0x%04x)\n", mm->lupd_mcc, mm->lupd_mnc, mm->lupd_lac);
 
        return gsm48_mm_tx_loc_upd_req(ms);
 }
@@ -2392,6 +2417,8 @@ static int gsm48_mm_rel_loc_upd_rej(struct osmocom_ms *ms, struct msgb *msg)
                sim: delete key seq number
                sim: apply update state
 #endif
+               /* update has finished */
+               mm->lupd_pending = 0;
        }
 
        /* send event to PLMN search process */
@@ -2416,17 +2443,27 @@ static int gsm48_mm_rel_loc_upd_rej(struct osmocom_ms *ms, struct msgb *msg)
        /* forbidden list */
        switch (mm->lupd_rej_cause) {
        case GSM48_REJECT_IMSI_UNKNOWN_IN_HLR:
+               LOGP(DSUM, LOGL_INFO, "Location update failed (IMSI unknown "
+                       "in HLR)\n");
+               break;
        case GSM48_REJECT_ILLEGAL_MS:
+               LOGP(DSUM, LOGL_INFO, "Location update failed (Illegal MS)\n");
+               break;
        case GSM48_REJECT_ILLEGAL_ME:
+               LOGP(DSUM, LOGL_INFO, "Location update failed (Illegal ME)\n");
                break;
        case GSM48_REJECT_PLMN_NOT_ALLOWED:
-               gsm_subscr_add_forbidden_plmn(subscr, subscr->lai_mcc,
-                       subscr->lai_mnc, mm->lupd_rej_cause);
+               gsm_subscr_add_forbidden_plmn(subscr, mm->lupd_mcc,
+                       mm->lupd_mnc, 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, subscr->lai_mcc, subscr->lai_mnc,
-                       subscr->lai_lac, mm->lupd_rej_cause);
+               gsm322_add_forbidden_la(ms, mm->lupd_mcc, mm->lupd_mnc,
+                       mm->lupd_lac, mm->lupd_rej_cause);
+               LOGP(DSUM, LOGL_INFO, "Location update failed (LAI not "
+                       "allowed)\n");
                break;
        default:
                /* 4.4.4.9 continue with failure handling */
@@ -2464,7 +2501,6 @@ static int gsm48_mm_loc_upd_failed(struct osmocom_ms *ms, struct msgb *msg)
 {
        struct gsm48_mmlayer *mm = &ms->mmlayer;
        struct gsm_subscriber *subscr = &ms->subscr;
-       struct gsm322_cellsel *cs = &ms->cellsel;
 
        LOGP(DSUM, LOGL_INFO, "Location update failed\n");
 
@@ -2472,10 +2508,9 @@ 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
-        && cs->selected
-        && cs->sel_mcc == subscr->lai_mcc
-        && cs->sel_mnc == subscr->lai_mnc
-        && cs->sel_lac == subscr->lai_lac) {
+        && mm->lupd_mcc == subscr->lai_mcc
+        && mm->lupd_mnc == subscr->lai_mnc
+        && mm->lupd_lac == subscr->lai_lac) {
                if (mm->lupd_attempt < 4) {
                        LOGP(DSUM, LOGL_INFO, "Try location update later\n");
                        LOGP(DMM, LOGL_INFO, "Loc. upd. failed, retry #%d\n",
index f38eb93..40926ab 100644 (file)
@@ -3596,7 +3596,8 @@ static struct dldatastate {
 #endif
 
        /* release */
-       {SBIT(GSM48_RR_ST_DEDICATED),
+       {SBIT(GSM48_RR_ST_CONN_PEND) |
+        SBIT(GSM48_RR_ST_DEDICATED),
         RSL_MT_REL_IND, gsm48_rr_rel_ind},
 
        {SBIT(GSM48_RR_ST_REL_PEND),
index 8a3a450..f52458d 100644 (file)
@@ -218,6 +218,21 @@ int gsm_subscr_is_forbidden_plmn(struct gsm_subscriber *subscr, uint16_t mcc,
        return 0;
 }
 
+int gsm_subscr_dump_forbidden_plmn(struct osmocom_ms *ms,
+                       void (*print)(void *, const char *, ...), void *priv)
+{
+       struct gsm_subscriber *subscr = &ms->subscr;
+       struct gsm_sub_plmn_na *temp;
+
+       print(priv, "MCC    |MNC    |cause\n");
+       print(priv, "-------+-------+-------\n");
+       llist_for_each_entry(temp, &subscr->plmn_na, entry)
+               print(priv, "%03d    |%02d     |#%d\n",
+                       temp->mcc, temp->mnc, temp->cause);
+
+       return 0;
+}
+
 /* dump subscriber */
 void gsm_subscr_dump(struct gsm_subscriber *subscr,
                        void (*print)(void *, const char *, ...), void *priv)
index d588843..39e3f4f 100644 (file)
@@ -217,6 +217,36 @@ DEFUN(show_ba, show_ba_cmd, "show ba MS_NAME [mcc] [mnc]",
        return CMD_SUCCESS;
 }
 
+DEFUN(show_forb_plmn, show_forb_plmn_cmd, "show forbidden plmn MS_NAME",
+       SHOW_STR "Display information about forbidden cells / networks\n"
+       "Display forbidden PLMNs\nName of MS (see \"show ms\")")
+{
+       struct osmocom_ms *ms;
+
+       ms = get_ms(argv[0], vty);
+       if (!ms)
+               return CMD_WARNING;
+
+       gsm_subscr_dump_forbidden_plmn(ms, print_vty, vty);
+
+       return CMD_SUCCESS;
+}
+
+DEFUN(show_forb_la, show_forb_la_cmd, "show forbidden location-area MS_NAME",
+       SHOW_STR "Display information about forbidden cells / networks\n"
+       "Display forbidden location areas\nName of MS (see \"show ms\")")
+{
+       struct osmocom_ms *ms;
+
+       ms = get_ms(argv[0], vty);
+       if (!ms)
+               return CMD_WARNING;
+
+       gsm322_dump_forbidden_la(ms, print_vty, vty);
+
+       return CMD_SUCCESS;
+}
+
 DEFUN(insert_test, insert_test_cmd, "insert testcard MS_NAME [mcc] [mnc]",
        "Insert ...\nInsert test card\nName of MS (see \"show ms\")\n"
        "Mobile Country Code\nMobile Network Code")
@@ -645,6 +675,10 @@ int ms_vty_init(void)
        install_element(VIEW_NODE, &show_cell_si_cmd);
        install_element(ENABLE_NODE, &show_ba_cmd);
        install_element(VIEW_NODE, &show_ba_cmd);
+       install_element(ENABLE_NODE, &show_forb_la_cmd);
+       install_element(VIEW_NODE, &show_forb_la_cmd);
+       install_element(ENABLE_NODE, &show_forb_plmn_cmd);
+       install_element(VIEW_NODE, &show_forb_plmn_cmd);
 
        install_element(ENABLE_NODE, &insert_test_cmd);
        install_element(ENABLE_NODE, &remove_sim_cmd);