diff options
Diffstat (limited to 'src/gprs/gprs_gmm.c')
-rw-r--r-- | src/gprs/gprs_gmm.c | 71 |
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]); |