2 * (C) 2010 by Andreas Eversberg <jolly@eversberg.eu>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
27 #include <arpa/inet.h>
29 #include <osmocore/msgb.h>
30 #include <osmocore/utils.h>
31 #include <osmocore/gsm48.h>
32 #include <osmocore/talloc.h>
34 #include <osmocom/logging.h>
35 #include <osmocom/osmocom_data.h>
36 #include <osmocom/gsm48_cc.h>
37 #include <osmocom/l23_app.h>
38 #include <osmocom/networks.h>
42 void mm_conn_free(struct gsm48_mm_conn *conn);
43 static int gsm48_rcv_rr(struct osmocom_ms *ms, struct msgb *msg);
44 static int gsm48_rcv_mmr(struct osmocom_ms *ms, struct msgb *msg);
45 static int gsm48_mm_ev(struct osmocom_ms *ms, int msg_type, struct msgb *msg);
46 static int gsm48_mm_tx_id_rsp(struct osmocom_ms *ms, uint8_t mi_type);
47 static int gsm48_mm_tx_loc_upd_req(struct osmocom_ms *ms);
48 static int gsm48_mm_loc_upd_failed(struct osmocom_ms *ms, struct msgb *msg);
49 static int gsm48_mm_conn_go_dedic(struct osmocom_ms *ms);
50 static int gsm48_mm_init_mm_reject(struct osmocom_ms *ms, struct msgb *msg);
51 static int gsm48_mm_data_ind(struct osmocom_ms *ms, struct msgb *msg);
52 static void new_mm_state(struct gsm48_mmlayer *mm, int state, int substate);
53 static int gsm48_mm_loc_upd_normal(struct osmocom_ms *ms, struct msgb *msg);
54 static int gsm48_mm_loc_upd_periodic(struct osmocom_ms *ms, struct msgb *msg);
55 static int gsm48_mm_loc_upd(struct osmocom_ms *ms, struct msgb *msg);
62 * Notes on IMSI detach procedure:
64 * At the end of the procedure, the state of MM, RR, cell selection: No SIM.
66 * In MM IDLE state, cell available: RR is establised, IMSI detach specific
67 * procedure is performed.
69 * In MM IDLE state, no cell: State is silently changed to No SIM.
71 * During any MM connection state, or Wait for network command: All MM
72 * connections (if any) are released locally, and IMSI detach specific
73 * procedure is performed.
75 * During IMSI detach processing: Request of IMSI detach is ignored.
77 * Any other state: The special 'delay_detach' flag is set only. If set, at any
78 * state transition we will clear the flag and restart the procedure again.
80 * The procedure is not spec conform, but always succeeds.
84 /* Notes on Service states:
86 * There are two PLMN search states:
88 * - PLMN SEARCH NORMAL
91 * They are entered, if: (4.2.1.2)
94 * - user has asked PLMN selection in certain Service states
95 * - coverage is lost in certain Service states
97 * - (optionally see 4.2.1.2)
99 * PLMN SEARCH NORMAL state is then entered, if all these conditions are met:
106 * Otherwhise PLMN SEARCH is entered.
108 * During PLMN SEARCH NORMAL state: (4.2.2.5)
109 * - on expirery of T3211 or T3213: Perform location update, when back
110 * to NORMAL SERVICE state.
111 * - on expirery of T3212: Perform periodic location update, when back
112 * to NORMAL SERVICE state.
113 * - perform IMSI detach
114 * - perform MM connections
115 * - respond to paging (if possible)
117 * During PLMN SEARCH state: (4.2.2.6)
118 * - reject MM connection except for emergency calls
121 * The NO CELL AVAILABLE state is entered, if:
122 * - no cell found during PLMN search
124 * During NO CELL AVAILABLE state:
125 * - reject any MM connection
128 * The NO IMSI state is entered if:
130 * - and cell is selected during PLMN SEARCH states
132 * During NO IMSO state: (4.2.2.4)
133 * - reject MM connection except for emergency calls
136 * The LIMITED SERVICE state is entered if:
138 * - and SIM state is U3
139 * - and cell is selected
141 * During LIMITED SERVICE state: (4.2.2.3)
142 * - reject MM connection except for emergency calls
143 * - perform location update, if new LAI is entered
146 * The LOCATION UPDATE NEEDED state is entered if:
148 * - and location update must be performed for any reason
150 * During LOCATION UPDATE NEEDED state:
151 * - reject MM connection except for emergency calls
153 * This state is left if location update is possible and directly enter
154 * state ATTEMPTING TO UPDATE and trigger location update.
155 * The function gsm48_mm_loc_upd_possible() is used to check this on state
159 * The ATTEMPTING TO UPDATE state is entered if:
161 * - and SIM state is U2
162 * - and cell is selected
164 * During ATTEMPTING TO UPDATE state: (4.2.2.2)
165 * - on expirery of T3211 or T3213: Perform location updated
166 * - on expirery of T3212: Perform location updated
167 * - on change of LAI: Perform location update
168 * - (abnormal cases unsupported)
169 * - accept MM connection for emergency calls
170 * - trigger location update on any other MM connection
171 * - respond to paging (with IMSI only, because in U2 TMSI is not valid)
174 * The NORMAL SERVICE state is entered if:
176 * - and SIM state is U1
177 * - and cell is selected
178 * - and SIM LAI == cell
180 * During NORMAL SERVICE state: (4.2.2.1)
181 * - on expirery of T3211 or T3213: Perform location updated
182 * - on expirery of T3212: Perform location updated
183 * - on change of LAI: Perform location update
184 * - perform IMSI detach
185 * - perform MM connections
186 * - respond to paging
189 * gsm48_mm_set_plmn_search() is used enter PLMN SEARCH or PLMN SEARCH NORMAL
190 * state. Depending on the conditions above, the appropiate state is selected.
193 * gsm48_mm_return_idle() is used to select the Service state when returning
194 * to MM IDLE state after cell reselection.
197 * If cell selection process indicates NO_CELL_FOUND:
199 * - NO CELL AVAILABLE state is entered, if not already.
201 * gsm48_mm_no_cell_found() is used to select the Service state.
204 * If cell selection process indicates CELL_SELECTED:
206 * - NO IMSI state is entered, if no SIM valid.
207 * - Otherwise NORMAL SERVICES state is entered, if
208 * SIM state is U1, SIM LAI == cell, IMSI is attached, T3212 not expired.
209 * - Otherwise NORMAL SERVICES state is entered, if
210 * SIM state is U1, SIM LAI == cell, attach not required, T3212 not expired.
211 * - Otherwise LIMITED SERVICE state is entered, if
212 * CS mode is automatic, cell is forbidden PLMN or forbidden LA.
213 * - Otherwise LIMITED SERVICE state is entered, if
214 * CS mode is manual, cell is not the selected one.
215 * - Otherwise LOCATION UPDATE NEEDED state is entered.
217 * gsm48_mm_cell_selected() is used to select the Service state.
225 /* decode network name */
226 static int decode_network_name(char *name, int name_len,
229 uint8_t in_len = lv[0];
236 /* must be CB encoded */
237 if ((lv[1] & 0x70) != 0x00)
240 padding = lv[1] & 0x03;
241 length = ((in_len - 1) * 8 - padding) / 7;
244 if (length >= name_len)
245 length = name_len - 1;
246 gsm_7bit_decode(name, lv + 2, length);
252 /* encode 'mobile identity' */
253 int gsm48_encode_mi(uint8_t *buf, struct msgb *msg, struct osmocom_ms *ms,
256 struct gsm_subscriber *subscr = &ms->subscr;
257 struct gsm_settings *set = &ms->settings;
261 case GSM_MI_TYPE_TMSI:
262 gsm48_generate_mid_from_tmsi(buf, subscr->tmsi);
264 case GSM_MI_TYPE_IMSI:
265 gsm48_generate_mid_from_imsi(buf, subscr->imsi);
267 case GSM_MI_TYPE_IMEI:
268 gsm48_generate_mid_from_imsi(buf, set->imei);
270 case GSM_MI_TYPE_IMEISV:
271 gsm48_generate_mid_from_imsi(buf, set->imeisv);
273 case GSM_MI_TYPE_NONE:
275 buf[0] = GSM48_IE_MOBILE_ID;
281 buf[2] = (buf[2] & ~GSM_MI_TYPE_MASK) | mi_type;
285 ie = msgb_put(msg, 1 + buf[1]);
286 memcpy(ie, buf + 1, 1 + buf[1]);
292 /* encode 'classmark 1' */
293 int gsm48_encode_classmark1(struct gsm48_classmark1 *cm, uint8_t rev_lev,
294 uint8_t es_ind, uint8_t a5_1, uint8_t pwr_lev)
296 memset(cm, 0, sizeof(*cm));
297 cm->rev_lev = rev_lev;
300 cm->pwr_lev = pwr_lev;
309 static void timeout_mm_t3210(void *arg)
311 struct gsm48_mmlayer *mm = arg;
313 LOGP(DMM, LOGL_INFO, "timer T3210 (loc. upd. timeout) has fired\n");
314 gsm48_mm_ev(mm->ms, GSM48_MM_EVENT_TIMEOUT_T3210, NULL);
317 static void timeout_mm_t3211(void *arg)
319 struct gsm48_mmlayer *mm = arg;
321 LOGP(DSUM, LOGL_INFO, "Location update retry\n");
322 LOGP(DMM, LOGL_INFO, "timer T3211 (loc. upd. retry delay) has fired\n");
323 gsm48_mm_ev(mm->ms, GSM48_MM_EVENT_TIMEOUT_T3211, NULL);
326 static void timeout_mm_t3212(void *arg)
328 struct gsm48_mmlayer *mm = arg;
330 LOGP(DSUM, LOGL_INFO, "Periodic location update\n");
331 LOGP(DMM, LOGL_INFO, "timer T3212 (periodic loc. upd. delay) has "
334 /* reset attempt counter when attempting to update (4.4.4.5) */
335 if (mm->state == GSM48_MM_ST_MM_IDLE
336 && mm->substate == GSM48_MM_SST_ATTEMPT_UPDATE)
337 mm->lupd_attempt = 0;
339 gsm48_mm_ev(mm->ms, GSM48_MM_EVENT_TIMEOUT_T3212, NULL);
342 static void timeout_mm_t3213(void *arg)
344 struct gsm48_mmlayer *mm = arg;
346 LOGP(DSUM, LOGL_INFO, "Location update retry\n");
347 LOGP(DMM, LOGL_INFO, "timer T3213 (delay after RA failure) has "
349 gsm48_mm_ev(mm->ms, GSM48_MM_EVENT_TIMEOUT_T3213, NULL);
352 static void timeout_mm_t3230(void *arg)
354 struct gsm48_mmlayer *mm = arg;
356 LOGP(DMM, LOGL_INFO, "timer T3230 (MM connection timeout) has "
358 gsm48_mm_ev(mm->ms, GSM48_MM_EVENT_TIMEOUT_T3230, NULL);
361 static void timeout_mm_t3220(void *arg)
363 struct gsm48_mmlayer *mm = arg;
365 LOGP(DMM, LOGL_INFO, "timer T3220 (IMSI detach keepalive) has "
367 gsm48_mm_ev(mm->ms, GSM48_MM_EVENT_TIMEOUT_T3220, NULL);
370 static void timeout_mm_t3240(void *arg)
372 struct gsm48_mmlayer *mm = arg;
374 LOGP(DMM, LOGL_INFO, "timer T3240 (RR release timeout) has fired\n");
375 gsm48_mm_ev(mm->ms, GSM48_MM_EVENT_TIMEOUT_T3240, NULL);
378 static void start_mm_t3210(struct gsm48_mmlayer *mm)
380 LOGP(DMM, LOGL_INFO, "starting T3210 (loc. upd. timeout) with %d.%d "
381 "seconds\n", GSM_T3210_MS);
382 mm->t3210.cb = timeout_mm_t3210;
384 bsc_schedule_timer(&mm->t3210, GSM_T3210_MS);
387 static void start_mm_t3211(struct gsm48_mmlayer *mm)
389 LOGP(DMM, LOGL_INFO, "starting T3211 (loc. upd. retry delay) with "
390 "%d.%d seconds\n", GSM_T3211_MS);
391 mm->t3211.cb = timeout_mm_t3211;
393 bsc_schedule_timer(&mm->t3211, GSM_T3211_MS);
396 static void start_mm_t3212(struct gsm48_mmlayer *mm, int sec)
398 /* don't start, if is not available */
402 LOGP(DMM, LOGL_INFO, "starting T3212 (periodic loc. upd. delay) with "
403 "%d seconds\n", sec);
404 mm->t3212.cb = timeout_mm_t3212;
406 bsc_schedule_timer(&mm->t3212, sec, 0);
409 static void start_mm_t3213(struct gsm48_mmlayer *mm)
411 LOGP(DMM, LOGL_INFO, "starting T3213 (delay after RA failure) with "
412 "%d.%d seconds\n", GSM_T3213_MS);
413 mm->t3213.cb = timeout_mm_t3213;
415 bsc_schedule_timer(&mm->t3213, GSM_T3213_MS);
418 static void start_mm_t3220(struct gsm48_mmlayer *mm)
420 LOGP(DMM, LOGL_INFO, "starting T3220 (IMSI detach keepalive) with "
421 "%d.%d seconds\n", GSM_T3220_MS);
422 mm->t3220.cb = timeout_mm_t3220;
424 bsc_schedule_timer(&mm->t3220, GSM_T3220_MS);
427 static void start_mm_t3230(struct gsm48_mmlayer *mm)
429 LOGP(DMM, LOGL_INFO, "starting T3230 (MM connection timeout) with "
430 "%d.%d seconds\n", GSM_T3230_MS);
431 mm->t3230.cb = timeout_mm_t3230;
433 bsc_schedule_timer(&mm->t3230, GSM_T3230_MS);
436 static void start_mm_t3240(struct gsm48_mmlayer *mm)
438 LOGP(DMM, LOGL_INFO, "starting T3240 (RR release timeout) with %d.%d "
439 "seconds\n", GSM_T3240_MS);
440 mm->t3240.cb = timeout_mm_t3240;
442 bsc_schedule_timer(&mm->t3240, GSM_T3240_MS);
445 static void stop_mm_t3210(struct gsm48_mmlayer *mm)
447 if (bsc_timer_pending(&mm->t3210)) {
448 LOGP(DMM, LOGL_INFO, "stopping pending (loc. upd. timeout) "
450 bsc_del_timer(&mm->t3210);
454 static void stop_mm_t3211(struct gsm48_mmlayer *mm)
456 if (bsc_timer_pending(&mm->t3211)) {
457 LOGP(DMM, LOGL_INFO, "stopping pending (loc. upd. retry "
458 "delay) timer T3211\n");
459 bsc_del_timer(&mm->t3211);
463 static void stop_mm_t3212(struct gsm48_mmlayer *mm)
465 if (bsc_timer_pending(&mm->t3212)) {
466 LOGP(DMM, LOGL_INFO, "stopping pending (periodic loc. upd. "
467 "delay) timer T3212\n");
468 bsc_del_timer(&mm->t3212);
472 static void stop_mm_t3213(struct gsm48_mmlayer *mm)
474 if (bsc_timer_pending(&mm->t3213)) {
475 LOGP(DMM, LOGL_INFO, "stopping pending (delay after RA "
476 "failure) timer T3213\n");
477 bsc_del_timer(&mm->t3213);
481 static void stop_mm_t3220(struct gsm48_mmlayer *mm)
483 if (bsc_timer_pending(&mm->t3220)) {
484 LOGP(DMM, LOGL_INFO, "stopping pending (IMSI detach keepalive) "
486 bsc_del_timer(&mm->t3220);
490 static void stop_mm_t3230(struct gsm48_mmlayer *mm)
492 if (bsc_timer_pending(&mm->t3230)) {
493 LOGP(DMM, LOGL_INFO, "stopping pending (MM connection timeout) "
495 bsc_del_timer(&mm->t3230);
499 static void stop_mm_t3240(struct gsm48_mmlayer *mm)
501 if (bsc_timer_pending(&mm->t3240)) {
502 LOGP(DMM, LOGL_INFO, "stopping pending (RR release timeout) "
504 bsc_del_timer(&mm->t3240);
508 static void stop_mm_t3241(struct gsm48_mmlayer *mm)
510 /* not implemented, not required */
517 /* names of MM events */
518 static const struct value_string gsm48_mmevent_names[] = {
519 { GSM48_MM_EVENT_CELL_SELECTED, "MM_EVENT_CELL_SELECTED" },
520 { GSM48_MM_EVENT_NO_CELL_FOUND, "MM_EVENT_NO_CELL_FOUND" },
521 { GSM48_MM_EVENT_TIMEOUT_T3210, "MM_EVENT_TIMEOUT_T3210" },
522 { GSM48_MM_EVENT_TIMEOUT_T3211, "MM_EVENT_TIMEOUT_T3211" },
523 { GSM48_MM_EVENT_TIMEOUT_T3212, "MM_EVENT_TIMEOUT_T3212" },
524 { GSM48_MM_EVENT_TIMEOUT_T3213, "MM_EVENT_TIMEOUT_T3213" },
525 { GSM48_MM_EVENT_TIMEOUT_T3220, "MM_EVENT_TIMEOUT_T3220" },
526 { GSM48_MM_EVENT_TIMEOUT_T3230, "MM_EVENT_TIMEOUT_T3230" },
527 { GSM48_MM_EVENT_TIMEOUT_T3240, "MM_EVENT_TIMEOUT_T3240" },
528 { GSM48_MM_EVENT_IMSI_DETACH, "MM_EVENT_IMSI_DETACH" },
529 { GSM48_MM_EVENT_PAGING, "MM_EVENT_PAGING" },
530 { GSM48_MM_EVENT_AUTH_RESPONSE, "MM_EVENT_AUTH_RESPONSE" },
531 { GSM48_MM_EVENT_SYSINFO, "MM_EVENT_SYSINFO" },
532 { GSM48_MM_EVENT_USER_PLMN_SEL, "MM_EVENT_USER_PLMN_SEL" },
536 const char *get_mmevent_name(int value)
538 return get_value_string(gsm48_mmevent_names, value);
541 /* names of MM-SAP */
542 static const struct value_string gsm48_mm_msg_names[] = {
543 { GSM48_MT_MM_IMSI_DETACH_IND, "MT_MM_IMSI_DETACH_IND" },
544 { GSM48_MT_MM_LOC_UPD_ACCEPT, "MT_MM_LOC_UPD_ACCEPT" },
545 { GSM48_MT_MM_LOC_UPD_REJECT, "MT_MM_LOC_UPD_REJECT" },
546 { GSM48_MT_MM_LOC_UPD_REQUEST, "MT_MM_LOC_UPD_REQUEST" },
547 { GSM48_MT_MM_AUTH_REJ, "MT_MM_AUTH_REJ" },
548 { GSM48_MT_MM_AUTH_REQ, "MT_MM_AUTH_REQ" },
549 { GSM48_MT_MM_AUTH_RESP, "MT_MM_AUTH_RESP" },
550 { GSM48_MT_MM_ID_REQ, "MT_MM_ID_REQ" },
551 { GSM48_MT_MM_ID_RESP, "MT_MM_ID_RESP" },
552 { GSM48_MT_MM_TMSI_REALL_CMD, "MT_MM_TMSI_REALL_CMD" },
553 { GSM48_MT_MM_TMSI_REALL_COMPL, "MT_MM_TMSI_REALL_COMPL" },
554 { GSM48_MT_MM_CM_SERV_ACC, "MT_MM_CM_SERV_ACC" },
555 { GSM48_MT_MM_CM_SERV_REJ, "MT_MM_CM_SERV_REJ" },
556 { GSM48_MT_MM_CM_SERV_ABORT, "MT_MM_CM_SERV_ABORT" },
557 { GSM48_MT_MM_CM_SERV_REQ, "MT_MM_CM_SERV_REQ" },
558 { GSM48_MT_MM_CM_SERV_PROMPT, "MT_MM_CM_SERV_PROMPT" },
559 { GSM48_MT_MM_CM_REEST_REQ, "MT_MM_CM_REEST_REQ" },
560 { GSM48_MT_MM_ABORT, "MT_MM_ABORT" },
561 { GSM48_MT_MM_NULL, "MT_MM_NULL" },
562 { GSM48_MT_MM_STATUS, "MT_MM_STATUS" },
563 { GSM48_MT_MM_INFO, "MT_MM_INFO" },
567 const char *get_mm_name(int value)
569 return get_value_string(gsm48_mm_msg_names, value);
572 /* names of MMxx-SAP */
573 static const struct value_string gsm48_mmxx_msg_names[] = {
574 { GSM48_MMCC_EST_REQ, "MMCC_EST_REQ" },
575 { GSM48_MMCC_EST_IND, "MMCC_EST_IND" },
576 { GSM48_MMCC_EST_CNF, "MMCC_EST_CNF" },
577 { GSM48_MMCC_REL_REQ, "MMCC_REL_REQ" },
578 { GSM48_MMCC_REL_IND, "MMCC_REL_IND" },
579 { GSM48_MMCC_DATA_REQ, "MMCC_DATA_REQ" },
580 { GSM48_MMCC_DATA_IND, "MMCC_DATA_IND" },
581 { GSM48_MMCC_UNIT_DATA_REQ, "MMCC_UNIT_DATA_REQ" },
582 { GSM48_MMCC_UNIT_DATA_IND, "MMCC_UNIT_DATA_IND" },
583 { GSM48_MMCC_SYNC_IND, "MMCC_SYNC_IND" },
584 { GSM48_MMCC_REEST_REQ, "MMCC_REEST_REQ" },
585 { GSM48_MMCC_REEST_CNF, "MMCC_REEST_CNF" },
586 { GSM48_MMCC_ERR_IND, "MMCC_ERR_IND" },
587 { GSM48_MMCC_PROMPT_IND, "MMCC_PROMPT_IND" },
588 { GSM48_MMCC_PROMPT_REJ, "MMCC_PROMPT_REJ" },
589 { GSM48_MMSS_EST_REQ, "MMSS_EST_REQ" },
590 { GSM48_MMSS_EST_IND, "MMSS_EST_IND" },
591 { GSM48_MMSS_EST_CNF, "MMSS_EST_CNF" },
592 { GSM48_MMSS_REL_REQ, "MMSS_REL_REQ" },
593 { GSM48_MMSS_REL_IND, "MMSS_REL_IND" },
594 { GSM48_MMSS_DATA_REQ, "MMSS_DATA_REQ" },
595 { GSM48_MMSS_DATA_IND, "MMSS_DATA_IND" },
596 { GSM48_MMSS_UNIT_DATA_REQ, "MMSS_UNIT_DATA_REQ" },
597 { GSM48_MMSS_UNIT_DATA_IND, "MMSS_UNIT_DATA_IND" },
598 { GSM48_MMSS_REEST_REQ, "MMSS_REEST_REQ" },
599 { GSM48_MMSS_REEST_CNF, "MMSS_REEST_CNF" },
600 { GSM48_MMSS_ERR_IND, "MMSS_ERR_IND" },
601 { GSM48_MMSS_PROMPT_IND, "MMSS_PROMPT_IND" },
602 { GSM48_MMSS_PROMPT_REJ, "MMSS_PROMPT_REJ" },
603 { GSM48_MMSMS_EST_REQ, "MMSMS_EST_REQ" },
604 { GSM48_MMSMS_EST_IND, "MMSMS_EST_IND" },
605 { GSM48_MMSMS_EST_CNF, "MMSMS_EST_CNF" },
606 { GSM48_MMSMS_REL_REQ, "MMSMS_REL_REQ" },
607 { GSM48_MMSMS_REL_IND, "MMSMS_REL_IND" },
608 { GSM48_MMSMS_DATA_REQ, "MMSMS_DATA_REQ" },
609 { GSM48_MMSMS_DATA_IND, "MMSMS_DATA_IND" },
610 { GSM48_MMSMS_UNIT_DATA_REQ, "MMSMS_UNIT_DATA_REQ" },
611 { GSM48_MMSMS_UNIT_DATA_IND, "MMSMS_UNIT_DATA_IND" },
612 { GSM48_MMSMS_REEST_REQ, "MMSMS_REEST_REQ" },
613 { GSM48_MMSMS_REEST_CNF, "MMSMS_REEST_CNF" },
614 { GSM48_MMSMS_ERR_IND, "MMSMS_ERR_IND" },
615 { GSM48_MMSMS_PROMPT_IND, "MMSMS_PROMPT_IND" },
616 { GSM48_MMSMS_PROMPT_REJ, "MMSMS_PROMPT_REJ" },
620 const char *get_mmxx_name(int value)
622 return get_value_string(gsm48_mmxx_msg_names, value);
625 /* names of MMR-SAP */
626 static const struct value_string gsm48_mmr_msg_names[] = {
627 { GSM48_MMR_REG_REQ, "MMR_REG_REQ" },
628 { GSM48_MMR_REG_CNF, "MMR_REG_CNF" },
629 { GSM48_MMR_NREG_REQ, "MMR_NREG_REQ" },
630 { GSM48_MMR_NREG_IND, "MMR_NREG_IND" },
634 const char *get_mmr_name(int value)
636 return get_value_string(gsm48_mmr_msg_names, value);
639 /* allocate GSM 04.08 message (MMxx-SAP) */
640 struct msgb *gsm48_mmxx_msgb_alloc(int msg_type, uint32_t ref,
641 uint8_t transaction_id)
644 struct gsm48_mmxx_hdr *mmh;
646 msg = msgb_alloc_headroom(MMXX_ALLOC_SIZE+MMXX_ALLOC_HEADROOM,
647 MMXX_ALLOC_HEADROOM, "GSM 04.08 MMxx");
651 mmh = (struct gsm48_mmxx_hdr *)msgb_put(msg, sizeof(*mmh));
652 mmh->msg_type = msg_type;
654 mmh->transaction_id = transaction_id;
659 /* allocate MM event message */
660 struct msgb *gsm48_mmevent_msgb_alloc(int msg_type)
663 struct gsm48_mm_event *mme;
665 msg = msgb_alloc_headroom(sizeof(*mme), 0, "GSM 04.08 MM event");
669 mme = (struct gsm48_mm_event *)msgb_put(msg, sizeof(*mme));
670 mme->msg_type = msg_type;
675 /* allocate MMR message */
676 struct msgb *gsm48_mmr_msgb_alloc(int msg_type)
679 struct gsm48_mmr *mmr;
681 msg = msgb_alloc_headroom(sizeof(*mmr), 0, "GSM 04.08 MMR");
685 mmr = (struct gsm48_mmr *)msgb_put(msg, sizeof(*mmr));
686 mmr->msg_type = msg_type;
691 /* queue message (MMxx-SAP) */
692 int gsm48_mmxx_upmsg(struct osmocom_ms *ms, struct msgb *msg)
694 struct gsm48_mmlayer *mm = &ms->mmlayer;
696 msgb_enqueue(&mm->mmxx_upqueue, msg);
701 /* queue message (MMR-SAP) */
702 int gsm48_mmr_downmsg(struct osmocom_ms *ms, struct msgb *msg)
704 struct gsm48_mmlayer *mm = &ms->mmlayer;
706 msgb_enqueue(&mm->mmr_downqueue, msg);
711 /* queue MM event message */
712 int gsm48_mmevent_msg(struct osmocom_ms *ms, struct msgb *msg)
714 struct gsm48_mmlayer *mm = &ms->mmlayer;
716 msgb_enqueue(&mm->event_queue, msg);
721 /* dequeue messages (MMxx-SAP) */
722 int gsm48_mmxx_dequeue(struct osmocom_ms *ms)
724 struct gsm48_mmlayer *mm = &ms->mmlayer;
726 struct gsm48_mmxx_hdr *mmh;
729 while ((msg = msgb_dequeue(&mm->mmxx_upqueue))) {
730 mmh = (struct gsm48_mmxx_hdr *) msg->data;
731 switch (mmh->msg_type & GSM48_MMXX_MASK) {
732 case GSM48_MMCC_CLASS:
733 gsm48_rcv_cc(ms, msg);
736 case GSM48_MMSS_CLASS:
737 gsm48_rcv_ss(ms, msg);
739 case GSM48_MMSMS_CLASS:
740 gsm48_rcv_sms(ms, msg);
745 work = 1; /* work done */
751 /* dequeue messages (MMR-SAP) */
752 int gsm48_mmr_dequeue(struct osmocom_ms *ms)
754 struct gsm48_mmlayer *mm = &ms->mmlayer;
756 struct gsm48_mmr *mmr;
759 while ((msg = msgb_dequeue(&mm->mmr_downqueue))) {
760 mmr = (struct gsm48_mmr *) msg->data;
761 gsm48_rcv_mmr(ms, msg);
763 work = 1; /* work done */
769 /* dequeue messages (RR-SAP) */
770 int gsm48_rr_dequeue(struct osmocom_ms *ms)
772 struct gsm48_mmlayer *mm = &ms->mmlayer;
776 while ((msg = msgb_dequeue(&mm->rr_upqueue))) {
777 /* msg is freed there */
778 gsm48_rcv_rr(ms, msg);
779 work = 1; /* work done */
785 /* dequeue MM event messages */
786 int gsm48_mmevent_dequeue(struct osmocom_ms *ms)
788 struct gsm48_mmlayer *mm = &ms->mmlayer;
789 struct gsm48_mm_event *mme;
793 while ((msg = msgb_dequeue(&mm->event_queue))) {
794 mme = (struct gsm48_mm_event *) msg->data;
795 gsm48_mm_ev(ms, mme->msg_type, msg);
797 work = 1; /* work done */
803 /* push RR header and send to RR */
804 static int gsm48_mm_to_rr(struct osmocom_ms *ms, struct msgb *msg,
805 int msg_type, uint8_t cause)
807 struct gsm48_rr_hdr *rrh;
810 msgb_push(msg, sizeof(struct gsm48_rr_hdr));
811 rrh = (struct gsm48_rr_hdr *) msg->data;
812 rrh->msg_type = msg_type;
815 /* send message to RR */
816 return gsm48_rr_downmsg(ms, msg);
823 const char *gsm48_mm_state_names[] = {
827 "location updating initiated",
829 "wait for outgoing MM connection",
830 "MM connection active",
831 "IMSI detach initiated",
832 "process CM service prompt",
833 "wait for network command",
834 "location updating reject",
837 "wait for RR connection (location updating)",
838 "wait for RR connection (MM connection)",
839 "wait for RR connection (IMSI detach)",
841 "wait for re-establishment",
842 "wait for RR connection active",
844 "wait for additional outgoing MM connection",
845 "MM_CONN_ACTIVE_VGCS",
847 "location updating pending",
848 "IMSI detach pending",
849 "RR connection release not allowed"
852 const char *gsm48_mm_substate_names[] = {
855 "attempting to update",
859 "location updating needed",
861 "PLMN search (normal)",
866 /* change state from LOCATION UPDATE NEEDED to ATTEMPTING TO UPDATE */
867 static int gsm48_mm_loc_upd_possible(struct gsm48_mmlayer *mm)
869 // TODO: check if really possible
870 new_mm_state(mm, GSM48_MM_ST_MM_IDLE, GSM48_MM_SST_ATTEMPT_UPDATE);
871 return gsm48_mm_loc_upd_normal(mm->ms, NULL);
874 /* Set new MM state, also new substate in case of MM IDLE state. */
875 static void new_mm_state(struct gsm48_mmlayer *mm, int state, int substate)
878 if (mm->state == GSM48_MM_ST_MM_IDLE && state == mm->state)
879 LOGP(DMM, LOGL_INFO, "new MM IDLE state %s -> %s\n",
880 gsm48_mm_substate_names[mm->substate],
881 gsm48_mm_substate_names[substate]);
882 /* IDLE -> non-IDLE */
883 else if (mm->state == GSM48_MM_ST_MM_IDLE)
884 LOGP(DMM, LOGL_INFO, "new state MM IDLE, %s -> %s\n",
885 gsm48_mm_substate_names[mm->substate],
886 gsm48_mm_state_names[state]);
887 /* non-IDLE -> IDLE */
888 else if (state == GSM48_MM_ST_MM_IDLE)
889 LOGP(DMM, LOGL_INFO, "new state %s -> MM IDLE, %s\n",
890 gsm48_mm_state_names[mm->state],
891 gsm48_mm_substate_names[substate]);
892 /* non-IDLE -> non-IDLE */
894 LOGP(DMM, LOGL_INFO, "new state %s -> %s\n",
895 gsm48_mm_state_names[mm->state],
896 gsm48_mm_state_names[state]);
898 /* remember most recent substate */
899 if (mm->state == GSM48_MM_ST_MM_IDLE)
900 mm->mr_substate = mm->substate;
903 mm->substate = substate;
905 /* resend detach event, if flag is set */
906 if (state == GSM48_MM_ST_MM_IDLE && mm->delay_detach) {
909 mm->delay_detach = 0;
911 nmsg = gsm48_mmevent_msgb_alloc(GSM48_MM_EVENT_IMSI_DETACH);
914 gsm48_mmevent_msg(mm->ms, nmsg);
917 /* 4.4.2 start T3212 in MM IDLE mode if not started or has expired */
918 if (state == GSM48_MM_ST_MM_IDLE
919 && (substate == GSM48_MM_SST_NORMAL_SERVICE
920 || substate == GSM48_MM_SST_ATTEMPT_UPDATE)) {
921 /* start periodic location update timer */
922 if (!bsc_timer_pending(&mm->t3212))
923 start_mm_t3212(mm, mm->t3212_value);
924 /* perform pending location update */
925 if (mm->lupd_retry) {
926 LOGP(DMM, LOGL_INFO, "Loc. upd. pending (type %d)\n",
929 gsm48_mm_loc_upd(mm->ms, NULL);
930 /* must exit, because this function can be called
935 if (mm->lupd_periodic) {
936 struct gsm48_sysinfo *s = &mm->ms->cellsel.sel_si;
938 LOGP(DMM, LOGL_INFO, "Periodic loc. upd. pending "
939 "(type %d)\n", mm->lupd_type);
940 mm->lupd_periodic = 0;
942 gsm48_mm_loc_upd_periodic(mm->ms, NULL);
944 LOGP(DMM, LOGL_INFO, "but not requred\n");
945 /* must exit, because this function can be called
952 /* check if location update is possible */
953 if (state == GSM48_MM_ST_MM_IDLE
954 && substate == GSM48_MM_SST_LOC_UPD_NEEDED) {
955 gsm48_mm_loc_upd_possible(mm);
956 /* must exit, because this function can be called recursively */
961 /* return PLMN SEARCH or PLMN SEARCH NORMAL state */
962 static int gsm48_mm_set_plmn_search(struct osmocom_ms *ms)
964 struct gsm_subscriber *subscr = &ms->subscr;
965 struct gsm322_cellsel *cs = &ms->cellsel;
967 /* SIM not inserted */
968 if (!subscr->sim_valid) {
969 LOGP(DMM, LOGL_INFO, "Selecting PLMN SEARCH state, because "
971 return GSM48_MM_SST_PLMN_SEARCH;
974 /* SIM not updated */
975 if (subscr->ustate != GSM_SIM_U1_UPDATED) {
976 LOGP(DMM, LOGL_INFO, "Selecting PLMN SEARCH state, because "
977 "SIM not updated.\n");
978 return GSM48_MM_SST_PLMN_SEARCH;
980 if (!subscr->lai_valid) {
981 LOGP(DMM, LOGL_INFO, "Selecting PLMN SEARCH state, because "
982 "LAI in SIM not valid.\n");
983 return GSM48_MM_SST_PLMN_SEARCH;
986 /* no cell selected */
988 LOGP(DMM, LOGL_INFO, "Selecting PLMN SEARCH state, because "
989 "no cell selected.\n");
990 return GSM48_MM_SST_PLMN_SEARCH;
993 /* selected cell's LAI not equal to LAI stored on the sim */
994 if (cs->sel_mcc != subscr->lai_mcc
995 || cs->sel_mnc != subscr->lai_mnc
996 || cs->sel_lac != subscr->lai_lac) {
997 LOGP(DMM, LOGL_INFO, "Selecting PLMN SEARCH state, because "
998 "LAI of selected cell (MCC %s MNC %s LAC 0x%04x) "
999 "!= LAI in SIM (MCC %s MNC %s LAC 0x%04x).\n",
1000 gsm_print_mcc(cs->sel_mcc), gsm_print_mnc(cs->sel_mnc),
1001 cs->sel_lac, gsm_print_mcc(subscr->lai_mcc),
1002 gsm_print_mnc(subscr->lai_mnc), subscr->lai_lac);
1003 return GSM48_MM_SST_PLMN_SEARCH;
1006 /* SIM is updated in this LA */
1007 LOGP(DMM, LOGL_INFO, "Selecting PLMN SEARCH NORMAL state.\n");
1008 return GSM48_MM_SST_PLMN_SEARCH_NORMAL;
1011 /* 4.2.3 when returning to MM IDLE state, this function is called */
1012 static int gsm48_mm_return_idle(struct osmocom_ms *ms, struct msgb *msg)
1014 struct gsm_subscriber *subscr = &ms->subscr;
1015 struct gsm48_mmlayer *mm = &ms->mmlayer;
1016 struct gsm322_cellsel *cs = &ms->cellsel;
1018 /* 4.4.4.9 start T3211 when RR is released */
1019 if (mm->start_t3211) {
1020 LOGP(DMM, LOGL_INFO, "Starting T3211 after RR release.\n");
1021 mm->start_t3211 = 0;
1025 /* return from location update with "Roaming not allowed" */
1026 if (mm->state == GSM48_MM_ST_LOC_UPD_REJ && mm->lupd_rej_cause == 13) {
1027 LOGP(DMM, LOGL_INFO, "Roaming not allowed as returning to "
1029 new_mm_state(mm, GSM48_MM_ST_MM_IDLE,
1030 gsm48_mm_set_plmn_search(ms));
1035 /* no SIM present or invalid */
1036 if (!subscr->sim_valid) {
1037 LOGP(DMM, LOGL_INFO, "SIM invalid as returning to MM IDLE\n");
1039 /* stop periodic location updating */
1040 mm->lupd_pending = 0;
1041 stop_mm_t3212(mm); /* 4.4.2 */
1043 new_mm_state(mm, GSM48_MM_ST_MM_IDLE, GSM48_MM_SST_NO_IMSI);
1048 /* selected cell equals the registered LAI */
1049 if (subscr->lai_valid
1050 && cs->sel_mcc == subscr->lai_mcc
1051 && cs->sel_mnc == subscr->lai_mnc
1052 && cs->sel_lac == subscr->lai_lac) {
1053 LOGP(DMM, LOGL_INFO, "We are in registered LAI as returning "
1055 /* if SIM not updated (abnormal case as described in 4.4.4.9) */
1056 if (subscr->ustate != GSM_SIM_U1_UPDATED)
1057 new_mm_state(mm, GSM48_MM_ST_MM_IDLE,
1058 GSM48_MM_SST_ATTEMPT_UPDATE);
1060 new_mm_state(mm, GSM48_MM_ST_MM_IDLE,
1061 GSM48_MM_SST_NORMAL_SERVICE);
1066 /* location update allowed */
1067 if (cs->state == GSM322_C3_CAMPED_NORMALLY) {
1068 LOGP(DMM, LOGL_INFO, "We are camping normally as returning to "
1070 new_mm_state(mm, GSM48_MM_ST_MM_IDLE,
1071 GSM48_MM_SST_LOC_UPD_NEEDED);
1072 } else { /* location update not allowed */
1073 LOGP(DMM, LOGL_INFO, "We are camping on any cell as returning "
1075 new_mm_state(mm, GSM48_MM_ST_MM_IDLE,
1076 GSM48_MM_SST_LIMITED_SERVICE);
1082 /* 4.2.1.1 Service state PLMN SEARCH (NORMAL) is left if no cell found */
1083 static int gsm48_mm_no_cell_found(struct osmocom_ms *ms, struct msgb *msg)
1085 struct gsm48_mmlayer *mm = &ms->mmlayer;
1087 new_mm_state(mm, GSM48_MM_ST_MM_IDLE, GSM48_MM_SST_NO_CELL_AVAIL);
1092 /* 4.2.1.1 Service state PLMN SEARCH (NORMAL) / NO CELL AVAILABLE is left
1095 static int gsm48_mm_cell_selected(struct osmocom_ms *ms, struct msgb *msg)
1097 struct gsm_subscriber *subscr = &ms->subscr;
1098 struct gsm48_mmlayer *mm = &ms->mmlayer;
1099 struct gsm322_plmn *plmn = &ms->plmn;
1100 struct gsm322_cellsel *cs = &ms->cellsel;
1101 struct gsm48_sysinfo *s = &cs->sel_si;
1102 struct gsm_settings *set = &ms->settings;
1104 /* no SIM is inserted */
1105 if (!subscr->sim_valid) {
1106 LOGP(DMM, LOGL_INFO, "SIM invalid as cell is selected.\n");
1107 new_mm_state(mm, GSM48_MM_ST_MM_IDLE, GSM48_MM_SST_NO_IMSI);
1112 /* SIM not updated in this LA */
1113 if (subscr->ustate == GSM_SIM_U1_UPDATED
1114 && subscr->lai_valid
1115 && cs->sel_mcc == subscr->lai_mcc
1116 && cs->sel_mnc == subscr->lai_mnc
1117 && cs->sel_lac == subscr->lai_lac
1118 && !mm->lupd_periodic) {
1119 if (subscr->imsi_attached) {
1122 LOGP(DMM, LOGL_INFO, "Valid in location area.\n");
1123 new_mm_state(mm, GSM48_MM_ST_MM_IDLE,
1124 GSM48_MM_SST_NORMAL_SERVICE);
1126 /* send message to PLMN search process */
1127 nmsg = gsm322_msgb_alloc(GSM322_EVENT_REG_SUCCESS);
1130 gsm322_plmn_sendmsg(ms, nmsg);
1134 if (!s->att_allowed) {
1137 LOGP(DMM, LOGL_INFO, "Attachment not required.\n");
1138 new_mm_state(mm, GSM48_MM_ST_MM_IDLE,
1139 GSM48_MM_SST_NORMAL_SERVICE);
1141 /* send message to PLMN search process */
1142 nmsg = gsm322_msgb_alloc(GSM322_EVENT_REG_SUCCESS);
1145 gsm322_plmn_sendmsg(ms, nmsg);
1149 /* else, continue */
1152 /* PLMN mode auto and selected cell is forbidden */
1153 if (set->plmn_mode == PLMN_MODE_AUTO
1154 && (gsm_subscr_is_forbidden_plmn(subscr, cs->sel_mcc, cs->sel_mnc)
1155 || gsm322_is_forbidden_la(ms, cs->sel_mcc, cs->sel_mnc,
1159 LOGP(DMM, LOGL_INFO, "Selected cell is forbidden.\n");
1160 new_mm_state(mm, GSM48_MM_ST_MM_IDLE,
1161 GSM48_MM_SST_LIMITED_SERVICE);
1163 /* send message to PLMN search process */
1164 nmsg = gsm322_msgb_alloc(GSM322_EVENT_ROAMING_NA);
1167 gsm322_plmn_sendmsg(ms, nmsg);
1172 /* PLMN mode manual and selected cell not selected PLMN */
1173 if (set->plmn_mode == PLMN_MODE_MANUAL
1174 && (plmn->mcc != cs->sel_mcc
1175 || plmn->mnc != cs->sel_mnc)) {
1178 LOGP(DMM, LOGL_INFO, "Selected cell not found.\n");
1179 new_mm_state(mm, GSM48_MM_ST_MM_IDLE,
1180 GSM48_MM_SST_LIMITED_SERVICE);
1182 /* send message to PLMN search process */
1183 nmsg = gsm322_msgb_alloc(GSM322_EVENT_REG_FAILED);
1186 gsm322_plmn_sendmsg(ms, nmsg);
1192 new_mm_state(mm, GSM48_MM_ST_MM_IDLE, GSM48_MM_SST_LOC_UPD_NEEDED);
1197 /* 4.2.1.2 Service state PLMN SEARCH (NORMAL) is entered */
1198 static int gsm48_mm_plmn_search(struct osmocom_ms *ms, struct msgb *msg)
1200 struct gsm48_mmlayer *mm = &ms->mmlayer;
1202 new_mm_state(mm, GSM48_MM_ST_MM_IDLE, gsm48_mm_set_plmn_search(ms));
1211 /* initialize Mobility Management process */
1212 int gsm48_mm_init(struct osmocom_ms *ms)
1214 struct gsm48_mmlayer *mm = &ms->mmlayer;
1216 memset(mm, 0, sizeof(*mm));
1219 LOGP(DMM, LOGL_INFO, "init Mobility Management process\n");
1222 mm->state = GSM48_MM_ST_MM_IDLE;
1223 mm->substate = gsm48_mm_set_plmn_search(ms);
1226 INIT_LLIST_HEAD(&mm->mm_conn);
1227 INIT_LLIST_HEAD(&mm->rr_upqueue);
1228 INIT_LLIST_HEAD(&mm->mmxx_upqueue);
1229 INIT_LLIST_HEAD(&mm->mmr_downqueue);
1230 INIT_LLIST_HEAD(&mm->event_queue);
1235 /* exit MM process */
1236 int gsm48_mm_exit(struct osmocom_ms *ms)
1238 struct gsm48_mmlayer *mm = &ms->mmlayer;
1239 struct gsm48_mm_conn *conn;
1242 LOGP(DMM, LOGL_INFO, "exit Mobility Management process\n");
1245 while (!llist_empty(&mm->mm_conn)) {
1246 conn = llist_entry(mm->mm_conn.next,
1247 struct gsm48_mm_conn, list);
1248 llist_del(&conn->list);
1251 while ((msg = msgb_dequeue(&mm->rr_upqueue)))
1253 while ((msg = msgb_dequeue(&mm->mmxx_upqueue)))
1255 while ((msg = msgb_dequeue(&mm->mmr_downqueue)))
1257 while ((msg = msgb_dequeue(&mm->event_queue)))
1273 * MM connection management
1276 static const char *gsm48_mmxx_state_names[] = {
1284 uint32_t mm_conn_new_ref = 1;
1286 /* new MM connection state */
1287 static void new_conn_state(struct gsm48_mm_conn *conn, int state)
1289 LOGP(DMM, LOGL_INFO, "(ref %d) new state %s -> %s\n", conn->ref,
1290 gsm48_mmxx_state_names[conn->state],
1291 gsm48_mmxx_state_names[state]);
1292 conn->state = state;
1295 /* find MM connection by protocol+ID */
1296 struct gsm48_mm_conn *mm_conn_by_id(struct gsm48_mmlayer *mm,
1297 uint8_t proto, uint8_t transaction_id)
1299 struct gsm48_mm_conn *conn;
1301 llist_for_each_entry(conn, &mm->mm_conn, list) {
1302 if (conn->protocol == proto &&
1303 conn->transaction_id == transaction_id)
1309 /* find MM connection by reference */
1310 struct gsm48_mm_conn *mm_conn_by_ref(struct gsm48_mmlayer *mm,
1313 struct gsm48_mm_conn *conn;
1315 llist_for_each_entry(conn, &mm->mm_conn, list) {
1316 if (conn->ref == ref)
1322 /* create MM connection instance */
1323 static struct gsm48_mm_conn* mm_conn_new(struct gsm48_mmlayer *mm,
1324 int proto, uint8_t transaction_id, uint32_t ref)
1326 struct gsm48_mm_conn *conn = talloc_zero(l23_ctx, struct gsm48_mm_conn);
1331 LOGP(DMM, LOGL_INFO, "New MM Connection (proto 0x%02x trans_id %d "
1332 "ref %d)\n", proto, transaction_id, ref);
1335 conn->state = GSM48_MMXX_ST_IDLE;
1336 conn->transaction_id = transaction_id;
1337 conn->protocol = proto;
1340 llist_add(&conn->list, &mm->mm_conn);
1345 /* destroy MM connection instance */
1346 void mm_conn_free(struct gsm48_mm_conn *conn)
1348 LOGP(DMM, LOGL_INFO, "Freeing MM Connection\n");
1350 new_conn_state(conn, GSM48_MMXX_ST_IDLE);
1352 llist_del(&conn->list);
1357 /* support function to release pending/all ongoing MM connections */
1358 static int gsm48_mm_release_mm_conn(struct osmocom_ms *ms, int abort_any,
1359 uint8_t cause, int error)
1361 struct gsm48_mmlayer *mm = &ms->mmlayer;
1362 struct gsm48_mm_conn *conn, *conn2;
1364 struct gsm48_mmxx_hdr *nmmh;
1367 LOGP(DMM, LOGL_INFO, "Release any MM Connection\n");
1369 LOGP(DMM, LOGL_INFO, "Release pending MM Connections\n");
1371 /* release MM connection(s) */
1372 llist_for_each_entry_safe(conn, conn2, &mm->mm_conn, list) {
1373 /* abort any OR the pending connection */
1374 if (abort_any || conn->state == GSM48_MMXX_ST_CONN_PEND) {
1375 /* send MMxx-REL-IND */
1377 switch(conn->protocol) {
1378 case GSM48_PDISC_CC:
1379 nmsg = gsm48_mmxx_msgb_alloc(
1380 error ? GSM48_MMCC_ERR_IND
1381 : GSM48_MMCC_REL_IND, conn->ref,
1382 conn->transaction_id);
1384 case GSM48_PDISC_NC_SS:
1385 nmsg = gsm48_mmxx_msgb_alloc(
1386 error ? GSM48_MMSS_ERR_IND
1387 : GSM48_MMSS_REL_IND, conn->ref,
1388 conn->transaction_id);
1390 case GSM48_PDISC_SMS:
1391 nmsg = gsm48_mmxx_msgb_alloc(
1392 error ? GSM48_MMSMS_ERR_IND
1393 : GSM48_MMSMS_REL_IND, conn->ref,
1394 conn->transaction_id);
1398 /* this should not happen */
1400 continue; /* skip if not of CC type */
1402 nmmh = (struct gsm48_mmxx_hdr *)nmsg->data;
1403 nmmh->cause = cause;
1404 gsm48_mmxx_upmsg(ms, nmsg);
1413 * process handlers (Common procedures)
1416 /* sending MM STATUS message */
1417 static int gsm48_mm_tx_mm_status(struct osmocom_ms *ms, uint8_t cause)
1420 struct gsm48_hdr *ngh;
1421 uint8_t *reject_cause;
1423 LOGP(DMM, LOGL_INFO, "MM STATUS (cause #%d)\n", cause);
1425 nmsg = gsm48_l3_msgb_alloc();
1428 ngh = (struct gsm48_hdr *)msgb_put(nmsg, sizeof(*ngh));
1429 reject_cause = msgb_put(nmsg, 1);
1431 ngh->proto_discr = GSM48_PDISC_MM;
1432 ngh->msg_type = GSM48_MT_MM_STATUS;
1433 *reject_cause = cause;
1435 /* push RR header and send down */
1436 return gsm48_mm_to_rr(ms, nmsg, GSM48_RR_DATA_REQ, 0);
1439 /* 4.3.1.2 sending TMSI REALLOCATION COMPLETE message */
1440 static int gsm48_mm_tx_tmsi_reall_cpl(struct osmocom_ms *ms)
1443 struct gsm48_hdr *ngh;
1445 LOGP(DMM, LOGL_INFO, "TMSI REALLOCATION COMPLETE\n");
1447 nmsg = gsm48_l3_msgb_alloc();
1450 ngh = (struct gsm48_hdr *)msgb_put(nmsg, sizeof(*ngh));
1452 ngh->proto_discr = GSM48_PDISC_MM;
1453 ngh->msg_type = GSM48_MT_MM_TMSI_REALL_COMPL;
1455 /* push RR header and send down */
1456 return gsm48_mm_to_rr(ms, nmsg, GSM48_RR_DATA_REQ, 0);
1459 /* 4.3.1 TMSI REALLOCATION COMMAND is received */
1460 static int gsm48_mm_rx_tmsi_realloc_cmd(struct osmocom_ms *ms, struct msgb *msg)
1462 struct gsm_subscriber *subscr = &ms->subscr;
1463 struct gsm48_hdr *gh = msgb_l3(msg);
1464 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
1465 struct gsm48_loc_area_id *lai = (struct gsm48_loc_area_id *) gh->data;
1466 uint8_t mi_type, *mi;
1469 if (payload_len < sizeof(struct gsm48_loc_area_id) + 2) {
1471 LOGP(DMM, LOGL_NOTICE, "Short read of TMSI REALLOCATION "
1472 "COMMAND message error.\n");
1476 gsm48_decode_lai(lai, &subscr->lai_mcc, &subscr->lai_mnc,
1479 mi = gh->data + sizeof(struct gsm48_loc_area_id);
1480 mi_type = mi[1] & GSM_MI_TYPE_MASK;
1482 case GSM_MI_TYPE_TMSI:
1483 if (payload_len + sizeof(struct gsm48_loc_area_id) < 6
1486 memcpy(&tmsi, mi+2, 4);
1487 subscr->tmsi = ntohl(tmsi);
1488 subscr->tmsi_valid = 1;
1489 LOGP(DMM, LOGL_INFO, "TMSI 0x%08x (%u) assigned.\n",
1490 subscr->tmsi, subscr->tmsi);
1491 gsm48_mm_tx_tmsi_reall_cpl(ms);
1493 case GSM_MI_TYPE_IMSI:
1494 subscr->tmsi_valid = 0;
1495 LOGP(DMM, LOGL_INFO, "TMSI removed.\n");
1496 gsm48_mm_tx_tmsi_reall_cpl(ms);
1499 LOGP(DMM, LOGL_NOTICE, "TMSI reallocation with unknown MI "
1500 "type %d.\n", mi_type);
1501 gsm48_mm_tx_mm_status(ms, GSM48_REJECT_INCORRECT_MESSAGE);
1503 return 0; /* don't store in SIM */
1507 store / remove from sim
1514 static int gsm48_mm_tx_auth_rsp(struct osmocom_ms *ms, struct msgb *msg);
1517 /* 4.3.2.2 AUTHENTICATION REQUEST is received */
1518 static int gsm48_mm_rx_auth_req(struct osmocom_ms *ms, struct msgb *msg)
1520 struct gsm_subscriber *subscr = &ms->subscr;
1521 struct gsm48_hdr *gh = msgb_l3(msg);
1522 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
1523 struct gsm48_auth_req *ar = (struct gsm48_auth_req *) gh->data;
1525 if (payload_len < sizeof(struct gsm48_auth_req)) {
1526 LOGP(DMM, LOGL_NOTICE, "Short read of AUTHENTICATION REQUEST "
1527 "message error.\n");
1531 /* SIM is not available */
1532 if (!subscr->sim_valid) {
1533 LOGP(DMM, LOGL_INFO, "AUTHENTICATION REQUEST without SIM\n");
1534 return gsm48_mm_tx_mm_status(ms,
1535 GSM48_REJECT_MSG_NOT_COMPATIBLE);
1538 LOGP(DMM, LOGL_INFO, "AUTHENTICATION REQUEST (seq %d)\n", ar->key_seq);
1540 /* key_seq and random */
1543 (..., ar->key_seq, ar->rand);
1547 struct gsm48_mm_event *nmme;
1548 nmsg = gsm48_l3_msgb_alloc();
1551 nmme = (struct gsm48_mm_event *)msgb_put(nmsg, sizeof(*nmme));
1552 *((uint32_t *)nmme->sres) = 0x12345678;
1553 gsm48_mm_tx_auth_rsp(ms, nmsg);
1557 /* wait for auth response event from SIM */
1561 /* 4.3.2.2 sending AUTHENTICATION RESPONSE */
1562 static int gsm48_mm_tx_auth_rsp(struct osmocom_ms *ms, struct msgb *msg)
1564 struct gsm48_mm_event *mme = (struct gsm48_mm_event *) msg->data;
1566 struct gsm48_hdr *ngh;
1569 LOGP(DMM, LOGL_INFO, "AUTHENTICATION RESPONSE\n");
1571 nmsg = gsm48_l3_msgb_alloc();
1574 ngh = (struct gsm48_hdr *)msgb_put(nmsg, sizeof(*ngh));
1576 ngh->proto_discr = GSM48_PDISC_MM;
1577 ngh->msg_type = GSM48_MT_MM_AUTH_RESP;
1580 sres = msgb_put(nmsg, 4);
1581 memcpy(sres, mme->sres, 4);
1583 /* push RR header and send down */
1584 return gsm48_mm_to_rr(ms, nmsg, GSM48_RR_DATA_REQ, 0);
1587 /* 4.3.2.5 AUTHENTICATION REJECT is received */
1588 static int gsm48_mm_rx_auth_rej(struct osmocom_ms *ms, struct msgb *msg)
1590 struct gsm_subscriber *subscr = &ms->subscr;
1591 struct gsm48_mmlayer *mm = &ms->mmlayer;
1593 LOGP(DMM, LOGL_INFO, "AUTHENTICATION REJECT\n");
1595 stop_mm_t3212(mm); /* 4.4.2 */
1598 subscr->sim_valid = 0;
1600 /* TMSI and LAI invalid */
1601 subscr->lai_valid = 0;
1602 subscr->tmsi_valid = 0;
1604 /* key is invalid */
1605 subscr->key_seq = 7;
1608 new_sim_ustate(subscr, GSM_SIM_U3_ROAMING_NA);
1611 sim: delete tmsi, lai
1612 sim: delete key seq number
1613 sim: set update status
1616 /* abort IMSI detach procedure */
1617 if (mm->state == GSM48_MM_ST_IMSI_DETACH_INIT) {
1619 struct gsm48_rr_hdr *nrrh;
1621 /* abort RR connection */
1622 nmsg = gsm48_rr_msgb_alloc(GSM48_RR_ABORT_REQ);
1625 nrrh = (struct gsm48_rr_hdr *) msgb_put(nmsg, sizeof(*nrrh));
1626 nrrh->cause = GSM48_RR_CAUSE_NORMAL;
1627 gsm48_rr_downmsg(ms, nmsg);
1629 /* CS process will trigger: return to MM IDLE / No SIM */
1636 /* 4.3.3.1 IDENTITY REQUEST is received */
1637 static int gsm48_mm_rx_id_req(struct osmocom_ms *ms, struct msgb *msg)
1639 struct gsm_subscriber *subscr = &ms->subscr;
1640 struct gsm48_hdr *gh = msgb_l3(msg);
1641 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
1644 if (payload_len < 1) {
1645 LOGP(DMM, LOGL_NOTICE, "Short read of IDENTITY REQUEST message "
1650 mi_type = *gh->data;
1652 /* check if request can be fulfilled */
1653 if (!subscr->sim_valid) {
1654 LOGP(DMM, LOGL_INFO, "IDENTITY REQUEST without SIM\n");
1655 return gsm48_mm_tx_mm_status(ms,
1656 GSM48_REJECT_MSG_NOT_COMPATIBLE);
1658 if (mi_type == GSM_MI_TYPE_TMSI && !subscr->tmsi_valid) {
1659 LOGP(DMM, LOGL_INFO, "IDENTITY REQUEST of TMSI, but we have no "
1661 return gsm48_mm_tx_mm_status(ms,
1662 GSM48_REJECT_MSG_NOT_COMPATIBLE);
1664 LOGP(DMM, LOGL_INFO, "IDENTITY REQUEST (mi_type %d)\n", mi_type);
1666 return gsm48_mm_tx_id_rsp(ms, mi_type);
1669 /* send IDENTITY RESPONSE message */
1670 static int gsm48_mm_tx_id_rsp(struct osmocom_ms *ms, uint8_t mi_type)
1673 struct gsm48_hdr *ngh;
1676 LOGP(DMM, LOGL_INFO, "IDENTITY RESPONSE\n");
1678 nmsg = gsm48_l3_msgb_alloc();
1681 ngh = (struct gsm48_hdr *)msgb_put(nmsg, sizeof(*ngh));
1683 ngh->proto_discr = GSM48_PDISC_MM;
1684 ngh->msg_type = GSM48_MT_MM_ID_RESP;
1687 gsm48_encode_mi(buf, nmsg, ms, mi_type);
1689 /* push RR header and send down */
1690 return gsm48_mm_to_rr(ms, nmsg, GSM48_RR_DATA_REQ, 0);
1693 /* 4.3.4.1 sending IMSI DETACH INDICATION message */
1694 static int gsm48_mm_tx_imsi_detach(struct osmocom_ms *ms, int rr_prim)
1696 struct gsm_subscriber *subscr = &ms->subscr;
1697 struct gsm_support *sup = &ms->support;
1698 struct gsm48_rrlayer *rr = &ms->rrlayer;
1700 struct gsm48_hdr *ngh;
1703 struct gsm48_classmark1 cm;
1706 LOGP(DMM, LOGL_INFO, "IMSI DETACH INDICATION\n");
1708 nmsg = gsm48_l3_msgb_alloc();
1711 ngh = (struct gsm48_hdr *)msgb_put(nmsg, sizeof(*ngh));
1713 ngh->proto_discr = GSM48_PDISC_MM;
1714 ngh->msg_type = GSM48_MT_MM_IMSI_DETACH_IND;
1717 if (rr->cd_now.arfcn >= 512 && rr->cd_now.arfcn <= 885)
1718 pwr_lev = sup->pwr_lev_1800;
1720 pwr_lev = sup->pwr_lev_900;
1721 gsm48_encode_classmark1(&cm, sup->rev_lev, sup->es_ind, sup->a5_1,
1723 msgb_v_put(nmsg, *((uint8_t *)&cm));
1725 if (subscr->tmsi_valid) /* have TMSI ? */
1726 gsm48_encode_mi(buf, nmsg, ms, GSM_MI_TYPE_TMSI);
1728 gsm48_encode_mi(buf, nmsg, ms, GSM_MI_TYPE_IMSI);
1730 /* push RR header and send down */
1731 return gsm48_mm_to_rr(ms, nmsg, rr_prim, RR_EST_CAUSE_OTHER_SDCCH);
1734 /* detach has ended */
1735 static int gsm48_mm_imsi_detach_end(struct osmocom_ms *ms, struct msgb *msg)
1737 struct gsm48_mmlayer *mm = &ms->mmlayer;
1738 struct gsm_subscriber *subscr = &ms->subscr;
1741 LOGP(DMM, LOGL_INFO, "IMSI has been detached.\n");
1743 /* stop IMSI detach timer (if running) */
1753 subscr->sim_valid = 0;
1755 /* power off when IMSI is detached */
1756 if (mm->power_off) {
1761 /* send SIM remove event to gsm322 */
1762 nmsg = gsm322_msgb_alloc(GSM322_EVENT_SIM_REMOVE);
1765 gsm322_plmn_sendmsg(ms, nmsg);
1767 /* CS process will trigger return to MM IDLE / No SIM */
1771 /* start an IMSI detach in MM IDLE */
1772 static int gsm48_mm_imsi_detach_start(struct osmocom_ms *ms, struct msgb *msg)
1774 struct gsm_subscriber *subscr = &ms->subscr;
1775 struct gsm48_mmlayer *mm = &ms->mmlayer;
1776 struct gsm48_sysinfo *s = &ms->cellsel.sel_si;
1778 /* we may silently finish IMSI detach */
1779 if (!s->att_allowed || !subscr->imsi_attached) {
1780 LOGP(DMM, LOGL_INFO, "IMSI detach not required.\n");
1782 return gsm48_mm_imsi_detach_end(ms, msg);
1784 LOGP(DMM, LOGL_INFO, "IMSI detach started (MM IDLE)\n");
1786 new_mm_state(mm, GSM48_MM_ST_WAIT_RR_CONN_IMSI_D, 0);
1788 /* establish RR and send IMSI detach */
1789 return gsm48_mm_tx_imsi_detach(ms, GSM48_RR_EST_REQ);
1792 /* IMSI detach has been sent, wait for RR release */
1793 static int gsm48_mm_imsi_detach_sent(struct osmocom_ms *ms, struct msgb *msg)
1795 struct gsm48_mmlayer *mm = &ms->mmlayer;
1797 /* start T3220 (4.3.4.1) */
1800 LOGP(DMM, LOGL_INFO, "IMSI detach started (Wait for RR release)\n");
1802 new_mm_state(mm, GSM48_MM_ST_IMSI_DETACH_INIT, 0);
1807 /* release MM connection and proceed with IMSI detach */
1808 static int gsm48_mm_imsi_detach_release(struct osmocom_ms *ms, struct msgb *msg)
1810 struct gsm_subscriber *subscr = &ms->subscr;
1811 struct gsm48_mmlayer *mm = &ms->mmlayer;
1812 struct gsm48_sysinfo *s = &ms->cellsel.sel_si;
1814 /* stop MM connection timer */
1817 /* release all connections */
1818 gsm48_mm_release_mm_conn(ms, 1, 16, 0);
1820 /* wait for release of RR */
1821 if (!s->att_allowed || !subscr->imsi_attached) {
1822 LOGP(DMM, LOGL_INFO, "IMSI detach not required.\n");
1823 new_mm_state(mm, GSM48_MM_ST_WAIT_NETWORK_CMD, 0);
1825 /* power off when IMSI is detached */
1826 if (mm->power_off) {
1834 /* send IMSI detach */
1835 gsm48_mm_tx_imsi_detach(ms, GSM48_RR_DATA_REQ);
1837 /* go to sent state */
1838 return gsm48_mm_imsi_detach_sent(ms, msg);
1841 /* ignore ongoing IMSI detach */
1842 static int gsm48_mm_imsi_detach_ignore(struct osmocom_ms *ms, struct msgb *msg)
1847 /* delay until state change (and then retry) */
1848 static int gsm48_mm_imsi_detach_delay(struct osmocom_ms *ms, struct msgb *msg)
1850 struct gsm48_mmlayer *mm = &ms->mmlayer;
1852 LOGP(DMM, LOGL_INFO, "IMSI detach delayed.\n");
1854 /* remember to detach later */
1855 mm->delay_detach = 1;
1860 /* 4.3.5.2 ABORT is received */
1861 static int gsm48_mm_rx_abort(struct osmocom_ms *ms, struct msgb *msg)
1863 struct gsm48_mmlayer *mm = &ms->mmlayer;
1864 struct gsm_subscriber *subscr = &ms->subscr;
1865 struct gsm48_hdr *gh = msgb_l3(msg);
1866 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
1867 uint8_t reject_cause;
1869 if (payload_len < 1) {
1870 LOGP(DMM, LOGL_NOTICE, "Short read of ABORT message error.\n");
1874 reject_cause = *gh->data;
1876 if (llist_empty(&mm->mm_conn)) {
1877 LOGP(DMM, LOGL_NOTICE, "ABORT (cause #%d) while no MM "
1878 "connection is established.\n", reject_cause);
1879 return gsm48_mm_tx_mm_status(ms,
1880 GSM48_REJECT_MSG_NOT_COMPATIBLE);
1882 LOGP(DMM, LOGL_NOTICE, "ABORT (cause #%d) while MM connection "
1883 "is established.\n", reject_cause);
1884 /* stop MM connection timer */
1887 gsm48_mm_release_mm_conn(ms, 1, 16, 0);
1890 if (reject_cause == GSM48_REJECT_ILLEGAL_ME) {
1892 subscr->sim_valid = 0;
1894 /* TMSI and LAI invalid */
1895 subscr->lai_valid = 0;
1896 subscr->tmsi_valid = 0;
1898 /* key is invalid */
1899 subscr->key_seq = 7;
1902 new_sim_ustate(subscr, GSM_SIM_U3_ROAMING_NA);
1905 sim: delete tmsi, lai
1906 sim: delete key seq number
1907 sim: apply update state
1910 /* CS process will trigger: return to MM IDLE / No SIM */
1917 /* 4.3.6.2 MM INFORMATION is received */
1918 static int gsm48_mm_rx_info(struct osmocom_ms *ms, struct msgb *msg)
1920 struct gsm48_mmlayer *mm = &ms->mmlayer;
1921 struct gsm48_hdr *gh = msgb_l3(msg);
1922 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
1923 struct tlv_parsed tp;
1925 if (payload_len < 0) {
1926 LOGP(DMM, LOGL_NOTICE, "Short read of MM INFORMATION message "
1930 tlv_parse(&tp, &gsm48_mm_att_tlvdef, gh->data, payload_len, 0, 0);
1933 if (TLVP_PRESENT(&tp, GSM48_IE_NAME_LONG)) {
1934 decode_network_name(mm->name_long, sizeof(mm->name_long),
1935 TLVP_VAL(&tp, GSM48_IE_NAME_LONG)-1);
1938 if (TLVP_PRESENT(&tp, GSM48_IE_NAME_SHORT)) {
1939 decode_network_name(mm->name_short, sizeof(mm->name_short),
1940 TLVP_VAL(&tp, GSM48_IE_NAME_SHORT)-1);
1947 * process handlers for Location Update + IMSI attach (MM specific procedures)
1950 /* 4.4.2 received sysinfo change event */
1951 static int gsm48_mm_sysinfo(struct osmocom_ms *ms, struct msgb *msg)
1953 struct gsm48_mmlayer *mm = &ms->mmlayer;
1954 struct gsm48_sysinfo *s = &ms->cellsel.sel_si;
1956 /* t3212 not changed in these states */
1957 if (mm->state == GSM48_MM_ST_MM_IDLE
1958 && (mm->substate == GSM48_MM_SST_NO_CELL_AVAIL
1959 || mm->substate == GSM48_MM_SST_LIMITED_SERVICE
1960 || mm->substate == GSM48_MM_SST_PLMN_SEARCH
1961 || mm->substate == GSM48_MM_SST_PLMN_SEARCH_NORMAL))
1964 /* new periodic location update timer timeout */
1965 if (s->t3212 && s->t3212 != mm->t3212_value) {
1966 if (bsc_timer_pending(&mm->t3212)) {
1968 struct timeval current_time;
1971 gettimeofday(¤t_time, NULL);
1972 t = mm->t3212.timeout.tv_sec - current_time.tv_sec;
1975 LOGP(DMM, LOGL_INFO, "New T3212 while timer is running "
1976 "(value %d rest %d)\n", s->t3212, t);
1978 /* rest time modulo given value */
1979 mm->t3212.timeout.tv_sec = current_time.tv_sec
1982 uint32_t rand = random();
1984 LOGP(DMM, LOGL_INFO, "New T3212 while timer is not "
1985 "running (value %d)\n", s->t3212);
1987 /* value between 0 and given value */
1988 start_mm_t3212(mm, rand % (s->t3212 + 1));
1990 mm->t3212_value = s->t3212;
1996 /* 4.4.4.1 (re)start location update
1998 * this function is called by
1999 * - normal location update
2000 * - periodic location update
2001 * - imsi attach (normal loc. upd. function)
2002 * - retry timers (T3211 and T3213)
2004 static int gsm48_mm_loc_upd(struct osmocom_ms *ms, struct msgb *msg)
2006 struct gsm48_mmlayer *mm = &ms->mmlayer;
2007 struct gsm322_cellsel *cs = &ms->cellsel;
2008 struct gsm48_sysinfo *s = &cs->sel_si;
2009 struct gsm_subscriber *subscr = &ms->subscr;
2013 /* (re)start only if we still require location update */
2014 if (!mm->lupd_pending) {
2015 LOGP(DMM, LOGL_INFO, "No loc. upd. pending.\n");
2019 /* must camp normally */
2020 if (cs->state != GSM322_C3_CAMPED_NORMALLY) {
2021 LOGP(DMM, LOGL_INFO, "Loc. upd. not camping normally.\n");
2022 msg_type = GSM322_EVENT_REG_FAILED;
2024 LOGP(DSUM, LOGL_INFO, "Location update not possible\n");
2025 mm->lupd_pending = 0;
2026 /* send message to PLMN search process */
2027 nmsg = gsm322_msgb_alloc(msg_type);
2030 gsm322_plmn_sendmsg(ms, nmsg);
2034 /* if LAI is forbidden, don't start */
2035 if (gsm_subscr_is_forbidden_plmn(subscr, cs->sel_mcc, cs->sel_mnc)) {
2036 LOGP(DMM, LOGL_INFO, "Loc. upd. not allowed PLMN.\n");
2037 msg_type = GSM322_EVENT_ROAMING_NA;
2040 if (gsm322_is_forbidden_la(ms, cs->sel_mcc,
2041 cs->sel_mnc, cs->sel_lac)) {
2042 LOGP(DMM, LOGL_INFO, "Loc. upd. not allowed LA.\n");
2043 msg_type = GSM322_EVENT_ROAMING_NA;
2047 /* 4.4.4.9 if cell is barred, don't start */
2048 if ((!subscr->acc_barr && s->cell_barr)
2049 || (!subscr->acc_barr && !((subscr->acc_class & 0xfbff) &
2050 (s->class_barr ^ 0xffff)))) {
2051 LOGP(DMM, LOGL_INFO, "Loc. upd. no access.\n");
2052 msg_type = GSM322_EVENT_ROAMING_NA;
2056 mm->lupd_mcc = cs->sel_mcc;
2057 mm->lupd_mnc = cs->sel_mnc;
2058 mm->lupd_lac = cs->sel_lac;
2060 LOGP(DSUM, LOGL_INFO, "Perform location update (MCC %s, MNC %s "
2061 "LAC 0x%04x)\n", gsm_print_mcc(mm->lupd_mcc),
2062 gsm_print_mnc(mm->lupd_mnc), mm->lupd_lac);
2064 return gsm48_mm_tx_loc_upd_req(ms);
2067 /* initiate a normal location update / imsi attach */
2068 static int gsm48_mm_loc_upd_normal(struct osmocom_ms *ms, struct msgb *msg)
2070 struct gsm48_mmlayer *mm = &ms->mmlayer;
2071 struct gsm_subscriber *subscr = &ms->subscr;
2072 struct gsm322_cellsel *cs = &ms->cellsel;
2073 struct gsm48_sysinfo *s = &cs->sel_si;
2076 /* in case we already have a location update going on */
2077 if (mm->lupd_pending) {
2078 LOGP(DMM, LOGL_INFO, "Loc. upd. already pending.\n");
2083 /* no location update, if limited service */
2084 if (cs->state != GSM322_C3_CAMPED_NORMALLY) {
2085 LOGP(DMM, LOGL_INFO, "Loc. upd. not allowed.\n");
2087 /* send message to PLMN search process */
2088 nmsg = gsm322_msgb_alloc(GSM322_EVENT_REG_FAILED);
2091 gsm322_plmn_sendmsg(ms, nmsg);
2096 /* if location update is not required */
2097 if (subscr->ustate == GSM_SIM_U1_UPDATED
2099 && cs->sel_mcc == subscr->lai_mcc
2100 && cs->sel_mnc == subscr->lai_mnc
2101 && cs->sel_lac == subscr->lai_lac
2102 && (subscr->imsi_attached
2103 || !s->att_allowed)) {
2104 LOGP(DMM, LOGL_INFO, "Loc. upd. not required.\n");
2105 subscr->imsi_attached = 1;
2107 /* send message to PLMN search process */
2108 nmsg = gsm322_msgb_alloc(GSM322_EVENT_REG_SUCCESS);
2111 gsm322_plmn_sendmsg(ms, nmsg);
2116 /* 4.4.3 is attachment required? */
2117 if (subscr->ustate == GSM_SIM_U1_UPDATED
2119 && cs->sel_mcc == subscr->lai_mcc
2120 && cs->sel_mnc == subscr->lai_mnc
2121 && cs->sel_lac == subscr->lai_lac
2122 && !subscr->imsi_attached
2123 && s->att_allowed) {
2124 /* do location update for IMSI attach */
2125 LOGP(DMM, LOGL_INFO, "Do Loc. upd. for IMSI attach.\n");
2128 /* do normal location update */
2129 LOGP(DMM, LOGL_INFO, "Do normal Loc. upd.\n");
2133 /* start location update */
2134 mm->lupd_attempt = 0;
2135 mm->lupd_pending = 1;
2136 mm->lupd_ra_failure = 0;
2138 return gsm48_mm_loc_upd(ms, msg);
2141 /* initiate a periodic location update */
2142 static int gsm48_mm_loc_upd_periodic(struct osmocom_ms *ms, struct msgb *msg)
2144 struct gsm48_mmlayer *mm = &ms->mmlayer;
2146 /* in case we already have a location update going on */
2147 if (mm->lupd_pending) {
2148 LOGP(DMM, LOGL_INFO, "Loc. upd. already pending.\n");
2152 /* start periodic location update */
2154 mm->lupd_pending = 1;
2155 mm->lupd_ra_failure = 0;
2157 return gsm48_mm_loc_upd(ms, msg);
2160 /* ignore location update */
2161 static int gsm48_mm_loc_upd_ignore(struct osmocom_ms *ms, struct msgb *msg)
2166 /* 9.2.15 send LOCATION UPDATING REQUEST message */
2167 static int gsm48_mm_tx_loc_upd_req(struct osmocom_ms *ms)
2169 struct gsm48_mmlayer *mm = &ms->mmlayer;
2170 struct gsm_support *sup = &ms->support;
2171 struct gsm_subscriber *subscr = &ms->subscr;
2172 struct gsm48_rrlayer *rr = &ms->rrlayer;
2174 struct gsm48_hdr *ngh;
2175 struct gsm48_loc_upd_req *nlu; /* NOTE: mi_len is part of struct */
2179 LOGP(DMM, LOGL_INFO, "LOCATION UPDATING REQUEST\n");
2181 nmsg = gsm48_l3_msgb_alloc();
2184 ngh = (struct gsm48_hdr *)msgb_put(nmsg, sizeof(*ngh));
2185 nlu = (struct gsm48_loc_upd_req *)msgb_put(nmsg, sizeof(*nlu));
2187 ngh->proto_discr = GSM48_PDISC_MM;
2188 ngh->msg_type = GSM48_MT_MM_LOC_UPD_REQUEST;
2190 /* location updating type */
2191 nlu->type = mm->lupd_type;
2193 nlu->key_seq = subscr->key_seq;
2194 /* LAI (use last SIM stored LAI) */
2195 gsm48_generate_lai(&nlu->lai,
2196 subscr->lai_mcc, subscr->lai_mnc, subscr->lai_lac);
2198 if (rr->cd_now.arfcn >= 512 && rr->cd_now.arfcn <= 885)
2199 pwr_lev = sup->pwr_lev_1800;
2201 pwr_lev = sup->pwr_lev_900;
2202 gsm48_encode_classmark1(&nlu->classmark1, sup->rev_lev, sup->es_ind,
2203 sup->a5_1, pwr_lev);
2205 if (subscr->tmsi_valid) /* have TMSI ? */
2206 gsm48_encode_mi(buf, NULL, ms, GSM_MI_TYPE_TMSI);
2208 gsm48_encode_mi(buf, NULL, ms, GSM_MI_TYPE_IMSI);
2209 msgb_put(nmsg, buf[1]); /* length is part of nlu */
2210 memcpy(&nlu->mi_len, buf + 1, 1 + buf[1]);
2212 new_mm_state(mm, GSM48_MM_ST_WAIT_RR_CONN_LUPD, 0);
2214 /* push RR header and send down */
2215 return gsm48_mm_to_rr(ms, nmsg, GSM48_RR_EST_REQ, RR_EST_CAUSE_LOC_UPD);
2218 /* 4.4.4.1 RR is esablised during location update */
2219 static int gsm48_mm_est_loc_upd(struct osmocom_ms *ms, struct msgb *msg)
2221 struct gsm48_mmlayer *mm = &ms->mmlayer;
2223 /* start location update timer */
2226 new_mm_state(mm, GSM48_MM_ST_LOC_UPD_INIT, 0);
2231 /* 4.4.4.6 LOCATION UPDATING ACCEPT is received */
2232 static int gsm48_mm_rx_loc_upd_acc(struct osmocom_ms *ms, struct msgb *msg)
2234 struct gsm48_mmlayer *mm = &ms->mmlayer;
2235 struct gsm_subscriber *subscr = &ms->subscr;
2236 struct gsm48_hdr *gh = msgb_l3(msg);
2237 struct gsm48_loc_area_id *lai = (struct gsm48_loc_area_id *) gh->data;
2238 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2239 struct tlv_parsed tp;
2242 if (payload_len < sizeof(struct gsm48_loc_area_id)) {
2244 LOGP(DMM, LOGL_NOTICE, "Short read of LOCATION UPDATING ACCEPT "
2245 "message error.\n");
2248 tlv_parse(&tp, &gsm48_mm_att_tlvdef,
2249 gh->data + sizeof(struct gsm48_loc_area_id),
2250 payload_len - sizeof(struct gsm48_loc_area_id), 0, 0);
2252 /* update has finished */
2253 mm->lupd_pending = 0;
2255 /* RA was successfull */
2256 mm->lupd_ra_failure = 0;
2258 /* stop periodic location updating timer */
2259 stop_mm_t3212(mm); /* 4.4.2 */
2262 subscr->lai_valid = 1;
2263 gsm48_decode_lai(lai, &subscr->lai_mcc, &subscr->lai_mnc,
2266 /* stop location update timer */
2269 /* reset attempt counter */
2270 mm->lupd_attempt = 0;
2272 /* mark SIM as attached */
2273 subscr->imsi_attached = 1;
2275 /* set the status in the sim to updated */
2276 new_sim_ustate(subscr, GSM_SIM_U1_UPDATED);
2278 sim: apply update state
2281 /* set last registered PLMN */
2282 subscr->plmn_valid = 1;
2283 subscr->plmn_mcc = subscr->lai_mcc;
2284 subscr->plmn_mnc = subscr->lai_mnc;
2289 LOGP(DSUM, LOGL_INFO, "Location update accepted\n");
2290 LOGP(DMM, LOGL_INFO, "LOCATION UPDATING ACCEPT (mcc %s mnc %s "
2291 "lac 0x%04x)\n", gsm_print_mcc(subscr->lai_mcc),
2292 gsm_print_mnc(subscr->lai_mnc), subscr->lai_lac);
2294 /* remove LA from forbidden list */
2295 gsm322_del_forbidden_la(ms, subscr->lai_mcc, subscr->lai_mnc,
2299 if (TLVP_PRESENT(&tp, GSM48_IE_MOBILE_ID)) {
2304 mi = TLVP_VAL(&tp, GSM48_IE_MOBILE_ID)-1;
2307 mi_type = mi[1] & GSM_MI_TYPE_MASK;
2309 case GSM_MI_TYPE_TMSI:
2310 if (payload_len + sizeof(struct gsm48_loc_area_id) < 6
2313 memcpy(&tmsi, mi+2, 4);
2314 subscr->tmsi = ntohl(tmsi);
2315 subscr->tmsi_valid = 1;
2316 LOGP(DMM, LOGL_INFO, "got TMSI 0x%08x (%u)\n",
2317 subscr->tmsi, subscr->tmsi);
2322 case GSM_MI_TYPE_IMSI:
2323 LOGP(DMM, LOGL_INFO, "TMSI removed\n");
2324 subscr->tmsi_valid = 0;
2328 /* send TMSI REALLOCATION COMPLETE */
2329 gsm48_mm_tx_tmsi_reall_cpl(ms);
2332 LOGP(DMM, LOGL_NOTICE, "TMSI reallocation with unknown "
2333 "MI type %d.\n", mi_type);
2337 /* send message to PLMN search process */
2338 nmsg = gsm322_msgb_alloc(GSM322_EVENT_REG_SUCCESS);
2341 gsm322_plmn_sendmsg(ms, nmsg);
2343 /* follow on proceed */
2344 if (TLVP_PRESENT(&tp, GSM48_IE_MOBILE_ID))
2345 LOGP(DMM, LOGL_NOTICE, "follow-on proceed not supported.\n");
2347 /* start RR release timer */
2350 new_mm_state(mm, GSM48_MM_ST_WAIT_NETWORK_CMD, 0);
2355 /* 4.4.4.7 LOCATION UPDATING REJECT is received */
2356 static int gsm48_mm_rx_loc_upd_rej(struct osmocom_ms *ms, struct msgb *msg)
2358 struct gsm48_mmlayer *mm = &ms->mmlayer;
2359 struct gsm48_hdr *gh = msgb_l3(msg);
2360 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2362 if (payload_len < 1) {
2363 LOGP(DMM, LOGL_NOTICE, "Short read of LOCATION UPDATING REJECT "
2364 "message error.\n");
2368 /* RA was successfull */
2369 mm->lupd_ra_failure = 0;
2371 /* stop periodic location updating timer */
2372 stop_mm_t3212(mm); /* 4.4.2 */
2374 /* stop location update timer */
2377 /* store until RR is released */
2378 mm->lupd_rej_cause = *gh->data;
2380 /* start RR release timer */
2383 new_mm_state(mm, GSM48_MM_ST_LOC_UPD_REJ, 0);
2388 /* 4.4.4.7 RR is released after location update reject */
2389 static int gsm48_mm_rel_loc_upd_rej(struct osmocom_ms *ms, struct msgb *msg)
2391 struct gsm48_mmlayer *mm = &ms->mmlayer;
2392 struct gsm_subscriber *subscr = &ms->subscr;
2394 struct gsm322_msg *ngm;
2396 LOGP(DMM, LOGL_INFO, "Loc. upd. rejected (cause %d)\n",
2397 mm->lupd_rej_cause);
2400 switch (mm->lupd_rej_cause) {
2401 case GSM48_REJECT_IMSI_UNKNOWN_IN_HLR:
2402 case GSM48_REJECT_ILLEGAL_MS:
2403 case GSM48_REJECT_ILLEGAL_ME:
2404 /* reset attempt counter */
2405 mm->lupd_attempt = 0;
2408 subscr->sim_valid = 0;
2411 case GSM48_REJECT_PLMN_NOT_ALLOWED:
2412 case GSM48_REJECT_LOC_NOT_ALLOWED:
2413 case GSM48_REJECT_ROAMING_NOT_ALLOWED:
2414 /* TMSI and LAI invalid */
2415 subscr->lai_valid = 0;
2416 subscr->tmsi_valid = 0;
2418 /* key is invalid */
2419 subscr->key_seq = 7;
2422 new_sim_ustate(subscr, GSM_SIM_U3_ROAMING_NA);
2424 sim: delete tmsi, lai
2425 sim: delete key seq number
2426 sim: apply update state
2428 /* update has finished */
2429 mm->lupd_pending = 0;
2432 /* send event to PLMN search process */
2433 switch(mm->lupd_rej_cause) {
2434 case GSM48_REJECT_ROAMING_NOT_ALLOWED:
2435 nmsg = gsm322_msgb_alloc(GSM322_EVENT_ROAMING_NA);
2437 case GSM48_REJECT_IMSI_UNKNOWN_IN_HLR:
2438 case GSM48_REJECT_ILLEGAL_MS:
2439 case GSM48_REJECT_ILLEGAL_ME:
2440 nmsg = gsm322_msgb_alloc(GSM322_EVENT_INVALID_SIM);
2443 nmsg = gsm322_msgb_alloc(GSM322_EVENT_REG_FAILED);
2447 ngm = (struct gsm322_msg *)nmsg->data;
2448 ngm->reject = mm->lupd_rej_cause;
2449 gsm322_plmn_sendmsg(ms, nmsg);
2451 /* forbidden list */
2452 switch (mm->lupd_rej_cause) {
2453 case GSM48_REJECT_IMSI_UNKNOWN_IN_HLR:
2454 LOGP(DSUM, LOGL_INFO, "Location update failed (IMSI unknown "
2457 case GSM48_REJECT_ILLEGAL_MS:
2458 LOGP(DSUM, LOGL_INFO, "Location update failed (Illegal MS)\n");
2460 case GSM48_REJECT_ILLEGAL_ME:
2461 LOGP(DSUM, LOGL_INFO, "Location update failed (Illegal ME)\n");
2463 case GSM48_REJECT_PLMN_NOT_ALLOWED:
2464 gsm_subscr_add_forbidden_plmn(subscr, mm->lupd_mcc,
2465 mm->lupd_mnc, mm->lupd_rej_cause);
2466 LOGP(DSUM, LOGL_INFO, "Location update failed (PLMN not "
2469 case GSM48_REJECT_LOC_NOT_ALLOWED:
2470 case GSM48_REJECT_ROAMING_NOT_ALLOWED:
2471 gsm322_add_forbidden_la(ms, mm->lupd_mcc, mm->lupd_mnc,
2472 mm->lupd_lac, mm->lupd_rej_cause);
2473 LOGP(DSUM, LOGL_INFO, "Location update failed (LAI not "
2477 /* 4.4.4.9 continue with failure handling */
2478 return gsm48_mm_loc_upd_failed(ms, NULL);
2481 /* CS proc triggers: return to IDLE, case 13 is also handled there */
2485 /* 4.2.2 delay a location update */
2486 static int gsm48_mm_loc_upd_delay_per(struct osmocom_ms *ms, struct msgb *msg)
2488 struct gsm48_mmlayer *mm = &ms->mmlayer;
2490 LOGP(DMM, LOGL_INFO, "Schedule a pending periodic loc. upd.\n");
2491 mm->lupd_periodic = 1;
2496 /* delay a location update retry */
2497 static int gsm48_mm_loc_upd_delay_retry(struct osmocom_ms *ms, struct msgb *msg)
2499 struct gsm48_mmlayer *mm = &ms->mmlayer;
2501 LOGP(DMM, LOGL_INFO, "Schedule a pending periodic loc. upd.\n");
2507 /* process failues as described in the lower part of 4.4.4.9 */
2508 static int gsm48_mm_loc_upd_failed(struct osmocom_ms *ms, struct msgb *msg)
2510 struct gsm48_mmlayer *mm = &ms->mmlayer;
2511 struct gsm_subscriber *subscr = &ms->subscr;
2513 LOGP(DSUM, LOGL_INFO, "Location update failed\n");
2515 /* stop location update timer, if running */
2518 if (subscr->ustate == GSM_SIM_U1_UPDATED
2519 && mm->lupd_mcc == subscr->lai_mcc
2520 && mm->lupd_mnc == subscr->lai_mnc
2521 && mm->lupd_lac == subscr->lai_lac) {
2522 if (mm->lupd_attempt < 4) {
2523 LOGP(DSUM, LOGL_INFO, "Try location update later\n");
2524 LOGP(DMM, LOGL_INFO, "Loc. upd. failed, retry #%d\n",
2527 /* start update retry timer */
2530 /* CS process will trigger: return to MM IDLE */
2533 LOGP(DMM, LOGL_INFO, "Loc. upd. failed too often.\n");
2536 /* TMSI and LAI invalid */
2537 subscr->lai_valid = 0;
2538 subscr->tmsi_valid = 0;
2540 /* key is invalid */
2541 subscr->key_seq = 7;
2544 new_sim_ustate(subscr, GSM_SIM_U2_NOT_UPDATED);
2547 sim: delete tmsi, lai
2548 sim: delete key seq number
2549 sim: set update status
2552 /* start update retry timer (RR connection is released) */
2553 if (mm->lupd_attempt < 4) {
2554 mm->start_t3211 = 1;
2555 LOGP(DSUM, LOGL_INFO, "Try location update later\n");
2558 /* CS process will trigger: return to MM IDLE */
2562 /* abort a location update due to radio failure or release */
2563 static int gsm48_mm_rel_loc_upd_abort(struct osmocom_ms *ms, struct msgb *msg)
2565 struct gsm48_mmlayer *mm = &ms->mmlayer;
2566 struct gsm48_rr_hdr *rrh = (struct gsm48_rr_hdr *)msg->data;
2568 if (rrh->msg_type == GSM48_RR_REL_IND) {
2569 LOGP(DMM, LOGL_INFO, "RR link released after loc. upd.\n");
2571 /* continue with failure handling */
2572 return gsm48_mm_loc_upd_failed(ms, NULL);
2575 LOGP(DMM, LOGL_INFO, "Loc. upd. aborted by radio (cause #%d)\n",
2578 /* random access failure, but not two successive failures */
2579 if (rrh->cause == RR_REL_CAUSE_RA_FAILURE && !mm->lupd_ra_failure) {
2580 mm->lupd_ra_failure = 1;
2582 /* start RA failure timer */
2588 /* RA was successfull or sent twice */
2589 mm->lupd_ra_failure = 0;
2591 /* continue with failure handling */
2592 return gsm48_mm_loc_upd_failed(ms, NULL);
2595 /* location update has timed out */
2596 static int gsm48_mm_loc_upd_timeout(struct osmocom_ms *ms, struct msgb *msg)
2599 struct gsm48_rr_hdr *nrrh;
2601 /* abort RR connection */
2602 nmsg = gsm48_rr_msgb_alloc(GSM48_RR_ABORT_REQ);
2605 nrrh = (struct gsm48_rr_hdr *) msgb_put(nmsg, sizeof(*nrrh));
2606 nrrh->cause = GSM48_RR_CAUSE_ABNORMAL_TIMER;
2607 gsm48_rr_downmsg(ms, nmsg);
2609 /* continue with failure handling */
2610 return gsm48_mm_loc_upd_failed(ms, NULL);
2614 * process handlers for MM connections
2617 /* cm reestablish request message from upper layer */
2618 static int gsm48_mm_tx_cm_serv_req(struct osmocom_ms *ms, int rr_prim,
2619 uint8_t cause, uint8_t cm_serv)
2621 struct gsm_subscriber *subscr = &ms->subscr;
2622 struct gsm_settings *settings = &ms->settings;
2624 struct gsm48_hdr *ngh;
2625 struct gsm48_service_request *nsr; /* NOTE: includes MI length */
2629 LOGP(DMM, LOGL_INFO, "CM SERVICE REQUEST (cause %d)\n", cause);
2631 nmsg = gsm48_l3_msgb_alloc();
2634 ngh = (struct gsm48_hdr *)msgb_put(nmsg, sizeof(*ngh));
2635 nsr = (struct gsm48_service_request *)msgb_put(nmsg, sizeof(*nsr));
2636 cm2lv = (uint8_t *)&nsr->classmark;
2638 ngh->proto_discr = GSM48_PDISC_MM;
2639 ngh->msg_type = GSM48_MT_MM_CM_SERV_REQ;
2642 nsr->cm_service_type = cm_serv;
2643 nsr->cipher_key_seq = subscr->key_seq;
2645 cm2lv[0] = sizeof(struct gsm48_classmark2);
2646 gsm48_rr_enc_cm2(ms, (struct gsm48_classmark2 *)(cm2lv + 1));
2648 if (!subscr->sim_valid) { /* have no SIM ? */
2649 if (settings->emergency_imsi[0])
2650 gsm48_generate_mid_from_imsi(buf,
2651 settings->emergency_imsi);
2653 gsm48_encode_mi(buf, NULL, ms, GSM_MI_TYPE_IMEI);
2654 } else if (subscr->tmsi_valid) /* have TMSI ? */
2655 gsm48_encode_mi(buf, NULL, ms, GSM_MI_TYPE_TMSI);
2657 gsm48_encode_mi(buf, NULL, ms, GSM_MI_TYPE_IMSI);
2658 msgb_put(nmsg, buf[1]); /* length is part of nsr */
2659 memcpy(&nsr->mi_len, buf + 1, 1 + buf[1]);
2660 /* prio is optional for eMLPP */
2662 /* push RR header and send down */
2663 return gsm48_mm_to_rr(ms, nmsg, rr_prim, cause);
2666 /* cm service abort message from upper layer */
2667 static int gsm48_mm_tx_cm_service_abort(struct osmocom_ms *ms)
2670 struct gsm48_hdr *ngh;
2672 LOGP(DMM, LOGL_INFO, "CM SERVICE ABORT\n");
2674 nmsg = gsm48_l3_msgb_alloc();
2677 ngh = (struct gsm48_hdr *)msgb_put(nmsg, sizeof(*ngh));
2679 ngh->proto_discr = GSM48_PDISC_MM;
2680 ngh->msg_type = GSM48_MT_MM_CM_SERV_ABORT;
2682 /* push RR header and send down */
2683 return gsm48_mm_to_rr(ms, nmsg, GSM48_RR_DATA_REQ, 0);
2686 /* cm service acknowledge is received from lower layer */
2687 static int gsm48_mm_rx_cm_service_acc(struct osmocom_ms *ms, struct msgb *msg)
2689 struct gsm48_mmlayer *mm = &ms->mmlayer;
2691 /* stop MM connection timer */
2694 new_mm_state(mm, GSM48_MM_ST_MM_CONN_ACTIVE, 0);
2696 return gsm48_mm_conn_go_dedic(ms);
2699 /* 9.2.6 CM SERVICE REJECT message received */
2700 static int gsm48_mm_rx_cm_service_rej(struct osmocom_ms *ms, struct msgb *msg)
2702 struct gsm48_mmlayer *mm = &ms->mmlayer;
2703 struct gsm_subscriber *subscr = &ms->subscr;
2704 struct gsm48_hdr *gh = msgb_l3(msg);
2705 unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
2706 uint8_t abort_any = 0;
2707 uint8_t reject_cause;
2709 if (payload_len < 1) {
2710 LOGP(DMM, LOGL_NOTICE, "Short read of cm service reject "
2711 "message error.\n");
2716 reject_cause = *gh->data;
2718 LOGP(DMM, LOGL_INFO, "CM SERVICE REJECT (cause %d)\n", reject_cause);
2720 /* stop MM connection timer */
2723 /* selection action on cause value */
2724 switch (reject_cause) {
2725 case GSM48_REJECT_IMSI_UNKNOWN_IN_VLR:
2726 case GSM48_REJECT_ILLEGAL_ME:
2729 /* TMSI and LAI invalid */
2730 subscr->lai_valid = 0;
2731 subscr->tmsi_valid = 0;
2733 /* key is invalid */
2734 subscr->key_seq = 7;
2737 new_sim_ustate(subscr, GSM_SIM_U2_NOT_UPDATED);
2740 sim: delete tmsi, lai
2741 sim: delete key seq number
2742 sim: set update status
2745 /* change to WAIT_NETWORK_CMD state impied by abort_any == 1 */
2747 if (reject_cause == GSM48_REJECT_ILLEGAL_ME)
2748 subscr->sim_valid = 0;
2752 /* state implied by the number of remaining connections */
2756 /* release MM connection(s) */
2757 gsm48_mm_release_mm_conn(ms, abort_any, 16, 0);
2759 /* state depends on the existance of remaining MM connections */
2760 if (llist_empty(&mm->mm_conn))
2761 new_mm_state(mm, GSM48_MM_ST_WAIT_NETWORK_CMD, 0);
2763 new_mm_state(mm, GSM48_MM_ST_MM_CONN_ACTIVE, 0);
2768 /* initiate an MM connection 4.5.1.1
2770 * this function is called when:
2771 * - no RR connection exists
2772 * - an RR connection exists, but this is the first MM connection
2773 * - an RR connection exists, and there are already MM connection(s)
2775 static int gsm48_mm_init_mm(struct osmocom_ms *ms, struct msgb *msg,
2778 struct gsm48_mmlayer *mm = &ms->mmlayer;
2779 struct gsm_subscriber *subscr = &ms->subscr;
2780 struct gsm48_mmxx_hdr *mmh = (struct gsm48_mmxx_hdr *)msg->data;
2781 int msg_type = mmh->msg_type;
2783 uint8_t cause = 0, cm_serv = 0, proto = 0;
2785 struct gsm48_mmxx_hdr *nmmh;
2786 struct gsm48_mm_conn *conn, *conn_found = NULL;
2788 /* reset loc. upd. counter on CM service request */
2789 mm->lupd_attempt = 0;
2791 /* find if there is already a pending connection */
2792 llist_for_each_entry(conn, &mm->mm_conn, list) {
2793 if (conn->state == GSM48_MMXX_ST_CONN_PEND) {
2799 /* if pending connection */
2801 LOGP(DMM, LOGL_INFO, "Init MM Connection, but already have "
2802 "pending MM Connection.\n");
2807 case GSM48_MMCC_EST_REQ:
2808 nmsg = gsm48_mmxx_msgb_alloc(GSM48_MMCC_REL_IND,
2809 mmh->ref, mmh->transaction_id);
2811 case GSM48_MMSS_EST_REQ:
2812 nmsg = gsm48_mmxx_msgb_alloc(GSM48_MMSS_REL_IND,
2813 mmh->ref, mmh->transaction_id);
2815 case GSM48_MMSMS_EST_REQ:
2816 nmsg = gsm48_mmxx_msgb_alloc(GSM48_MMSMS_REL_IND,
2817 mmh->ref, mmh->transaction_id);
2822 nmmh = (struct gsm48_mmxx_hdr *)nmsg->data;
2823 nmmh->cause = cause;
2824 gsm48_mmxx_upmsg(ms, nmsg);
2828 /* in case of an emergency setup */
2829 if (msg_type == GSM48_MMCC_EST_REQ && mmh->emergency)
2832 /* if sim is not updated */
2833 if (!emergency && subscr->ustate != GSM_SIM_U1_UPDATED) {
2834 LOGP(DMM, LOGL_INFO, "Init MM Connection, but SIM not "
2840 /* current MM idle state
2841 * (implies MM IDLE state, otherwise this function is not called)
2843 switch (mm->substate) {
2844 case GSM48_MM_SST_NORMAL_SERVICE:
2845 case GSM48_MM_SST_PLMN_SEARCH_NORMAL:
2846 LOGP(DMM, LOGL_INFO, "Init MM Connection.\n");
2847 break; /* allow when normal */
2848 case GSM48_MM_SST_LOC_UPD_NEEDED:
2849 case GSM48_MM_SST_ATTEMPT_UPDATE:
2850 /* store mm request if attempting to update */
2852 LOGP(DMM, LOGL_INFO, "Init MM Connection, but "
2853 "attempting to update.\n");
2856 /* Some day implement delay and start loc upd. */
2860 /* reject if not emergency */
2862 LOGP(DMM, LOGL_INFO, "Init MM Connection, not in "
2870 /* set cause, service, proto */
2872 case GSM48_MMCC_EST_REQ:
2874 cause = RR_EST_CAUSE_EMERGENCY;
2875 cm_serv = GSM48_CMSERV_EMERGENCY;
2877 cause = RR_EST_CAUSE_ORIG_TCHF;
2878 cm_serv = GSM48_CMSERV_MO_CALL_PACKET;
2880 proto = GSM48_PDISC_CC;
2882 case GSM48_MMSS_EST_REQ:
2883 cause = RR_EST_CAUSE_OTHER_SDCCH;
2884 cm_serv = GSM48_CMSERV_SUP_SERV;
2885 proto = GSM48_PDISC_NC_SS;
2887 case GSM48_MMSMS_EST_REQ:
2888 cause = RR_EST_CAUSE_OTHER_SDCCH;
2889 cm_serv = GSM48_CMSERV_SMS;
2890 proto = GSM48_PDISC_SMS;
2894 /* create MM connection instance */
2895 conn = mm_conn_new(mm, proto, mmh->transaction_id, mmh->ref);
2899 new_conn_state(conn, GSM48_MMXX_ST_CONN_PEND);
2901 /* send CM SERVICE REQUEST */
2903 return gsm48_mm_tx_cm_serv_req(ms, rr_prim, cause, cm_serv);
2908 /* 4.5.1.1 a) MM connection request triggers RR connection */
2909 static int gsm48_mm_init_mm_no_rr(struct osmocom_ms *ms, struct msgb *msg)
2911 struct gsm48_mmlayer *mm = &ms->mmlayer;
2914 /* start MM connection by requesting RR connection */
2915 rc = gsm48_mm_init_mm(ms, msg, GSM48_RR_EST_REQ);
2919 new_mm_state(mm, GSM48_MM_ST_WAIT_RR_CONN_MM_CON, 0);
2924 /* 4.5.1.1 a) RR is esablised during mm connection, wait for CM accepted */
2925 static int gsm48_mm_est_mm_con(struct osmocom_ms *ms, struct msgb *msg)
2927 struct gsm48_mmlayer *mm = &ms->mmlayer;
2929 /* 4.5.1.7 if there is no more MM connection */
2930 if (llist_empty(&mm->mm_conn)) {
2931 LOGP(DMM, LOGL_INFO, "MM Connection, are already gone.\n");
2933 /* start RR release timer */
2936 new_mm_state(mm, GSM48_MM_ST_WAIT_NETWORK_CMD, 0);
2939 return gsm48_mm_tx_cm_service_abort(ms);
2942 /* start MM connection timer */
2945 new_mm_state(mm, GSM48_MM_ST_WAIT_OUT_MM_CONN, 0);
2950 /* 4.5.1.1 b) MM connection request on existing RR connection */
2951 static int gsm48_mm_init_mm_first(struct osmocom_ms *ms, struct msgb *msg)
2953 struct gsm48_mmlayer *mm = &ms->mmlayer;
2956 /* start MM connection by sending data */
2957 rc = gsm48_mm_init_mm(ms, msg, GSM48_RR_DATA_REQ);
2961 /* stop "RR connection release not allowed" timer */
2964 /* start MM connection timer */
2967 new_mm_state(mm, GSM48_MM_ST_WAIT_OUT_MM_CONN, 0);
2972 /* 4.5.1.1 b) another MM connection request on existing RR connection */
2973 static int gsm48_mm_init_mm_more(struct osmocom_ms *ms, struct msgb *msg)
2975 struct gsm48_mmlayer *mm = &ms->mmlayer;
2978 /* start MM connection by sending data */
2979 rc = gsm48_mm_init_mm(ms, msg, GSM48_RR_DATA_REQ);
2983 /* start MM connection timer */
2986 new_mm_state(mm, GSM48_MM_ST_WAIT_ADD_OUT_MM_CON, 0);
2991 /* 4.5.1.1 b) delay on WAIT FOR NETWORK COMMAND state */
2992 static int gsm48_mm_init_mm_wait(struct osmocom_ms *ms, struct msgb *msg)
2995 gsm48_mm_init_mm_reject(ms, msg);
2997 this requires handling when leaving this state...
2999 struct gsm48_mmlayer *mm = &ms->mmlayer;
3002 /* just create the MM connection in pending state */
3003 rc = gsm48_mm_init_mm(ms, msg, 0);
3007 /* start MM connection timer */
3010 new_mm_state(mm, GSM48_MM_ST_WAIT_ADD_OUT_MM_CON, 0);
3016 /* initiate an mm connection other cases */
3017 static int gsm48_mm_init_mm_reject(struct osmocom_ms *ms, struct msgb *msg)
3019 struct gsm48_mmxx_hdr *mmh = (struct gsm48_mmxx_hdr *)msg->data;
3020 int msg_type = mmh->msg_type;
3022 struct gsm48_mmxx_hdr *nmmh;
3027 case GSM48_MMCC_EST_REQ:
3028 nmsg = gsm48_mmxx_msgb_alloc(GSM48_MMCC_REL_IND, mmh->ref,
3029 mmh->transaction_id);
3031 case GSM48_MMSS_EST_REQ:
3032 nmsg = gsm48_mmxx_msgb_alloc(GSM48_MMSS_REL_IND, mmh->ref,
3033 mmh->transaction_id);
3035 case GSM48_MMSMS_EST_REQ:
3036 nmsg = gsm48_mmxx_msgb_alloc(GSM48_MMSMS_REL_IND, mmh->ref,
3037 mmh->transaction_id);
3042 nmmh = (struct gsm48_mmxx_hdr *)nmsg->data;
3044 gsm48_mmxx_upmsg(ms, nmsg);
3049 /* accepting pending connection, got dedicated mode
3051 * this function is called:
3052 * - when ciphering command is received
3053 * - when cm service is accepted
3055 static int gsm48_mm_conn_go_dedic(struct osmocom_ms *ms)
3057 struct gsm48_mmlayer *mm = &ms->mmlayer;
3058 struct gsm48_mm_conn *conn, *conn_found = NULL;
3060 struct gsm48_mmxx_hdr *nmmh;
3062 /* the first and only pending connection is the recent requested */
3063 llist_for_each_entry(conn, &mm->mm_conn, list) {
3064 if (conn->state == GSM48_MMXX_ST_CONN_PEND) {
3070 /* if no pending connection (anymore) */
3072 LOGP(DMM, LOGL_INFO, "No pending MM Connection.\n");
3077 new_conn_state(conn, GSM48_MMXX_ST_DEDICATED);
3079 /* send establishment confirm */
3081 switch(conn_found->protocol) {
3082 case GSM48_PDISC_CC:
3083 nmsg = gsm48_mmxx_msgb_alloc(GSM48_MMCC_EST_CNF, conn->ref,
3084 conn->transaction_id);
3086 case GSM48_PDISC_NC_SS:
3087 nmsg = gsm48_mmxx_msgb_alloc(GSM48_MMSS_EST_CNF, conn->ref,
3088 conn->transaction_id);
3090 case GSM48_PDISC_SMS:
3091 nmsg = gsm48_mmxx_msgb_alloc(GSM48_MMSMS_EST_CNF, conn->ref,
3092 conn->transaction_id);
3097 nmmh = (struct gsm48_mmxx_hdr *)nmsg->data;
3099 gsm48_mmxx_upmsg(ms, nmsg);
3104 /* a RR-SYNC-IND is received during MM connection establishment */
3105 static int gsm48_mm_sync_ind_wait(struct osmocom_ms *ms, struct msgb *msg)
3107 struct gsm48_mmlayer *mm = &ms->mmlayer;
3109 /* stop MM connection timer */
3112 return gsm48_mm_conn_go_dedic(ms);
3115 /* a RR-SYNC-IND is received during MM connection active */
3116 static int gsm48_mm_sync_ind_active(struct osmocom_ms *ms, struct msgb *msg)
3118 struct gsm48_mmlayer *mm = &ms->mmlayer;
3119 struct gsm48_mm_conn *conn;
3121 struct gsm48_mmxx_hdr *nmmh;
3123 /* stop MM connection timer */
3126 /* broadcast all MMCC connection(s) */
3127 llist_for_each_entry(conn, &mm->mm_conn, list) {
3128 /* send MMCC-SYNC-IND */
3130 switch(conn->protocol) {
3131 case GSM48_PDISC_CC:
3132 nmsg = gsm48_mmxx_msgb_alloc(GSM48_MMCC_SYNC_IND,
3133 conn->ref, conn->transaction_id);
3137 continue; /* skip if not of CC type */
3138 nmmh = (struct gsm48_mmxx_hdr *)nmsg->data;
3140 /* copy L3 message */
3141 nmsg->l3h = msgb_put(nmsg, msgb_l3len(msg));
3142 memcpy(nmsg->l3h, msg->l3h, msgb_l3len(msg));
3143 gsm48_mmxx_upmsg(ms, nmsg);
3149 /* 4.5.1.2 RR abort/release is received during MM connection establishment */
3150 static int gsm48_mm_abort_mm_con(struct osmocom_ms *ms, struct msgb *msg)
3152 struct gsm48_mmlayer *mm = &ms->mmlayer;
3153 struct gsm48_rr_hdr *rrh = (struct gsm48_rr_hdr *)msg->data;
3156 /* this conversion is not of any standard */
3157 switch(rrh->cause) {
3158 case RR_REL_CAUSE_NOT_AUTHORIZED:
3159 case RR_REL_CAUSE_EMERGENCY_ONLY:
3160 case RR_REL_CAUSE_TRY_LATER:
3163 case RR_REL_CAUSE_NORMAL:
3170 /* stop MM connection timer */
3173 /* release all connections */
3174 gsm48_mm_release_mm_conn(ms, 1, cause, 1);
3176 /* no RR connection, so we return to MM IDLE */
3177 if (mm->state == GSM48_MM_ST_WAIT_RR_CONN_MM_CON)
3178 return gsm48_mm_return_idle(ms, NULL);
3180 /* CS process will trigger: return to MM IDLE */
3184 /* 4.5.1.2 timeout is received during MM connection establishment */
3185 static int gsm48_mm_timeout_mm_con(struct osmocom_ms *ms, struct msgb *msg)
3187 struct gsm48_mmlayer *mm = &ms->mmlayer;
3189 /* release pending connection */
3190 gsm48_mm_release_mm_conn(ms, 0, 102, 0);
3192 /* state depends on the existance of remaining MM connections */
3193 if (llist_empty(&mm->mm_conn)) {
3194 /* start RR release timer */
3197 new_mm_state(mm, GSM48_MM_ST_WAIT_NETWORK_CMD, 0);
3199 new_mm_state(mm, GSM48_MM_ST_MM_CONN_ACTIVE, 0);
3204 /* respond to paging */
3205 static int gsm48_mm_est(struct osmocom_ms *ms, struct msgb *msg)
3207 struct gsm48_mmlayer *mm = &ms->mmlayer;
3209 new_mm_state(mm, GSM48_MM_ST_WAIT_NETWORK_CMD, 0);
3215 static int gsm48_mm_data(struct osmocom_ms *ms, struct msgb *msg)
3217 struct gsm48_mmlayer *mm = &ms->mmlayer;
3218 struct gsm48_mmxx_hdr *mmh = (struct gsm48_mmxx_hdr *)msg->data;
3219 struct gsm48_mm_conn *conn;
3220 int msg_type = mmh->msg_type;
3222 /* get connection, if not exist (anymore), release */
3223 conn = mm_conn_by_ref(mm, mmh->ref);
3225 LOGP(DMM, LOGL_INFO, "MMXX_DATA_REQ with unknown (already "
3226 "released) ref=%d, sending MMXX_REL_IND\n", mmh->ref);
3227 switch(msg_type & GSM48_MMXX_MASK) {
3228 case GSM48_MMCC_CLASS:
3229 mmh->msg_type = GSM48_MMCC_REL_IND;
3231 case GSM48_MMSS_CLASS:
3232 mmh->msg_type = GSM48_MMSS_REL_IND;
3234 case GSM48_MMSMS_CLASS:
3235 mmh->msg_type = GSM48_MMSMS_REL_IND;
3240 /* mirror message with REL_IND + cause */
3241 return gsm48_mmxx_upmsg(ms, msg);
3244 /* pull MM header */
3245 msgb_pull(msg, sizeof(struct gsm48_mmxx_hdr));
3247 /* push RR header and send down */
3248 return gsm48_mm_to_rr(ms, msg, GSM48_RR_DATA_REQ, 0);
3251 /* release of MM connection (active state) */
3252 static int gsm48_mm_release_active(struct osmocom_ms *ms, struct msgb *msg)
3254 struct gsm48_mmlayer *mm = &ms->mmlayer;
3255 struct gsm48_mmxx_hdr *mmh = (struct gsm48_mmxx_hdr *)msg->data;
3256 struct gsm48_mm_conn *conn;
3258 /* get connection, if not exist (anymore), release */
3259 conn = mm_conn_by_ref(mm, mmh->ref);
3263 /* state depends on the existance of remaining MM connections */
3264 if (llist_empty(&mm->mm_conn)) {
3265 /* start RR release timer */
3268 new_mm_state(mm, GSM48_MM_ST_WAIT_NETWORK_CMD, 0);
3270 new_mm_state(mm, GSM48_MM_ST_MM_CONN_ACTIVE, 0);
3275 /* release of MM connection (wait for additional state) */
3276 static int gsm48_mm_release_wait_add(struct osmocom_ms *ms, struct msgb *msg)
3278 struct gsm48_mmlayer *mm = &ms->mmlayer;
3279 struct gsm48_mmxx_hdr *mmh = (struct gsm48_mmxx_hdr *)msg->data;
3280 struct gsm48_mm_conn *conn;
3282 /* get connection, if not exist (anymore), release */
3283 conn = mm_conn_by_ref(mm, mmh->ref);
3290 /* release of MM connection (wait for active state) */
3291 static int gsm48_mm_release_wait_active(struct osmocom_ms *ms, struct msgb *msg)
3293 struct gsm48_mmlayer *mm = &ms->mmlayer;
3294 struct gsm48_mmxx_hdr *mmh = (struct gsm48_mmxx_hdr *)msg->data;
3295 struct gsm48_mm_conn *conn;
3297 /* get connection, if not exist (anymore), release */
3298 conn = mm_conn_by_ref(mm, mmh->ref);
3302 /* 4.5.1.7 if there is no MM connection during wait for active state */
3303 if (llist_empty(&mm->mm_conn)) {
3304 LOGP(DMM, LOGL_INFO, "No MM Connection during 'wait for "
3305 "active' state.\n");
3307 /* start RR release timer */
3310 new_mm_state(mm, GSM48_MM_ST_WAIT_NETWORK_CMD, 0);
3313 return gsm48_mm_tx_cm_service_abort(ms);
3319 /* release of MM connection (wait for RR state) */
3320 static int gsm48_mm_release_wait_rr(struct osmocom_ms *ms, struct msgb *msg)
3322 struct gsm48_mmlayer *mm = &ms->mmlayer;
3323 struct gsm48_mmxx_hdr *mmh = (struct gsm48_mmxx_hdr *)msg->data;
3324 struct gsm48_mm_conn *conn;
3326 /* get connection, if not exist (anymore), release */
3327 conn = mm_conn_by_ref(mm, mmh->ref);
3331 /* later, if RR connection is established, the CM SERIVE ABORT
3332 * message will be sent
3337 /* abort RR connection (due to T3240) */
3338 static int gsm48_mm_abort_rr(struct osmocom_ms *ms, struct msgb *msg)
3341 struct gsm48_rr_hdr *nrrh;
3343 /* send abort to RR */
3344 nmsg = gsm48_rr_msgb_alloc(GSM48_RR_ABORT_REQ);
3347 nrrh = (struct gsm48_rr_hdr *) msgb_put(nmsg, sizeof(*nrrh));
3348 nrrh->cause = GSM48_RR_CAUSE_ABNORMAL_TIMER;
3349 gsm48_rr_downmsg(ms, nmsg);
3351 /* CS process will trigger: return to MM IDLE / No SIM */
3359 /* RR is released in other states */
3360 static int gsm48_mm_rel_other(struct osmocom_ms *ms, struct msgb *msg)
3362 /* CS process will trigger: return to MM IDLE */
3370 /* state trasitions for MMxx-SAP messages from upper layers */
3371 static struct downstate {
3375 int (*rout) (struct osmocom_ms *ms, struct msgb *msg);
3376 } downstatelist[] = {
3377 /* 4.2.2.1 Normal service */
3378 {SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_NORMAL_SERVICE),
3379 GSM48_MMCC_EST_REQ, gsm48_mm_init_mm_no_rr},
3381 {SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_NORMAL_SERVICE),
3382 GSM48_MMSS_EST_REQ, gsm48_mm_init_mm_no_rr},
3384 {SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_NORMAL_SERVICE),
3385 GSM48_MMSMS_EST_REQ, gsm48_mm_init_mm_no_rr},
3387 /* 4.2.2.2 Attempt to update / Loc. Upd. needed */
3388 {SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_ATTEMPT_UPDATE) |
3389 SBIT(GSM48_MM_SST_LOC_UPD_NEEDED),
3390 GSM48_MMCC_EST_REQ, gsm48_mm_init_mm_no_rr}, /* emergency only */
3392 /* 4.2.2.3 Limited service */
3393 {SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_LIMITED_SERVICE),
3394 GSM48_MMCC_EST_REQ, gsm48_mm_init_mm_no_rr},
3396 /* 4.2.2.4 No IMSI */
3397 {SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_NO_IMSI),
3398 GSM48_MMCC_EST_REQ, gsm48_mm_init_mm_no_rr},
3400 /* 4.2.2.5 PLMN search, normal service */
3401 {SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_PLMN_SEARCH_NORMAL),
3402 GSM48_MMCC_EST_REQ, gsm48_mm_init_mm_no_rr},
3404 {SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_PLMN_SEARCH_NORMAL),
3405 GSM48_MMSS_EST_REQ, gsm48_mm_init_mm_no_rr},
3407 {SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_PLMN_SEARCH_NORMAL),
3408 GSM48_MMSMS_EST_REQ, gsm48_mm_init_mm_no_rr},
3410 /* 4.2.2.6 PLMN search */
3411 {SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_PLMN_SEARCH),
3412 GSM48_MMCC_EST_REQ, gsm48_mm_init_mm_no_rr},
3414 /* 4.5.1.1 MM Connection (EST) */
3415 {SBIT(GSM48_MM_ST_RR_CONN_RELEASE_NA), ALL_STATES,
3416 GSM48_MMCC_EST_REQ, gsm48_mm_init_mm_first},
3418 {SBIT(GSM48_MM_ST_RR_CONN_RELEASE_NA), ALL_STATES,
3419 GSM48_MMSS_EST_REQ, gsm48_mm_init_mm_first},
3421 {SBIT(GSM48_MM_ST_RR_CONN_RELEASE_NA), ALL_STATES,
3422 GSM48_MMSMS_EST_REQ, gsm48_mm_init_mm_first},
3424 {SBIT(GSM48_MM_ST_MM_CONN_ACTIVE), ALL_STATES,
3425 GSM48_MMCC_EST_REQ, gsm48_mm_init_mm_more},
3427 {SBIT(GSM48_MM_ST_MM_CONN_ACTIVE), ALL_STATES,
3428 GSM48_MMSS_EST_REQ, gsm48_mm_init_mm_more},
3430 {SBIT(GSM48_MM_ST_MM_CONN_ACTIVE), ALL_STATES,
3431 GSM48_MMSMS_EST_REQ, gsm48_mm_init_mm_more},
3433 {SBIT(GSM48_MM_ST_WAIT_NETWORK_CMD), ALL_STATES,
3434 GSM48_MMCC_EST_REQ, gsm48_mm_init_mm_wait},
3436 {SBIT(GSM48_MM_ST_WAIT_NETWORK_CMD), ALL_STATES,
3437 GSM48_MMSS_EST_REQ, gsm48_mm_init_mm_wait},
3439 {SBIT(GSM48_MM_ST_WAIT_NETWORK_CMD), ALL_STATES,
3440 GSM48_MMSMS_EST_REQ, gsm48_mm_init_mm_wait},
3442 {ALL_STATES, ALL_STATES,
3443 GSM48_MMCC_EST_REQ, gsm48_mm_init_mm_reject},
3445 {ALL_STATES, ALL_STATES,
3446 GSM48_MMSS_EST_REQ, gsm48_mm_init_mm_reject},
3448 {ALL_STATES, ALL_STATES,
3449 GSM48_MMSMS_EST_REQ, gsm48_mm_init_mm_reject},
3451 /* 4.5.2.1 MM Connection (DATA) */
3452 {SBIT(GSM48_MM_ST_MM_CONN_ACTIVE) |
3453 SBIT(GSM48_MM_ST_WAIT_ADD_OUT_MM_CON), ALL_STATES,
3454 GSM48_MMCC_DATA_REQ, gsm48_mm_data},
3456 {SBIT(GSM48_MM_ST_MM_CONN_ACTIVE) |
3457 SBIT(GSM48_MM_ST_WAIT_ADD_OUT_MM_CON), ALL_STATES,
3458 GSM48_MMSS_DATA_REQ, gsm48_mm_data},
3460 {SBIT(GSM48_MM_ST_MM_CONN_ACTIVE) |
3461 SBIT(GSM48_MM_ST_WAIT_ADD_OUT_MM_CON), ALL_STATES,
3462 GSM48_MMSMS_DATA_REQ, gsm48_mm_data},
3464 /* 4.5.2.1 MM Connection (REL) */
3465 {SBIT(GSM48_MM_ST_MM_CONN_ACTIVE), ALL_STATES,
3466 GSM48_MMCC_REL_REQ, gsm48_mm_release_active},
3468 {SBIT(GSM48_MM_ST_MM_CONN_ACTIVE), ALL_STATES,
3469 GSM48_MMSS_REL_REQ, gsm48_mm_release_active},
3471 {SBIT(GSM48_MM_ST_MM_CONN_ACTIVE), ALL_STATES,
3472 GSM48_MMSMS_REL_REQ, gsm48_mm_release_active},
3474 {SBIT(GSM48_MM_ST_WAIT_ADD_OUT_MM_CON), ALL_STATES,
3475 GSM48_MMCC_REL_REQ, gsm48_mm_release_wait_add},
3477 {SBIT(GSM48_MM_ST_WAIT_ADD_OUT_MM_CON), ALL_STATES,
3478 GSM48_MMSS_REL_REQ, gsm48_mm_release_wait_add},
3480 {SBIT(GSM48_MM_ST_WAIT_ADD_OUT_MM_CON), ALL_STATES,
3481 GSM48_MMSMS_REL_REQ, gsm48_mm_release_wait_add},
3483 {SBIT(GSM48_MM_ST_WAIT_OUT_MM_CONN), ALL_STATES,
3484 GSM48_MMCC_REL_REQ, gsm48_mm_release_wait_active},
3486 {SBIT(GSM48_MM_ST_WAIT_OUT_MM_CONN), ALL_STATES,
3487 GSM48_MMSS_REL_REQ, gsm48_mm_release_wait_active},
3489 {SBIT(GSM48_MM_ST_WAIT_OUT_MM_CONN), ALL_STATES,
3490 GSM48_MMSMS_REL_REQ, gsm48_mm_release_wait_active},
3492 {SBIT(GSM48_MM_ST_WAIT_RR_CONN_MM_CON), ALL_STATES,
3493 GSM48_MMCC_REL_REQ, gsm48_mm_release_wait_rr},
3495 {SBIT(GSM48_MM_ST_WAIT_RR_CONN_MM_CON), ALL_STATES,
3496 GSM48_MMSS_REL_REQ, gsm48_mm_release_wait_rr},
3498 {SBIT(GSM48_MM_ST_WAIT_RR_CONN_MM_CON), ALL_STATES,
3499 GSM48_MMSMS_REL_REQ, gsm48_mm_release_wait_rr},
3503 (sizeof(downstatelist) / sizeof(struct downstate))
3505 int gsm48_mmxx_downmsg(struct osmocom_ms *ms, struct msgb *msg)
3507 struct gsm48_mmlayer *mm = &ms->mmlayer;
3508 struct gsm48_mmxx_hdr *mmh = (struct gsm48_mmxx_hdr *)msg->data;
3509 int msg_type = mmh->msg_type;
3510 struct gsm48_mm_conn *conn;
3513 /* keep up to date with the transaction ID */
3514 conn = mm_conn_by_ref(mm, mmh->ref);
3516 conn->transaction_id = mmh->transaction_id;
3518 LOGP(DMM, LOGL_INFO, "(ms %s) Received '%s' event in state %s\n",
3519 ms->name, get_mmxx_name(msg_type),
3520 gsm48_mm_state_names[mm->state]);
3521 if (mm->state == GSM48_MM_ST_MM_IDLE)
3522 LOGP(DMM, LOGL_INFO, "-> substate %s\n",
3523 gsm48_mm_substate_names[mm->substate]);
3524 LOGP(DMM, LOGL_INFO, "-> callref %d, transaction_id %d\n",
3525 mmh->ref, mmh->transaction_id);
3527 /* Find function for current state and message */
3528 for (i = 0; i < DOWNSLLEN; i++)
3529 if ((msg_type == downstatelist[i].type)
3530 && ((1 << mm->state) & downstatelist[i].states)
3531 && ((1 << mm->substate) & downstatelist[i].substates))
3533 if (i == DOWNSLLEN) {
3534 LOGP(DMM, LOGL_NOTICE, "Message unhandled at this state.\n");
3539 rc = downstatelist[i].rout(ms, msg);
3541 if (downstatelist[i].rout != gsm48_mm_data)
3547 /* state trasitions for radio ressource messages (lower layer) */
3548 static struct rrdatastate {
3551 int (*rout) (struct osmocom_ms *ms, struct msgb *msg);
3552 } rrdatastatelist[] = {
3554 {SBIT(GSM48_MM_ST_MM_IDLE),
3555 GSM48_RR_EST_IND, gsm48_mm_est},
3558 {SBIT(GSM48_MM_ST_WAIT_RR_CONN_IMSI_D), /* 4.3.4.4 */
3559 GSM48_RR_EST_CNF, gsm48_mm_imsi_detach_sent},
3561 {SBIT(GSM48_MM_ST_WAIT_RR_CONN_IMSI_D), /* 4.3.4.4 (unsuc.) */
3562 GSM48_RR_REL_IND, gsm48_mm_imsi_detach_end},
3564 {SBIT(GSM48_MM_ST_WAIT_RR_CONN_IMSI_D), /* 4.3.4.4 (lost) */
3565 GSM48_RR_ABORT_IND, gsm48_mm_imsi_detach_end},
3567 /* location update */
3568 {SBIT(GSM48_MM_ST_WAIT_RR_CONN_LUPD), /* 4.4.4.1 */
3569 GSM48_RR_EST_CNF, gsm48_mm_est_loc_upd},
3571 {SBIT(GSM48_MM_ST_LOC_UPD_INIT) |
3572 SBIT(GSM48_MM_ST_WAIT_RR_CONN_LUPD), /* 4.4.4.9 */
3573 GSM48_RR_REL_IND, gsm48_mm_rel_loc_upd_abort},
3575 {SBIT(GSM48_MM_ST_LOC_UPD_INIT) |
3576 SBIT(GSM48_MM_ST_WAIT_RR_CONN_LUPD), /* 4.4.4.9 */
3577 GSM48_RR_ABORT_IND, gsm48_mm_rel_loc_upd_abort},
3579 {SBIT(GSM48_MM_ST_LOC_UPD_REJ), /* 4.4.4.7 */
3580 GSM48_RR_REL_IND, gsm48_mm_rel_loc_upd_rej},
3582 {SBIT(GSM48_MM_ST_LOC_UPD_REJ), /* 4.4.4.7 */
3583 GSM48_RR_ABORT_IND, gsm48_mm_rel_loc_upd_rej},
3585 /* MM connection (EST) */
3586 {SBIT(GSM48_MM_ST_WAIT_RR_CONN_MM_CON), /* 4.5.1.1 */
3587 GSM48_RR_EST_CNF, gsm48_mm_est_mm_con},
3589 /* MM connection (DATA) */
3591 GSM48_RR_DATA_IND, gsm48_mm_data_ind},
3593 /* MM connection (SYNC) */
3594 {SBIT(GSM48_MM_ST_WAIT_OUT_MM_CONN) |
3595 SBIT(GSM48_MM_ST_WAIT_ADD_OUT_MM_CON), /* 4.5.1.1 */
3596 GSM48_RR_SYNC_IND, gsm48_mm_sync_ind_wait},
3598 {SBIT(GSM48_MM_ST_MM_CONN_ACTIVE),
3599 GSM48_RR_SYNC_IND, gsm48_mm_sync_ind_active},
3601 /* MM connection (REL/ABORT) */
3602 {SBIT(GSM48_MM_ST_WAIT_RR_CONN_MM_CON) |
3603 SBIT(GSM48_MM_ST_WAIT_OUT_MM_CONN) |
3604 SBIT(GSM48_MM_ST_WAIT_ADD_OUT_MM_CON), /* 4.5.1.2 */
3605 GSM48_RR_REL_IND, gsm48_mm_abort_mm_con},
3607 {SBIT(GSM48_MM_ST_WAIT_RR_CONN_MM_CON) |
3608 SBIT(GSM48_MM_ST_WAIT_OUT_MM_CONN) |
3609 SBIT(GSM48_MM_ST_WAIT_ADD_OUT_MM_CON), /* 4.5.1.2 */
3610 GSM48_RR_ABORT_IND, gsm48_mm_abort_mm_con},
3612 /* MM connection (REL/ABORT with re-establishment possibility) */
3613 {SBIT(GSM48_MM_ST_MM_CONN_ACTIVE), /* not supported */
3614 GSM48_RR_REL_IND, gsm48_mm_abort_mm_con},
3616 {SBIT(GSM48_MM_ST_MM_CONN_ACTIVE) |
3617 SBIT(GSM48_MM_ST_WAIT_ADD_OUT_MM_CON), /* not supported */
3618 GSM48_RR_ABORT_IND, gsm48_mm_abort_mm_con},
3622 GSM48_RR_REL_IND, gsm48_mm_rel_other},
3625 GSM48_RR_ABORT_IND, gsm48_mm_rel_other},
3628 #define RRDATASLLEN \
3629 (sizeof(rrdatastatelist) / sizeof(struct rrdatastate))
3631 static int gsm48_rcv_rr(struct osmocom_ms *ms, struct msgb *msg)
3633 struct gsm48_mmlayer *mm = &ms->mmlayer;
3634 struct gsm48_rr_hdr *rrh = (struct gsm48_rr_hdr *)msg->data;
3635 int msg_type = rrh->msg_type;
3638 LOGP(DMM, LOGL_INFO, "(ms %s) Received '%s' from RR in state %s\n",
3639 ms->name, get_rr_name(msg_type),
3640 gsm48_mm_state_names[mm->state]);
3642 /* find function for current state and message */
3643 for (i = 0; i < RRDATASLLEN; i++)
3644 if ((msg_type == rrdatastatelist[i].type)
3645 && ((1 << mm->state) & rrdatastatelist[i].states))
3647 if (i == RRDATASLLEN) {
3648 LOGP(DMM, LOGL_NOTICE, "Message unhandled at this state.\n");
3653 rc = rrdatastatelist[i].rout(ms, msg);
3655 if (rrdatastatelist[i].rout != gsm48_mm_data_ind)
3661 /* state trasitions for mobile managemnt messages (lower layer) */
3662 static struct mmdatastate {
3665 int (*rout) (struct osmocom_ms *ms, struct msgb *msg);
3666 } mmdatastatelist[] = {
3667 {ALL_STATES, /* 4.3.1.2 */
3668 GSM48_MT_MM_TMSI_REALL_CMD, gsm48_mm_rx_tmsi_realloc_cmd},
3670 {ALL_STATES, /* 4.3.2.2 */
3671 GSM48_MT_MM_AUTH_REQ, gsm48_mm_rx_auth_req},
3673 {ALL_STATES, /* 4.3.2.5 */
3674 GSM48_MT_MM_AUTH_REJ, gsm48_mm_rx_auth_rej},
3676 {ALL_STATES, /* 4.3.3.2 */
3677 GSM48_MT_MM_ID_REQ, gsm48_mm_rx_id_req},
3679 {ALL_STATES, /* 4.3.5.2 */
3680 GSM48_MT_MM_ABORT, gsm48_mm_rx_abort},
3682 {ALL_STATES, /* 4.3.6.2 */
3683 GSM48_MT_MM_INFO, gsm48_mm_rx_info},
3685 {SBIT(GSM48_MM_ST_LOC_UPD_INIT), /* 4.4.4.6 */
3686 GSM48_MT_MM_LOC_UPD_ACCEPT, gsm48_mm_rx_loc_upd_acc},
3688 {SBIT(GSM48_MM_ST_LOC_UPD_INIT), /* 4.4.4.7 */
3689 GSM48_MT_MM_LOC_UPD_REJECT, gsm48_mm_rx_loc_upd_rej},
3691 {ALL_STATES, /* 4.5.1.1 */
3692 GSM48_MT_MM_CM_SERV_ACC, gsm48_mm_rx_cm_service_acc},
3694 {ALL_STATES, /* 4.5.1.1 */
3695 GSM48_MT_MM_CM_SERV_REJ, gsm48_mm_rx_cm_service_rej},
3698 #define MMDATASLLEN \
3699 (sizeof(mmdatastatelist) / sizeof(struct mmdatastate))
3701 static int gsm48_mm_data_ind(struct osmocom_ms *ms, struct msgb *msg)
3703 struct gsm48_mmlayer *mm = &ms->mmlayer;
3704 struct gsm48_hdr *gh = msgb_l3(msg);
3705 uint8_t pdisc = gh->proto_discr & 0x0f;
3706 uint8_t msg_type = gh->msg_type & 0xbf;
3707 struct gsm48_mmxx_hdr *mmh;
3708 int msg_supported = 0; /* determine, if message is supported at all */
3709 int rr_prim = -1, rr_est = -1; /* no prim set */
3714 if (msg_type == GSM48_MT_MM_NULL)
3717 /* pull the RR header */
3718 msgb_pull(msg, sizeof(struct gsm48_rr_hdr));
3720 /* create transaction (if not exists) and push message */
3722 case GSM48_PDISC_CC:
3723 rr_prim = GSM48_MMCC_DATA_IND;
3724 rr_est = GSM48_MMCC_EST_IND;
3727 case GSM48_PDISC_NC_SS:
3728 rr_prim = GSM48_MMSS_DATA_IND;
3729 rr_est = GSM48_MMSS_EST_IND;
3731 case GSM48_PDISC_SMS:
3732 rr_prim = GSM48_MMSMS_DATA_IND;
3733 rr_est = GSM48_MMSMS_EST_IND;
3737 if (rr_prim != -1) {
3738 uint8_t transaction_id = ((gh->proto_discr & 0xf0) ^ 0x80) >> 4;
3740 struct gsm48_mm_conn *conn;
3742 /* find transaction, if any */
3743 conn = mm_conn_by_id(mm, pdisc, transaction_id);
3745 /* create MM connection instance */
3747 conn = mm_conn_new(mm, pdisc, transaction_id,
3754 /* push new header */
3755 msgb_push(msg, sizeof(struct gsm48_mmxx_hdr));
3756 mmh = (struct gsm48_mmxx_hdr *)msg->data;
3757 mmh->msg_type = rr_prim;
3758 mmh->ref = conn->ref;
3760 /* go MM CONN ACTIVE state */
3761 if (mm->state == GSM48_MM_ST_WAIT_NETWORK_CMD
3762 || mm->state == GSM48_MM_ST_RR_CONN_RELEASE_NA) {
3763 /* stop RR release timer */
3766 /* stop "RR connection release not allowed" timer */
3769 new_mm_state(mm, GSM48_MM_ST_MM_CONN_ACTIVE, 0);
3773 /* forward message */
3775 case GSM48_PDISC_MM:
3776 skip_ind = (gh->proto_discr & 0xf0) >> 4;
3778 /* ignore if skip indicator is not B'0000' */
3781 break; /* follow the selection proceedure below */
3783 case GSM48_PDISC_CC:
3784 return gsm48_rcv_cc(ms, msg);
3787 case GSM48_PDISC_NC_SS:
3788 return gsm48_rcv_ss(ms, msg);
3790 case GSM48_PDISC_SMS:
3791 return gsm48_rcv_sms(ms, msg);
3795 LOGP(DMM, LOGL_NOTICE, "Protocol type 0x%02x unsupported.\n",
3798 return gsm48_mm_tx_mm_status(ms,
3799 GSM48_REJECT_MSG_TYPE_NOT_IMPLEMENTED);
3802 LOGP(DMM, LOGL_INFO, "(ms %s) Received '%s' in MM state %s\n", ms->name,
3803 get_mm_name(msg_type), gsm48_mm_state_names[mm->state]);
3805 stop_mm_t3212(mm); /* 4.4.2 */
3807 /* 11.2 re-start pending RR release timer */
3808 if (bsc_timer_pending(&mm->t3240)) {
3813 /* find function for current state and message */
3814 for (i = 0; i < MMDATASLLEN; i++) {
3815 if (msg_type == mmdatastatelist[i].type)
3817 if ((msg_type == mmdatastatelist[i].type)
3818 && ((1 << mm->state) & mmdatastatelist[i].states))
3821 if (i == MMDATASLLEN) {
3823 if (msg_supported) {
3824 LOGP(DMM, LOGL_NOTICE, "Message unhandled at this "
3826 return gsm48_mm_tx_mm_status(ms,
3827 GSM48_REJECT_MSG_TYPE_NOT_COMPATIBLE);
3829 LOGP(DMM, LOGL_NOTICE, "Message not supported.\n");
3830 return gsm48_mm_tx_mm_status(ms,
3831 GSM48_REJECT_MSG_TYPE_NOT_IMPLEMENTED);
3835 rc = mmdatastatelist[i].rout(ms, msg);
3842 /* state trasitions for mobile management events */
3843 static struct eventstate {
3847 int (*rout) (struct osmocom_ms *ms, struct msgb *msg);
3848 } eventstatelist[] = {
3849 /* 4.2.3 return to MM IDLE */
3850 {ALL_STATES - SBIT(GSM48_MM_ST_MM_IDLE), ALL_STATES,
3851 GSM48_MM_EVENT_NO_CELL_FOUND, gsm48_mm_no_cell_found},
3853 {ALL_STATES - SBIT(GSM48_MM_ST_MM_IDLE), ALL_STATES,
3854 GSM48_MM_EVENT_CELL_SELECTED, gsm48_mm_return_idle},
3856 /* 4.2.2.1 Normal service */
3857 {SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_NORMAL_SERVICE),
3858 GSM48_MM_EVENT_NO_CELL_FOUND, gsm48_mm_plmn_search}, /* 4.2.1.2 */
3860 {SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_NORMAL_SERVICE),
3861 GSM48_MM_EVENT_CELL_SELECTED, gsm48_mm_loc_upd_normal}, /* change */
3863 {SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_NORMAL_SERVICE),
3864 GSM48_MM_EVENT_TIMEOUT_T3211, gsm48_mm_loc_upd},
3866 {SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_NORMAL_SERVICE),
3867 GSM48_MM_EVENT_TIMEOUT_T3213, gsm48_mm_loc_upd},
3869 {SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_NORMAL_SERVICE),
3870 GSM48_MM_EVENT_TIMEOUT_T3212, gsm48_mm_loc_upd_periodic},
3872 {SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_NORMAL_SERVICE),
3873 GSM48_MM_EVENT_IMSI_DETACH, gsm48_mm_imsi_detach_start},
3875 /* 4.2.2.2 Attempt to update / Loc. upd. needed */
3876 {SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_ATTEMPT_UPDATE) |
3877 SBIT(GSM48_MM_SST_LOC_UPD_NEEDED),
3878 GSM48_MM_EVENT_USER_PLMN_SEL, gsm48_mm_plmn_search}, /* 4.2.1.2 */
3880 {SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_ATTEMPT_UPDATE) |
3881 SBIT(GSM48_MM_SST_LOC_UPD_NEEDED),
3882 GSM48_MM_EVENT_NO_CELL_FOUND, gsm48_mm_plmn_search}, /* 4.2.1.2 */
3884 {SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_ATTEMPT_UPDATE) |
3885 SBIT(GSM48_MM_SST_LOC_UPD_NEEDED),
3886 GSM48_MM_EVENT_CELL_SELECTED, gsm48_mm_loc_upd_normal}, /* change */
3888 {SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_ATTEMPT_UPDATE),
3889 GSM48_MM_EVENT_TIMEOUT_T3211, gsm48_mm_loc_upd},
3891 {SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_ATTEMPT_UPDATE),
3892 GSM48_MM_EVENT_TIMEOUT_T3213, gsm48_mm_loc_upd},
3894 {SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_ATTEMPT_UPDATE),
3895 GSM48_MM_EVENT_TIMEOUT_T3212, gsm48_mm_loc_upd_periodic},
3897 /* 4.2.2.3 Limited service */
3898 {SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_LIMITED_SERVICE),
3899 GSM48_MM_EVENT_USER_PLMN_SEL, gsm48_mm_plmn_search}, /* 4.2.1.2 */
3901 {SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_LIMITED_SERVICE),
3902 GSM48_MM_EVENT_NO_CELL_FOUND, gsm48_mm_plmn_search}, /* 4.2.1.2 */
3904 {SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_LIMITED_SERVICE),
3905 GSM48_MM_EVENT_CELL_SELECTED, gsm48_mm_loc_upd_normal}, /* if allow. */
3907 {SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_LIMITED_SERVICE),
3908 GSM48_MM_EVENT_TIMEOUT_T3212, gsm48_mm_loc_upd_delay_per}, /* 4.4.2 */
3910 /* 4.2.2.4 No IMSI */
3911 /* 4.2.2.5 PLMN search, normal service */
3912 {SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_PLMN_SEARCH_NORMAL),
3913 GSM48_MM_EVENT_NO_CELL_FOUND, gsm48_mm_no_cell_found}, /* 4.2.1.1 */
3915 {SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_PLMN_SEARCH_NORMAL),
3916 GSM48_MM_EVENT_CELL_SELECTED, gsm48_mm_cell_selected}, /* 4.2.1.1 */
3918 {SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_PLMN_SEARCH_NORMAL),
3919 GSM48_MM_EVENT_TIMEOUT_T3211, gsm48_mm_loc_upd_delay_retry},
3921 {SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_PLMN_SEARCH_NORMAL),
3922 GSM48_MM_EVENT_TIMEOUT_T3213, gsm48_mm_loc_upd_delay_retry},
3924 {SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_PLMN_SEARCH_NORMAL),
3925 GSM48_MM_EVENT_TIMEOUT_T3212, gsm48_mm_loc_upd_delay_per}, /* 4.4.2 */
3927 {SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_PLMN_SEARCH_NORMAL),
3928 GSM48_MM_EVENT_IMSI_DETACH, gsm48_mm_imsi_detach_start},
3930 /* 4.2.2.6 PLMN search */
3931 {SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_PLMN_SEARCH),
3932 GSM48_MM_EVENT_NO_CELL_FOUND, gsm48_mm_no_cell_found}, /* 4.2.1.1 */
3934 {SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_PLMN_SEARCH),
3935 GSM48_MM_EVENT_CELL_SELECTED, gsm48_mm_cell_selected}, /* 4.2.1.1 */
3937 {SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_PLMN_SEARCH),
3938 GSM48_MM_EVENT_TIMEOUT_T3212, gsm48_mm_loc_upd_delay_per}, /* 4.4.2 */
3940 /* No cell available */
3941 {SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_NO_CELL_AVAIL),
3942 GSM48_MM_EVENT_CELL_SELECTED, gsm48_mm_cell_selected}, /* 4.2.1.1 */
3944 {SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_NO_CELL_AVAIL),
3945 GSM48_MM_EVENT_TIMEOUT_T3212, gsm48_mm_loc_upd_delay_per}, /* 4.4.2 */
3947 /* IMSI detach in other cases */
3948 {SBIT(GSM48_MM_ST_MM_IDLE), ALL_STATES, /* silently detach */
3949 GSM48_MM_EVENT_IMSI_DETACH, gsm48_mm_imsi_detach_end},
3951 {SBIT(GSM48_MM_ST_WAIT_OUT_MM_CONN) |
3952 SBIT(GSM48_MM_ST_MM_CONN_ACTIVE) |
3953 SBIT(GSM48_MM_ST_PROCESS_CM_SERV_P) |
3954 SBIT(GSM48_MM_ST_WAIT_REEST) |
3955 SBIT(GSM48_MM_ST_WAIT_ADD_OUT_MM_CON) |
3956 SBIT(GSM48_MM_ST_MM_CONN_ACTIVE_VGCS) |
3957 SBIT(GSM48_MM_ST_WAIT_NETWORK_CMD), ALL_STATES, /* we can release */
3958 GSM48_MM_EVENT_IMSI_DETACH, gsm48_mm_imsi_detach_release},
3960 {SBIT(GSM48_MM_ST_WAIT_RR_CONN_IMSI_D) |
3961 SBIT(GSM48_MM_ST_IMSI_DETACH_INIT) |
3962 SBIT(GSM48_MM_ST_IMSI_DETACH_PEND), ALL_STATES, /* ignore */
3963 GSM48_MM_EVENT_IMSI_DETACH, gsm48_mm_imsi_detach_ignore},
3965 {ALL_STATES, ALL_STATES,
3966 GSM48_MM_EVENT_IMSI_DETACH, gsm48_mm_imsi_detach_delay},
3968 {GSM48_MM_ST_IMSI_DETACH_INIT, ALL_STATES,
3969 GSM48_MM_EVENT_TIMEOUT_T3220, gsm48_mm_imsi_detach_end},
3971 /* location update in other cases */
3972 {ALL_STATES, ALL_STATES,
3973 GSM48_MM_EVENT_TIMEOUT_T3212, gsm48_mm_loc_upd_ignore},
3975 {ALL_STATES - SBIT(GSM48_MM_ST_MM_IDLE), ALL_STATES,
3976 GSM48_MM_EVENT_TIMEOUT_T3210, gsm48_mm_loc_upd_timeout},
3978 {ALL_STATES - SBIT(GSM48_MM_ST_MM_IDLE), ALL_STATES,
3979 GSM48_MM_EVENT_TIMEOUT_T3213, gsm48_mm_loc_upd_failed},
3980 /* 4.4.4.9 c) (but without retry) */
3983 {ALL_STATES, ALL_STATES,
3984 GSM48_MM_EVENT_SYSINFO, gsm48_mm_sysinfo},
3986 /* T3240 timed out */
3987 {SBIT(GSM48_MM_ST_WAIT_NETWORK_CMD) |
3988 SBIT(GSM48_MM_ST_LOC_UPD_REJ), ALL_STATES, /* 4.4.4.8 */
3989 GSM48_MM_EVENT_TIMEOUT_T3240, gsm48_mm_abort_rr},
3991 /* T3230 timed out */
3992 {SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_NORMAL_SERVICE),
3993 GSM48_MM_EVENT_TIMEOUT_T3230, gsm48_mm_timeout_mm_con},
3995 /* SIM reports SRES */
3996 {ALL_STATES, ALL_STATES, /* 4.3.2.2 */
3997 GSM48_MM_EVENT_AUTH_RESPONSE, gsm48_mm_tx_auth_rsp},
4000 /* change in classmark is reported */
4001 {ALL_STATES, ALL_STATES,
4002 GSM48_MM_EVENT_CLASSMARK_CHG, gsm48_mm_classm_chg},
4006 #define EVENTSLLEN \
4007 (sizeof(eventstatelist) / sizeof(struct eventstate))
4009 static int gsm48_mm_ev(struct osmocom_ms *ms, int msg_type, struct msgb *msg)
4011 struct gsm48_mmlayer *mm = &ms->mmlayer;
4014 if (mm->state == GSM48_MM_ST_MM_IDLE)
4015 LOGP(DMM, LOGL_INFO, "(ms %s) Received '%s' event in state "
4016 "MM IDLE, %s\n", ms->name, get_mmevent_name(msg_type),
4017 gsm48_mm_substate_names[mm->substate]);
4019 LOGP(DMM, LOGL_INFO, "(ms %s) Received '%s' event in state "
4020 "%s\n", ms->name, get_mmevent_name(msg_type),
4021 gsm48_mm_state_names[mm->state]);
4023 /* Find function for current state and message */
4024 for (i = 0; i < EVENTSLLEN; i++)
4025 if ((msg_type == eventstatelist[i].type)
4026 && ((1 << mm->state) & eventstatelist[i].states)
4027 && ((1 << mm->substate) & eventstatelist[i].substates))
4029 if (i == EVENTSLLEN) {
4030 LOGP(DMM, LOGL_NOTICE, "Message unhandled at this state.\n");
4034 rc = eventstatelist[i].rout(ms, msg);
4040 * MM Register (SIM insert and remove)
4043 /* register new SIM card and trigger attach */
4044 static int gsm48_mmr_reg_req(struct osmocom_ms *ms)
4046 struct gsm48_mmlayer *mm = &ms->mmlayer;
4049 /* schedule insertion of SIM */
4050 nmsg = gsm322_msgb_alloc(GSM322_EVENT_SIM_INSERT);
4053 gsm322_plmn_sendmsg(ms, nmsg);
4055 /* 4.2.1.2 SIM is inserted in state NO IMSI */
4056 if (mm->state == GSM48_MM_ST_MM_IDLE
4057 && mm->substate == GSM48_MM_SST_NO_IMSI)
4058 new_mm_state(mm, GSM48_MM_ST_MM_IDLE,
4059 gsm48_mm_set_plmn_search(ms));
4064 /* trigger detach of sim card */
4065 static int gsm48_mmr_nreg_req(struct osmocom_ms *ms)
4067 struct gsm48_mmlayer *mm = &ms->mmlayer;
4070 nmsg = gsm322_msgb_alloc(GSM48_MM_EVENT_IMSI_DETACH);
4073 gsm48_mmevent_msg(mm->ms, nmsg);
4078 static int gsm48_rcv_mmr(struct osmocom_ms *ms, struct msgb *msg)
4080 struct gsm48_mmr *mmr = (struct gsm48_mmr *)msg->data;
4081 int msg_type = mmr->msg_type;
4084 LOGP(DMM, LOGL_INFO, "(ms %s) Received '%s' event\n", ms->name,
4085 get_mmr_name(msg_type));
4087 case GSM48_MMR_REG_REQ:
4088 rc = gsm48_mmr_reg_req(ms);
4090 case GSM48_MMR_NREG_REQ:
4091 rc = gsm48_mmr_nreg_req(ms);
4094 LOGP(DMM, LOGL_NOTICE, "Message unhandled.\n");