/* * Copyright 2009, 2010 Free Software Foundation, Inc. * * This software is distributed under the terms of the GNU Affero Public License. * See the COPYING file in the main directory for details. * * This use of this software may be subject to additional restrictions. * See the LEGAL file in the main directory for details. This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ #include #include #include "GSMLogicalChannel.h" #include "GSML3RRMessages.h" // mobID #include "Sockets.h" #include "CollectMSInfo.h" #include "RRLPQueryController.h" namespace GSM { namespace RRLP { // Assistance Data: /* 15> rrlp:decodePDU(util:zeroones_to_bin("010000100000010000001000")). {ok,{'PDU',2, {msrPositionRsp, {'MsrPosition-Rsp',asn1_NOVALUE,asn1_NOVALUE,asn1_NOVALUE, asn1_NOVALUE,asn1_NOVALUE, {'LocationError',notEnoughSats,asn1_NOVALUE}, asn1_NOVALUE,asn1_NOVALUE,asn1_NOVALUE,asn1_NOVALUE}}}} */ /** @return true if got RR response */ PositionResult doRRLPQuery(L3MobileIdentity mobID, LogicalChannel* chan, BitVector& rrlp_position_request) { return RRLPQueryManager::instance()->doTransaction(mobID, chan, rrlp_position_request); } PositionResult doRRLPQuery(L3MobileIdentity mobID, LogicalChannel* chan) { return RRLPQueryManager::instance()->doTransaction(mobID, chan); } // Not actually used right now. void doMultipleRRLPQueries(L3MobileIdentity mobID, LogicalChannel* chan) { if (doRRLPQuery(mobID, chan).mValid) { int tests = 0; bool done = false; while (tests > 0 && !done) { LOG(INFO) << "test " << tests; done = doRRLPQuery(mobID, chan).mValid; --tests; } } } void logMSInfo(LogicalChannel* LCH, L3MobileIdentity mobID) { // Log without position, in a way that we can easily tell there was no position - use negatives (we only // use positives right now PositionResult pr; pr.mValid = true; pr.mPos.mLat = pr.mPos.mLon = -1; logMSInfo(LCH, pr, mobID); } // FIXME -- Most of this should be replaced with Wireshark GSMTAP logging. // mobID is just logged as INFO for debugging void logMSInfo(LogicalChannel* LCH, const PositionResult& pr, L3MobileIdentity mobID) { // Config says we should collect. So collect. Timeval now; std::ostringstream stream; stream << now; // GPS (if valid) if (pr.mValid) { stream << "," << pr.mPos.mLat << "," << pr.mPos.mLon; } else { stream << ",0.0,0.0"; } // own transceiver parameters stream << "," << LCH->FER() << "," << LCH->RSSI() << "," << LCH->timingError() << "," << LCH->actualMSPower() << "," << LCH->actualMSTiming(); // MS transceiver parameters const L3MeasurementResults& m = LCH->SACCH()->measurementResults(); unsigned RXLEV_NCELL[6]; m.RXLEV_NCELL(RXLEV_NCELL); unsigned BCCH_FREQ_NCELL[6]; m.BCCH_FREQ_NCELL(BCCH_FREQ_NCELL); unsigned BSIC_NCELL[6]; m.BSIC_NCELL(BSIC_NCELL); stream << "," << m.BA_USED() << "," << m.DTX_USED() << "," << m.MEAS_VALID() << "," << m.RXLEV_FULL_SERVING_CELL() << "," << m.RXLEV_SUB_SERVING_CELL() << "," << m.RXQUAL_FULL_SERVING_CELL() << "," << m.RXQUAL_SUB_SERVING_CELL() << "," << m.NO_NCELL(); for (unsigned i = 0 ; i < m.NO_NCELL() && i < 6; ++i) { stream << "," << RXLEV_NCELL[i] << "," << BCCH_FREQ_NCELL[i] << "," << BSIC_NCELL[i]; } unsigned port = gConfig.getNum("Indications.TargetPort"); const char* ip = gConfig.getStr("Indications.TargetIP"); UDPSocket collect_sock(0, ip, port); collect_sock.write(stream.str().c_str()); LOG(INFO) << "(" << mobID << ")Lat,Lon,FER,RSSI,timingError,actualMSPower,actualMSTiming"; LOG(INFO) << stream.str().c_str(); } void collectMSInfo(L3MobileIdentity mobID, LogicalChannel* LCH, bool withRRLP) { // Check configuration // RRLP Test code. we now have a channel, send a request for position static const char* rrlpOnName = "GSM.RRLP"; PositionResult pr; if (gConfig.defines(rrlpOnName) && gConfig.getNum(rrlpOnName) == 1 && withRRLP) { LOG(INFO) << "Doing RRLPQuery"; pr = doRRLPQuery(mobID, LCH); // FIXME: put this back in RRLP::RRLPQuery logMSInfo(LCH, pr, mobID); } else { logMSInfo(LCH, mobID); } } }; // namespace RRLP }; // namespace GSM /* Replies I got for the RRLP so far: Mostly: 0000 0101 00011011 0 5 1B MM MM TMSI REALLOCATION COMPLETE This is an MM TMSI REALLOCATION COMPLETE Sometimes: 000001100001001001100001 0000 0110 00010010 01100001 0 6 12 61 RR RR Status Message type non existent or not implemented. This is an RR message (good!) --- Android G1 19.8 0000 0110 00111000 00000000 00000001 00000110 0000 0110 00111000 00000000 00001110 0100001000000100100110010001001011010000000000010000000000010010100100000100010000000000001011000101000000100100 Once: 0000 0110 00111000 00000000 00010010 0 RR 001 0 001 0 00000 1 Ref num = 1 No extensions msrPositionRsp The rest (didn't parse this yet) 0010011001000110101101000000000000000000000000111100101100100001000000010000000100001010100010101000110000001100000011101000111010 1 68 00 00 07 96 42 02 02 15 15 18 18 1D 1D Also got (not sure from who - lots of phones here, I think they camped without me really requiring that - maybe should add an option to ignore specific IMSI's?). 0000 0110 00110100 11011110 01010011 RR GPRS Suspension Request 111110010001010100010011000000000001010000010111100101100000000100000001 And 00000110 00111000 00000000 00010010 010000100000010010011001000110101101000000000000000000000000111100101100100001000000010000000100001010100010101000110000001100000011101000111010 */