aboutsummaryrefslogtreecommitdiffstats
path: root/src/gprs/gprs_gmm.c
diff options
context:
space:
mode:
authorAlexander Couzens <lynxis@fe80.eu>2018-05-22 18:29:14 +0200
committerHarald Welte <laforge@gnumonks.org>2018-09-13 13:51:37 +0000
commitf7198d7dbb84d038a82eec5ad0b86f7f29ca411e (patch)
treeba6bdf8dbe9055009459ba28c900c98b5590656f /src/gprs/gprs_gmm.c
parent941ee147f92b6064b5e5feff166ecfb97cea85b1 (diff)
gprs_gmm: introduce a GMM Attach Request FSM
The old GMM Attach Request handling used a recursive function which can not handle certain states and is quite complex and hard to extend. The new FSM handles such request in a FSM and can be called multiple times. Change-Id: I58b9c17be9776a03bb2a5b21e99135cfefc8c912
Diffstat (limited to 'src/gprs/gprs_gmm.c')
-rw-r--r--src/gprs/gprs_gmm.c47
1 files changed, 38 insertions, 9 deletions
diff --git a/src/gprs/gprs_gmm.c b/src/gprs/gprs_gmm.c
index bea63dc5..a363c709 100644
--- a/src/gprs/gprs_gmm.c
+++ b/src/gprs/gprs_gmm.c
@@ -59,6 +59,7 @@
#include <osmocom/sgsn/gprs_utils.h>
#include <osmocom/sgsn/gprs_subscriber.h>
#include <osmocom/sgsn/sgsn.h>
+#include <osmocom/sgsn/gprs_gmm_attach.h>
#include <osmocom/sgsn/signal.h>
#include <osmocom/sgsn/gprs_sndcp.h>
@@ -791,7 +792,7 @@ static int gsm48_rx_gmm_auth_ciph_resp(struct sgsn_mm_ctx *ctx,
/* FIXME: enable LLC cipheirng */
/* Check if we can let the mobile station enter */
- return gsm48_gmm_authorize(ctx);
+ return osmo_fsm_inst_dispatch(ctx->gmm_att_req.fsm, E_AUTH_RESP_RECV_SUCCESS, NULL);
}
/* Section 9.4.10: Authentication and Ciphering Failure */
@@ -836,7 +837,7 @@ static int gsm48_rx_gmm_auth_ciph_fail(struct sgsn_mm_ctx *ctx,
rc = gprs_subscr_request_auth_info(ctx, auts,
ctx->auth_triplet.vec.rand);
if (!rc)
- return 0;
+ return osmo_fsm_inst_dispatch(ctx->gmm_att_req.fsm, E_AUTH_RESP_RECV_RESYNC, NULL);
/* on error, fall through to send a reject */
LOGMMCTXP(LOGL_ERROR, ctx,
"Sending AUTS to HLR failed (rc = %d)\n", rc);
@@ -1107,7 +1108,10 @@ void gsm0408_gprs_authenticate(struct sgsn_mm_ctx *ctx)
{
ctx->sec_ctx = OSMO_AUTH_TYPE_NONE;
- gsm48_gmm_authorize(ctx);
+ if (ctx->gmm_att_req.fsm->state != ST_INIT)
+ osmo_fsm_inst_dispatch(ctx->gmm_att_req.fsm, E_VLR_ANSWERED, (void *) 0);
+ else
+ gsm48_gmm_authorize(ctx);
}
void gsm0408_gprs_access_granted(struct sgsn_mm_ctx *ctx)
@@ -1118,7 +1122,8 @@ void gsm0408_gprs_access_granted(struct sgsn_mm_ctx *ctx)
"Authorized, continuing procedure, IMSI=%s\n",
ctx->imsi);
/* Continue with the authorization */
- gsm48_gmm_authorize(ctx);
+ if (ctx->gmm_att_req.fsm->state != ST_INIT)
+ osmo_fsm_inst_dispatch(ctx->gmm_att_req.fsm, E_VLR_ANSWERED, (void *) 0);
break;
default:
LOGMMCTXP(LOGL_INFO, ctx,
@@ -1139,8 +1144,8 @@ void gsm0408_gprs_access_denied(struct sgsn_mm_ctx *ctx, int gmm_cause)
"with cause '%s' (%d)\n",
get_value_string(gsm48_gmm_cause_names, gmm_cause),
gmm_cause);
- gsm48_tx_gmm_att_rej(ctx, gmm_cause);
- mm_ctx_cleanup_free(ctx, "GPRS ATTACH REJECT");
+ if (ctx->gmm_att_req.fsm->state != ST_INIT)
+ osmo_fsm_inst_dispatch(ctx->gmm_att_req.fsm, E_REJECT, (void *) (long) gmm_cause);
break;
case GMM_REGISTERED_NORMAL:
case GMM_REGISTERED_SUSPENDED:
@@ -1183,6 +1188,7 @@ static int gsm48_rx_gmm_id_resp(struct sgsn_mm_ctx *ctx, struct msgb *msg)
{
struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_gmmh(msg);
uint8_t mi_type = gh->data[1] & GSM_MI_TYPE_MASK;
+ long mi_typel = mi_type;
char mi_string[GSM48_MI_SIZE];
gsm48_mi_to_string(mi_string, sizeof(mi_string), &gh->data[1], gh->data[0]);
@@ -1235,7 +1241,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);
+ return osmo_fsm_inst_dispatch(ctx->gmm_att_req.fsm, E_IDEN_RESP_RECV, (void *)mi_typel);
}
/* Allocate a new P-TMSI and change context state */
@@ -1425,8 +1431,8 @@ static int gsm48_rx_gmm_att_req(struct sgsn_mm_ctx *ctx, struct msgb *msg,
gprs_llgmm_assign(ctx->gb.llme, ctx->gb.tlli, ctx->gb.tlli_new);
}
- ctx->pending_req = GSM48_MT_GMM_ATTACH_REQ;
- return gsm48_gmm_authorize(ctx);
+ osmo_fsm_inst_dispatch(ctx->gmm_att_req.fsm, E_ATTACH_REQ_RECV, msg);
+ return 0;
err_inval:
LOGPC(DMM, LOGL_INFO, "\n");
@@ -1447,6 +1453,28 @@ rejected:
}
+
+/* Checks if two attach request contain the IEs and IE values
+ * return 0 if equal
+ * return -1 if error
+ * return 1 if unequal
+ *
+ * Only do a simple memcmp for now.
+ */
+int gprs_gmm_attach_req_ies(struct msgb *a, struct msgb *b)
+{
+ struct gsm48_hdr *gh_a = (struct gsm48_hdr *) msgb_gmmh(a);
+ struct gsm48_hdr *gh_b = (struct gsm48_hdr *) msgb_gmmh(b);
+
+#define GMM_ATTACH_REQ_LEN 26
+
+ /* there is the LLC FCS behind */
+ if (msgb_l3len(a) < GMM_ATTACH_REQ_LEN || msgb_l3len(b) < GMM_ATTACH_REQ_LEN)
+ return -1;
+
+ return !!memcmp(gh_a, gh_b, GMM_ATTACH_REQ_LEN);
+}
+
/* Section 4.7.4.1 / 9.4.5.2 MO Detach request */
static int gsm48_rx_gmm_det_req(struct sgsn_mm_ctx *ctx, struct msgb *msg)
{
@@ -2023,6 +2051,7 @@ static int gsm0408_rcv_gmm(struct sgsn_mm_ctx *mmctx, struct msgb *msg,
mmctx_set_mm_state(mmctx, MM_READY);
rc = 0;
+ osmo_fsm_inst_dispatch(mmctx->gmm_att_req.fsm, E_ATTACH_COMPLETE_RECV, 0);
memset(&sig_data, 0, sizeof(sig_data));
sig_data.mm = mmctx;
osmo_signal_dispatch(SS_SGSN, S_SGSN_ATTACH, &sig_data);