コード例 #1
0
// generate a 128' random number
string generateRand(string imsi)
{
	string ki = gSubscriberRegistry.imsiGet(imsi, "ki");
	string ret;
	if (ki.length() != 0) {
		LOG(INFO) << "ki is known";
		// generate and return rand (clear any cached rand or sres)
		gSubscriberRegistry.imsiSet(imsi, "rand", "", "sres", "");
		ret = soGenerateIt();
	} else {
		string wRand = gSubscriberRegistry.imsiGet(imsi, "rand");
		if (wRand.length() != 0) {
			LOG(INFO) << "ki is unknown, rand is cached";
			// return cached rand
			ret = wRand;
		} else {
			LOG(INFO) << "ki is unknown, rand is not cached";
			// generate rand, cache rand, clear sres, and return rand
			wRand = soGenerateIt();
			gSubscriberRegistry.imsiSet(imsi, "rand", wRand, "sres", "");
			ret = wRand;
		}
	}
	return ret;
}
コード例 #2
0
ファイル: srmanager.cpp プロジェクト: Gabotero/OpenBTS
void table(const char *tableName, vector<string> &cols, bool addButtonP, const char *note)
{
	cout << "<h4>" << gDatabase << "." << tableName << "  " << note << "</h4>\n";
	initTable(cols);
	ostringstream os;
	os << "select id," << join(",", cols) << " from " << tableName;
	sqlite3_stmt *stmt;
	if (sqlite3_prepare_statement(gSubscriberRegistry.db(), &stmt,os.str().c_str())) {
		LOG(ERR) << "sqlite3_prepare_statement problem - statement: " << os.str();
		LOG(ERR) << "   " << sqlite3_errmsg(gSubscriberRegistry.db());
		return;
	}
	int src = sqlite3_run_query(gSubscriberRegistry.db(), stmt);
	while (src == SQLITE_ROW) {
		vector<string> values;
		const char *id = (const char*)sqlite3_column_text(stmt, 0);
		for (int i = 1; i <= (int)cols.size(); i++) {
			const char *value = (const char*)sqlite3_column_text(stmt, i);
			values.push_back(value ? value : "(null)");
		}
		tableRow(cols, values, UPDATE_BUTTON | DELETE_BUTTON, id);
		src = sqlite3_run_query(gSubscriberRegistry.db(), stmt);
	}
	sqlite3_finalize(stmt);
	if (addButtonP) {
		vector<string> dummy;
		tableRow(cols, dummy, ADD_BUTTON, "0");
	}
}
コード例 #3
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;
}
コード例 #4
0
ファイル: test.cpp プロジェクト: 0x7678/OpenBTS
void foo(string s)
{
	uint64_t h;
	uint64_t l;
	sr.stringToUint(s, &h, &l);
	LOG(INFO) << sr.uintToString(h, l) << " " << s;
}
コード例 #5
0
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;



}
コード例 #6
0
ファイル: servershare.cpp プロジェクト: Gabotero/OpenBTS
void imsiSet(string imsi, string key1, string value1, string key2, string value2)
{
	string name = imsi.substr(0,4) == "IMSI" ? imsi : "IMSI" + imsi;
	ostringstream os2;
	os2 << "update sip_buddies set " << key1 << " = \"" << value1 << "\"," << key2 << " = \"" << value2 << "\" where username = \"" << name << "\"";
	if (!sqlite3_command(gSubscriberRegistry.db(), os2.str().c_str())) {
		LOG(ERR) << "sqlite3_command problem";
		return;
	}
}
コード例 #7
0
ファイル: srmanager.cpp プロジェクト: Gabotero/OpenBTS
void getFields(vector<string> *fields, vector<bool> *isSet)
{ 
	vector<string> vsc;
	split(' ', gVisibleSipColumns, &vsc);
	sqlite3_stmt *stmt;
	const char *cmd = "pragma table_info(sip_buddies)";
	if (sqlite3_prepare_statement(gSubscriberRegistry.db(), &stmt, cmd)) {
		LOG(ERR) << "sqlite3_prepare_statement problem - statement: " << cmd;
		LOG(ERR) << "   " << sqlite3_errmsg(gSubscriberRegistry.db());
		return;
	}
	int src = sqlite3_run_query(gSubscriberRegistry.db(), stmt);
	while (src == SQLITE_ROW) {
		string field = (char*)sqlite3_column_text(stmt, 1);
		fields->push_back(field);
		isSet->push_back(find(vsc.begin(), vsc.end(), field) != vsc.end());
		src = sqlite3_run_query(gSubscriberRegistry.db(), stmt);
	}
	sqlite3_finalize(stmt);
}
コード例 #8
0
ファイル: servershare.cpp プロジェクト: Gabotero/OpenBTS
string imsiGet(string imsi, string key)
{
	string name = imsi.substr(0,4) == "IMSI" ? imsi : "IMSI" + imsi;
	char *value;
	if (!sqlite3_single_lookup(gSubscriberRegistry.db(), "sip_buddies", "username", name.c_str(), key.c_str(), value)) {
		return "";
	}
	if (!value) { return ""; }
	string retValue = value;
	free(value);
	return retValue;
}
コード例 #9
0
ファイル: subscriberserver.cpp プロジェクト: 0x7678/OpenBTS
// run an sql statement through sqlite3 to get a response
void generateSqlResponse()
{
	string stmts = getArg("stmts");
	vector<string> vstmts;
	split(';', stmts, &vstmts);
	vector<string>::iterator it;
	for (it = vstmts.begin(); it != vstmts.end(); it++) {
		sqlite3_stmt *stmt;
		if (sqlite3_prepare_statement(gSubscriberRegistry.db(), &stmt, it->c_str())) {
			LOG(ERR) << "sqlite3_prepare_statement problem - statement: " << it->c_str();
			return;
		}
		int src = sqlite3_run_query(gSubscriberRegistry.db(), stmt);
		while (src == SQLITE_ROW) {
			string resp = "res=";
			int cols = sqlite3_column_count(stmt);
			for (int i = 0; i < cols; i++) {
				resp.append((const char*)sqlite3_column_text(stmt, i));
			}
			gResponse.push_back(resp);
			src = sqlite3_run_query(gSubscriberRegistry.db(), stmt);
		}
	}
}
コード例 #10
0
ファイル: servershare.cpp プロジェクト: Gabotero/OpenBTS
bool randEqual(string a, string b)
{
	uint64_t rand1h = 0;
	uint64_t rand1l = 0;
	uint64_t rand2h = 0;
	uint64_t rand2l = 0;

	if (a.empty() || b.empty())
		return false;

	gSubscriberRegistry.stringToUint(a, &rand1h, &rand1l);
	gSubscriberRegistry.stringToUint(b, &rand2h, &rand2l);

	LOG(DEBUG) << "rand1h = " << rand1h << ", rand1l = " << rand1l;
	LOG(DEBUG) << "rand2h = " << rand2h << ", rand2l = " << rand2l;

	return (rand1h == rand2h) && (rand1l == rand2l);
}
コード例 #11
0
ファイル: srmanager.cpp プロジェクト: Gabotero/OpenBTS
void doCmd(string cmd)
{
	string table;
	vector<string> cols;
	if (gArgs.find("dial") == gArgs.end()) {
		table = "sip_buddies";
		split(' ', gVisibleSipColumns, &cols);
	} else {
		table = "dialdata_table";
		split(' ', gVisibleExtColumns, &cols);
	}
	string id = gArgs["id"];
	ostringstream os;
	if (cmd == "add") {
		string names = join(",", cols);
		vector<string> values0;
		vector<string>::iterator it;
		for (it = cols.begin(); it != cols.end(); it++) {
			values0.push_back(nullCheck(gArgs[*it]));
		}
		string values = join(",", values0);
		os << "insert into " << table << " (" << names << ") values (" << values << ")";
	} else if (cmd == "delete") {
		os << "delete from " << table << " where id = " << id;
	} else if (cmd == "update") {
		vector<string> sets0;
		vector<string>::iterator it;
		for (it = cols.begin(); it != cols.end(); it++) {
			sets0.push_back(*it + "=" + nullCheck(gArgs[*it]));
		}
		string sets = join(",", sets0);
		os << "update " << table << " set " << sets << " where id = " << id;
	} else {
		LOG(ERR) << "internal error";
	}
	LOG(INFO) << os.str();
	if (!sqlite3_command(gSubscriberRegistry.db(), os.str().c_str())) {
		LOG(ERR) << "sqlite3_command problem - statement: " << os.str();
		return;
	}
	mainTables();
}
コード例 #12
0
ファイル: srmanager.cpp プロジェクト: Gabotero/OpenBTS
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();
}
コード例 #13
0
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);
	}

}
コード例 #14
0
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;
}
コード例 #15
0
ファイル: test.cpp プロジェクト: 0x7678/OpenBTS
void foo(uint32_t n, string s)
{
	LOG(INFO) << sr.uintToString(n) << " " << s;
}
コード例 #16
0
ファイル: OpenBTS.cpp プロジェクト: TeamFSS/public
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;
			}
		}

		return 0;
	}

	createStats();
 
	gReports.incr("OpenBTS.Starts");

	int sock = socket(AF_UNIX,SOCK_DGRAM,0);
	if (sock<0) {
		perror("creating CLI datagram socket");
		LOG(ALERT) << "cannot create socket for CLI";
		gReports.incr("OpenBTS.Exit.CLI.Socket");
		exit(1);
	}

	try {

	srandom(time(NULL));

	gConfig.setUpdateHook(purgeConfig);
	gLogInit("openbts",gConfig.getStr("Log.Level").c_str());
	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(gConfig.getStr("Control.Reporting.TransactionTable").c_str());
	gPhysStatus.open(gConfig.getStr("Control.Reporting.PhysStatusTable").c_str());
	gBTS.init();
	gSubscriberRegistry.init();
	gParser.addCommands();

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

	// is the radio running?
	// Start the transceiver interface.
	LOG(INFO) << "checking transceiver";
	//gTRX.ARFCN(0)->powerOn();
	//sleep(gConfig.getNum("TRX.Timeout.Start",2));
	bool haveTRX = gTRX.ARFCN(0)->powerOn(false);

	Thread transceiverThread;
	if (!haveTRX) {
		transceiverThread.start((void*(*)(void*)) startTransceiver, NULL);
		// sleep to let the FPGA code load
		// TODO: we should be "pinging" the radio instead of sleeping
		sleep(5);
	} else {
		LOG(NOTICE) << "transceiver already running";
	}

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


	//
	// Configure the radio.
	//

	gTRX.start();

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

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

	// Send either TSC or full BSIC depending on radio need
	if (gConfig.getBool("GSM.Radio.NeedBSIC")) {
		// Send BSIC to 
		C0radio->setBSIC(gBTS.BSIC());
	} else {
		// 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(true);
	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,0,gSDCCH_4_0),
		SDCCHLogicalChannel(0,0,gSDCCH_4_1),
		SDCCHLogicalChannel(0,0,gSDCCH_4_2),
		SDCCHLogicalChannel(0,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/8,sCount%8);
			sCount++;
		}
	}

	// Create C-VII slots.
	for (int i=0; i<gConfig.getNum("GSM.Channels.NumC7s"); i++) {
		gBTS.createCombinationVII(gTRX,sCount/8,sCount%8);
		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/8,sCount%8);
			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.
	if (gConfig.getNum("GSM.Channels.SDCCHReserve")>=(int)gBTS.SDCCHTotal()) {
		unsigned val = gBTS.SDCCHTotal() - 1;
		LOG(CRIT) << "GSM.Channels.SDCCHReserve too big, changing to " << val;
		gConfig.set("GSM.Channels.SDCCHReserve",val);
	}


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


	cout << "\nsystem ready\n";
	cout << "\nuse the OpenBTSCLI utility to access CLI\n";
	LOG(INFO) << "system ready";

	struct sockaddr_un cmdSockName;
	cmdSockName.sun_family = AF_UNIX;
	const char* sockpath = gConfig.getStr("CLI.SocketPath").c_str();
	char rmcmd[strlen(sockpath)+5];
	sprintf(rmcmd,"rm %s",sockpath);
	system(rmcmd);
	strcpy(cmdSockName.sun_path,sockpath);
	if (bind(sock, (struct sockaddr *) &cmdSockName, sizeof(struct sockaddr_un))) {
		perror("binding name to cmd datagram socket");
		LOG(ALERT) << "cannot bind socket for CLI at " << sockpath;
		gReports.incr("OpenBTS.Exit.CLI.Socket");
		exit(1);
	}

	while (1) {
		char cmdbuf[1000];
		struct sockaddr_un source;
		socklen_t sourceSize = sizeof(source);
		int nread = recvfrom(sock,cmdbuf,sizeof(cmdbuf)-1,0,(struct sockaddr*)&source,&sourceSize);
		gReports.incr("OpenBTS.CLI.Command");
		cmdbuf[nread]='\0';
		LOG(INFO) << "received command \"" << cmdbuf << "\" from " << source.sun_path;
		std::ostringstream sout;
		int res = gParser.process(cmdbuf,sout);
		const std::string rspString= sout.str();
		const char* rsp = rspString.c_str();
		LOG(INFO) << "sending " << strlen(rsp) << "-char result to " << source.sun_path;
		if (sendto(sock,rsp,strlen(rsp)+1,0,(struct sockaddr*)&source,sourceSize)<0) {
			LOG(ERR) << "can't send CLI response to " << source.sun_path;
			gReports.incr("OpenBTS.CLI.Command.ResponseFailure");
		}
		// res<0 means to exit the application
		if (res<0) break;
		gReports.incr("OpenBTS.Exit.Normal.CLI");
	}

	} // try

	catch (ConfigurationTableKeyNotFound e) {
		LOG(EMERG) << "required configuration parameter " << e.key() << " not defined, aborting";
		gReports.incr("OpenBTS.Exit.Error.ConfigurationParamterNotFound");
	}

	//if (gTransceiverPid) kill(gTransceiverPid, SIGKILL);
	close(sock);

}
コード例 #17
0
// is imsi in the database?
bool imsiFound(string imsi)
{
	string x = gSubscriberRegistry.imsiGet(imsi, "id");
	return x.length() != 0;
}
コード例 #18
0
ファイル: test.cpp プロジェクト: 0x7678/OpenBTS
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;


}
コード例 #19
0
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;
}
コード例 #20
0
int
main(int argc, char **argv)
{
	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();

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

	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;
}