aboutsummaryrefslogtreecommitdiffstats
path: root/src/gprs/gprs_gmm.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gprs/gprs_gmm.c')
-rw-r--r--src/gprs/gprs_gmm.c71
1 files changed, 40 insertions, 31 deletions
diff --git a/src/gprs/gprs_gmm.c b/src/gprs/gprs_gmm.c
index 46c49318f..f6cc0d47e 100644
--- a/src/gprs/gprs_gmm.c
+++ b/src/gprs/gprs_gmm.c
@@ -55,6 +55,8 @@
#define PTMSI_ALLOC
+#define GSM0408_T3302 (10 | GPRS_TMR_2SECONDS)
+
/* Section 11.2.2 / Table 11.4 MM timers netowkr side */
#define GSM0408_T3322_SECS 6 /* DETACH_REQ -> DETACH_ACC */
#define GSM0408_T3350_SECS 6 /* waiting for ATT/RAU/TMSI COMPL */
@@ -359,7 +361,7 @@ static int gsm48_tx_gmm_att_ack(struct sgsn_mm_ctx *mm)
aa = (struct gsm48_attach_ack *) msgb_put(msg, sizeof(*aa));
aa->force_stby = 0; /* not indicated */
aa->att_result = 1; /* GPRS only */
- aa->ra_upd_timer = GPRS_TMR_MINUTE | 10;
+ aa->ra_upd_timer = GSM0408_T3302;
aa->radio_prio = 4; /* lowest */
gsm48_construct_ra(aa->ra_id.digits, &mm->ra);
@@ -549,7 +551,6 @@ static int gsm48_gmm_authorize(struct sgsn_mm_ctx *ctx,
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);
}
if (!strlen(ctx->imei)) {
@@ -635,6 +636,21 @@ static int gsm48_rx_gmm_att_req(struct sgsn_mm_ctx *ctx, struct msgb *msg,
DEBUGP(DMM, "-> GMM ATTACH REQUEST ");
+ if (ctx && ((ctx->mm_state == GMM_REGISTERED_NORMAL) ||
+ (ctx->mm_state == GMM_REGISTERED_SUSPENDED))) {
+ struct sgsn_pdp_ctx *pdp, *pdp2;
+
+ LOGP(DMM, LOGL_NOTICE, "Attach requested by already-attached "
+ "mobile. Deleting existing contexts\n");
+
+ llist_for_each_entry_safe(pdp, pdp2, &ctx->pdp_list, list) {
+ sgsn_delete_pdp_ctx(pdp, 1);
+ }
+
+ sgsn_mm_ctx_free(ctx);
+ ctx = NULL;
+ }
+
/* As per TS 04.08 Chapter 4.7.1.4, the attach request arrives either
* with a foreign TLLI (P-TMSI that was allocated to the MS before),
* or with random TLLI. */
@@ -644,7 +660,7 @@ static int gsm48_rx_gmm_att_req(struct sgsn_mm_ctx *ctx, struct msgb *msg,
/* MS network capability 10.5.5.12 */
msnc_len = *cur++;
msnc = cur;
- if (msnc_len > 8)
+ if (msnc_len > MS_NETWORK_CAPA_MAX_LENGTH)
goto err_inval;
cur += msnc_len;
@@ -675,7 +691,7 @@ static int gsm48_rx_gmm_att_req(struct sgsn_mm_ctx *ctx, struct msgb *msg,
/* MS Radio Access Capability 10.5.5.12a */
ms_ra_acc_cap_len = *cur++;
ms_ra_acc_cap = cur;
- if (ms_ra_acc_cap_len > 51)
+ if (ms_ra_acc_cap_len > MS_RADIO_ACCESS_CAPA_MAX_LENGTH)
goto err_inval;
/* Optional: Old P-TMSI Signature, Requested READY timer, TMSI Status */
@@ -689,16 +705,7 @@ static int gsm48_rx_gmm_att_req(struct sgsn_mm_ctx *ctx, struct msgb *msg,
#if 0
return gsm48_tx_gmm_att_rej(msg, GMM_CAUSE_IMSI_UNKNOWN);
#else
- /* As a temorary hack, we simply assume that the IMSI exists,
- * as long as it is part of 'our' network */
- char mccmnc[16];
- snprintf(mccmnc, sizeof(mccmnc), "%03d%02d", ra_id.mcc, ra_id.mnc);
- if (strncmp(mccmnc, mi_string, 5)) {
- LOGP(DMM, LOGL_INFO, "Rejecting ATTACH REQUESET IMSI=%s\n",
- mi_string);
- return gsm48_tx_gmm_att_rej_oldmsg(msg,
- GMM_CAUSE_GPRS_NOTALLOWED);
- }
+ /* As a temorary hack, we simply assume that the IMSI exists */
ctx = sgsn_mm_ctx_alloc(0, &ra_id);
if (!ctx)
return gsm48_tx_gmm_att_rej_oldmsg(msg, GMM_CAUSE_NET_FAIL);
@@ -785,7 +792,7 @@ static int gsm48_rx_gmm_det_req(struct sgsn_mm_ctx *ctx, struct msgb *msg)
llist_for_each_entry_safe(pdp, pdp2, &ctx->pdp_list, list) {
LOGP(DMM, LOGL_NOTICE, "Dropping PDP context for NSAPI=%u "
"due to GPRS DETACH REQUEST\n", pdp->nsapi);
- sgsn_delete_pdp_ctx(pdp);
+ sgsn_delete_pdp_ctx(pdp, 0);
/* FIXME: the callback wants to transmit a DEACT PDP CTX ACK,
* which is quite stupid for a MS that has just detached.. */
}
@@ -819,7 +826,7 @@ static int gsm48_tx_gmm_ra_upd_ack(struct sgsn_mm_ctx *mm)
rua = (struct gsm48_ra_upd_ack *) msgb_put(msg, sizeof(*rua));
rua->force_stby = 0; /* not indicated */
rua->upd_result = 0; /* RA updated */
- rua->ra_upd_timer = GPRS_TMR_MINUTE | 10;
+ rua->ra_upd_timer = GSM0408_T3302;
gsm48_construct_ra(rua->ra_id.digits, &mm->ra);
@@ -879,7 +886,7 @@ static void process_ms_ctx_status(struct sgsn_mm_ctx *mmctx,
LOGP(DMM, LOGL_NOTICE, "Dropping PDP context for NSAPI=%u "
"due to PDP CTX STATUS IE= 0x%04x\n",
pdp->nsapi, pdp_status);
- sgsn_delete_pdp_ctx(pdp);
+ sgsn_delete_pdp_ctx(pdp, 0);
}
}
}
@@ -936,6 +943,8 @@ static int gsm48_rx_gmm_ra_upd_req(struct sgsn_mm_ctx *mmctx, struct msgb *msg,
return gsm48_tx_gmm_ra_upd_rej(msg, GMM_CAUSE_MS_ID_NOT_DERIVED);
}
+ gprs_llgmm_suspend(mmctx->llme);
+
/* Store new BVCI/NSEI in MM context (FIXME: delay until we ack?) */
msgid2mmctx(mmctx, msg);
/* Bump the statistics of received signalling msgs for this MM context */
@@ -1023,30 +1032,25 @@ static int gsm0408_rcv_gmm(struct sgsn_mm_ctx *mmctx, struct msgb *msg,
case GSM48_MT_GMM_ATTACH_COMPL:
/* only in case SGSN offered new P-TMSI */
DEBUGP(DMM, "-> ATTACH COMPLETE\n");
+ mmctx->mm_state = GMM_REGISTERED_NORMAL;
mmctx_timer_stop(mmctx, 3350);
mmctx->p_tmsi_old = 0;
- /* Unassign the old TLLI */
mmctx->tlli = mmctx->tlli_new;
- gprs_llgmm_assign(mmctx->llme, 0xffffffff, mmctx->tlli_new,
- GPRS_ALGO_GEA0, NULL);
+ gprs_llgmm_resume(mmctx->llme);
break;
case GSM48_MT_GMM_RA_UPD_COMPL:
/* only in case SGSN offered new P-TMSI */
DEBUGP(DMM, "-> ROUTEING AREA UPDATE COMPLETE\n");
mmctx_timer_stop(mmctx, 3350);
mmctx->p_tmsi_old = 0;
- /* Unassign the old TLLI */
mmctx->tlli = mmctx->tlli_new;
- gprs_llgmm_assign(mmctx->llme, 0xffffffff, mmctx->tlli_new,
- GPRS_ALGO_GEA0, NULL);
+ gprs_llgmm_resume(mmctx->llme);
break;
case GSM48_MT_GMM_PTMSI_REALL_COMPL:
DEBUGP(DMM, "-> PTMSI REALLLICATION COMPLETE\n");
mmctx_timer_stop(mmctx, 3350);
mmctx->p_tmsi_old = 0;
- /* Unassign the old TLLI */
mmctx->tlli = mmctx->tlli_new;
- //gprs_llgmm_assign(mmctx->llme, 0xffffffff, mmctx->tlli_new, GPRS_ALGO_GEA0, NULL);
break;
case GSM48_MT_GMM_AUTH_CIPH_RESP:
rc = gsm48_rx_gmm_auth_ciph_resp(mmctx, msg);
@@ -1071,8 +1075,8 @@ static void mmctx_timer_cb(void *_mm)
case 3350: /* waiting for ATTACH COMPLETE */
if (mm->num_T_exp >= 5) {
LOGP(DMM, LOGL_NOTICE, "T3350 expired >= 5 times\n");
- mm->mm_state = GMM_DEREGISTERED;
- /* FIXME: should we return some error? */
+ gprs_llgmm_resume(mm->llme);
+ gprs_llgmm_reset_state(mm->llme);
break;
}
/* re-transmit the respective msg and re-start timer */
@@ -1409,7 +1413,7 @@ static int gsm48_rx_gsm_deact_pdp_req(struct sgsn_mm_ctx *mm, struct msgb *msg)
return _gsm48_tx_gsm_deact_pdp_acc(mm, transaction_id);
}
- return sgsn_delete_pdp_ctx(pdp);
+ return sgsn_delete_pdp_ctx(pdp, 0);
}
/* Section 9.5.9: Deactivate PDP Context Accept */
@@ -1429,7 +1433,7 @@ static int gsm48_rx_gsm_deact_pdp_ack(struct sgsn_mm_ctx *mm, struct msgb *msg)
return 0;
}
- return sgsn_delete_pdp_ctx(pdp);
+ return sgsn_delete_pdp_ctx(pdp, 0);
}
static int gsm48_rx_gsm_status(struct sgsn_mm_ctx *ctx, struct msgb *msg)
@@ -1453,7 +1457,7 @@ static void pdpctx_timer_cb(void *_pdp)
if (pdp->num_T_exp >= 4) {
LOGP(DMM, LOGL_NOTICE, "T3395 expired >= 5 times\n");
pdp->state = PDP_STATE_INACTIVE;
- sgsn_delete_pdp_ctx(pdp);
+ sgsn_delete_pdp_ctx(pdp, 0);
break;
}
gsm48_tx_gsm_deact_pdp_req(pdp, GSM_CAUSE_NET_FAIL);
@@ -1522,7 +1526,12 @@ int gsm0408_gprs_rcvmsg(struct msgb *msg, struct gprs_llc_llme *llme)
int rc = -EINVAL;
bssgp_parse_cell_id(&ra_id, msgb_bcid(msg));
- mmctx = sgsn_mm_ctx_by_tlli(msgb_tlli(msg), &ra_id);
+ mmctx = sgsn_mm_ctx_by_tlli(llme->tlli, &ra_id);
+
+ if (!mmctx && (llme->old_tlli != 0xffffffff)) {
+ mmctx = sgsn_mm_ctx_by_tlli(llme->old_tlli, &ra_id);
+ }
+
if (mmctx) {
msgid2mmctx(mmctx, msg);
rate_ctr_inc(&mmctx->ctrg->ctr[GMM_CTR_PKTS_SIG_IN]);