diff --git a/Control/CallControl.cpp b/Control/CallControl.cpp index e32790a..c416a2c 100644 --- a/Control/CallControl.cpp +++ b/Control/CallControl.cpp @@ -303,6 +303,13 @@ bool callManagementDispatchGSM(TransactionEntry *transaction, GSM::LogicalChanne // GSM 04.08 5.4.3.2 if (dynamic_cast(message)) { LOG(INFO) << "GSM Disconnect " << *transaction; + /* late RLLP request */ + if (gConfig.defines("Control.Call.QueryRRLP.Late")) { + // Query for RRLP + if (!sendRRLP(transaction->subscriber(), LCH)) { + LOG(INFO) << "RRLP request failed"; + } + } transaction->resetTimers(); LCH->send(GSM::L3Release(transaction->L3TI())); transaction->setTimer("308"); @@ -326,6 +333,13 @@ bool callManagementDispatchGSM(TransactionEntry *transaction, GSM::LogicalChanne // Release (2nd step of MTD) if (dynamic_cast(message)) { LOG(INFO) << "GSM Release " << *transaction; + /* late RLLP request */ + if (gConfig.defines("Control.Call.QueryRRLP.Late")) { + // Query for RRLP + if (!sendRRLP(transaction->subscriber(), LCH)) { + LOG(INFO) << "RRLP request failed"; + } + } transaction->resetTimers(); LCH->send(GSM::L3ReleaseComplete(transaction->L3TI())); LCH->send(GSM::L3ChannelRelease()); @@ -660,7 +674,6 @@ void Control::MOCStarter(const GSM::L3CMServiceRequest* req, GSM::LogicalChannel GSM::L3MobileIdentity mobileID = req->mobileID(); resolveIMSI(mobileID,LCH); - // FIXME -- At this point, verify the that subscriber has access to this service. // If the subscriber isn't authorized, send a CM Service Reject with // cause code, 0x41, "requested service option not subscribed", @@ -693,6 +706,17 @@ void Control::MOCStarter(const GSM::L3CMServiceRequest* req, GSM::LogicalChannel } throw UnexpectedMessage(); } + + /* early RLLP request */ + /* this seems to need to be sent after initial call setup + -kurtis */ + if (gConfig.defines("Control.Call.QueryRRLP.Early")) { + // Query for RRLP + if (!sendRRLP(mobileID, LCH)) { + LOG(INFO) << "RRLP request failed"; + } + } + LOG(INFO) << *setup; // Pull out the L3 short transaction information now. // See GSM 04.07 11.2.3.1.3. @@ -910,23 +934,18 @@ void Control::MTCStarter(TransactionEntry *transaction, GSM::LogicalChannel *LCH assert(LCH); LOG(INFO) << "MTC on " << LCH->type() << " transaction: "<< *transaction; - /* first RLLP request */ - if (gConfig.defines("Control.Call.QueryRRLP")) { - // Query for RRLP - RRLPServer wRRLPServer(transaction->subscriber(), LCH); - if (!wRRLPServer.assist()) { - LOG(INFO) << "RRLPServer::assist problem"; - } - // can still try to check location even if assist didn't work - if (!wRRLPServer.locate()) { - LOG(INFO) << "RRLPServer::locate problem"; - } - } - // Determine if very early assigment already happened. bool veryEarly = false; if (LCH->type()==GSM::FACCHType) veryEarly=true; + /* early RLLP request */ + if (gConfig.defines("Control.Call.QueryRRLP.Early")) { + // Query for RRLP + if (!sendRRLP(transaction->subscriber(), LCH)) { + LOG(INFO) << "RRLP request failed"; + } + } + // Allocate a TCH for the call. GSM::TCHFACCHLogicalChannel *TCH = NULL; if (!veryEarly) { diff --git a/Control/MobilityManagement.cpp b/Control/MobilityManagement.cpp index 0b497bf..27628d0 100644 --- a/Control/MobilityManagement.cpp +++ b/Control/MobilityManagement.cpp @@ -187,13 +187,8 @@ void Control::LocationUpdatingController(const L3LocationUpdatingRequest* lur, L if (gConfig.defines("Control.LUR.QueryRRLP")) { // Query for RRLP - RRLPServer wRRLPServer(mobileID, DCCH); - if (!wRRLPServer.assist()) { - LOG(INFO) << "RRLPServer::assist problem"; - } - // can still try to check location even if assist didn't work - if (!wRRLPServer.locate()) { - LOG(INFO) << "RRLPServer::locate problem"; + if (!sendRRLP(mobileID, DCCH)) { + LOG(INFO) << "RRLP request failed"; } } diff --git a/Control/RRLPServer.cpp b/Control/RRLPServer.cpp index 2f02464..1900faf 100644 --- a/Control/RRLPServer.cpp +++ b/Control/RRLPServer.cpp @@ -272,3 +272,17 @@ bool RRLPServer::transact() // not reached } +bool sendRRLP(GSM::L3MobileIdentity mobileID, GSM::LogicalChannel *LCH) +{ + // Query for RRLP + RRLPServer wRRLPServer(mobileID, LCH); + if (!wRRLPServer.assist()) { + LOG(INFO) << "assist problem"; + } + // can still try to check location even if assist didn't work + if (!wRRLPServer.locate()) { + LOG(INFO) << "locate problem"; + return false; + } + return true; +} diff --git a/Control/RRLPServer.h b/Control/RRLPServer.h index 624c155..a5ac4fb 100644 --- a/Control/RRLPServer.h +++ b/Control/RRLPServer.h @@ -35,7 +35,7 @@ class L3MobileIdentity; class RRLPServer { public: - RRLPServer(GSM::L3MobileIdentity wMobileID, GSM::LogicalChannel *wDCCH); + RRLPServer(GSM::L3MobileIdentity wMobileID, GSM::LogicalChannel *wDCCH); // tell server to send location assistance to mobile bool assist(); // tell server to ask mobile for location @@ -51,4 +51,6 @@ class RRLPServer bool trouble; }; +bool sendRRLP(GSM::L3MobileIdentity mobileID, GSM::LogicalChannel *LCH); + #endif diff --git a/Control/SMSControl.cpp b/Control/SMSControl.cpp index 02193e6..41f6beb 100644 --- a/Control/SMSControl.cpp +++ b/Control/SMSControl.cpp @@ -283,6 +283,14 @@ void Control::MOSMSController(const GSM::L3CMServiceRequest *req, GSM::LogicalCh ack.parse(*CM); LOG(INFO) << "CPAck " << ack; + /* MOSMS RLLP request */ + if (gConfig.defines("Control.SMS.QueryRRLP")) { + // Query for RRLP + if (!sendRRLP(mobileID, LCH)) { + LOG(INFO) << "RRLP request failed"; + } + } + // Done. LCH->send(GSM::L3ChannelRelease()); gTransactionTable.remove(transaction); @@ -456,18 +464,13 @@ void Control::MTSMSController(TransactionEntry *transaction, GSM::LogicalChannel transaction->GSMState(GSM::SMSDelivering); LOG(INFO) << "transaction: "<< *transaction; - /* first RLLP request */ + /* MTSMS RLLP request */ if (gConfig.defines("Control.SMS.QueryRRLP")) { // Query for RRLP - RRLPServer wRRLPServer(transaction->subscriber(), LCH); - if (!wRRLPServer.assist()) { - LOG(INFO) << "RRLPServer::assist problem"; + if(!sendRRLP(transaction->subscriber(), LCH)){ + LOG(INFO) << "RRLP request failed"; } - // can still try to check location even if assist didn't work - if (!wRRLPServer.locate()) { - LOG(INFO) << "RRLPServer::locate problem"; - } - } + } bool success = deliverSMSToMS(transaction->calling().digits(),transaction->message(), transaction->messageType(),transaction->L3TI(),LCH); @@ -592,6 +595,18 @@ void Control::InCallMOSMSController(const CPData *cpData, TransactionEntry* tran ack.parse(*CM); LOG(INFO) << "CPAck " << ack; + /* I had a hell of a time testing this with my B100 + I know it went off, that's all. If things fail, look + here -kurtis */ + + /* MOSMS RLLP request */ + if (gConfig.defines("Control.SMS.QueryRRLP")) { + // Query for RRLP + if (!sendRRLP(transaction->subscriber(), LCH)) { + LOG(INFO) << "RRLP request failed"; + } + } + gTransactionTable.remove(transaction); } diff --git a/apps/OpenBTS.example.sql b/apps/OpenBTS.example.sql index dc52326..f4439bb 100644 --- a/apps/OpenBTS.example.sql +++ b/apps/OpenBTS.example.sql @@ -4,7 +4,8 @@ CREATE TABLE CONFIG ( KEYSTRING TEXT UNIQUE NOT NULL, VALUESTRING TEXT, STATIC I INSERT INTO "CONFIG" VALUES('CLI.Prompt','OpenBTS> ',0,0,'Prompt for the OpenBTS command line interface.'); INSERT INTO "CONFIG" VALUES('Control.Reporting.PhysStatusTable','/var/run/OpenBTSChannelTable.db',1,0,'File path for channel status reporting database. Static.'); INSERT INTO "CONFIG" VALUES('Control.Reporting.TMSITable','/var/run/OpenBTSTMSITable.db',1,0,'File path for TMSITable database. Static.'); -INSERT INTO "CONFIG" VALUES('Control.Call.QueryRRLP',NULL,0,1,'If not NULL, query every MS for its location via RRLP during a mobile terminated call.'); +INSERT INTO "CONFIG" VALUES('Control.Call.QueryRRLP.Early',NULL,0,1,'If not NULL, query every MS for its location via RRLP during the setup of a call.'); +INSERT INTO "CONFIG" VALUES('Control.Call.QueryRRLP.Late',NULL,0,1,'If not NULL, query every MS for its location via RRLP during the teardown of a call.'); INSERT INTO "CONFIG" VALUES('Control.GSMTAP.TargetIP',NULL,0,1,'Target IP address for GSMTAP packets; the IP address of Wireshark, if you use it for GSM.'); INSERT INTO "CONFIG" VALUES('Control.LUR.AttachDetach',1,0,0,'Attach/detach flag. Set to 1 to use attach/detach procedure, 0 otherwise. This will make initial LUR more prompt. It will also cause an un-regstration if the handset powers off and really heavy LUR loads in areas with spotty coverage.'); INSERT INTO "CONFIG" VALUES('Control.LUR.FailedRegistration.Message','Your handset is not provisioned for this network. ',0,1,'If defined, send this text message, followed by the IMSI, to unprovisioned handsets that are denied registration.'); @@ -20,7 +21,7 @@ INSERT INTO "CONFIG" VALUES('Control.LUR.QueryRRLP',NULL,0,1,'If not NULL, query INSERT INTO "CONFIG" VALUES('Control.LUR.SendTMSIs',NULL,0,1,'If not NULL, send new TMSI assignments to handsets that are allowed to attach.'); INSERT INTO "CONFIG" VALUES('Control.LUR.UnprovisionedRejectCause','0x04',0,0,'Reject cause for location updating failures for unprovisioned phones. Reject causes come from GSM 04.08 10.5.3.6. Reject cause 0x04, IMSI not in VLR, is usually the right one.'); INSERT INTO "CONFIG" VALUES('Control.NumSQLTries','3',0,0,'Number of times to retry SQL queries before declaring a database access failure.'); -INSERT INTO "CONFIG" VALUES('Control.SMS.QueryRRLP',NULL,0,1,'If not NULL, query every MS for its location via RRLP during a mobile terminated SMS.'); +INSERT INTO "CONFIG" VALUES('Control.SMS.QueryRRLP',NULL,0,1,'If not NULL, query every MS for its location via RRLP during an SMS.'); INSERT INTO "CONFIG" VALUES('Control.TMSITable.MaxAge','72',0,0,'Maximum allowed age for a TMSI in hours.'); INSERT INTO "CONFIG" VALUES('Control.TMSITable.MaxSize','100000',0,0,'Maximum size of TMSI table before oldest TMSIs are discarded.'); INSERT INTO "CONFIG" VALUES('Control.VEA',1,0,1,'If not NULL, user very early assignment for speech call establishment. See GSM 04.08 Section 7.3.2 for a detailed explanation of assignment types. If VEA is selected, GSM.CellSelection.NECI should be set to 1. See GSM 04.08 Sections 9.1.8 and 10.5.2.4 for an explanation of the NECI bit.');