aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJacob Erlbeck <jerlbeck@sysmocom.de>2014-10-28 12:23:29 +0100
committerHolger Hans Peter Freyther <holger@moiji-mobile.com>2014-11-14 08:57:50 +0100
commit93eae8ec78d145cf87b7858ebee60c72da7a2d20 (patch)
treec1ba9d775fa7a078a5832fc9431cf994beaef091
parent3911880b68ddd92c9dd89d6ac20c26807e33f905 (diff)
sgsn: Reorganize and fix gsm48_gmm_authorize
Currently the order of the 'if' clauses in gsm48_gmm_authorize doesn't match the order in which the conditional parts are entered. This makes it difficult to maintain. In addition the t3350_mode is not stored in every path, so that this information is lost when the identification procedure is started. Since the default value coincidentally is GMM_T3350_MODE_ATT, this doesn't hurt for Attach Requests which are the only messages that initially trigger the authentication yet. This patch changes the order of the 'if' clause to match the processing order, it removes the t3350_mode parameter entirely and introduces a mm->pending_req field. The latter must be set when the request that causes the authorization before calling gsm48_gmm_authorize. The gprs_t3350_mode enum is extended by GMM_T3350_MODE_NONE (value 0, which is the default) to make it possible to detect related initialisation errors or race conditions. Sponsored-by: On-Waves ehf
-rw-r--r--openbsc/include/openbsc/gprs_sgsn.h6
-rw-r--r--openbsc/src/gprs/gprs_gmm.c58
2 files changed, 48 insertions, 16 deletions
diff --git a/openbsc/include/openbsc/gprs_sgsn.h b/openbsc/include/openbsc/gprs_sgsn.h
index 73731fe97..75797dba0 100644
--- a/openbsc/include/openbsc/gprs_sgsn.h
+++ b/openbsc/include/openbsc/gprs_sgsn.h
@@ -48,6 +48,7 @@ enum gprs_pdp_ctx {
};
enum gprs_t3350_mode {
+ GMM_T3350_MODE_NONE,
GMM_T3350_MODE_ATT,
GMM_T3350_MODE_RAU,
GMM_T3350_MODE_PTMSI_REALL,
@@ -111,6 +112,11 @@ struct sgsn_mm_ctx {
enum gprs_t3350_mode t3350_mode;
uint8_t t3370_id_type;
+ uint8_t pending_req; /* the request's message type */
+ /* TODO: There isn't much semantic difference between t3350_mode
+ * (refers to the timer) and pending_req (refers to the procedure),
+ * where mm->T == 3350 => mm->t3350_mode == f(mm->pending_req). Check
+ * whether one of them can be dropped. */
};
#define LOGMMCTXP(level, mm, fmt, args...) \
diff --git a/openbsc/src/gprs/gprs_gmm.c b/openbsc/src/gprs/gprs_gmm.c
index a5f9b782a..e661b4875 100644
--- a/openbsc/src/gprs/gprs_gmm.c
+++ b/openbsc/src/gprs/gprs_gmm.c
@@ -625,27 +625,15 @@ static int gsm48_rx_gmm_auth_ciph_resp(struct sgsn_mm_ctx *ctx,
}
/* Check if we can already authorize a subscriber */
-static int gsm48_gmm_authorize(struct sgsn_mm_ctx *ctx,
- enum gprs_t3350_mode t3350_mode)
+static int gsm48_gmm_authorize(struct sgsn_mm_ctx *ctx)
{
- if (strlen(ctx->imei) && strlen(ctx->imsi)) {
-#ifdef PTMSI_ALLOC
- ctx->t3370_id_type = GSM_MI_TYPE_NONE;
-
- /* Start T3350 and re-transmit up to 5 times until ATTACH COMPLETE */
- ctx->t3350_mode = t3350_mode;
- mmctx_timer_start(ctx, 3350, GSM0408_T3350_SECS);
-#endif
- ctx->mm_state = GMM_REGISTERED_NORMAL;
- return gsm48_tx_gmm_att_ack(ctx);
- }
+ /* Request IMSI and IMEI from the MS if they are unknown */
if (!strlen(ctx->imei)) {
ctx->mm_state = GMM_COMMON_PROC_INIT;
ctx->t3370_id_type = GSM_MI_TYPE_IMEI;
mmctx_timer_start(ctx, 3370, GSM0408_T3370_SECS);
return gsm48_tx_gmm_id_req(ctx, GSM_MI_TYPE_IMEI);
}
-
if (!strlen(ctx->imsi)) {
ctx->mm_state = GMM_COMMON_PROC_INIT;
ctx->t3370_id_type = GSM_MI_TYPE_IMSI;
@@ -653,6 +641,31 @@ static int gsm48_gmm_authorize(struct sgsn_mm_ctx *ctx,
return gsm48_tx_gmm_id_req(ctx, GSM_MI_TYPE_IMSI);
}
+ /* All information required for authentication is available */
+
+ ctx->t3370_id_type = GSM_MI_TYPE_NONE;
+
+ switch (ctx->pending_req) {
+ case 0:
+ LOGMMCTXP(LOGL_INFO, ctx,
+ "no pending request, authorization completed\n");
+ break;
+ case GSM48_MT_GMM_ATTACH_REQ:
+#ifdef PTMSI_ALLOC
+ /* Start T3350 and re-transmit up to 5 times until ATTACH COMPLETE */
+ mmctx_timer_start(ctx, 3350, GSM0408_T3350_SECS);
+ ctx->t3350_mode = GMM_T3350_MODE_ATT;
+#endif
+
+ ctx->mm_state = GMM_REGISTERED_NORMAL;
+ return gsm48_tx_gmm_att_ack(ctx);
+ default:
+ LOGMMCTXP(LOGL_ERROR, ctx,
+ "only Attach Request is supported yet, "
+ "got request type %u\n", ctx->pending_req);
+ break;
+ }
+
return 0;
}
@@ -715,7 +728,7 @@ static int gsm48_rx_gmm_id_resp(struct sgsn_mm_ctx *ctx, struct msgb *msg)
}
/* Check if we can let the mobile station enter */
- return gsm48_gmm_authorize(ctx, ctx->t3350_mode);
+ return gsm48_gmm_authorize(ctx);
}
/* Section 9.4.1 Attach request */
@@ -856,7 +869,8 @@ static int gsm48_rx_gmm_att_req(struct sgsn_mm_ctx *ctx, struct msgb *msg,
gprs_llgmm_assign(ctx->llme, ctx->tlli, ctx->tlli_new,
GPRS_ALGO_GEA0, NULL);
- return gsm48_gmm_authorize(ctx, GMM_T3350_MODE_ATT);
+ ctx->pending_req = GSM48_MT_GMM_ATTACH_REQ;
+ return gsm48_gmm_authorize(ctx);
err_inval:
LOGPC(DMM, LOGL_INFO, "\n");
@@ -1168,7 +1182,9 @@ static int gsm0408_rcv_gmm(struct sgsn_mm_ctx *mmctx, struct msgb *msg,
/* only in case SGSN offered new P-TMSI */
LOGMMCTXP(LOGL_INFO, mmctx, "-> ATTACH COMPLETE\n");
mmctx_timer_stop(mmctx, 3350);
+ mmctx->t3350_mode = GMM_T3350_MODE_NONE;
mmctx->p_tmsi_old = 0;
+ mmctx->pending_req = 0;
/* Unassign the old TLLI */
mmctx->tlli = mmctx->tlli_new;
gprs_llgmm_assign(mmctx->llme, 0xffffffff, mmctx->tlli_new,
@@ -1179,7 +1195,9 @@ static int gsm0408_rcv_gmm(struct sgsn_mm_ctx *mmctx, struct msgb *msg,
/* only in case SGSN offered new P-TMSI */
LOGMMCTXP(LOGL_INFO, mmctx, "-> ROUTEING AREA UPDATE COMPLETE\n");
mmctx_timer_stop(mmctx, 3350);
+ mmctx->t3350_mode = GMM_T3350_MODE_NONE;
mmctx->p_tmsi_old = 0;
+ mmctx->pending_req = 0;
/* Unassign the old TLLI */
mmctx->tlli = mmctx->tlli_new;
gprs_llgmm_assign(mmctx->llme, 0xffffffff, mmctx->tlli_new,
@@ -1189,7 +1207,9 @@ static int gsm0408_rcv_gmm(struct sgsn_mm_ctx *mmctx, struct msgb *msg,
case GSM48_MT_GMM_PTMSI_REALL_COMPL:
LOGMMCTXP(LOGL_INFO, mmctx, "-> PTMSI REALLLICATION COMPLETE\n");
mmctx_timer_stop(mmctx, 3350);
+ mmctx->t3350_mode = GMM_T3350_MODE_NONE;
mmctx->p_tmsi_old = 0;
+ mmctx->pending_req = 0;
/* Unassign the old TLLI */
mmctx->tlli = mmctx->tlli_new;
//gprs_llgmm_assign(mmctx->llme, 0xffffffff, mmctx->tlli_new, GPRS_ALGO_GEA0, NULL);
@@ -1219,6 +1239,8 @@ static void mmctx_timer_cb(void *_mm)
if (mm->num_T_exp >= 5) {
LOGMMCTXP(LOGL_NOTICE, mm, "T3350 expired >= 5 times\n");
mm->mm_state = GMM_DEREGISTERED;
+ mm->t3350_mode = GMM_T3350_MODE_NONE;
+ mm->pending_req = 0;
/* FIXME: should we return some error? */
break;
}
@@ -1233,6 +1255,10 @@ static void mmctx_timer_cb(void *_mm)
case GMM_T3350_MODE_PTMSI_REALL:
/* FIXME */
break;
+ case GMM_T3350_MODE_NONE:
+ LOGMMCTXP(LOGL_NOTICE, mm,
+ "T3350 mode wasn't set, ignoring timeout\n");
+ break;
}
osmo_timer_schedule(&mm->timer, GSM0408_T3350_SECS, 0);
break;