// 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; }
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"); } }
// 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; }
void foo(string s) { uint64_t h; uint64_t l; sr.stringToUint(s, &h, &l); LOG(INFO) << sr.uintToString(h, l) << " " << s; }
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; }
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; } }
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); }
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; }
// 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); } } }
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); }
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(); }
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[]) { 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); } }
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; }
void foo(uint32_t n, string s) { LOG(INFO) << sr.uintToString(n) << " " << s; }
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); }
// is imsi in the database? bool imsiFound(string imsi) { string x = gSubscriberRegistry.imsiGet(imsi, "id"); return x.length() != 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; }
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; }
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; }