Compare commits

..

22 Commits

Author SHA1 Message Date
Jonathan Santos
57ae3aa256 Release version 0.9.13-0~jrsantos.5 2011-08-11 02:58:33 -04:00
Jonathan Santos
6f3c2f1b91 gprs: Also check tlli_new in sgsn_mm_ctx_by_tlli 2011-08-11 02:56:42 -04:00
Jonathan Santos
b3994d0dd2 gprs: Change T3302 to 20 seconds 2011-08-11 02:56:36 -04:00
Jonathan Santos
0fa1677013 Release version 0.9.13-0~jrsantos.4 2011-07-31 13:05:14 -04:00
Jonathan Santos
a101a5f43e gprs: Fix retry of ATTACH REQUEST from mobile
If, for some reason, the mobile did not receive an ATTACH ACCEPT
it resends an ATTACH REQUEST.  The SGSN then would send a new
ATTACH ACCEPT.  However, after sending the new ATTACH REQUEST, it
was unable to find the GMM context if the mobile uses the old
foreign tlli (as it is allowed to do).  This fixes that.
2011-07-31 12:31:00 -04:00
Jonathan Santos
fd7223f7e6 gprs: Fix premature TLLI change
During the GPRS Attach procedure, the SGSN was changing the TLLI
to the new TLLI when sending the second Identity Request.  This
was caused by the sgsn_mm_ctx_by_tlli() function changing the TLLI.
It is usually bad form to have a lookup function change values.
2011-07-31 10:27:52 -04:00
Jonathan Santos
7cfdff76ca Revert "gprs: Fix bug that caused TLLI to change prematurely"
This reverts commit bd92172bf4.
2011-07-31 10:27:31 -04:00
Jonathan Santos
a5fee1cb8d Release version 0.9.13-0~jrsantos.3 2011-07-22 13:10:05 -04:00
Jonathan Santos
e5b7ad8119 gprs: Reset LLC state when Timer 3350 expires
This works around a problem that occurs if a mobile loses packet
data connectivity, e.g. moves out of coverage or switches over
to a circuit-switched call, while a data transfer is occurring.
The mobile would reset its LLC state, causing it to be
unsynchronized with the SGSN.  Therefore the SGSN would drop
incoming frames until the sequence numbers matched.  This
workaround resets the LLC state in the SGSN if T3350 expires,
indicating that Routing Area Updating Request, Attach Request,
or P-TMSI Realloc Command has failed.
2011-07-21 15:30:41 -04:00
Jonathan Santos
5f7d3cd6d2 gprs: Fix LLC UI window
According to TS 44.064 section 8.4.2, the LLC layer should only
drop UI frames if V(UR)-32 <= N(U) < V(UR).  The code was dropping
frames whenever N(U) < V(UR).  Consequently, large amounts of
packets could be dropped if, e.g., V(UR)==511 and the frame with
N(U)==511 was lost.  All frames would be dropped until the next
time a frame with N(U)==511 is received.
2011-06-23 17:57:06 -04:00
Jonathan Santos
7ad066c5c3 gprs: Suspend user data transmission during Routing Area Updating
TS 24.008 version 9.5.0 Release 9 sec 4.7.5:
     In A/Gb mode, user data transmission in the MS shall be
     suspended during the routing area updating procedure, except
     if the routing area updating procedure is triggered by a PS
     handover procedure as described in 3GPP TS 43.129 [113];
     user data reception shall be possible. User data transmission
     in the network may be suspended during the routing area
     updating procedure.
2011-06-23 17:47:27 -04:00
Jonathan Santos
a0fb1bb847 Merge branch 'attach_already_attached' 2011-06-23 17:46:50 -04:00
Jonathan Santos
dec0ea8fd2 gprs: Set GMM state to GMM_REGISTERED_NORMAL after ATTACH_COMPLETE received
The SGSN was updating the GMM state when sending the ATTACH_ACCEPT, when
it should enter that state after the ATTACH_COMPLETE is received.
2011-06-23 17:45:38 -04:00
Jonathan Santos
8f3a5a2f0b gprs: Delete GMM and PDP contexts if ATTACH_REQUEST received from already-attached MS
TS 24.008 version 9.5.0 Release 9 sec 4.7.3.1.6:
     If an ATTACH REQUEST message is received in state GMM-REGISTERED
     the network may initiate the GMM common procedures; if it turned
     out that the ATTACH REQUEST message was send by an MS that has
     already been attached, the GMM context, PDP contexts and MBMS
     contexts, if any, are deleted and the new ATTACH REQUEST is
     progressed.
2011-06-23 17:45:19 -04:00
Jonathan Santos
749a666d84 Merge branch 'nexus_s_attach' 2011-06-23 15:37:31 -04:00
Jonathan Santos
bd92172bf4 gprs: Fix bug that caused TLLI to change prematurely 2011-06-23 15:30:31 -04:00
Jonathan Santos
fe7724f1d4 gprs: Fix bugs that reset LLC sequence numbers improperly 2011-06-23 15:30:31 -04:00
Jonathan Santos
ac9341c9c3 gprs: Fix bug where SGSN was sending all LLC UI frames with N(U)=0
Convert foreign TLLIs to local TLLIs for storage in LLME context.
2011-06-23 15:30:31 -04:00
Jonathan Santos
eb2730e646 gprs: Fix possible segfault on attach caused by MS Network Capability larger than 4 octets
The SGSN was allowing MS Network Capability of up to 8 octets, but only allocating
storage for 4 octets.

TS 23.060 version 9.7.0 Release 9 section 6.14.2 states:
  To allow for the addition of future features, the SGSN shall
  store the UE Network Capability and the MS Network Capability
  even if either or both is larger than specified in TS 24.008
  [13]/TS 24.301 [102], up to a maximum size of 32 octets for
  each IE.
2011-06-23 15:30:30 -04:00
Jonathan Santos
dbf8411b2f gprs: Fix segfault on attach caused by MS Radio Access Capability larger than 14 octets
Newer phones are using a MS Radio Access Capability larger than the
14 octets specified in 04.08 Release 1998 (up to 50 octets in Rel 9).
This caused the SGSN to crash since it only allocated storage for
14 octets but tried to store up to 51 octets.

TS 23.060 version 9.7.0 Release 9 section 6.14.1.1 states:
  To allow for the addition of future radio technologies, frequency
  bands, and other enhancements, the SGSN shall store the MS radio
  access capability even if it is larger than specified in TS 24.008
  [13], up to a maximum size of 255 octets.
2011-06-23 15:30:30 -04:00
Jonathan Santos
bab770e493 Merge branch 'allow_all_imsis' 2011-06-10 13:25:22 -04:00
Jonathan Santos
87f424d6d4 Allow all IMSIs
This reverts commit eafe22ca72 from upstream git
repository.
2011-05-25 14:50:40 -04:00
8 changed files with 164 additions and 56 deletions

35
debian/changelog vendored
View File

@@ -1,3 +1,38 @@
opensgsn (0.9.13-0~jrsantos.5) unstable; urgency=low
* gprs: Change T3302 to 20 seconds
* gprs: Also check tlli_new in sgsn_mm_ctx_by_tlli
-- Jonathan Santos <jrsantos@jonathanrsantos.com> Thu, 11 Aug 2011 02:57:38 -0400
opensgsn (0.9.13-0~jrsantos.4) unstable; urgency=low
* Revert "gprs: Fix bug that caused TLLI to change prematurely"
* gprs: Fix premature TLLI change
* gprs: Fix retry of ATTACH REQUEST from mobile
-- Jonathan Santos <jrsantos@jonathanrsantos.com> Sun, 31 Jul 2011 12:56:09 -0400
opensgsn (0.9.13-0~jrsantos.3) unstable; urgency=low
* Allow all IMSIs
* gprs: Fix segfault on attach caused by MS Radio Access Capability
larger than 14 octets
* gprs: Fix possible segfault on attach caused by MS Network
Capability larger than 4 octets
* gprs: Fix bug where SGSN was sending all LLC UI frames with N(U)=0
* gprs: Fix bugs that reset LLC sequence numbers improperly
* gprs: Fix bug that caused TLLI to change prematurely
* gprs: Delete GMM and PDP contexts if ATTACH_REQUEST received from
already-attached MS
* gprs: Set GMM state to GMM_REGISTERED_NORMAL after ATTACH_COMPLETE
received
* gprs: Suspend user data transmission during Routing Area Updating
* gprs: Fix LLC UI window
* gprs: Reset LLC state when Timer 3350 expires
-- Jonathan Santos <jrsantos@jonathanrsantos.com> Fri, 22 Jul 2011 13:07:05 -0400
opensgsn (0.9.13-0~jrsantos.2) unstable; urgency=low
* Fix bug that caused dpkg-gencontrol to fail

View File

@@ -140,6 +140,8 @@ struct gprs_llc_llme {
uint16_t bvci;
uint16_t nsei;
struct gprs_llc_lle lle[NUM_SAPIS];
int suspended;
};
extern struct llist_head gprs_llc_llmes;
@@ -156,6 +158,9 @@ int gprs_llgmm_assign(struct gprs_llc_llme *llme,
uint32_t old_tlli, uint32_t new_tlli,
enum gprs_ciph_algo alg, const uint8_t *kc);
int gprs_llgmm_suspend(struct gprs_llc_llme *llme);
int gprs_llgmm_resume(struct gprs_llc_llme *llme);
void gprs_llgmm_reset_state(struct gprs_llc_llme *llme);
int gprs_llc_init(const char *cipher_plugin_path);
int gprs_llc_vty_init(void);

View File

@@ -50,7 +50,8 @@ enum gprs_t3350_mode {
GMM_T3350_MODE_PTMSI_REALL,
};
#define MS_RADIO_ACCESS_CAPA
#define MS_RADIO_ACCESS_CAPA_MAX_LENGTH 255
#define MS_NETWORK_CAPA_MAX_LENGTH 32
/* According to TS 03.60, Table 5: SGSN MM and PDP Contexts */
/* Extended by 3GPP TS 23.060, Table 6: SGSN MM and PDP Contexts */
@@ -78,11 +79,11 @@ struct sgsn_mm_ctx {
/* CKSN */
enum gprs_ciph_algo ciph_algo;
struct {
uint8_t buf[14]; /* 10.5.5.12a */
uint8_t buf[MS_RADIO_ACCESS_CAPA_MAX_LENGTH]; /* 10.5.5.12a */
uint8_t len;
} ms_radio_access_capa;
struct {
uint8_t buf[4]; /* 10.5.5.12 */
uint8_t buf[MS_NETWORK_CAPA_MAX_LENGTH]; /* 10.5.5.12 */
uint8_t len;
} ms_network_capa;
uint16_t drx_parms;

View File

@@ -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 */

View File

@@ -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]);

View File

@@ -340,7 +340,7 @@ int gprs_llc_tx_ui(struct msgb *msg, uint8_t sapi, int command,
struct gprs_llc_llme *llme;
LOGP(DLLC, LOGL_ERROR, "LLC TX: unknown TLLI 0x%08x, "
"creating LLME on the fly\n", msgb_tlli(msg));
llme = llme_alloc(msgb_tlli(msg));
llme = llme_alloc(tlli_foreign2local(msgb_tlli(msg)));
lle = &llme->lle[sapi];
}
@@ -350,6 +350,12 @@ int gprs_llc_tx_ui(struct msgb *msg, uint8_t sapi, int command,
return -EFBIG;
}
if ((sapi != GPRS_SAPI_GMM) && lle->llme->suspended) {
LOGP(DLLC, LOGL_DEBUG, "LLC TX: suspended TLLI 0x08x, "
"dropping UI frame\n", msgb_tlli(msg));
return 0;
}
/* Update LLE's (BVCI, NSEI) tuple */
lle->llme->bvci = msgb_bvci(msg);
lle->llme->nsei = msgb_nsei(msg);
@@ -476,17 +482,21 @@ static int gprs_llc_hdr_rx(struct gprs_llc_hdr_parsed *gph,
}
break;
case GPRS_LLC_UI:
if (gph->seq_tx < lle->vu_recv) {
LOGP(DLLC, LOGL_NOTICE, "TLLI=%08x dropping UI, vurecv %u <= %u\n",
lle->llme ? lle->llme->tlli : -1,
gph->seq_tx, lle->vu_recv);
return -EIO;
}
/* Increment the sequence number that we expect in the next frame */
lle->vu_recv = (gph->seq_tx + 1) % 512;
/* Increment Overflow Counter */
if ((gph->seq_tx + 1) / 512)
lle->oc_ui_recv += 512;
{
int delta = (lle->vu_recv - gph->seq_tx) & 0x1ff;
if (0 < delta && delta < 32) {
LOGP(DLLC, LOGL_NOTICE, "TLLI=%08x dropping UI, vurecv %u <= %u\n",
lle->llme ? lle->llme->tlli : -1,
gph->seq_tx, lle->vu_recv);
return -EIO;
}
/* Increment the sequence number that we expect in the next frame */
lle->vu_recv = (gph->seq_tx + 1) & 0x1ff;
/* Increment Overflow Counter */
if (lle->vu_recv == 0) {
lle->oc_ui_recv += 512;
}
}
break;
}
@@ -808,12 +818,12 @@ int gprs_llgmm_assign(struct gprs_llc_llme *llme,
* received from peer. */
if (llme->old_tlli != 0xffffffff) {
llme->old_tlli = 0xffffffff;
llme->tlli = new_tlli;
llme->tlli = tlli_foreign2local(new_tlli);
} else {
/* If TLLI old == 0xffffffff was assigned to LLME, then this is
* TLLI assignmemt according to 8.3.1 */
llme->old_tlli = 0xffffffff;
llme->tlli = new_tlli;
llme->tlli = tlli_foreign2local(new_tlli);
llme->state = GPRS_LLMS_ASSIGNED;
/* 8.5.3.1 For all LLE's */
for (i = 0; i < ARRAY_SIZE(llme->lle); i++) {
@@ -828,8 +838,8 @@ int gprs_llgmm_assign(struct gprs_llc_llme *llme,
/* TLLI Change 8.3.2 */
/* Both TLLI Old and TLLI New are assigned; use New when
* (re)transmitting. Accept toth Old and New on Rx */
llme->old_tlli = llme->tlli;
llme->tlli = new_tlli;
llme->old_tlli = tlli_foreign2local(old_tlli);
llme->tlli = tlli_foreign2local(new_tlli);
llme->state = GPRS_LLMS_ASSIGNED;
} else if (old_tlli != 0xffffffff && new_tlli == 0xffffffff) {
/* TLLI Unassignment 8.3.3) */
@@ -846,6 +856,42 @@ int gprs_llgmm_assign(struct gprs_llc_llme *llme,
return 0;
}
int gprs_llgmm_suspend(struct gprs_llc_llme* llme)
{
llme->suspended = 1;
return 0;
}
int gprs_llgmm_resume(struct gprs_llc_llme* llme)
{
llme->suspended = 0;
return 0;
}
void gprs_llgmm_reset_state(struct gprs_llc_llme *llme)
{
unsigned int i;
if (llme == 0)
{
LOGP(DLLC, LOGL_ERROR, "LLC TX: trying to reset LLC states "
"but passed null llme by gmm\n");
return;
}
LOGP(DLLC, LOGL_NOTICE, "LLC RX: reset state variable for TLLI 0x%08x",
llme->tlli);
/* 8.5.3.1 For all LLE's */
for (i = 0; i < ARRAY_SIZE(llme->lle); i++) {
struct gprs_llc_lle *l = &llme->lle[i];
l->vu_recv = 0; /* lets not mess with send state variable now */
/* l->vu_send = l->vu_recv = 0; */
l->retrans_ctr = 0;
l->state = GPRS_LLES_ASSIGNED_ADM;
/* FIXME Set parameters according to table 9 */
}
}
int gprs_llc_init(const char *cipher_plugin_path)
{
return gprs_cipher_load(cipher_plugin_path);

View File

@@ -97,7 +97,7 @@ struct sgsn_mm_ctx *sgsn_mm_ctx_by_tlli(uint32_t tlli,
int tlli_type;
llist_for_each_entry(ctx, &sgsn_mm_ctxts, list) {
if (tlli == ctx->tlli &&
if ((tlli == ctx->tlli || tlli == ctx->tlli_new) &&
ra_id_equals(raid, &ctx->ra))
return ctx;
}
@@ -108,14 +108,14 @@ struct sgsn_mm_ctx *sgsn_mm_ctx_by_tlli(uint32_t tlli,
llist_for_each_entry(ctx, &sgsn_mm_ctxts, list) {
if ((ctx->p_tmsi | 0xC0000000) == tlli ||
(ctx->p_tmsi_old && (ctx->p_tmsi_old | 0xC0000000) == tlli)) {
ctx->tlli = tlli;
return ctx;
}
}
break;
case TLLI_FOREIGN:
llist_for_each_entry(ctx, &sgsn_mm_ctxts, list) {
if (tlli == tlli_foreign(ctx->tlli) &&
if ((tlli == tlli_foreign(ctx->tlli) ||
tlli == tlli_foreign(ctx->tlli_new)) &&
ra_id_equals(raid, &ctx->ra))
return ctx;
}

View File

@@ -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);