Make random extension range configurable

Previously if subscriber was automatically created it got assigned
random MSISDN number between 20000 and 49999. Make it configurable with
new vty command "subscriber-create-on-demand random" and expand vty
tests to check it.

Change-Id: I040a1d227b0c7a1601dc7c33eccb0007941408a6
Related: OS#1658
This commit is contained in:
Max 2016-06-07 15:32:16 +02:00 committed by Harald Welte
parent 2fa9b68813
commit 3911533651
11 changed files with 78 additions and 16 deletions

View File

@ -35,13 +35,15 @@ int db_prepare(void);
int db_fini(void); int db_fini(void);
/* subscriber management */ /* subscriber management */
struct gsm_subscriber *db_create_subscriber(const char *imsi); struct gsm_subscriber *db_create_subscriber(const char *imsi, uint64_t smin,
uint64_t smax);
struct gsm_subscriber *db_get_subscriber(enum gsm_subscriber_field field, struct gsm_subscriber *db_get_subscriber(enum gsm_subscriber_field field,
const char *subscr); const char *subscr);
int db_sync_subscriber(struct gsm_subscriber *subscriber); int db_sync_subscriber(struct gsm_subscriber *subscriber);
int db_subscriber_expire(void *priv, void (*callback)(void *priv, long long unsigned int id)); int db_subscriber_expire(void *priv, void (*callback)(void *priv, long long unsigned int id));
int db_subscriber_alloc_tmsi(struct gsm_subscriber *subscriber); int db_subscriber_alloc_tmsi(struct gsm_subscriber *subscriber);
int db_subscriber_alloc_exten(struct gsm_subscriber *subscriber); int db_subscriber_alloc_exten(struct gsm_subscriber *subscriber, uint64_t smin,
uint64_t smax);
int db_subscriber_alloc_token(struct gsm_subscriber *subscriber, uint32_t* token); int db_subscriber_alloc_token(struct gsm_subscriber *subscriber, uint32_t* token);
int db_subscriber_assoc_imei(struct gsm_subscriber *subscriber, char *imei); int db_subscriber_assoc_imei(struct gsm_subscriber *subscriber, char *imei);
int db_subscriber_delete(struct gsm_subscriber *subscriber); int db_subscriber_delete(struct gsm_subscriber *subscriber);

View File

@ -290,6 +290,8 @@ struct gsm_network {
/* subscriber related features */ /* subscriber related features */
int subscr_creation_mode; int subscr_creation_mode;
uint64_t ext_min;
uint64_t ext_max;
struct gsm_subscriber_group *subscr_group; struct gsm_subscriber_group *subscr_group;
struct gsm_sms_queue *sms_queue; struct gsm_sms_queue *sms_queue;

View File

@ -90,7 +90,8 @@ enum gsm_subscriber_update_reason {
struct gsm_subscriber *subscr_get(struct gsm_subscriber *subscr); struct gsm_subscriber *subscr_get(struct gsm_subscriber *subscr);
struct gsm_subscriber *subscr_put(struct gsm_subscriber *subscr); struct gsm_subscriber *subscr_put(struct gsm_subscriber *subscr);
struct gsm_subscriber *subscr_create_subscriber(struct gsm_subscriber_group *sgrp, struct gsm_subscriber *subscr_create_subscriber(struct gsm_subscriber_group *sgrp,
const char *imsi); const char *imsi, uint64_t smin,
uint64_t smax);
struct gsm_subscriber *subscr_get_by_tmsi(struct gsm_subscriber_group *sgrp, struct gsm_subscriber *subscr_get_by_tmsi(struct gsm_subscriber_group *sgrp,
uint32_t tmsi); uint32_t tmsi);
struct gsm_subscriber *subscr_get_by_imsi(struct gsm_subscriber_group *sgrp, struct gsm_subscriber *subscr_get_by_imsi(struct gsm_subscriber_group *sgrp,

View File

@ -104,7 +104,8 @@ struct gsm_network *gsm_network_init(uint16_t country_code, uint16_t network_cod
net->stats.bts.rsl_fail = osmo_counter_alloc("net.bts.rsl_fail"); net->stats.bts.rsl_fail = osmo_counter_alloc("net.bts.rsl_fail");
net->mncc_recv = mncc_recv; net->mncc_recv = mncc_recv;
net->ext_min = GSM_MIN_EXTEN;
net->ext_max = GSM_MAX_EXTEN;
gsm_net_update_ctype(net); gsm_net_update_ctype(net);
return net; return net;

View File

@ -18,6 +18,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
#include <osmocom/ctrl/control_cmd.h> #include <osmocom/ctrl/control_cmd.h>
#include <openbsc/gsm_data.h> #include <openbsc/gsm_data.h>
#include <openbsc/gsm_subscriber.h> #include <openbsc/gsm_subscriber.h>
@ -95,7 +96,9 @@ static int set_subscriber_modify(struct ctrl_cmd *cmd, void *data)
subscr = subscr_get_by_imsi(net->subscr_group, imsi); subscr = subscr_get_by_imsi(net->subscr_group, imsi);
if (!subscr) if (!subscr)
subscr = subscr_create_subscriber(net->subscr_group, imsi); subscr = subscr_create_subscriber(net->subscr_group, imsi,
net->ext_min,
net->ext_max);
if (!subscr) if (!subscr)
goto fail; goto fail;

View File

@ -518,7 +518,8 @@ int db_fini(void)
return 0; return 0;
} }
struct gsm_subscriber *db_create_subscriber(const char *imsi) struct gsm_subscriber *db_create_subscriber(const char *imsi, uint64_t smin,
uint64_t smax)
{ {
dbi_result result; dbi_result result;
struct gsm_subscriber *subscr; struct gsm_subscriber *subscr;
@ -550,7 +551,7 @@ struct gsm_subscriber *db_create_subscriber(const char *imsi)
strncpy(subscr->imsi, imsi, sizeof(subscr->imsi)-1); strncpy(subscr->imsi, imsi, sizeof(subscr->imsi)-1);
dbi_result_free(result); dbi_result_free(result);
LOGP(DDB, LOGL_INFO, "New Subscriber: ID %llu, IMSI %s\n", subscr->id, subscr->imsi); LOGP(DDB, LOGL_INFO, "New Subscriber: ID %llu, IMSI %s\n", subscr->id, subscr->imsi);
db_subscriber_alloc_exten(subscr); db_subscriber_alloc_exten(subscr, smin, smax);
return subscr; return subscr;
} }
@ -1249,13 +1250,14 @@ int db_subscriber_alloc_tmsi(struct gsm_subscriber *subscriber)
return 0; return 0;
} }
int db_subscriber_alloc_exten(struct gsm_subscriber *subscriber) int db_subscriber_alloc_exten(struct gsm_subscriber *subscriber, uint64_t smin,
uint64_t smax)
{ {
dbi_result result = NULL; dbi_result result = NULL;
uint32_t try; uint32_t try;
for (;;) { for (;;) {
try = (rand()%(GSM_MAX_EXTEN-GSM_MIN_EXTEN+1)+GSM_MIN_EXTEN); try = (rand() % (smax - smin + 1) + smin);
result = dbi_conn_queryf(conn, result = dbi_conn_queryf(conn,
"SELECT * FROM Subscriber " "SELECT * FROM Subscriber "
"WHERE extension = %i", "WHERE extension = %i",

View File

@ -537,7 +537,8 @@ static struct gsm_subscriber *subscr_create(const struct gsm_network *net,
if (!subscr_regexp_check(net, imsi)) if (!subscr_regexp_check(net, imsi))
return NULL; return NULL;
return subscr_create_subscriber(net->subscr_group, imsi); return subscr_create_subscriber(net->subscr_group, imsi, net->ext_min,
net->ext_max);
} }
/* Parse Chapter 9.2.11 Identity Response */ /* Parse Chapter 9.2.11 Identity Response */

View File

@ -203,9 +203,10 @@ void subscr_remove_request(struct subscr_request *request)
} }
struct gsm_subscriber *subscr_create_subscriber(struct gsm_subscriber_group *sgrp, struct gsm_subscriber *subscr_create_subscriber(struct gsm_subscriber_group *sgrp,
const char *imsi) const char *imsi, uint64_t smin,
uint64_t smax)
{ {
struct gsm_subscriber *subscr = db_create_subscriber(imsi); struct gsm_subscriber *subscr = db_create_subscriber(imsi, smin, smax);
if (subscr) if (subscr)
subscr->group = sgrp; subscr->group = sgrp;
return subscr; return subscr;

View File

@ -21,6 +21,8 @@
#include <stdlib.h> #include <stdlib.h>
#include <limits.h> #include <limits.h>
#include <unistd.h> #include <unistd.h>
#include <stdbool.h>
#include <inttypes.h>
#include <time.h> #include <time.h>
#include <osmocom/vty/command.h> #include <osmocom/vty/command.h>
@ -240,7 +242,9 @@ DEFUN(subscriber_create,
if (subscr) if (subscr)
db_sync_subscriber(subscr); db_sync_subscriber(subscr);
else { else {
subscr = subscr_create_subscriber(gsmnet->subscr_group, argv[0]); subscr = subscr_create_subscriber(gsmnet->subscr_group, argv[0],
gsmnet->ext_min,
gsmnet->ext_max);
if (!subscr) { if (!subscr) {
vty_out(vty, "%% No subscriber created for IMSI %s%s", vty_out(vty, "%% No subscriber created for IMSI %s%s",
@ -1031,6 +1035,25 @@ DEFUN(cfg_nitb, cfg_nitb_cmd,
return CMD_SUCCESS; return CMD_SUCCESS;
} }
/* Note: limit on the parameter length is set by internal vty code limitations */
DEFUN(cfg_nitb_subscr_random, cfg_nitb_subscr_random_cmd,
"subscriber-create-on-demand random <1-9999999999> <2-9999999999>",
"Set random parameters for a new record when a subscriber is first seen.\n"
"Set random parameters for a new record when a subscriber is first seen.\n"
"Minimum for subscriber extension\n""Maximum for subscriber extension\n")
{
struct gsm_network *gsmnet = gsmnet_from_vty(vty);
uint64_t mi = atoi(argv[0]), ma = atoi(argv[1]);
if (mi >= ma) {
vty_out(vty, "Incorrect range: %s >= %s, expected MIN < MAX%s",
argv[0], argv[1], VTY_NEWLINE);
return CMD_WARNING;
}
gsmnet->ext_min = mi;
gsmnet->ext_max = ma;
return CMD_SUCCESS;
}
DEFUN(cfg_nitb_subscr_create, cfg_nitb_subscr_create_cmd, DEFUN(cfg_nitb_subscr_create, cfg_nitb_subscr_create_cmd,
"subscriber-create-on-demand [regexp]", "subscriber-create-on-demand [regexp]",
"Make a new record when a subscriber is first seen.\n" "Make a new record when a subscriber is first seen.\n"
@ -1080,6 +1103,10 @@ static int config_write_nitb(struct vty *vty)
vty_out(vty, "nitb%s", VTY_NEWLINE); vty_out(vty, "nitb%s", VTY_NEWLINE);
vty_out(vty, " %ssubscriber-create-on-demand%s%s", vty_out(vty, " %ssubscriber-create-on-demand%s%s",
pref, reg, VTY_NEWLINE); pref, reg, VTY_NEWLINE);
if (gsmnet->ext_min != GSM_MIN_EXTEN || gsmnet->ext_max != GSM_MAX_EXTEN)
vty_out(vty, " subscriber-create-on-demand random %"PRIu64" %"
PRIu64"%s", gsmnet->ext_min, gsmnet->ext_max,
VTY_NEWLINE);
vty_out(vty, " %sassign-tmsi%s", vty_out(vty, " %sassign-tmsi%s",
gsmnet->avoid_tmsi ? "no " : "", VTY_NEWLINE); gsmnet->avoid_tmsi ? "no " : "", VTY_NEWLINE);
return CMD_SUCCESS; return CMD_SUCCESS;
@ -1134,6 +1161,7 @@ int bsc_vty_init_extra(void)
install_element(CONFIG_NODE, &cfg_nitb_cmd); install_element(CONFIG_NODE, &cfg_nitb_cmd);
install_node(&nitb_node, config_write_nitb); install_node(&nitb_node, config_write_nitb);
install_element(NITB_NODE, &cfg_nitb_subscr_create_cmd); install_element(NITB_NODE, &cfg_nitb_subscr_create_cmd);
install_element(NITB_NODE, &cfg_nitb_subscr_random_cmd);
install_element(NITB_NODE, &cfg_nitb_no_subscr_create_cmd); install_element(NITB_NODE, &cfg_nitb_no_subscr_create_cmd);
install_element(NITB_NODE, &cfg_nitb_assign_tmsi_cmd); install_element(NITB_NODE, &cfg_nitb_assign_tmsi_cmd);
install_element(NITB_NODE, &cfg_nitb_no_assign_tmsi_cmd); install_element(NITB_NODE, &cfg_nitb_no_assign_tmsi_cmd);

View File

@ -164,7 +164,7 @@ static void test_subs(const char *alice_imsi, char *imei1, char *imei2)
struct gsm_subscriber *alice = NULL, *alice_db; struct gsm_subscriber *alice = NULL, *alice_db;
char scratch_str[256]; char scratch_str[256];
alice = db_create_subscriber(alice_imsi); alice = db_create_subscriber(alice_imsi, GSM_MIN_EXTEN, GSM_MAX_EXTEN);
db_subscriber_assoc_imei(alice, imei1); db_subscriber_assoc_imei(alice, imei1);
if (imei2) if (imei2)
db_subscriber_assoc_imei(alice, imei2); db_subscriber_assoc_imei(alice, imei2);
@ -217,7 +217,7 @@ int main()
struct gsm_subscriber *alice_db; struct gsm_subscriber *alice_db;
char *alice_imsi = "3243245432345"; char *alice_imsi = "3243245432345";
alice = db_create_subscriber(alice_imsi); alice = db_create_subscriber(alice_imsi, GSM_MIN_EXTEN, GSM_MAX_EXTEN);
db_sync_subscriber(alice); db_sync_subscriber(alice);
alice_db = db_get_subscriber(GSM_SUBSCRIBER_IMSI, alice->imsi); alice_db = db_get_subscriber(GSM_SUBSCRIBER_IMSI, alice->imsi);
COMPARE(alice, alice_db); COMPARE(alice, alice_db);
@ -228,7 +228,7 @@ int main()
test_subs("9993245423445", "1234567890", "6543560920"); test_subs("9993245423445", "1234567890", "6543560920");
/* create it again and see it fails */ /* create it again and see it fails */
alice = db_create_subscriber(alice_imsi); alice = db_create_subscriber(alice_imsi, GSM_MIN_EXTEN, GSM_MAX_EXTEN);
OSMO_ASSERT(!alice); OSMO_ASSERT(!alice);
test_sms(); test_sms();

View File

@ -424,11 +424,13 @@ class TestVTYNITB(TestVTYGenericBSC):
self.vty.enable() self.vty.enable()
imsi = "204300854013739" imsi = "204300854013739"
imsi2 = "204301824913769"
wrong_imsi = "204300999999999" wrong_imsi = "204300999999999"
# Lets create one # Lets create one
res = self.vty.command('subscriber create imsi '+imsi) res = self.vty.command('subscriber create imsi '+imsi)
self.assert_(res.find(" IMSI: "+imsi) > 0) self.assert_(res.find(" IMSI: "+imsi) > 0)
self.assert_(res.find("Extension") > 0)
self.vty.verify('subscriber imsi '+wrong_imsi+' name wrong', ['% No subscriber found for imsi '+wrong_imsi]) self.vty.verify('subscriber imsi '+wrong_imsi+' name wrong', ['% No subscriber found for imsi '+wrong_imsi])
res = self.vty.command('subscriber imsi '+imsi+' name '+('X' * 160)) res = self.vty.command('subscriber imsi '+imsi+' name '+('X' * 160))
@ -442,9 +444,28 @@ class TestVTYNITB(TestVTYGenericBSC):
self.vty.verify('subscriber imsi '+imsi+' extension '+('1' * 14), ['']) self.vty.verify('subscriber imsi '+imsi+' extension '+('1' * 14), [''])
# With narrow random interval
self.vty.command("configure terminal")
self.vty.command("nitb")
self.assertTrue(self.vty.verify("subscriber-create-on-demand", ['']))
# wrong interval
res = self.vty.command("subscriber-create-on-demand random 221 122")
self.assert_(res.find("122") > 0)
self.assert_(res.find("221") > 0)
# correct interval
self.assertTrue(self.vty.verify("subscriber-create-on-demand random 221 222", ['']))
self.vty.command("end")
res = self.vty.command('subscriber create imsi ' + imsi2)
self.assert_(res.find(" IMSI: " + imsi2) > 0)
self.assert_(res.find("221") > 0 or res.find("222") > 0)
self.assert_(res.find(" Extension: ") > 0)
# Delete it # Delete it
res = self.vty.command('subscriber delete imsi '+imsi) res = self.vty.command('subscriber delete imsi '+imsi)
self.assert_(res != "") self.assert_(res != "")
res = self.vty.command('subscriber delete imsi ' + imsi2)
self.assert_(res != "")
def testShowPagingGroup(self): def testShowPagingGroup(self):
res = self.vty.command("show paging-group 255 1234567") res = self.vty.command("show paging-group 255 1234567")