· 6 years ago · May 18, 2019, 08:34 PM
1/*
2* Copyright 2011 Range Networks, Inc.
3* All Rights Reserved.
4* Copyright (C) 2013-2014 Null Team Impex SRL
5* Copyright (C) 2014 Legba, Inc
6*
7* This software is distributed under multiple licenses;
8* see the COPYING file in the main directory for licensing
9* information for this specific distribuion.
10*
11* This use of this software may be subject to additional restrictions.
12* See the LEGAL file in the main directory for details.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17*/
18
19#include <list>
20//#include "RList.h"
21#include "LLC.h"
22//#include "MSInfo.h"
23#include "GPRSL3Messages.h"
24#include "Ggsn.h"
25#include "Sgsn.h"
26#include "SgsnConn.h"
27#include "Utils.h"
28#include "Globals.h"
29//#include "MAC.h"
30#include "miniggsn.h"
31
32#include <stdlib.h>
33#include <string.h>
34#include <stdio.h>
35#include <iomanip>
36
37using namespace Utils;
38using namespace Connection;
39#define CASENAME(x) case x: return #x;
40#define SRB3 3
41
42//using namespace SIP;
43
44namespace SGSN {
45typedef std::list<SgsnInfo*> SgsnInfoList_t;
46static SgsnInfoList_t sSgsnInfoList;
47typedef std::list<GmmInfo*> GmmInfoList_t;
48static GmmInfoList_t sGmmInfoList;
49static Mutex sSgsnListMutex; // One lock sufficient for all lists maintained by SGSN.
50static void dumpGmmInfo();
51#if RN_UMTS
52//static void sendAuthenticationRequest(SgsnInfo *si, string IMSI);
53#endif
54
55//static void killOtherTlli(SgsnInfo *si,uint32_t newTlli);
56static SgsnInfo *sgsnGetSgsnInfoByHandle(uint32_t mshandle, bool create);
57static int getNMO();
58
59unsigned int sgsnDebug()
60{
61 if (gConfig.getBool("SGSN.Debug"))
62 return GPRS::GPRSDebug;
63 return 0;
64}
65
66bool enableMultislot()
67{
68 return gConfig.getNum("GPRS.Multislot.Max.Downlink") > 1 ||
69 gConfig.getNum("GPRS.Multislot.Max.Uplink") > 1;
70}
71
72const char *GmmCause::name(unsigned mt, bool ornull)
73{
74 switch (mt) {
75 CASENAME(IMSI_unknown_in_HLR)
76 CASENAME(Illegal_MS)
77 CASENAME(IMEI_not_accepted)
78 CASENAME(Illegal_ME)
79 CASENAME(GPRS_services_not_allowed)
80 CASENAME(GPRS_services_and_non_GPRS_services_not_allowed)
81 CASENAME(MS_identity_cannot_be_derived_by_the_network)
82 CASENAME(Implicitly_detached)
83 CASENAME(PLMN_not_allowed)
84 CASENAME(Location_Area_not_allowed)
85 CASENAME(Roaming_not_allowed_in_this_location_area)
86 CASENAME(GPRS_services_not_allowed_in_this_PLMN)
87 CASENAME(No_Suitable_Cells_In_Location_Area)
88 CASENAME(MSC_temporarily_not_reachable)
89 CASENAME(Network_failure)
90 CASENAME(MAC_failure)
91 CASENAME(Synch_failure)
92 CASENAME(Congestion)
93 CASENAME(GSM_authentication_unacceptable)
94 CASENAME(Not_authorized_for_this_CSG)
95 CASENAME(No_PDP_context_activated)
96 // 0x30 to 0x3f - retry upon entry into a new cell?
97 CASENAME(Semantically_incorrect_message)
98 CASENAME(Invalid_mandatory_information)
99 CASENAME(Message_type_nonexistent_or_not_implemented)
100 CASENAME(Message_type_not_compatible_with_the_protocol_state)
101 CASENAME(Information_element_nonexistent_or_not_implemented)
102 CASENAME(Conditional_IE_error)
103 CASENAME(Message_not_compatible_with_the_protocol_state)
104 CASENAME(Protocol_error_unspecified)
105 default:
106 return ornull ? 0 : "unrecognized GmmCause type";
107 }
108}
109
110SgsnInfo::SgsnInfo(uint32_t wMsHandle) :
111 //mState(GmmState::GmmNotOurTlli),
112 mGmmp(0),
113 mLlcEngine(0),
114 mMsHandle(wMsHandle),
115 mConnId(GprsConnNone),
116 mT3310FinishAttach(15000), // 15 seconds
117 mT3370ImsiRequest(6000) // 6 seconds
118 // mSuspended(0),
119{
120 //memset(mOldMcc,0,sizeof(mOldMcc));
121 //memset(mOldMnc,0,sizeof(mOldMnc));
122 time(&mLastUseTime);
123#if RN_UMTS == 0
124 mLlcEngine = new LlcEngine(this);
125#endif
126 sSgsnInfoList.push_back(this);
127 SGSNLOGF(INFO,GPRS_OK|GPRS_MSG,"SGSN","Created SgsnInfo:" << this);
128}
129
130SgsnInfo::~SgsnInfo()
131{
132 if (mLlcEngine) {delete mLlcEngine;}
133}
134
135void SgsnInfo::clearConn(int state, int btsPrim, unsigned char info)
136{
137 if (state >= 0)
138 return;
139 int id = getConnId();
140 mConnId = state;
141 if (gGprsMap.unmap(this) && (id >= 0)) {
142 setConnId(state);
143 gSigConn.send((BtsPrimitive)btsPrim,info,id);
144 }
145}
146
147void SgsnInfo::sirm()
148{
149 clearConn(GprsConnNone,SigConnLost);
150 std::ostringstream ss;
151 sgsnInfoDump(this,ss);
152 //SGSNLOGF(INFO,GPRS_OK|GPRS_MSG,"SGSN","Removing SgsnInfo:"<<ss);
153 SGSNLOGF(INFO,GPRS_OK|GPRS_MSG,"SGSN","Removing SgsnInfo:"<<(!ss.fail()));
154 sSgsnInfoList.remove(this);
155 GmmInfo *gmm = getGmm();
156 if (gmm && (gmm->getSI() == this)) {
157 gmm->msi = 0;
158 if (gmm->isRegistered())
159 gmm->setGmmState(GmmState::GmmRegistrationPending);
160 }
161 delete this;
162}
163
164// This is for use by the Command Line Interface
165// Return true on success.
166bool cliSgsnInfoDelete(SgsnInfo *si)
167{
168 ScopedLock lock(sSgsnListMutex);
169 GmmInfo *gmm = si->getGmm();
170 if (gmm && gmm->getSI() == si) {
171 // You cannot delete this si by itself. Must delete the GmmInfo instead.
172 return false;
173 }
174 si->sirm();
175 return true;
176}
177
178// This is the generalized printer to identify an SgsnInfo.
179// The alternate sgsnInfoDump is used only for gmmDump and prints
180// only that info that is not duplicated in the Gmm.
181std::ostream& operator<<(std::ostream& os, const SgsnInfo*si)
182{
183 MSUEAdapter *ms = si->getMS();
184 if (ms)
185 os << ms->msid();
186#if RN_UMTS
187 os << LOGHEX2("(URNTI", si->mMsHandle) << ")";
188#else
189 os << LOGHEX2("(TLLI", si->mMsHandle) << ")";
190#endif
191 if (si->getGmm()) { os << LOGVAR2("imsi",si->getGmm()->mImsi.hexstr()); }
192 os << " ConnID=" << si->getConnId() << " (" << si->mConnId << ")";
193 os << " [" << hex << (void*) si << "]";
194 return os;
195}
196
197// Reset this connection, for example, because it is doing a GmmDetach or a new GmmAttach.
198void SgsnInfo::sgsnReset(uint8_t wType)
199{
200 clearConn(GprsConnNone,SigGprsDetach,wType);
201 freePdpAll(true);
202 if (mLlcEngine) { mLlcEngine->getLlcGmm()->reset(); }
203}
204
205// The operator is allowed to choose the P-TMSI allocation strategy, subject to the constraints
206// that they should not collide in the same routing area, must not be all 1s, and we dont allow all 0s either.
207// Note that the MS sends RA [Routing Area] along with TMSI.
208// The MS creates a local TLLI from the P-TMSI by setting the top two bits,
209// so the P-TMSI is really limited to 30 bits.
210// For UMTS, the URNTI consists of a 20-bit (really 16-bit, because it must fit in that) UE id
211// plus a 12 bit SRNC id.
212static uint32_t gPTmsiNext = 0;
213static uint32_t allocatePTmsi()
214{
215 if (gPTmsiNext == 0) {
216 // Add in the time to the starting TMSI so if the BTS is restarted there is a better chance
217 // of not using the same tmsis over again.
218 time_t now;
219 time(&now);
220 gPTmsiNext = ((now&0xff)<<12) + 1;
221 }
222 if (gPTmsiNext == 0 || gPTmsiNext >= (1<<30)) { gPTmsiNext = 1; }
223 return gPTmsiNext++;
224 //return Tlli::makeLocalTlli(gPTmsiNext++);
225}
226
227MSUEAdapter *SgsnInfo::getMS() const
228{
229 // The MSInfo struct disappears after a period of time, so look it up.
230 //return GPRS::gL2MAC.macFindMSByTLLI(mMsHandle,0);
231 return SgsnAdapter::findMs(mMsHandle);
232}
233
234GmmInfo::GmmInfo(ByteVector &imsi, uint32_t ptmsi):
235 mImsi(imsi), mState(GmmState::GmmDeregistered), msi(0)
236{
237 memset(mPdps,0,sizeof(mPdps));
238 mPTmsi = ptmsi ? ptmsi : allocatePTmsi();
239 mGprsMultislotClass = -1; // -1 means invalid.
240 mAttachTime = 0;
241 // Must set activityTime to prevent immediate removal from list by another phone simultaneously connection.
242 setActivity();
243 ScopedLock lock(sSgsnListMutex);
244 sGmmInfoList.push_back(this);
245}
246
247GmmInfo::~GmmInfo()
248{
249 freePdpAll(true);
250}
251
252// Assumes sSgsnListMutex is locked on entry.
253static void GmmRemove(GmmInfo *gmm)
254{
255 std::ostringstream ss;
256 gmmInfoDump(gmm,ss,0);
257 //SGSNLOGF(INFO,GPRS_OK|GPRS_MSG,"SGSN","Removing gmm:"<<ss);
258 SGSNLOGF(INFO,GPRS_OK|GPRS_MSG,"SGSN","Removing gmm:"<<(!ss.fail()));
259 SgsnInfo *si;
260 RN_FOR_ALL(SgsnInfoList_t,sSgsnInfoList,si) {
261 // The second test here should be redundant.
262 if (si->getGmm() == gmm || gmm->getSI() == si) {
263 si->sirm(); // yes this is suboptimal, but list is short
264 }
265 }
266#if 0
267 for (SgsnInfoList_t::iterator itr = sSgsnInfoList.begin(); itr != sSgsnInfoList.end(); ) {
268 SgsnInfo *si = *itr;
269 if (si->getGmm() == gmm) {
270 itr = sSgsnInfoList.erase(itr);
271 delete si;
272 } else {
273 itr++;
274 }
275 }
276#endif
277 sGmmInfoList.remove(gmm);
278 delete gmm;
279}
280
281
282// This is for use by the Command Line Interface
283void cliGmmDelete(GmmInfo *gmm)
284{
285 ScopedLock lock(sSgsnListMutex);
286 GmmRemove(gmm);
287}
288
289PdpContext *GmmInfo::getPdp(unsigned nsapi)
290{
291 //return mSndcp[nsapi] ? mSndcp[nsapi]->mPdp : 0;
292 assert(nsapi < sNumPdps);
293 setActivity();
294 return mPdps[nsapi];
295}
296
297// True if the pdpcontext is not in state PDP-INACTIVE
298bool GmmInfo::isNSapiActive(unsigned nsapi)
299{
300 assert(nsapi < sNumPdps);
301 return !(mPdps[nsapi] == 0 || mPdps[nsapi]->isPdpInactive());
302}
303
304// This status is sent back to the MS in messages to indicate what the Network thinks
305// what PDPContexts are currently in use.
306PdpContextStatus GmmInfo::getPdpContextStatus()
307{
308 PdpContextStatus result(true);
309 for (int i = 0; i <= 7; i++) {
310 if (isNSapiActive(i)) { result.mStatus[0] |= (1<<i); }
311 if (isNSapiActive(i+8)) { result.mStatus[1] |= (1<<i); }
312 }
313 return result;
314}
315
316void GmmInfo::connectPdp(PdpContext *pdp, mg_con_t *mgp)
317{
318 // Order may be important here.
319 // We dont want to hook the mgp up until the stack is all connected and prepared
320 // to receive packets, because they could come blasting in any time,
321 // even before any outgoing packets are sent.
322 assert(pdp->mNSapi >= 0 && pdp->mNSapi < (int)sNumPdps);
323 mPdps[pdp->mNSapi] = pdp;
324 // getSI() should never NULL. The mLlcEngine is null in umts.
325 SgsnInfo *si = getSI();
326 assert(si);
327 if (si->mLlcEngine) { si->mLlcEngine->allocSndcp(si,pdp->mNSapi,pdp->mLlcSapi); }
328 if (mgp)
329 mg_con_open(mgp,pdp);
330}
331
332// Return TRUE if the pdp was allocated.
333bool GmmInfo::freePdp(unsigned nsapi)
334{
335 assert(nsapi < sNumPdps);
336 PdpContext *pdp = mPdps[nsapi];
337 mPdps[nsapi] = 0;
338 if (pdp) delete pdp; // This disconnects the mgp also.
339 // getSI() should never be NULL. The mLlcEngine is null in umts.
340#if SNDCP_IN_PDP
341 // sndcp is in the PdpContext and deleted automatically.
342 // Do we want to reset the LLC Sapi? Doubt it because it is shared.
343#else
344 LlcEngine *llc = getSI() ? getSI()->mLlcEngine : NULL;
345 if (llc) { llc->freeSndcp(nsapi); }
346#endif
347 return !!pdp;
348}
349
350void SgsnInfo::deactivateRabs(unsigned nsapiMask)
351{
352#if RN_UMTS
353// MSUEAdapter *ms = getMS();
354// if (ms) {
355// ms->msDeactivateRabs(nsapiMask);
356// } else {
357// SGSNERROR("ggsn: DeactivatePdpContextRequest: MS not found "<<this);
358// }
359#endif
360}
361
362// Return a mask of RABs that were freed.
363unsigned GmmInfo::freePdpAll(bool freeRabsToo)
364{
365 unsigned rabMask = 0;
366 for (unsigned nsapi = 0; nsapi < sNumPdps; nsapi++) {
367 if (freePdp(nsapi)) { rabMask |= 1<<nsapi; }
368 }
369 if (freeRabsToo && rabMask) {
370 // It would be a serious internal error for getSI() to fail, but check anyway.
371 if (getSI()) { getSI()->deactivateRabs(rabMask); }
372 }
373 if (rabMask) addShellRequest("PdpDeactivateAll",this);
374 return rabMask;
375}
376
377void SgsnInfo::sgsnSend2PdpLowSide(int nsapi, ByteVector &packet)
378{
379 PdpContext *pdp = getPdp(nsapi);
380 if (!pdp)
381 return;
382 int id = getConnId();
383 if (id >= 0) {
384 if (pdp->mWaitUpstream)
385 return;
386 unsigned char buf[4];
387 buf[0] = nsapi;
388 buf[1] = buf[2] = buf [3] = 0;
389 gMediaConn.send(id,buf,4,packet.begin(),packet.size());
390 }
391 else
392 pdp->pdpWriteLowSide(packet);
393}
394
395// The rbid is not used by GPRS, and is just 0.
396void SgsnInfo::sgsnSend2MsHighSide(ByteVector &pdu,const char *descr, int rbid, unsigned int sapi)
397{
398 MSUEAdapter *ms = getMS();
399#if RN_UMTS
400 // TODO: It would be safer not to call getMS, but just send the dlpdu through
401 // an InterthreadQueue and let the UMTS or GPRS L2 handle that part in its own thread.
402 // In that case we have to add oldTlli to the message also.
403// if (!ms) {
404// SGSNWARN("no corresponding MS for URNTI " << mMsHandle);
405// return;
406// }
407 // For UMTS we pass the rbid which is an intrinsic part of this channel.
408 // TODO: Update UMTS to use DownlinkPdu too.
409// ms->msWriteHighSide(pdu,rbid,descr);
410#else
411 GmmInfo *gmm = getGmm();
412 uint32_t tlli, aliasTlli = 0;
413 if (gmm && gmm->isRegistered()) {
414 tlli = gmm->getTlli(); // The TLLI based on the assigned P-TMSI.
415 } else {
416 // We send the message using the TLLI of the SgsnInfo,
417 // which is the one the MS used to talk to us.
418 tlli = mMsHandle;
419 // If we know the P-TMSI that will be used for the local TLLI
420 // for this MS after the attach procedure, notify L2.
421 if (gmm) { aliasTlli = gmm->getTlli(); }
422 if (aliasTlli == tlli) { aliasTlli = 0; } // Be tidy; but dont think this can happen.
423 }
424 if (!ms) {
425 LOG(WARNING) << "no corresponding MS for" << this;
426 return;
427 }
428 SGSNLOGF(DEBUG,GPRS_MSG,"SGSN","Creating '" << descr << "' PDU with TLLI=" << LOGVALHEX(tlli) << "," <<LOGVALHEX(aliasTlli) << " for " << ms->msid());
429 GprsSgsnDownlinkPdu *dlpdu = new GprsSgsnDownlinkPdu(pdu,tlli,aliasTlli,descr,sapi);
430 //ms->msWriteHighSide(dlpdu);
431 // This is thread safe:
432 // Go ahead and enqueue it even if there is no MS
433 SgsnAdapter::saWriteHighSide(dlpdu);
434#endif
435}
436
437void SgsnInfo::sgsnWriteHighSideMsg(L3GprsDlMsg &msg)
438{
439#if RN_UMTS
440 // bypass llc
441// ByteVector bv(1000);
442// bv.setAppendP(0,0);
443// msg.gWrite(bv);
444// SGSNLOG("Sending "<<msg.str() <<this);
445// sgsnSend2MsHighSide(bv,msg.mtname(),SRB3); // TODO: Is SRB3 correct?
446#else
447 LlcDlFrame lframe(1000);
448 lframe.setAppendP(0,0);
449 msg.gWrite(lframe);
450 SGSNLOGF(INFO,GPRS_OK|GPRS_MSG,"SGSN","Sending "<<msg.str() <<this<<" frame(first20)="<<lframe.head(MIN(20,lframe.size())));
451 mLlcEngine->getLlcGmm()->lleWriteHighSide(lframe,msg.isSenseCmd(),msg.mtname());
452#endif
453}
454
455// Incoming packets on a PdpContext come here.
456void SgsnInfo::sgsnWriteHighSide(ByteVector &sdu,int nsapi)
457{
458#if RN_UMTS
459 // The PDCP is a complete no-op.
460// sgsnSend2MsHighSide(sdu,"userdata",nsapi);
461#else
462 mLlcEngine->llcWriteHighSide(sdu,nsapi);
463#endif
464}
465
466// TLLI 03.03 2.6, Specified in binary:
467// starts with 11 - local tlli
468// starts with 10 - foreign tlli
469// starts with 01111 - random tlli
470// starts with 01110 - auxiliary tlli.
471// TLLI may not be all 1s, and if it starts with one of the above, cant be all 0s either.
472//struct Tlli {
473// enum Type { Unused, LocalTlli, ForeignTlli, RandomTlli, AuxTlli, UnknownTlli };
474// static Type tlli2Type(uint32_t tlli) {
475// unsigned toptwo = tlli >> (32-2); // It is unsigned, dont have to mask.
476// if (toptwo == 0x3) return LocalTlli;
477// if (toptwo == 0x2) return ForeignTlli;
478// unsigned topfive = tlli >> (32-5); // It is unsigned, dont have to mask.
479// if (topfive == 0x0f) return RandomTlli;
480// if (topfive == 0x0e) return AuxTlli;
481// return UnknownTlli;
482// }
483// //static uint32_t tlli2ptmsi(uint32_t tlli) { return tlli & ~sLocalTlliMask; }
484// // Make a local TLLI
485// //static uint32_t makeLocalTlli(uint32_t tmsi) { return tmsi | sLocalTlliMask; }
486//};
487
488// Return Network Mode of Operation 1,2,3
489static int getNMO()
490{
491 return gConfig.getNum("GPRS.NMO");
492}
493
494static void sendAttachAccept(SgsnInfo *si)
495{
496 si->mT3310FinishAttach.reset();
497 GmmInfo *gmm = si->getGmm();
498 assert(gmm);
499 //L3GmmMsgAttachAccept aa(si->attachResult(),gmm->getPTmsi(),si->mAttachMobileId);
500 uint32_t ptmsi = gmm->getPTmsi();
501 L3GmmMsgAttachAccept aa(si->attachResult(),ptmsi);
502 // We are finished with the attach procedure now.
503 // Note that we are using the si (and TLLI) that the message was sent on.
504 // If the BTS and the MS disagreed on the attach state at the start of this procedure,
505 // we reset the MS registration to match what the MS thinks to make sure we will
506 // use the old TLLI in the si, not the new one based on the PTMSI.
507 si->sgsnWriteHighSideMsg(aa);
508}
509
510static void sendAttachReject(SgsnInfo *si, unsigned cause)
511{
512 L3GmmMsgAttachReject ar(cause);
513 si->sgsnWriteHighSideMsg(ar);
514}
515
516static void handleAttachStep(SgsnInfo *si)
517{
518 GmmInfo *gmm = si->getGmm();
519 if (!gmm) { // This cannot happen.
520 SGSNLOGF(ERR,GPRS_ERR,"SGSN","No imsi found for MS during Attach procedure"<<si);
521 return;
522 }
523#if RN_UMTS
524 assert(0);
525 // Must do the Security Proecedure first, message flow like this:
526 // L3 AttachRequest
527 // MS ---------------------------------> Network
528 // RRC SecurityModeCommand
529 // MS <--------------------------------- Network
530 // RRC SecurityModeComplete
531 // MS ---------------------------------> Network
532 // L3 AttachAccept
533 // MS <--------------------------------- Network
534 // (pat) Update: Havind added the authentication for NMO I in here,
535 // so the above procedure is now moved to
536
537 // If we are in NMO 2, authentication was allegedly already done by
538 // the Mobility Management protocol layer, in which case there is
539 // a Kc sitting in the TMSI table.
540 // We need to pass it a nul-terminated IMSI string.
541// string IMSI = gmm->mImsi.hexstr();
542 //int len = gmm->mImsi.size();
543 //char imsi[len+2];
544 //memcpy(imsi,gmm->mImsi.hexstr().c_str(),len);
545 //imsi[len] = 0;
546// LOG(INFO) << "Looking up Kc for imsi " << IMSI;
547// string Kcs = gTMSITable.getKc(IMSI.c_str());
548// if (Kcs.length() <= 1) {
549// SGSNERROR("No Kc found for MS in TMSI table during Attach procedure"<<si);
550 // need to do authentication, send authentication request
551 //sendAuthenticationRequest(si);
552// }
553// sendAuthenticationRequest(si,IMSI);
554#else
555 // We must use the TLLI that the MS used, not the PTMSI.
556 // To do that, reset the registered status.
557 switch (si->mtAttachInfo.mMsgType) {
558 case L3GmmMsg::AttachRequest:
559 gmm->setGmmState(GmmState::GmmDeregistered);
560 sendAttachAccept(si);
561 break;
562 case L3GmmMsg::RoutingAreaUpdateRequest:
563 {
564 L3GmmMsgRAUpdateAccept raa(si->mtAttachInfo.mRAUpdateType,si->getPdpContextStatus(),
565 gmm->getPTmsi(),0);
566 si->sgsnWriteHighSideMsg(raa);
567 break;
568 }
569 default:
570 SGSNLOGF(INFO,GPRS_ERR,"SGSN","Unmatched attach response "<<si);
571 break;
572 }
573#endif
574}
575
576#if RN_UMTS
577// Called from UMTS when it receives the SecurityModeComplete or SecurityModeFailure msg.
578//void MSUEAdapter::sgsnHandleSecurityModeComplete(bool success)
579//{
580// SgsnInfo *si = sgsnGetSgsnInfo();
581// // The si would only be null if the UE sent us a spurious SecurityModeComplete command.
582// if (si == NULL) {
583// SGSNERROR("Received spurious SecurityMode completion command for UE:"<<msid());
584// return;
585// }
586// if (! si->mT3310FinishAttach.active()) {
587// SGSNERROR("Received security response after T3310 expiration for UE:"<<si);
588// return;
589// }
590// if (success) {
591// sendAttachAccept(si); // happiness
592// } else {
593// SGSNERROR("Integrity Protection failed for UE:"<<si);
594// // Oops! We could send an attach reject, but why bother?
595// // The UE already knows it failed, no recovery is possible,
596// // and it will timeout shortly anyway.
597// }
598//}
599#endif
600
601static void adjustConnectionId(SgsnInfo *si)
602{
603 SGSNLOGF(INFO,GPRS_OK|GPRS_MSG,"SGSN","adjusting connection" << si);
604 int id = si->getConnId();
605 if (id == GprsConnNone) { // GmmInfo conn ID is none
606 id = si->mConnId;
607 if (id == GprsConnNone) // also none in SigInfo
608 return;
609 si->setConnId(id);
610 }
611 SgsnInfo* si2 = gGprsMap.find(id);
612 if (si == si2) {
613 si->setConnId(id);
614 return;
615 }
616 if (si2) {
617 // we already have a different SgsnInfo mapped on the id of the GmmInfo
618 // we want to replace it in the mapping
619 // first make sure to unmap the current SgsnInfo connection Id
620 // and release its own connection id
621 SGSNLOGF(INFO,GPRS_OK|GPRS_MSG,"SGSN","replacing TLLI" << LOGHEX2("old",si2->mMsHandle)
622 << LOGHEX2("with new",si->mMsHandle) << " in connection " << id);
623 if (gGprsMap.unmap(si) && si->mConnId >= 0)
624 gSigConn.send(SigConnLost,0,si->mConnId);
625 // remove the ownership of the GmmInfo connection id from the old SgsnInfo
626 si2->mConnId = GprsConnNone;
627 }
628 si->setConnId(id);
629 gGprsMap.remap(si,id);
630}
631
632static unsigned int sendConnAttachReq(SgsnInfo *si, bool authenticated = false)
633{
634 int id = si->getConnId();
635 if (id < 0) {
636 id = si->mConnId;
637 si->mConnId = si->getConnId();
638 if (id >= 0) {
639 // This can happen if we just re-identified a locally handled IMSI
640 gGprsMap.unmap(si);
641 gSigConn.send(SigConnLost,0,id);
642 }
643 return GmmCause::Congestion;
644 }
645 bool update = (si->mtAttachInfo.mMsgType == L3GmmMsg::RoutingAreaUpdateRequest);
646 GmmInfo *gmm = si->getGmm();
647 std::ostringstream buf;
648 buf << "tlli=" << hex << std::setw(8) << std::setfill('0') << si->mMsHandle;
649 if (gmm) {
650 buf << " imsi=" << gmm->mImsi.hexstr();
651 if (!gmm->mImei.empty())
652 buf << " imei=" << gmm->mImei;
653 }
654 else {
655 uint32_t ptmsi = si->mtAttachInfo.mAttachReqPTmsi;
656 if (update && !ptmsi) {
657 if ((si->mMsHandle & 0x80000000)) {
658 ptmsi = (si->mMsHandle | 0x40000000);
659 // remember this ptmsi, we don't want GmmInfo to alloc one
660 // and SGSN will return IMSI
661 si->mtAttachInfo.mAttachReqPTmsi = ptmsi;
662 }
663 else
664 return GmmCause::Implicitly_detached;
665 }
666 buf << " ptmsi=" << hex << std::setw(8) << std::setfill('0') << ptmsi;
667 }
668 if (si->mAUTS.size()) {
669 buf << " rand=" << si->mRAND.hexstr();
670 buf << " auts=" << si->mAUTS.hexstr();
671 si->mAUTS.clear();
672 }
673 buf << " authenticated=" << (authenticated ? "true" : "false");
674 if (update)
675 buf << " pdps=" << hex << std::setw(4) << std::setfill('0') << si->mtAttachInfo.mPdpContextStatus.toInt();
676 return (gSigConn.send(SigGprsAttachReq,0,id,buf.str()) ? 0 : GmmCause::Congestion);
677}
678
679static void handleAuthenticationResponse(SgsnInfo *si, L3GmmMsgAuthenticationResponse &armsg)
680{
681 GmmInfo *gmm = si->getGmm();
682 if (!gmm) {
683 SGSNLOGF(ERR,GPRS_ERR,"SGSN","No imsi found for MS during Attach procedure"<<si);
684 return;
685 }
686
687 if (armsg.mSRES != si->mSRES) {
688 SGSNLOGF(INFO,GPRS_OK|GPRS_MSG,"SGSN","Authentication error on" << si << LOGVAR(armsg.mSRES) << LOGVAR(si->mSRES));
689 si->clearConn(GprsConnNone,SigConnLost);
690 return;
691 }
692 if (armsg.mMobileId.isImeiSv())
693 gmm->mImei = armsg.mMobileId.getAsBcd();
694
695 switch (si->getConnId()) {
696 case GprsConnNone:
697 sendImplicitlyDetached(si);
698 return;
699 case GprsConnLocal:
700 handleAttachStep(si);
701 return;
702 }
703 sendConnAttachReq(si,true);
704}
705
706static void handleAuthenticationFailure(SgsnInfo *si, L3GmmMsgAuthenticationFailure &afmsg)
707{
708 GmmInfo *gmm = si->getGmm();
709 if (!gmm) {
710 SGSNLOGF(ERR,GPRS_ERR,"SGSN","No imsi found for MS during Attach procedure"<<si);
711 return;
712 }
713
714 if ((si->getConnId() < 0) || !afmsg.mAUTS.size() || !si->mRAND.size()) {
715 sendImplicitlyDetached(si);
716 return;
717 }
718 si->mAUTS = afmsg.mAUTS;
719 sendConnAttachReq(si,false);
720}
721
722static void handleIdentityResponse(SgsnInfo *si, L3GmmMsgIdentityResponse &irmsg)
723{
724 if (! si->mT3310FinishAttach.active()) {
725 // Well that is interesting. We got a spurious identity response.
726 SGSNLOGF(ERR,GPRS_ERR,"SGSN","unexpected message:"<<irmsg.str());
727 return;
728 } else {
729 // The MS sent an attach request. Try to send the response using the new IMSI.
730 if (! irmsg.mMobileId.isImsi()) {
731 SGSNLOGF(ERR,GPRS_ERR,"SGSN","Identity Response message does not include imsi:"<<irmsg.str());
732 return;
733 }
734 ByteVector passbyreftmp = irmsg.mMobileId.getImsi(); // c++ foo bar
735 findGmmByImsi(passbyreftmp,si); // Always succeeds - creates if necessary, sets si->mGmmp.
736 adjustConnectionId(si);
737
738 // Use the imsi as the mobileId in the AttachAccept.
739 //si->mAttachMobileId = irmsg.mMobileId;
740 if (sendConnAttachReq(si))
741 handleAttachStep(si);
742 //si->mT3310FinishAttach.reset();
743 //GmmInfo *gmm = findGmmByImsi(passbyreftmp,si); // Always succeeds - creates if necessary.
744 // TODO: Why do we send the mobileid? It seems to Work this way, just wondering, because
745 // the message is delivered to the MS based on the L2 connection as defined by si.
746 //L3GmmMsgAttachAccept aa(si->attachResult(),gmm->getPTmsi(),irmsg.mMobileId);
747 //si->sgsnWriteHighSideMsg(aa);
748 }
749}
750
751void AttachInfo::stashMsgInfo(GMMAttach &msgIEs,
752 bool isAttach, int msgType) // true: attach request; false: RAUpdate
753{
754 mMsgType = msgType;
755 // Save the MCC and MNC from which the MS drifted in on for reporting.
756 // We only save them the first time we see them, because I am afraid
757 // after that they will revert to our own MCC and MNC.
758 if (! mPrevRaId.valid()) { mPrevRaId = msgIEs.mOldRaId; }
759
760 //if (mOldMcc[0] == 0 && mOldMcc[1] == 0) {
761 // for (int i = 0; i < 3; i++) { mOldMcc[i] = DEHEXIFY(msgIEs.mOldRaId.mMCC[i]); }
762 //}
763 //if (mOldMnc[0] == 0 && mOldMnc[1] == 0) {
764 // for (int i = 0; i < 3; i++) { mOldMnc[i] = DEHEXIFY(msgIEs.mOldRaId.mMNC[i]); }
765 //}
766
767 // If a PTMSI was specified in the AttachRequest we need to remember it.
768 if (isAttach && msgIEs.mMobileId.isTmsi()) {
769 mAttachReqPTmsi = msgIEs.mMobileId.getTmsi();
770 }
771
772 if (msgIEs.mMsRadioAccessCapability.size()) {
773 mMsRadioAccessCap = msgIEs.mMsRadioAccessCapability;
774 }
775 //mAttachMobileId = msgIEs.mMobileId;
776 //if (msgIEs.mPdpContextStatus.valid())
777 mPdpContextStatus = msgIEs.mPdpContextStatus;
778}
779
780void AttachInfo::copyFrom(AttachInfo &other)
781{
782 if (! mPrevRaId.valid()) { mPrevRaId = other.mPrevRaId; }
783 if (! mAttachReqPTmsi) { mAttachReqPTmsi = other.mAttachReqPTmsi; }
784 if (! mAttachReqType) { mAttachReqType = other.mAttachReqType; }
785 mRAUpdateType = other.mRAUpdateType;
786 mPdpContextStatus = other.mPdpContextStatus;
787 if (other.mMsRadioAccessCap.size()) {
788 mMsRadioAccessCap = other.mMsRadioAccessCap;
789 }
790 mMsgType = other.mMsgType;
791}
792
793void AttachInfo::reset()
794{
795 mAttachReqType = (AttachType) 0;
796 mAttachReqPTmsi = 0;
797 mRAUpdateType = RAUpdated;
798 mMsgType = -1;
799}
800
801void sendImplicitlyDetached(SgsnInfo *si, unsigned type, unsigned cause)
802{
803 GmmInfo* gmm = si->getGmm();
804 if (gmm && gmm->isRegistered() && (gmm->getSI() == si))
805 gmm->setGmmState(GmmState::GmmRegistrationPending);
806 L3GmmMsgGmmStatus statusMsg(GmmCause::Implicitly_detached);
807 si->sgsnWriteHighSideMsg(statusMsg);
808 // The above didn't do it, so try sending one of these too:
809 // Detach type 1 means re-attach required.
810 //L3GmmMsgDetachRequest dtr(1,GmmCause::Implicitly_detached);
811 // 7-2012: Tried taking out the cause to stop the Multitech modem
812 // sending 'invalid mandatory information'.
813 // The only reason obvious to send that is in 24.008 8.5 is an unexpected IE,
814 // so maybe it is the cause. But it did not help.
815 L3GmmMsgDetachRequest dtr(type,cause);
816 si->sgsnWriteHighSideMsg(dtr);
817}
818
819static void sendIdentityRequest(SgsnInfo *si)
820{
821 // 3GPP 24.008 11.2.2 When T3370 expires we can send another Identity Request.
822 // However we are also going to use it inverted, and send Identity Requests
823 // no closer together than T3370.
824 // If this expires, the MS will try again.
825 if (si->mT3370ImsiRequest.active() && !si->mT3370ImsiRequest.expired())
826 return;
827 // Send off a request for the imsi.
828 L3GmmMsgIdentityRequest irmsg;
829 si->mT3370ImsiRequest.set();
830 // We only use the timer in this case, so we only set it in this case, instead
831 // of at the top of this function.
832 si->mT3310FinishAttach.set();
833 si->sgsnWriteHighSideMsg(irmsg);
834}
835
836// Complete the attach request locally
837static void handleAttachRequestLocally(SgsnInfo *si, GmmInfo *gmm)
838{
839 // 7-1-2012: Working on multitech modem failure to reattach bug.
840 // I tried taking this out to send an extra identity request,
841 // but then the modem did not respond to that identity request,
842 // just like before it did not respond to the second attach request.
843 // Even after deleting all but that single SgsnInfo, and modifying the msid
844 // to print both tllis, and looking at pat.log the message is definitely
845 // sent on the correct TLLi.
846 // But if you tell the modem to detach and then try attach again,
847 // then the modem uses a new TLLI and sends an IMSI, so it thinks
848 // it was attached, but it is sending an attach request anyway, with a PTMSI.
849 // But the first attach used a PTMSI, and it succeeded.
850 // Things to try: send protocol incompabible blah blah.
851 // Try converting to local tlli (0xc...); I tried that before but maybe
852 // the tlli change procedure was wrong back then.
853 // Send a detach, although I think the modem ignores this.
854 if (!gmm) {
855 // We need need to ask for an imsi.
856 // There is a slight problem that we only have 6 seconds to register the MS,
857 // which may not be enough time to do the IdentityResponse Challenge.
858 // Therefore we save the IMSI associated with the TLLI that we got from the Identity response
859 // challenge in the SgsnInfo, and when the MS tries again with the same TLLI,
860 // we can skip the IdentityRequest phase.
861 sendIdentityRequest(si);
862 return;
863 }
864#if 0
865 // We dont care if the MS already had a P-TMSI.
866 // If it is doing an attach, go ahead and assign a new one.
867 if (!si->mAllocatedTmsiTlli) {
868 si->mAllocatedTmsiTlli = Sgsn::allocateTlli();
869 }
870 // We cant set the tlli in the MS until it has received the new tlli,
871 // because we have to use the previous tlli to talk to it.
872#endif
873 // This was for testing:
874 //L3GmmMsgIdentityRequest irmsg;
875 //si->sgsnWriteHighSideMsg(irmsg);
876
877 // We are assigning this ptmsi to the MS.
878 handleAttachStep(si);
879 //si->mT3310FinishAttach.reset();
880 //L3GmmMsgAttachAccept aa(si->attachResult(),gmm->getPTmsi(),armsg.mMobileId);
881 //si->sgsnWriteHighSideMsg(aa);
882}
883
884// The ms may send a P-TMSI or IMSI in the mobile id.
885static void handleAttachRequest(SgsnInfo *si, L3GmmMsgAttachRequest &armsg)
886{
887 switch ((AttachType) (unsigned) armsg.mAttachType) {
888 case AttachTypeGprsWhileImsiAttached:
889 SGSNLOGF(INFO,GPRS_MSG,"SGSN","NOTICE attach type "<<(int)armsg.mAttachType <<si);
890 // Fall through
891 case AttachTypeGprs:
892 si->mtAttachInfo.mAttachReqType = AttachTypeGprs;
893 break;
894 case AttachTypeCombined:
895 if (getNMO() != 1) {
896 // The MS should not have done this.
897 LOG(ERR)<<"Combined Attach attempt incompatible with NMO 1 "<<si;
898 } else {
899 SGSNLOGF(INFO,GPRS_OK,"SGSN","NOTICE attach type "<<(int)armsg.mAttachType <<si);
900 }
901 si->mtAttachInfo.mAttachReqType = AttachTypeCombined;
902 break;
903 }
904 //uint32_t newptmsi;
905
906 // Save info from the message:
907 si->mtAttachInfo.stashMsgInfo(armsg,true,armsg.MTI());
908
909 // Re-init the state machine.
910 // If the MS does a re-attach, we may have an existing SgsnInfo from earlier, so we must reset it now:
911 // si->sgsnReset(); // 6-3-2012: changed to just freePdpAll.
912 si->freePdpAll(true);
913
914 GmmInfo *gmm = si->getGmm();
915 if (gmm && armsg.mMobileId.isTmsi())
916 gmm->setPTmsi(armsg.mMobileId.getTmsi());
917 else if (!gmm && armsg.mMobileId.isImsi()) {
918 // The MS included the IMSI in the attach request
919 ByteVector imsi = armsg.mMobileId.getImsi();
920 gmm = findGmmByImsi(imsi,si); // Create the gmm and associate with si.
921 }
922
923 SgsnInfo *si2 = 0;
924 if (si->mConnId >= 0) {
925 si2 = gGprsMap.find(si->mConnId);
926 if (si2 != si) {
927 SGSNLOGF(INFO,GPRS_CHECK_FAIL,"SGSN","Reset connection of unmapped" << si);
928 si->mConnId = GprsConnNone;
929 if ((si->getConnId() >= 0) && !si2)
930 si->setConnId(GprsConnNone); // Clear connection in GmmInfo
931 }
932 }
933 switch (si->getConnId()) {
934 case GprsConnNone:
935 {
936 // Allocate a connection if this is the first time
937 if (si2 && (si2->mConnId >= 0)) {
938 SGSNLOGF(INFO,GPRS_CHECK_FAIL,"SGSN","replacing TLLI" << LOGHEX2("old",si2->mMsHandle) << LOGHEX2("with new",si->mMsHandle) << " in connection " << si2->mConnId);
939 gGprsMap.remap(si,si2->mConnId);
940 si->setConnId(si2->mConnId);
941 }
942 else
943 si->setConnId(gGprsMap.map(si));
944 GmmCause::Cause cause = GmmCause::Congestion;
945 if (si->getConnId() >= 0) {
946 // Make sure current TLLI is the primary in MS info
947 MSUEAdapter *ms = si->getMS();
948 if (ms)
949 ms->msChangeTlli(si->mMsHandle);
950 if (gmm)
951 gmm->msi = si;
952 SGSNLOGF(INFO,GPRS_CHECK_OK,"SGSN","Connection allocated to" << si);
953 if (!(cause = (GmmCause::Cause)sendConnAttachReq(si)))
954 return;
955 }
956 sendAttachReject(si,cause);
957 si->sirm();
958 return;
959 }
960 case GprsConnLocal:
961 break;
962 default:
963 // Already sent upstream a SigGprsAttachReq and we have an ID
964 sendConnAttachReq(si);
965 return;
966 }
967
968 handleAttachRequestLocally(si,gmm);
969}
970
971
972static void handleAttachComplete(SgsnInfo *si, L3GmmUlMsg &msg)
973{
974 // The ms is acknowledging receipt of the new tlli.
975 GmmInfo *gmm = si->getGmm();
976 if (!gmm) {
977 // The attach complete does not match this ms state.
978 // Happens, for example, when you first turn on the bts and the ms
979 // is still trying to complete a previous attach. Ignore it.
980 // The MS will timeout and try to attach again.
981 SGSNLOGF(INFO,GPRS_CHECK_FAIL|GPRS_ERR,"SGSN","Ignoring spurious " << msg.mtname() << " " << si);
982 // Dont send a reject because we did not reject anything.
983 return;
984 }
985 //SGSNLOG("attach complete gmm="<<((uint32_t)gmm));
986 gmm->setGmmState(GmmState::GmmRegisteredNormal);
987 gmm->setAttachTime();
988 gmm->msi = si;
989#if RN_UMTS
990#else
991 // Start using the tlli associated with this imsi/ptmsi when we talk to the ms.
992 SgsnInfo* othersi = si->changeTlli(true);
993#endif
994 if (othersi->getConnId() >= 0) {
995 adjustConnectionId(othersi);
996 MSUEAdapter *ms = othersi->getMS();
997 if (ms)
998 ms->msChangeTlli(othersi->mMsHandle);
999 gSigConn.send(SigGprsAttachOk,1,othersi->getConnId());
1000 }
1001 if (msg.MTI() == L3GmmMsg::AttachComplete)
1002 addShellRequest("GprsAttach",gmm);
1003 si->mtAttachInfo.reset();
1004
1005#if 0 // nope, we are going to pass the TLLI down with each message and let GPRS deal with it.
1006 //if (! Sgsn::isUmts()) {
1007 // // Update the TLLI in all the known MS structures.
1008 // // Only the SGSN knows that the MSInfo with these various TLLIs
1009 // // are in fact the same MS. But GPRS needs to know because
1010 // // the MS will continue to use the old TLLIs, and it will botch
1011 // // up if, for example, it is in the middle of a procedure on one TLLI
1012 // // and the MS is using another TLLI, which is easy to happen given the
1013 // // extremely long lag times in message flight.
1014 // // The BSSG spec assumes there only two TLLIs, but I have seen
1015 // // the Blackberry use three simultaneously.
1016 // SgsnInfo *sip;
1017 // uint32_t newTlli = gmm->getTlli();
1018 // RN_FOR_ALL(SgsnInfoList_t,sSgsnInfoList,sip) {
1019 // if (sip->getGmm == gmm) {
1020 // UEAdapter *ms = sip->getMS();
1021 // // or should we set the ptmsi??
1022 // if (ms) ms->changeTlli(newTlli);
1023 // }
1024 // }
1025 //}
1026#endif
1027}
1028
1029static void handleDetachRequest(SgsnInfo *si, L3GmmMsgDetachRequest &drmsg)
1030{
1031 L3GmmMsgDetachAccept detachAccept(0);
1032 GmmInfo *gmm = si->getGmm();
1033 if (!gmm) {
1034 // Hmm, but fall through, because it is certainly detached.
1035 } else {
1036 gmm->setGmmState(GmmState::GmmDeregistered);
1037 }
1038 si->sgsnWriteHighSideMsg(detachAccept);
1039 si->sgsnReset(drmsg.mDetachType);
1040 if (gmm) addShellRequest("GprsDetach",gmm);
1041}
1042
1043static void sendRAUpdateReject(SgsnInfo *si, unsigned cause)
1044{
1045 L3GmmMsgRAUpdateReject raur(cause);
1046 si->sgsnWriteHighSideMsg(raur);
1047}
1048
1049// TODO: Need to follow 4.7.13 of 24.008
1050static void handleServiceRequest(SgsnInfo *si, L3GmmMsgServiceRequest &srmsg)
1051{
1052 GmmInfo *gmm = si->getGmm();
1053 // TODO: Should we check the PTmsi and the PDP context status???
1054 if (!gmm) {
1055 L3GmmMsgServiceReject sr(GmmCause::Implicitly_detached);
1056 si->sgsnWriteHighSideMsg(sr);
1057 return;
1058 } else {
1059 gmm->setActivity();
1060 L3GmmMsgServiceAccept sa(si->getPdpContextStatus());
1061 si->sgsnWriteHighSideMsg(sa);
1062 }
1063}
1064
1065// 24.008 4.7.5, and I quote:
1066// "The routing area updating procedure is always initiated by the MS.
1067// It is only invoked in state GMM-REGISTERED."
1068// The MS may send an mMobileId containing a P-TMSI, and it sends TmsiStatus
1069// telling if it has a valid TMSI.
1070static void handleRAUpdateReqLocally(SgsnInfo *si, GmmInfo *gmm)
1071{
1072 if (!gmm) {
1073 sendRAUpdateReject(si,GmmCause::Implicitly_detached);
1074 return;
1075 }
1076 L3GmmMsgRAUpdateAccept raa(si->mtAttachInfo.mRAUpdateType,si->getPdpContextStatus(),
1077 gmm->getPTmsi(),0);
1078 si->sgsnWriteHighSideMsg(raa);
1079}
1080
1081static void handleRAUpdateRequest(SgsnInfo *si, L3GmmMsgRAUpdateRequest &raumsg)
1082{
1083 SGSNLOGF(INFO,GPRS_CHECK_FAIL,"SGSN","Received RA Update Req on " << si);
1084 switch (raumsg.mUpdateType) {
1085 case RAUpdated:
1086 case PeriodicUpdating:
1087 raumsg.mUpdateType = RAUpdated;
1088 break;
1089 case CombinedRALAUpdated:
1090 case CombinedRALAWithImsiAttach:
1091 LOG(WARNING) << "Combined RA/LA update requested is not supported,"
1092 " overwriting it to RA update" << si;
1093 raumsg.mUpdateType = RAUpdated;
1094 break;
1095 }
1096 si->mtAttachInfo.mRAUpdateType = (RAUpdateType)(unsigned)raumsg.mUpdateType;
1097 si->mtAttachInfo.stashMsgInfo(raumsg,false,raumsg.MTI());
1098
1099 GmmInfo *gmm = si->getGmm();
1100 if (gmm)
1101 // make sure to use during RAUpdate procudere the TLLI with which the MS came
1102 gmm->setGmmState(GmmState::GmmRegistrationPending);
1103
1104 SgsnInfo *si2 = 0;
1105 if (si->mConnId >= 0) {
1106 si2 = gGprsMap.find(si->mConnId);
1107 if (si2 != si) {
1108 SGSNLOGF(INFO,GPRS_CHECK_FAIL,"SGSN","Reset connection of unmapped" << si);
1109 si->mConnId = GprsConnNone;
1110 if ((si->getConnId() >= 0) && !si2)
1111 si->setConnId(GprsConnNone); // Clear connection in GmmInfo
1112 }
1113 }
1114 switch (si->getConnId()) {
1115 case GprsConnNone:
1116 {
1117 // Allocate a connection if this is the first time
1118 if (si2 && (si2->mConnId >= 0)) {
1119 SGSNLOGF(INFO,GPRS_CHECK_FAIL,"SGSN","replacing TLLI" << LOGHEX2("old",si2->mMsHandle) << LOGHEX2("with new",si->mMsHandle) << " in connection " << si2->mConnId);
1120 gGprsMap.remap(si,si2->mConnId);
1121 si->setConnId(si2->mConnId);
1122 }
1123 else
1124 si->setConnId(gGprsMap.map(si));
1125 GmmCause::Cause cause = GmmCause::Congestion;
1126 if (si->getConnId() >= 0) {
1127 // Make sure current TLLI is the primary in MS info
1128 MSUEAdapter *ms = si->getMS();
1129 if (ms)
1130 ms->msChangeTlli(si->mMsHandle);
1131 if (gmm)
1132 gmm->msi = si;
1133 SGSNLOGF(INFO,GPRS_CHECK_OK,"SGSN","Connection allocated to" << si);
1134 if (!(cause = (GmmCause::Cause)sendConnAttachReq(si)))
1135 return;
1136 }
1137 sendRAUpdateReject(si,cause);
1138 si->sirm();
1139 return;
1140 }
1141 case GprsConnLocal:
1142 break;
1143 default:
1144 {
1145 // we might have a SgsnInfo with ConnId=None and GmmInfo with valid connID from a previous attach request
1146 // make sure to reset the mapping
1147 adjustConnectionId(si);
1148 GmmCause::Cause cause = GmmCause::Congestion;
1149 if (!(cause = (GmmCause::Cause)sendConnAttachReq(si)))
1150 return;
1151 sendRAUpdateReject(si,cause);
1152 si->sirm();
1153 return;
1154 }
1155 }
1156 // otherwise - handle locally
1157 handleRAUpdateReqLocally(si,gmm);
1158}
1159
1160static inline void handleRAUpdateComplete(SgsnInfo *si, L3GmmMsgRAUpdateComplete &racmsg)
1161{
1162 handleAttachComplete(si,racmsg);
1163}
1164
1165// This message may arrive on a DCCH channel via the GSM RR stack, rather than a GPRS message,
1166// and as such, could be running in a separate thread.
1167// We queue the message for processing.
1168// The suspension may be user initiated or by the MS doing some RR messages,
1169// most often, Location Area Update. The spec says we are supposed to freeze
1170// the LLC state and continue after resume. But in the permanent case any incoming packets
1171// will be hopelessly stale after resumption, so we just toss them. Note that web sites chatter
1172// incessantly with keepalives even when they look quiescent to the user, and we dont want
1173// all that crap to back up in the downlink queue.
1174// In the temporary case, which is only a second or two, we will attempt to preserve the packets
1175// to prevent a temporary loss of service. I have observed that the MS first stops responding
1176// to the BSS for about a second before sending the RACH to initiate the RR procedure,
1177// so there is no warning at all. However, we MUST cancel the TBFs. If we dont, and after
1178// finishing the RR procedure the MS gets back to GPRS before the previous TBFs timeout,
1179// it assumes they are new TBFs, which creates havoc, because the acknacks do not correspond
1180// to the previous TBF. This generates the "STUCK" condition, up to a 10 second loss of service,
1181// and I even saw the Blackberry detach and reattach to recover.
1182// In either case the MS signals resumption by sending us anything on the uplink.
1183// WARNING: This runs in a different thread.
1184bool Sgsn::handleGprsSuspensionRequest(uint32_t wTlli,
1185 const ByteVector &wraid) // The Routing Area id.
1186{
1187 SGSNLOGF(INFO,GPRS_MSG,"SGSN","Received GPRS SuspensionRequest for"<<LOGHEX2("tlli",wTlli));
1188 MSUEAdapter* ms = SgsnAdapter::findMs(wTlli);
1189 if (!ms) {
1190 GLOG(NOTICE) << "Received GPRS suspension request for unknown TLLI=" << LOGVALHEX(wTlli);
1191 return false;
1192 }
1193 GmmState::state tlliState = ms->suspend();
1194 return tlliState == GmmState::GmmRegisteredSuspended;
1195 // TODO:
1196 // if sgsn not enabled, return false.
1197 // save the channel?
1198 // Send the resumption ie in the RR channel release afterward.
1199}
1200
1201// WARNING: This runs in a different thread.
1202void Sgsn::notifyGsmActivity(const char *imsi)
1203{
1204}
1205
1206// WARNING: This runs in a different thread
1207void Sgsn::sendPaging(const char* imsi, uint32_t tmsi, GSM::ChannelType chanType)
1208{
1209 if (!imsi)
1210 return;
1211 ByteVector imsiBv;
1212 if (!imsiBv.fromBcd(imsi)) {
1213 GPRSLOG(NOTICE,GPRS_MSG) << "Failed to unhexify received IMSI=" << imsi;
1214 return;
1215 }
1216 GmmInfo* gmm = findGmmByImsi(imsiBv,0);
1217 if (!(gmm && gmm->getGmmState() == GmmState::GmmRegisteredNormal))
1218 return;
1219 MSUEAdapter* ms = SgsnAdapter::findMs(gmm->getTlli());
1220 if (!ms)
1221 return;
1222 ms->page(imsiBv,tmsi,chanType);
1223}
1224
1225// Utility function to reject a PDP context activation
1226static void sendPdpContextReject(SgsnInfo *si,SmCause::Cause cause,unsigned ti)
1227{
1228 L3SmMsgActivatePdpContextReject pdpRej(ti,cause);
1229 si->sgsnWriteHighSideMsg(pdpRej);
1230}
1231
1232// Utility function to extract prefixed string
1233static std::string getPrefixed(const char* tag, const char* buf)
1234{
1235 std::string str;
1236 if (tag && buf) {
1237 const char* start = ::strstr(buf,tag);
1238 if (start) {
1239 start += ::strlen(tag);
1240 const char* end = ::strchr(start,' ');
1241 if (end)
1242 str.assign(start,end - start);
1243 else
1244 str.assign(start);
1245 }
1246 }
1247 return str;
1248}
1249
1250// Utility function to convert a string to integer
1251static long toInteger(const char* str, long defVal = -1)
1252{
1253 if (!str || !*str)
1254 return defVal;
1255 char* eptr = 0;
1256 long val = ::strtol(str,&eptr,0);
1257 return (!eptr || *eptr) ? defVal : val;
1258}
1259
1260inline static long toInteger(const std::string& str, long defVal = -1)
1261{
1262 return toInteger(str.c_str(),defVal);
1263}
1264
1265// Utility function to convert a string to boolean
1266static bool toBoolean(const char* str, bool defVal = false)
1267{
1268 if (!str || !*str)
1269 return defVal;
1270 if (!::strcmp(str,"true"))
1271 return true;
1272 if (!::strcmp(str,"false"))
1273 return false;
1274 return defVal;
1275}
1276
1277inline static bool toBoolean(const std::string& str, bool defVal = false)
1278{
1279 return toBoolean(str.c_str(),defVal);
1280}
1281
1282// Utility function to pick IMSI and P-TMSI and attach a new GmmInfo if needed
1283void setMsi(SgsnInfo* si, const char* text)
1284{
1285 GmmInfo *gmm = si->getGmm();
1286 if (!gmm) {
1287 ByteVector imsi;
1288 imsi.fromBcd(getPrefixed("imsi=",text));
1289 if (imsi.size()) {
1290 gmm = findGmmByImsi(imsi,si,si->mtAttachInfo.mAttachReqPTmsi);
1291 adjustConnectionId(si);
1292 gmm->setGmmState(GmmState::GmmRegistrationPending);
1293 }
1294 }
1295 if (gmm) {
1296 std::string str = getPrefixed("ptmsi=",text);
1297 if (!str.empty()) {
1298 long int ptmsi = ::strtol(str.c_str(),0,16);
1299 if ((ptmsi > 0) && (ptmsi != gmm->getPTmsi())) {
1300 gmm->setPTmsi(ptmsi);
1301 adjustConnectionId(si);
1302 findSgsnInfoByHandle(ptmsi,true)->setGmm(gmm);
1303 }
1304 }
1305 }
1306}
1307
1308// Application needs IMSI in attach request
1309void SgsnConn::identityReq(SgsnInfo* si)
1310{
1311 sendIdentityRequest(si);
1312}
1313
1314// Application requests authentication
1315// Provides RAND, SRES, possibly AUTN, Kc or Ik+Ck
1316void SgsnConn::authRequest(SgsnInfo* si, const char* text)
1317{
1318 setMsi(si,text);
1319 if (si->getConnId() < 0) {
1320 // This can happen if we just re-identified a detached or locally handled IMSI
1321 int id = si->mConnId;
1322 si->mConnId = si->getConnId();
1323 if (id >= 0) {
1324 gGprsMap.unmap(si);
1325 gSigConn.send(SigConnLost,0,id);
1326 }
1327 if (si->getConnId() == GprsConnLocal)
1328 handleAttachRequestLocally(si,si->getGmm());
1329 return;
1330 }
1331 si->mRAND.fromHexa(getPrefixed("rand=",text));
1332 if (!si->mRAND.size()) {
1333 SGSNLOGF(ERR,GPRS_ERR,"SGSN","Missing RAND for" << si);
1334 return;
1335 }
1336 si->mSRES.fromHexa(getPrefixed("sres=",text));
1337 si->mKc.fromHexa(getPrefixed("kc=",text));
1338 si->mCk.fromHexa(getPrefixed("ck=",text));
1339 si->mIk.fromHexa(getPrefixed("ik=",text));
1340 GmmInfo *gmm = si->getGmm();
1341 L3GmmMsgAuthentication amsg(si->mRAND,(!gmm || gmm->mImei.empty()));
1342 amsg.mAutn.fromHexa(getPrefixed("autn=",text));
1343 si->sgsnWriteHighSideMsg(amsg);
1344}
1345
1346// Application requests everything else to continue locally
1347// Connection is already cleared
1348void SgsnConn::attachLBO(SgsnInfo* si)
1349{
1350 si->setConnId(GprsConnLocal);
1351 handleAttachRequestLocally(si,si->getGmm());
1352}
1353
1354// Application rejected the attach
1355// Connection is already cleared
1356void SgsnConn::attachRej(SgsnInfo* si, unsigned char cause)
1357{
1358 si->setConnId(GprsConnNone);
1359 GmmInfo *gmm = si->getGmm();
1360 if (gmm)
1361 gmm->setGmmState(GmmState::GmmDeregistered);
1362 switch (si->mtAttachInfo.mMsgType) {
1363 case L3GmmMsg::AttachRequest:
1364 sendAttachReject(si,cause);
1365 break;
1366 case L3GmmMsg::RoutingAreaUpdateRequest:
1367 sendRAUpdateReject(si,cause);
1368 break;
1369 default:
1370 SGSNLOGF(WARNING,GPRS_ERR,"SGSN","Received unmatched Attach/RAUpdate response " <<si);
1371 break;
1372 }
1373}
1374
1375// Application accepted to handle the attach
1376void SgsnConn::attachAccept(SgsnInfo* si, const char* text)
1377{
1378 setMsi(si,text);
1379 // update PDP Context Status
1380 std::string str = getPrefixed("pdps=",text);
1381 if (!str.empty()) {
1382 long int pdps = ::strtol(str.c_str(),0,16);
1383 if ((pdps >= 0) && (pdps < 0xffff))
1384 si->mtAttachInfo.mPdpContextStatus.fromInt(pdps);
1385 GmmInfo* gmm = si->getGmm();
1386 if (gmm) {
1387 std::string llcsapis = getPrefixed("llcsapis=",text);
1388 std::string tids = getPrefixed("tids=",text);
1389 if (pdps && !(llcsapis.length() && tids.length())) {
1390 SGSNLOGF(WARNING,GPRS_ERR,"SGSN","Missing LLC SAPIs/TIDs information for PDP contexts, " <<
1391 "removing all active ones");
1392 pdps = 0;
1393 }
1394 for (uint16_t i = 0; i < 16; i++) {
1395 bool active = !!((pdps >> i) & 0x01);
1396 uint8_t llcsapi = 0xff;
1397 uint8_t tid = 0xff;
1398 if (active) {
1399 unsigned int pos = llcsapis.find(',');
1400 if (pos == std::string::npos) {
1401 SGSNLOGF(WARNING,GPRS_ERR,"SGSN","Missing LLC SAPI information for NSAPI " <<
1402 i << ", deactivating context");
1403 active = false;
1404 }
1405 else {
1406 llcsapi = ::strtoul(llcsapis.substr(0,pos).c_str(),0,10);
1407 llcsapis = llcsapis.substr(pos + 1);
1408 }
1409 pos = tids.find(',');
1410 if (pos == std::string::npos) {
1411 SGSNLOGF(WARNING,GPRS_ERR,"SGSN","Missing TID information for NSAPI " <<
1412 i << ", deactivating context");
1413 active = false;
1414 }
1415 else {
1416 tid = ::strtoul(tids.substr(0,pos).c_str(),0,10);
1417 tids = tids.substr(pos + 1);
1418 }
1419 }
1420 if (!active) {
1421 if (!gmm->isNSapiActive(i))
1422 continue;
1423 SGSNLOGF(INFO,GPRS_CHECK_OK,"SGSN","Deactivating PDP context for NSAPI=" << i);
1424 gmm->freePdp(i);
1425 continue;
1426 }
1427 // active
1428 PdpContext *pdp = gmm->getPdp(i);
1429 L3GprsDlMsg::MsgSense sense = (tid & 0x80) ? L3GprsDlMsg::senseReply : L3GprsDlMsg::senseCmd;
1430 tid &= 0x7f;
1431 if (pdp && !(pdp->mLlcSapi == llcsapi && pdp->mSense == sense && pdp->mTransactionId == tid)) {
1432 SGSNLOGF(INFO,GPRS_CHECK_FAIL,"SGSN","PDP Context parameters don't match, replacing " <<
1433 " PDP context for NSAPI=" << i);
1434 gmm->freePdp(i);
1435 pdp = 0;
1436 }
1437 if (!pdp) {
1438 pdp = new PdpContext(gmm,0,i,llcsapi);
1439 gmm->connectPdp(pdp,0);
1440 }
1441 pdp->mTransactionId = tid;
1442 pdp->setSense(sense);
1443 pdp->mWaitUpstream = false;
1444 }
1445 }
1446 }
1447 handleAttachStep(si);
1448}
1449
1450// Application requests network initiated GPRS detach
1451// Connection is already cleared
1452void SgsnConn::detach(SgsnInfo* si, unsigned char cause, const char* text)
1453{
1454 switch (si->mtAttachInfo.mMsgType) {
1455 case L3GmmMsg::AttachRequest:
1456 case L3GmmMsg::RoutingAreaUpdateRequest:
1457 attachRej(si,cause);
1458 return;
1459 default:
1460 break;
1461 }
1462 si->setConnId(GprsConnNone);
1463 GmmInfo *gmm = si->getGmm();
1464 if (gmm)
1465 SGSNLOGF(WARNING,GPRS_ERR,"SGSN"," gmm state = " << GmmState::GmmState2Name(gmm->getGmmState()));
1466 if (gmm)
1467 gmm->setGmmState(GmmState::GmmDeregistered);
1468 sendImplicitlyDetached(si,toInteger(getPrefixed("type=",text),1),
1469 toInteger(getPrefixed("error=",text),cause));
1470 si->sgsnReset();
1471}
1472
1473// PDP activation response or Network requested PDP activation
1474void SgsnConn::pdpActivate(SgsnInfo* si, bool reply, const char* text)
1475{
1476 if (reply) {
1477 int nsapi = toInteger(getPrefixed("nsapi=",text),-1);
1478 if (nsapi < 5 || nsapi > 15) {
1479 SGSNLOGF(WARNING,GPRS_ERR,"SGSN","Invalid PDP Activate Reply NS SAPI:" << nsapi);
1480 return;
1481 }
1482 PdpContext *pdp = si->getPdp(nsapi);
1483 if (!pdp) {
1484 SGSNLOGF(WARNING,GPRS_ERR,"SGSN","PDP Activate Reply for missing NS SAPI:" << nsapi);
1485 return;
1486 }
1487 int err = toInteger(getPrefixed("error=",text),-1);
1488 if ((err < 0) && toBoolean(getPrefixed("error=",text)))
1489 err = SmCause::Protocol_error_unspecified;
1490 if (err >= 0 && err <= 127) {
1491 unsigned ti = pdp->mTransactionId;
1492 si->freePdp(nsapi);
1493 sendPdpContextReject(si,(SmCauseType)err,ti);
1494 return;
1495 }
1496 pdp->mWaitUpstream = false;
1497 L3SmMsgActivatePdpContextAccept pdpa(pdp->mTransactionId);
1498 pdpa.mLlcSapi = pdp->mLlcSapi;
1499 pdpa.mQoS.fromHexa(getPrefixed("qos=",text));
1500 if (pdpa.mQoS.size() < 3) {
1501 SmQoS resultQoS(12);
1502 resultQoS.defaultPS(pdp->mRabStatus.mRateDownlink,pdp->mRabStatus.mRateUplink);
1503 pdpa.mQoS = resultQoS;
1504 }
1505 pdpa.mRadioPriority = toInteger(getPrefixed("priority=",text),2);
1506 pdpa.mPco.fromHexa(getPrefixed("pco=",text));
1507 pdpa.mPdpAddress.fromHexa(getPrefixed("pdpaddr=",text));
1508 si->sgsnWriteHighSideMsg(pdpa);
1509 }
1510 else {
1511 // TODO
1512 SGSNLOGF(INFO,GPRS_ERR,"SGSN","Network requested PDP activation not implemented");
1513 }
1514}
1515
1516// PDP modification response or Network requested PDP modification
1517void SgsnConn::pdpModify(SgsnInfo* si, bool reply, const char* text)
1518{
1519 // TODO
1520 SGSNLOGF(INFO,GPRS_ERR,"SGSN","PDP modification not implemented");
1521}
1522
1523// Network requested PDP deactivation
1524void SgsnConn::pdpDeactivate(SgsnInfo* si, const char* text)
1525{
1526 int nsapi = toInteger(getPrefixed("nsapi=",text),-1);
1527 if (nsapi < 5 || nsapi > 15) {
1528 SGSNLOGF(WARNING,GPRS_ERR,"SGSN","Invalid PDP Deactivate NS SAPI:" << nsapi);
1529 return;
1530 }
1531 PdpContext *pdp = si->getPdp(nsapi);
1532 if (!pdp)
1533 return;
1534 pdp->mWaitUpstream = true;
1535 int err = toInteger(getPrefixed("error=",text),-1);
1536 if (err < 0)
1537 err = SmCause::Protocol_error_unspecified;
1538 unsigned ti = pdp->mTransactionId;
1539 L3GprsDlMsg::MsgSense sense = pdp->mSense;
1540 si->freePdp(nsapi);
1541 L3SmMsgDeactivatePdpContextRequest deact(ti,(SmCauseType)err,
1542 toBoolean(getPrefixed("teardown=",text)),sense);
1543 deact.mPco.fromHexa(getPrefixed("pco=",text));
1544 si->sgsnWriteHighSideMsg(deact);
1545}
1546
1547// Data was received for the user
1548void SgsnConn::userData(SgsnInfo* si, const unsigned char* data, size_t len)
1549{
1550 if (len <= 4)
1551 return;
1552 uint8_t nsapi = data[0] & 0x7f;
1553 PdpContext *pdp = si->getPdp(nsapi);
1554 if (!pdp)
1555 return;
1556 ByteVectorTemp sdu((unsigned char*)data + 4,len - 4);
1557 si->sgsnWriteHighSide(sdu,nsapi);
1558}
1559
1560static void handleActivatePdpContextRequest(SgsnInfo *si, L3SmMsgActivatePdpContextRequest &pdpr)
1561{
1562 // Validate request first
1563 if (!LlcEngine::isValidDataSapi(pdpr.mLlcSapi)) {
1564 SGSNLOGF(WARNING,GPRS_ERR,"SGSN","Invalid PDP Activate LLC SAPI:" << pdpr.mLlcSapi);
1565 sendPdpContextReject(si,SmCause::Invalid_mandatory_information,pdpr.mTransactionId);
1566 return;
1567 }
1568 if ((pdpr.mNSapi < 5) || (pdpr.mNSapi > 15)) {
1569 SGSNLOGF(WARNING,GPRS_ERR,"SGSN","Invalid PDP Activate NS SAPI:" << pdpr.mNSapi);
1570 sendPdpContextReject(si,SmCause::Invalid_mandatory_information,pdpr.mTransactionId);
1571 return;
1572 }
1573 if (!si->isRegistered()) {
1574 sendPdpContextReject(si,SmCause::Message_not_compatible_with_the_protocol_state,pdpr.mTransactionId);
1575 sendImplicitlyDetached(si);
1576 si->sgsnReset();
1577 return;
1578 }
1579 // Message is valid and the MS is GMM registered
1580 GmmInfo *gmm = si->getGmm();
1581 PdpContext *pdp = gmm->getPdp(pdpr.mNSapi);
1582 if (pdp) {
1583 if (pdp->mTransactionId != pdpr.mTransactionId) {
1584 SGSNLOGF(WARNING,GPRS_ERR,"SGSN","Already used NS SAPI:" << pdpr.mNSapi);
1585 sendPdpContextReject(si,SmCause::NSAPI_already_used,pdpr.mTransactionId);
1586 return;
1587 }
1588 SGSNLOGF(INFO,GPRS_ERR,"SGSN","Duplicate PDP activate for NS SAPI:" << pdpr.mNSapi);
1589 }
1590 else {
1591 pdp = new PdpContext(gmm,0,pdpr.mNSapi,pdpr.mLlcSapi);
1592 gmm->connectPdp(pdp,0);
1593 }
1594 pdp->update(pdpr);
1595
1596 std::ostringstream buf;
1597 buf << "nsapi=" << pdpr.mNSapi;
1598 buf << " llcsapi=" << pdpr.mLlcSapi;
1599 buf << " tid=" << ((pdp->mSense == L3GprsDlMsg::senseReply ? 0x80 : 0x00) | (uint8_t)pdp->mTransactionId);
1600 buf << " qos=" << pdpr.mQoS.hexstr();
1601 buf << " pdpaddr=" << pdpr.mPdpAddress.hexstr();
1602 buf << " type=" << pdpr.mRequestType;
1603 if (pdpr.mApName.size())
1604 buf << " apn=" << pdpr.mApName.hexstr();
1605 if (pdpr.mPco.size())
1606 buf << " pco=" << pdpr.mPco.hexstr();
1607 gSigConn.send(SigPdpActivate,0,si->getConnId(),buf.str());
1608}
1609
1610static void handleDeactivatePdpContextRequest(SgsnInfo *si, L3SmMsgDeactivatePdpContextRequest &deact)
1611{
1612 std::ostringstream buf;
1613 unsigned int nsapi = 0;
1614 unsigned int nsapiMask = 0;
1615 if (deact.mTearDownIndicator)
1616 nsapiMask = si->freePdpAll(false);
1617 else {
1618 for (; nsapi <= 15; nsapi++) {
1619 PdpContext *pdp = si->getPdp(nsapi);
1620 if (pdp && (pdp->mTransactionId == deact.mTransactionId)) {
1621 si->freePdp(nsapi);
1622 nsapiMask = 1 << nsapi;
1623 break;
1624 }
1625 }
1626 if (!nsapiMask) {
1627 nsapi = 0;
1628 SGSNLOGF(WARNING,GPRS_ERR,"SGSN","No PDP context to deactivate for TI=" << deact.mTransactionId);
1629 }
1630 }
1631 // Accept PDP context deactivation even if not yet cleared upstream
1632 L3SmMsgDeactivatePdpContextAccept deactaccept(deact.mTransactionId);
1633 si->sgsnWriteHighSideMsg(deactaccept);
1634 if (nsapiMask)
1635 si->deactivateRabs(nsapiMask);
1636 if (deact.mTearDownIndicator)
1637 buf << "teardown=true";
1638 else
1639 buf << "nsapi=" << nsapi;
1640 buf << " mask=0x" << hex << std::setw(2) << std::setfill('0') << nsapiMask;
1641 gSigConn.send(SigPdpDeactivate,0,si->getConnId(),buf.str());
1642}
1643
1644static void handleL3GmmMsg(SgsnInfo *si,ByteVector &frame1)
1645{
1646 L3GmmFrame frame(frame1);
1647 // Standard L3 header is 2 bytes:
1648 unsigned mt = frame.getMsgType(); // message type
1649 //SGSNLOG("CRACKING GMM MSG TYPE "<<mt);
1650 MSUEAdapter *ms = si->getMS();
1651 if (ms == NULL) {
1652 // This is a serious internal error.
1653 SGSNLOGF(ERR,GPRS_ERR,"SGSN","L3 message "<<L3GmmMsg::name(mt)
1654 <<" for non-existent MS Info struct" <<LOGHEX2("tlli",si->mMsHandle));
1655 return;
1656 }
1657 switch (mt) {
1658 case L3GmmMsg::AttachRequest: {
1659 L3GmmMsgAttachRequest armsg;
1660 armsg.gmmParse(frame);
1661 SGSNLOGF(INFO,GPRS_OK,"SGSN","Received "<<armsg.str()<<si << "\n received buffer " << frame1.hexstr());
1662 handleAttachRequest(si,armsg);
1663 dumpGmmInfo();
1664 break;
1665 }
1666 case L3GmmMsg::AttachComplete: {
1667 L3GmmMsgAttachComplete acmsg;
1668 //acmsg.gmmParse(frame); // not needed, nothing in it.
1669 SGSNLOGF(INFO,GPRS_OK,"SGSN","Received "<<acmsg.str()<<si);
1670 handleAttachComplete(si,acmsg);
1671 dumpGmmInfo();
1672 break;
1673 }
1674 case L3GmmMsg::IdentityResponse: {
1675 L3GmmMsgIdentityResponse irmsg;
1676 irmsg.gmmParse(frame);
1677 SGSNLOGF(INFO,GPRS_OK,"SGSN","Received "<<irmsg.str()<<si);
1678 handleIdentityResponse(si,irmsg);
1679 break;
1680 }
1681 case L3GmmMsg::DetachRequest: {
1682 L3GmmMsgDetachRequest drmsg;
1683 drmsg.gmmParse(frame);
1684 SGSNLOGF(INFO,GPRS_OK,"SGSN","Received "<<drmsg.str()<<si);
1685 handleDetachRequest(si,drmsg);
1686 break;
1687 }
1688 case L3GmmMsg::DetachAccept:
1689 SGSNLOGF(INFO,GPRS_OK,"SGSN","Received DetachAccept");
1690 //TODO...
1691 break;
1692 case L3GmmMsg::RoutingAreaUpdateRequest: {
1693 L3GmmMsgRAUpdateRequest raumsg;
1694 raumsg.gmmParse(frame);
1695 SGSNLOGF(INFO,GPRS_OK,"SGSN","Received "<<raumsg.str()<<si);
1696 handleRAUpdateRequest(si,raumsg);
1697 break;
1698 }
1699 case L3GmmMsg::RoutingAreaUpdateComplete: {
1700 L3GmmMsgRAUpdateComplete racmsg;
1701 //racmsg.gmmParse(frame); not needed
1702 SGSNLOGF(INFO,GPRS_OK,"SGSN","Received RAUpdateComplete "<<si);
1703 handleRAUpdateComplete(si,racmsg);
1704 break;
1705 }
1706 case L3GmmMsg::GMMStatus: {
1707 L3GmmMsgGmmStatus stmsg;
1708 stmsg.gmmParse(frame);
1709 SGSNLOGF(INFO,GPRS_OK,"SGSN","Received GMMStatus: "<<stmsg.mCause<<"=" <<GmmCause::name(stmsg.mCause)<<si);
1710 break;
1711 }
1712 case L3GmmMsg::AuthenticationAndCipheringResp: {
1713 L3GmmMsgAuthenticationResponse armsg;
1714 armsg.gmmParse(frame);
1715 SGSNLOGF(INFO,GPRS_OK,"SGSN","Received AuthenticationAndCipheringResp message "<<armsg.str()<<si);
1716 handleAuthenticationResponse(si,armsg);
1717 break;
1718 }
1719 case L3GmmMsg::AuthenticationAndCipheringFailure: {
1720 L3GmmMsgAuthenticationFailure afmsg;
1721 afmsg.gmmParse(frame);
1722 SGSNLOGF(INFO,GPRS_OK,"SGSN","Received AuthenticationAndCipheringFailure message "<<afmsg.str()<<si);
1723 handleAuthenticationFailure(si,afmsg);
1724 break;
1725 }
1726 case L3GmmMsg::ServiceRequest: {
1727 L3GmmMsgServiceRequest srmsg;
1728 srmsg.gmmParse(frame);
1729 SGSNLOGF(INFO,GPRS_OK,"SGSN","Received ServiceRequest message" << si);
1730 handleServiceRequest(si,srmsg);
1731 break;
1732 }
1733
1734 // Downlink direction messages:
1735 //RoutingAreaUpdateAccept = 0x09,
1736 //AttachAccept = 0x02,
1737 //AttachReject = 0x04,
1738 //RoutingAreaUpdateReject = 0x0b,
1739
1740 // Other: TODO?
1741 //ServiceAccept = 0x0d,
1742 //ServiceReject = 0x0e,
1743 //PTMSIReallocationCommand = 0x10,
1744 //PTMSIReallocationComplete = 0x11,
1745 //AuthenticationAndCipheringRej = 0x14,
1746 //AuthenticationAndCipheringFailure = 0x1c,
1747 //GMMInformation = 0x21,
1748 default:
1749 //SGSNWARN("Ignoring GPRS GMM message type "<<mt <<L3GmmMsg::name(mt));
1750 return;
1751 }
1752}
1753
1754static bool handleL3SmMsg(SgsnInfo *si,ByteVector &frame1)
1755{
1756 L3SmFrame frame(frame1);
1757 unsigned mt = frame.getMsgType();
1758 switch (si->getConnId()) {
1759 case GprsConnNone:
1760 SGSNLOGF(ERR,GPRS_ERR,"SGSN","L3 message " << L3SmMsg::name(mt) << " in invalid state" << si);
1761 sendImplicitlyDetached(si);
1762 return true;
1763 case GprsConnLocal:
1764 return false;
1765 }
1766 if (gGprsMap.find(si->getConnId()) != si) {
1767 SGSNLOGF(ERR,GPRS_ERR,"SGSN","SM for not mapped" << si);
1768 if (!si->isRegistered()) {
1769 sendImplicitlyDetached(si);
1770 si->sgsnReset();
1771 return true;
1772 }
1773 adjustConnectionId(si);
1774 }
1775 switch (mt) {
1776 case L3SmMsg::ActivatePDPContextRequest:
1777 {
1778 L3SmMsgActivatePdpContextRequest pdpr(frame);
1779 SGSNLOGF(INFO,GPRS_OK,"SGSN","Received " << pdpr.str() << si);
1780 handleActivatePdpContextRequest(si,pdpr);
1781 }
1782 break;
1783 case L3SmMsg::SMStatus:
1784 {
1785 L3SmMsgSmStatus stmsg(frame);
1786 SGSNLOGF(INFO,GPRS_OK,"SGSN","Received SmStatus: " << stmsg.str() << si);
1787 }
1788 break;
1789 case L3SmMsg::DeactivatePDPContextRequest:
1790 {
1791 L3SmMsgDeactivatePdpContextRequest deact(frame);
1792 SGSNLOGF(INFO,GPRS_OK,"SGSN","Received DeactivatePdpContextRequest: " << deact.str());
1793 handleDeactivatePdpContextRequest(si,deact);
1794 }
1795 break;
1796 case L3SmMsg::DeactivatePDPContextAccept:
1797 {
1798 L3SmMsgDeactivatePdpContextAccept deact(frame);
1799 SGSNLOGF(INFO,GPRS_OK,"SGSN","Received DeactivatePdpContextAccept: " << deact.str());
1800 }
1801 break;
1802 // TODO: handle more messages
1803 default:
1804 SGSNLOGF(WARNING,GPRS_ERR,"SGSN","Ignoring GPRS SM message type " << mt << " " << L3SmMsg::name(mt));
1805 break;
1806 }
1807 return true;
1808}
1809
1810// This is the old UMTS-centric entry point
1811//void Sgsn::sgsnWriteLowSide(ByteVector &payload,SgsnInfo *si, unsigned rbid)
1812//{
1813// // No Pdcp, so just send it off.
1814// si->sgsnSend2PdpLowSide(rbid, payload);
1815//}
1816
1817// The handle is the URNTI and the rbid specfies the rab.
1818// In gprs, the handle is the TLLI and all the rab info is encoded into the
1819// payload with LLC headers so rbid is not used, which was a pretty dopey design.
1820void MSUEAdapter::sgsnWriteLowSide(ByteVector &payload, uint32_t handle, unsigned rbid)
1821{
1822 SgsnInfo *si = sgsnGetSgsnInfoByHandle(handle,true); // Create if necessary.
1823#if RN_UMTS
1824 // No Pdcp, so just send it off.
1825// si->sgsnSend2PdpLowSide(rbid, payload);
1826#else
1827 si->mLlcEngine->llcWriteLowSide(payload,si);
1828#endif
1829}
1830
1831#if RN_UMTS
1832//void MSUEAdapter::sgsnHandleL3Msg(uint32_t handle, ByteVector &msgFrame)
1833//{
1834// SgsnInfo *si = sgsnGetSgsnInfoByHandle(handle,true); // Create if necessary.
1835// handleL3Msg(si,msgFrame);
1836//}
1837#endif
1838
1839void handleL3Msg(SgsnInfo *si, ByteVector &bv)
1840{
1841 unsigned pd = 0;
1842 try {
1843 L3GprsFrame frame(bv);
1844 if (frame.size() == 0) { // David saw this happen.
1845 //SGSNWARN("completely empty L3 uplink message "<<si);
1846 return;
1847 }
1848 pd = frame.getNibble(0,0); // protocol descriminator
1849 switch ((GSM::L3PD) pd) {
1850 case GSM::L3GPRSMobilityManagementPD: { // Couldnt we shorten this?
1851 handleL3GmmMsg(si,frame);
1852 break;
1853 }
1854 case GSM::L3GPRSSessionManagementPD: { // Couldnt we shorten this?
1855 if (!handleL3SmMsg(si,frame))
1856 Ggsn::handleL3SmMsg(si,frame);
1857 break;
1858 }
1859 // TODO: Send GSM messages somewhere
1860 default:
1861 SGSNLOGF(WARNING,GPRS_ERR,"SGSN","unsupported L3 Message PD:"<<pd);
1862 }
1863 } catch(SgsnError) {
1864 return; // Handled already
1865 } catch(ByteVectorError) { // oops!
1866 SGSNLOGF(ERR,GPRS_ERR,"SGSN","internal error assembling SGSN message, pd="<<pd); // not much to go on.
1867 }
1868}
1869
1870// Forces the SgsnInfo to exist.
1871// For GPRS the handle is a TLLI.
1872// From GSM03.03 sec 2.6 Structure of TLLI; and reproduced at class MSInfo comments.
1873// The top bits of the TLLI encode where it came from.
1874// A local TLLI has top 2 bits 11, and low 30 bits are the P-TMSI.
1875// For UMTS, the handle is the invariant URNTI.
1876SgsnInfo *findSgsnInfoByHandle(uint32_t handle, bool create)
1877{
1878 SgsnInfo *si, *result = NULL;
1879 // We can delete unused SgsnInfo as soon as the attach procedure is over,
1880 // which is 15s, but let them hang around a bit longer so the user can see them.
1881 int idletime = gConfig.getNum("SGSN.Timer.MS.Idle");
1882 time_t now; time(&now);
1883
1884 ScopedLock lock(sSgsnListMutex);
1885 RN_FOR_ALL(SgsnInfoList_t,sSgsnInfoList,si) {
1886 if (si->mMsHandle == handle) {result=si; continue;}
1887#if RN_UMTS
1888#else
1889#if NEW_TLLI_ASSIGN_PROCEDURE
1890 if (si->mAltTlli == handle) {result=si;continue;}
1891#endif
1892#endif
1893 // Kill off old ones, except ones that are the primary one for a gmm.
1894 GmmInfo *gmm = si->getGmm();
1895 if (gmm==NULL || gmm->getSI() != si) {
1896 if (now - si->mLastUseTime > idletime) { si->sirm(); }
1897 }
1898 }
1899 if (result) {
1900 time(&result->mLastUseTime);
1901 return result;
1902 }
1903 if (!create) { return NULL; }
1904
1905 // Make a new one.
1906 SgsnInfo *sinew = new SgsnInfo(handle);
1907 return sinew;
1908}
1909
1910// Now we create the SgsnInfo for the assigned ptmsi as soon as the ptmsi is created,
1911// even if the MS has not used it yet.
1912//GmmInfo *SgsnInfo::findGmm()
1913//{
1914// if (mGmmp) { return mGmmp; } // Hooked up previously.
1915// return NULL;
1916// Old comment:
1917// For GPRS, the MS contacts with some random tlli, then we create a GmmInfo and a PTMSI,
1918// and send the PTMSI to the MS, but the GmmInfo is not yet hooked to any SgsnInfos.
1919// The MS will then call us again using a TLLI derived from the PTMSI,
1920// and we hook up that SgsnInfo to the GmmInfo right here.
1921// if (! Sgsn::isUmts()) {
1922// uint32_t tlli = mMsHandle;
1923// // Only a local TLLI can be converted to a P-TMSI to look up the Gmm context.
1924// if (Tlli::tlli2Type(tlli) == Tlli::LocalTlli) {
1925// uint32_t ptmsi = Tlli::tlli2ptmsi(tlli);
1926// GmmInfo *gmm;
1927// RN_FOR_ALL(GmmInfoList_t,sGmmInfoList,gmm) {
1928// if (gmm->mPTmsi == ptmsi) {
1929// SGSNLOG("Hooking up"<<LOGHEX2("tlli",tlli)<<" to"<<LOGHEX2("ptmsi",ptmsi));
1930// this->setGmm(gmm);
1931// gmm->msi = this;
1932// return gmm;
1933// }
1934// }
1935// }
1936// } else {
1937// // In UMTS the Gmm context is indexed by URNTI.
1938// // If this doesnt work right, we will need to look up the Gmm context
1939// // from the ptmsi in the L3 messages.
1940// }
1941// return NULL;
1942//}
1943
1944// Works, but not currently used:
1945void MSUEAdapter::sgsnFreePdpAll(uint32_t mshandle)
1946{
1947 SgsnInfo *si = sgsnGetSgsnInfoByHandle(mshandle,false);
1948 if (si) si->freePdpAll(true);
1949}
1950
1951// Forces it to exist if it did not already.
1952static SgsnInfo *sgsnGetSgsnInfoByHandle(uint32_t mshandle, bool create)
1953{
1954 // We cant cache this thing for GPRS because it changes
1955 // during the TLLI assignment procedure.
1956 // We could cache it for UMTS, but that assumes the lifetime of the SgsnInfo
1957 // is greater than the UE, both of which are controlled by user parameters,
1958 // so to be safe, we are just going to look it up every time.
1959 // TODO: go back to caching it in UMTS only.
1960 //if (! mSgsnInfo) {
1961 //uint32_t mshandle = msGetHandle();
1962 //mSgsnInfo = findSgsnInfoByHandle(mshandle,create);
1963 //}
1964 //return mSgsnInfo;
1965 return findSgsnInfoByHandle(mshandle,create);
1966}
1967
1968#if RN_UMTS
1969//SgsnInfo *MSUEAdapter::sgsnGetSgsnInfo()
1970//{
1971// uint32_t mshandle = msGetHandle();
1972// return findSgsnInfoByHandle(mshandle,false);
1973//}
1974#else
1975void MSUEAdapter::sgsnSendKeepAlive()
1976{
1977 // TODO
1978}
1979#endif
1980
1981#if RN_UMTS
1982 // not applicable
1983#else
1984static void parseCaps(GmmInfo *gmm)
1985{
1986 if (/*gmm->mGprsMultislotClass == -1 &&*/ gmm->mgAttachInfo.mMsRadioAccessCap.size()) {
1987 MsRaCapability caps(gmm->mgAttachInfo.mMsRadioAccessCap);
1988 gmm->mGprsMultislotClass = caps.mCList[0].getCap(AccessCapabilities::GPRSMultislotClass);
1989 gmm->mGprsGeranFeaturePackI = caps.mCList[0].getCap(AccessCapabilities::GERANFeaturePackage1);
1990 }
1991}
1992
1993
1994int MSUEAdapter::sgsnGetMultislotClass(uint32_t mshandle)
1995{
1996 SgsnInfo *si = sgsnGetSgsnInfoByHandle(mshandle,false);
1997 if (!si) { return -1; }
1998 GmmInfo *gmm = si->getGmm(); // Must be non-null or we would not be here.
1999 if (!gmm) { return -1; } // But dont crash if I'm mistaken.
2000 parseCaps(gmm);
2001 return gmm->mGprsMultislotClass;
2002}
2003
2004bool MSUEAdapter::sgsnGetGeranFeaturePackI(uint32_t mshandle)
2005{
2006 SgsnInfo *si = sgsnGetSgsnInfoByHandle(mshandle,false);
2007 if (!si) { return -1; }
2008 GmmInfo *gmm = si->getGmm(); // Must be non-null or we would not be here.
2009 if (!gmm) { return -1; } // But dont crash if I'm mistaken.
2010 parseCaps(gmm);
2011 return gmm->mGprsGeranFeaturePackI;
2012}
2013#endif
2014
2015GmmState::state MSUEAdapter::sgsnGetRegistrationState(uint32_t mshandle, GmmInfo** outGmm)
2016{
2017 SgsnInfo *si = sgsnGetSgsnInfoByHandle(mshandle,false);
2018 if (!si) { return GmmState::GmmDeregistered; }
2019 GmmInfo *gmm = si->getGmm(); // Must be non-null or we would not be here.
2020 if (!gmm) { return GmmState::GmmDeregistered; }
2021 if (outGmm) *outGmm = gmm;
2022 return gmm->getGmmState();
2023}
2024
2025GmmState::state MSUEAdapter::suspend()
2026{
2027 GmmInfo* gmm = 0;
2028 GmmState::state state = sgsnGetRegistrationState(msGetHandle(),&gmm);
2029 if (state == GmmState::GmmRegisteredNormal && gmm)
2030 gmm->setGmmState((state = GmmState::GmmRegisteredSuspended));
2031 return state;
2032}
2033
2034GmmState::state MSUEAdapter::resume()
2035{
2036 GmmInfo* gmm = 0;
2037 GmmState::state state = sgsnGetRegistrationState(msGetHandle(),&gmm);
2038 if (!(state == SGSN::GmmState::GmmRegisteredSuspended && gmm))
2039 return state;
2040 GLOG(INFO) << "Resuming GPRS for " << msid();
2041 state = GmmState::GmmRegisteredNormal;
2042 gmm->setGmmState(state);
2043 return state;
2044}
2045
2046#if RN_UMTS
2047//void MSUEAdapter::sgsnHandleRabSetupResponse(unsigned rabId, bool success)
2048//{
2049// SgsnInfo *si = sgsnGetSgsnInfo();
2050// if (si == NULL) {
2051// // Dont think this can happen, but be safe.
2052// SGSNERROR("Received spurious RabSetupResponse for UE:"<<msid());
2053// return;
2054// }
2055// if (success) {
2056// PdpContext *pdp = si->getPdp(rabId);
2057// if (pdp==NULL) return; // FIXME: Not sure what to do here
2058// if (pdp->mUmtsStatePending) {
2059// pdp->update(pdp->mPendingPdpr);
2060// pdp->mUmtsStatePending = false;
2061// }
2062// sendPdpContextAccept(si,pdp);
2063// } else {
2064// // We do NOT want to send a RAB teardown message - we got here because
2065// // the RAB setup did not work in the first place. Just free it.
2066// si->freePdp(rabId);
2067// }
2068//}
2069#endif
2070
2071const char *GmmState::GmmState2Name(GmmState::state state)
2072{
2073 switch (state) {
2074 CASENAME(GmmDeregistered)
2075 CASENAME(GmmRegistrationPending)
2076 CASENAME(GmmRegisteredNormal)
2077 CASENAME(GmmRegisteredSuspended)
2078 }
2079 return "";
2080}
2081
2082// The alternate sgsnInfoPrint is used only for gmmDump and prints
2083void sgsnInfoDump(SgsnInfo *si,std::ostream&os)
2084{
2085 //if (si == gmm->getSI()) {continue;} // Already printed the main one.
2086 uint32_t handle = si->mMsHandle;
2087 os << "SgsnInfo"<<LOGHEX(handle)
2088 <<" T3370:active="<<si->mT3370ImsiRequest.active()
2089 <<" remaining=" << si->mT3370ImsiRequest.remaining();
2090 MSUEAdapter *ms = si->getMS();
2091 if (ms) { os << ms->msid(); }
2092 else { os << " MS=not_active"; }
2093 AttachInfo *ati = &si->mtAttachInfo;
2094 if (ati->mPrevRaId.valid()) { os << " prev:"; ati->mPrevRaId.text(os); }
2095 if (!si->getGmm()) { os << " no gmm"; }
2096 os << endl;
2097}
2098
2099void gmmInfoDump(GmmInfo *gmm,std::ostream&os,int options)
2100{
2101 os << " GMM Context:";
2102 os << LOGVAR2("imsi",gmm->mImsi.hexstr());
2103 os << LOGHEX2("ptmsi",gmm->mPTmsi);
2104 os << LOGHEX2("tlli",gmm->getTlli());
2105 if (!gmm->mImei.empty())
2106 os << LOGVAR2("imei",gmm->mImei);
2107 os << LOGVAR2("state",GmmState::GmmState2Name(gmm->getGmmState()));
2108 time_t now; time(&now);
2109 os << LOGVAR2("age",(gmm->mAttachTime ? now - gmm->mAttachTime : 0));
2110 os << LOGVAR2("idle",now - gmm->mActivityTime);
2111 SgsnInfo *si = gmm->getSI();
2112 if (!(options & printNoMsId)) {
2113 if (si) { // Can this be null? No, but dont crash.
2114 // The mPrevRaId is generally invalid in the SgsnInfo for the GMM,
2115 // because it is the one we assigned, and the routing info is in the SgsnInfo
2116 // the MS initially called in on.
2117 //os << LOGVAR2("oldMCC",si->mOldMcc);
2118 //os << LOGVAR2("oldMNC",si->mOldMnc);
2119 // The GPRS ms struct will disappear shortly after the MS stops communicating with us.
2120 MSUEAdapter *ms = si->getMS();
2121 if (ms) { os << ms->msid(); }
2122 else { os << " MS=not_active"; }
2123 }
2124 }
2125
2126 if (gmm->mConnId >= 0)
2127 os << " ConnId=" << gmm->mConnId;
2128 else {
2129 os << " IPs=";
2130 int ipcnt = 0;
2131 for (unsigned nsapi = 0; nsapi < GmmInfo::sNumPdps; nsapi++) {
2132 if (gmm->isNSapiActive(nsapi)) {
2133 // FIXME: Darn it, we need to lock the pdp contexts for this too.
2134 // Go ahead and do it anyway, because collision is very low probability.
2135 PdpContext *pdp = gmm->getPdp(nsapi);
2136 mg_con_t *mgp; // Temp variable reduces probability of race; the mgp itself is immortal.
2137 if (pdp && (mgp=pdp->mgp)) {
2138 char buf[30];
2139 if (ipcnt++) {os <<",";}
2140 os << ip_ntoa(mgp->mg_ip,buf);
2141 }
2142 }
2143 }
2144 if (ipcnt == 0) { os <<"none"; }
2145 }
2146 os << endl;
2147
2148 if (options & printDebug) {
2149 // Print out all the SgsnInfos associated with this GmmInfo.
2150 RN_FOR_ALL(SgsnInfoList_t,sSgsnInfoList,si) {
2151 if (si->getGmm() != gmm) {continue;}
2152 os <<"\t"; // this sgsn is associated with the GmmInfo just above it.
2153 sgsnInfoDump(si,os);
2154 }
2155 }
2156
2157 // Now the caps:
2158 if ((options & printCaps) && gmm->mgAttachInfo.mMsRadioAccessCap.size()) {
2159 MsRaCapability caps(gmm->mgAttachInfo.mMsRadioAccessCap);
2160 caps.text2(os,true);
2161 }
2162 //os << endl; // This is extra. There is one at the end of the caps.
2163}
2164
2165void gmmDump(std::ostream &os)
2166{
2167 // The sSgsnListMutex exists for this moment: to allow this cli list routine
2168 // to run from a foreign thread.
2169 ScopedLock lock(sSgsnListMutex);
2170 int debug = sgsnDebug();
2171 GmmInfo *gmm;
2172 RN_FOR_ALL(GmmInfoList_t,sGmmInfoList,gmm) {
2173 gmmInfoDump(gmm,os,debug ? printDebug : 0);
2174 os << endl; // This is extra. There is one at the end of the caps.
2175 }
2176 // Finally, print out SgsnInfo that are not yet associated with a GmmInfo.
2177 if (debug) {
2178 SgsnInfo *si;
2179 RN_FOR_ALL(SgsnInfoList_t,sSgsnInfoList,si) {
2180 if (! si->getGmm()) { sgsnInfoDump(si,os); }
2181 }
2182 }
2183}
2184
2185void dumpGmmInfo()
2186{
2187 if (sgsnDebug()) {
2188 std::ostringstream ss;
2189 gmmDump(ss);
2190 SGSNLOGF(INFO,GPRS_MSG,"SGSN",ss.str());
2191 }
2192}
2193
2194void SgsnInfo::setGmm(GmmInfo *gmm)
2195{
2196 // Copy pertinent info from the Routing Update or Attach Request message into the GmmInfo.
2197 gmm->mgAttachInfo.copyFrom(mtAttachInfo);
2198 this->mGmmp = gmm;
2199}
2200
2201#if NEW_TLLI_ASSIGN_PROCEDURE
2202static void killOtherTlli(SgsnInfo *si,uint32_t newTlli)
2203{
2204 SgsnInfo *othersi = findSgsnInfoByHandle(newTlli,false);
2205 if (othersi && othersi != si) {
2206 if (othersi->getGmm()) {
2207 // This 'impossible' situation can happen if an MS that
2208 // is already attached tries to attach again.
2209 // Easy to reproduce by pulling the power on an MS. (Turning off may not be enough.)
2210 // For example:
2211 // MS -> attachrequest TLLI=80000001; creates new SgsnInfo 80000001
2212 // MS <- attachaccept
2213 // MS -> attachcomplete TLLI=c0000001; SgsnInfo 80000001 changed to c0000001
2214 // MS gets confused (turn off or pull battery)
2215 // MS -> attachrequest TLLI=80000001; creates new SgsnInfo 80000001
2216 // MS <- attachaccept TLLI=80000001; <--- PROBLEM 1! See below.
2217 // MS -> attachcomplete TLLI=c0000001; <--- PROBLEM 2: Both SgsnInfo exist.
2218 // PROBLEM 1: We have already issued the TLLI change command so L2
2219 // is now using the new TLLI. We will use the old TLLI (80000001)
2220 // in the attachaccept, which will cause a 'change tlli' procedure in L2
2221 // to switch back to TLLI 80000001 temporarily.
2222 // PROBLEM 2: Solved by deleting the original registered SgsnInfo (c0000001 above)
2223 // and then caller will change the TLLI of the unregistred one (80000001 above.)
2224 SGSNLOGF(WARNING,GPRS_ERR,"SGSN","Probable repeat attach request: TLLI change procedure"<<LOGVAR(newTlli)
2225 <<" for SgsnInfo:"<<si
2226 <<" found existing registered SgsnInfo:"<<othersi);
2227 // I dont think any recovery is possible; sgsn is screwed up.
2228 } else {
2229 // We dont know or care where this old SgsnInfo came from.
2230 // Destroy it with prejudice and use si, which is the
2231 // SgsnInfo the MS is using to talk with us right now.
2232 SGSNLOGF(WARNING,GPRS_ERR,"SGSN","TLLI change procedure"<<LOGVAR(newTlli)
2233 <<" for SgsnInfo:"<<si
2234 <<" overwriting existing unregistered SgsnInfo:"<<othersi);
2235 othersi->sirm();
2236 }
2237 }
2238}
2239#endif
2240
2241// Switch to the new tlli. If now, do it now, otherwise, just allocate the new SgsnInfo,
2242#if NEW_TLLI_ASSIGN_PROCEDURE
2243// just set altTlli to the future TLLI we will be using after the attach procedure,
2244#endif
2245// which we do ahead of time so we can inform GPRS L2 that the new and old TLLIs are the same MS.
2246// Return the new si. In the new tlli procedure, it is the same as the old.
2247// ------------------
2248// Note the following sequence, easy to reproduce by pulling the power on an MS:
2249// MS -> attachrequest TLLI=80000001; creates new SgsnInfo 80000001
2250// MS <- attachaccept
2251// MS -> attachcomplete TLLI=c0000001; SgsnInfo 80000001 changed to c0000001
2252// MS gets confused (turn off or pull battery)
2253// MS -> attachrequest TLLI=80000001; creates new SgsnInfo 80000001
2254// MS <- attachaccept TLLI=80000001; <--- PROBLEM 1! See below.
2255// MS -> attachcomplete TLLI=c0000001; <--- PROBLEM 2: Both SgsnInfo exist.
2256// PROBLEM 1: We have already issued the TLLI change command so L2
2257// is now using the new TLLI. Easy fix is we use the old TLLI (80000001)
2258// in the attachaccept, which will cause a 'change tlli' procedure in L2
2259// to switch back to TLLI 80000001 temporarily until we receive attachcomplete.
2260// PROBLEM 2: The SgsnInfo for the new tlli will already exist.
2261// ???? Solved by deleting the original registered SgsnInfo (c0000001 above)
2262// ???? and then caller will change the TLLI of the unregistred one (80000001 above.)
2263SgsnInfo * SgsnInfo::changeTlli(bool now)
2264{
2265 GmmInfo *gmm = getGmm();
2266 uint32_t newTlli = gmm->getTlli();
2267#if NEW_TLLI_ASSIGN_PROCEDURE
2268 SgsnInfo *si = this;
2269 if (si->mMsHandle != newTlli) {
2270 killOtherTlli(si,newTlli);
2271 if (now) {
2272 si->mAltTlli = si->mMsHandle;
2273 si->mMsHandle = newTlli;
2274 } else {
2275 si->mAltTlli = newTlli;
2276 }
2277 }
2278 return si;
2279#else
2280 SgsnInfo *othersi = findSgsnInfoByHandle(newTlli,true);
2281 // We will use the new tlli for downlink l3 messages, eg, pdp context messages,
2282 // unless they use some other SI specifically, like AttachAccept
2283 // must be sent on the SI tha the AttachRequest arrived on.
2284 if (othersi != this) {
2285 if (!othersi->getMS()) {
2286 // Alias new TLLI in the MSInfo so it can be identified later
2287 MSUEAdapter *ms = getMS();
2288 if (ms)
2289 ms->msAliasTlli(newTlli);
2290 }
2291 othersi->setGmm(gmm);
2292 othersi->mConnId = getConnId();
2293 SGSNLOGF(INFO,GPRS_CHECK_FAIL,"SGSN","Changing TLLI" << (now ? " now" : "") << " to" << othersi);
2294 if (now) {
2295 gmm->msi = othersi;
2296 if (mConnId >= 0) {
2297 SGSNLOGF(INFO,GPRS_CHECK_OK|GPRS_OK,"SGSN","replacing TLLI" << LOGHEX2("old",mMsHandle) << LOGHEX2("with new",othersi->mMsHandle) << " in connection " << mConnId);
2298 gGprsMap.remap(othersi,mConnId);
2299 }
2300 }
2301 }
2302 return othersi;
2303#endif
2304}
2305
2306// If si, forces the GmmInfo for this imsi to exist and associates it with that si.
2307// If si == NULL, return NULL if gmm not found - used for CLI.
2308GmmInfo *findGmmByImsi(ByteVector &imsi, SgsnInfo *si, uint32_t ptmsi)
2309{
2310 ScopedLock lock(sSgsnListMutex);
2311 GmmInfo *gmm, *result = NULL;
2312 // 24.008 11.2.2: Implicit Detach timer default is 4 min greater
2313 // than T3323, which can be provided in AttachAccept, otherwise
2314 // defaults to T3312, which defaults to 54 minutes.
2315 int attachlimit = gConfig.getNum("SGSN.Timer.ImplicitDetach"); // expiration time in seconds.
2316 time_t now; time(&now);
2317 RN_FOR_ALL(GmmInfoList_t,sGmmInfoList,gmm) {
2318 if (now - gmm->mActivityTime > attachlimit) {
2319 GmmRemove(gmm);
2320 continue;
2321 }
2322 if (gmm->mImsi == imsi) { result = gmm; }
2323 }
2324 if (result) {
2325 if (si) si->setGmm(result);
2326 return result;
2327 }
2328 if (!si) { return NULL; }
2329
2330 // Not found. Make a new one in state Registration Pending.
2331 gmm = new GmmInfo(imsi,ptmsi);
2332 gmm->setGmmState(GmmState::GmmRegistrationPending);
2333 gmm->mConnId = si->getConnId();
2334 si->setGmm(gmm);
2335 gmm->msi = si;
2336 SGSNLOGF(INFO,GPRS_OK,"SGSN","Allocated new GMM info for" << si);
2337#if RN_UMTS
2338 // For UMTS, the si is indexed by URNTI, which is invariant, so hook up and we are finished.
2339#else
2340 // We hook up the GMM context to the SgsnInfo corresponding to the assigned P-TMSI,
2341 // even if that SgsnInfo does not exist yet,
2342 // rather than the SgsnInfo corresponding to the current TLLI, which could be anything.
2343 // The MS will use the SgsnInfo for the P-TMSI to talk to us after a successful attach.
2344 si->changeTlli(false);
2345//#if NEW_TLLI_ASSIGN_PROCEDURE
2346// // 3GPP 04.64 7.2.1.1 and 8.3: Perform the TLLI reassignment procedure.
2347// // Change the TLLI in the SgsnInfo the MS is currently using.
2348// // The important point is that the LLC state does not change.
2349// uint32_t newTlli = gmm->getTlli();
2350// killOtherTlli(si,newTlli);
2351// // Do the TLLI reassignment.
2352// if (si->mMsHandle != newTlli) { // Any other case is extremely unlikely.
2353// // We must continue using the existing MsHandle until we
2354// // receive the AttachComplete message from the MS, but mark
2355// // that the new tlli is an alias for this TLLI.
2356// si->mAltTlli = newTlli;
2357// }
2358//#else
2359// SgsnInfo *newsi = findSgsnInfoByTlli(gmm->getTlli(),true);
2360// newsi->setGmm(gmm);
2361// // NO, not until attachComplete: gmm->msi = newsi; // Use this one instead.
2362//#endif
2363#endif
2364 return gmm;
2365}
2366
2367void RabStatus::text(std::ostream &os) const
2368{
2369 os <<"RabStatus(mStatus=";
2370 switch (mStatus) {
2371 case RabIdle: os << "idle"; break;
2372 case RabFailure: os << "failure"; break;
2373 case RabPending: os << "pending"; break;
2374 case RabAllocated: os << "allocated"; break;
2375 case RabDeactPending: os << "deactPending"; break;
2376 }
2377 os<<LOGVAR2("mFailCode",SmCause::name(mFailCode));
2378 os<<LOGVAR(mRateDownlink)<<LOGVAR(mRateUplink);
2379 os<<")";
2380}
2381
2382void MSUEAdapter::sgsnPrint(uint32_t mshandle, int options, std::ostream &os)
2383{
2384 ScopedLock lock(sSgsnListMutex); // Probably not needed.
2385 SgsnInfo *si = sgsnGetSgsnInfoByHandle(mshandle,false);
2386 if (!si) { os << " GMM state unknown\n"; return; }
2387 GmmInfo *gmm = si->getGmm(); // Must be non-null or we would not be here.
2388 if (!gmm) { os << " GMM state unknown\n"; return; }
2389 gmmInfoDump(gmm,os,options);
2390}
2391
2392}; // namespace