diff options
-rw-r--r-- | include/openbsc/sgsn.h | 2 | ||||
-rw-r--r-- | src/gprs/gprs_gmm.c | 29 | ||||
-rw-r--r-- | src/gprs/sgsn_libgtp.c | 16 |
3 files changed, 36 insertions, 11 deletions
diff --git a/include/openbsc/sgsn.h b/include/openbsc/sgsn.h index 84db87e91..7ca7e1c44 100644 --- a/include/openbsc/sgsn.h +++ b/include/openbsc/sgsn.h @@ -48,7 +48,7 @@ struct sgsn_pdp_ctx *sgsn_create_pdp_ctx(struct sgsn_ggsn_ctx *ggsn, struct sgsn_mm_ctx *mmctx, uint16_t nsapi, struct tlv_parsed *tp); -int sgsn_delete_pdp_ctx(struct sgsn_pdp_ctx *pctx); +int sgsn_delete_pdp_ctx(struct sgsn_pdp_ctx *pctx, int implicit); /* gprs_sndcp.c */ diff --git a/src/gprs/gprs_gmm.c b/src/gprs/gprs_gmm.c index 467c7a0bd..b722f1212 100644 --- a/src/gprs/gprs_gmm.c +++ b/src/gprs/gprs_gmm.c @@ -549,7 +549,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 +634,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. */ @@ -772,7 +786,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.. */ } @@ -866,7 +880,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); } } } @@ -1006,6 +1020,7 @@ 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; /* Inform LLC layer about new TLLI but keep old active */ @@ -1055,8 +1070,6 @@ 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? */ break; } /* re-transmit the respective msg and re-start timer */ @@ -1393,7 +1406,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 */ @@ -1413,7 +1426,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) @@ -1437,7 +1450,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); diff --git a/src/gprs/sgsn_libgtp.c b/src/gprs/sgsn_libgtp.c index 7b10a45a3..b2d8874ac 100644 --- a/src/gprs/sgsn_libgtp.c +++ b/src/gprs/sgsn_libgtp.c @@ -208,12 +208,20 @@ struct sgsn_pdp_ctx *sgsn_create_pdp_ctx(struct sgsn_ggsn_ctx *ggsn, } /* SGSN wants to delete a PDP context */ -int sgsn_delete_pdp_ctx(struct sgsn_pdp_ctx *pctx) +int sgsn_delete_pdp_ctx(struct sgsn_pdp_ctx *pctx, int implicit) { LOGP(DGPRS, LOGL_ERROR, "Delete PDP Context\n"); + if (implicit != 0) { + /* Deactivate the SNDCP layer */ + sndcp_sm_deactivate_ind(&pctx->mm->llme->lle[pctx->sapi], pctx->nsapi); + } + /* FIXME: decide if we need teardown or not ! */ - return gtp_delete_context_req(pctx->ggsn->gsn, pctx->lib, pctx, 1); + return gtp_delete_context_req(pctx->ggsn->gsn, + pctx->lib, + implicit == 0 ? pctx : NULL, + 1); } struct cause_map { @@ -312,6 +320,10 @@ static int delete_pdp_conf(struct pdp_t *pdp, void *cbp, int cause) DEBUGP(DGPRS, "Received DELETE PDP CTX CONF, cause=%d(%s)\n", cause, get_value_string(gtp_cause_strs, cause)); + if (!pctx) { + return 0; + } + /* Deactivate the SNDCP layer */ sndcp_sm_deactivate_ind(&pctx->mm->llme->lle[pctx->sapi], pctx->nsapi); |