Esempio n. 1
0
void startTransceiver()
{
	//if local kill the process currently listening on this port
	char killCmd[32];
	if (gConfig.getStr("TRX.IP") == "127.0.0.1"){
		sprintf(killCmd,"fuser -k -n udp %d",(int)gConfig.getNum("TRX.Port"));
		if (system(killCmd)) {}
	}

	// Start the transceiver binary, if the path is defined.
	// If the path is not defined, the transceiver must be started by some other process.
	char TRXnumARFCN[4];
	sprintf(TRXnumARFCN,"%1d",(int)gConfig.getNum("GSM.Radio.ARFCNs"));
	std::string extra_args = gConfig.getStr("TRX.Args");
	LOG(NOTICE) << "starting transceiver " << transceiverPath << " w/ " << TRXnumARFCN << " ARFCNs and Args:" << extra_args;
	gTransceiverPid = vfork();
	LOG_ASSERT(gTransceiverPid>=0);
	if (gTransceiverPid==0) {
		// Pid==0 means this is the process that starts the transceiver.
	    execlp(transceiverPath,transceiverPath,TRXnumARFCN,extra_args.c_str(),(void*)NULL);
		LOG(EMERG) << "cannot find " << transceiverPath;
		_exit(1);
	} else {
		int status;
		waitpid(gTransceiverPid, &status,0);
		LOG(EMERG) << "Transceiver quit with status " << status << ". Exiting.";
		exit(2);
	}
}
Esempio n. 2
0
void gLogInit(const char* name, const char* level, int facility)
{
	// Set the level if one has been specified.
	if (level) {
		gConfig.set("Log.Level",level);
	}
	gPid = getpid();

	// Pat added, tired of the syslog facility.
	// Both the transceiver and OpenBTS use this same facility, but only OpenBTS/OpenNodeB may use this log file:
	string str = gConfig.getStr("Log.File");
	if (gLogToFile==0 && str.length() && 0==strncmp(gCmdName,"Open",4)) {
		const char *fn = str.c_str();
		if (fn && *fn && strlen(fn)>3) {	// strlen because a garbage char is getting in sometimes.
			gLogToFile = fopen(fn,"w"); // New log file each time we start.
			if (gLogToFile) {
                                time_t now = time(NULL);
                                std::string result;
                                Timeval::isoTime(now, result);
                                fprintf(gLogToFile,"Starting at %s",result.c_str());
				fflush(gLogToFile);
				std::cout << name <<" logging to file: " << fn << "\n";
			}
		}
	}

	// Open the log connection.
	openlog(name,0,facility);

	// We cant call this from the Mutex itself because the Logger uses Mutex.
	gMutexLogLevel = gGetLoggingLevel("Mutex.cpp");
}
Esempio n. 3
0
/* Run sanity check on configuration table
 *     The global table constructor cannot provide notification in the
 *     event of failure. Make sure that we can access the database,
 *     write to it, and that it contains the bare minimum required keys.
 */
bool testConfig()
{
    int val = 9999;
    std::string test = "asldfkjsaldkf";
    const char *key = "Log.Level";

    /* Attempt to query */
    try {
        gConfig.getStr(key);
    } catch (...) {
        std::cerr << std::endl;
        std::cerr << "Config: Failed query required key " << key
                  << std::endl;
        return false;
    }

    /* Attempt to set a test value in the global config */
    if (!gConfig.set(test, val)) {
        std::cerr << std::endl;
        std::cerr << "Config: Failed to set test key" << std::endl;
        return false;
    } else {
        gConfig.remove(test);
    }

    return true;
}
Esempio n. 4
0
void SelfDetect::RegisterProgram(const char *argv0)
{
    const char *p = strrchr((char*)argv0,'/');
    if (p == NULL) {
        p = argv0;
    }

    char buf[100];
    snprintf(buf, sizeof(buf)-1, "/var/run/%s.pid", p);
    LOG(NOTICE) << "*** Registering program " << argv0 << " to " << buf;

    // first, verify we aren't already running.
    struct stat stbuf;
    if (stat(buf, &stbuf) >= 0)
    {
        LOG(CRIT) << "*** An instance of " << p << " is already running. ";
        LOG(CRIT) << "*** If this is not the case, deleting this file will allow " << p << " to start: " << buf << " exiting...";
        Exit::exit(Exit::DETECTFILE);
    }

    FILE *fp = fopen(buf, "w");
    if (fp == NULL)
    {
        LOG(CRIT) << "*** Unable to create " << buf << ": " << strerror(errno) << " exiting...";
        Exit::exit(Exit::CREATEFILE);
    }
    fprintf(fp, "%d\n", getpid());
    fclose(fp);
    atexit(e);
    gSigVec.CoreName(gConfig.getStr("Core.File"), gConfig.getBool("Core.Pid"));
    gSigVec.TarName(gConfig.getStr("Core.TarFile"), gConfig.getBool("Core.SaveFiles"));

    // Now, register for all signals to do the cleanup
    for (int i = 1; i < UnixSignal::C_NSIG; i++)
    {
        switch(i)
        {
        // Add any signals that need to bypass the signal handling behavior
        // here.  Currently, SIGCHLD is needed because a signal is generated
        // when stuff related to the transciever (which is a child process)
        // occurs.  In that case, the openbts log output was:
        //		openbts: ALERT 3073816320 05:03:50.4 OpenBTS.cpp:491:main: starting the transceiver
        //		openbts: NOTICE 3073816320 05:03:50.4 SelfDetect.cpp:91:Exit: *** Terminating because of signal 17
        //		openbts: NOTICE 3031243584 05:03:50.4 OpenBTS.cpp:165:startTransceiver: starting transceiver ./transceiver w/ 1 ARFCNs and Args:
        //		openbts: NOTICE 3073816320 05:03:50.4 SelfDetect.cpp:98:Exit: *** Terminating ./OpenBTS
        //		openbts: NOTICE 3073816320 05:03:50.4 SelfDetect.cpp:105:Exit: *** Removing pid file /var/run/OpenBTS.pid
        case SIGCONT:
        case SIGCHLD:
            break;
        default:
            gSigVec.Register(sigfcn, i);
            break;
        }
    }
    mProg = strdup(argv0);
    mFile = strdup(buf);
}
int SubscriberRegistry::init()
{
	string ldb = gConfig.getStr("SubscriberRegistry.db");
	size_t p = ldb.find_last_of('/');
	if (p == string::npos) {
		LOG(EMERG) << "SubscriberRegistry.db not in a directory?";
		mDB = NULL;
		return 1;
	}
	string dir = ldb.substr(0, p);
	struct stat buf;
	if (stat(dir.c_str(), &buf)) {
		LOG(EMERG) << dir << " does not exist";
		mDB = NULL;
		return 1;
	}
	mNumSQLTries=gConfig.getNum("Control.NumSQLTries"); 
	int rc = sqlite3_open(ldb.c_str(),&mDB);
	if (rc) {
		LOG(EMERG) << "Cannot open SubscriberRegistry database: " << ldb << " error: " << sqlite3_errmsg(mDB);
		sqlite3_close(mDB);
		mDB = NULL;
		return 1;
	}
	if (!sqlite3_command(mDB,createRRLPTable,mNumSQLTries)) {
		LOG(EMERG) << "Cannot create RRLP table";
		return 1;
	}
	if (!sqlite3_command(mDB,createDDTable,mNumSQLTries)) {
		LOG(EMERG) << "Cannot create DIALDATA_TABLE table";
		return 1;
	}
	if (!sqlite3_command(mDB,createRateTable,mNumSQLTries)) {
		LOG(EMERG) << "Cannot create rate table";
		return 1;
	}
	if (!sqlite3_command(mDB,createSBTable,mNumSQLTries)) {
		LOG(EMERG) << "Cannot create SIP_BUDDIES table";
		return 1;
	}
	// Set high-concurrency WAL mode.
	if (!sqlite3_command(mDB,enableWAL,mNumSQLTries)) {
		LOG(EMERG) << "Cannot enable WAL mode on database at " << ldb << ", error message: " << sqlite3_errmsg(mDB);
	}
	if (!getCLIDLocal("IMSI001010000000000")) {
		// This is a test SIM provided with the BTS.
		if (addUser("IMSI001010000000000", "2100") != SUCCESS) {
        		LOG(EMERG) << "Cannot insert test SIM";
		}
	}
	return 0;
}
// verify sres given rand and imsi's ki
// may set kc
// may cache sres and rand
bool authenticate(string imsi, string randx, string sres, string *kc)
{
	string ki = gSubscriberRegistry.imsiGet(imsi, "ki");
	bool ret;
	if (ki.length() == 0) {
		// Ki is unknown
		string sres2 = gSubscriberRegistry.imsiGet(imsi, "sres");
		if (sres2.length() == 0) {
			LOG(INFO) << "ki unknown, no upstream server, sres not cached";
			// first time - cache sres and rand so next time
			// correct cell phone will calc same sres from same rand
			gSubscriberRegistry.imsiSet(imsi, "sres", sres, "rand", randx);
			ret = true;
		} else {
			LOG(INFO) << "ki unknown, no upstream server, sres cached";
			// check against cached values of rand and sres
			string rand2 = gSubscriberRegistry.imsiGet(imsi, "rand");
			// TODO - on success, compute and return kc
			LOG(DEBUG) << "comparing " << sres << " to " << sres2 << " and " << randx << " to " << rand2;
			ret = sresEqual(sres, sres2) && randEqual(randx, rand2);
		}
	} else {
		LOG(INFO) << "ki known";
		// Ki is known, so do normal authentication
		ostringstream os;
		// per user value from subscriber registry
		string a3a8 = gSubscriberRegistry.imsiGet(imsi, "a3_a8");
		if (a3a8.length() == 0) {
			// config value is default
			a3a8 = gConfig.getStr("SubscriberRegistry.A3A8");
		}
		os << a3a8 << " 0x" << ki << " 0x" << randx;
		// must not put ki into the log
		// LOG(INFO) << "running " << os.str();
		FILE *f = popen(os.str().c_str(), "r");
		if (f == NULL) {
			LOG(CRIT) << "error: popen failed";
			return false;
		}
		char sres2[26];
		char *str = fgets(sres2, 26, f);
		if (str != NULL && strlen(str) == 25) str[24] = 0;
		if (str == NULL || strlen(str) != 24) {
			LOG(CRIT) << "error: popen result failed";
			return false;
		}
		int st = pclose(f);
		if (st == -1) {
			LOG(CRIT) << "error: pclose failed";
			return false;
		}
		// first 8 chars are SRES;  rest are Kc
		*kc = sres2+8;
		sres2[8] = 0;
		LOG(INFO) << "result = " << sres2;
		ret = sresEqual(sres, sres2);
	}
	LOG(INFO) << "returning = " << ret;
	return ret;
}
Esempio n. 7
0
// Allow applications to also pass in a filename.  Filename should come from the database
void gLogInitWithFile(const char* name, const char* level, int facility, char * LogFilePath)
{
	// Set the level if one has been specified.
	if (level) {
		gConfig.set("Log.Level",level);
	}

	if (gLogToFile==0 && LogFilePath != 0 && *LogFilePath != 0 && strlen(LogFilePath) > 0) {
		gLogToFile = fopen(LogFilePath,"w"); // New log file each time we start.
		if (gLogToFile) {
			time_t now = time(NULL);
                        std::string result;
                        Timeval::isoTime(now, result);
			fprintf(gLogToFile,"Starting at %s",result.c_str());
			fflush(gLogToFile);
			std::cout << name <<" logging to file: " << LogFilePath << "\n";
		}
	}

	// Open the log connection.
	openlog(name,0,facility);

	// We cant call this from the Mutex itself because the Logger uses Mutex.
	gMutexLogLevel = gGetLoggingLevel("Mutex.cpp");
}
// For handover.  Only remove the local cache.  BS2 will have updated the global.
SubscriberRegistry::Status SubscriberRegistry::removeUser(const char* IMSI)
{
	if (!IMSI) {
		LOG(WARNING) << "SubscriberRegistry::addUser attempting add of NULL IMSI";
		return FAILURE;
	}
	LOG(INFO) << "removeUser(" << IMSI << ")";
	string server = gConfig.getStr("SubscriberRegistry.UpstreamServer");
	if (server.length() == 0) {
		LOG(INFO) << "not removing user if no upstream server";
		return FAILURE;
	}
	ostringstream os;
	os << "delete from sip_buddies where name = ";
	os << "\"" << IMSI << "\"";
	os << ";";
	LOG(INFO) << os.str();
	SubscriberRegistry::Status st = sqlLocal(os.str().c_str(), NULL);
	ostringstream os2;
	os2 << "delete from dialdata_table where dial = ";
	os2 << "\"" << IMSI << "\"";
	LOG(INFO) << os2.str();
	SubscriberRegistry::Status st2 = sqlLocal(os2.str().c_str(), NULL);
	return st == SUCCESS && st2 == SUCCESS ? SUCCESS : FAILURE;
}
SubscriberRegistry::SubscriberRegistry()
{
	string ldb = gConfig.getStr("SubscriberRegistry.db");
	int rc = sqlite3_open(ldb.c_str(),&mDB);
	if (rc) {
		LOG(EMERG) << "Cannot open SubscriberRegistry database: " << sqlite3_errmsg(mDB);
		sqlite3_close(mDB);
		mDB = NULL;
		return;
	}
    if (!sqlite3_command(mDB,createRRLPTable)) {
        LOG(EMERG) << "Cannot create RRLP table";
    }
    if (!sqlite3_command(mDB,createDDTable)) {
        LOG(EMERG) << "Cannot create DIALDATA_TABLE table";
    }
    if (!sqlite3_command(mDB,createSBTable)) {
        LOG(EMERG) << "Cannot create SIP_BUDDIES table";
    }
	if (!getCLIDLocal("IMSI001010000000000")) {
		// This is a test SIM provided with the BTS.
		if (addUser("IMSI001010000000000", "2100") != SUCCESS) {
			LOG(EMERG) << "Cannot insert test SIM";
		}
	}
}
Esempio n. 10
0
/** Add an alarm to the alarm list. */
void addAlarm(const string& s)
{
    alarmsLock.lock();
    alarmsList.push_back(s);
	unsigned maxAlarms = gConfig.getNum("Log.Alarms.Max");
    while (alarmsList.size() > maxAlarms) alarmsList.pop_front();
    alarmsLock.unlock();
}
Esempio n. 11
0
// Set all the Log.Group debug levels based on database settings
void LogGroup::setAll()
{
	LOG(DEBUG);
	string prefix = string(LogGroupPrefix);
	for (unsigned g = 0; g < _NumberOfLogGroups; g++) {
		int level = 0;
		string param = prefix + mGroupNames[g];
		if (gConfig.defines(param)) {
			string levelName = gConfig.getStr(param);
			// (pat) The "unconfig" command does not remove the value, it just gives it an empty value, so check for that.
			if (levelName.size()) {
				//LOG(DEBUG) << "Setting "<<LOGVAR(param)<<LOGVAR(levelName);
				level = lookupLevel2(param,levelName);
			}
		}
		mDebugLevel[g] = level;
	}
}
Esempio n. 12
0
/** Define a function to call any time the configuration database changes. */
void purgeConfig(void*,int,char const*, char const*, sqlite3_int64)
{
	// (pat) NO NO NO.  Do not call LOG from here - it may result in infinite recursion.
	// LOG(INFO) << "purging configuration cache";
	gConfig.purge();
	gBTS.regenerateBeacon();
	gResetWatchdog();
	gLogGroup.setAll();
}
Esempio n. 13
0
// Add an alarm to the alarm list, and send it out via udp
//
// On the first call we read the ip and port from the configuration
// TODO - is there any global setup function where this should be done? -- Alon
void addAlarm(const string& s)
{
	// Socket open and close on every alarm - wise?
	// Probably.  That way we are sure to pick up changes in the target address.
	// Alarms should not happen often.
	if (gConfig.defines("Log.Alarms.TargetIP")) {
		UDPSocket alarmsocket(0,
			gConfig.getStr("Log.Alarms.TargetIP"),
			gConfig.getNum("Log.Alarms.TargetPort"));
		alarmsocket.write(s.c_str());
	}
    // append to list and reduce list to max alarm count
    alarmsLock.lock();
    alarmsList.push_back(s);
	unsigned maxAlarms = gConfig.getNum("Log.Alarms.Max");
    while (alarmsList.size() > maxAlarms) alarmsList.pop_front();
    alarmsLock.unlock();
}
Esempio n. 14
0
int getLoggingLevel(const char* filename)
{
	// Default level?
	if (!filename) return lookupLevel("Log.Level");

	// This can afford to be inefficient since it is not called that often.
	string keyName;
	keyName.reserve(100);
	keyName.append("Log.Level.");
	keyName.append(filename);
	if (gConfig.defines(keyName)) {
		string keyVal = gConfig.getStr(keyName);
		// (pat 4-2014) The CLI 'unconfig' command does not unset the value, it just gives an empty value,
		// so check for that and treat it as an unset value, ie, do nothing.
		if (keyVal.size()) {
			return lookupLevel2(keyName,keyVal);
		}
	}
	return lookupLevel("Log.Level");
}
Esempio n. 15
0
int main(int argc, char **argv)
{
	gLogInit("SubscriberRegistryTest",gConfig.getStr("Log.Level").c_str(),LOG_LOCAL7);

	// The idea is just to make sure things are connected right.  The important code is shared, and tested elsewhere.


	// add a user
	sr.addUser("imsi", "clid");
	// testing mappings of known user
	sr.getCLIDLocal("imsi");
	sr.getIMSI("clid");
	// test mapping of unknow user (so it won't be found locally)
	sr.getCLIDLocal("imsi_unknown");
	sr.getRandForAuthentication(false, "imsi_r1");
	sr.authenticate(false, "imsi_a1","rand_a1","sres_a1");


	// but test the conversions
	foo(0xffffffff, "ffffffff");
	foo(0x00000000, "00000000");
	foo(0x12345678, "12345678");
	foo(0x9abcdef0, "9abcdef0");

	foo("ffffffffffffffff0000000000000000");
	foo("0000000000000000ffffffffffffffff");
	foo("0123456789abcdef0123456789abcdef");


	// billing testing - not tested elsewhere

	sr.setPrepaid("imsi", false);
	bool b;
	sr.isPrepaid("imsi", b);
	LOG(INFO) << "should be false " << b;

	sr.setPrepaid("imsi", true);
	sr.isPrepaid("imsi", b);
	LOG(INFO) << "should be true " << b;

	sr.setSeconds("imsi", 100);
	int t;
	sr.secondsRemaining("imsi", t);
	LOG(INFO) << "should be 100 " << t;

	sr.addSeconds("imsi", -50, t);
	LOG(INFO) << "should be 50 " << t;

	sr.addSeconds("imsi", -100, t);
	LOG(INFO) << "should be 0 " << t;


}
Esempio n. 16
0
/** Given a string, return the corresponding level name. */
static int lookupLevel2(const string& key, const string &keyVal)
{
	int level = levelStringToInt(keyVal);

	if (level == -1) {
		string defaultLevel = gConfig.mSchema["Log.Level"].getDefaultValue();
		level = levelStringToInt(defaultLevel);
		_LOG(CRIT) << "undefined logging level (" << key << " = \"" << keyVal << "\") defaulting to \"" << defaultLevel << ".\" Valid levels are: EMERG, ALERT, CRIT, ERR, WARNING, NOTICE, INFO or DEBUG";
		gConfig.set(key, defaultLevel);
	}

	return level;
}
Esempio n. 17
0
int main(int argc, char **argv)
{
	// start the html return
	initHtml();
	// read the config file
	gVisibleSipColumns = gConfig.getStr("SubscriberRegistry.Manager.VisibleColumns");
	gUrl = "/cgi/srmanager.cgi";
	gTitle = gConfig.getStr("SubscriberRegistry.Manager.Title");
	// connect to the database
	gDatabase = gConfig.getStr("SubscriberRegistry.db");
	// decode the http query
	decodeQuery(gArgs);
	// execute command
	string what = gArgs["what"];
	if (!what.length() || what == "Main") {
		mainTables();
	} else if (what == "Add") {
		doCmd("add");
	} else if (what == "Update") {
		doCmd("update");
	} else if (what == "Delete") {
		doCmd("delete");
	} else if (what == "Provision") {
		gSubscriberRegistry.addUser(gArgs["imsi"].c_str(), gArgs["phonenumber"].c_str());
		mainTables();
	} else if (what == "Submit") {
		doVisibles();
		mainTables();
	} else {
		cout << "unrecognized what parameter<br>\n";
		map<string,string>::iterator it;
		for (it = gArgs.begin(); it != gArgs.end(); it++) {
			cout << it->first << " -> " << it->second << "<br>\n";
		}
	}
	// finish the html return
	endHtml();
}
int main(int argc, char *argv[]) {

	SubscriberRegistry gHLR;

	gLogInit("HLRTest");
	gConfig.set("Log.Level","DEBUG");

	if (argc!=2) {
		std::cerr << "usage: " << argv[0] << " <number>" << std::endl;
		exit(-1);
	}
	const char *targ = argv[1];

	char *IMSI = gHLR.getIMSI(targ);
	if (IMSI) std::cout << "IMSI for " << targ << " is " << IMSI << std::endl;
	else std::cout << "no IMSI found for " << targ << std::endl;

	char *CLID = gHLR.getCLIDLocal(IMSI);
	if (CLID) std::cout << "CLID for " << IMSI << " is " << CLID << std::endl;
	else std::cout << "no CLID found for " << IMSI << std::endl;

	char *regIP = gHLR.getRegistrationIP("234100223456161");
	if (regIP) std::cout << "registration IP for " << IMSI << " is " << regIP << std::endl;
	else std::cout << "no regIP found for " << IMSI << std::endl;

	IMSI = gHLR.getIMSI(targ);
	if (IMSI) std::cout << "IMSI for " << targ << " is " << IMSI << std::endl;
	else std::cout << "no IMSI found for " << targ << std::endl;

	CLID = gHLR.getCLIDLocal(IMSI);
	if (CLID) std::cout << "CLID for " << IMSI << " is " << CLID << std::endl;
	else std::cout << "no CLID found for " << IMSI << std::endl;


	const char targ2[] = "1234567890";
	gHLR.addUser("123456789012345",targ2);

	sleep(2);

	IMSI = gHLR.getIMSI(targ2);
	if (IMSI) std::cout << "IMSI for " << targ2 << " is " << IMSI << std::endl;
	else std::cout << "no IMSI found for " << targ2 << std::endl;

	CLID = gHLR.getCLIDLocal(IMSI);
	if (CLID) std::cout << "CLID for " << IMSI << " is " << CLID << std::endl;
	else std::cout << "no CLID found for " << IMSI << std::endl;



}
Esempio n. 19
0
void doVisibles()
{
	gVisibleSipColumns = "";
	map<string,string>::iterator it;
	bool first = true;
	for (it = gArgs.begin(); it != gArgs.end(); it++) {
		if (it->first == "what") continue;
		if (first) {
			first = false;
		} else {
			gVisibleSipColumns += " ";
		}
		gVisibleSipColumns += it->first;
	}
	if (!gConfig.set("SubscriberRegistry.Manager.VisibleColumns", gVisibleSipColumns)) {
		LOG(ERR) << "unable to update SubscriberRegistry.Manager.VisibleColumns";
	}
}
Esempio n. 20
0
void gLogInit(const char* defaultLevel)
{
	// Define defaults in the global config
	if (!gConfig.defines("Log.Level")) {
		gConfig.set("Log.Level",defaultLevel);
		LOG(FORCE) << "Setting initial global logging level to " << defaultLevel;
	}
	if (!gConfig.defines("Log.Alarms.TargetPort")) {
		gConfig.set("Log.Alarms.TargetPort",DEFAULT_ALARM_PORT);
	}
	if (!gConfig.defines("Log.Alarms.Max")) {
		gConfig.set("Log.Alarms.Max",DEFAULT_MAX_ALARMS);
	}
}
Esempio n. 21
0
void startTransceiver()
{
	// kill any stray transceiver process
	system("killall transceiver");

	// Start the transceiver binary, if the path is defined.
	// If the path is not defined, the transceiver must be started by some other process.
    char TRXnumARFCN[16];
    sprintf(TRXnumARFCN,"%1d", static_cast<int>(gConfig.getNum("GSM.Radio.ARFCNs")));
	LOG(NOTICE) << "starting transceiver " << transceiverPath << " " << TRXnumARFCN;
	gTransceiverPid = vfork();
	LOG_ASSERT(gTransceiverPid>=0);
	if (gTransceiverPid==0) {
		// Pid==0 means this is the process that starts the transceiver.
		execlp(transceiverPath,transceiverPath,TRXnumARFCN,NULL);
		LOG(EMERG) << "cannot find " << transceiverPath;
		_exit(1);
	} else {
		int status;
		waitpid(gTransceiverPid, &status,0);
		LOG(EMERG) << "Transceiver quit with status " << status << ". Exiting.";
		exit(2);
	}
}
int SubscriberRegistry::init()
{
	string ldb = gConfig.getStr("SubscriberRegistry.db");
	int rc = sqlite3_open(ldb.c_str(),&mDB);
	if (rc) {
		LOG(EMERG) << "Cannot open SubscriberRegistry database: " << sqlite3_errmsg(mDB);
		sqlite3_close(mDB);
		mDB = NULL;
		return FAILURE;
	}
	if (!sqlite3_command(mDB,createRRLPTable)) {
		LOG(EMERG) << "Cannot create RRLP table";
	  return FAILURE;
	}
	if (!sqlite3_command(mDB,createDDTable)) {
		LOG(EMERG) << "Cannot create DIALDATA_TABLE table";
		return FAILURE;
	}
	if (!sqlite3_command(mDB,createSBTable)) {
		LOG(EMERG) << "Cannot create SIP_BUDDIES table";
		return FAILURE;
	}
	return SUCCESS;
}
Esempio n. 23
0
int main(int argc, char *argv[])
{
  if ( signal( SIGINT, ctrlCHandler ) == SIG_ERR )
  {
    cerr << "Couldn't install signal handler for SIGINT" << endl;
    exit(1);
  }

  if ( signal( SIGTERM, ctrlCHandler ) == SIG_ERR )
  {
    cerr << "Couldn't install signal handler for SIGTERM" << endl;
    exit(1);
  }
  // Configure logger.
  gLogInit("transceiver",gConfig.getStr("Log.Level").c_str(),LOG_LOCAL7);

  srandom(time(NULL));

  int mOversamplingRate = 1;
  RAD1Device *usrp = new RAD1Device(mOversamplingRate*1625.0e3/6.0);
  usrp->make(); 

  RadioInterface* radio = new RadioInterface(usrp,3,SAMPSPERSYM,mOversamplingRate,false);
  Transceiver *trx = new Transceiver(5700,"127.0.0.1",SAMPSPERSYM,GSM::Time(2,0),radio);
  trx->receiveFIFO(radio->receiveFIFO());

  trx->start();
  //int i = 0;
  while(!gbShutdown) { sleep(1); } //i++; if (i==60) exit(1);}

  cout << "Shutting down transceiver..." << endl;

//  trx->stop();
  delete trx;
//  delete radio;
}
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>
#include <time.h>
#include <unistd.h>

#include <Logger.h>
#include <Globals.h>
#include <NodeManager.h>
#include <JSONDB.h>
#include "servershare.h"
#include "SubscriberRegistry.h"

using namespace std;

ConfigurationTable gConfig("/etc/OpenBTS/sipauthserve.db", "sipauthserve", getConfigurationKeys());
Log dummy("sipauthserve", gConfig.getStr("Log.Level").c_str(), LOG_LOCAL7);

int my_udp_port;

// just using this for the database access
SubscriberRegistry gSubscriberRegistry;

/** The remote node manager. */ 
NodeManager gNodeManager;

/** The JSON<->DB interface. */ 
JSONDB gJSONDB;

/** Application specific NodeManager logic for handling requests. */
JsonBox::Object nmHandler(JsonBox::Object& request)
Esempio n. 25
0
int main(int argc, char *argv[])
{
  if ( signal( SIGINT, ctrlCHandler ) == SIG_ERR )
  {
    cerr << "Couldn't install signal handler for SIGINT" << endl;
    exit(1);
  }

  if ( signal( SIGTERM, ctrlCHandler ) == SIG_ERR )
  {
    cerr << "Couldn't install signal handler for SIGTERM" << endl;
    exit(1);
  }
  // Configure logger.
  gLogInit("transceiver",gConfig.getStr("Log.Level").c_str(),LOG_LOCAL7);

  gFactoryCalibration.readEEPROM();

  int numARFCN=1;
  if (argc>1) numARFCN = atoi(argv[1]);

#ifdef SINGLEARFCN
  numARFCN=1;
#endif

  srandom(time(NULL));

  int mOversamplingRate = 1;
  switch(numARFCN) {
   
  case 1: 
	mOversamplingRate = 1;
	break;
  case 2:
	mOversamplingRate = 6;
 	break;
  case 3:
	mOversamplingRate = 8;
	break;
  case 4:
	mOversamplingRate = 12;
	break;
  case 5:
	mOversamplingRate = 16;
	break;
  default:
	break;
  }
  //int mOversamplingRate = numARFCN/2 + numARFCN;
  //mOversamplingRate = 15; //mOversamplingRate*2;
  //if ((numARFCN > 1) && (mOversamplingRate % 2)) mOversamplingRate++;
  RAD1Device *usrp = new RAD1Device(mOversamplingRate*1625.0e3/6.0);
  //DummyLoad *usrp = new DummyLoad(mOversamplingRate*1625.0e3/6.0);
  usrp->make(); 

  RadioInterface* radio = new RadioInterface(usrp,3,SAMPSPERSYM,mOversamplingRate,false,numARFCN);
  Transceiver *trx = new Transceiver(5700,"127.0.0.1",SAMPSPERSYM,GSM::Time(2,0),radio,
				     numARFCN,mOversamplingRate,false);
  trx->receiveFIFO(radio->receiveFIFO());

/*
  signalVector *gsmPulse = generateGSMPulse(2,1);
  BitVector normalBurstSeg = "0000101010100111110010101010010110101110011000111001101010000";
  BitVector normalBurst(BitVector(normalBurstSeg,gTrainingSequence[0]),normalBurstSeg);
  signalVector *modBurst = modulateBurst(normalBurst,*gsmPulse,8,1);
  signalVector *modBurst9 = modulateBurst(normalBurst,*gsmPulse,9,1);
  signalVector *interpolationFilter = createLPF(0.6/mOversamplingRate,6*mOversamplingRate,1);
  signalVector totalBurst1(*modBurst,*modBurst9);
  signalVector totalBurst2(*modBurst,*modBurst);
  signalVector totalBurst(totalBurst1,totalBurst2);
  scaleVector(totalBurst,usrp->fullScaleInputValue());
  double beaconFreq = -1.0*(numARFCN-1)*200e3;
  signalVector finalVec(625*mOversamplingRate);
  for (int j = 0; j < numARFCN; j++) {
	signalVector *frequencyShifter = new signalVector(625*mOversamplingRate);
	frequencyShifter->fill(1.0);
	frequencyShift(frequencyShifter,frequencyShifter,2.0*M_PI*(beaconFreq+j*400e3)/(1625.0e3/6.0*mOversamplingRate));
  	signalVector *interpVec = polyphaseResampleVector(totalBurst,mOversamplingRate,1,interpolationFilter);
	multVector(*interpVec,*frequencyShifter);
	addVector(finalVec,*interpVec); 	
  }
  signalVector::iterator itr = finalVec.begin();
  short finalVecShort[2*finalVec.size()];
  short *shortItr = finalVecShort;
  while (itr < finalVec.end()) {
	*shortItr++ = (short) (itr->real());
	*shortItr++ = (short) (itr->imag());
	itr++;
  }
  usrp->loadBurst(finalVecShort,finalVec.size());
*/
  trx->start();
  //int i = 0;
  while(!gbShutdown) { sleep(1); } //i++; if (i==60) exit(1);}

  cout << "Shutting down transceiver..." << endl;

//  trx->stop();
  delete trx;
//  delete radio;
}
int main(int argc, char *argv[])
{

	try {

	srandom(time(NULL));

	gConfig.setUpdateHook(purgeConfig);
	gLogInit("openbts",gConfig.getStr("Log.Level").c_str(),LOG_LOCAL7);
	LOG(ALERT) << "OpenBTS starting, ver " << VERSION << " build date " << __DATE__;

	COUT("\n\n" << gOpenBTSWelcome << "\n");
	gTMSITable.open(gConfig.getStr("Control.Reporting.TMSITable").c_str());
	gTransactionTable.init();
	gPhysStatus.open(gConfig.getStr("Control.Reporting.PhysStatusTable").c_str());
	gBTS.init();
	gSubscriberRegistry.init();
	gParser.addCommands();

	COUT("\nStarting the system...");

	Thread transceiverThread;
	transceiverThread.start((void*(*)(void*)) startTransceiver, NULL);

	// Start the SIP interface.
	gSIPInterface.start();


	//
	// Configure the radio.
	//

	// Start the transceiver interface.
	// Sleep long enough for the USRP to bootload.
	sleep(5);
	gTRX.start();

	// Set up the interface to the radio.
	// Get a handle to the C0 transceiver interface.
	ARFCNManager* C0radio = gTRX.ARFCN();

	// Tuning.
	// Make sure its off for tuning.
	C0radio->powerOff();
	// Get the ARFCN list.
	unsigned C0 = gConfig.getNum("GSM.Radio.C0");
	// Tune the radio.
	LOG(INFO) << "tuning TRX to ARFCN " << C0;
	ARFCNManager* radio = gTRX.ARFCN();
	radio->tune(C0);

	// Set TSC same as BCC everywhere.
	C0radio->setTSC(gBTS.BCC());

	// Set maximum expected delay spread.
	C0radio->setMaxDelay(gConfig.getNum("GSM.Radio.MaxExpectedDelaySpread"));

	// Set Receiver Gain
	C0radio->setRxGain(gConfig.getNum("GSM.Radio.RxGain"));

	// Turn on and power up.
	C0radio->powerOn();
	C0radio->setPower(gConfig.getNum("GSM.Radio.PowerManager.MinAttenDB"));

	//
	// Create a C-V channel set on C0T0.
	//

	// C-V on C0T0
	C0radio->setSlot(0,5);
	// SCH
	SCHL1FEC SCH;
	SCH.downstream(C0radio);
	SCH.open();
	// FCCH
	FCCHL1FEC FCCH;
	FCCH.downstream(C0radio);
	FCCH.open();
	// BCCH
	BCCHL1FEC BCCH;
	BCCH.downstream(C0radio);
	BCCH.open();
	// RACH
	RACHL1FEC RACH(gRACHC5Mapping);
	RACH.downstream(C0radio);
	RACH.open();
	// CCCHs
	CCCHLogicalChannel CCCH0(gCCCH_0Mapping);
	CCCH0.downstream(C0radio);
	CCCH0.open();
	CCCHLogicalChannel CCCH1(gCCCH_1Mapping);
	CCCH1.downstream(C0radio);
	CCCH1.open();
	CCCHLogicalChannel CCCH2(gCCCH_2Mapping);
	CCCH2.downstream(C0radio);
	CCCH2.open();
	// use CCCHs as AGCHs
	gBTS.addAGCH(&CCCH0);
	gBTS.addAGCH(&CCCH1);
	gBTS.addAGCH(&CCCH2);

	// C-V C0T0 SDCCHs
	SDCCHLogicalChannel C0T0SDCCH[4] = {
		SDCCHLogicalChannel(0,gSDCCH_4_0),
		SDCCHLogicalChannel(0,gSDCCH_4_1),
		SDCCHLogicalChannel(0,gSDCCH_4_2),
		SDCCHLogicalChannel(0,gSDCCH_4_3),
	};
	Thread C0T0SDCCHControlThread[4];
	for (int i=0; i<4; i++) {
		C0T0SDCCH[i].downstream(C0radio);
		C0T0SDCCHControlThread[i].start((void*(*)(void*))Control::DCCHDispatcher,&C0T0SDCCH[i]);
		C0T0SDCCH[i].open();
		gBTS.addSDCCH(&C0T0SDCCH[i]);
	}


	//
	// Configure the other slots.
	//

	// Count configured slots.
	unsigned sCount = 1;

	if (gConfig.defines("GSM.Channels.C1sFirst")) {
		// Create C-I slots.
		for (int i=0; i<gConfig.getNum("GSM.Channels.NumC1s"); i++) {
			gBTS.createCombinationI(gTRX,sCount);
			sCount++;
		}
	}

	// Create C-VII slots.
	for (int i=0; i<gConfig.getNum("GSM.Channels.NumC7s"); i++) {
		gBTS.createCombinationVII(gTRX,sCount);
		sCount++;
	}

	if (!gConfig.defines("GSM.Channels.C1sFirst")) {
		// Create C-I slots.
		for (int i=0; i<gConfig.getNum("GSM.Channels.NumC1s"); i++) {
			gBTS.createCombinationI(gTRX,sCount);
			sCount++;
		}
	}


	// Set up idle filling on C0 as needed.
	while (sCount<8) {
		gBTS.createCombination0(gTRX,sCount);
		sCount++;
	}

	/*
		Note: The number of different paging subchannels on       
		the CCCH is:                                        
                                                           
		MAX(1,(3 - BS-AG-BLKS-RES)) * BS-PA-MFRMS           
			if CCCH-CONF = "001"                        
		(9 - BS-AG-BLKS-RES) * BS-PA-MFRMS                  
			for other values of CCCH-CONF               
	*/

	// Set up the pager.
	// Set up paging channels.
	// HACK -- For now, use a single paging channel, since paging groups are broken.
	gBTS.addPCH(&CCCH2);

	// Be sure we are not over-reserving.
	LOG_ASSERT(gConfig.getNum("GSM.CCCH.PCH.Reserve")<(int)gBTS.numAGCHs());

	// OK, now it is safe to start the BTS.
	gBTS.start();

#ifdef HAVE_LIBREADLINE // [
	// start console
	using_history();

	static const char * const history_file_name = "/.openbts_history";
	char *history_name = 0;
	char *home_dir = getenv("HOME");

	if(home_dir) {
		size_t home_dir_len = strlen(home_dir);
		size_t history_file_len = strlen(history_file_name);
		size_t history_len = home_dir_len + history_file_len + 1;
		if(history_len > home_dir_len) {
			if(!(history_name = (char *)malloc(history_len))) {
				LOG(ERR) << "malloc failed: " << strerror(errno);
				exit(2);
			}
			memcpy(history_name, home_dir, home_dir_len);
			memcpy(history_name + home_dir_len, history_file_name,
			   history_file_len + 1);
			read_history(history_name);
		}
	}
#endif // HAVE_LIBREADLINE ]



	LOG(INFO) << "system ready";
	COUT("\n\nWelcome to OpenBTS.  Type \"help\" to see available commands.");
        // FIXME: We want to catch control-d (emacs keybinding for exit())


	// The logging parts were removed from this loop.
	// If we want them back, they will need to go into their own thread.
	while (1) {
#ifdef HAVE_LIBREADLINE // [
		char *inbuf = readline(gConfig.getStr("CLI.Prompt").c_str());
		if (!inbuf) break;
		if (*inbuf) {
			add_history(inbuf);
			// The parser returns -1 on exit.
			if (gParser.process(inbuf, cout, cin)<0) {
				free(inbuf);
				break;
			}
		}
		free(inbuf);
#else // HAVE_LIBREADLINE ][
		cout << endl << gConfig.getStr("CLI.Prompt");
		cout.flush();
		char inbuf[1024];
		cin.getline(inbuf,1024,'\n');
		// The parser returns -1 on exit.
		if (gParser.process(inbuf,cout,cin)<0) break;
#endif // !HAVE_LIBREADLINE ]
	}

#ifdef HAVE_LIBREADLINE // [
	if(history_name) {
		int e = write_history(history_name);
		if(e) {
			fprintf(stderr, "error: history: %s\n", strerror(e));
		}
		free(history_name);
		history_name = 0;
	}
#endif // HAVE_LIBREADLINE ]

	if (gTransceiverPid) kill(gTransceiverPid, SIGKILL);


	}

	catch (ConfigurationTableKeyNotFound e) {

		LOG(ALERT) << "configuration key " << e.key() << " not defined";
		exit(2);
	}

}
int
main(int argc, char **argv)
{
	// TODO: Properly parse and handle any arguments
	if (argc > 1) {
		for (int argi = 0; argi < argc; argi++) {
			if (!strcmp(argv[argi], "--version") ||
			    !strcmp(argv[argi], "-v")) {
				cout << gVersionString << endl;
			}
			if (!strcmp(argv[argi], "--gensql")) {
				cout << gConfig.getDefaultSQL(string(argv[0]), gVersionString) << endl;
			}
			if (!strcmp(argv[argi], "--gentex")) {
				cout << gConfig.getTeX(string(argv[0]), gVersionString) << endl;
			}
		}

		return 0;
	}

	sockaddr_in si_me;
	sockaddr_in si_other;
	int aSocket;
	char buf[BUFLEN];

	LOG(ALERT) << argv[0] << " (re)starting";
	srand ( time(NULL) + (int)getpid() );
	my_udp_port = gConfig.getNum("SubscriberRegistry.Port");
	gSubscriberRegistry.init();
	gNodeManager.setAppLogicHandler(&nmHandler);
	gNodeManager.start(45064);

	// init osip lib
	osip_t *osip;
	int i=osip_init(&osip);
	if (i!=0) {
		LOG(ALERT) << "cannot init sip lib";
		exit(1);
	}

	if ((aSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) {
		LOG(ALERT) << "can't initialize socket";
		exit(1);
	}

	memset((char *) &si_me, 0, sizeof(si_me));
	si_me.sin_family = AF_INET;
	si_me.sin_port = htons(my_udp_port);
	si_me.sin_addr.s_addr = htonl(INADDR_ANY);
	if (bind(aSocket, (sockaddr*)&si_me, sizeof(si_me)) == -1) {
		LOG(ALERT) << "can't bind socket on port " << my_udp_port;
		exit(1);
	}

	LOG(NOTICE) << "binding on port " << my_udp_port;

	while (true) {
		gConfig.purge();
		socklen_t slen = sizeof(si_other);
		memset(buf, 0, BUFLEN);
		if (recvfrom(aSocket, buf, BUFLEN, 0, (sockaddr*)&si_other, &slen) == -1) {
			LOG(ERR) << "recvfrom problem";
			continue;
		}

		LOG(INFO) << " receiving " << buf;

		char *dest = processBuffer(buf);
		if (dest == NULL) {
			continue;
		}

		if (sendto(aSocket, dest, strlen(dest), 0, (sockaddr*)&si_other, sizeof(si_other)) == -1) {
			LOG(ERR) << "sendto problem";
			continue;
		}
		osip_free(dest);
	}

	close(aSocket);
	return 0;
}
Esempio n. 28
0
static int lookupLevel(const string& key)
{
	string val = gConfig.getStr(key);
	return lookupLevel2(key,val);
}
Esempio n. 29
0
/** Return the current logging level for a given source file. */
Log::Level gLoggingLevel(const char* filename)
{
	const string keyName = string("Log.Level.") + string(filename);
	if (gConfig.defines(keyName)) return gLookupLevel(gConfig.getStr(keyName));
	return gLookupLevel(gConfig.getStr("Log.Level"));
}
char *processBuffer(char *buffer)
{
	int i;

	// parse sip message
	osip_message_t *sip;
	i=osip_message_init(&sip);
	if (i!=0) {
		LOG(ERR) << "cannot allocate";
		osip_message_free(sip);
		return NULL;
	}
	i=osip_message_parse(sip, buffer, strlen(buffer));
	if (i!=0) {
		LOG(ERR) << "cannot parse sip message";
		osip_message_free(sip);
		return NULL;
	}

	prettyPrint("request", sip);

	// response starts as clone of message
	osip_message_t *response;
	osip_message_clone(sip, &response);

	osip_from_t * contact_header = (osip_from_t*)osip_list_get(&sip->contacts,0);
	osip_uri_t* contact_url = contact_header->url; 
	char *remote_host = contact_url->host;
	char *remote_port = contact_url->port;

	// return via
	ostringstream newvia;
	// newvia << "SIP/2.0/UDP localhost:5063;branch=1;[email protected]";
	const char *my_ipaddress = "localhost";
	newvia << "SIP/2.0/UDP " << my_ipaddress << ":" << my_udp_port << ";branch=1;received="
		<< "*****@*****.**"; // << my_network.string_addr((struct sockaddr *)netaddr, netaddrlen, false);
	osip_message_append_via(response, newvia.str().c_str());

	// no method
	osip_message_set_method(response, NULL);

	string imsi = imsiClean(imsiFromSip(sip));
	string imsiTo = imsiClean(imsiToSip(sip));
	if ((imsi == "EXIT") && (imsiTo == "EXIT")) exit(0); // for testing only
	if (!imsiFound(imsi)) {
		LOG(NOTICE) << "imsi unknown";
		// imsi problem => 404 IMSI Not Found
		osip_message_set_status_code (response, 404);
		osip_message_set_reason_phrase (response, osip_strdup("IMSI Not Found"));
	} else if (gConfig.defines("SubscriberRegistry.IgnoreAuthentication")) {
                osip_message_set_status_code (response, 200);
                osip_message_set_reason_phrase (response, osip_strdup("OK"));
                LOG(INFO) << "success, imsi " << imsi << " registering for IP address " << remote_host;
                gSubscriberRegistry.imsiSet(imsi,"ipaddr", remote_host, "port", remote_port);
	} else {
		// look for rand and sres in Authorization header (assume imsi same as in from)
		string randx;
		string sres;
		// sip parser is not working reliably for Authorization, so we'll do the parsing
		char *RAND = strcasestr(buffer, "nonce=");
		char *SRES = strcasestr(buffer, "response=");
		if (RAND && SRES) {
			// find RAND digits
			RAND += 6;
			while (!isalnum(*RAND)) { RAND++; }
			RAND[32] = 0;
			int j=0;
			// FIXME -- These loops should use strspn instead.
			while(isalnum(RAND[j])) { j++; }
			RAND[j] = '\0';
			// find SRES digits
			SRES += 9;
			while (!isalnum(*SRES)) { SRES++; }
			int i=0;
			// FIXME -- These loops should use strspn instead.
			while(isalnum(SRES[i])) { i++; }
			SRES[i] = '\0';
			LOG(INFO) << "rand = /" << RAND << "/";
			LOG(INFO) << "sres = /" << SRES << "/";
		}
		if (!RAND || !SRES) {
			LOG(NOTICE) << "imsi " << imsi << " known, 1st register";
			// no rand and sres => 401 Unauthorized
			osip_message_set_status_code (response, 401);
			osip_message_set_reason_phrase (response, osip_strdup("Unauthorized"));
			// but include rand in www_authenticate
			osip_www_authenticate_t *auth;
			osip_www_authenticate_init(&auth);
			// auth type is required by osip_www_authenticate_to_str (and therefore osip_message_to_str)
			string auth_type = "Digest";
			osip_www_authenticate_set_auth_type(auth, osip_strdup(auth_type.c_str()));
			// returning RAND in www_authenticate header
			string randz = generateRand(imsi);
			osip_www_authenticate_set_nonce(auth, osip_strdup(randz.c_str()));
			i = osip_list_add (&response->www_authenticates, auth, -1);
			if (i < 0) LOG(ERR) << "problem adding www_authenticate";
		} else {
			string kc;
			bool sres_good = authenticate(imsi, RAND, SRES, &kc);
			LOG(INFO) << "imsi " << imsi << " known, 2nd register, good = " << sres_good;
			if (sres_good) {
				// sres matches rand => 200 OK
				osip_message_set_status_code (response, 200);
				osip_message_set_reason_phrase (response, osip_strdup("OK"));
				if (kc.size() != 0) {
					osip_authentication_info *auth;
					osip_authentication_info_init(&auth);
					osip_authentication_info_set_cnonce(auth, osip_strdup(kc.c_str()));
					i = osip_list_add (&response->authentication_infos, auth, -1);
					if (i < 0) LOG(ERR) << "problem adding authentication_infos";
				}
				// (pat 9-2013) Add the caller id.
				static string calleridstr("callerid");
				string callid = gSubscriberRegistry.imsiGet(imsi,calleridstr);
				if (callid.size()) {
					char buf[120];
					// Per RFC3966 the telephone numbers should begin with "+" only if it is globally unique throughout the world.
					// We should not add the "+" here, it should be in the database if appropriate.
					snprintf(buf,120,"<tel:%s>",callid.c_str());
					osip_message_set_header(response,"P-Associated-URI",buf);
				}
				// And register it.
				LOG(INFO) << "success, registering for IP address " << remote_host;
				gSubscriberRegistry.imsiSet(imsi,"ipaddr", remote_host, "port", remote_port);
			} else {
				// sres does not match rand => 401 Unauthorized
				osip_message_set_status_code (response, 401);
				osip_message_set_reason_phrase (response, osip_strdup("Unauthorized"));
			}
		}
	}

	prettyPrint("response", response);
	size_t length = 0;
	char *dest;
	int ii = osip_message_to_str(response, &dest, &length);
	if (ii != 0) {
		LOG(ERR) << "cannot get printable message";
	}

	osip_message_free(sip);
	osip_message_free(response);

	return dest;
}