aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/openbsc/sgsn.h2
-rw-r--r--src/gprs/gprs_gmm.c25
-rw-r--r--src/gprs/sgsn_libgtp.c16
3 files changed, 35 insertions, 8 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..942d93f47 100644
--- a/src/gprs/gprs_gmm.c
+++ b/src/gprs/gprs_gmm.c
@@ -635,6 +635,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 +787,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 +881,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);
}
}
}
@@ -1393,7 +1408,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 +1428,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 +1452,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);