- leaving new features in public trunk but backing P3.1 branch back to C3.1 for stability

git-svn-id: http://wush.net/svn/range/software/public/openbts/branches/P3.1@6518 19bc5d8c-e614-43d4-8b26-e1612bc8e597
This commit is contained in:
Michael Iedema
2013-09-19 09:46:21 +00:00
parent 2f1394a646
commit aab8237962
50 changed files with 3020 additions and 3737 deletions

View File

@@ -809,6 +809,9 @@ int _config(string mode, int argc, char** argv, ostream& os)
return FAILURE;
}
// }
if (string(argv[1]).compare("GSM.Radio.Band") == 0) {
gConfig.mSchema["GSM.Radio.C0"].updateValidValues(getARFCNsString(gConfig.getNum("GSM.Radio.Band")));
}
vector<string> warnings = gConfig.crossCheck(argv[1]);
vector<string>::iterator warning = warnings.begin();
while (warning != warnings.end()) {
@@ -878,6 +881,9 @@ int rmconfig(int argc, char** argv, ostream& os)
return FAILURE;
}
if (string(argv[1]).compare("GSM.Radio.Band") == 0) {
gConfig.mSchema["GSM.Radio.C0"].updateValidValues(getARFCNsString(gConfig.getNum("GSM.Radio.Band")));
}
os << argv[1] << " set back to its default value" << endl;
vector<string> warnings = gConfig.crossCheck(argv[1]);
vector<string>::iterator warning = warnings.begin();
@@ -977,6 +983,7 @@ int page(int argc, char **argv, ostream& os)
}
int testcall(int argc, char **argv, ostream& os)
{
if (argc!=3) return BAD_NUM_ARGS;
@@ -1280,15 +1287,9 @@ int stats(int argc, char** argv, ostream& os)
{
char cmd[200];
if (argc==2) {
if (strcmp(argv[1],"clear")==0) {
gReports.clear();
os << "stats table (gReporting) cleared" << endl;
return SUCCESS;
}
if (argc==2)
sprintf(cmd,"sqlite3 %s 'select name||\": \"||value||\" events over \"||((%lu-clearedtime)/60)||\" minutes\" from reporting where name like \"%%%s%%\";'",
gConfig.getStr("Control.Reporting.StatsTable").c_str(), time(NULL), argv[1]);
}
else if (argc==1)
sprintf(cmd,"sqlite3 %s 'select name||\": \"||value||\" events over \"||((%lu-clearedtime)/60)||\" minutes\" from reporting;'",
gConfig.getStr("Control.Reporting.StatsTable").c_str(), time(NULL));
@@ -1346,7 +1347,7 @@ void Parser::addCommands()
addCommand("gprs", GPRS::gprsCLI,"GPRS mode sub-command. Type: gprs help for more");
addCommand("sgsn", SGSN::sgsnCLI,"SGSN mode sub-command. Type: sgsn help for more");
addCommand("crashme", crashme, "force crash of OpenBTS for testing purposes");
addCommand("stats", stats,"[patt] OR clear -- print all, or selected, performance counters, OR clear all counters");
addCommand("stats", stats,"[patt] -- print all, or selected, performance statistics");
}

View File

@@ -529,14 +529,6 @@ bool callManagementDispatchGSM(TransactionEntry *transaction, GSM::LogicalChanne
return false;
}
if (dynamic_cast<const GSM::L3CipheringModeComplete*>(message)) {
LOG(DEBUG) << "received Ciphering Mode Complete on " << *LCH << " for " << transaction->subscriber();
// Although the spec (04.08 3.4.7) says you can start ciphering the downlink at this time,
// it also says you can start when you successfully decrypt an uplink layer 2 frame,
// which is what we do.
return false;
}
// Stubs for unsupported features.
// We need to answer the handset so it doesn't hang.
@@ -831,25 +823,6 @@ bool waitInCall(TransactionEntry *transaction, GSM::TCHFACCHLogicalChannel *TCH,
void Control::callManagementLoop(TransactionEntry *transaction, GSM::TCHFACCHLogicalChannel* TCH)
{
LOG(INFO) << " call connected " << *transaction;
if (gConfig.getBool("GSM.Cipher.Encrypt")) {
int encryptionAlgorithm = gTMSITable.getPreferredA5Algorithm(transaction->subscriber().digits());
if (!encryptionAlgorithm) {
LOG(DEBUG) << "A5/3 and A5/1 not supported: NOT sending Ciphering Mode Command on " << *TCH << " for " << transaction->subscriber();
} else if (TCH->decryptUplink_maybe(transaction->subscriber().digits(), encryptionAlgorithm)) {
// send Ciphering Mode Command
// start reception in new mode (GSM 04.08, 3.4.7)
// The spec says to start decrypting uplink at this time, but that would cause us to
// start decrypting before the Ciphering Mode Command is acknowledged, so we start
// maybe decrypting - try decoding without decrypting, and when a frame comes along
// that fails, we try decrypting, and if that passes than we start decrypting everything.
LOG(DEBUG) << "sending Ciphering Mode Command on " << *TCH << " for " << transaction->subscriber();
TCH->send(GSM::L3CipheringModeCommand(
GSM::L3CipheringModeSetting(true, encryptionAlgorithm),
GSM::L3CipheringModeResponse(false)));
} else {
LOG(DEBUG) << "no ki: NOT sending Ciphering Mode Command on " << *TCH << " for " << transaction->subscriber();
}
}
gReports.incr("OpenBTS.GSM.CC.CallMinutes");
// poll everything until the call is finished
// A rough count of frames.

View File

@@ -261,27 +261,6 @@ void Control::LocationUpdatingController(const L3LocationUpdatingRequest* lur, L
return;
}
// Query for classmark?
// This needs to happen before encryption.
// It can't be optional if encryption is desired.
if (IMSIAttach && (gConfig.getBool("GSM.Cipher.Encrypt") || gConfig.getBool("Control.LUR.QueryClassmark"))) {
DCCH->send(L3ClassmarkEnquiry());
L3Message* msg = getMessage(DCCH);
L3ClassmarkChange *resp = dynamic_cast<L3ClassmarkChange*>(msg);
if (!resp) {
if (msg) {
LOG(WARNING) << "Unexpected message " << *msg;
delete msg;
}
throw UnexpectedMessage();
}
LOG(INFO) << *resp;
const L3MobileStationClassmark2& classmark = resp->classmark();
if (!gTMSITable.classmark(IMSI,classmark))
LOG(WARNING) << "failed access to TMSITable";
delete msg;
}
// Did we get a RAND for challenge-response?
if (RAND.length() != 0) {
// Get the mobile's SRES.
@@ -319,19 +298,6 @@ void Control::LocationUpdatingController(const L3LocationUpdatingRequest* lur, L
DCCH->send(L3ChannelRelease());
return;
}
if (gConfig.getBool("GSM.Cipher.Encrypt")) {
int encryptionAlgorithm = gTMSITable.getPreferredA5Algorithm(IMSI);
if (!encryptionAlgorithm) {
LOG(DEBUG) << "A5/3 and A5/1 not supported: NOT sending Ciphering Mode Command on " << *DCCH << " for " << mobileID;
} else if (DCCH->decryptUplink_maybe(mobileID.digits(), encryptionAlgorithm)) {
LOG(DEBUG) << "sending Ciphering Mode Command on " << *DCCH << " for " << mobileID;
DCCH->send(GSM::L3CipheringModeCommand(
GSM::L3CipheringModeSetting(true, encryptionAlgorithm),
GSM::L3CipheringModeResponse(false)));
} else {
LOG(DEBUG) << "no ki: NOT sending Ciphering Mode Command on " << *DCCH << " for " << mobileID;
}
}
gReports.incr("OpenBTS.GSM.MM.Authenticate.Success");
}
catch(SIPTimeout) {
@@ -397,6 +363,25 @@ void Control::LocationUpdatingController(const L3LocationUpdatingRequest* lur, L
delete msg;
}
// Query for classmark?
if (IMSIAttach && gConfig.getBool("Control.LUR.QueryClassmark")) {
DCCH->send(L3ClassmarkEnquiry());
L3Message* msg = getMessage(DCCH);
L3ClassmarkChange *resp = dynamic_cast<L3ClassmarkChange*>(msg);
if (!resp) {
if (msg) {
LOG(WARNING) << "Unexpected message " << *msg;
delete msg;
}
throw UnexpectedMessage();
}
LOG(INFO) << *resp;
const L3MobileStationClassmark2& classmark = resp->classmark();
if (!gTMSITable.classmark(IMSI,classmark))
LOG(WARNING) << "failed access to TMSITable";
delete msg;
}
// We fail closed unless we're configured otherwise
if (!success && !openRegistration) {
LOG(INFO) << "registration FAILED: " << mobileID;

View File

@@ -261,7 +261,7 @@ void AccessGrantResponder(
// for DTM phones; haven't looked into it.
// Set the channel physical parameters from the RACH burst.
LCH->setPhy(RSSI,timingError,gBTS.clock().systime(when.FN()));
LCH->setPhy(RSSI,timingError);
gReports.incr("OpenBTS.GSM.RR.RACH.TA.Accepted",(int)(timingError));
// Assignment, GSM 04.08 3.3.1.1.3.1.
@@ -317,7 +317,7 @@ void abortInboundHandover(TransactionEntry* transaction, unsigned cause, GSM::Lo
bool Control::SaveHandoverAccess(unsigned handoverReference, float RSSI, float timingError, const GSM::Time& timestamp)
bool Control::SaveHandoverAccess(unsigned handoverReference, float RSSI, float timingError)
{
// In this function, we are "BS2" in the ladder diagram.
// This is called from L1 when a handover burst arrives.
@@ -339,7 +339,7 @@ bool Control::SaveHandoverAccess(unsigned handoverReference, float RSSI, float t
}
LOG(INFO) << "saving handover access for " << *transaction;
transaction->setInboundHandover(RSSI,timingError,gBTS.clock().systime(timestamp));
transaction->setInboundHandover(RSSI,timingError);
return true;
}

View File

@@ -57,7 +57,7 @@ void PagingResponseHandler(const GSM::L3PagingResponse*, GSM::LogicalChannel*);
void AssignmentCompleteHandler(const GSM::L3AssignmentComplete*, GSM::TCHFACCHLogicalChannel*);
/** Save handover parameters from L1 in the proper transaction record. */
bool SaveHandoverAccess(unsigned handoverReference, float RSSI, float timingError, const GSM::Time& timestamp);
bool SaveHandoverAccess(unsigned handoverReference, float RSSI, float timingError);
/** Process the handover access; returns when the transaction is cleared. */
void ProcessHandoverAccess(GSM::TCHFACCHLogicalChannel *TCH);

View File

@@ -60,17 +60,6 @@ sqlite3* SMSCBConnectDatabase(const char* path, sqlite3 **DB)
}
void encode7(char mc, int &shift, unsigned int &dp, int &buf, char *thisPage)
{
buf |= (mc & 0x7F) << shift--;
if (shift < 0) {
shift = 7;
} else {
thisPage[dp++] = buf & 0xFF;
buf = buf >> 8;
}
}
void SMSCBSendMessage(sqlite3* DB, sqlite3_stmt* stmt, GSM::CBCHLogicalChannel* CBCH)
{
@@ -108,36 +97,18 @@ void SMSCBSendMessage(sqlite3* DB, sqlite3_stmt* stmt, GSM::CBCHLogicalChannel*
// even though the input text is ASCII for now.
char thisPage[82];
unsigned dp = 0;
int codingScheme;
if (false) { // in case anybody wants to make the encoding selectable
codingScheme = 0x11; // UCS2
thisPage[dp++] = languageCode >> 8;
thisPage[dp++] = languageCode & 0x0ff;
while (dp<82 && mp<messageLen) {
thisPage[dp++] = 0;
thisPage[dp++] = messageText[mp++];
}
while (dp<82) { thisPage[dp++] = 0; thisPage[dp++]='\r'; }
} else {
// 03.38 section 5
codingScheme = 0x10; // 7'
int buf = 0;
int shift = 0;
// The spec (above) says to put this language stuff in, but it doesn't work on my samsung galaxy y.
// encode7(languageCode >> 8, shift, dp, buf, thisPage);
// encode7(languageCode & 0xFF, shift, dp, buf, thisPage);
// encode7('\r', shift, dp, buf, thisPage);
while (dp<81 && mp<messageLen) {
encode7(messageText[mp++], shift, dp, buf, thisPage);
}
while (dp<81) { encode7('\r', shift, dp, buf, thisPage); }
thisPage[dp++] = buf;
thisPage[dp++] = languageCode >> 8;
thisPage[dp++] = languageCode & 0x0ff;
while (dp<82 && mp<messageLen) {
thisPage[dp++] = 0;
thisPage[dp++] = messageText[mp++];
}
while (dp<82) { thisPage[dp++] = 0; thisPage[dp++]='\r'; }
// Format the page into an L3 message.
GSM::L3SMSCBMessage message(
GSM::L3SMSCBSerialNumber(GS,messageCode,updateNumber),
GSM::L3SMSCBMessageIdentifier(messageID),
GSM::L3SMSCBDataCodingScheme(codingScheme),
GSM::L3SMSCBDataCodingScheme(0x11), // UCS2
GSM::L3SMSCBPageParameter(page+1,numPages),
GSM::L3SMSCBContent(thisPage)
);

View File

@@ -135,9 +135,7 @@ bool handleRPDU(TransactionEntry *transaction, const RLFrame& RPDU)
body << submit.UD().decode();
} else if (contentType == "application/vnd.3gpp.sms") {
LOG(DEBUG) << "RPDU: " << RPDU;
RPDU.hex(body);
LOG(DEBUG) << "RPDU result: " << body;
} else {
LOG(ALERT) << "\"" << contentType << "\" is not a valid SMS payload type";
}

View File

@@ -55,8 +55,7 @@ static const char* createTMSITable = {
"RANDLOWER INTEGER, " // authentication token
"SRES INTEGER, " // authentication token
"DEG_LAT FLOAT, " // RRLP result
"DEG_LONG FLOAT, " // RRLP result
"kc varchar(33) default '' "
"DEG_LONG FLOAT " // RRLP result
")"
};
@@ -261,31 +260,6 @@ bool TMSITable::classmark(const char* IMSI, const GSM::L3MobileStationClassmark2
}
int TMSITable::getPreferredA5Algorithm(const char* IMSI)
{
char query[200];
sprintf(query, "SELECT A5_SUPPORT from TMSI_TABLE WHERE IMSI=\"%s\"", IMSI);
sqlite3_stmt *stmt;
if (sqlite3_prepare_statement(mDB,&stmt,query)) {
LOG(ERR) << "sqlite3_prepare_statement failed for " << query;
return 0;
}
if (sqlite3_run_query(mDB,stmt)!=SQLITE_ROW) {
// Returning false here just means the IMSI is not there yet.
sqlite3_finalize(stmt);
return 0;
}
int cm = sqlite3_column_int(stmt,0);
sqlite3_finalize(stmt);
if (cm&1) return 3;
// if (cm&2) return 2; not supported
if (cm&4) return 1;
return 0;
}
void TMSITable::putAuthTokens(const char* IMSI, uint64_t upperRAND, uint64_t lowerRAND, uint32_t SRES)
{
char query[300];

View File

@@ -91,9 +91,6 @@ class TMSITable {
/** Set the classmark. */
bool classmark(const char* IMSI, const GSM::L3MobileStationClassmark2& classmark);
/** Get the preferred A5 algorithm (3, 1, or 0). */
int getPreferredA5Algorithm(const char* IMSI);
/** Save a RAND/SRES pair. */
void putAuthTokens(const char* IMSI, uint64_t upperRAND, uint64_t lowerRAND, uint32_t SRES);

View File

@@ -1068,9 +1068,9 @@ string TransactionEntry::handoverString() const
mSIP.RTPSession()->rtp.last_rcv_SR_ts << "," <<
mSIP.RTPSession()->rtp.last_rcv_SR_time.tv_sec << "," << mSIP.RTPSession()->rtp.last_rcv_SR_time.tv_usec << "," <<
mSIP.RTPSession()->rtp.snd_seq << "," <<
//mSIP.RTPSession()->rtp.last_rtcp_report_snt_r << "," <<
//mSIP.RTPSession()->rtp.last_rtcp_report_snt_s << "," <<
//mSIP.RTPSession()->rtp.rtcp_report_snt_interval << "," <<
mSIP.RTPSession()->rtp.last_rtcp_report_snt_r << "," <<
mSIP.RTPSession()->rtp.last_rtcp_report_snt_s << "," <<
mSIP.RTPSession()->rtp.rtcp_report_snt_interval << "," <<
mSIP.RTPSession()->rtp.last_rtcp_packet_count << "," <<
mSIP.RTPSession()->rtp.sent_payload_bytes;
@@ -1124,11 +1124,11 @@ void TransactionEntry::setOutboundHandover(
}
void TransactionEntry::setInboundHandover(float RSSI, float timingError, double timestamp)
void TransactionEntry::setInboundHandover(float RSSI, float timingError)
{
if (mRemoved) throw RemovedTransaction(mID);
ScopedLock lock(mLock);
mChannel->setPhy(RSSI,timingError,timestamp);
mChannel->setPhy(RSSI,timingError);
mInboundRSSI = RSSI;
mInboundTimingError = timingError;
}

View File

@@ -262,8 +262,7 @@ class TransactionEntry {
/** Set the inbound handover parameters on the channel; state should alread be HandoverInbound. */
void setInboundHandover(
float wRSSI,
float wTimingError,
double wTimestamp
float wTimingError
);
// This is thread-safe because mInboundPeer is only modified in the constructor.

View File

@@ -29,7 +29,6 @@ namespace BSSG {
// GSM 08.16 describes tne NS layer.
// GSM 08.18 sec 10 describes the PDU messages that the SGSN can send to the BSS.
// GSM 48.018 is the updated spec with PS-HANDOVER related commands.
// Definitions:
// NSE - Network Service Entity. There is one or more NSE inside the BSS for signaling.
// NSEI == Network Service Entity Indicator

View File

@@ -237,19 +237,6 @@ int32_t Clock::FN() const
return currentFN;
}
double Clock::systime(const GSM::Time& when) const
{
ScopedLock lock(mLock);
const double slotMicroseconds = (48.0 / 13e6) * 156.25;
const double frameMicroseconds = slotMicroseconds * 8.0;
int32_t elapsedFrames = when.FN() - mBaseFN;
if (elapsedFrames<0) elapsedFrames += gHyperframe;
double elapsedUSec = elapsedFrames * frameMicroseconds + when.TN() * slotMicroseconds;
double baseSeconds = mBaseTime.sec() + mBaseTime.usec()*1e-6;
double st = baseSeconds + 1e-6*elapsedUSec;
return st;
}
void Clock::wait(const Time& when) const
{

View File

@@ -560,9 +560,6 @@ class Clock {
/** Block until the clock passes a given time. */
void wait(const Time&) const;
/** Return the system time associated with a given timestamp. */
double systime(const Time&) const;
};

View File

@@ -120,7 +120,7 @@ void GSMConfig::regenerateBeacon()
L3Frame SI3L3(UNIT_DATA);
SI3->write(SI3L3);
L2Header SI3Header(L2Length(SI3L3.L2Length()));
mSI3Frame = L2Frame(SI3Header,SI3L3,true);
mSI3Frame = L2Frame(SI3Header,SI3L3);
LOG(DEBUG) << "mSI3Frame " << mSI3Frame;
// SI4
@@ -134,7 +134,7 @@ void GSMConfig::regenerateBeacon()
//printf("SI4 bodylength=%d l2len=%d\n",SI4.l2BodyLength(),SI4L3.L2Length());
//printf("SI4L3.size=%d\n",SI4L3.size());
L2Header SI4Header(L2Length(SI4L3.L2Length()));
mSI4Frame = L2Frame(SI4Header,SI4L3,true);
mSI4Frame = L2Frame(SI4Header,SI4L3);
LOG(DEBUG) << "mSI4Frame " << mSI4Frame;
#if GPRS_PAT | GPRS_TEST
@@ -148,12 +148,17 @@ void GSMConfig::regenerateBeacon()
//printf("SI13 bodylength=%d l2len=%d\n",SI13.l2BodyLength(),SI13L3.L2Length());
//printf("SI13L3.size=%d\n",SI13L3.size());
L2Header SI13Header(L2Length(SI13L3.L2Length()));
mSI13Frame = L2Frame(SI13Header,SI13L3,true);
mSI13Frame = L2Frame(SI13Header,SI13L3);
LOG(DEBUG) << "mSI13Frame " << mSI13Frame;
#endif
// SI5
regenerateSI5();
L3SystemInformationType5 *SI5 = new L3SystemInformationType5(neighbors);
if (mSI5) delete mSI5;
mSI5 = SI5;
LOG(INFO) << *SI5;
SI5->write(mSI5Frame);
LOG(DEBUG) << "mSI5Frame " << mSI5Frame;
// SI6
L3SystemInformationType6 *SI6 = new L3SystemInformationType6;
@@ -166,18 +171,8 @@ void GSMConfig::regenerateBeacon()
}
void GSMConfig::regenerateSI5()
{
std::vector<unsigned> neighbors = gNeighborTable.ARFCNList();
// if the neighbor list is emtpy, put ourselves on it
if (neighbors.size()==0) neighbors.push_back(gConfig.getNum("GSM.Radio.C0"));
L3SystemInformationType5 *SI5 = new L3SystemInformationType5(neighbors);
if (mSI5) delete mSI5;
mSI5 = SI5;
LOG(INFO) << *SI5;
SI5->write(mSI5Frame);
LOG(DEBUG) << "mSI5Frame " << mSI5Frame;
}
CCCHLogicalChannel* GSMConfig::minimumLoad(CCCHList &chanList)
{

View File

@@ -190,12 +190,6 @@ class GSMConfig {
*/
void regenerateBeacon();
/**
SI5 is generated separately because it may get random
neighbors added each time it's sent.
*/
void regenerateSI5();
/**
Hold off on channel allocations; don't answer RACH.
@param val true to hold, false to clear hold

View File

@@ -32,7 +32,6 @@
#include <Logger.h>
#include <assert.h>
#include <math.h>
#include <time.h>
#include "../GPRS/GPRSExport.h"
@@ -190,9 +189,7 @@ L1Encoder::L1Encoder(unsigned wCN, unsigned wTN, const TDMAMapping& wMapping, L1
mTotalBursts(0),
mPrevWriteTime(gBTS.time().FN(),wTN),
mNextWriteTime(gBTS.time().FN(),wTN),
mRunning(false),mActive(false),
mEncrypted(ENCRYPT_NO),
mEncryptionAlgorithm(0)
mRunning(false),mActive(false)
{
assert((int)mCN<gConfig.getNum("GSM.Radio.ARFCNs"));
assert(mMapping.allowedSlot(mTN));
@@ -235,12 +232,6 @@ void L1Encoder::open()
mActive = true;
resync();
mPrevWriteTime = gBTS.time();
// Turning off encryption when the channel closes would be a nightmare
// (catching all the ways, and performing the handshake under less than
// ideal conditions), so we leave encryption on to the bitter end,
// then clear the encryption flag here, when the channel gets reused.
mEncrypted = ENCRYPT_NO;
mEncryptionAlgorithm = 0;
}
@@ -322,42 +313,6 @@ unsigned L1Encoder::ARFCN() const
return mDownstream->ARFCN();
}
int unhex(const char c)
{
if (c >= '0' && c <= '9') return c - '0';
if (c >= 'A' && c <= 'F') return c - 'A' + 10;
if (c >= 'a' && c <= 'f') return c - 'a' + 10;
assert(0);
}
// Given IMSI, copy Kc. Return true iff there *is* a Kc.
bool imsi2kc(string wIMSI, unsigned char *wKc)
{
string kc = gTMSITable.getKc(wIMSI.c_str());
if (kc.length() == 0) return false;
while (kc.length() < 16) {
kc = '0' + kc;
}
assert(kc.length() == 16);
unsigned char *dst = wKc;
for (size_t p = 0; p < kc.length(); p += 2) {
*dst++ = (unhex(kc[p]) << 4) | (unhex(kc[p+1]));
}
return true;
}
// Turn on encryption phase-in, which is watching for bad frames and
// retrying them with encryption.
// Return false and leave encryption off if there's no Kc.
bool L1Decoder::decrypt_maybe(string wIMSI, int wA5Alg)
{
if (!imsi2kc(wIMSI, mKc)) return false;
mEncrypted = ENCRYPT_MAYBE;
mEncryptionAlgorithm = wA5Alg;
return true;
}
unsigned L1Decoder::ARFCN() const
@@ -383,12 +338,6 @@ void L1Decoder::open()
mT3109.reset();
mT3101.set();
mActive = true;
// Turning off encryption when the channel closes would be a nightmare
// (catching all the ways, and performing the handshake under less than
// ideal conditions), so we leave encryption on to the bitter end,
// then clear the encryption flag here, when the channel gets reused.
mEncrypted = ENCRYPT_NO;
mEncryptionAlgorithm = 0;
}
@@ -458,10 +407,10 @@ void L1Encoder::handoverPending(bool flag)
{
if (flag) {
bool ok = mDownstream->setHandover(mTN);
if (!ok) LOG(WARNING) << "handover setup failed";
if (!ok) LOG(ALERT) << "handover setup failed";
} else {
bool ok = mDownstream->clearHandover(mTN);
if (!ok) LOG(WARNING) << "handover clear failed";
if (!ok) LOG(ALERT) << "handover clear failed";
}
}
@@ -621,10 +570,8 @@ SharedL1Decoder::SharedL1Decoder()
mHParity(0x06f,6,8),mHU(18),mHD(mHU.head(8))
{
for (int i=0; i<4; i++) {
mE[i] = SoftVector(114);
mI[i] = SoftVector(114);
// Fill with zeros just to make Valgrind happy.
mE[i].fill(.0);
mI[i].fill(.0);
}
}
@@ -639,97 +586,16 @@ void XCCHL1Decoder::writeLowSideRx(const RxBurst& inBurst)
OBJLOG(DEBUG) <<"XCCHL1Decoder not active, ignoring input";
return;
}
// save frame number for possible decrypting
int B = mMapping.reverseMapping(inBurst.time().FN()) % 4;
mFN[B] = inBurst.time().FN();
// Accept the burst into the deinterleaving buffer.
// Return true if we are ready to interleave.
if (!processBurst(inBurst)) return;
if (mEncrypted == ENCRYPT_YES) {
decrypt();
}
if (mEncrypted == ENCRYPT_MAYBE) {
saveMi();
}
deinterleave();
if (decode()) {
countGoodFrame();
mD.LSB8MSB();
handleGoodFrame();
} else {
if (mEncrypted == ENCRYPT_MAYBE) {
// We don't want to start decryption until we get the (encrypted) layer 2 acknowledgement
// of the Ciphering Mode Command, so we start maybe decrypting when we send the command,
// and when the frame comes along, we'll see that it doesn't pass normal decoding, but
// when we try again with decryption, it will pass. Unless it's just noise.
OBJLOG(DEBUG) << "XCCHL1Decoder: try decoding again with decryption";
restoreMi();
decrypt();
deinterleave();
if (decode()) {
OBJLOG(DEBUG) << "XCCHL1Decoder: success on 2nd try";
// We've successfully decoded an encrypted frame. Start decrypting all uplink frames.
mEncrypted = ENCRYPT_YES;
// Also start encrypting downlink frames.
parent()->encoder()->mEncrypted = ENCRYPT_YES;
parent()->encoder()->mEncryptionAlgorithm = mEncryptionAlgorithm;
countGoodFrame();
mD.LSB8MSB();
handleGoodFrame();
} else {
countBadFrame();
}
} else {
countBadFrame();
}
}
}
void XCCHL1Decoder::saveMi()
{
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 114; j++) {
mE[i].settfb(j, mI[i].softbit(j));
}
}
}
void XCCHL1Decoder::restoreMi()
{
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 114; j++) {
mI[i].settfb(j, mE[i].softbit(j));
}
}
}
void XCCHL1Decoder::decrypt()
{
// decrypt y
for (int i = 0; i < 4; i++) {
unsigned char block1[15];
unsigned char block2[15];
// 03.20 C.1.2
// 05.02 3.3.2.2.1
int fn = mFN[i];
int t1 = fn / (26*51);
int t2 = fn % 26;
int t3 = fn % 51;
int count = (t1<<11) | (t3<<5) | t2;
if (mEncryptionAlgorithm == 1) {
A51_GSM(mKc, 64, count, block1, block2);
} else {
A53_GSM(mKc, 64, count, block1, block2);
}
for (int j = 0; j < 114; j++) {
if ((block2[j/8] & (0x80 >> (j%8)))) {
mI[i].settfb(j, 1.0 - mI[i].softbit(j));
}
}
countBadFrame();
}
}
@@ -862,6 +728,25 @@ void XCCHL1Decoder::handleGoodFrame()
}
float SACCHL1Decoder::RSSI() const
{
float sum=mRSSI[0]+mRSSI[1]+mRSSI[2]+mRSSI[3];
return 0.25F*sum;
}
void SACCHL1Decoder::RSSIBumpDown(float dB)
{
mRSSI[0] -= dB;
mRSSI[1] -= dB;
mRSSI[2] -= dB;
mRSSI[3] -= dB;
}
float SACCHL1Decoder::timingError() const
{
float sum=mTimingError[0]+mTimingError[1]+mTimingError[2]+mTimingError[3];
return 0.25F*sum;
}
@@ -875,16 +760,16 @@ bool SACCHL1Decoder::processBurst(const RxBurst& inBurst)
// The actual phone settings change every 4 bursts,
// so average over all 4.
// RSSI is dB wrt full scale.
mRSSI = inBurst.RSSI();
mRSSI[mRSSICounter] = inBurst.RSSI();
// Timing error is a float in symbol intervals.
mTimingError = inBurst.timingError();
// Timestamp
mTimestamp = gBTS.clock().systime(inBurst.time());
mTimingError[mRSSICounter] = inBurst.timingError();
OBJLOG(INFO) << "SACCHL1Decoder " << " RSSI=" << inBurst.RSSI()
<< " timestamp=" << mTimestamp
<< " timingError=" << inBurst.timingError();
mRSSICounter++;
if (mRSSICounter>3) mRSSICounter=0;
return XCCHL1Decoder::processBurst(inBurst);
}
@@ -949,10 +834,8 @@ void SharedL1Encoder::initInterleave(int mIsize)
// Set up the interleaving buffers.
for(int k = 0; k<mIsize; k++) {
mI[k] = BitVector(114);
mE[k] = BitVector(114);
// Fill with zeros just to make Valgrind happy.
mI[k].fill(0);
mE[k].fill(0);
}
}
@@ -1035,7 +918,7 @@ void XCCHL1Encoder::sendFrame(const L2Frame& frame)
//mFECEnc.encodeFrame41(frame,headerOffset(),mFECEnc.mVCoder);
encodeFrame41(frame,headerOffset(), false);
const int qCS1[8] = { 1,1,1,1,1,1,1,1 }; // magically identifies CS-1.
transmit(mI,mE,qCS1);
transmit(mI,qCS1);
}
@@ -1073,7 +956,7 @@ void SharedL1Encoder::interleave41()
// before each transmission, rather than having them be static.
// The qbits, also called stealing bits, are defined in GSM05.03.
// For GPRS they specify the encoding type: CS-1 through CS-4.
void L1Encoder::transmit(BitVector *mI, BitVector *mE, const int *qbits)
void L1Encoder::transmit(BitVector *mI, const int *qbits)
{
// Format the bits into the bursts.
// GSM 05.03 4.1.5, 05.02 5.2.3
@@ -1086,55 +969,12 @@ void L1Encoder::transmit(BitVector *mI, BitVector *mE, const int *qbits)
return;
}
// add noise
// the noise insertion happens below, merged in with the ciphering
int p = gConfig.getFloat("GSM.Cipher.CCHBER") * (float)0xFFFFFF;
for (int qi=0,B=0; B<4; B++) {
mBurst.time(mNextWriteTime);
// encrypt y
if (mEncrypted == ENCRYPT_YES) {
unsigned char block1[15];
unsigned char block2[15];
unsigned char *kc = parent()->decoder()->kc();
// 03.20 C.1.2
// 05.02 3.3.2.2.1
int fn = mNextWriteTime.FN();
int t1 = fn / (26*51);
int t2 = fn % 26;
int t3 = fn % 51;
int count = (t1<<11) | (t3<<5) | t2;
if (mEncryptionAlgorithm == 1) {
A51_GSM(kc, 64, count, block1, block2);
} else {
A53_GSM(kc, 64, count, block1, block2);
}
for (int i = 0; i < 114; i++) {
int b = p ? (random() & 0xFFFFFF) < p : 0;
b = b ^ (block1[i/8] >> (7-(i%8)));
mE[B].settfb(i, mI[B].bit(i) ^ (b&1));
}
} else {
if (p) {
for (int i = 0; i < 114; i++) {
int b = (random() & 0xFFFFFF) < p;
mE[B].settfb(i, mI[B].bit(i) ^ b);
}
} else {
// no noise or encryption. use mI below.
}
}
// Copy in the "encrypted" bits, GSM 05.03 4.1.5, 05.02 5.2.3.
OBJLOG(DEBUG) << "transmit mE["<<B<<"]=" << mE[B];
if (p || mEncrypted == ENCRYPT_YES) {
mE[B].segment(0,57).copyToSegment(mBurst,3);
mE[B].segment(57,57).copyToSegment(mBurst,88);
} else {
// no noise or encryption. use mI.
mI[B].segment(0,57).copyToSegment(mBurst,3);
mI[B].segment(57,57).copyToSegment(mBurst,88);
}
OBJLOG(DEBUG) << "transmit mI["<<B<<"]=" << mI[B];
mI[B].segment(0,57).copyToSegment(mBurst,3);
mI[B].segment(57,57).copyToSegment(mBurst,88);
mBurst.Hl(qbits[qi++]);
mBurst.Hu(qbits[qi++]);
// Send it to the radio.
@@ -1305,11 +1145,9 @@ TCHFACCHL1Decoder::TCHFACCHL1Decoder(
mTCHParity(0x0b,3,50)
{
for (int i=0; i<8; i++) {
mE[i] = SoftVector(114);
mI[i] = SoftVector(114);
// Fill with zeros just to make Valgrind happy.
mI[i].fill(.0);
mE[i].fill(.0);
}
}
@@ -1359,7 +1197,7 @@ void TCHFACCHL1Decoder::writeLowSideRx(const RxBurst& inBurst)
unsigned ref = mHD.peekField(0,8);
LOG(INFO) << "handover access ref=" << ref;
if (!Control::SaveHandoverAccess(ref,inBurst.RSSI(),inBurst.timingError(),inBurst.time())) return;
if (!Control::SaveHandoverAccess(ref,inBurst.RSSI(),inBurst.timingError())) return;
mUpstream->writeLowSide(HANDOVER_ACCESS);
return;
}
@@ -1368,6 +1206,8 @@ void TCHFACCHL1Decoder::writeLowSideRx(const RxBurst& inBurst)
// (pat) How the burst gets here:
// TRXManager.cpp has a wDemuxTable for each frame+timeslot with a pointer to
// a virtual L1Decoder::writeLowSideRx() function. For traffic channels, this maps to
@@ -1394,21 +1234,10 @@ bool TCHFACCHL1Decoder::processBurst( const RxBurst& inBurst)
inBurst.data1().copyToSegment(mI[B],0);
inBurst.data2().copyToSegment(mI[B],57);
// save the frame numbers for each burst for possible decryption later
mFN[B] = inBurst.time().FN();
// Every 4th frame is the start of a new block.
// So if this isn't a "4th" frame, return now.
if (B%4!=3) return false;
if (mEncrypted == ENCRYPT_MAYBE) {
saveMi();
}
if (mEncrypted == ENCRYPT_YES) {
decrypt(B);
}
// Deinterleave according to the diagonal "phase" of B.
// See GSM 05.03 3.1.3.
// Deinterleaves i[] to c[]
@@ -1419,30 +1248,7 @@ bool TCHFACCHL1Decoder::processBurst( const RxBurst& inBurst)
bool stolen = inBurst.Hl();
OBJLOG(DEBUG) <<"TCHFACCHL1Decoder Hl=" << inBurst.Hl() << " Hu=" << inBurst.Hu();
if (stolen) {
bool ok = decode();
if (!ok && mEncrypted == ENCRYPT_MAYBE) {
// We don't want to start decryption until we get the (encrypted) layer 2 acknowledgement
// of the Ciphering Mode Command, so we start maybe decrypting when we send the command,
// and when the frame comes along, we'll see that it doesn't pass normal decoding, but
// when we try again with decryption, it will pass. Unless it's just noise.
OBJLOG(DEBUG) << "TCHFACCHL1Decoder: try decoding again with decryption";
restoreMi();
decrypt(-1);
// re-deinterleave
if (B==3) deinterleave(4);
else deinterleave(0);
// re-decode
ok = decode();
if (ok) {
OBJLOG(DEBUG) << "TCHFACCHL1Decoder: success on 2nd try";
// We've successfully decoded an encrypted frame. Start decrypting all uplink frames.
mEncrypted = ENCRYPT_YES;
// Also start encrypting downlink frames.
parent()->encoder()->mEncrypted = ENCRYPT_YES;
parent()->encoder()->mEncryptionAlgorithm = mEncryptionAlgorithm;
}
}
if (ok) {
if (decode()) {
OBJLOG(DEBUG) <<"TCHFACCHL1Decoder good FACCH frame";
countGoodFrame();
mD.LSB8MSB();
@@ -1470,52 +1276,6 @@ bool TCHFACCHL1Decoder::processBurst( const RxBurst& inBurst)
}
void TCHFACCHL1Decoder::saveMi()
{
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 114; j++) {
mE[i].settfb(j, mI[i].softbit(j));
}
}
}
void TCHFACCHL1Decoder::restoreMi()
{
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 114; j++) {
mI[i].settfb(j, mE[i].softbit(j));
}
}
}
void TCHFACCHL1Decoder::decrypt(int B)
{
// decrypt x
unsigned char block1[15];
unsigned char block2[15];
int bb = B==7 ? 4 : 0;
int be = B<0 ? 8 : bb+4;
for (int i = bb; i < be; i++) {
// 03.20 C.1.2
// 05.02 3.3.2.2.1
int fn = mFN[i];
int t1 = fn / (26*51);
int t2 = fn % 26;
int t3 = fn % 51;
int count = (t1<<11) | (t3<<5) | t2;
if (mEncryptionAlgorithm == 1) {
A51_GSM(mKc, 64, count, block1, block2);
} else {
A53_GSM(mKc, 64, count, block1, block2);
}
for (int j = 0; j < 114; j++) {
if ((block2[j/8] & (0x80 >> (j%8)))) {
mI[i].settfb(j, 1.0 - mI[i].softbit(j));
}
}
}
}
void TCHFACCHL1Decoder::deinterleave(int blockOffset )
@@ -1654,10 +1414,8 @@ TCHFACCHL1Encoder::TCHFACCHL1Encoder(
{
for(int k = 0; k<8; k++) {
mI[k] = BitVector(114);
mE[k] = BitVector(114);
// Fill with zeros just to make Valgrind happy.
mI[k].fill(0);
mE[k].fill(0);
}
}
@@ -1808,57 +1566,15 @@ void TCHFACCHL1Encoder::dispatch()
// Interleave c[] to i[].
interleave31(mOffset);
// randomly toggle bits in control channel bursts
// the toggle happens below, merged in with the ciphering
int p = currentFACCH ? gConfig.getFloat("GSM.Cipher.CCHBER") * (float)0xFFFFFF : 0;
// "mapping on a burst"
// Map c[] into outgoing normal bursts, marking stealing flags as needed.
// GMS 05.03 3.1.4.
for (int B=0; B<4; B++) {
// set TDMA position
mBurst.time(mNextWriteTime);
// encrypt x
if (mEncrypted == ENCRYPT_YES) {
unsigned char block1[15];
unsigned char block2[15];
unsigned char *kc = parent()->decoder()->kc();
// 03.20 C.1.2
// 05.02 3.3.2.2.1
int fn = mNextWriteTime.FN();
int t1 = fn / (26*51);
int t2 = fn % 26;
int t3 = fn % 51;
int count = (t1<<11) | (t3<<5) | t2;
if (mEncryptionAlgorithm == 1) {
A51_GSM(kc, 64, count, block1, block2);
} else {
A53_GSM(kc, 64, count, block1, block2);
}
for (int i = 0; i < 114; i++) {
int b = p ? (random() & 0xFFFFFF) < p : 0;
b = b ^ (block1[i/8] >> (7-(i%8)));
mE[B+mOffset].settfb(i, mI[B+mOffset].bit(i) ^ (b&1));
}
} else {
if (p) {
for (int i = 0; i < 114; i++) {
int b = (random() & 0xFFFFFF) < p;
mE[B+mOffset].settfb(i, mI[B+mOffset].bit(i) ^ b);
}
} else {
// no noise and no encryption - use mI below
}
}
// copy in the bits
if (p || mEncrypted == ENCRYPT_YES) {
mE[B+mOffset].segment(0,57).copyToSegment(mBurst,3);
mE[B+mOffset].segment(57,57).copyToSegment(mBurst,88);
} else {
// no noise and no encryption - use mI
mI[B+mOffset].segment(0,57).copyToSegment(mBurst,3);
mI[B+mOffset].segment(57,57).copyToSegment(mBurst,88);
}
mI[B+mOffset].segment(0,57).copyToSegment(mBurst,3);
mI[B+mOffset].segment(57,57).copyToSegment(mBurst,88);
// stealing bits
mBurst.Hu(currentFACCH);
mBurst.Hl(mPreviousFACCH);
@@ -1903,9 +1619,9 @@ void SACCHL1FEC::setPhy(const SACCHL1FEC& other)
mSACCHEncoder->setPhy(*other.mSACCHEncoder);
}
void SACCHL1FEC::setPhy(float RSSI, float timingError, double wTimestamp)
void SACCHL1FEC::setPhy(float RSSI, float timingError)
{
mSACCHDecoder->setPhy(RSSI,timingError,wTimestamp);
mSACCHDecoder->setPhy(RSSI,timingError);
mSACCHEncoder->setPhy(RSSI,timingError);
}
@@ -1925,13 +1641,12 @@ void SACCHL1Decoder::open()
void SACCHL1Decoder::setPhy(float wRSSI, float wTimingError, double wTimestamp)
void SACCHL1Decoder::setPhy(float wRSSI, float wTimingError)
{
// Used to initialize L1 phy parameters.
mRSSI=wRSSI;
mTimingError=wTimingError;
mTimestamp=wTimestamp;
OBJLOG(INFO) << "SACCHL1Decoder RSSI=" << wRSSI << " timingError=" << wTimingError << " timestamp=" << wTimestamp;
for (int i=0; i<4; i++) mRSSI[i]=wRSSI;
for (int i=0; i<4; i++) mTimingError[i]=wTimingError;
OBJLOG(INFO) << "SACCHL1Decoder RSSI=" << wRSSI << "timingError=" << wTimingError;
}
void SACCHL1Decoder::setPhy(const SACCHL1Decoder& other)
@@ -1940,11 +1655,9 @@ void SACCHL1Decoder::setPhy(const SACCHL1Decoder& other)
// from those of a preexisting established channel.
mActualMSPower = other.mActualMSPower;
mActualMSTiming = other.mActualMSTiming;
mRSSI=other.mRSSI;
mTimingError=other.mTimingError;
mTimestamp=other.mTimestamp;
OBJLOG(INFO) << "SACCHL1Decoder actuals RSSI=" << mRSSI << " timingError=" << mTimingError
<< " timestamp=" << mTimestamp
for (int i=0; i<4; i++) mRSSI[i]=other.mRSSI[i];
for (int i=0; i<4; i++) mTimingError[i]=other.mTimingError[i];
OBJLOG(INFO) << "SACCHL1Decoder actuals RSSI=" << mRSSI[0] << "timingError=" << mTimingError[0]
<< " MSPower=" << mActualMSPower << " MSTiming=" << mActualMSTiming;
}

View File

@@ -30,9 +30,6 @@
#include "GSMTransfer.h"
#include "GSMTDMA.h"
#include "a53.h"
#include "A51.h"
#include "GSM610Tables.h"
#include <Globals.h>
@@ -69,14 +66,6 @@ class TrafficTranscoder;
*/
enum EncryptionType {
ENCRYPT_NO,
ENCRYPT_MAYBE,
ENCRYPT_YES
};
/**
Abstract class for L1 encoders.
@@ -129,9 +118,6 @@ class L1Encoder {
public:
EncryptionType mEncrypted;
int mEncryptionAlgorithm;
/**
The basic encoder constructor.
@param wCN carrier index.
@@ -152,7 +138,7 @@ class L1Encoder {
ARFCNManager *getRadio() { return mDownstream; }
// Used by XCCHEncoder
void transmit(BitVector *mI, BitVector *mE, const int *qbits);
void transmit(BitVector *mI, const int *qbits);
/**@name Accessors. */
//@{
@@ -272,10 +258,7 @@ class L1Decoder {
// (pat) Moved to classes that use the convolutional coder.
//ViterbiR2O4 mVCoder; ///< nearly all GSM channels use the same convolutional code
EncryptionType mEncrypted;
int mEncryptionAlgorithm;
unsigned char mKc[8];
int mFN[8];
unsigned mRSSIHistory[4];
public:
@@ -294,9 +277,7 @@ class L1Decoder {
mRunning(false),
mFER(0.0F),
mCN(wCN),mTN(wTN),
mMapping(wMapping),mParent(wParent),
mEncrypted(ENCRYPT_NO),
mEncryptionAlgorithm(0)
mMapping(wMapping),mParent(wParent)
{
// Start T3101 so that the channel will
// become recyclable soon.
@@ -378,9 +359,6 @@ class L1Decoder {
public:
void countGoodFrame();
void countBadFrame();
bool decrypt_maybe(string wIMSI, int wA5Alg);
unsigned char *kc() { return mKc; }
};
@@ -682,7 +660,6 @@ class SharedL1Encoder
public:
BitVector mD; ///< d[], as per GSM 05.03 2.2 Incoming Data.
BitVector mI[4]; ///< i[][], as per GSM 05.03 2.2 Outgoing Data.
BitVector mE[4];
/**
Encode u[] to c[].
@@ -722,7 +699,6 @@ class SharedL1Decoder
BitVector mDP; ///< d[]:p[] (data & parity)
public:
BitVector mD; ///< d[], as per GSM 05.03 2.2
SoftVector mE[4];
SoftVector mI[4]; ///< i[][], as per GSM 05.03 2.2
/**@name Handover Access Burst FEC state. */
//@{
@@ -780,10 +756,6 @@ class XCCHL1Decoder :
XCCHL1Decoder(unsigned wCN, unsigned wTN, const TDMAMapping& wMapping,
L1FEC *wParent);
void saveMi();
void restoreMi();
void decrypt();
protected:
/** Offset to the start of the L2 header. */
@@ -853,9 +825,9 @@ class SACCHL1Decoder : public XCCHL1Decoder {
private:
SACCHL1FEC *mSACCHParent;
volatile float mRSSI; ///< most recent RSSI, dB wrt full scale
volatile float mTimingError; ///< Timing error history in symbols
volatile double mTimestamp; ///< system time of most recent received burst
unsigned mRSSICounter;
volatile float mRSSI[4]; ///< RSSI history , dB wrt full scale
volatile float mTimingError[4]; ///< Timing error histoty in symbol
volatile int mActualMSPower; ///< actual MS tx power in dBm
volatile int mActualMSTiming; ///< actual MS tx timing advance in symbols
@@ -868,12 +840,10 @@ class SACCHL1Decoder : public XCCHL1Decoder {
SACCHL1FEC *wParent)
:XCCHL1Decoder(wCN,wTN,wMapping,(L1FEC*)wParent),
mSACCHParent(wParent),
mRSSI(0.0F),
mTimingError(0.0F),
mTimestamp(0.0),
mActualMSPower(0),
mActualMSTiming(0)
{ }
mRSSICounter(0)
{
for (int i=0; i<4; i++) mRSSI[i]=0.0F;
}
ChannelType channelType() const { return SACCHType; }
@@ -889,24 +859,21 @@ class SACCHL1Decoder : public XCCHL1Decoder {
bool processBurst(const RxBurst&);
/** Set pyshical parameters for initialization. */
void setPhy(float wRSSI, float wTimingError, double wTimestamp);
void setPhy(float wRSSI, float wTimingError);
void setPhy(const SACCHL1Decoder& other);
/** RSSI of most recent received burst, in dB wrt full scale. */
float RSSI() const { return mRSSI; }
float RSSI() const;
/** Artificially push down RSSI to induce the handset to push more power. */
void RSSIBumpDown(float dB) { mRSSI -= dB; }
void RSSIBumpDown(float dB);
/**
Timing error of most recent received burst, symbol units.
Positive is late; negative is early.
*/
float timingError() const { return mTimingError; }
/** Timestamp of most recent received burst. */
double timestamp() const { return mTimestamp; }
float timingError() const;
protected:
@@ -1003,7 +970,6 @@ private:
bool mPreviousFACCH; ///< A copy of the previous stealing flag state.
size_t mOffset; ///< Current deinterleaving offset.
BitVector mE[8];
// (pat) Yes, the mI here duplicates but overrides the same
// vector down in XCCHL1Encoder.
BitVector mI[8]; ///< deinterleaving history, 8 blocks instead of 4
@@ -1073,7 +1039,6 @@ class TCHFACCHL1Decoder : public XCCHL1Decoder {
protected:
SoftVector mE[8]; ///< deinterleaving history, 8 blocks instead of 4
SoftVector mI[8]; ///< deinterleaving history, 8 blocks instead of 4
BitVector mTCHU; ///< u[] (uncoded) in the spec
BitVector mTCHD; ///< d[] (data) in the spec
@@ -1106,10 +1071,6 @@ class TCHFACCHL1Decoder : public XCCHL1Decoder {
deinterleave, decode, handleGoodFrame.
*/
bool processBurst( const RxBurst& );
void saveMi();
void restoreMi();
void decrypt(int B);
/** Deinterleave i[] to c[]. */
void deinterleave(int blockOffset );
@@ -1478,11 +1439,10 @@ class SACCHL1FEC : public L1FEC {
//@{
float RSSI() const { return mSACCHDecoder->RSSI(); }
float timingError() const { return mSACCHDecoder->timingError(); }
double timestamp() const { return mSACCHDecoder->timestamp(); }
int actualMSPower() const { return mSACCHDecoder->actualMSPower(); }
int actualMSTiming() const { return mSACCHDecoder->actualMSTiming(); }
void setPhy(const SACCHL1FEC&);
virtual void setPhy(float RSSI, float timingError, double wTimestamp);
virtual void setPhy(float RSSI, float timingError);
void RSSIBumpDown(int dB) { mSACCHDecoder->RSSIBumpDown(dB); }
//@}
};

View File

@@ -65,7 +65,7 @@ void CCCHL2::writeHighSide(const GSM::L3Frame& l3)
assert(mDownstream);
assert(l3.primitive()==UNIT_DATA);
L2Header header(L2Length(l3.L2Length()));
mDownstream->writeHighSide(L2Frame(header,l3,true));
mDownstream->writeHighSide(L2Frame(header,l3));
}
@@ -87,7 +87,6 @@ L2LAPDm::L2LAPDm(unsigned wC, unsigned wSAPI)
mIdleFrame.fillField(8*0,(mC<<1)|1,8); // address
mIdleFrame.fillField(8*1,3,8); // control
mIdleFrame.fillField(8*2,1,8); // length
if (gConfig.getBool("GSM.Cipher.ScrambleFiller")) mIdleFrame.randomizeFiller(8*4);
}

View File

@@ -377,7 +377,7 @@ void L3RequestReference::writeV( L3Frame &dest, size_t &wp ) const
void L3RequestReference::text(ostream& os) const
{
os << hex << "RA=0x" << mRA << dec;
os << "RA=" << mRA;
// pat added: This is the frame number recomputed from T1p, T2, T3:
unsigned recomputed = 51 * ((mT3-mT2) % 26) + mT3 + 51 * 26 * mT1p;
os << " T=" << recomputed;
@@ -784,39 +784,6 @@ void L3HandoverReference::text(ostream& os) const
}
size_t L3CipheringModeSetting::lengthV() const
{
return 0;
}
void L3CipheringModeSetting::writeV(L3Frame& frame, size_t& wp) const
{
frame.writeField(wp, mCiphering? mAlgorithm-1: 0, 3);
frame.writeField(wp, mCiphering, 1);
}
void L3CipheringModeSetting::text(ostream& os) const
{
os << "ciphering=" << mCiphering;
os << " algorithm=A5/" << mAlgorithm;
}
size_t L3CipheringModeResponse::lengthV() const
{
return 0;
}
void L3CipheringModeResponse::writeV(L3Frame& frame, size_t& wp) const
{
frame.writeField(wp, 0, 3);
frame.writeField(wp, mIncludeIMEISV, 1);
}
void L3CipheringModeResponse::text(ostream& os) const
{
os << "includeIMEISV=" << mIncludeIMEISV;
}
void L3SynchronizationIndication::writeV(L3Frame& frame, size_t& wp) const
{
frame.writeField(wp,0xD,4);

View File

@@ -876,49 +876,6 @@ class L3HandoverReference : public L3ProtocolElement
unsigned value() const { return mValue; }
};
/** GSM 04.08 10.5.2.9 */
class L3CipheringModeSetting : public L3ProtocolElement
{
protected:
bool mCiphering;
int mAlgorithm; // algorithm is A5/mAlgorithm
public:
L3CipheringModeSetting(bool wCiphering, int wAlgorithm)
:mCiphering(wCiphering), mAlgorithm(wAlgorithm)
{
// assert(wAlgorithm >= 1 && wAlgorithm <= 7);
}
size_t lengthV() const;
void writeV(L3Frame&, size_t& wp) const;
void parseV( const L3Frame&, size_t&, size_t) { abort(); }
void parseV(const L3Frame&, size_t&) { abort(); }
void text(std::ostream&) const;
};
/** GSM 04.08 10.5.2.10 */
class L3CipheringModeResponse : public L3ProtocolElement
{
protected:
bool mIncludeIMEISV;
public:
L3CipheringModeResponse(bool wIncludeIMEISV)
:mIncludeIMEISV(wIncludeIMEISV)
{ }
size_t lengthV() const;
void writeV(L3Frame&, size_t& wp) const;
void parseV( const L3Frame&, size_t&, size_t) { abort(); }
void parseV(const L3Frame&, size_t&) { abort(); }
void text(std::ostream&) const;
};
/** GSM 04.08 10.5.2.39 */
class L3SynchronizationIndication : public L3ProtocolElement
{

View File

@@ -121,10 +121,6 @@ ostream& GSM::operator<<(ostream& os, L3RRMessage::MessageType val)
os << "Handover Complete"; break;
case L3RRMessage::HandoverFailure:
os << "Handover Failure"; break;
case L3RRMessage::CipheringModeCommand:
os << "Ciphering Mode Command"; break;
case L3RRMessage::CipheringModeComplete:
os << "Ciphering Mode Complete"; break;
case L3RRMessage::PhysicalInformation:
os << "Physical Information"; break;
default: os << hex << "0x" << (int)val << dec;
@@ -155,7 +151,6 @@ L3RRMessage* GSM::L3RRFactory(L3RRMessage::MessageType MTI)
case L3RRMessage::ApplicationInformation: return new L3ApplicationInformation();
case L3RRMessage::HandoverComplete: return new L3HandoverComplete();
case L3RRMessage::HandoverFailure: return new L3HandoverFailure();
case L3RRMessage::CipheringModeComplete: return new L3CipheringModeComplete();
// Partial support just to get along with some phones.
case L3RRMessage::GPRSSuspensionRequest: return new L3GPRSSuspensionRequest();
default:
@@ -466,12 +461,6 @@ void L3SystemInformationType5::writeBody(L3Frame& dest, size_t &wp) const
- BCCH Frequency List 10.5.2.22 M V 16
*/
mBCCHFrequencyList.writeV(dest,wp);
wp -= 111;
int p = gConfig.getFloat("GSM.Cipher.RandomNeighbor") * (float)0xFFFFFF;
for (unsigned i = 1; i <= 111; i++) {
int b = ((random() & 0xFFFFFF) < p) | dest.peekField(wp, 1);
dest.writeField(wp, b, 1);
}
}
@@ -872,39 +861,6 @@ void L3HandoverFailure::text(ostream& os) const
os << "cause=" << mCause;
}
int L3CipheringModeCommand::MTI() const
{
return CipheringModeCommand;
}
void L3CipheringModeCommand::writeBody(L3Frame& frame, size_t& wp) const
{
// reverse order of 1/2-octet fields
mCipheringResponse.writeV(frame,wp);
mCipheringModeSetting.writeV(frame,wp);
}
void L3CipheringModeCommand::text(ostream& os) const
{
L3RRMessage::text(os);
os << "ciphering mode setting=(" << mCipheringModeSetting << ")";
os << " ciphering response=(" << mCipheringResponse << ")";
}
int L3CipheringModeComplete::MTI() const
{
return CipheringModeComplete;
}
void L3CipheringModeComplete::parseBody(const L3Frame& frame, size_t& rp)
{
// mobile equipment identity optional
}
void L3CipheringModeComplete::text(ostream& os) const
{
L3RRMessage::text(os);
}
void L3PhysicalInformation::writeBody(L3Frame& frame, size_t& wp) const
{

View File

@@ -101,7 +101,6 @@ class L3RRMessage : public L3Message {
///@name ciphering
//@{
CipheringModeCommand=0x35,
CipheringModeComplete=0x32,
//@}
///@name miscellaneous
//@{
@@ -1121,43 +1120,6 @@ class L3HandoverFailure : public L3RRMessageNRO {
};
/** GSM 04.08 9.1.9 */
class L3CipheringModeCommand : public L3RRMessageNRO {
protected:
L3CipheringModeSetting mCipheringModeSetting;
L3CipheringModeResponse mCipheringResponse;
public:
L3CipheringModeCommand(L3CipheringModeSetting wCipheringModeSetting, L3CipheringModeResponse wCipheringResponse)
: mCipheringModeSetting(wCipheringModeSetting),
mCipheringResponse(wCipheringResponse)
{ }
int MTI() const;
size_t l2BodyLength() const { return 1; }
void writeBody(L3Frame&, size_t&) const;
void text(std::ostream&) const;
};
/** GSM 04.08 9.1.10 */
class L3CipheringModeComplete : public L3RRMessageNRO {
protected:
public:
int MTI() const;
size_t l2BodyLength() const { return 0; }
void parseBody(const L3Frame&, size_t&);
void text(std::ostream&) const;
};
/** GSM 04.08 9.1.28 */
class L3PhysicalInformation : public L3RRMessageNRO {

View File

@@ -372,10 +372,7 @@ void SACCHLogicalChannel::serviceLoop()
// Send alternating SI5/SI6.
// These L3Frames were created with the UNIT_DATA primivitive.
OBJLOG(DEBUG) << "sending SI5/6 on SACCH";
if (count%2) {
gBTS.regenerateSI5();
LogicalChannel::send(gBTS.SI5Frame());
}
if (count%2) LogicalChannel::send(gBTS.SI5Frame());
else LogicalChannel::send(gBTS.SI6Frame());
count++;
@@ -467,16 +464,14 @@ void *GSM::SACCHLogicalChannelServiceLoopAdapter(SACCHLogicalChannel* chan)
// These have to go into the .cpp file to prevent an illegal forward reference.
void LogicalChannel::setPhy(float wRSSI, float wTimingError, double wTimestamp)
{ assert(mSACCH); mSACCH->setPhy(wRSSI,wTimingError,wTimestamp); }
void LogicalChannel::setPhy(float wRSSI, float wTimingError)
{ assert(mSACCH); mSACCH->setPhy(wRSSI,wTimingError); }
void LogicalChannel::setPhy(const LogicalChannel& other)
{ assert(mSACCH); mSACCH->setPhy(*other.SACCH()); }
float LogicalChannel::RSSI() const
{ assert(mSACCH); return mSACCH->RSSI(); }
float LogicalChannel::timingError() const
{ assert(mSACCH); return mSACCH->timingError(); }
double LogicalChannel::timestamp() const
{ assert(mSACCH); return mSACCH->timestamp(); }
int LogicalChannel::actualMSPower() const
{ assert(mSACCH); return mSACCH->actualMSPower(); }
int LogicalChannel::actualMSTiming() const

View File

@@ -117,7 +117,7 @@ public:
GSM::Time getNextWriteTime() { return mL1->encoder()->getNextWriteTime(); }
/** Set L1 physical parameters from a RACH or pre-exsting channel. */
virtual void setPhy(float wRSSI, float wTimingError, double wTimestamp);
virtual void setPhy(float wRSSI, float wTimingError);
/* Set L1 physical parameters from an existing logical channel. */
virtual void setPhy(const LogicalChannel&);
@@ -276,8 +276,6 @@ public:
virtual float RSSI() const;
/** Uplink timing error. */
virtual float timingError() const;
/** System timestamp of RSSI and TA */
virtual double timestamp() const;
/** Actual MS uplink power. */
virtual int actualMSPower() const;
/** Actual MS uplink timing advance. */
@@ -330,8 +328,6 @@ public:
public:
bool inUseByGPRS() { return mL1->inUseByGPRS(); }
bool decryptUplink_maybe(string wIMSI, int wA5Alg) { return mL1->decoder()->decrypt_maybe(wIMSI, wA5Alg); }
};
@@ -432,11 +428,9 @@ class SACCHLogicalChannel : public LogicalChannel {
//@{
float RSSI() const { return mSACCHL1->RSSI(); }
float timingError() const { return mSACCHL1->timingError(); }
double timestamp() const { return mSACCHL1->timestamp(); }
int actualMSPower() const { return mSACCHL1->actualMSPower(); }
int actualMSTiming() const { return mSACCHL1->actualMSTiming(); }
void setPhy(float RSSI, float timingError, double wTimestamp)
{ mSACCHL1->setPhy(RSSI,timingError,wTimestamp); }
void setPhy(float RSSI, float timingError) { mSACCHL1->setPhy(RSSI,timingError); }
void setPhy(const SACCHLogicalChannel& other) { mSACCHL1->setPhy(*other.mSACCHL1); }
void RSSIBumpDown(int dB) { assert(mL1); mSACCHL1->RSSIBumpDown(dB); }

View File

@@ -19,7 +19,6 @@
#include "GSMTransfer.h"
#include "GSML3Message.h"
#include "Globals.h"
using namespace std;
@@ -208,43 +207,6 @@ void L2Frame::idleFill()
}
}
void L2Frame::randomizeFiller(unsigned start)
{
/* for debugging
// no filler or first filler is 0x2b
if (start-8 < size() && peekField(start-8,8) != 0x2b) {
LOG(ALERT) << *this << " " << start;
assert(0);
}
// reset of filler is 0x2b
for (unsigned i = start; i < size(); i+=8) {
if (peekField(i,8) != 0x2b) {
LOG(ALERT) << *this << " " << start << " " << i;
assert(0);
}
}
*/
for (unsigned i = start; i < size(); i++) {
settfb(i, random() & 1);
}
}
void L2Frame::randomizeFiller(const L2Header& header)
{
switch (header.format()) {
case L2Header::FmtA:
case L2Header::FmtB:
randomizeFiller((header.length().L() + 4) * 8);
return;
case L2Header::FmtBbis:
case L2Header::FmtB4:
randomizeFiller((header.length().L() + 2) * 8);
return;
default:
return;
}
}
L2Frame::L2Frame(const BitVector& bits, Primitive prim)
:BitVector(23*8),mPrimitive(prim)
@@ -256,7 +218,7 @@ L2Frame::L2Frame(const BitVector& bits, Primitive prim)
#include <stdio.h>
L2Frame::L2Frame(const L2Header& header, const BitVector& l3, bool noran)
L2Frame::L2Frame(const L2Header& header, const BitVector& l3)
:BitVector(23*8),mPrimitive(DATA)
{
idleFill();
@@ -265,8 +227,6 @@ L2Frame::L2Frame(const L2Header& header, const BitVector& l3, bool noran)
assert((header.bitsNeeded()+l3.size())<=this->size());
size_t wp = header.write(*this);
l3.copyToSegment(*this,wp);
// FIXME - figure out why randomizeFiller doesn't like the "noran" headers
if (gConfig.getBool("GSM.Cipher.ScrambleFiller") && !noran) randomizeFiller(header);
}
@@ -275,7 +235,6 @@ L2Frame::L2Frame(const L2Header& header)
{
idleFill();
header.write(*this);
if (gConfig.getBool("GSM.Cipher.ScrambleFiller")) randomizeFiller(header);
}
@@ -351,7 +310,6 @@ const L2Frame& GSM::L2IdleFrame()
idleFrame.fillField(8*0,3,8); // address
idleFrame.fillField(8*1,3,8); // control
idleFrame.fillField(8*2,1,8); // length
if (gConfig.getBool("GSM.Cipher.ScrambleFiller")) idleFrame.randomizeFiller(8*4);
}
return idleFrame;
}

View File

@@ -98,7 +98,6 @@ class TxBurst : public BitVector {
/**@name Basic accessors. */
//@{
// Since mTime is volatile, we can't return a reference.
Time time() const { return mTime; }
void time(const Time& wTime) { mTime = wTime; }
//@}
@@ -162,7 +161,6 @@ class RxBurst : public SoftVector {
{ }
// Since mTime is volatile, we can't return a reference.
Time time() const { return mTime; }
void time(const Time& wTime) { mTime = wTime; }
@@ -466,9 +464,6 @@ class L2Frame : public BitVector {
public:
void randomizeFiller(unsigned start);
void randomizeFiller(const L2Header& header);
/** Fill the frame with the GSM idle pattern, GSM 04.06 2.2. */
void idleFill();
@@ -495,7 +490,7 @@ class L2Frame : public BitVector {
The L3Frame must fit in the L2Frame.
The primitive is DATA.
*/
L2Frame(const L2Header&, const BitVector&, bool noran=false);
L2Frame(const L2Header&, const BitVector&);
/**
Make an L2Frame from a header with no payload.
@@ -531,10 +526,7 @@ class L2Frame : public BitVector {
/** Set/clear the PF bit. */
void PF(bool wPF) { mStart[8+3]=wPF; }
/**
Look into the header and get the length of the payload.
Assumes A or B header, or B4 header with L2 pseudo length in L3.
*/
/** Look into the header and get the length of the payload. */
unsigned L() const { return peekField(8*2,6); }
/** Get the "more data" bit (M). */

View File

@@ -1,4 +1,3 @@
//#define RN_DEVELOPER_MODE 1
/**@file Global system parameters. */
/*
* Copyright 2008, 2009 Free Software Foundation, Inc.
@@ -69,5 +68,8 @@ void gResetWatchdog();
size_t gWatchdogRemaining();
bool gWatchdogExpired();
/** Build valid ARFCN string. */
extern std::string getARFCNsString(unsigned);
extern ReportingTable gReports;
#endif

View File

@@ -625,6 +625,7 @@ bool miniggsn_init()
tun_fd = ip_tun_open(tun_if_name,route_str);
if (tun_fd < 0) {
MGERROR("ggsn: ERROR: Could not open tun device %s",tun_if_name);
LOG(ALERT) << "Cound not open tun device:"<<tun_if_name; // TEMPORARY MESSAGE
return false;
}
}

View File

@@ -289,18 +289,14 @@ void SIPEngine::writePrivateHeaders(osip_message_t *msg, const GSM::LogicalChann
{
// P-PHY-Info
// This is a non-standard private header in OpenBTS.
// TA=<timing advance> TE=<TA error> UpRSSI=<uplink RSSI> TxPwr=<MS tx power>
// DnRSSIdBm=<downlink RSSI> time=<system time of measurements>
// TA=<timing advance> TE=<TA error> UpRSSI=<uplink RSSI> TxPwr=<MS tx power> DnRSSIdBm=<downlink RSSI>
// Get the values.
if (chan) {
LOG(DEBUG);
char phy_info[400];
sprintf(phy_info,"OpenBTS; TA=%d TE=%f UpRSSI=%f TxPwr=%d DnRSSIdBm=%d time=%9.3lf",
char phy_info[200];
sprintf(phy_info,"OpenBTS; TA=%d TE=%f UpRSSI=%f TxPwr=%d DnRSSIdBm=%d",
chan->actualMSTiming(), chan->timingError(),
chan->RSSI(), chan->actualMSPower(),
chan->measurementResults().RXLEV_FULL_SERVING_CELL_dBm(),
chan->timestamp());
LOG(DEBUG) << "PHY-info: " << phy_info;
chan->measurementResults().RXLEV_FULL_SERVING_CELL_dBm());
osip_message_set_header(msg,"P-PHY-Info",phy_info);
}
@@ -432,56 +428,6 @@ bool SIPEngine::Register( Method wMethod , const GSM::LogicalChannel* chan, stri
return success;
}
float geodecode1(const char **p, int *err, bool colonExpected)
{
float n = 0;
const char *q = *p;
while (**p >= '0' && **p <= '9') {
n = n * 10 + **p - '0';
(*p)++;
}
if (q == *p) *err = 1;
if (colonExpected) {
if (**p == ':') {
(*p)++;
} else {
*err = 1;
}
}
return n;
}
float geodecode(const char **p, int *err)
{
float n = 0;
float m = 1;
while (**p == ' ') {
(*p)++;
}
if (**p == '-') {
m = -1;
(*p)++;
}
n = geodecode1(p, err, true);
n += geodecode1(p, err, true)/60.0;
n += geodecode1(p, err, false)/3600.0;
if (**p == ' ' || **p == 0) return n * m;
switch (**p) {
case 'N':
case 'E':
(*p)++;
return n * m;
case 'S':
case 'W':
(*p)++;
return n * m * -1.0;
}
*err = 1;
return 0;
}
SIPState SIPEngine::MOCSendINVITE( const char * wCalledUsername,
const char * wCalledDomain , short wRtp_port, unsigned wCodec,
const GSM::LogicalChannel *chan)

View File

@@ -266,11 +266,8 @@ void SIPInterface::drive()
// heroic efforts to get it to parse the www-authenticate header failed,
// so we'll just crowbar that sucker in.
char *p = strcasestr(mReadBuffer, "nonce");
if (p && p[-1] != 'c') { // nonce but not cnonce
p += 6;
char *q = p;
while (isalnum(*q)) { q++; }
string RAND = string(mReadBuffer, p-mReadBuffer, q-p);
if (p) {
string RAND = string(mReadBuffer, p-mReadBuffer+6, 32);
LOG(INFO) << "crowbar www-authenticate " << RAND;
osip_www_authenticate_t *auth;
osip_www_authenticate_init(&auth);
@@ -281,23 +278,6 @@ void SIPInterface::drive()
if (k < 0) LOG(ERR) << "problem adding www_authenticate";
}
// The parser doesn't seem to be interested in authentication info either.
// Get kc from there and put it in tmsi table.
char *pp = strcasestr(mReadBuffer, "cnonce");
if (pp) {
pp += 7;
char *qq = pp;
while (isalnum(*qq)) { qq++; }
string kc = string(mReadBuffer, pp-mReadBuffer, qq-pp);
LOG(INFO) << "storing kc in TMSI table"; // mustn't display kc in log
const char *imsi = osip_uri_get_username(msg->to->url);
if (imsi && strlen(imsi) > 0) {
gTMSITable.putKc(imsi+4, kc);
} else {
LOG(ERR) << "can't find imsi to store kc";
}
}
if (msg->sip_method) LOG(DEBUG) << "read method " << msg->sip_method;
// Must check if msg is an invite.
@@ -531,6 +511,8 @@ bool SIPInterface::checkInvite( osip_message_t * msg)
}
LOG(DEBUG) << "callerID " << callerID << "@" << callerHost;
// HACK - Check for leading "+".
if (*callerID=='+') callerID++;
// Build the transaction table entry.
// This constructor sets TI automatically for an MT transaction.

View File

@@ -546,7 +546,7 @@ bool ::ARFCNManager::clearHandover(unsigned TN)
assert(TN<8);
int status = sendCommand("NOHANDOVER",TN);
if (status!=0) {
LOG(WARNING) << "NOHANDOVER failed with status " << status;
LOG(ALERT) << "NOHANDOVER failed with status " << status;
return false;
}
return true;

File diff suppressed because it is too large Load Diff

View File

@@ -32,7 +32,7 @@ noinst_PROGRAMS = \
OpenBTSDo \
OpenBTSCLI
OpenBTS_SOURCES = OpenBTS.cpp GetConfigurationKeys.cpp
OpenBTS_SOURCES = OpenBTS.cpp
OpenBTS_CPPFLAGS = $(STD_DEFINES_AND_INCLUDES)
ourlibs = \
@@ -52,7 +52,7 @@ ourlibs = \
$(OSIP_LIBS) \
$(ORTP_LIBS)
OpenBTS_LDADD = $(ourlibs) -ldl -losipparser2 -losip2 -lortp -la53
OpenBTS_LDADD = $(ourlibs) -ldl -losipparser2 -losip2 -lortp
OpenBTSCLI_SOURCES = OpenBTSCLI.cpp
# RedHat RHEL5 needs to have ncurses included
@@ -85,4 +85,6 @@ install: OpenBTS OpenBTSCLI OpenBTSDo
mkdir -p "$(DESTDIR)/home/openbts/"
install CLI "$(DESTDIR)/home/openbts/"
install openbtsconfig "$(DESTDIR)/home/openbts/"
install killBTS "$(DESTDIR)/home/openbts/"
install startBTS "$(DESTDIR)/home/openbts/"

File diff suppressed because it is too large Load Diff

View File

@@ -6,9 +6,10 @@
-- rather in the program's ConfigurationKey schema.
--
PRAGMA foreign_keys=OFF;
PRAGMA journal_mode=WAL;
BEGIN TRANSACTION;
CREATE TABLE IF NOT EXISTS CONFIG ( KEYSTRING TEXT UNIQUE NOT NULL, VALUESTRING TEXT, STATIC INTEGER DEFAULT 0, OPTIONAL INTEGER DEFAULT 0, COMMENTS TEXT DEFAULT '');
INSERT OR IGNORE INTO "CONFIG" VALUES('CLI.SocketPath','/var/run/command',0,0,'Path for Unix domain datagram socket used for the OpenBTS console interface.');
INSERT OR IGNORE INTO "CONFIG" VALUES('CLI.SocketPath','/var/run/OpenBTS/command',0,0,'Path for Unix domain datagram socket used for the OpenBTS console interface.');
INSERT OR IGNORE INTO "CONFIG" VALUES('Control.Call.QueryRRLP.Early','0',0,0,'1=enabled, 0=disabled - Query every MS for its location via RRLP during the setup of a call.');
INSERT OR IGNORE INTO "CONFIG" VALUES('Control.Call.QueryRRLP.Late','0',0,0,'1=enabled, 0=disabled - Query every MS for its location via RRLP during the teardown of a call.');
INSERT OR IGNORE INTO "CONFIG" VALUES('Control.GSMTAP.GPRS','0',0,0,'1=enabled, 0=disabled - Capture GPRS signaling and traffic at L1/L2 interface via GSMTAP.');
@@ -33,13 +34,13 @@ INSERT OR IGNORE INTO "CONFIG" VALUES('Control.LUR.WhiteListing.Message','Your h
INSERT OR IGNORE INTO "CONFIG" VALUES('Control.LUR.WhiteListing.RejectCause','0x04',0,0,'Reject cause for handset not in the whitelist, when whitelisting is enforced. Reject causes come from GSM 04.08 10.5.3.6. Reject cause 0x04, IMSI not in VLR, is usually the right one.');
INSERT OR IGNORE INTO "CONFIG" VALUES('Control.LUR.WhiteListing.ShortCode','1000',0,0,'The return address for the whitelisting notificiation message.');
INSERT OR IGNORE INTO "CONFIG" VALUES('Control.NumSQLTries','3',0,0,'Number of times to retry SQL queries before declaring a database access failure.');
INSERT OR IGNORE INTO "CONFIG" VALUES('Control.Reporting.PhysStatusTable','/var/run/ChannelTable.db',1,0,'File path for channel status reporting database. Static.');
INSERT OR IGNORE INTO "CONFIG" VALUES('Control.Reporting.PhysStatusTable','/var/run/OpenBTS/ChannelTable.db',1,0,'File path for channel status reporting database. Static.');
INSERT OR IGNORE INTO "CONFIG" VALUES('Control.Reporting.StatsTable','/var/log/OpenBTSStats.db',1,0,'File path for statistics reporting database. Static.');
INSERT OR IGNORE INTO "CONFIG" VALUES('Control.Reporting.TMSITable','/var/run/TMSITable.db',1,0,'File path for TMSITable database. Static.');
INSERT OR IGNORE INTO "CONFIG" VALUES('Control.Reporting.TransactionTable','/var/run/TransactionTable.db',1,0,'File path for transaction table database. Static.');
INSERT OR IGNORE INTO "CONFIG" VALUES('Control.Reporting.TMSITable','/var/run/OpenBTS/TMSITable.db',1,0,'File path for TMSITable database. Static.');
INSERT OR IGNORE INTO "CONFIG" VALUES('Control.Reporting.TransactionTable','/var/run/OpenBTS/TransactionTable.db',1,0,'File path for transaction table database. Static.');
INSERT OR IGNORE INTO "CONFIG" VALUES('Control.SACCHTimeout.BumpDown','1',0,0,'Decrease the RSSI by this amount to induce more power in the MS each time we fail to receive a response from it.');
INSERT OR IGNORE INTO "CONFIG" VALUES('Control.SMS.QueryRRLP','0',0,0,'1=enabled, 0=disabled - Query every MS for its location via RRLP during an SMS.');
INSERT OR IGNORE INTO "CONFIG" VALUES('Control.SMSCB.Table','',1,0,'File path for SMSCB scheduling database. By default, this feature is disabled. To enable, specify a file path for the database e.g. /var/run/SMSCB.db. To disable again, execute "unconfig Control.SMSCB.Table". Static.');
INSERT OR IGNORE INTO "CONFIG" VALUES('Control.SMSCB.Table','',1,0,'File path for SMSCB scheduling database. By default, this feature is disabled. To enable, specify a file path for the database e.g. /var/run/OpenBTS/SMSCB.db. To disable again, execute "unconfig Control.SMSCB.Table". Static.');
INSERT OR IGNORE INTO "CONFIG" VALUES('Control.TestCall.AutomaticModeChange','0',0,0,'1=enabled, 0=disabled - Automatically change the channel mode of a TCH/FACCH from signaling-only to speech-V1 before starting the fuzzing interface.');
INSERT OR IGNORE INTO "CONFIG" VALUES('Control.TestCall.LocalPort','24020',0,0,'Port number part of source for L3 payloads received from the handset in fuzzing interface.');
INSERT OR IGNORE INTO "CONFIG" VALUES('Control.TestCall.PollTime','100',0,0,'Polling time of the fuzzing interface in milliseconds.');
@@ -52,7 +53,7 @@ INSERT OR IGNORE INTO "CONFIG" VALUES('GGSN.Firewall.Enable','1',1,0,'0=no firew
INSERT OR IGNORE INTO "CONFIG" VALUES('GGSN.IP.MaxPacketSize','1520',1,0,'Maximum size of an IP packet. Should normally be 1520. Static.');
INSERT OR IGNORE INTO "CONFIG" VALUES('GGSN.IP.ReuseTimeout','180',1,0,'How long IP addresses are reserved after a session ends. Static.');
INSERT OR IGNORE INTO "CONFIG" VALUES('GGSN.IP.TossDuplicatePackets','0',1,0,'1=enabled, 0=disabled - Toss duplicate TCP/IP packets to prevent unnecessary traffic on the radio. Static.');
INSERT OR IGNORE INTO "CONFIG" VALUES('GGSN.Logfile.Name','/var/log/openbts-ggsn.log',1,0,'If specified, internet traffic is logged to this file e.g. ggsn.log Static.');
INSERT OR IGNORE INTO "CONFIG" VALUES('GGSN.Logfile.Name','',1,0,'If specified, internet traffic is logged to this file e.g. ggsn.log Static.');
INSERT OR IGNORE INTO "CONFIG" VALUES('GGSN.MS.IP.Base','192.168.99.1',1,0,'Base IP address assigned to MS. Static.');
INSERT OR IGNORE INTO "CONFIG" VALUES('GGSN.MS.IP.MaxCount','254',1,0,'Number of IP addresses to use for MS. Static.');
INSERT OR IGNORE INTO "CONFIG" VALUES('GGSN.MS.IP.Route','',1,0,'A route address to be used for downstream clients. By default, OpenBTS manufactures this value from the GGSN.MS.IP.Base assuming a 24 bit mask. To override, specify a route address in the form xxx.xxx.xxx.xxx/yy. The address must encompass all MS IP addresses. To use the auto-generated value again, execute "unconfig GGSN.MS.IP.Route". Static.');
@@ -76,7 +77,7 @@ INSERT OR IGNORE INTO "CONFIG" VALUES('GPRS.Counters.TbfRelease','5',0,0,'Maximu
INSERT OR IGNORE INTO "CONFIG" VALUES('GPRS.Debug','0',0,0,'1=enabled, 0=disabled - Toggle GPRS debugging.');
INSERT OR IGNORE INTO "CONFIG" VALUES('GPRS.Downlink.KeepAlive','300',0,0,'How often to send keep-alive messages for persistent TBFs in milliseconds; must be long enough to avoid simultaneous in-flight duplicates, and short enough that MS gets one every 5 seconds. GSM 5.08 10.2.2 indicates MS must get a block every 360ms');
INSERT OR IGNORE INTO "CONFIG" VALUES('GPRS.Downlink.Persist','0',0,0,'After completion, downlink TBFs are held open for this time in milliseconds. If non-zero, must be greater than GPRS.Downlink.KeepAlive.');
INSERT OR IGNORE INTO "CONFIG" VALUES('GPRS.Enable','0',0,0,'1=enabled, 0=disabled - If enabled, GPRS service is advertised in the C0T0 beacon, and GPRS service may be started on demand. See also GPRS.Channels.*.');
INSERT OR IGNORE INTO "CONFIG" VALUES('GPRS.Enable','1',0,0,'1=enabled, 0=disabled - If enabled, GPRS service is advertised in the C0T0 beacon, and GPRS service may be started on demand. See also GPRS.Channels.*.');
INSERT OR IGNORE INTO "CONFIG" VALUES('GPRS.LocalTLLI.Enable','1',0,0,'1=enabled, 0=disabled - Enable recognition of local TLLI');
INSERT OR IGNORE INTO "CONFIG" VALUES('GPRS.MS.KeepExpiredCount','20',0,0,'How many expired MS structs to retain; they can be viewed with gprs list ms -x');
INSERT OR IGNORE INTO "CONFIG" VALUES('GPRS.MS.Power.Alpha','10',0,0,'MS power control parameter, unitless, in steps of 0.1, so a parameter of 5 is an alpha value of 0.5. Determines sensitivity of handset to variations in downlink RSSI. Valid range is 0...10 for alpha values of 0...1.0. See GSM 05.08 10.2.1.');
@@ -121,10 +122,6 @@ INSERT OR IGNORE INTO "CONFIG" VALUES('GSM.Channels.C1sFirst','0',1,0,'1=enabled
INSERT OR IGNORE INTO "CONFIG" VALUES('GSM.Channels.NumC1s','7',1,0,'Number of Combination-I timeslots to configure. The C-I slot carries a single full-rate TCH, used for speech calling. Static.');
INSERT OR IGNORE INTO "CONFIG" VALUES('GSM.Channels.NumC7s','0',1,0,'Number of Combination-VII timeslots to configure. The C-VII slot carries 8 SDCCHs, useful to handle high registration loads or SMS. If C0T0 is C-IV, which it always is in C2.9 and earlier,, you must have at least one C-VII also. Static.');
INSERT OR IGNORE INTO "CONFIG" VALUES('GSM.Channels.SDCCHReserve','0',0,0,'Number of SDCCHs to reserve for non-LUR operations. This can be used to force LUR transactions into a lower priority.');
INSERT OR IGNORE INTO "CONFIG" VALUES('GSM.Cipher.CCHBER','0',0,0,'Probability of a bit getting toggled in a control channel burst for cracking protection.');
INSERT OR IGNORE INTO "CONFIG" VALUES('GSM.Cipher.Encrypt','0',0,0,'1=enabled, 0=disabled - Encrypt traffic between phone and OpenBTS.');
INSERT OR IGNORE INTO "CONFIG" VALUES('GSM.Cipher.RandomNeighbor','0',0,0,'Probability of a random neighbor being added to SI5 for cracking protection.');
INSERT OR IGNORE INTO "CONFIG" VALUES('GSM.Cipher.ScrambleFiller','0',0,0,'1=enabled, 0=disabled - Scramble filler in layer 2 for cracking protection.');
INSERT OR IGNORE INTO "CONFIG" VALUES('GSM.Control.GPRSMaxIgnore','5',0,0,'Ignore GPRS messages on GSM control channels. Value is number of consecutive messages to ignore.');
INSERT OR IGNORE INTO "CONFIG" VALUES('GSM.Handover.FailureHoldoff','5',0,0,'The number of seconds to wait before attempting another handover with a given neighbor BTS.');
INSERT OR IGNORE INTO "CONFIG" VALUES('GSM.Handover.LocalRSSIMin','-80',0,0,'Do not handover if downlink RSSI is above this level (in dBm), regardless of power difference.');
@@ -183,7 +180,7 @@ INSERT OR IGNORE INTO "CONFIG" VALUES('Log.Alarms.Max','20',0,0,'Maximum number
INSERT OR IGNORE INTO "CONFIG" VALUES('Log.File','',0,0,'Path to use for textfile based logging. By default, this feature is disabled. To enable, specify an absolute path to the file you wish to use, eg: /tmp/my-debug.log. To disable again, execute "unconfig Log.File".');
INSERT OR IGNORE INTO "CONFIG" VALUES('Log.Level','NOTICE',0,0,'Default logging level when no other level is defined for a file.');
INSERT OR IGNORE INTO "CONFIG" VALUES('Peering.Neighbor.RefreshAge','60000',0,0,'Milliseconds before refreshing parameters from a neighbor.');
INSERT OR IGNORE INTO "CONFIG" VALUES('Peering.NeighborTable.Path','/var/run/NeighborTable.db',1,0,'File path for neighbor information database. Static.');
INSERT OR IGNORE INTO "CONFIG" VALUES('Peering.NeighborTable.Path','/var/run/OpenBTS/NeighborTable.db',1,0,'File path for neighbor information database. Static.');
INSERT OR IGNORE INTO "CONFIG" VALUES('Peering.Port','16001',1,0,'The UDP port used by the peer interface for handover. Static.');
INSERT OR IGNORE INTO "CONFIG" VALUES('Peering.ResendCount','5',0,0,'Number of tries to send message over the peer interface before giving up');
INSERT OR IGNORE INTO "CONFIG" VALUES('Peering.ResendTimeout','100',0,0,'Milliseconds before resending a message on the peer interface');

View File

@@ -44,7 +44,7 @@
#endif
#define DEFAULT_CMD_PATH "/var/run/command"
#define DEFAULT_CMD_PATH "/var/run/OpenBTS/command"
#define DEFAULT_RSP_PATH "./response"

View File

@@ -3,7 +3,7 @@
:PREROUTING ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A POSTROUTING -o wlan0 -j MASQUERADE
-A POSTROUTING -o eth0 -j MASQUERADE
COMMIT
# Generated by iptables-save v1.4.4
*filter

14
apps/killBTS Executable file
View File

@@ -0,0 +1,14 @@
#!/bin/bash
# This script goes into ~openbts/.
#Stop asterisk if it's currently running
sudo service asterisk status | grep -iqP "\bis running\b" && sudo service asterisk stop
echo "Killing SMQueue"
sudo killall runloop.smqueue.sh
echo "Killing the Subscriber Registry"
sudo killall runloop.sipauthserve.sh
echo "Killing OpenBTS and Transceiver"
sudo killall runloop.OpenBTS.sh

36
apps/startBTS Executable file
View File

@@ -0,0 +1,36 @@
# create the tmpfs /var/run directory
if [ ! -e /var/run/OpenBTS ]; then
mkdir /var/run/OpenBTS
fi
if [ ! -e /var/run/rrlp ]; then
mkdir /var/run/rrlp
chmod 777 /var/run/rrlp
fi
# This script assumes that the following are installed in /OpenBTS:
# * OpenBTS
# * Transceiver
# * ezusb.ihx
# * fpga.rbf
# * runloop.sh for OpenBTS.
#Start asterisk if it is not currently running
sudo service asterisk status | grep -iqP "\bnot running\b" && sudo service asterisk start
# start OpenBTS
echo "Starting OpenBTS and Transceiver"
cd /OpenBTS ; sudo screen -S OpenBTS -d -m ./runloop.OpenBTS.sh
# This script assumes that the following are installed in /smqueue:
# * smqueue
# * smqueue.db
# * runloop.sh for smqueue
# start smqueue
echo "Starting SMQueue"
cd /OpenBTS ; sudo screen -S smqueue -d -m ./runloop.smqueue.sh
# start the subscriber registry
echo "Starting the Subscriber Registry"
cd /OpenBTS ; sudo screen -S sipauth -d -m ./runloop.sipauthserve.sh

View File

@@ -18,7 +18,7 @@ dnl You should have received a copy of the GNU General Public License
dnl along with this program. If not, see <http://www.gnu.org/licenses/>.
dnl
AC_INIT(openbts-public,TRUNK)
AC_INIT(openbts,3.1TRUNK)
AC_PREREQ(2.57)
AC_CONFIG_SRCDIR([config/Makefile.am])
AC_CONFIG_AUX_DIR([.])

8
debian/changelog vendored
View File

@@ -1,11 +1,5 @@
openbts-public (3.2) UNRELEASED; urgency=low
openbts-public (3.1) UNRELEASED; urgency=low
* Public sync
-- Kurtis <kheimerl@darth-maul> Thu, 01 Aug 2013 20:37:03 -0700
openbts-public (3.2) UNRELEASED; urgency=low
* Test
-- Donald C. Kirker <donald.kirker@rangenetworks.com> Mon, 22 Apr 2013 00:11:00 -0700

1
debian/compat vendored
View File

@@ -1 +0,0 @@
1

8
debian/control vendored
View File

@@ -1,5 +1,4 @@
Source: openbts-public
Provides: openbts
Section: comm
Priority: optional
Maintainer: Range Networks, Inc. <info@rangenetworks.com>
@@ -8,11 +7,10 @@ Build-Depends: build-essential, debhelper (>= 7), libosip2-dev, pkg-config, auto
Standards-Version: 3.7.3
Package: openbts-public
Provides: openbts
Version: TRUNK
Version: P3.1TRUNK
Section: comm
Priority: optional
Architecture: any
Architecture: i386
Essential: no
Depends: sqlite3 (>= 3.7), libosip2-4, libusb-1.0-0, libortp8 (<= 0.20), libglib2.0-0, libgl1-mesa-glx, libc6, libasound2, pkg-config, libpcre3, gawk, screen
Depends: sqlite3, libosip2-4, libusb-1.0-0, libortp8, libglib2.0-0, libgl1-mesa-glx, libc6-i686, libasound2, pkg-config, libpcre3, gawk, screen
Description: OpenBTS Public software.

18
debian/postinst vendored
View File

@@ -20,20 +20,20 @@
configure()
{
DB_LOC=/etc/OpenBTS/OpenBTS.db
DATE=$(date +'%Y-%m-%d.%H:%M:%S')
CONFIG_BACKUP=$DB_LOC.dump-$DATE
DATE=$(date --rfc-3339='date')
CONFIG_BACKUP=/etc/OpenBTS/OpenBTS.dump-$DATE
if [ ! -e $CONFIG_BACKUP ]; then
sqlite3 $DB_LOC ".dump" > $CONFIG_BACKUP
sqlite3 /etc/OpenBTS/OpenBTS.db ".dump" > $CONFIG_BACKUP
fi
sqlite3 $DB_LOC ".read /etc/OpenBTS/OpenBTS.example.sql" > /dev/null 2>&1
sqlite3 /etc/OpenBTS/OpenBTS.db ".read /etc/OpenBTS/OpenBTS.example.sql" > /dev/null 2>&1
#chown openbts:openbts /home/openbts/CLI
#chown openbts:openbts /home/openbts/openbtsconfig
#chown openbts:openbts /home/openbts/startBTS
#chown openbts:openbts /home/openbts/killBTS
chown openbts:openbts /home/openbts/CLI
chown openbts:openbts /home/openbts/openbtsconfig
chown openbts:openbts /home/openbts/startBTS
chown openbts:openbts /home/openbts/killBTS
}

24
debian/postinst.old vendored Executable file
View File

@@ -0,0 +1,24 @@
#!/bin/bash
INSTALL_DIR=/OpenBTS
DATE=$(date --rfc-3339='date')
BACKUP_DIR=$INSTALL_DIR/backup_$DATE
CONFIG_BACKUP=/etc/OpenBTS/OpenBTS.dump-$DATE
if [ ! -e $BACKUP_DIR ]; then
mkdir $BACKUP_DIR/
mv $INSTALL_DIR/OpenBTS $BACKUP_DIR/
mv $INSTALL_DIR/transceiver $BACKUP_DIR/
fi
if [ ! -e $CONFIG_BACKUP ]; then
sqlite3 /etc/OpenBTS/OpenBTS.db ".dump" > $CONFIG_BACKUP
fi
sqlite3 /etc/OpenBTS/OpenBTS.db ".read /etc/OpenBTS/OpenBTS_3.0.0.sql" &>/dev/null

3
debian/preinst vendored
View File

@@ -15,9 +15,8 @@ set -e
install()
{
INSTALL_DIR=/OpenBTS
DATE=$(date +'%Y-%m-%d.%H:%M:%S')
DATE=$(date --rfc-3339='date')
BACKUP_DIR=$INSTALL_DIR/backup_$DATE
if [ -f $INSTALL_DIR/OpenBTS -a -f $INSTALL_DIR/transceiver ]; then

8
debian/prerm vendored
View File

@@ -16,15 +16,9 @@ set -e
# for details, see http://www.debian.org/doc/debian-policy/ or
# the debian-policy package
APP=OpenBTS
remove()
{
if [ "$(pidof $APP)" ]; then
killall $APP
else
echo "$APP not running"
fi
killall runloop.OpenBTS.sh &>/dev/null
}
case "$1" in

7
debian/prerm.old vendored Executable file
View File

@@ -0,0 +1,7 @@
#!/bin/bash
killall runloop.OpenBTS.sh &>/dev/null

3
debian/rules vendored
View File

@@ -108,8 +108,7 @@ binary-common:
# dh_perl
dh_makeshlibs
dh_installdeb
# dh_shlibdeps
dh_shlibdeps --dpkg-shlibdeps-params=--ignore-missing-info
dh_shlibdeps
dh_gencontrol
dh_md5sums
dh_builddeb